?RCS: $Id: Cppsym.U,v 3.0.1.5 1995/05/12 11:59:11 ram Exp $
?RCS:
?RCS: Copyright (c) 1991-1993, Raphael Manfredi
?RCS:
?RCS: You may redistribute only under the terms of the Artistic License,
?RCS: as specified in the README file that comes with the distribution.
?RCS: You may reuse parts of this distribution only within the terms of
?RCS: that same Artistic License; a copy of which may be found at the root
?RCS: of the source tree for dist 3.0.
?RCS:
?RCS: $Log: Cppsym.U,v $
?RCS: Revision 3.0.1.5  1995/05/12  11:59:11  ram
?RCS: patch54: split awk command onto two lines for older awk's (ADO)
?RCS:
?RCS: Revision 3.0.1.4  1995/01/11  14:55:57  ram
?RCS: patch45: new cc vs. cpp symbol checking suggested by JHI
?RCS: patch45: added more cpp symbols (JHI)
?RCS:
?RCS: Revision 3.0.1.3  1994/10/29  15:51:32  ram
?RCS: patch36: added ?F: line for metalint file checking
?RCS: patch36: new symbols ardent and titan (ADO)
?RCS:
?RCS: Revision 3.0.1.2  1994/06/20  06:53:32  ram
?RCS: patch30: extended cpp symbol lookup list (JHI)
?RCS: patch30: renamed attrlist symbol into al for brevity
?RCS:
?RCS: Revision 3.0.1.1  1993/12/15  08:14:14  ram
?RCS: patch15: added new cpp symbols __bsdi__ and BSD_NET2
?RCS:
?RCS: Revision 3.0  1993/08/18  12:04:50  ram
?RCS: Baseline for dist 3.0 netwide release.
?RCS:
?X: This unit produces a shell script called Cppsym, which can be used to
?X: determine whether any in a list of symbols is defined by the C compilation
?X: chain (C preprocessor symbols plus C compiler native ones).
?X: It can determine the status of any symbol, though the symbols in $al
?X: are more easily determined.  If you want to add to $al you can do
?X: it in Myinit.U.
?MAKE:Cppsym ccsymbols cppsymbols cppccsymbols: run \
	eunicefix Guess awk cat tr sed sort rm rm_try startsh osname \
	+cc +gccversion test comm uniq echo Options trnl \
	optimize ccflags ldflags libs cpp_stuff cpp
