#!/bin/sh # Copyright (c) 2016-2018, Carsten Kunze # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. usage () { echo "Usage: $0 [-s] [-D ...]" echo " -s Silence output" echo " -D" echo " Add define to CFLAGS" exit $1 } SFLAG= MAKE= DEFS= LIB_LEX= LIB_CURSES= cat /dev/null > compat.h while [ $# -gt 0 ]; do case $1 in -s) SFLAG=1 ;; -D*) DEFS="$DEFS $1" ;; *) echo "$0: $1: Unknown option" >&2 usage 1 ;; esac shift done check_for () { [ -e $LOG ] && cat <>$LOG ================================================================================ EOT A="Checking for $1 ... " printf "$A\n\n" >>$LOG [ -z "$SFLAG" ] && printf "$A" } compile () { rm -f ${TMPNAM}.o $TMPNAM $OUT $ERR $MAKE -f $OUTMK $TMPNAM > $OUT 2> $ERR RESULT=$? cat $OUT $ERR >> $LOG if [ $RESULT -eq 0 ]; then true; else false; fi } test_result () { RESULT=$? RESULT_TEXT=${1:-0} # 1: omit "no", 2: say nothing if [ $RESULT -eq 0 ]; then echo success >>$LOG [ -z "$SFLAG" -a $RESULT_TEXT -lt 2 ] && \ echo "yes$PASS_TEXT" PASS_TEXT= [ -e $TMPC ] && rm -f $TMPC true else [ -z "$SFLAG" -a $RESULT_TEXT -lt 1 ] && echo no if [ -e $TMPC ]; then echo "Failed program:" >>$LOG pr -n -t $TMPC >>$LOG rm -f $TMPC fi false fi } gen_mk () { [ $# -eq 0 ] && rm -f $OUTMK [ -n "$LEX" ] && echo "LEX=$LEX" >> $OUTMK [ -n "$FLOAT_STORE" ] && echo "FLOAT_STORE=$FLOAT_STORE" >> $OUTMK [ -n "$DEFS" ] && echo "DEFINES=$DEFS" >> $OUTMK [ -n "$INCDIR_CURSES" ] && echo "INCDIR_CURSES=$INCDIR_CURSES" >> $OUTMK [ -n "$RPATH_CURSES" ] && echo "RPATH_CURSES=$RPATH_CURSES" >> $OUTMK [ -n "$LIBDIR_CURSES" ] && echo "LIBDIR_CURSES=$LIBDIR_CURSES" \ >> $OUTMK [ -n "$LIB_CURSES" ] && echo "LIB_CURSES=$LIB_CURSES" >> $OUTMK [ -n "$LIB_AVLBST" ] && echo "LIB_AVLBST=$LIB_AVLBST" >> $OUTMK [ -n "$LIB_LEX" ] && echo "LIB_LEX=$LIB_LEX" >> $OUTMK [ -n "$__CDBG" ] && echo "__CDBG=$__CDBG" >> $OUTMK [ -n "$__CXXDBG" ] && echo "__CXXDBG=$__CXXDBG" >> $OUTMK [ -n "$__CLDBG" ] && echo "__CLDBG=$__CLDBG" >> $OUTMK [ -n "$__CLXXDBG" ] && echo "__CLXXDBG=$__CLXXDBG" >> $OUTMK cat $INMK >> $OUTMK || exit 1 } check_make () { check_for "make(1)" cat <$TMPMK all: true EOT make -f $TMPMK >> $LOG 2>&1 test_result && { MAKE=make return } echo "Failed makefile:" >>$LOG pr -n -t $TMPMK >>$LOG check_for "bmake(1)" cat <$TMPMK all: true EOT bmake -f $TMPMK >> $LOG 2>&1 test_result && MAKE=bmake } check_strlcpy () { check_for "strlcpy(3)" cat <$TMPC #include int main(int argc, char **argv) { char a[10]; (void)argc; strlcpy(a, *argv, sizeof a); return 0; } EOT compile if test_result; then DEFS="$DEFS -DHAVE_STRLCPY" else H=compat.h grep -q '' $H 2>/dev/null || cat <>$H #include EOT cat <>$H size_t strlcpy(char *, const char *, size_t); EOT fi } check_strlcat () { check_for "strlcat(3)" cat <$TMPC #include int main(int argc, char **argv) { char a[10]; (void)argc; *a = 0; strlcat(a, *argv, sizeof a); return 0; } EOT compile if test_result; then DEFS="$DEFS -DHAVE_STRLCAT" else H=compat.h grep -q '' $H 2>/dev/null || cat <>$H #include EOT cat <>$H size_t strlcat(char *, const char *, size_t); EOT fi } check_Sanitizer () { check_for "CC Sanitizer" # C only __CDBG= __CLDBG= __CCXXDBG= # C++ only __CXXDBG= __CLXXDBG= __CDBG="$__CDBG -Wmissing-prototypes" __CDBG="$__CDBG -Wstrict-prototypes" __CCXXDBG="$__CCXXDBG -g -O0 -fno-omit-frame-pointer -fno-optimize-sibling-calls" __CCXXDBG="$__CCXXDBG -Wall" __CCXXDBG="$__CCXXDBG -Wextra" __CCXXDBG="$__CCXXDBG -Wbad-function-cast" __CCXXDBG="$__CCXXDBG -Wcast-align" __CCXXDBG="$__CCXXDBG -Wcast-qual" #__CCXXDBG="$__CCXXDBG -Wconversion" __CCXXDBG="$__CCXXDBG -Wfloat-equal" __CCXXDBG="$__CCXXDBG -Wlogical-not-parentheses" __CCXXDBG="$__CCXXDBG -Wshadow" __CCXXDBG="$__CCXXDBG -Wsign-compare" __CCXXDBG="$__CCXXDBG -Wundef" __CCXXDBG="$__CCXXDBG -Wuninitialized" __CCXXDBG="$__CCXXDBG -Wunused-parameter" __CCXXDBG="$__CCXXDBG -Wunused-function" __CCXXDBG="$__CCXXDBG -Wwrite-strings" __CLXXDBG="$__CLXXDBG -fno-common -fsanitize=address -fsanitize=undefined" #__CLXXDBG="$__CLXXDBG -fsanitize-recover=all" [ -n "$CC" ] || CC=cc VER=`$CC --version` if echo $VER | grep -iq gcc || echo $VER | \ grep -iq 'Free Software Foundation'; then [ -z "$SFLAG" ] && printf "(gcc) " #__CCXXDBG="$__CCXXDBG -Wduplicated-branches" __CCXXDBG="$__CCXXDBG -Wduplicated-cond" __CCXXDBG="$__CCXXDBG -Wjump-misses-init" __CCXXDBG="$__CCXXDBG -Wlogical-op" #__CLXXDBG="$__CLXXDBG -fprofile-arcs -ftest-coverage" __CLXXDBG="$__CLXXDBG -fsanitize=float-divide-by-zero" __CLXXDBG="$__CLXXDBG -fsanitize=float-cast-overflow" elif echo $VER | grep -q clang; then [ -z "$SFLAG" ] && printf "(clang) " __CCXXDBG="$__CCXXDBG -Wincompatible-pointer-types-discards-qualifiers" __CCXXDBG="$__CCXXDBG -Wmissing-variable-declarations" __CXXDBG="$__CXXDBG -Wunused-private-field" __CLXXDBG="$__CLXXDBG -fsanitize=unsigned-integer-overflow" else [ -z "$SFLAG" ] && echo "Unknown compiler" return fi # Most C++ options can be used for C too __CDBG="$__CDBG $__CCXXDBG" __CLDBG="$__CLDBG $__CLXXDBG" __CXXDBG="$__CXXDBG $__CCXXDBG" cat <$TMPC int main() { return 0; } EOT gen_mk cat <>$OUTMK $TMPNAM: ${TMPNAM}.o \$(CC) \$(__CDBG) \$(__CLDBG) -o \$@ ${TMPNAM}.o EOT compile test_result || { __CLDBG= __CLXXDBG= } } [ ! -s compat.h ] && rm compat.h OUTMK=Makefile INMK=${OUTMK}.in CFG=config TMPNAM=.$CFG TMPMK=${TMPNAM}.mk TMPC=${TMPNAM}.c TMPL=${TMPNAM}.l # For lex tests only ... OUT=${TMPNAM}.out ERR=${TMPNAM}.err LOG=${CFG}.log rm -f $LOG gen_mk check_make check_strlcpy check_strlcat #check_Sanitizer __CLDBG=`echo $__CLDBG | sed 's/-fsanitize=address//'` __CLXXDBG=`echo $__CLXXDBG | sed 's/-fsanitize=address//'` TermTest () { check_for "$1" Term="$1" echo "TERMLIB=$1" > $OUTMK gen_mk 1 cat <>$OUTMK $TMPNAM: ${TMPNAM}.o \$(TLIB) \$(CC) \$(WARN) \$(DEFINES) -o \$@ ${TMPNAM}.o \$(TERMLIB) EOT cat <>$TMPC #include int tgetent(char *, const char *); int main() { char tcbuf[2048]; char *terms[] = { "xterm", "screen" }; unsigned i; for (i = 0; i < sizeof(terms)/sizeof(*terms); i++) if (tgetent(tcbuf, terms[i]) != 1) { fprintf(stderr, "Unknown terminal type \"%s\"\n", terms[i]); return i + 1; } return 0; } EOT compile test_result 2 && ./$TMPNAM 2>> $LOG && { echo yes return } echo no false } TestLocalTermlib () { #TermTest "-Llibterm -ltermlib" && return TermTest "-ltinfo" && return TermTest "-lncurses" && return ODEFS=$DEFS D="-I/usr/pkg/include -L/usr/pkg/lib -Wl,-rpath,/usr/pkg/lib" DEFS="$DEFS $D" TermTest "-lncurses $D" && return DEFS=$ODEFS TermTest "-lcurses" && return TermTest "-Llibterm -ltermlib" && return } TestLocalTermlib echo "TERMLIB=$Term" > $OUTMK gen_mk 1 rm -f $TMPNAM*