fstrm-0.2.0/ 0000755 0001750 0001750 00000000000 12427010215 007637 5 0000000 0000000 fstrm-0.2.0/build-aux/ 0000755 0001750 0001750 00000000000 12427010215 011531 5 0000000 0000000 fstrm-0.2.0/build-aux/depcomp 0000755 0001750 0001750 00000056016 12427010213 013034 0000000 0000000 #! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2013-05-30.07; # UTC
# Copyright (C) 1999-2013 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:
fstrm-0.2.0/build-aux/test-driver 0000755 0001750 0001750 00000010277 12427010213 013654 0000000 0000000 #! /bin/sh
# test-driver - basic testsuite driver script.
scriptversion=2013-07-13.22; # UTC
# Copyright (C) 2011-2013 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.
# This file is maintained in Automake, please report
# bugs to or send patches to
# .
# Make unconditional expansion of undefined variables an error. This
# helps a lot in preventing typo-related bugs.
set -u
usage_error ()
{
echo "$0: $*" >&2
print_usage >&2
exit 2
}
print_usage ()
{
cat <$log_file 2>&1
estatus=$?
if test $enable_hard_errors = no && test $estatus -eq 99; then
estatus=1
fi
case $estatus:$expect_failure in
0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
0:*) col=$grn res=PASS recheck=no gcopy=no;;
77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
*:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
*:*) col=$red res=FAIL recheck=yes gcopy=yes;;
esac
# Report outcome to console.
echo "${col}${res}${std}: $test_name"
# Register the test result, and other relevant metadata.
echo ":test-result: $res" > $trs_file
echo ":global-test-result: $res" >> $trs_file
echo ":recheck: $recheck" >> $trs_file
echo ":copy-in-global-log: $gcopy" >> $trs_file
# 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:
fstrm-0.2.0/build-aux/compile 0000755 0001750 0001750 00000016245 12427010213 013035 0000000 0000000 #! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2012-10-14.11; # UTC
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
# Written by Tom Tromey .
#
# 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.
# This file is maintained in Automake, please report
# bugs to or send patches to
# .
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.
Report bugs to .
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# 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:
fstrm-0.2.0/build-aux/config.guess 0000755 0001750 0001750 00000123550 12427010213 013775 0000000 0000000 #! /bin/sh
# Attempt to guess a canonical system name.
# Copyright 1992-2014 Free Software Foundation, Inc.
timestamp='2014-03-23'
# 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.
#
# 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 with a ChangeLog entry to config-patches@gnu.org.
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-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."
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/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
echo ${IBM_ARCH}-ibm-aix${IBM_REV}
exit ;;
*:AIX:*:*)
echo rs6000-ibm-aix
exit ;;
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
echo romp-ibm-bsd4.4
exit ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
exit ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
exit ;;
DPX/2?00:B.O.S.:*:*)
echo m68k-bull-sysv3
exit ;;
9000/[34]??:4.3bsd:1.*:*)
echo m68k-hp-bsd
exit ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
exit ;;
9000/[34678]??:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
if [ -x /usr/bin/getconf ]; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "${sc_cpu_version}" in
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case "${sc_kernel_bits}" in
32) HP_ARCH="hppa2.0n" ;;
64) HP_ARCH="hppa2.0w" ;;
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
esac ;;
esac
fi
if [ "${HP_ARCH}" = "" ]; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#define _HPUX_SOURCE
#include
#include
int main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
#endif
long cpu = sysconf (_SC_CPU_VERSION);
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
case CPU_PA_RISC2_0:
#if defined(_SC_KERNEL_BITS)
switch (bits)
{
case 64: puts ("hppa2.0w"); break;
case 32: puts ("hppa2.0n"); break;
default: puts ("hppa2.0"); break;
} break;
#else /* !defined(_SC_KERNEL_BITS) */
puts ("hppa2.0"); break;
#endif
default: puts ("hppa1.0"); break;
}
exit (0);
}
EOF
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
if [ ${HP_ARCH} = "hppa2.0w" ]
then
eval $set_cc_for_build
# hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
# 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
# generating 64-bit code. GNU and HP use different nomenclature:
#
# $ CC_FOR_BUILD=cc ./config.guess
# => hppa2.0w-hp-hpux11.23
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
# => hppa64-hp-hpux11.23
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
grep -q __LP64__
then
HP_ARCH="hppa2.0w"
else
HP_ARCH="hppa64"
fi
fi
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
exit ;;
ia64:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
echo ia64-hp-hpux${HPUX_REV}
exit ;;
3050*:HI-UX:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#include
int
main ()
{
long cpu = sysconf (_SC_CPU_VERSION);
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
results, however. */
if (CPU_IS_PA_RISC (cpu))
{
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
default: puts ("hppa-hitachi-hiuxwe2"); break;
}
}
else if (CPU_IS_HP_MC68K (cpu))
puts ("m68k-hitachi-hiuxwe2");
else puts ("unknown-hitachi-hiuxwe2");
exit (0);
}
EOF
$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
{ echo "$SYSTEM_NAME"; exit; }
echo unknown-hitachi-hiuxwe2
exit ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
echo hppa1.1-hp-bsd
exit ;;
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
exit ;;
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
echo hppa1.0-hp-mpeix
exit ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
echo hppa1.1-hp-osf
exit ;;
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
exit ;;
i*86:OSF1:*:*)
if [ -x /usr/sbin/sysversion ] ; then
echo ${UNAME_MACHINE}-unknown-osf1mk
else
echo ${UNAME_MACHINE}-unknown-osf1
fi
exit ;;
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
exit ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
exit ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
exit ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*[A-Z]90:*:*:*)
echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
exit ;;
CRAY*TS:*:*:*)
echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*T3E:*:*:*)
echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*SV1:*:*:*)
echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
*:UNICOS/mp:*:*)
echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
5000:UNIX_System_V:4.*:*)
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
exit ;;
sparc*:BSD/OS:*:*)
echo sparc-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:BSD/OS:*:*)
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:FreeBSD:*:*)
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:
fstrm-0.2.0/build-aux/config.sub 0000755 0001750 0001750 00000105634 12427010213 013443 0000000 0000000 #! /bin/sh
# Configuration validation subroutine script.
# Copyright 1992-2014 Free Software Foundation, Inc.
timestamp='2014-05-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").
# Please send patches with a ChangeLog entry to config-patches@gnu.org.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
# Each package is responsible for reporting which valid configurations
# it does not support. The user should be able to distinguish
# a failure to support a valid configuration from a meaningless
# configuration.
# The goal of this file is to map all the various variations of a given
# machine specification into a single specification in the form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or in some cases, the newer four-part form:
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS
$0 [OPTION] ALIAS
Canonicalize a configuration name.
Operation modes:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to ."
version="\
GNU config.sub ($timestamp)
Copyright 1992-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."
help="
Try \`$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help"
exit 1 ;;
*local*)
# First pass through any local machine types.
echo $1
exit ;;
* )
break ;;
esac
done
case $# in
0) echo "$me: missing argument$help" >&2
exit 1;;
1) ;;
*) echo "$me: too many arguments$help" >&2
exit 1;;
esac
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
knetbsd*-gnu* | netbsd*-gnu* | \
kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
android-linux)
os=-linux-android
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
then os=`echo $1 | sed 's/.*-/-/'`
else os=; fi
;;
esac
### Let's recognize common machines as not being operating systems so
### that things like config.sub decstation-3100 work. We also
### recognize some manufacturers as not being operating systems, so we
### can provide default operating systems below.
case $os in
-sun*os*)
# Prevent following clause from handling this invalid input.
;;
-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple | -axis | -knuth | -cray | -microblaze*)
os=
basic_machine=$1
;;
-bluegene*)
os=-cnk
;;
-sim | -cisco | -oki | -wec | -winbond)
os=
basic_machine=$1
;;
-scout)
;;
-wrs)
os=-vxworks
basic_machine=$1
;;
-chorusos*)
os=-chorusos
basic_machine=$1
;;
-chorusrdb)
os=-chorusrdb
basic_machine=$1
;;
-hiux*)
os=-hiuxwe2
;;
-sco6)
os=-sco5v6
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5)
os=-sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco4)
os=-sco3.2v4
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2.[4-9]*)
os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco3.2v[4-9]*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5v6*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco*)
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-udk*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-isc)
os=-isc2.2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-clix*)
basic_machine=clipper-intergraph
;;
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-lynx*178)
os=-lynxos178
;;
-lynx*5)
os=-lynxos5
;;
-lynx*)
os=-lynxos
;;
-ptx*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
;;
-windowsnt*)
os=`echo $os | sed -e 's/windowsnt/winnt/'`
;;
-psos*)
os=-psos
;;
-mint | -mint[0-9]*)
basic_machine=m68k-atari
os=-mint
;;
esac
# Decode aliases for certain CPU-COMPANY combinations.
case $basic_machine in
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
| aarch64 | aarch64_be \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arceb \
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
| avr | avr32 \
| be32 | be64 \
| bfin \
| c4x | c8051 | clipper \
| d10v | d30v | dlx | dsp16xx \
| epiphany \
| fido | fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| k1om \
| le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
| mips64octeon | mips64octeonel \
| mips64orion | mips64orionel \
| mips64r5900 | mips64r5900el \
| mips64vr | mips64vrel \
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa32r6 | mipsisa32r6el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64r6 | mipsisa64r6el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipsr5900 | mipsr5900el \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| moxie \
| mt \
| msp430 \
| nds32 | nds32le | nds32be \
| nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
| open8 | or1k | or1knd | or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
| rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
| spu \
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
| ubicom32 \
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| we32k \
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
basic_machine=$basic_machine-unknown
;;
c54x)
basic_machine=tic54x-unknown
;;
c55x)
basic_machine=tic55x-unknown
;;
c6x)
basic_machine=tic6x-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
;;
ms1)
basic_machine=mt-unknown
;;
strongarm | thumb | xscale)
basic_machine=arm-unknown
;;
xgate)
basic_machine=$basic_machine-unknown
os=-none
;;
xscaleeb)
basic_machine=armeb-unknown
;;
xscaleel)
basic_machine=armel-unknown
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
i*86 | x86_64)
basic_machine=$basic_machine-pc
;;
# Object if more than one company name word.
*-*-*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
;;
# Recognize the basic CPU types with company name.
580-* \
| a29k-* \
| aarch64-* | aarch64_be-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
| c8051-* | clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
| k1om-* \
| le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
| microblaze-* | microblazeel-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
| mips64octeon-* | mips64octeonel-* \
| mips64orion-* | mips64orionel-* \
| mips64r5900-* | mips64r5900el-* \
| mips64vr-* | mips64vrel-* \
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa32r6-* | mipsisa32r6el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64r6-* | mipsisa64r6el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipsr5900-* | mipsr5900el-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
| nds32-* | nds32le-* | nds32be-* \
| nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
| or1k*-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
| rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
| tahoe-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tile*-* \
| tron-* \
| ubicom32-* \
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
| vax-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
| ymp-* \
| z8k-* | z80-*)
;;
# Recognize the basic CPU types without company name, with glob match.
xtensa*)
basic_machine=$basic_machine-unknown
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
386bsd)
basic_machine=i386-unknown
os=-bsd
;;
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
basic_machine=m68000-att
;;
3b*)
basic_machine=we32k-att
;;
a29khif)
basic_machine=a29k-amd
os=-udi
;;
abacus)
basic_machine=abacus-unknown
;;
adobe68k)
basic_machine=m68010-adobe
os=-scout
;;
alliant | fx80)
basic_machine=fx80-alliant
;;
altos | altos3068)
basic_machine=m68k-altos
;;
am29k)
basic_machine=a29k-none
os=-bsd
;;
amd64)
basic_machine=x86_64-pc
;;
amd64-*)
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
amdahl)
basic_machine=580-amdahl
os=-sysv
;;
amiga | amiga-*)
basic_machine=m68k-unknown
;;
amigaos | amigados)
basic_machine=m68k-unknown
os=-amigaos
;;
amigaunix | amix)
basic_machine=m68k-unknown
os=-sysv4
;;
apollo68)
basic_machine=m68k-apollo
os=-sysv
;;
apollo68bsd)
basic_machine=m68k-apollo
os=-bsd
;;
aros)
basic_machine=i386-pc
os=-aros
;;
aux)
basic_machine=m68k-apple
os=-aux
;;
balance)
basic_machine=ns32k-sequent
os=-dynix
;;
blackfin)
basic_machine=bfin-unknown
os=-linux
;;
blackfin-*)
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
bluegene*)
basic_machine=powerpc-ibm
os=-cnk
;;
c54x-*)
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c55x-*)
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c6x-*)
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c90)
basic_machine=c90-cray
os=-unicos
;;
cegcc)
basic_machine=arm-unknown
os=-cegcc
;;
convex-c1)
basic_machine=c1-convex
os=-bsd
;;
convex-c2)
basic_machine=c2-convex
os=-bsd
;;
convex-c32)
basic_machine=c32-convex
os=-bsd
;;
convex-c34)
basic_machine=c34-convex
os=-bsd
;;
convex-c38)
basic_machine=c38-convex
os=-bsd
;;
cray | j90)
basic_machine=j90-cray
os=-unicos
;;
craynv)
basic_machine=craynv-cray
os=-unicosmp
;;
cr16 | cr16-*)
basic_machine=cr16-unknown
os=-elf
;;
crds | unos)
basic_machine=m68k-crds
;;
crisv32 | crisv32-* | etraxfs*)
basic_machine=crisv32-axis
;;
cris | cris-* | etrax*)
basic_machine=cris-axis
;;
crx)
basic_machine=crx-unknown
os=-elf
;;
da30 | da30-*)
basic_machine=m68k-da30
;;
decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
basic_machine=mips-dec
;;
decsystem10* | dec10*)
basic_machine=pdp10-dec
os=-tops10
;;
decsystem20* | dec20*)
basic_machine=pdp10-dec
os=-tops20
;;
delta | 3300 | motorola-3300 | motorola-delta \
| 3300-motorola | delta-motorola)
basic_machine=m68k-motorola
;;
delta88)
basic_machine=m88k-motorola
os=-sysv3
;;
dicos)
basic_machine=i686-pc
os=-dicos
;;
djgpp)
basic_machine=i586-pc
os=-msdosdjgpp
;;
dpx20 | dpx20-*)
basic_machine=rs6000-bull
os=-bosx
;;
dpx2* | dpx2*-bull)
basic_machine=m68k-bull
os=-sysv3
;;
ebmon29k)
basic_machine=a29k-amd
os=-ebmon
;;
elxsi)
basic_machine=elxsi-elxsi
os=-bsd
;;
encore | umax | mmax)
basic_machine=ns32k-encore
;;
es1800 | OSE68k | ose68k | ose | OSE)
basic_machine=m68k-ericsson
os=-ose
;;
fx2800)
basic_machine=i860-alliant
;;
genix)
basic_machine=ns32k-ns
;;
gmicro)
basic_machine=tron-gmicro
os=-sysv
;;
go32)
basic_machine=i386-pc
os=-go32
;;
h3050r* | hiux*)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
;;
h8300hms)
basic_machine=h8300-hitachi
os=-hms
;;
h8300xray)
basic_machine=h8300-hitachi
os=-xray
;;
h8500hms)
basic_machine=h8500-hitachi
os=-hms
;;
harris)
basic_machine=m88k-harris
os=-sysv3
;;
hp300-*)
basic_machine=m68k-hp
;;
hp300bsd)
basic_machine=m68k-hp
os=-bsd
;;
hp300hpux)
basic_machine=m68k-hp
os=-hpux
;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hp9k2[0-9][0-9] | hp9k31[0-9])
basic_machine=m68000-hp
;;
hp9k3[2-9][0-9])
basic_machine=m68k-hp
;;
hp9k6[0-9][0-9] | hp6[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hp9k7[0-79][0-9] | hp7[0-79][0-9])
basic_machine=hppa1.1-hp
;;
hp9k78[0-9] | hp78[0-9])
# FIXME: really hppa2.0-hp
basic_machine=hppa1.1-hp
;;
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
# FIXME: really hppa2.0-hp
basic_machine=hppa1.1-hp
;;
hp9k8[0-9][13679] | hp8[0-9][13679])
basic_machine=hppa1.1-hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
basic_machine=hppa1.0-hp
;;
hppa-next)
os=-nextstep3
;;
hppaosf)
basic_machine=hppa1.1-hp
os=-osf
;;
hppro)
basic_machine=hppa1.1-hp
os=-proelf
;;
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
;;
i*86v4*)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv4
;;
i*86v)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv
;;
i*86sol2)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-solaris2
;;
i386mach)
basic_machine=i386-mach
os=-mach
;;
i386-vsta | vsta)
basic_machine=i386-unknown
os=-vsta
;;
iris | iris4d)
basic_machine=mips-sgi
case $os in
-irix*)
;;
*)
os=-irix4
;;
esac
;;
isi68 | isi)
basic_machine=m68k-isi
os=-sysv
;;
m68knommu)
basic_machine=m68k-unknown
os=-linux
;;
m68knommu-*)
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
m88k-omron*)
basic_machine=m88k-omron
;;
magnum | m3230)
basic_machine=mips-mips
os=-sysv
;;
merlin)
basic_machine=ns32k-utek
os=-sysv
;;
microblaze*)
basic_machine=microblaze-xilinx
;;
mingw64)
basic_machine=x86_64-pc
os=-mingw64
;;
mingw32)
basic_machine=i686-pc
os=-mingw32
;;
mingw32ce)
basic_machine=arm-unknown
os=-mingw32ce
;;
miniframe)
basic_machine=m68000-convergent
;;
*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
basic_machine=m68k-atari
os=-mint
;;
mips3*-*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
;;
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
monitor)
basic_machine=m68k-rom68k
os=-coff
;;
morphos)
basic_machine=powerpc-unknown
os=-morphos
;;
msdos)
basic_machine=i386-pc
os=-msdos
;;
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
msys)
basic_machine=i686-pc
os=-msys
;;
mvs)
basic_machine=i370-ibm
os=-mvs
;;
nacl)
basic_machine=le32-unknown
os=-nacl
;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
;;
netbsd386)
basic_machine=i386-unknown
os=-netbsd
;;
netwinder)
basic_machine=armv4l-rebel
os=-linux
;;
news | news700 | news800 | news900)
basic_machine=m68k-sony
os=-newsos
;;
news1000)
basic_machine=m68030-sony
os=-newsos
;;
news-3600 | risc-news)
basic_machine=mips-sony
os=-newsos
;;
necv70)
basic_machine=v70-nec
os=-sysv
;;
next | m*-next )
basic_machine=m68k-next
case $os in
-nextstep* )
;;
-ns2*)
os=-nextstep2
;;
*)
os=-nextstep3
;;
esac
;;
nh3000)
basic_machine=m68k-harris
os=-cxux
;;
nh[45]000)
basic_machine=m88k-harris
os=-cxux
;;
nindy960)
basic_machine=i960-intel
os=-nindy
;;
mon960)
basic_machine=i960-intel
os=-mon960
;;
nonstopux)
basic_machine=mips-compaq
os=-nonstopux
;;
np1)
basic_machine=np1-gould
;;
neo-tandem)
basic_machine=neo-tandem
;;
nse-tandem)
basic_machine=nse-tandem
;;
nsr-tandem)
basic_machine=nsr-tandem
;;
op50n-* | op60c-*)
basic_machine=hppa1.1-oki
os=-proelf
;;
openrisc | openrisc-*)
basic_machine=or32-unknown
;;
os400)
basic_machine=powerpc-ibm
os=-os400
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
os=-ose
;;
os68k)
basic_machine=m68k-none
os=-os68k
;;
pa-hitachi)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
;;
paragon)
basic_machine=i860-intel
os=-osf
;;
parisc)
basic_machine=hppa-unknown
os=-linux
;;
parisc-*)
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
pbd)
basic_machine=sparc-tti
;;
pbb)
basic_machine=m68k-tti
;;
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
pc98)
basic_machine=i386-pc
;;
pc98-*)
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium | p5 | k5 | k6 | nexgen | viac3)
basic_machine=i586-pc
;;
pentiumpro | p6 | 6x86 | athlon | athlon_*)
basic_machine=i686-pc
;;
pentiumii | pentium2 | pentiumiii | pentium3)
basic_machine=i686-pc
;;
pentium4)
basic_machine=i786-pc
;;
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumpro-* | p6-* | 6x86-* | athlon-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium4-*)
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pn)
basic_machine=pn-gould
;;
power) basic_machine=power-ibm
;;
ppc | ppcbe) basic_machine=powerpc-unknown
;;
ppc-* | ppcbe-*)
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
;;
ppcle-* | powerpclittle-*)
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64) basic_machine=powerpc64-unknown
;;
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
basic_machine=powerpc64le-unknown
;;
ppc64le-* | powerpc64little-*)
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ps2)
basic_machine=i386-ibm
;;
pw32)
basic_machine=i586-unknown
os=-pw32
;;
rdos | rdos64)
basic_machine=x86_64-pc
os=-rdos
;;
rdos32)
basic_machine=i386-pc
os=-rdos
;;
rom68k)
basic_machine=m68k-rom68k
os=-coff
;;
rm[46]00)
basic_machine=mips-siemens
;;
rtpc | rtpc-*)
basic_machine=romp-ibm
;;
s390 | s390-*)
basic_machine=s390-ibm
;;
s390x | s390x-*)
basic_machine=s390x-ibm
;;
sa29200)
basic_machine=a29k-amd
os=-udi
;;
sb1)
basic_machine=mipsisa64sb1-unknown
;;
sb1el)
basic_machine=mipsisa64sb1el-unknown
;;
sde)
basic_machine=mipsisa32-sde
os=-elf
;;
sei)
basic_machine=mips-sei
os=-seiux
;;
sequent)
basic_machine=i386-sequent
;;
sh)
basic_machine=sh-hitachi
os=-hms
;;
sh5el)
basic_machine=sh5le-unknown
;;
sh64)
basic_machine=sh64-unknown
;;
sparclite-wrs | simso-wrs)
basic_machine=sparclite-wrs
os=-vxworks
;;
sps7)
basic_machine=m68k-bull
os=-sysv2
;;
spur)
basic_machine=spur-unknown
;;
st2000)
basic_machine=m68k-tandem
;;
stratus)
basic_machine=i860-stratus
os=-sysv4
;;
strongarm-* | thumb-*)
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
sun2)
basic_machine=m68000-sun
;;
sun2os3)
basic_machine=m68000-sun
os=-sunos3
;;
sun2os4)
basic_machine=m68000-sun
os=-sunos4
;;
sun3os3)
basic_machine=m68k-sun
os=-sunos3
;;
sun3os4)
basic_machine=m68k-sun
os=-sunos4
;;
sun4os3)
basic_machine=sparc-sun
os=-sunos3
;;
sun4os4)
basic_machine=sparc-sun
os=-sunos4
;;
sun4sol2)
basic_machine=sparc-sun
os=-solaris2
;;
sun3 | sun3-*)
basic_machine=m68k-sun
;;
sun4)
basic_machine=sparc-sun
;;
sun386 | sun386i | roadrunner)
basic_machine=i386-sun
;;
sv1)
basic_machine=sv1-cray
os=-unicos
;;
symmetry)
basic_machine=i386-sequent
os=-dynix
;;
t3e)
basic_machine=alphaev5-cray
os=-unicos
;;
t90)
basic_machine=t90-cray
os=-unicos
;;
tile*)
basic_machine=$basic_machine-unknown
os=-linux-gnu
;;
tx39)
basic_machine=mipstx39-unknown
;;
tx39el)
basic_machine=mipstx39el-unknown
;;
toad1)
basic_machine=pdp10-xkl
os=-tops20
;;
tower | tower-32)
basic_machine=m68k-ncr
;;
tpf)
basic_machine=s390x-ibm
os=-tpf
;;
udi29k)
basic_machine=a29k-amd
os=-udi
;;
ultra3)
basic_machine=a29k-nyu
os=-sym1
;;
v810 | necv810)
basic_machine=v810-nec
os=-none
;;
vaxv)
basic_machine=vax-dec
os=-sysv
;;
vms)
basic_machine=vax-dec
os=-vms
;;
vpp*|vx|vx-*)
basic_machine=f301-fujitsu
;;
vxworks960)
basic_machine=i960-wrs
os=-vxworks
;;
vxworks68)
basic_machine=m68k-wrs
os=-vxworks
;;
vxworks29k)
basic_machine=a29k-wrs
os=-vxworks
;;
w65*)
basic_machine=w65-wdc
os=-none
;;
w89k-*)
basic_machine=hppa1.1-winbond
os=-proelf
;;
xbox)
basic_machine=i686-pc
os=-mingw32
;;
xps | xps100)
basic_machine=xps100-honeywell
;;
xscale-* | xscalee[bl]-*)
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
;;
ymp)
basic_machine=ymp-cray
os=-unicos
;;
z8k-*-coff)
basic_machine=z8k-unknown
os=-sim
;;
z80-*-coff)
basic_machine=z80-unknown
os=-sim
;;
none)
basic_machine=none-none
os=-none
;;
# Here we handle the default manufacturer of certain CPU types. It is in
# some cases the only manufacturer, in others, it is the most popular.
w89k)
basic_machine=hppa1.1-winbond
;;
op50n)
basic_machine=hppa1.1-oki
;;
op60c)
basic_machine=hppa1.1-oki
;;
romp)
basic_machine=romp-ibm
;;
mmix)
basic_machine=mmix-knuth
;;
rs6000)
basic_machine=rs6000-ibm
;;
vax)
basic_machine=vax-dec
;;
pdp10)
# there are many clones, so DEC is not a safe bet
basic_machine=pdp10-unknown
;;
pdp11)
basic_machine=pdp11-dec
;;
we32k)
basic_machine=we32k-att
;;
sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
basic_machine=sparc-sun
;;
cydra)
basic_machine=cydra-cydrome
;;
orion)
basic_machine=orion-highlevel
;;
orion105)
basic_machine=clipper-highlevel
;;
mac | mpw | mac-mpw)
basic_machine=m68k-apple
;;
pmac | pmac-mpw)
basic_machine=powerpc-apple
;;
*-unknown)
# Make sure to match an already-canonicalized machine name.
;;
*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
;;
esac
# Here we canonicalize certain aliases for manufacturers.
case $basic_machine in
*-digital*)
basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
;;
*-commodore*)
basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
;;
*)
;;
esac
# Decode manufacturer-specific aliases for certain operating systems.
if [ x"$os" != x"" ]
then
case $os in
# First match some system type aliases
# that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
-auroraux)
os=-auroraux
;;
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
-solaris)
os=-solaris2
;;
-svr4*)
os=-sysv4
;;
-unixware*)
os=-sysv4.2uw
;;
-gnu/linux*)
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;;
# First accept the basic system types.
# The portable systems comes first.
# Each alternative MUST END IN A *, to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
| -sym* | -kopensolaris* | -plan9* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* | -aros* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
| -bitrig* | -openbsd* | -solidbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* | -cegcc* \
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
case $basic_machine in
x86-* | i*86-*)
;;
*)
os=-nto$os
;;
esac
;;
-nto-qnx*)
;;
-nto*)
os=`echo $os | sed -e 's|nto|nto-qnx|'`
;;
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
;;
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
;;
-linux-dietlibc)
os=-linux-dietlibc
;;
-linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
-sunos5*)
os=`echo $os | sed -e 's|sunos5|solaris2|'`
;;
-sunos6*)
os=`echo $os | sed -e 's|sunos6|solaris3|'`
;;
-opened*)
os=-openedition
;;
-os400*)
os=-os400
;;
-wince*)
os=-wince
;;
-osfrose*)
os=-osfrose
;;
-osf*)
os=-osf
;;
-utek*)
os=-bsd
;;
-dynix*)
os=-bsd
;;
-acis*)
os=-aos
;;
-atheos*)
os=-atheos
;;
-syllable*)
os=-syllable
;;
-386bsd)
os=-bsd
;;
-ctix* | -uts*)
os=-sysv
;;
-nova*)
os=-rtmk-nova
;;
-ns2 )
os=-nextstep2
;;
-nsk*)
os=-nsk
;;
# Preserve the version number of sinix5.
-sinix5.*)
os=`echo $os | sed -e 's|sinix|sysv|'`
;;
-sinix*)
os=-sysv4
;;
-tpf*)
os=-tpf
;;
-triton*)
os=-sysv3
;;
-oss*)
os=-sysv3
;;
-svr4)
os=-sysv4
;;
-svr3)
os=-sysv3
;;
-sysvr4)
os=-sysv4
;;
# This must come after -sysvr4.
-sysv*)
;;
-ose*)
os=-ose
;;
-es1800*)
os=-ose
;;
-xenix)
os=-xenix
;;
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
os=-mint
;;
-aros*)
os=-aros
;;
-zvmoe)
os=-zvmoe
;;
-dicos*)
os=-dicos
;;
-nacl*)
;;
-none)
;;
*)
# Get rid of the `-' at the beginning of $os.
os=`echo $os | sed 's/[^-]*-//'`
echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
exit 1
;;
esac
else
# Here we handle the default operating systems that come with various machines.
# The value should be what the vendor currently ships out the door with their
# machine or put another way, the most popular os provided with the machine.
# Note that if you're going to try to match "-MANUFACTURER" here (say,
# "-sun"), then you have to tell the case statement up towards the top
# that MANUFACTURER isn't an operating system. Otherwise, code above
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.
case $basic_machine in
score-*)
os=-elf
;;
spu-*)
os=-elf
;;
*-acorn)
os=-riscix1.2
;;
arm*-rebel)
os=-linux
;;
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
;;
c8051-*)
os=-elf
;;
hexagon-*)
os=-elf
;;
tic54x-*)
os=-coff
;;
tic55x-*)
os=-coff
;;
tic6x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
os=-tops20
;;
pdp11-*)
os=-none
;;
*-dec | vax-*)
os=-ultrix4.2
;;
m68*-apollo)
os=-domain
;;
i386-sun)
os=-sunos4.0.2
;;
m68000-sun)
os=-sunos3
;;
m68*-cisco)
os=-aout
;;
mep-*)
os=-elf
;;
mips*-cisco)
os=-elf
;;
mips*-*)
os=-elf
;;
or32-*)
os=-coff
;;
*-tti) # must be before sparc entry or we get the wrong os.
os=-sysv3
;;
sparc-* | *-sun)
os=-sunos4.1.1
;;
*-be)
os=-beos
;;
*-haiku)
os=-haiku
;;
*-ibm)
os=-aix
;;
*-knuth)
os=-mmixware
;;
*-wec)
os=-proelf
;;
*-winbond)
os=-proelf
;;
*-oki)
os=-proelf
;;
*-hp)
os=-hpux
;;
*-hitachi)
os=-hiux
;;
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
os=-sysv
;;
*-cbm)
os=-amigaos
;;
*-dg)
os=-dgux
;;
*-dolphin)
os=-sysv3
;;
m68k-ccur)
os=-rtu
;;
m88k-omron*)
os=-luna
;;
*-next )
os=-nextstep
;;
*-sequent)
os=-ptx
;;
*-crds)
os=-unos
;;
*-ns)
os=-genix
;;
i370-*)
os=-mvs
;;
*-next)
os=-nextstep3
;;
*-gould)
os=-sysv
;;
*-highlevel)
os=-bsd
;;
*-encore)
os=-bsd
;;
*-sgi)
os=-irix
;;
*-siemens)
os=-sysv4
;;
*-masscomp)
os=-rtu
;;
f30[01]-fujitsu | f700-fujitsu)
os=-uxpv
;;
*-rom68k)
os=-coff
;;
*-*bug)
os=-coff
;;
*-apple)
os=-macos
;;
*-atari*)
os=-mint
;;
*)
os=-none
;;
esac
fi
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer. We pick the logical manufacturer.
vendor=unknown
case $basic_machine in
*-unknown)
case $os in
-riscix*)
vendor=acorn
;;
-sunos*)
vendor=sun
;;
-cnk*|-aix*)
vendor=ibm
;;
-beos*)
vendor=be
;;
-hpux*)
vendor=hp
;;
-mpeix*)
vendor=hp
;;
-hiux*)
vendor=hitachi
;;
-unos*)
vendor=crds
;;
-dgux*)
vendor=dg
;;
-luna*)
vendor=omron
;;
-genix*)
vendor=ns
;;
-mvs* | -opened*)
vendor=ibm
;;
-os400*)
vendor=ibm
;;
-ptx*)
vendor=sequent
;;
-tpf*)
vendor=ibm
;;
-vxsim* | -vxworks* | -windiss*)
vendor=wrs
;;
-aux*)
vendor=apple
;;
-hms*)
vendor=hitachi
;;
-mpw* | -macos*)
vendor=apple
;;
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
vendor=atari
;;
-vos*)
vendor=stratus
;;
esac
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;;
esac
echo $basic_machine$os
exit
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
fstrm-0.2.0/build-aux/install-sh 0000755 0001750 0001750 00000033255 12427010213 013463 0000000 0000000 #!/bin/sh
# install - install a program, script, or datafile
scriptversion=2011-11-20.07; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
nl='
'
IFS=" "" $nl"
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit=${DOITPROG-}
if test -z "$doit"; then
doit_exec=exec
else
doit_exec=$doit
fi
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_glob='?'
initialize_posix_glob='
test "$posix_glob" != "?" || {
if (set -f) 2>/dev/null; then
posix_glob=
else
posix_glob=:
fi
}
'
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
no_target_directory=
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *' '* | *'
'* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t) dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) no_target_directory=true;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test -n "$no_target_directory"; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
# Prefer dirname, but fall back on a substitute if dirname fails.
dstdir=`
(dirname "$dst") 2>/dev/null ||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$dst" : 'X\(//\)[^/]' \| \
X"$dst" : 'X\(//\)$' \| \
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
echo X"$dst" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'
`
test -d "$dstdir"
dstdir_status=$?
fi
fi
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
eval "$initialize_posix_glob"
oIFS=$IFS
IFS=/
$posix_glob set -f
set fnord $dstdir
shift
$posix_glob set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
eval "$initialize_posix_glob" &&
$posix_glob set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
$posix_glob set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# 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:
fstrm-0.2.0/build-aux/missing 0000755 0001750 0001750 00000015330 12427010213 013050 0000000 0000000 #! /bin/sh
# Common wrapper for a few potentially missing GNU programs.
scriptversion=2013-10-28.13; # UTC
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard , 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, 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.
if test $# -eq 0; then
echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
case $1 in
--is-lightweight)
# Used by our autoconf macros to check whether the available missing
# script is modern enough.
exit 0
;;
--run)
# Back-compat with the calling convention used by older automake.
shift
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal autoconf autoheader autom4te automake makeinfo
bison yacc flex lex help2man
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
'g' are ignored when checking the name.
Send bug reports to ."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: unknown '$1' option"
echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
# Run the given program, remember its exit status.
"$@"; st=$?
# If it succeeded, we are done.
test $st -eq 0 && exit 0
# Also exit now if we it failed (or wasn't found), and '--version' was
# passed; such an option is passed most likely to detect whether the
# program is present and works.
case $2 in --version|--help) exit $st;; esac
# Exit code 63 means version mismatch. This often happens when the user
# tries to use an ancient version of a tool on a file that requires a
# minimum version.
if test $st -eq 63; then
msg="probably too old"
elif test $st -eq 127; then
# Program was missing.
msg="missing on your system"
else
# Program was found and executed, but failed. Give up.
exit $st
fi
perl_URL=http://www.perl.org/
flex_URL=http://flex.sourceforge.net/
gnu_software_URL=http://www.gnu.org/software
program_details ()
{
case $1 in
aclocal|automake)
echo "The '$1' program is part of the GNU Automake package:"
echo "<$gnu_software_URL/automake>"
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/autoconf>"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
autoconf|autom4te|autoheader)
echo "The '$1' program is part of the GNU Autoconf package:"
echo "<$gnu_software_URL/autoconf/>"
echo "It also requires GNU m4 and Perl in order to run:"
echo "<$gnu_software_URL/m4/>"
echo "<$perl_URL>"
;;
esac
}
give_advice ()
{
# Normalize program name to check for.
normalized_program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
printf '%s\n' "'$1' is $msg."
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
case $normalized_program in
autoconf*)
echo "You should only need it if you modified 'configure.ac',"
echo "or m4 files included by it."
program_details 'autoconf'
;;
autoheader*)
echo "You should only need it if you modified 'acconfig.h' or"
echo "$configure_deps."
program_details 'autoheader'
;;
automake*)
echo "You should only need it if you modified 'Makefile.am' or"
echo "$configure_deps."
program_details 'automake'
;;
aclocal*)
echo "You should only need it if you modified 'acinclude.m4' or"
echo "$configure_deps."
program_details 'aclocal'
;;
autom4te*)
echo "You might have modified some maintainer files that require"
echo "the 'autom4te' program to be rebuilt."
program_details 'autom4te'
;;
bison*|yacc*)
echo "You should only need it if you modified a '.y' file."
echo "You may want to install the GNU Bison package:"
echo "<$gnu_software_URL/bison/>"
;;
lex*|flex*)
echo "You should only need it if you modified a '.l' file."
echo "You may want to install the Fast Lexical Analyzer package:"
echo "<$flex_URL>"
;;
help2man*)
echo "You should only need it if you modified a dependency" \
"of a man page."
echo "You may want to install the GNU Help2man package:"
echo "<$gnu_software_URL/help2man/>"
;;
makeinfo*)
echo "You should only need it if you modified a '.texi' file, or"
echo "any other file indirectly affecting the aspect of the manual."
echo "You might want to install the Texinfo package:"
echo "<$gnu_software_URL/texinfo/>"
echo "The spurious makeinfo call might also be the consequence of"
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
echo "want to install GNU make:"
echo "<$gnu_software_URL/make/>"
;;
*)
echo "You might have modified some files without having the proper"
echo "tools for further handling them. Check the 'README' file, it"
echo "often tells you about the needed prerequisites for installing"
echo "this package. You may also peek at any GNU archive site, in"
echo "case some other package contains this missing '$1' program."
;;
esac
}
give_advice "$1" | sed -e '1s/^/WARNING: /' \
-e '2,$s/^/ /' >&2
# Propagate the correct exit status (expected to be 127 for a program
# not found, 63 for a program that failed due to version mismatch).
exit $st
# Local variables:
# 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:
fstrm-0.2.0/build-aux/ltmain.sh 0000644 0001750 0001750 00001052030 12427010207 013273 0000000 0000000
# libtool (GNU libtool) 2.4.2
# Written by Gordon Matzigkeit , 1996
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
# 2007, 2008, 2009, 2010, 2011 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 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 GNU Libtool; see the file COPYING. If not, a copy
# can be downloaded from http://www.gnu.org/licenses/gpl.html,
# or obtained by writing to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Usage: $progname [OPTION]... [MODE-ARG]...
#
# Provide generalized library-building support services.
#
# --config show all configuration variables
# --debug enable verbose shell tracing
# -n, --dry-run display commands without modifying any files
# --features display basic configuration information and exit
# --mode=MODE use operation mode MODE
# --preserve-dup-deps don't remove duplicate dependency libraries
# --quiet, --silent don't print informational messages
# --no-quiet, --no-silent
# print informational messages (default)
# --no-warn don't display warning messages
# --tag=TAG use configuration variables from tag TAG
# -v, --verbose print more informational messages than default
# --no-verbose don't print the extra informational messages
# --version print version information
# -h, --help, --help-all print short, long, or detailed help message
#
# MODE must be one of the following:
#
# clean remove files from the build directory
# compile compile a source file into a libtool object
# execute automatically set library path, then run a program
# finish complete the installation of libtool libraries
# install install libraries or executables
# link create a library or an executable
# uninstall remove libraries from an installed directory
#
# MODE-ARGS vary depending on the MODE. When passed as first option,
# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that.
# Try `$progname --help --mode=MODE' for a more detailed description of MODE.
#
# When reporting a bug, please describe a test case to reproduce it and
# include the following information:
#
# host-triplet: $host
# shell: $SHELL
# compiler: $LTCC
# compiler flags: $LTCFLAGS
# linker: $LD (gnu? $with_gnu_ld)
# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.10
# automake: $automake_version
# autoconf: $autoconf_version
#
# Report bugs to .
# GNU libtool home page: .
# General help using GNU software: .
PROGRAM=libtool
PACKAGE=libtool
VERSION="2.4.2 Debian-2.4.2-1.10"
TIMESTAMP=""
package_revision=1.3337
# Be Bourne compatible
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
# Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
fi
BIN_SH=xpg4; export BIN_SH # for Tru64
DUALCASE=1; export DUALCASE # for MKS sh
# A function that is used when there is no print builtin or printf.
func_fallback_echo ()
{
eval 'cat <<_LTECHO_EOF
$1
_LTECHO_EOF'
}
# NLS nuisances: We save the old values to restore during execute mode.
lt_user_locale=
lt_safe_locale=
for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
do
eval "if test \"\${$lt_var+set}\" = set; then
save_$lt_var=\$$lt_var
$lt_var=C
export $lt_var
lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\"
lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\"
fi"
done
LC_ALL=C
LANGUAGE=C
export LANGUAGE LC_ALL
$lt_unset CDPATH
# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
# is ksh but when the shell is invoked as "sh" and the current value of
# the _XPG environment variable is not equal to 1 (one), the special
# positional parameter $0, within a function call, is the name of the
# function.
progpath="$0"
: ${CP="cp -f"}
test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'}
: ${MAKE="make"}
: ${MKDIR="mkdir"}
: ${MV="mv -f"}
: ${RM="rm -f"}
: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
: ${Xsed="$SED -e 1s/^X//"}
# Global variables:
EXIT_SUCCESS=0
EXIT_FAILURE=1
EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing.
EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake.
exit_status=$EXIT_SUCCESS
# Make sure IFS has a sensible default
lt_nl='
'
IFS=" $lt_nl"
dirname="s,/[^/]*$,,"
basename="s,^.*/,,"
# func_dirname file append nondir_replacement
# Compute the dirname of FILE. If nonempty, add APPEND to the result,
# otherwise set result to NONDIR_REPLACEMENT.
func_dirname ()
{
func_dirname_result=`$ECHO "${1}" | $SED "$dirname"`
if test "X$func_dirname_result" = "X${1}"; then
func_dirname_result="${3}"
else
func_dirname_result="$func_dirname_result${2}"
fi
} # func_dirname may be replaced by extended shell implementation
# func_basename file
func_basename ()
{
func_basename_result=`$ECHO "${1}" | $SED "$basename"`
} # func_basename may be replaced by extended shell implementation
# func_dirname_and_basename file append nondir_replacement
# perform func_basename and func_dirname in a single function
# call:
# dirname: Compute the dirname of FILE. If nonempty,
# add APPEND to the result, otherwise set result
# to NONDIR_REPLACEMENT.
# value returned in "$func_dirname_result"
# basename: Compute filename of FILE.
# value retuned in "$func_basename_result"
# Implementation must be kept synchronized with func_dirname
# and func_basename. For efficiency, we do not delegate to
# those functions but instead duplicate the functionality here.
func_dirname_and_basename ()
{
# Extract subdirectory from the argument.
func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"`
if test "X$func_dirname_result" = "X${1}"; then
func_dirname_result="${3}"
else
func_dirname_result="$func_dirname_result${2}"
fi
func_basename_result=`$ECHO "${1}" | $SED -e "$basename"`
} # func_dirname_and_basename may be replaced by extended shell implementation
# func_stripname 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).
# func_strip_suffix prefix name
func_stripname ()
{
case ${2} in
.*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
esac
} # func_stripname may be replaced by extended shell implementation
# These SED scripts presuppose an absolute path with a trailing slash.
pathcar='s,^/\([^/]*\).*$,\1,'
pathcdr='s,^/[^/]*,,'
removedotparts=':dotsl
s@/\./@/@g
t dotsl
s,/\.$,/,'
collapseslashes='s@/\{1,\}@/@g'
finalslash='s,/*$,/,'
# func_normal_abspath PATH
# Remove doubled-up and trailing slashes, "." path components,
# and cancel out any ".." path components in PATH after making
# it an absolute path.
# value returned in "$func_normal_abspath_result"
func_normal_abspath ()
{
# Start from root dir and reassemble the path.
func_normal_abspath_result=
func_normal_abspath_tpath=$1
func_normal_abspath_altnamespace=
case $func_normal_abspath_tpath in
"")
# Empty path, that just means $cwd.
func_stripname '' '/' "`pwd`"
func_normal_abspath_result=$func_stripname_result
return
;;
# The next three entries are used to spot a run of precisely
# two leading slashes without using negated character classes;
# we take advantage of case's first-match behaviour.
///*)
# Unusual form of absolute path, do nothing.
;;
//*)
# Not necessarily an ordinary path; POSIX reserves leading '//'
# and for example Cygwin uses it to access remote file shares
# over CIFS/SMB, so we conserve a leading double slash if found.
func_normal_abspath_altnamespace=/
;;
/*)
# Absolute path, do nothing.
;;
*)
# Relative path, prepend $cwd.
func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath
;;
esac
# Cancel out all the simple stuff to save iterations. We also want
# the path to end with a slash for ease of parsing, so make sure
# there is one (and only one) here.
func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
-e "$removedotparts" -e "$collapseslashes" -e "$finalslash"`
while :; do
# Processed it all yet?
if test "$func_normal_abspath_tpath" = / ; then
# If we ascended to the root using ".." the result may be empty now.
if test -z "$func_normal_abspath_result" ; then
func_normal_abspath_result=/
fi
break
fi
func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \
-e "$pathcar"`
func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
-e "$pathcdr"`
# Figure out what to do with it
case $func_normal_abspath_tcomponent in
"")
# Trailing empty path component, ignore it.
;;
..)
# Parent dir; strip last assembled component from result.
func_dirname "$func_normal_abspath_result"
func_normal_abspath_result=$func_dirname_result
;;
*)
# Actual path component, append it.
func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent
;;
esac
done
# Restore leading double-slash if one was found on entry.
func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result
}
# func_relative_path SRCDIR DSTDIR
# generates a relative path from SRCDIR to DSTDIR, with a trailing
# slash if non-empty, suitable for immediately appending a filename
# without needing to append a separator.
# value returned in "$func_relative_path_result"
func_relative_path ()
{
func_relative_path_result=
func_normal_abspath "$1"
func_relative_path_tlibdir=$func_normal_abspath_result
func_normal_abspath "$2"
func_relative_path_tbindir=$func_normal_abspath_result
# Ascend the tree starting from libdir
while :; do
# check if we have found a prefix of bindir
case $func_relative_path_tbindir in
$func_relative_path_tlibdir)
# found an exact match
func_relative_path_tcancelled=
break
;;
$func_relative_path_tlibdir*)
# found a matching prefix
func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir"
func_relative_path_tcancelled=$func_stripname_result
if test -z "$func_relative_path_result"; then
func_relative_path_result=.
fi
break
;;
*)
func_dirname $func_relative_path_tlibdir
func_relative_path_tlibdir=${func_dirname_result}
if test "x$func_relative_path_tlibdir" = x ; then
# Have to descend all the way to the root!
func_relative_path_result=../$func_relative_path_result
func_relative_path_tcancelled=$func_relative_path_tbindir
break
fi
func_relative_path_result=../$func_relative_path_result
;;
esac
done
# Now calculate path; take care to avoid doubling-up slashes.
func_stripname '' '/' "$func_relative_path_result"
func_relative_path_result=$func_stripname_result
func_stripname '/' '/' "$func_relative_path_tcancelled"
if test "x$func_stripname_result" != x ; then
func_relative_path_result=${func_relative_path_result}/${func_stripname_result}
fi
# Normalisation. If bindir is libdir, return empty string,
# else relative path ending with a slash; either way, target
# file name can be directly appended.
if test ! -z "$func_relative_path_result"; then
func_stripname './' '' "$func_relative_path_result/"
func_relative_path_result=$func_stripname_result
fi
}
# The name of this program:
func_dirname_and_basename "$progpath"
progname=$func_basename_result
# Make sure we have an absolute path for reexecution:
case $progpath in
[\\/]*|[A-Za-z]:\\*) ;;
*[\\/]*)
progdir=$func_dirname_result
progdir=`cd "$progdir" && pwd`
progpath="$progdir/$progname"
;;
*)
save_IFS="$IFS"
IFS=${PATH_SEPARATOR-:}
for progdir in $PATH; do
IFS="$save_IFS"
test -x "$progdir/$progname" && break
done
IFS="$save_IFS"
test -n "$progdir" || progdir=`pwd`
progpath="$progdir/$progname"
;;
esac
# Sed substitution that helps us do robust quoting. It backslashifies
# metacharacters that are still active within double-quoted strings.
Xsed="${SED}"' -e 1s/^X//'
sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
# Same as above, but do not quote variable references.
double_quote_subst='s/\(["`\\]\)/\\\1/g'
# Sed substitution that turns a string into a regex matching for the
# string literally.
sed_make_literal_regex='s,[].[^$\\*\/],\\&,g'
# Sed substitution that converts a w32 file name or path
# which contains forward slashes, into one that contains
# (escaped) backslashes. A very naive implementation.
lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
# Re-`\' parameter expansions in output of double_quote_subst that were
# `\'-ed in input to the same. If an odd number of `\' preceded a '$'
# in input to double_quote_subst, that '$' was protected from expansion.
# Since each input `\' is now two `\'s, look for any number of runs of
# four `\'s followed by two `\'s and then a '$'. `\' that '$'.
bs='\\'
bs2='\\\\'
bs4='\\\\\\\\'
dollar='\$'
sed_double_backslash="\
s/$bs4/&\\
/g
s/^$bs2$dollar/$bs&/
s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g
s/\n//g"
# Standard options:
opt_dry_run=false
opt_help=false
opt_quiet=false
opt_verbose=false
opt_warning=:
# func_echo arg...
# Echo program name prefixed message, along with the current mode
# name if it has been set yet.
func_echo ()
{
$ECHO "$progname: ${opt_mode+$opt_mode: }$*"
}
# func_verbose arg...
# Echo program name prefixed message in verbose mode only.
func_verbose ()
{
$opt_verbose && func_echo ${1+"$@"}
# A bug in bash halts the script if the last line of a function
# fails when set -e is in force, so we need another command to
# work around that:
:
}
# func_echo_all arg...
# Invoke $ECHO with all args, space-separated.
func_echo_all ()
{
$ECHO "$*"
}
# func_error arg...
# Echo program name prefixed message to standard error.
func_error ()
{
$ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
}
# func_warning arg...
# Echo program name prefixed warning message to standard error.
func_warning ()
{
$opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
# bash bug again:
:
}
# func_fatal_error arg...
# Echo program name prefixed message to standard error, and exit.
func_fatal_error ()
{
func_error ${1+"$@"}
exit $EXIT_FAILURE
}
# func_fatal_help arg...
# Echo program name prefixed message to standard error, followed by
# a help hint, and exit.
func_fatal_help ()
{
func_error ${1+"$@"}
func_fatal_error "$help"
}
help="Try \`$progname --help' for more information." ## default
# func_grep expression filename
# Check whether EXPRESSION matches any line of FILENAME, without output.
func_grep ()
{
$GREP "$1" "$2" >/dev/null 2>&1
}
# func_mkdir_p directory-path
# Make sure the entire path to DIRECTORY-PATH is available.
func_mkdir_p ()
{
my_directory_path="$1"
my_dir_list=
if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then
# Protect directory names starting with `-'
case $my_directory_path in
-*) my_directory_path="./$my_directory_path" ;;
esac
# While some portion of DIR does not yet exist...
while test ! -d "$my_directory_path"; do
# ...make a list in topmost first order. Use a colon delimited
# list incase some portion of path contains whitespace.
my_dir_list="$my_directory_path:$my_dir_list"
# If the last portion added has no slash in it, the list is done
case $my_directory_path in */*) ;; *) break ;; esac
# ...otherwise throw away the child directory and loop
my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"`
done
my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'`
save_mkdir_p_IFS="$IFS"; IFS=':'
for my_dir in $my_dir_list; do
IFS="$save_mkdir_p_IFS"
# mkdir can fail with a `File exist' error if two processes
# try to create one of the directories concurrently. Don't
# stop in that case!
$MKDIR "$my_dir" 2>/dev/null || :
done
IFS="$save_mkdir_p_IFS"
# Bail out if we (or some other process) failed to create a directory.
test -d "$my_directory_path" || \
func_fatal_error "Failed to create \`$1'"
fi
}
# func_mktempdir [string]
# Make a temporary directory that won't clash with other running
# libtool processes, and avoids race conditions if possible. If
# given, STRING is the basename for that directory.
func_mktempdir ()
{
my_template="${TMPDIR-/tmp}/${1-$progname}"
if test "$opt_dry_run" = ":"; then
# Return a directory name, but don't create it in dry-run mode
my_tmpdir="${my_template}-$$"
else
# If mktemp works, use that first and foremost
my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
if test ! -d "$my_tmpdir"; then
# Failing that, at least try and use $RANDOM to avoid a race
my_tmpdir="${my_template}-${RANDOM-0}$$"
save_mktempdir_umask=`umask`
umask 0077
$MKDIR "$my_tmpdir"
umask $save_mktempdir_umask
fi
# If we're not in dry-run mode, bomb out on failure
test -d "$my_tmpdir" || \
func_fatal_error "cannot create temporary directory \`$my_tmpdir'"
fi
$ECHO "$my_tmpdir"
}
# func_quote_for_eval arg
# Aesthetically quote ARG to be evaled later.
# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT
# is double-quoted, suitable for a subsequent eval, whereas
# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters
# which are still active within double quotes backslashified.
func_quote_for_eval ()
{
case $1 in
*[\\\`\"\$]*)
func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;;
*)
func_quote_for_eval_unquoted_result="$1" ;;
esac
case $func_quote_for_eval_unquoted_result in
# Double-quote args containing shell metacharacters to delay
# word splitting, command substitution and and variable
# expansion for a subsequent eval.
# Many Bourne shells cannot handle close brackets correctly
# in scan sets, so we specify it separately.
*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\""
;;
*)
func_quote_for_eval_result="$func_quote_for_eval_unquoted_result"
esac
}
# func_quote_for_expand arg
# Aesthetically quote ARG to be evaled later; same as above,
# but do not quote variable references.
func_quote_for_expand ()
{
case $1 in
*[\\\`\"]*)
my_arg=`$ECHO "$1" | $SED \
-e "$double_quote_subst" -e "$sed_double_backslash"` ;;
*)
my_arg="$1" ;;
esac
case $my_arg in
# Double-quote args containing shell metacharacters to delay
# word splitting and command substitution for a subsequent eval.
# Many Bourne shells cannot handle close brackets correctly
# in scan sets, so we specify it separately.
*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
my_arg="\"$my_arg\""
;;
esac
func_quote_for_expand_result="$my_arg"
}
# func_show_eval cmd [fail_exp]
# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is
# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
# is given, then evaluate it.
func_show_eval ()
{
my_cmd="$1"
my_fail_exp="${2-:}"
${opt_silent-false} || {
func_quote_for_expand "$my_cmd"
eval "func_echo $func_quote_for_expand_result"
}
if ${opt_dry_run-false}; then :; else
eval "$my_cmd"
my_status=$?
if test "$my_status" -eq 0; then :; else
eval "(exit $my_status); $my_fail_exp"
fi
fi
}
# func_show_eval_locale cmd [fail_exp]
# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is
# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
# is given, then evaluate it. Use the saved locale for evaluation.
func_show_eval_locale ()
{
my_cmd="$1"
my_fail_exp="${2-:}"
${opt_silent-false} || {
func_quote_for_expand "$my_cmd"
eval "func_echo $func_quote_for_expand_result"
}
if ${opt_dry_run-false}; then :; else
eval "$lt_user_locale
$my_cmd"
my_status=$?
eval "$lt_safe_locale"
if test "$my_status" -eq 0; then :; else
eval "(exit $my_status); $my_fail_exp"
fi
fi
}
# func_tr_sh
# Turn $1 into a string suitable for a shell variable name.
# Result is stored in $func_tr_sh_result. All characters
# not in the set a-zA-Z0-9_ are replaced with '_'. Further,
# if $1 begins with a digit, a '_' is prepended as well.
func_tr_sh ()
{
case $1 in
[0-9]* | *[!a-zA-Z0-9_]*)
func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'`
;;
* )
func_tr_sh_result=$1
;;
esac
}
# func_version
# Echo version message to standard output and exit.
func_version ()
{
$opt_debug
$SED -n '/(C)/!b go
:more
/\./!{
N
s/\n# / /
b more
}
:go
/^# '$PROGRAM' (GNU /,/# warranty; / {
s/^# //
s/^# *$//
s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/
p
}' < "$progpath"
exit $?
}
# func_usage
# Echo short help message to standard output and exit.
func_usage ()
{
$opt_debug
$SED -n '/^# Usage:/,/^# *.*--help/ {
s/^# //
s/^# *$//
s/\$progname/'$progname'/
p
}' < "$progpath"
echo
$ECHO "run \`$progname --help | more' for full usage"
exit $?
}
# func_help [NOEXIT]
# Echo long help message to standard output and exit,
# unless 'noexit' is passed as argument.
func_help ()
{
$opt_debug
$SED -n '/^# Usage:/,/# Report bugs to/ {
:print
s/^# //
s/^# *$//
s*\$progname*'$progname'*
s*\$host*'"$host"'*
s*\$SHELL*'"$SHELL"'*
s*\$LTCC*'"$LTCC"'*
s*\$LTCFLAGS*'"$LTCFLAGS"'*
s*\$LD*'"$LD"'*
s/\$with_gnu_ld/'"$with_gnu_ld"'/
s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/
s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/
p
d
}
/^# .* home page:/b print
/^# General help using/b print
' < "$progpath"
ret=$?
if test -z "$1"; then
exit $ret
fi
}
# func_missing_arg argname
# Echo program name prefixed message to standard error and set global
# exit_cmd.
func_missing_arg ()
{
$opt_debug
func_error "missing argument for $1."
exit_cmd=exit
}
# func_split_short_opt shortopt
# Set func_split_short_opt_name and func_split_short_opt_arg shell
# variables after splitting SHORTOPT after the 2nd character.
func_split_short_opt ()
{
my_sed_short_opt='1s/^\(..\).*$/\1/;q'
my_sed_short_rest='1s/^..\(.*\)$/\1/;q'
func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"`
func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"`
} # func_split_short_opt may be replaced by extended shell implementation
# func_split_long_opt longopt
# Set func_split_long_opt_name and func_split_long_opt_arg shell
# variables after splitting LONGOPT at the `=' sign.
func_split_long_opt ()
{
my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q'
my_sed_long_arg='1s/^--[^=]*=//'
func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"`
func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"`
} # func_split_long_opt may be replaced by extended shell implementation
exit_cmd=:
magic="%%%MAGIC variable%%%"
magic_exe="%%%MAGIC EXE variable%%%"
# Global variables.
nonopt=
preserve_args=
lo2o="s/\\.lo\$/.${objext}/"
o2lo="s/\\.${objext}\$/.lo/"
extracted_archives=
extracted_serial=0
# If this variable is set in any of the actions, the command in it
# will be execed at the end. This prevents here-documents from being
# left over by shells.
exec_cmd=
# func_append var value
# Append VALUE to the end of shell variable VAR.
func_append ()
{
eval "${1}=\$${1}\${2}"
} # func_append may be replaced by extended shell implementation
# func_append_quoted var value
# Quote VALUE and append to the end of shell variable VAR, separated
# by a space.
func_append_quoted ()
{
func_quote_for_eval "${2}"
eval "${1}=\$${1}\\ \$func_quote_for_eval_result"
} # func_append_quoted may be replaced by extended shell implementation
# func_arith arithmetic-term...
func_arith ()
{
func_arith_result=`expr "${@}"`
} # func_arith may be replaced by extended shell implementation
# func_len string
# STRING may not start with a hyphen.
func_len ()
{
func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len`
} # func_len may be replaced by extended shell implementation
# func_lo2o object
func_lo2o ()
{
func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"`
} # func_lo2o may be replaced by extended shell implementation
# func_xform libobj-or-source
func_xform ()
{
func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'`
} # func_xform may be replaced by extended shell implementation
# func_fatal_configuration arg...
# Echo program name prefixed message to standard error, followed by
# a configuration failure hint, and exit.
func_fatal_configuration ()
{
func_error ${1+"$@"}
func_error "See the $PACKAGE documentation for more information."
func_fatal_error "Fatal configuration error."
}
# func_config
# Display the configuration for all the tags in this script.
func_config ()
{
re_begincf='^# ### BEGIN LIBTOOL'
re_endcf='^# ### END LIBTOOL'
# Default configuration.
$SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
# Now print the configurations for the tags.
for tagname in $taglist; do
$SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
done
exit $?
}
# func_features
# Display the features supported by this script.
func_features ()
{
echo "host: $host"
if test "$build_libtool_libs" = yes; then
echo "enable shared libraries"
else
echo "disable shared libraries"
fi
if test "$build_old_libs" = yes; then
echo "enable static libraries"
else
echo "disable static libraries"
fi
exit $?
}
# func_enable_tag tagname
# Verify that TAGNAME is valid, and either flag an error and exit, or
# enable the TAGNAME tag. We also add TAGNAME to the global $taglist
# variable here.
func_enable_tag ()
{
# Global variable:
tagname="$1"
re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
sed_extractcf="/$re_begincf/,/$re_endcf/p"
# Validate tagname.
case $tagname in
*[!-_A-Za-z0-9,/]*)
func_fatal_error "invalid tag name: $tagname"
;;
esac
# Don't test for the "default" C tag, as we know it's
# there but not specially marked.
case $tagname in
CC) ;;
*)
if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
taglist="$taglist $tagname"
# Evaluate the configuration. Be careful to quote the path
# and the sed script, to avoid splitting on whitespace, but
# also don't use non-portable quotes within backquotes within
# quotes we have to do it in 2 steps:
extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
eval "$extractedcf"
else
func_error "ignoring unknown tag $tagname"
fi
;;
esac
}
# func_check_version_match
# Ensure that we are using m4 macros, and libtool script from the same
# release of libtool.
func_check_version_match ()
{
if test "$package_revision" != "$macro_revision"; then
if test "$VERSION" != "$macro_version"; then
if test -z "$macro_version"; then
cat >&2 <<_LT_EOF
$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
$progname: definition of this LT_INIT comes from an older release.
$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
$progname: and run autoconf again.
_LT_EOF
else
cat >&2 <<_LT_EOF
$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
$progname: and run autoconf again.
_LT_EOF
fi
else
cat >&2 <<_LT_EOF
$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision,
$progname: but the definition of this LT_INIT comes from revision $macro_revision.
$progname: You should recreate aclocal.m4 with macros from revision $package_revision
$progname: of $PACKAGE $VERSION and run autoconf again.
_LT_EOF
fi
exit $EXIT_MISMATCH
fi
}
# Shorthand for --mode=foo, only valid as the first argument
case $1 in
clean|clea|cle|cl)
shift; set dummy --mode clean ${1+"$@"}; shift
;;
compile|compil|compi|comp|com|co|c)
shift; set dummy --mode compile ${1+"$@"}; shift
;;
execute|execut|execu|exec|exe|ex|e)
shift; set dummy --mode execute ${1+"$@"}; shift
;;
finish|finis|fini|fin|fi|f)
shift; set dummy --mode finish ${1+"$@"}; shift
;;
install|instal|insta|inst|ins|in|i)
shift; set dummy --mode install ${1+"$@"}; shift
;;
link|lin|li|l)
shift; set dummy --mode link ${1+"$@"}; shift
;;
uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
shift; set dummy --mode uninstall ${1+"$@"}; shift
;;
esac
# Option defaults:
opt_debug=:
opt_dry_run=false
opt_config=false
opt_preserve_dup_deps=false
opt_features=false
opt_finish=false
opt_help=false
opt_help_all=false
opt_silent=:
opt_warning=:
opt_verbose=:
opt_silent=false
opt_verbose=false
# Parse options once, thoroughly. This comes as soon as possible in the
# script to make things like `--version' happen as quickly as we can.
{
# this just eases exit handling
while test $# -gt 0; do
opt="$1"
shift
case $opt in
--debug|-x) opt_debug='set -x'
func_echo "enabling shell trace mode"
$opt_debug
;;
--dry-run|--dryrun|-n)
opt_dry_run=:
;;
--config)
opt_config=:
func_config
;;
--dlopen|-dlopen)
optarg="$1"
opt_dlopen="${opt_dlopen+$opt_dlopen
}$optarg"
shift
;;
--preserve-dup-deps)
opt_preserve_dup_deps=:
;;
--features)
opt_features=:
func_features
;;
--finish)
opt_finish=:
set dummy --mode finish ${1+"$@"}; shift
;;
--help)
opt_help=:
;;
--help-all)
opt_help_all=:
opt_help=': help-all'
;;
--mode)
test $# = 0 && func_missing_arg $opt && break
optarg="$1"
opt_mode="$optarg"
case $optarg in
# Valid mode arguments:
clean|compile|execute|finish|install|link|relink|uninstall) ;;
# Catch anything else as an error
*) func_error "invalid argument for $opt"
exit_cmd=exit
break
;;
esac
shift
;;
--no-silent|--no-quiet)
opt_silent=false
func_append preserve_args " $opt"
;;
--no-warning|--no-warn)
opt_warning=false
func_append preserve_args " $opt"
;;
--no-verbose)
opt_verbose=false
func_append preserve_args " $opt"
;;
--silent|--quiet)
opt_silent=:
func_append preserve_args " $opt"
opt_verbose=false
;;
--verbose|-v)
opt_verbose=:
func_append preserve_args " $opt"
opt_silent=false
;;
--tag)
test $# = 0 && func_missing_arg $opt && break
optarg="$1"
opt_tag="$optarg"
func_append preserve_args " $opt $optarg"
func_enable_tag "$optarg"
shift
;;
-\?|-h) func_usage ;;
--help) func_help ;;
--version) func_version ;;
# Separate optargs to long options:
--*=*)
func_split_long_opt "$opt"
set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"}
shift
;;
# Separate non-argument short options:
-\?*|-h*|-n*|-v*)
func_split_short_opt "$opt"
set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"}
shift
;;
--) break ;;
-*) func_fatal_help "unrecognized option \`$opt'" ;;
*) set dummy "$opt" ${1+"$@"}; shift; break ;;
esac
done
# Validate options:
# save first non-option argument
if test "$#" -gt 0; then
nonopt="$opt"
shift
fi
# preserve --debug
test "$opt_debug" = : || func_append preserve_args " --debug"
case $host in
*cygwin* | *mingw* | *pw32* | *cegcc*)
# don't eliminate duplications in $postdeps and $predeps
opt_duplicate_compiler_generated_deps=:
;;
*)
opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps
;;
esac
$opt_help || {
# Sanity checks first:
func_check_version_match
if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
func_fatal_configuration "not configured to build any kind of library"
fi
# Darwin sucks
eval std_shrext=\"$shrext_cmds\"
# Only execute mode is allowed to have -dlopen flags.
if test -n "$opt_dlopen" && test "$opt_mode" != execute; then
func_error "unrecognized option \`-dlopen'"
$ECHO "$help" 1>&2
exit $EXIT_FAILURE
fi
# Change the help message to a mode-specific one.
generic_help="$help"
help="Try \`$progname --help --mode=$opt_mode' for more information."
}
# Bail if the options were screwed
$exit_cmd $EXIT_FAILURE
}
## ----------- ##
## Main. ##
## ----------- ##
# func_lalib_p file
# True iff FILE is a libtool `.la' library or `.lo' object file.
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_lalib_p ()
{
test -f "$1" &&
$SED -e 4q "$1" 2>/dev/null \
| $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
}
# func_lalib_unsafe_p file
# True iff FILE is a libtool `.la' library or `.lo' object file.
# This function implements the same check as func_lalib_p without
# resorting to external programs. To this end, it redirects stdin and
# closes it afterwards, without saving the original file descriptor.
# As a safety measure, use it only where a negative result would be
# fatal anyway. Works if `file' does not exist.
func_lalib_unsafe_p ()
{
lalib_p=no
if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
for lalib_p_l in 1 2 3 4
do
read lalib_p_line
case "$lalib_p_line" in
\#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
esac
done
exec 0<&5 5<&-
fi
test "$lalib_p" = yes
}
# func_ltwrapper_script_p file
# True iff FILE is a libtool wrapper script
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_ltwrapper_script_p ()
{
func_lalib_p "$1"
}
# func_ltwrapper_executable_p file
# True iff FILE is a libtool wrapper executable
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_ltwrapper_executable_p ()
{
func_ltwrapper_exec_suffix=
case $1 in
*.exe) ;;
*) func_ltwrapper_exec_suffix=.exe ;;
esac
$GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
}
# func_ltwrapper_scriptname file
# Assumes file is an ltwrapper_executable
# uses $file to determine the appropriate filename for a
# temporary ltwrapper_script.
func_ltwrapper_scriptname ()
{
func_dirname_and_basename "$1" "" "."
func_stripname '' '.exe' "$func_basename_result"
func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper"
}
# func_ltwrapper_p file
# True iff FILE is a libtool wrapper script or wrapper executable
# This function is only a basic sanity check; it will hardly flush out
# determined imposters.
func_ltwrapper_p ()
{
func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
}
# func_execute_cmds commands fail_cmd
# Execute tilde-delimited COMMANDS.
# If FAIL_CMD is given, eval that upon failure.
# FAIL_CMD may read-access the current command in variable CMD!
func_execute_cmds ()
{
$opt_debug
save_ifs=$IFS; IFS='~'
for cmd in $1; do
IFS=$save_ifs
eval cmd=\"$cmd\"
func_show_eval "$cmd" "${2-:}"
done
IFS=$save_ifs
}
# func_source file
# Source FILE, adding directory component if necessary.
# Note that it is not necessary on cygwin/mingw to append a dot to
# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
# behavior happens only for exec(3), not for open(2)! Also, sourcing
# `FILE.' does not work on cygwin managed mounts.
func_source ()
{
$opt_debug
case $1 in
*/* | *\\*) . "$1" ;;
*) . "./$1" ;;
esac
}
# func_resolve_sysroot PATH
# Replace a leading = in PATH with a sysroot. Store the result into
# func_resolve_sysroot_result
func_resolve_sysroot ()
{
func_resolve_sysroot_result=$1
case $func_resolve_sysroot_result in
=*)
func_stripname '=' '' "$func_resolve_sysroot_result"
func_resolve_sysroot_result=$lt_sysroot$func_stripname_result
;;
esac
}
# func_replace_sysroot PATH
# If PATH begins with the sysroot, replace it with = and
# store the result into func_replace_sysroot_result.
func_replace_sysroot ()
{
case "$lt_sysroot:$1" in
?*:"$lt_sysroot"*)
func_stripname "$lt_sysroot" '' "$1"
func_replace_sysroot_result="=$func_stripname_result"
;;
*)
# Including no sysroot.
func_replace_sysroot_result=$1
;;
esac
}
# func_infer_tag arg
# Infer tagged configuration to use if any are available and
# if one wasn't chosen via the "--tag" command line option.
# Only attempt this if the compiler in the base compile
# command doesn't match the default compiler.
# arg is usually of the form 'gcc ...'
func_infer_tag ()
{
$opt_debug
if test -n "$available_tags" && test -z "$tagname"; then
CC_quoted=
for arg in $CC; do
func_append_quoted CC_quoted "$arg"
done
CC_expanded=`func_echo_all $CC`
CC_quoted_expanded=`func_echo_all $CC_quoted`
case $@ in
# Blanks in the command may have been stripped by the calling shell,
# but not from the CC environment variable when configure was run.
" $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
" $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;;
# Blanks at the start of $base_compile will cause this to fail
# if we don't check for them as well.
*)
for z in $available_tags; do
if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
# Evaluate the configuration.
eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
CC_quoted=
for arg in $CC; do
# Double-quote args containing other shell metacharacters.
func_append_quoted CC_quoted "$arg"
done
CC_expanded=`func_echo_all $CC`
CC_quoted_expanded=`func_echo_all $CC_quoted`
case "$@ " in
" $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
" $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*)
# The compiler in the base compile command matches
# the one in the tagged configuration.
# Assume this is the tagged configuration we want.
tagname=$z
break
;;
esac
fi
done
# If $tagname still isn't set, then no tagged configuration
# was found and let the user know that the "--tag" command
# line option must be used.
if test -z "$tagname"; then
func_echo "unable to infer tagged configuration"
func_fatal_error "specify a tag with \`--tag'"
# else
# func_verbose "using $tagname tagged configuration"
fi
;;
esac
fi
}
# func_write_libtool_object output_name pic_name nonpic_name
# Create a libtool object file (analogous to a ".la" file),
# but don't create it if we're doing a dry run.
func_write_libtool_object ()
{
write_libobj=${1}
if test "$build_libtool_libs" = yes; then
write_lobj=\'${2}\'
else
write_lobj=none
fi
if test "$build_old_libs" = yes; then
write_oldobj=\'${3}\'
else
write_oldobj=none
fi
$opt_dry_run || {
cat >${write_libobj}T </dev/null`
if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then
func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" |
$SED -e "$lt_sed_naive_backslashify"`
else
func_convert_core_file_wine_to_w32_result=
fi
fi
}
# end: func_convert_core_file_wine_to_w32
# func_convert_core_path_wine_to_w32 ARG
# Helper function used by path conversion functions when $build is *nix, and
# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly
# configured wine environment available, with the winepath program in $build's
# $PATH. Assumes ARG has no leading or trailing path separator characters.
#
# ARG is path to be converted from $build format to win32.
# Result is available in $func_convert_core_path_wine_to_w32_result.
# Unconvertible file (directory) names in ARG are skipped; if no directory names
# are convertible, then the result may be empty.
func_convert_core_path_wine_to_w32 ()
{
$opt_debug
# unfortunately, winepath doesn't convert paths, only file names
func_convert_core_path_wine_to_w32_result=""
if test -n "$1"; then
oldIFS=$IFS
IFS=:
for func_convert_core_path_wine_to_w32_f in $1; do
IFS=$oldIFS
func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f"
if test -n "$func_convert_core_file_wine_to_w32_result" ; then
if test -z "$func_convert_core_path_wine_to_w32_result"; then
func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result"
else
func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result"
fi
fi
done
IFS=$oldIFS
fi
}
# end: func_convert_core_path_wine_to_w32
# func_cygpath ARGS...
# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when
# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2)
# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or
# (2), returns the Cygwin file name or path in func_cygpath_result (input
# file name or path is assumed to be in w32 format, as previously converted
# from $build's *nix or MSYS format). In case (3), returns the w32 file name
# or path in func_cygpath_result (input file name or path is assumed to be in
# Cygwin format). Returns an empty string on error.
#
# ARGS are passed to cygpath, with the last one being the file name or path to
# be converted.
#
# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH
# environment variable; do not put it in $PATH.
func_cygpath ()
{
$opt_debug
if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then
func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null`
if test "$?" -ne 0; then
# on failure, ensure result is empty
func_cygpath_result=
fi
else
func_cygpath_result=
func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'"
fi
}
#end: func_cygpath
# func_convert_core_msys_to_w32 ARG
# Convert file name or path ARG from MSYS format to w32 format. Return
# result in func_convert_core_msys_to_w32_result.
func_convert_core_msys_to_w32 ()
{
$opt_debug
# awkward: cmd appends spaces to result
func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null |
$SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"`
}
#end: func_convert_core_msys_to_w32
# func_convert_file_check ARG1 ARG2
# Verify that ARG1 (a file name in $build format) was converted to $host
# format in ARG2. Otherwise, emit an error message, but continue (resetting
# func_to_host_file_result to ARG1).
func_convert_file_check ()
{
$opt_debug
if test -z "$2" && test -n "$1" ; then
func_error "Could not determine host file name corresponding to"
func_error " \`$1'"
func_error "Continuing, but uninstalled executables may not work."
# Fallback:
func_to_host_file_result="$1"
fi
}
# end func_convert_file_check
# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH
# Verify that FROM_PATH (a path in $build format) was converted to $host
# format in TO_PATH. Otherwise, emit an error message, but continue, resetting
# func_to_host_file_result to a simplistic fallback value (see below).
func_convert_path_check ()
{
$opt_debug
if test -z "$4" && test -n "$3"; then
func_error "Could not determine the host path corresponding to"
func_error " \`$3'"
func_error "Continuing, but uninstalled executables may not work."
# Fallback. This is a deliberately simplistic "conversion" and
# should not be "improved". See libtool.info.
if test "x$1" != "x$2"; then
lt_replace_pathsep_chars="s|$1|$2|g"
func_to_host_path_result=`echo "$3" |
$SED -e "$lt_replace_pathsep_chars"`
else
func_to_host_path_result="$3"
fi
fi
}
# end func_convert_path_check
# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG
# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT
# and appending REPL if ORIG matches BACKPAT.
func_convert_path_front_back_pathsep ()
{
$opt_debug
case $4 in
$1 ) func_to_host_path_result="$3$func_to_host_path_result"
;;
esac
case $4 in
$2 ) func_append func_to_host_path_result "$3"
;;
esac
}
# end func_convert_path_front_back_pathsep
##################################################
# $build to $host FILE NAME CONVERSION FUNCTIONS #
##################################################
# invoked via `$to_host_file_cmd ARG'
#
# In each case, ARG is the path to be converted from $build to $host format.
# Result will be available in $func_to_host_file_result.
# func_to_host_file ARG
# Converts the file name ARG from $build format to $host format. Return result
# in func_to_host_file_result.
func_to_host_file ()
{
$opt_debug
$to_host_file_cmd "$1"
}
# end func_to_host_file
# func_to_tool_file ARG LAZY
# converts the file name ARG from $build format to toolchain format. Return
# result in func_to_tool_file_result. If the conversion in use is listed
# in (the comma separated) LAZY, no conversion takes place.
func_to_tool_file ()
{
$opt_debug
case ,$2, in
*,"$to_tool_file_cmd",*)
func_to_tool_file_result=$1
;;
*)
$to_tool_file_cmd "$1"
func_to_tool_file_result=$func_to_host_file_result
;;
esac
}
# end func_to_tool_file
# func_convert_file_noop ARG
# Copy ARG to func_to_host_file_result.
func_convert_file_noop ()
{
func_to_host_file_result="$1"
}
# end func_convert_file_noop
# func_convert_file_msys_to_w32 ARG
# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic
# conversion to w32 is not available inside the cwrapper. Returns result in
# func_to_host_file_result.
func_convert_file_msys_to_w32 ()
{
$opt_debug
func_to_host_file_result="$1"
if test -n "$1"; then
func_convert_core_msys_to_w32 "$1"
func_to_host_file_result="$func_convert_core_msys_to_w32_result"
fi
func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_msys_to_w32
# func_convert_file_cygwin_to_w32 ARG
# Convert file name ARG from Cygwin to w32 format. Returns result in
# func_to_host_file_result.
func_convert_file_cygwin_to_w32 ()
{
$opt_debug
func_to_host_file_result="$1"
if test -n "$1"; then
# because $build is cygwin, we call "the" cygpath in $PATH; no need to use
# LT_CYGPATH in this case.
func_to_host_file_result=`cygpath -m "$1"`
fi
func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_cygwin_to_w32
# func_convert_file_nix_to_w32 ARG
# Convert file name ARG from *nix to w32 format. Requires a wine environment
# and a working winepath. Returns result in func_to_host_file_result.
func_convert_file_nix_to_w32 ()
{
$opt_debug
func_to_host_file_result="$1"
if test -n "$1"; then
func_convert_core_file_wine_to_w32 "$1"
func_to_host_file_result="$func_convert_core_file_wine_to_w32_result"
fi
func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_nix_to_w32
# func_convert_file_msys_to_cygwin ARG
# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set.
# Returns result in func_to_host_file_result.
func_convert_file_msys_to_cygwin ()
{
$opt_debug
func_to_host_file_result="$1"
if test -n "$1"; then
func_convert_core_msys_to_w32 "$1"
func_cygpath -u "$func_convert_core_msys_to_w32_result"
func_to_host_file_result="$func_cygpath_result"
fi
func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_msys_to_cygwin
# func_convert_file_nix_to_cygwin ARG
# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed
# in a wine environment, working winepath, and LT_CYGPATH set. Returns result
# in func_to_host_file_result.
func_convert_file_nix_to_cygwin ()
{
$opt_debug
func_to_host_file_result="$1"
if test -n "$1"; then
# convert from *nix to w32, then use cygpath to convert from w32 to cygwin.
func_convert_core_file_wine_to_w32 "$1"
func_cygpath -u "$func_convert_core_file_wine_to_w32_result"
func_to_host_file_result="$func_cygpath_result"
fi
func_convert_file_check "$1" "$func_to_host_file_result"
}
# end func_convert_file_nix_to_cygwin
#############################################
# $build to $host PATH CONVERSION FUNCTIONS #
#############################################
# invoked via `$to_host_path_cmd ARG'
#
# In each case, ARG is the path to be converted from $build to $host format.
# The result will be available in $func_to_host_path_result.
#
# Path separators are also converted from $build format to $host format. If
# ARG begins or ends with a path separator character, it is preserved (but
# converted to $host format) on output.
#
# All path conversion functions are named using the following convention:
# file name conversion function : func_convert_file_X_to_Y ()
# path conversion function : func_convert_path_X_to_Y ()
# where, for any given $build/$host combination the 'X_to_Y' value is the
# same. If conversion functions are added for new $build/$host combinations,
# the two new functions must follow this pattern, or func_init_to_host_path_cmd
# will break.
# func_init_to_host_path_cmd
# Ensures that function "pointer" variable $to_host_path_cmd is set to the
# appropriate value, based on the value of $to_host_file_cmd.
to_host_path_cmd=
func_init_to_host_path_cmd ()
{
$opt_debug
if test -z "$to_host_path_cmd"; then
func_stripname 'func_convert_file_' '' "$to_host_file_cmd"
to_host_path_cmd="func_convert_path_${func_stripname_result}"
fi
}
# func_to_host_path ARG
# Converts the path ARG from $build format to $host format. Return result
# in func_to_host_path_result.
func_to_host_path ()
{
$opt_debug
func_init_to_host_path_cmd
$to_host_path_cmd "$1"
}
# end func_to_host_path
# func_convert_path_noop ARG
# Copy ARG to func_to_host_path_result.
func_convert_path_noop ()
{
func_to_host_path_result="$1"
}
# end func_convert_path_noop
# func_convert_path_msys_to_w32 ARG
# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic
# conversion to w32 is not available inside the cwrapper. Returns result in
# func_to_host_path_result.
func_convert_path_msys_to_w32 ()
{
$opt_debug
func_to_host_path_result="$1"
if test -n "$1"; then
# Remove leading and trailing path separator characters from ARG. MSYS
# behavior is inconsistent here; cygpath turns them into '.;' and ';.';
# and winepath ignores them completely.
func_stripname : : "$1"
func_to_host_path_tmp1=$func_stripname_result
func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
func_to_host_path_result="$func_convert_core_msys_to_w32_result"
func_convert_path_check : ";" \
"$func_to_host_path_tmp1" "$func_to_host_path_result"
func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
fi
}
# end func_convert_path_msys_to_w32
# func_convert_path_cygwin_to_w32 ARG
# Convert path ARG from Cygwin to w32 format. Returns result in
# func_to_host_file_result.
func_convert_path_cygwin_to_w32 ()
{
$opt_debug
func_to_host_path_result="$1"
if test -n "$1"; then
# See func_convert_path_msys_to_w32:
func_stripname : : "$1"
func_to_host_path_tmp1=$func_stripname_result
func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"`
func_convert_path_check : ";" \
"$func_to_host_path_tmp1" "$func_to_host_path_result"
func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
fi
}
# end func_convert_path_cygwin_to_w32
# func_convert_path_nix_to_w32 ARG
# Convert path ARG from *nix to w32 format. Requires a wine environment and
# a working winepath. Returns result in func_to_host_file_result.
func_convert_path_nix_to_w32 ()
{
$opt_debug
func_to_host_path_result="$1"
if test -n "$1"; then
# See func_convert_path_msys_to_w32:
func_stripname : : "$1"
func_to_host_path_tmp1=$func_stripname_result
func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
func_to_host_path_result="$func_convert_core_path_wine_to_w32_result"
func_convert_path_check : ";" \
"$func_to_host_path_tmp1" "$func_to_host_path_result"
func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
fi
}
# end func_convert_path_nix_to_w32
# func_convert_path_msys_to_cygwin ARG
# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set.
# Returns result in func_to_host_file_result.
func_convert_path_msys_to_cygwin ()
{
$opt_debug
func_to_host_path_result="$1"
if test -n "$1"; then
# See func_convert_path_msys_to_w32:
func_stripname : : "$1"
func_to_host_path_tmp1=$func_stripname_result
func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
func_cygpath -u -p "$func_convert_core_msys_to_w32_result"
func_to_host_path_result="$func_cygpath_result"
func_convert_path_check : : \
"$func_to_host_path_tmp1" "$func_to_host_path_result"
func_convert_path_front_back_pathsep ":*" "*:" : "$1"
fi
}
# end func_convert_path_msys_to_cygwin
# func_convert_path_nix_to_cygwin ARG
# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a
# a wine environment, working winepath, and LT_CYGPATH set. Returns result in
# func_to_host_file_result.
func_convert_path_nix_to_cygwin ()
{
$opt_debug
func_to_host_path_result="$1"
if test -n "$1"; then
# Remove leading and trailing path separator characters from
# ARG. msys behavior is inconsistent here, cygpath turns them
# into '.;' and ';.', and winepath ignores them completely.
func_stripname : : "$1"
func_to_host_path_tmp1=$func_stripname_result
func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result"
func_to_host_path_result="$func_cygpath_result"
func_convert_path_check : : \
"$func_to_host_path_tmp1" "$func_to_host_path_result"
func_convert_path_front_back_pathsep ":*" "*:" : "$1"
fi
}
# end func_convert_path_nix_to_cygwin
# func_mode_compile arg...
func_mode_compile ()
{
$opt_debug
# Get the compilation command and the source file.
base_compile=
srcfile="$nonopt" # always keep a non-empty value in "srcfile"
suppress_opt=yes
suppress_output=
arg_mode=normal
libobj=
later=
pie_flag=
for arg
do
case $arg_mode in
arg )
# do not "continue". Instead, add this to base_compile
lastarg="$arg"
arg_mode=normal
;;
target )
libobj="$arg"
arg_mode=normal
continue
;;
normal )
# Accept any command-line options.
case $arg in
-o)
test -n "$libobj" && \
func_fatal_error "you cannot specify \`-o' more than once"
arg_mode=target
continue
;;
-pie | -fpie | -fPIE)
func_append pie_flag " $arg"
continue
;;
-shared | -static | -prefer-pic | -prefer-non-pic)
func_append later " $arg"
continue
;;
-no-suppress)
suppress_opt=no
continue
;;
-Xcompiler)
arg_mode=arg # the next one goes into the "base_compile" arg list
continue # The current "srcfile" will either be retained or
;; # replaced later. I would guess that would be a bug.
-Wc,*)
func_stripname '-Wc,' '' "$arg"
args=$func_stripname_result
lastarg=
save_ifs="$IFS"; IFS=','
for arg in $args; do
IFS="$save_ifs"
func_append_quoted lastarg "$arg"
done
IFS="$save_ifs"
func_stripname ' ' '' "$lastarg"
lastarg=$func_stripname_result
# Add the arguments to base_compile.
func_append base_compile " $lastarg"
continue
;;
*)
# Accept the current argument as the source file.
# The previous "srcfile" becomes the current argument.
#
lastarg="$srcfile"
srcfile="$arg"
;;
esac # case $arg
;;
esac # case $arg_mode
# Aesthetically quote the previous argument.
func_append_quoted base_compile "$lastarg"
done # for arg
case $arg_mode in
arg)
func_fatal_error "you must specify an argument for -Xcompile"
;;
target)
func_fatal_error "you must specify a target with \`-o'"
;;
*)
# Get the name of the library object.
test -z "$libobj" && {
func_basename "$srcfile"
libobj="$func_basename_result"
}
;;
esac
# Recognize several different file suffixes.
# If the user specifies -o file.o, it is replaced with file.lo
case $libobj in
*.[cCFSifmso] | \
*.ada | *.adb | *.ads | *.asm | \
*.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
*.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup)
func_xform "$libobj"
libobj=$func_xform_result
;;
esac
case $libobj in
*.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
*)
func_fatal_error "cannot determine name of library object from \`$libobj'"
;;
esac
func_infer_tag $base_compile
for arg in $later; do
case $arg in
-shared)
test "$build_libtool_libs" != yes && \
func_fatal_configuration "can not build a shared library"
build_old_libs=no
continue
;;
-static)
build_libtool_libs=no
build_old_libs=yes
continue
;;
-prefer-pic)
pic_mode=yes
continue
;;
-prefer-non-pic)
pic_mode=no
continue
;;
esac
done
func_quote_for_eval "$libobj"
test "X$libobj" != "X$func_quote_for_eval_result" \
&& $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \
&& func_warning "libobj name \`$libobj' may not contain shell special characters."
func_dirname_and_basename "$obj" "/" ""
objname="$func_basename_result"
xdir="$func_dirname_result"
lobj=${xdir}$objdir/$objname
test -z "$base_compile" && \
func_fatal_help "you must specify a compilation command"
# Delete any leftover library objects.
if test "$build_old_libs" = yes; then
removelist="$obj $lobj $libobj ${libobj}T"
else
removelist="$lobj $libobj ${libobj}T"
fi
# On Cygwin there's no "real" PIC flag so we must build both object types
case $host_os in
cygwin* | mingw* | pw32* | os2* | cegcc*)
pic_mode=default
;;
esac
if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
# non-PIC code in shared libraries is not supported
pic_mode=default
fi
# Calculate the filename of the output object if compiler does
# not support -o with -c
if test "$compiler_c_o" = no; then
output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext}
lockfile="$output_obj.lock"
else
output_obj=
need_locks=no
lockfile=
fi
# Lock this critical section if it is needed
# We use this script file to make the link, it avoids creating a new file
if test "$need_locks" = yes; then
until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
func_echo "Waiting for $lockfile to be removed"
sleep 2
done
elif test "$need_locks" = warn; then
if test -f "$lockfile"; then
$ECHO "\
*** ERROR, $lockfile exists and contains:
`cat $lockfile 2>/dev/null`
This indicates that another process is trying to use the same
temporary object file, and libtool could not work around it because
your compiler does not support \`-c' and \`-o' together. If you
repeat this compilation, it may succeed, by chance, but you had better
avoid parallel builds (make -j) in this platform, or get a better
compiler."
$opt_dry_run || $RM $removelist
exit $EXIT_FAILURE
fi
func_append removelist " $output_obj"
$ECHO "$srcfile" > "$lockfile"
fi
$opt_dry_run || $RM $removelist
func_append removelist " $lockfile"
trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
func_to_tool_file "$srcfile" func_convert_file_msys_to_w32
srcfile=$func_to_tool_file_result
func_quote_for_eval "$srcfile"
qsrcfile=$func_quote_for_eval_result
# Only build a PIC object if we are building libtool libraries.
if test "$build_libtool_libs" = yes; then
# Without this assignment, base_compile gets emptied.
fbsd_hideous_sh_bug=$base_compile
if test "$pic_mode" != no; then
command="$base_compile $qsrcfile $pic_flag"
else
# Don't build PIC code
command="$base_compile $qsrcfile"
fi
func_mkdir_p "$xdir$objdir"
if test -z "$output_obj"; then
# Place PIC objects in $objdir
func_append command " -o $lobj"
fi
func_show_eval_locale "$command" \
'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
if test "$need_locks" = warn &&
test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
$ECHO "\
*** ERROR, $lockfile contains:
`cat $lockfile 2>/dev/null`
but it should contain:
$srcfile
This indicates that another process is trying to use the same
temporary object file, and libtool could not work around it because
your compiler does not support \`-c' and \`-o' together. If you
repeat this compilation, it may succeed, by chance, but you had better
avoid parallel builds (make -j) in this platform, or get a better
compiler."
$opt_dry_run || $RM $removelist
exit $EXIT_FAILURE
fi
# Just move the object if needed, then go on to compile the next one
if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
func_show_eval '$MV "$output_obj" "$lobj"' \
'error=$?; $opt_dry_run || $RM $removelist; exit $error'
fi
# Allow error messages only from the first compilation.
if test "$suppress_opt" = yes; then
suppress_output=' >/dev/null 2>&1'
fi
fi
# Only build a position-dependent object if we build old libraries.
if test "$build_old_libs" = yes; then
if test "$pic_mode" != yes; then
# Don't build PIC code
command="$base_compile $qsrcfile$pie_flag"
else
command="$base_compile $qsrcfile $pic_flag"
fi
if test "$compiler_c_o" = yes; then
func_append command " -o $obj"
fi
# Suppress compiler output if we already did a PIC compilation.
func_append command "$suppress_output"
func_show_eval_locale "$command" \
'$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
if test "$need_locks" = warn &&
test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
$ECHO "\
*** ERROR, $lockfile contains:
`cat $lockfile 2>/dev/null`
but it should contain:
$srcfile
This indicates that another process is trying to use the same
temporary object file, and libtool could not work around it because
your compiler does not support \`-c' and \`-o' together. If you
repeat this compilation, it may succeed, by chance, but you had better
avoid parallel builds (make -j) in this platform, or get a better
compiler."
$opt_dry_run || $RM $removelist
exit $EXIT_FAILURE
fi
# Just move the object if needed
if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
func_show_eval '$MV "$output_obj" "$obj"' \
'error=$?; $opt_dry_run || $RM $removelist; exit $error'
fi
fi
$opt_dry_run || {
func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
# Unlock the critical section if it was locked
if test "$need_locks" != no; then
removelist=$lockfile
$RM "$lockfile"
fi
}
exit $EXIT_SUCCESS
}
$opt_help || {
test "$opt_mode" = compile && func_mode_compile ${1+"$@"}
}
func_mode_help ()
{
# We need to display help for each of the modes.
case $opt_mode in
"")
# Generic help is extracted from the usage comments
# at the start of this file.
func_help
;;
clean)
$ECHO \
"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
Remove files from the build directory.
RM is the name of the program to use to delete files associated with each FILE
(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
to RM.
If FILE is a libtool library, object or program, all the files associated
with it are deleted. Otherwise, only FILE itself is deleted using RM."
;;
compile)
$ECHO \
"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
Compile a source file into a libtool library object.
This mode accepts the following additional options:
-o OUTPUT-FILE set the output file name to OUTPUT-FILE
-no-suppress do not suppress compiler output for multiple passes
-prefer-pic try to build PIC objects only
-prefer-non-pic try to build non-PIC objects only
-shared do not build a \`.o' file suitable for static linking
-static only build a \`.o' file suitable for static linking
-Wc,FLAG pass FLAG directly to the compiler
COMPILE-COMMAND is a command to be used in creating a \`standard' object file
from the given SOURCEFILE.
The output file name is determined by removing the directory component from
SOURCEFILE, then substituting the C source code suffix \`.c' with the
library object suffix, \`.lo'."
;;
execute)
$ECHO \
"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
Automatically set library path, then run a program.
This mode accepts the following additional options:
-dlopen FILE add the directory containing FILE to the library path
This mode sets the library path environment variable according to \`-dlopen'
flags.
If any of the ARGS are libtool executable wrappers, then they are translated
into their corresponding uninstalled binary, and any of their required library
directories are added to the library path.
Then, COMMAND is executed, with ARGS as arguments."
;;
finish)
$ECHO \
"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
Complete the installation of libtool libraries.
Each LIBDIR is a directory that contains libtool libraries.
The commands that this mode executes may require superuser privileges. Use
the \`--dry-run' option if you just want to see what would be executed."
;;
install)
$ECHO \
"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
Install executables or libraries.
INSTALL-COMMAND is the installation command. The first component should be
either the \`install' or \`cp' program.
The following components of INSTALL-COMMAND are treated specially:
-inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation
The rest of the components are interpreted as arguments to that command (only
BSD-compatible install options are recognized)."
;;
link)
$ECHO \
"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
Link object files or libraries together to form another library, or to
create an executable program.
LINK-COMMAND is a command using the C compiler that you would use to create
a program from several object files.
The following components of LINK-COMMAND are treated specially:
-all-static do not do any dynamic linking at all
-avoid-version do not add a version suffix if possible
-bindir BINDIR specify path to binaries directory (for systems where
libraries must be found in the PATH setting at runtime)
-dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
-dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
-export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
-export-symbols SYMFILE
try to export only the symbols listed in SYMFILE
-export-symbols-regex REGEX
try to export only the symbols matching REGEX
-LLIBDIR search LIBDIR for required installed libraries
-lNAME OUTPUT-FILE requires the installed library libNAME
-module build a library that can dlopened
-no-fast-install disable the fast-install mode
-no-install link a not-installable executable
-no-undefined declare that a library does not refer to external symbols
-o OUTPUT-FILE create OUTPUT-FILE from the specified objects
-objectlist FILE Use a list of object files found in FILE to specify objects
-precious-files-regex REGEX
don't remove output files matching REGEX
-release RELEASE specify package release information
-rpath LIBDIR the created library will eventually be installed in LIBDIR
-R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
-shared only do dynamic linking of libtool libraries
-shrext SUFFIX override the standard shared library file extension
-static do not do any dynamic linking of uninstalled libtool libraries
-static-libtool-libs
do not do any dynamic linking of libtool libraries
-version-info CURRENT[:REVISION[:AGE]]
specify library version info [each variable defaults to 0]
-weak LIBNAME declare that the target provides the LIBNAME interface
-Wc,FLAG
-Xcompiler FLAG pass linker-specific FLAG directly to the compiler
-Wl,FLAG
-Xlinker FLAG pass linker-specific FLAG directly to the linker
-XCClinker FLAG pass link-specific FLAG to the compiler driver (CC)
All other options (arguments beginning with \`-') are ignored.
Every other argument is treated as a filename. Files ending in \`.la' are
treated as uninstalled libtool libraries, other files are standard or library
object files.
If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
only library objects (\`.lo' files) may be specified, and \`-rpath' is
required, except when creating a convenience library.
If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
using \`ar' and \`ranlib', or on Windows using \`lib'.
If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
is created, otherwise an executable program is created."
;;
uninstall)
$ECHO \
"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
Remove libraries from an installation directory.
RM is the name of the program to use to delete files associated with each FILE
(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
to RM.
If FILE is a libtool library, all the files associated with it are deleted.
Otherwise, only FILE itself is deleted using RM."
;;
*)
func_fatal_help "invalid operation mode \`$opt_mode'"
;;
esac
echo
$ECHO "Try \`$progname --help' for more information about other modes."
}
# Now that we've collected a possible --mode arg, show help if necessary
if $opt_help; then
if test "$opt_help" = :; then
func_mode_help
else
{
func_help noexit
for opt_mode in compile link execute install finish uninstall clean; do
func_mode_help
done
} | sed -n '1p; 2,$s/^Usage:/ or: /p'
{
func_help noexit
for opt_mode in compile link execute install finish uninstall clean; do
echo
func_mode_help
done
} |
sed '1d
/^When reporting/,/^Report/{
H
d
}
$x
/information about other modes/d
/more detailed .*MODE/d
s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/'
fi
exit $?
fi
# func_mode_execute arg...
func_mode_execute ()
{
$opt_debug
# The first argument is the command name.
cmd="$nonopt"
test -z "$cmd" && \
func_fatal_help "you must specify a COMMAND"
# Handle -dlopen flags immediately.
for file in $opt_dlopen; do
test -f "$file" \
|| func_fatal_help "\`$file' is not a file"
dir=
case $file in
*.la)
func_resolve_sysroot "$file"
file=$func_resolve_sysroot_result
# Check to see that this really is a libtool archive.
func_lalib_unsafe_p "$file" \
|| func_fatal_help "\`$lib' is not a valid libtool archive"
# Read the libtool library.
dlname=
library_names=
func_source "$file"
# Skip this library if it cannot be dlopened.
if test -z "$dlname"; then
# Warn if it was a shared library.
test -n "$library_names" && \
func_warning "\`$file' was not linked with \`-export-dynamic'"
continue
fi
func_dirname "$file" "" "."
dir="$func_dirname_result"
if test -f "$dir/$objdir/$dlname"; then
func_append dir "/$objdir"
else
if test ! -f "$dir/$dlname"; then
func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'"
fi
fi
;;
*.lo)
# Just add the directory containing the .lo file.
func_dirname "$file" "" "."
dir="$func_dirname_result"
;;
*)
func_warning "\`-dlopen' is ignored for non-libtool libraries and objects"
continue
;;
esac
# Get the absolute pathname.
absdir=`cd "$dir" && pwd`
test -n "$absdir" && dir="$absdir"
# Now add the directory to shlibpath_var.
if eval "test -z \"\$$shlibpath_var\""; then
eval "$shlibpath_var=\"\$dir\""
else
eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
fi
done
# This variable tells wrapper scripts just to set shlibpath_var
# rather than running their programs.
libtool_execute_magic="$magic"
# Check if any of the arguments is a wrapper script.
args=
for file
do
case $file in
-* | *.la | *.lo ) ;;
*)
# Do a test to see if this is really a libtool program.
if func_ltwrapper_script_p "$file"; then
func_source "$file"
# Transform arg to wrapped name.
file="$progdir/$program"
elif func_ltwrapper_executable_p "$file"; then
func_ltwrapper_scriptname "$file"
func_source "$func_ltwrapper_scriptname_result"
# Transform arg to wrapped name.
file="$progdir/$program"
fi
;;
esac
# Quote arguments (to preserve shell metacharacters).
func_append_quoted args "$file"
done
if test "X$opt_dry_run" = Xfalse; then
if test -n "$shlibpath_var"; then
# Export the shlibpath_var.
eval "export $shlibpath_var"
fi
# Restore saved environment variables
for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
do
eval "if test \"\${save_$lt_var+set}\" = set; then
$lt_var=\$save_$lt_var; export $lt_var
else
$lt_unset $lt_var
fi"
done
# Now prepare to actually exec the command.
exec_cmd="\$cmd$args"
else
# Display what would be done.
if test -n "$shlibpath_var"; then
eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
echo "export $shlibpath_var"
fi
$ECHO "$cmd$args"
exit $EXIT_SUCCESS
fi
}
test "$opt_mode" = execute && func_mode_execute ${1+"$@"}
# func_mode_finish arg...
func_mode_finish ()
{
$opt_debug
libs=
libdirs=
admincmds=
for opt in "$nonopt" ${1+"$@"}
do
if test -d "$opt"; then
func_append libdirs " $opt"
elif test -f "$opt"; then
if func_lalib_unsafe_p "$opt"; then
func_append libs " $opt"
else
func_warning "\`$opt' is not a valid libtool archive"
fi
else
func_fatal_error "invalid argument \`$opt'"
fi
done
if test -n "$libs"; then
if test -n "$lt_sysroot"; then
sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"`
sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;"
else
sysroot_cmd=
fi
# Remove sysroot references
if $opt_dry_run; then
for lib in $libs; do
echo "removing references to $lt_sysroot and \`=' prefixes from $lib"
done
else
tmpdir=`func_mktempdir`
for lib in $libs; do
sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \
> $tmpdir/tmp-la
mv -f $tmpdir/tmp-la $lib
done
${RM}r "$tmpdir"
fi
fi
if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
for libdir in $libdirs; do
if test -n "$finish_cmds"; then
# Do each command in the finish commands.
func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
'"$cmd"'"'
fi
if test -n "$finish_eval"; then
# Do the single finish_eval.
eval cmds=\"$finish_eval\"
$opt_dry_run || eval "$cmds" || func_append admincmds "
$cmds"
fi
done
fi
# Exit here if they wanted silent mode.
$opt_silent && exit $EXIT_SUCCESS
if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
echo "----------------------------------------------------------------------"
echo "Libraries have been installed in:"
for libdir in $libdirs; do
$ECHO " $libdir"
done
echo
echo "If you ever happen to want to link against installed libraries"
echo "in a given directory, LIBDIR, you must either use libtool, and"
echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
echo "flag during linking and do at least one of the following:"
if test -n "$shlibpath_var"; then
echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
echo " during execution"
fi
if test -n "$runpath_var"; then
echo " - add LIBDIR to the \`$runpath_var' environment variable"
echo " during linking"
fi
if test -n "$hardcode_libdir_flag_spec"; then
libdir=LIBDIR
eval flag=\"$hardcode_libdir_flag_spec\"
$ECHO " - use the \`$flag' linker flag"
fi
if test -n "$admincmds"; then
$ECHO " - have your system administrator run these commands:$admincmds"
fi
if test -f /etc/ld.so.conf; then
echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
fi
echo
echo "See any operating system documentation about shared libraries for"
case $host in
solaris2.[6789]|solaris2.1[0-9])
echo "more information, such as the ld(1), crle(1) and ld.so(8) manual"
echo "pages."
;;
*)
echo "more information, such as the ld(1) and ld.so(8) manual pages."
;;
esac
echo "----------------------------------------------------------------------"
fi
exit $EXIT_SUCCESS
}
test "$opt_mode" = finish && func_mode_finish ${1+"$@"}
# func_mode_install arg...
func_mode_install ()
{
$opt_debug
# There may be an optional sh(1) argument at the beginning of
# install_prog (especially on Windows NT).
if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
# Allow the use of GNU shtool's install command.
case $nonopt in *shtool*) :;; *) false;; esac; then
# Aesthetically quote it.
func_quote_for_eval "$nonopt"
install_prog="$func_quote_for_eval_result "
arg=$1
shift
else
install_prog=
arg=$nonopt
fi
# The real first argument should be the name of the installation program.
# Aesthetically quote it.
func_quote_for_eval "$arg"
func_append install_prog "$func_quote_for_eval_result"
install_shared_prog=$install_prog
case " $install_prog " in
*[\\\ /]cp\ *) install_cp=: ;;
*) install_cp=false ;;
esac
# We need to accept at least all the BSD install flags.
dest=
files=
opts=
prev=
install_type=
isdir=no
stripme=
no_mode=:
for arg
do
arg2=
if test -n "$dest"; then
func_append files " $dest"
dest=$arg
continue
fi
case $arg in
-d) isdir=yes ;;
-f)
if $install_cp; then :; else
prev=$arg
fi
;;
-g | -m | -o)
prev=$arg
;;
-s)
stripme=" -s"
continue
;;
-*)
;;
*)
# If the previous option needed an argument, then skip it.
if test -n "$prev"; then
if test "x$prev" = x-m && test -n "$install_override_mode"; then
arg2=$install_override_mode
no_mode=false
fi
prev=
else
dest=$arg
continue
fi
;;
esac
# Aesthetically quote the argument.
func_quote_for_eval "$arg"
func_append install_prog " $func_quote_for_eval_result"
if test -n "$arg2"; then
func_quote_for_eval "$arg2"
fi
func_append install_shared_prog " $func_quote_for_eval_result"
done
test -z "$install_prog" && \
func_fatal_help "you must specify an install program"
test -n "$prev" && \
func_fatal_help "the \`$prev' option requires an argument"
if test -n "$install_override_mode" && $no_mode; then
if $install_cp; then :; else
func_quote_for_eval "$install_override_mode"
func_append install_shared_prog " -m $func_quote_for_eval_result"
fi
fi
if test -z "$files"; then
if test -z "$dest"; then
func_fatal_help "no file or destination specified"
else
func_fatal_help "you must specify a destination"
fi
fi
# Strip any trailing slash from the destination.
func_stripname '' '/' "$dest"
dest=$func_stripname_result
# Check to see that the destination is a directory.
test -d "$dest" && isdir=yes
if test "$isdir" = yes; then
destdir="$dest"
destname=
else
func_dirname_and_basename "$dest" "" "."
destdir="$func_dirname_result"
destname="$func_basename_result"
# Not a directory, so check to see that there is only one file specified.
set dummy $files; shift
test "$#" -gt 1 && \
func_fatal_help "\`$dest' is not a directory"
fi
case $destdir in
[\\/]* | [A-Za-z]:[\\/]*) ;;
*)
for file in $files; do
case $file in
*.lo) ;;
*)
func_fatal_help "\`$destdir' must be an absolute directory name"
;;
esac
done
;;
esac
# This variable tells wrapper scripts just to set variables rather
# than running their programs.
libtool_install_magic="$magic"
staticlibs=
future_libdirs=
current_libdirs=
for file in $files; do
# Do each installation.
case $file in
*.$libext)
# Do the static libraries later.
func_append staticlibs " $file"
;;
*.la)
func_resolve_sysroot "$file"
file=$func_resolve_sysroot_result
# Check to see that this really is a libtool archive.
func_lalib_unsafe_p "$file" \
|| func_fatal_help "\`$file' is not a valid libtool archive"
library_names=
old_library=
relink_command=
func_source "$file"
# Add the libdir to current_libdirs if it is the destination.
if test "X$destdir" = "X$libdir"; then
case "$current_libdirs " in
*" $libdir "*) ;;
*) func_append current_libdirs " $libdir" ;;
esac
else
# Note the libdir as a future libdir.
case "$future_libdirs " in
*" $libdir "*) ;;
*) func_append future_libdirs " $libdir" ;;
esac
fi
func_dirname "$file" "/" ""
dir="$func_dirname_result"
func_append dir "$objdir"
if test -n "$relink_command"; then
# Determine the prefix the user has applied to our future dir.
inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
# Don't allow the user to place us outside of our expected
# location b/c this prevents finding dependent libraries that
# are installed to the same prefix.
# At present, this check doesn't affect windows .dll's that
# are installed into $libdir/../bin (currently, that works fine)
# but it's something to keep an eye on.
test "$inst_prefix_dir" = "$destdir" && \
func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
if test -n "$inst_prefix_dir"; then
# Stick the inst_prefix_dir data into the link command.
relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
else
relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
fi
func_warning "relinking \`$file'"
func_show_eval "$relink_command" \
'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
fi
# See the names of the shared library.
set dummy $library_names; shift
if test -n "$1"; then
realname="$1"
shift
srcname="$realname"
test -n "$relink_command" && srcname="$realname"T
# Install the shared library and build the symlinks.
func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \
'exit $?'
tstripme="$stripme"
case $host_os in
cygwin* | mingw* | pw32* | cegcc*)
case $realname in
*.dll.a)
tstripme=""
;;
esac
;;
esac
if test -n "$tstripme" && test -n "$striplib"; then
func_show_eval "$striplib $destdir/$realname" 'exit $?'
fi
if test "$#" -gt 0; then
# Delete the old symlinks, and create new ones.
# Try `ln -sf' first, because the `ln' binary might depend on
# the symlink we replace! Solaris /bin/ln does not understand -f,
# so we also need to try rm && ln -s.
for linkname
do
test "$linkname" != "$realname" \
&& func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
done
fi
# Do each command in the postinstall commands.
lib="$destdir/$realname"
func_execute_cmds "$postinstall_cmds" 'exit $?'
fi
# Install the pseudo-library for information purposes.
func_basename "$file"
name="$func_basename_result"
instname="$dir/$name"i
func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
# Maybe install the static library, too.
test -n "$old_library" && func_append staticlibs " $dir/$old_library"
;;
*.lo)
# Install (i.e. copy) a libtool object.
# Figure out destination file name, if it wasn't already specified.
if test -n "$destname"; then
destfile="$destdir/$destname"
else
func_basename "$file"
destfile="$func_basename_result"
destfile="$destdir/$destfile"
fi
# Deduce the name of the destination old-style object file.
case $destfile in
*.lo)
func_lo2o "$destfile"
staticdest=$func_lo2o_result
;;
*.$objext)
staticdest="$destfile"
destfile=
;;
*)
func_fatal_help "cannot copy a libtool object to \`$destfile'"
;;
esac
# Install the libtool object if requested.
test -n "$destfile" && \
func_show_eval "$install_prog $file $destfile" 'exit $?'
# Install the old object if enabled.
if test "$build_old_libs" = yes; then
# Deduce the name of the old-style object file.
func_lo2o "$file"
staticobj=$func_lo2o_result
func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
fi
exit $EXIT_SUCCESS
;;
*)
# Figure out destination file name, if it wasn't already specified.
if test -n "$destname"; then
destfile="$destdir/$destname"
else
func_basename "$file"
destfile="$func_basename_result"
destfile="$destdir/$destfile"
fi
# If the file is missing, and there is a .exe on the end, strip it
# because it is most likely a libtool script we actually want to
# install
stripped_ext=""
case $file in
*.exe)
if test ! -f "$file"; then
func_stripname '' '.exe' "$file"
file=$func_stripname_result
stripped_ext=".exe"
fi
;;
esac
# Do a test to see if this is really a libtool program.
case $host in
*cygwin* | *mingw*)
if func_ltwrapper_executable_p "$file"; then
func_ltwrapper_scriptname "$file"
wrapper=$func_ltwrapper_scriptname_result
else
func_stripname '' '.exe' "$file"
wrapper=$func_stripname_result
fi
;;
*)
wrapper=$file
;;
esac
if func_ltwrapper_script_p "$wrapper"; then
notinst_deplibs=
relink_command=
func_source "$wrapper"
# Check the variables that should have been set.
test -z "$generated_by_libtool_version" && \
func_fatal_error "invalid libtool wrapper script \`$wrapper'"
finalize=yes
for lib in $notinst_deplibs; do
# Check to see that each library is installed.
libdir=
if test -f "$lib"; then
func_source "$lib"
fi
libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test
if test -n "$libdir" && test ! -f "$libfile"; then
func_warning "\`$lib' has not been installed in \`$libdir'"
finalize=no
fi
done
relink_command=
func_source "$wrapper"
outputname=
if test "$fast_install" = no && test -n "$relink_command"; then
$opt_dry_run || {
if test "$finalize" = yes; then
tmpdir=`func_mktempdir`
func_basename "$file$stripped_ext"
file="$func_basename_result"
outputname="$tmpdir/$file"
# Replace the output file specification.
relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
$opt_silent || {
func_quote_for_expand "$relink_command"
eval "func_echo $func_quote_for_expand_result"
}
if eval "$relink_command"; then :
else
func_error "error: relink \`$file' with the above command before installing it"
$opt_dry_run || ${RM}r "$tmpdir"
continue
fi
file="$outputname"
else
func_warning "cannot relink \`$file'"
fi
}
else
# Install the binary that we compiled earlier.
file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"`
fi
fi
# remove .exe since cygwin /usr/bin/install will append another
# one anyway
case $install_prog,$host in
*/usr/bin/install*,*cygwin*)
case $file:$destfile in
*.exe:*.exe)
# this is ok
;;
*.exe:*)
destfile=$destfile.exe
;;
*:*.exe)
func_stripname '' '.exe' "$destfile"
destfile=$func_stripname_result
;;
esac
;;
esac
func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
$opt_dry_run || if test -n "$outputname"; then
${RM}r "$tmpdir"
fi
;;
esac
done
for file in $staticlibs; do
func_basename "$file"
name="$func_basename_result"
# Set up the ranlib parameters.
oldlib="$destdir/$name"
func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
tool_oldlib=$func_to_tool_file_result
func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
if test -n "$stripme" && test -n "$old_striplib"; then
func_show_eval "$old_striplib $tool_oldlib" 'exit $?'
fi
# Do each command in the postinstall commands.
func_execute_cmds "$old_postinstall_cmds" 'exit $?'
done
test -n "$future_libdirs" && \
func_warning "remember to run \`$progname --finish$future_libdirs'"
if test -n "$current_libdirs"; then
# Maybe just do a dry run.
$opt_dry_run && current_libdirs=" -n$current_libdirs"
exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
else
exit $EXIT_SUCCESS
fi
}
test "$opt_mode" = install && func_mode_install ${1+"$@"}
# func_generate_dlsyms outputname originator pic_p
# Extract symbols from dlprefiles and create ${outputname}S.o with
# a dlpreopen symbol table.
func_generate_dlsyms ()
{
$opt_debug
my_outputname="$1"
my_originator="$2"
my_pic_p="${3-no}"
my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'`
my_dlsyms=
if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
if test -n "$NM" && test -n "$global_symbol_pipe"; then
my_dlsyms="${my_outputname}S.c"
else
func_error "not configured to extract global symbols from dlpreopened files"
fi
fi
if test -n "$my_dlsyms"; then
case $my_dlsyms in
"") ;;
*.c)
# Discover the nlist of each of the dlfiles.
nlist="$output_objdir/${my_outputname}.nm"
func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
# Parse the name list into a source file.
func_verbose "creating $output_objdir/$my_dlsyms"
$opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */
/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */
#ifdef __cplusplus
extern \"C\" {
#endif
#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4))
#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
#endif
/* 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 con't be const, because runtime
relocations are performed -- see ld's documentation on pseudo-relocs. */
# define LT_DLSYM_CONST
#elif defined(__osf__)
/* This system does not cope well with relocations in const data. */
# define LT_DLSYM_CONST
#else
# define LT_DLSYM_CONST const
#endif
/* External symbol declarations for the compiler. */\
"
if test "$dlself" = yes; then
func_verbose "generating symbol list for \`$output'"
$opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
# Add our own program objects to the symbol list.
progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP`
for progfile in $progfiles; do
func_to_tool_file "$progfile" func_convert_file_msys_to_w32
func_verbose "extracting global C symbols from \`$func_to_tool_file_result'"
$opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'"
done
if test -n "$exclude_expsyms"; then
$opt_dry_run || {
eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
eval '$MV "$nlist"T "$nlist"'
}
fi
if test -n "$export_symbols_regex"; then
$opt_dry_run || {
eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
eval '$MV "$nlist"T "$nlist"'
}
fi
# Prepare the list of exported symbols
if test -z "$export_symbols"; then
export_symbols="$output_objdir/$outputname.exp"
$opt_dry_run || {
$RM $export_symbols
eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
case $host in
*cygwin* | *mingw* | *cegcc* )
eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
;;
esac
}
else
$opt_dry_run || {
eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
eval '$MV "$nlist"T "$nlist"'
case $host in
*cygwin* | *mingw* | *cegcc* )
eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
;;
esac
}
fi
fi
for dlprefile in $dlprefiles; do
func_verbose "extracting global C symbols from \`$dlprefile'"
func_basename "$dlprefile"
name="$func_basename_result"
case $host in
*cygwin* | *mingw* | *cegcc* )
# if an import library, we need to obtain dlname
if func_win32_import_lib_p "$dlprefile"; then
func_tr_sh "$dlprefile"
eval "curr_lafile=\$libfile_$func_tr_sh_result"
dlprefile_dlbasename=""
if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then
# Use subshell, to avoid clobbering current variable values
dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"`
if test -n "$dlprefile_dlname" ; then
func_basename "$dlprefile_dlname"
dlprefile_dlbasename="$func_basename_result"
else
# no lafile. user explicitly requested -dlpreopen .
$sharedlib_from_linklib_cmd "$dlprefile"
dlprefile_dlbasename=$sharedlib_from_linklib_result
fi
fi
$opt_dry_run || {
if test -n "$dlprefile_dlbasename" ; then
eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"'
else
func_warning "Could not compute DLL name from $name"
eval '$ECHO ": $name " >> "$nlist"'
fi
func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe |
$SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'"
}
else # not an import lib
$opt_dry_run || {
eval '$ECHO ": $name " >> "$nlist"'
func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
}
fi
;;
*)
$opt_dry_run || {
eval '$ECHO ": $name " >> "$nlist"'
func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
}
;;
esac
done
$opt_dry_run || {
# Make sure we have at least an empty file.
test -f "$nlist" || : > "$nlist"
if test -n "$exclude_expsyms"; then
$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
$MV "$nlist"T "$nlist"
fi
# Try sorting and uniquifying the output.
if $GREP -v "^: " < "$nlist" |
if sort -k 3 /dev/null 2>&1; then
sort -k 3
else
sort +2
fi |
uniq > "$nlist"S; then
:
else
$GREP -v "^: " < "$nlist" > "$nlist"S
fi
if test -f "$nlist"S; then
eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
else
echo '/* NONE */' >> "$output_objdir/$my_dlsyms"
fi
echo >> "$output_objdir/$my_dlsyms" "\
/* The mapping between symbol names and symbols. */
typedef struct {
const char *name;
void *address;
} lt_dlsymlist;
extern LT_DLSYM_CONST lt_dlsymlist
lt_${my_prefix}_LTX_preloaded_symbols[];
LT_DLSYM_CONST lt_dlsymlist
lt_${my_prefix}_LTX_preloaded_symbols[] =
{\
{ \"$my_originator\", (void *) 0 },"
case $need_lib_prefix in
no)
eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
;;
*)
eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
;;
esac
echo >> "$output_objdir/$my_dlsyms" "\
{0, (void *) 0}
};
/* This works around a problem in FreeBSD linker */
#ifdef FREEBSD_WORKAROUND
static const void *lt_preloaded_setup() {
return lt_${my_prefix}_LTX_preloaded_symbols;
}
#endif
#ifdef __cplusplus
}
#endif\
"
} # !$opt_dry_run
pic_flag_for_symtable=
case "$compile_command " in
*" -static "*) ;;
*)
case $host in
# compiling the symbol table file with pic_flag works around
# a FreeBSD bug that causes programs to crash when -lm is
# linked before any other PIC object. But we must not use
# pic_flag when linking with -static. The problem exists in
# FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
*-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
*-*-hpux*)
pic_flag_for_symtable=" $pic_flag" ;;
*)
if test "X$my_pic_p" != Xno; then
pic_flag_for_symtable=" $pic_flag"
fi
;;
esac
;;
esac
symtab_cflags=
for arg in $LTCFLAGS; do
case $arg in
-pie | -fpie | -fPIE) ;;
*) func_append symtab_cflags " $arg" ;;
esac
done
# Now compile the dynamic symbol file.
func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
# Clean up the generated files.
func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"'
# Transform the symbol file into the correct name.
symfileobj="$output_objdir/${my_outputname}S.$objext"
case $host in
*cygwin* | *mingw* | *cegcc* )
if test -f "$output_objdir/$my_outputname.def"; then
compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
else
compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
fi
;;
*)
compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
;;
esac
;;
*)
func_fatal_error "unknown suffix for \`$my_dlsyms'"
;;
esac
else
# We keep going just in case the user didn't refer to
# lt_preloaded_symbols. The linker will fail if global_symbol_pipe
# really was required.
# Nullify the symbol file.
compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"`
finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"`
fi
}
# func_win32_libid arg
# return the library type of file 'arg'
#
# Need a lot of goo to handle *both* DLLs and import libs
# Has to be a shell function in order to 'eat' the argument
# that is supplied when $file_magic_command is called.
# Despite the name, also deal with 64 bit binaries.
func_win32_libid ()
{
$opt_debug
win32_libid_type="unknown"
win32_fileres=`file -L $1 2>/dev/null`
case $win32_fileres in
*ar\ archive\ import\ library*) # definitely import
win32_libid_type="x86 archive import"
;;
*ar\ archive*) # could be an import, or static
# Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD.
if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
$EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then
func_to_tool_file "$1" func_convert_file_msys_to_w32
win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" |
$SED -n -e '
1,100{
/ I /{
s,.*,import,
p
q
}
}'`
case $win32_nmres in
import*) win32_libid_type="x86 archive import";;
*) win32_libid_type="x86 archive static";;
esac
fi
;;
*DLL*)
win32_libid_type="x86 DLL"
;;
*executable*) # but shell scripts are "executable" too...
case $win32_fileres in
*MS\ Windows\ PE\ Intel*)
win32_libid_type="x86 DLL"
;;
esac
;;
esac
$ECHO "$win32_libid_type"
}
# func_cygming_dll_for_implib ARG
#
# Platform-specific function to extract the
# name of the DLL associated with the specified
# import library ARG.
# Invoked by eval'ing the libtool variable
# $sharedlib_from_linklib_cmd
# Result is available in the variable
# $sharedlib_from_linklib_result
func_cygming_dll_for_implib ()
{
$opt_debug
sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"`
}
# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs
#
# The is the core of a fallback implementation of a
# platform-specific function to extract the name of the
# DLL associated with the specified import library LIBNAME.
#
# SECTION_NAME is either .idata$6 or .idata$7, depending
# on the platform and compiler that created the implib.
#
# Echos the name of the DLL associated with the
# specified import library.
func_cygming_dll_for_implib_fallback_core ()
{
$opt_debug
match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"`
$OBJDUMP -s --section "$1" "$2" 2>/dev/null |
$SED '/^Contents of section '"$match_literal"':/{
# Place marker at beginning of archive member dllname section
s/.*/====MARK====/
p
d
}
# These lines can sometimes be longer than 43 characters, but
# are always uninteresting
/:[ ]*file format pe[i]\{,1\}-/d
/^In archive [^:]*:/d
# Ensure marker is printed
/^====MARK====/p
# Remove all lines with less than 43 characters
/^.\{43\}/!d
# From remaining lines, remove first 43 characters
s/^.\{43\}//' |
$SED -n '
# Join marker and all lines until next marker into a single line
/^====MARK====/ b para
H
$ b para
b
:para
x
s/\n//g
# Remove the marker
s/^====MARK====//
# Remove trailing dots and whitespace
s/[\. \t]*$//
# Print
/./p' |
# we now have a list, one entry per line, of the stringified
# contents of the appropriate section of all members of the
# archive which possess that section. Heuristic: eliminate
# all those which have a first or second character that is
# a '.' (that is, objdump's representation of an unprintable
# character.) This should work for all archives with less than
# 0x302f exports -- but will fail for DLLs whose name actually
# begins with a literal '.' or a single character followed by
# a '.'.
#
# Of those that remain, print the first one.
$SED -e '/^\./d;/^.\./d;q'
}
# func_cygming_gnu_implib_p ARG
# This predicate returns with zero status (TRUE) if
# ARG is a GNU/binutils-style import library. Returns
# with nonzero status (FALSE) otherwise.
func_cygming_gnu_implib_p ()
{
$opt_debug
func_to_tool_file "$1" func_convert_file_msys_to_w32
func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'`
test -n "$func_cygming_gnu_implib_tmp"
}
# func_cygming_ms_implib_p ARG
# This predicate returns with zero status (TRUE) if
# ARG is an MS-style import library. Returns
# with nonzero status (FALSE) otherwise.
func_cygming_ms_implib_p ()
{
$opt_debug
func_to_tool_file "$1" func_convert_file_msys_to_w32
func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'`
test -n "$func_cygming_ms_implib_tmp"
}
# func_cygming_dll_for_implib_fallback ARG
# Platform-specific function to extract the
# name of the DLL associated with the specified
# import library ARG.
#
# This fallback implementation is for use when $DLLTOOL
# does not support the --identify-strict option.
# Invoked by eval'ing the libtool variable
# $sharedlib_from_linklib_cmd
# Result is available in the variable
# $sharedlib_from_linklib_result
func_cygming_dll_for_implib_fallback ()
{
$opt_debug
if func_cygming_gnu_implib_p "$1" ; then
# binutils import library
sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"`
elif func_cygming_ms_implib_p "$1" ; then
# ms-generated import library
sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"`
else
# unknown
sharedlib_from_linklib_result=""
fi
}
# func_extract_an_archive dir oldlib
func_extract_an_archive ()
{
$opt_debug
f_ex_an_ar_dir="$1"; shift
f_ex_an_ar_oldlib="$1"
if test "$lock_old_archive_extraction" = yes; then
lockfile=$f_ex_an_ar_oldlib.lock
until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
func_echo "Waiting for $lockfile to be removed"
sleep 2
done
fi
func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \
'stat=$?; rm -f "$lockfile"; exit $stat'
if test "$lock_old_archive_extraction" = yes; then
$opt_dry_run || rm -f "$lockfile"
fi
if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
:
else
func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
fi
}
# func_extract_archives gentop oldlib ...
func_extract_archives ()
{
$opt_debug
my_gentop="$1"; shift
my_oldlibs=${1+"$@"}
my_oldobjs=""
my_xlib=""
my_xabs=""
my_xdir=""
for my_xlib in $my_oldlibs; do
# Extract the objects.
case $my_xlib in
[\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
*) my_xabs=`pwd`"/$my_xlib" ;;
esac
func_basename "$my_xlib"
my_xlib="$func_basename_result"
my_xlib_u=$my_xlib
while :; do
case " $extracted_archives " in
*" $my_xlib_u "*)
func_arith $extracted_serial + 1
extracted_serial=$func_arith_result
my_xlib_u=lt$extracted_serial-$my_xlib ;;
*) break ;;
esac
done
extracted_archives="$extracted_archives $my_xlib_u"
my_xdir="$my_gentop/$my_xlib_u"
func_mkdir_p "$my_xdir"
case $host in
*-darwin*)
func_verbose "Extracting $my_xabs"
# Do not bother doing anything if just a dry run
$opt_dry_run || {
darwin_orig_dir=`pwd`
cd $my_xdir || exit $?
darwin_archive=$my_xabs
darwin_curdir=`pwd`
darwin_base_archive=`basename "$darwin_archive"`
darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
if test -n "$darwin_arches"; then
darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
darwin_arch=
func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
for darwin_arch in $darwin_arches ; do
func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
$LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
func_extract_an_archive "`pwd`" "${darwin_base_archive}"
cd "$darwin_curdir"
$RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
done # $darwin_arches
## Okay now we've a bunch of thin objects, gotta fatten them up :)
darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u`
darwin_file=
darwin_files=
for darwin_file in $darwin_filelist; do
darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP`
$LIPO -create -output "$darwin_file" $darwin_files
done # $darwin_filelist
$RM -rf unfat-$$
cd "$darwin_orig_dir"
else
cd $darwin_orig_dir
func_extract_an_archive "$my_xdir" "$my_xabs"
fi # $darwin_arches
} # !$opt_dry_run
;;
*)
func_extract_an_archive "$my_xdir" "$my_xabs"
;;
esac
my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP`
done
func_extract_archives_result="$my_oldobjs"
}
# func_emit_wrapper [arg=no]
#
# Emit a libtool wrapper script on stdout.
# Don't directly open a file because we may want to
# incorporate the script contents within a cygwin/mingw
# wrapper executable. Must ONLY be called from within
# func_mode_link because it depends on a number of variables
# set therein.
#
# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
# variable will take. If 'yes', then the emitted script
# will assume that the directory in which it is stored is
# the $objdir directory. This is a cygwin/mingw-specific
# behavior.
func_emit_wrapper ()
{
func_emit_wrapper_arg1=${1-no}
$ECHO "\
#! $SHELL
# $output - temporary wrapper script for $objdir/$outputname
# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
#
# The $output program cannot be directly executed until all the libtool
# libraries that it depends on are installed.
#
# This wrapper script should never be moved out of the build directory.
# If it is, it will not operate correctly.
# Sed substitution that helps us do robust quoting. It backslashifies
# metacharacters that are still active within double-quoted strings.
sed_quote_subst='$sed_quote_subst'
# Be Bourne compatible
if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
# Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
else
case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
fi
BIN_SH=xpg4; export BIN_SH # for Tru64
DUALCASE=1; export DUALCASE # for MKS sh
# 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
relink_command=\"$relink_command\"
# This environment variable determines our operation mode.
if test \"\$libtool_install_magic\" = \"$magic\"; then
# install mode needs the following variables:
generated_by_libtool_version='$macro_version'
notinst_deplibs='$notinst_deplibs'
else
# When we are sourced in execute mode, \$file and \$ECHO are already set.
if test \"\$libtool_execute_magic\" != \"$magic\"; then
file=\"\$0\""
qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"`
$ECHO "\
# A function that is used when there is no print builtin or printf.
func_fallback_echo ()
{
eval 'cat <<_LTECHO_EOF
\$1
_LTECHO_EOF'
}
ECHO=\"$qECHO\"
fi
# Very basic option parsing. These options are (a) specific to
# the libtool wrapper, (b) are identical between the wrapper
# /script/ and the wrapper /executable/ which is used only on
# windows platforms, and (c) all begin with the string "--lt-"
# (application programs are unlikely to have options which match
# this pattern).
#
# There are only two supported options: --lt-debug and
# --lt-dump-script. There is, deliberately, no --lt-help.
#
# The first argument to this parsing function should be the
# script's $0 value, followed by "$@".
lt_option_debug=
func_parse_lt_options ()
{
lt_script_arg0=\$0
shift
for lt_opt
do
case \"\$lt_opt\" in
--lt-debug) lt_option_debug=1 ;;
--lt-dump-script)
lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\`
test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=.
lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\`
cat \"\$lt_dump_D/\$lt_dump_F\"
exit 0
;;
--lt-*)
\$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2
exit 1
;;
esac
done
# Print the debug banner immediately:
if test -n \"\$lt_option_debug\"; then
echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2
fi
}
# Used when --lt-debug. Prints its arguments to stdout
# (redirection is the responsibility of the caller)
func_lt_dump_args ()
{
lt_dump_args_N=1;
for lt_arg
do
\$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\"
lt_dump_args_N=\`expr \$lt_dump_args_N + 1\`
done
}
# Core function for launching the target application
func_exec_program_core ()
{
"
case $host in
# Backslashes separate directories on plain windows
*-*-mingw | *-*-os2* | *-cegcc*)
$ECHO "\
if test -n \"\$lt_option_debug\"; then
\$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2
func_lt_dump_args \${1+\"\$@\"} 1>&2
fi
exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
"
;;
*)
$ECHO "\
if test -n \"\$lt_option_debug\"; then
\$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2
func_lt_dump_args \${1+\"\$@\"} 1>&2
fi
exec \"\$progdir/\$program\" \${1+\"\$@\"}
"
;;
esac
$ECHO "\
\$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
exit 1
}
# A function to encapsulate launching the target application
# Strips options in the --lt-* namespace from \$@ and
# launches target application with the remaining arguments.
func_exec_program ()
{
case \" \$* \" in
*\\ --lt-*)
for lt_wr_arg
do
case \$lt_wr_arg in
--lt-*) ;;
*) set x \"\$@\" \"\$lt_wr_arg\"; shift;;
esac
shift
done ;;
esac
func_exec_program_core \${1+\"\$@\"}
}
# Parse options
func_parse_lt_options \"\$0\" \${1+\"\$@\"}
# Find the directory that this script lives in.
thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\`
test \"x\$thisdir\" = \"x\$file\" && thisdir=.
# Follow symbolic links until we get to the real thisdir.
file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\`
while test -n \"\$file\"; do
destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\`
# If there was a directory component, then change thisdir.
if test \"x\$destdir\" != \"x\$file\"; then
case \"\$destdir\" in
[\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
*) thisdir=\"\$thisdir/\$destdir\" ;;
esac
fi
file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\`
file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\`
done
# Usually 'no', except on cygwin/mingw when embedded into
# the cwrapper.
WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1
if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
# special case for '.'
if test \"\$thisdir\" = \".\"; then
thisdir=\`pwd\`
fi
# remove .libs from thisdir
case \"\$thisdir\" in
*[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;;
$objdir ) thisdir=. ;;
esac
fi
# Try to get the absolute directory name.
absdir=\`cd \"\$thisdir\" && pwd\`
test -n \"\$absdir\" && thisdir=\"\$absdir\"
"
if test "$fast_install" = yes; then
$ECHO "\
program=lt-'$outputname'$exeext
progdir=\"\$thisdir/$objdir\"
if test ! -f \"\$progdir/\$program\" ||
{ file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
test \"X\$file\" != \"X\$progdir/\$program\"; }; then
file=\"\$\$-\$program\"
if test ! -d \"\$progdir\"; then
$MKDIR \"\$progdir\"
else
$RM \"\$progdir/\$file\"
fi"
$ECHO "\
# relink executable if necessary
if test -n \"\$relink_command\"; then
if relink_command_output=\`eval \$relink_command 2>&1\`; then :
else
$ECHO \"\$relink_command_output\" >&2
$RM \"\$progdir/\$file\"
exit 1
fi
fi
$MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
{ $RM \"\$progdir/\$program\";
$MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
$RM \"\$progdir/\$file\"
fi"
else
$ECHO "\
program='$outputname'
progdir=\"\$thisdir/$objdir\"
"
fi
$ECHO "\
if test -f \"\$progdir/\$program\"; then"
# fixup the dll searchpath if we need to.
#
# Fix the DLL searchpath if we need to. Do this before prepending
# to shlibpath, because on Windows, both are PATH and uninstalled
# libraries must come first.
if test -n "$dllsearchpath"; then
$ECHO "\
# Add the dll search path components to the executable PATH
PATH=$dllsearchpath:\$PATH
"
fi
# Export our shlibpath_var if we have one.
if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
$ECHO "\
# Add our own library path to $shlibpath_var
$shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
# Some systems cannot cope with colon-terminated $shlibpath_var
# The second colon is a workaround for a bug in BeOS R4 sed
$shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\`
export $shlibpath_var
"
fi
$ECHO "\
if test \"\$libtool_execute_magic\" != \"$magic\"; then
# Run the actual program with our arguments.
func_exec_program \${1+\"\$@\"}
fi
else
# The program doesn't exist.
\$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
\$ECHO \"This script is just a wrapper for \$program.\" 1>&2
\$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
exit 1
fi
fi\
"
}
# func_emit_cwrapperexe_src
# emit the source code for a wrapper executable on stdout
# Must ONLY be called from within func_mode_link because
# it depends on a number of variable set therein.
func_emit_cwrapperexe_src ()
{
cat <
#include
#ifdef _MSC_VER
# include
# include
# include
#else
# include
# include
# ifdef __CYGWIN__
# include
# endif
#endif
#include
#include
#include
#include
#include
#include
#include
#include
/* declarations of non-ANSI functions */
#if defined(__MINGW32__)
# ifdef __STRICT_ANSI__
int _putenv (const char *);
# endif
#elif defined(__CYGWIN__)
# ifdef __STRICT_ANSI__
char *realpath (const char *, char *);
int putenv (char *);
int setenv (const char *, const char *, int);
# endif
/* #elif defined (other platforms) ... */
#endif
/* portability defines, excluding path handling macros */
#if defined(_MSC_VER)
# define setmode _setmode
# define stat _stat
# define chmod _chmod
# define getcwd _getcwd
# define putenv _putenv
# define S_IXUSR _S_IEXEC
# ifndef _INTPTR_T_DEFINED
# define _INTPTR_T_DEFINED
# define intptr_t int
# endif
#elif defined(__MINGW32__)
# define setmode _setmode
# define stat _stat
# define chmod _chmod
# define getcwd _getcwd
# define putenv _putenv
#elif defined(__CYGWIN__)
# define HAVE_SETENV
# define FOPEN_WB "wb"
/* #elif defined (other platforms) ... */
#endif
#if defined(PATH_MAX)
# define LT_PATHMAX PATH_MAX
#elif defined(MAXPATHLEN)
# define LT_PATHMAX MAXPATHLEN
#else
# define LT_PATHMAX 1024
#endif
#ifndef S_IXOTH
# define S_IXOTH 0
#endif
#ifndef S_IXGRP
# define S_IXGRP 0
#endif
/* path handling portability macros */
#ifndef DIR_SEPARATOR
# define DIR_SEPARATOR '/'
# define PATH_SEPARATOR ':'
#endif
#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
defined (__OS2__)
# define HAVE_DOS_BASED_FILE_SYSTEM
# define FOPEN_WB "wb"
# ifndef DIR_SEPARATOR_2
# define DIR_SEPARATOR_2 '\\'
# endif
# ifndef PATH_SEPARATOR_2
# define PATH_SEPARATOR_2 ';'
# endif
#endif
#ifndef DIR_SEPARATOR_2
# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
#else /* DIR_SEPARATOR_2 */
# define IS_DIR_SEPARATOR(ch) \
(((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
#endif /* DIR_SEPARATOR_2 */
#ifndef PATH_SEPARATOR_2
# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
#else /* PATH_SEPARATOR_2 */
# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
#endif /* PATH_SEPARATOR_2 */
#ifndef FOPEN_WB
# define FOPEN_WB "w"
#endif
#ifndef _O_BINARY
# define _O_BINARY 0
#endif
#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
#define XFREE(stale) do { \
if (stale) { free ((void *) stale); stale = 0; } \
} while (0)
#if defined(LT_DEBUGWRAPPER)
static int lt_debug = 1;
#else
static int lt_debug = 0;
#endif
const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */
void *xmalloc (size_t num);
char *xstrdup (const char *string);
const char *base_name (const char *name);
char *find_executable (const char *wrapper);
char *chase_symlinks (const char *pathspec);
int make_executable (const char *path);
int check_executable (const char *path);
char *strendzap (char *str, const char *pat);
void lt_debugprintf (const char *file, int line, const char *fmt, ...);
void lt_fatal (const char *file, int line, const char *message, ...);
static const char *nonnull (const char *s);
static const char *nonempty (const char *s);
void lt_setenv (const char *name, const char *value);
char *lt_extend_str (const char *orig_value, const char *add, int to_end);
void lt_update_exe_path (const char *name, const char *value);
void lt_update_lib_path (const char *name, const char *value);
char **prepare_spawn (char **argv);
void lt_dump_script (FILE *f);
EOF
cat <= 0)
&& (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
return 1;
else
return 0;
}
int
make_executable (const char *path)
{
int rval = 0;
struct stat st;
lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n",
nonempty (path));
if ((!path) || (!*path))
return 0;
if (stat (path, &st) >= 0)
{
rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
}
return rval;
}
/* Searches for the full path of the wrapper. Returns
newly allocated full path name if found, NULL otherwise
Does not chase symlinks, even on platforms that support them.
*/
char *
find_executable (const char *wrapper)
{
int has_slash = 0;
const char *p;
const char *p_next;
/* static buffer for getcwd */
char tmp[LT_PATHMAX + 1];
int tmp_len;
char *concat_name;
lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n",
nonempty (wrapper));
if ((wrapper == NULL) || (*wrapper == '\0'))
return NULL;
/* Absolute path? */
#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
{
concat_name = xstrdup (wrapper);
if (check_executable (concat_name))
return concat_name;
XFREE (concat_name);
}
else
{
#endif
if (IS_DIR_SEPARATOR (wrapper[0]))
{
concat_name = xstrdup (wrapper);
if (check_executable (concat_name))
return concat_name;
XFREE (concat_name);
}
#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
}
#endif
for (p = wrapper; *p; p++)
if (*p == '/')
{
has_slash = 1;
break;
}
if (!has_slash)
{
/* no slashes; search PATH */
const char *path = getenv ("PATH");
if (path != NULL)
{
for (p = path; *p; p = p_next)
{
const char *q;
size_t p_len;
for (q = p; *q; q++)
if (IS_PATH_SEPARATOR (*q))
break;
p_len = q - p;
p_next = (*q == '\0' ? q : q + 1);
if (p_len == 0)
{
/* empty path: current directory */
if (getcwd (tmp, LT_PATHMAX) == NULL)
lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
nonnull (strerror (errno)));
tmp_len = strlen (tmp);
concat_name =
XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
memcpy (concat_name, tmp, tmp_len);
concat_name[tmp_len] = '/';
strcpy (concat_name + tmp_len + 1, wrapper);
}
else
{
concat_name =
XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
memcpy (concat_name, p, p_len);
concat_name[p_len] = '/';
strcpy (concat_name + p_len + 1, wrapper);
}
if (check_executable (concat_name))
return concat_name;
XFREE (concat_name);
}
}
/* not found in PATH; assume curdir */
}
/* Relative path | not found in path: prepend cwd */
if (getcwd (tmp, LT_PATHMAX) == NULL)
lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
nonnull (strerror (errno)));
tmp_len = strlen (tmp);
concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
memcpy (concat_name, tmp, tmp_len);
concat_name[tmp_len] = '/';
strcpy (concat_name + tmp_len + 1, wrapper);
if (check_executable (concat_name))
return concat_name;
XFREE (concat_name);
return NULL;
}
char *
chase_symlinks (const char *pathspec)
{
#ifndef S_ISLNK
return xstrdup (pathspec);
#else
char buf[LT_PATHMAX];
struct stat s;
char *tmp_pathspec = xstrdup (pathspec);
char *p;
int has_symlinks = 0;
while (strlen (tmp_pathspec) && !has_symlinks)
{
lt_debugprintf (__FILE__, __LINE__,
"checking path component for symlinks: %s\n",
tmp_pathspec);
if (lstat (tmp_pathspec, &s) == 0)
{
if (S_ISLNK (s.st_mode) != 0)
{
has_symlinks = 1;
break;
}
/* search backwards for last DIR_SEPARATOR */
p = tmp_pathspec + strlen (tmp_pathspec) - 1;
while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
p--;
if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
{
/* no more DIR_SEPARATORS left */
break;
}
*p = '\0';
}
else
{
lt_fatal (__FILE__, __LINE__,
"error accessing file \"%s\": %s",
tmp_pathspec, nonnull (strerror (errno)));
}
}
XFREE (tmp_pathspec);
if (!has_symlinks)
{
return xstrdup (pathspec);
}
tmp_pathspec = realpath (pathspec, buf);
if (tmp_pathspec == 0)
{
lt_fatal (__FILE__, __LINE__,
"could not follow symlinks for %s", pathspec);
}
return xstrdup (tmp_pathspec);
#endif
}
char *
strendzap (char *str, const char *pat)
{
size_t len, patlen;
assert (str != NULL);
assert (pat != NULL);
len = strlen (str);
patlen = strlen (pat);
if (patlen <= len)
{
str += len - patlen;
if (strcmp (str, pat) == 0)
*str = '\0';
}
return str;
}
void
lt_debugprintf (const char *file, int line, const char *fmt, ...)
{
va_list args;
if (lt_debug)
{
(void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line);
va_start (args, fmt);
(void) vfprintf (stderr, fmt, args);
va_end (args);
}
}
static void
lt_error_core (int exit_status, const char *file,
int line, const char *mode,
const char *message, va_list ap)
{
fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode);
vfprintf (stderr, message, ap);
fprintf (stderr, ".\n");
if (exit_status >= 0)
exit (exit_status);
}
void
lt_fatal (const char *file, int line, const char *message, ...)
{
va_list ap;
va_start (ap, message);
lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap);
va_end (ap);
}
static const char *
nonnull (const char *s)
{
return s ? s : "(null)";
}
static const char *
nonempty (const char *s)
{
return (s && !*s) ? "(empty)" : nonnull (s);
}
void
lt_setenv (const char *name, const char *value)
{
lt_debugprintf (__FILE__, __LINE__,
"(lt_setenv) setting '%s' to '%s'\n",
nonnull (name), nonnull (value));
{
#ifdef HAVE_SETENV
/* always make a copy, for consistency with !HAVE_SETENV */
char *str = xstrdup (value);
setenv (name, str, 1);
#else
int len = strlen (name) + 1 + strlen (value) + 1;
char *str = XMALLOC (char, len);
sprintf (str, "%s=%s", name, value);
if (putenv (str) != EXIT_SUCCESS)
{
XFREE (str);
}
#endif
}
}
char *
lt_extend_str (const char *orig_value, const char *add, int to_end)
{
char *new_value;
if (orig_value && *orig_value)
{
int orig_value_len = strlen (orig_value);
int add_len = strlen (add);
new_value = XMALLOC (char, add_len + orig_value_len + 1);
if (to_end)
{
strcpy (new_value, orig_value);
strcpy (new_value + orig_value_len, add);
}
else
{
strcpy (new_value, add);
strcpy (new_value + add_len, orig_value);
}
}
else
{
new_value = xstrdup (add);
}
return new_value;
}
void
lt_update_exe_path (const char *name, const char *value)
{
lt_debugprintf (__FILE__, __LINE__,
"(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
nonnull (name), nonnull (value));
if (name && *name && value && *value)
{
char *new_value = lt_extend_str (getenv (name), value, 0);
/* some systems can't cope with a ':'-terminated path #' */
int len = strlen (new_value);
while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
{
new_value[len-1] = '\0';
}
lt_setenv (name, new_value);
XFREE (new_value);
}
}
void
lt_update_lib_path (const char *name, const char *value)
{
lt_debugprintf (__FILE__, __LINE__,
"(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
nonnull (name), nonnull (value));
if (name && *name && value && *value)
{
char *new_value = lt_extend_str (getenv (name), value, 0);
lt_setenv (name, new_value);
XFREE (new_value);
}
}
EOF
case $host_os in
mingw*)
cat <<"EOF"
/* Prepares an argument vector before calling spawn().
Note that spawn() does not by itself call the command interpreter
(getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&v);
v.dwPlatformId == VER_PLATFORM_WIN32_NT;
}) ? "cmd.exe" : "command.com").
Instead it simply concatenates the arguments, separated by ' ', and calls
CreateProcess(). We must quote the arguments since Win32 CreateProcess()
interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
special way:
- Space and tab are interpreted as delimiters. They are not treated as
delimiters if they are surrounded by double quotes: "...".
- Unescaped double quotes are removed from the input. Their only effect is
that within double quotes, space and tab are treated like normal
characters.
- Backslashes not followed by double quotes are not special.
- But 2*n+1 backslashes followed by a double quote become
n backslashes followed by a double quote (n >= 0):
\" -> "
\\\" -> \"
\\\\\" -> \\"
*/
#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
char **
prepare_spawn (char **argv)
{
size_t argc;
char **new_argv;
size_t i;
/* Count number of arguments. */
for (argc = 0; argv[argc] != NULL; argc++)
;
/* Allocate new argument vector. */
new_argv = XMALLOC (char *, argc + 1);
/* Put quoted arguments into the new argument vector. */
for (i = 0; i < argc; i++)
{
const char *string = argv[i];
if (string[0] == '\0')
new_argv[i] = xstrdup ("\"\"");
else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
{
int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
size_t length;
unsigned int backslashes;
const char *s;
char *quoted_string;
char *p;
length = 0;
backslashes = 0;
if (quote_around)
length++;
for (s = string; *s != '\0'; s++)
{
char c = *s;
if (c == '"')
length += backslashes + 1;
length++;
if (c == '\\')
backslashes++;
else
backslashes = 0;
}
if (quote_around)
length += backslashes + 1;
quoted_string = XMALLOC (char, length + 1);
p = quoted_string;
backslashes = 0;
if (quote_around)
*p++ = '"';
for (s = string; *s != '\0'; s++)
{
char c = *s;
if (c == '"')
{
unsigned int j;
for (j = backslashes + 1; j > 0; j--)
*p++ = '\\';
}
*p++ = c;
if (c == '\\')
backslashes++;
else
backslashes = 0;
}
if (quote_around)
{
unsigned int j;
for (j = backslashes; j > 0; j--)
*p++ = '\\';
*p++ = '"';
}
*p = '\0';
new_argv[i] = quoted_string;
}
else
new_argv[i] = (char *) string;
}
new_argv[argc] = NULL;
return new_argv;
}
EOF
;;
esac
cat <<"EOF"
void lt_dump_script (FILE* f)
{
EOF
func_emit_wrapper yes |
$SED -n -e '
s/^\(.\{79\}\)\(..*\)/\1\
\2/
h
s/\([\\"]\)/\\\1/g
s/$/\\n/
s/\([^\n]*\).*/ fputs ("\1", f);/p
g
D'
cat <<"EOF"
}
EOF
}
# end: func_emit_cwrapperexe_src
# func_win32_import_lib_p ARG
# True if ARG is an import lib, as indicated by $file_magic_cmd
func_win32_import_lib_p ()
{
$opt_debug
case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in
*import*) : ;;
*) false ;;
esac
}
# func_mode_link arg...
func_mode_link ()
{
$opt_debug
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
# It is impossible to link a dll without this setting, and
# we shouldn't force the makefile maintainer to figure out
# which system we are compiling for in order to pass an extra
# flag for every libtool invocation.
# allow_undefined=no
# FIXME: Unfortunately, there are problems with the above when trying
# to make a dll which has undefined symbols, in which case not
# even a static library is built. For now, we need to specify
# -no-undefined on the libtool link line when we can be certain
# that all symbols are satisfied, otherwise we get a static library.
allow_undefined=yes
;;
*)
allow_undefined=yes
;;
esac
libtool_args=$nonopt
base_compile="$nonopt $@"
compile_command=$nonopt
finalize_command=$nonopt
compile_rpath=
finalize_rpath=
compile_shlibpath=
finalize_shlibpath=
convenience=
old_convenience=
deplibs=
old_deplibs=
compiler_flags=
linker_flags=
dllsearchpath=
lib_search_path=`pwd`
inst_prefix_dir=
new_inherited_linker_flags=
avoid_version=no
bindir=
dlfiles=
dlprefiles=
dlself=no
export_dynamic=no
export_symbols=
export_symbols_regex=
generated=
libobjs=
ltlibs=
module=no
no_install=no
objs=
non_pic_objects=
precious_files_regex=
prefer_static_libs=no
preload=no
prev=
prevarg=
release=
rpath=
xrpath=
perm_rpath=
temp_rpath=
thread_safe=no
vinfo=
vinfo_number=no
weak_libs=
single_module="${wl}-single_module"
func_infer_tag $base_compile
# We need to know -static, to get the right output filenames.
for arg
do
case $arg in
-shared)
test "$build_libtool_libs" != yes && \
func_fatal_configuration "can not build a shared library"
build_old_libs=no
break
;;
-all-static | -static | -static-libtool-libs)
case $arg in
-all-static)
if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
func_warning "complete static linking is impossible in this configuration"
fi
if test -n "$link_static_flag"; then
dlopen_self=$dlopen_self_static
fi
prefer_static_libs=yes
;;
-static)
if test -z "$pic_flag" && test -n "$link_static_flag"; then
dlopen_self=$dlopen_self_static
fi
prefer_static_libs=built
;;
-static-libtool-libs)
if test -z "$pic_flag" && test -n "$link_static_flag"; then
dlopen_self=$dlopen_self_static
fi
prefer_static_libs=yes
;;
esac
build_libtool_libs=no
build_old_libs=yes
break
;;
esac
done
# See if our shared archives depend on static archives.
test -n "$old_archive_from_new_cmds" && build_old_libs=yes
# Go through the arguments, transforming them on the way.
while test "$#" -gt 0; do
arg="$1"
shift
func_quote_for_eval "$arg"
qarg=$func_quote_for_eval_unquoted_result
func_append libtool_args " $func_quote_for_eval_result"
# If the previous option needs an argument, assign it.
if test -n "$prev"; then
case $prev in
output)
func_append compile_command " @OUTPUT@"
func_append finalize_command " @OUTPUT@"
;;
esac
case $prev in
bindir)
bindir="$arg"
prev=
continue
;;
dlfiles|dlprefiles)
if test "$preload" = no; then
# Add the symbol object into the linking commands.
func_append compile_command " @SYMFILE@"
func_append finalize_command " @SYMFILE@"
preload=yes
fi
case $arg in
*.la | *.lo) ;; # We handle these cases below.
force)
if test "$dlself" = no; then
dlself=needless
export_dynamic=yes
fi
prev=
continue
;;
self)
if test "$prev" = dlprefiles; then
dlself=yes
elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
dlself=yes
else
dlself=needless
export_dynamic=yes
fi
prev=
continue
;;
*)
if test "$prev" = dlfiles; then
func_append dlfiles " $arg"
else
func_append dlprefiles " $arg"
fi
prev=
continue
;;
esac
;;
expsyms)
export_symbols="$arg"
test -f "$arg" \
|| func_fatal_error "symbol file \`$arg' does not exist"
prev=
continue
;;
expsyms_regex)
export_symbols_regex="$arg"
prev=
continue
;;
framework)
case $host in
*-*-darwin*)
case "$deplibs " in
*" $qarg.ltframework "*) ;;
*) func_append deplibs " $qarg.ltframework" # this is fixed later
;;
esac
;;
esac
prev=
continue
;;
inst_prefix)
inst_prefix_dir="$arg"
prev=
continue
;;
objectlist)
if test -f "$arg"; then
save_arg=$arg
moreargs=
for fil in `cat "$save_arg"`
do
# func_append moreargs " $fil"
arg=$fil
# A libtool-controlled object.
# Check to see that this really is a libtool object.
if func_lalib_unsafe_p "$arg"; then
pic_object=
non_pic_object=
# Read the .lo file
func_source "$arg"
if test -z "$pic_object" ||
test -z "$non_pic_object" ||
test "$pic_object" = none &&
test "$non_pic_object" = none; then
func_fatal_error "cannot find name of object for \`$arg'"
fi
# Extract subdirectory from the argument.
func_dirname "$arg" "/" ""
xdir="$func_dirname_result"
if test "$pic_object" != none; then
# Prepend the subdirectory the object is found in.
pic_object="$xdir$pic_object"
if test "$prev" = dlfiles; then
if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
func_append dlfiles " $pic_object"
prev=
continue
else
# If libtool objects are unsupported, then we need to preload.
prev=dlprefiles
fi
fi
# CHECK ME: I think I busted this. -Ossama
if test "$prev" = dlprefiles; then
# Preload the old-style object.
func_append dlprefiles " $pic_object"
prev=
fi
# A PIC object.
func_append libobjs " $pic_object"
arg="$pic_object"
fi
# Non-PIC object.
if test "$non_pic_object" != none; then
# Prepend the subdirectory the object is found in.
non_pic_object="$xdir$non_pic_object"
# A standard non-PIC object
func_append non_pic_objects " $non_pic_object"
if test -z "$pic_object" || test "$pic_object" = none ; then
arg="$non_pic_object"
fi
else
# If the PIC object exists, use it instead.
# $xdir was prepended to $pic_object above.
non_pic_object="$pic_object"
func_append non_pic_objects " $non_pic_object"
fi
else
# Only an error if not doing a dry-run.
if $opt_dry_run; then
# Extract subdirectory from the argument.
func_dirname "$arg" "/" ""
xdir="$func_dirname_result"
func_lo2o "$arg"
pic_object=$xdir$objdir/$func_lo2o_result
non_pic_object=$xdir$func_lo2o_result
func_append libobjs " $pic_object"
func_append non_pic_objects " $non_pic_object"
else
func_fatal_error "\`$arg' is not a valid libtool object"
fi
fi
done
else
func_fatal_error "link input file \`$arg' does not exist"
fi
arg=$save_arg
prev=
continue
;;
precious_regex)
precious_files_regex="$arg"
prev=
continue
;;
release)
release="-$arg"
prev=
continue
;;
rpath | xrpath)
# We need an absolute path.
case $arg in
[\\/]* | [A-Za-z]:[\\/]*) ;;
*)
func_fatal_error "only absolute run-paths are allowed"
;;
esac
if test "$prev" = rpath; then
case "$rpath " in
*" $arg "*) ;;
*) func_append rpath " $arg" ;;
esac
else
case "$xrpath " in
*" $arg "*) ;;
*) func_append xrpath " $arg" ;;
esac
fi
prev=
continue
;;
shrext)
shrext_cmds="$arg"
prev=
continue
;;
weak)
func_append weak_libs " $arg"
prev=
continue
;;
xcclinker)
func_append linker_flags " $qarg"
func_append compiler_flags " $qarg"
prev=
func_append compile_command " $qarg"
func_append finalize_command " $qarg"
continue
;;
xcompiler)
func_append compiler_flags " $qarg"
prev=
func_append compile_command " $qarg"
func_append finalize_command " $qarg"
continue
;;
xlinker)
func_append linker_flags " $qarg"
func_append compiler_flags " $wl$qarg"
prev=
func_append compile_command " $wl$qarg"
func_append finalize_command " $wl$qarg"
continue
;;
*)
eval "$prev=\"\$arg\""
prev=
continue
;;
esac
fi # test -n "$prev"
prevarg="$arg"
case $arg in
-all-static)
if test -n "$link_static_flag"; then
# See comment for -static flag below, for more details.
func_append compile_command " $link_static_flag"
func_append finalize_command " $link_static_flag"
fi
continue
;;
-allow-undefined)
# FIXME: remove this flag sometime in the future.
func_fatal_error "\`-allow-undefined' must not be used because it is the default"
;;
-avoid-version)
avoid_version=yes
continue
;;
-bindir)
prev=bindir
continue
;;
-dlopen)
prev=dlfiles
continue
;;
-dlpreopen)
prev=dlprefiles
continue
;;
-export-dynamic)
export_dynamic=yes
continue
;;
-export-symbols | -export-symbols-regex)
if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
func_fatal_error "more than one -exported-symbols argument is not allowed"
fi
if test "X$arg" = "X-export-symbols"; then
prev=expsyms
else
prev=expsyms_regex
fi
continue
;;
-framework)
prev=framework
continue
;;
-inst-prefix-dir)
prev=inst_prefix
continue
;;
# The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
# so, if we see these flags be careful not to treat them like -L
-L[A-Z][A-Z]*:*)
case $with_gcc/$host in
no/*-*-irix* | /*-*-irix*)
func_append compile_command " $arg"
func_append finalize_command " $arg"
;;
esac
continue
;;
-L*)
func_stripname "-L" '' "$arg"
if test -z "$func_stripname_result"; then
if test "$#" -gt 0; then
func_fatal_error "require no space between \`-L' and \`$1'"
else
func_fatal_error "need path for \`-L' option"
fi
fi
func_resolve_sysroot "$func_stripname_result"
dir=$func_resolve_sysroot_result
# We need an absolute path.
case $dir in
[\\/]* | [A-Za-z]:[\\/]*) ;;
*)
absdir=`cd "$dir" && pwd`
test -z "$absdir" && \
func_fatal_error "cannot determine absolute directory name of \`$dir'"
dir="$absdir"
;;
esac
case "$deplibs " in
*" -L$dir "* | *" $arg "*)
# Will only happen for absolute or sysroot arguments
;;
*)
# Preserve sysroot, but never include relative directories
case $dir in
[\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;;
*) func_append deplibs " -L$dir" ;;
esac
func_append lib_search_path " $dir"
;;
esac
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'`
case :$dllsearchpath: in
*":$dir:"*) ;;
::) dllsearchpath=$dir;;
*) func_append dllsearchpath ":$dir";;
esac
case :$dllsearchpath: in
*":$testbindir:"*) ;;
::) dllsearchpath=$testbindir;;
*) func_append dllsearchpath ":$testbindir";;
esac
;;
esac
continue
;;
-l*)
if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*)
# These systems don't actually have a C or math library (as such)
continue
;;
*-*-os2*)
# These systems don't actually have a C library (as such)
test "X$arg" = "X-lc" && continue
;;
*-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
# Do not include libc due to us having libc/libc_r.
test "X$arg" = "X-lc" && continue
;;
*-*-rhapsody* | *-*-darwin1.[012])
# Rhapsody C and math libraries are in the System framework
func_append deplibs " System.ltframework"
continue
;;
*-*-sco3.2v5* | *-*-sco5v6*)
# Causes problems with __ctype
test "X$arg" = "X-lc" && continue
;;
*-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
# Compiler inserts libc in the correct place for threads to work
test "X$arg" = "X-lc" && continue
;;
esac
elif test "X$arg" = "X-lc_r"; then
case $host in
*-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
# Do not include libc_r directly, use -pthread flag.
continue
;;
esac
fi
func_append deplibs " $arg"
continue
;;
-module)
module=yes
continue
;;
# Tru64 UNIX uses -model [arg] to determine the layout of C++
# classes, name mangling, and exception handling.
# Darwin uses the -arch flag to determine output architecture.
-model|-arch|-isysroot|--sysroot)
func_append compiler_flags " $arg"
func_append compile_command " $arg"
func_append finalize_command " $arg"
prev=xcompiler
continue
;;
-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
|-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
func_append compiler_flags " $arg"
func_append compile_command " $arg"
func_append finalize_command " $arg"
case "$new_inherited_linker_flags " in
*" $arg "*) ;;
* ) func_append new_inherited_linker_flags " $arg" ;;
esac
continue
;;
-multi_module)
single_module="${wl}-multi_module"
continue
;;
-no-fast-install)
fast_install=no
continue
;;
-no-install)
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
# The PATH hackery in wrapper scripts is required on Windows
# and Darwin in order for the loader to find any dlls it needs.
func_warning "\`-no-install' is ignored for $host"
func_warning "assuming \`-no-fast-install' instead"
fast_install=no
;;
*) no_install=yes ;;
esac
continue
;;
-no-undefined)
allow_undefined=no
continue
;;
-objectlist)
prev=objectlist
continue
;;
-o) prev=output ;;
-precious-files-regex)
prev=precious_regex
continue
;;
-release)
prev=release
continue
;;
-rpath)
prev=rpath
continue
;;
-R)
prev=xrpath
continue
;;
-R*)
func_stripname '-R' '' "$arg"
dir=$func_stripname_result
# We need an absolute path.
case $dir in
[\\/]* | [A-Za-z]:[\\/]*) ;;
=*)
func_stripname '=' '' "$dir"
dir=$lt_sysroot$func_stripname_result
;;
*)
func_fatal_error "only absolute run-paths are allowed"
;;
esac
case "$xrpath " in
*" $dir "*) ;;
*) func_append xrpath " $dir" ;;
esac
continue
;;
-shared)
# The effects of -shared are defined in a previous loop.
continue
;;
-shrext)
prev=shrext
continue
;;
-static | -static-libtool-libs)
# The effects of -static are defined in a previous loop.
# We used to do the same as -all-static on platforms that
# didn't have a PIC flag, but the assumption that the effects
# would be equivalent was wrong. It would break on at least
# Digital Unix and AIX.
continue
;;
-thread-safe)
thread_safe=yes
continue
;;
-version-info)
prev=vinfo
continue
;;
-version-number)
prev=vinfo
vinfo_number=yes
continue
;;
-weak)
prev=weak
continue
;;
-Wc,*)
func_stripname '-Wc,' '' "$arg"
args=$func_stripname_result
arg=
save_ifs="$IFS"; IFS=','
for flag in $args; do
IFS="$save_ifs"
func_quote_for_eval "$flag"
func_append arg " $func_quote_for_eval_result"
func_append compiler_flags " $func_quote_for_eval_result"
done
IFS="$save_ifs"
func_stripname ' ' '' "$arg"
arg=$func_stripname_result
;;
-Wl,*)
func_stripname '-Wl,' '' "$arg"
args=$func_stripname_result
arg=
save_ifs="$IFS"; IFS=','
for flag in $args; do
IFS="$save_ifs"
func_quote_for_eval "$flag"
func_append arg " $wl$func_quote_for_eval_result"
func_append compiler_flags " $wl$func_quote_for_eval_result"
func_append linker_flags " $func_quote_for_eval_result"
done
IFS="$save_ifs"
func_stripname ' ' '' "$arg"
arg=$func_stripname_result
;;
-Xcompiler)
prev=xcompiler
continue
;;
-Xlinker)
prev=xlinker
continue
;;
-XCClinker)
prev=xcclinker
continue
;;
# -msg_* for osf cc
-msg_*)
func_quote_for_eval "$arg"
arg="$func_quote_for_eval_result"
;;
# Flags to be passed through unchanged, with rationale:
# -64, -mips[0-9] enable 64-bit mode for the SGI compiler
# -r[0-9][0-9]* specify processor for the SGI compiler
# -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler
# +DA*, +DD* enable 64-bit mode for the HP compiler
# -q* compiler args for the IBM compiler
# -m*, -t[45]*, -txscale* architecture-specific flags for GCC
# -F/path path to uninstalled frameworks, gcc on darwin
# -p, -pg, --coverage, -fprofile-* profiling flags for GCC
# @file GCC response files
# -tp=* Portland pgcc target processor selection
# --sysroot=* for sysroot support
# -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
-64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
-t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
-O*|-flto*|-fwhopr*|-fuse-linker-plugin)
func_quote_for_eval "$arg"
arg="$func_quote_for_eval_result"
func_append compile_command " $arg"
func_append finalize_command " $arg"
func_append compiler_flags " $arg"
continue
;;
# Some other compiler flag.
-* | +*)
func_quote_for_eval "$arg"
arg="$func_quote_for_eval_result"
;;
*.$objext)
# A standard object.
func_append objs " $arg"
;;
*.lo)
# A libtool-controlled object.
# Check to see that this really is a libtool object.
if func_lalib_unsafe_p "$arg"; then
pic_object=
non_pic_object=
# Read the .lo file
func_source "$arg"
if test -z "$pic_object" ||
test -z "$non_pic_object" ||
test "$pic_object" = none &&
test "$non_pic_object" = none; then
func_fatal_error "cannot find name of object for \`$arg'"
fi
# Extract subdirectory from the argument.
func_dirname "$arg" "/" ""
xdir="$func_dirname_result"
if test "$pic_object" != none; then
# Prepend the subdirectory the object is found in.
pic_object="$xdir$pic_object"
if test "$prev" = dlfiles; then
if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
func_append dlfiles " $pic_object"
prev=
continue
else
# If libtool objects are unsupported, then we need to preload.
prev=dlprefiles
fi
fi
# CHECK ME: I think I busted this. -Ossama
if test "$prev" = dlprefiles; then
# Preload the old-style object.
func_append dlprefiles " $pic_object"
prev=
fi
# A PIC object.
func_append libobjs " $pic_object"
arg="$pic_object"
fi
# Non-PIC object.
if test "$non_pic_object" != none; then
# Prepend the subdirectory the object is found in.
non_pic_object="$xdir$non_pic_object"
# A standard non-PIC object
func_append non_pic_objects " $non_pic_object"
if test -z "$pic_object" || test "$pic_object" = none ; then
arg="$non_pic_object"
fi
else
# If the PIC object exists, use it instead.
# $xdir was prepended to $pic_object above.
non_pic_object="$pic_object"
func_append non_pic_objects " $non_pic_object"
fi
else
# Only an error if not doing a dry-run.
if $opt_dry_run; then
# Extract subdirectory from the argument.
func_dirname "$arg" "/" ""
xdir="$func_dirname_result"
func_lo2o "$arg"
pic_object=$xdir$objdir/$func_lo2o_result
non_pic_object=$xdir$func_lo2o_result
func_append libobjs " $pic_object"
func_append non_pic_objects " $non_pic_object"
else
func_fatal_error "\`$arg' is not a valid libtool object"
fi
fi
;;
*.$libext)
# An archive.
func_append deplibs " $arg"
func_append old_deplibs " $arg"
continue
;;
*.la)
# A libtool-controlled library.
func_resolve_sysroot "$arg"
if test "$prev" = dlfiles; then
# This library was specified with -dlopen.
func_append dlfiles " $func_resolve_sysroot_result"
prev=
elif test "$prev" = dlprefiles; then
# The library was specified with -dlpreopen.
func_append dlprefiles " $func_resolve_sysroot_result"
prev=
else
func_append deplibs " $func_resolve_sysroot_result"
fi
continue
;;
# Some other compiler argument.
*)
# Unknown arguments in both finalize_command and compile_command need
# to be aesthetically quoted because they are evaled later.
func_quote_for_eval "$arg"
arg="$func_quote_for_eval_result"
;;
esac # arg
# Now actually substitute the argument into the commands.
if test -n "$arg"; then
func_append compile_command " $arg"
func_append finalize_command " $arg"
fi
done # argument parsing loop
test -n "$prev" && \
func_fatal_help "the \`$prevarg' option requires an argument"
if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
eval arg=\"$export_dynamic_flag_spec\"
func_append compile_command " $arg"
func_append finalize_command " $arg"
fi
oldlibs=
# calculate the name of the file, without its directory
func_basename "$output"
outputname="$func_basename_result"
libobjs_save="$libobjs"
if test -n "$shlibpath_var"; then
# get the directories listed in $shlibpath_var
eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\`
else
shlib_search_path=
fi
eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
func_dirname "$output" "/" ""
output_objdir="$func_dirname_result$objdir"
func_to_tool_file "$output_objdir/"
tool_output_objdir=$func_to_tool_file_result
# Create the object directory.
func_mkdir_p "$output_objdir"
# Determine the type of output
case $output in
"")
func_fatal_help "you must specify an output file"
;;
*.$libext) linkmode=oldlib ;;
*.lo | *.$objext) linkmode=obj ;;
*.la) linkmode=lib ;;
*) linkmode=prog ;; # Anything else should be a program.
esac
specialdeplibs=
libs=
# Find all interdependent deplibs by searching for libraries
# that are linked more than once (e.g. -la -lb -la)
for deplib in $deplibs; do
if $opt_preserve_dup_deps ; then
case "$libs " in
*" $deplib "*) func_append specialdeplibs " $deplib" ;;
esac
fi
func_append libs " $deplib"
done
if test "$linkmode" = lib; then
libs="$predeps $libs $compiler_lib_search_path $postdeps"
# Compute libraries that are listed more than once in $predeps
# $postdeps and mark them as special (i.e., whose duplicates are
# not to be eliminated).
pre_post_deps=
if $opt_duplicate_compiler_generated_deps; then
for pre_post_dep in $predeps $postdeps; do
case "$pre_post_deps " in
*" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;;
esac
func_append pre_post_deps " $pre_post_dep"
done
fi
pre_post_deps=
fi
deplibs=
newdependency_libs=
newlib_search_path=
need_relink=no # whether we're linking any uninstalled libtool libraries
notinst_deplibs= # not-installed libtool libraries
notinst_path= # paths that contain not-installed libtool libraries
case $linkmode in
lib)
passes="conv dlpreopen link"
for file in $dlfiles $dlprefiles; do
case $file in
*.la) ;;
*)
func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file"
;;
esac
done
;;
prog)
compile_deplibs=
finalize_deplibs=
alldeplibs=no
newdlfiles=
newdlprefiles=
passes="conv scan dlopen dlpreopen link"
;;
*) passes="conv"
;;
esac
for pass in $passes; do
# The preopen pass in lib mode reverses $deplibs; put it back here
# so that -L comes before libs that need it for instance...
if test "$linkmode,$pass" = "lib,link"; then
## FIXME: Find the place where the list is rebuilt in the wrong
## order, and fix it there properly
tmp_deplibs=
for deplib in $deplibs; do
tmp_deplibs="$deplib $tmp_deplibs"
done
deplibs="$tmp_deplibs"
fi
if test "$linkmode,$pass" = "lib,link" ||
test "$linkmode,$pass" = "prog,scan"; then
libs="$deplibs"
deplibs=
fi
if test "$linkmode" = prog; then
case $pass in
dlopen) libs="$dlfiles" ;;
dlpreopen) libs="$dlprefiles" ;;
link)
libs="$deplibs %DEPLIBS%"
test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
;;
esac
fi
if test "$linkmode,$pass" = "lib,dlpreopen"; then
# Collect and forward deplibs of preopened libtool libs
for lib in $dlprefiles; do
# Ignore non-libtool-libs
dependency_libs=
func_resolve_sysroot "$lib"
case $lib in
*.la) func_source "$func_resolve_sysroot_result" ;;
esac
# Collect preopened libtool deplibs, except any this library
# has declared as weak libs
for deplib in $dependency_libs; do
func_basename "$deplib"
deplib_base=$func_basename_result
case " $weak_libs " in
*" $deplib_base "*) ;;
*) func_append deplibs " $deplib" ;;
esac
done
done
libs="$dlprefiles"
fi
if test "$pass" = dlopen; then
# Collect dlpreopened libraries
save_deplibs="$deplibs"
deplibs=
fi
for deplib in $libs; do
lib=
found=no
case $deplib in
-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
|-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
if test "$linkmode,$pass" = "prog,link"; then
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
func_append compiler_flags " $deplib"
if test "$linkmode" = lib ; then
case "$new_inherited_linker_flags " in
*" $deplib "*) ;;
* ) func_append new_inherited_linker_flags " $deplib" ;;
esac
fi
fi
continue
;;
-l*)
if test "$linkmode" != lib && test "$linkmode" != prog; then
func_warning "\`-l' is ignored for archives/objects"
continue
fi
func_stripname '-l' '' "$deplib"
name=$func_stripname_result
if test "$linkmode" = lib; then
searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
else
searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
fi
for searchdir in $searchdirs; do
for search_ext in .la $std_shrext .so .a; do
# Search the libtool library
lib="$searchdir/lib${name}${search_ext}"
if test -f "$lib"; then
if test "$search_ext" = ".la"; then
found=yes
else
found=no
fi
break 2
fi
done
done
if test "$found" != yes; then
# deplib doesn't seem to be a libtool library
if test "$linkmode,$pass" = "prog,link"; then
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
deplibs="$deplib $deplibs"
test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
fi
continue
else # deplib is a libtool library
# If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
# We need to do some special things here, and not later.
if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
case " $predeps $postdeps " in
*" $deplib "*)
if func_lalib_p "$lib"; then
library_names=
old_library=
func_source "$lib"
for l in $old_library $library_names; do
ll="$l"
done
if test "X$ll" = "X$old_library" ; then # only static version available
found=no
func_dirname "$lib" "" "."
ladir="$func_dirname_result"
lib=$ladir/$old_library
if test "$linkmode,$pass" = "prog,link"; then
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
deplibs="$deplib $deplibs"
test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
fi
continue
fi
fi
;;
*) ;;
esac
fi
fi
;; # -l
*.ltframework)
if test "$linkmode,$pass" = "prog,link"; then
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
deplibs="$deplib $deplibs"
if test "$linkmode" = lib ; then
case "$new_inherited_linker_flags " in
*" $deplib "*) ;;
* ) func_append new_inherited_linker_flags " $deplib" ;;
esac
fi
fi
continue
;;
-L*)
case $linkmode in
lib)
deplibs="$deplib $deplibs"
test "$pass" = conv && continue
newdependency_libs="$deplib $newdependency_libs"
func_stripname '-L' '' "$deplib"
func_resolve_sysroot "$func_stripname_result"
func_append newlib_search_path " $func_resolve_sysroot_result"
;;
prog)
if test "$pass" = conv; then
deplibs="$deplib $deplibs"
continue
fi
if test "$pass" = scan; then
deplibs="$deplib $deplibs"
else
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
fi
func_stripname '-L' '' "$deplib"
func_resolve_sysroot "$func_stripname_result"
func_append newlib_search_path " $func_resolve_sysroot_result"
;;
*)
func_warning "\`-L' is ignored for archives/objects"
;;
esac # linkmode
continue
;; # -L
-R*)
if test "$pass" = link; then
func_stripname '-R' '' "$deplib"
func_resolve_sysroot "$func_stripname_result"
dir=$func_resolve_sysroot_result
# Make sure the xrpath contains only unique directories.
case "$xrpath " in
*" $dir "*) ;;
*) func_append xrpath " $dir" ;;
esac
fi
deplibs="$deplib $deplibs"
continue
;;
*.la)
func_resolve_sysroot "$deplib"
lib=$func_resolve_sysroot_result
;;
*.$libext)
if test "$pass" = conv; then
deplibs="$deplib $deplibs"
continue
fi
case $linkmode in
lib)
# Linking convenience modules into shared libraries is allowed,
# but linking other static libraries is non-portable.
case " $dlpreconveniencelibs " in
*" $deplib "*) ;;
*)
valid_a_lib=no
case $deplibs_check_method in
match_pattern*)
set dummy $deplibs_check_method; shift
match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \
| $EGREP "$match_pattern_regex" > /dev/null; then
valid_a_lib=yes
fi
;;
pass_all)
valid_a_lib=yes
;;
esac
if test "$valid_a_lib" != yes; then
echo
$ECHO "*** Warning: Trying to link with static lib archive $deplib."
echo "*** I have the capability to make that library automatically link in when"
echo "*** you link to this library. But I can only do this if you have a"
echo "*** shared version of the library, which you do not appear to have"
echo "*** because the file extensions .$libext of this argument makes me believe"
echo "*** that it is just a static archive that I should not use here."
else
echo
$ECHO "*** Warning: Linking the shared library $output against the"
$ECHO "*** static library $deplib is not portable!"
deplibs="$deplib $deplibs"
fi
;;
esac
continue
;;
prog)
if test "$pass" != link; then
deplibs="$deplib $deplibs"
else
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
fi
continue
;;
esac # linkmode
;; # *.$libext
*.lo | *.$objext)
if test "$pass" = conv; then
deplibs="$deplib $deplibs"
elif test "$linkmode" = prog; then
if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
# If there is no dlopen support or we're linking statically,
# we need to preload.
func_append newdlprefiles " $deplib"
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
else
func_append newdlfiles " $deplib"
fi
fi
continue
;;
%DEPLIBS%)
alldeplibs=yes
continue
;;
esac # case $deplib
if test "$found" = yes || test -f "$lib"; then :
else
func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'"
fi
# Check to see that this really is a libtool archive.
func_lalib_unsafe_p "$lib" \
|| func_fatal_error "\`$lib' is not a valid libtool archive"
func_dirname "$lib" "" "."
ladir="$func_dirname_result"
dlname=
dlopen=
dlpreopen=
libdir=
library_names=
old_library=
inherited_linker_flags=
# If the library was installed with an old release of libtool,
# it will not redefine variables installed, or shouldnotlink
installed=yes
shouldnotlink=no
avoidtemprpath=
# Read the .la file
func_source "$lib"
# Convert "-framework foo" to "foo.ltframework"
if test -n "$inherited_linker_flags"; then
tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'`
for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
case " $new_inherited_linker_flags " in
*" $tmp_inherited_linker_flag "*) ;;
*) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";;
esac
done
fi
dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
if test "$linkmode,$pass" = "lib,link" ||
test "$linkmode,$pass" = "prog,scan" ||
{ test "$linkmode" != prog && test "$linkmode" != lib; }; then
test -n "$dlopen" && func_append dlfiles " $dlopen"
test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen"
fi
if test "$pass" = conv; then
# Only check for convenience libraries
deplibs="$lib $deplibs"
if test -z "$libdir"; then
if test -z "$old_library"; then
func_fatal_error "cannot find name of link library for \`$lib'"
fi
# It is a libtool convenience library, so add in its objects.
func_append convenience " $ladir/$objdir/$old_library"
func_append old_convenience " $ladir/$objdir/$old_library"
tmp_libs=
for deplib in $dependency_libs; do
deplibs="$deplib $deplibs"
if $opt_preserve_dup_deps ; then
case "$tmp_libs " in
*" $deplib "*) func_append specialdeplibs " $deplib" ;;
esac
fi
func_append tmp_libs " $deplib"
done
elif test "$linkmode" != prog && test "$linkmode" != lib; then
func_fatal_error "\`$lib' is not a convenience library"
fi
continue
fi # $pass = conv
# Get the name of the library we link against.
linklib=
if test -n "$old_library" &&
{ test "$prefer_static_libs" = yes ||
test "$prefer_static_libs,$installed" = "built,no"; }; then
linklib=$old_library
else
for l in $old_library $library_names; do
linklib="$l"
done
fi
if test -z "$linklib"; then
func_fatal_error "cannot find name of link library for \`$lib'"
fi
# This library was specified with -dlopen.
if test "$pass" = dlopen; then
if test -z "$libdir"; then
func_fatal_error "cannot -dlopen a convenience library: \`$lib'"
fi
if test -z "$dlname" ||
test "$dlopen_support" != yes ||
test "$build_libtool_libs" = no; then
# If there is no dlname, no dlopen support or we're linking
# statically, we need to preload. We also need to preload any
# dependent libraries so libltdl's deplib preloader doesn't
# bomb out in the load deplibs phase.
func_append dlprefiles " $lib $dependency_libs"
else
func_append newdlfiles " $lib"
fi
continue
fi # $pass = dlopen
# We need an absolute path.
case $ladir in
[\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
*)
abs_ladir=`cd "$ladir" && pwd`
if test -z "$abs_ladir"; then
func_warning "cannot determine absolute directory name of \`$ladir'"
func_warning "passing it literally to the linker, although it might fail"
abs_ladir="$ladir"
fi
;;
esac
func_basename "$lib"
laname="$func_basename_result"
# Find the relevant object directory and library name.
if test "X$installed" = Xyes; then
if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
func_warning "library \`$lib' was moved."
dir="$ladir"
absdir="$abs_ladir"
libdir="$abs_ladir"
else
dir="$lt_sysroot$libdir"
absdir="$lt_sysroot$libdir"
fi
test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
else
if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
dir="$ladir"
absdir="$abs_ladir"
# Remove this search path later
func_append notinst_path " $abs_ladir"
else
dir="$ladir/$objdir"
absdir="$abs_ladir/$objdir"
# Remove this search path later
func_append notinst_path " $abs_ladir"
fi
fi # $installed = yes
func_stripname 'lib' '.la' "$laname"
name=$func_stripname_result
# This library was specified with -dlpreopen.
if test "$pass" = dlpreopen; then
if test -z "$libdir" && test "$linkmode" = prog; then
func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'"
fi
case "$host" in
# special handling for platforms with PE-DLLs.
*cygwin* | *mingw* | *cegcc* )
# Linker will automatically link against shared library if both
# static and shared are present. Therefore, ensure we extract
# symbols from the import library if a shared library is present
# (otherwise, the dlopen module name will be incorrect). We do
# this by putting the import library name into $newdlprefiles.
# We recover the dlopen module name by 'saving' the la file
# name in a special purpose variable, and (later) extracting the
# dlname from the la file.
if test -n "$dlname"; then
func_tr_sh "$dir/$linklib"
eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname"
func_append newdlprefiles " $dir/$linklib"
else
func_append newdlprefiles " $dir/$old_library"
# Keep a list of preopened convenience libraries to check
# that they are being used correctly in the link pass.
test -z "$libdir" && \
func_append dlpreconveniencelibs " $dir/$old_library"
fi
;;
* )
# Prefer using a static library (so that no silly _DYNAMIC symbols
# are required to link).
if test -n "$old_library"; then
func_append newdlprefiles " $dir/$old_library"
# Keep a list of preopened convenience libraries to check
# that they are being used correctly in the link pass.
test -z "$libdir" && \
func_append dlpreconveniencelibs " $dir/$old_library"
# Otherwise, use the dlname, so that lt_dlopen finds it.
elif test -n "$dlname"; then
func_append newdlprefiles " $dir/$dlname"
else
func_append newdlprefiles " $dir/$linklib"
fi
;;
esac
fi # $pass = dlpreopen
if test -z "$libdir"; then
# Link the convenience library
if test "$linkmode" = lib; then
deplibs="$dir/$old_library $deplibs"
elif test "$linkmode,$pass" = "prog,link"; then
compile_deplibs="$dir/$old_library $compile_deplibs"
finalize_deplibs="$dir/$old_library $finalize_deplibs"
else
deplibs="$lib $deplibs" # used for prog,scan pass
fi
continue
fi
if test "$linkmode" = prog && test "$pass" != link; then
func_append newlib_search_path " $ladir"
deplibs="$lib $deplibs"
linkalldeplibs=no
if test "$link_all_deplibs" != no || test -z "$library_names" ||
test "$build_libtool_libs" = no; then
linkalldeplibs=yes
fi
tmp_libs=
for deplib in $dependency_libs; do
case $deplib in
-L*) func_stripname '-L' '' "$deplib"
func_resolve_sysroot "$func_stripname_result"
func_append newlib_search_path " $func_resolve_sysroot_result"
;;
esac
# Need to link against all dependency_libs?
if test "$linkalldeplibs" = yes; then
deplibs="$deplib $deplibs"
else
# Need to hardcode shared library paths
# or/and link against static libraries
newdependency_libs="$deplib $newdependency_libs"
fi
if $opt_preserve_dup_deps ; then
case "$tmp_libs " in
*" $deplib "*) func_append specialdeplibs " $deplib" ;;
esac
fi
func_append tmp_libs " $deplib"
done # for deplib
continue
fi # $linkmode = prog...
if test "$linkmode,$pass" = "prog,link"; then
if test -n "$library_names" &&
{ { test "$prefer_static_libs" = no ||
test "$prefer_static_libs,$installed" = "built,yes"; } ||
test -z "$old_library"; }; then
# We need to hardcode the library path
if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
# Make sure the rpath contains only unique directories.
case "$temp_rpath:" in
*"$absdir:"*) ;;
*) func_append temp_rpath "$absdir:" ;;
esac
fi
# Hardcode the library path.
# Skip directories that are in the system default run-time
# search path.
case " $sys_lib_dlsearch_path " in
*" $absdir "*) ;;
*)
case "$compile_rpath " in
*" $absdir "*) ;;
*) func_append compile_rpath " $absdir" ;;
esac
;;
esac
case " $sys_lib_dlsearch_path " in
*" $libdir "*) ;;
*)
case "$finalize_rpath " in
*" $libdir "*) ;;
*) func_append finalize_rpath " $libdir" ;;
esac
;;
esac
fi # $linkmode,$pass = prog,link...
if test "$alldeplibs" = yes &&
{ test "$deplibs_check_method" = pass_all ||
{ test "$build_libtool_libs" = yes &&
test -n "$library_names"; }; }; then
# We only need to search for static libraries
continue
fi
fi
link_static=no # Whether the deplib will be linked statically
use_static_libs=$prefer_static_libs
if test "$use_static_libs" = built && test "$installed" = yes; then
use_static_libs=no
fi
if test -n "$library_names" &&
{ test "$use_static_libs" = no || test -z "$old_library"; }; then
case $host in
*cygwin* | *mingw* | *cegcc*)
# No point in relinking DLLs because paths are not encoded
func_append notinst_deplibs " $lib"
need_relink=no
;;
*)
if test "$installed" = no; then
func_append notinst_deplibs " $lib"
need_relink=yes
fi
;;
esac
# This is a shared library
# Warn about portability, can't link against -module's on some
# systems (darwin). Don't bleat about dlopened modules though!
dlopenmodule=""
for dlpremoduletest in $dlprefiles; do
if test "X$dlpremoduletest" = "X$lib"; then
dlopenmodule="$dlpremoduletest"
break
fi
done
if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then
echo
if test "$linkmode" = prog; then
$ECHO "*** Warning: Linking the executable $output against the loadable module"
else
$ECHO "*** Warning: Linking the shared library $output against the loadable module"
fi
$ECHO "*** $linklib is not portable!"
fi
if test "$linkmode" = lib &&
test "$hardcode_into_libs" = yes; then
# Hardcode the library path.
# Skip directories that are in the system default run-time
# search path.
case " $sys_lib_dlsearch_path " in
*" $absdir "*) ;;
*)
case "$compile_rpath " in
*" $absdir "*) ;;
*) func_append compile_rpath " $absdir" ;;
esac
;;
esac
case " $sys_lib_dlsearch_path " in
*" $libdir "*) ;;
*)
case "$finalize_rpath " in
*" $libdir "*) ;;
*) func_append finalize_rpath " $libdir" ;;
esac
;;
esac
fi
if test -n "$old_archive_from_expsyms_cmds"; then
# figure out the soname
set dummy $library_names
shift
realname="$1"
shift
libname=`eval "\\$ECHO \"$libname_spec\""`
# use dlname if we got it. it's perfectly good, no?
if test -n "$dlname"; then
soname="$dlname"
elif test -n "$soname_spec"; then
# bleh windows
case $host in
*cygwin* | mingw* | *cegcc*)
func_arith $current - $age
major=$func_arith_result
versuffix="-$major"
;;
esac
eval soname=\"$soname_spec\"
else
soname="$realname"
fi
# Make a new name for the extract_expsyms_cmds to use
soroot="$soname"
func_basename "$soroot"
soname="$func_basename_result"
func_stripname 'lib' '.dll' "$soname"
newlib=libimp-$func_stripname_result.a
# If the library has no export list, then create one now
if test -f "$output_objdir/$soname-def"; then :
else
func_verbose "extracting exported symbol list from \`$soname'"
func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
fi
# Create $newlib
if test -f "$output_objdir/$newlib"; then :; else
func_verbose "generating import library for \`$soname'"
func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
fi
# make sure the library variables are pointing to the new library
dir=$output_objdir
linklib=$newlib
fi # test -n "$old_archive_from_expsyms_cmds"
if test "$linkmode" = prog || test "$opt_mode" != relink; then
add_shlibpath=
add_dir=
add=
lib_linked=yes
case $hardcode_action in
immediate | unsupported)
if test "$hardcode_direct" = no; then
add="$dir/$linklib"
case $host in
*-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
*-*-sysv4*uw2*) add_dir="-L$dir" ;;
*-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
*-*-unixware7*) add_dir="-L$dir" ;;
*-*-darwin* )
# if the lib is a (non-dlopened) module then we can not
# link against it, someone is ignoring the earlier warnings
if /usr/bin/file -L $add 2> /dev/null |
$GREP ": [^:]* bundle" >/dev/null ; then
if test "X$dlopenmodule" != "X$lib"; then
$ECHO "*** Warning: lib $linklib is a module, not a shared library"
if test -z "$old_library" ; then
echo
echo "*** And there doesn't seem to be a static archive available"
echo "*** The link will probably fail, sorry"
else
add="$dir/$old_library"
fi
elif test -n "$old_library"; then
add="$dir/$old_library"
fi
fi
esac
elif test "$hardcode_minus_L" = no; then
case $host in
*-*-sunos*) add_shlibpath="$dir" ;;
esac
add_dir="-L$dir"
add="-l$name"
elif test "$hardcode_shlibpath_var" = no; then
add_shlibpath="$dir"
add="-l$name"
else
lib_linked=no
fi
;;
relink)
if test "$hardcode_direct" = yes &&
test "$hardcode_direct_absolute" = no; then
add="$dir/$linklib"
elif test "$hardcode_minus_L" = yes; then
add_dir="-L$absdir"
# Try looking first in the location we're being installed to.
if test -n "$inst_prefix_dir"; then
case $libdir in
[\\/]*)
func_append add_dir " -L$inst_prefix_dir$libdir"
;;
esac
fi
add="-l$name"
elif test "$hardcode_shlibpath_var" = yes; then
add_shlibpath="$dir"
add="-l$name"
else
lib_linked=no
fi
;;
*) lib_linked=no ;;
esac
if test "$lib_linked" != yes; then
func_fatal_configuration "unsupported hardcode properties"
fi
if test -n "$add_shlibpath"; then
case :$compile_shlibpath: in
*":$add_shlibpath:"*) ;;
*) func_append compile_shlibpath "$add_shlibpath:" ;;
esac
fi
if test "$linkmode" = prog; then
test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
test -n "$add" && compile_deplibs="$add $compile_deplibs"
else
test -n "$add_dir" && deplibs="$add_dir $deplibs"
test -n "$add" && deplibs="$add $deplibs"
if test "$hardcode_direct" != yes &&
test "$hardcode_minus_L" != yes &&
test "$hardcode_shlibpath_var" = yes; then
case :$finalize_shlibpath: in
*":$libdir:"*) ;;
*) func_append finalize_shlibpath "$libdir:" ;;
esac
fi
fi
fi
if test "$linkmode" = prog || test "$opt_mode" = relink; then
add_shlibpath=
add_dir=
add=
# Finalize command for both is simple: just hardcode it.
if test "$hardcode_direct" = yes &&
test "$hardcode_direct_absolute" = no; then
add="$libdir/$linklib"
elif test "$hardcode_minus_L" = yes; then
add_dir="-L$libdir"
add="-l$name"
elif test "$hardcode_shlibpath_var" = yes; then
case :$finalize_shlibpath: in
*":$libdir:"*) ;;
*) func_append finalize_shlibpath "$libdir:" ;;
esac
add="-l$name"
elif test "$hardcode_automatic" = yes; then
if test -n "$inst_prefix_dir" &&
test -f "$inst_prefix_dir$libdir/$linklib" ; then
add="$inst_prefix_dir$libdir/$linklib"
else
add="$libdir/$linklib"
fi
else
# We cannot seem to hardcode it, guess we'll fake it.
add_dir="-L$libdir"
# Try looking first in the location we're being installed to.
if test -n "$inst_prefix_dir"; then
case $libdir in
[\\/]*)
func_append add_dir " -L$inst_prefix_dir$libdir"
;;
esac
fi
add="-l$name"
fi
if test "$linkmode" = prog; then
test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
else
test -n "$add_dir" && deplibs="$add_dir $deplibs"
test -n "$add" && deplibs="$add $deplibs"
fi
fi
elif test "$linkmode" = prog; then
# Here we assume that one of hardcode_direct or hardcode_minus_L
# is not unsupported. This is valid on all known static and
# shared platforms.
if test "$hardcode_direct" != unsupported; then
test -n "$old_library" && linklib="$old_library"
compile_deplibs="$dir/$linklib $compile_deplibs"
finalize_deplibs="$dir/$linklib $finalize_deplibs"
else
compile_deplibs="-l$name -L$dir $compile_deplibs"
finalize_deplibs="-l$name -L$dir $finalize_deplibs"
fi
elif test "$build_libtool_libs" = yes; then
# Not a shared library
if test "$deplibs_check_method" != pass_all; then
# We're trying link a shared library against a static one
# but the system doesn't support it.
# Just print a warning and add the library to dependency_libs so
# that the program can be linked against the static library.
echo
$ECHO "*** Warning: This system can not link to static lib archive $lib."
echo "*** I have the capability to make that library automatically link in when"
echo "*** you link to this library. But I can only do this if you have a"
echo "*** shared version of the library, which you do not appear to have."
if test "$module" = yes; then
echo "*** But as you try to build a module library, libtool will still create "
echo "*** a static module, that should work as long as the dlopening application"
echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
if test -z "$global_symbol_pipe"; then
echo
echo "*** However, this would only work if libtool was able to extract symbol"
echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
echo "*** not find such a program. So, this module is probably useless."
echo "*** \`nm' from GNU binutils and a full rebuild may help."
fi
if test "$build_old_libs" = no; then
build_libtool_libs=module
build_old_libs=yes
else
build_libtool_libs=no
fi
fi
else
deplibs="$dir/$old_library $deplibs"
link_static=yes
fi
fi # link shared/static library?
if test "$linkmode" = lib; then
if test -n "$dependency_libs" &&
{ test "$hardcode_into_libs" != yes ||
test "$build_old_libs" = yes ||
test "$link_static" = yes; }; then
# Extract -R from dependency_libs
temp_deplibs=
for libdir in $dependency_libs; do
case $libdir in
-R*) func_stripname '-R' '' "$libdir"
temp_xrpath=$func_stripname_result
case " $xrpath " in
*" $temp_xrpath "*) ;;
*) func_append xrpath " $temp_xrpath";;
esac;;
*) func_append temp_deplibs " $libdir";;
esac
done
dependency_libs="$temp_deplibs"
fi
func_append newlib_search_path " $absdir"
# Link against this library
test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
# ... and its dependency_libs
tmp_libs=
for deplib in $dependency_libs; do
newdependency_libs="$deplib $newdependency_libs"
case $deplib in
-L*) func_stripname '-L' '' "$deplib"
func_resolve_sysroot "$func_stripname_result";;
*) func_resolve_sysroot "$deplib" ;;
esac
if $opt_preserve_dup_deps ; then
case "$tmp_libs " in
*" $func_resolve_sysroot_result "*)
func_append specialdeplibs " $func_resolve_sysroot_result" ;;
esac
fi
func_append tmp_libs " $func_resolve_sysroot_result"
done
if test "$link_all_deplibs" != no; then
# Add the search paths of all dependency libraries
for deplib in $dependency_libs; do
path=
case $deplib in
-L*) path="$deplib" ;;
*.la)
func_resolve_sysroot "$deplib"
deplib=$func_resolve_sysroot_result
func_dirname "$deplib" "" "."
dir=$func_dirname_result
# We need an absolute path.
case $dir in
[\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
*)
absdir=`cd "$dir" && pwd`
if test -z "$absdir"; then
func_warning "cannot determine absolute directory name of \`$dir'"
absdir="$dir"
fi
;;
esac
if $GREP "^installed=no" $deplib > /dev/null; then
case $host in
*-*-darwin*)
depdepl=
eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
if test -n "$deplibrary_names" ; then
for tmp in $deplibrary_names ; do
depdepl=$tmp
done
if test -f "$absdir/$objdir/$depdepl" ; then
depdepl="$absdir/$objdir/$depdepl"
darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
if test -z "$darwin_install_name"; then
darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
fi
func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}"
func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}"
path=
fi
fi
;;
*)
path="-L$absdir/$objdir"
;;
esac
else
eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
test -z "$libdir" && \
func_fatal_error "\`$deplib' is not a valid libtool archive"
test "$absdir" != "$libdir" && \
func_warning "\`$deplib' seems to be moved"
path="-L$absdir"
fi
;;
esac
case " $deplibs " in
*" $path "*) ;;
*) deplibs="$path $deplibs" ;;
esac
done
fi # link_all_deplibs != no
fi # linkmode = lib
done # for deplib in $libs
if test "$pass" = link; then
if test "$linkmode" = "prog"; then
compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
else
compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
fi
fi
dependency_libs="$newdependency_libs"
if test "$pass" = dlpreopen; then
# Link the dlpreopened libraries before other libraries
for deplib in $save_deplibs; do
deplibs="$deplib $deplibs"
done
fi
if test "$pass" != dlopen; then
if test "$pass" != conv; then
# Make sure lib_search_path contains only unique directories.
lib_search_path=
for dir in $newlib_search_path; do
case "$lib_search_path " in
*" $dir "*) ;;
*) func_append lib_search_path " $dir" ;;
esac
done
newlib_search_path=
fi
if test "$linkmode,$pass" != "prog,link"; then
vars="deplibs"
else
vars="compile_deplibs finalize_deplibs"
fi
for var in $vars dependency_libs; do
# Add libraries to $var in reverse order
eval tmp_libs=\"\$$var\"
new_libs=
for deplib in $tmp_libs; do
# FIXME: Pedantically, this is the right thing to do, so
# that some nasty dependency loop isn't accidentally
# broken:
#new_libs="$deplib $new_libs"
# Pragmatically, this seems to cause very few problems in
# practice:
case $deplib in
-L*) new_libs="$deplib $new_libs" ;;
-R*) ;;
*)
# And here is the reason: when a library appears more
# than once as an explicit dependence of a library, or
# is implicitly linked in more than once by the
# compiler, it is considered special, and multiple
# occurrences thereof are not removed. Compare this
# with having the same library being listed as a
# dependency of multiple other libraries: in this case,
# we know (pedantically, we assume) the library does not
# need to be listed more than once, so we keep only the
# last copy. This is not always right, but it is rare
# enough that we require users that really mean to play
# such unportable linking tricks to link the library
# using -Wl,-lname, so that libtool does not consider it
# for duplicate removal.
case " $specialdeplibs " in
*" $deplib "*) new_libs="$deplib $new_libs" ;;
*)
case " $new_libs " in
*" $deplib "*) ;;
*) new_libs="$deplib $new_libs" ;;
esac
;;
esac
;;
esac
done
tmp_libs=
for deplib in $new_libs; do
case $deplib in
-L*)
case " $tmp_libs " in
*" $deplib "*) ;;
*) func_append tmp_libs " $deplib" ;;
esac
;;
*) func_append tmp_libs " $deplib" ;;
esac
done
eval $var=\"$tmp_libs\"
done # for var
fi
# Last step: remove runtime libs from dependency_libs
# (they stay in deplibs)
tmp_libs=
for i in $dependency_libs ; do
case " $predeps $postdeps $compiler_lib_search_path " in
*" $i "*)
i=""
;;
esac
if test -n "$i" ; then
func_append tmp_libs " $i"
fi
done
dependency_libs=$tmp_libs
done # for pass
if test "$linkmode" = prog; then
dlfiles="$newdlfiles"
fi
if test "$linkmode" = prog || test "$linkmode" = lib; then
dlprefiles="$newdlprefiles"
fi
case $linkmode in
oldlib)
if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
func_warning "\`-dlopen' is ignored for archives"
fi
case " $deplibs" in
*\ -l* | *\ -L*)
func_warning "\`-l' and \`-L' are ignored for archives" ;;
esac
test -n "$rpath" && \
func_warning "\`-rpath' is ignored for archives"
test -n "$xrpath" && \
func_warning "\`-R' is ignored for archives"
test -n "$vinfo" && \
func_warning "\`-version-info/-version-number' is ignored for archives"
test -n "$release" && \
func_warning "\`-release' is ignored for archives"
test -n "$export_symbols$export_symbols_regex" && \
func_warning "\`-export-symbols' is ignored for archives"
# Now set the variables for building old libraries.
build_libtool_libs=no
oldlibs="$output"
func_append objs "$old_deplibs"
;;
lib)
# Make sure we only generate libraries of the form `libNAME.la'.
case $outputname in
lib*)
func_stripname 'lib' '.la' "$outputname"
name=$func_stripname_result
eval shared_ext=\"$shrext_cmds\"
eval libname=\"$libname_spec\"
;;
*)
test "$module" = no && \
func_fatal_help "libtool library \`$output' must begin with \`lib'"
if test "$need_lib_prefix" != no; then
# Add the "lib" prefix for modules if required
func_stripname '' '.la' "$outputname"
name=$func_stripname_result
eval shared_ext=\"$shrext_cmds\"
eval libname=\"$libname_spec\"
else
func_stripname '' '.la' "$outputname"
libname=$func_stripname_result
fi
;;
esac
if test -n "$objs"; then
if test "$deplibs_check_method" != pass_all; then
func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs"
else
echo
$ECHO "*** Warning: Linking the shared library $output against the non-libtool"
$ECHO "*** objects $objs is not portable!"
func_append libobjs " $objs"
fi
fi
test "$dlself" != no && \
func_warning "\`-dlopen self' is ignored for libtool libraries"
set dummy $rpath
shift
test "$#" -gt 1 && \
func_warning "ignoring multiple \`-rpath's for a libtool library"
install_libdir="$1"
oldlibs=
if test -z "$rpath"; then
if test "$build_libtool_libs" = yes; then
# Building a libtool convenience library.
# Some compilers have problems with a `.al' extension so
# convenience libraries should have the same extension an
# archive normally would.
oldlibs="$output_objdir/$libname.$libext $oldlibs"
build_libtool_libs=convenience
build_old_libs=yes
fi
test -n "$vinfo" && \
func_warning "\`-version-info/-version-number' is ignored for convenience libraries"
test -n "$release" && \
func_warning "\`-release' is ignored for convenience libraries"
else
# Parse the version information argument.
save_ifs="$IFS"; IFS=':'
set dummy $vinfo 0 0 0
shift
IFS="$save_ifs"
test -n "$7" && \
func_fatal_help "too many parameters to \`-version-info'"
# convert absolute version numbers to libtool ages
# this retains compatibility with .la files and attempts
# to make the code below a bit more comprehensible
case $vinfo_number in
yes)
number_major="$1"
number_minor="$2"
number_revision="$3"
#
# There are really only two kinds -- those that
# use the current revision as the major version
# and those that subtract age and use age as
# a minor version. But, then there is irix
# which has an extra 1 added just for fun
#
case $version_type in
# correct linux to gnu/linux during the next big refactor
darwin|linux|osf|windows|none)
func_arith $number_major + $number_minor
current=$func_arith_result
age="$number_minor"
revision="$number_revision"
;;
freebsd-aout|freebsd-elf|qnx|sunos)
current="$number_major"
revision="$number_minor"
age="0"
;;
irix|nonstopux)
func_arith $number_major + $number_minor
current=$func_arith_result
age="$number_minor"
revision="$number_minor"
lt_irix_increment=no
;;
*)
func_fatal_configuration "$modename: unknown library version type \`$version_type'"
;;
esac
;;
no)
current="$1"
revision="$2"
age="$3"
;;
esac
# Check that each of the things are valid numbers.
case $current in
0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
*)
func_error "CURRENT \`$current' must be a nonnegative integer"
func_fatal_error "\`$vinfo' is not valid version information"
;;
esac
case $revision in
0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
*)
func_error "REVISION \`$revision' must be a nonnegative integer"
func_fatal_error "\`$vinfo' is not valid version information"
;;
esac
case $age in
0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
*)
func_error "AGE \`$age' must be a nonnegative integer"
func_fatal_error "\`$vinfo' is not valid version information"
;;
esac
if test "$age" -gt "$current"; then
func_error "AGE \`$age' is greater than the current interface number \`$current'"
func_fatal_error "\`$vinfo' is not valid version information"
fi
# Calculate the version variables.
major=
versuffix=
verstring=
case $version_type in
none) ;;
darwin)
# Like Linux, but with the current version available in
# verstring for coding it into the library header
func_arith $current - $age
major=.$func_arith_result
versuffix="$major.$age.$revision"
# Darwin ld doesn't like 0 for these options...
func_arith $current + 1
minor_current=$func_arith_result
xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
;;
freebsd-aout)
major=".$current"
versuffix=".$current.$revision";
;;
freebsd-elf)
major=".$current"
versuffix=".$current"
;;
irix | nonstopux)
if test "X$lt_irix_increment" = "Xno"; then
func_arith $current - $age
else
func_arith $current - $age + 1
fi
major=$func_arith_result
case $version_type in
nonstopux) verstring_prefix=nonstopux ;;
*) verstring_prefix=sgi ;;
esac
verstring="$verstring_prefix$major.$revision"
# Add in all the interfaces that we are compatible with.
loop=$revision
while test "$loop" -ne 0; do
func_arith $revision - $loop
iface=$func_arith_result
func_arith $loop - 1
loop=$func_arith_result
verstring="$verstring_prefix$major.$iface:$verstring"
done
# Before this point, $major must not contain `.'.
major=.$major
versuffix="$major.$revision"
;;
linux) # correct to gnu/linux during the next big refactor
func_arith $current - $age
major=.$func_arith_result
versuffix="$major.$age.$revision"
;;
osf)
func_arith $current - $age
major=.$func_arith_result
versuffix=".$current.$age.$revision"
verstring="$current.$age.$revision"
# Add in all the interfaces that we are compatible with.
loop=$age
while test "$loop" -ne 0; do
func_arith $current - $loop
iface=$func_arith_result
func_arith $loop - 1
loop=$func_arith_result
verstring="$verstring:${iface}.0"
done
# Make executables depend on our current version.
func_append verstring ":${current}.0"
;;
qnx)
major=".$current"
versuffix=".$current"
;;
sunos)
major=".$current"
versuffix=".$current.$revision"
;;
windows)
# Use '-' rather than '.', since we only want one
# extension on DOS 8.3 filesystems.
func_arith $current - $age
major=$func_arith_result
versuffix="-$major"
;;
*)
func_fatal_configuration "unknown library version type \`$version_type'"
;;
esac
# Clear the version info if we defaulted, and they specified a release.
if test -z "$vinfo" && test -n "$release"; then
major=
case $version_type in
darwin)
# we can't check for "0.0" in archive_cmds due to quoting
# problems, so we reset it completely
verstring=
;;
*)
verstring="0.0"
;;
esac
if test "$need_version" = no; then
versuffix=
else
versuffix=".0.0"
fi
fi
# Remove version info from name if versioning should be avoided
if test "$avoid_version" = yes && test "$need_version" = no; then
major=
versuffix=
verstring=""
fi
# Check to see if the archive will have undefined symbols.
if test "$allow_undefined" = yes; then
if test "$allow_undefined_flag" = unsupported; then
func_warning "undefined symbols not allowed in $host shared libraries"
build_libtool_libs=no
build_old_libs=yes
fi
else
# Don't allow undefined symbols.
allow_undefined_flag="$no_undefined_flag"
fi
fi
func_generate_dlsyms "$libname" "$libname" "yes"
func_append libobjs " $symfileobj"
test "X$libobjs" = "X " && libobjs=
if test "$opt_mode" != relink; then
# Remove our outputs, but don't remove object files since they
# may have been created when compiling PIC objects.
removelist=
tempremovelist=`$ECHO "$output_objdir/*"`
for p in $tempremovelist; do
case $p in
*.$objext | *.gcno)
;;
$output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
if test "X$precious_files_regex" != "X"; then
if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
then
continue
fi
fi
func_append removelist " $p"
;;
*) ;;
esac
done
test -n "$removelist" && \
func_show_eval "${RM}r \$removelist"
fi
# Now set the variables for building old libraries.
if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
func_append oldlibs " $output_objdir/$libname.$libext"
# Transform .lo files to .o files.
oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP`
fi
# Eliminate all temporary directories.
#for path in $notinst_path; do
# lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"`
# deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"`
# dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"`
#done
if test -n "$xrpath"; then
# If the user specified any rpath flags, then add them.
temp_xrpath=
for libdir in $xrpath; do
func_replace_sysroot "$libdir"
func_append temp_xrpath " -R$func_replace_sysroot_result"
case "$finalize_rpath " in
*" $libdir "*) ;;
*) func_append finalize_rpath " $libdir" ;;
esac
done
if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
dependency_libs="$temp_xrpath $dependency_libs"
fi
fi
# Make sure dlfiles contains only unique files that won't be dlpreopened
old_dlfiles="$dlfiles"
dlfiles=
for lib in $old_dlfiles; do
case " $dlprefiles $dlfiles " in
*" $lib "*) ;;
*) func_append dlfiles " $lib" ;;
esac
done
# Make sure dlprefiles contains only unique files
old_dlprefiles="$dlprefiles"
dlprefiles=
for lib in $old_dlprefiles; do
case "$dlprefiles " in
*" $lib "*) ;;
*) func_append dlprefiles " $lib" ;;
esac
done
if test "$build_libtool_libs" = yes; then
if test -n "$rpath"; then
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*)
# these systems don't actually have a c library (as such)!
;;
*-*-rhapsody* | *-*-darwin1.[012])
# Rhapsody C library is in the System framework
func_append deplibs " System.ltframework"
;;
*-*-netbsd*)
# Don't link with libc until the a.out ld.so is fixed.
;;
*-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
# Do not include libc due to us having libc/libc_r.
;;
*-*-sco3.2v5* | *-*-sco5v6*)
# Causes problems with __ctype
;;
*-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
# Compiler inserts libc in the correct place for threads to work
;;
*)
# Add libc to deplibs on all other systems if necessary.
if test "$build_libtool_need_lc" = "yes"; then
func_append deplibs " -lc"
fi
;;
esac
fi
# Transform deplibs into only deplibs that can be linked in shared.
name_save=$name
libname_save=$libname
release_save=$release
versuffix_save=$versuffix
major_save=$major
# I'm not sure if I'm treating the release correctly. I think
# release should show up in the -l (ie -lgmp5) so we don't want to
# add it in twice. Is that correct?
release=""
versuffix=""
major=""
newdeplibs=
droppeddeps=no
case $deplibs_check_method in
pass_all)
# Don't check for shared/static. Everything works.
# This might be a little naive. We might want to check
# whether the library exists or not. But this is on
# osf3 & osf4 and I'm not really sure... Just
# implementing what was already the behavior.
newdeplibs=$deplibs
;;
test_compile)
# This code stresses the "libraries are programs" paradigm to its
# limits. Maybe even breaks it. We compile a program, linking it
# against the deplibs as a proxy for the library. Then we can check
# whether they linked in statically or dynamically with ldd.
$opt_dry_run || $RM conftest.c
cat > conftest.c </dev/null`
$nocaseglob
else
potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
fi
for potent_lib in $potential_libs; do
# Follow soft links.
if ls -lLd "$potent_lib" 2>/dev/null |
$GREP " -> " >/dev/null; then
continue
fi
# The statement above tries to avoid entering an
# endless loop below, in case of cyclic links.
# We might still enter an endless loop, since a link
# loop can be closed while we follow links,
# but so what?
potlib="$potent_lib"
while test -h "$potlib" 2>/dev/null; do
potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
case $potliblink in
[\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
*) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";;
esac
done
if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
$SED -e 10q |
$EGREP "$file_magic_regex" > /dev/null; then
func_append newdeplibs " $a_deplib"
a_deplib=""
break 2
fi
done
done
fi
if test -n "$a_deplib" ; then
droppeddeps=yes
echo
$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
echo "*** I have the capability to make that library automatically link in when"
echo "*** you link to this library. But I can only do this if you have a"
echo "*** shared version of the library, which you do not appear to have"
echo "*** because I did check the linker path looking for a file starting"
if test -z "$potlib" ; then
$ECHO "*** with $libname but no candidates were found. (...for file magic test)"
else
$ECHO "*** with $libname and none of the candidates passed a file format test"
$ECHO "*** using a file magic. Last file checked: $potlib"
fi
fi
;;
*)
# Add a -L argument.
func_append newdeplibs " $a_deplib"
;;
esac
done # Gone through all deplibs.
;;
match_pattern*)
set dummy $deplibs_check_method; shift
match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
for a_deplib in $deplibs; do
case $a_deplib in
-l*)
func_stripname -l '' "$a_deplib"
name=$func_stripname_result
if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
case " $predeps $postdeps " in
*" $a_deplib "*)
func_append newdeplibs " $a_deplib"
a_deplib=""
;;
esac
fi
if test -n "$a_deplib" ; then
libname=`eval "\\$ECHO \"$libname_spec\""`
for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
for potent_lib in $potential_libs; do
potlib="$potent_lib" # see symlink-check above in file_magic test
if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \
$EGREP "$match_pattern_regex" > /dev/null; then
func_append newdeplibs " $a_deplib"
a_deplib=""
break 2
fi
done
done
fi
if test -n "$a_deplib" ; then
droppeddeps=yes
echo
$ECHO "*** Warning: linker path does not have real file for library $a_deplib."
echo "*** I have the capability to make that library automatically link in when"
echo "*** you link to this library. But I can only do this if you have a"
echo "*** shared version of the library, which you do not appear to have"
echo "*** because I did check the linker path looking for a file starting"
if test -z "$potlib" ; then
$ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
else
$ECHO "*** with $libname and none of the candidates passed a file format test"
$ECHO "*** using a regex pattern. Last file checked: $potlib"
fi
fi
;;
*)
# Add a -L argument.
func_append newdeplibs " $a_deplib"
;;
esac
done # Gone through all deplibs.
;;
none | unknown | *)
newdeplibs=""
tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'`
if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
for i in $predeps $postdeps ; do
# can't use Xsed below, because $i might contain '/'
tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"`
done
fi
case $tmp_deplibs in
*[!\ \ ]*)
echo
if test "X$deplibs_check_method" = "Xnone"; then
echo "*** Warning: inter-library dependencies are not supported in this platform."
else
echo "*** Warning: inter-library dependencies are not known to be supported."
fi
echo "*** All declared inter-library dependencies are being dropped."
droppeddeps=yes
;;
esac
;;
esac
versuffix=$versuffix_save
major=$major_save
release=$release_save
libname=$libname_save
name=$name_save
case $host in
*-*-rhapsody* | *-*-darwin1.[012])
# On Rhapsody replace the C library with the System framework
newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'`
;;
esac
if test "$droppeddeps" = yes; then
if test "$module" = yes; then
echo
echo "*** Warning: libtool could not satisfy all declared inter-library"
$ECHO "*** dependencies of module $libname. Therefore, libtool will create"
echo "*** a static module, that should work as long as the dlopening"
echo "*** application is linked with the -dlopen flag."
if test -z "$global_symbol_pipe"; then
echo
echo "*** However, this would only work if libtool was able to extract symbol"
echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
echo "*** not find such a program. So, this module is probably useless."
echo "*** \`nm' from GNU binutils and a full rebuild may help."
fi
if test "$build_old_libs" = no; then
oldlibs="$output_objdir/$libname.$libext"
build_libtool_libs=module
build_old_libs=yes
else
build_libtool_libs=no
fi
else
echo "*** The inter-library dependencies that have been dropped here will be"
echo "*** automatically added whenever a program is linked with this library"
echo "*** or is declared to -dlopen it."
if test "$allow_undefined" = no; then
echo
echo "*** Since this library must not contain undefined symbols,"
echo "*** because either the platform does not support them or"
echo "*** it was explicitly requested with -no-undefined,"
echo "*** libtool will only create a static version of it."
if test "$build_old_libs" = no; then
oldlibs="$output_objdir/$libname.$libext"
build_libtool_libs=module
build_old_libs=yes
else
build_libtool_libs=no
fi
fi
fi
fi
# Done checking deplibs!
deplibs=$newdeplibs
fi
# Time to change all our "foo.ltframework" stuff back to "-framework foo"
case $host in
*-*-darwin*)
newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
;;
esac
# move library search paths that coincide with paths to not yet
# installed libraries to the beginning of the library search list
new_libs=
for path in $notinst_path; do
case " $new_libs " in
*" -L$path/$objdir "*) ;;
*)
case " $deplibs " in
*" -L$path/$objdir "*)
func_append new_libs " -L$path/$objdir" ;;
esac
;;
esac
done
for deplib in $deplibs; do
case $deplib in
-L*)
case " $new_libs " in
*" $deplib "*) ;;
*) func_append new_libs " $deplib" ;;
esac
;;
*) func_append new_libs " $deplib" ;;
esac
done
deplibs="$new_libs"
# All the library-specific variables (install_libdir is set above).
library_names=
old_library=
dlname=
# Test again, we may have decided not to build it any more
if test "$build_libtool_libs" = yes; then
# Remove ${wl} instances when linking with ld.
# FIXME: should test the right _cmds variable.
case $archive_cmds in
*\$LD\ *) wl= ;;
esac
if test "$hardcode_into_libs" = yes; then
# Hardcode the library paths
hardcode_libdirs=
dep_rpath=
rpath="$finalize_rpath"
test "$opt_mode" != relink && rpath="$compile_rpath$rpath"
for libdir in $rpath; do
if test -n "$hardcode_libdir_flag_spec"; then
if test -n "$hardcode_libdir_separator"; then
func_replace_sysroot "$libdir"
libdir=$func_replace_sysroot_result
if test -z "$hardcode_libdirs"; then
hardcode_libdirs="$libdir"
else
# Just accumulate the unique libdirs.
case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
*"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
;;
*)
func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
;;
esac
fi
else
eval flag=\"$hardcode_libdir_flag_spec\"
func_append dep_rpath " $flag"
fi
elif test -n "$runpath_var"; then
case "$perm_rpath " in
*" $libdir "*) ;;
*) func_append perm_rpath " $libdir" ;;
esac
fi
done
# Substitute the hardcoded libdirs into the rpath.
if test -n "$hardcode_libdir_separator" &&
test -n "$hardcode_libdirs"; then
libdir="$hardcode_libdirs"
eval "dep_rpath=\"$hardcode_libdir_flag_spec\""
fi
if test -n "$runpath_var" && test -n "$perm_rpath"; then
# We should set the runpath_var.
rpath=
for dir in $perm_rpath; do
func_append rpath "$dir:"
done
eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
fi
test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
fi
shlibpath="$finalize_shlibpath"
test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
if test -n "$shlibpath"; then
eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
fi
# Get the real and link names of the library.
eval shared_ext=\"$shrext_cmds\"
eval library_names=\"$library_names_spec\"
set dummy $library_names
shift
realname="$1"
shift
if test -n "$soname_spec"; then
eval soname=\"$soname_spec\"
else
soname="$realname"
fi
if test -z "$dlname"; then
dlname=$soname
fi
lib="$output_objdir/$realname"
linknames=
for link
do
func_append linknames " $link"
done
# Use standard objects if they are pic
test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP`
test "X$libobjs" = "X " && libobjs=
delfiles=
if test -n "$export_symbols" && test -n "$include_expsyms"; then
$opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
export_symbols="$output_objdir/$libname.uexp"
func_append delfiles " $export_symbols"
fi
orig_export_symbols=
case $host_os in
cygwin* | mingw* | cegcc*)
if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
# exporting using user supplied symfile
if test "x`$SED 1q $export_symbols`" != xEXPORTS; then
# and it's NOT already a .def file. Must figure out
# which of the given symbols are data symbols and tag
# them as such. So, trigger use of export_symbols_cmds.
# export_symbols gets reassigned inside the "prepare
# the list of exported symbols" if statement, so the
# include_expsyms logic still works.
orig_export_symbols="$export_symbols"
export_symbols=
always_export_symbols=yes
fi
fi
;;
esac
# Prepare the list of exported symbols
if test -z "$export_symbols"; then
if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
func_verbose "generating symbol list for \`$libname.la'"
export_symbols="$output_objdir/$libname.exp"
$opt_dry_run || $RM $export_symbols
cmds=$export_symbols_cmds
save_ifs="$IFS"; IFS='~'
for cmd1 in $cmds; do
IFS="$save_ifs"
# Take the normal branch if the nm_file_list_spec branch
# doesn't work or if tool conversion is not needed.
case $nm_file_list_spec~$to_tool_file_cmd in
*~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*)
try_normal_branch=yes
eval cmd=\"$cmd1\"
func_len " $cmd"
len=$func_len_result
;;
*)
try_normal_branch=no
;;
esac
if test "$try_normal_branch" = yes \
&& { test "$len" -lt "$max_cmd_len" \
|| test "$max_cmd_len" -le -1; }
then
func_show_eval "$cmd" 'exit $?'
skipped_export=false
elif test -n "$nm_file_list_spec"; then
func_basename "$output"
output_la=$func_basename_result
save_libobjs=$libobjs
save_output=$output
output=${output_objdir}/${output_la}.nm
func_to_tool_file "$output"
libobjs=$nm_file_list_spec$func_to_tool_file_result
func_append delfiles " $output"
func_verbose "creating $NM input file list: $output"
for obj in $save_libobjs; do
func_to_tool_file "$obj"
$ECHO "$func_to_tool_file_result"
done > "$output"
eval cmd=\"$cmd1\"
func_show_eval "$cmd" 'exit $?'
output=$save_output
libobjs=$save_libobjs
skipped_export=false
else
# The command line is too long to execute in one step.
func_verbose "using reloadable object file for export list..."
skipped_export=:
# Break out early, otherwise skipped_export may be
# set to false by a later but shorter cmd.
break
fi
done
IFS="$save_ifs"
if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then
func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
fi
fi
fi
if test -n "$export_symbols" && test -n "$include_expsyms"; then
tmp_export_symbols="$export_symbols"
test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
$opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
fi
if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then
# The given exports_symbols file has to be filtered, so filter it.
func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
# FIXME: $output_objdir/$libname.filter potentially contains lots of
# 's' commands which not all seds can handle. GNU sed should be fine
# though. Also, the filter scales superlinearly with the number of
# global variables. join(1) would be nice here, but unfortunately
# isn't a blessed tool.
$opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
func_append delfiles " $export_symbols $output_objdir/$libname.filter"
export_symbols=$output_objdir/$libname.def
$opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
fi
tmp_deplibs=
for test_deplib in $deplibs; do
case " $convenience " in
*" $test_deplib "*) ;;
*)
func_append tmp_deplibs " $test_deplib"
;;
esac
done
deplibs="$tmp_deplibs"
if test -n "$convenience"; then
if test -n "$whole_archive_flag_spec" &&
test "$compiler_needs_object" = yes &&
test -z "$libobjs"; then
# extract the archives, so we have objects to list.
# TODO: could optimize this to just extract one archive.
whole_archive_flag_spec=
fi
if test -n "$whole_archive_flag_spec"; then
save_libobjs=$libobjs
eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
test "X$libobjs" = "X " && libobjs=
else
gentop="$output_objdir/${outputname}x"
func_append generated " $gentop"
func_extract_archives $gentop $convenience
func_append libobjs " $func_extract_archives_result"
test "X$libobjs" = "X " && libobjs=
fi
fi
if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
eval flag=\"$thread_safe_flag_spec\"
func_append linker_flags " $flag"
fi
# Make a backup of the uninstalled library when relinking
if test "$opt_mode" = relink; then
$opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
fi
# Do each of the archive commands.
if test "$module" = yes && test -n "$module_cmds" ; then
if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
eval test_cmds=\"$module_expsym_cmds\"
cmds=$module_expsym_cmds
else
eval test_cmds=\"$module_cmds\"
cmds=$module_cmds
fi
else
if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
eval test_cmds=\"$archive_expsym_cmds\"
cmds=$archive_expsym_cmds
else
eval test_cmds=\"$archive_cmds\"
cmds=$archive_cmds
fi
fi
if test "X$skipped_export" != "X:" &&
func_len " $test_cmds" &&
len=$func_len_result &&
test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
:
else
# The command line is too long to link in one step, link piecewise
# or, if using GNU ld and skipped_export is not :, use a linker
# script.
# Save the value of $output and $libobjs because we want to
# use them later. If we have whole_archive_flag_spec, we
# want to use save_libobjs as it was before
# whole_archive_flag_spec was expanded, because we can't
# assume the linker understands whole_archive_flag_spec.
# This may have to be revisited, in case too many
# convenience libraries get linked in and end up exceeding
# the spec.
if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
save_libobjs=$libobjs
fi
save_output=$output
func_basename "$output"
output_la=$func_basename_result
# Clear the reloadable object creation command queue and
# initialize k to one.
test_cmds=
concat_cmds=
objlist=
last_robj=
k=1
if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then
output=${output_objdir}/${output_la}.lnkscript
func_verbose "creating GNU ld script: $output"
echo 'INPUT (' > $output
for obj in $save_libobjs
do
func_to_tool_file "$obj"
$ECHO "$func_to_tool_file_result" >> $output
done
echo ')' >> $output
func_append delfiles " $output"
func_to_tool_file "$output"
output=$func_to_tool_file_result
elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then
output=${output_objdir}/${output_la}.lnk
func_verbose "creating linker input file list: $output"
: > $output
set x $save_libobjs
shift
firstobj=
if test "$compiler_needs_object" = yes; then
firstobj="$1 "
shift
fi
for obj
do
func_to_tool_file "$obj"
$ECHO "$func_to_tool_file_result" >> $output
done
func_append delfiles " $output"
func_to_tool_file "$output"
output=$firstobj\"$file_list_spec$func_to_tool_file_result\"
else
if test -n "$save_libobjs"; then
func_verbose "creating reloadable object files..."
output=$output_objdir/$output_la-${k}.$objext
eval test_cmds=\"$reload_cmds\"
func_len " $test_cmds"
len0=$func_len_result
len=$len0
# Loop over the list of objects to be linked.
for obj in $save_libobjs
do
func_len " $obj"
func_arith $len + $func_len_result
len=$func_arith_result
if test "X$objlist" = X ||
test "$len" -lt "$max_cmd_len"; then
func_append objlist " $obj"
else
# The command $test_cmds is almost too long, add a
# command to the queue.
if test "$k" -eq 1 ; then
# The first file doesn't have a previous command to add.
reload_objs=$objlist
eval concat_cmds=\"$reload_cmds\"
else
# All subsequent reloadable object files will link in
# the last one created.
reload_objs="$objlist $last_robj"
eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\"
fi
last_robj=$output_objdir/$output_la-${k}.$objext
func_arith $k + 1
k=$func_arith_result
output=$output_objdir/$output_la-${k}.$objext
objlist=" $obj"
func_len " $last_robj"
func_arith $len0 + $func_len_result
len=$func_arith_result
fi
done
# Handle the remaining objects by creating one last
# reloadable object file. All subsequent reloadable object
# files will link in the last one created.
test -z "$concat_cmds" || concat_cmds=$concat_cmds~
reload_objs="$objlist $last_robj"
eval concat_cmds=\"\${concat_cmds}$reload_cmds\"
if test -n "$last_robj"; then
eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\"
fi
func_append delfiles " $output"
else
output=
fi
if ${skipped_export-false}; then
func_verbose "generating symbol list for \`$libname.la'"
export_symbols="$output_objdir/$libname.exp"
$opt_dry_run || $RM $export_symbols
libobjs=$output
# Append the command to create the export file.
test -z "$concat_cmds" || concat_cmds=$concat_cmds~
eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
if test -n "$last_robj"; then
eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
fi
fi
test -n "$save_libobjs" &&
func_verbose "creating a temporary reloadable object file: $output"
# Loop through the commands generated above and execute them.
save_ifs="$IFS"; IFS='~'
for cmd in $concat_cmds; do
IFS="$save_ifs"
$opt_silent || {
func_quote_for_expand "$cmd"
eval "func_echo $func_quote_for_expand_result"
}
$opt_dry_run || eval "$cmd" || {
lt_exit=$?
# Restore the uninstalled library and exit
if test "$opt_mode" = relink; then
( cd "$output_objdir" && \
$RM "${realname}T" && \
$MV "${realname}U" "$realname" )
fi
exit $lt_exit
}
done
IFS="$save_ifs"
if test -n "$export_symbols_regex" && ${skipped_export-false}; then
func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
fi
fi
if ${skipped_export-false}; then
if test -n "$export_symbols" && test -n "$include_expsyms"; then
tmp_export_symbols="$export_symbols"
test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
$opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
fi
if test -n "$orig_export_symbols"; then
# The given exports_symbols file has to be filtered, so filter it.
func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
# FIXME: $output_objdir/$libname.filter potentially contains lots of
# 's' commands which not all seds can handle. GNU sed should be fine
# though. Also, the filter scales superlinearly with the number of
# global variables. join(1) would be nice here, but unfortunately
# isn't a blessed tool.
$opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
func_append delfiles " $export_symbols $output_objdir/$libname.filter"
export_symbols=$output_objdir/$libname.def
$opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
fi
fi
libobjs=$output
# Restore the value of output.
output=$save_output
if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
test "X$libobjs" = "X " && libobjs=
fi
# Expand the library linking commands again to reset the
# value of $libobjs for piecewise linking.
# Do each of the archive commands.
if test "$module" = yes && test -n "$module_cmds" ; then
if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
cmds=$module_expsym_cmds
else
cmds=$module_cmds
fi
else
if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
cmds=$archive_expsym_cmds
else
cmds=$archive_cmds
fi
fi
fi
if test -n "$delfiles"; then
# Append the command to remove temporary files to $cmds.
eval cmds=\"\$cmds~\$RM $delfiles\"
fi
# Add any objects from preloaded convenience libraries
if test -n "$dlprefiles"; then
gentop="$output_objdir/${outputname}x"
func_append generated " $gentop"
func_extract_archives $gentop $dlprefiles
func_append libobjs " $func_extract_archives_result"
test "X$libobjs" = "X " && libobjs=
fi
save_ifs="$IFS"; IFS='~'
for cmd in $cmds; do
IFS="$save_ifs"
eval cmd=\"$cmd\"
$opt_silent || {
func_quote_for_expand "$cmd"
eval "func_echo $func_quote_for_expand_result"
}
$opt_dry_run || eval "$cmd" || {
lt_exit=$?
# Restore the uninstalled library and exit
if test "$opt_mode" = relink; then
( cd "$output_objdir" && \
$RM "${realname}T" && \
$MV "${realname}U" "$realname" )
fi
exit $lt_exit
}
done
IFS="$save_ifs"
# Restore the uninstalled library and exit
if test "$opt_mode" = relink; then
$opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
if test -n "$convenience"; then
if test -z "$whole_archive_flag_spec"; then
func_show_eval '${RM}r "$gentop"'
fi
fi
exit $EXIT_SUCCESS
fi
# Create links to the real library.
for linkname in $linknames; do
if test "$realname" != "$linkname"; then
func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
fi
done
# If -module or -export-dynamic was specified, set the dlname.
if test "$module" = yes || test "$export_dynamic" = yes; then
# On all known operating systems, these are identical.
dlname="$soname"
fi
fi
;;
obj)
if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
func_warning "\`-dlopen' is ignored for objects"
fi
case " $deplibs" in
*\ -l* | *\ -L*)
func_warning "\`-l' and \`-L' are ignored for objects" ;;
esac
test -n "$rpath" && \
func_warning "\`-rpath' is ignored for objects"
test -n "$xrpath" && \
func_warning "\`-R' is ignored for objects"
test -n "$vinfo" && \
func_warning "\`-version-info' is ignored for objects"
test -n "$release" && \
func_warning "\`-release' is ignored for objects"
case $output in
*.lo)
test -n "$objs$old_deplibs" && \
func_fatal_error "cannot build library object \`$output' from non-libtool objects"
libobj=$output
func_lo2o "$libobj"
obj=$func_lo2o_result
;;
*)
libobj=
obj="$output"
;;
esac
# Delete the old objects.
$opt_dry_run || $RM $obj $libobj
# Objects from convenience libraries. This assumes
# single-version convenience libraries. Whenever we create
# different ones for PIC/non-PIC, this we'll have to duplicate
# the extraction.
reload_conv_objs=
gentop=
# reload_cmds runs $LD directly, so let us get rid of
# -Wl from whole_archive_flag_spec and hope we can get by with
# turning comma into space..
wl=
if test -n "$convenience"; then
if test -n "$whole_archive_flag_spec"; then
eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'`
else
gentop="$output_objdir/${obj}x"
func_append generated " $gentop"
func_extract_archives $gentop $convenience
reload_conv_objs="$reload_objs $func_extract_archives_result"
fi
fi
# If we're not building shared, we need to use non_pic_objs
test "$build_libtool_libs" != yes && libobjs="$non_pic_objects"
# Create the old-style object.
reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
output="$obj"
func_execute_cmds "$reload_cmds" 'exit $?'
# Exit if we aren't doing a library object file.
if test -z "$libobj"; then
if test -n "$gentop"; then
func_show_eval '${RM}r "$gentop"'
fi
exit $EXIT_SUCCESS
fi
if test "$build_libtool_libs" != yes; then
if test -n "$gentop"; then
func_show_eval '${RM}r "$gentop"'
fi
# Create an invalid libtool object if no PIC, so that we don't
# accidentally link it into a program.
# $show "echo timestamp > $libobj"
# $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
exit $EXIT_SUCCESS
fi
if test -n "$pic_flag" || test "$pic_mode" != default; then
# Only do commands if we really have different PIC objects.
reload_objs="$libobjs $reload_conv_objs"
output="$libobj"
func_execute_cmds "$reload_cmds" 'exit $?'
fi
if test -n "$gentop"; then
func_show_eval '${RM}r "$gentop"'
fi
exit $EXIT_SUCCESS
;;
prog)
case $host in
*cygwin*) func_stripname '' '.exe' "$output"
output=$func_stripname_result.exe;;
esac
test -n "$vinfo" && \
func_warning "\`-version-info' is ignored for programs"
test -n "$release" && \
func_warning "\`-release' is ignored for programs"
test "$preload" = yes \
&& test "$dlopen_support" = unknown \
&& test "$dlopen_self" = unknown \
&& test "$dlopen_self_static" = unknown && \
func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support."
case $host in
*-*-rhapsody* | *-*-darwin1.[012])
# On Rhapsody replace the C library is the System framework
compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'`
finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'`
;;
esac
case $host in
*-*-darwin*)
# Don't allow lazy linking, it breaks C++ global constructors
# But is supposedly fixed on 10.4 or later (yay!).
if test "$tagname" = CXX ; then
case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
10.[0123])
func_append compile_command " ${wl}-bind_at_load"
func_append finalize_command " ${wl}-bind_at_load"
;;
esac
fi
# Time to change all our "foo.ltframework" stuff back to "-framework foo"
compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
;;
esac
# move library search paths that coincide with paths to not yet
# installed libraries to the beginning of the library search list
new_libs=
for path in $notinst_path; do
case " $new_libs " in
*" -L$path/$objdir "*) ;;
*)
case " $compile_deplibs " in
*" -L$path/$objdir "*)
func_append new_libs " -L$path/$objdir" ;;
esac
;;
esac
done
for deplib in $compile_deplibs; do
case $deplib in
-L*)
case " $new_libs " in
*" $deplib "*) ;;
*) func_append new_libs " $deplib" ;;
esac
;;
*) func_append new_libs " $deplib" ;;
esac
done
compile_deplibs="$new_libs"
func_append compile_command " $compile_deplibs"
func_append finalize_command " $finalize_deplibs"
if test -n "$rpath$xrpath"; then
# If the user specified any rpath flags, then add them.
for libdir in $rpath $xrpath; do
# This is the magic to use -rpath.
case "$finalize_rpath " in
*" $libdir "*) ;;
*) func_append finalize_rpath " $libdir" ;;
esac
done
fi
# Now hardcode the library paths
rpath=
hardcode_libdirs=
for libdir in $compile_rpath $finalize_rpath; do
if test -n "$hardcode_libdir_flag_spec"; then
if test -n "$hardcode_libdir_separator"; then
if test -z "$hardcode_libdirs"; then
hardcode_libdirs="$libdir"
else
# Just accumulate the unique libdirs.
case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
*"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
;;
*)
func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
;;
esac
fi
else
eval flag=\"$hardcode_libdir_flag_spec\"
func_append rpath " $flag"
fi
elif test -n "$runpath_var"; then
case "$perm_rpath " in
*" $libdir "*) ;;
*) func_append perm_rpath " $libdir" ;;
esac
fi
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'`
case :$dllsearchpath: in
*":$libdir:"*) ;;
::) dllsearchpath=$libdir;;
*) func_append dllsearchpath ":$libdir";;
esac
case :$dllsearchpath: in
*":$testbindir:"*) ;;
::) dllsearchpath=$testbindir;;
*) func_append dllsearchpath ":$testbindir";;
esac
;;
esac
done
# Substitute the hardcoded libdirs into the rpath.
if test -n "$hardcode_libdir_separator" &&
test -n "$hardcode_libdirs"; then
libdir="$hardcode_libdirs"
eval rpath=\" $hardcode_libdir_flag_spec\"
fi
compile_rpath="$rpath"
rpath=
hardcode_libdirs=
for libdir in $finalize_rpath; do
if test -n "$hardcode_libdir_flag_spec"; then
if test -n "$hardcode_libdir_separator"; then
if test -z "$hardcode_libdirs"; then
hardcode_libdirs="$libdir"
else
# Just accumulate the unique libdirs.
case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
*"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
;;
*)
func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
;;
esac
fi
else
eval flag=\"$hardcode_libdir_flag_spec\"
func_append rpath " $flag"
fi
elif test -n "$runpath_var"; then
case "$finalize_perm_rpath " in
*" $libdir "*) ;;
*) func_append finalize_perm_rpath " $libdir" ;;
esac
fi
done
# Substitute the hardcoded libdirs into the rpath.
if test -n "$hardcode_libdir_separator" &&
test -n "$hardcode_libdirs"; then
libdir="$hardcode_libdirs"
eval rpath=\" $hardcode_libdir_flag_spec\"
fi
finalize_rpath="$rpath"
if test -n "$libobjs" && test "$build_old_libs" = yes; then
# Transform all the library objects into standard objects.
compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
fi
func_generate_dlsyms "$outputname" "@PROGRAM@" "no"
# template prelinking step
if test -n "$prelink_cmds"; then
func_execute_cmds "$prelink_cmds" 'exit $?'
fi
wrappers_required=yes
case $host in
*cegcc* | *mingw32ce*)
# Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.
wrappers_required=no
;;
*cygwin* | *mingw* )
if test "$build_libtool_libs" != yes; then
wrappers_required=no
fi
;;
*)
if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
wrappers_required=no
fi
;;
esac
if test "$wrappers_required" = no; then
# Replace the output file specification.
compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
link_command="$compile_command$compile_rpath"
# We have no uninstalled library dependencies, so finalize right now.
exit_status=0
func_show_eval "$link_command" 'exit_status=$?'
if test -n "$postlink_cmds"; then
func_to_tool_file "$output"
postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
func_execute_cmds "$postlink_cmds" 'exit $?'
fi
# Delete the generated files.
if test -f "$output_objdir/${outputname}S.${objext}"; then
func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"'
fi
exit $exit_status
fi
if test -n "$compile_shlibpath$finalize_shlibpath"; then
compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
fi
if test -n "$finalize_shlibpath"; then
finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
fi
compile_var=
finalize_var=
if test -n "$runpath_var"; then
if test -n "$perm_rpath"; then
# We should set the runpath_var.
rpath=
for dir in $perm_rpath; do
func_append rpath "$dir:"
done
compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
fi
if test -n "$finalize_perm_rpath"; then
# We should set the runpath_var.
rpath=
for dir in $finalize_perm_rpath; do
func_append rpath "$dir:"
done
finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
fi
fi
if test "$no_install" = yes; then
# We don't need to create a wrapper script.
link_command="$compile_var$compile_command$compile_rpath"
# Replace the output file specification.
link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
# Delete the old output file.
$opt_dry_run || $RM $output
# Link the executable and exit
func_show_eval "$link_command" 'exit $?'
if test -n "$postlink_cmds"; then
func_to_tool_file "$output"
postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
func_execute_cmds "$postlink_cmds" 'exit $?'
fi
exit $EXIT_SUCCESS
fi
if test "$hardcode_action" = relink; then
# Fast installation is not supported
link_command="$compile_var$compile_command$compile_rpath"
relink_command="$finalize_var$finalize_command$finalize_rpath"
func_warning "this platform does not like uninstalled shared libraries"
func_warning "\`$output' will be relinked during installation"
else
if test "$fast_install" != no; then
link_command="$finalize_var$compile_command$finalize_rpath"
if test "$fast_install" = yes; then
relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'`
else
# fast_install is set to needless
relink_command=
fi
else
link_command="$compile_var$compile_command$compile_rpath"
relink_command="$finalize_var$finalize_command$finalize_rpath"
fi
fi
# Replace the output file specification.
link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
# Delete the old output files.
$opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
func_show_eval "$link_command" 'exit $?'
if test -n "$postlink_cmds"; then
func_to_tool_file "$output_objdir/$outputname"
postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
func_execute_cmds "$postlink_cmds" 'exit $?'
fi
# Now create the wrapper script.
func_verbose "creating $output"
# Quote the relink command for shipping.
if test -n "$relink_command"; then
# Preserve any variables that may affect compiler behavior
for var in $variables_saved_for_relink; do
if eval test -z \"\${$var+set}\"; then
relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
elif eval var_value=\$$var; test -z "$var_value"; then
relink_command="$var=; export $var; $relink_command"
else
func_quote_for_eval "$var_value"
relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
fi
done
relink_command="(cd `pwd`; $relink_command)"
relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
fi
# Only actually do things if not in dry run mode.
$opt_dry_run || {
# win32 will think the script is a binary if it has
# a .exe suffix, so we strip it off here.
case $output in
*.exe) func_stripname '' '.exe' "$output"
output=$func_stripname_result ;;
esac
# test for cygwin because mv fails w/o .exe extensions
case $host in
*cygwin*)
exeext=.exe
func_stripname '' '.exe' "$outputname"
outputname=$func_stripname_result ;;
*) exeext= ;;
esac
case $host in
*cygwin* | *mingw* )
func_dirname_and_basename "$output" "" "."
output_name=$func_basename_result
output_path=$func_dirname_result
cwrappersource="$output_path/$objdir/lt-$output_name.c"
cwrapper="$output_path/$output_name.exe"
$RM $cwrappersource $cwrapper
trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
func_emit_cwrapperexe_src > $cwrappersource
# The wrapper executable is built using the $host compiler,
# because it contains $host paths and files. If cross-
# compiling, it, like the target executable, must be
# executed on the $host or under an emulation environment.
$opt_dry_run || {
$LTCC $LTCFLAGS -o $cwrapper $cwrappersource
$STRIP $cwrapper
}
# Now, create the wrapper script for func_source use:
func_ltwrapper_scriptname $cwrapper
$RM $func_ltwrapper_scriptname_result
trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
$opt_dry_run || {
# note: this script will not be executed, so do not chmod.
if test "x$build" = "x$host" ; then
$cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
else
func_emit_wrapper no > $func_ltwrapper_scriptname_result
fi
}
;;
* )
$RM $output
trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
func_emit_wrapper no > $output
chmod +x $output
;;
esac
}
exit $EXIT_SUCCESS
;;
esac
# See if we need to build an old-fashioned archive.
for oldlib in $oldlibs; do
if test "$build_libtool_libs" = convenience; then
oldobjs="$libobjs_save $symfileobj"
addlibs="$convenience"
build_libtool_libs=no
else
if test "$build_libtool_libs" = module; then
oldobjs="$libobjs_save"
build_libtool_libs=no
else
oldobjs="$old_deplibs $non_pic_objects"
if test "$preload" = yes && test -f "$symfileobj"; then
func_append oldobjs " $symfileobj"
fi
fi
addlibs="$old_convenience"
fi
if test -n "$addlibs"; then
gentop="$output_objdir/${outputname}x"
func_append generated " $gentop"
func_extract_archives $gentop $addlibs
func_append oldobjs " $func_extract_archives_result"
fi
# Do each command in the archive commands.
if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
cmds=$old_archive_from_new_cmds
else
# Add any objects from preloaded convenience libraries
if test -n "$dlprefiles"; then
gentop="$output_objdir/${outputname}x"
func_append generated " $gentop"
func_extract_archives $gentop $dlprefiles
func_append oldobjs " $func_extract_archives_result"
fi
# POSIX demands no paths to be encoded in archives. We have
# to avoid creating archives with duplicate basenames if we
# might have to extract them afterwards, e.g., when creating a
# static archive out of a convenience library, or when linking
# the entirety of a libtool archive into another (currently
# not supported by libtool).
if (for obj in $oldobjs
do
func_basename "$obj"
$ECHO "$func_basename_result"
done | sort | sort -uc >/dev/null 2>&1); then
:
else
echo "copying selected object files to avoid basename conflicts..."
gentop="$output_objdir/${outputname}x"
func_append generated " $gentop"
func_mkdir_p "$gentop"
save_oldobjs=$oldobjs
oldobjs=
counter=1
for obj in $save_oldobjs
do
func_basename "$obj"
objbase="$func_basename_result"
case " $oldobjs " in
" ") oldobjs=$obj ;;
*[\ /]"$objbase "*)
while :; do
# Make sure we don't pick an alternate name that also
# overlaps.
newobj=lt$counter-$objbase
func_arith $counter + 1
counter=$func_arith_result
case " $oldobjs " in
*[\ /]"$newobj "*) ;;
*) if test ! -f "$gentop/$newobj"; then break; fi ;;
esac
done
func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
func_append oldobjs " $gentop/$newobj"
;;
*) func_append oldobjs " $obj" ;;
esac
done
fi
func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
tool_oldlib=$func_to_tool_file_result
eval cmds=\"$old_archive_cmds\"
func_len " $cmds"
len=$func_len_result
if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
cmds=$old_archive_cmds
elif test -n "$archiver_list_spec"; then
func_verbose "using command file archive linking..."
for obj in $oldobjs
do
func_to_tool_file "$obj"
$ECHO "$func_to_tool_file_result"
done > $output_objdir/$libname.libcmd
func_to_tool_file "$output_objdir/$libname.libcmd"
oldobjs=" $archiver_list_spec$func_to_tool_file_result"
cmds=$old_archive_cmds
else
# the command line is too long to link in one step, link in parts
func_verbose "using piecewise archive linking..."
save_RANLIB=$RANLIB
RANLIB=:
objlist=
concat_cmds=
save_oldobjs=$oldobjs
oldobjs=
# Is there a better way of finding the last object in the list?
for obj in $save_oldobjs
do
last_oldobj=$obj
done
eval test_cmds=\"$old_archive_cmds\"
func_len " $test_cmds"
len0=$func_len_result
len=$len0
for obj in $save_oldobjs
do
func_len " $obj"
func_arith $len + $func_len_result
len=$func_arith_result
func_append objlist " $obj"
if test "$len" -lt "$max_cmd_len"; then
:
else
# the above command should be used before it gets too long
oldobjs=$objlist
if test "$obj" = "$last_oldobj" ; then
RANLIB=$save_RANLIB
fi
test -z "$concat_cmds" || concat_cmds=$concat_cmds~
eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
objlist=
len=$len0
fi
done
RANLIB=$save_RANLIB
oldobjs=$objlist
if test "X$oldobjs" = "X" ; then
eval cmds=\"\$concat_cmds\"
else
eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
fi
fi
fi
func_execute_cmds "$cmds" 'exit $?'
done
test -n "$generated" && \
func_show_eval "${RM}r$generated"
# Now create the libtool archive.
case $output in
*.la)
old_library=
test "$build_old_libs" = yes && old_library="$libname.$libext"
func_verbose "creating $output"
# Preserve any variables that may affect compiler behavior
for var in $variables_saved_for_relink; do
if eval test -z \"\${$var+set}\"; then
relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
elif eval var_value=\$$var; test -z "$var_value"; then
relink_command="$var=; export $var; $relink_command"
else
func_quote_for_eval "$var_value"
relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
fi
done
# Quote the link command for shipping.
relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
if test "$hardcode_automatic" = yes ; then
relink_command=
fi
# Only create the output if not a dry run.
$opt_dry_run || {
for installed in no yes; do
if test "$installed" = yes; then
if test -z "$install_libdir"; then
break
fi
output="$output_objdir/$outputname"i
# Replace all uninstalled libtool libraries with the installed ones
newdependency_libs=
for deplib in $dependency_libs; do
case $deplib in
*.la)
func_basename "$deplib"
name="$func_basename_result"
func_resolve_sysroot "$deplib"
eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result`
test -z "$libdir" && \
func_fatal_error "\`$deplib' is not a valid libtool archive"
func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name"
;;
-L*)
func_stripname -L '' "$deplib"
func_replace_sysroot "$func_stripname_result"
func_append newdependency_libs " -L$func_replace_sysroot_result"
;;
-R*)
func_stripname -R '' "$deplib"
func_replace_sysroot "$func_stripname_result"
func_append newdependency_libs " -R$func_replace_sysroot_result"
;;
*) func_append newdependency_libs " $deplib" ;;
esac
done
dependency_libs="$newdependency_libs"
newdlfiles=
for lib in $dlfiles; do
case $lib in
*.la)
func_basename "$lib"
name="$func_basename_result"
eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
test -z "$libdir" && \
func_fatal_error "\`$lib' is not a valid libtool archive"
func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name"
;;
*) func_append newdlfiles " $lib" ;;
esac
done
dlfiles="$newdlfiles"
newdlprefiles=
for lib in $dlprefiles; do
case $lib in
*.la)
# Only pass preopened files to the pseudo-archive (for
# eventual linking with the app. that links it) if we
# didn't already link the preopened objects directly into
# the library:
func_basename "$lib"
name="$func_basename_result"
eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
test -z "$libdir" && \
func_fatal_error "\`$lib' is not a valid libtool archive"
func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name"
;;
esac
done
dlprefiles="$newdlprefiles"
else
newdlfiles=
for lib in $dlfiles; do
case $lib in
[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
*) abs=`pwd`"/$lib" ;;
esac
func_append newdlfiles " $abs"
done
dlfiles="$newdlfiles"
newdlprefiles=
for lib in $dlprefiles; do
case $lib in
[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
*) abs=`pwd`"/$lib" ;;
esac
func_append newdlprefiles " $abs"
done
dlprefiles="$newdlprefiles"
fi
$RM $output
# place dlname in correct position for cygwin
# In fact, it would be nice if we could use this code for all target
# systems that can't hard-code library paths into their executables
# and that have no shared library path variable independent of PATH,
# but it turns out we can't easily determine that from inspecting
# libtool variables, so we have to hard-code the OSs to which it
# applies here; at the moment, that means platforms that use the PE
# object format with DLL files. See the long comment at the top of
# tests/bindir.at for full details.
tdlname=$dlname
case $host,$output,$installed,$module,$dlname in
*cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll)
# If a -bindir argument was supplied, place the dll there.
if test "x$bindir" != x ;
then
func_relative_path "$install_libdir" "$bindir"
tdlname=$func_relative_path_result$dlname
else
# Otherwise fall back on heuristic.
tdlname=../bin/$dlname
fi
;;
esac
$ECHO > $output "\
# $outputname - a libtool library file
# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname='$tdlname'
# Names of this library.
library_names='$library_names'
# The name of the static archive.
old_library='$old_library'
# Linker flags that can not go in dependency_libs.
inherited_linker_flags='$new_inherited_linker_flags'
# Libraries that this one depends upon.
dependency_libs='$dependency_libs'
# Names of additional weak libraries provided by this library
weak_library_names='$weak_libs'
# Version information for $libname.
current=$current
age=$age
revision=$revision
# Is this an already installed library?
installed=$installed
# Should we warn about portability when linking against -modules?
shouldnotlink=$module
# Files to dlopen/dlpreopen
dlopen='$dlfiles'
dlpreopen='$dlprefiles'
# Directory that this library needs to be installed in:
libdir='$install_libdir'"
if test "$installed" = no && test "$need_relink" = yes; then
$ECHO >> $output "\
relink_command=\"$relink_command\""
fi
done
}
# Do a symbolic link so that the libtool archive can be found in
# LD_LIBRARY_PATH before the program is installed.
func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
;;
esac
exit $EXIT_SUCCESS
}
{ test "$opt_mode" = link || test "$opt_mode" = relink; } &&
func_mode_link ${1+"$@"}
# func_mode_uninstall arg...
func_mode_uninstall ()
{
$opt_debug
RM="$nonopt"
files=
rmforce=
exit_status=0
# This variable tells wrapper scripts just to set variables rather
# than running their programs.
libtool_install_magic="$magic"
for arg
do
case $arg in
-f) func_append RM " $arg"; rmforce=yes ;;
-*) func_append RM " $arg" ;;
*) func_append files " $arg" ;;
esac
done
test -z "$RM" && \
func_fatal_help "you must specify an RM program"
rmdirs=
for file in $files; do
func_dirname "$file" "" "."
dir="$func_dirname_result"
if test "X$dir" = X.; then
odir="$objdir"
else
odir="$dir/$objdir"
fi
func_basename "$file"
name="$func_basename_result"
test "$opt_mode" = uninstall && odir="$dir"
# Remember odir for removal later, being careful to avoid duplicates
if test "$opt_mode" = clean; then
case " $rmdirs " in
*" $odir "*) ;;
*) func_append rmdirs " $odir" ;;
esac
fi
# Don't error if the file doesn't exist and rm -f was used.
if { test -L "$file"; } >/dev/null 2>&1 ||
{ test -h "$file"; } >/dev/null 2>&1 ||
test -f "$file"; then
:
elif test -d "$file"; then
exit_status=1
continue
elif test "$rmforce" = yes; then
continue
fi
rmfiles="$file"
case $name in
*.la)
# Possibly a libtool archive, so verify it.
if func_lalib_p "$file"; then
func_source $dir/$name
# Delete the libtool libraries and symlinks.
for n in $library_names; do
func_append rmfiles " $odir/$n"
done
test -n "$old_library" && func_append rmfiles " $odir/$old_library"
case "$opt_mode" in
clean)
case " $library_names " in
*" $dlname "*) ;;
*) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;;
esac
test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i"
;;
uninstall)
if test -n "$library_names"; then
# Do each command in the postuninstall commands.
func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
fi
if test -n "$old_library"; then
# Do each command in the old_postuninstall commands.
func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
fi
# FIXME: should reinstall the best remaining shared library.
;;
esac
fi
;;
*.lo)
# Possibly a libtool object, so verify it.
if func_lalib_p "$file"; then
# Read the .lo file
func_source $dir/$name
# Add PIC object to the list of files to remove.
if test -n "$pic_object" &&
test "$pic_object" != none; then
func_append rmfiles " $dir/$pic_object"
fi
# Add non-PIC object to the list of files to remove.
if test -n "$non_pic_object" &&
test "$non_pic_object" != none; then
func_append rmfiles " $dir/$non_pic_object"
fi
fi
;;
*)
if test "$opt_mode" = clean ; then
noexename=$name
case $file in
*.exe)
func_stripname '' '.exe' "$file"
file=$func_stripname_result
func_stripname '' '.exe' "$name"
noexename=$func_stripname_result
# $file with .exe has already been added to rmfiles,
# add $file without .exe
func_append rmfiles " $file"
;;
esac
# Do a test to see if this is a libtool program.
if func_ltwrapper_p "$file"; then
if func_ltwrapper_executable_p "$file"; then
func_ltwrapper_scriptname "$file"
relink_command=
func_source $func_ltwrapper_scriptname_result
func_append rmfiles " $func_ltwrapper_scriptname_result"
else
relink_command=
func_source $dir/$noexename
fi
# note $name still contains .exe if it was in $file originally
# as does the version of $file that was added into $rmfiles
func_append rmfiles " $odir/$name $odir/${name}S.${objext}"
if test "$fast_install" = yes && test -n "$relink_command"; then
func_append rmfiles " $odir/lt-$name"
fi
if test "X$noexename" != "X$name" ; then
func_append rmfiles " $odir/lt-${noexename}.c"
fi
fi
fi
;;
esac
func_show_eval "$RM $rmfiles" 'exit_status=1'
done
# Try to remove the ${objdir}s in the directories where we deleted files
for dir in $rmdirs; do
if test -d "$dir"; then
func_show_eval "rmdir $dir >/dev/null 2>&1"
fi
done
exit $exit_status
}
{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } &&
func_mode_uninstall ${1+"$@"}
test -z "$opt_mode" && {
help="$generic_help"
func_fatal_help "you must specify a MODE"
}
test -z "$exec_cmd" && \
func_fatal_help "invalid operation mode \`$opt_mode'"
if test -n "$exec_cmd"; then
eval exec "$exec_cmd"
exit $EXIT_FAILURE
fi
exit $exit_status
# The TAGs below are defined such that we never get into a situation
# in which we disable both kinds of libraries. Given conflicting
# choices, we go for a static library, that is the most portable,
# since we can't tell whether shared libraries were disabled because
# the user asked for that or because the platform doesn't support
# them. This is particularly important on AIX, because we don't
# support having both static and shared libraries enabled at the same
# time on that platform, so we default to a shared-only configuration.
# If a disable-shared tag is given, we'll fallback to a static-only
# configuration. But we'll never go from static-only to shared-only.
# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
build_libtool_libs=no
build_old_libs=yes
# ### END LIBTOOL TAG CONFIG: disable-shared
# ### BEGIN LIBTOOL TAG CONFIG: disable-static
build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
# ### END LIBTOOL TAG CONFIG: disable-static
# Local Variables:
# mode:shell-script
# sh-indentation:2
# End:
# vi:sw=2
fstrm-0.2.0/fstrm/ 0000755 0001750 0001750 00000000000 12427010215 010772 5 0000000 0000000 fstrm-0.2.0/fstrm/libfstrm.pc.in 0000644 0001750 0001750 00000000330 12330751177 013475 0000000 0000000 prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libfstrm
Description: FrameStream C library
Version: @VERSION@
Libs: -L${libdir} -lfstrm
Libs.private:
Cflags: -I${includedir}
fstrm-0.2.0/fstrm/fstrm.h 0000644 0001750 0001750 00000030275 12330751177 012241 0000000 0000000 /*
* Copyright (c) 2013-2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*! \file
* \mainpage Introduction
*
* This is `fstrm`, a C implementation of the Frame Streams data transport
* protocol.
*
* Frame Streams is a light weight, binary clean protocol that allows for the
* transport of arbitrarily encoded data payload sequences with minimal framing
* overhead -- just four bytes per data frame. Frame Streams does not specify an
* encoding format for data frames and can be used with any data serialization
* format that produces byte sequences, such as [Protocol Buffers], [XML],
* [JSON], [MessagePack], [YAML], etc. Frame Streams can be used as both a
* streaming transport over a reliable byte stream socket (TCP sockets, TLS
* connections, `AF_UNIX` sockets, etc.) for data in motion as well as a file
* format for data at rest. A "Content Type" header identifies the type of
* payload being carried over an individual Frame Stream and allows cooperating
* programs to determine how to interpret a given sequence of data payloads.
*
* `fstrm` is an optimized C implementation of Frame Streams that includes a
* fast, lockless circular queue implementation and exposes library interfaces
* for setting up a dedicated Frame Streams I/O thread and asynchronously
* submitting data frames for transport from worker threads. It was originally
* written to facilitate the addition of high speed binary logging to DNS
* servers written in C using the [dnstap] log format.
*
* This is the API documentation for the `fstrm` library. For the project
* hosting site, see .
*
* \authors Farsight Security, Inc. and the `fstrm` authors.
*
* \copyright 2013-2014. Licensed under the terms of the [Apache-2.0] license.
*
* [Protocol Buffers]: https://developers.google.com/protocol-buffers/
* [XML]: http://www.w3.org/TR/xml11/
* [JSON]: http://www.json.org/
* [MessagePack]: http://msgpack.org/
* [YAML]: http://www.yaml.org/
* [dnstap]: http://dnstap.info/
* [Apache-2.0]: http://www.apache.org/licenses/LICENSE-2.0
*
* \page overview Library overview
*
* \section init Initializing the library
*
* `fstrm` has no global library state. In most cases, only a single
* \ref fstrm_iothr library context object will be needed for the entire process,
* which will implicitly create a background I/O serialization thread. This I/O
* thread is bound to a particular output writer (for example, an `AF_UNIX`
* socket) and is fully buffered -- submitted data frames will be accumulated in
* an output buffer and periodically flushed, minimizing the number of system
* calls that need to be performed. This frees worker threads from waiting for a
* write() to complete.
*
* `fstrm` abstracts the actual I/O operations needed to read or write a byte
* stream. File and socket I/O implementations are included in the library, but
* if necessary `fstrm` can be extended to support new types of byte stream
* transports. See the \ref fstrm_reader, \ref fstrm_writer, and \ref fstrm_rdwr
* interfaces for details.
*
* The following code example shows the initialization of an `fstrm_iothr`
* library context object connected to an \ref fstrm_file writer.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const char *file_path = "/tmp/output.fs";
struct fstrm_file_options *fopt;
struct fstrm_iothr *iothr;
struct fstrm_writer *writer;
fopt = fstrm_file_options_init();
fstrm_file_options_set_file_path(fopt, file_path);
writer = fstrm_file_writer_init(fopt, NULL);
if (!writer) {
fprintf(stderr, "Error: fstrm_file_writer_init() failed.\n");
exit(EXIT_FAILURE);
}
iothr = fstrm_iothr_init(NULL, &writer);
if (!iothr) {
fprintf(stderr, "Error: fstrm_iothr_init() failed.\n");
exit(EXIT_FAILURE);
}
fstrm_file_options_destroy(&fopt);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Since the I/O operations are abstracted through the `fstrm_writer` interface,
* the `writer` variable in the above example could instead have been
* initialized with a completely different implementation. For example,
* \ref fstrm_unix_writer objects can be initialized as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const char *socket_path = "/tmp/output.sock";
struct fstrm_writer *writer;
struct fstrm_unix_writer_options *uwopt;
uwopt = fstrm_unix_writer_options_init();
fstrm_unix_writer_options_set_socket_path(uwopt, socket_path);
writer = fstrm_unix_writer_init(uwopt, NULL);
if (!writer) {
fprintf(stderr, "Error: fstrm_unix_writer_init() failed.\n");
exit(EXIT_FAILURE);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* \section queue Getting an input queue
*
* After the `fstrm_iothr` object has been created with fstrm_iothr_init(), an
* input queue handle can be obtained with the fstrm_iothr_get_input_queue()
* function, which returns an `fstrm_iothr_queue` object. This function is
* thread-safe and returns a unique queue each time it is called, up to the
* number of queues specified by fstrm_iothr_options_set_num_input_queues().
* `fstrm_iothr_queue` objects belong to their parent `fstrm_iothr` object and
* will be destroyed when the parent `fstrm_iothr` object is destroyed.
*
* The following code example shows a single `fstrm_iothr_queue` handle being
* obtained from an already initialized `fstrm_iothr` library context object.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 'iothr' is a struct fstrm_iothr *
struct fstrm_iothr_queue *ioq;
ioq = fstrm_iothr_get_input_queue(iothr);
if (!ioq) {
fprintf(stderr, "Error: fstrm_iothr_get_input_queue() failed.\n");
exit(EXIT_FAILURE);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* \section submit Submitting data frames
*
* Once the `fstrm_iothr` object has been created and an `fstrm_iothr_queue`
* handle is available, data frames can be submitted for asynchronous writing
* using the fstrm_iothr_submit() function. A callback is passed to this
* function which will be invoked to deallocate the data frame once the I/O
* thread has completed processing it. In the common case where the data frame
* is dynamically allocated with `malloc()`, the deallocation callback must call
* `free()`. fstrm_free_wrapper() is provided as a convenience function which
* does this and can be specified as the `free_func` parameter to
* fstrm_iothr_submit().
*
* If space is available in the queue, fstrm_iothr_submit() will return
* #fstrm_res_success, indicating that ownership of the memory allocation for the
* data frame has passed from the caller to the library. The caller must not
* reuse or deallocate the memory for the data frame after a successful call to
* fstrm_iothr_submit().
*
* Callers must check the return value of fstrm_iothr_submit(). If this function
* fails, that is, it returns any result code other than #fstrm_res_success, the
* caller must deallocate or otherwise dispose of memory allocated for the data
* frame, in order to avoid leaking memory. fstrm_iothr_submit() can fail with
* #fstrm_res_again if there is currently no space in the circular queue for an
* additional frame, in which case a later call to fstrm_iothr_submit() with the
* same parameters may succeed. However, if fstrm_iothr_submit() fails with
* #fstrm_res_invalid, then there is a problem with the parameters and a later
* call will not succeed.
*
* The following code example shows data frames containing a short sequence of
* bytes being created and submitted repeatedly, with appropriate error
* handling. Note that the data frames in this example intentionally contain
* embedded unprintable characters, showing that Frame Streams is binary clean.
* This example follows from the previous examples, where the `iothr` and `ioq`
* variables have already been initialized.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 'iothr' is a struct fstrm_iothr *
// 'ioq' is a struct fstrm_queue *
const unsigned num_frames = 100;
const uint8_t frame_template[] = {
'H', 'e', 'l', 'l', 'o', 0x00, 0x01, 0x02, 0x03,
'W', 'o', 'r', 'l', 'd', 0x04, 0x05, 0x06, 0x07,
};
for (unsigned i = 0; i < num_frames; i++) {
// Allocate a new frame from the template.
uint8_t *frame = malloc(sizeof(frame_template));
if (!frame)
break;
memcpy(frame, frame_template, sizeof(frame_template));
// Submit the frame for writing.
for (;;) {
fstrm_res res;
res = fstrm_iothr_submit(iothr, ioq, frame,
sizeof(frame_template),
fstrm_free_wrapper, NULL);
if (res == fstrm_res_success) {
// Frame successfully queued.
break;
} else if (res == fstrm_res_again) {
// Queue is full. Try again in a busy loop.
// Alternatively, if loss can be tolerated we
// could free the frame here and break out of
// the loop.
continue;
} else {
// Permanent failure.
free(frame);
fputs("fstrm_iothr_submit() failed.\n", stderr);
break;
}
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* \section shutdown Shutting down
*
* Calling fstrm_iothr_destroy() on the `fstrm_iothr` object will signal the I/O
* thread to flush any outstanding data frames being written and will deallocate
* all associated resources. This function is synchronous and does not return
* until the I/O thread has terminated.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 'iothr' is a struct fstrm_iothr *
fstrm_iothr_destroy(&iothr);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#ifndef FSTRM_H
#define FSTRM_H
#ifdef __cplusplus
extern "C" {
#endif
#include
#include
#include
/**
* \defgroup fstrm_res fstrm_res
*
* Library result codes.
* @{
*/
/**
* Result codes for functions.
*/
typedef enum {
/** Success. */
fstrm_res_success,
/** Failure. */
fstrm_res_failure,
/** Resource temporarily unavailable. */
fstrm_res_again,
/** Parameters were invalid. */
fstrm_res_invalid,
/** The end of a stream has been reached. */
fstrm_res_stop,
} fstrm_res;
/**@}*/
struct fstrm_control;
struct fstrm_file_options;
struct fstrm_iothr;
struct fstrm_iothr_options;
struct fstrm_iothr_queue;
struct fstrm_rdwr;
struct fstrm_reader_options;
struct fstrm_unix_writer_options;
struct fstrm_writer;
struct fstrm_writer_options;
#include
#include
#include
#include
#include
#include
#include
#ifdef __cplusplus
}
#endif
#endif /* FSTRM_H */
fstrm-0.2.0/fstrm/control.h 0000644 0001750 0001750 00000047173 12330751177 012573 0000000 0000000 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FSTRM_CONTROL_H
#define FSTRM_CONTROL_H
/**
* \defgroup fstrm_control fstrm_control
*
* `fstrm_control` is an interface for encoding and decoding Frame Streams
* control frames.
*
* Two types of frames are possible in a Frame Streams byte stream: **data
* frames** and **control frames**. Both are variable length byte sequences
* prefixed by a 32-bit big endian unsigned integer (the **frame length**)
* specifying the length of the following byte sequence. If this frame length
* value is greater than zero, the **frame length** specifies the **data frame
* length**, and a data frame follows it. If the frame length is zero (i.e., it
* is the four byte sequence `00 00 00 00`), this is an **escape sequence**,
* which means that a control frame follows. The control frame itself is
* prefixed by a 32-bit big endian unsigned integer (the **control frame
* length**) specifying the length of the following **control frame payload**.
*
* There are two types of control frames used for uni-directional streams:
* `START` and `STOP`. These control frame types bracket the stream of data
* frames. `START` indicates the beginning of the stream and communicates
* metadata about the stream to follow, and `STOP` indicates the end of the
* stream.
*
* Bi-directional streams make use of three additional control frame types:
* `READY`, `ACCEPT`, and `FINISH`. These control frame types are used in a
* simple handshake protocol between sender and receiver.
*
* A uni-directional Frame Streams byte stream normally consists of the
* following:
*
* 1. The `START` control frame.
* 2. A sequence of zero or more data frames or control frames that are not of
* the control frame types `START`, `STOP`, `ACCEPT`, `READY`, or
* `FINISH`.
* 3. The `STOP` control frame.
*
* The `START` and `STOP` control frames are not optional. The `START` control
* frame must appear at the beginning of the byte stream, and the `STOP` control
* frame must appear at the end of the byte stream. (If the byte stream has an
* end.) `START` control frames must not appear anywhere other than at the
* beginning of the byte stream, and `STOP` control frames must not appear
* anywhere other than at the end of the byte stream. Only one `START` control
* frame and only one `STOP` control frame may appear in a Frame Streams byte
* stream.
*
* Control frames may optionally include zero or more **control frame fields**.
* There is currently one type of control frame field defined: `CONTENT_TYPE`.
* This field specifies a variable length byte sequence describing the encoding
* of data frames that appear in the Frame Streams byte stream. This field is
* used by cooperating programs to unambiguously identify how to interpret the
* data frames in a particular Frame Streams byte stream. For instance, this
* field may specify a particular schema to use to interpret the data frames
* appearing in the byte stream. Zero, one, or more `CONTENT_TYPE` fields may
* appear in `READY` or `ACCEPT` control frames. Zero or one `CONTENT_TYPE`
* fields may appear in `START` control frames. No `CONTENT_TYPE` fields may
* appear in `STOP` or `FINISH` control frames.
*
* A uni-directional Frame Streams encoder would normally produce a byte stream
* as follows:
*
* 1. Write the `START` **control frame**.
* + At the start of the byte stream, write the four byte **escape
* sequence** `00 00 00 00` that precedes control frames.
* + Write the **control frame length** as a 32-bit big endian unsigned
* integer.
* + Write the **control frame payload**. It must be a `START` control
* frame. It may optionally specify a `CONTENT_TYPE` field.
* 2. Write zero or more **data frames**.
* 3. Write the `STOP` **control frame**.
* + At the start of the byte stream, write the four byte **escape
* sequence** `00 00 00 00` that precedes control frames.
* + Write the **control frame length** as a 32-bit big endian unsigned
* integer.
* + Write the **control frame payload**. It must be a `STOP` control
* frame.
*
* A uni-directional Frame Streams decoder would normally process the byte
* stream as follows:
*
* 1. Read the `START` control frame.
* + At the start of the byte stream, read the four byte **escape
* sequence** `00 00 00 00` that precedes control frames.
* + Read the 32-bit big endian unsigned integer specifying the **control
* frame length**.
* + Decode the **control frame payload**. It must be a `START` control
* frame. It may optionally specify a `CONTENT_TYPE` field.
* 2. Repeatedly read data frames or control frames following the `START`
* control frame.
* + Read the **frame length**, a 32-bit big endian unsigned integer.
* + If the **frame length** is zero, a control frame follows:
* + Read the 32-bit big endian unsigned integer specifying the
* **control frame length**.
* + Decode the **control frame payload**. If it is a `STOP`
* control frame, the end of the Frame Streams byte stream has
* occurred, and no frames follow. Break out of the decoding loop
* and halt processing. (`READY`, `ACCEPT`, `START`, and `FINISH`
* may not occur here. For forward compatibility, control frames of
* types other than the types `READY`, `ACCEPT`, `START`, `STOP`,
* and `FINISH` must be ignored here. No control frames specified
* in the future may alter the encoding of succeeding frames.)
* + If the **frame length** is non-zero, it specifies the number of bytes
* in the following **data frame**. Consume these bytes from the byte
* stream.
*
* The functions fstrm_control_encode() and fstrm_control_decode() are provided
* to encode and decode control frames. See the detailed descriptions of those
* functions for code examples showing their usage.
*
* @{
*/
/**
* The maximum length in bytes of an "Accept", "Start", or "Stop" control frame
* payload. This excludes the escape sequence and the control frame length.
*/
#define FSTRM_CONTROL_FRAME_LENGTH_MAX 512
/**
* The maximum length in bytes of a "Content Type" control frame field payload.
* This excludes the field type and payload length.
*/
#define FSTRM_CONTROL_FIELD_CONTENT_TYPE_LENGTH_MAX 256
/**
* Control frame types.
*/
typedef enum {
/** Control frame type value for "Accept" control frames. */
FSTRM_CONTROL_ACCEPT = 0x01,
/** Control frame type value for "Start" control frames. */
FSTRM_CONTROL_START = 0x02,
/** Control frame type value for "Stop" control frames. */
FSTRM_CONTROL_STOP = 0x03,
/** Control frame type value for "Ready" control frames. */
FSTRM_CONTROL_READY = 0x04,
/** Control frame type value for "Finish" control frames. */
FSTRM_CONTROL_FINISH = 0x05,
} fstrm_control_type;
/**
* Control frame field types. These are optional fields that can appear in
* control frames.
*/
typedef enum {
/**
* Control frame field type value for the "Content Type" control frame
* option.
*/
FSTRM_CONTROL_FIELD_CONTENT_TYPE = 0x01,
} fstrm_control_field;
/**
* Flags for controlling the behavior of the encoding and decoding functions.
*/
typedef enum {
/**
* Set to control whether to include the control frame header in
* encoding/decoding operations.
*
* Causes fstrm_control_encode() and fstrm_control_encoded_size() to
* include the control frame header containing the escape sequence and
* control frame payload length in the encoded output. Otherwise, only
* the control frame payload itself is encoded.
*
* Tells fstrm_control_decode() that the input buffer to be decoded
* begins with the control frame header containing the escape sequence
* and control frame payload length. (Note that this requires the caller
* to peek at the input buffer to calculate the right buffer length.)
* Otherwise, the input buffer begins with the control frame payload.
*/
FSTRM_CONTROL_FLAG_WITH_HEADER = (1 << 0),
} fstrm_control_flag;
/**
* Convert an `fstrm_control_type` enum value to a string representation.
* Unknown values are represented as `"FSTRM_CONTROL_UNKNOWN"`.
*
* \param type The `fstrm_control_type` enum value.
* \return The string representation of the enum value. (Always non-NULL.)
*/
const char *
fstrm_control_type_to_str(fstrm_control_type type);
/**
* Convert an `fstrm_control_field` enum value to a string representation.
* Unknown values are represented as `"FSTRM_CONTROL_FIELD_UNKNOWN"`.
*
* \param f_type The `fstrm_control_field` enum value.
* \return The string representation of the enum value. (Always non-NULL.)
*/
const char *
fstrm_control_field_type_to_str(fstrm_control_field f_type);
/**
* Initialize an `fstrm_control` object. This object represents Frame Streams
* control frames and is used for encoding and decoding control frames.
*
* \return
* An `fstrm_control` object.
*/
struct fstrm_control *
fstrm_control_init(void);
/**
* Destroy an `fstrm_control` object.
*
* \param[in] c
* Pointer to an `fstrm_control` object.
*/
void
fstrm_control_destroy(struct fstrm_control **c);
/**
* Reinitialize an `fstrm_control` object. This resets the internal state to
* default values.
*
* \param c
* `fstrm_control` object.
*/
void
fstrm_control_reset(struct fstrm_control *c);
/**
* Retrieve the type of the control frame.
*
* \param c
* `fstrm_control` object.
* \param[out] type
* Type of the control frame.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_control_get_type(
const struct fstrm_control *c,
fstrm_control_type *type);
/**
* Set the type of the control frame.
*
* \param c
* `fstrm_control` object.
* \param[in] type
* Type of the control frame.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_control_set_type(
struct fstrm_control *c,
fstrm_control_type type);
/**
* Retrieve the number of "Content Type" fields present in the control frame.
*
* \param c
* `fstrm_control` object.
* \param[out] n_content_type
* The number of "Content Type" fields.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_control_get_num_field_content_type(
const struct fstrm_control *c,
size_t *n_content_type);
/**
* Retrieve a "Content Type" field from the control frame. This function
* returns a reference which must not be modified. Control frames may contain
* zero, one, or more "Content Type" fields.
*
* \see fstrm_control_get_num_field_content_type()
*
* \param c
* `fstrm_control` object.
* \param[in] idx
* The index of the "Content Type" field to retrieve.
* \param[out] content_type
* Pointer to where the reference to the "Content Type" string will be
* stored. Note that this string is not NUL-terminated and may contain
* embedded NULs.
* \param[out] len_content_type
* The number of bytes in `content_type`.
*
* \retval #fstrm_res_success
* The control frame has a "Content Type" field.
* \retval #fstrm_res_failure
* The control frame does not have a "Content Type" field.
*/
fstrm_res
fstrm_control_get_field_content_type(
const struct fstrm_control *c,
const size_t idx,
const uint8_t **content_type,
size_t *len_content_type);
/**
* Add a "Content Type" field to the control frame. This function makes a copy
* of the provided string. This function may be called multiple times, in which
* case multiple "Content Type" fields will be added to the control frame.
*
* The "Content Type" fields are removed on a call to fstrm_control_reset().
*
* \param c
* `fstrm_control` object.
* \param[in] content_type
* The "Content Type" string to copy. Note that this string is not
* NUL-terminated and may contain embedded NULs.
* \param[in] len_content_type
* The number of bytes in `content_type`.
*
* \retval #fstrm_res_success
* The "Content Type" field was successfully added.
* \retval #fstrm_res_failure
* The "Content Type" string is too long.
*/
fstrm_res
fstrm_control_add_field_content_type(
struct fstrm_control *c,
const uint8_t *content_type,
size_t len_content_type);
/**
* Check if the control frame matches a particular content type value. That is,
* the content type given in the `match` and `len_match` parameters is checked
* for compatibility with the content types (if any) specified in the control
* frame.
*
* \param c
* `fstrm_control` object.
* \param match
* The "Content Type" string to match. Note that this string is not
* NUL-terminated and may contain embedded NULs. May be NULL, in which case
* the control frame must not have any content type fields in order to
* match.
* \param len_match
* The number of bytes in `match`.
*
* \retval #fstrm_res_success
* A match was found.
* \retval #fstrm_res_failure
* A match was not found.
*/
fstrm_res
fstrm_control_match_field_content_type(
const struct fstrm_control *c,
const uint8_t *match,
const size_t len_match);
/**
* Decode a control frame from a buffer. The buffer starts with either the
* escape sequence or the control frame payload depending on whether the
* `FSTRM_CONTROL_FLAG_WITH_HEADER` flag is set or not. In either case, the
* 'len_control_frame' parameter must be exact. Underflow or overflow is not
* permitted.
*
* The following code example shows a function that decodes a control frame
* payload:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static fstrm_res
decode_control_frame(const void *control_frame, size_t len_control_frame)
{
fstrm_res res;
fstrm_control_type c_type;
struct fstrm_control *c;
uint32_t flags = 0;
c = fstrm_control_init();
res = fstrm_control_decode(c, control_frame, len_control_frame, flags);
if (res != fstrm_res_success) {
puts("fstrm_control_decode() failed.");
fstrm_control_destroy(&c);
return res;
}
res = fstrm_control_get_type(c, &c_type);
if (res != fstrm_res_success) {
puts("fstrm_control_get_type() failed.");
fstrm_control_destroy(&c);
return res;
}
printf("The control frame is of type %s (%u).\n",
fstrm_control_type_to_str(c_type), c_type);
size_t n_content_type;
res = fstrm_control_get_num_field_content_type(c, &n_content_type);
if (res != fstrm_res_success) {
puts("fstrm_control_get_num_field_content_type() failed.");
fstrm_control_destroy(&c);
return res;
}
const uint8_t *content_type;
size_t len_content_type;
for (size_t idx = 0; idx < n_content_type; idx++) {
res = fstrm_control_get_field_content_type(c, idx,
&content_type, &len_content_type);
if (res == fstrm_res_success) {
printf("The control frame has a CONTENT_TYPE field of length %zd.\n",
len_content_type);
}
}
fstrm_control_destroy(&c);
return fstrm_res_success;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* \param c
* `fstrm_control` object. Its state will be overwritten.
* \param[in] control_frame
* Buffer containing the serialized control frame.
* \param[in] len_control_frame
* The number of bytes in `control_frame`. This parameter must specify the
* exact number of bytes in the control frame.
* \param flags
* Flags controlling the decoding process. See #fstrm_control_flag.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_control_decode(
struct fstrm_control *c,
const void *control_frame,
size_t len_control_frame,
const uint32_t flags);
/**
* Calculate the number of bytes needed to serialize the control frame.
*
* \param c
* `fstrm_control` object.
* \param[out] len_control_frame
* The number of bytes needed to encode `c`.
* \param flags
* Flags controlling the encoding process. See #fstrm_control_flag.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_control_encoded_size(
const struct fstrm_control *c,
size_t *len_control_frame,
const uint32_t flags);
/**
* Encode a control frame into a buffer. Since a Frame Streams control frame is
* a variable length byte sequence of up to #FSTRM_CONTROL_FRAME_LENGTH_MAX
* bytes, this function can be used in two different ways. The first way is to
* call fstrm_control_encoded_size() to obtain the exact number of bytes needed
* to encode the frame, and then pass a buffer of this exact size to
* fstrm_control_encode(). The following example shows this usage:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fstrm_res res;
struct fstrm_control *c;
uint8_t *control_frame;
size_t len_control_frame;
uint32_t flags = 0;
c = fstrm_control_init();
res = fstrm_control_set_type(c, FSTRM_CONTROL_START);
if (res != fstrm_res_success) {
// Error handling goes here.
}
// Calculate the number of bytes needed.
res = fstrm_control_encoded_size(c, &len_control_frame, flags);
if (res != fstrm_res_success) {
// Error handling goes here.
}
// 'len_control_frame' now specifies the number of bytes required for
// the control frame. Allocate the needed space.
control_frame = malloc(len_control_frame);
if (!control_frame) {
// Error handling goes here.
}
// Serialize the control frame into the allocated buffer.
res = fstrm_control_encode(c, control_frame, &len_control_frame, 0);
if (res != fstrm_res_success) {
// Error handling goes here.
}
// Do something with 'control_frame' and 'len_control_frame'.
// Clean up.
free(control_frame);
fstrm_control_destroy(&c);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* The second way to use fstrm_control_encode() is to allocate a statically
* sized buffer of #FSTRM_CONTROL_FRAME_LENGTH_MAX bytes. The exact number of
* bytes serialized by the encoder will be returned in the `len_control_frame`
* parameter. The following example shows this usage:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fstrm_res res;
struct fstrm_control *c;
uint8_t control_frame[FSTRM_CONTROL_FRAME_LENGTH_MAX];
size_t len_control_frame = sizeof(control_frame);
c = fstrm_control_init();
res = fstrm_control_set_type(c, FSTRM_CONTROL_START);
if (res != fstrm_res_success) {
// Error handling.
}
// Serialize the control frame.
res = fstrm_control_encode(c, control_frame, &len_control_frame, 0);
if (res != fstrm_res_success) {
// Error handling goes here.
}
// Do something with 'control_frame' and 'len_control_frame'.
// Clean up.
fstrm_control_destroy(&c);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* \param c
* `fstrm_control` object.
* \param[out] control_frame
* The buffer in which to serialize the control frame.
* \param[in,out] len_control_frame
* The size in bytes of `control_frame`. On a successful return, contains
* the number of bytes actually written into `control_frame`.
* \param flags
* Flags controlling the encoding process. See #fstrm_control_flag.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_control_encode(
const struct fstrm_control *c,
void *control_frame,
size_t *len_control_frame,
const uint32_t flags);
/**@}*/
#endif /* FSTRM_CONTROL_H */
fstrm-0.2.0/fstrm/iothr.h 0000644 0001750 0001750 00000035154 12342165321 012225 0000000 0000000 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FSTRM_IOTHR_H
#define FSTRM_IOTHR_H
/**
* \defgroup fstrm_iothr fstrm_iothr
*
* The `fstrm_iothr` interface creates a background I/O thread which writes
* Frame Streams encapsulated data frames into an output stream specified by an
* \ref fstrm_writer object. It exposes non-blocking input queues that can be
* used by worker threads to asynchronously write data frames to the output
* stream. A deferred deallocation callback is invoked after the I/O thread has
* disposed of a queued data frame.
*
* In order to create an `fstrm_iothr` object, the caller must first configure
* and instantiate an `fstrm_writer` object and pass this instance to the
* fstrm_iothr_init() function. The `fstrm_iothr` object then takes ownership of
* the `fstrm_writer` object. It is responsible for serializing writes and will
* take care of destroying the captive `fstrm_writer` object at the same time
* the `fstrm_iothr` object is destroyed. The caller should not perform any
* operations on the captive `fstrm_writer` object after it has been passed to
* `fstrm_iothr_init()`.
*
* Parameters used to configure the I/O thread are passed through an
* `fstrm_iothr_options` object. These options have to be specified in advance
* and are mostly performance knobs which have reasonable defaults.
*
* Once the `fstrm_iothr` object has been created, handles to the input queues
* used to submit data frames can be obtained by calling
* `fstrm_iothr_get_input_queue()`. This function can be called up to
* **num_input_queues** times, and can be safely called concurrently. For
* instance, in an application with a fixed number of worker threads, an input
* queue can be dedicated to each worker thread by setting the
* **num_input_queues** option to the number of worker threads, and then calling
* `fstrm_iothr_get_input_queue()` from each worker thread's startup function to
* obtain a per-thread input queue.
*
* @{
*/
/**
* Initialize an `fstrm_iothr_options` object. This is needed to pass
* configuration parameters to fstrm_iothr_init().
*
* \return
* `fstrm_iothr_options` object.
*/
struct fstrm_iothr_options *
fstrm_iothr_options_init(void);
/**
* Destroy an `fstrm_iothr_options` object.
*
* \param opt
* Pointer to `fstrm_iothr_options` object.
*/
void
fstrm_iothr_options_destroy(struct fstrm_iothr_options **opt);
/**
* Set the `buffer_hint` parameter. This is the threshold number of bytes to
* accumulate in the output buffer before forcing a buffer flush.
*
* \param opt
* `fstrm_iothr_options` object.
* \param buffer_hint
* New `buffer_hint` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_buffer_hint(
struct fstrm_iothr_options *opt,
unsigned buffer_hint);
/** Minimum `buffer_hint` value. */
#define FSTRM_IOTHR_BUFFER_HINT_MIN 1024
/** Default `buffer_hint` value. */
#define FSTRM_IOTHR_BUFFER_HINT_DEFAULT 8192
/** Maximum `buffer_hint` value. */
#define FSTRM_IOTHR_BUFFER_HINT_MAX 65536
/**
* Set the `flush_timeout` parameter. This is the number of seconds to allow
* unflushed data to remain in the output buffer.
*
* \param opt
* `fstrm_iothr_options` object.
* \param flush_timeout
* New `flush_timeout` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_flush_timeout(
struct fstrm_iothr_options *opt,
unsigned flush_timeout);
/** Minimum `flush_timeout` value. */
#define FSTRM_IOTHR_FLUSH_TIMEOUT_MIN 1
/** Default `flush_timeout` value. */
#define FSTRM_IOTHR_FLUSH_TIMEOUT_DEFAULT 1
/** Maximum `flush_timeout` value. */
#define FSTRM_IOTHR_FLUSH_TIMEOUT_MAX 600
/**
* Set the `input_queue_size` parameter. This is the number of queue entries to
* allocate per each input queue. This option controls the number of outstanding
* data frames per input queue that can be outstanding for deferred processing
* by the `fstrm_iothr` object and thus affects performance and memory usage.
*
* This parameter must be a power-of-2.
*
* \param opt
* `fstrm_iothr_options` object.
* \param input_queue_size
* New `input_queue_size` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_input_queue_size(
struct fstrm_iothr_options *opt,
unsigned input_queue_size);
/** Minimum `input_queue_size` value. */
#define FSTRM_IOTHR_INPUT_QUEUE_SIZE_MIN 2
/** Default `input_queue_size` value. */
#define FSTRM_IOTHR_INPUT_QUEUE_SIZE_DEFAULT 512
/** Maximum `input_queue_size` value. */
#define FSTRM_IOTHR_INPUT_QUEUE_SIZE_MAX 16384
/**
* Set the `num_input_queues` parameter. This is the number of input queues to
* create and must match the number of times that fstrm_iothr_get_input_queue()
* is called on the corresponding `fstrm_iothr` object.
*
* \param opt
* `fstrm_iothr_options` object.
* \param num_input_queues
* New `num_input_queues` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_num_input_queues(
struct fstrm_iothr_options *opt,
unsigned num_input_queues);
/** Minimum `num_input_queues` value. */
#define FSTRM_IOTHR_NUM_INPUT_QUEUES_MIN 1
/** Default `num_input_queues` value. */
#define FSTRM_IOTHR_NUM_INPUT_QUEUES_DEFAULT 1
/**
* Set the `output_queue_size` parameter. This is the number of queue entries to
* allocate for the output queue. This option controls the maximum number of
* data frames that can be accumulated in the output queue before a buffer flush
* must occur and thus affects performance and memory usage.
*
* \param opt
* `fstrm_iothr_options` object.
* \param output_queue_size
* New `output_queue_size` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_output_queue_size(
struct fstrm_iothr_options *opt,
unsigned output_queue_size);
/** Minimum `output_queue_size` value. */
#define FSTRM_IOTHR_OUTPUT_QUEUE_SIZE_MIN 2
/** Default `output_queue_size` value. */
#define FSTRM_IOTHR_OUTPUT_QUEUE_SIZE_DEFAULT 64
/** Maximum `output_queue_size` value. */
#define FSTRM_IOTHR_OUTPUT_QUEUE_SIZE_MAX IOV_MAX
/**
* Queue models.
* \see fstrm_iothr_options_set_queue_model()
*/
typedef enum {
/** Single Producer, Single Consumer. */
FSTRM_IOTHR_QUEUE_MODEL_SPSC,
/** Multiple Producer, Single Consumer. */
FSTRM_IOTHR_QUEUE_MODEL_MPSC,
} fstrm_iothr_queue_model;
/**
* Set the `queue_model` parameter. This controls what queueing semantics to use
* for `fstrm_iothr_queue` objects. Single Producer queues
* (#FSTRM_IOTHR_QUEUE_MODEL_SPSC) may only have a single thread at a time
* calling fstrm_iothr_submit() on a given `fstrm_iothr_queue` object, while
* Multiple Producer queues (#FSTRM_IOTHR_QUEUE_MODEL_MPSC) may have multiple
* threads concurrently calling fstrm_iothr_submit() on a given
* `fstrm_iothr_queue` object.
*
* \param opt
* `fstrm_iothr_options` object.
* \param queue_model
* New `queue_model` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_queue_model(
struct fstrm_iothr_options *opt,
fstrm_iothr_queue_model queue_model);
/** Default `queue_model` value. */
#define FSTRM_IOTHR_QUEUE_MODEL_DEFAULT FSTRM_IOTHR_QUEUE_MODEL_SPSC
/**
* Set the `queue_notify_threshold` parameter. This controls the number of
* outstanding queue entries to allow on an input queue before waking the I/O
* thread, which will cause the outstanding queue entries to begin draining.
*
* \param opt
* `fstrm_iothr_options` object.
* \param queue_notify_threshold
* New `queue_notify_threshold` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_queue_notify_threshold(
struct fstrm_iothr_options *opt,
unsigned queue_notify_threshold);
/** Minimum `queue_notify_threshold` value. */
#define FSTRM_IOTHR_QUEUE_NOTIFY_THRESHOLD_MIN 1
/** Default `queue_notify_threshold` value. */
#define FSTRM_IOTHR_QUEUE_NOTIFY_THRESHOLD_DEFAULT 32
/**
* Set the `reopen_interval` parameter. This controls the number of seconds to
* wait between attempts to reopen a closed `fstrm_writer` output stream.
*
* \param opt
* `fstrm_iothr_options` object.
* \param reopen_interval
* New `queue_notify_threshold` value.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_iothr_options_set_reopen_interval(
struct fstrm_iothr_options *opt,
unsigned reopen_interval);
/** Minimum `reopen_interval` value. */
#define FSTRM_IOTHR_REOPEN_INTERVAL_MIN 1
/** Default `reopen_interval` value. */
#define FSTRM_IOTHR_REOPEN_INTERVAL_DEFAULT 5
/** Maximum `reopen_interval` value. */
#define FSTRM_IOTHR_REOPEN_INTERVAL_MAX 600
/**
* Initialize an `fstrm_iothr` object. This creates a background I/O thread
* which asynchronously writes data frames submitted by other threads which call
* fstrm_iothr_submit().
*
* \param opt
* `fstrm_iothr_options` object. May be NULL, in which case default values
* will be used.
*
* \param writer
* Pointer to `fstrm_writer` object. Must be non-NULL.
*
* \return
* `fstrm_iothr` object.
* \retval
* NULL on failure.
*/
struct fstrm_iothr *
fstrm_iothr_init(
const struct fstrm_iothr_options *opt,
struct fstrm_writer **writer);
/**
* Destroy an `fstrm_iothr` object. This signals the background I/O thread to
* flush or discard any queued data frames and deallocates any resources used
* internally. This function blocks until the I/O thread has terminated.
*
* \param iothr
* Pointer to `fstrm_iothr` object.
*/
void
fstrm_iothr_destroy(struct fstrm_iothr **iothr);
/**
* Obtain an `fstrm_iothr_queue` object for submitting data frames to the
* `fstrm_iothr` object. `fstrm_iothr_queue` objects are child objects of their
* parent `fstrm_iothr` object and will be destroyed when fstrm_iothr_destroy()
* is called on the parent `fstrm_iothr` object.
*
* This function is thread-safe and may be called simultaneously from any
* thread. For example, in a program which employs a fixed number of worker
* threads to handle requests, fstrm_iothr_get_input_queue() may be called from
* a thread startup routine without synchronization.
*
* `fstrm_iothr` objects allocate a fixed total number of `fstrm_iothr_queue`
* objects during the call to fstrm_iothr_init(). To adjust this parameter, use
* fstrm_iothr_options_set_num_input_queues().
*
* This function will fail if it is called more than **num_input_queues** times.
* By default, only one input queue is initialized per `fstrm_iothr` object.
*
* For optimum performance in a threaded program, each worker thread submitting
* data frames should have a dedicated `fstrm_iothr_queue` object. This allows
* each worker thread to have its own queue which is processed independently by
* the I/O thread. If the queue model for the `fstrm_iothr` object is set to
* #FSTRM_IOTHR_QUEUE_MODEL_SPSC, this results in contention-free access to the
* input queue.
*
* \param iothr
* `fstrm_iothr` object.
*
* \return
* `fstrm_iothr_queue` object.
* \retval
* NULL on failure.
*/
struct fstrm_iothr_queue *
fstrm_iothr_get_input_queue(struct fstrm_iothr *iothr);
/**
* Obtain an `fstrm_iothr_queue` object for submitting data frames to the
* `fstrm_iothr` object. This function is like fstrm_iothr_get_input_queue()
* except it indexes into the `fstrm_iothr_queue`'s array of input queues.
*
* \param iothr
* `fstrm_iothr` object.
* \param idx
* Index of the `fstrm_iothr_queue` object to retrieve. This value is
* limited by the **num_input_queues** option.
*
* \return
* `fstrm_iothr_queue` object.
* \retval
* NULL on failure.
*/
struct fstrm_iothr_queue *
fstrm_iothr_get_input_queue_idx(struct fstrm_iothr *iothr, size_t idx);
/**
* Submit a data frame to the background I/O thread. If successfully queued and
* the I/O thread has an active output stream opened, the data frame will be
* asynchronously written to the output stream.
*
* When this function returns #fstrm_res_success, responsibility for
* deallocating the data frame specified by the `data` parameter passes to the
* `fstrm` library. The caller **MUST** ensure that the `data` object remains
* valid after fstrm_iothr_submit() returns. The callback function specified by
* the `free_func` parameter will be invoked once the data frame is no longer
* needed by the `fstrm` library. For example, if the data frame is dynamically
* allocated, the data frame may be deallocated in the callback function.
*
* Note that if this function returns #fstrm_res_failure, the responsibility for
* deallocating the data frame remains with the caller.
*
* As a convenience, if `data` is allocated with the system's `malloc()`,
* `fstrm_free_wrapper` may be provided as the `free_func` parameter with the
* `free_data` parameter set to `NULL`. This will cause the system's `free()` to
* be invoked to deallocate `data`.
*
* `free_func` may be NULL, in which case no callback function will be invoked
* to dispose of `buf`. This behavior may be useful if `data` is a global,
* statically allocated object.
*
* \param iothr
* `fstrm_iothr` object.
* \param ioq
* `fstrm_iothr_queue` object.
* \param data
* Data frame bytes.
* \param len
* Number of bytes in `data`.
* \param free_func
* Callback function to deallocate the data frame. The `data` and
* `free_data` parameters passed to this callback will be the same values
* originally supplied in the call to fstrm_iothr_submit().
* \param free_data
* Parameter to pass to `free_func`.
*
* \retval #fstrm_res_success
* The data frame was successfully queued.
* \retval #fstrm_res_again
* The queue is full.
* \retval #fstrm_res_failure
* Permanent failure.
*/
fstrm_res
fstrm_iothr_submit(
struct fstrm_iothr *iothr, struct fstrm_iothr_queue *ioq,
void *data, size_t len,
void (*free_func)(void *buf, void *free_data), void *free_data);
/**
* Wrapper function for the system's `free()`, suitable for use as the
* `free_func` callback for fstrm_iothr_submit().
*
* \param data
* Object to call `free()` on.
* \param free_data
* Unused.
*/
void
fstrm_free_wrapper(void *data, void *free_data);
/**@}*/
#endif /* FSTRM_IOTHR_H */
fstrm-0.2.0/fstrm/file.h 0000644 0001750 0001750 00000005202 12330751177 012015 0000000 0000000 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FSTRM_FILE_H
#define FSTRM_FILE_H
/**
* \defgroup fstrm_file fstrm_file
*
* `fstrm_file` contains interfaces for opening \ref fstrm_reader or
* \ref fstrm_writer objects that are backed by file I/O.
*
* @{
*/
/**
* Initialize an `fstrm_file_options` object, which is needed to configure the
* file path to be opened by fstrm_file_reader_init() or
* fstrm_file_writer_init().
*
* \return
* `fstrm_file_options` object.
*/
struct fstrm_file_options *
fstrm_file_options_init(void);
/**
* Destroy an `fstrm_file_options` object.
*
* \param fopt
* Pointer to `fstrm_file_options` object.
*/
void
fstrm_file_options_destroy(struct fstrm_file_options **fopt);
/**
* Set the `file_path` option. This is a filesystem path to a regular file to be
* opened for reading or writing.
*
* \param fopt
* `fstrm_file_options` object.
* \param file_path
* The filesystem path for a regular file.
*/
void
fstrm_file_options_set_file_path(struct fstrm_file_options *fopt,
const char *file_path);
/**
* Open a file containing Frame Streams data for reading.
*
* \param fopt
* `fstrm_file_options` object. Must be non-NULL, and have the `file_path`
* option set.
* \param ropt
* `fstrm_reader_options` object. May be NULL, in which case default values
* will be used.
*
* \return
* `fstrm_reader` object.
* \retval
* NULL on failure.
*/
struct fstrm_reader *
fstrm_file_reader_init(const struct fstrm_file_options *fopt,
const struct fstrm_reader_options *ropt);
/**
* Open a file for writing Frame Streams data. The file will be truncated if it
* already exists.
*
* \param fopt
* `fstrm_file_options` object. Must be non-NULL, and have the `file_path`
* option set.
* \param wopt
* `fstrm_writer_options` object. May be NULL, in which case default values
* will be used.
*
* \return
* `fstrm_writer` object.
* \retval
* NULL on failure.
*/
struct fstrm_writer *
fstrm_file_writer_init(const struct fstrm_file_options *fopt,
const struct fstrm_writer_options *wopt);
/**@}*/
#endif /* FSTRM_FILE_H */
fstrm-0.2.0/fstrm/rdwr.h 0000644 0001750 0001750 00000021477 12330751177 012070 0000000 0000000 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FSTRM_RDWR_H
#define FSTRM_RDWR_H
/**
* \defgroup fstrm_rdwr fstrm_rdwr
*
* `fstrm_rdwr` is an interface for abstracting the process of reading and
* writing data to byte streams. It allows extending the `fstrm` library to
* support reading and writing Frame Streams data to new kinds of byte stream
* transports. (It also allows building mock interfaces for testing the correct
* functioning of the library.)
*
* `fstrm_rdwr` is a low-level interface that is used in conjunction with the
* higher level \ref fstrm_reader and \ref fstrm_writer interfaces. The
* following methods need to be defined for `fstrm_rdwr` implementations:
*
* Method name | Method type | Method description
* ------------ | ----------------------------- | ------------------
* `destroy` | #fstrm_rdwr_destroy_func | Destroys the instance.
* `open` | #fstrm_rdwr_open_func | Opens the stream.
* `close` | #fstrm_rdwr_close_func | Closes the stream.
* `read` | #fstrm_rdwr_read_func | Reads bytes from the stream.
* `write` | #fstrm_rdwr_write_func | Writes bytes to the stream.
*
* The `destroy` method is optional. It cleans up any remaining resources
* associated with the instance.
*
* The `open` method is required. It should perform the actual opening of the
* byte stream and prepare it to read or write data.
*
* The `close` method is required. It should perform the actual closing of the
* byte stream.
*
* If the `fstrm_rdwr` object is to be used in an `fstrm_reader` object, it must
* have a `read` method. If the `fstrm_rdwr` object embedded in an
* `fstrm_reader` object also has a `write` method, the stream will be
* considered bi-directional (that is, it supports both reading and writing) and
* handshaking will be performed. If a `read` method is supplied but a `write`
* method is not, the reader's stream will instead be considered
* uni-directional. See \ref fstrm_reader for details.
*
* If the `fstrm_rdwr` object is to be used in an `fstrm_writer` object, it must
* have a `write` method. If the `fstrm_rdwr` object embedded in an
* `fstrm_writer` object also has a `read` method, the stream will be considered
* bi-directional and shaking will be performed. If a `write` method is supplied
* but a `read` method is not, the writer's stream will instead be considered
* uni-directional. See \ref fstrm_writer for details.
*
* An `fstrm_rdwr` instance is created with a call to `fstrm_rdwr_init()`,
* optionally passing a pointer to some state object associated with the
* instance. This pointer will be passed as the first argument to each of the
* methods described above. Then, the various `fstrm_rdwr_set_*()` functions
* should be used to configure the functions to be used to invoke the methods
* required for the `fstrm_rdwr` object.
*
* @{
*/
/**
* `destroy` method function type. This method is invoked to deallocate any
* per-stream resources used by an `fstrm_rdwr` implementation.
*
* \see fstrm_rdwr_set_destroy()
*
* \param obj
* The `obj` value passed to `fstrm_rdwr_init()`.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
typedef fstrm_res
(*fstrm_rdwr_destroy_func)(void *obj);
/**
* `open` method function type. This method is invoked to open the stream and
* prepare it for reading or writing. For example, if an `fstrm_rdwr`
* implementation is backed by file I/O, this method might be responsible for
* opening a file descriptor.
*
* \see fstrm_rdwr_set_open()
*
* \param obj
* The `obj` value passed to `fstrm_rdwr_init()`.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
typedef fstrm_res
(*fstrm_rdwr_open_func)(void *obj);
/**
* `close` method function type. This method is invoked to close the stream. For
* example, if an `fstrm_rdwr` implementation is backed by file I/O, this method
* might be responsible for closing a file descriptor.
*
* \see fstrm_rdwr_set_close()
*
* \param obj
* The `obj` value passed to `fstrm_rdwr_init()`.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
typedef fstrm_res
(*fstrm_rdwr_close_func)(void *obj);
/**
* `read` method function type. This method is used to read data from a stream.
* It must satisfy the full amount of data requested, unless the stream has
* ended.
*
* \see fstrm_rdwr_set_read()
*
* \param obj
* The `obj` value passed to `fstrm_rdwr_init()`.
* \param data
* The buffer in which to place the data read.
* \param count
* The number of bytes requested.
*
* \retval #fstrm_res_success
* The data was read successfully.
* \retval #fstrm_res_failure
* An unexpected failure occurred.
* \retval #fstrm_res_stop
* The end of the stream has occurred.
*/
typedef fstrm_res
(*fstrm_rdwr_read_func)(void *obj, void *data, size_t count);
/**
* `write` method function type. This method is used to write data to a stream.
* It must perform the full write of all data, unless an error has occurred.
*
* \see fstrm_rdwr_set_write()
*
* \param obj
* The `obj` value passed to `fstrm_rdwr_init()`.
* \param iov
* Array of `struct iovec` objects.
* \param iovcnt
* Number of `struct iovec` objects in `iov`.
*
* \return #fstrm_res_success
* \return #fstrm_res_failure
*/
typedef fstrm_res
(*fstrm_rdwr_write_func)(void *obj, const struct iovec *iov, int iovcnt);
/**
* Initialize a new `fstrm_rdwr` object.
*
* \param obj
* Per-object state.
*
* \return
* `fstrm_rdwr` object.
* \retval
* NULL on failure.
*/
struct fstrm_rdwr *
fstrm_rdwr_init(void *obj);
/**
* Destroy an `fstrm_rdwr` object. This invokes the underlying `destroy` method
* as well.
*
* \param rdwr
* Pointer to an `fstrm_rdwr` object.
*
* \return #fstrm_res_success
* \return #fstrm_res_failure
*/
fstrm_res
fstrm_rdwr_destroy(struct fstrm_rdwr **rdwr);
/**
* Invoke the `open` method on an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
*
* \return #fstrm_res_success
* \return #fstrm_res_failure
*/
fstrm_res
fstrm_rdwr_open(struct fstrm_rdwr *rdwr);
/**
* Invoke the `close` method on an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
*
* \return #fstrm_res_success
* \return #fstrm_res_failure
*/
fstrm_res
fstrm_rdwr_close(struct fstrm_rdwr *rdwr);
/**
* Invoke the `read` method on an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
* \param data
* The buffer in which to place the data read.
* \param count
* The number of bytes to read.
*
* \return #fstrm_res_success
* \return #fstrm_res_failure
* \return #fstrm_res_stop
*/
fstrm_res
fstrm_rdwr_read(struct fstrm_rdwr *rdwr, void *data, size_t count);
/**
* Invoke the `write` method on an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
* \param iov
* Array of `struct iovec` objects.
* \param iovcnt
* Number of `struct iovec` objects in `iov`.
*
* \return #fstrm_res_success
* \return #fstrm_res_failure
*/
fstrm_res
fstrm_rdwr_write(struct fstrm_rdwr *rdwr, const struct iovec *iov, int iovcnt);
/**
* Set the `destroy` method for an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
* \param fn
* Function to use.
*/
void
fstrm_rdwr_set_destroy(
struct fstrm_rdwr *rdwr,
fstrm_rdwr_destroy_func fn);
/**
* Set the `open` method for an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
* \param fn
* Function to use.
*/
void
fstrm_rdwr_set_open(
struct fstrm_rdwr *rdwr,
fstrm_rdwr_open_func fn);
/**
* Set the `close` method for an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
* \param fn
* Function to use.
*/
void
fstrm_rdwr_set_close(
struct fstrm_rdwr *rdwr,
fstrm_rdwr_close_func fn);
/**
* Set the `read` method for an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
* \param fn
* Function to use.
*/
void
fstrm_rdwr_set_read(
struct fstrm_rdwr *rdwr,
fstrm_rdwr_read_func fn);
/**
* Set the `write` method for an `fstrm_rdwr` object.
*
* \param rdwr
* The `fstrm_rdwr` object.
* \param fn
* Function to use.
*/
void
fstrm_rdwr_set_write(
struct fstrm_rdwr *rdwr,
fstrm_rdwr_write_func fn);
/**@}*/
#endif /* FSTRM_RDWR_H */
fstrm-0.2.0/fstrm/reader.h 0000644 0001750 0001750 00000016720 12330751177 012347 0000000 0000000 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FSTRM_READER_H
#define FSTRM_READER_H
/**
* \defgroup fstrm_reader fstrm_reader
*
* `fstrm_reader` is an interface for reading Frame Streams data from a byte
* stream. The underlying byte stream I/O operations are abstracted by the
* \ref fstrm_rdwr interface. Thus, the `fstrm_reader` interface can be used to
* read Frame Streams data from any source whose read/write operations are
* wrapped by an `fstrm_rdwr` object.
*
* Some basic `fstrm_reader` implementations are already provided in the `fstrm`
* library. See fstrm_file_reader_init() to create an `fstrm_reader` object that
* reads Frame Streams data from a regular file.
*
* @{
*/
/**
* The default `max_frame_size` value.
*/
#define FSTRM_READER_MAX_FRAME_SIZE_DEFAULT 1048576
/**
* Initialize an `fstrm_reader_options` object.
*
* \return
* `fstrm_reader_options` object.
*/
struct fstrm_reader_options *
fstrm_reader_options_init(void);
/**
* Destroy an `fstrm_reader_options` object.
*
* \param ropt
* Pointer to `fstrm_reader_options` object.
*/
void
fstrm_reader_options_destroy(
struct fstrm_reader_options **ropt);
/**
* Add a "Content Type" value to the set of content types accepted by the
* `fstrm_reader`. This function makes a copy of the provided string. This
* function may be called multiple times, in which case multiple "Content Type"
* values will be accepted by the reader.
*
* If the reader has no content types set, it will accept any content type.
*
* \param ropt
* `fstrm_reader_options` object.
* \param content_type
* The "Content Type" string to copy. Note that this string is not
* NUL-terminated and may contain embedded NULs.
* \param len_content_type
* The number of bytes in `content_type`.
*
* \retval #fstrm_res_success
* The "Content Type" field was successfully added.
* \retval #fstrm_res_failure
* The "Content Type" string is too long.
*/
fstrm_res
fstrm_reader_options_add_content_type(
struct fstrm_reader_options *ropt,
const void *content_type,
size_t len_content_type);
/**
* Set the maximum frame size that the reader is willing to accept. This
* enforces an upper limit on the amount of memory used to buffer incoming data
* from the reader's byte stream.
*
* If this option is not set, it defaults to
* #FSTRM_READER_MAX_FRAME_SIZE_DEFAULT.
*
* \param ropt
* `fstrm_reader_options` object.
* \param max_frame_size
* The maximum frame size value.
*
* \retval #fstrm_res_success
* The `max_frame_size` value was successfully set.
* \retval #fstrm_res_failure
* The `max_frame_size` value was too large or too small.
*/
fstrm_res
fstrm_reader_options_set_max_frame_size(
struct fstrm_reader_options *ropt,
size_t max_frame_size);
/**
* Initialize a new `fstrm_reader` object based on an underlying `fstrm_rdwr`
* object and an `fstrm_reader_options` object.
*
* The underlying `fstrm_rdwr` object MUST have a `read` method. It MAY
* optionally have a `write` method, in which case the stream will be treated as
* a bi-directional, handshaked stream. Otherwise, if there is no `write` method
* the stream will be treated as a uni-directional stream.
*
* This function is useful for implementing functions that return new types of
* `fstrm_reader` objects, such as fstrm_file_reader_init().
*
* After a successful call to this function, the ownership of the `fstrm_rdwr`
* object passes from the caller to the `fstrm_reader` object. The caller
* should perform no further calls on the `fstrm_rdwr` object. The `fstrm_rdwr`
* object will be cleaned up on a call to fstrm_reader_destroy().
*
* \param ropt
* `fstrm_reader_options` object. May be NULL, in which case default values
* will be used.
*
* \param rdwr
* Pointer to `fstrm_rdwr` object. Must be non-NULL. The `fstrm_rdwr`
* object must have a `read` method, and may optionally have a `write`
* method.
*
* \return
* `fstrm_reader` object.
* \retval
* NULL on failure.
*/
struct fstrm_reader *
fstrm_reader_init(
const struct fstrm_reader_options *ropt,
struct fstrm_rdwr **rdwr);
/**
* Destroy an `fstrm_reader` object. This implicitly calls fstrm_reader_close()
* if necessary.
*
* \param r
* Pointer to `fstrm_reader` object.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_reader_destroy(struct fstrm_reader **r);
/**
* Open an `fstrm_reader` object and prepare it to read data.
*
* This checks that the content type in the byte stream, if specified, matches
* one of the content types specified in the `fstrm_reader_options` object used
* to initialize the `fstrm_reader` object.
*
* This function may fail if there was an underlying problem opening the input
* stream.
*
* \param r
* `fstrm_reader` object.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_reader_open(struct fstrm_reader *r);
/**
* Close an `fstrm_reader` object. Once it has been closed, no data frames may
* subsequently be read.
*
* Calling this function is optional; it may be implicitly invoked by a call to
* fstrm_reader_destroy().
*
* \param r
* `fstrm_reader` object.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_reader_close(struct fstrm_reader *r);
/**
* Read a data frame from an `fstrm_reader` object. This frame is held in an
* internal buffer owned by the `fstrm_reader` object and should not be modified
* by the caller. The contents of this buffer will be overwritten by a
* subsequent call to fstrm_reader_read().
*
* This function implicitly calls fstrm_reader_open() if necessary.
*
* \param r
* `fstrm_reader` object.
* \param[out] data
* Pointer to buffer containing the data frame payload.
* \param[out] len_data
* The number of bytes available in `data`.
*
* \retval #fstrm_res_success
* A data frame was successfully read.
* \retval #fstrm_res_stop
* The end of the stream has been reached.
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_reader_read(
struct fstrm_reader *r,
const uint8_t **data,
size_t *len_data);
/**
* Obtain a pointer to an `fstrm_control` object used during processing. Objects
* returned by this function are owned by the `fstrm_reader` object and must not
* be modified by the caller. After a call to fstrm_reader_destroy() these
* pointers will no longer be valid.
*
* For example, this function can be used to obtain a pointer to the START
* control frame, which can be queried to see which "Content Type" was
* negotiated during the opening of the reader.
*
* This function implicitly calls fstrm_reader_open() if necessary.
*
* \param r
* `fstrm_reader` object.
* \param type
* Which control frame to return.
* \param[out] control
* The `fstrm_control` object.
*
* \retval #fstrm_res_success
* If an `fstrm_control` object was returned.
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_reader_get_control(
struct fstrm_reader *r,
fstrm_control_type type,
const struct fstrm_control **control);
/**@}*/
#endif /* FSTRM_READER_H */
fstrm-0.2.0/fstrm/unix_writer.h 0000644 0001750 0001750 00000004507 12330751177 013464 0000000 0000000 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FSTRM_UNIX_WRITER_H
#define FSTRM_UNIX_WRITER_H
/**
* \defgroup fstrm_unix_writer fstrm_unix_writer
*
* `fstrm_unix_writer` is an interface for opening an \ref fstrm_writer object
* that is backed by I/O on a stream-oriented (`SOCK_STREAM`) Unix socket.
*
* @{
*/
/**
* Initialize an `fstrm_unix_writer_options` object, which is needed to
* configure the socket path to be opened by the writer.
*
* \return
* `fstrm_unix_writer_options` object.
*/
struct fstrm_unix_writer_options *
fstrm_unix_writer_options_init(void);
/**
* Destroy an `fstrm_unix_writer_options` object.
*
* \param uwopt
* Pointer to `fstrm_unix_writer_options` object.
*/
void
fstrm_unix_writer_options_destroy(
struct fstrm_unix_writer_options **uwopt);
/**
* Set the `socket_path` option. This is a filesystem path that will be
* connected to as an `AF_UNIX` socket.
*
* \param uwopt
* `fstrm_unix_writer_options` object.
* \param socket_path
* The filesystem path to the `AF_UNIX` socket.
*/
void
fstrm_unix_writer_options_set_socket_path(
struct fstrm_unix_writer_options *uwopt,
const char *socket_path);
/**
* Initialize the `fstrm_writer` object. Note that the `AF_UNIX` socket will not
* actually be opened until a subsequent call to fstrm_writer_open().
*
* \param uwopt
* `fstrm_unix_writer_options` object. Must be non-NULL, and have the
* `socket_path` option set.
* \param wopt
* `fstrm_writer_options` object. May be NULL, in which chase default
* values will be used.
*
* \return
* `fstrm_writer` object.
* \retval
* NULL on failure.
*/
struct fstrm_writer *
fstrm_unix_writer_init(
const struct fstrm_unix_writer_options *uwopt,
const struct fstrm_writer_options *wopt);
/**@}*/
#endif /* FSTRM_UNIX_WRITER_H */
fstrm-0.2.0/fstrm/writer.h 0000644 0001750 0001750 00000017265 12345652114 012423 0000000 0000000 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FSTRM_WRITER_H
#define FSTRM_WRITER_H
/**
* \defgroup fstrm_writer fstrm_writer
*
* `fstrm_writer` is an interface for writing Frame Streams data into a byte
* stream. The underlying byte stream I/O operations are abstracted by the
* \ref fstrm_rdwr interface. Thus, the `fstrm_writer` interface can be used to
* write Frame Streams data to any type of output whose read/write operations
* are wrapped by an `fstrm_rdwr` object.
*
* Some basic `fstrm_writer` implementations are already provided in the `fstrm`
* library. See fstrm_file_writer_init() for an implementation that writes to
* a regular file and fstrm_unix_writer_init() for an implementation that writes
* to a Unix socket.
*
* @{
*/
/**
* Initialize an `fstrm_writer_options` object.
*
* \return
* `fstrm_writer_options` object.
*/
struct fstrm_writer_options *
fstrm_writer_options_init(void);
/**
* Destroy an `fstrm_writer_options` object.
*
* \param wopt
* Pointer to `fstrm_writer_options` object.
*/
void
fstrm_writer_options_destroy(
struct fstrm_writer_options **wopt);
/**
* Add a "Content Type" value to the set of content types that can be negotiated
* by the writer. This function makes a copy of the provided string. This
* function may be called multiple times, in which case multiple "Content Type"
* values will be accepted by the reader.
*
* For uni-directional streams like regular files, the negotiated content type
* will simply be the first content type provided to this function. For
* bi-directional streams like sockets, a handshake occurs and the remote end
* determines which content type should be sent. In the latter case, after the
* writer has been successfully opened with a call to fstrm_writer_open(), the
* fstrm_writer_get_control() function should be called with `type` set to
* `FSTRM_CONTROL_ACCEPT` and the control frame queried in order to determine
* the negotiated content type.
*
* \param wopt
* `fstrm_writer_options` object.
* \param content_type
* The "Content Type" string to copy. Note that this string is not
* NUL-terminated and may contain embedded NULs.
* \param len_content_type
* The number of bytes in `content_type`.
*
* \retval #fstrm_res_success
* The "Content Type" field was successfully added.
* \retval #fstrm_res_failure
* The "Content Type" string is too long.
*/
fstrm_res
fstrm_writer_options_add_content_type(
struct fstrm_writer_options *wopt,
const void *content_type,
size_t len_content_type);
/**
* Initialize a new `fstrm_writer` object based on an underlying `fstrm_rdwr`
* object and an `fstrm_writer_options` object.
*
* The underlying `fstrm_rdwr` object MUST have a `write` method. It MAY
* optionally have a `read` method, in which case the stream will be treated as
* a bi-directional, handshaked stream. Otherwise, if there is no `read` method
* the stream will be treated as a uni-directional stream.
*
* This function is useful for implementing functions that return new types of
* `fstrm_writer` objects, such as fstrm_file_writer_init() and
* fstrm_unix_writer_init().
*
* After a successful call to this function, the ownership of the `fstrm_rdwr`
* object passes from the caller to the `fstrm_writer` object. The caller
* should perform no further calls on the `fstrm_rdwr` object. The `fstrm_rdwr`
* object will be cleaned up on a call to fstrm_writer_destroy().
*
* \param wopt
* `fstrm_writer_options` object. May be NULL, in which case default values
* will be used.
*
* \param rdwr
* Pointer to `fstrm_rdwr` object. Must be non-NULL. The `fstrm_rdwr`
* object must have a `write` method, and may optionally have a `read`
* method.
*
* \return
* `fstrm_writer` object.
* \retval
* NULL on failure.
*/
struct fstrm_writer *
fstrm_writer_init(
const struct fstrm_writer_options *wopt,
struct fstrm_rdwr **rdwr);
/**
* Destroy an `fstrm_writer` object. This implicitly calls fstrm_writer_close()
* if necessary.
*
* \param w
* Pointer to `fstrm_writer` object.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_writer_destroy(struct fstrm_writer **w);
/**
* Open an `fstrm_writer` object and prepare it to write data. For
* bi-directional writer implementations, this performs content type
* negotiation.
*
* This function may fail if there was an underlying problem opening the output
* stream.
*
* \param w
* `fstrm_writer` object.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_writer_open(struct fstrm_writer *w);
/**
* Close an `fstrm_writer` object. Open it has been closed, no data frames may
* subsequently be written.
*
* Calling this function is optional; it may be implicitly invoked by a call to
* fstrm_writer_destroy().
*
* \param w
* `fstrm_writer` object.
*
* \retval #fstrm_res_success
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_writer_close(struct fstrm_writer *w);
/**
* Write a data frame to an `fstrm_writer` object.
*
* This function implicitly calls fstrm_writer_open() if necessary.
*
* \param w
* `fstrm_writer` object.
* \param[in] data
* Buffer containing the data frame payload.
* \param[in] len_data
* The number of bytes in `data`.
*
* \retval #fstrm_res_success
* The data frame was successfully written.
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_writer_write(
struct fstrm_writer *w,
const void *data,
size_t len_data);
/**
* Write multiple data frames to an `fstrm_writer` object.
*
* This function implicitly calls fstrm_writer_open() if necessary.
*
* Data frames are passed similarly to the `writev()` system call, with an array
* of `struct iovec` objects describing the data frame payloads and their
* lengths. The complete set of data frames will be written to the output
* stream after a successful call.
*
* \param w
* `fstrm_writer` object.
* \param iov
* Array of `struct iovec` objects.
* \param iovcnt
* Number of `struct iovec` objects in `iov`.
*
* \retval #fstrm_res_success
* The data frames were successfully written.
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_writer_writev(
struct fstrm_writer *w,
const struct iovec *iov,
int iovcnt);
/**
* Obtain a pointer to an `fstrm_control` object used during processing. Objects
* returned by this function are owned by the `fstrm_reader` object and must not
* be modified by the caller. After a call to fstrm_reader_destroy() these
* pointers will no longer be valid.
*
* For example, with bi-directional streams this function can be used to obtain
* a pointer to the ACCEPT control frame, which can be queried to see which
* "Content Type" was negotiated during the opening of the writer.
*
* This function implicitly calls fstrm_writer_open() if necessary.
*
* \param w
* `fstrm_writer` object.
* \param type
* Which control frame to return.
* \param[out] control
* The `fstrm_control` object.
*
* \retval #fstrm_res_success
* If an `fstrm_control` object was returned.
* \retval #fstrm_res_failure
*/
fstrm_res
fstrm_writer_get_control(
struct fstrm_writer *w,
fstrm_control_type type,
struct fstrm_control **control);
/**@}*/
#endif /* FSTRM_WRITER_H */
fstrm-0.2.0/fstrm/fstrm-private.h 0000644 0001750 0001750 00000007755 12330751177 013720 0000000 0000000 /*
* Copyright (c) 2013-2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FSTRM_PRIVATE_H
#define FSTRM_PRIVATE_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "fstrm.h"
#include "libmy/my_alloc.h"
#include "libmy/my_memory_barrier.h"
#include "libmy/my_queue.h"
#include "libmy/read_bytes.h"
#include "libmy/vector.h"
#if defined(__GNUC__)
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
# define warn_unused_result __attribute__ ((warn_unused_result))
#else
# define likely(x)
# define unlikely(x)
# define warn_unused_result
#endif
#ifndef MSG_NOSIGNAL
# define MSG_NOSIGNAL 0
#endif
#ifndef IOV_MAX
# define IOV_MAX 1024
#endif
/* fs_buf, fs_bufvec */
typedef struct {
size_t len;
uint8_t *data;
} fs_buf;
VECTOR_GENERATE(fs_bufvec, fs_buf);
/* buffer helpers */
warn_unused_result
static inline bool
fs_load_be32(const uint8_t **buf, size_t *len, uint32_t *val)
{
uint32_t be32_val;
if (*len < sizeof(be32_val))
return false;
memmove(&be32_val, *buf, sizeof(be32_val));
*val = ntohl(be32_val);
*len -= sizeof(be32_val);
*buf += sizeof(be32_val);
return true;
}
warn_unused_result
static inline bool
fs_store_be32(uint8_t **buf, size_t *len, const uint32_t val)
{
uint32_t be32_val;
be32_val = ntohl(val);
if (*len < sizeof(be32_val))
return false;
memmove(*buf, &be32_val, sizeof(be32_val));
*len -= sizeof(be32_val);
*buf += sizeof(be32_val);
return true;
}
warn_unused_result
static inline bool
fs_load_bytes(uint8_t *bytes, size_t len_bytes,
const uint8_t **buf, size_t *len)
{
if (*len < len_bytes)
return false;
memmove(bytes, *buf, len_bytes);
*len -= len_bytes;
*buf += len_bytes;
return true;
}
warn_unused_result
static inline bool
fs_store_bytes(uint8_t **buf, size_t *len,
const uint8_t *bytes, size_t len_bytes)
{
if (*len < len_bytes)
return false;
memmove(*buf, bytes, len_bytes);
*len -= len_bytes;
*buf += len_bytes;
return true;
}
/* rdwr */
struct fstrm_rdwr_ops {
fstrm_rdwr_destroy_func destroy;
fstrm_rdwr_open_func open;
fstrm_rdwr_close_func close;
fstrm_rdwr_read_func read;
fstrm_rdwr_write_func write;
};
struct fstrm_rdwr {
struct fstrm_rdwr_ops ops;
void *obj;
bool opened;
};
fstrm_res
fstrm__rdwr_read_control_frame(struct fstrm_rdwr *,
struct fstrm_control *,
fstrm_control_type *,
const bool with_escape);
fstrm_res
fstrm__rdwr_read_control(struct fstrm_rdwr *,
struct fstrm_control **,
fstrm_control_type wanted_type);
fstrm_res
fstrm__rdwr_write_control_frame(struct fstrm_rdwr *,
const struct fstrm_control *);
fstrm_res
fstrm__rdwr_write_control(struct fstrm_rdwr *,
fstrm_control_type type,
const fs_buf *content_type);
/* time */
bool fstrm__get_best_monotonic_clock_gettime(clockid_t *);
bool fstrm__get_best_monotonic_clock_pthread(clockid_t *);
bool fstrm__get_best_monotonic_clocks(clockid_t *clkid_gettime,
clockid_t *clkid_pthread,
char **errstr_out);
int fstrm__pthread_cond_timedwait(clockid_t, pthread_cond_t *, pthread_mutex_t *, unsigned);
/* queue */
#ifdef MY_HAVE_MEMORY_BARRIERS
extern const struct my_queue_ops my_queue_mb_ops;
#endif
extern const struct my_queue_ops my_queue_mutex_ops;
#endif /* FSTRM_PRIVATE_H */
fstrm-0.2.0/fstrm/control.c 0000644 0001750 0001750 00000027527 12330751177 012567 0000000 0000000 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "fstrm-private.h"
struct fstrm_control {
fstrm_control_type type;
fs_bufvec *content_types;
};
const char *
fstrm_control_type_to_str(fstrm_control_type type)
{
switch (type) {
case FSTRM_CONTROL_ACCEPT:
return "FSTRM_CONTROL_ACCEPT";
case FSTRM_CONTROL_START:
return "FSTRM_CONTROL_START";
case FSTRM_CONTROL_STOP:
return "FSTRM_CONTROL_STOP";
case FSTRM_CONTROL_READY:
return "FSTRM_CONTROL_READY";
case FSTRM_CONTROL_FINISH:
return "FSTRM_CONTROL_FINISH";
default:
return "FSTRM_CONTROL_UNKNOWN";
}
}
const char *
fstrm_control_field_type_to_str(fstrm_control_field f_type)
{
switch (f_type) {
case FSTRM_CONTROL_FIELD_CONTENT_TYPE:
return "FSTRM_CONTROL_FIELD_CONTENT_TYPE";
default:
return "FSTRM_CONTROL_FIELD_UNKNOWN";
}
}
struct fstrm_control *
fstrm_control_init(void)
{
struct fstrm_control *c;
c = my_calloc(1, sizeof(*c));
c->content_types = fs_bufvec_init(1);
return c;
}
void
fstrm_control_destroy(struct fstrm_control **c)
{
if (*c != NULL) {
fstrm_control_reset(*c);
fs_bufvec_destroy(&(*c)->content_types);
my_free(*c);
}
}
void
fstrm_control_reset(struct fstrm_control *c)
{
for (size_t i = 0; i < fs_bufvec_size(c->content_types); i++) {
fs_buf buf = fs_bufvec_value(c->content_types, i);
my_free(buf.data);
}
fs_bufvec_reset(c->content_types);
c->type = 0;
}
fstrm_res
fstrm_control_get_type(const struct fstrm_control *c, fstrm_control_type *type)
{
switch (c->type) {
case FSTRM_CONTROL_ACCEPT: /* FALLTHROUGH */
case FSTRM_CONTROL_START: /* FALLTHROUGH */
case FSTRM_CONTROL_STOP: /* FALLTHROUGH */
case FSTRM_CONTROL_READY: /* FALLTHROUGH */
case FSTRM_CONTROL_FINISH:
*type = c->type;
return fstrm_res_success;
default:
return fstrm_res_failure;
}
}
fstrm_res
fstrm_control_set_type(struct fstrm_control *c, fstrm_control_type type)
{
switch (type) {
case FSTRM_CONTROL_ACCEPT: /* FALLTHROUGH */
case FSTRM_CONTROL_START: /* FALLTHROUGH */
case FSTRM_CONTROL_STOP: /* FALLTHROUGH */
case FSTRM_CONTROL_READY: /* FALLTHROUGH */
case FSTRM_CONTROL_FINISH:
c->type = type;
return fstrm_res_success;
default:
return fstrm_res_failure;
}
}
fstrm_res
fstrm_control_get_num_field_content_type(const struct fstrm_control *c,
size_t *n_content_type)
{
*n_content_type = fs_bufvec_size(c->content_types);
switch (c->type) {
case FSTRM_CONTROL_STOP: /* FALLTHROUGH */
case FSTRM_CONTROL_FINISH: /* FALLTHROUGH */
/*
* STOP and FINISH frames may not have any content type fields.
*/
*n_content_type = 0;
break;
case FSTRM_CONTROL_START:
/* START frames may not have more than one content type field. */
if (*n_content_type > 1)
*n_content_type = 1;
break;
default:
break;
}
return fstrm_res_success;
}
fstrm_res
fstrm_control_get_field_content_type(const struct fstrm_control *c,
const size_t idx,
const uint8_t **content_type,
size_t *len_content_type)
{
if (idx < fs_bufvec_size(c->content_types)) {
fs_buf buf = fs_bufvec_value(c->content_types, idx);
*content_type = buf.data;
*len_content_type = buf.len;
return fstrm_res_success;
}
return fstrm_res_failure;
}
fstrm_res
fstrm_control_add_field_content_type(struct fstrm_control *c,
const uint8_t *content_type,
size_t len_content_type)
{
fs_buf ctype;
ctype.len = len_content_type;
ctype.data = my_malloc(ctype.len);
memcpy(ctype.data, content_type, ctype.len);
fs_bufvec_add(c->content_types, ctype);
return fstrm_res_success;
}
fstrm_res
fstrm_control_match_field_content_type(const struct fstrm_control *c,
const uint8_t *match,
const size_t len_match)
{
fstrm_res res;
size_t n_ctype = 0;
/*
* STOP and FINISH frames don't have a content type. They never match.
*/
if (c->type == FSTRM_CONTROL_STOP || c->type == FSTRM_CONTROL_FINISH)
return fstrm_res_failure;
res = fstrm_control_get_num_field_content_type(c, &n_ctype);
if (res != fstrm_res_success)
return res;
if (n_ctype == 0) {
/* Control frame doesn't set any content type. */
return fstrm_res_success;
} else {
/*
* The content type must match one of the control frame's
* content types.
*/
if (match == NULL) {
/*
* The control frame has at least one content type set,
* which cannot match an unset content type.
*/
return fstrm_res_failure;
}
for (size_t idx = 0; idx < n_ctype; idx++) {
/*
* Check against all the content types in the control
* frame.
*/
const uint8_t *content_type = NULL;
size_t len_content_type = 0;
res = fstrm_control_get_field_content_type(c, idx,
&content_type, &len_content_type);
if (res != fstrm_res_success)
return res;
if (len_content_type != len_match)
continue;
if (memcmp(content_type, match, len_match) == 0) {
/* Exact match. */
return fstrm_res_success;
}
}
}
return fstrm_res_failure;
}
fstrm_res
fstrm_control_decode(struct fstrm_control *c,
const void *control_frame,
size_t len_control_frame,
const uint32_t flags)
{
const uint8_t *buf = control_frame;
size_t len = len_control_frame;
uint32_t val;
fstrm_control_reset(c);
if (flags & FSTRM_CONTROL_FLAG_WITH_HEADER) {
/* Read the outer frame length. */
if (!fs_load_be32(&buf, &len, &val))
return fstrm_res_failure;
/* The outer frame length must be zero, since this is a control frame. */
if (val != 0)
return fstrm_res_failure;
/* Read the control frame length. */
if (!fs_load_be32(&buf, &len, &val))
return fstrm_res_failure;
/* Enforce maximum control frame size. */
if (val > FSTRM_CONTROL_FRAME_LENGTH_MAX)
return fstrm_res_failure;
/*
* Require that the control frame length matches the number of
* bytes remaining in 'buf'.
*/
if (val != len)
return fstrm_res_failure;
} else {
/* Enforce maximum control frame size. */
if (len_control_frame > FSTRM_CONTROL_FRAME_LENGTH_MAX)
return fstrm_res_failure;
}
/* Read the control frame type. */
if (!fs_load_be32(&buf, &len, &val))
return fstrm_res_failure;
switch (val) {
case FSTRM_CONTROL_ACCEPT: /* FALLTHROUGH */
case FSTRM_CONTROL_START: /* FALLTHROUGH */
case FSTRM_CONTROL_STOP: /* FALLTHROUGH */
case FSTRM_CONTROL_READY: /* FALLTHROUGH */
case FSTRM_CONTROL_FINISH:
c->type = (fstrm_control_type) val;
break;
default:
return fstrm_res_failure;
}
/* Read any control frame fields. */
while (len > 0) {
/* Read the control frame field type. */
if (!fs_load_be32(&buf, &len, &val))
return fstrm_res_failure;
switch (val) {
case FSTRM_CONTROL_FIELD_CONTENT_TYPE: {
fs_buf c_type;
/* Read the length of the "Content Type" payload. */
if (!fs_load_be32(&buf, &len, &val))
return fstrm_res_failure;
c_type.len = val;
/*
* Sanity check the length field. It cannot be larger
* than 'len', the number of bytes remaining in 'buf'.
*/
if (c_type.len > len)
return fstrm_res_failure;
/* Enforce limit on "Content Type" payload length. */
if (c_type.len > FSTRM_CONTROL_FIELD_CONTENT_TYPE_LENGTH_MAX)
return fstrm_res_failure;
/* Read the "Content Type" payload. */
c_type.data = my_malloc(c_type.len);
if (!fs_load_bytes(c_type.data, c_type.len, &buf, &len))
{
my_free(c_type.data);
return fstrm_res_failure;
}
/* Insert the "Content Type" field. */
fs_bufvec_add(c->content_types, c_type);
break;
}
default:
return fstrm_res_failure;
}
}
/* Enforce limits on the number of "Content Type" fields. */
const size_t n_ctype = fs_bufvec_size(c->content_types);
switch (c->type) {
case FSTRM_CONTROL_START:
if (n_ctype > 1)
return fstrm_res_failure;
break;
case FSTRM_CONTROL_STOP:
/* FALLTHROUGH */
case FSTRM_CONTROL_FINISH:
if (n_ctype > 0)
return fstrm_res_failure;
break;
case FSTRM_CONTROL_ACCEPT:
/* FALLTHROUGH */
case FSTRM_CONTROL_READY:
/* FALLTHROUGH */
default:
break;
}
return fstrm_res_success;
}
fstrm_res
fstrm_control_encoded_size(const struct fstrm_control *c,
size_t *len_control_frame,
const uint32_t flags)
{
size_t len = 0;
if (flags & FSTRM_CONTROL_FLAG_WITH_HEADER) {
/* Escape: 32-bit BE integer. */
len += sizeof(uint32_t);
/* Frame length: 32-bit BE integer. */
len += sizeof(uint32_t);
}
/* Control type: 32-bit BE integer. */
len += sizeof(uint32_t);
/* "Content Type" fields. */
for (size_t i = 0; i < fs_bufvec_size(c->content_types); i++) {
/* Do not add "Content Type" fields to STOP or FINISH frames. */
if (c->type == FSTRM_CONTROL_STOP ||
c->type == FSTRM_CONTROL_FINISH)
{
break;
}
fs_buf c_type = fs_bufvec_value(c->content_types, i);
/* FSTRM_CONTROL_FIELD_CONTENT_TYPE: 32-bit BE integer. */
len += sizeof(uint32_t);
/* Length of the "Content Type" string: 32-bit BE integer. */
len += sizeof(uint32_t);
/* Enforce limit on "Content Type" payload length. */
if (c_type.len > FSTRM_CONTROL_FIELD_CONTENT_TYPE_LENGTH_MAX)
return fstrm_res_failure;
/* The "Content Type" payload. */
len += c_type.len;
/* Only add one "Content Type" field to START frames. */
if (c->type == FSTRM_CONTROL_START)
break;
}
/* Sanity check the overall length. */
if (len > FSTRM_CONTROL_FRAME_LENGTH_MAX)
return fstrm_res_failure;
*len_control_frame = len;
return fstrm_res_success;
}
fstrm_res
fstrm_control_encode(const struct fstrm_control *c,
void *control_frame,
size_t *len_control_frame,
const uint32_t flags)
{
fstrm_res res;
size_t encoded_size;
/* Calculate the size of the control frame. */
res = fstrm_control_encoded_size(c, &encoded_size, flags);
if (res != fstrm_res_success)
return res;
/*
* The caller must have provided a large enough buffer to serialize the
* control frame.
*/
if (*len_control_frame < encoded_size)
return fstrm_res_failure;
/*
* Now actually serialize the control frame.
*/
size_t len = encoded_size;
uint8_t *buf = control_frame;
if (flags & FSTRM_CONTROL_FLAG_WITH_HEADER) {
/* Escape: 32-bit BE integer. Zero. */
if (!fs_store_be32(&buf, &len, 0))
return fstrm_res_failure;
/*
* Frame length: 32-bit BE integer.
*
* This does not include the length of the escape frame or the length
* of the frame length field itself, so subtract 2*4 bytes from the
* total length.
*/
if (!fs_store_be32(&buf, &len, encoded_size - 2 * sizeof(uint32_t)))
return fstrm_res_failure;
}
/* Control type: 32-bit BE integer. */
if (!fs_store_be32(&buf, &len, c->type))
return fstrm_res_failure;
/* "Content Type" fields. */
for (size_t i = 0; i < fs_bufvec_size(c->content_types); i++) {
/* Do not add "Content Type" fields to STOP or FINISH frames. */
if (c->type == FSTRM_CONTROL_STOP ||
c->type == FSTRM_CONTROL_FINISH)
{
break;
}
fs_buf c_type = fs_bufvec_value(c->content_types, i);
/* FSTRM_CONTROL_FIELD_CONTENT_TYPE: 32-bit BE integer. */
if (!fs_store_be32(&buf, &len, FSTRM_CONTROL_FIELD_CONTENT_TYPE))
return fstrm_res_failure;
/* Length of the "Content Type" payload: 32-bit BE integer. */
if (!fs_store_be32(&buf, &len, c_type.len))
return fstrm_res_failure;
/* The "Content Type" string itself. */
if (!fs_store_bytes(&buf, &len, c_type.data, c_type.len))
return fstrm_res_failure;
/* Only add one "Content Type" field to START frames. */
if (c->type == FSTRM_CONTROL_START)
break;
}
*len_control_frame = encoded_size;
return fstrm_res_success;
}
fstrm-0.2.0/fstrm/file.c 0000644 0001750 0001750 00000007365 12330751177 012024 0000000 0000000 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "fstrm-private.h"
struct fstrm_file_options {
char *file_path;
};
struct fstrm__file {
FILE *fp;
char *file_path;
char file_mode[2];
};
struct fstrm_file_options *
fstrm_file_options_init(void)
{
return my_calloc(1, sizeof(struct fstrm_file_options));
}
void
fstrm_file_options_destroy(struct fstrm_file_options **fopt)
{
if (*fopt != NULL) {
my_free((*fopt)->file_path);
my_free(*fopt);
}
}
void
fstrm_file_options_set_file_path(struct fstrm_file_options *fopt,
const char *file_path)
{
my_free(fopt->file_path);
if (file_path != NULL)
fopt->file_path = my_strdup(file_path);
}
static fstrm_res
fstrm__file_op_open(void *obj)
{
struct fstrm__file *f = obj;
if (f->fp == NULL && f->file_path != NULL) {
f->fp = fopen(f->file_path, f->file_mode);
if (f->fp == NULL)
return fstrm_res_failure;
return fstrm_res_success;
}
return fstrm_res_failure;
}
static fstrm_res
fstrm__file_op_close(void *obj)
{
struct fstrm__file *f = obj;
if (f->fp != NULL) {
FILE *fp = f->fp;
f->fp = NULL;
if (fclose(fp) != 0)
return fstrm_res_failure;
return fstrm_res_success;
}
return fstrm_res_failure;
}
static fstrm_res
fstrm__file_op_read(void *obj, void *data, size_t count)
{
struct fstrm__file *f = obj;
if (likely(f->fp != NULL)) {
if (likely(fread(data, count, 1, f->fp) == 1)) {
return fstrm_res_success;
} else {
if (ferror(f->fp))
return fstrm_res_failure;
if (feof(f->fp))
return fstrm_res_stop;
}
}
return fstrm_res_failure;
}
static fstrm_res
fstrm__file_op_write(void *obj, const struct iovec *iov, int iovcnt) {
struct fstrm__file *f = obj;
if (unlikely(f->fp == NULL))
return fstrm_res_failure;
for (int idx = 0; idx < iovcnt; idx++) {
if (unlikely(fwrite(iov[idx].iov_base, iov[idx].iov_len, 1, f->fp) != 1)) {
(void)fstrm__file_op_close(f);
return fstrm_res_failure;
}
}
return fstrm_res_success;
}
static fstrm_res
fstrm__file_op_destroy(void *obj)
{
struct fstrm__file *f = obj;
my_free(f->file_path);
my_free(f);
return fstrm_res_success;
}
static struct fstrm_rdwr *
fstrm__file_init(const struct fstrm_file_options *fopt, const char file_mode)
{
struct fstrm__file *f;
struct fstrm_rdwr *rdwr;
if (fopt->file_path == NULL)
return NULL;
f = my_calloc(1, sizeof(*f));
f->file_path = my_strdup(fopt->file_path);
f->file_mode[0] = file_mode;
f->file_mode[1] = '\0';
rdwr = fstrm_rdwr_init(f);
fstrm_rdwr_set_destroy(rdwr, fstrm__file_op_destroy);
fstrm_rdwr_set_open(rdwr, fstrm__file_op_open);
fstrm_rdwr_set_close(rdwr, fstrm__file_op_close);
return rdwr;
}
struct fstrm_reader *
fstrm_file_reader_init(const struct fstrm_file_options *fopt,
const struct fstrm_reader_options *ropt)
{
struct fstrm_rdwr *rdwr = fstrm__file_init(fopt, 'r');
if (!rdwr)
return NULL;
fstrm_rdwr_set_read(rdwr, fstrm__file_op_read);
return fstrm_reader_init(ropt, &rdwr);
}
struct fstrm_writer *
fstrm_file_writer_init(const struct fstrm_file_options *fopt,
const struct fstrm_writer_options *wopt)
{
struct fstrm_rdwr *rdwr = fstrm__file_init(fopt, 'w');
if (!rdwr)
return NULL;
fstrm_rdwr_set_write(rdwr, fstrm__file_op_write);
return fstrm_writer_init(wopt, &rdwr);
}
fstrm-0.2.0/fstrm/iothr.c 0000644 0001750 0001750 00000036417 12413062007 012217 0000000 0000000 /*
* Copyright (c) 2013-2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "fstrm-private.h"
static void *fstrm__iothr_thr(void *);
struct fstrm_iothr_options {
unsigned buffer_hint;
unsigned flush_timeout;
unsigned input_queue_size;
unsigned num_input_queues;
unsigned output_queue_size;
unsigned queue_notify_threshold;
unsigned reopen_interval;
fstrm_iothr_queue_model queue_model;
};
static const struct fstrm_iothr_options default_fstrm_iothr_options = {
.buffer_hint = FSTRM_IOTHR_BUFFER_HINT_DEFAULT,
.flush_timeout = FSTRM_IOTHR_FLUSH_TIMEOUT_DEFAULT,
.input_queue_size = FSTRM_IOTHR_INPUT_QUEUE_SIZE_DEFAULT,
.num_input_queues = FSTRM_IOTHR_NUM_INPUT_QUEUES_DEFAULT,
.output_queue_size = FSTRM_IOTHR_OUTPUT_QUEUE_SIZE_DEFAULT,
.queue_model = FSTRM_IOTHR_QUEUE_MODEL_DEFAULT,
.queue_notify_threshold = FSTRM_IOTHR_QUEUE_NOTIFY_THRESHOLD_DEFAULT,
.reopen_interval = FSTRM_IOTHR_REOPEN_INTERVAL_DEFAULT,
};
struct fstrm_iothr_queue {
struct my_queue *q;
};
struct fstrm__iothr_queue_entry {
/* The deallocation callback. */
void (*free_func)(void *, void *);
void *free_data;
/* The actual payload bytes, allocated by the caller. */
void *data;
/* Number of bytes in 'data'. */
uint32_t len_data;
};
struct fstrm_iothr {
/* The I/O thread. */
pthread_t thr;
/* Copy of options. supplied by caller. */
struct fstrm_iothr_options opt;
/* Queue implementation. */
const struct my_queue_ops *queue_ops;
/* Writer. */
struct fstrm_writer *writer;
/* Whether the writer is opened or not. */
bool opened;
/* Last time the writer's 'open' method was called. */
time_t last_open_attempt;
/* Allocated array of input queues, size opt.num_input_queues. */
struct fstrm_iothr_queue *queues;
/* Whether the I/O thread is shutting down. */
volatile bool shutting_down;
/* Optimal clockid_t's. */
clockid_t clkid_gettime;
clockid_t clkid_pthread;
/*
* Conditional variable and lock, used by producer thread
* (fstrm_iothr_submit) to signal sleeping I/O thread that the low
* watermark (opt.queue_notify_threshold) has been reached.
*/
pthread_cond_t cv;
pthread_mutex_t cv_lock;
/* Used to return unique queues from fstrm_iothr_get_queue(). */
pthread_mutex_t get_queue_lock;
unsigned get_queue_idx;
/* Output queue. */
unsigned outq_idx;
struct iovec *outq_iov;
struct fstrm__iothr_queue_entry *outq_entries;
unsigned outq_nbytes;
};
struct fstrm_iothr_options *
fstrm_iothr_options_init(void)
{
struct fstrm_iothr_options *opt;
opt = my_malloc(sizeof(*opt));
memmove(opt, &default_fstrm_iothr_options, sizeof(*opt));
return opt;
}
void
fstrm_iothr_options_destroy(struct fstrm_iothr_options **opt)
{
if (*opt != NULL)
my_free(*opt);
}
fstrm_res
fstrm_iothr_options_set_buffer_hint(struct fstrm_iothr_options *opt,
unsigned buffer_hint)
{
if (buffer_hint < FSTRM_IOTHR_BUFFER_HINT_MIN ||
buffer_hint > FSTRM_IOTHR_BUFFER_HINT_MAX)
{
return fstrm_res_failure;
}
opt->buffer_hint = buffer_hint;
return fstrm_res_success;
}
fstrm_res
fstrm_iothr_options_set_flush_timeout(struct fstrm_iothr_options *opt,
unsigned flush_timeout)
{
if (flush_timeout < FSTRM_IOTHR_FLUSH_TIMEOUT_MIN ||
flush_timeout > FSTRM_IOTHR_FLUSH_TIMEOUT_MAX)
{
return fstrm_res_failure;
}
opt->flush_timeout = flush_timeout;
return fstrm_res_success;
}
fstrm_res
fstrm_iothr_options_set_input_queue_size(struct fstrm_iothr_options *opt,
unsigned input_queue_size)
{
if (input_queue_size < FSTRM_IOTHR_INPUT_QUEUE_SIZE_MIN ||
input_queue_size > FSTRM_IOTHR_INPUT_QUEUE_SIZE_MAX ||
input_queue_size & 1)
{
return fstrm_res_failure;
}
opt->input_queue_size = input_queue_size;
return fstrm_res_success;
}
fstrm_res
fstrm_iothr_options_set_num_input_queues(struct fstrm_iothr_options *opt,
unsigned num_input_queues)
{
if (num_input_queues < FSTRM_IOTHR_NUM_INPUT_QUEUES_MIN)
return fstrm_res_failure;
opt->num_input_queues = num_input_queues;
return fstrm_res_success;
}
fstrm_res
fstrm_iothr_options_set_output_queue_size(struct fstrm_iothr_options *opt,
unsigned output_queue_size)
{
if (output_queue_size < FSTRM_IOTHR_OUTPUT_QUEUE_SIZE_MIN ||
output_queue_size > FSTRM_IOTHR_OUTPUT_QUEUE_SIZE_MAX)
{
return fstrm_res_failure;
}
opt->output_queue_size = output_queue_size;
return fstrm_res_success;
}
fstrm_res
fstrm_iothr_options_set_queue_model(struct fstrm_iothr_options *opt,
fstrm_iothr_queue_model queue_model)
{
if (queue_model != FSTRM_IOTHR_QUEUE_MODEL_SPSC &&
queue_model != FSTRM_IOTHR_QUEUE_MODEL_MPSC)
{
return fstrm_res_failure;
}
opt->queue_model = queue_model;
return fstrm_res_success;
}
fstrm_res
fstrm_iothr_options_set_queue_notify_threshold(struct fstrm_iothr_options *opt,
unsigned queue_notify_threshold)
{
if (queue_notify_threshold < FSTRM_IOTHR_QUEUE_NOTIFY_THRESHOLD_MIN)
return fstrm_res_failure;
opt->queue_notify_threshold = queue_notify_threshold;
return fstrm_res_success;
}
fstrm_res
fstrm_iothr_options_set_reopen_interval(struct fstrm_iothr_options *opt,
unsigned reopen_interval)
{
if (reopen_interval < FSTRM_IOTHR_REOPEN_INTERVAL_MIN ||
reopen_interval > FSTRM_IOTHR_REOPEN_INTERVAL_MAX)
{
return fstrm_res_failure;
}
opt->reopen_interval = reopen_interval;
return fstrm_res_success;
}
struct fstrm_iothr *
fstrm_iothr_init(const struct fstrm_iothr_options *opt,
struct fstrm_writer **writer)
{
struct fstrm_iothr *iothr = NULL;
int res;
pthread_condattr_t ca;
/* Initialize fstrm_iothr and copy options. */
iothr = my_calloc(1, sizeof(*iothr));
if (opt == NULL)
opt = &default_fstrm_iothr_options;
memmove(&iothr->opt, opt, sizeof(iothr->opt));
/*
* Some platforms have a ridiculously low IOV_MAX, literally the lowest
* value even allowed by POSIX, which is lower than our conservative
* FSTRM_IOTHR_OUTPUT_QUEUE_SIZE_DEFAULT. Accomodate these platforms by
* silently clamping output_queue_size to IOV_MAX.
*/
if (iothr->opt.output_queue_size > IOV_MAX)
iothr->opt.output_queue_size = IOV_MAX;
/*
* Set the queue implementation.
*
* The memory barrier based queue implementation is the only one of our
* queue implementations that supports SPSC, so if it is not available,
* use the mutex based queue implementation instead. The mutex
* implementation is technically MPSC, but MPSC is strictly stronger
* than SPSC.
*/
if (iothr->opt.queue_model == FSTRM_IOTHR_QUEUE_MODEL_SPSC) {
#ifdef MY_HAVE_MEMORY_BARRIERS
iothr->queue_ops = &my_queue_mb_ops;
#else
iothr->queue_ops = &my_queue_mutex_ops;
#endif
} else {
iothr->queue_ops = &my_queue_mutex_ops;
}
/* Detect best clocks. */
if (!fstrm__get_best_monotonic_clocks(&iothr->clkid_gettime,
&iothr->clkid_pthread,
NULL))
{
goto fail;
}
/* Initialize the input queues. */
iothr->queues = my_calloc(iothr->opt.num_input_queues,
sizeof(struct fstrm_iothr_queue));
for (size_t i = 0; i < iothr->opt.num_input_queues; i++) {
iothr->queues[i].q = iothr->queue_ops->init(iothr->opt.input_queue_size,
sizeof(struct fstrm__iothr_queue_entry));
if (iothr->queues[i].q == NULL)
goto fail;
}
/* Initialize the output queue. */
iothr->outq_iov = my_calloc(iothr->opt.output_queue_size,
sizeof(struct iovec));
iothr->outq_entries = my_calloc(iothr->opt.output_queue_size,
sizeof(struct fstrm__iothr_queue_entry));
/* Initialize the condition variable. */
res = pthread_condattr_init(&ca);
assert(res == 0);
res = pthread_condattr_setclock(&ca, iothr->clkid_pthread);
assert(res == 0);
res = pthread_cond_init(&iothr->cv, &ca);
assert(res == 0);
res = pthread_condattr_destroy(&ca);
assert(res == 0);
/* Initialize the mutex protecting the condition variable. */
res = pthread_mutex_init(&iothr->cv_lock, NULL);
assert(res == 0);
/* Initialize the mutex protecting fstrm_iothr_get_queue(). */
res = pthread_mutex_init(&iothr->get_queue_lock, NULL);
assert(res == 0);
/* Take the caller's writer. */
iothr->writer = *writer;
*writer = NULL;
/* Start the I/O thread. */
res = pthread_create(&iothr->thr, NULL, fstrm__iothr_thr, iothr);
assert(res == 0);
return iothr;
fail:
fstrm_iothr_destroy(&iothr);
return NULL;
}
static inline void
fstrm__iothr_queue_entry_free_bytes(struct fstrm__iothr_queue_entry *entry)
{
if (entry->free_func != NULL)
entry->free_func(entry->data, entry->free_data);
}
static void
fstrm__iothr_free_queues(struct fstrm_iothr *iothr)
{
size_t i;
for (i = 0; i < iothr->opt.num_input_queues; i++) {
struct my_queue *queue;
struct fstrm__iothr_queue_entry entry;
queue = iothr->queues[i].q;
while (iothr->queue_ops->remove(queue, &entry, NULL))
fstrm__iothr_queue_entry_free_bytes(&entry);
iothr->queue_ops->destroy(&queue);
}
my_free(iothr->queues);
}
void
fstrm_iothr_destroy(struct fstrm_iothr **iothr)
{
if (*iothr != NULL) {
/*
* Signal the I/O thread that a shutdown is in progress.
* This waits for the I/O thread to finish.
*/
(*iothr)->shutting_down = true;
pthread_cond_signal(&(*iothr)->cv);
pthread_join((*iothr)->thr, NULL);
/* Destroy the writer by calling its 'destroy' method. */
(void)fstrm_writer_destroy(&(*iothr)->writer);
/* Cleanup our allocations. */
fstrm__iothr_free_queues(*iothr);
my_free((*iothr)->outq_iov);
my_free((*iothr)->outq_entries);
my_free(*iothr);
}
}
struct fstrm_iothr_queue *
fstrm_iothr_get_input_queue(struct fstrm_iothr *iothr)
{
struct fstrm_iothr_queue *q = NULL;
pthread_mutex_lock(&iothr->get_queue_lock);
if (iothr->get_queue_idx < iothr->opt.num_input_queues) {
q = &iothr->queues[iothr->get_queue_idx];
iothr->get_queue_idx++;
}
pthread_mutex_unlock(&iothr->get_queue_lock);
return q;
}
struct fstrm_iothr_queue *
fstrm_iothr_get_input_queue_idx(struct fstrm_iothr *iothr, size_t idx)
{
struct fstrm_iothr_queue *q = NULL;
if (idx < iothr->opt.num_input_queues)
q = &iothr->queues[idx];
return q;
}
void
fstrm_free_wrapper(void *data,
void *free_data __attribute__((__unused__)))
{
free(data);
}
fstrm_res
fstrm_iothr_submit(struct fstrm_iothr *iothr, struct fstrm_iothr_queue *ioq,
void *data, size_t len,
void (*free_func)(void *, void *), void *free_data)
{
unsigned space = 0;
struct fstrm__iothr_queue_entry entry;
if (unlikely(iothr->shutting_down))
return fstrm_res_failure;
if (unlikely(len < 1 || len >= UINT32_MAX || data == NULL))
return fstrm_res_invalid;
entry.data = data;
entry.len_data = (uint32_t) len;
entry.free_func = free_func;
entry.free_data = free_data;
if (likely(len > 0) && iothr->queue_ops->insert(ioq->q, &entry, &space)) {
if (space == iothr->opt.queue_notify_threshold)
pthread_cond_signal(&iothr->cv);
return fstrm_res_success;
} else {
return fstrm_res_again;
}
}
static void
fstrm__iothr_close(struct fstrm_iothr *iothr)
{
if (iothr->opened) {
iothr->opened = false;
fstrm_writer_close(iothr->writer);
}
}
static void
fstrm__iothr_flush_output(struct fstrm_iothr *iothr)
{
fstrm_res res;
/* Do the actual write. */
if (likely(iothr->opened && iothr->outq_idx > 0)) {
res = fstrm_writer_writev(iothr->writer, iothr->outq_iov,
iothr->outq_idx);
if (res != fstrm_res_success)
fstrm__iothr_close(iothr);
}
/* Perform the deferred deallocations. */
for (unsigned i = 0; i < iothr->outq_idx; i++)
fstrm__iothr_queue_entry_free_bytes(&iothr->outq_entries[i]);
/* Zero counters and indices. */
iothr->outq_idx = 0;
iothr->outq_nbytes = 0;
}
static void
fstrm__iothr_maybe_flush_output(struct fstrm_iothr *iothr, size_t nbytes)
{
assert(iothr->outq_idx <= iothr->opt.output_queue_size);
if (iothr->outq_idx > 0) {
if (iothr->outq_idx >= iothr->opt.output_queue_size ||
iothr->outq_nbytes + nbytes >= iothr->opt.buffer_hint)
{
/*
* If the output queue is full, or there are more than
* 'buffer_hint' bytes of data ready to be sent, flush
* the output.
*/
fstrm__iothr_flush_output(iothr);
}
}
}
static void
fstrm__iothr_process_queue_entry(struct fstrm_iothr *iothr,
struct fstrm__iothr_queue_entry *entry)
{
if (likely(iothr->opened)) {
size_t nbytes = sizeof(uint32_t) + entry->len_data;
fstrm__iothr_maybe_flush_output(iothr, nbytes);
/* Copy the entry to the array of outstanding queue entries. */
iothr->outq_entries[iothr->outq_idx] = *entry;
/* Add an iovec for the entry. */
iothr->outq_iov[iothr->outq_idx].iov_base = (void *)entry->data;
iothr->outq_iov[iothr->outq_idx].iov_len = (size_t)entry->len_data;
/* Increment the number of output queue entries. */
iothr->outq_idx++;
/* There are now nbytes more data waiting to be sent. */
iothr->outq_nbytes += nbytes;
} else {
/* Writer is closed, just discard the payload. */
fstrm__iothr_queue_entry_free_bytes(entry);
}
}
static unsigned
fstrm__iothr_process_queues(struct fstrm_iothr *iothr)
{
struct fstrm__iothr_queue_entry entry;
unsigned total = 0;
/*
* Remove input queue entries from each thread's circular queue, and
* add them to our output queue.
*/
for (unsigned i = 0; i < iothr->opt.num_input_queues; i++) {
if (iothr->queue_ops->remove(iothr->queues[i].q, &entry, NULL)) {
fstrm__iothr_process_queue_entry(iothr, &entry);
total++;
}
}
return total;
}
static fstrm_res
fstrm__iothr_open(struct fstrm_iothr *iothr)
{
fstrm_res res;
res = fstrm_writer_open(iothr->writer);
if (res == fstrm_res_success)
iothr->opened = true;
else
iothr->opened = false;
return res;
}
static void
fstrm__iothr_maybe_open(struct fstrm_iothr *iothr)
{
/* If we're already connected, there's nothing to do. */
if (likely(iothr->opened))
return;
int rv;
time_t since;
struct timespec ts;
/* Check if the reopen interval has expired yet. */
rv = clock_gettime(iothr->clkid_gettime, &ts);
assert(rv == 0);
since = ts.tv_sec - iothr->last_open_attempt;
if (since < (time_t) iothr->opt.reopen_interval)
return;
/* Attempt to open the transport. */
iothr->last_open_attempt = ts.tv_sec;
if (fstrm__iothr_open(iothr) != fstrm_res_success)
return;
}
static void
fstrm__iothr_thr_setup(void)
{
sigset_t set;
int s;
sigemptyset(&set);
sigaddset(&set, SIGPIPE);
s = pthread_sigmask(SIG_BLOCK, &set, NULL);
assert(s == 0);
}
static void *
fstrm__iothr_thr(void *arg)
{
struct fstrm_iothr *iothr = (struct fstrm_iothr *)arg;
fstrm__iothr_thr_setup();
fstrm__iothr_maybe_open(iothr);
for (;;) {
int res;
unsigned count;
if (unlikely(iothr->shutting_down)) {
while (fstrm__iothr_process_queues(iothr));
fstrm__iothr_flush_output(iothr);
fstrm__iothr_close(iothr);
break;
}
fstrm__iothr_maybe_open(iothr);
count = fstrm__iothr_process_queues(iothr);
if (count != 0)
continue;
res = fstrm__pthread_cond_timedwait(iothr->clkid_pthread,
&iothr->cv, &iothr->cv_lock,
iothr->opt.flush_timeout);
if (res == ETIMEDOUT)
fstrm__iothr_flush_output(iothr);
}
return NULL;
}
fstrm-0.2.0/fstrm/rdwr.c 0000644 0001750 0001750 00000014447 12330751177 012062 0000000 0000000 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "fstrm-private.h"
struct fstrm_rdwr *
fstrm_rdwr_init(void *obj)
{
struct fstrm_rdwr *rdwr;
rdwr = my_calloc(1, sizeof(*rdwr));
rdwr->obj = obj;
return rdwr;
}
fstrm_res
fstrm_rdwr_destroy(struct fstrm_rdwr **rdwr)
{
fstrm_res res = fstrm_res_success;
if (*rdwr != NULL) {
if ((*rdwr)->ops.destroy != NULL)
res = (*rdwr)->ops.destroy((*rdwr)->obj);
my_free(*rdwr);
}
return res;
}
fstrm_res
fstrm_rdwr_open(struct fstrm_rdwr *rdwr)
{
fstrm_res res;
if (unlikely(rdwr->ops.open == NULL))
return fstrm_res_failure;
res = rdwr->ops.open(rdwr->obj);
if (res == fstrm_res_success)
rdwr->opened = true;
return res;
}
fstrm_res
fstrm_rdwr_close(struct fstrm_rdwr *rdwr)
{
if (unlikely(rdwr->ops.close == NULL))
return fstrm_res_failure;
if (rdwr->opened) {
rdwr->opened = false;
return rdwr->ops.close(rdwr->obj);
}
return fstrm_res_success;
}
fstrm_res
fstrm_rdwr_read(struct fstrm_rdwr *rdwr, void *data, size_t count)
{
fstrm_res res;
/* If the rdwr is not opened, it cannot be read from. */
if (unlikely(!rdwr->opened))
return fstrm_res_failure;
/* This should never be called on a rdwr without a read method. */
if (unlikely(rdwr->ops.read == NULL))
return fstrm_res_failure;
/*
* Invoke the rdwr's read method. If this fails we need to clean up by
* invoking the close method.
*/
res = rdwr->ops.read(rdwr->obj, data, count);
if (unlikely(res != fstrm_res_success))
(void)fstrm_rdwr_close(rdwr);
return res;
}
fstrm_res
fstrm_rdwr_write(struct fstrm_rdwr *rdwr, const struct iovec *iov, int iovcnt)
{
fstrm_res res;
/* If the rdwr is not opened, it cannot be written to. */
if (unlikely(!rdwr->opened))
return fstrm_res_failure;
/* This should never be called on a rdwr without a write method. */
if (unlikely(rdwr->ops.write == NULL))
return fstrm_res_failure;
/*
* Invoke the rdwr's write method. If this fails we need to clean up by
* invoking the close method.
*/
res = rdwr->ops.write(rdwr->obj, iov, iovcnt);
if (unlikely(res != fstrm_res_success))
(void)fstrm_rdwr_close(rdwr);
return res;
}
void
fstrm_rdwr_set_destroy(struct fstrm_rdwr *rdwr,
fstrm_rdwr_destroy_func fn)
{
rdwr->ops.destroy = fn;
}
void
fstrm_rdwr_set_open(struct fstrm_rdwr *rdwr,
fstrm_rdwr_open_func fn)
{
rdwr->ops.open = fn;
}
void
fstrm_rdwr_set_close(struct fstrm_rdwr *rdwr,
fstrm_rdwr_close_func fn)
{
rdwr->ops.close = fn;
}
void
fstrm_rdwr_set_read(struct fstrm_rdwr *rdwr,
fstrm_rdwr_read_func fn)
{
rdwr->ops.read = fn;
}
void
fstrm_rdwr_set_write(struct fstrm_rdwr *rdwr,
fstrm_rdwr_write_func fn)
{
rdwr->ops.write = fn;
}
fstrm_res
fstrm__rdwr_read_control_frame(struct fstrm_rdwr *rdwr,
struct fstrm_control *control,
fstrm_control_type *type,
const bool with_escape)
{
const uint32_t flags = 0;
uint32_t tmp;
fstrm_res res;
if (with_escape) {
/* Read the escape sequence. */
res = fstrm_rdwr_read(rdwr, &tmp, sizeof(tmp));
if (res != fstrm_res_success)
return res;
if (ntohl(tmp) != 0)
return fstrm_res_failure;
}
/* Read the control frame length. */
res = fstrm_rdwr_read(rdwr, &tmp, sizeof(tmp));
if (res != fstrm_res_success)
return res;
const size_t len_control_frame = ntohl(tmp);
/* Sanity check the control frame length. */
if (len_control_frame > FSTRM_CONTROL_FRAME_LENGTH_MAX)
return fstrm_res_failure;
/* Read the control frame. */
uint8_t control_frame[len_control_frame];
res = fstrm_rdwr_read(rdwr, control_frame, sizeof(control_frame));
if (res != fstrm_res_success)
return res;
/* Decode the control frame. */
assert(control != NULL);
res = fstrm_control_decode(control,
control_frame, len_control_frame,
flags);
if (res != fstrm_res_success)
return res;
/* Get the type. */
if (type != NULL) {
res = fstrm_control_get_type(control, type);
if (res != fstrm_res_success)
return res;
}
return fstrm_res_success;
}
fstrm_res
fstrm__rdwr_read_control(struct fstrm_rdwr *rdwr,
struct fstrm_control **control,
fstrm_control_type wanted_type)
{
fstrm_res res;
fstrm_control_type actual_type;
if (*control == NULL)
*control = fstrm_control_init();
res = fstrm__rdwr_read_control_frame(rdwr, *control, &actual_type, true);
if (res != fstrm_res_success)
return res;
if (actual_type != wanted_type)
return fstrm_res_failure;
return fstrm_res_success;
}
fstrm_res
fstrm__rdwr_write_control_frame(struct fstrm_rdwr *rdwr,
const struct fstrm_control *control)
{
const uint32_t flags = FSTRM_CONTROL_FLAG_WITH_HEADER;
size_t len_control_frame = 0;
fstrm_res res;
/* Calculate the length of the control frame. */
res = fstrm_control_encoded_size(control, &len_control_frame, flags);
if (res != fstrm_res_success)
return res;
/* Serialize the control frame. */
uint8_t control_frame[len_control_frame];
res = fstrm_control_encode(control, control_frame, &len_control_frame, flags);
if (res != fstrm_res_success)
return res;
/* Write the control frame. */
struct iovec control_iov = {
.iov_base = (void *) &control_frame[0],
.iov_len = len_control_frame,
};
return fstrm_rdwr_write(rdwr, &control_iov, 1);
}
fstrm_res
fstrm__rdwr_write_control(struct fstrm_rdwr *rdwr,
fstrm_control_type type,
const fs_buf *content_type)
{
fstrm_res res = fstrm_res_failure;
struct fstrm_control *control = fstrm_control_init();
res = fstrm_control_set_type(control, type);
if (res != fstrm_res_success)
goto out;
if (content_type != NULL && content_type->data != NULL) {
res = fstrm_control_add_field_content_type(control,
content_type->data, content_type->len);
if (res != fstrm_res_success)
goto out;
}
res = fstrm__rdwr_write_control_frame(rdwr, control);
out:
fstrm_control_destroy(&control);
return res;
}
fstrm-0.2.0/fstrm/reader.c 0000644 0001750 0001750 00000024760 12423526312 012337 0000000 0000000 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "fstrm-private.h"
#include "libmy/ubuf.h"
typedef enum {
fstrm_reader_state_opening,
fstrm_reader_state_opened,
fstrm_reader_state_closing,
fstrm_reader_state_closed,
fstrm_reader_state_failed,
} fstrm_reader_state;
struct fstrm_reader {
fstrm_reader_state state;
fs_bufvec *content_types;
size_t max_frame_size;
struct fstrm_rdwr *rdwr;
struct fstrm_control *control_start;
struct fstrm_control *control_stop;
struct fstrm_control *control_ready;
struct fstrm_control *control_accept;
struct fstrm_control *control_tmp;
ubuf *buf;
};
struct fstrm_reader_options {
fs_bufvec *content_types;
size_t max_frame_size;
};
static const struct fstrm_reader_options default_fstrm_reader_options = {
.max_frame_size = FSTRM_READER_MAX_FRAME_SIZE_DEFAULT,
};
struct fstrm_reader_options *
fstrm_reader_options_init(void)
{
struct fstrm_reader_options *ropt;
ropt = my_calloc(1, sizeof(*ropt));
memmove(ropt, &default_fstrm_reader_options, sizeof(*ropt));
return ropt;
}
void
fstrm_reader_options_destroy(struct fstrm_reader_options **ropt)
{
if (*ropt != NULL) {
if ((*ropt)->content_types != NULL) {
for (size_t i = 0; i < fs_bufvec_size((*ropt)->content_types); i++) {
fs_buf ctype = fs_bufvec_value((*ropt)->content_types, i);
my_free(ctype.data);
}
fs_bufvec_destroy(&(*ropt)->content_types);
}
my_free(*ropt);
}
}
fstrm_res
fstrm_reader_options_add_content_type(
struct fstrm_reader_options *ropt,
const void *content_type,
size_t len_content_type)
{
if (len_content_type > FSTRM_CONTROL_FIELD_CONTENT_TYPE_LENGTH_MAX)
return fstrm_res_failure;
if (ropt->content_types == NULL)
ropt->content_types = fs_bufvec_init(1);
fs_buf ctype = {
.len = len_content_type,
.data = my_malloc(len_content_type),
};
memmove(ctype.data, content_type, ctype.len);
fs_bufvec_add(ropt->content_types, ctype);
return fstrm_res_success;
}
fstrm_res
fstrm_reader_options_set_max_frame_size(
struct fstrm_reader_options *ropt,
size_t max_frame_size)
{
if (max_frame_size < FSTRM_CONTROL_FRAME_LENGTH_MAX ||
max_frame_size > UINT32_MAX - 1)
{
return fstrm_res_failure;
}
ropt->max_frame_size = max_frame_size;
return fstrm_res_success;
}
struct fstrm_reader *
fstrm_reader_init(const struct fstrm_reader_options *ropt,
struct fstrm_rdwr **rdwr)
{
if (ropt == NULL)
ropt = &default_fstrm_reader_options;
if ((*rdwr)->ops.read == NULL)
return NULL;
struct fstrm_reader *r = my_calloc(1, sizeof(*r));
r->rdwr = *rdwr;
*rdwr = NULL;
r->content_types = fs_bufvec_init(1);
r->buf = ubuf_init(FSTRM_CONTROL_FRAME_LENGTH_MAX);
/* Copy options. */
r->max_frame_size = ropt->max_frame_size;
if (ropt->content_types != NULL) {
for (size_t i = 0; i < fs_bufvec_size(ropt->content_types); i++) {
fs_buf ctype = fs_bufvec_value(ropt->content_types, i);
fs_buf ctype_copy = {
.len = ctype.len,
.data = my_malloc(ctype.len),
};
memmove(ctype_copy.data, ctype.data, ctype.len);
fs_bufvec_add(r->content_types, ctype_copy);
}
}
r->state = fstrm_reader_state_opening;
return r;
}
fstrm_res
fstrm_reader_destroy(struct fstrm_reader **r)
{
fstrm_res res = fstrm_res_failure;
if (*r != NULL) {
if ((*r)->state == fstrm_reader_state_opened ||
(*r)->state == fstrm_reader_state_closing)
{
res = fstrm_reader_close(*r);
}
fstrm_control_destroy(&(*r)->control_tmp);
fstrm_control_destroy(&(*r)->control_accept);
fstrm_control_destroy(&(*r)->control_ready);
fstrm_control_destroy(&(*r)->control_stop);
fstrm_control_destroy(&(*r)->control_start);
fstrm_rdwr_destroy(&(*r)->rdwr);
ubuf_destroy(&(*r)->buf);
for (size_t i = 0; i < fs_bufvec_size((*r)->content_types); i++) {
fs_buf ctype = fs_bufvec_value((*r)->content_types, i);
my_free(ctype.data);
}
fs_bufvec_destroy(&(*r)->content_types);
my_free(*r);
}
return res;
}
static fstrm_res
fstrm__reader_open_unidirectional(struct fstrm_reader *r)
{
fstrm_res res;
/* Read the START frame. */
res = fstrm__rdwr_read_control(r->rdwr, &r->control_start, FSTRM_CONTROL_START);
if (res != fstrm_res_success)
return res;
/* Match the START content type. */
bool match = true;
for (size_t i = 0; i < fs_bufvec_size(r->content_types); i++) {
fs_buf ctype = fs_bufvec_value(r->content_types, i);
res = fstrm_control_match_field_content_type(r->control_start,
ctype.data, ctype.len);
if (res == fstrm_res_success) {
match = true;
break;
} else {
match = false;
continue;
}
}
if (!match) {
/* Unwanted content type. */
return fstrm_res_failure;
}
r->state = fstrm_reader_state_opened;
return fstrm_res_success;
}
static fstrm_res
fstrm__reader_open_bidirectional(struct fstrm_reader *r)
{
fstrm_res res;
/* Read the READY frame. */
res = fstrm__rdwr_read_control(r->rdwr, &r->control_ready, FSTRM_CONTROL_READY);
if (res != fstrm_res_success)
return res;
/* Initialize the ACCEPT frame. */
if (r->control_accept != NULL)
fstrm_control_reset(r->control_accept);
else
r->control_accept = fstrm_control_init();
res = fstrm_control_set_type(r->control_accept, FSTRM_CONTROL_ACCEPT);
if (res != fstrm_res_success)
return res;
/* Add matching content types from the READY frame to the ACCEPT frame. */
for (size_t i = 0; i < fs_bufvec_size(r->content_types); i++) {
fs_buf ctype = fs_bufvec_value(r->content_types, i);
res = fstrm_control_match_field_content_type(r->control_ready,
ctype.data, ctype.len);
if (res == fstrm_res_success) {
res = fstrm_control_add_field_content_type(r->control_accept,
ctype.data, ctype.len);
if (res != fstrm_res_success)
return res;
}
}
/* Write the ACCEPT frame. */
res = fstrm__rdwr_write_control_frame(r->rdwr, r->control_accept);
if (res != fstrm_res_success)
return res;
/* Do the rest of the open. */
return fstrm__reader_open_unidirectional(r);
}
fstrm_res
fstrm_reader_open(struct fstrm_reader *r)
{
fstrm_res res;
if (r->state == fstrm_reader_state_opened)
return fstrm_res_failure;
res = fstrm_rdwr_open(r->rdwr);
if (res != fstrm_res_success)
return res;
if (r->rdwr->ops.write != NULL) {
/* Bi-directional transport. */
res = fstrm__reader_open_bidirectional(r);
if (res != fstrm_res_success)
return res;
} else {
/* Uni-directional transport. */
res = fstrm__reader_open_unidirectional(r);
if (res != fstrm_res_success)
return res;
}
r->state = fstrm_reader_state_opened;
return fstrm_res_success;
}
static inline fstrm_res
fstrm__reader_read_be32(struct fstrm_reader *r, uint32_t *out)
{
fstrm_res res;
uint32_t tmp;
res = fstrm_rdwr_read(r->rdwr, &tmp, sizeof(tmp));
if (unlikely(res != fstrm_res_success))
return res;
*out = ntohl(tmp);
return fstrm_res_success;
}
static fstrm_res
fstrm__reader_next_data(struct fstrm_reader *r,
const uint8_t **data, size_t *len_data)
{
fstrm_res res = fstrm_res_failure;
for (;;) {
uint32_t len;
/* Read the frame length. */
res = fstrm__reader_read_be32(r, &len);
if (unlikely(res != fstrm_res_success))
goto fail;
if (likely(len != 0)) {
/* This is a data frame. */
/* Enforce maximum frame size. */
if (unlikely(len > r->max_frame_size))
goto fail;
/* Read the data frame. */
ubuf_clip(r->buf, 0);
ubuf_reserve(r->buf, len);
res = fstrm_rdwr_read(r->rdwr, ubuf_ptr(r->buf), len);
if (unlikely(res != fstrm_res_success))
goto fail;
/* Export the data frame to the caller. */
*data = ubuf_ptr(r->buf);
*len_data = len;
return fstrm_res_success;
} else if (len == 0) {
/* This is a control frame. */
/* Read the control frame. */
fstrm_control_type type;
if (r->control_tmp == NULL)
r->control_tmp = fstrm_control_init();
res = fstrm__rdwr_read_control_frame(r->rdwr,
r->control_tmp, &type, false);
if (unlikely(res != fstrm_res_success))
goto fail;
/* Break if this is the end of the stream. */
if (type == FSTRM_CONTROL_STOP) {
/*
(void)fstrm__rdwr_write_control(r->rdwr,
FSTRM_CONTROL_FINISH, NULL);
*/
r->state = fstrm_reader_state_closing;
r->control_stop = r->control_tmp;
r->control_tmp = NULL;
return fstrm_res_stop;
}
}
}
fail:
r->state = fstrm_reader_state_failed;
return res;
}
static fstrm_res
fstrm__reader_maybe_open(struct fstrm_reader *r)
{
fstrm_res res;
if (unlikely(r->state == fstrm_reader_state_opening)) {
res = fstrm_reader_open(r);
if (res != fstrm_res_success)
return res;
}
return fstrm_res_success;
}
fstrm_res
fstrm_reader_close(struct fstrm_reader *r)
{
fstrm_res res;
if (r->state != fstrm_reader_state_opened &&
r->state != fstrm_reader_state_closing)
{
return fstrm_res_failure;
}
r->state = fstrm_reader_state_closed;
if (r->rdwr->ops.write != NULL) {
/* For bi-directional transports, write the FINISH frame. */
res = fstrm__rdwr_write_control(r->rdwr, FSTRM_CONTROL_FINISH, NULL);
if (res != fstrm_res_success) {
(void)fstrm_rdwr_close(r->rdwr);
return res;
}
}
return fstrm_rdwr_close(r->rdwr);
}
fstrm_res
fstrm_reader_read(struct fstrm_reader *r, const uint8_t **data, size_t *len_data)
{
fstrm_res res;
res = fstrm__reader_maybe_open(r);
if (res != fstrm_res_success)
return res;
if (likely(r->state == fstrm_reader_state_opened)) {
return fstrm__reader_next_data(r, data, len_data);
} else if (r->state == fstrm_reader_state_closed) {
return fstrm_res_stop;
}
return fstrm_res_failure;
}
fstrm_res
fstrm_reader_get_control(struct fstrm_reader *r,
fstrm_control_type type,
const struct fstrm_control **control)
{
fstrm_res res;
res = fstrm__reader_maybe_open(r);
if (res != fstrm_res_success)
return res;
*control = NULL;
switch (type) {
case FSTRM_CONTROL_START:
*control = r->control_start;
break;
case FSTRM_CONTROL_STOP:
*control = r->control_stop;
break;
case FSTRM_CONTROL_READY:
*control = r->control_ready;
break;
case FSTRM_CONTROL_ACCEPT:
*control = r->control_accept;
break;
case FSTRM_CONTROL_FINISH:
/* FALLTHROUGH */
default:
return fstrm_res_failure;
}
return fstrm_res_success;
}
fstrm-0.2.0/fstrm/time.c 0000644 0001750 0001750 00000006026 12413063311 012020 0000000 0000000 /*
* Copyright (c) 2013-2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "fstrm-private.h"
bool
fstrm__get_best_monotonic_clock_pthread(clockid_t *c)
{
bool res = false;
int rc;
struct timespec ts;
pthread_condattr_t ca;
rc = pthread_condattr_init(&ca);
assert(rc == 0);
#if defined(CLOCK_MONOTONIC_COARSE)
*c = CLOCK_MONOTONIC_COARSE;
if (clock_gettime(*c, &ts) == 0 &&
pthread_condattr_setclock(&ca, *c) == 0)
{
res = true;
goto out;
}
#endif
#if defined(CLOCK_MONOTONIC_RAW)
*c = CLOCK_MONOTONIC_RAW;
if (clock_gettime(*c, &ts) == 0 &&
pthread_condattr_setclock(&ca, *c) == 0)
{
res = true;
goto out;
}
#endif
#if defined(CLOCK_MONOTONIC_FAST)
*c = CLOCK_MONOTONIC_FAST;
if (clock_gettime(*c, &ts) == 0 &&
pthread_condattr_setclock(&ca, *c) == 0)
{
res = true;
goto out;
}
#endif
#if defined(CLOCK_MONOTONIC)
*c = CLOCK_MONOTONIC;
if (clock_gettime(*c, &ts) == 0 &&
pthread_condattr_setclock(&ca, *c) == 0)
{
res = true;
goto out;
}
#endif
out:
rc = pthread_condattr_destroy(&ca);
assert(rc == 0);
return res;
}
bool
fstrm__get_best_monotonic_clock_gettime(clockid_t *c)
{
struct timespec ts;
#if defined(CLOCK_MONOTONIC_COARSE)
if (!clock_gettime((*c) = CLOCK_MONOTONIC_COARSE, &ts))
return true;
#endif
#if defined(CLOCK_MONOTONIC_RAW)
if (!clock_gettime((*c) = CLOCK_MONOTONIC_RAW, &ts))
return true;
#endif
#if defined(CLOCK_MONOTONIC_FAST)
if (!clock_gettime((*c) = CLOCK_MONOTONIC_FAST, &ts))
return true;
#endif
#if defined(CLOCK_MONOTONIC)
if (!clock_gettime((*c) = CLOCK_MONOTONIC, &ts))
return true;
#endif
return false;
}
bool
fstrm__get_best_monotonic_clocks(clockid_t *clkid_gettime,
clockid_t *clkid_pthread,
char **err)
{
if (clkid_gettime != NULL &&
!fstrm__get_best_monotonic_clock_gettime(clkid_gettime))
{
if (err != NULL)
*err = my_strdup("no clock available for clock_gettime()");
return false;
}
if (clkid_pthread != NULL &&
!fstrm__get_best_monotonic_clock_pthread(clkid_pthread))
{
if (err != NULL)
*err = my_strdup("no clock available for pthread_cond_timedwait()");
return false;
}
return true;
}
int
fstrm__pthread_cond_timedwait(clockid_t clock_id,
pthread_cond_t *cond,
pthread_mutex_t *mutex,
unsigned seconds)
{
int res;
struct timespec ts;
res = clock_gettime(clock_id, &ts);
assert(res == 0);
ts.tv_sec += seconds;
pthread_mutex_lock(mutex);
res = pthread_cond_timedwait(cond, mutex, &ts);
pthread_mutex_unlock(mutex);
return res;
}
fstrm-0.2.0/fstrm/unix_writer.c 0000644 0001750 0001750 00000012316 12330751177 013454 0000000 0000000 /*
* Copyright (c) 2013-2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include
#include
#include
#include
#include
#include "fstrm-private.h"
struct fstrm_unix_writer_options {
char *socket_path;
};
struct fstrm__unix_writer {
bool connected;
int fd;
struct sockaddr_un sa;
};
struct fstrm_unix_writer_options *
fstrm_unix_writer_options_init(void)
{
return my_calloc(1, sizeof(struct fstrm_unix_writer_options));
}
void
fstrm_unix_writer_options_destroy(struct fstrm_unix_writer_options **uwopt)
{
if (*uwopt != NULL) {
my_free((*uwopt)->socket_path);
my_free(*uwopt);
}
}
void
fstrm_unix_writer_options_set_socket_path(
struct fstrm_unix_writer_options *uwopt,
const char *socket_path)
{
my_free(uwopt->socket_path);
if (socket_path != NULL)
uwopt->socket_path = my_strdup(socket_path);
}
static fstrm_res
fstrm__unix_writer_op_open(void *obj)
{
struct fstrm__unix_writer *w = obj;
/* Nothing to do if the socket is already connected. */
if (w->connected)
return fstrm_res_success;
/* Open an AF_UNIX socket. Request socket close-on-exec if available. */
#if defined(SOCK_CLOEXEC)
w->fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (w->fd < 0 && errno == EINVAL)
w->fd = socket(AF_UNIX, SOCK_STREAM, 0);
#else
w->fd = socket(AF_UNIX, SOCK_STREAM, 0);
#endif
if (w->fd < 0)
return fstrm_res_failure;
/*
* Request close-on-exec if available. There is nothing that can be done
* if the F_SETFD call to fcntl() fails, so don't bother checking the
* return value.
*
* https://lwn.net/Articles/412131/
* [ Ghosts of Unix past, part 2: Conflated designs ]
*/
#if defined(FD_CLOEXEC)
int flags = fcntl(w->fd, F_GETFD, 0);
if (flags != -1) {
flags |= FD_CLOEXEC;
(void) fcntl(w->fd, F_SETFD, flags);
}
#endif
#if defined(SO_NOSIGPIPE)
/*
* Ugh, no signals, please!
*
* https://lwn.net/Articles/414618/
* [ Ghosts of Unix past, part 3: Unfixable designs ]
*/
static const int on = 1;
if (setsockopt(w->fd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on)) != 0) {
close(w->fd);
return fstrm_res_failure;
}
#endif
/* Connect the AF_UNIX socket. */
if (connect(w->fd, (struct sockaddr *) &w->sa, sizeof(w->sa)) < 0) {
close(w->fd);
return fstrm_res_failure;
}
w->connected = true;
return fstrm_res_success;
}
static fstrm_res
fstrm__unix_writer_op_close(void *obj)
{
struct fstrm__unix_writer *w = obj;
if (w->connected) {
w->connected = false;
if (close(w->fd) != 0)
return fstrm_res_failure;
return fstrm_res_success;
}
return fstrm_res_failure;
}
static fstrm_res
fstrm__unix_writer_op_read(void *obj, void *buf, size_t nbytes)
{
struct fstrm__unix_writer *w = obj;
if (likely(w->connected)) {
if (read_bytes(w->fd, buf, nbytes))
return fstrm_res_success;
}
return fstrm_res_failure;
}
static fstrm_res
fstrm__unix_writer_op_write(void *obj, const struct iovec *iov, int iovcnt)
{
struct fstrm__unix_writer *w = obj;
size_t nbytes = 0;
ssize_t written = 0;
int cur = 0;
struct msghdr msg = {
.msg_iov = (struct iovec *) /* Grr! */ iov,
.msg_iovlen = iovcnt,
};
if (unlikely(!w->connected))
return fstrm_res_failure;
for (int i = 0; i < iovcnt; i++)
nbytes += iov[i].iov_len;
for (;;) {
do {
written = sendmsg(w->fd, &msg, MSG_NOSIGNAL);
} while (written == -1 && errno == EINTR);
if (written == -1)
return fstrm_res_failure;
if (cur == 0 && written == (ssize_t) nbytes)
return fstrm_res_success;
while (written >= (ssize_t) msg.msg_iov[cur].iov_len)
written -= msg.msg_iov[cur++].iov_len;
if (cur == iovcnt)
return fstrm_res_success;
msg.msg_iov[cur].iov_base = (void *)
((char *) msg.msg_iov[cur].iov_base + written);
msg.msg_iov[cur].iov_len -= written;
}
}
static fstrm_res
fstrm__unix_writer_op_destroy(void *obj)
{
struct fstrm__unix_writer *w = obj;
my_free(w);
return fstrm_res_success;
}
struct fstrm_writer *
fstrm_unix_writer_init(const struct fstrm_unix_writer_options *uwopt,
const struct fstrm_writer_options *wopt)
{
struct fstrm_rdwr *rdwr;
struct fstrm__unix_writer *uw;
if (uwopt->socket_path == NULL)
return NULL;
if (strlen(uwopt->socket_path) + 1 > sizeof(uw->sa.sun_path))
return NULL;
uw = my_calloc(1, sizeof(*uw));
uw->sa.sun_family = AF_UNIX;
strncpy(uw->sa.sun_path, uwopt->socket_path, sizeof(uw->sa.sun_path) - 1);
rdwr = fstrm_rdwr_init(uw);
fstrm_rdwr_set_destroy(rdwr, fstrm__unix_writer_op_destroy);
fstrm_rdwr_set_open(rdwr, fstrm__unix_writer_op_open);
fstrm_rdwr_set_close(rdwr, fstrm__unix_writer_op_close);
fstrm_rdwr_set_read(rdwr, fstrm__unix_writer_op_read);
fstrm_rdwr_set_write(rdwr, fstrm__unix_writer_op_write);
return fstrm_writer_init(wopt, &rdwr);
}
fstrm-0.2.0/fstrm/writer.c 0000644 0001750 0001750 00000024772 12373460613 012421 0000000 0000000 /*
* Copyright (c) 2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "fstrm-private.h"
#define FSTRM__WRITER_IOVEC_SIZE 256
typedef enum {
fstrm_writer_state_opening,
fstrm_writer_state_opened,
fstrm_writer_state_closed,
fstrm_writer_state_failed,
} fstrm_writer_state;
struct fstrm_writer_options {
fs_bufvec *content_types;
};
struct fstrm_writer {
fstrm_writer_state state;
fs_bufvec *content_types;
struct fstrm_rdwr *rdwr;
struct fstrm_control *control_ready;
struct fstrm_control *control_accept;
struct fstrm_control *control_start;
struct fstrm_control *control_finish;
struct iovec *iovecs;
uint32_t *be32_lens;
};
struct fstrm_writer_options *
fstrm_writer_options_init(void)
{
return my_calloc(1, sizeof(struct fstrm_writer_options));
}
void
fstrm_writer_options_destroy(struct fstrm_writer_options **wopt)
{
if (*wopt != NULL) {
if ((*wopt)->content_types != NULL) {
for (size_t i = 0; i < fs_bufvec_size((*wopt)->content_types); i++) {
fs_buf ctype = fs_bufvec_value((*wopt)->content_types, i);
my_free(ctype.data);
}
fs_bufvec_destroy(&(*wopt)->content_types);
}
my_free(*wopt);
}
}
fstrm_res
fstrm_writer_options_add_content_type(
struct fstrm_writer_options *wopt,
const void *content_type,
size_t len_content_type)
{
if (len_content_type > FSTRM_CONTROL_FIELD_CONTENT_TYPE_LENGTH_MAX)
return fstrm_res_failure;
if (wopt->content_types == NULL)
wopt->content_types = fs_bufvec_init(1);
fs_buf ctype = {
.len = len_content_type,
.data = my_malloc(len_content_type),
};
memmove(ctype.data, content_type, ctype.len);
fs_bufvec_add(wopt->content_types, ctype);
return fstrm_res_success;
}
struct fstrm_writer *
fstrm_writer_init(const struct fstrm_writer_options *wopt,
struct fstrm_rdwr **rdwr)
{
if ((*rdwr)->ops.write == NULL)
return NULL;
struct fstrm_writer *w = my_calloc(1, sizeof(*w));
w->rdwr = *rdwr;
*rdwr = NULL;
w->content_types = fs_bufvec_init(1);
/* Copy options. */
if (wopt != NULL && wopt->content_types != NULL) {
for (size_t i = 0; i < fs_bufvec_size(wopt->content_types); i++) {
fs_buf ctype = fs_bufvec_value(wopt->content_types, i);
fs_buf ctype_copy = {
.len = ctype.len,
.data = my_malloc(ctype.len)
};
memmove(ctype_copy.data, ctype.data, ctype.len);
fs_bufvec_add(w->content_types, ctype_copy);
}
}
w->iovecs = my_calloc(FSTRM__WRITER_IOVEC_SIZE, sizeof(struct iovec));
w->be32_lens = my_calloc(FSTRM__WRITER_IOVEC_SIZE / 2, sizeof(uint32_t));
w->state = fstrm_writer_state_opening;
return w;
}
fstrm_res
fstrm_writer_destroy(struct fstrm_writer **w)
{
fstrm_res res = fstrm_res_failure;
if (*w != NULL) {
if ((*w)->state == fstrm_writer_state_opened)
res = fstrm_writer_close(*w);
fstrm_control_destroy(&(*w)->control_finish);
fstrm_control_destroy(&(*w)->control_start);
fstrm_control_destroy(&(*w)->control_accept);
fstrm_control_destroy(&(*w)->control_ready);
fstrm_rdwr_destroy(&(*w)->rdwr);
for (size_t i = 0; i < fs_bufvec_size((*w)->content_types); i++) {
fs_buf ctype = fs_bufvec_value((*w)->content_types, i);
my_free(ctype.data);
}
fs_bufvec_destroy(&(*w)->content_types);
my_free((*w)->iovecs);
my_free((*w)->be32_lens);
my_free(*w);
}
return res;
}
static fstrm_res
fstrm__writer_open_bidirectional(struct fstrm_writer *w)
{
fstrm_res res;
/* Initialize the READY frame. */
if (w->control_ready != NULL)
fstrm_control_reset(w->control_ready);
else
w->control_ready = fstrm_control_init();
res = fstrm_control_set_type(w->control_ready, FSTRM_CONTROL_READY);
if (res != fstrm_res_success)
return res;
for (size_t i = 0; i < fs_bufvec_size(w->content_types); i++) {
fs_buf ctype = fs_bufvec_value(w->content_types, i);
res = fstrm_control_add_field_content_type(w->control_ready,
ctype.data, ctype.len);
if (res != fstrm_res_success)
return res;
}
/* Write the READY frame. */
res = fstrm__rdwr_write_control_frame(w->rdwr, w->control_ready);
if (res != fstrm_res_success)
return res;
/* Wait for the ACCEPT frame. */
res = fstrm__rdwr_read_control(w->rdwr, &w->control_accept, FSTRM_CONTROL_ACCEPT);
if (res != fstrm_res_success)
return res;
/* Match the ACCEPT content type. */
bool match = true;
const uint8_t *match_ctype = NULL;
size_t len_match_ctype = 0;
for (size_t i = 0; i < fs_bufvec_size(w->content_types); i++) {
fs_buf ctype = fs_bufvec_value(w->content_types, i);
res = fstrm_control_match_field_content_type(w->control_accept,
ctype.data, ctype.len);
if (res == fstrm_res_success) {
match_ctype = ctype.data;
len_match_ctype = ctype.len;
break;
} else {
match = false;
continue;
}
}
if (!match) {
/* Content type negotiation failed. */
return fstrm_res_failure;
}
/* Initialize the START frame. */
if (w->control_start != NULL)
fstrm_control_reset(w->control_start);
else
w->control_start = fstrm_control_init();
res = fstrm_control_set_type(w->control_start, FSTRM_CONTROL_START);
if (res != fstrm_res_success)
return res;
if (match_ctype != NULL) {
res = fstrm_control_add_field_content_type(w->control_start,
match_ctype, len_match_ctype);
if (res != fstrm_res_success)
return res;
}
/* Write the START frame. */
res = fstrm__rdwr_write_control_frame(w->rdwr, w->control_start);
if (res != fstrm_res_success)
return res;
return fstrm_res_success;
}
static fstrm_res
fstrm__writer_open_unidirectional(struct fstrm_writer *w)
{
fstrm_res res;
/* Initialize the START frame. */
if (w->control_start != NULL)
fstrm_control_reset(w->control_start);
else
w->control_start = fstrm_control_init();
res = fstrm_control_set_type(w->control_start, FSTRM_CONTROL_START);
if (res != fstrm_res_success)
return res;
/* Set the content type. */
if (fs_bufvec_size(w->content_types) > 0) {
fs_buf ctype = fs_bufvec_value(w->content_types, 0);
res = fstrm_control_add_field_content_type(w->control_start,
ctype.data, ctype.len);
if (res != fstrm_res_success)
return res;
}
/* Write the START frame. */
res = fstrm__rdwr_write_control_frame(w->rdwr, w->control_start);
if (res != fstrm_res_success)
return res;
return fstrm_res_success;
}
fstrm_res
fstrm_writer_open(struct fstrm_writer *w)
{
fstrm_res res;
if (w->state == fstrm_writer_state_opened)
return fstrm_res_success;
res = fstrm_rdwr_open(w->rdwr);
if (res != fstrm_res_success)
return res;
if (w->rdwr->ops.read != NULL) {
/* Bi-directional transport. */
res = fstrm__writer_open_bidirectional(w);
if (res != fstrm_res_success)
return res;
} else {
/* Uni-directional transport. */
res = fstrm__writer_open_unidirectional(w);
if (res != fstrm_res_success)
return res;
}
w->state = fstrm_writer_state_opened;
return fstrm_res_success;
}
static fstrm_res
fstrm__writer_maybe_open(struct fstrm_writer *w)
{
fstrm_res res;
if (unlikely(w->state == fstrm_writer_state_opening)) {
res = fstrm_writer_open(w);
if (res != fstrm_res_success)
return res;
}
return fstrm_res_success;
}
fstrm_res
fstrm_writer_close(struct fstrm_writer *w)
{
fstrm_res res;
if (w->state != fstrm_writer_state_opened)
return fstrm_res_failure;
/* Write the STOP frame. */
res = fstrm__rdwr_write_control(w->rdwr, FSTRM_CONTROL_STOP, NULL);
if (res != fstrm_res_success) {
(void)fstrm_rdwr_close(w->rdwr);
return res;
}
if (w->rdwr->ops.read != NULL) {
/* For bi-directional transports, wait for the FINISH frame. */
res = fstrm__rdwr_read_control(w->rdwr, &w->control_finish,
FSTRM_CONTROL_FINISH);
if (res != fstrm_res_success) {
(void)fstrm_rdwr_close(w->rdwr);
return res;
}
}
res = fstrm_rdwr_close(w->rdwr);
w->state = fstrm_writer_state_closed;
return res;
}
static fstrm_res
fstrm__writer_write_iov(struct fstrm_writer *w, const struct iovec *iov, int iovcnt)
{
for (int i = 0, iov_idx = 0; i < iovcnt; i++) {
/* Frame length. */
w->be32_lens[i] = htonl(iov[i].iov_len);
w->iovecs[iov_idx].iov_len = sizeof(uint32_t);
w->iovecs[iov_idx].iov_base = (void *) &w->be32_lens[i];
iov_idx += 1;
/* Frame data. */
memcpy(&w->iovecs[iov_idx], &iov[i], sizeof(struct iovec));
iov_idx += 1;
}
return fstrm_rdwr_write(w->rdwr, w->iovecs, 2 * iovcnt);
}
static fstrm_res
fstrm__writer_write_iov_stupid(struct fstrm_writer *w,
const struct iovec *iov, int iovcnt)
{
fstrm_res res;
int iov_max = FSTRM__WRITER_IOVEC_SIZE / 2;
if (iov_max > IOV_MAX)
iov_max = IOV_MAX;
assert(iov_max > 0);
while (iovcnt > 0) {
int iovcnt_to_write = iov_max;
if (iovcnt_to_write > iovcnt)
iovcnt_to_write = iovcnt;
res = fstrm__writer_write_iov(w, iov, iovcnt_to_write);
if (res != fstrm_res_success)
return res;
iov += iovcnt_to_write;
iovcnt -= iovcnt_to_write;
}
return fstrm_res_success;
}
fstrm_res
fstrm_writer_write(struct fstrm_writer *w, const void *data, size_t len_data)
{
struct iovec iov = {
.iov_base = (void *) data,
.iov_len = len_data,
};
return fstrm_writer_writev(w, &iov, 1);
}
fstrm_res
fstrm_writer_writev(struct fstrm_writer *w, const struct iovec *iov, int iovcnt)
{
fstrm_res res;
if (unlikely(iovcnt < 1))
return fstrm_res_success;
res = fstrm__writer_maybe_open(w);
if (res != fstrm_res_success)
return res;
if (likely(w->state == fstrm_writer_state_opened)) {
if (likely((2 * iovcnt) <= FSTRM__WRITER_IOVEC_SIZE))
return fstrm__writer_write_iov(w, iov, iovcnt);
else
return fstrm__writer_write_iov_stupid(w, iov, iovcnt);
}
return fstrm_res_failure;
}
fstrm_res
fstrm_writer_get_control(struct fstrm_writer *w,
fstrm_control_type type,
struct fstrm_control **control)
{
fstrm_res res;
res = fstrm__writer_maybe_open(w);
if (res != fstrm_res_success)
return res;
*control = NULL;
switch (type) {
case FSTRM_CONTROL_ACCEPT:
*control = w->control_accept;
break;
case FSTRM_CONTROL_FINISH:
*control = w->control_finish;
break;
case FSTRM_CONTROL_READY:
*control = w->control_ready;
break;
case FSTRM_CONTROL_START:
*control = w->control_start;
break;
case FSTRM_CONTROL_STOP:
/* FALLTHROUGH */
default:
return fstrm_res_failure;
}
return fstrm_res_success;
}
fstrm-0.2.0/fstrm/libfstrm.sym 0000644 0001750 0001750 00000004734 12342165321 013303 0000000 0000000 LIBFSTRM_0.2.0 {
global:
fstrm_control_add_field_content_type;
fstrm_control_decode;
fstrm_control_destroy;
fstrm_control_encode;
fstrm_control_encoded_size;
fstrm_control_field_type_to_str;
fstrm_control_get_field_content_type;
fstrm_control_get_num_field_content_type;
fstrm_control_get_type;
fstrm_control_init;
fstrm_control_match_field_content_type;
fstrm_control_reset;
fstrm_control_set_type;
fstrm_control_type_to_str;
fstrm_file_options_destroy;
fstrm_file_options_init;
fstrm_file_options_set_file_path;
fstrm_file_reader_init;
fstrm_file_writer_init;
fstrm_free_wrapper;
fstrm_iothr_destroy;
fstrm_iothr_get_input_queue;
fstrm_iothr_get_input_queue_idx;
fstrm_iothr_init;
fstrm_iothr_options_destroy;
fstrm_iothr_options_init;
fstrm_iothr_options_set_buffer_hint;
fstrm_iothr_options_set_flush_timeout;
fstrm_iothr_options_set_input_queue_size;
fstrm_iothr_options_set_num_input_queues;
fstrm_iothr_options_set_output_queue_size;
fstrm_iothr_options_set_queue_model;
fstrm_iothr_options_set_queue_notify_threshold;
fstrm_iothr_options_set_reopen_interval;
fstrm_iothr_submit;
fstrm_rdwr_close;
fstrm_rdwr_destroy;
fstrm_rdwr_init;
fstrm_rdwr_open;
fstrm_rdwr_read;
fstrm_rdwr_set_close;
fstrm_rdwr_set_destroy;
fstrm_rdwr_set_open;
fstrm_rdwr_set_read;
fstrm_rdwr_set_write;
fstrm_rdwr_write;
fstrm_reader_close;
fstrm_reader_destroy;
fstrm_reader_get_control;
fstrm_reader_init;
fstrm_reader_open;
fstrm_reader_options_add_content_type;
fstrm_reader_options_destroy;
fstrm_reader_options_init;
fstrm_reader_options_set_max_frame_size;
fstrm_reader_read;
fstrm_unix_writer_init;
fstrm_unix_writer_options_destroy;
fstrm_unix_writer_options_init;
fstrm_unix_writer_options_set_socket_path;
fstrm_writer_close;
fstrm_writer_destroy;
fstrm_writer_get_control;
fstrm_writer_init;
fstrm_writer_open;
fstrm_writer_options_add_content_type;
fstrm_writer_options_destroy;
fstrm_writer_options_init;
fstrm_writer_write;
fstrm_writer_writev;
local:
*;
};
fstrm-0.2.0/libmy/ 0000755 0001750 0001750 00000000000 12427010215 010753 5 0000000 0000000 fstrm-0.2.0/libmy/my_alloc.h 0000644 0001750 0001750 00000002727 12330751177 012667 0000000 0000000 #ifndef MY_ALLOC_H
#define MY_ALLOC_H
#include
#include
#include
static inline void *
my_calloc(size_t nmemb, size_t size)
{
void *ptr = calloc(nmemb, size);
assert(ptr != NULL);
return (ptr);
}
static inline void *
my_malloc(size_t size)
{
void *ptr = malloc(size);
assert(ptr != NULL);
return (ptr);
}
static inline void *
my_realloc(void *ptr, size_t size)
{
ptr = realloc(ptr, size);
assert(ptr != NULL);
return (ptr);
}
static inline char *
my_strdup(const char *s)
{
char *ptr = strdup(s);
assert(ptr != NULL);
return (ptr);
}
#define my_free(ptr) do { free(ptr); (ptr) = NULL; } while (0)
#if defined(MY_ALLOC_WARN_DEPRECATED)
static inline void *my_calloc_deprecated(size_t, size_t)
__attribute__ ((deprecated("use my_calloc, not calloc")));
static inline void *my_malloc_deprecated(size_t)
__attribute__ ((deprecated("use my_malloc, not malloc")));
static inline void *my_realloc_deprecated(void *, size_t)
__attribute__ ((deprecated("use my_realloc, not realloc")));
static inline void *
my_calloc_deprecated(size_t nmemb, size_t size)
{
return calloc(nmemb, size);
}
static inline void *
my_malloc_deprecated(size_t size)
{
return malloc(size);
}
static inline void *
my_realloc_deprecated(void *ptr, size_t size)
{
return realloc(ptr, size);
}
#define calloc my_calloc_deprecated
#define malloc my_malloc_deprecated
#define realloc my_realloc_deprecated
#endif /* MY_ALLOC_WARN_DEPRECATED */
#endif /* MY_ALLOC_H */
fstrm-0.2.0/libmy/my_memory_barrier.h 0000644 0001750 0001750 00000001063 12330751177 014603 0000000 0000000 #ifndef MY_MEMORY_BARRIER_H
#define MY_MEMORY_BARRIER_H
#if defined(__GNUC__)
# if defined(__x86_64__)
# define MY_HAVE_MEMORY_BARRIERS 1
# define smp_mb() asm volatile("mfence" ::: "memory")
# define smp_rmb() asm volatile("" ::: "memory")
# define smp_wmb() asm volatile("" ::: "memory")
# elif defined(__ia64__)
# define MY_HAVE_MEMORY_BARRIERS 1
# define smp_mb() asm volatile ("mf" ::: "memory")
# define smp_rmb() asm volatile ("mf" ::: "memory")
# define smp_wmb() asm volatile ("mf" ::: "memory")
# endif
#endif
#endif /* MY_MEMORY_BARRIER_H */
fstrm-0.2.0/libmy/my_queue.h 0000644 0001750 0001750 00000005567 12330751177 012726 0000000 0000000 #ifndef MY_QUEUE_H
#define MY_QUEUE_H
#include
/**
* \file
*
* Fixed-size single-producer / single-consumer queue.
*
* This is a generic queue that supports a single producer thread and a
* single consumer thread. The implementation uses a fixed power-of-2 size
* circular buffer.
*
* The my_queue_insert() and my_queue_remove() functions are "non-blocking";
* that is, the policies for queue full / queue empty conditions are left to
* the caller. These functions return a boolean indicating whether the queue
* operation succeeded or not. For example, a producer that spins until an
* element is successfully enqueued might look like:
*
* void *item;
* produce_item(&item);
* while (!my_queue_insert(q, item, NULL));
*
* And a consumer that spins until an element is successfully dequeued
* might look like:
*
* void *item;
* while (!my_queue_remove(q, &item, NULL));
* consume_item(item);
*
* The my_queue_insert() and my_queue_remove() functions take an optional third
* parameter for returning the spaces remaining in the queue or the count of
* elements remaining, respectively. This allows for more complicated
* coordination between producer and consumer, for instance a consumer thread
* that sleeps when the queue is empty and is woken by the producer when it
* adds an element to an empty queue.
*/
struct my_queue;
/**
* Initialize a new queue.
*
* \param[in] num_entries Number of elements in the queue. Must be >=2, and a power-of-2.
* \param[in] size_entry Size in bytes of each queue entry.
* \return Opaque pointer that is NULL on failure or non-NULL on success.
*/
struct my_queue *
my_queue_init(unsigned num_entries, unsigned size_entry);
/**
* Destroy a queue.
*/
void
my_queue_destroy(struct my_queue **q);
/**
* Describe the queue implementation type.
*/
const char *
my_queue_impl_type(void);
/**
* Insert an element into the queue.
*
* \param[in] q Queue object.
* \param[in] elem Element object.
* \param[out] space If non-NULL, pointer to store the number of remaining
* spaces in the queue.
* \return true if the element was inserted into the queue,
* false if the queue is full.
*/
bool
my_queue_insert(struct my_queue *q, void *elem, unsigned *space);
/**
* Remove an element from the queue.
*
* \param[in] q Queue object.
* \param[out] elem Where the element object will be copied.
* \param[out] count If non-NULL, pointer to store the count of elements
* remaining in the queue.
* \return true if an element was removed from the queue,
* false if the queue is empty.
*/
bool
my_queue_remove(struct my_queue *q, void *elem, unsigned *count);
struct my_queue_ops {
struct my_queue *(*init)(unsigned, unsigned);
void (*destroy)(struct my_queue **);
const char *(*impl_type)(void);
bool (*insert)(struct my_queue *, void *, unsigned *);
bool (*remove)(struct my_queue *, void *, unsigned *);
};
#endif /* MY_QUEUE_H */
fstrm-0.2.0/libmy/my_queue_mb.c 0000644 0001750 0001750 00000006125 12330751177 013366 0000000 0000000 /*
* Copyright (c) 2013, 2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "my_memory_barrier.h"
#ifdef MY_HAVE_MEMORY_BARRIERS
#include
#include
#include
#include "my_alloc.h"
#include "my_queue.h"
#define MY_ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
struct my_queue *
my_queue_mb_init(unsigned, unsigned);
void
my_queue_mb_destroy(struct my_queue **);
const char *
my_queue_mb_impl_type(void);
bool
my_queue_mb_insert(struct my_queue *, void *, unsigned *);
bool
my_queue_mb_remove(struct my_queue *, void *, unsigned *);
struct my_queue {
uint8_t *data;
unsigned num_elems;
unsigned sizeof_elem;
unsigned head;
unsigned tail;
};
struct my_queue *
my_queue_mb_init(unsigned num_elems, unsigned sizeof_elem)
{
struct my_queue *q;
if (num_elems < 2 || ((num_elems - 1) & num_elems) != 0)
return (NULL);
q = my_calloc(1, sizeof(*q));
q->num_elems = num_elems;
q->sizeof_elem = sizeof_elem;
q->data = my_calloc(q->num_elems, q->sizeof_elem);
return (q);
}
void
my_queue_mb_destroy(struct my_queue **q)
{
if (*q) {
free((*q)->data);
free(*q);
*q = NULL;
}
}
const char *
my_queue_mb_impl_type(void)
{
return ("memory barrier");
}
static inline unsigned
q_space(unsigned head, unsigned tail, unsigned size)
{
return ((tail - (head + 1)) & (size - 1));
}
static inline unsigned
q_count(unsigned head, unsigned tail, unsigned size)
{
return ((head - tail) & (size - 1));
}
bool
my_queue_mb_insert(struct my_queue *q, void *item, unsigned *pspace)
{
bool res = false;
unsigned head = q->head;
unsigned tail = MY_ACCESS_ONCE(q->tail);
unsigned space = q_space(head, tail, q->num_elems);
if (space >= 1) {
memcpy(&q->data[head * q->sizeof_elem], item, q->sizeof_elem);
smp_wmb();
q->head = (head + 1) & (q->num_elems - 1);
smp_wmb();
res = true;
space--;
}
if (pspace != NULL)
*pspace = space;
return (res);
}
bool
my_queue_mb_remove(struct my_queue *q, void *item, unsigned *pcount)
{
bool res = false;
unsigned head = MY_ACCESS_ONCE(q->head);
unsigned tail = q->tail;
unsigned count = q_count(head, tail, q->num_elems);
if (count >= 1) {
memcpy(item, &q->data[tail * q->sizeof_elem], q->sizeof_elem);
smp_mb();
q->tail = (tail + 1) & (q->num_elems - 1);
res = true;
count--;
}
if (pcount != NULL)
*pcount = count;
return (res);
}
const struct my_queue_ops my_queue_mb_ops = {
.init =
my_queue_mb_init,
.destroy =
my_queue_mb_destroy,
.impl_type =
my_queue_mb_impl_type,
.insert =
my_queue_mb_insert,
.remove =
my_queue_mb_remove,
};
#endif /* MY_HAVE_MEMORY_BARRIERS */
fstrm-0.2.0/libmy/my_queue_mutex.c 0000644 0001750 0001750 00000006665 12330751177 014143 0000000 0000000 /*
* Copyright (c) 2013, 2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include
#include
#include
#include
#include
#include "my_alloc.h"
#include "my_queue.h"
#if defined(__GNUC__)
# define _aligned __attribute__((aligned(64)))
#else
# define _aligned
#endif
struct my_queue {
uint8_t *data;
unsigned num_elems;
unsigned sizeof_elem;
unsigned head;
unsigned tail;
pthread_mutex_t lock _aligned;
};
struct my_queue *
my_queue_mutex_init(unsigned, unsigned);
void
my_queue_mutex_destroy(struct my_queue **);
const char *
my_queue_mutex_impl_type(void);
bool
my_queue_mutex_insert(struct my_queue *, void *, unsigned *);
bool
my_queue_mutex_remove(struct my_queue *, void *, unsigned *);
struct my_queue *
my_queue_mutex_init(unsigned num_elems, unsigned sizeof_elem)
{
struct my_queue *q;
if (num_elems < 2 || ((num_elems - 1) & num_elems) != 0)
return (NULL);
q = my_calloc(1, sizeof(*q));
q->num_elems = num_elems;
q->sizeof_elem = sizeof_elem;
q->data = my_calloc(q->num_elems, q->sizeof_elem);
int rc = pthread_mutex_init(&q->lock, NULL);
assert(rc == 0);
return (q);
}
void
my_queue_mutex_destroy(struct my_queue **q)
{
if (*q) {
pthread_mutex_destroy(&(*q)->lock);
free((*q)->data);
free(*q);
*q = NULL;
}
}
const char *
my_queue_mutex_impl_type(void)
{
return ("pthread mutex");
}
static inline void
q_lock(struct my_queue *q)
{
int rc = pthread_mutex_lock(&q->lock);
assert(rc == 0);
}
static inline void
q_unlock(struct my_queue *q)
{
int rc = pthread_mutex_unlock(&q->lock);
assert(rc == 0);
}
static inline unsigned
q_space(unsigned head, unsigned tail, unsigned size)
{
return ((tail - (head + 1)) & (size - 1));
}
static inline unsigned
q_count(unsigned head, unsigned tail, unsigned size)
{
return ((head - tail) & (size - 1));
}
bool
my_queue_mutex_insert(struct my_queue *q, void *item, unsigned *pspace)
{
q_lock(q);
bool res = false;
unsigned head = q->head;
unsigned tail = q->tail;
unsigned space = q_space(head, tail, q->num_elems);
if (space >= 1) {
memcpy(&q->data[head * q->sizeof_elem], item, q->sizeof_elem);
q->head = (head + 1) & (q->num_elems - 1);
res = true;
space--;
}
q_unlock(q);
if (pspace)
*pspace = space;
return (res);
}
bool
my_queue_mutex_remove(struct my_queue *q, void *item, unsigned *pcount)
{
q_lock(q);
bool res = false;
unsigned head = q->head;
unsigned tail = q->tail;
unsigned count = q_count(head, tail, q->num_elems);
if (count >= 1) {
memcpy(item, &q->data[tail * q->sizeof_elem], q->sizeof_elem);
q->tail = (tail + 1) & (q->num_elems - 1);
res = true;
count--;
}
q_unlock(q);
if (pcount)
*pcount = count;
return (res);
}
const struct my_queue_ops my_queue_mutex_ops = {
.init =
my_queue_mutex_init,
.destroy =
my_queue_mutex_destroy,
.impl_type =
my_queue_mutex_impl_type,
.insert =
my_queue_mutex_insert,
.remove =
my_queue_mutex_remove,
};
fstrm-0.2.0/libmy/read_bytes.h 0000644 0001750 0001750 00000000764 12330751177 013210 0000000 0000000 #ifndef MY_READ_BYTES_H
#define MY_READ_BYTES_H
#include
#include
#include
#include
static inline bool
read_bytes(int fd, uint8_t *buf, size_t bytes_needed)
{
while (bytes_needed > 0) {
ssize_t bytes_read;
bytes_read = read(fd, buf, bytes_needed);
if (bytes_read == -1 && errno == EINTR)
continue;
else if (bytes_read <= 0)
return false;
bytes_needed -= bytes_read;
buf += bytes_read;
}
return true;
}
#endif /* MY_READ_BYTES_H */
fstrm-0.2.0/libmy/ubuf.h 0000644 0001750 0001750 00000004360 12330751177 012024 0000000 0000000 /*
* Copyright (c) 2012 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MY_UBUF_H
#define MY_UBUF_H
#include
#include
#include
#include
#include
#include
#include "vector.h"
VECTOR_GENERATE(ubuf, uint8_t);
static inline ubuf *
ubuf_new(void)
{
return (ubuf_init(64));
}
static inline ubuf *
ubuf_dup_cstr(const char *s)
{
size_t len = strlen(s);
ubuf *u = ubuf_init(len + 1);
ubuf_append(u, (const uint8_t *) s, len);
return (u);
}
static inline void
ubuf_add_cstr(ubuf *u, const char *s)
{
if (ubuf_size(u) > 0 && ubuf_value(u, ubuf_size(u) - 1) == '\x00')
ubuf_clip(u, ubuf_size(u) - 1);
ubuf_append(u, (const uint8_t *) s, strlen(s));
}
static inline void
ubuf_cterm(ubuf *u)
{
if (ubuf_size(u) == 0 ||
(ubuf_size(u) > 0 && ubuf_value(u, ubuf_size(u) - 1) != '\x00'))
{
ubuf_append(u, (const uint8_t *) "\x00", 1);
}
}
static inline char *
ubuf_cstr(ubuf *u)
{
ubuf_cterm(u);
return ((char *) ubuf_data(u));
}
static inline void
ubuf_add_fmt(ubuf *u, const char *fmt, ...)
{
va_list args, args_copy;
int status, needed;
if (ubuf_size(u) > 0 && ubuf_value(u, ubuf_size(u) - 1) == '\x00')
ubuf_clip(u, ubuf_size(u) - 1);
va_start(args, fmt);
va_copy(args_copy, args);
needed = vsnprintf(NULL, 0, fmt, args_copy);
assert(needed >= 0);
va_end(args_copy);
ubuf_reserve(u, ubuf_size(u) + needed + 1);
status = vsnprintf((char *) ubuf_ptr(u), needed + 1, fmt, args);
assert(status >= 0);
ubuf_advance(u, needed);
va_end(args);
}
static inline void
ubuf_rstrip(ubuf *u, char s)
{
if (ubuf_size(u) > 0 &&
ubuf_value(u, ubuf_size(u) - 1) == ((uint8_t) s))
{
ubuf_clip(u, ubuf_size(u) - 1);
}
}
#endif /* MY_UBUF_H */
fstrm-0.2.0/libmy/vector.h 0000644 0001750 0001750 00000011603 12330751177 012363 0000000 0000000 /*
* Copyright (c) 2012-2014 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include
#include "my_alloc.h"
#define VECTOR_GENERATE(name, type) \
typedef struct name##__vector { \
type * _v; \
type * _p; \
size_t _n, _n_alloced, _hint; \
} name; \
__attribute__((unused)) \
static inline name * \
name##_init(unsigned hint) \
{ \
name *vec; \
vec = my_calloc(1, sizeof(name)); \
if (hint == 0) hint = 1; \
vec->_hint = vec->_n_alloced = hint; \
vec->_v = my_malloc(vec->_n_alloced * sizeof(type)); \
vec->_p = &(vec->_v[0]); \
return (vec); \
} \
__attribute__((unused)) \
static inline void \
name##_reinit(unsigned hint, name *vec) \
{ \
if (hint == 0) hint = 1; \
vec->_hint = vec->_n_alloced = hint; \
vec->_n = 0; \
vec->_v = my_malloc(vec->_n_alloced * sizeof(type)); \
vec->_p = &(vec->_v[0]); \
} \
__attribute__((unused)) \
static inline void \
name##_detach(name *vec, type **out, size_t *outsz) \
{ \
*(out) = (vec)->_v; \
*(outsz) = (vec)->_n; \
(vec)->_n = 0; \
(vec)->_n_alloced = (vec)->_hint; \
(vec)->_v = my_malloc((vec)->_n_alloced * sizeof(type)); \
(vec)->_p = &(vec->_v[0]); \
} \
__attribute__((unused)) \
static inline void \
name##_destroy(name **vec) \
{ \
if (*vec) { \
my_free((*vec)->_v); \
my_free((*vec)); \
} \
} \
__attribute__((unused)) \
static inline void \
name##_reserve(name *vec, size_t n_elems) \
{ \
while ((n_elems) > ((vec)->_n_alloced - (vec)->_n)) { \
(vec)->_n_alloced *= 2; \
(vec)->_v = my_realloc((vec)->_v, (vec)->_n_alloced \
* sizeof(type)); \
(vec)->_p = &((vec)->_v[(vec)->_n]); \
} \
} \
__attribute__((unused)) \
static inline void \
name##_add(name *vec, type elem) \
{ \
while ((vec)->_n + 1 > (vec)->_n_alloced) { \
(vec)->_n_alloced *= 2; \
(vec)->_v = my_realloc((vec)->_v, (vec)->_n_alloced \
* sizeof(type)); \
(vec)->_p = &((vec)->_v[(vec)->_n]); \
} \
(vec)->_v[(vec)->_n] = elem; \
(vec)->_n += 1; \
(vec)->_p = &((vec)->_v[(vec)->_n]); \
} \
__attribute__((unused)) \
static inline void \
name##_append(name *vec, type const *elems, size_t n_elems) \
{ \
name##_reserve(vec, n_elems); \
memcpy((vec)->_v + (vec)->_n, elems, (n_elems) * sizeof(type)); \
(vec)->_n += (n_elems); \
(vec)->_p = &((vec)->_v[(vec)->_n]); \
} \
__attribute__((unused)) \
static inline void \
name##_extend(name *vec0, name *vec1) \
{ \
name##_append(vec0, (vec1)->_v, (vec1)->_n); \
} \
__attribute__((unused)) \
static inline void \
name##_reset(name *vec) \
{ \
(vec)->_n = 0; \
if ((vec)->_n_alloced > (vec)->_hint) { \
(vec)->_n_alloced = (vec)->_hint; \
(vec)->_v = my_realloc((vec)->_v, (vec)->_n_alloced \
* sizeof(type)); \
} \
(vec)->_p = &(vec->_v[0]); \
} \
__attribute__((unused)) \
static inline void \
name##_clip(name *vec, size_t n_elems) \
{ \
if (n_elems < (vec)->_n) { \
(vec)->_n = n_elems; \
(vec)->_p = &((vec)->_v[(vec)->_n]); \
} \
} \
__attribute__((unused)) \
static inline size_t \
name##_bytes(name *vec) \
{ \
return ((vec)->_n * sizeof(type)); \
} \
__attribute__((unused)) \
static inline size_t \
name##_size(name *vec) \
{ \
return ((vec)->_n); \
} \
__attribute__((unused)) \
static inline type \
name##_value(name *vec, size_t i) \
{ \
assert(i < (vec)->_n); \
return ((vec)->_v[i]); \
} \
__attribute__((unused)) \
static inline type * \
name##_ptr(name *vec) \
{ \
return ((vec)->_p); \
} \
__attribute__((unused)) \
static inline type * \
name##_data(name *vec) \
{ \
return ((vec)->_v); \
} \
__attribute__((unused)) \
static inline void \
name##_advance(name *vec, size_t x) \
{ \
assert(x <= ((vec)->_n_alloced - (vec)->_n)); \
(vec)->_n += x; \
(vec)->_p = &((vec)->_v[(vec)->_n]); \
}
fstrm-0.2.0/libmy/argv.c 0000644 0001750 0001750 00000251547 12342165401 012020 0000000 0000000 /*
* Generic argv processor...
*
* Copyright 2000 by Gray Watson
*
* This file is part of the argv library.
*
* Permission to use, copy, modify, and distribute this software for
* any purpose and without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies, and that the name of Gray Watson not be used in advertising
* or publicity pertaining to distribution of the document or software
* without specific, written prior permission.
*
* Gray Watson makes no representations about the suitability of the
* software described herein for any purpose. It is provided "as is"
* without express or implied warranty.
*
* The author may be contacted via http://256.com/gray/
*
* $Id: argv.c,v 1.111 2010/02/15 13:34:25 gray Exp $
*/
#include
#include
#include
#include
#include "argv.h"
#include "argv_loc.h"
/* internal routines -- we need this because of recusion */
static void do_list(argv_t *grid, const int arg_c, char **argv,
argv_t **queue_list, int *queue_head_p,
int *queue_tail_p, int *okay_bp);
#define LOC_SNPRINTF(...) (void)snprintf(__VA_ARGS__);
#define SNP_ARG(buf, buf_size) buf, buf_size
/*
* exported variables
*/
/* This is a processed version of argv[0], pre-path removed: /bin/ls -> ls */
char argv_program[PROGRAM_NAME + 1] = "Unknown";
/* A global value of argv from main after argv_process has been called */
char **argv_argv = NULL;
/* A global value of argc from main after argv_process has been called */
int argv_argc = 0;
/* This should be set externally to provide general program help to user */
char *argv_help_string = NULL;
/* This should be set externally to provide version information to the user */
char *argv_version_string = NULL;
/*
* Are we running interactively? This will exit on errors. Set to
* false to return error codes instead.
*/
int argv_interactive = ARGV_TRUE;
/*
* The FILE stream that argv out_puts all its errors. Set to NULL to
* not dump any error messages. Default is stderr.
*/
FILE *argv_error_stream = ERROR_STREAM_INIT;
/*
* This is the error code to exit with when we have a usage error and
* we are in interactive mode.
*/
int argv_error_code = EXIT_CODE;
/*
* global settings
*/
/*
* Set to 1 (the default) to enable the handling of -l=foo or
* --logfile=foo type of arguments. Set to 0 to disable. This allows
* you to specifically assign a value to an argument.
*/
int argv_close_enable_b = 1;
/*
* If the library sees a "--" argument, it will turn off further
* argument process. Set to 1 to enable the ability of specifying
* additional "--" arguments to reenable (basically toggle on then
* off) argument processing. Set to 0 (the default) to disable this
* behavior.
*/
int argv_last_toggle_b = 0;
/*
* Set to 1 (the default) to have the library accept multiple usage of
* the same argument. Set to 0 to have the library generate an error
* if you use an argument twice.
*/
int argv_multi_accept_b = 1;
/*
* Set to one of the ARGV_USAGE_ defines in the argv.h file. This
* tell the library what usage information to display when --usage is
* specified by the user. Default is ARGV_USAGE_LONG.
*/
int argv_usage_type = ARGV_USAGE_LONG;
/*
* Set to one of the ARGV_USAGE_ defines in the argv.h file. This
* tell the library what usage information to display when an error is
* encountered. The usage information accompanies the error message.
* Default is ARGV_USAGE_SEE.
*/
int argv_error_type = ARGV_USAGE_LONG;
/*
* Set to 1 (the default) if you want the library look for associated
* arguments from the associated program's environmental variable. If
* set the 0 then no environmental variable will be used. If you are
* running program foo then the library will look for the
* environmental variable ARGV_foo and will add those to the argument
* list specified on the command line. By default they will be
* inserted in front of those on the command line unless the
* argv_env_after_b is set to 1.
*
* NOTE: this is set by argv_process automatically. If you do not
* want this behavior, you should use argv_process_no_env.
*/
int argv_process_env_b = 1;
/*
* Set to 1 if you want the library to append the arguments from the
* program's environmental variable after those specified on the
* command line. If set the 0 (the default) then they will be
* inserted before those specified on the command line. See
* argv_process_env_b for more information.
*/
int argv_env_after_b = 0;
/*
* local variables
*/
/* empty argument array */
static argv_t empty[] = {{ ARGV_LAST, NULL, 0, NULL, NULL, NULL }};
static int enabled_b = ARGV_FALSE; /* are the lights on? */
/****************************** startup routine ******************************/
/*
* static void argv_startup
*
* DESCRIPTION:
*
* Turn on the lights.
*
* RETURNS:
*
* None.
*
* ARGUMENTS:
*
* None.
*/
static void argv_startup(void)
{
if (enabled_b) {
return;
}
enabled_b = ARGV_TRUE;
/* ANSI says we cannot predefine this above */
if (argv_error_stream == ERROR_STREAM_INIT) {
argv_error_stream = stderr;
}
}
/***************************** general utilities *****************************/
/*
* static int btoi
*
* DESCRIPTION:
*
* Binary string to integer translation.
*
* RETURNS:
*
* Integer converted from the string.
*
* ARGUMENTS:
*
* str - String of binary 0s and 1s that we are converting.
*/
static int btoi(const char *str)
{
int ret = 0;
/* strip off spaces */
for (; isspace((unsigned char) *str); str++) {
}
for (; *str == '0' || *str == '1'; str++) {
ret *= 2;
ret += *str - '0';
}
return ret;
}
/*
* static int otoi
*
* DESCRIPTION:
*
* Octal string to integer translation.
*
* RETURNS:
*
* Integer converted from the string.
*
* ARGUMENTS:
*
* str - String of octal digits that we are converting.
*/
static int otoi(const char *str)
{
int ret = 0;
/* strip off spaces */
for (; isspace((unsigned char) *str); str++) {
}
for (; *str >= '0' && *str <= '7'; str++) {
ret *= 8;
ret += *str - '0';
}
return ret;
}
/*
* static int htoi
*
* DESCRIPTION:
*
* Hexadecimal string to integer translation.
*
* RETURNS:
*
* Integer converted from the string.
*
* ARGUMENTS:
*
* str - String of hexadecimal characters and digits that we are
* converting.
*/
static int htoi(const char *str)
{
int ret = 0;
/* strip off spaces */
for (; isspace((unsigned char) *str); str++) {
}
/* skip a leading 0[xX] */
if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) {
str += 2;
}
for (; isdigit((unsigned char) *str) ||
(*str >= 'a' && *str <= 'f') || (*str >= 'A' && *str <= 'F');
str++) {
ret *= 16;
if (*str >= 'a' && *str <= 'f') {
ret += *str - 'a' + 10;
}
else if (*str >= 'A' && *str <= 'F') {
ret += *str - 'A' + 10;
}
else {
ret += *str - '0';
}
}
return ret;
}
/*
* static char *string_copy
*
* DESCRIPTION:
*
* Basically a strdup for compatibility sake.
*
* RETURNS:
*
* Character pointer that must be freed later.
*
* ARGUMENTS:
*
* str - String we are copying.
*/
static char *string_copy(const char *str)
{
const char *str_p;
char *copy, *copy_p;
int len;
len = strlen(str);
copy = (char *)malloc(len + 1);
if (copy == NULL) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: memory error during argument processing\n",
argv_program);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return NULL;
}
for (str_p = str, copy_p = copy; *str_p != '\0';) {
*copy_p++ = *str_p++;
}
*copy_p = '\0';
return copy;
}
/*
* static char **vectorize
*
* DESCRIPTION:
*
* Break a string up into its arguments separated by one of the
* characters in a token string and return an array of char pointers.
*
* NOTE: the string argument should stay around until that time.
*
* RETURNS:
*
* Success - Allocated list of character poiners into the string
* argument which must be freed later.
*
* Failure - NULL
*
* ARGUMENTS:
*
* str - String we are tokenizing.
*
* tok - List of token characters to look for in the string.
*
* num_tok_p - Pointer to an integer which will be set to the number
* of tokens found in the string.
*/
static char **vectorize(char *str, const char *tok, int *num_tok_p)
{
char **vect_p;
char *tmp, *str_p, *tok_p;
int tok_c, tok_n;
/* count the tokens */
tmp = string_copy(str);
if (tmp == NULL) {
return NULL;
}
str_p = tmp;
tok_c = 0;
while (1) {
tok_p = strsep(&str_p, tok);
if (tok_p == NULL) {
break;
}
/* skip empty tokens */
if (*tok_p != '\0') {
tok_c++;
}
}
tok_n = tok_c;
free(tmp);
*num_tok_p = tok_n;
if (tok_c == 0) {
return NULL;
}
/* allocate the pointer grid */
vect_p = (char **)malloc(sizeof(char *) * tok_n);
if (vect_p == NULL) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: memory error during argument processing\n",
argv_program);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return NULL;
}
/* load the tokens into the list */
str_p = str;
for (tok_c = 0; tok_c < tok_n;) {
tok_p = strsep(&str_p, tok);
if (tok_p == NULL) {
break;
}
/* skip empty tokens */
if (*tok_p != '\0') {
vect_p[tok_c] = tok_p;
tok_c++;
}
}
return vect_p;
}
/*
* static int expand_buf
*
* DESCRIPTION:
*
* Translates a buffer of bytes into its printable version.
*
* NOTE: it does _not_ add a \0 at the end of OUT.
*
* RETURNS:
*
* Number of characters written in to the output buffer.
*
* ARGUMENTS:
*
* buf - Input buffer of bytes.
*
* buf_size - Size of the input buffer. If < 0 then the routing will
* translate up to the first \0.
*
* out - Output buffer for the translated characters.
*
* out_size - Maximum size of the output buffer.
*/
static int expand_buf(const void *buf, const int buf_size,
char *out, const int out_size)
{
int buf_c;
const unsigned char *buf_p, *spec_p;
char *max_p, *out_p = out;
/* setup our max pointer */
max_p = out + out_size;
/* run through the input buffer, counting the characters as we go */
for (buf_c = 0, buf_p = (const unsigned char *)buf;; buf_c++, buf_p++) {
/* did we reach the end of the buffer? */
if (buf_size < 0) {
if (*buf_p == '\0') {
break;
}
}
else {
if (buf_c >= buf_size) {
break;
}
}
/* search for special characters */
for (spec_p = (unsigned char *)SPECIAL_CHARS + 1;
*(spec_p - 1) != '\0';
spec_p += 2) {
if (*spec_p == *buf_p) {
break;
}
}
/* did we find one? */
if (*(spec_p - 1) != '\0') {
if (out_p + 2 >= max_p) {
break;
}
LOC_SNPRINTF(SNP_ARG(out_p, 2), "\\%c", *(spec_p - 1));
out_p += 2;
continue;
}
/* print out any 7-bit printable characters */
if (*buf_p < 128 && isprint(*buf_p)) {
if (out_p + 1 >= max_p) {
break;
}
*out_p = *(char *)buf_p;
out_p += 1;
}
else {
if (out_p + 4 >= max_p) {
break;
}
LOC_SNPRINTF(SNP_ARG(out_p, 4), "\\%03o", *buf_p);
out_p += 4;
}
}
return out_p - out;
}
/****************************** usage routines *******************************/
/*
* static void usage_short
*
* DESCRIPTION:
*
* Print a short-format usage message.
*
* RETURNS:
*
* None.
*
* ARGUMENTS:
*
* args - Array of argv_t structions whose usage messages you print.
*
* flags - User flags.
*/
static void usage_short(const argv_t *args, const int flag)
{
const argv_t *arg_p;
int len, col_c = 0;
int mark_b = ARGV_FALSE;
const char *prefix;
if (argv_error_stream == NULL) {
return;
}
/* print the usage message header */
(void)fprintf(argv_error_stream, "%s%s", USAGE_LABEL, argv_program);
col_c += USAGE_LABEL_LENGTH + strlen(argv_program);
/*
* print all of the boolean arguments first.
* NOTE: we assume they all fit on the line
*/
for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) {
/* skip or-specifiers */
if (arg_p->ar_short_arg == ARGV_OR
|| arg_p->ar_short_arg == ARGV_XOR) {
continue;
}
/* skip non booleans */
if (HAS_ARG(arg_p->ar_type)) {
continue;
}
/* skip args with no short component */
if (arg_p->ar_short_arg == '\0') {
continue;
}
if (! mark_b) {
len = 2 + SHORT_PREFIX_LENGTH;
prefix = " [";
/* we check for -2 here because we should have 1 arg and ] on line */
if (col_c + len > SCREEN_WIDTH - 2) {
(void)fprintf(argv_error_stream, "\n%*.*s",
(int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "");
col_c = USAGE_LABEL_LENGTH;
/* if we are the start of a line, skip any starting spaces */
if (*prefix == ' ') {
prefix++;
len--;
}
}
(void)fprintf(argv_error_stream, "%s%s", prefix, SHORT_PREFIX);
col_c += len;
mark_b = ARGV_TRUE;
}
len = 1;
/* we check for -1 here because we should need ] */
if (col_c + len > SCREEN_WIDTH - 1) {
(void)fprintf(argv_error_stream, "]\n%*.*s",
(int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "");
col_c = USAGE_LABEL_LENGTH;
/* restart the short option list */
(void)fprintf(argv_error_stream, "[%s", SHORT_PREFIX);
col_c += 1 + SHORT_PREFIX_LENGTH;
}
(void)fprintf(argv_error_stream, "%c", arg_p->ar_short_arg);
col_c++;
}
if (mark_b) {
(void)fprintf(argv_error_stream, "]");
col_c++;
}
/* print remaining (non-boolean) arguments */
for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) {
int var_len;
const char *var_str, *postfix;
/* skip or-specifiers */
if (arg_p->ar_short_arg == ARGV_OR
|| arg_p->ar_short_arg == ARGV_XOR) {
continue;
}
/* skip booleans types */
if (! HAS_ARG(arg_p->ar_type)) {
continue;
}
if (arg_p->ar_var_label == NULL) {
if (ARGV_TYPE(arg_p->ar_type) == ARGV_BOOL_ARG
|| ARGV_TYPE(arg_p->ar_type) == ARGV_BOOL_INT_ARG) {
var_str = BOOL_ARG_LABEL;
var_len = BOOL_ARG_LENGTH;
}
else {
var_len = UNKNOWN_ARG_LENGTH;
var_str = UNKNOWN_ARG;
}
}
else {
var_len = strlen(arg_p->ar_var_label);
var_str = arg_p->ar_var_label;
}
if (arg_p->ar_short_arg == ARGV_MAND) {
/* print the mandatory argument desc */
len = 1 + var_len;
prefix = " ";
postfix = "";
}
else if (arg_p->ar_short_arg == ARGV_MAYBE) {
/* print the maybe argument desc */
len = 2 + var_len + 1;
prefix = " [";
postfix = "]";
}
else {
/* handle options with arguments */
/* " [" + short_prefix + char */
len = 2 + SHORT_PREFIX_LENGTH + 1;
prefix = " [";
/* do we need to wrap */
if (col_c + len > SCREEN_WIDTH) {
(void)fprintf(argv_error_stream, "\n%*.*s",
(int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "");
col_c = USAGE_LABEL_LENGTH;
/* if we are the start of a line, skip any starting spaces */
if (*prefix == ' ') {
prefix++;
len--;
}
}
(void)fprintf(argv_error_stream, "%s%s%c",
prefix, SHORT_PREFIX, arg_p->ar_short_arg);
col_c += len;
len = 1 + var_len + 1;
prefix = " ";
postfix = "]";
}
if (col_c + len > SCREEN_WIDTH) {
(void)fprintf(argv_error_stream, "\n%*.*s",
(int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "");
col_c = USAGE_LABEL_LENGTH;
/* if we are the start of a line, skip any starting spaces */
if (*prefix == ' ') {
prefix++;
len--;
}
}
(void)fprintf(argv_error_stream, "%s%s%s", prefix, var_str, postfix);
col_c += len;
}
(void)fprintf(argv_error_stream, "\n");
if (flag == ARGV_USAGE_SHORT_REM) {
(void)fprintf(argv_error_stream,
"%*.*sUse the '%s%s' argument for more assistance.\n",
(int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "",
LONG_PREFIX, USAGE_ARG);
}
}
/*
* static void display_arg
*
* DESCRIPTION:
*
* Display an argument type while keeping track of the column we are
* in.
*
* RETURNS:
*
* None.
*
* ARGUMENTS:
*
* stream - Output stream we are writing to.
*
* arg_p - Argument that we are displaying.
*
* max - Maximum column position to write to.
*
* col_cp - Pointer to an integer to record the column position.
*/
static void display_arg(FILE *stream, const argv_t *arg_p, const int max,
int *col_cp)
{
int var_len, len;
if (arg_p->ar_var_label == NULL) {
var_len = 0;
}
else {
var_len = strlen(arg_p->ar_var_label);
}
switch (ARGV_TYPE(arg_p->ar_type)) {
case ARGV_BOOL:
case ARGV_BOOL_NEG:
case ARGV_INCR:
case ARGV_BOOL_INT:
case ARGV_BOOL_INT_NEG:
break;
case ARGV_BOOL_ARG:
case ARGV_BOOL_INT_ARG:
(void)fprintf(stream, "%s", BOOL_ARG_LABEL);
(*col_cp) += BOOL_ARG_LENGTH;
break;
case ARGV_CHAR:
case ARGV_CHAR_P:
case ARGV_SHORT:
case ARGV_U_SHORT:
case ARGV_INT:
case ARGV_U_INT:
case ARGV_LONG:
case ARGV_U_LONG:
case ARGV_FLOAT:
case ARGV_DOUBLE:
case ARGV_BIN:
case ARGV_OCT:
case ARGV_HEX:
case ARGV_SIZE:
case ARGV_U_SIZE:
if (arg_p->ar_var_label == NULL) {
len = max - *col_cp;
(void)fprintf(stream, "%-.*s", len, UNKNOWN_ARG);
*col_cp += MIN(len, (int)UNKNOWN_ARG_LENGTH);
}
else {
len = max - *col_cp;
(void)fprintf(stream, "%-.*s", len, arg_p->ar_var_label);
*col_cp += MIN(len, var_len);
}
break;
}
}
/*
* static void display_option
*
* DESCRIPTION:
*
* Display an option entry while while keeping track of the column we
* are in.
*
* RETURNS:
*
* None.
*
* ARGUMENTS:
*
* stream - Output stream we are writing to.
*
* arg_p - Argument that we are displaying.
*
* max - Maximum column position to write to.
*
* col_cp - Pointer to an integer to record the column position.
*/
static void display_option(FILE *stream, const argv_t *arg_p, int *col_cp)
{
if (stream == NULL) {
return;
}
(void)fputc('[', stream);
(*col_cp)++;
/* arg maybe does not have a -? preface */
if (arg_p->ar_short_arg != ARGV_MAYBE) {
(void)fprintf(stream, "%s%c",
SHORT_PREFIX, arg_p->ar_short_arg);
*col_cp += SHORT_PREFIX_LENGTH + 1;
if (HAS_ARG(arg_p->ar_type)) {
/* display optional argument */
(void)fputc(' ', stream);
(*col_cp)++;
}
}
display_arg(stream, arg_p, LONG_COLUMN - 1, col_cp);
(void)fputc(']', stream);
(*col_cp)++;
}
/*
* static void usage_long
*
* DESCRIPTION:
*
* Print a long-format usage message.
*
* RETURNS:
*
* None.
*
* ars - Array of argv_t structures whose usage we are printing.
*/
static void usage_long(const argv_t *args)
{
const argv_t *arg_p;
int col_c, len;
if (argv_error_stream == NULL) {
return;
}
/* print the usage message header */
(void)fprintf(argv_error_stream, "%s%s\n", USAGE_LABEL, argv_program);
/* run through the argument structure */
for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) {
/* skip or specifiers */
if (arg_p->ar_short_arg == ARGV_OR || arg_p->ar_short_arg == ARGV_XOR) {
continue;
}
/* indent to the short-option col_c */
(void)fprintf(argv_error_stream, "%*.*s", SHORT_COLUMN, SHORT_COLUMN, "");
/* start column counter */
col_c = SHORT_COLUMN;
/* print the short-arg stuff if there */
if (arg_p->ar_short_arg == '\0') {
(void)fputc('[', argv_error_stream);
col_c++;
}
else {
if (arg_p->ar_short_arg == '\0') {
;
}
else if (arg_p->ar_short_arg == ARGV_MAND) {
display_arg(argv_error_stream, arg_p, COMMENT_COLUMN, &col_c);
}
else {
/* ARGV_MAYBE handled here */
display_option(argv_error_stream, arg_p, &col_c);
}
/* put the long-option message on the correct column */
if (col_c < LONG_COLUMN) {
(void)fprintf(argv_error_stream, "%*.*s",
LONG_COLUMN - col_c, LONG_COLUMN - col_c, "");
col_c = LONG_COLUMN;
}
}
/* print the long-option message */
if (arg_p->ar_long_arg != NULL) {
len = COMMENT_COLUMN - col_c - (LONG_PREFIX_LENGTH + 1);
if (arg_p->ar_short_arg != '\0') {
(void)fprintf(argv_error_stream, "%s", LONG_LABEL);
col_c += LONG_LABEL_LENGTH;
len -= LONG_LABEL_LENGTH;
}
(void)fprintf(argv_error_stream, "%s%-.*s",
LONG_PREFIX, len, arg_p->ar_long_arg);
col_c += LONG_PREFIX_LENGTH + MIN(len, (int)strlen(arg_p->ar_long_arg));
}
/* add the optional argument if no short-arg */
if (arg_p->ar_short_arg == '\0') {
if (HAS_ARG(arg_p->ar_type)) {
(void)fputc(' ', argv_error_stream);
col_c++;
}
/* display any optional arguments */
display_arg(argv_error_stream, arg_p, COMMENT_COLUMN - 1, &col_c);
(void)fputc(']', argv_error_stream);
col_c++;
}
/* print the comment */
if (arg_p->ar_comment != NULL) {
/* put the comment message on the correct column */
if (col_c < COMMENT_COLUMN) {
(void)fprintf(argv_error_stream, "%*.*s",
COMMENT_COLUMN - col_c,
COMMENT_COLUMN - col_c, "");
col_c = COMMENT_COLUMN;
}
len = SCREEN_WIDTH - col_c - COMMENT_LABEL_LENGTH;
(void)fprintf(argv_error_stream, "%s%-.*s",
COMMENT_LABEL, len, arg_p->ar_comment);
}
(void)fprintf(argv_error_stream, "\n");
}
}
/*
* static void do_usage
*
* DESCRIPTION:
*
* Print the usage messages.
*
* RETURNS:
*
* None.
*
* ARGUMENTS:
*
* args - Array of argv_t structures.
*
* flag - Users flags which will tell us whether to display short or
* long usage messages.
*/
static void do_usage(const argv_t *args, const int flag)
{
if (argv_error_stream == NULL) {
return;
}
if (flag == ARGV_USAGE_SEE) {
(void)fprintf(argv_error_stream,
"%*.*sUse the '%s%s' argument for assistance.\n",
(int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "",
LONG_PREFIX, USAGE_ARG);
}
else if (flag == ARGV_USAGE_SHORT || flag == ARGV_USAGE_SHORT_REM) {
usage_short(args, flag);
}
else if (flag == ARGV_USAGE_LONG || flag == ARGV_USAGE_ALL) {
usage_long(args);
}
if (flag == ARGV_USAGE_ALL) {
(void)fprintf(argv_error_stream, "\n");
(void)fprintf(argv_error_stream,
"%*.*sUse '%s%s' for default usage information.\n",
SHORT_COLUMN, SHORT_COLUMN, "",
LONG_PREFIX, USAGE_ARG);
(void)fprintf(argv_error_stream,
"%*.*sUse '%s%s' for short usage information.\n",
SHORT_COLUMN, SHORT_COLUMN, "",
LONG_PREFIX, USAGE_SHORT_ARG);
(void)fprintf(argv_error_stream,
"%*.*sUse '%s%s' for long usage information.\n",
SHORT_COLUMN, SHORT_COLUMN, "",
LONG_PREFIX, USAGE_LONG_ARG);
(void)fprintf(argv_error_stream,
"%*.*sUse '%s%s' for all usage information.\n",
SHORT_COLUMN, SHORT_COLUMN, "",
LONG_PREFIX, USAGE_ALL_ARG);
(void)fprintf(argv_error_stream,
"%*.*sUse '%s%s' to display the help message.\n",
SHORT_COLUMN, SHORT_COLUMN, "",
LONG_PREFIX, HELP_ARG);
(void)fprintf(argv_error_stream,
"%*.*sUse '%s%s' to display the version message.\n",
SHORT_COLUMN, SHORT_COLUMN, "",
LONG_PREFIX, VERSION_ARG);
(void)fprintf(argv_error_stream,
"%*.*sUse '%s%s' to display the options and their values.\n",
SHORT_COLUMN, SHORT_COLUMN, "",
LONG_PREFIX, DISPLAY_ARG);
}
}
/******************************* preprocessing *******************************/
/*
* static int preprocess_array
*
* DESCRIPTION:
*
* Preprocess argument array entries and set the mandatory and maybe
* flags.
*
* RETURNS:
*
* Success - 0
*
* Faulure - -1
*
* ARGUMENTS:
*
* args - Array of argv_t structures.
*
* arg_n - Number of entries in the argv_t array. We need this for a
* couple of reasons.
*/
static int preprocess_array(argv_t *args, const int arg_n)
{
argv_t *arg_p;
int mand_array_b = ARGV_FALSE, maybe_field_b = ARGV_FALSE;
/* count the args and find the first mandatory */
for (arg_p = args; arg_p < args + arg_n; arg_p++) {
/* clear internal flags */
arg_p->ar_type &= ~ARGV_FLAG_USED;
/* do we have a mandatory-array? */
if (arg_p->ar_short_arg == ARGV_MAND) {
if (mand_array_b) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, no ARGV_MAND's can follow a MAND or MAYBE array\n",
argv_program, INTERNAL_ERROR_NAME);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return ERROR;
}
if (maybe_field_b) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, no ARGV_MAND's can follow a ARGV_MAYBE\n",
argv_program, INTERNAL_ERROR_NAME);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return ERROR;
}
if (arg_p->ar_type & ARGV_FLAG_ARRAY) {
mand_array_b = ARGV_TRUE;
}
}
/* do we have a maybe field? */
if (arg_p->ar_short_arg == ARGV_MAYBE) {
if (mand_array_b) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, no ARGV_MAYBE's can follow a MAND or MAYBE array\n",
argv_program, INTERNAL_ERROR_NAME);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return ERROR;
}
maybe_field_b = ARGV_TRUE;
if (arg_p->ar_type & ARGV_FLAG_ARRAY) {
mand_array_b = ARGV_TRUE;
}
}
/* handle initializing the argument array */
if (arg_p->ar_type & ARGV_FLAG_ARRAY) {
argv_array_t *arrp = (argv_array_t *)arg_p->ar_variable;
if (! HAS_ARG(arg_p->ar_type)) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, cannot have an array of boolean values\n",
argv_program, INTERNAL_ERROR_NAME);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return ERROR;
}
if (ARGV_TYPE(arg_p->ar_type) == ARGV_INCR) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, cannot have an array of incremental values\n",
argv_program, INTERNAL_ERROR_NAME);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return ERROR;
}
arrp->aa_entry_n = 0;
}
/* verify variable pointer */
if (arg_p->ar_variable == NULL
&& arg_p->ar_short_arg != ARGV_OR
&& arg_p->ar_short_arg != ARGV_XOR) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, NULL variable specified in arg array\n",
argv_program, INTERNAL_ERROR_NAME);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return ERROR;
}
/* verify [X]OR's */
if (arg_p->ar_short_arg == ARGV_OR
|| arg_p->ar_short_arg == ARGV_XOR) {
/* that they are not at the start or end of list */
if (arg_p == args || arg_p >= (args + arg_n - 1)) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, ARGV_[X]OR entries cannot be at start or end of array\n",
argv_program, INTERNAL_ERROR_NAME);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return ERROR;
}
/* that two aren't next to each other */
if ((arg_p - 1)->ar_short_arg == ARGV_OR
|| (arg_p - 1)->ar_short_arg == ARGV_XOR) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, two ARGV_[X]OR entries cannot be next to each other\n",
argv_program, INTERNAL_ERROR_NAME);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return ERROR;
}
}
}
return NOERROR;
}
/*
* static int string_to_value
*
* DESCRIPTION:
*
* Translate string value argument into a variable value depending on
* its type.
*
* RETURNS:
*
* Success - 0
*
* Faulure - -1
*
* ARGUMENTS:
*
* arg - Argument string.
*
* var - Pointer to our variable.
*
* type - Type of the variable.
*/
static int string_to_value(const char *arg, ARGV_PNT var,
const unsigned int type)
{
argv_array_t *arr_p;
argv_type_t *type_p;
unsigned int val_type = ARGV_TYPE(type), size = 0;
/* find the type and the size for array */
for (type_p = argv_types; type_p->at_value != 0; type_p++) {
if (type_p->at_value == val_type) {
size = type_p->at_size;
break;
}
}
if (type_p->at_value == 0) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream, "%s: illegal variable type %d\n",
__FILE__, val_type);
}
return ERROR;
}
if (type & ARGV_FLAG_ARRAY) {
arr_p = (argv_array_t *)var;
if (arr_p->aa_entry_n == 0) {
arr_p->aa_entries = (char *)malloc(ARRAY_INCR *size);
}
else if (arr_p->aa_entry_n % ARRAY_INCR == 0) {
arr_p->aa_entries =
(char *)realloc(arr_p->aa_entries, (arr_p->aa_entry_n + ARRAY_INCR) *
size);
}
if (arr_p->aa_entries == NULL) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: memory error during argument processing\n",
argv_program);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return ERROR;
}
var = (char *)(arr_p->aa_entries) + arr_p->aa_entry_n * size;
arr_p->aa_entry_n++;
}
/* translate depending on type */
switch (val_type) {
case ARGV_BOOL:
/* if no close argument, set to true */
if (arg == NULL) {
*(char *)var = ARGV_TRUE;
}
else if (*(char *)arg == 't' || *(char *)arg == 'T'
|| *(char *)arg == 'y' || *(char *)arg == 'Y'
|| *(char *)arg == '1') {
*(char *)var = ARGV_TRUE;
}
else {
*(char *)var = ARGV_FALSE;
}
break;
case ARGV_BOOL_NEG:
/* if no close argument, set to false */
if (arg == NULL) {
*(char *)var = ARGV_FALSE;
}
else if (*(char *)arg == 't' || *(char *)arg == 'T'
|| *(char *)arg == 'y' || *(char *)arg == 'Y'
|| *(char *)arg == '1') {
*(char *)var = ARGV_TRUE;
}
else {
*(char *)var = ARGV_FALSE;
}
break;
case ARGV_BOOL_ARG:
if (*(char *)arg == 't' || *(char *)arg == 'T'
|| *(char *)arg == 'y' || *(char *)arg == 'Y'
|| *(char *)arg == '1') {
*(char *)var = ARGV_TRUE;
}
else {
*(char *)var = ARGV_FALSE;
}
break;
case ARGV_CHAR:
*(char *)var = *(char *)arg;
break;
case ARGV_CHAR_P:
*(char **)var = string_copy((char *)arg);
if (*(char **)var == NULL) {
return ERROR;
}
break;
case ARGV_SHORT:
*(short *)var = (short)atoi(arg);
break;
case ARGV_U_SHORT:
*(unsigned short *)var = (unsigned short)atoi(arg);
break;
case ARGV_INT:
*(int *)var = atoi(arg);
break;
case ARGV_U_INT:
*(unsigned int *)var = atoi(arg);
break;
case ARGV_LONG:
*(long *)var = atol(arg);
break;
case ARGV_U_LONG:
*(unsigned long *)var = atol(arg);
break;
case ARGV_FLOAT:
(void)sscanf(arg, "%f", (float *)var);
break;
case ARGV_DOUBLE:
(void)sscanf(arg, "%lf", (double *)var);
break;
case ARGV_BIN:
*(int *)var = btoi(arg);
break;
case ARGV_OCT:
*(int *)var = otoi(arg);
break;
case ARGV_HEX:
*(int *)var = htoi(arg);
break;
case ARGV_INCR:
/* if no close argument then increment else set the value */
if (arg == NULL) {
(*(int *)var)++;
}
else {
*(int *)var = atoi(arg);
}
break;
case ARGV_SIZE:
{
const char *arg_p;
long val;
/* take initial integer point */
val = atol(arg);
for (arg_p = arg;
*arg_p == ' ' || *arg_p == '-' || *arg_p == '+'
|| (*arg_p >= '0' && *arg_p <= '9');
arg_p++) {
}
if (*arg_p == 'b' || *arg_p == 'B') {
val *= 1;
}
else if (*arg_p == 'k' || *arg_p == 'K') {
val *= 1024;
}
else if (*arg_p == 'm' || *arg_p == 'M') {
val *= 1024 * 1024;
}
else if (*arg_p == 'g' || *arg_p == 'G') {
val *= 1024 * 1024 * 1024;
}
*(long *)var = val;
}
break;
case ARGV_U_SIZE:
{
const char *arg_p;
unsigned long val;
/* take initial integer point */
val = (unsigned long)atol(arg);
for (arg_p = arg;
*arg_p == ' ' || *arg_p == '-' || *arg_p == '+'
|| (*arg_p >= '0' && *arg_p <= '9');
arg_p++) {
}
if (*arg_p == 'b' || *arg_p == 'B') {
val *= 1;
}
else if (*arg_p == 'k' || *arg_p == 'K') {
val *= 1024;
}
else if (*arg_p == 'm' || *arg_p == 'M') {
val *= 1024 * 1024;
}
else if (*arg_p == 'g' || *arg_p == 'G') {
val *= 1024 * 1024 * 1024;
}
*(unsigned long *)var = val;
}
break;
case ARGV_BOOL_INT:
/* if no close argument, set to true */
if (arg == NULL) {
*(int *)var = ARGV_TRUE;
}
else if (*(char *)arg == 't' || *(char *)arg == 'T'
|| *(char *)arg == 'y' || *(char *)arg == 'Y'
|| *(char *)arg == '1') {
*(int *)var = ARGV_TRUE;
}
else {
*(int *)var = ARGV_FALSE;
}
break;
case ARGV_BOOL_INT_NEG:
/* if no close argument, set to false */
if (arg == NULL) {
*(int *)var = ARGV_FALSE;
}
else if (*(char *)arg == 't' || *(char *)arg == 'T'
|| *(char *)arg == 'y' || *(char *)arg == 'Y'
|| *(char *)arg == '1') {
*(int *)var = ARGV_TRUE;
}
else {
*(int *)var = ARGV_FALSE;
}
break;
case ARGV_BOOL_INT_ARG:
if (*(char *)arg == 't' || *(char *)arg == 'T'
|| *(char *)arg == 'y' || *(char *)arg == 'Y'
|| *(char *)arg == '1') {
*(int *)var = ARGV_TRUE;
}
else {
*(int *)var = ARGV_FALSE;
}
break;
}
return NOERROR;
}
/*
* static int value_to_string
*
* DESCRIPTION:
*
* Translate value from variable depending on its type intoits string
* represetnation in buffer.
*
* RETURNS:
*
* Number of characters added to the buffer.
*
* ARGUMENTS:
*
* var - Variable pointer.
*
* type - Type of variable.
*
* buf - User buffer to convert into.
*
* buf_size - Size of the user buffer.
*/
static int value_to_string(const ARGV_PNT var, const unsigned int type,
char *buf, const int buf_size)
{
int len = 0;
/*
* NOTE: without a snprintf, we have to hope that buf_size > integer
* and the string repesentations of the numbers.
*/
/* translate depending on type */
switch (ARGV_TYPE(type)) {
case ARGV_BOOL:
case ARGV_BOOL_NEG:
case ARGV_BOOL_ARG:
if (*(char *)var) {
strncpy(buf, "true (! 0)", buf_size);
}
else {
strncpy(buf, "false (0)", buf_size);
}
buf[buf_size - 1] = '\0';
len = strlen(buf);
break;
case ARGV_CHAR:
len = expand_buf((char *)var, 1, buf, buf_size);
break;
case ARGV_CHAR_P:
if (*(char **)var == NULL) {
strncpy(buf, "(null)", buf_size);
buf[buf_size - 1] = '\0';
len = strlen(buf);
}
else {
len = expand_buf(*(char **)var, -1, buf, buf_size);
}
break;
case ARGV_SHORT:
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%d", *(short *)var);
len = strlen(buf);
break;
case ARGV_U_SHORT:
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%d", *(unsigned short *)var);
len = strlen(buf);
break;
case ARGV_INT:
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%d", *(int *)var);
len = strlen(buf);
break;
case ARGV_U_INT:
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%u", *(unsigned int *)var);
len = strlen(buf);
break;
case ARGV_LONG:
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%ld", *(long *)var);
len = strlen(buf);
break;
case ARGV_U_LONG:
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%lu", *(unsigned long *)var);
len = strlen(buf);
break;
case ARGV_FLOAT:
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%f", *(float *)var);
len = strlen(buf);
break;
case ARGV_DOUBLE:
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%f", *(double *)var);
len = strlen(buf);
break;
/* this should be a routine */
case ARGV_BIN:
{
int bit_c, bit, first_b = ARGV_FALSE;
char binary[2 + 128 + 1], *bin_bounds_p, *bin_p = binary;
if (*(int *)var == 0) {
strncpy(buf, "0", buf_size);
}
else {
bin_bounds_p = binary + sizeof(binary);
/* initially write binary number into tmp buffer, then copy into out */
*bin_p++ = '0';
*bin_p++ = 'b';
for (bit_c = sizeof(int) * BITS_IN_BYTE - 1; bit_c >= 0; bit_c--) {
bit = *(int *)var & (1 << bit_c);
if (bit == 0) {
if (first_b) {
*bin_p++ = '0';
}
}
else {
*bin_p++ = '1';
first_b = ARGV_TRUE;
}
}
/* add on the decimal equivalent */
LOC_SNPRINTF(SNP_ARG(bin_p, bin_bounds_p - bin_p)," (%d)",
*(int *)var);
/* find the \0 at end */
for (; *bin_p != '\0'; bin_p++) {
}
/* now we copy from the binary buffer to the output */
strncpy(buf, binary, buf_size);
}
buf[buf_size - 1] = '\0';
len = strlen(buf);
}
break;
case ARGV_OCT:
if (*(int *)var == 0) {
(void)strncpy(buf, "0", buf_size);
buf[buf_size - 1] = '\0';
}
else {
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%#o (%d)",
*(int *)var, *(int *)var);
}
len = strlen(buf);
break;
case ARGV_HEX:
if (*(int *)var == 0) {
(void)strcpy(buf, "0");
}
else {
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%#x (%d)",
*(int *)var, *(int *)var);
}
len = strlen(buf);
break;
case ARGV_INCR:
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%d", *(int *)var);
len = strlen(buf);
break;
case ARGV_SIZE:
{
long morf, val = *(long *)var;
if (val == 0) {
(void)strcpy(buf, "0");
}
else if (val % (1024 * 1024 * 1024) == 0) {
morf = val / (1024 * 1024 * 1024);
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%ldg (%ld)", morf, val);
}
else if (val % (1024 * 1024) == 0) {
morf = val / (1024 * 1024);
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%ldm (%ld)", morf, val);
}
else if (val % 1024 == 0) {
morf = val / 1024;
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%ldk (%ld)", morf, val);
}
else {
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%ld", val);
}
len = strlen(buf);
}
break;
case ARGV_U_SIZE:
{
unsigned long morf, val = *(unsigned long *)var;
if (val == 0) {
(void)strcpy(buf, "0");
}
else if (val % (1024 * 1024 * 1024) == 0) {
morf = val / (1024 * 1024 * 1024);
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%ldg (%ld)", morf, val);
}
else if (val % (1024 * 1024) == 0) {
morf = val / (1024 * 1024);
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%ldm (%ld)", morf, val);
}
else if (val % 1024 == 0) {
morf = val / 1024;
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%ldk (%ld)", morf, val);
}
else {
LOC_SNPRINTF(SNP_ARG(buf, buf_size), "%ld", val);
}
len = strlen(buf);
}
break;
case ARGV_BOOL_INT:
case ARGV_BOOL_INT_NEG:
case ARGV_BOOL_INT_ARG:
if (*(int *)var) {
strncpy(buf, "true (! 0)", buf_size);
}
else {
strncpy(buf, "false (0)", buf_size);
}
buf[buf_size - 1] = '\0';
len = strlen(buf);
break;
default:
strncpy(buf, "(unknown)", buf_size);
buf[buf_size - 1] = '\0';
len = strlen(buf);
break;
}
return len;
}
/*
* static void display_variables
*
* DESCRIPTION:
*
* Display all of the variable values from our array.
*
* RETURNS:
*
* None.
*
* ARGUMENTS:
*
* args - Array of argv_t structures whose variables we are
* displaying.
*/
static void display_variables(const argv_t *args)
{
const argv_t *arg_p;
argv_type_t *type_p;
char buf[256];
int len, col_c;
unsigned int val_type;
/* run through the argument structure */
for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) {
val_type = ARGV_TYPE(arg_p->ar_type);
/* skip or specifiers */
if (arg_p->ar_short_arg == ARGV_OR || arg_p->ar_short_arg == ARGV_XOR) {
continue;
}
col_c = 0;
if (arg_p->ar_short_arg == '\0') {
if (arg_p->ar_long_arg != NULL) {
len = COMMENT_COLUMN - col_c - (LONG_PREFIX_LENGTH + 1);
if (arg_p->ar_short_arg != '\0') {
(void)fprintf(argv_error_stream, "%s", LONG_LABEL);
col_c += LONG_LABEL_LENGTH;
len -= LONG_LABEL_LENGTH;
}
(void)fprintf(argv_error_stream, "%s%-.*s",
LONG_PREFIX, len, arg_p->ar_long_arg);
col_c += LONG_PREFIX_LENGTH + MIN(len,
(int)strlen(arg_p->ar_long_arg));
}
}
else if (arg_p->ar_short_arg == ARGV_MAND) {
display_arg(argv_error_stream, arg_p, COMMENT_COLUMN, &col_c);
}
else {
/* ARGV_MAYBE handled here */
display_option(argv_error_stream, arg_p, &col_c);
}
/* put the type in the correct column */
if (col_c < LONG_COLUMN) {
(void)fprintf(argv_error_stream, "%*.*s",
LONG_COLUMN - col_c, LONG_COLUMN - col_c, "");
col_c = LONG_COLUMN;
}
/* find the type */
type_p = NULL;
for (type_p = argv_types; type_p->at_value != 0; type_p++) {
if (type_p->at_value == ARGV_TYPE(arg_p->ar_type)) {
int tlen;
len = COMMENT_COLUMN - col_c - 1;
tlen = strlen(type_p->at_name);
(void)fprintf(argv_error_stream, " %-.*s", len, type_p->at_name);
col_c += MIN(len, tlen);
if (arg_p->ar_type & ARGV_FLAG_ARRAY) {
(void)fprintf(argv_error_stream, "%s", ARRAY_LABEL);
col_c += sizeof(ARRAY_LABEL) - 1;
}
break;
}
}
if (col_c < COMMENT_COLUMN) {
(void)fprintf(argv_error_stream, "%*.*s",
COMMENT_COLUMN - col_c, COMMENT_COLUMN - col_c, "");
col_c = COMMENT_COLUMN;
}
if (arg_p->ar_type & ARGV_FLAG_ARRAY) {
argv_array_t *arr_p;
int entry_c, size = 0;
/* find the type and the size for array */
if (type_p == NULL) {
(void)fprintf(argv_error_stream, "%s: illegal variable type %d\n",
__FILE__, val_type);
continue;
}
size = type_p->at_size;
arr_p = (argv_array_t *)arg_p->ar_variable;
if (arr_p->aa_entry_n == 0) {
(void)fprintf(argv_error_stream, "no entries");
}
else {
for (entry_c = 0; entry_c < arr_p->aa_entry_n; entry_c++) {
ARGV_PNT var;
if (entry_c > 0) {
(void)fputc(',', argv_error_stream);
}
var = (char *)(arr_p->aa_entries) + entry_c * size;
len = value_to_string(var, val_type, buf, sizeof(buf));
(void)fwrite(buf, sizeof(char), len, argv_error_stream);
}
}
}
else {
len = value_to_string(arg_p->ar_variable, val_type, buf, sizeof(buf));
(void)fwrite(buf, sizeof(char), len, argv_error_stream);
}
(void)fputc('\n', argv_error_stream);
}
}
/************************** checking used arguments **************************/
/*
* static int check_or
*
* DESCRIPTION:
*
* Check out if an argument has an ARGV_OR attached to it and both
* variables have not been set.
*
* RETURNS:
*
* Success - 0
*
* Faulure - -1
*
* ARGUMENTS:
*
* args - Array of argv_t structures that we are checking.
*
* which_p - Pointer to the specific argument that we are checking for
* the ARGV_OR.
*/
static int check_or(const argv_t *args, const argv_t *which_p)
{
const argv_t *arg_p, *match_p = NULL;
/* check ORs below */
for (arg_p = which_p - 2; arg_p >= args; arg_p -= 2) {
if ((arg_p + 1)->ar_short_arg != ARGV_OR
&& (arg_p + 1)->ar_short_arg != ARGV_XOR) {
break;
}
if (arg_p->ar_type & ARGV_FLAG_USED) {
match_p = arg_p;
break;
}
}
/* check ORs above */
if (match_p == NULL) {
/* NOTE: we assume that which_p is not pointing now to ARGV_LAST */
for (arg_p = which_p + 2;
arg_p->ar_short_arg != ARGV_LAST
&& (arg_p - 1)->ar_short_arg != ARGV_LAST;
arg_p += 2) {
if ((arg_p - 1)->ar_short_arg != ARGV_OR
&& (arg_p - 1)->ar_short_arg != ARGV_XOR) {
break;
}
if (arg_p->ar_type & ARGV_FLAG_USED) {
match_p = arg_p;
break;
}
}
}
/* did we not find a problem? */
if (match_p == NULL) {
return NOERROR;
}
if (argv_error_stream == NULL) {
return ERROR;
}
(void)fprintf(argv_error_stream,
"%s: %s, specify only one of the following:\n",
argv_program, USAGE_ERROR_NAME);
/* little hack to print the one that matched and the one we were checking */
for (;;) {
if (match_p->ar_long_arg == NULL) {
(void)fprintf(argv_error_stream, "%*.*s%s%c\n",
(int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "",
SHORT_PREFIX, match_p->ar_short_arg);
}
else {
(void)fprintf(argv_error_stream, "%*.*s%s%c (%s%s)\n",
(int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "",
SHORT_PREFIX, match_p->ar_short_arg,
LONG_PREFIX, match_p->ar_long_arg);
}
if (match_p == which_p) {
break;
}
match_p = which_p;
}
return ERROR;
}
/*
* static int check_xor
*
* DESCRIPTION:
*
* Check out if an argument has an ARGV_XOR attached to it and that at
* least one but not both variables have been set.
*
* RETURNS:
*
* Success - 0
*
* Faulure - -1
*
* ARGUMENTS:
*
* args - Array of argv_t structures that we are checking.
*
* which_p - Pointer to the specific argument that we are checking for
* the ARGV_XOR.
*/
static int check_xor(const argv_t *args)
{
const argv_t *start_p = NULL, *arg_p;
/* run through the list of arguments */
for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) {
/* only check the XORs */
if (arg_p->ar_short_arg != ARGV_XOR) {
continue;
}
start_p = arg_p;
/*
* NOTE: we are guaranteed that we are on a XOR so there is
* something below and above...
*/
if ((arg_p - 1)->ar_type & ARGV_FLAG_USED) {
start_p = NULL;
}
/* run through all XORs */
for (;;) {
arg_p++;
if (arg_p->ar_type & ARGV_FLAG_USED) {
start_p = NULL;
}
if ((arg_p + 1)->ar_short_arg != ARGV_XOR) {
break;
}
arg_p++;
}
/* were none of the xor's filled? */
if (start_p != NULL) {
break;
}
}
/* did we not find a problem? */
if (start_p == NULL) {
return NOERROR;
}
/* arg_p points to the first XOR which failed */
if (argv_error_stream == NULL) {
return ERROR;
}
(void)fprintf(argv_error_stream, "%s: %s, must specify one of:\n",
argv_program, USAGE_ERROR_NAME);
for (arg_p = start_p;; arg_p += 2) {
/*
* NOTE: we are guaranteed that we are on a XOR so there is
* something below and above...
*/
(void)fprintf(argv_error_stream, "%*.*s%s%c",
(int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "",
SHORT_PREFIX, (arg_p - 1)->ar_short_arg);
if ((arg_p - 1)->ar_long_arg != NULL) {
(void)fprintf(argv_error_stream, " (%s%s)",
LONG_PREFIX, (arg_p - 1)->ar_long_arg);
}
(void)fprintf(argv_error_stream, "\n");
if (arg_p->ar_short_arg != ARGV_XOR) {
break;
}
}
return ERROR;
}
/*
* static int check_mand
*
* DESCRIPTION:
*
* Verify that all of the mandatory arguments in our array have been
* specified.
*
* RETURNS:
*
* Success - 0
*
* Faulure - -1
*
* ARGUMENTS:
*
* args - Array of argv_t structures that we are checking.
*/
static int check_mand(const argv_t *args)
{
const argv_t *arg_p;
int mand_c = 0, flag_c = 0;
/* see if there are any mandatory args left */
for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) {
if (arg_p->ar_short_arg == ARGV_MAND
&& (! (arg_p->ar_type & ARGV_FLAG_USED))) {
mand_c++;
}
if (arg_p->ar_type & ARGV_FLAG_MAND
&& (! (arg_p->ar_type & ARGV_FLAG_USED))) {
flag_c++;
if (argv_error_stream != NULL) {
if (flag_c == 1) {
(void)fprintf(argv_error_stream,
"%s: %s, these mandatory flags must be specified:\n",
argv_program, USAGE_ERROR_NAME);
}
(void)fprintf(argv_error_stream, "%*.*s%s%c",
(int)USAGE_LABEL_LENGTH, (int)USAGE_LABEL_LENGTH, "",
SHORT_PREFIX, arg_p->ar_short_arg);
if (arg_p->ar_long_arg != NULL) {
(void)fprintf(argv_error_stream, " (%s%s)",
LONG_PREFIX, arg_p->ar_long_arg);
}
(void)fprintf(argv_error_stream, "\n");
}
}
}
if (mand_c > 0 && argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, %d more mandatory argument%s must be specified\n",
argv_program, USAGE_ERROR_NAME,
mand_c, (mand_c == 1 ? "" : "s"));
}
if (mand_c > 0 || flag_c > 0) {
return ERROR;
}
else {
return NOERROR;
}
}
/*
* static int check_opt
*
* DESCRIPTION:
*
* Check for any missing argument options.
*
* RETURNS:
*
* Success - 0
*
* Faulure - -1
*
* ARGUMENTS:
*
* queue_head - Head of the option queue.
*
* queue_tail - Tail of the option queue.
*/
static int check_opt(const int queue_head, const int queue_tail)
{
int queue_c;
queue_c = queue_head - queue_tail;
if (queue_c > 0) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, %d more option-argument%s must be specified\n",
argv_program, USAGE_ERROR_NAME,
queue_c, (queue_c == 1 ? "" : "s"));
}
return ERROR;
}
return NOERROR;
}
/**************************** argument processing ****************************/
/*
* static void file_args
*
* DESCRIPTION:
*
* Read in arguments from a file and process them like they were
* specified on the command line.
*
* RETURNS:
*
* Success - 0
*
* Faulure - -1
*
* ARGUMENTS:
*
* path -> File of the arguments we are reading in.
*
* grid -> Array of argv_t structures we are using.
*
* queue_list <-> Our option queue for storing options to arguments.
*
* queue_head_p <-> Pointer to integer which will be updated with the
* head position in our option queue.
*
* queue_tail_p <-> Pointer to integer which will be updated with the
* tail position in our option queue.
*
* okay_bp <- Pointer to an integer which is set with 0 if the
* arguments specified in the env variable are somehow invalid.
*/
static void file_args(const char *path, argv_t *grid,
argv_t **queue_list, int *queue_head_p,
int *queue_tail_p, int *okay_bp)
{
char **argv, **argv_p;
int arg_c, max;
FILE *infile;
char line[FILE_LINE_SIZE], *line_p;
/* open the input file */
if (strcmp(path, "-") == 0) {
infile = stdin;
}
else {
infile = fopen(path, "r");
}
if (infile == NULL) {
*okay_bp = ARGV_FALSE;
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: could not load command-line arguments from: %s\n",
argv_program, path);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return;
}
/* get an array of char * */
arg_c = 0;
max = ARRAY_INCR;
argv = malloc(sizeof(char *) * max);
if (argv == NULL) {
*okay_bp = ARGV_FALSE;
if (infile != stdin) {
(void)fclose(infile);
}
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: memory error during argument processing\n",
argv_program);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return;
}
argv_p = argv;
/* read in the file lines */
while (fgets(line, sizeof(line), infile) != NULL) {
/* punch the \n at end of line */
for (line_p = line; *line_p != '\n' && *line_p != '\0'; line_p++) {
}
*line_p = '\0';
/* skip blank lines */
if (line_p == line) {
continue;
}
*argv_p = string_copy(line);
if (*argv_p == NULL) {
*okay_bp = ARGV_FALSE;
return;
}
argv_p++;
arg_c++;
/* do we need to grow the array of pointers? */
if (arg_c == max) {
max += ARRAY_INCR;
argv = realloc(argv, sizeof(char *) * max);
if (argv == NULL) {
*okay_bp = ARGV_FALSE;
if (infile != stdin) {
(void)fclose(infile);
}
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: memory error during argument processing\n",
argv_program);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return;
}
argv_p = argv + arg_c;
}
}
/* now do the list */
do_list(grid, arg_c, argv, queue_list, queue_head_p, queue_tail_p, okay_bp);
/* now free up the list */
for (argv_p = argv; argv_p < argv + arg_c; argv_p++) {
free(*argv_p);
}
free(argv);
if (infile != stdin) {
(void)fclose(infile);
}
}
/*
* static void do_arg
*
* DESCRIPTION:
*
* Process an argument in MATCH_P which looking at GRID. sets okay_p
* to FALSE if the argument was not okay.
*
* RETURNS:
*
* None.
*
* ARGUMENTS:
*
* grid -> Our array of argv_t structures.
*
* match_p -> Entry in our argv_t structure array that matches the
* specified argument.
*
* close_p -> Pointer to the value closely associated (with an '=')
* with this option or NULL if none.
*
* queue_list <-> Our option queue for storing options to arguments.
*
* queue_head_p <-> Pointer to integer which will be updated with the
* head position in our option queue.
*
* okay_bp <- Pointer to an integer which is set with 0 if the
* arguments specified in the env variable are somehow invalid.
*/
static void do_arg(argv_t *grid, argv_t *match_p, const char *close_p,
argv_t **queue_list, int *queue_head_p, int *okay_bp)
{
if (! argv_multi_accept_b) {
/*
* have we used this one before?
* NOTE: should this be a warning or a non-error altogether?
*/
if (match_p->ar_type & ARGV_FLAG_USED
&& (! (match_p->ar_type & ARGV_FLAG_ARRAY))
&& ARGV_TYPE(match_p->ar_type) != ARGV_INCR) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, you've already specified the '%c' argument\n",
argv_program, USAGE_ERROR_NAME,
match_p->ar_short_arg);
}
*okay_bp = ARGV_FALSE;
}
}
/* we used this argument */
match_p->ar_type |= ARGV_FLAG_USED;
/* check arguments that must be OR'd */
if (check_or(grid, match_p) != NOERROR) {
/*
* don't return here else we might generate an XOR error
* because the argument wasn't specified
*/
*okay_bp = ARGV_FALSE;
}
/*
* If we have a close argument, pass to translate. If it is a
* boolean or increment variable, then pass in a value of null
* else queue it for needing a value argument.
*/
if (argv_close_enable_b && close_p != NULL) {
if (string_to_value(close_p, match_p->ar_variable,
match_p->ar_type) != NOERROR) {
*okay_bp = ARGV_FALSE;
}
}
else if (! HAS_ARG(match_p->ar_type)) {
if (string_to_value(NULL, match_p->ar_variable,
match_p->ar_type) != NOERROR) {
*okay_bp = ARGV_FALSE;
}
}
else if (argv_close_enable_b && close_p != NULL) {
if (string_to_value(close_p, match_p->ar_variable,
match_p->ar_type) != NOERROR) {
*okay_bp = ARGV_FALSE;
}
}
else {
queue_list[*queue_head_p] = match_p;
(*queue_head_p)++;
}
}
/*
* static int is_number
*
* DESCRIPTION:
*
* Examine an argument string to see if it really is a negative number
* being passed into a previously specified argument.
*
* Thanks much to Nick Kisseberth for pointing out this oversight.
*
* RETURNS:
*
* 1 if a number otherwise 0.
*
* ARGUMENTS:
*
* str - String which may be a number.
*/
static int is_number(const char *str)
{
const char *str_p;
/* empty strings are not numbers */
if (str[0] == '\0') {
return 0;
}
/*
* All chars in the string should be number chars for it to be a
* number. Yes this will return yes if the argument is "00-" but
* we'll chalk this up to user error.
*/
for (str_p = str; *str_p != '\0'; str_p++) {
if (strchr(NUMBER_ARG_CHARS, *str_p) == NULL) {
return 0;
}
}
return 1;
}
/*
* static void do_list
*
* DESCRIPTION:
*
* Process a list of arguments with our array of argv_t structures
*
* RETURNS:
*
* None.
*
* ARGUMENTS:
*
* grid - Our array of argv_t structures.
*
* arg_c - Number of arguments in argv.
*
* argv - User argument array of character pointers.
*
* queue_list <-> Our option queue for storing options to arguments.
*
* queue_head_p <-> Pointer to integer which will be updated with the
* head position in our option queue.
*
* queue_tail_p <-> Pointer to integer which will be updated with the
* tail position in our option queue.
*
* okay_bp - Pointer to an integer which is set with 0 if the
* arguments specified in the env variable are somehow invalid.
*/
static void do_list(argv_t *grid, const int arg_c, char **argv,
argv_t **queue_list, int *queue_head_p,
int *queue_tail_p, int *okay_bp)
{
argv_t *grid_p, *match_p;
int len, char_c, unwant_c = 0;
int last_arg_b = ARGV_FALSE;
char *close_p = NULL, **arg_p;
/* run throught rest of arguments */
for (arg_p = argv; arg_p < argv + arg_c; arg_p++) {
/* have we reached the LAST_ARG marker? */
if (strcmp(LAST_ARG, *arg_p) == 0) {
if (last_arg_b) {
if (argv_last_toggle_b) {
last_arg_b = ARGV_FALSE;
continue;
}
}
else {
last_arg_b = ARGV_TRUE;
continue;
}
}
/* are we processing a long option? */
if ((! last_arg_b)
&& strncmp(LONG_PREFIX, *arg_p, LONG_PREFIX_LENGTH) == 0) {
/*
* check for close equals marker
*
* NOTE: duplicated in the short prefix section below. In here otherwise
* we process normal args with x=5 instead of just -x=5.
*/
if (argv_close_enable_b) {
close_p = strchr(*arg_p, ARG_EQUALS);
/* if we found the special char then punch the null and set pointer */
if (close_p != NULL) {
*close_p = '\0';
close_p++;
}
}
/* get length of rest of argument */
len = strlen(*arg_p) - LONG_PREFIX_LENGTH;
/* we need more than the prefix */
if (len <= 0) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, empty long-option prefix '%s'\n",
argv_program, USAGE_ERROR_NAME, *arg_p);
}
*okay_bp = ARGV_FALSE;
continue;
}
match_p = NULL;
/* run though long options looking for a match */
for (grid_p = grid; grid_p->ar_short_arg != ARGV_LAST; grid_p++) {
if (grid_p->ar_long_arg == NULL) {
continue;
}
if (strncmp(*arg_p + LONG_PREFIX_LENGTH,
grid_p->ar_long_arg, len) == 0) {
if (match_p != NULL) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, '%s' might be '%s' or '%s'\n",
argv_program, USAGE_ERROR_NAME, *arg_p,
grid_p->ar_long_arg, match_p->ar_long_arg);
}
*okay_bp = ARGV_FALSE;
break;
}
/* record a possible match */
match_p = grid_p;
/* don't break, need to see if another one matches */
}
}
/* if we found a match but quit then we must have found two matches */
if (match_p != NULL && grid_p->ar_short_arg != ARGV_LAST) {
continue;
}
if (match_p != NULL) {
(void)do_arg(grid, match_p, close_p, queue_list, queue_head_p,
okay_bp);
continue;
}
/* we did not find long-option match */
/* check for special file value */
if (strncmp(FILE_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) {
if (argv_close_enable_b && close_p != NULL) {
/* open the file and read in the args */
file_args(close_p, grid, queue_list, queue_head_p, queue_tail_p,
okay_bp);
}
else {
/* HACK: we enqueue null for the file argument */
queue_list[*queue_head_p] = NULL;
(*queue_head_p)++;
}
continue;
}
/* check for special usage value */
if (strncmp(USAGE_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0
|| strncmp(HELP_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) {
if (argv_interactive) {
do_usage(grid, argv_usage_type);
(void)exit(0);
}
continue;
}
/* check for special short-usage value */
if (strncmp(USAGE_SHORT_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) {
if (argv_interactive) {
do_usage(grid, ARGV_USAGE_SHORT);
(void)exit(0);
}
continue;
}
/* check for special long-usage value */
if (strncmp(USAGE_LONG_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) {
if (argv_interactive) {
do_usage(grid, ARGV_USAGE_LONG);
(void)exit(0);
}
continue;
}
/* check for special long-usage value */
if (strncmp(USAGE_ALL_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) {
if (argv_interactive) {
do_usage(grid, ARGV_USAGE_ALL);
(void)exit(0);
}
continue;
}
/* check for special help value */
if (strncmp(HELP_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) {
if (argv_interactive) {
if (argv_error_stream != NULL) {
if (argv_help_string == NULL) {
(void)fprintf(argv_error_stream,
"%s: I'm sorry, no help is available.\n",
argv_program);
}
else {
(void)fprintf(argv_error_stream, "%s: %s\n",
argv_program, argv_help_string);
}
}
(void)exit(0);
}
continue;
}
/* check for special version value */
if (strncmp(VERSION_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) {
if (argv_interactive) {
if (argv_error_stream != NULL) {
if (argv_version_string == NULL) {
(void)fprintf(argv_error_stream,
"%s: no version information is available.\n",
argv_program);
}
else {
(void)fprintf(argv_error_stream, "%s: %s\n",
argv_program, argv_version_string);
}
}
(void)exit(0);
}
continue;
}
/* check for display arguments value */
if (strncmp(DISPLAY_ARG, *arg_p + LONG_PREFIX_LENGTH, len) == 0) {
if (argv_interactive) {
if (argv_error_stream != NULL) {
display_variables(grid);
}
(void)exit(0);
}
continue;
}
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, unknown long option '%s'.\n",
argv_program, USAGE_ERROR_NAME, *arg_p);
}
*okay_bp = ARGV_FALSE;
continue;
}
/* are we processing a short option? */
if ((! last_arg_b)
&& strncmp(SHORT_PREFIX, *arg_p, SHORT_PREFIX_LENGTH) == 0
&& !(strlen(*arg_p) == 1)) {
/*
* check for close equals marker
*
* NOTE: duplicated in the long prefix section above. In here otherwise
* we process normal args with x=5 instead of just -x=5.
*/
if (argv_close_enable_b) {
close_p = strchr(*arg_p, ARG_EQUALS);
/* if we found the special char then punch the null and set pointer */
if (close_p != NULL) {
*close_p = '\0';
close_p++;
}
}
/* get length of rest of argument */
len = strlen(*arg_p) - SHORT_PREFIX_LENGTH;
/* we need more than the prefix */
if (len <= 0) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, empty short-option prefix '%s'\n",
argv_program, USAGE_ERROR_NAME, *arg_p);
}
*okay_bp = ARGV_FALSE;
continue;
}
/* run through the chars in this option */
for (char_c = 0; char_c < len; char_c++) {
/* run through the arg list looking for a match */
for (match_p = grid; match_p->ar_short_arg != ARGV_LAST; match_p++) {
if (match_p->ar_short_arg ==
(*arg_p)[SHORT_PREFIX_LENGTH + char_c]) {
break;
}
}
/* did we not find argument? */
if (match_p->ar_short_arg == ARGV_LAST) {
/* check for special usage value */
if ((*arg_p)[SHORT_PREFIX_LENGTH + char_c] == USAGE_CHAR_ARG) {
if (argv_interactive) {
do_usage(grid, argv_usage_type);
(void)exit(0);
}
continue;
}
/*
* allow values with negative signs if we are at the start
* of an argument list, and if the argument is a number, and
* we already have a variable looking for a value. Thanks
* to Nick Kisseberth for pointing out this oversight.
*/
if (char_c == 0 && is_number(*arg_p)
&& *queue_head_p > *queue_tail_p) {
match_p = queue_list[*queue_tail_p];
/*
* NOTE: we don't advance the queue tail here unless we
* find out that we can use it below
*/
switch (ARGV_TYPE(match_p->ar_type)) {
case ARGV_SHORT:
case ARGV_INT:
case ARGV_LONG:
case ARGV_FLOAT:
case ARGV_DOUBLE:
string_to_value(*arg_p, match_p->ar_variable, match_p->ar_type);
char_c = len;
/* we actually used it so we advance the queue tail position */
(*queue_tail_p)++;
continue;
break;
}
}
/* create an error string */
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, unknown short option '%s%c'.\n",
argv_program, USAGE_ERROR_NAME, SHORT_PREFIX,
(*arg_p)[SHORT_PREFIX_LENGTH + char_c]);
}
*okay_bp = ARGV_FALSE;
continue;
}
do_arg(grid, match_p, close_p, queue_list, queue_head_p, okay_bp);
}
continue;
}
/* could this be a value? */
if (grid->ar_short_arg != ARGV_LAST && *queue_head_p > *queue_tail_p) {
/* pull the variable waiting for a value from the queue */
match_p = queue_list[*queue_tail_p];
(*queue_tail_p)++;
/* HACK: is this the file argument */
if (match_p == NULL) {
file_args(*arg_p, grid, queue_list, queue_head_p, queue_tail_p,
okay_bp);
}
else {
if (string_to_value(*arg_p, match_p->ar_variable,
match_p->ar_type) != NOERROR) {
*okay_bp = ARGV_FALSE;
}
}
continue;
}
/* process mandatory args if some left to process */
for (grid_p = grid; grid_p->ar_short_arg != ARGV_LAST; grid_p++) {
if (grid_p->ar_short_arg == ARGV_MAND
&& ((! (grid_p->ar_type & ARGV_FLAG_USED))
|| grid_p->ar_type & ARGV_FLAG_ARRAY)) {
break;
}
}
if (grid_p->ar_short_arg != ARGV_LAST) {
/* absorb another mand. arg */
if (string_to_value(*arg_p, grid_p->ar_variable,
grid_p->ar_type) != NOERROR) {
*okay_bp = ARGV_FALSE;
}
grid_p->ar_type |= ARGV_FLAG_USED;
continue;
}
/* process maybe args if some left to process */
for (grid_p = grid; grid_p->ar_short_arg != ARGV_LAST; grid_p++) {
if (grid_p->ar_short_arg == ARGV_MAYBE
&& ((! (grid_p->ar_type & ARGV_FLAG_USED))
|| grid_p->ar_type & ARGV_FLAG_ARRAY)) {
break;
}
}
if (grid_p->ar_short_arg != ARGV_LAST) {
/* absorb another maybe arg */
if (string_to_value(*arg_p, grid_p->ar_variable,
grid_p->ar_type) != NOERROR) {
*okay_bp = ARGV_FALSE;
}
grid_p->ar_type |= ARGV_FLAG_USED;
continue;
}
/* default is an error */
unwant_c++;
*okay_bp = ARGV_FALSE;
}
if (unwant_c > 0 && argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, %d unwanted additional argument%s\n",
argv_program, USAGE_ERROR_NAME,
unwant_c, (unwant_c == 1 ? "" : "s"));
}
}
/****************************** env processing *******************************/
/*
* static char ** preprocess_env_args
*
* DESCRIPTION:
*
* Preprocess the environmental variable arguments, if any.
*
* RETURNS:
*
* A (char *) array that contains the arguments which needs to be
* freed later. If it returns NULL then there are no env args.
*
* Faulure - -1
*
* ARGUMENTS:
*
* environ_pp - Pointer to a (char *) which will be set with the env
* string that will need to be freed after the env vector is processed.
*
* env_np - Pointer to an integer which is set with the number
* of environ arguments.
*/
static char **preprocess_env_args(char **environ_pp, int *env_np)
{
char env_name[1024], *environ_p;
*env_np = 0;
/* create the env variable */
LOC_SNPRINTF(SNP_ARG(env_name, sizeof(env_name)), ENVIRON_FORMAT,
argv_program);
/* NOTE: by default the env name is all uppercase */
for (environ_p = env_name; *environ_p != '\0'; environ_p++) {
if (islower((unsigned char) *environ_p)) {
*environ_p = toupper((unsigned char) *environ_p);
}
}
environ_p = getenv(env_name);
if (environ_p == NULL) {
return NULL;
}
/* break the list into tokens and do the list */
environ_p = string_copy(environ_p);
if (environ_p == NULL) {
(void)fprintf(argv_error_stream,
"%s: problems allocating memory for environmental arguments\n",
argv_program);
return NULL;
}
*environ_pp = environ_p;
return vectorize(environ_p, " \t", env_np);
}
/*
* static int process_env
*
* DESCRIPTION:
*
* Process the global env variables.
*
* RETURNS:
*
* Success - 0
*
* Faulure - -1
*
* ARGUMENTS:
*
* None.
*/
static int process_env(void)
{
static int done_b = ARGV_FALSE;
char *env_val, *tok_p, *env_p;
int len;
/* make sure we only do this once */
if (done_b) {
return NOERROR;
}
done_b = ARGV_TRUE;
/* get the argv information */
env_val = getenv(GLOBAL_NAME);
if (env_val == NULL) {
return NOERROR;
}
/* save a copy of it */
env_val = string_copy(env_val);
if (env_val == NULL) {
return ERROR;
}
env_p = env_val;
for (;;) {
tok_p = strsep(&env_p, " \t,:");
if (tok_p == NULL) {
break;
}
/* skip any empty tokens */
if (*tok_p == '\0') {
continue;
}
len = strlen(GLOBAL_CLOSE);
if (strncmp(GLOBAL_CLOSE, tok_p, len) == 0) {
tok_p += len;
if (strcmp(tok_p, "disable") == 0
|| strcmp(tok_p, "off") == 0
|| strcmp(tok_p, "no") == 0
|| strcmp(tok_p, "0") == 0) {
argv_close_enable_b = 0;
}
else if (strcmp(tok_p, "enable") == 0
|| strcmp(tok_p, "on") == 0
|| strcmp(tok_p, "yes") == 0
|| strcmp(tok_p, "1") == 0) {
argv_close_enable_b = 1;
}
else {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: illegal env variable '%s' '%s' argument '%s'\n",
__FILE__, GLOBAL_NAME, GLOBAL_CLOSE, tok_p);
}
}
continue;
}
len = strlen(GLOBAL_LASTTOG);
if (strncmp(GLOBAL_LASTTOG, tok_p, len) == 0) {
tok_p += len;
if (strcmp(tok_p, "disable") == 0
|| strcmp(tok_p, "off") == 0
|| strcmp(tok_p, "no") == 0
|| strcmp(tok_p, "0") == 0) {
argv_last_toggle_b = 0;
}
else if (strcmp(tok_p, "enable") == 0
|| strcmp(tok_p, "on") == 0
|| strcmp(tok_p, "yes") == 0
|| strcmp(tok_p, "1") == 0) {
argv_last_toggle_b = 1;
}
else {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: illegal env variable '%s' '%s' argument '%s'\n",
__FILE__, GLOBAL_NAME, GLOBAL_LASTTOG, tok_p);
}
}
continue;
}
len = strlen(GLOBAL_ENV);
if (strncmp(GLOBAL_ENV, tok_p, len) == 0) {
tok_p += len;
if (strcmp(tok_p, "none") == 0) {
argv_process_env_b = 0;
argv_env_after_b = 0;
}
else if (strcmp(tok_p, "before") == 0) {
argv_process_env_b = 1;
argv_env_after_b = 0;
}
else if (strcmp(tok_p, "after") == 0) {
argv_process_env_b = 1;
argv_env_after_b = 1;
}
else {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: illegal env variable '%s' '%s' argument '%s'\n",
__FILE__, GLOBAL_NAME, GLOBAL_ENV, tok_p);
}
}
continue;
}
len = strlen(GLOBAL_ERROR);
if (strncmp(GLOBAL_ERROR, tok_p, len) == 0) {
tok_p += len;
if (strcmp(tok_p, "none") == 0) {
argv_error_type = ARGV_USAGE_NONE;
}
else if (strcmp(tok_p, "see") == 0) {
argv_error_type = ARGV_USAGE_SEE;
}
else if (strcmp(tok_p, "short") == 0) {
argv_error_type = ARGV_USAGE_SHORT;
}
else if (strcmp(tok_p, "shortrem") == 0) {
argv_error_type = ARGV_USAGE_SHORT_REM;
}
else if (strcmp(tok_p, "long") == 0) {
argv_error_type = ARGV_USAGE_LONG;
}
else if (strcmp(tok_p, "all") == 0) {
argv_error_type = ARGV_USAGE_ALL;
}
else {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: illegal env variable '%s' '%s' argument '%s'\n",
__FILE__, GLOBAL_NAME, GLOBAL_ERROR, tok_p);
}
}
continue;
}
len = strlen(GLOBAL_MULTI);
if (strncmp(GLOBAL_MULTI, tok_p, len) == 0) {
tok_p += len;
if (strcmp(tok_p, "reject") == 0) {
argv_multi_accept_b = 0;
}
else if (strcmp(tok_p, "accept") == 0) {
argv_multi_accept_b = 1;
}
else {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: illegal env variable '%s' '%s' argument '%s'\n",
__FILE__, GLOBAL_NAME, GLOBAL_MULTI, tok_p);
}
}
continue;
}
len = strlen(GLOBAL_USAGE);
if (strncmp(GLOBAL_USAGE, tok_p, len) == 0) {
tok_p += len;
if (strcmp(tok_p, "short") == 0) {
argv_usage_type = ARGV_USAGE_SHORT;
}
else if (strcmp(tok_p, "shortrem") == 0) {
argv_usage_type = ARGV_USAGE_SHORT_REM;
}
else if (strcmp(tok_p, "long") == 0) {
argv_usage_type = ARGV_USAGE_LONG;
}
else if (strcmp(tok_p, "all") == 0) {
argv_usage_type = ARGV_USAGE_ALL;
}
else {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: illegal env variable '%s' '%s' argument '%s'\n",
__FILE__, GLOBAL_NAME, GLOBAL_USAGE, tok_p);
}
}
continue;
}
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: illegal env variable '%s' setting '%s'\n",
__FILE__, GLOBAL_NAME, tok_p);
}
}
free(env_val);
return NOERROR;
}
/***************************** exported routines *****************************/
/*
* int argv_process_no_env
*
* DESCRIPTION:
*
* Process the user arguments with an argv_t structure array. Like
* argv_process_args but without the processing of the argv
* environmental variables.
*
* RETURNS:
*
* Success - 0
*
* Failure - -1
*
* ARGUMENTS:
*
* args - Array of argv_t structures.
*
* arg_n - Number of arguments in the argv array.
*
* argv - Array of character pointers terminated by 0L.
*/
int argv_process_no_env(argv_t *args, const int arg_n, char **argv)
{
int entry_c;
const char *prog_p;
char **env_vect_p, *environ_p = NULL;
int okay_b = ARGV_TRUE;
argv_t *arg_p;
argv_t **queue_list = NULL;
int queue_head = 0, queue_tail = 0, env_n, total_arg_n;
if (args == NULL) {
args = empty;
}
if (arg_n < 0) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, argc argument to argv_process is %d\n",
__FILE__, INTERNAL_ERROR_NAME, arg_n);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return ERROR;
}
if (argv == NULL) {
if (argv_error_stream != NULL) {
(void)fprintf(argv_error_stream,
"%s: %s, argv argument to argv_process is NULL\n",
__FILE__, INTERNAL_ERROR_NAME);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return ERROR;
}
/* set global variables */
argv_argv = argv;
argv_argc = arg_n;
/* build the program name from the argv[0] path */
{
const char *tmp_p;
prog_p = *argv;
for (tmp_p = *argv; *tmp_p != '\0'; tmp_p++) {
if (*tmp_p == '/') {
prog_p = tmp_p + 1;
}
}
}
/* so we can step on the environmental space */
(void)strncpy(argv_program, prog_p, PROGRAM_NAME);
/* count the args */
entry_c = 0;
for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) {
entry_c++;
}
/* verify the argument array */
if (preprocess_array(args, entry_c) != NOERROR) {
return ERROR;
}
/* preprocess environmental args */
env_vect_p = preprocess_env_args(&environ_p, &env_n);
total_arg_n = arg_n + env_n;
/* allocate our value queue */
if (total_arg_n > 0) {
/* allocate our argument queue */
queue_list = (argv_t **)malloc(sizeof(argv_t *) * total_arg_n);
if (queue_list == NULL) {
return ERROR;
}
queue_head = 0;
queue_tail = 0;
}
/* do the env args before? */
if (argv_process_env_b && (! argv_env_after_b) && env_vect_p != NULL) {
do_list(args, env_n, env_vect_p, queue_list, &queue_head, &queue_tail,
&okay_b);
free(env_vect_p);
free(environ_p);
env_vect_p = NULL;
}
/* do the external args */
do_list(args, arg_n - 1, argv + 1, queue_list, &queue_head, &queue_tail,
&okay_b);
/* DO the env args after? */
if (argv_process_env_b && argv_env_after_b && env_vect_p != NULL) {
do_list(args, env_n, env_vect_p, queue_list, &queue_head, &queue_tail,
&okay_b);
free(env_vect_p);
free(environ_p);
env_vect_p = NULL;
}
/* make sure the XOR and MAND args and argument-options are okay */
if (check_mand(args) != NOERROR) {
okay_b = ARGV_FALSE;
}
if (check_opt(queue_head, queue_tail) != NOERROR) {
okay_b = ARGV_FALSE;
}
if (check_xor(args) != NOERROR) {
okay_b = ARGV_FALSE;
}
/* if we allocated the space then free it */
if (arg_n > 0) {
free(queue_list);
}
/* was there an error? */
if (! okay_b) {
if (argv_error_stream != NULL) {
do_usage(args, argv_error_type);
}
if (argv_interactive) {
(void)exit(argv_error_code);
}
return ERROR;
}
return NOERROR;
}
/*
* int argv_process
*
* DESCRIPTION:
*
* Processes a number of arguments depending on the argument array.
* This routine will not modify the argv array in any way.
*
* NOTE: it will modify the args array by setting various flags in the
* type field. returns 0 if no error else -1.
*
* ARGUMENTS:
*
* args - Array of argv_t structures that we are using to process the
* user argument array. If null then an empty array is used.
*
* argc - Number of arguments in the argv argument array.
*
* argv - Array of character pointer arguments terminated by a 0L.
*/
int argv_process(argv_t *args, const int argc, char **argv)
{
if (! enabled_b) {
argv_startup();
}
/* we only process env variables here */
if (process_env() != NOERROR) {
return ERROR;
}
if (argv_process_no_env(args, argc, argv) == NOERROR) {
return NOERROR;
}
else {
return ERROR;
}
}
/*
* int argv_usage
*
* DESCRIPTION:
*
* Print the standard usage messages for our argument array. You can
* specify whether you want to see a short or long usage messages.
*
* NOTE: if this is called before argv_process then the program name
* may be invalid.
*
* RETURNS:
*
* Success - 0
*
* Failure - -1
*
* ARGUMENTS:
*
* args - Our argument array to print the usage messages about. If
* null then an empty array is used.
*
* which - Either ARGV_USAGE_SHORT (for short usage messages),
* ARGV_USAGE_LONG (for long usage messages), or ARGV_USAGE_DEFAULT
* (the user's default either long or short).
*/
int argv_usage(const argv_t *args, const int which)
{
if (! enabled_b) {
argv_startup();
}
if (process_env() != NOERROR) {
return ERROR;
}
if (args == NULL) {
args = empty;
}
if (which == ARGV_USAGE_SHORT
|| which == ARGV_USAGE_LONG
|| which == ARGV_USAGE_ALL) {
do_usage(args, which);
}
else {
/* default/env settings */
do_usage(args, argv_usage_type);
}
return NOERROR;
}
/*
* int argv_was_used
*
* DESCRIPTION:
*
* See if an argument was used in a previous call to argv_process.
*
* RETURNS:
*
* 1 if yes it was used, else 0 if not.
*
* ARGUMENTS:
*
* args - Argument list to search.
*
* short_arg - Short argument to see if it was used.
*/
int argv_was_used(const argv_t *args, const char short_arg)
{
const argv_t *arg_p;
if (! enabled_b) {
argv_startup();
}
for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) {
if (arg_p->ar_short_arg == short_arg) {
if (arg_p->ar_type & ARGV_FLAG_USED) {
return 1;
}
else {
return 0;
}
}
}
return 0;
}
/*
* int argv_long_was_used
*
* DESCRIPTION:
*
* See if a long argument was used in a previous call to argv_process.
*
* RETURNS:
*
* 1 if yes it was used, else 0 if not.
*
* ARGUMENTS:
*
* args - Argument list to search.
*
* long_arg - Long argument to see if it was used.
*/
int argv_long_was_used(const argv_t *args, const char *long_arg)
{
const argv_t *arg_p;
if (! enabled_b) {
argv_startup();
}
for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) {
if (arg_p->ar_long_arg == long_arg) {
if (arg_p->ar_type & ARGV_FLAG_USED) {
return 1;
}
else {
return 0;
}
}
}
return 0;
}
/*
* int argv_entry_was_used
*
* DESCRIPTION:
*
* See if an entry in the argument array was used in a previous call
* to argv_process.
*
* RETURNS:
*
* 1 if yes it was used, else 0 if not.
*
* ARGUMENTS:
*
* argv_entry_p - Pointer to an entry in a argv_t list.
*/
int argv_entry_was_used(const argv_t *argv_entry_p)
{
if (argv_entry_p->ar_type & ARGV_FLAG_USED) {
return 1;
}
else {
return 0;
}
}
/*
* void argv_cleanup
*
* DESCRIPTION:
*
* Frees up any allocations associated with the argument array during
* argv_process. This should be done at the end of the program or
* after all the arguments have been referenced.
*
* RETURNS:
*
* None.
*
* ARGUMENTS:
*
* args - Argument array we are cleaning up.
*/
void argv_cleanup(const argv_t *args)
{
const argv_t *arg_p;
int entry_c;
if (! enabled_b) {
argv_startup();
}
if (args == NULL) {
return;
}
/* run through the argument structure */
for (arg_p = args; arg_p->ar_short_arg != ARGV_LAST; arg_p++) {
/* handle any arrays */
if (arg_p->ar_type & ARGV_FLAG_ARRAY) {
argv_array_t *arr_p = (argv_array_t *)arg_p->ar_variable;
/* free any entries */
if (arr_p->aa_entry_n > 0) {
if (ARGV_TYPE(arg_p->ar_type) == ARGV_CHAR_P) {
for (entry_c = 0; entry_c < arr_p->aa_entry_n; entry_c++) {
free(ARGV_ARRAY_ENTRY(*arr_p, char *, entry_c));
}
}
free(arr_p->aa_entries);
}
arr_p->aa_entries = NULL;
arr_p->aa_entry_n = 0;
continue;
}
/* handle individual charps */
if (arg_p->ar_type & ARGV_FLAG_USED
&& ARGV_TYPE(arg_p->ar_type) == ARGV_CHAR_P) {
free(*(char **)arg_p->ar_variable);
continue;
}
}
}
/*
* int argv_copy_args
*
* DESCRIPTION:
*
* Copy all the arguements (not including the 0th) one after the other
* into the user specified buffer.
*
* NOTE: you can get the 0th argument from argv_argv[0] or
* argv_program.
*
* RETURNS:
*
* Success - 0
*
* Failure - -1
*
* ARGUMENTS:
*
* buf - Buffer to copy all of the user arguments into.
*
* buf_size - Size of the buffer.
*/
int argv_copy_args(char *buf, const int buf_size)
{
char **argv_p, *buf_p = buf, *arg_p;
int arg_c, size_c = buf_size;
if (! enabled_b) {
argv_startup();
}
if (buf_size <= 0) {
return NOERROR;
}
*buf_p = '\0';
if (argv_argv == NULL || buf_size == 1) {
return NOERROR;
}
for (argv_p = argv_argv + 1, arg_c = 1;
arg_c < argv_argc;
argv_p++, arg_c++) {
/* we compare against 2 for the ' ' and the \0 */
if (size_c < 2) {
break;
}
if (argv_p > argv_argv + 1) {
*buf_p++ = ' ';
size_c--;
}
/* we always compare against 2 to include the \0 */
for (arg_p = *argv_p; *arg_p != '\0' && size_c >= 2; size_c--) {
*buf_p++ = *arg_p++;
}
}
*buf_p = '\0';
return NOERROR;
}
/*
* int argv_value_string
*
* DESCRIPTION:
*
* Convert the value of a RC entry to its string equivalent in the
* buffer provided.
*
* RETURNS:
*
* Length of bytes copied into the buffer.
*
* ARGUMENTS:
*
* argv_entry_p - Pointer to an entry in a argv_t list.
*
* buf - Buffer to convert the value into.
*
* buf_size - Size of the buffer.
*/
int argv_value_string(const argv_t *argv_entry_p, char *buf,
const int buf_size)
{
argv_array_t *arr_p;
int ret, len;
char details[128];
if (! enabled_b) {
argv_startup();
}
/* do we have an array here? */
if (argv_entry_p->ar_type & ARGV_FLAG_ARRAY) {
/* if we have an array, then */
arr_p = (argv_array_t *)argv_entry_p->ar_variable;
if (arr_p->aa_entry_n == 0) {
strncpy(buf, "0 array entries", buf_size);
buf[buf_size - 1] = '\0';
ret = strlen(buf);
}
else {
len = value_to_string(arr_p->aa_entries,
ARGV_TYPE(argv_entry_p->ar_type),
buf, buf_size);
if (arr_p->aa_entry_n == 1) {
ret = len;
}
else {
LOC_SNPRINTF(SNP_ARG(details, sizeof(details)), " (1st of %d entries)",
arr_p->aa_entry_n);
strncpy(buf + len, details, buf_size - len);
buf[buf_size - 1] = '\0';
ret = strlen(buf);
}
}
}
else {
ret = value_to_string(argv_entry_p->ar_variable, argv_entry_p->ar_type,
buf, buf_size);
}
return ret;
}
/*
* int argv_type_info
*
* DESCRIPTION:
*
* Get internal information about the type of the argument.
*
* RETURNS:
*
* The name of the type.
*
* ARGUMENTS:
*
* type - Number of argument type.
*
* size_p - Pointer to an unsigned integer which, if not NULL, will be
* set with the size of the type.
*
* desc_p - Pointer to a constant character pointer which, if not
* NULL, will be pointed to a description of the type.
*/
const char *argv_type_info(const unsigned int type, unsigned int *size_p,
const char **desc_p)
{
unsigned int val_type;
argv_type_t *type_p;
val_type = ARGV_TYPE(type);
for (type_p = argv_types; type_p->at_value != 0; type_p++) {
if (type_p->at_value == val_type) {
if (size_p != NULL) {
*size_p = type_p->at_size;
}
if (desc_p != NULL) {
*desc_p = type_p->at_desc;
}
return type_p->at_name;
}
}
if (size_p != NULL) {
*size_p = 0;
}
if (desc_p != NULL) {
*desc_p = "Unknown type";
}
return "(unknown type)";
}
fstrm-0.2.0/libmy/argv.h 0000644 0001750 0001750 00000035741 12330751177 012031 0000000 0000000 /*
* Defines for a generic argv and argc processor...
*
* Copyright 2000 by Gray Watson
*
* This file is part of the argv library.
*
* Permission to use, copy, modify, and distribute this software for
* any purpose and without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies, and that the name of Gray Watson not be used in advertising
* or publicity pertaining to distribution of the document or software
* without specific, written prior permission.
*
* Gray Watson makes no representations about the suitability of the
* software described herein for any purpose. It is provided "as is"
* without express or implied warranty.
*
* The author may be contacted via http://256.com/gray/
*
* $Id: argv.h.1,v 1.22 2010/02/15 13:59:37 gray Exp $
*/
#ifndef __ARGV_H__
#define __ARGV_H__
#ifdef __cplusplus
extern "C" {
#if 0
}
#endif
#endif
/*
* Version string for the library
*
* NOTE to gray: whenever this is changed, corresponding Changlog and
* NEWS entries *must* be entered and argv.texi updated.
*
* ARGV LIBRARY VERSION -- 2.7.0
*/
/* argv version defines */
#define ARGV_VERSION_MAJOR 2 /* X.0.0 */
#define ARGV_VERSION_MINOR 7 /* 0.X.0 */
#define ARGV_VERSION_PATCH 0 /* 0.0.X */
/* produced by configure, inserted into argv.h */
/* used to handle the const operator */
/* const is available */
/* NOTE: start of $Id: argv.h.3,v 1.33 2007/01/08 20:32:57 gray Exp $ */
/*
* Generic and standardized argument processor. You describe the arguments
* that you are looking for along with their types and these routines do the
* work to convert them into values.
*
* These routines also provide standardized error and usage messages as well
* as good usage documentation and long and short options.
*/
#include /* have to for FILE * below */
/* this defines what type the standard void memory-pointer is */
#if (defined(__STDC__) && __STDC__ == 1) || defined(__cplusplus)
#define ARGV_PNT void *
#else
#define ARGV_PNT char *
#endif
/*
* argument information structure. this specifies the allowable options
* and some information about each one.
*
* { 'O', "optimize", ARGV_BOOL, &optimize, NULL, "turn on optimization" }
* { 'c', "config", ARGV_CHAR_P, &config, "file", "configuration file" }
*/
typedef struct {
char ar_short_arg; /* short argument, 'd' if '-d' */
const char *ar_long_arg; /* long version of arg, '--delete' */
unsigned int ar_type; /* type of option, see values below */
ARGV_PNT ar_variable; /* address of associated variable */
const char *ar_var_label; /* label for variable description */
const char *ar_comment; /* comment for usage message */
} argv_t;
/*
* Argument array type. when ARGV_FLAG_ARRAY is |'d with the ar_type
* in the above structure then multiple instances of the option are
* allowed and each instance is stored into the following structure
* that MUST be in ar_variable in the above arg_t structure.
*
* NOTE: after the arguments have been processed, if aa_entryn is > 0
* then aa_entries needs to be free'd by user. argv_cleanup() can be
* used for this
*/
typedef struct {
int aa_entry_n; /* number of elements in aa_entrees */
ARGV_PNT aa_entries; /* entry list specified */
} argv_array_t;
/* extract the count of the elements from an argv ARRAY */
#define ARGV_ARRAY_COUNT(array) ((array).aa_entry_n)
/* extract WHICH entry of TYPE from an argv ARRAY */
#define ARGV_ARRAY_ENTRY(array, type, which) \
(((type *)(array).aa_entries)[which])
/* extract a pointer to WHICH entry of TYPE from an argv ARRAY */
#define ARGV_ARRAY_ENTRY_P(array, type, which) \
(((type *)(array).aa_entries) + which)
/* special ar_short_arg value to mark the last entry in the argument array */
#define ARGV_LAST ((char)255)
/*
* special ar_short_arg value to mark mandatory arguments (i.e. arguments that
* *must* be specified. for arguments that are not optional like [-b].
* to have a variable number of mandatory args then make the last MAND
* entry be a ARG_ARRAY type.
*/
#define ARGV_MAND ((char)254)
/*
* special ar_short_arg value to mark that there is the possibility of
* a mandatory argument here if one is specified.
*/
#define ARGV_MAYBE ((char)253)
/*
* special ar_short_arg value to say that the previous and next arguments in
* the list should not be used together.
* {'a'...}, {ARG_OR}, {'b'...}, {ARG_OR}, {'c'...} means
* the user should only specific -a or -b or -c but not 2 or more.
*/
#define ARGV_OR ((char)252)
/*
* special ar_short_arg value that is the same as ARGV_OR but one of the args
* must be used.
* {'a'...}, {ARG_ONE_OF}, {'b'...}, {ARG_ONE_OF}, {'c'...} means
* the user must specify one of -a or -b or -c but not 2 or more.
* ARGV_XOR is there for compatibility with older versions.
*/
#define ARGV_ONE_OF ((char)251)
#define ARGV_XOR ((char)251)
/*
* ar_type values of arg_t
* NOTE: if this list is changed, some defines in argv_loc need to be changed
*/
#define ARGV_BOOL 1 /* boolean type, sets to ARGV_TRUE */
#define ARGV_BOOL_NEG 2 /* like bool but sets to ARGV_FALSE */
#define ARGV_BOOL_ARG 3 /* like bool but takes a yes/no arg */
#define ARGV_CHAR 4 /* single character */
#define ARGV_CHAR_P 5 /* same as STRING */
#define ARGV_SHORT 6 /* short integer number */
#define ARGV_U_SHORT 7 /* unsigned short integer number */
#define ARGV_INT 8 /* integer number */
#define ARGV_U_INT 9 /* unsigned integer number */
#define ARGV_LONG 10 /* long integer number */
#define ARGV_U_LONG 11 /* unsinged long integer number */
#define ARGV_FLOAT 12 /* floating pointer number */
#define ARGV_DOUBLE 13 /* double floating pointer number */
#define ARGV_BIN 14 /* binary number (0s and 1s) */
#define ARGV_OCT 15 /* octal number, (base 8) */
#define ARGV_HEX 16 /* hexadecimal number, (base 16) */
#define ARGV_INCR 17 /* int arg which gets ++ each time */
#define ARGV_SIZE 18 /* long arg which knows mMbBkKgG */
#define ARGV_U_SIZE 19 /* u_long arg which knows mMbBkKgG */
#define ARGV_BOOL_INT 20 /* like bool but takes an integer var*/
#define ARGV_BOOL_INT_NEG 21 /* like bool-neg but with an integer */
#define ARGV_BOOL_INT_ARG 22 /* like bool-arg but with an integer */
#define ARGV_TYPE(t) ((t) & 0x3F) /* strip off all but the var type */
#define ARGV_FLAG_ARRAY (1 << 14) /* OR with type to indicate array */
#define ARGV_FLAG_MAND (1 << 13) /* OR with type to mark mandatory */
/* NOTE: other internal flags defined in argv_loc.h */
/* argv_usage which argument values */
#define ARGV_USAGE_NONE 0 /* no usage messages -- special */
#define ARGV_USAGE_SHORT 1 /* print short usage messages */
#define ARGV_USAGE_LONG 2 /* print long-format usage messages */
#define ARGV_USAGE_DEFAULT 3 /* default usage messages */
#define ARGV_USAGE_SEE 4 /* say see --usage for more info */
#define ARGV_USAGE_SHORT_REM 5 /* short + reminder how to get long */
#define ARGV_USAGE_ALL 6 /* all usage information */
/* boolean type settings */
#define ARGV_FALSE 0
#define ARGV_TRUE 1
/*<<<<<<<<<< The below prototypes are auto-generated by fillproto */
/* This is a processed version of argv[0], pre-path removed: /bin/ls -> ls */
extern
char argv_program[/* PROGRAM_NAME + 1 */];
/* A global value of argv from main after argv_process has been called */
extern
char **argv_argv;
/* A global value of argc from main after argv_process has been called */
extern
int argv_argc;
/* This should be set externally to provide general program help to user */
extern
char *argv_help_string;
/* This should be set externally to provide version information to the user */
extern
char *argv_version_string;
/*
* Are we running interactively? This will exit on errors. Set to
* false to return error codes instead.
*/
extern
int argv_interactive;
/*
* The FILE stream that argv out_puts all its errors. Set to NULL to
* not dump any error messages. Default is stderr.
*/
extern
FILE *argv_error_stream;
/*
* This is the error code to exit with when we have a usage error and
* we are in interactive mode.
*/
extern
int argv_error_code;
/*
* Set to 1 (the default) to enable the handling of -l=foo or
* --logfile=foo type of arguments. Set to 0 to disable. This allows
* you to specifically assign a value to an argument.
*/
extern
int argv_close_enable_b;
/*
* If the library sees a "--" argument, it will turn off further
* argument process. Set to 1 to enable the ability of specifying
* additional "--" arguments to reenable (basically toggle on then
* off) argument processing. Set to 0 (the default) to disable this
* behavior.
*/
extern
int argv_last_toggle_b;
/*
* Set to 1 (the default) to have the library accept multiple usage of
* the same argument. Set to 0 to have the library generate an error
* if you use an argument twice.
*/
extern
int argv_multi_accept_b;
/*
* Set to one of the ARGV_USAGE_ defines in the argv.h file. This
* tell the library what usage information to display when --usage is
* specified by the user. Default is ARGV_USAGE_LONG.
*/
extern
int argv_usage_type;
/*
* Set to one of the ARGV_USAGE_ defines in the argv.h file. This
* tell the library what usage information to display when an error is
* encountered. The usage information accompanies the error message.
* Default is ARGV_USAGE_SEE.
*/
extern
int argv_error_type;
/*
* Set to 1 (the default) if you want the library look for associated
* arguments from the associated program's environmental variable. If
* set the 0 then no environmental variable will be used. If you are
* running program foo then the library will look for the
* environmental variable ARGV_foo and will add those to the argument
* list specified on the command line. By default they will be
* inserted in front of those on the command line unless the
* argv_env_after_b is set to 1.
*
* NOTE: this is set by argv_process automatically. If you do not
* want this behavior, you should use argv_process_no_env.
*/
extern
int argv_process_env_b;
/*
* Set to 1 if you want the library to append the arguments from the
* program's environmental variable after those specified on the
* command line. If set the 0 (the default) then they will be
* inserted before those specified on the command line. See
* argv_process_env_b for more information.
*/
extern
int argv_env_after_b;
/*
* int argv_process_no_env
*
* DESCRIPTION:
*
* Process the user arguments with an argv_t structure array. Like
* argv_process_args but without the processing of the argv
* environmental variables.
*
* RETURNS:
*
* Success - 0
*
* Failure - -1
*
* ARGUMENTS:
*
* args - Array of argv_t structures.
*
* arg_c - Number of arguments in the argv array.
*
* argv - Array of character pointers terminated by 0L.
*/
extern
int argv_process_no_env(argv_t *args, const int arg_c, char **argv);
/*
* int argv_process
*
* DESCRIPTION:
*
* Processes a number of arguments depending on the argument array.
* This routine will not modify the argv array in any way.
*
* NOTE: it will modify the args array by setting various flags in the
* type field. returns 0 if no error else -1.
*
* ARGUMENTS:
*
* args - Array of argv_t structures that we are using to process the
* user argument array. If null then an empty array is used.
*
* argc - Number of arguments in the argv argument array.
*
* argv - Array of character pointer arguments terminated by a 0L.
*/
extern
int argv_process(argv_t *args, const int argc, char **argv);
/*
* int argv_usage
*
* DESCRIPTION:
*
* Print the standard usage messages for our argument array. You can
* specify whether you want to see a short or long usage messages.
*
* NOTE: if this is called before argv_process then the program name
* may be invalid.
*
* RETURNS:
*
* Success - 0
*
* Failure - -1
*
* ARGUMENTS:
*
* args - Our argument array to print the usage messages about. If
* null then an empty array is used.
*
* which - Either ARGV_USAGE_SHORT (for short usage messages),
* ARGV_USAGE_LONG (for long usage messages), or ARGV_USAGE_DEFAULT
* (the user's default either long or short).
*/
extern
int argv_usage(const argv_t *args, const int which);
/*
* int argv_was_used
*
* DESCRIPTION:
*
* See if an argument was used in a previous call to argv_process.
*
* RETURNS:
*
* 1 if yes it was used, else 0 if not.
*
* ARGUMENTS:
*
* args - Argument list to search.
*
* short_arg - Short argument to see if it was used.
*/
extern
int argv_was_used(const argv_t *args, const char short_arg);
/*
* int argv_long_was_used
*
* DESCRIPTION:
*
* See if a long argument was used in a previous call to argv_process.
*
* RETURNS:
*
* 1 if yes it was used, else 0 if not.
*
* ARGUMENTS:
*
* args - Argument list to search.
*
* long_arg - Long argument to see if it was used.
*/
extern
int argv_long_was_used(const argv_t *args, const char *long_arg);
/*
* int argv_entry_was_used
*
* DESCRIPTION:
*
* See if an entry in the argument array was used in a previous call
* to argv_process.
*
* RETURNS:
*
* 1 if yes it was used, else 0 if not.
*
* ARGUMENTS:
*
* argv_entry_p - Pointer to an entry in a argv_t list.
*/
extern
int argv_entry_was_used(const argv_t *argv_entry_p);
/*
* void argv_cleanup
*
* DESCRIPTION:
*
* Frees up any allocations associated with the argument array during
* argv_process. This should be done at the end of the program or
* after all the arguments have been referenced.
*
* RETURNS:
*
* None.
*
* ARGUMENTS:
*
* args - Argument array we are cleaning up.
*/
extern
void argv_cleanup(const argv_t *args);
/*
* int argv_copy_args
*
* DESCRIPTION:
*
* Copy all the arguements (not including the 0th) one after the other
* into the user specified buffer.
*
* NOTE: you can get the 0th argument from argv_argv[0] or
* argv_program.
*
* RETURNS:
*
* Success - 0
*
* Failure - -1
*
* ARGUMENTS:
*
* buf - Buffer to copy all of the user arguments into.
*
* buf_size - Size of the buffer.
*/
extern
int argv_copy_args(char *buf, const int buf_size);
/*
* int argv_value_string
*
* DESCRIPTION:
*
* Convert the value of a RC entry to its string equivalent in the
* buffer provided.
*
* RETURNS:
*
* Length of bytes copied into the buffer.
*
* ARGUMENTS:
*
* argv_entry_p - Pointer to an entry in a argv_t list.
*
* buf - Buffer to convert the value into.
*
* buf_size - Size of the buffer.
*/
extern
int argv_value_string(const argv_t *argv_entry_p, char *buf,
const int buf_size);
/*
* int argv_type_info
*
* DESCRIPTION:
*
* Get internal information about the type of the argument.
*
* RETURNS:
*
* The name of the type.
*
* ARGUMENTS:
*
* type - Number of argument type.
*
* size_p - Pointer to an unsigned integer which, if not NULL, will be
* set with the size of the type.
*
* desc_p - Pointer to a constant character pointer which, if not
* NULL, will be pointed to a description of the type.
*/
extern
const char *argv_type_info(const unsigned int type, unsigned int *size_p,
const char **desc_p);
/*<<<<<<<<<< This is end of the auto-generated output from fillproto. */
#ifdef __cplusplus
#if 0
{
#endif
}
#endif
#endif /* ! __ARGV_H__ */
fstrm-0.2.0/libmy/argv_loc.h 0000644 0001750 0001750 00000017113 12330751177 012657 0000000 0000000 /*
* Local defines for the argv module
*
* Copyright 2000 by Gray Watson
*
* This file is part of the argv library.
*
* Permission to use, copy, modify, and distribute this software for
* any purpose and without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies, and that the name of Gray Watson not be used in advertising
* or publicity pertaining to distribution of the document or software
* without specific, written prior permission.
*
* Gray Watson makes no representations about the suitability of the
* software described herein for any purpose. It is provided "as is"
* without express or implied warranty.
*
* The author may be contacted via http://256.com/gray/
*
* $Id: argv_loc.h,v 1.50 2007/01/08 20:32:57 gray Exp $
*/
#ifndef __ARGV_LOC_H__
#define __ARGV_LOC_H__
#ifdef __cplusplus
extern "C" {
#if 0
}
#endif
#endif
#include "argv.h" /* to get the types */
/*
* some compilation options
*/
/* to include RCS ids in the code */
#ifndef INCLUDE_RCS_IDS
#define INCLUDE_RCS_IDS 1
#endif
/*
* generic constants
*/
/* special consideration for NULL. some compilers bitch if I redefine it */
#ifndef NULL
#define NULL 0L
#endif
#undef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#undef NOERROR
#define NOERROR 0
#undef ERROR
#define ERROR (-1)
#undef STDIN
#define STDIN 0
/*
* local argv defines
*/
#define ERROR_STREAM_INIT (FILE *)0x1 /* hack to init stderr FILE* */
#define NO_VALUE (-1) /* no mandatory args value */
#define ARRAY_INCR 10 /* increment by 10 every 10 */
#define SCREEN_WIDTH 79 /* width of screen till wrap */
#define BITS_IN_BYTE 8 /* bits in a byte */
#define SPECIAL_CHARS "e\033^^\"\"''\\\\n\nr\rt\tb\bf\fa\007"
#define DUMP_SPACE_BUF 128 /* space for memory dump */
#define ARG_MALLOC_INCR 20 /* alloc in 10 increments */
#define FILE_LINE_SIZE 1024 /* max size of file lines */
/* internal flags set in the ar_type field */
/* NOTE: other external flags defined in argv.h */
#define ARGV_FLAG_USED (1 << 12) /* if arg has been specified */
/* error messages */
#define USAGE_ERROR_NAME "usage problem"
#define INTERNAL_ERROR_NAME "internal argv error"
/*
* settings to vary the output of the argument routines
*/
#define PROGRAM_NAME 256 /* max size of program name */
#define EXIT_CODE 1 /* argv exit code for errors */
/* global env settings */
#define GLOBAL_NAME "GLOBAL_ARGV" /* global argv env name */
#define GLOBAL_CLOSE "close=" /* close arg setting */
#define GLOBAL_ENV "env=" /* env setting */
#define GLOBAL_ERROR "error=" /* error setting */
#define GLOBAL_MULTI "multi=" /* multi setting */
#define GLOBAL_USAGE "usage=" /* usage setting */
#define GLOBAL_LASTTOG "lasttog=" /* last-arg toggle */
/* special argument definitions */
#define LAST_ARG "--" /* arg to mark end of args */
#define LONG_PREFIX "--" /* prefix for long args */
#define SHORT_PREFIX "-" /* prefix for short args */
#define UNKNOWN_ARG "??" /* unknown argument output */
#define ARG_EQUALS '=' /* to assign value to option */
#define NUMBER_ARG_CHARS "0123456789+-." /* characters in numbers */
/* how to produce the env var using sprintf and the argv_program variable */
#define ENVIRON_FORMAT "ARGV_%s"
/* special short-argument strings */
#define USAGE_CHAR_ARG '?' /* default short-opt usage */
/* special long-argument strings */
#define DISPLAY_ARG "argv-display" /* display arg variable vals */
#define FILE_ARG "argv-file" /* read args from file */
#define HELP_ARG "help" /* default help option */
#define USAGE_ARG "usage" /* default usage option */
#define USAGE_SHORT_ARG "usage-short" /* default usage-short opt */
#define USAGE_LONG_ARG "usage-long" /* default usage-long opt */
#define USAGE_ALL_ARG "usage-all" /* default usage-all opt */
#define VERSION_ARG "version" /* default version option */
/* spacing on line for usage messages */
#define SHORT_COLUMN 0 /* spaces to indent for short-args */
#define LONG_COLUMN 18 /* column for long options */
#define COMMENT_COLUMN 34 /* column for comments */
/* some in-line "labels" for comments */
#define USAGE_LABEL "Usage: " /* usage message start */
#define LONG_LABEL "or " /* put before long-option */
#define COMMENT_LABEL "" /* put before comments */
#define ARRAY_LABEL " array" /* put after displayed type */
#define BOOL_ARG_LABEL "yes|no" /* label for bool-arg arg */
/* some sizeof defines */
#define SHORT_PREFIX_LENGTH (sizeof(SHORT_PREFIX) - 1)
#define LONG_PREFIX_LENGTH (sizeof(LONG_PREFIX) - 1)
#define USAGE_LABEL_LENGTH (sizeof(USAGE_LABEL) - 1)
#define COMMENT_LABEL_LENGTH (sizeof(COMMENT_LABEL) - 1)
#define LONG_LABEL_LENGTH (sizeof(LONG_LABEL) - 1)
#define UNKNOWN_ARG_LENGTH (sizeof(UNKNOWN_ARG) - 1)
#define BOOL_ARG_LENGTH (sizeof(BOOL_ARG_LABEL) - 1)
#define HAS_ARG(type) (! (ARGV_TYPE(type) == ARGV_BOOL \
|| ARGV_TYPE(type) == ARGV_BOOL_NEG \
|| ARGV_TYPE(type) == ARGV_INCR \
|| ARGV_TYPE(type) == ARGV_BOOL_INT \
|| ARGV_TYPE(type) == ARGV_BOOL_INT_NEG))
/******************************** argv types *********************************/
/* strcture defining argv types */
typedef struct {
unsigned int at_value; /* value of the type */
const char *at_name; /* name of the type */
unsigned int at_size; /* size of type */
const char *at_desc; /* description of the type */
} argv_type_t;
static argv_type_t argv_types[] = {
{ ARGV_BOOL, "flag", sizeof(char),
"if option used, set variable to 1" },
{ ARGV_BOOL_NEG, "negative flag", sizeof(int),
"if option used, set variable to 0" },
{ ARGV_BOOL_ARG, "flag with arg", sizeof(char),
"like boolean but with an argument, true/yes/1 sets var to 1" },
{ ARGV_CHAR, "character", sizeof(char),
"single character" },
{ ARGV_CHAR_P, "string", sizeof(char *),
"multiple characters terminated with a '\\0'" },
{ ARGV_SHORT, "short integer", sizeof(short),
"decimal short-sized integer value" },
{ ARGV_U_SHORT, "unsigned short integer", sizeof(unsigned short),
"decimal unsigned short-sized integer value" },
{ ARGV_INT, "integer", sizeof(int),
"decimal integer value" },
{ ARGV_U_INT, "unsigned integer", sizeof(unsigned int),
"decimal unsigned integer value" },
{ ARGV_LONG, "long integer", sizeof(long),
"decimal long-sized integer value" },
{ ARGV_U_LONG, "unsigned long", sizeof(unsigned long),
"decimal unsigned long-sized integer value" },
{ ARGV_FLOAT, "floating point", sizeof(float),
"real number with decimal point" },
{ ARGV_DOUBLE, "double floating point", sizeof(double),
"double precision real number with decimal point" },
{ ARGV_BIN, "binary", sizeof(int),
"base 2 value with digits of 0 or 1" },
{ ARGV_OCT, "octal", sizeof(int),
"base 8 value with digits from 0-7" },
{ ARGV_HEX, "hexadecimal", sizeof(int),
"base 16 value with digits from 0-9, A-F" },
{ ARGV_INCR, "increment", sizeof(int),
"increment variable each time option used" },
{ ARGV_SIZE, "long size", sizeof(long),
"size as long int + [bkmg] b=byte,k=kilo,m=meg,g=gig" },
{ ARGV_U_SIZE, "unsigned long size", sizeof(unsigned long),
"size as unsigned long int + [bkmg] b=byte,k=kilo,m=meg,g=gig" },
{ ARGV_BOOL_INT, "integer boolean", sizeof(int),
"if option used, set integer variable to 1" },
{ ARGV_BOOL_INT_NEG, "integer boolean", sizeof(int),
"if option used, set integer variable to 0" },
{ ARGV_BOOL_INT_ARG, "integer boolean", sizeof(int),
"like boolean but with an argument, true/yes/1 sets integer var to 1" },
{ 0, NULL, 0, NULL }
};
#ifdef __cplusplus
#if 0
{
#endif
}
#endif
#endif /* ! __ARGV_LOC_H__ */
fstrm-0.2.0/libmy/print_string.h 0000644 0001750 0001750 00000002101 12330751177 013574 0000000 0000000 /*
* Copyright (c) 2012 by Farsight Security, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MY_PRINT_STRING_H
#define MY_PRINT_STRING_H
#include
#include
#include
static inline void
print_string(const void *data, size_t len, FILE *out)
{
uint8_t *str = (uint8_t *) data;
fputc('"', out);
while (len-- != 0) {
unsigned c = *(str++);
if (isprint(c)) {
if (c == '"')
fputs("\\\"", out);
else
fputc(c, out);
} else {
fprintf(out, "\\x%02x", c);
}
}
fputc('"', out);
}
#endif /* MY_PRINT_STRING_H */
fstrm-0.2.0/libmy/my_time.h 0000644 0001750 0001750 00000002641 12342165401 012516 0000000 0000000 #ifndef MY_TIME_H
#define MY_TIME_H
#include
#include
#include
#include
#if HAVE_CLOCK_GETTIME
static inline void
my_gettime(clockid_t clk_id, struct timespec *ts)
{
int res;
res = clock_gettime(clk_id, ts);
assert(res == 0);
}
#else
static inline void
my_gettime(int clk_id __attribute__((unused)), struct timespec *ts)
{
struct timeval tv;
int res;
res = gettimeofday(&tv, NULL);
assert(res == 0);
ts->tv_sec = tv.tv_sec;
ts->tv_nsec = tv.tv_usec * 1000;
}
#endif
static inline void
my_timespec_add(const struct timespec *a, struct timespec *b) {
b->tv_sec += a->tv_sec;
b->tv_nsec += a->tv_nsec;
while (b->tv_nsec >= 1000000000) {
b->tv_sec += 1;
b->tv_nsec -= 1000000000;
}
}
static inline void
my_timespec_sub(const struct timespec *a, struct timespec *b)
{
b->tv_sec -= a->tv_sec;
b->tv_nsec -= a->tv_nsec;
if (b->tv_nsec < 0) {
b->tv_sec -= 1;
b->tv_nsec += 1000000000;
}
}
static inline double
my_timespec_to_double(const struct timespec *ts)
{
return (ts->tv_sec + ts->tv_nsec / 1E9);
}
static inline void
my_timespec_from_double(double seconds, struct timespec *ts) {
ts->tv_sec = (time_t) seconds;
ts->tv_nsec = (long) ((seconds - ((int) seconds)) * 1E9);
}
static inline void
my_nanosleep(const struct timespec *ts)
{
struct timespec rqt, rmt;
for (rqt = *ts; nanosleep(&rqt, &rmt) < 0 && errno == EINTR; rqt = rmt)
;
}
#endif /* MY_TIME_H */
fstrm-0.2.0/m4/ 0000755 0001750 0001750 00000000000 12427010215 010157 5 0000000 0000000 fstrm-0.2.0/m4/ax_pthread.m4 0000644 0001750 0001750 00000031267 12330751177 012505 0000000 0000000 # ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
#
# DESCRIPTION
#
# This macro figures out how to build C programs using POSIX threads. It
# sets the PTHREAD_LIBS output variable to the threads library and linker
# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
# flags that are needed. (The user can also force certain compiler
# flags/libs to be tested by setting these environment variables.)
#
# Also sets PTHREAD_CC to any special C compiler that is needed for
# multi-threaded programs (defaults to the value of CC otherwise). (This
# is necessary on AIX to use the special cc_r compiler alias.)
#
# NOTE: You are assumed to not only compile your program with these flags,
# but also link it with them as well. e.g. you should link with
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
#
# If you are only building threads programs, you may wish to use these
# variables in your default LIBS, CFLAGS, and CC:
#
# LIBS="$PTHREAD_LIBS $LIBS"
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# CC="$PTHREAD_CC"
#
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
#
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
# PTHREAD_CFLAGS.
#
# ACTION-IF-FOUND is a list of shell commands to run if a threads library
# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
# is not found. If ACTION-IF-FOUND is not specified, the default action
# will define HAVE_PTHREAD.
#
# Please let the authors know if this macro fails on any platform, or if
# you have any other suggestions or comments. This macro was based on work
# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
# Alejandro Forero Cuervo to the autoconf macro repository. We are also
# grateful for the helpful feedback of numerous users.
#
# Updated for Autoconf 2.68 by Daniel Richard G.
#
# LICENSE
#
# Copyright (c) 2008 Steven G. Johnson
# Copyright (c) 2011 Daniel Richard G.
#
# 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 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, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 20
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
AC_DEFUN([AX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
AC_LANG_PUSH([C])
ax_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on True64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes)
AC_MSG_RESULT($ax_pthread_ok)
if test x"$ax_pthread_ok" = xno; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
fi
# We must check for the threads library under a number of different
# names; the ordering is very important because some systems
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items starting with a "-" are
# C compiler flags, and other items are library names, except for "none"
# which indicates that we try without any flags at all, and "pthread-config"
# which is a program returning the flags for the Pth emulation library.
ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
# pthreads: AIX (must check this before -lpthread)
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
# -pthreads: Solaris/gcc
# -mthreads: Mingw32/gcc, Lynx/gcc
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads too;
# also defines -D_REENTRANT)
# ... -mt is also the pthreads flag for HP/aCC
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)
case ${host_os} in
solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
# a function called by this macro, so we could check for that, but
# who knows whether they'll stub that too in a future libc.) So,
# we'll just look for -pthreads and -lpthread first:
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
;;
darwin*)
ax_pthread_flags="-pthread $ax_pthread_flags"
;;
esac
if test x"$ax_pthread_ok" = xno; then
for flag in $ax_pthread_flags; do
case $flag in
none)
AC_MSG_CHECKING([whether pthreads work without any flags])
;;
-*)
AC_MSG_CHECKING([whether pthreads work with $flag])
PTHREAD_CFLAGS="$flag"
;;
pthread-config)
AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no)
if test x"$ax_pthread_config" = xno; then continue; fi
PTHREAD_CFLAGS="`pthread-config --cflags`"
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
;;
*)
AC_MSG_CHECKING([for the pthreads library -l$flag])
PTHREAD_LIBS="-l$flag"
;;
esac
save_LIBS="$LIBS"
save_CFLAGS="$CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
# need a special flag -Kthread to make this header compile.)
# We check for pthread_join because it is in -lpthread on IRIX
# while pthread_create is in libc. We check for pthread_attr_init
# due to DEC craziness with -lpthreads. We check for
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include
static void routine(void *a) { a = 0; }
static void *start_routine(void *a) { return a; }],
[pthread_t th; pthread_attr_t attr;
pthread_create(&th, 0, start_routine, 0);
pthread_join(th, 0);
pthread_attr_init(&attr);
pthread_cleanup_push(routine, 0);
pthread_cleanup_pop(0) /* ; */])],
[ax_pthread_ok=yes],
[])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
AC_MSG_RESULT($ax_pthread_ok)
if test "x$ax_pthread_ok" = xyes; then
break;
fi
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
done
fi
# Various other checks:
if test "x$ax_pthread_ok" = xyes; then
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
AC_MSG_CHECKING([for joinable pthread attribute])
attr_name=unknown
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ],
[int attr = $attr; return attr /* ; */])],
[attr_name=$attr; break],
[])
done
AC_MSG_RESULT($attr_name)
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
[Define to necessary symbol if this constant
uses a non-standard name on your system.])
fi
AC_MSG_CHECKING([if more special flags are required for pthreads])
flag=no
case ${host_os} in
aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
osf* | hpux*) flag="-D_REENTRANT";;
solaris*)
if test "$GCC" = "yes"; then
flag="-D_REENTRANT"
else
flag="-mt -D_REENTRANT"
fi
;;
esac
AC_MSG_RESULT(${flag})
if test "x$flag" != xno; then
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
fi
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
ax_cv_PTHREAD_PRIO_INHERIT, [
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT;]])],
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
[ax_cv_PTHREAD_PRIO_INHERIT=no])
])
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.]))
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
# More AIX lossage: compile with *_r variant
if test "x$GCC" != xyes; then
case $host_os in
aix*)
AS_CASE(["x/$CC"],
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
[#handle absolute path differently from PATH based program lookup
AS_CASE(["x$CC"],
[x/*],
[AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
[AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
;;
esac
fi
fi
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
AC_SUBST(PTHREAD_LIBS)
AC_SUBST(PTHREAD_CFLAGS)
AC_SUBST(PTHREAD_CC)
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test x"$ax_pthread_ok" = xyes; then
ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
:
else
ax_pthread_ok=no
$2
fi
AC_LANG_POP
])dnl AX_PTHREAD
fstrm-0.2.0/m4/ld-version-script.m4 0000644 0001750 0001750 00000003364 12330751177 013747 0000000 0000000 # ld-version-script.m4 serial 3
dnl Copyright (C) 2008-2014 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl From Simon Josefsson
# FIXME: The test below returns a false positive for mingw
# cross-compiles, 'local:' statements does not reduce number of
# exported symbols in a DLL. Use --disable-ld-version-script to work
# around the problem.
# gl_LD_VERSION_SCRIPT
# --------------------
# Check if LD supports linker scripts, and define automake conditional
# HAVE_LD_VERSION_SCRIPT if so.
AC_DEFUN([gl_LD_VERSION_SCRIPT],
[
AC_ARG_ENABLE([ld-version-script],
AS_HELP_STRING([--enable-ld-version-script],
[enable linker version script (default is enabled when possible)]),
[have_ld_version_script=$enableval], [])
if test -z "$have_ld_version_script"; then
AC_MSG_CHECKING([if LD -Wl,--version-script works])
save_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map"
cat > conftest.map < conftest.map <