?MAKE:	-pick add $@ %<
?T:also symbols i postprocess_cc_v tHdrH
?X:
?X: The symbol list is in alpha order for ease of maintenance...
?X:
?X: Lots of new symbols (mostly rummaged from gcc), courtesy of
?X: Jarkko Hietaniemi <jhi@snakemail.hut.fi> -- RAM, 06/06/94
?X:
?S:ccsymbols:
?S:	The variable contains the symbols defined by the C compiler alone.
?S:	The symbols defined by cpp or by cc when it calls cpp are not in
?S:	this list, see cppsymbols and cppccsymbols.
?S:	The list is a space-separated list of symbol=value tokens.
?S:.
?S:cppsymbols:
?S:	The variable contains the symbols defined by the C preprocessor
?S:	alone.  The symbols defined by cc or by cc when it calls cpp are
?S:	not in this list, see ccsymbols and cppccsymbols.
?S:	The list is a space-separated list of symbol=value tokens.
?S:.
?S:cppccsymbols:
?S:	The variable contains the symbols defined by the C compiler
?S:	when it calls cpp.  The symbols defined by the cc alone or cpp
?S:	alone are not in this list, see ccsymbols and cppsymbols.
?S:	The list is a space-separated list of symbol=value tokens.
?S:.
?F:./Cppsym
?F:./Cppsym.know
?F:!Cppsym.true
?F:!ccsym.com
?F:!ccsym.cpp
?F:!ccsym.own
?X: fake LINT hints
?LINT:change ccflags
?LINT:extern s
?LINT:extern s__
: Preprocessor symbols
echo " "
$echo "Guessing which symbols your C compiler and preprocessor define..." >&4
?X: If your symbol is mixed case, just add it as-is.
?X: All symbols will be transformed to both all-lower and all-upper.
?X: Also drop any leading/trailing underscores, the scan will try all those.
$cat <<'EOSH' > Cppsym.know
a29k aarch64 ABI64 aegis AES_SOURCE AIX AIX32 AIX370 AIX41 AIX42
AIX43 aixpc AIX_SOURCE alliant ALL_SOURCE alpha AM29000 am29000
AMD64 amd64 amiga AMIGAOS AMIX ansi ANSI_C_SOURCE apollo arch_ppc
arch_pwr ardent ARM ARM32 atarist att386 att3b
BeOS BIG_ENDIAN BIT_MSF BSD bsd bsd43 bsd4_2 BSD4_3 bsd4_3 bsd4_4
BSDCOMPAT bsdi BSD_4_3 BSD_4_4 BSD_NET2 BSD_TIME BSD_TYPES bull
byteorder byte_order
c cadmus clang clipper CMU COFF COMPILER_VERSION concurrent
convex cpu CRAY cray CRAYMPP ctix CX_UX CYGWIN
DECC DGUX DGUX_SOURCE DJGPP dmert DOLPHIN DPX2 DSO Dynix DynixPTX
ELF encore EPI EXTENSIONS
FAVOR_BSD FILE_OFFSET_BITS FORTIFY_SOURCE FreeBSD
GCC_NEW_VARARGS gcos gcx gimpel GLIBC GLIBC_MINOR GNUC GNUC_MINOR
GNU_LIBRARY GNU_SOURCE GO32 gould GOULD_PN
H3050R H3050RX hbullx20 hcx host_mips hp200 hp300 HP700 hp700
hp800 hp9000 hp9000s200 hp9000s300 hp9000s400
hp9000s700 hp9000s800 hp9k8 hppa hpux HPUX_SOURCE hp_osf
i186 i286 i386 i486 i586 i686 i8086 i80960 i860 I960 IA32 IA64
iAPX286 ibm ibm032 ibmesa IBMR2 ibmrt ILP32 ILP64
INLINE_INTRINSICS INT64 INTEL interdata INTRINSICS is68k itanium
ksr1
LANGUAGE_C LARGEFILE64_SOURCE LARGEFILE_SOURCE LARGE_FILE_API
LFS64_LARGEFILE LFS_LARGEFILE LIBCATAMOUNT Linux LITTLE_ENDIAN
LONG64 LONGDOUBLE LONGLONG LONG_DOUBLE LONG_LONG LP64 luna
luna88k Lynx
M68000 m68k m88100 m88k M88KBCS_TARGET MACH machine MachTen
MATH_HAS_NO_SIDE_EFFECTS mc300 mc500 mc68000 mc68010 mc68020
mc68030 mc68040 mc68060 mc68k mc68k32 mc700 mc88000 mc88100
merlin mert MiNT mips MIPSEB MIPSEL MIPS_FPSET MIPS_ISA MIPS_SIM
MIPS_SZINT MIPS_SZLONG MIPS_SZPTR MODERN_C motorola MSDOS
MTXINU MULTIMAX MVS mvs M_AMD64 M_ARM M_ARMT M_COFF M_I186 M_I286
M_I386 M_I8086 M_I86 M_I86SM M_IA64 M_IX86 M_PPC M_SYS3 M_SYS5
M_SYSIII M_SYSV M_UNIX M_X86 M_XENIX
n16 ncl_el ncl_mr NetBSD news1500 news1700 news1800 news1900
news3700 news700 news800 news900 NeXT NLS nonstopux ns16000
ns32000 ns32016 ns32332 ns32k nsc32000
OCS88 OEMVS OpenBSD os OS2 OS390 osf OSF1 OSF_SOURCE
PARAGON parisc pa_risc PA_RISC1_1 PA_RISC2_0 pc532 pdp11 PGC PIC
plexus PORTAR posix POSIX1B_SOURCE POSIX2_SOURCE POSIX4_SOURCE
POSIX_C_SOURCE POSIX_SOURCE POWER powerpc ppc PROTOTYPES PWB pyr
QK_USER QNX
R3000 REENTRANT RES Rhapsody RISC6000 riscix riscos RT
S390 S390x SA110 SCO scs sequent sgi SGI_SOURCE SH SH3 sinix
SIZE_INT SIZE_LONG SIZE_PTR SOCKETS_SOURCE SOCKET_SOURCE sony
sonyrisc sony_news sparc sparclite sparcv8 sparcv9 spectrum
stardent stdc STDC_EXT stratos sun sun3 sun386 Sun386i svr3 svr4
SVR4_2 SVR4_SOURCE svr5 SX system SYSTYPE_BSD SYSTYPE_BSD43
SYSTYPE_BSD44 SYSTYPE_SVR4 SYSTYPE_SVR5 SYSTYPE_SYSV SYSV SYSV3
SYSV4 SYSV5 sysV68 sysV88
Tek4132 Tek4300 thumb thw_370 thw_intel thw_rs6000 titan TM3200
TM5400 TM5600 tower tower32 tower32_200 tower32_600 tower32_700
tower32_800 tower32_850 tss
u370 u3b u3b2 u3b20 u3b200 u3b20d u3b5 ultrix UMAXV UnicomPBB
UnicomPBD UNICOS UNICOSMK unix UNIX95 UNIX99 unixpc unos USE_BSD
USE_FILE_OFFSET64 USE_GNU USE_ISOC9X USE_LARGEFILE
USE_LARGEFILE64 USE_MISC USE_POSIX USE_POSIX199309
USE_POSIX199506 USE_POSIX2 USE_REENTRANT USE_SVID USE_UNIX98
USE_XOPEN USE_XOPEN_EXTENDED USGr4 USGr4_2 UTek Utek UTS UWIN
uxpm uxps
vax venix VMESA vms
x86_64 xenix Xenix286 XOPEN_SOURCE XOPEN_SOURCE_EXTENDED XPG2
XPG2_EXTENDED XPG3 XPG3_EXTENDED XPG4 XPG4_EXTENDED
z8000 zarch
EOSH
# Maybe put other stuff here too.
?X:Some OS's will have a dash in their $osname
?X:e.g. Android is known as linux-android
?X:The preprocessor will interpret the dash as a minus
./tr '-' '_' <<EOSH >>Cppsym.know
$osname
EOSH
./tr '[a-z]' '[A-Z]' < Cppsym.know > Cppsym.a
./tr '[A-Z]' '[a-z]' < Cppsym.know > Cppsym.b
$cat Cppsym.know > Cppsym.c
$cat Cppsym.a Cppsym.b Cppsym.c | $tr ' ' $trnl | $sort | $uniq > Cppsym.know
$rm -f Cppsym.a Cppsym.b Cppsym.c
cat <<EOSH > Cppsym
$startsh
if $test \$# -gt 0; then
    echo \$* | $tr " " "$trnl" | ./Cppsym.try > Cppsym.got
    if $test -s Cppsym.got; then
	$rm -f Cppsym.got
	exit 0
    fi
    $rm -f Cppsym.got
    exit 1
else
    $tr " " "$trnl" | ./Cppsym.try
    exit 0
fi
EOSH
chmod +x Cppsym
$eunicefix Cppsym
?X: The below awk script will die a horrible death if
?X: some of the tested symbols are not long ints.
?X: Also, we do not make difference between just defined and defined zero.
cat <<EOSH > Cppsym.try
$startsh
cat <<'EOCP' > try.c
#include <stdio.h>
#if cpp_stuff == 1
#define STRINGIFY(a)    "a"
#endif
#if cpp_stuff == 42
#define StGiFy(a)  #a
#define STRINGIFY(a)    StGiFy(a)
#endif
#if $cpp_stuff != 1 && $cpp_stuff != 42
#   include "Bletch: How does this C preprocessor stringify macros?"
#endif
int main() {
EOCP
?X: The length($1) command guards against possible empty entries.
?X: The awk snippet is know to give heartburn to UNICOS/mk awk.
$awk \\
EOSH
cat <<'EOSH' >> Cppsym.try
'length($1) > 0 {
    printf "#ifdef %s\nprintf(\"%s=%%s\\n\", STRINGIFY(%s));\n#endif\n", $1, $1, $1
    printf "#ifdef _%s\nprintf(\"_%s=%%s\\n\", STRINGIFY(_%s));\n#endif\n", $1, $1, $1
    printf "#ifdef __%s\nprintf(\"__%s=%%s\\n\", STRINGIFY(__%s));\n#endif\n", $1, $1, $1
    printf "#ifdef __%s__\nprintf(\"__%s__=%%s\\n\", STRINGIFY(__%s__));\n#endif\n", $1, $1, $1
}' >> try.c
echo 'return 0;}' >> try.c
EOSH
cat <<EOSH >> Cppsym.try
ccflags="$ccflags"
case "$osname-$gccversion" in
irix-) ccflags="\$ccflags -woff 1178" ;;
os2-*) ccflags="\$ccflags -Zlinker /PM:VIO" ;;
esac
$cc -o try -Dcpp_stuff=$cpp_stuff $optimize \$ccflags $ldflags try.c $libs 2>/dev/null && $run ./try | $sed 's/ /\\\\ /g'
EOSH
chmod +x Cppsym.try
$eunicefix Cppsym.try
./Cppsym < Cppsym.know | $sort | $uniq > Cppsym.true
: Add in any Linux cpp "predefined macros":
case "$osname::$gccversion" in
  *linux*::*.*|*gnukfreebsd*::*.*|gnu::*.*)
    tHdrH=_tmpHdr
    rm -f $tHdrH'.h' $tHdrH
    touch $tHdrH'.h'
    # Filter out macro arguments, such as Linux's __INT8_C(c)
    if $cpp -dM $tHdrH'.h' > $tHdrH'_cppsym.h' && [ -s $tHdrH'_cppsym.h' ]; then
       sed -e 's/#define[\ \  ]*//;s/[\ \     ].*$//' -e 's/(.*//' <$tHdrH'_cppsym.h' >$tHdrH'_cppsym.real'
       if [ -s $tHdrH'_cppsym.real' ]; then
	  cat $tHdrH'_cppsym.real' Cppsym.know | sort | uniq | ./Cppsym | sort | uniq > Cppsym.true
       fi
    fi
    rm -f $tHdrH'.h' $tHdrH'_cppsym.h' $tHdrH'_cppsym.real'
  ;;
esac
: now check the C compiler for additional symbols
?X: suggested by Jarkko Hietaniemi <jhi@snakemail.hut.fi>, thanks!
postprocess_cc_v=''
case "$osname" in
aix) postprocess_cc_v="|$tr , ' '" ;;
esac
$cat >ccsym <<EOS
$startsh
$cat >tmp.c <<EOF
extern int foo;
EOF
for i in \`$cc -v -c tmp.c 2>&1 $postprocess_cc_v\`
do
	case "\$i" in
	-D*) echo "\$i" | $sed 's/^-D//;s/['\''\"]//g';;
	-A*) $test "$gccversion" && echo "\$i" | $sed 's/^-A//' | $sed 's/\(.*\)(\(.*\))/\1=\2/';;
	esac
done
$rm_try
EOS
postprocess_cc_v=''
chmod +x ccsym
$eunicefix ccsym
./ccsym > ccsym1.raw
?X: AIX complains if $uniq is passed an empty file.  ($sort apparently
?X: doesn't care.)  --AD  14 July 1998
if $test -s ccsym1.raw; then
    $sort ccsym1.raw | $uniq >ccsym.raw
else
    mv ccsym1.raw ccsym.raw
fi

?X: canonicalize symbols for easier sort/uniq/comm usage: append =1 if no = sign
?X: the awk script must be on two lines for older awk programs, sigh! -- ADO
$awk '/=/ { print $0; next }
	{ print $0"=1" }' ccsym.raw >ccsym.list
$comm -13 Cppsym.true ccsym.list >ccsym.own
$comm -12 Cppsym.true ccsym.list >ccsym.com
$comm -23 Cppsym.true ccsym.list >ccsym.cpp
also=''
if $test -z ccsym.raw; then
	echo "Your C compiler doesn't seem to define any symbols!" >&4
	echo " "
	echo "However, your C preprocessor defines the following symbols:"
	$cat Cppsym.true
	ccsymbols=''
	cppsymbols=`$cat Cppsym.true`
	cppsymbols=`echo $cppsymbols`
	cppccsymbols="$cppsymbols"
else
	if $test -s ccsym.com; then
		echo "Your C compiler and pre-processor define these symbols:"
		$sed -e 's/\(..*\)=.*/\1/' ccsym.com
		also='also '
		symbols='ones'
		cppccsymbols=`$cat ccsym.com`
		cppccsymbols=`echo $cppccsymbols`
		$test "$silent" || sleep 1
	fi
	if $test -s ccsym.cpp; then
		$test "$also" && echo " "
		echo "Your C pre-processor ${also}defines the following symbols:"
		$sed -e 's/\(..*\)=.*/\1/' ccsym.cpp
		also='further '
		cppsymbols=`$cat ccsym.cpp`
		cppsymbols=`echo $cppsymbols`
		$test "$silent" || sleep 1
	fi
	if $test -s ccsym.own; then
		$test "$also" && echo " "
		echo "Your C compiler ${also}defines the following cpp symbols:"
		$sed -e 's/\(..*\)=1/\1/' ccsym.own
		$sed -e 's/\(..*\)=.*/\1/' ccsym.own | $uniq >>Cppsym.true
		ccsymbols=`$cat ccsym.own`
		ccsymbols=`echo $ccsymbols`
		$test "$silent" || sleep 1
	fi
fi

: add -D_FORTIFY_SOURCE if feasible and not already there
case "$gccversion" in
[456789].*|[1-9][0-9]*)	case "$optimize$ccflags" in
	*-O*)	case "$ccflags$cppsymbols" in
		*_FORTIFY_SOURCE=*) # Don't add it again.
			echo "You seem to have -D_FORTIFY_SOURCE already, not adding it." >&4
			;;
		*)	echo "Adding -D_FORTIFY_SOURCE=2 to ccflags..." >&4
			ccflags="$ccflags -D_FORTIFY_SOURCE=2"
			;;
		esac
		;;
	*)	echo "You have gcc 4.* or later but not optimizing, not adding -D_FORTIFY_SOURCE." >&4
		;;
	esac
	;;
*)	echo "You seem not to have gcc 4.* or later, not adding -D_FORTIFY_SOURCE." >&4
	;;
esac

