From: kvigor Date: Tue, 3 Jul 2001 17:51:28 +0000 (+0000) Subject: Port of CPP from GCC 3.0 X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=1dee3f68905452521caecd9dd9cd01db4e47ed76;p=fw%2Fsdcc Port of CPP from GCC 3.0 git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1009 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/support/cpp2/Makefile.in b/support/cpp2/Makefile.in new file mode 100644 index 00000000..bc762001 --- /dev/null +++ b/support/cpp2/Makefile.in @@ -0,0 +1,244 @@ +# Makefile for GNU C Preprocessor. +# +# hacked from gcc Makefile by kvigor. +# +# Copyright (C) 1987, 1988, 1990, 1991, 1992, 1993, 1994, 1995 +# 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + +#This file is part of GNU CC. + +#GNU CC 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. + +#GNU CC is distributed in the hope that 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 CC; see the file COPYING. If not, write to +#the Free Software Foundation, 59 Temple Place - Suite 330, +#Boston MA 02111-1307, USA. + +PRJDIR = ../.. +TARGET = $(PRJDIR)/bin/sdcpp2 + +# This is the default target. +all: $(TARGET) + +# Directory where sources are, from where we are. +srcdir = @srcdir@ + + + +LIBS = @LIBS@ +ALL_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) \ + $(CFLAGS) $(WARN_CFLAGS) $(XCFLAGS) @DEFS@ +ALL_CPPFLAGS = $(CPPFLAGS) $(X_CPPFLAGS) $(T_CPPFLAGS) + +CC = @CC@ +AR = ar +AR_FLAGS = rc +RANLIB = @RANLIB@ +SHELL = /bin/sh +# on sysV, define this as cp. +INSTALL = @INSTALL@ +# Some systems may be missing symbolic links, regular links, or both. +# Allow configure to check this and use "ln -s", "ln", or "cp" as appropriate. +LN=@LN@ +LN_S=@LN_S@ +# These permit overriding just for certain files. +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +@SET_MAKE@ +# Some compilers can't handle cc -c blah.c -o foo/blah.o. +# In stage2 and beyond, we force this to "-o $@" since we know we're using gcc. +OUTPUT_OPTION = @OUTPUT_OPTION@ + +# Some versions of `touch' (such as the version on Solaris 2.8) +# do not correctly set the timestamp due to buggy versions of `utime' +# in the kernel. So, we use `echo' instead. +STAMP = echo timestamp > + +# Where to find some libiberty headers. +LIBIBERTY_DIR = $(srcdir)/libiberty +OBSTACK_H = $(LIBIBERTY_DIR)/obstack.h +SPLAY_TREE_H= $(LIBIBERTY_DIR)/splay-tree.h + +# Test to see whether exists in the system header files. +LIMITS_H_TEST = [ -f $(SYSTEM_HEADER_DIR)/limits.h ] + +# Common prefix for installation directories. +# NOTE: This directory must exist when you start installation. +prefix = @prefix@ +# Directory in which to put localized header files. On the systems with +# gcc as the native cc, `local_prefix' may not be `prefix' which is +# `/usr'. +# NOTE: local_prefix *should not* default from prefix. +local_prefix = @local_prefix@ +# Directory in which to put host dependent programs and libraries +exec_prefix = @exec_prefix@ +# Directory in which to put the executable for the command `gcc' +bindir = @bindir@ +includedir = $(local_prefix)/include +# where the info files go +exeext = @host_exeext@ + +# Top build directory, relative to here. +top_builddir = . + +# Whether we were configured with NLS. +USE_NLS = @USE_NLS@ + +# Internationalization library. +INTLLIBS = @INTLLIBS@ + +# Change this to a null string if obstacks are installed in the +# system library. +OBSTACK=obstack.o + +# End of variables for you to override. + +install: all + $(INSTALL) -s $(TARGET) $(bindir)/sdcpp + +clean: + -rm -f $(TARGET) *.o core libcpp.a + +distclean: clean + -rm -f auto-host.h auto-build.h cstamp-h Makefile + -rm -f config.status config.run config.cache config.bak config.log *~ + +# This tells GNU Make version 3 not to put all variables in the environment. +.NOEXPORT: + +# GCONFIG_H lists the config files that the generator files depend on, while +# CONFIG_H lists the the ones ordinary gcc files depend on, which includes +# a file generated by gencodes. +CONFIG_H = config.h +SYSTEM_H = system.h hwint.h + +# sed inserts variable overrides after the following line. +####target overrides +@target_overrides@ + +####host overrides +@host_overrides@ + +####cross overrides +@cross_defines@ +@cross_overrides@ + +####build overrides +@build_overrides@ +# + +INCLUDES = -I$(srcdir) -I$(LIBIBERTY_DIR) + +# Always use -I$(srcdir)/config when compiling. +.c.o: + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION) + +# cstamp-h.in controls rebuilding of config.in. +# It is named cstamp-h.in and not stamp-h.in so the mostlyclean rule doesn't +# delete it. A stamp file is needed as autoheader won't update the file if +# nothing has changed. +# It remains in the source directory and is part of the distribution. +# This follows what is done in shellutils, fileutils, etc. +# "echo timestamp" is used instead of touch to be consistent with other +# packages that use autoconf (??? perhaps also to avoid problems with patch?). +# ??? Newer versions have a maintainer mode that may be useful here. +$(srcdir)/config.in: $(srcdir)/cstamp-h.in $(srcdir)/acconfig.h +$(srcdir)/cstamp-h.in: $(srcdir)/configure.in $(srcdir)/acconfig.h + (cd $(srcdir) && autoheader) + @rm -f $(srcdir)/cstamp-h.in + echo timestamp > $(srcdir)/cstamp-h.in +auto-host.h: cstamp-h ; @true +cstamp-h: config.in config.status + CONFIG_HEADERS=auto-host.h:config.in LANGUAGES="$(CONFIG_LANGUAGES)" $(SHELL) config.status + +# Really, really stupid make features, such as SUN's KEEP_STATE, may force +# a target to build even if it is up-to-date. So we must verify that +# config.status does not exist before failing. +config.status: $(srcdir)/configure version.c + @if [ ! -f config.status ] ; then \ + echo You must configure gcc. Look at http://gcc.gnu.org/install/ for details.; \ + false; \ + else \ + LANGUAGES="$(CONFIG_LANGUAGES)" $(SHELL) config.status --recheck; \ + fi + +version.o: version.c version.h + +hashtable.o: hashtable.c hashtable.h $(CONFIG_H) $(SYSTEM_H) $(OBSTACK_H) + +prefix.o: prefix.c $(CONFIG_H) $(SYSTEM_H) Makefile prefix.h + $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + -DPREFIX=\"$(prefix)\" \ + -c $(srcdir)/prefix.c + +intl.o: intl.c intl.h Makefile + $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + -DLOCALEDIR=\"$(localedir)\" \ + -c $(srcdir)/intl.c + +# +# Remake cpp and protoize. + +PREPROCESSOR_DEFINES = \ + -DGCC_INCLUDE_DIR=\"$(libsubdir)/include\" \ + -DGPLUSPLUS_INCLUDE_DIR=\"$(gcc_gxx_include_dir)\" \ + -DGPLUSPLUS_TOOL_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/$(target_alias)\" \ + -DGPLUSPLUS_BACKWARD_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/backward\" \ + -DLOCAL_INCLUDE_DIR=\"$(includedir)\" \ + -DCROSS_INCLUDE_DIR=\"$(gcc_tooldir)/sys-include\" \ + -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" + +LIBCPP_OBJS = cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o \ + cpphash.o cpperror.o cppinit.o cppdefault.o \ + hashtable.o mkdeps.o prefix.o version.o mbchar.o + +LIBCPP_DEPS = cpplib.h cpphash.h hashtable.h intl.h $(OBSTACK_H) $(SYSTEM_H) + +# Most of the other archives built/used by this makefile are for +# targets. This one is strictly for the host. +libcpp.a: $(LIBCPP_OBJS) + -rm -rf libcpp.a + $(AR) $(AR_FLAGS) libcpp.a $(LIBCPP_OBJS) + -$(RANLIB) libcpp.a + +MY_LIBIBERTY_BITS = intl.o safe-ctype.o obstack.o splay-tree.o \ + lbasename.o + +$(TARGET): cppmain.o intl.o $(MY_LIBIBERTY_BITS) libcpp.a $(LIBDEPS) + $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ cppmain.o \ + $(MY_LIBIBERTY_BITS) libcpp.a $(LIBS) + +cppmain.o: cppmain.c $(CONFIG_H) cpplib.h intl.h $(SYSTEM_H) + +cpperror.o: cpperror.c $(CONFIG_H) $(LIBCPP_DEPS) +cppexp.o: cppexp.c $(CONFIG_H) $(LIBCPP_DEPS) +cpplex.o: cpplex.c $(CONFIG_H) $(LIBCPP_DEPS) mbchar.h +cppmacro.o: cppmacro.c $(CONFIG_H) $(LIBCPP_DEPS) +cpplib.o: cpplib.c $(CONFIG_H) $(LIBCPP_DEPS) +cpphash.o: cpphash.c $(CONFIG_H) $(LIBCPP_DEPS) +cppfiles.o: cppfiles.c $(CONFIG_H) $(LIBCPP_DEPS) $(SPLAY_TREE_H) mkdeps.h +cppinit.o: cppinit.c $(CONFIG_H) $(LIBCPP_DEPS) cppdefault.h \ + mkdeps.h prefix.h output.h version.h +safe-ctype.o: $(LIBIBERTY_DIR)/safe-ctype.c $(LIBIBERTY_DIR)/safe-ctype.h $(CONFIG_H) $(LIBCPP_DEPS) + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION) +obstack.o: $(LIBIBERTY_DIR)/obstack.c $(LIBIBERTY_DIR)/obstack.h $(CONFIG_H) $(LIBCPP_DEPS) + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION) +splay-tree.o: $(LIBIBERTY_DIR)/splay-tree.c $(LIBIBERTY_DIR)/splay-tree.h $(CONFIG_H) $(LIBCPP_DEPS) + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION) +lbasename.o: $(LIBIBERTY_DIR)/lbasename.c $(CONFIG_H) $(LIBCPP_DEPS) + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION) +cppdefault.o: cppdefault.c $(CONFIG_H) $(SYSTEM_H) cppdefault.h Makefile + $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ + $(PREPROCESSOR_DEFINES) \ + -c $(srcdir)/cppdefault.c + +mkdeps.o: mkdeps.c $(CONFIG_H) $(SYSTEM_H) mkdeps.h + diff --git a/support/cpp2/acconfig.h b/support/cpp2/acconfig.h new file mode 100644 index 00000000..dec619b8 --- /dev/null +++ b/support/cpp2/acconfig.h @@ -0,0 +1,41 @@ +/* Define to 1 if NLS is requested. */ +#undef ENABLE_NLS + +/* Define as 1 if you have catgets and don't want to use GNU gettext. */ +#undef HAVE_CATGETS + +/* Define as 1 if you have gettext and don't want to use GNU gettext. */ +#undef HAVE_GETTEXT + +/* Define if your locale.h file contains LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES + +/* Define as 1 if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if your assembler supports specifying the maximum number + of bytes to skip when using the GAS .p2align command. */ +#undef HAVE_GAS_MAX_SKIP_P2ALIGN + +/* Define if your assembler supports .balign and .p2align. */ +#undef HAVE_GAS_BALIGN_AND_P2ALIGN + +/* Define if your assembler uses the old HImode fild and fist notation. */ +#undef HAVE_GAS_FILDS_FISTS + +/* Define to `int' if doesn't define. */ +#undef ssize_t + +@BOTTOM@ + +/* Bison unconditionally undefines `const' if neither `__STDC__' nor + __cplusplus are defined. That's a problem since we use `const' in + the GCC headers, and the resulting bison code is therefore type + unsafe. Thus, we must match the bison behavior here. */ + +#ifndef __STDC__ +#ifndef __cplusplus +#undef const +#define const +#endif +#endif diff --git a/support/cpp2/aclocal.m4 b/support/cpp2/aclocal.m4 new file mode 100644 index 00000000..0cc940e2 --- /dev/null +++ b/support/cpp2/aclocal.m4 @@ -0,0 +1,888 @@ +dnl See whether we can include both string.h and strings.h. +AC_DEFUN(gcc_AC_HEADER_STRING, +[AC_CACHE_CHECK([whether string.h and strings.h may both be included], + gcc_cv_header_string, +[AC_TRY_COMPILE([#include +#include ], , gcc_cv_header_string=yes, gcc_cv_header_string=no)]) +if test $gcc_cv_header_string = yes; then + AC_DEFINE(STRING_WITH_STRINGS, 1, [Define if you can safely include both and .]) +fi +]) + +dnl See whether we need a declaration for a function. +dnl The result is highly dependent on the INCLUDES passed in, so make sure +dnl to use a different cache variable name in this macro if it is invoked +dnl in a different context somewhere else. +dnl gcc_AC_CHECK_DECL(SYMBOL, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]]) +AC_DEFUN(gcc_AC_CHECK_DECL, +[AC_MSG_CHECKING([whether $1 is declared]) +AC_CACHE_VAL(gcc_cv_have_decl_$1, +[AC_TRY_COMPILE([$4], +[#ifndef $1 +char *(*pfn) = (char *(*)) $1 ; +#endif], eval "gcc_cv_have_decl_$1=yes", eval "gcc_cv_have_decl_$1=no")]) +if eval "test \"`echo '$gcc_cv_have_decl_'$1`\" = yes"; then + AC_MSG_RESULT(yes) ; ifelse([$2], , :, [$2]) +else + AC_MSG_RESULT(no) ; ifelse([$3], , :, [$3]) +fi +])dnl + +dnl Check multiple functions to see whether each needs a declaration. +dnl Arrange to define HAVE_DECL_ to 0 or 1 as appropriate. +dnl gcc_AC_CHECK_DECLS(SYMBOLS, +dnl [ACTION-IF-NEEDED [, ACTION-IF-NOT-NEEDED [, INCLUDES]]]) +AC_DEFUN(gcc_AC_CHECK_DECLS, +[for ac_func in $1 +do +changequote(, )dnl + ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` +changequote([, ])dnl +gcc_AC_CHECK_DECL($ac_func, + [AC_DEFINE_UNQUOTED($ac_tr_decl, 1) $2], + [AC_DEFINE_UNQUOTED($ac_tr_decl, 0) $3], +dnl It is possible that the include files passed in here are local headers +dnl which supply a backup declaration for the relevant prototype based on +dnl the definition of (or lack of) the HAVE_DECL_ macro. If so, this test +dnl will always return success. E.g. see libiberty.h's handling of +dnl `basename'. To avoid this, we define the relevant HAVE_DECL_ macro to +dnl 1 so that any local headers used do not provide their own prototype +dnl during this test. +#undef $ac_tr_decl +#define $ac_tr_decl 1 + $4 +) +done +dnl Automatically generate config.h entries via autoheader. +if test x = y ; then + patsubst(translit([$1], [a-z], [A-Z]), [\w+], + [AC_DEFINE([HAVE_DECL_\&], 1, + [Define to 1 if we found this declaration otherwise define to 0.])])dnl +fi +]) + +dnl See if symbolic links work and if not, try to substitute either hard links or simple copy. +AC_DEFUN(gcc_AC_PROG_LN_S, +[AC_MSG_CHECKING(whether ln -s works) +AC_CACHE_VAL(gcc_cv_prog_LN_S, +[rm -f conftestdata_t +echo >conftestdata_f +if ln -s conftestdata_f conftestdata_t 2>/dev/null +then + gcc_cv_prog_LN_S="ln -s" +else + if ln conftestdata_f conftestdata_t 2>/dev/null + then + gcc_cv_prog_LN_S=ln + else + gcc_cv_prog_LN_S=cp + fi +fi +rm -f conftestdata_f conftestdata_t +])dnl +LN_S="$gcc_cv_prog_LN_S" +if test "$gcc_cv_prog_LN_S" = "ln -s"; then + AC_MSG_RESULT(yes) +else + if test "$gcc_cv_prog_LN_S" = "ln"; then + AC_MSG_RESULT([no, using ln]) + else + AC_MSG_RESULT([no, and neither does ln, so using cp]) + fi +fi +AC_SUBST(LN_S)dnl +]) + +dnl See if hard links work and if not, try to substitute either symbolic links or simple copy. +AC_DEFUN(gcc_AC_PROG_LN, +[AC_MSG_CHECKING(whether ln works) +AC_CACHE_VAL(gcc_cv_prog_LN, +[rm -f conftestdata_t +echo >conftestdata_f +if ln conftestdata_f conftestdata_t 2>/dev/null +then + gcc_cv_prog_LN="ln" +else + if ln -s conftestdata_f conftestdata_t 2>/dev/null + then + gcc_cv_prog_LN="ln -s" + else + gcc_cv_prog_LN=cp + fi +fi +rm -f conftestdata_f conftestdata_t +])dnl +LN="$gcc_cv_prog_LN" +if test "$gcc_cv_prog_LN" = "ln"; then + AC_MSG_RESULT(yes) +else + if test "$gcc_cv_prog_LN" = "ln -s"; then + AC_MSG_RESULT([no, using ln -s]) + else + AC_MSG_RESULT([no, and neither does ln -s, so using cp]) + fi +fi +AC_SUBST(LN)dnl +]) + +dnl Define MKDIR_TAKES_ONE_ARG if mkdir accepts only one argument instead +dnl of the usual 2. +AC_DEFUN(gcc_AC_FUNC_MKDIR_TAKES_ONE_ARG, +[AC_CACHE_CHECK([if mkdir takes one argument], gcc_cv_mkdir_takes_one_arg, +[AC_TRY_COMPILE([ +#include +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_DIRECT_H +# include +#endif], [mkdir ("foo", 0);], + gcc_cv_mkdir_takes_one_arg=no, gcc_cv_mkdir_takes_one_arg=yes)]) +if test $gcc_cv_mkdir_takes_one_arg = yes ; then + AC_DEFINE(MKDIR_TAKES_ONE_ARG, 1, [Define if host mkdir takes a single argument.]) +fi +]) + +AC_DEFUN(gcc_AC_PROG_INSTALL, +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +AC_MSG_CHECKING(for a BSD compatible install) +if test -z "$INSTALL"; then +AC_CACHE_VAL(ac_cv_path_install, +[ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + # OSF/1 installbsd also uses dspmsg, but is usable. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" +])dnl + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +dnl We do special magic for INSTALL instead of AC_SUBST, to get +dnl relative paths right. +AC_MSG_RESULT($INSTALL) +AC_SUBST(INSTALL)dnl + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' +AC_SUBST(INSTALL_PROGRAM)dnl + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' +AC_SUBST(INSTALL_DATA)dnl +]) + +#serial 1 +dnl This test replaces the one in autoconf. +dnl Currently this macro should have the same name as the autoconf macro +dnl because gettext's gettext.m4 (distributed in the automake package) +dnl still uses it. Otherwise, the use in gettext.m4 makes autoheader +dnl give these diagnostics: +dnl configure.in:556: AC_TRY_COMPILE was called before AC_ISC_POSIX +dnl configure.in:556: AC_TRY_RUN was called before AC_ISC_POSIX + +undefine([AC_ISC_POSIX]) +AC_DEFUN(AC_ISC_POSIX, + [ + dnl This test replaces the obsolescent AC_ISC_POSIX kludge. + AC_CHECK_LIB(cposix, strerror, [LIBS="$LIBS -lcposix"]) + ] +) + + +dnl GCC_PATH_PROG(VARIABLE, PROG-TO-CHECK-FOR [, VALUE-IF-NOT-FOUND [, PATH]]) +dnl like AC_PATH_PROG but use other cache variables +AC_DEFUN(GCC_PATH_PROG, +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(gcc_cv_path_$1, +[case "[$]$1" in + /*) + gcc_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + ?:/*) + gcc_cv_path_$1="[$]$1" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$4], , $PATH, [$4])" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + gcc_cv_path_$1="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" +dnl If no 3rd arg is given, leave the cache variable unset, +dnl so GCC_PATH_PROGS will keep looking. +ifelse([$3], , , [ test -z "[$]gcc_cv_path_$1" && gcc_cv_path_$1="$3" +])dnl + ;; +esac])dnl +$1="$gcc_cv_path_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + + + +dnl GCC_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN(GCC_PATH_PROG_WITH_TEST, +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(gcc_cv_path_$1, +[case "[$]$1" in + /*) + gcc_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + gcc_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so GCC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]gcc_cv_path_$1" && gcc_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$gcc_cv_path_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +# Check whether mmap can map an arbitrary page from /dev/zero or with +# MAP_ANONYMOUS, without MAP_FIXED. +AC_DEFUN([AC_FUNC_MMAP_ANYWHERE], +[AC_CHECK_FUNCS(getpagesize) +# The test program for the next two tests is the same except for one +# set of ifdefs. +changequote({{{,}}})dnl +{{{cat >ct-mmap.inc <<'EOF' +#include +#include +#include +#include +#include +#include + +#if !defined (MAP_ANONYMOUS) && defined (MAP_ANON) +# define MAP_ANONYMOUS MAP_ANON +#endif + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +#ifndef MAP_FAILED +# define MAP_FAILED -1 +#endif + +#undef perror_exit +#define perror_exit(str, val) \ + do { perror(str); exit(val); } while (0) + +/* Some versions of cygwin mmap require that munmap is called with the + same parameters as mmap. GCC expects that this is not the case. + Test for various forms of this problem. Warning - icky signal games. */ + +static sigset_t unblock_sigsegv; +static jmp_buf r; +static size_t pg; +static int devzero; + +static char * +anonmap (size) + size_t size; +{ +#ifdef USE_MAP_ANON + return (char *) mmap (0, size, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); +#else + return (char *) mmap (0, size, PROT_READ|PROT_WRITE, + MAP_PRIVATE, devzero, 0); +#endif +} + +static void +sigsegv (unused) + int unused; +{ + sigprocmask (SIG_UNBLOCK, &unblock_sigsegv, 0); + longjmp (r, 1); +} + +/* Basic functionality test. */ +void +test_0 () +{ + char *x = anonmap (pg); + if (x == (char *) MAP_FAILED) + perror_exit("test 0 mmap", 2); + + *(int *)x += 1; + + if (munmap(x, pg) < 0) + perror_exit("test 0 munmap", 3); +} + +/* 1. If we map a 2-page region and unmap its second page, the first page + must remain. */ +static void +test_1 () +{ + char *x = anonmap (pg * 2); + if (x == (char *)MAP_FAILED) + perror_exit ("test 1 mmap", 4); + + signal (SIGSEGV, sigsegv); + if (setjmp (r)) + perror_exit ("test 1 fault", 5); + + x[0] = 1; + x[pg] = 1; + + if (munmap (x + pg, pg) < 0) + perror_exit ("test 1 munmap 1", 6); + x[0] = 2; + + if (setjmp (r) == 0) + { + x[pg] = 1; + perror_exit ("test 1 no fault", 7); + } + if (munmap (x, pg) < 0) + perror_exit ("test 1 munmap 2", 8); +} + +/* 2. If we map a 2-page region and unmap its first page, the second + page must remain. */ +static void +test_2 () +{ + char *x = anonmap (pg * 2); + if (x == (char *)MAP_FAILED) + perror_exit ("test 2 mmap", 9); + + signal (SIGSEGV, sigsegv); + if (setjmp (r)) + perror_exit ("test 2 fault", 10); + + x[0] = 1; + x[pg] = 1; + + if (munmap (x, pg) < 0) + perror_exit ("test 2 munmap 1", 11); + + x[pg] = 2; + + if (setjmp (r) == 0) + { + x[0] = 1; + perror_exit ("test 2 no fault", 12); + } + + if (munmap (x+pg, pg) < 0) + perror_exit ("test 2 munmap 2", 13); +} + +/* 3. If we map two adjacent 1-page regions and unmap them both with + one munmap, both must go away. + + Getting two adjacent 1-page regions with two mmap calls is slightly + tricky. All OS's tested skip over already-allocated blocks; therefore + we have been careful to unmap all allocated regions in previous tests. + HP/UX allocates pages backward in memory. No OS has yet been observed + to be so perverse as to leave unmapped space between consecutive calls + to mmap. */ + +static void +test_3 () +{ + char *x, *y, *z; + + x = anonmap (pg); + if (x == (char *)MAP_FAILED) + perror_exit ("test 3 mmap 1", 14); + y = anonmap (pg); + if (y == (char *)MAP_FAILED) + perror_exit ("test 3 mmap 2", 15); + + if (y != x + pg) + { + if (y == x - pg) + z = y, y = x, x = z; + else + { + fprintf (stderr, "test 3 nonconsecutive pages - %lx, %lx\n", + (unsigned long)x, (unsigned long)y); + exit (16); + } + } + + signal (SIGSEGV, sigsegv); + if (setjmp (r)) + perror_exit ("test 3 fault", 17); + + x[0] = 1; + y[0] = 1; + + if (munmap (x, pg*2) < 0) + perror_exit ("test 3 munmap", 18); + + if (setjmp (r) == 0) + { + x[0] = 1; + perror_exit ("test 3 no fault 1", 19); + } + + signal (SIGSEGV, sigsegv); + if (setjmp (r) == 0) + { + y[0] = 1; + perror_exit ("test 3 no fault 2", 20); + } +} + +int +main () +{ + sigemptyset (&unblock_sigsegv); + sigaddset (&unblock_sigsegv, SIGSEGV); + pg = getpagesize (); +#ifndef USE_MAP_ANON + devzero = open ("/dev/zero", O_RDWR); + if (devzero < 0) + perror_exit ("open /dev/zero", 1); +#endif + + test_0(); + test_1(); + test_2(); + test_3(); + + exit(0); +} +EOF}}} +changequote([,])dnl + +AC_CACHE_CHECK(for working mmap from /dev/zero, + ac_cv_func_mmap_dev_zero, +[AC_TRY_RUN( + [#include "ct-mmap.inc"], + ac_cv_func_mmap_dev_zero=yes, + [if test $? -lt 4 + then ac_cv_func_mmap_dev_zero=no + else ac_cv_func_mmap_dev_zero=buggy + fi], + # If this is not cygwin, and /dev/zero is a character device, it's probably + # safe to assume it works. + [case "$host_os" in + cygwin* | win32 | pe | mingw* ) ac_cv_func_mmap_dev_zero=buggy ;; + * ) if test -c /dev/zero + then ac_cv_func_mmap_dev_zero=yes + else ac_cv_func_mmap_dev_zero=no + fi ;; + esac]) +]) +if test $ac_cv_func_mmap_dev_zero = yes; then + AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1, + [Define if mmap can get us zeroed pages from /dev/zero.]) +fi + +AC_CACHE_CHECK([for working mmap with MAP_ANON(YMOUS)], + ac_cv_func_mmap_anon, +[AC_TRY_RUN( + [#define USE_MAP_ANON +#include "ct-mmap.inc"], + ac_cv_func_mmap_anon=yes, + [if test $? -lt 4 + then ac_cv_func_mmap_anon=no + else ac_cv_func_mmap_anon=buggy + fi], + # Unlike /dev/zero, it is not safe to assume MAP_ANON(YMOUS) works + # just because it's there. Some SCO Un*xen define it but don't implement it. + ac_cv_func_mmap_anon=no) +]) +if test $ac_cv_func_mmap_anon = yes; then + AC_DEFINE(HAVE_MMAP_ANON, 1, + [Define if mmap can get us zeroed pages using MAP_ANON(YMOUS).]) +fi +rm -f ct-mmap.inc +]) + +# Check whether mmap can map a plain file, without MAP_FIXED. +AC_DEFUN([AC_FUNC_MMAP_FILE], +[AC_CACHE_CHECK(for working mmap of a file, ac_cv_func_mmap_file, +[# Create a file one thousand bytes long. +for i in 1 2 3 4 5 6 7 8 9 0 +do for j in 1 2 3 4 5 6 7 8 9 0 +do echo $i $j xxxxx +done +done > conftestdata$$ + +AC_TRY_RUN([ +/* Test by Zack Weinberg. Modified from MMAP_ANYWHERE test by + Richard Henderson and Alexandre Oliva. + Check whether read-only mmap of a plain file works. */ +#include +#include +#include +#include + +int main() +{ + char *x; + int fd; + struct stat st; + + fd = open("conftestdata$$", O_RDONLY); + if (fd < 0) + exit(1); + + if (fstat (fd, &st)) + exit(2); + + x = (char*)mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (x == (char *) -1) + exit(3); + + if (x[0] != '1' || x[1] != ' ' || x[2] != '1' || x[3] != ' ') + exit(4); + + if (munmap(x, st.st_size) < 0) + exit(5); + + exit(0); +}], ac_cv_func_mmap_file=yes, ac_cv_func_mmap_file=no, +ac_cv_func_mmap_file=no)]) +if test $ac_cv_func_mmap_file = yes; then + AC_DEFINE(HAVE_MMAP_FILE, 1, + [Define if read-only mmap of a plain file works.]) +fi +]) + +dnl Locate a program and check that its version is acceptable. +dnl AC_PROG_CHECK_VER(var, name, version-switch, +dnl version-extract-regexp, version-glob) +AC_DEFUN(gcc_AC_CHECK_PROG_VER, +[AC_CHECK_PROG([$1], [$2], [$2]) +if test -n "[$]$1"; then + # Found it, now check the version. + AC_CACHE_CHECK(for modern $2, gcc_cv_prog_$2_modern, +[changequote(<<,>>)dnl + ac_prog_version=`<<$>>$1 $3 2>&1 | + sed -n 's/^.*patsubst(<<$4>>,/,\/).*$/\1/p'` +changequote([,])dnl + echo "configure:__oline__: version of $2 is $ac_prog_version" >&AC_FD_CC +changequote(<<,>>)dnl + case $ac_prog_version in + '') gcc_cv_prog_$2_modern=no;; + <<$5>>) + gcc_cv_prog_$2_modern=yes;; + *) gcc_cv_prog_$2_modern=no;; + esac +changequote([,])dnl +]) +else + gcc_cv_prog_$2_modern=no +fi +]) + +dnl Determine if enumerated bitfields are unsigned. ISO C says they can +dnl be either signed or unsigned. +dnl +AC_DEFUN(gcc_AC_C_ENUM_BF_UNSIGNED, +[AC_CACHE_CHECK(for unsigned enumerated bitfields, gcc_cv_enum_bf_unsigned, +[AC_TRY_RUN(#include +enum t { BLAH = 128 } ; +struct s_t { enum t member : 8; } s ; +int main(void) +{ + s.member = BLAH; + if (s.member < 0) exit(1); + exit(0); + +}, gcc_cv_enum_bf_unsigned=yes, gcc_cv_enum_bf_unsigned=no, gcc_cv_enum_bf_unsigned=yes)]) +if test $gcc_cv_enum_bf_unsigned = yes; then + AC_DEFINE(ENUM_BITFIELDS_ARE_UNSIGNED, 1, + [Define if enumerated bitfields are treated as unsigned values.]) +fi]) + +dnl Host type sizes probe. +dnl By Kaveh R. Ghazi. One typo fixed since. +dnl +AC_DEFUN([gcc_AC_COMPILE_CHECK_SIZEOF], +[changequote(<<, >>)dnl +dnl The name to #define. +define(<>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl +dnl The cache variable name. +define(<>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl +changequote([, ])dnl +AC_MSG_CHECKING(size of $1) +AC_CACHE_VAL(AC_CV_NAME, +[for ac_size in 4 8 1 2 16 $3 ; do # List sizes in rough order of prevalence. + AC_TRY_COMPILE([#include "confdefs.h" +#include +$2 +], [switch (0) case 0: case (sizeof ($1) == $ac_size):;], AC_CV_NAME=$ac_size) + if test x$AC_CV_NAME != x ; then break; fi +done +]) +if test x$AC_CV_NAME = x ; then + AC_MSG_ERROR([cannot determine a size for $1]) +fi +AC_MSG_RESULT($AC_CV_NAME) +AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The number of bytes in type $1]) +undefine([AC_TYPE_NAME])dnl +undefine([AC_CV_NAME])dnl +]) + +dnl Probe number of bits in a byte. +dnl Note C89 requires CHAR_BIT >= 8. +dnl +AC_DEFUN(gcc_AC_C_CHAR_BIT, +[AC_CACHE_CHECK(for CHAR_BIT, gcc_cv_decl_char_bit, +[AC_EGREP_CPP(found, +[#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef CHAR_BIT +found +#endif], gcc_cv_decl_char_bit=yes, gcc_cv_decl_char_bit=no) +]) +if test $gcc_cv_decl_char_bit = no; then + AC_CACHE_CHECK(number of bits in a byte, gcc_cv_c_nbby, +[i=8 + gcc_cv_c_nbby= + while test $i -lt 65; do + AC_TRY_COMPILE(, + [switch(0) { + case (unsigned char)((unsigned long)1 << $i) == ((unsigned long)1 << $i): + case (unsigned char)((unsigned long)1<<($i-1)) == ((unsigned long)1<<($i-1)): + ; }], + [gcc_cv_c_nbby=$i; break]) + i=`expr $i + 1` + done + test -z "$gcc_cv_c_nbby" && gcc_cv_c_nbby=failed +]) +if test $gcc_cv_c_nbby = failed; then + AC_MSG_ERROR(cannot determine number of bits in a byte) +else + AC_DEFINE_UNQUOTED(CHAR_BIT, $gcc_cv_c_nbby, + [Define as the number of bits in a byte, if \`limits.h' doesn't.]) +fi +fi]) + +dnl Host character set probe. +dnl The EBCDIC values match the table in config/i370/i370.c; +dnl there are other versions of EBCDIC but GCC won't work with them. +dnl +AC_DEFUN([gcc_AC_C_CHARSET], +[AC_CACHE_CHECK(execution character set, ac_cv_c_charset, + [AC_EGREP_CPP(ASCII, +[#if '\n' == 0x0A && ' ' == 0x20 && '0' == 0x30 \ + && 'A' == 0x41 && 'a' == 0x61 && '!' == 0x21 +ASCII +#endif], ac_cv_c_charset=ASCII) + if test x${ac_cv_c_charset+set} != xset; then + AC_EGREP_CPP(EBCDIC, +[#if '\n' == 0x15 && ' ' == 0x40 && '0' == 0xF0 \ + && 'A' == 0xC1 && 'a' == 0x81 && '!' == 0x5A +EBCDIC +#endif], ac_cv_c_charset=EBCDIC) + fi + if test x${ac_cv_c_charset+set} != xset; then + ac_cv_c_charset=unknown + fi]) +if test $ac_cv_c_charset = unknown; then + AC_MSG_ERROR([*** Cannot determine host character set.]) +elif test $ac_cv_c_charset = EBCDIC; then + AC_DEFINE(HOST_EBCDIC, 1, + [Define if the host execution character set is EBCDIC.]) +fi]) + +dnl Utility macro used by next two tests. +dnl AC_EXAMINE_OBJECT(C source code, +dnl commands examining object file, +dnl [commands to run if compile failed]): +dnl +dnl Compile the source code to an object file; then convert it into a +dnl printable representation. All unprintable characters and +dnl asterisks (*) are replaced by dots (.). All white space is +dnl deleted. Newlines (ASCII 0x10) in the input are preserved in the +dnl output, but runs of newlines are compressed to a single newline. +dnl Finally, line breaks are forcibly inserted so that no line is +dnl longer than 80 columns and the file ends with a newline. The +dnl result of all this processing is in the file conftest.dmp, which +dnl may be examined by the commands in the second argument. +dnl +AC_DEFUN([gcc_AC_EXAMINE_OBJECT], +[AC_LANG_SAVE +AC_LANG_C +dnl Next bit cribbed from AC_TRY_COMPILE. +cat > conftest.$ac_ext < conftest.dmp + $2 +ifelse($3, , , else + $3 +)dnl +fi +rm -rf conftest* +AC_LANG_RESTORE]) + +dnl Host endianness probe. +dnl This tests byte-within-word endianness. GCC actually needs +dnl to know word-within-larger-object endianness. They are the +dnl same on all presently supported hosts. +dnl Differs from AC_C_BIGENDIAN in that it does not require +dnl running a program on the host, and it defines the macro we +dnl want to see. +dnl +AC_DEFUN([gcc_AC_C_COMPILE_ENDIAN], +[AC_CACHE_CHECK(byte ordering, ac_cv_c_compile_endian, +[ac_cv_c_compile_endian=unknown +gcc_AC_EXAMINE_OBJECT([ +#ifdef HAVE_LIMITS_H +# include +#endif +/* This structure must have no internal padding. */ + struct { + char prefix[sizeof "\nendian:" - 1]; + short word; + char postfix[2]; + } tester = { + "\nendian:", +#if SIZEOF_SHORT == 4 + ('A' << (CHAR_BIT * 3)) | ('B' << (CHAR_BIT * 2)) | +#endif + ('A' << CHAR_BIT) | 'B', + 'X', '\n' +};], + [if grep 'endian:AB' conftest.dmp >/dev/null 2>&1; then + ac_cv_c_compile_endian=big-endian + elif grep 'endian:BA' conftest.dmp >/dev/null 2>&1; then + ac_cv_c_compile_endian=little-endian + fi]) +]) +if test $ac_cv_c_compile_endian = unknown; then + AC_MSG_ERROR([*** unable to determine endianness]) +elif test $ac_cv_c_compile_endian = big-endian; then + AC_DEFINE(HOST_WORDS_BIG_ENDIAN, 1, + [Define if the host machine stores words of multi-word integers in + big-endian order.]) +fi +]) + diff --git a/support/cpp2/ansidecl.h b/support/cpp2/ansidecl.h new file mode 100644 index 00000000..4ef6db80 --- /dev/null +++ b/support/cpp2/ansidecl.h @@ -0,0 +1,251 @@ +/* ANSI and traditional C compatability macros + Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* ANSI and traditional C compatibility macros + + ANSI C is assumed if __STDC__ is #defined. + + Macro ANSI C definition Traditional C definition + ----- ---- - ---------- ----------- - ---------- + PTR `void *' `char *' + LONG_DOUBLE `long double' `double' + VOLATILE `volatile' `' + SIGNED `signed' `' + PTRCONST `void *const' `char *' + ANSI_PROTOTYPES 1 not defined + + CONST is also defined, but is obsolete. Just use const. + + obsolete -- DEFUN (name, arglist, args) + + Defines function NAME. + + ARGLIST lists the arguments, separated by commas and enclosed in + parentheses. ARGLIST becomes the argument list in traditional C. + + ARGS list the arguments with their types. It becomes a prototype in + ANSI C, and the type declarations in traditional C. Arguments should + be separated with `AND'. For functions with a variable number of + arguments, the last thing listed should be `DOTS'. + + obsolete -- DEFUN_VOID (name) + + Defines a function NAME, which takes no arguments. + + obsolete -- EXFUN (name, (prototype)) -- obsolete. + + Replaced by PARAMS. Do not use; will disappear someday soon. + Was used in external function declarations. + In ANSI C it is `NAME PROTOTYPE' (so PROTOTYPE should be enclosed in + parentheses). In traditional C it is `NAME()'. + For a function that takes no arguments, PROTOTYPE should be `(void)'. + + obsolete -- PROTO (type, name, (prototype) -- obsolete. + + This one has also been replaced by PARAMS. Do not use. + + PARAMS ((args)) + + We could use the EXFUN macro to handle prototype declarations, but + the name is misleading and the result is ugly. So we just define a + simple macro to handle the parameter lists, as in: + + static int foo PARAMS ((int, char)); + + This produces: `static int foo();' or `static int foo (int, char);' + + EXFUN would have done it like this: + + static int EXFUN (foo, (int, char)); + + but the function is not external...and it's hard to visually parse + the function name out of the mess. EXFUN should be considered + obsolete; new code should be written to use PARAMS. + + DOTS is also obsolete. + + Examples: + + extern int printf PARAMS ((const char *format, ...)); +*/ + +#ifndef _ANSIDECL_H + +#define _ANSIDECL_H 1 + + +/* Every source file includes this file, + so they will all get the switch for lint. */ +/* LINTLIBRARY */ + + +#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32) +/* All known AIX compilers implement these things (but don't always + define __STDC__). The RISC/OS MIPS compiler defines these things + in SVR4 mode, but does not define __STDC__. */ + +#define PTR void * +#define PTRCONST void *CONST +#define LONG_DOUBLE long double + +#ifndef IN_GCC +#define AND , +#define NOARGS void +#define VOLATILE volatile +#define SIGNED signed +#endif /* ! IN_GCC */ + +#define PARAMS(paramlist) paramlist +#define ANSI_PROTOTYPES 1 + +#define VPARAMS(ARGS) ARGS +#define VA_START(va_list,var) va_start(va_list,var) + +/* These are obsolete. Do not use. */ +#ifndef IN_GCC +#define CONST const +#define DOTS , ... +#define PROTO(type, name, arglist) type name arglist +#define EXFUN(name, proto) name proto +#define DEFUN(name, arglist, args) name(args) +#define DEFUN_VOID(name) name(void) +#endif /* ! IN_GCC */ + +#else /* Not ANSI C. */ + +#define PTR char * +#define PTRCONST PTR +#define LONG_DOUBLE double + +#ifndef IN_GCC +#define AND ; +#define NOARGS +#define VOLATILE +#define SIGNED +#endif /* !IN_GCC */ + +#ifndef const /* some systems define it in header files for non-ansi mode */ +#define const +#endif + +#define PARAMS(paramlist) () + +#define VPARAMS(ARGS) (va_alist) va_dcl +#define VA_START(va_list,var) va_start(va_list) + +/* These are obsolete. Do not use. */ +#ifndef IN_GCC +#define CONST +#define DOTS +#define PROTO(type, name, arglist) type name () +#define EXFUN(name, proto) name() +#define DEFUN(name, arglist, args) name arglist args; +#define DEFUN_VOID(name) name() +#endif /* ! IN_GCC */ + +#endif /* ANSI C. */ + +/* Using MACRO(x,y) in cpp #if conditionals does not work with some + older preprocessors. Thus we can't define something like this: + +#define HAVE_GCC_VERSION(MAJOR, MINOR) \ + (__GNUC__ > (MAJOR) || (__GNUC__ == (MAJOR) && __GNUC_MINOR__ >= (MINOR))) + +and then test "#if HAVE_GCC_VERSION(2,7)". + +So instead we use the macro below and test it against specific values. */ + +/* This macro simplifies testing whether we are using gcc, and if it + is of a particular minimum version. (Both major & minor numbers are + significant.) This macro will evaluate to 0 if we are not using + gcc at all. */ +#ifndef GCC_VERSION +#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) +#endif /* GCC_VERSION */ + +/* Define macros for some gcc attributes. This permits us to use the + macros freely, and know that they will come into play for the + version of gcc in which they are supported. */ + +#if (GCC_VERSION < 2007) +# define __attribute__(x) +#endif + +/* Attribute __malloc__ on functions was valid as of gcc 2.96. */ +#ifndef ATTRIBUTE_MALLOC +# if (GCC_VERSION >= 2096) +# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) +# else +# define ATTRIBUTE_MALLOC +# endif /* GNUC >= 2.96 */ +#endif /* ATTRIBUTE_MALLOC */ + +/* Attributes on labels were valid as of gcc 2.93. */ +#ifndef ATTRIBUTE_UNUSED_LABEL +# if (GCC_VERSION >= 2093) +# define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED +# else +# define ATTRIBUTE_UNUSED_LABEL +# endif /* GNUC >= 2.93 */ +#endif /* ATTRIBUTE_UNUSED_LABEL */ + +#ifndef ATTRIBUTE_UNUSED +#define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +#endif /* ATTRIBUTE_UNUSED */ + +#ifndef ATTRIBUTE_NORETURN +#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) +#endif /* ATTRIBUTE_NORETURN */ + +#ifndef ATTRIBUTE_PRINTF +#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n))) +#define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2) +#define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3) +#define ATTRIBUTE_PRINTF_3 ATTRIBUTE_PRINTF(3, 4) +#define ATTRIBUTE_PRINTF_4 ATTRIBUTE_PRINTF(4, 5) +#define ATTRIBUTE_PRINTF_5 ATTRIBUTE_PRINTF(5, 6) +#endif /* ATTRIBUTE_PRINTF */ + +/* We use __extension__ in some places to suppress -pedantic warnings + about GCC extensions. This feature didn't work properly before + gcc 2.8. */ +#if GCC_VERSION < 2008 +#define __extension__ +#endif + +/* Bootstrap support: Autoconf will possibly define the `inline' or + `const' keywords as macros, however this is only valid for the + stage1 compiler. If we detect a modern version of gcc, + unconditionally reset the values. This makes sure the right thing + happens in stage2 and later. We need to do this very early; + i.e. before any header files that might use these keywords. + Otherwise conflicts might occur. */ + +#if (GCC_VERSION >= 2007) +# ifdef __STDC__ +# undef const +# endif +# undef inline +# define inline __inline__ /* __inline__ prevents -pedantic warnings */ +# ifndef HAVE_LONG_DOUBLE +# define HAVE_LONG_DOUBLE 1 +# endif +#endif /* GCC >= 2.7 */ + +#endif /* ansidecl.h */ diff --git a/support/cpp2/config.h b/support/cpp2/config.h new file mode 100644 index 00000000..476f7acc --- /dev/null +++ b/support/cpp2/config.h @@ -0,0 +1,2 @@ +#include "auto-host.h" +#include "sdcc.h" diff --git a/support/cpp2/config.in b/support/cpp2/config.in new file mode 100644 index 00000000..1a3552c7 --- /dev/null +++ b/support/cpp2/config.in @@ -0,0 +1,386 @@ +/* config.in. Generated automatically from configure.in by autoheader. */ + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define to `int' if doesn't define. */ +#undef gid_t + +/* Define if you have the ANSI # stringizing operator in cpp. */ +#undef HAVE_STRINGIZE + +/* Define if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define if you have . */ +#undef HAVE_VFORK_H + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + +/* Define if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Define to `long' if doesn't define. */ +#undef off_t + +/* Define to `int' if doesn't define. */ +#undef pid_t + +/* Define to `unsigned' if doesn't define. */ +#undef size_t + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to `int' if doesn't define. */ +#undef uid_t + +/* Define vfork as fork if vfork does not work. */ +#undef vfork + +/* Define as 1 if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define to `int' if doesn't define. */ +#undef ssize_t + +/* Define if you have the atoll function. */ +#undef HAVE_ATOLL + +/* Define if you have the atoq function. */ +#undef HAVE_ATOQ + +/* Define if you have the clock function. */ +#undef HAVE_CLOCK + +/* Define if you have the dcgettext function. */ +#undef HAVE_DCGETTEXT + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the getrlimit function. */ +#undef HAVE_GETRLIMIT + +/* Define if you have the getrusage function. */ +#undef HAVE_GETRUSAGE + +/* Define if you have the kill function. */ +#undef HAVE_KILL + +/* Define if you have the lstat function. */ +#undef HAVE_LSTAT + +/* Define if you have the munmap function. */ +#undef HAVE_MUNMAP + +/* Define if you have the nl_langinfo function. */ +#undef HAVE_NL_LANGINFO + +/* Define if you have the putenv function. */ +#undef HAVE_PUTENV + +/* Define if you have the setenv function. */ +#undef HAVE_SETENV + +/* Define if you have the setlocale function. */ +#undef HAVE_SETLOCALE + +/* Define if you have the setrlimit function. */ +#undef HAVE_SETRLIMIT + +/* Define if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if you have the strcasecmp function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the strchr function. */ +#undef HAVE_STRCHR + +/* Define if you have the strdup function. */ +#undef HAVE_STRDUP + +/* Define if you have the strrchr function. */ +#undef HAVE_STRRCHR + +/* Define if you have the strstr function. */ +#undef HAVE_STRSTR + +/* Define if you have the times function. */ +#undef HAVE_TIMES + +/* Define if you have the header file. */ +#undef HAVE_ARGZ_H + +/* Define if you have the header file. */ +#undef HAVE_DIRECT_H + +/* Define if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the header file. */ +#undef HAVE_ICONV_H + +/* Define if you have the header file. */ +#undef HAVE_LANGINFO_H + +/* Define if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define if you have the header file. */ +#undef HAVE_NL_TYPES_H + +/* Define if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIMES_H + +/* Define if you have the header file. */ +#undef HAVE_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the i library (-li). */ +#undef HAVE_LIBI + +/* Define to enable the use of a default linker. */ +#undef DEFAULT_LINKER + +/* Define to enable the use of a default assembler. */ +#undef DEFAULT_ASSEMBLER + +/* Define if you want more run-time sanity checks. This one gets a grab + bag of miscellaneous but relatively cheap checks. */ +#undef ENABLE_CHECKING + +/* Define if you want all operations on trees (the basic data + structure of the front ends) to be checked for dynamic type safety + at runtime. This is moderately expensive. */ +#undef ENABLE_TREE_CHECKING + +/* Define if you want all operations on RTL (the basic data structure + of the optimizer and back end) to be checked for dynamic type safety + at runtime. This is quite expensive. */ +#undef ENABLE_RTL_CHECKING + +/* Define if you want the garbage collector to do object poisoning and + other memory allocation checks. This is quite expensive. */ +#undef ENABLE_GC_CHECKING + +/* Define if you want the garbage collector to operate in maximally + paranoid mode, validating the entire heap and collecting garbage at + every opportunity. This is extremely expensive. */ +#undef ENABLE_GC_ALWAYS_COLLECT + +/* Define if you want the C and C++ compilers to support multibyte + character sets for source code. */ +#undef MULTIBYTE_CHARS + +/* Define if your compiler understands volatile. */ +#undef HAVE_VOLATILE + +/* Define if your compiler supports the `long double' type. */ +#undef HAVE_LONG_DOUBLE + +/* The number of bytes in type short */ +#undef SIZEOF_SHORT + +/* The number of bytes in type int */ +#undef SIZEOF_INT + +/* The number of bytes in type long */ +#undef SIZEOF_LONG + +/* Define if the host execution character set is EBCDIC. */ +#undef HOST_EBCDIC + +/* Always define this when using the GNU C Library */ +#undef _GNU_SOURCE + +/* Define if you have a working header file. */ +#undef HAVE_STDBOOL_H + +/* Define if you can safely include both and . */ +#undef STRING_WITH_STRINGS + +/* Define as the number of bits in a byte, if `limits.h' doesn't. */ +#undef CHAR_BIT + +/* Define if the host machine stores words of multi-word integers in + big-endian order. */ +#undef HOST_WORDS_BIG_ENDIAN + +/* Define to the floating point format of the host machine, if not IEEE. */ +#undef HOST_FLOAT_FORMAT + +/* Define to 1 if the host machine stores floating point numbers in + memory with the word containing the sign bit at the lowest address, + or to 0 if it does it the other way around. + + This macro should not be defined if the ordering is the same as for + multi-word integers. */ +#undef HOST_FLOAT_WORDS_BIG_ENDIAN + +/* Define if you have a working header file. */ +#undef HAVE_INTTYPES_H + +/* Define if printf supports %p. */ +#undef HAVE_PRINTF_PTR + +/* Define if mmap can get us zeroed pages from /dev/zero. */ +#undef HAVE_MMAP_DEV_ZERO + +/* Define if mmap can get us zeroed pages using MAP_ANON(YMOUS). */ +#undef HAVE_MMAP_ANON + +/* Define if read-only mmap of a plain file works. */ +#undef HAVE_MMAP_FILE + +/* Define to 1 if we found this declaration otherwise define to 0. */ +#undef HAVE_DECL_GETENV + +/* Define to 1 if we found this declaration otherwise define to 0. */ +#undef HAVE_DECL_ABORT + +/* Define to 1 if we found this declaration otherwise define to 0. */ +#undef HAVE_DECL_ERRNO + +/* Define to 1 if we found this declaration otherwise define to 0. */ +#undef HAVE_DECL_MALLOC + +/* Define to 1 if we found this declaration otherwise define to 0. */ +#undef HAVE_DECL_REALLOC + +/* Define to 1 if we found this declaration otherwise define to 0. */ +#undef HAVE_DECL_CALLOC + +/* Define to 1 if we found this declaration otherwise define to 0. */ +#undef HAVE_DECL_FREE + +/* Define to 1 if we found this declaration otherwise define to 0. */ +#undef HAVE_DECL_BASENAME + +/* Define to 1 if we found this declaration otherwise define to 0. */ +#undef HAVE_DECL_GETOPT + +/* Define to 1 if we found this declaration otherwise define to 0. */ +#undef HAVE_DECL_CLOCK + +/* Define to 1 if we found this declaration otherwise define to 0. */ +#undef HAVE_DECL_GETRLIMIT + +/* Define to 1 if we found this declaration otherwise define to 0. */ +#undef HAVE_DECL_SETRLIMIT + +/* Define to 1 if we found this declaration otherwise define to 0. */ +#undef HAVE_DECL_GETRUSAGE + +/* Define to 1 if we found this declaration otherwise define to 0. */ +#undef HAVE_DECL_TIMES + +/* Define if defines struct tms. */ +#undef HAVE_STRUCT_TMS + +/* Define if defines clock_t. */ +#undef HAVE_CLOCK_T + +/* Define if host mkdir takes a single argument. */ +#undef MKDIR_TAKES_ONE_ARG + +/* Define to the name of the distribution. */ +#undef PACKAGE + +/* Define to the version of the distribution. */ +#undef VERSION + +/* Define to 1 if installation paths should be looked up in Windows32 + Registry. Ignored on non windows32 hosts. */ +#undef ENABLE_WIN32_REGISTRY + +/* Define to be the last portion of registry key on windows hosts. */ +#undef WIN32_REGISTRY_KEY + +/* Define if your assembler supports .subsection and .subsection -1 starts + emitting at the beginning of your section. */ +#undef HAVE_GAS_SUBSECTION_ORDERING + +/* Define if your assembler supports .weak. */ +#undef HAVE_GAS_WEAK + +/* Define if your assembler supports .hidden. */ +#undef HAVE_GAS_HIDDEN + +/* Define if your assembler supports .uleb128. */ +#undef HAVE_AS_LEB128 + +/* Define if your assembler mis-optimizes .eh_frame data. */ +#undef USE_AS_TRADITIONAL_FORMAT + +/* Define if your assembler supports .register. */ +#undef HAVE_AS_REGISTER_PSEUDO_OP + +/* Define if your assembler supports -relax option. */ +#undef HAVE_AS_RELAX_OPTION + +/* Define if the assembler supports 64bit sparc. */ +#undef AS_SPARC64_FLAG + +/* Define if your assembler supports offsetable %lo(). */ +#undef HAVE_AS_OFFSETABLE_LO10 + +/* Define if your assembler supports dwarf2 .file/.loc directives, + and preserves file table indicies exactly as given. */ +#undef HAVE_AS_DWARF2_DEBUG_LINE + +/* Define 0/1 to force the choice for exception handling model. */ +#undef CONFIG_SJLJ_EXCEPTIONS + + +/* Bison unconditionally undefines `const' if neither `__STDC__' nor + __cplusplus are defined. That's a problem since we use `const' in + the GCC headers, and the resulting bison code is therefore type + unsafe. Thus, we must match the bison behavior here. */ + +#ifndef __STDC__ +#ifndef __cplusplus +#undef const +#define const +#endif +#endif diff --git a/support/cpp2/configargs.h b/support/cpp2/configargs.h new file mode 100644 index 00000000..d384cbb1 --- /dev/null +++ b/support/cpp2/configargs.h @@ -0,0 +1,3 @@ +/* Generated automatically. */ +static const char configuration_arguments[] = " : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) : (reconfigured) "; +static const char thread_model[] = ""; diff --git a/support/cpp2/configure b/support/cpp2/configure new file mode 100755 index 00000000..6d4e755a --- /dev/null +++ b/support/cpp2/configure @@ -0,0 +1,3633 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --with-gnu-ld arrange to work with GNU ld." +ac_help="$ac_help + --with-ld arrange to use the specified ld (full pathname)" +ac_help="$ac_help + --with-gnu-as arrange to work with GNU as" +ac_help="$ac_help + --with-as arrange to use the specified as (full pathname)" +ac_help="$ac_help + --with-stabs arrange to use stabs instead of host debug format" +ac_help="$ac_help + --with-elf arrange to use ELF instead of host debug format" +ac_help="$ac_help + --with-local-prefix=DIR specifies directory to put local include" +ac_help="$ac_help + --enable-c-mbchar enable multibyte characters for C and C++" +ac_help="$ac_help + --enable-maintainer-mode + enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=cppmain.c + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + + +remove=rm +hard_link=ln +symbolic_link='ln -s' +copy=cp + +# Check for additional parameters + +# With GNU ld +# Check whether --with-gnu-ld or --without-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval="$with_gnu_ld" + gnu_ld_flag="$with_gnu_ld" +else + gnu_ld_flag=no +fi + + +# With pre-defined ld +# Check whether --with-ld or --without-ld was given. +if test "${with_ld+set}" = set; then + withval="$with_ld" + DEFAULT_LINKER="$with_ld" +fi + +if test x"${DEFAULT_LINKER+set}" = x"set"; then + if test ! -x "$DEFAULT_LINKER"; then + echo "configure: warning: cannot execute: $DEFAULT_LINKER: check --with-ld or env. var. DEFAULT_LINKER" 1>&2 + elif $DEFAULT_LINKER -v < /dev/null 2>&1 | grep GNU > /dev/null; then + gnu_ld_flag=yes + fi + cat >> confdefs.h <&2 + elif $DEFAULT_ASSEMBLER -v < /dev/null 2>&1 | grep GNU > /dev/null; then + gas_flag=yes + fi + cat >> confdefs.h <&2; exit 1; } ;; +no) ;; +*) local_prefix=$with_local_prefix ;; +esac +fi + + +# Default local prefix if it is empty +if test x$local_prefix = x; then + local_prefix=/usr/local +fi + +# Enable Multibyte Characters for C/C++ +# Check whether --enable-c-mbchar or --disable-c-mbchar was given. +if test "${enable_c_mbchar+set}" = set; then + enableval="$enable_c_mbchar" + if test x$enable_c_mbchar != xno; then + cat >> confdefs.h <<\EOF +#define MULTIBYTE_CHARS 1 +EOF + +fi +fi + + +# Find the native compiler +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:666: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:696: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:747: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:779: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 790 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:795: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:821: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:826: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:854: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +if test "x$CC" != xcc; then + echo $ac_n "checking whether $CC and cc understand -c and -o together""... $ac_c" 1>&6 +echo "configure:887: checking whether $CC and cc understand -c and -o together" >&5 +else + echo $ac_n "checking whether cc understands -c and -o together""... $ac_c" 1>&6 +echo "configure:890: checking whether cc understands -c and -o together" >&5 +fi +set dummy $CC; ac_cc="`echo $2 | + sed -e 's/[^a-zA-Z0-9_]/_/g' -e 's/^[0-9]/_/'`" +if eval "test \"`echo '$''{'ac_cv_prog_cc_${ac_cc}_c_o'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'foo(){}' > conftest.c +# Make sure it works both with $CC and with simple cc. +# We do the test twice because some compilers refuse to overwrite an +# existing .o file with -o, though they will create one. +ac_try='${CC-cc} -c conftest.c -o conftest.o 1>&5' +if { (eval echo configure:902: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } && + test -f conftest.o && { (eval echo configure:903: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; +then + eval ac_cv_prog_cc_${ac_cc}_c_o=yes + if test "x$CC" != xcc; then + # Test first that cc exists at all. + if { ac_try='cc -c conftest.c 1>&5'; { (eval echo configure:908: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + ac_try='cc -c conftest.c -o conftest.o 1>&5' + if { (eval echo configure:910: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } && + test -f conftest.o && { (eval echo configure:911: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; + then + # cc works too. + : + else + # cc exists but doesn't like -o. + eval ac_cv_prog_cc_${ac_cc}_c_o=no + fi + fi + fi +else + eval ac_cv_prog_cc_${ac_cc}_c_o=no +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" = yes"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 + cat >> confdefs.h <<\EOF +#define NO_MINUS_C_MINUS_O 1 +EOF + +fi + +# autoconf is lame and doesn't give us any substitution variable for this. +if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" = no"; then + NO_MINUS_C_MINUS_O=yes +else + OUTPUT_OPTION='-o $@' +fi + + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:947: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:968: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:985: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1002: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +echo $ac_n "checking for inline""... $ac_c" 1>&6 +echo "configure:1027: checking for inline" >&5 +if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_inline=$ac_kw; break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done + +fi + +echo "$ac_t""$ac_cv_c_inline" 1>&6 +case "$ac_cv_c_inline" in + inline | yes) ;; + no) cat >> confdefs.h <<\EOF +#define inline +EOF + ;; + *) cat >> confdefs.h <&6 +echo "configure:1069: checking size of short" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence. + cat > conftest.$ac_ext < + + +int main() { +switch (0) case 0: case (sizeof (short) == $ac_size):; +; return 0; } +EOF +if { (eval echo configure:1085: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_sizeof_short=$ac_size +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* + if test x$ac_cv_sizeof_short != x ; then break; fi +done + +fi + +if test x$ac_cv_sizeof_short = x ; then + { echo "configure: error: cannot determine a size for short" 1>&2; exit 1; } +fi +echo "$ac_t""$ac_cv_sizeof_short" 1>&6 +cat >> confdefs.h <&6 +echo "configure:1108: checking size of int" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence. + cat > conftest.$ac_ext < + + +int main() { +switch (0) case 0: case (sizeof (int) == $ac_size):; +; return 0; } +EOF +if { (eval echo configure:1124: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_sizeof_int=$ac_size +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* + if test x$ac_cv_sizeof_int != x ; then break; fi +done + +fi + +if test x$ac_cv_sizeof_int = x ; then + { echo "configure: error: cannot determine a size for int" 1>&2; exit 1; } +fi +echo "$ac_t""$ac_cv_sizeof_int" 1>&6 +cat >> confdefs.h <&6 +echo "configure:1147: checking size of long" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + for ac_size in 4 8 1 2 16 ; do # List sizes in rough order of prevalence. + cat > conftest.$ac_ext < + + +int main() { +switch (0) case 0: case (sizeof (long) == $ac_size):; +; return 0; } +EOF +if { (eval echo configure:1163: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_sizeof_long=$ac_size +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* + if test x$ac_cv_sizeof_long != x ; then break; fi +done + +fi + +if test x$ac_cv_sizeof_long = x ; then + { echo "configure: error: cannot determine a size for long" 1>&2; exit 1; } +fi +echo "$ac_t""$ac_cv_sizeof_long" 1>&6 +cat >> confdefs.h <&6 +echo "configure:1187: checking execution character set" >&5 +if eval "test \"`echo '$''{'ac_cv_c_charset'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5 | + egrep "ASCII" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_c_charset=ASCII +fi +rm -f conftest* + + if test x${ac_cv_c_charset+set} != xset; then + cat > conftest.$ac_ext <&5 | + egrep "EBCDIC" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_c_charset=EBCDIC +fi +rm -f conftest* + + fi + if test x${ac_cv_c_charset+set} != xset; then + ac_cv_c_charset=unknown + fi +fi + +echo "$ac_t""$ac_cv_c_charset" 1>&6 +if test $ac_cv_c_charset = unknown; then + { echo "configure: error: *** Cannot determine host character set." 1>&2; exit 1; } +elif test $ac_cv_c_charset = EBCDIC; then + cat >> confdefs.h <<\EOF +#define HOST_EBCDIC 1 +EOF + +fi + +# If the native compiler is GCC, we can enable warnings even in stage1. +# That's useful for people building cross-compilers, or just running a +# quick `make'. +warn_cflags= +if test "x$GCC" = "xyes"; then + warn_cflags='$(GCC_WARN_CFLAGS)' +fi + + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:1248: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +echo $ac_n "checking whether a default assembler was specified""... $ac_c" 1>&6 +echo "configure:1276: checking whether a default assembler was specified" >&5 +if test x"${DEFAULT_ASSEMBLER+set}" = x"set"; then + if test x"$gas_flag" = x"no"; then + echo "$ac_t""yes ($DEFAULT_ASSEMBLER)" 1>&6 + else + echo "$ac_t""yes ($DEFAULT_ASSEMBLER - GNU as)" 1>&6 + fi +else + echo "$ac_t""no" 1>&6 +fi + +echo $ac_n "checking whether a default linker was specified""... $ac_c" 1>&6 +echo "configure:1288: checking whether a default linker was specified" >&5 +if test x"${DEFAULT_LINKER+set}" = x"set"; then + if test x"$gnu_ld_flag" = x"no"; then + echo "$ac_t""yes ($DEFAULT_LINKER)" 1>&6 + else + echo "$ac_t""yes ($DEFAULT_LINKER - GNU ld)" 1>&6 + fi +else + echo "$ac_t""no" 1>&6 +fi + +echo $ac_n "checking for GNU C library""... $ac_c" 1>&6 +echo "configure:1300: checking for GNU C library" >&5 +if eval "test \"`echo '$''{'gcc_cv_glibc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { + +#if ! (defined __GLIBC__ || defined __GNU_LIBRARY__) +#error Not a GNU C library system +#endif +; return 0; } +EOF +if { (eval echo configure:1315: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + gcc_cv_glibc=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gcc_cv_glibc=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gcc_cv_glibc" 1>&6 +if test $gcc_cv_glibc = yes; then + cat >> confdefs.h <<\EOF +#define _GNU_SOURCE 1 +EOF + +fi + +# Find some useful tools +echo $ac_n "checking whether ln works""... $ac_c" 1>&6 +echo "configure:1337: checking whether ln works" >&5 +if eval "test \"`echo '$''{'gcc_cv_prog_LN'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftestdata_t +echo >conftestdata_f +if ln conftestdata_f conftestdata_t 2>/dev/null +then + gcc_cv_prog_LN="ln" +else + if ln -s conftestdata_f conftestdata_t 2>/dev/null + then + gcc_cv_prog_LN="ln -s" + else + gcc_cv_prog_LN=cp + fi +fi +rm -f conftestdata_f conftestdata_t + +fi +LN="$gcc_cv_prog_LN" +if test "$gcc_cv_prog_LN" = "ln"; then + echo "$ac_t""yes" 1>&6 +else + if test "$gcc_cv_prog_LN" = "ln -s"; then + echo "$ac_t""no, using ln -s" 1>&6 + else + echo "$ac_t""no, and neither does ln -s, so using cp" 1>&6 + fi +fi + +echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 +echo "configure:1369: checking whether ln -s works" >&5 +if eval "test \"`echo '$''{'gcc_cv_prog_LN_S'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftestdata_t +echo >conftestdata_f +if ln -s conftestdata_f conftestdata_t 2>/dev/null +then + gcc_cv_prog_LN_S="ln -s" +else + if ln conftestdata_f conftestdata_t 2>/dev/null + then + gcc_cv_prog_LN_S=ln + else + gcc_cv_prog_LN_S=cp + fi +fi +rm -f conftestdata_f conftestdata_t + +fi +LN_S="$gcc_cv_prog_LN_S" +if test "$gcc_cv_prog_LN_S" = "ln -s"; then + echo "$ac_t""yes" 1>&6 +else + if test "$gcc_cv_prog_LN_S" = "ln"; then + echo "$ac_t""no, using ln" 1>&6 + else + echo "$ac_t""no, and neither does ln, so using cp" 1>&6 + fi +fi + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1403: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1460: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + # OSF/1 installbsd also uses dspmsg, but is usable. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:1511: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +#include +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1524: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:1591: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 +echo "configure:1615: checking whether time.h and sys/time.h may both be included" >&5 +if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +int main() { +struct tm *tp; +; return 0; } +EOF +if { (eval echo configure:1629: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_header_time=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_time=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_time" 1>&6 +if test $ac_cv_header_time = yes; then + cat >> confdefs.h <<\EOF +#define TIME_WITH_SYS_TIME 1 +EOF + +fi + +echo $ac_n "checking whether string.h and strings.h may both be included""... $ac_c" 1>&6 +echo "configure:1650: checking whether string.h and strings.h may both be included" >&5 +if eval "test \"`echo '$''{'gcc_cv_header_string'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +int main() { + +; return 0; } +EOF +if { (eval echo configure:1663: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + gcc_cv_header_string=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gcc_cv_header_string=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gcc_cv_header_string" 1>&6 +if test $gcc_cv_header_string = yes; then + cat >> confdefs.h <<\EOF +#define STRING_WITH_STRINGS 1 +EOF + +fi + +echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 +echo "configure:1684: checking for sys/wait.h that is POSIX.1 compatible" >&5 +if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif +int main() { +int s; +wait (&s); +s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; +; return 0; } +EOF +if { (eval echo configure:1705: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_header_sys_wait_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_sys_wait_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6 +if test $ac_cv_header_sys_wait_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_SYS_WAIT_H 1 +EOF + +fi + +for ac_hdr in limits.h stddef.h string.h strings.h stdlib.h time.h \ + fcntl.h unistd.h sys/file.h sys/time.h \ + sys/resource.h sys/param.h sys/times.h sys/stat.h \ + direct.h malloc.h langinfo.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1732: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1742: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + +# Check for thread headers. + +# These tests can't be done till we know if we have limits.h. +echo $ac_n "checking for CHAR_BIT""... $ac_c" 1>&6 +echo "configure:1773: checking for CHAR_BIT" >&5 +if eval "test \"`echo '$''{'gcc_cv_decl_char_bit'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#endif +#ifdef CHAR_BIT +found +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "found" >/dev/null 2>&1; then + rm -rf conftest* + gcc_cv_decl_char_bit=yes +else + rm -rf conftest* + gcc_cv_decl_char_bit=no +fi +rm -f conftest* + + +fi + +echo "$ac_t""$gcc_cv_decl_char_bit" 1>&6 +if test $gcc_cv_decl_char_bit = no; then + echo $ac_n "checking number of bits in a byte""... $ac_c" 1>&6 +echo "configure:1803: checking number of bits in a byte" >&5 +if eval "test \"`echo '$''{'gcc_cv_c_nbby'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + i=8 + gcc_cv_c_nbby= + while test $i -lt 65; do + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + gcc_cv_c_nbby=$i; break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* + i=`expr $i + 1` + done + test -z "$gcc_cv_c_nbby" && gcc_cv_c_nbby=failed + +fi + +echo "$ac_t""$gcc_cv_c_nbby" 1>&6 +if test $gcc_cv_c_nbby = failed; then + { echo "configure: error: cannot determine number of bits in a byte" 1>&2; exit 1; } +else + cat >> confdefs.h <&6 +echo "configure:1846: checking byte ordering" >&5 +if eval "test \"`echo '$''{'ac_cv_c_compile_endian'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_compile_endian=unknown + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext < +#endif +/* This structure must have no internal padding. */ + struct { + char prefix[sizeof "\nendian:" - 1]; + short word; + char postfix[2]; + } tester = { + "\nendian:", +#if SIZEOF_SHORT == 4 + ('A' << (CHAR_BIT * 3)) | ('B' << (CHAR_BIT * 2)) | +#endif + ('A' << CHAR_BIT) | 'B', + 'X', '\n' +}; +EOF +if { (eval echo configure:1880: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + od -c conftest.o | + sed 's/^[0-7]*[ ]*/ / + s/\*/./g + s/ \\n/*/g + s/ [0-9][0-9][0-9]/./g + s/ \\[^ ]/./g' | + tr -d ' + ' | tr -s '*' ' +' | fold | sed '$a\ +' > conftest.dmp + if grep 'endian:AB' conftest.dmp >/dev/null 2>&1; then + ac_cv_c_compile_endian=big-endian + elif grep 'endian:BA' conftest.dmp >/dev/null 2>&1; then + ac_cv_c_compile_endian=little-endian + fi +fi +rm -rf conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + + +fi + +echo "$ac_t""$ac_cv_c_compile_endian" 1>&6 +if test $ac_cv_c_compile_endian = unknown; then + { echo "configure: error: *** unable to determine endianness" 1>&2; exit 1; } +elif test $ac_cv_c_compile_endian = big-endian; then + cat >> confdefs.h <<\EOF +#define HOST_WORDS_BIG_ENDIAN 1 +EOF + +fi + + +# See if we have the mktemp command. +# Extract the first word of "mktemp", so it can be a program name with args. +set dummy mktemp; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1923: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_have_mktemp_command'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$have_mktemp_command"; then + ac_cv_prog_have_mktemp_command="$have_mktemp_command" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_have_mktemp_command="yes" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_have_mktemp_command" && ac_cv_prog_have_mktemp_command="no" +fi +fi +have_mktemp_command="$ac_cv_prog_have_mktemp_command" +if test -n "$have_mktemp_command"; then + echo "$ac_t""$have_mktemp_command" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +# See if the stage1 system preprocessor understands the ANSI C +# preprocessor stringification operator. (Used by symcat.h.) + + +echo $ac_n "checking for preprocessor stringizing operator""... $ac_c" 1>&6 +echo "configure:1956: checking for preprocessor stringizing operator" >&5 +if eval "test \"`echo '$''{'ac_cv_c_stringize'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5 | + egrep "#teststring" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_c_stringize=no +else + rm -rf conftest* + ac_cv_c_stringize=yes +fi +rm -f conftest* + +fi + +if test "${ac_cv_c_stringize}" = yes +then + cat >> confdefs.h <<\EOF +#define HAVE_STRINGIZE 1 +EOF + +fi +echo "$ac_t""${ac_cv_c_stringize}" 1>&6 + + +# Use only if it exists, +# doesn't clash with , and declares intmax_t. +echo $ac_n "checking for inttypes.h""... $ac_c" 1>&6 +echo "configure:1994: checking for inttypes.h" >&5 +if eval "test \"`echo '$''{'gcc_cv_header_inttypes_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +int main() { +intmax_t i = -1; +; return 0; } +EOF +if { (eval echo configure:2007: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + gcc_cv_header_inttypes_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gcc_cv_header_inttypes_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gcc_cv_header_inttypes_h" 1>&6 +if test $gcc_cv_header_inttypes_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_INTTYPES_H 1 +EOF + +fi + + +for ac_func in times clock strchr strrchr lstat +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2031: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2059: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +echo $ac_n "checking for ssize_t""... $ac_c" 1>&6 +echo "configure:2085: checking for ssize_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_ssize_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z_0-9])ssize_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_ssize_t=yes +else + rm -rf conftest* + ac_cv_type_ssize_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_ssize_t" 1>&6 +if test $ac_cv_type_ssize_t = no; then + cat >> confdefs.h <<\EOF +#define ssize_t int +EOF + +fi + + +for ac_func in getpagesize +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2121: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2149: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +# The test program for the next two tests is the same except for one +# set of ifdefs. +cat >ct-mmap.inc <<'EOF' +#include +#include +#include +#include +#include +#include + +#if !defined (MAP_ANONYMOUS) && defined (MAP_ANON) +# define MAP_ANONYMOUS MAP_ANON +#endif + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +#ifndef MAP_FAILED +# define MAP_FAILED -1 +#endif + +#undef perror_exit +#define perror_exit(str, val) \ + do { perror(str); exit(val); } while (0) + +/* Some versions of cygwin mmap require that munmap is called with the + same parameters as mmap. GCC expects that this is not the case. + Test for various forms of this problem. Warning - icky signal games. */ + +static sigset_t unblock_sigsegv; +static jmp_buf r; +static size_t pg; +static int devzero; + +static char * +anonmap (size) + size_t size; +{ +#ifdef USE_MAP_ANON + return (char *) mmap (0, size, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); +#else + return (char *) mmap (0, size, PROT_READ|PROT_WRITE, + MAP_PRIVATE, devzero, 0); +#endif +} + +static void +sigsegv (unused) + int unused; +{ + sigprocmask (SIG_UNBLOCK, &unblock_sigsegv, 0); + longjmp (r, 1); +} + +/* Basic functionality test. */ +void +test_0 () +{ + char *x = anonmap (pg); + if (x == (char *) MAP_FAILED) + perror_exit("test 0 mmap", 2); + + *(int *)x += 1; + + if (munmap(x, pg) < 0) + perror_exit("test 0 munmap", 3); +} + +/* 1. If we map a 2-page region and unmap its second page, the first page + must remain. */ +static void +test_1 () +{ + char *x = anonmap (pg * 2); + if (x == (char *)MAP_FAILED) + perror_exit ("test 1 mmap", 4); + + signal (SIGSEGV, sigsegv); + if (setjmp (r)) + perror_exit ("test 1 fault", 5); + + x[0] = 1; + x[pg] = 1; + + if (munmap (x + pg, pg) < 0) + perror_exit ("test 1 munmap 1", 6); + x[0] = 2; + + if (setjmp (r) == 0) + { + x[pg] = 1; + perror_exit ("test 1 no fault", 7); + } + if (munmap (x, pg) < 0) + perror_exit ("test 1 munmap 2", 8); +} + +/* 2. If we map a 2-page region and unmap its first page, the second + page must remain. */ +static void +test_2 () +{ + char *x = anonmap (pg * 2); + if (x == (char *)MAP_FAILED) + perror_exit ("test 2 mmap", 9); + + signal (SIGSEGV, sigsegv); + if (setjmp (r)) + perror_exit ("test 2 fault", 10); + + x[0] = 1; + x[pg] = 1; + + if (munmap (x, pg) < 0) + perror_exit ("test 2 munmap 1", 11); + + x[pg] = 2; + + if (setjmp (r) == 0) + { + x[0] = 1; + perror_exit ("test 2 no fault", 12); + } + + if (munmap (x+pg, pg) < 0) + perror_exit ("test 2 munmap 2", 13); +} + +/* 3. If we map two adjacent 1-page regions and unmap them both with + one munmap, both must go away. + + Getting two adjacent 1-page regions with two mmap calls is slightly + tricky. All OS's tested skip over already-allocated blocks; therefore + we have been careful to unmap all allocated regions in previous tests. + HP/UX allocates pages backward in memory. No OS has yet been observed + to be so perverse as to leave unmapped space between consecutive calls + to mmap. */ + +static void +test_3 () +{ + char *x, *y, *z; + + x = anonmap (pg); + if (x == (char *)MAP_FAILED) + perror_exit ("test 3 mmap 1", 14); + y = anonmap (pg); + if (y == (char *)MAP_FAILED) + perror_exit ("test 3 mmap 2", 15); + + if (y != x + pg) + { + if (y == x - pg) + z = y, y = x, x = z; + else + { + fprintf (stderr, "test 3 nonconsecutive pages - %lx, %lx\n", + (unsigned long)x, (unsigned long)y); + exit (16); + } + } + + signal (SIGSEGV, sigsegv); + if (setjmp (r)) + perror_exit ("test 3 fault", 17); + + x[0] = 1; + y[0] = 1; + + if (munmap (x, pg*2) < 0) + perror_exit ("test 3 munmap", 18); + + if (setjmp (r) == 0) + { + x[0] = 1; + perror_exit ("test 3 no fault 1", 19); + } + + signal (SIGSEGV, sigsegv); + if (setjmp (r) == 0) + { + y[0] = 1; + perror_exit ("test 3 no fault 2", 20); + } +} + +int +main () +{ + sigemptyset (&unblock_sigsegv); + sigaddset (&unblock_sigsegv, SIGSEGV); + pg = getpagesize (); +#ifndef USE_MAP_ANON + devzero = open ("/dev/zero", O_RDWR); + if (devzero < 0) + perror_exit ("open /dev/zero", 1); +#endif + + test_0(); + test_1(); + test_2(); + test_3(); + + exit(0); +} +EOF + +echo $ac_n "checking for working mmap from /dev/zero""... $ac_c" 1>&6 +echo "configure:2420: checking for working mmap from /dev/zero" >&5 +if eval "test \"`echo '$''{'ac_cv_func_mmap_dev_zero'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + # If this is not cygwin, and /dev/zero is a character device, it's probably + # safe to assume it works. + case "$host_os" in + cygwin* | win32 | pe | mingw* ) ac_cv_func_mmap_dev_zero=buggy ;; + * ) if test -c /dev/zero + then ac_cv_func_mmap_dev_zero=yes + else ac_cv_func_mmap_dev_zero=no + fi ;; + esac +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_mmap_dev_zero=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + if test $? -lt 4 + then ac_cv_func_mmap_dev_zero=no + else ac_cv_func_mmap_dev_zero=buggy + fi +fi +rm -fr conftest* +fi + + +fi + +echo "$ac_t""$ac_cv_func_mmap_dev_zero" 1>&6 +if test $ac_cv_func_mmap_dev_zero = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP_DEV_ZERO 1 +EOF + +fi + +echo $ac_n "checking for working mmap with MAP_ANON(YMOUS)""... $ac_c" 1>&6 +echo "configure:2467: checking for working mmap with MAP_ANON(YMOUS)" >&5 +if eval "test \"`echo '$''{'ac_cv_func_mmap_anon'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + # Unlike /dev/zero, it is not safe to assume MAP_ANON(YMOUS) works + # just because it's there. Some SCO Un*xen define it but don't implement it. + ac_cv_func_mmap_anon=no +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_mmap_anon=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + if test $? -lt 4 + then ac_cv_func_mmap_anon=no + else ac_cv_func_mmap_anon=buggy + fi +fi +rm -fr conftest* +fi + + +fi + +echo "$ac_t""$ac_cv_func_mmap_anon" 1>&6 +if test $ac_cv_func_mmap_anon = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP_ANON 1 +EOF + +fi +rm -f ct-mmap.inc + +echo $ac_n "checking for working mmap of a file""... $ac_c" 1>&6 +echo "configure:2510: checking for working mmap of a file" >&5 +if eval "test \"`echo '$''{'ac_cv_func_mmap_file'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # Create a file one thousand bytes long. +for i in 1 2 3 4 5 6 7 8 9 0 +do for j in 1 2 3 4 5 6 7 8 9 0 +do echo $i $j xxxxx +done +done > conftestdata$$ + +if test "$cross_compiling" = yes; then + ac_cv_func_mmap_file=no +else + cat > conftest.$ac_ext < +#include +#include +#include + +int main() +{ + char *x; + int fd; + struct stat st; + + fd = open("conftestdata$$", O_RDONLY); + if (fd < 0) + exit(1); + + if (fstat (fd, &st)) + exit(2); + + x = (char*)mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (x == (char *) -1) + exit(3); + + if (x[0] != '1' || x[1] != ' ' || x[2] != '1' || x[3] != ' ') + exit(4); + + if (munmap(x, st.st_size) < 0) + exit(5); + + exit(0); +} +EOF +if { (eval echo configure:2562: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_mmap_file=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_mmap_file=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_func_mmap_file" 1>&6 +if test $ac_cv_func_mmap_file = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP_FILE 1 +EOF + +fi + + +# We will need to find libiberty.h and ansidecl.h +saved_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -I${srcdir} -I${srcdir}/../include" +for ac_func in getenv abort errno \ + malloc realloc calloc free getopt clock +do + ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` +echo $ac_n "checking whether $ac_func is declared""... $ac_c" 1>&6 +echo "configure:2593: checking whether $ac_func is declared" >&5 +if eval "test \"`echo '$''{'gcc_cv_have_decl_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + eval "gcc_cv_have_decl_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "gcc_cv_have_decl_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$gcc_cv_have_decl_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 ; cat >> confdefs.h <&6 ; cat >> confdefs.h <> confdefs.h <<\EOF +#define HAVE_DECL_GETENV 1 +EOF + cat >> confdefs.h <<\EOF +#define HAVE_DECL_ABORT 1 +EOF + cat >> confdefs.h <<\EOF +#define HAVE_DECL_ERRNO 1 +EOF + \ + cat >> confdefs.h <<\EOF +#define HAVE_DECL_MALLOC 1 +EOF + cat >> confdefs.h <<\EOF +#define HAVE_DECL_REALLOC 1 +EOF + cat >> confdefs.h <<\EOF +#define HAVE_DECL_CALLOC 1 +EOF + cat >> confdefs.h <<\EOF +#define HAVE_DECL_FREE 1 +EOF + cat >> confdefs.h <<\EOF +#define HAVE_DECL_GETOPT 1 +EOF + cat >> confdefs.h <<\EOF +#define HAVE_DECL_CLOCK 1 +EOF +fi + + +for ac_func in times +do + ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` +echo $ac_n "checking whether $ac_func is declared""... $ac_c" 1>&6 +echo "configure:2673: checking whether $ac_func is declared" >&5 +if eval "test \"`echo '$''{'gcc_cv_have_decl_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#endif + + +int main() { +#ifndef $ac_func +char *(*pfn) = (char *(*)) $ac_func ; +#endif +; return 0; } +EOF +if { (eval echo configure:2696: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + eval "gcc_cv_have_decl_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "gcc_cv_have_decl_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$gcc_cv_have_decl_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 ; cat >> confdefs.h <&6 ; cat >> confdefs.h <> confdefs.h <<\EOF +#define HAVE_DECL_TIMES 1 +EOF +fi + + +# More time-related stuff. +echo $ac_n "checking for struct tms""... $ac_c" 1>&6 +echo "configure:2730: checking for struct tms" >&5 +if eval "test \"`echo '$''{'ac_cv_struct_tms'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest.$ac_ext < +#endif + +int main() { +struct tms tms; +; return 0; } +EOF +if { (eval echo configure:2749: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_struct_tms=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_struct_tms=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_struct_tms" 1>&6 +if test $ac_cv_struct_tms = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_STRUCT_TMS 1 +EOF + +fi + +# use gcc_cv_* here because this doesn't match the behavior of AC_CHECK_TYPE. +# revisit after autoconf 2.50. +echo $ac_n "checking for clock_t""... $ac_c" 1>&6 +echo "configure:2772: checking for clock_t" >&5 +if eval "test \"`echo '$''{'gcc_cv_type_clock_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + +cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + gcc_cv_type_clock_t=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gcc_cv_type_clock_t=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gcc_cv_type_clock_t" 1>&6 +if test $gcc_cv_type_clock_t = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_CLOCK_T 1 +EOF + +fi + +# Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests. +CFLAGS="$saved_CFLAGS" + +# mkdir takes a single argument on some systems. +echo $ac_n "checking if mkdir takes one argument""... $ac_c" 1>&6 +echo "configure:2813: checking if mkdir takes one argument" >&5 +if eval "test \"`echo '$''{'gcc_cv_mkdir_takes_one_arg'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_DIRECT_H +# include +#endif +int main() { +mkdir ("foo", 0); +; return 0; } +EOF +if { (eval echo configure:2835: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + gcc_cv_mkdir_takes_one_arg=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gcc_cv_mkdir_takes_one_arg=yes +fi +rm -f conftest* +fi + +echo "$ac_t""$gcc_cv_mkdir_takes_one_arg" 1>&6 +if test $gcc_cv_mkdir_takes_one_arg = yes ; then + cat >> confdefs.h <<\EOF +#define MKDIR_TAKES_ONE_ARG 1 +EOF + +fi + + +# File extensions +manext='.1' +objext='.o' + + + +build_xm_file= +build_xm_defines= +build_install_headers_dir=install-headers-tar +build_exeext= +host_xm_file= +host_xm_defines= +host_xmake_file= +host_truncate_target= +host_exeext= + +# Decode the host machine, then the target machine. +# For the host machine, we save the xm_file variable as host_xm_file; +# then we decode the target machine and forget everything else +# that came from the host machine. +#for machine in $build $host $target; do +# . ${srcdir}/config.gcc +#done + +extra_objs="${host_extra_objs} ${extra_objs}" + +# Default the target-machine variables that were not explicitly set. +if test x"$tm_file" = x +then tm_file=$cpu_type/$cpu_type.h; fi + +if test x"$extra_headers" = x +then extra_headers=; fi + +if test x$md_file = x +then md_file=$cpu_type/$cpu_type.md; fi + +if test x$out_file = x +then out_file=$cpu_type/$cpu_type.c; fi + +if test x"$tmake_file" = x +then tmake_file=$cpu_type/t-$cpu_type +fi + +if test x"$dwarf2" = xyes +then tm_file="$tm_file tm-dwarf2.h" +fi + +# Handle cpp installation. +if test x$enable_cpp != xno +then + tmake_file="$tmake_file t-install-cpp" +fi + +# auto-host.h is the file containing items generated by autoconf and is +# the first file included by config.h. +# If host=build, it is correct to have hconfig include auto-host.h +# as well. If host!=build, we are in error and need to do more +# work to find out the build config parameters. +if test x$host = x$build +then + build_auto=auto-host.h +else + # We create a subdir, then run autoconf in the subdir. + # To prevent recursion we set host and build for the new + # invocation of configure to the build for this invocation + # of configure. + tempdir=build.$$ + rm -rf $tempdir + mkdir $tempdir + cd $tempdir + case ${srcdir} in + /* | A-Za-z:\\/* ) realsrcdir=${srcdir};; + *) realsrcdir=../${srcdir};; + esac + CC=${CC_FOR_BUILD} ${realsrcdir}/configure \ + --target=$target --host=$build --build=$build + + # We just finished tests for the build machine, so rename + # the file auto-build.h in the gcc directory. + mv auto-host.h ../auto-build.h + cd .. + rm -rf $tempdir + build_auto=auto-build.h +fi + +tm_file="${tm_file} defaults.h" +host_xm_file="auto-host.h ansidecl.h ${host_xm_file} ${tm_file}" +build_xm_file="${build_auto} ansidecl.h ${build_xm_file} ${tm_file}" +xm_file="ansidecl.h ${xm_file} ${tm_file}" + +# Truncate the target if necessary +if test x$host_truncate_target != x; then + target=`echo $target | sed -e 's/\(..............\).*/\1/'` +fi + +# Get the version trigger filename from the toplevel +if test "${with_gcc_version_trigger+set}" = set; then + gcc_version_trigger=$with_gcc_version_trigger +else + gcc_version_trigger=${srcdir}/version.c +fi +gcc_version_full=`grep version_string ${gcc_version_trigger} | sed -e 's/.*"\([^"]*\)".*/\1/'` +gcc_version=`echo ${gcc_version_full} | sed -e 's/\([^ ]*\) .*/\1/'` + +# Compile in configure arguments. +if test -f configargs.h ; then + # Being re-configured. + gcc_config_arguments=`grep configuration_arguments configargs.h | sed -e 's/.*"\([^"]*\)".*/\1/'` + gcc_config_arguments="$gcc_config_arguments : (reconfigured) $TOPLEVEL_CONFIGURE_ARGUMENTS" +else + gcc_config_arguments="$TOPLEVEL_CONFIGURE_ARGUMENTS" +fi +cat > configargs.h <> confdefs.h <> confdefs.h <&6 +echo "configure:3000: checking what assembler to use" >&5 +gcc_cv_as= +gcc_cv_gas_major_version= +gcc_cv_gas_minor_version= +gcc_cv_as_gas_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/gas +if test -x "$DEFAULT_ASSEMBLER"; then + gcc_cv_as="$DEFAULT_ASSEMBLER" +elif test -x "$AS"; then + gcc_cv_as="$AS" +elif test -x as$host_exeext; then + # Build using assembler in the current directory. + gcc_cv_as=./as$host_exeext +elif test -f $gcc_cv_as_gas_srcdir/configure.in -a -f ../gas/Makefile; then + # Single tree build which includes gas. + for f in $gcc_cv_as_gas_srcdir/configure $gcc_cv_as_gas_srcdir/configure.in $gcc_cv_as_gas_srcdir/Makefile.in + do + gcc_cv_gas_version=`grep '^VERSION=[0-9]*\.[0-9]*' $f` + if test x$gcc_cv_gas_version != x; then + break + fi + done + gcc_cv_gas_major_version=`expr "$gcc_cv_gas_version" : "VERSION=\([0-9]*\)"` + gcc_cv_gas_minor_version=`expr "$gcc_cv_gas_version" : "VERSION=[0-9]*\.\([0-9]*\)"` +fi + +if test "x$gcc_cv_as" = x -a x$host = x$target; then + # Native build. + # Search the same directories that the installed compiler will + # search. Else we may find the wrong assembler and lose. If we + # do not find a suitable assembler binary, then try the user's + # path. + # + # Also note we have to check MD_EXEC_PREFIX before checking the + # user's path. Unfortunately, there is no good way to get at the + # value of MD_EXEC_PREFIX here. So we do a brute force search + # through all the known MD_EXEC_PREFIX values. Ugh. This needs + # to be fixed as part of the make/configure rewrite too. + + if test "x$exec_prefix" = xNONE; then + if test "x$prefix" = xNONE; then + test_prefix=/usr/local + else + test_prefix=$prefix + fi + else + test_prefix=$exec_prefix + fi + + # If the loop below does not find an assembler, then use whatever + # one we can find in the users's path. + # user's path. + gcc_cv_as=as$host_exeext + + test_dirs="$test_prefix/lib/gcc-lib/$target/$gcc_version \ + $test_prefix/lib/gcc-lib/$target \ + /usr/lib/gcc/$target/$gcc_version \ + /usr/lib/gcc/$target \ + $test_prefix/$target/bin/$target/$gcc_version \ + $test_prefix/$target/bin \ + /usr/libexec \ + /usr/ccs/gcc \ + /usr/ccs/bin \ + /udk/usr/ccs/bin \ + /bsd43/usr/lib/cmplrs/cc \ + /usr/cross64/usr/bin \ + /usr/lib/cmplrs/cc \ + /sysv/usr/lib/cmplrs/cc \ + /svr4/usr/lib/cmplrs/cc \ + /usr/bin" + + for dir in $test_dirs; do + if test -f $dir/as$host_exeext; then + gcc_cv_as=$dir/as$host_exeext + break; + fi + done +fi +if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then + echo "$ac_t"""newly built gas"" 1>&6 +else + echo "$ac_t""$gcc_cv_as" 1>&6 +fi + +# Figure out what nm we will be using. +echo $ac_n "checking what nm to use""... $ac_c" 1>&6 +echo "configure:3085: checking what nm to use" >&5 +if test -x nm$host_exeext; then + gcc_cv_nm=./nm$host_exeext +elif test x$host = x$target; then + # Native build. + gcc_cv_nm=nm$host_exeext +fi +echo "$ac_t""$gcc_cv_nm" 1>&6 + + +echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 +echo "configure:3096: checking whether to enable maintainer-specific portions of Makefiles" >&5 + # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then + enableval="$enable_maintainer_mode" + maintainer_mode=$enableval +else + maintainer_mode=no +fi + + +echo "$ac_t""$maintainer_mode" 1>&6 + +if test "$maintainer_mode" = "yes"; then + MAINT='' +else + MAINT='#' +fi + +# These (without "all_") are set in each config-lang.in. +# `language' must be a single word so is spelled singularly. +all_stagestuff= +all_outputs='Makefile' +# List of language makefile fragments. + +# Add the language fragments. +# Languages are added via two mechanisms. Some information must be +# recorded in makefile variables, these are defined in config-lang.in. +# We accumulate them and plug them into the main Makefile. +# The other mechanism is a set of hooks for each of the main targets +# like `clean', `install', etc. + +language_fragments="Make-lang" + +# Define variables host_canonical and build_canonical +# because some Cygnus local changes in the Makefile depend on them. +build_canonical=${build} +host_canonical=${host} +target_subdir= +if test "${host}" != "${target}" ; then + target_subdir=${target_alias}/ +fi + + + + +# Nothing to do for FLOAT_H, float_format already handled. +objdir=`pwd` + + +# Substitute configuration variables + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# Create the Makefile +# and configure language subdirectories +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir + +trap 'rm -fr `echo "$all_outputs auto-host.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@CC@%$CC%g +s%@NO_MINUS_C_MINUS_O@%$NO_MINUS_C_MINUS_O%g +s%@OUTPUT_OPTION@%$OUTPUT_OPTION%g +s%@CPP@%$CPP%g +s%@warn_cflags@%$warn_cflags%g +s%@SET_MAKE@%$SET_MAKE%g +s%@LN@%$LN%g +s%@LN_S@%$LN_S%g +s%@RANLIB@%$RANLIB%g +s%@INSTALL@%$INSTALL%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@have_mktemp_command@%$have_mktemp_command%g +s%@manext@%$manext%g +s%@objext@%$objext%g +s%@PACKAGE@%$PACKAGE%g +s%@VERSION@%$VERSION%g +s%@MAINT@%$MAINT%g +s%@build_canonical@%$build_canonical%g +s%@host_canonical@%$host_canonical%g +s%@target_subdir@%$target_subdir%g +s%@objdir@%$objdir%g +s%@all_stagestuff@%$all_stagestuff%g +s%@build_exeext@%$build_exeext%g +s%@build_install_headers_dir@%$build_install_headers_dir%g +s%@build_xm_file_list@%$build_xm_file_list%g +s%@build_xm_file@%$build_xm_file%g +s%@build_xm_defines@%$build_xm_defines%g +s%@check_languages@%$check_languages%g +s%@dep_host_xmake_file@%$dep_host_xmake_file%g +s%@dep_tmake_file@%$dep_tmake_file%g +s%@extra_c_flags@%$extra_c_flags%g +s%@extra_headers_list@%$extra_headers_list%g +s%@extra_objs@%$extra_objs%g +s%@extra_parts@%$extra_parts%g +s%@extra_passes@%$extra_passes%g +s%@extra_programs@%$extra_programs%g +s%@gcc_config_arguments@%$gcc_config_arguments%g +s%@gcc_version@%$gcc_version%g +s%@gcc_version_full@%$gcc_version_full%g +s%@gcc_version_trigger@%$gcc_version_trigger%g +s%@host_exeext@%$host_exeext%g +s%@host_extra_gcc_objs@%$host_extra_gcc_objs%g +s%@install@%$install%g +s%@lang_tree_files@%$lang_tree_files%g +s%@local_prefix@%$local_prefix%g +s%@md_file@%$md_file%g +s%@out_file@%$out_file%g +s%@out_object_file@%$out_object_file%g +s%@symbolic_link@%$symbolic_link%g +s%@thread_file@%$thread_file%g +s%@c_target_objs@%$c_target_objs%g +/@target_overrides@/r $target_overrides +s%@target_overrides@%%g +/@host_overrides@/r $host_overrides +s%@host_overrides@%%g +s%@cross_defines@%$cross_defines%g +/@cross_overrides@/r $cross_overrides +s%@cross_overrides@%%g +/@build_overrides@/r $build_overrides +s%@build_overrides@%%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +case x$CONFIG_HEADERS in +xauto-host.h:config.in) +echo > cstamp-h ;; +esac + +# Avoid having to add intl to our include paths. +if test -f intl/libintl.h; then + echo creating libintl.h + echo '#include "intl/libintl.h"' >libintl.h +fi + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/support/cpp2/configure.in b/support/cpp2/configure.in new file mode 100644 index 00000000..08217434 --- /dev/null +++ b/support/cpp2/configure.in @@ -0,0 +1,655 @@ +# configure.in for GNU CC +# Process this file with autoconf to generate a configuration script. + +# Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + +#This file is part of GNU CC. + +#GNU CC 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. + +#GNU CC is distributed in the hope that 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 CC; see the file COPYING. If not, write to +#the Free Software Foundation, 59 Temple Place - Suite 330, +#Boston, MA 02111-1307, USA. + +# Initialization and defaults +AC_PREREQ(2.13) +AC_INIT(cppmain.c) +AC_CONFIG_HEADER(auto-host.h:config.in) + +remove=rm +hard_link=ln +symbolic_link='ln -s' +copy=cp + +# Check for additional parameters + +# With GNU ld +AC_ARG_WITH(gnu-ld, +[ --with-gnu-ld arrange to work with GNU ld.], +gnu_ld_flag="$with_gnu_ld", +gnu_ld_flag=no) + +# With pre-defined ld +AC_ARG_WITH(ld, +[ --with-ld arrange to use the specified ld (full pathname)], +DEFAULT_LINKER="$with_ld") +if test x"${DEFAULT_LINKER+set}" = x"set"; then + if test ! -x "$DEFAULT_LINKER"; then + AC_MSG_WARN([cannot execute: $DEFAULT_LINKER: check --with-ld or env. var. DEFAULT_LINKER]) + elif $DEFAULT_LINKER -v < /dev/null 2>&1 | grep GNU > /dev/null; then + gnu_ld_flag=yes + fi + AC_DEFINE_UNQUOTED(DEFAULT_LINKER,"$DEFAULT_LINKER", + [Define to enable the use of a default linker.]) +fi + +# With GNU as +AC_ARG_WITH(gnu-as, +[ --with-gnu-as arrange to work with GNU as], +gas_flag="$with_gnu_as", +gas_flag=no) + +AC_ARG_WITH(as, +[ --with-as arrange to use the specified as (full pathname)], +DEFAULT_ASSEMBLER="$with_as") +if test x"${DEFAULT_ASSEMBLER+set}" = x"set"; then + if test ! -x "$DEFAULT_ASSEMBLER"; then + AC_MSG_WARN([cannot execute: $DEFAULT_ASSEMBLER: check --with-as or env. var. DEFAULT_ASSEMBLER]) + elif $DEFAULT_ASSEMBLER -v < /dev/null 2>&1 | grep GNU > /dev/null; then + gas_flag=yes + fi + AC_DEFINE_UNQUOTED(DEFAULT_ASSEMBLER,"$DEFAULT_ASSEMBLER", + [Define to enable the use of a default assembler.]) +fi + +# With stabs +AC_ARG_WITH(stabs, +[ --with-stabs arrange to use stabs instead of host debug format], +stabs="$with_stabs", +stabs=no) + +# With ELF +AC_ARG_WITH(elf, +[ --with-elf arrange to use ELF instead of host debug format], +elf="$with_elf", +elf=no) + +# Specify the local prefix +local_prefix= +AC_ARG_WITH(local-prefix, +[ --with-local-prefix=DIR specifies directory to put local include], +[case "${withval}" in +yes) AC_MSG_ERROR(bad value ${withval} given for local include directory prefix) ;; +no) ;; +*) local_prefix=$with_local_prefix ;; +esac]) + +# Default local prefix if it is empty +if test x$local_prefix = x; then + local_prefix=/usr/local +fi + +# Enable Multibyte Characters for C/C++ +AC_ARG_ENABLE(c-mbchar, +[ --enable-c-mbchar enable multibyte characters for C and C++], +if test x$enable_c_mbchar != xno; then + AC_DEFINE(MULTIBYTE_CHARS, 1, + [Define if you want the C and C++ compilers to support multibyte + character sets for source code.]) +fi) + +# Find the native compiler +AC_PROG_CC +AC_PROG_CC_C_O +# autoconf is lame and doesn't give us any substitution variable for this. +if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" = no"; then + NO_MINUS_C_MINUS_O=yes +else + OUTPUT_OPTION='-o $@' +fi +AC_SUBST(NO_MINUS_C_MINUS_O) +AC_SUBST(OUTPUT_OPTION) + +AC_PROG_CPP +AC_C_INLINE + +# sizeof(char) is 1 by definition. +gcc_AC_COMPILE_CHECK_SIZEOF(short) +gcc_AC_COMPILE_CHECK_SIZEOF(int) +gcc_AC_COMPILE_CHECK_SIZEOF(long) + +gcc_AC_C_CHARSET + +# If the native compiler is GCC, we can enable warnings even in stage1. +# That's useful for people building cross-compilers, or just running a +# quick `make'. +warn_cflags= +if test "x$GCC" = "xyes"; then + warn_cflags='$(GCC_WARN_CFLAGS)' +fi +AC_SUBST(warn_cflags) + +AC_PROG_MAKE_SET + +AC_MSG_CHECKING([whether a default assembler was specified]) +if test x"${DEFAULT_ASSEMBLER+set}" = x"set"; then + if test x"$gas_flag" = x"no"; then + AC_MSG_RESULT([yes ($DEFAULT_ASSEMBLER)]) + else + AC_MSG_RESULT([yes ($DEFAULT_ASSEMBLER - GNU as)]) + fi +else + AC_MSG_RESULT(no) +fi + +AC_MSG_CHECKING([whether a default linker was specified]) +if test x"${DEFAULT_LINKER+set}" = x"set"; then + if test x"$gnu_ld_flag" = x"no"; then + AC_MSG_RESULT([yes ($DEFAULT_LINKER)]) + else + AC_MSG_RESULT([yes ($DEFAULT_LINKER - GNU ld)]) + fi +else + AC_MSG_RESULT(no) +fi + +AC_MSG_CHECKING(for GNU C library) +AC_CACHE_VAL(gcc_cv_glibc, +[AC_TRY_COMPILE( + [#include ],[ +#if ! (defined __GLIBC__ || defined __GNU_LIBRARY__) +#error Not a GNU C library system +#endif], + [gcc_cv_glibc=yes], + gcc_cv_glibc=no)]) +AC_MSG_RESULT($gcc_cv_glibc) +if test $gcc_cv_glibc = yes; then + AC_DEFINE(_GNU_SOURCE, 1, [Always define this when using the GNU C Library]) +fi + +# Find some useful tools +gcc_AC_PROG_LN +gcc_AC_PROG_LN_S +AC_PROG_RANLIB +gcc_AC_PROG_INSTALL + +AC_HEADER_STDC +AC_HEADER_TIME +gcc_AC_HEADER_STRING +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS(limits.h stddef.h string.h strings.h stdlib.h time.h \ + fcntl.h unistd.h sys/file.h sys/time.h \ + sys/resource.h sys/param.h sys/times.h sys/stat.h \ + direct.h malloc.h langinfo.h) + +# Check for thread headers. + +# These tests can't be done till we know if we have limits.h. +gcc_AC_C_CHAR_BIT +gcc_AC_C_COMPILE_ENDIAN + +# See if we have the mktemp command. +AC_CHECK_PROG(have_mktemp_command, mktemp, yes, no) + +# See if the stage1 system preprocessor understands the ANSI C +# preprocessor stringification operator. (Used by symcat.h.) +AC_C_STRINGIZE + +# Use only if it exists, +# doesn't clash with , and declares intmax_t. +AC_MSG_CHECKING(for inttypes.h) +AC_CACHE_VAL(gcc_cv_header_inttypes_h, +[AC_TRY_COMPILE( + [#include +#include ], + [intmax_t i = -1;], + [gcc_cv_header_inttypes_h=yes], + gcc_cv_header_inttypes_h=no)]) +AC_MSG_RESULT($gcc_cv_header_inttypes_h) +if test $gcc_cv_header_inttypes_h = yes; then + AC_DEFINE(HAVE_INTTYPES_H, 1, + [Define if you have a working header file.]) +fi + +dnl Disabled until we have a complete test for buggy enum bitfields. +dnl gcc_AC_C_ENUM_BF_UNSIGNED + +AC_CHECK_FUNCS(times clock strchr strrchr lstat) + +AC_CHECK_TYPE(ssize_t, int) + +AC_FUNC_MMAP_ANYWHERE +AC_FUNC_MMAP_FILE + +# We will need to find libiberty.h and ansidecl.h +saved_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -I${srcdir} -I${srcdir}/../include" +gcc_AC_CHECK_DECLS(getenv abort errno \ + malloc realloc calloc free getopt clock, , ,[ +#include "ansidecl.h" +#include "system.h"]) + +gcc_AC_CHECK_DECLS(times, , ,[ +#include "ansidecl.h" +#include "system.h" +#ifdef HAVE_SYS_TIMES_H +#include +#endif +]) + +# More time-related stuff. +AC_CACHE_CHECK(for struct tms, ac_cv_struct_tms, [ +AC_TRY_COMPILE([ +#include "ansidecl.h" +#include "system.h" +#ifdef HAVE_SYS_TIMES_H +#include +#endif +], [struct tms tms;], ac_cv_struct_tms=yes, ac_cv_struct_tms=no)]) +if test $ac_cv_struct_tms = yes; then + AC_DEFINE(HAVE_STRUCT_TMS, 1, + [Define if defines struct tms.]) +fi + +# use gcc_cv_* here because this doesn't match the behavior of AC_CHECK_TYPE. +# revisit after autoconf 2.50. +AC_CACHE_CHECK(for clock_t, gcc_cv_type_clock_t, [ +AC_TRY_COMPILE([ +#include "ansidecl.h" +#include "system.h" +], [clock_t x;], gcc_cv_type_clock_t=yes, gcc_cv_type_clock_t=no)]) +if test $gcc_cv_type_clock_t = yes; then + AC_DEFINE(HAVE_CLOCK_T, 1, + [Define if defines clock_t.]) +fi + +# Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests. +CFLAGS="$saved_CFLAGS" + +# mkdir takes a single argument on some systems. +gcc_AC_FUNC_MKDIR_TAKES_ONE_ARG + +# File extensions +manext='.1' +objext='.o' +AC_SUBST(manext) +AC_SUBST(objext) + +build_xm_file= +build_xm_defines= +build_install_headers_dir=install-headers-tar +build_exeext= +host_xm_file= +host_xm_defines= +host_xmake_file= +host_truncate_target= +host_exeext= + +# Decode the host machine, then the target machine. +# For the host machine, we save the xm_file variable as host_xm_file; +# then we decode the target machine and forget everything else +# that came from the host machine. +#for machine in $build $host $target; do +# . ${srcdir}/config.gcc +#done + +extra_objs="${host_extra_objs} ${extra_objs}" + +# Default the target-machine variables that were not explicitly set. +if test x"$tm_file" = x +then tm_file=$cpu_type/$cpu_type.h; fi + +if test x"$extra_headers" = x +then extra_headers=; fi + +if test x$md_file = x +then md_file=$cpu_type/$cpu_type.md; fi + +if test x$out_file = x +then out_file=$cpu_type/$cpu_type.c; fi + +if test x"$tmake_file" = x +then tmake_file=$cpu_type/t-$cpu_type +fi + +if test x"$dwarf2" = xyes +then tm_file="$tm_file tm-dwarf2.h" +fi + +# Handle cpp installation. +if test x$enable_cpp != xno +then + tmake_file="$tmake_file t-install-cpp" +fi + +# auto-host.h is the file containing items generated by autoconf and is +# the first file included by config.h. +# If host=build, it is correct to have hconfig include auto-host.h +# as well. If host!=build, we are in error and need to do more +# work to find out the build config parameters. +if test x$host = x$build +then + build_auto=auto-host.h +else + # We create a subdir, then run autoconf in the subdir. + # To prevent recursion we set host and build for the new + # invocation of configure to the build for this invocation + # of configure. + tempdir=build.$$ + rm -rf $tempdir + mkdir $tempdir + cd $tempdir + case ${srcdir} in + /* | [A-Za-z]:[\\/]* ) realsrcdir=${srcdir};; + *) realsrcdir=../${srcdir};; + esac + CC=${CC_FOR_BUILD} ${realsrcdir}/configure \ + --target=$target --host=$build --build=$build + + # We just finished tests for the build machine, so rename + # the file auto-build.h in the gcc directory. + mv auto-host.h ../auto-build.h + cd .. + rm -rf $tempdir + build_auto=auto-build.h +fi + +tm_file="${tm_file} defaults.h" +host_xm_file="auto-host.h ansidecl.h ${host_xm_file} ${tm_file}" +build_xm_file="${build_auto} ansidecl.h ${build_xm_file} ${tm_file}" +xm_file="ansidecl.h ${xm_file} ${tm_file}" + +# Truncate the target if necessary +if test x$host_truncate_target != x; then + target=`echo $target | sed -e 's/\(..............\).*/\1/'` +fi + +# Get the version trigger filename from the toplevel +if test "${with_gcc_version_trigger+set}" = set; then + gcc_version_trigger=$with_gcc_version_trigger +else + gcc_version_trigger=${srcdir}/version.c +fi +changequote(,)dnl +gcc_version_full=`grep version_string ${gcc_version_trigger} | sed -e 's/.*"\([^"]*\)".*/\1/'` +gcc_version=`echo ${gcc_version_full} | sed -e 's/\([^ ]*\) .*/\1/'` + +# Compile in configure arguments. +if test -f configargs.h ; then + # Being re-configured. + gcc_config_arguments=`grep configuration_arguments configargs.h | sed -e 's/.*"\([^"]*\)".*/\1/'` + gcc_config_arguments="$gcc_config_arguments : (reconfigured) $TOPLEVEL_CONFIGURE_ARGUMENTS" +else + gcc_config_arguments="$TOPLEVEL_CONFIGURE_ARGUMENTS" +fi +cat > configargs.h < cstamp-h ;; +esac + +# Avoid having to add intl to our include paths. +if test -f intl/libintl.h; then + echo creating libintl.h + echo '#include "intl/libintl.h"' >libintl.h +fi +], +[ +host='${host}' +build='${build}' +target='${target}' +target_alias='${target_alias}' +srcdir='${srcdir}' +symbolic_link='${symbolic_link}' +program_transform_set='${program_transform_set}' +program_transform_name='${program_transform_name}' +dep_host_xmake_file='${dep_host_xmake_file}' +host_xmake_file='${host_xmake_file}' +dep_tmake_file='${dep_tmake_file}' +tmake_file='${tmake_file}' +thread_file='${thread_file}' +gcc_config_arguments='${gcc_config_arguments}' +gcc_version='${gcc_version}' +gcc_version_full='${gcc_version_full}' +gcc_version_trigger='${gcc_version_trigger}' +local_prefix='${local_prefix}' +build_install_headers_dir='${build_install_headers_dir}' +build_exeext='${build_exeext}' +host_exeext='${host_exeext}' +out_file='${out_file}' +gdb_needs_out_file_path='${gdb_needs_out_file_path}' +SET_MAKE='${SET_MAKE}' +target_list='${target_list}' +target_overrides='${target_overrides}' +host_overrides='${host_overrides}' +cross_defines='${cross_defines}' +cross_overrides='${cross_overrides}' +build_overrides='${build_overrides}' +cpp_install_dir='${cpp_install_dir}' +]) diff --git a/support/cpp2/cppdefault.c b/support/cpp2/cppdefault.c new file mode 100644 index 00000000..328971ba --- /dev/null +++ b/support/cpp2/cppdefault.c @@ -0,0 +1,80 @@ +/* CPP Library. + Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000 Free Software Foundation, Inc. + Contributed by Per Bothner, 1994-95. + Based on CCCP program by Paul Rubin, June 1986 + Adapted to ANSI C, Richard Stallman, Jan 1987 + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This file contains data definitions shared between cpplib and + tradcpp. */ + +#include "config.h" +#include "system.h" +#include "cppdefault.h" + +const struct default_include cpp_include_defaults[] +#ifdef INCLUDE_DEFAULTS += INCLUDE_DEFAULTS; +#else += { +#ifdef GPLUSPLUS_INCLUDE_DIR + /* Pick up GNU C++ generic include files. */ + { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 }, +#endif +#ifdef GPLUSPLUS_TOOL_INCLUDE_DIR + /* Pick up GNU C++ target-dependent include files. */ + { GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1 }, +#endif +#ifdef GPLUSPLUS_BACKWARD_INCLUDE_DIR + /* Pick up GNU C++ backward and deprecated include files. */ + { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1 }, +#endif +#ifdef LOCAL_INCLUDE_DIR + /* /usr/local/include comes before the fixincluded header files. */ + { LOCAL_INCLUDE_DIR, 0, 0, 1 }, +#endif +#ifdef GCC_INCLUDE_DIR + /* This is the dir for fixincludes and for gcc's private headers. */ + { GCC_INCLUDE_DIR, "GCC", 0, 0 }, +#endif +#ifdef CROSS_INCLUDE_DIR + /* One place the target system's headers might be. */ + { CROSS_INCLUDE_DIR, "GCC", 0, 0 }, +#endif +#ifdef TOOL_INCLUDE_DIR + /* Another place the target system's headers might be. */ + { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 }, +#endif +#ifdef SYSTEM_INCLUDE_DIR + /* Some systems have an extra dir of include files. */ + { SYSTEM_INCLUDE_DIR, 0, 0, 0 }, +#endif +#ifdef STANDARD_INCLUDE_DIR + /* /usr/include comes dead last. */ + { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 }, +#endif + { 0, 0, 0, 0 } + }; +#endif /* no INCLUDE_DEFAULTS */ + +#ifdef GCC_INCLUDE_DIR +const char cpp_GCC_INCLUDE_DIR[] = GCC_INCLUDE_DIR; +const size_t cpp_GCC_INCLUDE_DIR_len = sizeof GCC_INCLUDE_DIR - 8; +#else +const char cpp_GCC_INCLUDE_DIR[] = ""; +const size_t cpp_GCC_INCLUDE_DIR_len = 0; +#endif diff --git a/support/cpp2/cppdefault.h b/support/cpp2/cppdefault.h new file mode 100644 index 00000000..8ee6a1fd --- /dev/null +++ b/support/cpp2/cppdefault.h @@ -0,0 +1,112 @@ +/* CPP Library. + Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000 Free Software Foundation, Inc. + Contributed by Per Bothner, 1994-95. + Based on CCCP program by Paul Rubin, June 1986 + Adapted to ANSI C, Richard Stallman, Jan 1987 + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef GCC_CPPDEFAULT_H +#define GCC_CPPDEFAULT_H + +/* This header contains declarations and/or #defines for all the + hard-wired defaults in cpp. Note it's used by both cpplib and + tradcpp. */ + +#ifndef STANDARD_INCLUDE_DIR +#define STANDARD_INCLUDE_DIR "/usr/include" +#endif + +#ifndef STANDARD_INCLUDE_COMPONENT +#define STANDARD_INCLUDE_COMPONENT 0 +#endif + +#ifdef CROSS_COMPILE +#undef LOCAL_INCLUDE_DIR +#undef SYSTEM_INCLUDE_DIR +#undef STANDARD_INCLUDE_DIR +#else +#undef CROSS_INCLUDE_DIR +#endif + +/* We let tm.h override the types used here, to handle trivial differences + such as the choice of unsigned int or long unsigned int for size_t. + When machines start needing nontrivial differences in the size type, + it would be best to do something here to figure out automatically + from other information what type to use. */ + +/* The string value for __SIZE_TYPE__. */ + +#ifndef SIZE_TYPE +#define SIZE_TYPE "long unsigned int" +#endif + +/* The string value for __PTRDIFF_TYPE__. */ + +#ifndef PTRDIFF_TYPE +#define PTRDIFF_TYPE "long int" +#endif + +/* The string value for __WCHAR_TYPE__. */ + +#ifndef WCHAR_TYPE +#define WCHAR_TYPE "int" +#endif + +/* The string value for __WINT_TYPE__. */ + +#ifndef WINT_TYPE +#define WINT_TYPE "unsigned int" +#endif + +/* The string value for __USER_LABEL_PREFIX__ */ + +#ifndef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "" +#endif + +/* The string value for __REGISTER_PREFIX__ */ + +#ifndef REGISTER_PREFIX +#define REGISTER_PREFIX "" +#endif + +/* This is the default list of directories to search for include files. + It may be overridden by the various -I and -ixxx options. + + #include "file" looks in the same directory as the current file, + then this list. + #include just looks in this list. + + All these directories are treated as `system' include directories + (they are not subject to pedantic warnings in some cases). */ + +struct default_include +{ + const char *fname; /* The name of the directory. */ + const char *component; /* The component containing the directory + (see update_path in prefix.c) */ + int cplusplus; /* Only look here if we're compiling C++. */ + int cxx_aware; /* Includes in this directory don't need to + be wrapped in extern "C" when compiling + C++. */ +}; + +extern const struct default_include cpp_include_defaults[]; +extern const char cpp_GCC_INCLUDE_DIR[]; +extern const size_t cpp_GCC_INCLUDE_DIR_len; + +#endif /* ! GCC_CPPDEFAULT_H */ diff --git a/support/cpp2/cpperror.c b/support/cpp2/cpperror.c new file mode 100644 index 00000000..063489da --- /dev/null +++ b/support/cpp2/cpperror.c @@ -0,0 +1,484 @@ +/* Default error handlers for CPP Library. + Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998, 1999, 2000 + Free Software Foundation, Inc. + Written by Per Bothner, 1994. + Based on CCCP program by Paul Rubin, June 1986 + Adapted to ANSI C, Richard Stallman, Jan 1987 + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! */ + +#include "config.h" +#include "system.h" +#include "cpplib.h" +#include "cpphash.h" +#include "intl.h" + +static void print_containing_files PARAMS ((cpp_buffer *)); +static void print_location PARAMS ((cpp_reader *, + const char *, + const cpp_lexer_pos *)); + +/* Don't remove the blank before do, as otherwise the exgettext + script will mistake this as a function definition */ +#define v_message(msgid, ap) \ + do { vfprintf (stderr, _(msgid), ap); putc ('\n', stderr); } while (0) + +/* Print the file names and line numbers of the #include + commands which led to the current file. */ +static void +print_containing_files (ip) + cpp_buffer *ip; +{ + int first = 1; + + /* Find the other, outer source files. */ + for (ip = ip->prev; ip; ip = ip->prev) + { + if (first) + { + first = 0; + /* The current line in each outer source file is now the + same as the line of the #include. */ + fprintf (stderr, _("In file included from %s:%u"), + ip->nominal_fname, CPP_BUF_LINE (ip)); + } + else + /* Translators note: this message is used in conjunction + with "In file included from %s:%ld" and some other + tricks. We want something like this: + + | In file included from sys/select.h:123, + | from sys/types.h:234, + | from userfile.c:31: + | bits/select.h:45: + + with all the "from"s lined up. + The trailing comma is at the beginning of this message, + and the trailing colon is not translated. */ + fprintf (stderr, _(",\n from %s:%u"), + ip->nominal_fname, CPP_BUF_LINE (ip)); + } + fputs (":\n", stderr); +} + +static void +print_location (pfile, filename, pos) + cpp_reader *pfile; + const char *filename; + const cpp_lexer_pos *pos; +{ + cpp_buffer *buffer = pfile->buffer; + + if (!buffer) + fprintf (stderr, "%s: ", progname); + else + { + unsigned int line, col = 0; + enum cpp_buffer_type type = buffer->type; + + /* For _Pragma buffers, we want to print the location as + "foo.c:5:8: _Pragma:", where foo.c is the containing buffer. + For diagnostics relating to command line options, we want to + print ":" with no line number. */ + if (type == BUF_CL_OPTION || type == BUF_BUILTIN) + line = 0; + else + { + if (type == BUF_PRAGMA) + { + buffer = buffer->prev; + line = CPP_BUF_LINE (buffer); + col = CPP_BUF_COL (buffer); + } + else + { + if (pos == 0) + pos = cpp_get_line (pfile); + line = pos->line; + col = pos->col; + } + + if (col == 0) + col = 1; + + /* Don't repeat the include stack unnecessarily. */ + if (buffer->prev && ! buffer->include_stack_listed) + { + buffer->include_stack_listed = 1; + print_containing_files (buffer); + } + } + + if (filename == 0) + filename = buffer->nominal_fname; + + if (line == 0) + fprintf (stderr, "%s: ", filename); + else if (CPP_OPTION (pfile, show_column) == 0) + fprintf (stderr, "%s:%u: ", filename, line); + else + fprintf (stderr, "%s:%u:%u: ", filename, line, col); + + if (type == BUF_PRAGMA) + fprintf (stderr, "_Pragma: "); + } +} + +/* Set up for an error message: print the file and line, bump the error + counter, etc. + If it returns 0, this error has been suppressed. */ + +int +_cpp_begin_message (pfile, code, file, pos) + cpp_reader *pfile; + enum error_type code; + const char *file; + const cpp_lexer_pos *pos; +{ + int is_warning = 0; + + switch (code) + { + case PEDWARN: + case WARNING: + if (CPP_IN_SYSTEM_HEADER (pfile) + && ! CPP_OPTION (pfile, warn_system_headers)) + return 0; + case WARNING_SYSHDR: + if (CPP_OPTION (pfile, warnings_are_errors) + || (code == PEDWARN && CPP_OPTION (pfile, pedantic_errors))) + { + if (CPP_OPTION (pfile, inhibit_errors)) + return 0; + if (pfile->errors < CPP_FATAL_LIMIT) + pfile->errors++; + } + else + { + if (CPP_OPTION (pfile, inhibit_warnings)) + return 0; + is_warning = 1; + } + break; + + case ERROR: + if (CPP_OPTION (pfile, inhibit_errors)) + return 0; + if (pfile->errors < CPP_FATAL_LIMIT) + pfile->errors++; + break; + /* Fatal errors cannot be inhibited. */ + case FATAL: + pfile->errors = CPP_FATAL_LIMIT; + break; + case ICE: + fprintf (stderr, _("internal error: ")); + pfile->errors = CPP_FATAL_LIMIT; + break; + } + + print_location (pfile, file, pos); + if (is_warning) + fputs (_("warning: "), stderr); + + return 1; +} + +/* Exported interface. */ + +/* For reporting internal errors. Prints "internal error: " for you, + otherwise identical to cpp_fatal. */ + +void +cpp_ice VPARAMS ((cpp_reader *pfile, const char *msgid, ...)) +{ +#ifndef ANSI_PROTOTYPES + cpp_reader *pfile; + const char *msgid; +#endif + va_list ap; + + VA_START (ap, msgid); + +#ifndef ANSI_PROTOTYPES + pfile = va_arg (ap, cpp_reader *); + msgid = va_arg (ap, const char *); +#endif + + if (_cpp_begin_message (pfile, ICE, NULL, 0)) + v_message (msgid, ap); + va_end(ap); +} + +/* Same as cpp_error, except we consider the error to be "fatal", + such as inconsistent options. I.e. there is little point in continuing. + (We do not exit, to support use of cpplib as a library. + Instead, it is the caller's responsibility to check + CPP_FATAL_ERRORS. */ + +void +cpp_fatal VPARAMS ((cpp_reader *pfile, const char *msgid, ...)) +{ +#ifndef ANSI_PROTOTYPES + cpp_reader *pfile; + const char *msgid; +#endif + va_list ap; + + VA_START (ap, msgid); + +#ifndef ANSI_PROTOTYPES + pfile = va_arg (ap, cpp_reader *); + msgid = va_arg (ap, const char *); +#endif + + if (_cpp_begin_message (pfile, FATAL, NULL, 0)) + v_message (msgid, ap); + va_end(ap); +} + +void +cpp_error VPARAMS ((cpp_reader * pfile, const char *msgid, ...)) +{ +#ifndef ANSI_PROTOTYPES + cpp_reader *pfile; + const char *msgid; +#endif + va_list ap; + + VA_START(ap, msgid); + +#ifndef ANSI_PROTOTYPES + pfile = va_arg (ap, cpp_reader *); + msgid = va_arg (ap, const char *); +#endif + + if (_cpp_begin_message (pfile, ERROR, NULL, 0)) + v_message (msgid, ap); + va_end(ap); +} + +void +cpp_error_with_line VPARAMS ((cpp_reader *pfile, int line, int column, + const char *msgid, ...)) +{ +#ifndef ANSI_PROTOTYPES + cpp_reader *pfile; + int line; + int column; + const char *msgid; +#endif + va_list ap; + cpp_lexer_pos pos; + + VA_START (ap, msgid); + +#ifndef ANSI_PROTOTYPES + pfile = va_arg (ap, cpp_reader *); + line = va_arg (ap, int); + column = va_arg (ap, int); + msgid = va_arg (ap, const char *); +#endif + + pos.line = line; + pos.col = column; + if (_cpp_begin_message (pfile, ERROR, NULL, &pos)) + v_message (msgid, ap); + va_end(ap); +} + +/* Error including a message from `errno'. */ +void +cpp_error_from_errno (pfile, name) + cpp_reader *pfile; + const char *name; +{ + cpp_error (pfile, "%s: %s", name, xstrerror (errno)); +} + +void +cpp_warning VPARAMS ((cpp_reader * pfile, const char *msgid, ...)) +{ +#ifndef ANSI_PROTOTYPES + cpp_reader *pfile; + const char *msgid; +#endif + va_list ap; + + VA_START (ap, msgid); + +#ifndef ANSI_PROTOTYPES + pfile = va_arg (ap, cpp_reader *); + msgid = va_arg (ap, const char *); +#endif + + if (_cpp_begin_message (pfile, WARNING, NULL, 0)) + v_message (msgid, ap); + va_end(ap); +} + +void +cpp_warning_with_line VPARAMS ((cpp_reader * pfile, int line, int column, + const char *msgid, ...)) +{ +#ifndef ANSI_PROTOTYPES + cpp_reader *pfile; + int line; + int column; + const char *msgid; +#endif + va_list ap; + cpp_lexer_pos pos; + + VA_START (ap, msgid); + +#ifndef ANSI_PROTOTYPES + pfile = va_arg (ap, cpp_reader *); + line = va_arg (ap, int); + column = va_arg (ap, int); + msgid = va_arg (ap, const char *); +#endif + + pos.line = line; + pos.col = column; + if (_cpp_begin_message (pfile, WARNING, NULL, &pos)) + v_message (msgid, ap); + va_end(ap); +} + +void +cpp_pedwarn VPARAMS ((cpp_reader * pfile, const char *msgid, ...)) +{ +#ifndef ANSI_PROTOTYPES + cpp_reader *pfile; + const char *msgid; +#endif + va_list ap; + + VA_START (ap, msgid); + +#ifndef ANSI_PROTOTYPES + pfile = va_arg (ap, cpp_reader *); + msgid = va_arg (ap, const char *); +#endif + + if (_cpp_begin_message (pfile, PEDWARN, NULL, 0)) + v_message (msgid, ap); + va_end(ap); +} + +void +cpp_pedwarn_with_line VPARAMS ((cpp_reader * pfile, int line, int column, + const char *msgid, ...)) +{ +#ifndef ANSI_PROTOTYPES + cpp_reader *pfile; + int line; + int column; + const char *msgid; +#endif + va_list ap; + cpp_lexer_pos pos; + + VA_START (ap, msgid); + +#ifndef ANSI_PROTOTYPES + pfile = va_arg (ap, cpp_reader *); + line = va_arg (ap, int); + column = va_arg (ap, int); + msgid = va_arg (ap, const char *); +#endif + + pos.line = line; + pos.col = column; + if (_cpp_begin_message (pfile, PEDWARN, NULL, &pos)) + v_message (msgid, ap); + va_end(ap); +} + +/* Report a warning (or an error if pedantic_errors) + giving specified file name and line number, not current. */ + +void +cpp_pedwarn_with_file_and_line VPARAMS ((cpp_reader *pfile, + const char *file, int line, int col, + const char *msgid, ...)) +{ +#ifndef ANSI_PROTOTYPES + cpp_reader *pfile; + const char *file; + int line; + int col; + const char *msgid; +#endif + va_list ap; + cpp_lexer_pos pos; + + VA_START (ap, msgid); + +#ifndef ANSI_PROTOTYPES + pfile = va_arg (ap, cpp_reader *); + file = va_arg (ap, const char *); + line = va_arg (ap, int); + col = va_arg (ap, int); + msgid = va_arg (ap, const char *); +#endif + + pos.line = line; + pos.col = col; + if (_cpp_begin_message (pfile, PEDWARN, file, &pos)) + v_message (msgid, ap); + va_end(ap); +} + +/* Print an error message not associated with a file. */ +void +cpp_notice VPARAMS ((cpp_reader *pfile, const char *msgid, ...)) +{ +#ifndef ANSI_PROTOTYPES + cpp_reader *pfile; + const char *msgid; +#endif + va_list ap; + + VA_START (ap, msgid); + +#ifndef ANSI_PROTOTYPES + pfile = va_arg (ap, cpp_reader *); + msgid = va_arg (ap, const char *); +#endif + + if (pfile->errors < CPP_FATAL_LIMIT) + pfile->errors++; + + vfprintf (stderr, _(msgid), ap); + putc('\n', stderr); + + va_end(ap); +} + +void +cpp_notice_from_errno (pfile, name) + cpp_reader *pfile; + const char *name; +{ + if (name[0] == '\0') + name = "stdout"; + cpp_notice (pfile, "%s: %s", name, xstrerror (errno)); +} diff --git a/support/cpp2/cppexp.c b/support/cpp2/cppexp.c new file mode 100644 index 00000000..051551ed --- /dev/null +++ b/support/cpp2/cppexp.c @@ -0,0 +1,897 @@ +/* Parse C expressions for cpplib. + Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2001 + Free Software Foundation. + Contributed by Per Bothner, 1994. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "config.h" +#include "system.h" +#include "cpplib.h" +#include "cpphash.h" + +/* Yield nonzero if adding two numbers with A's and B's signs can yield a + number with SUM's sign, where A, B, and SUM are all C integers. */ +#define possible_sum_sign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0) + +static void integer_overflow PARAMS ((cpp_reader *)); +static HOST_WIDEST_INT left_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT, + unsigned int, + unsigned HOST_WIDEST_INT)); +static HOST_WIDEST_INT right_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT, + unsigned int, + unsigned HOST_WIDEST_INT)); +static struct op parse_number PARAMS ((cpp_reader *, const cpp_token *)); +static struct op parse_defined PARAMS ((cpp_reader *)); +static struct op lex PARAMS ((cpp_reader *, int, cpp_token *)); +static const unsigned char *op_as_text PARAMS ((cpp_reader *, enum cpp_ttype)); + +struct op +{ + enum cpp_ttype op; + U_CHAR prio; /* Priority of op. */ + U_CHAR flags; + U_CHAR unsignedp; /* True if value should be treated as unsigned. */ + HOST_WIDEST_INT value; /* The value logically "right" of op. */ +}; + +/* There is no "error" token, but we can't get comments in #if, so we can + abuse that token type. */ +#define CPP_ERROR CPP_COMMENT + +/* With -O2, gcc appears to produce nice code, moving the error + message load and subsequent jump completely out of the main path. */ +#define CPP_ICE(msgid) \ + do { cpp_ice (pfile, msgid); goto syntax_error; } while(0) +#define SYNTAX_ERROR(msgid) \ + do { cpp_error (pfile, msgid); goto syntax_error; } while(0) +#define SYNTAX_ERROR2(msgid, arg) \ + do { cpp_error (pfile, msgid, arg); goto syntax_error; } while(0) + +/* Parse and convert an integer for #if. Accepts decimal, hex, or octal + with or without size suffixes. */ +struct suffix +{ + unsigned char s[4]; + unsigned char u; + unsigned char l; +}; + +const struct suffix vsuf_1[] = { + { "u", 1, 0 }, { "U", 1, 0 }, + { "l", 0, 1 }, { "L", 0, 1 } +}; + +const struct suffix vsuf_2[] = { + { "ul", 1, 1 }, { "UL", 1, 1 }, { "uL", 1, 1 }, { "Ul", 1, 1 }, + { "lu", 1, 1 }, { "LU", 1, 1 }, { "Lu", 1, 1 }, { "lU", 1, 1 }, + { "ll", 0, 2 }, { "LL", 0, 2 } +}; + +const struct suffix vsuf_3[] = { + { "ull", 1, 2 }, { "ULL", 1, 2 }, { "uLL", 1, 2 }, { "Ull", 1, 2 }, + { "llu", 1, 2 }, { "LLU", 1, 2 }, { "LLu", 1, 2 }, { "llU", 1, 2 } +}; +#define Nsuff(tab) (sizeof tab / sizeof (struct suffix)) + +static struct op +parse_number (pfile, tok) + cpp_reader *pfile; + const cpp_token *tok; +{ + struct op op; + const U_CHAR *start = tok->val.str.text; + const U_CHAR *end = start + tok->val.str.len; + const U_CHAR *p = start; + int c = 0, i, nsuff; + unsigned HOST_WIDEST_INT n = 0, nd, MAX_over_base; + int base = 10; + int overflow = 0; + int digit, largest_digit = 0; + const struct suffix *sufftab; + + op.unsignedp = 0; + + if (p[0] == '0') + { + if (end - start >= 3 && (p[1] == 'x' || p[1] == 'X')) + { + p += 2; + base = 16; + } + else + { + p += 1; + base = 8; + } + } + + /* Some buggy compilers (e.g. MPW C) seem to need both casts. */ + MAX_over_base = (((unsigned HOST_WIDEST_INT) -1) + / ((unsigned HOST_WIDEST_INT) base)); + + for(; p < end; p++) + { + c = *p; + + if (c >= '0' && c <= '9') + digit = c - '0'; + /* We believe that in all live character sets, a-f are + consecutive, and so are A-F. */ + else if (base == 16 && c >= 'a' && c <= 'f') + digit = c - 'a' + 10; + else if (base == 16 && c >= 'A' && c <= 'F') + digit = c - 'A' + 10; + else + break; + + if (largest_digit < digit) + largest_digit = digit; + nd = n * base + digit; + overflow |= MAX_over_base < n || nd < n; + n = nd; + } + + if (p < end) + { + /* Check for a floating point constant. Note that float constants + with an exponent or suffix but no decimal point are technically + invalid (C99 6.4.4.2) but accepted elsewhere. */ + if ((c == '.' || c == 'F' || c == 'f') + || (base == 10 && (c == 'E' || c == 'e') + && p+1 < end && (p[1] == '+' || p[1] == '-')) + || (base == 16 && (c == 'P' || c == 'p') + && p+1 < end && (p[1] == '+' || p[1] == '-'))) + SYNTAX_ERROR ("floating point numbers are not valid in #if"); + + /* Determine the suffix. l means long, and u means unsigned. + See the suffix tables, above. */ + switch (end - p) + { + case 1: sufftab = vsuf_1; nsuff = Nsuff(vsuf_1); break; + case 2: sufftab = vsuf_2; nsuff = Nsuff(vsuf_2); break; + case 3: sufftab = vsuf_3; nsuff = Nsuff(vsuf_3); break; + default: goto invalid_suffix; + } + + for (i = 0; i < nsuff; i++) + if (memcmp (p, sufftab[i].s, end - p) == 0) + break; + if (i == nsuff) + goto invalid_suffix; + op.unsignedp = sufftab[i].u; + + if (CPP_WTRADITIONAL (pfile) + && sufftab[i].u + && ! cpp_sys_macro_p (pfile)) + cpp_warning (pfile, "traditional C rejects the `U' suffix"); + if (sufftab[i].l == 2 && CPP_OPTION (pfile, pedantic) + && ! CPP_OPTION (pfile, c99)) + cpp_pedwarn (pfile, "too many 'l' suffixes in integer constant"); + } + + if (base <= largest_digit) + cpp_pedwarn (pfile, "integer constant contains digits beyond the radix"); + + if (overflow) + cpp_pedwarn (pfile, "integer constant out of range"); + + /* If too big to be signed, consider it unsigned. */ + else if ((HOST_WIDEST_INT) n < 0 && ! op.unsignedp) + { + if (base == 10) + cpp_warning (pfile, "integer constant is so large that it is unsigned"); + op.unsignedp = 1; + } + + op.value = n; + op.op = CPP_INT; + return op; + + invalid_suffix: + cpp_error (pfile, "invalid suffix '%.*s' on integer constant", + (int) (end - p), p); + syntax_error: + op.op = CPP_ERROR; + return op; +} + +static struct op +parse_defined (pfile) + cpp_reader *pfile; +{ + int paren = 0; + cpp_hashnode *node = 0; + cpp_token token; + struct op op; + + /* Don't expand macros. */ + pfile->state.prevent_expansion++; + + cpp_get_token (pfile, &token); + if (token.type == CPP_OPEN_PAREN) + { + paren = 1; + cpp_get_token (pfile, &token); + } + + if (token.type == CPP_NAME) + { + node = token.val.node; + if (paren) + { + cpp_get_token (pfile, &token); + if (token.type != CPP_CLOSE_PAREN) + { + cpp_error (pfile, "missing ')' after \"defined\""); + node = 0; + } + } + } + else + { + cpp_error (pfile, "operator \"defined\" requires an identifier"); + if (token.flags & NAMED_OP) + { + cpp_token op; + + op.flags = 0; + op.type = token.type; + cpp_error (pfile, + "(\"%s\" is an alternative token for \"%s\" in C++)", + cpp_token_as_text (pfile, &token), + cpp_token_as_text (pfile, &op)); + } + } + + if (!node) + op.op = CPP_ERROR; + else + { + op.value = node->type == NT_MACRO; + op.unsignedp = 0; + op.op = CPP_INT; + + /* No macros? At top of file? */ + if (pfile->mi_state == MI_OUTSIDE && pfile->mi_cmacro == 0 + && pfile->mi_if_not_defined == MI_IND_NOT && pfile->mi_lexed == 1) + { + cpp_start_lookahead (pfile); + cpp_get_token (pfile, &token); + if (token.type == CPP_EOF) + pfile->mi_ind_cmacro = node; + cpp_stop_lookahead (pfile, 0); + } + } + + pfile->state.prevent_expansion--; + return op; +} + +/* Read one token. */ + +static struct op +lex (pfile, skip_evaluation, token) + cpp_reader *pfile; + int skip_evaluation; + cpp_token *token; +{ + struct op op; + + cpp_get_token (pfile, token); + + switch (token->type) + { + case CPP_INT: + case CPP_NUMBER: + return parse_number (pfile, token); + + case CPP_CHAR: + case CPP_WCHAR: + { + unsigned int chars_seen; + + /* This is always a signed type. */ + op.unsignedp = 0; + op.op = CPP_INT; + op.value = cpp_interpret_charconst (pfile, token, 1, 0, &chars_seen); + return op; + } + + case CPP_STRING: + case CPP_WSTRING: + SYNTAX_ERROR ("string constants are not valid in #if"); + + case CPP_FLOAT: + SYNTAX_ERROR ("floating point numbers are not valid in #if"); + + case CPP_OTHER: + if (ISGRAPH (token->val.c)) + SYNTAX_ERROR2 ("invalid character '%c' in #if", token->val.c); + else + SYNTAX_ERROR2 ("invalid character '\\%03o' in #if", token->val.c); + + case CPP_NAME: + if (token->val.node == pfile->spec_nodes.n_defined) + { + if (pfile->context->prev && CPP_PEDANTIC (pfile)) + cpp_pedwarn (pfile, "\"defined\" operator appears during macro expansion"); + + return parse_defined (pfile); + } + else if (CPP_OPTION (pfile, cplusplus) + && (token->val.node == pfile->spec_nodes.n_true + || token->val.node == pfile->spec_nodes.n_false)) + { + op.op = CPP_INT; + op.unsignedp = 0; + op.value = (token->val.node == pfile->spec_nodes.n_true); + + /* Warn about use of true or false in #if when pedantic + and stdbool.h has not been included. */ + if (CPP_PEDANTIC (pfile) + && ! cpp_defined (pfile, DSC("__bool_true_false_are_defined"))) + cpp_pedwarn (pfile, "ISO C++ does not permit \"%s\" in #if", + NODE_NAME (token->val.node)); + return op; + } + else + { + /* Controlling #if expressions cannot contain identifiers (they + could become macros in the future). */ + pfile->mi_state = MI_FAILED; + + op.op = CPP_INT; + op.unsignedp = 0; + op.value = 0; + + if (CPP_OPTION (pfile, warn_undef) && !skip_evaluation) + cpp_warning (pfile, "\"%s\" is not defined", + NODE_NAME (token->val.node)); + return op; + } + + case CPP_HASH: + { + int temp; + + op.op = CPP_INT; + if (_cpp_test_assertion (pfile, &temp)) + op.op = CPP_ERROR; + op.unsignedp = 0; + op.value = temp; + return op; + } + + case CPP_NOT: + /* We don't worry about its position here. */ + pfile->mi_if_not_defined = MI_IND_NOT; + /* Fall through. */ + + default: + if (((int) token->type > (int) CPP_EQ + && (int) token->type < (int) CPP_PLUS_EQ) + || token->type == CPP_EOF) + { + op.op = token->type; + return op; + } + + SYNTAX_ERROR2 ("\"%s\" is not valid in #if expressions", + cpp_token_as_text (pfile, token)); + } + + syntax_error: + op.op = CPP_ERROR; + return op; +} + +static void +integer_overflow (pfile) + cpp_reader *pfile; +{ + if (CPP_PEDANTIC (pfile)) + cpp_pedwarn (pfile, "integer overflow in preprocessor expression"); +} + +static HOST_WIDEST_INT +left_shift (pfile, a, unsignedp, b) + cpp_reader *pfile; + HOST_WIDEST_INT a; + unsigned int unsignedp; + unsigned HOST_WIDEST_INT b; +{ + if (b >= HOST_BITS_PER_WIDEST_INT) + { + if (! unsignedp && a != 0) + integer_overflow (pfile); + return 0; + } + else if (unsignedp) + return (unsigned HOST_WIDEST_INT) a << b; + else + { + HOST_WIDEST_INT l = a << b; + if (l >> b != a) + integer_overflow (pfile); + return l; + } +} + +static HOST_WIDEST_INT +right_shift (pfile, a, unsignedp, b) + cpp_reader *pfile ATTRIBUTE_UNUSED; + HOST_WIDEST_INT a; + unsigned int unsignedp; + unsigned HOST_WIDEST_INT b; +{ + if (b >= HOST_BITS_PER_WIDEST_INT) + return unsignedp ? 0 : a >> (HOST_BITS_PER_WIDEST_INT - 1); + else if (unsignedp) + return (unsigned HOST_WIDEST_INT) a >> b; + else + return a >> b; +} + +/* Operator precedence and flags table. + +After an operator is returned from the lexer, if it has priority less +than or equal to the operator on the top of the stack, we reduce the +stack by one operator and repeat the test. Since equal priorities +reduce, this is naturally left-associative. + +We handle right-associative operators by clearing the lower bit of all +left-associative operators, and setting it for right-associative ones. +After the reduction phase of a new operator, just before it is pushed +onto the stack, its RIGHT_ASSOC bit is cleared. The effect is that +during the reduction phase, the current right-associative operator has +a priority one greater than any other operator of otherwise equal +precedence that has been pushed on the top of the stack. This avoids +a reduction pass, and effectively makes the logic right-associative. + +The remaining cases are '(' and ')'. We handle '(' by skipping the +reduction phase completely. ')' is given lower priority than +everything else, including '(', effectively forcing a reduction of the +parenthesised expression. If there is no matching '(', the stack will +be reduced all the way to the beginning, exiting the parser in the +same way as the ultra-low priority end-of-expression dummy operator. +The exit code checks to see if the operator that caused it is ')', and +if so outputs an appropriate error message. + +The parser assumes all shifted operators require a right operand +unless the flag NO_R_OPERAND is set, and similarly for NO_L_OPERAND. +These semantics are automatically checked, any extra semantics need to +be handled with operator-specific code. */ + +#define FLAG_BITS 8 +#define FLAG_MASK ((1 << FLAG_BITS) - 1) +#define PRIO_SHIFT (FLAG_BITS + 1) +#define EXTRACT_PRIO(cnst) (cnst >> FLAG_BITS) +#define EXTRACT_FLAGS(cnst) (cnst & FLAG_MASK) + +/* Flags. */ +#define HAVE_VALUE (1 << 0) +#define NO_L_OPERAND (1 << 1) +#define NO_R_OPERAND (1 << 2) +#define SHORT_CIRCUIT (1 << 3) + +/* Priority and flag combinations. */ +#define RIGHT_ASSOC (1 << FLAG_BITS) +#define FORCE_REDUCE_PRIO (0 << PRIO_SHIFT) +#define CLOSE_PAREN_PRIO (1 << PRIO_SHIFT) +#define OPEN_PAREN_PRIO ((2 << PRIO_SHIFT) | NO_L_OPERAND) +#define COMMA_PRIO (3 << PRIO_SHIFT) +#define COND_PRIO ((4 << PRIO_SHIFT) | RIGHT_ASSOC | SHORT_CIRCUIT) +#define COLON_PRIO ((5 << PRIO_SHIFT) | SHORT_CIRCUIT) +#define OROR_PRIO ((6 << PRIO_SHIFT) | SHORT_CIRCUIT) +#define ANDAND_PRIO ((7 << PRIO_SHIFT) | SHORT_CIRCUIT) +#define OR_PRIO (8 << PRIO_SHIFT) +#define XOR_PRIO (9 << PRIO_SHIFT) +#define AND_PRIO (10 << PRIO_SHIFT) +#define MINMAX_PRIO (11 << PRIO_SHIFT) +#define EQUAL_PRIO (12 << PRIO_SHIFT) +#define LESS_PRIO (13 << PRIO_SHIFT) +#define SHIFT_PRIO (14 << PRIO_SHIFT) +#define PLUS_PRIO (15 << PRIO_SHIFT) +#define MUL_PRIO (16 << PRIO_SHIFT) +#define UNARY_PRIO ((17 << PRIO_SHIFT) | RIGHT_ASSOC | NO_L_OPERAND) + +/* Operator to priority map. Must be in the same order as the first + N entries of enum cpp_ttype. */ +static const short +op_to_prio[] = +{ + /* EQ */ 0, /* dummy entry - can't happen */ + /* NOT */ UNARY_PRIO, + /* GREATER */ LESS_PRIO, + /* LESS */ LESS_PRIO, + /* PLUS */ UNARY_PRIO, /* note these two can be unary */ + /* MINUS */ UNARY_PRIO, /* or binary */ + /* MULT */ MUL_PRIO, + /* DIV */ MUL_PRIO, + /* MOD */ MUL_PRIO, + /* AND */ AND_PRIO, + /* OR */ OR_PRIO, + /* XOR */ XOR_PRIO, + /* RSHIFT */ SHIFT_PRIO, + /* LSHIFT */ SHIFT_PRIO, + /* MIN */ MINMAX_PRIO, /* C++ specific */ + /* MAX */ MINMAX_PRIO, /* extensions */ + + /* COMPL */ UNARY_PRIO, + /* AND_AND */ ANDAND_PRIO, + /* OR_OR */ OROR_PRIO, + /* QUERY */ COND_PRIO, + /* COLON */ COLON_PRIO, + /* COMMA */ COMMA_PRIO, + /* OPEN_PAREN */ OPEN_PAREN_PRIO, + /* CLOSE_PAREN */ CLOSE_PAREN_PRIO, + /* EQ_EQ */ EQUAL_PRIO, + /* NOT_EQ */ EQUAL_PRIO, + /* GREATER_EQ */ LESS_PRIO, + /* LESS_EQ */ LESS_PRIO +}; + +#define COMPARE(OP) \ + top->unsignedp = 0; \ + top->value = (unsigned1 | unsigned2) \ + ? (unsigned HOST_WIDEST_INT) v1 OP (unsigned HOST_WIDEST_INT) v2 \ + : (v1 OP v2) +#define EQUALITY(OP) \ + top->value = v1 OP v2; \ + top->unsignedp = 0; +#define BITWISE(OP) \ + top->value = v1 OP v2; \ + top->unsignedp = unsigned1 | unsigned2; +#define MINMAX(OP) \ + top->value = (v1 OP v2) ? v1 : v2; \ + top->unsignedp = unsigned1 | unsigned2; +#define UNARY(OP) \ + top->value = OP v2; \ + top->unsignedp = unsigned2; \ + top->flags |= HAVE_VALUE; +#define SHIFT(PSH, MSH) \ + if (skip_evaluation) \ + break; \ + top->unsignedp = unsigned1; \ + if (v2 < 0 && ! unsigned2) \ + top->value = MSH (pfile, v1, unsigned1, -v2); \ + else \ + top->value = PSH (pfile, v1, unsigned1, v2); + +/* Parse and evaluate a C expression, reading from PFILE. + Returns the truth value of the expression. */ + +int +_cpp_parse_expr (pfile) + cpp_reader *pfile; +{ + /* The implementation is an operator precedence parser, i.e. a + bottom-up parser, using a stack for not-yet-reduced tokens. + + The stack base is 'stack', and the current stack pointer is 'top'. + There is a stack element for each operator (only), + and the most recently pushed operator is 'top->op'. + An operand (value) is stored in the 'value' field of the stack + element of the operator that precedes it. + In that case the 'flags' field has the HAVE_VALUE flag set. */ + +#define INIT_STACK_SIZE 20 + struct op init_stack[INIT_STACK_SIZE]; + struct op *stack = init_stack; + struct op *limit = stack + INIT_STACK_SIZE; + cpp_token token; + register struct op *top = stack + 1; + int skip_evaluation = 0; + int result; + + /* Set up detection of #if ! defined(). */ + pfile->mi_lexed = 0; + pfile->mi_if_not_defined = MI_IND_NONE; + + /* We've finished when we try to reduce this. */ + top->op = CPP_EOF; + /* Nifty way to catch missing '('. */ + top->prio = EXTRACT_PRIO(CLOSE_PAREN_PRIO); + /* Avoid missing right operand checks. */ + top->flags = NO_R_OPERAND; + + for (;;) + { + unsigned int prio; + unsigned int flags; + struct op op; + + /* Read a token */ + op = lex (pfile, skip_evaluation, &token); + pfile->mi_lexed++; + + /* If the token is an operand, push its value and get next + token. If it is an operator, get its priority and flags, and + try to reduce the expression on the stack. */ + switch (op.op) + { + case CPP_ERROR: + goto syntax_error; + push_immediate: + case CPP_INT: + /* Push a value onto the stack. */ + if (top->flags & HAVE_VALUE) + SYNTAX_ERROR ("missing binary operator"); + top->value = op.value; + top->unsignedp = op.unsignedp; + top->flags |= HAVE_VALUE; + continue; + + case CPP_EOF: prio = FORCE_REDUCE_PRIO; break; + case CPP_PLUS: + case CPP_MINUS: prio = PLUS_PRIO; if (top->flags & HAVE_VALUE) break; + /* else unary; fall through */ + default: prio = op_to_prio[op.op]; break; + } + + /* Separate the operator's code into priority and flags. */ + flags = EXTRACT_FLAGS(prio); + prio = EXTRACT_PRIO(prio); + if (prio == EXTRACT_PRIO(OPEN_PAREN_PRIO)) + goto skip_reduction; + + /* Check for reductions. Then push the operator. */ + while (prio <= top->prio) + { + HOST_WIDEST_INT v1, v2; + unsigned int unsigned1, unsigned2; + + /* Most operators that can appear on the stack require a + right operand. Check this before trying to reduce. */ + if ((top->flags & (HAVE_VALUE | NO_R_OPERAND)) == 0) + { + if (top->op == CPP_OPEN_PAREN) + SYNTAX_ERROR ("void expression between '(' and ')'"); + else + SYNTAX_ERROR2 ("operator '%s' has no right operand", + op_as_text (pfile, top->op)); + } + + unsigned2 = top->unsignedp, v2 = top->value; + top--; + unsigned1 = top->unsignedp, v1 = top->value; + + /* Now set top->value = (top[1].op)(v1, v2); */ + switch (top[1].op) + { + default: + cpp_ice (pfile, "impossible operator '%s'", + op_as_text (pfile, top[1].op)); + goto syntax_error; + + case CPP_NOT: UNARY(!); break; + case CPP_COMPL: UNARY(~); break; + case CPP_LESS: COMPARE(<); break; + case CPP_GREATER: COMPARE(>); break; + case CPP_LESS_EQ: COMPARE(<=); break; + case CPP_GREATER_EQ: COMPARE(>=); break; + case CPP_EQ_EQ: EQUALITY(==); break; + case CPP_NOT_EQ: EQUALITY(!=); break; + case CPP_AND: BITWISE(&); break; + case CPP_XOR: BITWISE(^); break; + case CPP_OR: BITWISE(|); break; + case CPP_LSHIFT: SHIFT(left_shift, right_shift); break; + case CPP_RSHIFT: SHIFT(right_shift, left_shift); break; + case CPP_MIN: MINMAX(<); break; + case CPP_MAX: MINMAX(>); break; + + case CPP_PLUS: + if (!(top->flags & HAVE_VALUE)) + { + /* Can't use UNARY(+) because K+R C did not have unary + plus. Can't use UNARY() because some compilers object + to the empty argument. */ + top->value = v2; + top->unsignedp = unsigned2; + top->flags |= HAVE_VALUE; + + if (CPP_WTRADITIONAL (pfile)) + cpp_warning (pfile, + "traditional C rejects the unary plus operator"); + } + else + { + top->value = v1 + v2; + top->unsignedp = unsigned1 | unsigned2; + if (! top->unsignedp && ! skip_evaluation + && ! possible_sum_sign (v1, v2, top->value)) + integer_overflow (pfile); + } + break; + case CPP_MINUS: + if (!(top->flags & HAVE_VALUE)) + { + UNARY(-); + if (!skip_evaluation && (top->value & v2) < 0 && !unsigned2) + integer_overflow (pfile); + } + else + { /* Binary '-' */ + top->value = v1 - v2; + top->unsignedp = unsigned1 | unsigned2; + if (! top->unsignedp && ! skip_evaluation + && ! possible_sum_sign (top->value, v2, v1)) + integer_overflow (pfile); + } + break; + case CPP_MULT: + top->unsignedp = unsigned1 | unsigned2; + if (top->unsignedp) + top->value = (unsigned HOST_WIDEST_INT) v1 * v2; + else if (!skip_evaluation) + { + top->value = v1 * v2; + if (v1 && (top->value / v1 != v2 + || (top->value & v1 & v2) < 0)) + integer_overflow (pfile); + } + break; + case CPP_DIV: + case CPP_MOD: + if (skip_evaluation) + break; + if (v2 == 0) + SYNTAX_ERROR ("division by zero in #if"); + top->unsignedp = unsigned1 | unsigned2; + if (top[1].op == CPP_DIV) + { + if (top->unsignedp) + top->value = (unsigned HOST_WIDEST_INT) v1 / v2; + else + { + top->value = v1 / v2; + if ((top->value & v1 & v2) < 0) + integer_overflow (pfile); + } + } + else + { + if (top->unsignedp) + top->value = (unsigned HOST_WIDEST_INT) v1 % v2; + else + top->value = v1 % v2; + } + break; + + case CPP_OR_OR: + top->value = v1 || v2; + top->unsignedp = 0; + if (v1) skip_evaluation--; + break; + case CPP_AND_AND: + top->value = v1 && v2; + top->unsignedp = 0; + if (!v1) skip_evaluation--; + break; + case CPP_COMMA: + if (CPP_PEDANTIC (pfile)) + cpp_pedwarn (pfile, "comma operator in operand of #if"); + top->value = v2; + top->unsignedp = unsigned2; + break; + case CPP_QUERY: + SYNTAX_ERROR ("syntax error '?' without following ':'"); + case CPP_COLON: + if (top[0].op != CPP_QUERY) + SYNTAX_ERROR ("syntax error ':' without preceding '?'"); + top--; + if (top->value) skip_evaluation--; + top->value = top->value ? v1 : v2; + top->unsignedp = unsigned1 | unsigned2; + break; + case CPP_OPEN_PAREN: + if (op.op != CPP_CLOSE_PAREN) + SYNTAX_ERROR ("missing ')' in expression"); + op.value = v2; + op.unsignedp = unsigned2; + goto push_immediate; + case CPP_EOF: + /* Reducing this dummy operator indicates we've finished. */ + if (op.op == CPP_CLOSE_PAREN) + SYNTAX_ERROR ("missing '(' in expression"); + goto done; + } + } + + /* Handle short-circuit evaluations. */ + if (flags & SHORT_CIRCUIT) + switch (op.op) + { + case CPP_OR_OR: if (top->value) skip_evaluation++; break; + case CPP_AND_AND: + case CPP_QUERY: if (!top->value) skip_evaluation++; break; + case CPP_COLON: + if (top[-1].value) /* Was '?' condition true? */ + skip_evaluation++; + else + skip_evaluation--; + default: + break; + } + + skip_reduction: + /* Check we have a left operand iff we need one. */ + if (flags & NO_L_OPERAND) + { + if (top->flags & HAVE_VALUE) + SYNTAX_ERROR2 ("missing binary operator before '%s'", + op_as_text (pfile, top->op)); + } + else + { + if (!(top->flags & HAVE_VALUE)) + SYNTAX_ERROR2 ("operator '%s' has no left operand", + op_as_text (pfile, top->op)); + } + + /* Check for and handle stack overflow. */ + top++; + if (top == limit) + { + struct op *new_stack; + int old_size = (char *) limit - (char *) stack; + int new_size = 2 * old_size; + if (stack != init_stack) + new_stack = (struct op *) xrealloc (stack, new_size); + else + { + new_stack = (struct op *) xmalloc (new_size); + memcpy (new_stack, stack, old_size); + } + stack = new_stack; + top = (struct op *) ((char *) new_stack + old_size); + limit = (struct op *) ((char *) new_stack + new_size); + } + + top->flags = flags; + top->prio = prio & ~EXTRACT_PRIO(RIGHT_ASSOC); + top->op = op.op; + } + + done: + result = (top[1].value != 0); + if (top != stack) + CPP_ICE ("unbalanced stack in #if"); + else if (!(top[1].flags & HAVE_VALUE)) + { + SYNTAX_ERROR ("#if with no expression"); + syntax_error: + result = 0; /* Return 0 on syntax error. */ + } + + /* Free dynamic stack if we allocated one. */ + if (stack != init_stack) + free (stack); + return result; +} + +static const unsigned char * +op_as_text (pfile, op) + cpp_reader *pfile; + enum cpp_ttype op; +{ + cpp_token token; + + token.type = op; + token.flags = 0; + return cpp_token_as_text (pfile, &token); +} diff --git a/support/cpp2/cppfiles.c b/support/cpp2/cppfiles.c new file mode 100644 index 00000000..137882b3 --- /dev/null +++ b/support/cpp2/cppfiles.c @@ -0,0 +1,1168 @@ +/* Part of CPP library. (include file handling) + Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998, + 1999, 2000, 2001 Free Software Foundation, Inc. + Written by Per Bothner, 1994. + Based on CCCP program by Paul Rubin, June 1986 + Adapted to ANSI C, Richard Stallman, Jan 1987 + Split out of cpplib.c, Zack Weinberg, Oct 1998 + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "config.h" +#include "system.h" +#include "cpplib.h" +#include "cpphash.h" +#include "intl.h" +#include "mkdeps.h" +#include "splay-tree.h" + +#ifdef HAVE_MMAP_FILE +# include +# ifndef MMAP_THRESHOLD +# define MMAP_THRESHOLD 3 /* Minimum page count to mmap the file. */ +# endif + +#else /* No MMAP_FILE */ +# undef MMAP_THRESHOLD +# define MMAP_THRESHOLD 0 +#endif + +#ifndef O_BINARY +# define O_BINARY 0 +#endif + +/* If errno is inspected immediately after a system call fails, it will be + nonzero, and no error number will ever be zero. */ +#ifndef ENOENT +# define ENOENT 0 +#endif +#ifndef ENOTDIR +# define ENOTDIR 0 +#endif + +/* Suppress warning about function macros used w/o arguments in traditional + C. It is unlikely that glibc's strcmp macro helps this file at all. */ +#undef strcmp + +/* This structure is used for the table of all includes. */ +struct include_file +{ + const char *name; /* actual path name of file */ + const cpp_hashnode *cmacro; /* macro, if any, preventing reinclusion. */ + const struct search_path *foundhere; + /* location in search path where file was + found, for #include_next and sysp. */ + const unsigned char *buffer; /* pointer to cached file contents */ + struct stat st; /* copy of stat(2) data for file */ + int fd; /* fd open on file (short term storage only) */ + int err_no; /* errno obtained if opening a file failed */ + unsigned short include_count; /* number of times file has been read */ + unsigned short refcnt; /* number of stacked buffers using this file */ + unsigned char mapped; /* file buffer is mmapped */ +}; + +/* The cmacro works like this: If it's NULL, the file is to be + included again. If it's NEVER_REREAD, the file is never to be + included again. Otherwise it is a macro hashnode, and the file is + to be included again if the macro is defined. */ +#define NEVER_REREAD ((const cpp_hashnode *)-1) +#define DO_NOT_REREAD(inc) \ +((inc)->cmacro && ((inc)->cmacro == NEVER_REREAD \ + || (inc)->cmacro->type == NT_MACRO)) +#define NO_INCLUDE_PATH ((struct include_file *) -1) + +static struct file_name_map *read_name_map + PARAMS ((cpp_reader *, const char *)); +static char *read_filename_string PARAMS ((int, FILE *)); +static char *remap_filename PARAMS ((cpp_reader *, char *, + struct search_path *)); +static struct search_path *search_from PARAMS ((cpp_reader *, + enum include_type)); +static struct include_file * + find_include_file PARAMS ((cpp_reader *, const cpp_token *, + enum include_type)); +static struct include_file *open_file PARAMS ((cpp_reader *, const char *)); +static int read_include_file PARAMS ((cpp_reader *, struct include_file *)); +static void stack_include_file PARAMS ((cpp_reader *, struct include_file *)); +static void purge_cache PARAMS ((struct include_file *)); +static void destroy_node PARAMS ((splay_tree_value)); +static int report_missing_guard PARAMS ((splay_tree_node, void *)); +static splay_tree_node find_or_create_entry PARAMS ((cpp_reader *, + const char *)); +static void handle_missing_header PARAMS ((cpp_reader *, const char *, int)); +static int remove_component_p PARAMS ((const char *)); + +/* Set up the splay tree we use to store information about all the + file names seen in this compilation. We also have entries for each + file we tried to open but failed; this saves system calls since we + don't try to open it again in future. + + The key of each node is the file name, after processing by + _cpp_simplify_pathname. The path name may or may not be absolute. + The path string has been malloced, as is automatically freed by + registering free () as the splay tree key deletion function. + + A node's value is a pointer to a struct include_file, and is never + NULL. */ +void +_cpp_init_includes (pfile) + cpp_reader *pfile; +{ + pfile->all_include_files + = splay_tree_new ((splay_tree_compare_fn) strcmp, + (splay_tree_delete_key_fn) free, + destroy_node); +} + +/* Tear down the splay tree. */ +void +_cpp_cleanup_includes (pfile) + cpp_reader *pfile; +{ + splay_tree_delete (pfile->all_include_files); +} + +/* Free a node. The path string is automatically freed. */ +static void +destroy_node (v) + splay_tree_value v; +{ + struct include_file *f = (struct include_file *)v; + + if (f) + { + purge_cache (f); + free (f); + } +} + +/* Mark a file to not be reread (e.g. #import, read failure). */ +void +_cpp_never_reread (file) + struct include_file *file; +{ + file->cmacro = NEVER_REREAD; +} + +/* Lookup a filename, which is simplified after making a copy, and + create an entry if none exists. errno is nonzero iff a (reported) + stat() error occurred during simplification. */ +static splay_tree_node +find_or_create_entry (pfile, fname) + cpp_reader *pfile; + const char *fname; +{ + splay_tree_node node; + struct include_file *file; + char *name = xstrdup (fname); + + _cpp_simplify_pathname (name); + node = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) name); + if (node) + free (name); + else + { + file = xcnew (struct include_file); + file->name = name; + file->err_no = errno; + node = splay_tree_insert (pfile->all_include_files, + (splay_tree_key) file->name, + (splay_tree_value) file); + } + + return node; +} + +/* Enter a file name in the splay tree, for the sake of cpp_included. */ +void +_cpp_fake_include (pfile, fname) + cpp_reader *pfile; + const char *fname; +{ + find_or_create_entry (pfile, fname); +} + +/* Given a file name, look it up in the cache; if there is no entry, + create one with a non-NULL value (regardless of success in opening + the file). If the file doesn't exist or is inaccessible, this + entry is flagged so we don't attempt to open it again in the + future. If the file isn't open, open it. The empty string is + interpreted as stdin. + + Returns an include_file structure with an open file descriptor on + success, or NULL on failure. */ + +static struct include_file * +open_file (pfile, filename) + cpp_reader *pfile; + const char *filename; +{ + splay_tree_node nd = find_or_create_entry (pfile, filename); + struct include_file *file = (struct include_file *) nd->value; + + if (file->err_no) + { + /* Ugh. handle_missing_header () needs errno to be set. */ + errno = file->err_no; + return 0; + } + + /* Don't reopen an idempotent file. */ + if (DO_NOT_REREAD (file)) + return file; + + /* Don't reopen one which is already loaded. */ + if (file->buffer != NULL) + return file; + + /* We used to open files in nonblocking mode, but that caused more + problems than it solved. Do take care not to acquire a + controlling terminal by mistake (this can't happen on sane + systems, but paranoia is a virtue). + + Use the three-argument form of open even though we aren't + specifying O_CREAT, to defend against broken system headers. + + O_BINARY tells some runtime libraries (notably DJGPP) not to do + newline translation; we can handle DOS line breaks just fine + ourselves. + + Special case: the empty string is translated to stdin. */ + + if (filename[0] == '\0') + file->fd = 0; + else + file->fd = open (file->name, O_RDONLY | O_NOCTTY | O_BINARY, 0666); + + if (file->fd != -1 && fstat (file->fd, &file->st) == 0) + { + /* If it's a directory, we return null and continue the search + as the file we're looking for may appear elsewhere in the + search path. */ + if (S_ISDIR (file->st.st_mode)) + errno = ENOENT; + else + { + /* Mark a regular, zero-length file never-reread now. */ + if (S_ISREG (file->st.st_mode) && file->st.st_size == 0) + { + _cpp_never_reread (file); + close (file->fd); + file->fd = -1; + } + + return file; + } + } + + /* Don't issue an error message if the file doesn't exist. */ + file->err_no = errno; + if (errno != ENOENT && errno != ENOTDIR) + cpp_error_from_errno (pfile, file->name); + + return 0; +} + +/* Place the file referenced by INC into a new buffer on PFILE's + stack. If there are errors, or the file should not be re-included, + a null (zero-length) buffer is pushed. */ + +static void +stack_include_file (pfile, inc) + cpp_reader *pfile; + struct include_file *inc; +{ + size_t len = 0; + cpp_buffer *fp; + int sysp, deps_sysp; + + /* We'll try removing deps_sysp after the release of 3.0. */ + deps_sysp = pfile->system_include_depth != 0; + sysp = MAX ((pfile->buffer ? pfile->buffer->sysp : 0), + (inc->foundhere ? inc->foundhere->sysp : 0)); + + /* For -M, add the file to the dependencies on its first inclusion. */ + if (CPP_OPTION (pfile, print_deps) > deps_sysp && !inc->include_count) + deps_add_dep (pfile->deps, inc->name); + + /* Not in cache? */ + if (! DO_NOT_REREAD (inc) && ! inc->buffer) + { + /* If an error occurs, do not try to read this file again. */ + if (read_include_file (pfile, inc)) + _cpp_never_reread (inc); + close (inc->fd); + inc->fd = -1; + } + + if (! DO_NOT_REREAD (inc)) + { + len = inc->st.st_size; + if (pfile->buffer) + { + /* We don't want MI guard advice for the main file. */ + inc->include_count++; + + /* Handle -H option. */ + if (CPP_OPTION (pfile, print_include_names)) + { + for (fp = pfile->buffer; fp; fp = fp->prev) + putc ('.', stderr); + fprintf (stderr, " %s\n", inc->name); + } + } + } + + /* Push a buffer. */ + fp = cpp_push_buffer (pfile, inc->buffer, len, BUF_FILE, inc->name); + fp->inc = inc; + fp->inc->refcnt++; + fp->sysp = sysp; + + /* Initialise controlling macro state. */ + pfile->mi_state = MI_OUTSIDE; + pfile->mi_cmacro = 0; + pfile->include_depth++; + + /* Generate the call back. */ + fp->lineno = 0; + _cpp_do_file_change (pfile, FC_ENTER, 0, 0); + fp->lineno = 1; +} + +/* Read the file referenced by INC into the file cache. + + If fd points to a plain file, we might be able to mmap it; we can + definitely allocate the buffer all at once. If fd is a pipe or + terminal, we can't do either. If fd is something weird, like a + block device, we don't want to read it at all. + + Unfortunately, different systems use different st.st_mode values + for pipes: some have S_ISFIFO, some S_ISSOCK, some are buggy and + zero the entire struct stat except a couple fields. Hence we don't + even try to figure out what something is, except for plain files + and block devices. + + FIXME: Flush file cache and try again if we run out of memory. */ + +static int +read_include_file (pfile, inc) + cpp_reader *pfile; + struct include_file *inc; +{ + ssize_t size, offset, count; + U_CHAR *buf; +#if MMAP_THRESHOLD + static int pagesize = -1; +#endif + + if (S_ISREG (inc->st.st_mode)) + { + /* off_t might have a wider range than ssize_t - in other words, + the max size of a file might be bigger than the address + space. We can't handle a file that large. (Anyone with + a single source file bigger than 2GB needs to rethink + their coding style.) Some systems (e.g. AIX 4.1) define + SSIZE_MAX to be much smaller than the actual range of the + type. Use INTTYPE_MAXIMUM unconditionally to ensure this + does not bite us. */ + if (inc->st.st_size > INTTYPE_MAXIMUM (ssize_t)) + { + cpp_error (pfile, "%s is too large", inc->name); + goto fail; + } + size = inc->st.st_size; + + inc->mapped = 0; +#if MMAP_THRESHOLD + if (pagesize == -1) + pagesize = getpagesize (); + + if (size / pagesize >= MMAP_THRESHOLD) + { + buf = (U_CHAR *) mmap (0, size, PROT_READ, MAP_PRIVATE, inc->fd, 0); + if (buf == (U_CHAR *)-1) + goto perror_fail; + inc->mapped = 1; + } + else +#endif + { + buf = (U_CHAR *) xmalloc (size); + offset = 0; + while (offset < size) + { + count = read (inc->fd, buf + offset, size - offset); + if (count < 0) + goto perror_fail; + if (count == 0) + { + cpp_warning (pfile, "%s is shorter than expected", inc->name); + break; + } + offset += count; + } + } + } + else if (S_ISBLK (inc->st.st_mode)) + { + cpp_error (pfile, "%s is a block device", inc->name); + goto fail; + } + else + { + /* 8 kilobytes is a sensible starting size. It ought to be + bigger than the kernel pipe buffer, and it's definitely + bigger than the majority of C source files. */ + size = 8 * 1024; + + buf = (U_CHAR *) xmalloc (size); + offset = 0; + while ((count = read (inc->fd, buf + offset, size - offset)) > 0) + { + offset += count; + if (offset == size) + buf = xrealloc (buf, (size *= 2)); + } + if (count < 0) + goto perror_fail; + + if (offset < size) + buf = xrealloc (buf, offset); + inc->st.st_size = offset; + } + + inc->buffer = buf; + return 0; + + perror_fail: + cpp_error_from_errno (pfile, inc->name); + fail: + return 1; +} + +static void +purge_cache (inc) + struct include_file *inc; +{ + if (inc->buffer) + { +#if MMAP_THRESHOLD + if (inc->mapped) + munmap ((PTR) inc->buffer, inc->st.st_size); + else +#endif + free ((PTR) inc->buffer); + inc->buffer = NULL; + } +} + +/* Return 1 if the file named by FNAME has been included before in + any context, 0 otherwise. */ +int +cpp_included (pfile, fname) + cpp_reader *pfile; + const char *fname; +{ + struct search_path *path; + char *name, *n; + splay_tree_node nd; + + if (IS_ABSOLUTE_PATHNAME (fname)) + { + /* Just look it up. */ + nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) fname); + return (nd && nd->value); + } + + /* Search directory path for the file. */ + name = (char *) alloca (strlen (fname) + pfile->max_include_len + 2); + for (path = CPP_OPTION (pfile, quote_include); path; path = path->next) + { + memcpy (name, path->name, path->len); + name[path->len] = '/'; + strcpy (&name[path->len + 1], fname); + if (CPP_OPTION (pfile, remap)) + n = remap_filename (pfile, name, path); + else + n = name; + + nd = splay_tree_lookup (pfile->all_include_files, (splay_tree_key) n); + if (nd && nd->value) + return 1; + } + return 0; +} + +/* Search for HEADER. Return 0 if there is no such file (or it's + un-openable), in which case an error code will be in errno. If + there is no include path to use it returns NO_INCLUDE_PATH, + otherwise an include_file structure. If this request originates + from a #include_next directive, set INCLUDE_NEXT to true. */ + +static struct include_file * +find_include_file (pfile, header, type) + cpp_reader *pfile; + const cpp_token *header; + enum include_type type; +{ + const char *fname = (const char *) header->val.str.text; + struct search_path *path; + struct include_file *file; + char *name, *n; + + if (IS_ABSOLUTE_PATHNAME (fname)) + return open_file (pfile, fname); + + /* For #include_next, skip in the search path past the dir in which + the current file was found, but if it was found via an absolute + path use the normal search logic. */ + if (type == IT_INCLUDE_NEXT && pfile->buffer->inc->foundhere) + path = pfile->buffer->inc->foundhere->next; + else if (header->type == CPP_HEADER_NAME) + path = CPP_OPTION (pfile, bracket_include); + else + path = search_from (pfile, type); + + if (path == NULL) + { + cpp_error (pfile, "No include path in which to find %s", fname); + return NO_INCLUDE_PATH; + } + + /* Search directory path for the file. */ + name = (char *) alloca (strlen (fname) + pfile->max_include_len + 2); + for (; path; path = path->next) + { + memcpy (name, path->name, path->len); + name[path->len] = '/'; + strcpy (&name[path->len + 1], fname); + if (CPP_OPTION (pfile, remap)) + n = remap_filename (pfile, name, path); + else + n = name; + + file = open_file (pfile, n); + if (file) + { + file->foundhere = path; + return file; + } + } + + return 0; +} + +/* Not everyone who wants to set system-header-ness on a buffer can + see the details of a buffer. This is an exported interface because + fix-header needs it. */ +void +cpp_make_system_header (pfile, syshdr, externc) + cpp_reader *pfile; + int syshdr, externc; +{ + int flags = 0; + + /* 1 = system header, 2 = system header to be treated as C. */ + if (syshdr) + flags = 1 + (externc != 0); + pfile->buffer->sysp = flags; + _cpp_do_file_change (pfile, FC_RENAME, pfile->buffer->nominal_fname, + pfile->buffer->lineno); +} + +/* Report on all files that might benefit from a multiple include guard. + Triggered by -H. */ +void +_cpp_report_missing_guards (pfile) + cpp_reader *pfile; +{ + int banner = 0; + splay_tree_foreach (pfile->all_include_files, report_missing_guard, + (PTR) &banner); +} + +static int +report_missing_guard (n, b) + splay_tree_node n; + void *b; +{ + struct include_file *f = (struct include_file *) n->value; + int *bannerp = (int *)b; + + if (f && f->cmacro == 0 && f->include_count == 1) + { + if (*bannerp == 0) + { + fputs (_("Multiple include guards may be useful for:\n"), stderr); + *bannerp = 1; + } + fputs (f->name, stderr); + putc ('\n', stderr); + } + return 0; +} + +/* Create a dependency, or issue an error message as appropriate. */ +static void +handle_missing_header (pfile, fname, angle_brackets) + cpp_reader *pfile; + const char *fname; + int angle_brackets; +{ + /* We will try making the RHS pfile->buffer->sysp after 3.0. */ + int print_dep = CPP_PRINT_DEPS(pfile) > (angle_brackets + || pfile->system_include_depth); + + if (CPP_OPTION (pfile, print_deps_missing_files) && print_dep) + { + if (!angle_brackets || IS_ABSOLUTE_PATHNAME (fname)) + deps_add_dep (pfile->deps, fname); + else + { + /* If requested as a system header, assume it belongs in + the first system header directory. */ + struct search_path *ptr = CPP_OPTION (pfile, bracket_include); + char *p; + int len = 0, fname_len = strlen (fname); + + if (ptr) + len = ptr->len; + + p = (char *) alloca (len + fname_len + 2); + if (len) + { + memcpy (p, ptr->name, len); + p[len++] = '/'; + } + memcpy (p + len, fname, fname_len + 1); + deps_add_dep (pfile->deps, p); + } + } + /* If -M was specified, then don't count this as an error, because + we can still produce correct output. Otherwise, we can't produce + correct output, because there may be dependencies we need inside + the missing file, and we don't know what directory this missing + file exists in. FIXME: Use a future cpp_diagnotic_with_errno () + for both of these cases. */ + else if (CPP_PRINT_DEPS (pfile) && ! print_dep) + cpp_warning (pfile, "%s: %s", fname, xstrerror (errno)); + else + cpp_error_from_errno (pfile, fname); +} + +/* Returns non-zero if a buffer was stacked. */ +int +_cpp_execute_include (pfile, header, type) + cpp_reader *pfile; + const cpp_token *header; + enum include_type type; +{ + struct include_file *inc = find_include_file (pfile, header, type); + + if (inc == 0) + handle_missing_header (pfile, (const char *) header->val.str.text, + header->type == CPP_HEADER_NAME); + else if (inc != NO_INCLUDE_PATH) + { + if (header->type == CPP_HEADER_NAME) + pfile->system_include_depth++; + + stack_include_file (pfile, inc); + + if (type == IT_IMPORT) + _cpp_never_reread (inc); + + return 1; + } + + return 0; +} + +/* Locate HEADER, and determine whether it is newer than the current + file. If it cannot be located or dated, return -1, if it is newer + newer, return 1, otherwise 0. */ +int +_cpp_compare_file_date (pfile, header) + cpp_reader *pfile; + const cpp_token *header; +{ + struct include_file *inc = find_include_file (pfile, header, 0); + + if (inc == NULL || inc == NO_INCLUDE_PATH) + return -1; + + if (inc->fd > 0) + { + close (inc->fd); + inc->fd = -1; + } + + return inc->st.st_mtime > pfile->buffer->inc->st.st_mtime; +} + + +/* Push an input buffer and load it up with the contents of FNAME. + If FNAME is "", read standard input. */ +int +_cpp_read_file (pfile, fname) + cpp_reader *pfile; + const char *fname; +{ + struct include_file *f = open_file (pfile, fname); + + if (f == NULL) + { + cpp_error_from_errno (pfile, fname); + return 0; + } + + stack_include_file (pfile, f); + return 1; +} + +/* Do appropriate cleanup when a file buffer is popped off the input + stack. */ +void +_cpp_pop_file_buffer (pfile, buf) + cpp_reader *pfile; + cpp_buffer *buf; +{ + struct include_file *inc = buf->inc; + + if (pfile->system_include_depth) + pfile->system_include_depth--; + if (pfile->include_depth) + pfile->include_depth--; + + /* Record the inclusion-preventing macro, which could be NULL + meaning no controlling macro, if we haven't got it already. */ + if (pfile->mi_state == MI_OUTSIDE && inc->cmacro == NULL) + inc->cmacro = pfile->mi_cmacro; + + /* Invalidate control macros in the #including file. */ + pfile->mi_state = MI_FAILED; + + inc->refcnt--; + if (inc->refcnt == 0 && DO_NOT_REREAD (inc)) + purge_cache (inc); +} + +/* Returns the first place in the include chain to start searching for + "" includes. This involves stripping away the basename of the + current file, unless -I- was specified. + + If we're handling -include or -imacros, use the "" chain, but with + the preprocessor's cwd prepended. */ +static struct search_path * +search_from (pfile, type) + cpp_reader *pfile; + enum include_type type; +{ + cpp_buffer *buffer = pfile->buffer; + unsigned int dlen; + + /* Command line uses the cwd, and does not cache the result. */ + if (type == IT_CMDLINE) + goto use_cwd; + + /* Ignore the current file's directory if -I- was given. */ + if (CPP_OPTION (pfile, ignore_srcdir)) + return CPP_OPTION (pfile, quote_include); + + if (! buffer->search_cached) + { + buffer->search_cached = 1; + + dlen = lbasename (buffer->inc->name) - buffer->inc->name; + + if (dlen) + { + /* We don't guarantee NAME is null-terminated. This saves + allocating and freeing memory, and duplicating it when faking + buffers in cpp_push_buffer. Drop a trailing '/'. */ + buffer->dir.name = buffer->inc->name; + if (dlen > 1) + dlen--; + } + else + { + use_cwd: + buffer->dir.name = "."; + dlen = 1; + } + + if (dlen > pfile->max_include_len) + pfile->max_include_len = dlen; + + buffer->dir.len = dlen; + buffer->dir.next = CPP_OPTION (pfile, quote_include); + buffer->dir.sysp = buffer->sysp; + } + + return &buffer->dir; +} + +/* The file_name_map structure holds a mapping of file names for a + particular directory. This mapping is read from the file named + FILE_NAME_MAP_FILE in that directory. Such a file can be used to + map filenames on a file system with severe filename restrictions, + such as DOS. The format of the file name map file is just a series + of lines with two tokens on each line. The first token is the name + to map, and the second token is the actual name to use. */ + +struct file_name_map +{ + struct file_name_map *map_next; + char *map_from; + char *map_to; +}; + +#define FILE_NAME_MAP_FILE "header.gcc" + +/* Read a space delimited string of unlimited length from a stdio + file. */ + +static char * +read_filename_string (ch, f) + int ch; + FILE *f; +{ + char *alloc, *set; + int len; + + len = 20; + set = alloc = xmalloc (len + 1); + if (! is_space(ch)) + { + *set++ = ch; + while ((ch = getc (f)) != EOF && ! is_space(ch)) + { + if (set - alloc == len) + { + len *= 2; + alloc = xrealloc (alloc, len + 1); + set = alloc + len / 2; + } + *set++ = ch; + } + } + *set = '\0'; + ungetc (ch, f); + return alloc; +} + +/* This structure holds a linked list of file name maps, one per directory. */ + +struct file_name_map_list +{ + struct file_name_map_list *map_list_next; + char *map_list_name; + struct file_name_map *map_list_map; +}; + +/* Read the file name map file for DIRNAME. */ + +static struct file_name_map * +read_name_map (pfile, dirname) + cpp_reader *pfile; + const char *dirname; +{ + register struct file_name_map_list *map_list_ptr; + char *name; + FILE *f; + + /* Check the cache of directories, and mappings in their remap file. */ + for (map_list_ptr = CPP_OPTION (pfile, map_list); map_list_ptr; + map_list_ptr = map_list_ptr->map_list_next) + if (! strcmp (map_list_ptr->map_list_name, dirname)) + return map_list_ptr->map_list_map; + + map_list_ptr = ((struct file_name_map_list *) + xmalloc (sizeof (struct file_name_map_list))); + map_list_ptr->map_list_name = xstrdup (dirname); + + /* The end of the list ends in NULL. */ + map_list_ptr->map_list_map = NULL; + + name = (char *) alloca (strlen (dirname) + strlen (FILE_NAME_MAP_FILE) + 2); + strcpy (name, dirname); + if (*dirname) + strcat (name, "/"); + strcat (name, FILE_NAME_MAP_FILE); + f = fopen (name, "r"); + + /* Silently return NULL if we cannot open. */ + if (f) + { + int ch; + int dirlen = strlen (dirname); + + while ((ch = getc (f)) != EOF) + { + char *from, *to; + struct file_name_map *ptr; + + if (is_space(ch)) + continue; + from = read_filename_string (ch, f); + while ((ch = getc (f)) != EOF && is_hspace(ch)) + ; + to = read_filename_string (ch, f); + + ptr = ((struct file_name_map *) + xmalloc (sizeof (struct file_name_map))); + ptr->map_from = from; + + /* Make the real filename absolute. */ + if (IS_ABSOLUTE_PATHNAME (to)) + ptr->map_to = to; + else + { + ptr->map_to = xmalloc (dirlen + strlen (to) + 2); + strcpy (ptr->map_to, dirname); + ptr->map_to[dirlen] = '/'; + strcpy (ptr->map_to + dirlen + 1, to); + free (to); + } + + ptr->map_next = map_list_ptr->map_list_map; + map_list_ptr->map_list_map = ptr; + + while ((ch = getc (f)) != '\n') + if (ch == EOF) + break; + } + fclose (f); + } + + /* Add this information to the cache. */ + map_list_ptr->map_list_next = CPP_OPTION (pfile, map_list); + CPP_OPTION (pfile, map_list) = map_list_ptr; + + return map_list_ptr->map_list_map; +} + +/* Remap an unsimplified path NAME based on the file_name_map (if any) + for LOC. */ +static char * +remap_filename (pfile, name, loc) + cpp_reader *pfile; + char *name; + struct search_path *loc; +{ + struct file_name_map *map; + const char *from, *p; + char *dir; + + if (! loc->name_map) + { + /* Get a null-terminated path. */ + char *dname = alloca (loc->len + 1); + memcpy (dname, loc->name, loc->len); + dname[loc->len] = '\0'; + + loc->name_map = read_name_map (pfile, dname); + if (! loc->name_map) + return name; + } + + /* This works since NAME has not been simplified yet. */ + from = name + loc->len + 1; + + for (map = loc->name_map; map; map = map->map_next) + if (!strcmp (map->map_from, from)) + return map->map_to; + + /* Try to find a mapping file for the particular directory we are + looking in. Thus #include will look up sys/types.h + in /usr/include/header.gcc and look up types.h in + /usr/include/sys/header.gcc. */ + p = strrchr (name, '/'); + if (!p) + return name; + + /* We know p != name as absolute paths don't call remap_filename. */ + if (p == name) + cpp_ice (pfile, "absolute file name in remap_filename"); + + dir = (char *) alloca (p - name + 1); + memcpy (dir, name, p - name); + dir[p - name] = '\0'; + from = p + 1; + + for (map = read_name_map (pfile, dir); map; map = map->map_next) + if (! strcmp (map->map_from, from)) + return map->map_to; + + return name; +} + +/* Returns true if it is safe to remove the final component of path, + when it is followed by a ".." component. We use lstat to avoid + symlinks if we have it. If not, we can still catch errors with + stat (). */ +static int +remove_component_p (path) + const char *path; +{ + struct stat s; + int result; + +#ifdef HAVE_LSTAT + result = lstat (path, &s); +#else + result = stat (path, &s); +#endif + + /* There's no guarantee that errno will be unchanged, even on + success. Cygwin's lstat(), for example, will often set errno to + ENOSYS. In case of success, reset errno to zero. */ + if (result == 0) + errno = 0; + + return result == 0 && S_ISDIR (s.st_mode); +} + +/* Simplify a path name in place, deleting redundant components. This + reduces OS overhead and guarantees that equivalent paths compare + the same (modulo symlinks). + + Transforms made: + foo/bar/../quux foo/quux + foo/./bar foo/bar + foo//bar foo/bar + /../quux /quux + //quux //quux (POSIX allows leading // as a namespace escape) + + Guarantees no trailing slashes. All transforms reduce the length + of the string. Returns PATH. errno is 0 if no error occurred; + nonzero if an error occurred when using stat () or lstat (). */ + +char * +_cpp_simplify_pathname (path) + char *path; +{ +#ifndef VMS + char *from, *to; + char *base, *orig_base; + int absolute = 0; + + errno = 0; + /* Don't overflow the empty path by putting a '.' in it below. */ + if (*path == '\0') + return path; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Convert all backslashes to slashes. */ + for (from = path; *from; from++) + if (*from == '\\') *from = '/'; + + /* Skip over leading drive letter if present. */ + if (ISALPHA (path[0]) && path[1] == ':') + from = to = &path[2]; + else + from = to = path; +#else + from = to = path; +#endif + + /* Remove redundant leading /s. */ + if (*from == '/') + { + absolute = 1; + to++; + from++; + if (*from == '/') + { + if (*++from == '/') + /* 3 or more initial /s are equivalent to 1 /. */ + while (*++from == '/'); + else + /* On some hosts // differs from /; Posix allows this. */ + to++; + } + } + + base = orig_base = to; + for (;;) + { + int move_base = 0; + + while (*from == '/') + from++; + + if (*from == '\0') + break; + + if (*from == '.') + { + if (from[1] == '\0') + break; + if (from[1] == '/') + { + from += 2; + continue; + } + else if (from[1] == '.' && (from[2] == '/' || from[2] == '\0')) + { + /* Don't simplify if there was no previous component. */ + if (absolute && orig_base == to) + { + from += 2; + continue; + } + /* Don't simplify if the previous component was "../", + or if an error has already occurred with (l)stat. */ + if (base != to && errno == 0) + { + /* We don't back up if it's a symlink. */ + *to = '\0'; + if (remove_component_p (path)) + { + while (to > base && *to != '/') + to--; + from += 2; + continue; + } + } + move_base = 1; + } + } + + /* Add the component separator. */ + if (to > orig_base) + *to++ = '/'; + + /* Copy this component until the trailing null or '/'. */ + while (*from != '\0' && *from != '/') + *to++ = *from++; + + if (move_base) + base = to; + } + + /* Change the empty string to "." so that it is not treated as stdin. + Null terminate. */ + if (to == path) + *to++ = '.'; + *to = '\0'; + + return path; +#else /* VMS */ + errno = 0; + return path; +#endif /* !VMS */ +} diff --git a/support/cpp2/cpphash.c b/support/cpp2/cpphash.c new file mode 100644 index 00000000..9e15ab48 --- /dev/null +++ b/support/cpp2/cpphash.c @@ -0,0 +1,122 @@ +/* Hash tables for the CPP library. + Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998, + 1999, 2000 Free Software Foundation, Inc. + Written by Per Bothner, 1994. + Based on CCCP program by Paul Rubin, June 1986 + Adapted to ANSI C, Richard Stallman, Jan 1987 + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! */ + +#include "config.h" +#include "system.h" +#include "cpplib.h" +#include "cpphash.h" + +static cpp_hashnode *alloc_node PARAMS ((hash_table *)); + +/* Return an identifier node for hashtable.c. Used by cpplib except + when integrated with the C front ends. */ + +static cpp_hashnode * +alloc_node (table) + hash_table *table; +{ + cpp_hashnode *node; + + node = (cpp_hashnode *) obstack_alloc (&table->pfile->hash_ob, + sizeof (cpp_hashnode)); + memset ((PTR) node, 0, sizeof (cpp_hashnode)); + return node; +} + +/* Set up the identifier hash table. Use TABLE if non-null, otherwise + create our own. */ + +void +_cpp_init_hashtable (pfile, table) + cpp_reader *pfile; + hash_table *table; +{ + if (table == NULL) + { + pfile->our_hashtable = 1; + table = ht_create (13); /* 8K (=2^13) entries. */ + table->alloc_node = (hashnode (*) PARAMS ((hash_table *))) alloc_node; + gcc_obstack_init (&pfile->hash_ob); + } + + table->pfile = pfile; + pfile->hash_table = table; +} + +/* Tear down the identifier hash table. */ + +void +_cpp_destroy_hashtable (pfile) + cpp_reader *pfile; +{ + if (pfile->our_hashtable) + { + free (pfile->hash_table); + obstack_free (&pfile->hash_ob, 0); + } +} + +/* Returns the hash entry for the STR of length LEN, creating one + if necessary. */ + +cpp_hashnode * +cpp_lookup (pfile, str, len) + cpp_reader *pfile; + const unsigned char *str; + unsigned int len; +{ + /* ht_lookup cannot return NULL. */ + return CPP_HASHNODE (ht_lookup (pfile->hash_table, str, len, HT_ALLOC)); +} + +/* Determine whether the str STR, of length LEN, is a defined macro. */ + +int +cpp_defined (pfile, str, len) + cpp_reader *pfile; + const unsigned char *str; + int len; +{ + cpp_hashnode *node; + + node = CPP_HASHNODE (ht_lookup (pfile->hash_table, str, len, HT_NO_INSERT)); + + /* If it's of type NT_MACRO, it cannot be poisoned. */ + return node && node->type == NT_MACRO; +} + +/* For all nodes in the hashtable, callback CB with parameters PFILE, + the node, and V. */ + +void +cpp_forall_identifiers (pfile, cb, v) + cpp_reader *pfile; + cpp_cb cb; + PTR v; +{ + /* We don't need a proxy since the hash table's identifier comes + first in cpp_hashnode. */ + ht_forall (pfile->hash_table, (ht_cb) cb, v); +} diff --git a/support/cpp2/cpphash.h b/support/cpp2/cpphash.h new file mode 100644 index 00000000..56d90681 --- /dev/null +++ b/support/cpp2/cpphash.h @@ -0,0 +1,517 @@ +/* Part of CPP library. + Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This header defines all the internal data structures and functions + that need to be visible across files. It's called cpphash.h for + historical reasons. */ + +#ifndef GCC_CPPHASH_H +#define GCC_CPPHASH_H + +#include "hashtable.h" + +struct directive; /* Deliberately incomplete. */ + +/* Test if a sign is valid within a preprocessing number. */ +#define VALID_SIGN(c, prevc) \ + (((c) == '+' || (c) == '-') && \ + ((prevc) == 'e' || (prevc) == 'E' \ + || (((prevc) == 'p' || (prevc) == 'P') \ + && CPP_OPTION (pfile, extended_numbers)))) + +#define CPP_OPTION(PFILE, OPTION) ((PFILE)->opts.OPTION) +#define CPP_BUFFER(PFILE) ((PFILE)->buffer) +#define CPP_BUF_LINE(BUF) ((BUF)->lineno) +#define CPP_BUF_COLUMN(BUF, CUR) ((CUR) - (BUF)->line_base + (BUF)->col_adjust) +#define CPP_BUF_COL(BUF) CPP_BUF_COLUMN(BUF, (BUF)->cur) + +/* Maximum nesting of cpp_buffers. We use a static limit, partly for + efficiency, and partly to limit runaway recursion. */ +#define CPP_STACK_MAX 200 + +/* Memory pools. */ +#define POOL_ALIGN(size, align) (((size) + ((align) - 1)) & ~((align) - 1)) +#define POOL_FRONT(p) ((p)->cur->front) +#define POOL_LIMIT(p) ((p)->cur->limit) +#define POOL_BASE(p) ((p)->cur->base) +#define POOL_SIZE(p) ((p)->cur->limit - (p)->cur->base) +#define POOL_ROOM(p) ((p)->cur->limit - (p)->cur->front) +#define POOL_USED(p) ((p)->cur->front - (p)->cur->base) +#define POOL_COMMIT(p, len) do {\ + ((p)->cur->front += POOL_ALIGN (len, (p)->align));\ + if ((p)->cur->front > (p)->cur->limit) abort ();} while (0) + +typedef struct cpp_chunk cpp_chunk; +struct cpp_chunk +{ + cpp_chunk *next; + unsigned char *front; + unsigned char *limit; + unsigned char *base; +}; + +typedef struct cpp_pool cpp_pool; +struct cpp_pool +{ + struct cpp_chunk *cur, *locked; + unsigned char *pos; /* Current position. */ + unsigned int align; + unsigned int locks; +}; + +/* List of directories to look for include files in. */ +struct search_path +{ + struct search_path *next; + + /* NOTE: NAME may not be null terminated for the case of the current + file's directory! */ + const char *name; + unsigned int len; + /* We use these to tell if the directory mentioned here is a duplicate + of an earlier directory on the search path. */ + ino_t ino; + dev_t dev; + /* Non-zero if it is a system include directory. */ + int sysp; + /* Mapping of file names for this directory. Only used on MS-DOS + and related platforms. */ + struct file_name_map *name_map; +}; + +/* Multiple-include optimisation. */ +enum mi_state {MI_FAILED = 0, MI_OUTSIDE}; +enum mi_ind {MI_IND_NONE = 0, MI_IND_NOT}; + +/* #include types. */ +enum include_type {IT_INCLUDE, IT_INCLUDE_NEXT, IT_IMPORT, IT_CMDLINE}; + +typedef struct toklist toklist; +struct toklist +{ + cpp_token *first; + cpp_token *limit; +}; + +typedef struct cpp_context cpp_context; +struct cpp_context +{ + /* Doubly-linked list. */ + cpp_context *next, *prev; + + /* Contexts other than the base context are contiguous tokens. + e.g. macro expansions, expanded argument tokens. */ + struct toklist list; + + /* For a macro context, these are the macro and its arguments. */ + cpp_macro *macro; +}; + +struct lexer_state +{ + /* Nonzero if first token on line is CPP_HASH. */ + unsigned char in_directive; + + /* Nonzero if in a directive that takes angle-bracketed headers. */ + unsigned char angled_headers; + + /* Nonzero to save comments. Turned off if discard_comments, and in + all directives apart from #define. */ + unsigned char save_comments; + + /* If nonzero the next token is at the beginning of the line. */ + unsigned char next_bol; + + /* Nonzero if we're mid-comment. */ + unsigned char lexing_comment; + + /* Nonzero if lexing __VA_ARGS__ is valid. */ + unsigned char va_args_ok; + + /* Nonzero if lexing poisoned identifiers is valid. */ + unsigned char poisoned_ok; + + /* Nonzero to prevent macro expansion. */ + unsigned char prevent_expansion; + + /* Nonzero when parsing arguments to a function-like macro. */ + unsigned char parsing_args; + + /* Nonzero when in a # NUMBER directive. */ + unsigned char line_extension; +}; + +/* Special nodes - identifiers with predefined significance. */ +struct spec_nodes +{ + cpp_hashnode *n_L; /* L"str" */ + cpp_hashnode *n_defined; /* defined operator */ + cpp_hashnode *n_true; /* C++ keyword true */ + cpp_hashnode *n_false; /* C++ keyword false */ + cpp_hashnode *n__Pragma; /* _Pragma operator */ + cpp_hashnode *n__STRICT_ANSI__; /* STDC_0_IN_SYSTEM_HEADERS */ + cpp_hashnode *n__CHAR_UNSIGNED__; /* plain char is unsigned */ + cpp_hashnode *n__VA_ARGS__; /* C99 vararg macros */ +}; + +struct cpp_buffer +{ + const unsigned char *cur; /* current position */ + const unsigned char *rlimit; /* end of valid data */ + const unsigned char *line_base; /* start of current line */ + cppchar_t read_ahead; /* read ahead character */ + cppchar_t extra_char; /* extra read-ahead for long tokens. */ + + struct cpp_reader *pfile; /* Owns this buffer. */ + struct cpp_buffer *prev; + + const unsigned char *buf; /* entire buffer */ + + /* Filename specified with #line command. */ + const char *nominal_fname; + + /* Pointer into the include table. Used for include_next and + to record control macros. */ + struct include_file *inc; + + /* Value of if_stack at start of this file. + Used to prohibit unmatched #endif (etc) in an include file. */ + struct if_stack *if_stack; + + /* Token column position adjustment owing to tabs in whitespace. */ + unsigned int col_adjust; + + /* Line number at line_base (above). */ + unsigned int lineno; + + /* Contains PREV_WHITE and/or AVOID_LPASTE. */ + unsigned char saved_flags; + + /* Because of the way the lexer works, -Wtrigraphs can sometimes + warn twice for the same trigraph. This helps prevent that. */ + const unsigned char *last_Wtrigraphs; + + /* True if we have already warned about C++ comments in this file. + The warning happens only for C89 extended mode with -pedantic on, + or for -Wtraditional, and only once per file (otherwise it would + be far too noisy). */ + unsigned char warned_cplusplus_comments; + + /* True if we don't process trigraphs and escaped newlines. True + for preprocessed input, command line directives, and _Pragma + buffers. */ + unsigned char from_stage3; + + /* Temporary storage for pfile->skipping whilst in a directive. */ + unsigned char was_skipping; + + /* 1 = system header file, 2 = C system header file used for C++. */ + unsigned char sysp; + + /* Nonzero means we have printed (while error reporting) a list of + containing files that matches the current status. */ + unsigned char include_stack_listed; + + /* Nonzero means that the directory to start searching for "" + include files has been calculated and stored in "dir" below. */ + unsigned char search_cached; + + /* Buffer type. */ + ENUM_BITFIELD (cpp_buffer_type) type : 8; + + /* The directory of the this buffer's file. Its NAME member is not + allocated, so we don't need to worry about freeing it. */ + struct search_path dir; +}; + +/* A cpp_reader encapsulates the "state" of a pre-processor run. + Applying cpp_get_token repeatedly yields a stream of pre-processor + tokens. Usually, there is only one cpp_reader object active. */ + +struct cpp_reader +{ + /* Top of buffer stack. */ + cpp_buffer *buffer; + + /* Lexer state. */ + struct lexer_state state; + + /* The position of the last lexed token and last lexed directive. */ + cpp_lexer_pos lexer_pos; + cpp_lexer_pos directive_pos; + + /* Memory pools. */ + cpp_pool ident_pool; /* For all identifiers, and permanent + numbers and strings. */ + cpp_pool macro_pool; /* For macro definitions. Permanent. */ + cpp_pool argument_pool; /* For macro arguments. Temporary. */ + + /* Context stack. */ + struct cpp_context base_context; + struct cpp_context *context; + + /* If in_directive, the directive if known. */ + const struct directive *directive; + + /* Multiple inlcude optimisation. */ + enum mi_state mi_state; + enum mi_ind mi_if_not_defined; + unsigned int mi_lexed; + const cpp_hashnode *mi_cmacro; + const cpp_hashnode *mi_ind_cmacro; + + /* Token lookahead. */ + struct cpp_lookahead *la_read; /* Read from this lookahead. */ + struct cpp_lookahead *la_write; /* Write to this lookahead. */ + struct cpp_lookahead *la_unused; /* Free store. */ + struct cpp_lookahead *la_saved; /* Backup when entering directive. */ + + /* Error counter for exit code. */ + unsigned int errors; + + /* Line and column where a newline was first seen in a string + constant (multi-line strings). */ + cpp_lexer_pos mlstring_pos; + + /* Buffer to hold macro definition string. */ + unsigned char *macro_buffer; + unsigned int macro_buffer_len; + + /* Current depth in #include directives that use <...>. */ + unsigned int system_include_depth; + + /* Current depth of buffer stack. */ + unsigned int buffer_stack_depth; + + /* Current depth in #include directives. */ + unsigned int include_depth; + + /* Tree of other included files. See cppfiles.c. */ + struct splay_tree_s *all_include_files; + + /* Current maximum length of directory names in the search path + for include files. (Altered as we get more of them.) */ + unsigned int max_include_len; + + /* Date and time tokens. Calculated together if either is requested. */ + cpp_token date; + cpp_token time; + + /* Opaque handle to the dependencies of mkdeps.c. Used by -M etc. */ + struct deps *deps; + + /* Obstack holding all macro hash nodes. This never shrinks. + See cpphash.c */ + struct obstack hash_ob; + + /* Obstack holding buffer and conditional structures. This is a + real stack. See cpplib.c. */ + struct obstack buffer_ob; + + /* Pragma table - dynamic, because a library user can add to the + list of recognized pragmas. */ + struct pragma_entry *pragmas; + + /* Call backs. */ + struct cpp_callbacks cb; + + /* Identifier hash table. */ + struct ht *hash_table; + + /* User visible options. */ + struct cpp_options opts; + + /* Special nodes - identifiers with predefined significance to the + preprocessor. */ + struct spec_nodes spec_nodes; + + /* We're printed a warning recommending against using #import. */ + unsigned char import_warning; + + /* True if we are skipping a failed conditional group. */ + unsigned char skipping; + + /* Whether to print our version number. Done this way so + we don't get it twice for -v -version. */ + unsigned char print_version; + + /* Whether cpplib owns the hashtable. */ + unsigned char our_hashtable; +}; + +/* Character classes. Based on the more primitive macros in safe-ctype.h. + If the definition of `numchar' looks odd to you, please look up the + definition of a pp-number in the C standard [section 6.4.8 of C99]. + + In the unlikely event that characters other than \r and \n enter + the set is_vspace, the macro handle_newline() in cpplex.c must be + updated. */ +#define _dollar_ok(x) ((x) == '$' && CPP_OPTION (pfile, dollars_in_ident)) + +#define is_idchar(x) (ISIDNUM(x) || _dollar_ok(x)) +#define is_numchar(x) ISIDNUM(x) +#define is_idstart(x) (ISIDST(x) || _dollar_ok(x)) +#define is_numstart(x) ISDIGIT(x) +#define is_hspace(x) ISBLANK(x) +#define is_vspace(x) IS_VSPACE(x) +#define is_nvspace(x) IS_NVSPACE(x) +#define is_space(x) IS_SPACE_OR_NUL(x) + +/* This table is constant if it can be initialized at compile time, + which is the case if cpp was compiled with GCC >=2.7, or another + compiler that supports C99. */ +#if HAVE_DESIGNATED_INITIALIZERS +extern const unsigned char _cpp_trigraph_map[UCHAR_MAX + 1]; +#else +extern unsigned char _cpp_trigraph_map[UCHAR_MAX + 1]; +#endif + +/* Macros. */ + +#define CPP_PRINT_DEPS(PFILE) CPP_OPTION (PFILE, print_deps) +#define CPP_IN_SYSTEM_HEADER(PFILE) \ + (CPP_BUFFER (PFILE) && CPP_BUFFER (PFILE)->sysp) +#define CPP_PEDANTIC(PF) CPP_OPTION (PF, pedantic) +#define CPP_WTRADITIONAL(PF) CPP_OPTION (PF, warn_traditional) + +/* In cpperror.c */ +enum error_type { WARNING = 0, WARNING_SYSHDR, PEDWARN, ERROR, FATAL, ICE }; +extern int _cpp_begin_message PARAMS ((cpp_reader *, enum error_type, + const char *, const cpp_lexer_pos *)); + +/* In cppmacro.c */ +extern void _cpp_free_definition PARAMS ((cpp_hashnode *)); +extern int _cpp_create_definition PARAMS ((cpp_reader *, cpp_hashnode *)); +extern void _cpp_pop_context PARAMS ((cpp_reader *)); +extern void _cpp_free_lookaheads PARAMS ((cpp_reader *)); +extern void _cpp_release_lookahead PARAMS ((cpp_reader *)); +extern void _cpp_push_token PARAMS ((cpp_reader *, const cpp_token *, + const cpp_lexer_pos *)); + +/* In cpphash.c */ +extern void _cpp_init_hashtable PARAMS ((cpp_reader *, hash_table *)); +extern void _cpp_destroy_hashtable PARAMS ((cpp_reader *)); + +/* In cppfiles.c */ +extern void _cpp_fake_include PARAMS ((cpp_reader *, const char *)); +extern void _cpp_never_reread PARAMS ((struct include_file *)); +extern char *_cpp_simplify_pathname PARAMS ((char *)); +extern int _cpp_read_file PARAMS ((cpp_reader *, const char *)); +extern int _cpp_execute_include PARAMS ((cpp_reader *, + const cpp_token *, + enum include_type)); +extern int _cpp_compare_file_date PARAMS ((cpp_reader *, + const cpp_token *)); +extern void _cpp_report_missing_guards PARAMS ((cpp_reader *)); +extern void _cpp_init_includes PARAMS ((cpp_reader *)); +extern void _cpp_cleanup_includes PARAMS ((cpp_reader *)); +extern void _cpp_pop_file_buffer PARAMS ((cpp_reader *, cpp_buffer *)); + +/* In cppexp.c */ +extern int _cpp_parse_expr PARAMS ((cpp_reader *)); + +/* In cpplex.c */ +extern void _cpp_lex_token PARAMS ((cpp_reader *, cpp_token *)); +extern int _cpp_equiv_tokens PARAMS ((const cpp_token *, + const cpp_token *)); +extern void _cpp_init_pool PARAMS ((cpp_pool *, unsigned int, + unsigned int, unsigned int)); +extern void _cpp_free_pool PARAMS ((cpp_pool *)); +extern unsigned char *_cpp_pool_reserve PARAMS ((cpp_pool *, unsigned int)); +extern unsigned char *_cpp_pool_alloc PARAMS ((cpp_pool *, unsigned int)); +extern unsigned char *_cpp_next_chunk PARAMS ((cpp_pool *, unsigned int, + unsigned char **)); +extern void _cpp_lock_pool PARAMS ((cpp_pool *)); +extern void _cpp_unlock_pool PARAMS ((cpp_pool *)); + +/* In cpplib.c */ +extern int _cpp_test_assertion PARAMS ((cpp_reader *, int *)); +extern int _cpp_handle_directive PARAMS ((cpp_reader *, int)); +extern void _cpp_define_builtin PARAMS ((cpp_reader *, const char *)); +extern void _cpp_do__Pragma PARAMS ((cpp_reader *)); +extern void _cpp_init_directives PARAMS ((cpp_reader *)); +extern void _cpp_init_internal_pragmas PARAMS ((cpp_reader *)); +extern void _cpp_do_file_change PARAMS ((cpp_reader *, enum cpp_fc_reason, + const char *, unsigned int)); + +/* Utility routines and macros. */ +#define DSC(str) (const U_CHAR *)str, sizeof str - 1 +#define xnew(T) (T *) xmalloc (sizeof(T)) +#define xcnew(T) (T *) xcalloc (1, sizeof(T)) +#define xnewvec(T, N) (T *) xmalloc (sizeof(T) * (N)) +#define xcnewvec(T, N) (T *) xcalloc (N, sizeof(T)) +#define xobnew(O, T) (T *) obstack_alloc (O, sizeof(T)) + +/* These are inline functions instead of macros so we can get type + checking. */ +typedef unsigned char U_CHAR; +#define U (const U_CHAR *) /* Intended use: U"string" */ + +static inline int ustrcmp PARAMS ((const U_CHAR *, const U_CHAR *)); +static inline int ustrncmp PARAMS ((const U_CHAR *, const U_CHAR *, + size_t)); +static inline size_t ustrlen PARAMS ((const U_CHAR *)); +static inline U_CHAR *uxstrdup PARAMS ((const U_CHAR *)); +static inline U_CHAR *ustrchr PARAMS ((const U_CHAR *, int)); +static inline int ufputs PARAMS ((const U_CHAR *, FILE *)); + +static inline int +ustrcmp (s1, s2) + const U_CHAR *s1, *s2; +{ + return strcmp ((const char *)s1, (const char *)s2); +} + +static inline int +ustrncmp (s1, s2, n) + const U_CHAR *s1, *s2; + size_t n; +{ + return strncmp ((const char *)s1, (const char *)s2, n); +} + +static inline size_t +ustrlen (s1) + const U_CHAR *s1; +{ + return strlen ((const char *)s1); +} + +static inline U_CHAR * +uxstrdup (s1) + const U_CHAR *s1; +{ + return (U_CHAR *) xstrdup ((const char *)s1); +} + +static inline U_CHAR * +ustrchr (s1, c) + const U_CHAR *s1; + int c; +{ + return (U_CHAR *) strchr ((const char *)s1, c); +} + +static inline int +ufputs (s, f) + const U_CHAR *s; + FILE *f; +{ + return fputs ((const char *)s, f); +} + +#endif /* ! GCC_CPPHASH_H */ diff --git a/support/cpp2/cppinit.c b/support/cpp2/cppinit.c new file mode 100644 index 00000000..0d3d3a0d --- /dev/null +++ b/support/cpp2/cppinit.c @@ -0,0 +1,1896 @@ +/* CPP Library. + Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2001 Free Software Foundation, Inc. + Contributed by Per Bothner, 1994-95. + Based on CCCP program by Paul Rubin, June 1986 + Adapted to ANSI C, Richard Stallman, Jan 1987 + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "config.h" +#include "system.h" +#include "cpplib.h" +#include "cpphash.h" +#include "output.h" +#include "prefix.h" +#include "intl.h" +#include "version.h" +#include "mkdeps.h" +#include "cppdefault.h" + +/* Predefined symbols, built-in macros, and the default include path. */ + +#ifndef GET_ENV_PATH_LIST +#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0) +#endif + +/* Windows does not natively support inodes, and neither does MSDOS. + Cygwin's emulation can generate non-unique inodes, so don't use it. + VMS has non-numeric inodes. */ +#ifdef VMS +# define INO_T_EQ(a, b) (!memcmp (&(a), &(b), sizeof (a))) +#else +# if (defined _WIN32 && ! defined (_UWIN)) || defined __MSDOS__ +# define INO_T_EQ(a, b) 0 +# else +# define INO_T_EQ(a, b) ((a) == (b)) +# endif +#endif + +/* Internal structures and prototypes. */ + +/* A `struct pending_option' remembers one -D, -A, -U, -include, or + -imacros switch. */ + +typedef void (* cl_directive_handler) PARAMS ((cpp_reader *, const char *)); +struct pending_option +{ + struct pending_option *next; + const char *arg; + cl_directive_handler handler; +}; + +/* The `pending' structure accumulates all the options that are not + actually processed until we hit cpp_start_read. It consists of + several lists, one for each type of option. We keep both head and + tail pointers for quick insertion. */ +struct cpp_pending +{ + struct pending_option *directive_head, *directive_tail; + + struct search_path *quote_head, *quote_tail; + struct search_path *brack_head, *brack_tail; + struct search_path *systm_head, *systm_tail; + struct search_path *after_head, *after_tail; + + struct pending_option *imacros_head, *imacros_tail; + struct pending_option *include_head, *include_tail; +}; + +#ifdef __STDC__ +#define APPEND(pend, list, elt) \ + do { if (!(pend)->list##_head) (pend)->list##_head = (elt); \ + else (pend)->list##_tail->next = (elt); \ + (pend)->list##_tail = (elt); \ + } while (0) +#else +#define APPEND(pend, list, elt) \ + do { if (!(pend)->list/**/_head) (pend)->list/**/_head = (elt); \ + else (pend)->list/**/_tail->next = (elt); \ + (pend)->list/**/_tail = (elt); \ + } while (0) +#endif + +static void print_help PARAMS ((void)); +static void path_include PARAMS ((cpp_reader *, + char *, int)); +static void init_library PARAMS ((void)); +static void init_builtins PARAMS ((cpp_reader *)); +static void append_include_chain PARAMS ((cpp_reader *, + char *, int, int)); +struct search_path * remove_dup_dir PARAMS ((cpp_reader *, + struct search_path *)); +struct search_path * remove_dup_dirs PARAMS ((cpp_reader *, + struct search_path *)); +static void merge_include_chains PARAMS ((cpp_reader *)); +static void do_includes PARAMS ((cpp_reader *, + struct pending_option *, + int)); +static void set_lang PARAMS ((cpp_reader *, enum c_lang)); +static void init_dependency_output PARAMS ((cpp_reader *)); +static void init_standard_includes PARAMS ((cpp_reader *)); +static void new_pending_directive PARAMS ((struct cpp_pending *, + const char *, + cl_directive_handler)); +static void output_deps PARAMS ((cpp_reader *)); +static int parse_option PARAMS ((const char *)); + +/* Fourth argument to append_include_chain: chain to use. + Note it's never asked to append to the quote chain. */ +enum { BRACKET = 0, SYSTEM, AFTER }; + +/* If we have designated initializers (GCC >2.7) these tables can be + initialized, constant data. Otherwise, they have to be filled in at + runtime. */ +#if HAVE_DESIGNATED_INITIALIZERS + +#define init_trigraph_map() /* Nothing. */ +#define TRIGRAPH_MAP \ +__extension__ const U_CHAR _cpp_trigraph_map[UCHAR_MAX + 1] = { + +#define END }; +#define s(p, v) [p] = v, + +#else + +#define TRIGRAPH_MAP U_CHAR _cpp_trigraph_map[UCHAR_MAX + 1] = { 0 }; \ + static void init_trigraph_map PARAMS ((void)) { \ + unsigned char *x = _cpp_trigraph_map; + +#define END } +#define s(p, v) x[p] = v; + +#endif + +TRIGRAPH_MAP + s('=', '#') s(')', ']') s('!', '|') + s('(', '[') s('\'', '^') s('>', '}') + s('/', '\\') s('<', '{') s('-', '~') +END + +#undef s +#undef END +#undef TRIGRAPH_MAP + +/* Given a colon-separated list of file names PATH, + add all the names to the search path for include files. */ + +static void +path_include (pfile, list, path) + cpp_reader *pfile; + char *list; + int path; +{ + char *p, *q, *name; + + p = list; + + do + { + /* Find the end of this name. */ + q = p; + while (*q != 0 && *q != PATH_SEPARATOR) q++; + if (q == p) + { + /* An empty name in the path stands for the current directory. */ + name = (char *) xmalloc (2); + name[0] = '.'; + name[1] = 0; + } + else + { + /* Otherwise use the directory that is named. */ + name = (char *) xmalloc (q - p + 1); + memcpy (name, p, q - p); + name[q - p] = 0; + } + + append_include_chain (pfile, name, path, 0); + + /* Advance past this name. */ + if (*q == 0) + break; + p = q + 1; + } + while (1); +} + +/* Append DIR to include path PATH. DIR must be permanently allocated + and writable. */ +static void +append_include_chain (pfile, dir, path, cxx_aware) + cpp_reader *pfile; + char *dir; + int path; + int cxx_aware ATTRIBUTE_UNUSED; +{ + struct cpp_pending *pend = CPP_OPTION (pfile, pending); + struct search_path *new; + struct stat st; + unsigned int len; + + if (*dir == '\0') + dir = xstrdup ("."); + _cpp_simplify_pathname (dir); + if (stat (dir, &st)) + { + /* Dirs that don't exist are silently ignored. */ + if (errno != ENOENT) + cpp_notice_from_errno (pfile, dir); + else if (CPP_OPTION (pfile, verbose)) + fprintf (stderr, _("ignoring nonexistent directory \"%s\"\n"), dir); + return; + } + + if (!S_ISDIR (st.st_mode)) + { + cpp_notice (pfile, "%s: Not a directory", dir); + return; + } + + len = strlen (dir); + if (len > pfile->max_include_len) + pfile->max_include_len = len; + + new = (struct search_path *) xmalloc (sizeof (struct search_path)); + new->name = dir; + new->len = len; + new->ino = st.st_ino; + new->dev = st.st_dev; + /* Both systm and after include file lists should be treated as system + include files since these two lists are really just a concatenation + of one "system" list. */ + if (path == SYSTEM || path == AFTER) +#ifdef NO_IMPLICIT_EXTERN_C + new->sysp = 1; +#else + new->sysp = cxx_aware ? 1 : 2; +#endif + else + new->sysp = 0; + new->name_map = NULL; + new->next = NULL; + + switch (path) + { + case BRACKET: APPEND (pend, brack, new); break; + case SYSTEM: APPEND (pend, systm, new); break; + case AFTER: APPEND (pend, after, new); break; + } +} + +/* Handle a duplicated include path. PREV is the link in the chain + before the duplicate. The duplicate is removed from the chain and + freed. Returns PREV. */ +struct search_path * +remove_dup_dir (pfile, prev) + cpp_reader *pfile; + struct search_path *prev; +{ + struct search_path *cur = prev->next; + + if (CPP_OPTION (pfile, verbose)) + fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"), cur->name); + + prev->next = cur->next; + free ((PTR) cur->name); + free (cur); + + return prev; +} + +/* Remove duplicate directories from a chain. Returns the tail of the + chain, or NULL if the chain is empty. This algorithm is quadratic + in the number of -I switches, which is acceptable since there + aren't usually that many of them. */ +struct search_path * +remove_dup_dirs (pfile, head) + cpp_reader *pfile; + struct search_path *head; +{ + struct search_path *prev = NULL, *cur, *other; + + for (cur = head; cur; cur = cur->next) + { + for (other = head; other != cur; other = other->next) + if (INO_T_EQ (cur->ino, other->ino) && cur->dev == other->dev) + { + cur = remove_dup_dir (pfile, prev); + break; + } + prev = cur; + } + + return prev; +} + +/* Merge the four include chains together in the order quote, bracket, + system, after. Remove duplicate dirs (as determined by + INO_T_EQ()). The system_include and after_include chains are never + referred to again after this function; all access is through the + bracket_include path. + + For the future: Check if the directory is empty (but + how?) and possibly preload the include hash. */ + +static void +merge_include_chains (pfile) + cpp_reader *pfile; +{ + struct search_path *quote, *brack, *systm, *qtail; + + struct cpp_pending *pend = CPP_OPTION (pfile, pending); + + quote = pend->quote_head; + brack = pend->brack_head; + systm = pend->systm_head; + qtail = pend->quote_tail; + + /* Paste together bracket, system, and after include chains. */ + if (systm) + pend->systm_tail->next = pend->after_head; + else + systm = pend->after_head; + + if (brack) + pend->brack_tail->next = systm; + else + brack = systm; + + /* This is a bit tricky. First we drop dupes from the quote-include + list. Then we drop dupes from the bracket-include list. + Finally, if qtail and brack are the same directory, we cut out + brack and move brack up to point to qtail. + + We can't just merge the lists and then uniquify them because + then we may lose directories from the <> search path that should + be there; consider -Ifoo -Ibar -I- -Ifoo -Iquux. It is however + safe to treat -Ibar -Ifoo -I- -Ifoo -Iquux as if written + -Ibar -I- -Ifoo -Iquux. */ + + remove_dup_dirs (pfile, brack); + qtail = remove_dup_dirs (pfile, quote); + + if (quote) + { + qtail->next = brack; + + /* If brack == qtail, remove brack as it's simpler. */ + if (INO_T_EQ (qtail->ino, brack->ino) && qtail->dev == brack->dev) + brack = remove_dup_dir (pfile, qtail); + } + else + quote = brack; + + CPP_OPTION (pfile, quote_include) = quote; + CPP_OPTION (pfile, bracket_include) = brack; +} + +/* Sets internal flags correctly for a given language, and defines + macros if necessary. */ +static void +set_lang (pfile, lang) + cpp_reader *pfile; + enum c_lang lang; +{ + /* Defaults. */ + CPP_OPTION (pfile, lang) = lang; + CPP_OPTION (pfile, objc) = 0; + CPP_OPTION (pfile, cplusplus) = 0; + CPP_OPTION (pfile, extended_numbers) = 1; /* Allowed in GNU C and C99. */ + + switch (lang) + { + /* GNU C. */ + case CLK_GNUC99: + CPP_OPTION (pfile, trigraphs) = 0; + CPP_OPTION (pfile, dollars_in_ident) = 1; + CPP_OPTION (pfile, cplusplus_comments) = 1; + CPP_OPTION (pfile, digraphs) = 1; + CPP_OPTION (pfile, c99) = 1; + break; + case CLK_GNUC89: + CPP_OPTION (pfile, trigraphs) = 0; + CPP_OPTION (pfile, dollars_in_ident) = 1; + CPP_OPTION (pfile, cplusplus_comments) = 1; + CPP_OPTION (pfile, digraphs) = 1; + CPP_OPTION (pfile, c99) = 0; + break; + + /* ISO C. */ + case CLK_STDC94: + case CLK_STDC89: + CPP_OPTION (pfile, trigraphs) = 1; + CPP_OPTION (pfile, dollars_in_ident) = 0; + CPP_OPTION (pfile, cplusplus_comments) = 0; + CPP_OPTION (pfile, digraphs) = lang == CLK_STDC94; + CPP_OPTION (pfile, c99) = 0; + CPP_OPTION (pfile, extended_numbers) = 0; + break; + case CLK_STDC99: + CPP_OPTION (pfile, trigraphs) = 1; + CPP_OPTION (pfile, dollars_in_ident) = 0; + CPP_OPTION (pfile, cplusplus_comments) = 1; + CPP_OPTION (pfile, digraphs) = 1; + CPP_OPTION (pfile, c99) = 1; + break; + + /* Objective C. */ + case CLK_OBJCXX: + CPP_OPTION (pfile, cplusplus) = 1; + case CLK_OBJC: + CPP_OPTION (pfile, trigraphs) = 0; + CPP_OPTION (pfile, dollars_in_ident) = 1; + CPP_OPTION (pfile, cplusplus_comments) = 1; + CPP_OPTION (pfile, digraphs) = 1; + CPP_OPTION (pfile, c99) = 0; + CPP_OPTION (pfile, objc) = 1; + break; + + /* C++. */ + case CLK_GNUCXX: + case CLK_CXX98: + CPP_OPTION (pfile, cplusplus) = 1; + CPP_OPTION (pfile, trigraphs) = lang == CLK_CXX98; + CPP_OPTION (pfile, dollars_in_ident) = lang == CLK_GNUCXX; + CPP_OPTION (pfile, cplusplus_comments) = 1; + CPP_OPTION (pfile, digraphs) = 1; + CPP_OPTION (pfile, c99) = 0; + break; + + /* Assembler. */ + case CLK_ASM: + CPP_OPTION (pfile, trigraphs) = 0; + CPP_OPTION (pfile, dollars_in_ident) = 0; /* Maybe not? */ + CPP_OPTION (pfile, cplusplus_comments) = 1; + CPP_OPTION (pfile, digraphs) = 0; + CPP_OPTION (pfile, c99) = 0; + break; + } +} + +#ifdef HOST_EBCDIC +static int opt_comp PARAMS ((const void *, const void *)); + +/* Run-time sorting of options array. */ +static int +opt_comp (p1, p2) + const void *p1, *p2; +{ + return strcmp (((struct cl_option *) p1)->opt_text, + ((struct cl_option *) p2)->opt_text); +} +#endif + +/* init initializes library global state. It might not need to + do anything depending on the platform and compiler. */ + +static void +init_library () +{ + static int initialized = 0; + + if (! initialized) + { + initialized = 1; + +#ifdef HOST_EBCDIC + /* For non-ASCII hosts, the cl_options array needs to be sorted at + runtime. */ + qsort (cl_options, N_OPTS, sizeof (struct cl_option), opt_comp); +#endif + + /* Set up the trigraph map. This doesn't need to do anything if + we were compiled with a compiler that supports C99 designated + initializers. */ + init_trigraph_map (); + } +} + +/* Initialize a cpp_reader structure. */ +cpp_reader * +cpp_create_reader (table, lang) + hash_table *table; + enum c_lang lang; +{ + struct spec_nodes *s; + cpp_reader *pfile; + + /* Initialise this instance of the library if it hasn't been already. */ + init_library (); + + pfile = (cpp_reader *) xcalloc (1, sizeof (cpp_reader)); + + set_lang (pfile, lang); + CPP_OPTION (pfile, warn_import) = 1; + CPP_OPTION (pfile, discard_comments) = 1; + CPP_OPTION (pfile, show_column) = 1; + CPP_OPTION (pfile, tabstop) = 8; + CPP_OPTION (pfile, operator_names) = 1; + + CPP_OPTION (pfile, pending) = + (struct cpp_pending *) xcalloc (1, sizeof (struct cpp_pending)); + + /* It's simplest to just create this struct whether or not it will + be needed. */ + pfile->deps = deps_init (); + + /* Initialize lexer state. */ + pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments); + + /* Indicate date and time not yet calculated. */ + pfile->date.type = CPP_EOF; + + /* Initialise the base context. */ + pfile->context = &pfile->base_context; + pfile->base_context.macro = 0; + pfile->base_context.prev = pfile->base_context.next = 0; + + /* Identifier pool initially 8K. Unaligned, permanent pool. */ + _cpp_init_pool (&pfile->ident_pool, 8 * 1024, 1, 0); + + /* Argument pool initially 8K. Aligned, temporary pool. */ + _cpp_init_pool (&pfile->argument_pool, 8 * 1024, 0, 1); + + /* Macro pool initially 8K. Aligned, permanent pool. */ + _cpp_init_pool (&pfile->macro_pool, 8 * 1024, 0, 0); + + /* Initialise the buffer obstack. */ + gcc_obstack_init (&pfile->buffer_ob); + + /* Initialise the hashtable. */ + _cpp_init_hashtable (pfile, table); + + _cpp_init_directives (pfile); + _cpp_init_includes (pfile); + _cpp_init_internal_pragmas (pfile); + + /* Initialize the special nodes. */ + s = &pfile->spec_nodes; + s->n_L = cpp_lookup (pfile, DSC("L")); + s->n_defined = cpp_lookup (pfile, DSC("defined")); + s->n_true = cpp_lookup (pfile, DSC("true")); + s->n_false = cpp_lookup (pfile, DSC("false")); + s->n__Pragma = cpp_lookup (pfile, DSC("_Pragma")); + s->n__STRICT_ANSI__ = cpp_lookup (pfile, DSC("__STRICT_ANSI__")); + s->n__CHAR_UNSIGNED__ = cpp_lookup (pfile, DSC("__CHAR_UNSIGNED__")); + s->n__VA_ARGS__ = cpp_lookup (pfile, DSC("__VA_ARGS__")); + s->n__VA_ARGS__->flags |= NODE_DIAGNOSTIC; + + return pfile; +} + +/* Free resources used by PFILE. Accessing PFILE after this function + returns leads to undefined behaviour. */ +int +cpp_destroy (pfile) + cpp_reader *pfile; +{ + int result; + struct search_path *dir, *dirn; + cpp_context *context, *contextn; + + while (CPP_BUFFER (pfile) != NULL) + cpp_pop_buffer (pfile); + + if (pfile->macro_buffer) + { + free ((PTR) pfile->macro_buffer); + pfile->macro_buffer = NULL; + pfile->macro_buffer_len = 0; + } + + deps_free (pfile->deps); + obstack_free (&pfile->buffer_ob, 0); + + _cpp_destroy_hashtable (pfile); + _cpp_cleanup_includes (pfile); + _cpp_free_lookaheads (pfile); + + _cpp_free_pool (&pfile->ident_pool); + _cpp_free_pool (&pfile->macro_pool); + _cpp_free_pool (&pfile->argument_pool); + + for (dir = CPP_OPTION (pfile, quote_include); dir; dir = dirn) + { + dirn = dir->next; + free ((PTR) dir->name); + free (dir); + } + + for (context = pfile->base_context.next; context; context = contextn) + { + contextn = context->next; + free (context); + } + + result = pfile->errors; + free (pfile); + + return result; +} + + +/* This structure defines one built-in identifier. A node will be + entered in the hash table under the name NAME, with value VALUE (if + any). If flags has OPERATOR, the node's operator field is used; if + flags has BUILTIN the node's builtin field is used. Macros that are + known at build time should not be flagged BUILTIN, as then they do + not appear in macro dumps with e.g. -dM or -dD. + + Two values are not compile time constants, so we tag + them in the FLAGS field instead: + VERS value is the global version_string, quoted + ULP value is the global user_label_prefix + + Also, macros with CPLUS set in the flags field are entered only for C++. */ + +struct builtin +{ + const U_CHAR *name; + const char *value; + unsigned char builtin; + unsigned char operator; + unsigned short flags; + unsigned short len; +}; +#define VERS 0x01 +#define ULP 0x02 +#define CPLUS 0x04 +#define BUILTIN 0x08 +#define OPERATOR 0x10 + +#define B(n, t) { U n, 0, t, 0, BUILTIN, sizeof n - 1 } +#define C(n, v) { U n, v, 0, 0, 0, sizeof n - 1 } +#define X(n, f) { U n, 0, 0, 0, f, sizeof n - 1 } +#define O(n, c, f) { U n, 0, 0, c, OPERATOR | f, sizeof n - 1 } +static const struct builtin builtin_array[] = +{ + B("__TIME__", BT_TIME), + B("__DATE__", BT_DATE), + B("__FILE__", BT_FILE), + B("__BASE_FILE__", BT_BASE_FILE), + B("__LINE__", BT_SPECLINE), + B("__INCLUDE_LEVEL__", BT_INCLUDE_LEVEL), + + X("__VERSION__", VERS), + X("__USER_LABEL_PREFIX__", ULP), + C("__REGISTER_PREFIX__", REGISTER_PREFIX), + C("__HAVE_BUILTIN_SETJMP__", "1"), +#ifndef NO_BUILTIN_SIZE_TYPE + C("__SIZE_TYPE__", SIZE_TYPE), +#endif +#ifndef NO_BUILTIN_PTRDIFF_TYPE + C("__PTRDIFF_TYPE__", PTRDIFF_TYPE), +#endif +#ifndef NO_BUILTIN_WCHAR_TYPE + C("__WCHAR_TYPE__", WCHAR_TYPE), +#endif +#ifndef NO_BUILTIN_WINT_TYPE + C("__WINT_TYPE__", WINT_TYPE), +#endif +#ifdef STDC_0_IN_SYSTEM_HEADERS + B("__STDC__", BT_STDC), +#else + C("__STDC__", "1"), +#endif + + /* Named operators known to the preprocessor. These cannot be #defined + and always have their stated meaning. They are treated like normal + identifiers except for the type code and the meaning. Most of them + are only for C++ (but see iso646.h). */ + O("and", CPP_AND_AND, CPLUS), + O("and_eq", CPP_AND_EQ, CPLUS), + O("bitand", CPP_AND, CPLUS), + O("bitor", CPP_OR, CPLUS), + O("compl", CPP_COMPL, CPLUS), + O("not", CPP_NOT, CPLUS), + O("not_eq", CPP_NOT_EQ, CPLUS), + O("or", CPP_OR_OR, CPLUS), + O("or_eq", CPP_OR_EQ, CPLUS), + O("xor", CPP_XOR, CPLUS), + O("xor_eq", CPP_XOR_EQ, CPLUS) +}; +#undef B +#undef C +#undef X +#undef O +#define builtin_array_end \ + builtin_array + sizeof(builtin_array)/sizeof(struct builtin) + +/* Subroutine of cpp_start_read; reads the builtins table above and + enters the macros into the hash table. */ +static void +init_builtins (pfile) + cpp_reader *pfile; +{ + const struct builtin *b; + + for(b = builtin_array; b < builtin_array_end; b++) + { + if ((b->flags & CPLUS) && ! CPP_OPTION (pfile, cplusplus)) + continue; + + if ((b->flags & OPERATOR) && ! CPP_OPTION (pfile, operator_names)) + continue; + + if (b->flags & (OPERATOR | BUILTIN)) + { + cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len); + if (b->flags & OPERATOR) + { + hp->flags |= NODE_OPERATOR; + hp->value.operator = b->operator; + } + else + { + hp->type = NT_MACRO; + hp->flags |= NODE_BUILTIN | NODE_WARN; + hp->value.builtin = b->builtin; + } + } + else /* A standard macro of some kind. */ + { + const char *val; + char *str; + + if (b->flags & VERS) + { + /* Allocate enough space for 'name "value"\n\0'. */ + str = alloca (b->len + strlen (version_string) + 5); + sprintf (str, "%s \"%s\"\n", b->name, version_string); + } + else + { + if (b->flags & ULP) + val = CPP_OPTION (pfile, user_label_prefix); + else + val = b->value; + + /* Allocate enough space for "name value\n\0". */ + str = alloca (b->len + strlen (val) + 3); + sprintf(str, "%s %s\n", b->name, val); + } + + _cpp_define_builtin (pfile, str); + } + } + + if (CPP_OPTION (pfile, cplusplus)) + { + _cpp_define_builtin (pfile, "__cplusplus 1"); + if (SUPPORTS_ONE_ONLY) + _cpp_define_builtin (pfile, "__GXX_WEAK__ 1"); + else + _cpp_define_builtin (pfile, "__GXX_WEAK__ 0"); + } + if (CPP_OPTION (pfile, objc)) + _cpp_define_builtin (pfile, "__OBJC__ 1"); + + if (CPP_OPTION (pfile, lang) == CLK_STDC94) + _cpp_define_builtin (pfile, "__STDC_VERSION__ 199409L"); + else if (CPP_OPTION (pfile, c99)) + _cpp_define_builtin (pfile, "__STDC_VERSION__ 199901L"); + + if (CPP_OPTION (pfile, lang) == CLK_STDC89 + || CPP_OPTION (pfile, lang) == CLK_STDC94 + || CPP_OPTION (pfile, lang) == CLK_STDC99) + _cpp_define_builtin (pfile, "__STRICT_ANSI__ 1"); + else if (CPP_OPTION (pfile, lang) == CLK_ASM) + _cpp_define_builtin (pfile, "__ASSEMBLER__ 1"); +} +#undef BUILTIN +#undef OPERATOR +#undef VERS +#undef ULP +#undef CPLUS +#undef builtin_array_end + +/* And another subroutine. This one sets up the standard include path. */ +static void +init_standard_includes (pfile) + cpp_reader *pfile; +{ + char *path; + const struct default_include *p; + const char *specd_prefix = CPP_OPTION (pfile, include_prefix); + + /* Several environment variables may add to the include search path. + CPATH specifies an additional list of directories to be searched + as if specified with -I, while C_INCLUDE_PATH, CPLUS_INCLUDE_PATH, + etc. specify an additional list of directories to be searched as + if specified with -isystem, for the language indicated. */ + + GET_ENV_PATH_LIST (path, "CPATH"); + if (path != 0 && *path != 0) + path_include (pfile, path, BRACKET); + + switch ((CPP_OPTION (pfile, objc) << 1) + CPP_OPTION (pfile, cplusplus)) + { + case 0: + GET_ENV_PATH_LIST (path, "C_INCLUDE_PATH"); + break; + case 1: + GET_ENV_PATH_LIST (path, "CPLUS_INCLUDE_PATH"); + break; + case 2: + GET_ENV_PATH_LIST (path, "OBJC_INCLUDE_PATH"); + break; + case 3: + GET_ENV_PATH_LIST (path, "OBJCPLUS_INCLUDE_PATH"); + break; + } + if (path != 0 && *path != 0) + path_include (pfile, path, SYSTEM); + + /* Search "translated" versions of GNU directories. + These have /usr/local/lib/gcc... replaced by specd_prefix. */ + if (specd_prefix != 0 && cpp_GCC_INCLUDE_DIR_len) + { + /* Remove the `include' from /usr/local/lib/gcc.../include. + GCC_INCLUDE_DIR will always end in /include. */ + int default_len = cpp_GCC_INCLUDE_DIR_len; + char *default_prefix = (char *) alloca (default_len + 1); + int specd_len = strlen (specd_prefix); + + memcpy (default_prefix, cpp_GCC_INCLUDE_DIR, default_len); + default_prefix[default_len] = '\0'; + + for (p = cpp_include_defaults; p->fname; p++) + { + /* Some standard dirs are only for C++. */ + if (!p->cplusplus + || (CPP_OPTION (pfile, cplusplus) + && !CPP_OPTION (pfile, no_standard_cplusplus_includes))) + { + /* Does this dir start with the prefix? */ + if (!memcmp (p->fname, default_prefix, default_len)) + { + /* Yes; change prefix and add to search list. */ + int flen = strlen (p->fname); + int this_len = specd_len + flen - default_len; + char *str = (char *) xmalloc (this_len + 1); + memcpy (str, specd_prefix, specd_len); + memcpy (str + specd_len, + p->fname + default_len, + flen - default_len + 1); + + append_include_chain (pfile, str, SYSTEM, p->cxx_aware); + } + } + } + } + + /* Search ordinary names for GNU include directories. */ + for (p = cpp_include_defaults; p->fname; p++) + { + /* Some standard dirs are only for C++. */ + if (!p->cplusplus + || (CPP_OPTION (pfile, cplusplus) + && !CPP_OPTION (pfile, no_standard_cplusplus_includes))) + { + char *str = xstrdup (update_path (p->fname, p->component)); + append_include_chain (pfile, str, SYSTEM, p->cxx_aware); + } + } +} + +/* Handles -imacro and -include from the command line. */ +static void +do_includes (pfile, p, scan) + cpp_reader *pfile; + struct pending_option *p; + int scan; +{ + while (p) + { + struct pending_option *q; + + /* Don't handle if -fpreprocessed. Later: maybe update this to + use the #include "" search path if cpp_read_file fails. */ + if (CPP_OPTION (pfile, preprocessed)) + cpp_error (pfile, "-include and -imacros cannot be used with -fpreprocessed"); + else + { + cpp_token header; + header.type = CPP_STRING; + header.val.str.text = (const unsigned char *) p->arg; + header.val.str.len = strlen (p->arg); + if (_cpp_execute_include (pfile, &header, IT_CMDLINE) && scan) + cpp_scan_buffer_nooutput (pfile, 0); + } + q = p->next; + free (p); + p = q; + } +} + +/* This is called after options have been processed. Setup for + processing input from the file named FNAME, or stdin if it is the + empty string. Return 1 on success, 0 on failure. */ +int +cpp_start_read (pfile, fname) + cpp_reader *pfile; + const char *fname; +{ + struct pending_option *p, *q; + + /* Set up the include search path now. */ + if (! CPP_OPTION (pfile, no_standard_includes)) + init_standard_includes (pfile); + + merge_include_chains (pfile); + + /* With -v, print the list of dirs to search. */ + if (CPP_OPTION (pfile, verbose)) + { + struct search_path *l; + fprintf (stderr, _("#include \"...\" search starts here:\n")); + for (l = CPP_OPTION (pfile, quote_include); l; l = l->next) + { + if (l == CPP_OPTION (pfile, bracket_include)) + fprintf (stderr, _("#include <...> search starts here:\n")); + fprintf (stderr, " %s\n", l->name); + } + fprintf (stderr, _("End of search list.\n")); + } + + if (CPP_OPTION (pfile, print_deps)) + /* Set the default target (if there is none already). */ + deps_add_default_target (pfile->deps, fname); + + /* Open the main input file. This must be done early, so we have a + buffer to stand on. */ + if (!_cpp_read_file (pfile, fname)) + return 0; + + /* If already preprocessed, don't install __LINE__, etc., and ignore + command line definitions and assertions. Handle -U's, -D's and + -A's in the order they were seen. */ + if (! CPP_OPTION (pfile, preprocessed)) + init_builtins (pfile); + + p = CPP_OPTION (pfile, pending)->directive_head; + while (p) + { + if (! CPP_OPTION (pfile, preprocessed)) + (*p->handler) (pfile, p->arg); + q = p->next; + free (p); + p = q; + } + + /* The -imacros files can be scanned now, but the -include files + have to be pushed onto the buffer stack and processed later, + otherwise cppmain.c won't see the tokens. include_head was built + up as a stack, and popping this stack onto the buffer stack means + we preserve the order of the command line. */ + do_includes (pfile, CPP_OPTION (pfile, pending)->imacros_head, 1); + do_includes (pfile, CPP_OPTION (pfile, pending)->include_head, 0); + + free (CPP_OPTION (pfile, pending)); + CPP_OPTION (pfile, pending) = NULL; + + return 1; +} + +/* Use mkdeps.c to output dependency information. */ +static void +output_deps (pfile) + cpp_reader *pfile; +{ + /* Stream on which to print the dependency information. */ + FILE *deps_stream = 0; + const char *deps_mode = CPP_OPTION (pfile, print_deps_append) ? "a" : "w"; + + if (CPP_OPTION (pfile, deps_file) == 0) + deps_stream = stdout; + else + { + deps_stream = fopen (CPP_OPTION (pfile, deps_file), deps_mode); + if (deps_stream == 0) + { + cpp_notice_from_errno (pfile, CPP_OPTION (pfile, deps_file)); + return; + } + } + + deps_write (pfile->deps, deps_stream, 72); + + if (CPP_OPTION (pfile, deps_phony_targets)) + deps_phony_targets (pfile->deps, deps_stream); + + /* Don't close stdout. */ + if (CPP_OPTION (pfile, deps_file)) + { + if (ferror (deps_stream) || fclose (deps_stream) != 0) + cpp_fatal (pfile, "I/O error on output"); + } +} + +/* This is called at the end of preprocessing. It pops the + last buffer and writes dependency output. It should also + clear macro definitions, such that you could call cpp_start_read + with a new filename to restart processing. */ +void +cpp_finish (pfile) + cpp_reader *pfile; +{ + if (CPP_BUFFER (pfile)) + { + cpp_ice (pfile, "buffers still stacked in cpp_finish"); + while (CPP_BUFFER (pfile)) + cpp_pop_buffer (pfile); + } + + /* Don't write the deps file if preprocessing has failed. */ + if (CPP_OPTION (pfile, print_deps) && pfile->errors == 0) + output_deps (pfile); + + /* Report on headers that could use multiple include guards. */ + if (CPP_OPTION (pfile, print_include_names)) + _cpp_report_missing_guards (pfile); +} + +static void +new_pending_directive (pend, text, handler) + struct cpp_pending *pend; + const char *text; + cl_directive_handler handler; +{ + struct pending_option *o = (struct pending_option *) + xmalloc (sizeof (struct pending_option)); + + o->arg = text; + o->next = NULL; + o->handler = handler; + APPEND (pend, directive, o); +} + +/* Irix6 "cc -n32" and OSF4 cc have problems with char foo[] = ("string"); + I.e. a const string initializer with parens around it. That is + what N_("string") resolves to, so we make no_* be macros instead. */ +#define no_arg N_("Argument missing after %s") +#define no_ass N_("Assertion missing after %s") +#define no_dir N_("Directory name missing after %s") +#define no_fil N_("File name missing after %s") +#define no_mac N_("Macro name missing after %s") +#define no_pth N_("Path name missing after %s") +#define no_num N_("Number missing after %s") +#define no_tgt N_("Target missing after %s") + +/* This is the list of all command line options, with the leading + "-" removed. It must be sorted in ASCII collating order. */ +#define COMMAND_LINE_OPTIONS \ + DEF_OPT("$", 0, OPT_dollar) \ + DEF_OPT("+", 0, OPT_plus) \ + DEF_OPT("-help", 0, OPT__help) \ + DEF_OPT("-target-help", 0, OPT_target__help) \ + DEF_OPT("-version", 0, OPT__version) \ + DEF_OPT("A", no_ass, OPT_A) \ + DEF_OPT("C", 0, OPT_C) \ + DEF_OPT("D", no_mac, OPT_D) \ + DEF_OPT("H", 0, OPT_H) \ + DEF_OPT("I", no_dir, OPT_I) \ + DEF_OPT("M", 0, OPT_M) \ + DEF_OPT("MD", no_fil, OPT_MD) \ + DEF_OPT("MF", no_fil, OPT_MF) \ + DEF_OPT("MG", 0, OPT_MG) \ + DEF_OPT("MM", 0, OPT_MM) \ + DEF_OPT("MMD", no_fil, OPT_MMD) \ + DEF_OPT("MP", 0, OPT_MP) \ + DEF_OPT("MQ", no_tgt, OPT_MQ) \ + DEF_OPT("MT", no_tgt, OPT_MT) \ + DEF_OPT("P", 0, OPT_P) \ + DEF_OPT("U", no_mac, OPT_U) \ + DEF_OPT("W", no_arg, OPT_W) /* arg optional */ \ + DEF_OPT("d", no_arg, OPT_d) \ + DEF_OPT("fleading-underscore", 0, OPT_fleading_underscore) \ + DEF_OPT("fno-leading-underscore", 0, OPT_fno_leading_underscore) \ + DEF_OPT("fno-operator-names", 0, OPT_fno_operator_names) \ + DEF_OPT("fno-preprocessed", 0, OPT_fno_preprocessed) \ + DEF_OPT("fno-show-column", 0, OPT_fno_show_column) \ + DEF_OPT("fpreprocessed", 0, OPT_fpreprocessed) \ + DEF_OPT("fshow-column", 0, OPT_fshow_column) \ + DEF_OPT("ftabstop=", no_num, OPT_ftabstop) \ + DEF_OPT("h", 0, OPT_h) \ + DEF_OPT("idirafter", no_dir, OPT_idirafter) \ + DEF_OPT("imacros", no_fil, OPT_imacros) \ + DEF_OPT("include", no_fil, OPT_include) \ + DEF_OPT("iprefix", no_pth, OPT_iprefix) \ + DEF_OPT("isystem", no_dir, OPT_isystem) \ + DEF_OPT("iwithprefix", no_dir, OPT_iwithprefix) \ + DEF_OPT("iwithprefixbefore", no_dir, OPT_iwithprefixbefore) \ + DEF_OPT("lang-asm", 0, OPT_lang_asm) \ + DEF_OPT("lang-c", 0, OPT_lang_c) \ + DEF_OPT("lang-c++", 0, OPT_lang_cplusplus) \ + DEF_OPT("lang-c89", 0, OPT_lang_c89) \ + DEF_OPT("lang-objc", 0, OPT_lang_objc) \ + DEF_OPT("lang-objc++", 0, OPT_lang_objcplusplus) \ + DEF_OPT("nostdinc", 0, OPT_nostdinc) \ + DEF_OPT("nostdinc++", 0, OPT_nostdincplusplus) \ + DEF_OPT("o", no_fil, OPT_o) \ + DEF_OPT("pedantic", 0, OPT_pedantic) \ + DEF_OPT("pedantic-errors", 0, OPT_pedantic_errors) \ + DEF_OPT("remap", 0, OPT_remap) \ + DEF_OPT("std=c++98", 0, OPT_std_cplusplus98) \ + DEF_OPT("std=c89", 0, OPT_std_c89) \ + DEF_OPT("std=c99", 0, OPT_std_c99) \ + DEF_OPT("std=c9x", 0, OPT_std_c9x) \ + DEF_OPT("std=gnu89", 0, OPT_std_gnu89) \ + DEF_OPT("std=gnu99", 0, OPT_std_gnu99) \ + DEF_OPT("std=gnu9x", 0, OPT_std_gnu9x) \ + DEF_OPT("std=iso9899:1990", 0, OPT_std_iso9899_1990) \ + DEF_OPT("std=iso9899:199409", 0, OPT_std_iso9899_199409) \ + DEF_OPT("std=iso9899:1999", 0, OPT_std_iso9899_1999) \ + DEF_OPT("std=iso9899:199x", 0, OPT_std_iso9899_199x) \ + DEF_OPT("trigraphs", 0, OPT_trigraphs) \ + DEF_OPT("v", 0, OPT_v) \ + DEF_OPT("version", 0, OPT_version) \ + DEF_OPT("w", 0, OPT_w) + +#define DEF_OPT(text, msg, code) code, +enum opt_code +{ + COMMAND_LINE_OPTIONS + N_OPTS +}; +#undef DEF_OPT + +struct cl_option +{ + const char *opt_text; + const char *msg; + size_t opt_len; + enum opt_code opt_code; +}; + +#define DEF_OPT(text, msg, code) { text, msg, sizeof(text) - 1, code }, +#ifdef HOST_EBCDIC +static struct cl_option cl_options[] = +#else +static const struct cl_option cl_options[] = +#endif +{ + COMMAND_LINE_OPTIONS +}; +#undef DEF_OPT +#undef COMMAND_LINE_OPTIONS + +/* Perform a binary search to find which, if any, option the given + command-line matches. Returns its index in the option array, + negative on failure. Complications arise since some options can be + suffixed with an argument, and multiple complete matches can occur, + e.g. -iwithprefix and -iwithprefixbefore. Moreover, we need to + accept options beginning with -W that we do not recognise, but not + to swallow any subsequent command line argument; this is handled as + special cases in cpp_handle_option. */ +static int +parse_option (input) + const char *input; +{ + unsigned int md, mn, mx; + size_t opt_len; + int comp; + + mn = 0; + mx = N_OPTS; + + while (mx > mn) + { + md = (mn + mx) / 2; + + opt_len = cl_options[md].opt_len; + comp = memcmp (input, cl_options[md].opt_text, opt_len); + + if (comp > 0) + mn = md + 1; + else if (comp < 0) + mx = md; + else + { + if (input[opt_len] == '\0') + return md; + /* We were passed more text. If the option takes an argument, + we may match a later option or we may have been passed the + argument. The longest possible option match succeeds. + If the option takes no arguments we have not matched and + continue the search (e.g. input="stdc++" match was "stdc"). */ + mn = md + 1; + if (cl_options[md].msg) + { + /* Scan forwards. If we get an exact match, return it. + Otherwise, return the longest option-accepting match. + This loops no more than twice with current options. */ + mx = md; + for (; mn < (unsigned int) N_OPTS; mn++) + { + opt_len = cl_options[mn].opt_len; + if (memcmp (input, cl_options[mn].opt_text, opt_len)) + break; + if (input[opt_len] == '\0') + return mn; + if (cl_options[mn].msg) + mx = mn; + } + return mx; + } + } + } + + return -1; +} + +/* Handle one command-line option in (argc, argv). + Can be called multiple times, to handle multiple sets of options. + Returns number of strings consumed. */ + +int +cpp_handle_option (pfile, argc, argv) + cpp_reader *pfile; + int argc; + char **argv; +{ + int i = 0; + struct cpp_pending *pend = CPP_OPTION (pfile, pending); + + /* Interpret "-" or a non-option as a file name. */ + if (argv[i][0] != '-' || argv[i][1] == '\0') + { + if (CPP_OPTION (pfile, in_fname) == NULL) + CPP_OPTION (pfile, in_fname) = argv[i]; + else if (CPP_OPTION (pfile, out_fname) == NULL) + CPP_OPTION (pfile, out_fname) = argv[i]; + else + cpp_fatal (pfile, "Too many filenames. Type %s --help for usage info", + progname); + } + else + { + enum opt_code opt_code; + int opt_index; + const char *arg = 0; + + /* Skip over '-'. */ + opt_index = parse_option (&argv[i][1]); + if (opt_index < 0) + return i; + + opt_code = cl_options[opt_index].opt_code; + if (cl_options[opt_index].msg) + { + arg = &argv[i][cl_options[opt_index].opt_len + 1]; + + /* Yuk. Special case for -W as it must not swallow + up any following argument. If this becomes common, add + another field to the cl_options table. */ + if (arg[0] == '\0' && opt_code != OPT_W) + { + arg = argv[++i]; + if (!arg) + { + cpp_fatal (pfile, cl_options[opt_index].msg, argv[i - 1]); + return argc; + } + } + } + + switch (opt_code) + { + case N_OPTS: /* Shut GCC up. */ + break; + case OPT_fleading_underscore: + CPP_OPTION (pfile, user_label_prefix) = "_"; + break; + case OPT_fno_leading_underscore: + CPP_OPTION (pfile, user_label_prefix) = ""; + break; + case OPT_fno_operator_names: + CPP_OPTION (pfile, operator_names) = 0; + break; + case OPT_fpreprocessed: + CPP_OPTION (pfile, preprocessed) = 1; + break; + case OPT_fno_preprocessed: + CPP_OPTION (pfile, preprocessed) = 0; + break; + case OPT_fshow_column: + CPP_OPTION (pfile, show_column) = 1; + break; + case OPT_fno_show_column: + CPP_OPTION (pfile, show_column) = 0; + break; + case OPT_ftabstop: + /* Silently ignore empty string, non-longs and silly values. */ + if (arg[0] != '\0') + { + char *endptr; + long tabstop = strtol (arg, &endptr, 10); + if (*endptr == '\0' && tabstop >= 1 && tabstop <= 100) + CPP_OPTION (pfile, tabstop) = tabstop; + } + break; + case OPT_w: + CPP_OPTION (pfile, inhibit_warnings) = 1; + break; + case OPT_h: + case OPT__help: + print_help (); + CPP_OPTION (pfile, help_only) = 1; + break; + case OPT_target__help: + /* Print if any target specific options. cpplib has none, but + make sure help_only gets set. */ + CPP_OPTION (pfile, help_only) = 1; + break; + + /* --version inhibits compilation, -version doesn't. -v means + verbose and -version. Historical reasons, don't ask. */ + case OPT__version: + CPP_OPTION (pfile, help_only) = 1; + pfile->print_version = 1; + break; + case OPT_v: + CPP_OPTION (pfile, verbose) = 1; + pfile->print_version = 1; + break; + case OPT_version: + pfile->print_version = 1; + break; + + case OPT_C: + CPP_OPTION (pfile, discard_comments) = 0; + break; + case OPT_P: + CPP_OPTION (pfile, no_line_commands) = 1; + break; + case OPT_dollar: /* Don't include $ in identifiers. */ + CPP_OPTION (pfile, dollars_in_ident) = 0; + break; + case OPT_H: + CPP_OPTION (pfile, print_include_names) = 1; + break; + case OPT_D: + new_pending_directive (pend, arg, cpp_define); + break; + case OPT_pedantic_errors: + CPP_OPTION (pfile, pedantic_errors) = 1; + /* fall through */ + case OPT_pedantic: + CPP_OPTION (pfile, pedantic) = 1; + break; + case OPT_trigraphs: + CPP_OPTION (pfile, trigraphs) = 1; + break; + case OPT_plus: + CPP_OPTION (pfile, cplusplus) = 1; + CPP_OPTION (pfile, cplusplus_comments) = 1; + break; + case OPT_remap: + CPP_OPTION (pfile, remap) = 1; + break; + case OPT_iprefix: + CPP_OPTION (pfile, include_prefix) = arg; + CPP_OPTION (pfile, include_prefix_len) = strlen (arg); + break; + case OPT_lang_c: + set_lang (pfile, CLK_GNUC89); + break; + case OPT_lang_cplusplus: + set_lang (pfile, CLK_GNUCXX); + break; + case OPT_lang_objc: + set_lang (pfile, CLK_OBJC); + break; + case OPT_lang_objcplusplus: + set_lang (pfile, CLK_OBJCXX); + break; + case OPT_lang_asm: + set_lang (pfile, CLK_ASM); + break; + case OPT_std_cplusplus98: + set_lang (pfile, CLK_CXX98); + break; + case OPT_std_gnu89: + set_lang (pfile, CLK_GNUC89); + break; + case OPT_std_gnu9x: + case OPT_std_gnu99: + set_lang (pfile, CLK_GNUC99); + break; + case OPT_std_iso9899_199409: + set_lang (pfile, CLK_STDC94); + break; + case OPT_std_iso9899_1990: + case OPT_std_c89: + case OPT_lang_c89: + set_lang (pfile, CLK_STDC89); + break; + case OPT_std_iso9899_199x: + case OPT_std_iso9899_1999: + case OPT_std_c9x: + case OPT_std_c99: + set_lang (pfile, CLK_STDC99); + break; + case OPT_nostdinc: + /* -nostdinc causes no default include directories. + You must specify all include-file directories with -I. */ + CPP_OPTION (pfile, no_standard_includes) = 1; + break; + case OPT_nostdincplusplus: + /* -nostdinc++ causes no default C++-specific include directories. */ + CPP_OPTION (pfile, no_standard_cplusplus_includes) = 1; + break; + case OPT_o: + if (CPP_OPTION (pfile, out_fname) == NULL) + CPP_OPTION (pfile, out_fname) = arg; + else + { + cpp_fatal (pfile, "Output filename specified twice"); + return argc; + } + break; + case OPT_d: + /* Args to -d specify what parts of macros to dump. + Silently ignore unrecognised options; they may + be aimed at the compiler proper. */ + { + char c; + + while ((c = *arg++) != '\0') + switch (c) + { + case 'M': + CPP_OPTION (pfile, dump_macros) = dump_only; + CPP_OPTION (pfile, no_output) = 1; + break; + case 'N': + CPP_OPTION (pfile, dump_macros) = dump_names; + break; + case 'D': + CPP_OPTION (pfile, dump_macros) = dump_definitions; + break; + case 'I': + CPP_OPTION (pfile, dump_includes) = 1; + break; + } + } + break; + + case OPT_MG: + CPP_OPTION (pfile, print_deps_missing_files) = 1; + break; + case OPT_M: + CPP_OPTION (pfile, print_deps) = 2; + break; + case OPT_MM: + CPP_OPTION (pfile, print_deps) = 1; + break; + case OPT_MF: + CPP_OPTION (pfile, deps_file) = arg; + break; + case OPT_MP: + CPP_OPTION (pfile, deps_phony_targets) = 1; + break; + case OPT_MQ: + case OPT_MT: + /* Add a target. -MQ quotes for Make. */ + deps_add_target (pfile->deps, arg, opt_code == OPT_MQ); + break; + + /* -MD and -MMD for cpp0 are deprecated and undocumented + (use -M or -MM with -MF instead), and probably should be + removed with the next major GCC version. For the moment + we allow these for the benefit of Automake 1.4, which + uses these when dependency tracking is enabled. Automake + 1.5 will fix this. */ + case OPT_MD: + CPP_OPTION (pfile, print_deps) = 2; + CPP_OPTION (pfile, deps_file) = arg; + break; + case OPT_MMD: + CPP_OPTION (pfile, print_deps) = 1; + CPP_OPTION (pfile, deps_file) = arg; + break; + + case OPT_A: + if (arg[0] == '-') + { + /* -A with an argument beginning with '-' acts as + #unassert on whatever immediately follows the '-'. + If "-" is the whole argument, we eliminate all + predefined macros and assertions, including those + that were specified earlier on the command line. + That way we can get rid of any that were passed + automatically in from GCC. */ + + if (arg[1] == '\0') + { + struct pending_option *o1, *o2; + + o1 = pend->directive_head; + while (o1) + { + o2 = o1->next; + free (o1); + o1 = o2; + } + pend->directive_head = NULL; + pend->directive_tail = NULL; + } + else + new_pending_directive (pend, arg + 1, cpp_unassert); + } + else + new_pending_directive (pend, arg, cpp_assert); + break; + case OPT_U: + new_pending_directive (pend, arg, cpp_undef); + break; + case OPT_I: /* Add directory to path for includes. */ + if (!strcmp (arg, "-")) + { + /* -I- means: + Use the preceding -I directories for #include "..." + but not #include <...>. + Don't search the directory of the present file + for #include "...". (Note that -I. -I- is not the same as + the default setup; -I. uses the compiler's working dir.) */ + if (! CPP_OPTION (pfile, ignore_srcdir)) + { + pend->quote_head = pend->brack_head; + pend->quote_tail = pend->brack_tail; + pend->brack_head = 0; + pend->brack_tail = 0; + CPP_OPTION (pfile, ignore_srcdir) = 1; + } + else + { + cpp_fatal (pfile, "-I- specified twice"); + return argc; + } + } + else + append_include_chain (pfile, xstrdup (arg), BRACKET, 0); + break; + case OPT_isystem: + /* Add directory to beginning of system include path, as a system + include directory. */ + append_include_chain (pfile, xstrdup (arg), SYSTEM, 0); + break; + case OPT_include: + { + struct pending_option *o = (struct pending_option *) + xmalloc (sizeof (struct pending_option)); + o->arg = arg; + + /* This list has to be built in reverse order so that + when cpp_start_read pushes all the -include files onto + the buffer stack, they will be scanned in forward order. */ + o->next = pend->include_head; + pend->include_head = o; + } + break; + case OPT_imacros: + { + struct pending_option *o = (struct pending_option *) + xmalloc (sizeof (struct pending_option)); + o->arg = arg; + o->next = NULL; + + APPEND (pend, imacros, o); + } + break; + case OPT_iwithprefix: + /* Add directory to end of path for includes, + with the default prefix at the front of its name. */ + /* fall through */ + case OPT_iwithprefixbefore: + /* Add directory to main path for includes, + with the default prefix at the front of its name. */ + { + char *fname; + int len; + + len = strlen (arg); + + if (CPP_OPTION (pfile, include_prefix) != 0) + { + size_t ipl = CPP_OPTION (pfile, include_prefix_len); + fname = xmalloc (ipl + len + 1); + memcpy (fname, CPP_OPTION (pfile, include_prefix), ipl); + memcpy (fname + ipl, arg, len + 1); + } + else if (cpp_GCC_INCLUDE_DIR_len) + { + fname = xmalloc (cpp_GCC_INCLUDE_DIR_len + len + 1); + memcpy (fname, cpp_GCC_INCLUDE_DIR, cpp_GCC_INCLUDE_DIR_len); + memcpy (fname + cpp_GCC_INCLUDE_DIR_len, arg, len + 1); + } + else + fname = xstrdup (arg); + + append_include_chain (pfile, fname, + opt_code == OPT_iwithprefix ? SYSTEM: BRACKET, 0); + } + break; + case OPT_idirafter: + /* Add directory to end of path for includes. */ + append_include_chain (pfile, xstrdup (arg), AFTER, 0); + break; + case OPT_W: + /* Silently ignore unrecognised options. */ + if (!strcmp (argv[i], "-Wall")) + { + CPP_OPTION (pfile, warn_trigraphs) = 1; + CPP_OPTION (pfile, warn_comments) = 1; + } + else if (!strcmp (argv[i], "-Wtraditional")) + CPP_OPTION (pfile, warn_traditional) = 1; + else if (!strcmp (argv[i], "-Wtrigraphs")) + CPP_OPTION (pfile, warn_trigraphs) = 1; + else if (!strcmp (argv[i], "-Wcomment")) + CPP_OPTION (pfile, warn_comments) = 1; + else if (!strcmp (argv[i], "-Wcomments")) + CPP_OPTION (pfile, warn_comments) = 1; + else if (!strcmp (argv[i], "-Wundef")) + CPP_OPTION (pfile, warn_undef) = 1; + else if (!strcmp (argv[i], "-Wimport")) + CPP_OPTION (pfile, warn_import) = 1; + else if (!strcmp (argv[i], "-Werror")) + CPP_OPTION (pfile, warnings_are_errors) = 1; + else if (!strcmp (argv[i], "-Wsystem-headers")) + CPP_OPTION (pfile, warn_system_headers) = 1; + else if (!strcmp (argv[i], "-Wno-traditional")) + CPP_OPTION (pfile, warn_traditional) = 0; + else if (!strcmp (argv[i], "-Wno-trigraphs")) + CPP_OPTION (pfile, warn_trigraphs) = 0; + else if (!strcmp (argv[i], "-Wno-comment")) + CPP_OPTION (pfile, warn_comments) = 0; + else if (!strcmp (argv[i], "-Wno-comments")) + CPP_OPTION (pfile, warn_comments) = 0; + else if (!strcmp (argv[i], "-Wno-undef")) + CPP_OPTION (pfile, warn_undef) = 0; + else if (!strcmp (argv[i], "-Wno-import")) + CPP_OPTION (pfile, warn_import) = 0; + else if (!strcmp (argv[i], "-Wno-error")) + CPP_OPTION (pfile, warnings_are_errors) = 0; + else if (!strcmp (argv[i], "-Wno-system-headers")) + CPP_OPTION (pfile, warn_system_headers) = 0; + break; + } + } + return i + 1; +} + +/* Handle command-line options in (argc, argv). + Can be called multiple times, to handle multiple sets of options. + Returns if an unrecognized option is seen. + Returns number of strings consumed. */ +int +cpp_handle_options (pfile, argc, argv) + cpp_reader *pfile; + int argc; + char **argv; +{ + int i; + int strings_processed; + + for (i = 0; i < argc; i += strings_processed) + { + strings_processed = cpp_handle_option (pfile, argc - i, argv + i); + if (strings_processed == 0) + break; + } + + return i; +} + +/* Extra processing when all options are parsed, after all calls to + cpp_handle_option[s]. Consistency checks etc. */ +void +cpp_post_options (pfile) + cpp_reader *pfile; +{ + if (pfile->print_version) + { + fprintf (stderr, _("GNU CPP version %s (cpplib)"), version_string); +#ifdef TARGET_VERSION + TARGET_VERSION; +#endif + fputc ('\n', stderr); + } + + /* Canonicalize in_fname and out_fname. We guarantee they are not + NULL, and that the empty string represents stdin / stdout. */ + if (CPP_OPTION (pfile, in_fname) == NULL + || !strcmp (CPP_OPTION (pfile, in_fname), "-")) + CPP_OPTION (pfile, in_fname) = ""; + + if (CPP_OPTION (pfile, out_fname) == NULL + || !strcmp (CPP_OPTION (pfile, out_fname), "-")) + CPP_OPTION (pfile, out_fname) = ""; + + /* -Wtraditional is not useful in C++ mode. */ + if (CPP_OPTION (pfile, cplusplus)) + CPP_OPTION (pfile, warn_traditional) = 0; + + /* Set this if it hasn't been set already. */ + if (CPP_OPTION (pfile, user_label_prefix) == NULL) + CPP_OPTION (pfile, user_label_prefix) = USER_LABEL_PREFIX; + + /* Permanently disable macro expansion if we are rescanning + preprocessed text. */ + if (CPP_OPTION (pfile, preprocessed)) + pfile->state.prevent_expansion = 1; + + /* We need to do this after option processing and before + cpp_start_read, as cppmain.c relies on the options->no_output to + set its callbacks correctly before calling cpp_start_read. */ + init_dependency_output (pfile); + + /* After checking the environment variables, check if -M or -MM has + not been specified, but other -M options have. */ + if (CPP_OPTION (pfile, print_deps) == 0 && + (CPP_OPTION (pfile, print_deps_missing_files) + || CPP_OPTION (pfile, deps_file) + || CPP_OPTION (pfile, deps_phony_targets))) + cpp_fatal (pfile, "you must additionally specify either -M or -MM"); +} + +/* Set up dependency-file output. */ +static void +init_dependency_output (pfile) + cpp_reader *pfile; +{ + char *spec, *s, *output_file; + + /* Either of two environment variables can specify output of deps. + Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET", + where OUTPUT_FILE is the file to write deps info to + and DEPS_TARGET is the target to mention in the deps. */ + + if (CPP_OPTION (pfile, print_deps) == 0) + { + spec = getenv ("DEPENDENCIES_OUTPUT"); + if (spec) + CPP_OPTION (pfile, print_deps) = 1; + else + { + spec = getenv ("SUNPRO_DEPENDENCIES"); + if (spec) + CPP_OPTION (pfile, print_deps) = 2; + else + return; + } + + /* Find the space before the DEPS_TARGET, if there is one. */ + s = strchr (spec, ' '); + if (s) + { + /* Let the caller perform MAKE quoting. */ + deps_add_target (pfile->deps, s + 1, 0); + output_file = (char *) xmalloc (s - spec + 1); + memcpy (output_file, spec, s - spec); + output_file[s - spec] = 0; + } + else + output_file = spec; + + /* Command line overrides environment variables. */ + if (CPP_OPTION (pfile, deps_file) == 0) + CPP_OPTION (pfile, deps_file) = output_file; + CPP_OPTION (pfile, print_deps_append) = 1; + } + + /* If dependencies go to standard output, or -MG is used, we should + suppress output. The user may be requesting other stuff to + stdout, with -dM, -v etc. We let them shoot themselves in the + foot. */ + if (CPP_OPTION (pfile, deps_file) == 0 + || CPP_OPTION (pfile, print_deps_missing_files)) + CPP_OPTION (pfile, no_output) = 1; +} + +static void +print_help () +{ + fprintf (stderr, _("Usage: %s [switches] input output\n"), progname); + /* To keep the lines from getting too long for some compilers, limit + to about 500 characters (6 lines) per chunk. */ + fputs (_("\ +Switches:\n\ + -include Include the contents of before other files\n\ + -imacros Accept definition of macros in \n\ + -iprefix Specify as a prefix for next two options\n\ + -iwithprefix Add to the end of the system include path\n\ + -iwithprefixbefore Add to the end of the main include path\n\ + -isystem Add to the start of the system include path\n\ +"), stdout); + fputs (_("\ + -idirafter Add to the end of the system include path\n\ + -I Add to the end of the main include path\n\ + -I- Fine-grained include path control; see info docs\n\ + -nostdinc Do not search system include directories\n\ + (dirs specified with -isystem will still be used)\n\ + -nostdinc++ Do not search system include directories for C++\n\ + -o Put output into \n\ +"), stdout); + fputs (_("\ + -pedantic Issue all warnings demanded by strict ISO C\n\ + -pedantic-errors Issue -pedantic warnings as errors instead\n\ + -trigraphs Support ISO C trigraphs\n\ + -lang-c Assume that the input sources are in C\n\ + -lang-c89 Assume that the input sources are in C89\n\ +"), stdout); + fputs (_("\ + -lang-c++ Assume that the input sources are in C++\n\ + -lang-objc Assume that the input sources are in ObjectiveC\n\ + -lang-objc++ Assume that the input sources are in ObjectiveC++\n\ + -lang-asm Assume that the input sources are in assembler\n\ +"), stdout); + fputs (_("\ + -std= Specify the conformance standard; one of:\n\ + gnu89, gnu99, c89, c99, iso9899:1990,\n\ + iso9899:199409, iso9899:1999\n\ + -+ Allow parsing of C++ style features\n\ + -w Inhibit warning messages\n\ + -Wtrigraphs Warn if trigraphs are encountered\n\ + -Wno-trigraphs Do not warn about trigraphs\n\ + -Wcomment{s} Warn if one comment starts inside another\n\ +"), stdout); + fputs (_("\ + -Wno-comment{s} Do not warn about comments\n\ + -Wtraditional Warn about features not present in traditional C\n\ + -Wno-traditional Do not warn about traditional C\n\ + -Wundef Warn if an undefined macro is used by #if\n\ + -Wno-undef Do not warn about testing undefined macros\n\ + -Wimport Warn about the use of the #import directive\n\ +"), stdout); + fputs (_("\ + -Wno-import Do not warn about the use of #import\n\ + -Werror Treat all warnings as errors\n\ + -Wno-error Do not treat warnings as errors\n\ + -Wsystem-headers Do not suppress warnings from system headers\n\ + -Wno-system-headers Suppress warnings from system headers\n\ + -Wall Enable all preprocessor warnings\n\ +"), stdout); + fputs (_("\ + -M Generate make dependencies\n\ + -MM As -M, but ignore system header files\n\ + -MF Write dependency output to the given file\n\ + -MG Treat missing header file as generated files\n\ +"), stdout); + fputs (_("\ + -MP Generate phony targets for all headers\n\ + -MQ Add a MAKE-quoted target\n\ + -MT Add an unquoted target\n\ +"), stdout); + fputs (_("\ + -D Define a with string '1' as its value\n\ + -D= Define a with as its value\n\ + -A () Assert the to \n\ + -A- () Disable the to \n\ + -U Undefine \n\ + -v Display the version number\n\ +"), stdout); + fputs (_("\ + -H Print the name of header files as they are used\n\ + -C Do not discard comments\n\ + -dM Display a list of macro definitions active at end\n\ + -dD Preserve macro definitions in output\n\ + -dN As -dD except that only the names are preserved\n\ + -dI Include #include directives in the output\n\ +"), stdout); + fputs (_("\ + -fpreprocessed Treat the input file as already preprocessed\n\ + -ftabstop= Distance between tab stops for column reporting\n\ + -P Do not generate #line directives\n\ + -$ Do not allow '$' in identifiers\n\ + -remap Remap file names when including files.\n\ + --version Display version information\n\ + -h or --help Display this information\n\ +"), stdout); +} diff --git a/support/cpp2/cpplex.c b/support/cpp2/cpplex.c new file mode 100644 index 00000000..74248272 --- /dev/null +++ b/support/cpp2/cpplex.c @@ -0,0 +1,2145 @@ +/* CPP Library - lexical analysis. + Copyright (C) 2000 Free Software Foundation, Inc. + Contributed by Per Bothner, 1994-95. + Based on CCCP program by Paul Rubin, June 1986 + Adapted to ANSI C, Richard Stallman, Jan 1987 + Broken out to separate file, Zack Weinberg, Mar 2000 + Single-pass line tokenization by Neil Booth, April 2000 + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This lexer works with a single pass of the file. Recently I + re-wrote it to minimize the places where we step backwards in the + input stream, to make future changes to support multi-byte + character sets fairly straight-forward. + + There is now only one routine where we do step backwards: + skip_escaped_newlines. This routine could probably also be changed + so that it doesn't need to step back. One possibility is to use a + trick similar to that used in lex_period and lex_percent. Two + extra characters might be needed, but skip_escaped_newlines itself + would probably be the only place that needs to be aware of that, + and changes to the remaining routines would probably only be needed + if they process a backslash. */ + +#include "config.h" +#include "system.h" +#include "cpplib.h" +#include "cpphash.h" + +/* MULTIBYTE_CHARS support only works for native compilers. + ??? Ideally what we want is to model widechar support after + the current floating point support. */ +#ifdef CROSS_COMPILE +#undef MULTIBYTE_CHARS +#endif + +#ifdef MULTIBYTE_CHARS +#include "mbchar.h" +#include +#endif + +/* Tokens with SPELL_STRING store their spelling in the token list, + and it's length in the token->val.name.len. */ +enum spell_type +{ + SPELL_OPERATOR = 0, + SPELL_CHAR, + SPELL_IDENT, + SPELL_STRING, + SPELL_NONE +}; + +struct token_spelling +{ + enum spell_type category; + const unsigned char *name; +}; + +const unsigned char *digraph_spellings [] = {U"%:", U"%:%:", U"<:", + U":>", U"<%", U"%>"}; + +#define OP(e, s) { SPELL_OPERATOR, U s }, +#define TK(e, s) { s, U STRINGX (e) }, +const struct token_spelling token_spellings [N_TTYPES] = {TTYPE_TABLE }; +#undef OP +#undef TK + +#define TOKEN_SPELL(token) (token_spellings[(token)->type].category) +#define TOKEN_NAME(token) (token_spellings[(token)->type].name) + +static cppchar_t handle_newline PARAMS ((cpp_buffer *, cppchar_t)); +static cppchar_t skip_escaped_newlines PARAMS ((cpp_buffer *, cppchar_t)); +static cppchar_t get_effective_char PARAMS ((cpp_buffer *)); + +static int skip_block_comment PARAMS ((cpp_reader *)); +static int skip_line_comment PARAMS ((cpp_reader *)); +static void adjust_column PARAMS ((cpp_reader *)); +static void skip_whitespace PARAMS ((cpp_reader *, cppchar_t)); +static cpp_hashnode *parse_identifier PARAMS ((cpp_reader *, cppchar_t)); +static void parse_number PARAMS ((cpp_reader *, cpp_string *, cppchar_t, int)); +static int unescaped_terminator_p PARAMS ((cpp_reader *, const U_CHAR *)); +static void parse_string PARAMS ((cpp_reader *, cpp_token *, cppchar_t)); +static void unterminated PARAMS ((cpp_reader *, int)); +static int trigraph_ok PARAMS ((cpp_reader *, cppchar_t)); +static void save_comment PARAMS ((cpp_reader *, cpp_token *, const U_CHAR *)); +static void lex_percent PARAMS ((cpp_buffer *, cpp_token *)); +static void lex_dot PARAMS ((cpp_reader *, cpp_token *)); +static int name_p PARAMS ((cpp_reader *, const cpp_string *)); +static int maybe_read_ucs PARAMS ((cpp_reader *, const unsigned char **, + const unsigned char *, unsigned int *)); + +static cpp_chunk *new_chunk PARAMS ((unsigned int)); +static int chunk_suitable PARAMS ((cpp_pool *, cpp_chunk *, unsigned int)); +static unsigned int hex_digit_value PARAMS ((unsigned int)); + +/* Utility routine: + + Compares, the token TOKEN to the NUL-terminated string STRING. + TOKEN must be a CPP_NAME. Returns 1 for equal, 0 for unequal. */ + +int +cpp_ideq (token, string) + const cpp_token *token; + const char *string; +{ + if (token->type != CPP_NAME) + return 0; + + return !ustrcmp (NODE_NAME (token->val.node), (const U_CHAR *) string); +} + +/* Call when meeting a newline. Returns the character after the newline + (or carriage-return newline combination), or EOF. */ +static cppchar_t +handle_newline (buffer, newline_char) + cpp_buffer *buffer; + cppchar_t newline_char; +{ + cppchar_t next = EOF; + + buffer->col_adjust = 0; + buffer->lineno++; + buffer->line_base = buffer->cur; + + /* Handle CR-LF and LF-CR combinations, get the next character. */ + if (buffer->cur < buffer->rlimit) + { + next = *buffer->cur++; + if (next + newline_char == '\r' + '\n') + { + buffer->line_base = buffer->cur; + if (buffer->cur < buffer->rlimit) + next = *buffer->cur++; + else + next = EOF; + } + } + + buffer->read_ahead = next; + return next; +} + +/* Subroutine of skip_escaped_newlines; called when a trigraph is + encountered. It warns if necessary, and returns true if the + trigraph should be honoured. FROM_CHAR is the third character of a + trigraph, and presumed to be the previous character for position + reporting. */ +static int +trigraph_ok (pfile, from_char) + cpp_reader *pfile; + cppchar_t from_char; +{ + int accept = CPP_OPTION (pfile, trigraphs); + + /* Don't warn about trigraphs in comments. */ + if (CPP_OPTION (pfile, warn_trigraphs) && !pfile->state.lexing_comment) + { + cpp_buffer *buffer = pfile->buffer; + if (accept) + cpp_warning_with_line (pfile, buffer->lineno, CPP_BUF_COL (buffer) - 2, + "trigraph ??%c converted to %c", + (int) from_char, + (int) _cpp_trigraph_map[from_char]); + else if (buffer->cur != buffer->last_Wtrigraphs) + { + buffer->last_Wtrigraphs = buffer->cur; + cpp_warning_with_line (pfile, buffer->lineno, + CPP_BUF_COL (buffer) - 2, + "trigraph ??%c ignored", (int) from_char); + } + } + + return accept; +} + +/* Assumes local variables buffer and result. */ +#define ACCEPT_CHAR(t) \ + do { result->type = t; buffer->read_ahead = EOF; } while (0) + +/* When we move to multibyte character sets, add to these something + that saves and restores the state of the multibyte conversion + library. This probably involves saving and restoring a "cookie". + In the case of glibc it is an 8-byte structure, so is not a high + overhead operation. In any case, it's out of the fast path. */ +#define SAVE_STATE() do { saved_cur = buffer->cur; } while (0) +#define RESTORE_STATE() do { buffer->cur = saved_cur; } while (0) + +/* Skips any escaped newlines introduced by NEXT, which is either a + '?' or a '\\'. Returns the next character, which will also have + been placed in buffer->read_ahead. This routine performs + preprocessing stages 1 and 2 of the ISO C standard. */ +static cppchar_t +skip_escaped_newlines (buffer, next) + cpp_buffer *buffer; + cppchar_t next; +{ + /* Only do this if we apply stages 1 and 2. */ + if (!buffer->from_stage3) + { + cppchar_t next1; + const unsigned char *saved_cur; + int space; + + do + { + if (buffer->cur == buffer->rlimit) + break; + + SAVE_STATE (); + if (next == '?') + { + next1 = *buffer->cur++; + if (next1 != '?' || buffer->cur == buffer->rlimit) + { + RESTORE_STATE (); + break; + } + + next1 = *buffer->cur++; + if (!_cpp_trigraph_map[next1] + || !trigraph_ok (buffer->pfile, next1)) + { + RESTORE_STATE (); + break; + } + + /* We have a full trigraph here. */ + next = _cpp_trigraph_map[next1]; + if (next != '\\' || buffer->cur == buffer->rlimit) + break; + SAVE_STATE (); + } + + /* We have a backslash, and room for at least one more character. */ + space = 0; + do + { + next1 = *buffer->cur++; + if (!is_nvspace (next1)) + break; + space = 1; + } + while (buffer->cur < buffer->rlimit); + + if (!is_vspace (next1)) + { + RESTORE_STATE (); + break; + } + + if (space && !buffer->pfile->state.lexing_comment) + cpp_warning (buffer->pfile, + "backslash and newline separated by space"); + + next = handle_newline (buffer, next1); + if (next == EOF) + cpp_pedwarn (buffer->pfile, "backslash-newline at end of file"); + } + while (next == '\\' || next == '?'); + } + + buffer->read_ahead = next; + return next; +} + +/* Obtain the next character, after trigraph conversion and skipping + an arbitrary string of escaped newlines. The common case of no + trigraphs or escaped newlines falls through quickly. */ +static cppchar_t +get_effective_char (buffer) + cpp_buffer *buffer; +{ + cppchar_t next = EOF; + + if (buffer->cur < buffer->rlimit) + { + next = *buffer->cur++; + + /* '?' can introduce trigraphs (and therefore backslash); '\\' + can introduce escaped newlines, which we want to skip, or + UCNs, which, depending upon lexer state, we will handle in + the future. */ + if (next == '?' || next == '\\') + next = skip_escaped_newlines (buffer, next); + } + + buffer->read_ahead = next; + return next; +} + +/* Skip a C-style block comment. We find the end of the comment by + seeing if an asterisk is before every '/' we encounter. Returns + non-zero if comment terminated by EOF, zero otherwise. */ +static int +skip_block_comment (pfile) + cpp_reader *pfile; +{ + cpp_buffer *buffer = pfile->buffer; + cppchar_t c = EOF, prevc = EOF; + + pfile->state.lexing_comment = 1; + while (buffer->cur != buffer->rlimit) + { + prevc = c, c = *buffer->cur++; + + next_char: + /* FIXME: For speed, create a new character class of characters + of interest inside block comments. */ + if (c == '?' || c == '\\') + c = skip_escaped_newlines (buffer, c); + + /* People like decorating comments with '*', so check for '/' + instead for efficiency. */ + if (c == '/') + { + if (prevc == '*') + break; + + /* Warn about potential nested comments, but not if the '/' + comes immediately before the true comment delimeter. + Don't bother to get it right across escaped newlines. */ + if (CPP_OPTION (pfile, warn_comments) + && buffer->cur != buffer->rlimit) + { + prevc = c, c = *buffer->cur++; + if (c == '*' && buffer->cur != buffer->rlimit) + { + prevc = c, c = *buffer->cur++; + if (c != '/') + cpp_warning_with_line (pfile, CPP_BUF_LINE (buffer), + CPP_BUF_COL (buffer), + "\"/*\" within comment"); + } + goto next_char; + } + } + else if (is_vspace (c)) + { + prevc = c, c = handle_newline (buffer, c); + goto next_char; + } + else if (c == '\t') + adjust_column (pfile); + } + + pfile->state.lexing_comment = 0; + buffer->read_ahead = EOF; + return c != '/' || prevc != '*'; +} + +/* Skip a C++ line comment. Handles escaped newlines. Returns + non-zero if a multiline comment. The following new line, if any, + is left in buffer->read_ahead. */ +static int +skip_line_comment (pfile) + cpp_reader *pfile; +{ + cpp_buffer *buffer = pfile->buffer; + unsigned int orig_lineno = buffer->lineno; + cppchar_t c; + + pfile->state.lexing_comment = 1; + do + { + c = EOF; + if (buffer->cur == buffer->rlimit) + break; + + c = *buffer->cur++; + if (c == '?' || c == '\\') + c = skip_escaped_newlines (buffer, c); + } + while (!is_vspace (c)); + + pfile->state.lexing_comment = 0; + buffer->read_ahead = c; /* Leave any newline for caller. */ + return orig_lineno != buffer->lineno; +} + +/* pfile->buffer->cur is one beyond the \t character. Update + col_adjust so we track the column correctly. */ +static void +adjust_column (pfile) + cpp_reader *pfile; +{ + cpp_buffer *buffer = pfile->buffer; + unsigned int col = CPP_BUF_COL (buffer) - 1; /* Zero-based column. */ + + /* Round it up to multiple of the tabstop, but subtract 1 since the + tab itself occupies a character position. */ + buffer->col_adjust += (CPP_OPTION (pfile, tabstop) + - col % CPP_OPTION (pfile, tabstop)) - 1; +} + +/* Skips whitespace, saving the next non-whitespace character. + Adjusts pfile->col_adjust to account for tabs. Without this, + tokens might be assigned an incorrect column. */ +static void +skip_whitespace (pfile, c) + cpp_reader *pfile; + cppchar_t c; +{ + cpp_buffer *buffer = pfile->buffer; + unsigned int warned = 0; + + do + { + /* Horizontal space always OK. */ + if (c == ' ') + ; + else if (c == '\t') + adjust_column (pfile); + /* Just \f \v or \0 left. */ + else if (c == '\0') + { + if (!warned) + { + cpp_warning (pfile, "null character(s) ignored"); + warned = 1; + } + } + else if (pfile->state.in_directive && CPP_PEDANTIC (pfile)) + cpp_pedwarn_with_line (pfile, CPP_BUF_LINE (buffer), + CPP_BUF_COL (buffer), + "%s in preprocessing directive", + c == '\f' ? "form feed" : "vertical tab"); + + c = EOF; + if (buffer->cur == buffer->rlimit) + break; + c = *buffer->cur++; + } + /* We only want non-vertical space, i.e. ' ' \t \f \v \0. */ + while (is_nvspace (c)); + + /* Remember the next character. */ + buffer->read_ahead = c; +} + +/* See if the characters of a number token are valid in a name (no + '.', '+' or '-'). */ +static int +name_p (pfile, string) + cpp_reader *pfile; + const cpp_string *string; +{ + unsigned int i; + + for (i = 0; i < string->len; i++) + if (!is_idchar (string->text[i])) + return 0; + + return 1; +} + +/* Parse an identifier, skipping embedded backslash-newlines. + Calculate the hash value of the token while parsing, for improved + performance. The hashing algorithm *must* match cpp_lookup(). */ + +static cpp_hashnode * +parse_identifier (pfile, c) + cpp_reader *pfile; + cppchar_t c; +{ + cpp_hashnode *result; + cpp_buffer *buffer = pfile->buffer; + unsigned int saw_dollar = 0, len; + struct obstack *stack = &pfile->hash_table->stack; + + do + { + do + { + obstack_1grow (stack, c); + + if (c == '$') + saw_dollar++; + + c = EOF; + if (buffer->cur == buffer->rlimit) + break; + + c = *buffer->cur++; + } + while (is_idchar (c)); + + /* Potential escaped newline? */ + if (c != '?' && c != '\\') + break; + c = skip_escaped_newlines (buffer, c); + } + while (is_idchar (c)); + + /* Remember the next character. */ + buffer->read_ahead = c; + + /* $ is not a identifier character in the standard, but is commonly + accepted as an extension. Don't warn about it in skipped + conditional blocks. */ + if (saw_dollar && CPP_PEDANTIC (pfile) && ! pfile->skipping) + cpp_pedwarn (pfile, "'$' character(s) in identifier"); + + /* Identifiers are null-terminated. */ + len = obstack_object_size (stack); + obstack_1grow (stack, '\0'); + + /* This routine commits the memory if necessary. */ + result = (cpp_hashnode *) + ht_lookup (pfile->hash_table, obstack_finish (stack), len, HT_ALLOCED); + + /* Some identifiers require diagnostics when lexed. */ + if (result->flags & NODE_DIAGNOSTIC && !pfile->skipping) + { + /* It is allowed to poison the same identifier twice. */ + if ((result->flags & NODE_POISONED) && !pfile->state.poisoned_ok) + cpp_error (pfile, "attempt to use poisoned \"%s\"", + NODE_NAME (result)); + + /* Constraint 6.10.3.5: __VA_ARGS__ should only appear in the + replacement list of a variadic macro. */ + if (result == pfile->spec_nodes.n__VA_ARGS__ + && !pfile->state.va_args_ok) + cpp_pedwarn (pfile, "__VA_ARGS__ can only appear in the expansion of a C99 variadic macro"); + } + + return result; +} + +/* Parse a number, skipping embedded backslash-newlines. */ +static void +parse_number (pfile, number, c, leading_period) + cpp_reader *pfile; + cpp_string *number; + cppchar_t c; + int leading_period; +{ + cpp_buffer *buffer = pfile->buffer; + cpp_pool *pool = &pfile->ident_pool; + unsigned char *dest, *limit; + + dest = POOL_FRONT (pool); + limit = POOL_LIMIT (pool); + + /* Place a leading period. */ + if (leading_period) + { + if (dest >= limit) + limit = _cpp_next_chunk (pool, 0, &dest); + *dest++ = '.'; + } + + do + { + do + { + /* Need room for terminating null. */ + if (dest + 1 >= limit) + limit = _cpp_next_chunk (pool, 0, &dest); + *dest++ = c; + + c = EOF; + if (buffer->cur == buffer->rlimit) + break; + + c = *buffer->cur++; + } + while (is_numchar (c) || c == '.' || VALID_SIGN (c, dest[-1])); + + /* Potential escaped newline? */ + if (c != '?' && c != '\\') + break; + c = skip_escaped_newlines (buffer, c); + } + while (is_numchar (c) || c == '.' || VALID_SIGN (c, dest[-1])); + + /* Remember the next character. */ + buffer->read_ahead = c; + + /* Null-terminate the number. */ + *dest = '\0'; + + number->text = POOL_FRONT (pool); + number->len = dest - number->text; + POOL_COMMIT (pool, number->len + 1); +} + +/* Subroutine of parse_string. Emits error for unterminated strings. */ +static void +unterminated (pfile, term) + cpp_reader *pfile; + int term; +{ + cpp_error (pfile, "missing terminating %c character", term); + + if (term == '\"' && pfile->mlstring_pos.line + && pfile->mlstring_pos.line != pfile->lexer_pos.line) + { + cpp_error_with_line (pfile, pfile->mlstring_pos.line, + pfile->mlstring_pos.col, + "possible start of unterminated string literal"); + pfile->mlstring_pos.line = 0; + } +} + +/* Subroutine of parse_string. */ +static int +unescaped_terminator_p (pfile, dest) + cpp_reader *pfile; + const unsigned char *dest; +{ + const unsigned char *start, *temp; + + /* In #include-style directives, terminators are not escapeable. */ + if (pfile->state.angled_headers) + return 1; + + start = POOL_FRONT (&pfile->ident_pool); + + /* An odd number of consecutive backslashes represents an escaped + terminator. */ + for (temp = dest; temp > start && temp[-1] == '\\'; temp--) + ; + + return ((dest - temp) & 1) == 0; +} + +/* Parses a string, character constant, or angle-bracketed header file + name. Handles embedded trigraphs and escaped newlines. The stored + string is guaranteed NUL-terminated, but it is not guaranteed that + this is the first NUL since embedded NULs are preserved. + + Multi-line strings are allowed, but they are deprecated. */ +static void +parse_string (pfile, token, terminator) + cpp_reader *pfile; + cpp_token *token; + cppchar_t terminator; +{ + cpp_buffer *buffer = pfile->buffer; + cpp_pool *pool = &pfile->ident_pool; + unsigned char *dest, *limit; + cppchar_t c; + unsigned int nulls = 0; + + dest = POOL_FRONT (pool); + limit = POOL_LIMIT (pool); + + for (;;) + { + if (buffer->cur == buffer->rlimit) + c = EOF; + else + c = *buffer->cur++; + + have_char: + /* We need space for the terminating NUL. */ + if (dest >= limit) + limit = _cpp_next_chunk (pool, 0, &dest); + + if (c == EOF) + { + unterminated (pfile, terminator); + break; + } + + /* Handle trigraphs, escaped newlines etc. */ + if (c == '?' || c == '\\') + c = skip_escaped_newlines (buffer, c); + + if (c == terminator && unescaped_terminator_p (pfile, dest)) + { + c = EOF; + break; + } + else if (is_vspace (c)) + { + /* In assembly language, silently terminate string and + character literals at end of line. This is a kludge + around not knowing where comments are. */ + if (CPP_OPTION (pfile, lang) == CLK_ASM && terminator != '>') + break; + + /* Character constants and header names may not extend over + multiple lines. In Standard C, neither may strings. + Unfortunately, we accept multiline strings as an + extension, except in #include family directives. */ + if (terminator != '"' || pfile->state.angled_headers) + { + unterminated (pfile, terminator); + break; + } + + cpp_pedwarn (pfile, "multi-line string literals are deprecated"); + if (pfile->mlstring_pos.line == 0) + pfile->mlstring_pos = pfile->lexer_pos; + + c = handle_newline (buffer, c); + *dest++ = '\n'; + goto have_char; + } + else if (c == '\0') + { + if (nulls++ == 0) + cpp_warning (pfile, "null character(s) preserved in literal"); + } + + *dest++ = c; + } + + /* Remember the next character. */ + buffer->read_ahead = c; + *dest = '\0'; + + token->val.str.text = POOL_FRONT (pool); + token->val.str.len = dest - token->val.str.text; + POOL_COMMIT (pool, token->val.str.len + 1); +} + +/* The stored comment includes the comment start and any terminator. */ +static void +save_comment (pfile, token, from) + cpp_reader *pfile; + cpp_token *token; + const unsigned char *from; +{ + unsigned char *buffer; + unsigned int len; + + len = pfile->buffer->cur - from + 1; /* + 1 for the initial '/'. */ + /* C++ comments probably (not definitely) have moved past a new + line, which we don't want to save in the comment. */ + if (pfile->buffer->read_ahead != EOF) + len--; + buffer = _cpp_pool_alloc (&pfile->ident_pool, len); + + token->type = CPP_COMMENT; + token->val.str.len = len; + token->val.str.text = buffer; + + buffer[0] = '/'; + memcpy (buffer + 1, from, len - 1); +} + +/* Subroutine of lex_token to handle '%'. A little tricky, since we + want to avoid stepping back when lexing %:%X. */ +static void +lex_percent (buffer, result) + cpp_buffer *buffer; + cpp_token *result; +{ + cppchar_t c; + + result->type = CPP_MOD; + /* Parsing %:%X could leave an extra character. */ + if (buffer->extra_char == EOF) + c = get_effective_char (buffer); + else + { + c = buffer->read_ahead = buffer->extra_char; + buffer->extra_char = EOF; + } + + if (c == '=') + ACCEPT_CHAR (CPP_MOD_EQ); + else if (CPP_OPTION (buffer->pfile, digraphs)) + { + if (c == ':') + { + result->flags |= DIGRAPH; + ACCEPT_CHAR (CPP_HASH); + if (get_effective_char (buffer) == '%') + { + buffer->extra_char = get_effective_char (buffer); + if (buffer->extra_char == ':') + { + buffer->extra_char = EOF; + ACCEPT_CHAR (CPP_PASTE); + } + else + /* We'll catch the extra_char when we're called back. */ + buffer->read_ahead = '%'; + } + } + else if (c == '>') + { + result->flags |= DIGRAPH; + ACCEPT_CHAR (CPP_CLOSE_BRACE); + } + } +} + +/* Subroutine of lex_token to handle '.'. This is tricky, since we + want to avoid stepping back when lexing '...' or '.123'. In the + latter case we should also set a flag for parse_number. */ +static void +lex_dot (pfile, result) + cpp_reader *pfile; + cpp_token *result; +{ + cpp_buffer *buffer = pfile->buffer; + cppchar_t c; + + /* Parsing ..X could leave an extra character. */ + if (buffer->extra_char == EOF) + c = get_effective_char (buffer); + else + { + c = buffer->read_ahead = buffer->extra_char; + buffer->extra_char = EOF; + } + + /* All known character sets have 0...9 contiguous. */ + if (c >= '0' && c <= '9') + { + result->type = CPP_NUMBER; + parse_number (pfile, &result->val.str, c, 1); + } + else + { + result->type = CPP_DOT; + if (c == '.') + { + buffer->extra_char = get_effective_char (buffer); + if (buffer->extra_char == '.') + { + buffer->extra_char = EOF; + ACCEPT_CHAR (CPP_ELLIPSIS); + } + else + /* We'll catch the extra_char when we're called back. */ + buffer->read_ahead = '.'; + } + else if (c == '*' && CPP_OPTION (pfile, cplusplus)) + ACCEPT_CHAR (CPP_DOT_STAR); + } +} + +void +_cpp_lex_token (pfile, result) + cpp_reader *pfile; + cpp_token *result; +{ + cppchar_t c; + cpp_buffer *buffer; + const unsigned char *comment_start; + unsigned char bol; + + skip: + bol = pfile->state.next_bol; + done_directive: + buffer = pfile->buffer; + pfile->state.next_bol = 0; + result->flags = buffer->saved_flags; + buffer->saved_flags = 0; + next_char: + pfile->lexer_pos.line = buffer->lineno; + next_char2: + pfile->lexer_pos.col = CPP_BUF_COLUMN (buffer, buffer->cur); + + c = buffer->read_ahead; + if (c == EOF && buffer->cur < buffer->rlimit) + { + c = *buffer->cur++; + pfile->lexer_pos.col++; + } + + do_switch: + buffer->read_ahead = EOF; + switch (c) + { + case EOF: + /* Non-empty files should end in a newline. Checking "bol" too + prevents multiple warnings when hitting the EOF more than + once, like in a directive. Don't warn for command line and + _Pragma buffers. */ + if (pfile->lexer_pos.col != 0 && !bol && !buffer->from_stage3) + cpp_pedwarn (pfile, "no newline at end of file"); + pfile->state.next_bol = 1; + pfile->skipping = 0; /* In case missing #endif. */ + result->type = CPP_EOF; + /* Don't do MI optimisation. */ + return; + + case ' ': case '\t': case '\f': case '\v': case '\0': + skip_whitespace (pfile, c); + result->flags |= PREV_WHITE; + goto next_char2; + + case '\n': case '\r': + if (!pfile->state.in_directive) + { + handle_newline (buffer, c); + bol = 1; + pfile->lexer_pos.output_line = buffer->lineno; + /* This is a new line, so clear any white space flag. + Newlines in arguments are white space (6.10.3.10); + parse_arg takes care of that. */ + result->flags &= ~(PREV_WHITE | AVOID_LPASTE); + goto next_char; + } + + /* Don't let directives spill over to the next line. */ + buffer->read_ahead = c; + pfile->state.next_bol = 1; + result->type = CPP_EOF; + /* Don't break; pfile->skipping might be true. */ + return; + + case '?': + case '\\': + /* These could start an escaped newline, or '?' a trigraph. Let + skip_escaped_newlines do all the work. */ + { + unsigned int lineno = buffer->lineno; + + c = skip_escaped_newlines (buffer, c); + if (lineno != buffer->lineno) + /* We had at least one escaped newline of some sort, and the + next character is in buffer->read_ahead. Update the + token's line and column. */ + goto next_char; + + /* We are either the original '?' or '\\', or a trigraph. */ + result->type = CPP_QUERY; + buffer->read_ahead = EOF; + if (c == '\\') + goto random_char; + else if (c != '?') + goto do_switch; + } + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + result->type = CPP_NUMBER; + parse_number (pfile, &result->val.str, c, 0); + break; + + case '$': + if (!CPP_OPTION (pfile, dollars_in_ident)) + goto random_char; + /* Fall through... */ + + case '_': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + result->type = CPP_NAME; + result->val.node = parse_identifier (pfile, c); + + /* 'L' may introduce wide characters or strings. */ + if (result->val.node == pfile->spec_nodes.n_L) + { + c = buffer->read_ahead; /* For make_string. */ + if (c == '\'' || c == '"') + { + ACCEPT_CHAR (c == '"' ? CPP_WSTRING: CPP_WCHAR); + goto make_string; + } + } + /* Convert named operators to their proper types. */ + else if (result->val.node->flags & NODE_OPERATOR) + { + result->flags |= NAMED_OP; + result->type = result->val.node->value.operator; + } + break; + + case '\'': + case '"': + result->type = c == '"' ? CPP_STRING: CPP_CHAR; + make_string: + parse_string (pfile, result, c); + break; + + case '/': + /* A potential block or line comment. */ + comment_start = buffer->cur; + result->type = CPP_DIV; + c = get_effective_char (buffer); + if (c == '=') + ACCEPT_CHAR (CPP_DIV_EQ); + if (c != '/' && c != '*') + break; + + if (c == '*') + { + if (skip_block_comment (pfile)) + cpp_error_with_line (pfile, pfile->lexer_pos.line, + pfile->lexer_pos.col, + "unterminated comment"); + } + else + { + if (!CPP_OPTION (pfile, cplusplus_comments) + && !CPP_IN_SYSTEM_HEADER (pfile)) + break; + + /* Warn about comments only if pedantically GNUC89, and not + in system headers. */ + if (CPP_OPTION (pfile, lang) == CLK_GNUC89 && CPP_PEDANTIC (pfile) + && ! buffer->warned_cplusplus_comments) + { + cpp_pedwarn (pfile, + "C++ style comments are not allowed in ISO C89"); + cpp_pedwarn (pfile, + "(this will be reported only once per input file)"); + buffer->warned_cplusplus_comments = 1; + } + + /* Skip_line_comment updates buffer->read_ahead. */ + if (skip_line_comment (pfile) && CPP_OPTION (pfile, warn_comments)) + cpp_warning_with_line (pfile, pfile->lexer_pos.line, + pfile->lexer_pos.col, + "multi-line comment"); + } + + /* Skipping the comment has updated buffer->read_ahead. */ + if (!pfile->state.save_comments) + { + result->flags |= PREV_WHITE; + goto next_char; + } + + /* Save the comment as a token in its own right. */ + save_comment (pfile, result, comment_start); + /* Don't do MI optimisation. */ + return; + + case '<': + if (pfile->state.angled_headers) + { + result->type = CPP_HEADER_NAME; + c = '>'; /* terminator. */ + goto make_string; + } + + result->type = CPP_LESS; + c = get_effective_char (buffer); + if (c == '=') + ACCEPT_CHAR (CPP_LESS_EQ); + else if (c == '<') + { + ACCEPT_CHAR (CPP_LSHIFT); + if (get_effective_char (buffer) == '=') + ACCEPT_CHAR (CPP_LSHIFT_EQ); + } + else if (c == '?' && CPP_OPTION (pfile, cplusplus)) + { + ACCEPT_CHAR (CPP_MIN); + if (get_effective_char (buffer) == '=') + ACCEPT_CHAR (CPP_MIN_EQ); + } + else if (c == ':' && CPP_OPTION (pfile, digraphs)) + { + ACCEPT_CHAR (CPP_OPEN_SQUARE); + result->flags |= DIGRAPH; + } + else if (c == '%' && CPP_OPTION (pfile, digraphs)) + { + ACCEPT_CHAR (CPP_OPEN_BRACE); + result->flags |= DIGRAPH; + } + break; + + case '>': + result->type = CPP_GREATER; + c = get_effective_char (buffer); + if (c == '=') + ACCEPT_CHAR (CPP_GREATER_EQ); + else if (c == '>') + { + ACCEPT_CHAR (CPP_RSHIFT); + if (get_effective_char (buffer) == '=') + ACCEPT_CHAR (CPP_RSHIFT_EQ); + } + else if (c == '?' && CPP_OPTION (pfile, cplusplus)) + { + ACCEPT_CHAR (CPP_MAX); + if (get_effective_char (buffer) == '=') + ACCEPT_CHAR (CPP_MAX_EQ); + } + break; + + case '%': + lex_percent (buffer, result); + if (result->type == CPP_HASH) + goto do_hash; + break; + + case '.': + lex_dot (pfile, result); + break; + + case '+': + result->type = CPP_PLUS; + c = get_effective_char (buffer); + if (c == '=') + ACCEPT_CHAR (CPP_PLUS_EQ); + else if (c == '+') + ACCEPT_CHAR (CPP_PLUS_PLUS); + break; + + case '-': + result->type = CPP_MINUS; + c = get_effective_char (buffer); + if (c == '>') + { + ACCEPT_CHAR (CPP_DEREF); + if (CPP_OPTION (pfile, cplusplus) + && get_effective_char (buffer) == '*') + ACCEPT_CHAR (CPP_DEREF_STAR); + } + else if (c == '=') + ACCEPT_CHAR (CPP_MINUS_EQ); + else if (c == '-') + ACCEPT_CHAR (CPP_MINUS_MINUS); + break; + + case '*': + result->type = CPP_MULT; + if (get_effective_char (buffer) == '=') + ACCEPT_CHAR (CPP_MULT_EQ); + break; + + case '=': + result->type = CPP_EQ; + if (get_effective_char (buffer) == '=') + ACCEPT_CHAR (CPP_EQ_EQ); + break; + + case '!': + result->type = CPP_NOT; + if (get_effective_char (buffer) == '=') + ACCEPT_CHAR (CPP_NOT_EQ); + break; + + case '&': + result->type = CPP_AND; + c = get_effective_char (buffer); + if (c == '=') + ACCEPT_CHAR (CPP_AND_EQ); + else if (c == '&') + ACCEPT_CHAR (CPP_AND_AND); + break; + + case '#': + c = buffer->extra_char; /* Can be set by error condition below. */ + if (c != EOF) + { + buffer->read_ahead = c; + buffer->extra_char = EOF; + } + else + c = get_effective_char (buffer); + + if (c == '#') + { + ACCEPT_CHAR (CPP_PASTE); + break; + } + + result->type = CPP_HASH; + do_hash: + if (!bol) + break; + /* 6.10.3 paragraph 11: If there are sequences of preprocessing + tokens within the list of arguments that would otherwise act + as preprocessing directives, the behavior is undefined. + + This implementation will report a hard error, terminate the + macro invocation, and proceed to process the directive. */ + if (pfile->state.parsing_args) + { + if (pfile->state.parsing_args == 2) + cpp_error (pfile, + "directives may not be used inside a macro argument"); + + /* Put a '#' in lookahead, return CPP_EOF for parse_arg. */ + buffer->extra_char = buffer->read_ahead; + buffer->read_ahead = '#'; + pfile->state.next_bol = 1; + result->type = CPP_EOF; + + /* Get whitespace right - newline_in_args sets it. */ + if (pfile->lexer_pos.col == 1) + result->flags &= ~(PREV_WHITE | AVOID_LPASTE); + } + else + { + /* This is the hash introducing a directive. */ + if (_cpp_handle_directive (pfile, result->flags & PREV_WHITE)) + goto done_directive; /* bol still 1. */ + /* This is in fact an assembler #. */ + } + break; + + case '|': + result->type = CPP_OR; + c = get_effective_char (buffer); + if (c == '=') + ACCEPT_CHAR (CPP_OR_EQ); + else if (c == '|') + ACCEPT_CHAR (CPP_OR_OR); + break; + + case '^': + result->type = CPP_XOR; + if (get_effective_char (buffer) == '=') + ACCEPT_CHAR (CPP_XOR_EQ); + break; + + case ':': + result->type = CPP_COLON; + c = get_effective_char (buffer); + if (c == ':' && CPP_OPTION (pfile, cplusplus)) + ACCEPT_CHAR (CPP_SCOPE); + else if (c == '>' && CPP_OPTION (pfile, digraphs)) + { + result->flags |= DIGRAPH; + ACCEPT_CHAR (CPP_CLOSE_SQUARE); + } + break; + + case '~': result->type = CPP_COMPL; break; + case ',': result->type = CPP_COMMA; break; + case '(': result->type = CPP_OPEN_PAREN; break; + case ')': result->type = CPP_CLOSE_PAREN; break; + case '[': result->type = CPP_OPEN_SQUARE; break; + case ']': result->type = CPP_CLOSE_SQUARE; break; + case '{': result->type = CPP_OPEN_BRACE; break; + case '}': result->type = CPP_CLOSE_BRACE; break; + case ';': result->type = CPP_SEMICOLON; break; + + /* @ is a punctuator in Objective C. */ + case '@': result->type = CPP_ATSIGN; break; + + random_char: + default: + result->type = CPP_OTHER; + result->val.c = c; + break; + } + + if (pfile->skipping) + goto skip; + + /* If not in a directive, this token invalidates controlling macros. */ + if (!pfile->state.in_directive) + pfile->mi_state = MI_FAILED; +} + +/* An upper bound on the number of bytes needed to spell a token, + including preceding whitespace. */ +unsigned int +cpp_token_len (token) + const cpp_token *token; +{ + unsigned int len; + + switch (TOKEN_SPELL (token)) + { + default: len = 0; break; + case SPELL_STRING: len = token->val.str.len; break; + case SPELL_IDENT: len = NODE_LEN (token->val.node); break; + } + /* 1 for whitespace, 4 for comment delimeters. */ + return len + 5; +} + +/* Write the spelling of a token TOKEN to BUFFER. The buffer must + already contain the enough space to hold the token's spelling. + Returns a pointer to the character after the last character + written. */ +unsigned char * +cpp_spell_token (pfile, token, buffer) + cpp_reader *pfile; /* Would be nice to be rid of this... */ + const cpp_token *token; + unsigned char *buffer; +{ + switch (TOKEN_SPELL (token)) + { + case SPELL_OPERATOR: + { + const unsigned char *spelling; + unsigned char c; + + if (token->flags & DIGRAPH) + spelling + = digraph_spellings[(int) token->type - (int) CPP_FIRST_DIGRAPH]; + else if (token->flags & NAMED_OP) + goto spell_ident; + else + spelling = TOKEN_NAME (token); + + while ((c = *spelling++) != '\0') + *buffer++ = c; + } + break; + + case SPELL_IDENT: + spell_ident: + memcpy (buffer, NODE_NAME (token->val.node), NODE_LEN (token->val.node)); + buffer += NODE_LEN (token->val.node); + break; + + case SPELL_STRING: + { + int left, right, tag; + switch (token->type) + { + case CPP_STRING: left = '"'; right = '"'; tag = '\0'; break; + case CPP_WSTRING: left = '"'; right = '"'; tag = 'L'; break; + case CPP_CHAR: left = '\''; right = '\''; tag = '\0'; break; + case CPP_WCHAR: left = '\''; right = '\''; tag = 'L'; break; + case CPP_HEADER_NAME: left = '<'; right = '>'; tag = '\0'; break; + default: left = '\0'; right = '\0'; tag = '\0'; break; + } + if (tag) *buffer++ = tag; + if (left) *buffer++ = left; + memcpy (buffer, token->val.str.text, token->val.str.len); + buffer += token->val.str.len; + if (right) *buffer++ = right; + } + break; + + case SPELL_CHAR: + *buffer++ = token->val.c; + break; + + case SPELL_NONE: + cpp_ice (pfile, "Unspellable token %s", TOKEN_NAME (token)); + break; + } + + return buffer; +} + +/* Returns a token as a null-terminated string. The string is + temporary, and automatically freed later. Useful for diagnostics. */ +unsigned char * +cpp_token_as_text (pfile, token) + cpp_reader *pfile; + const cpp_token *token; +{ + unsigned int len = cpp_token_len (token); + unsigned char *start = _cpp_pool_alloc (&pfile->ident_pool, len), *end; + + end = cpp_spell_token (pfile, token, start); + end[0] = '\0'; + + return start; +} + +/* Used by C front ends. Should really move to using cpp_token_as_text. */ +const char * +cpp_type2name (type) + enum cpp_ttype type; +{ + return (const char *) token_spellings[type].name; +} + +/* Writes the spelling of token to FP. Separate from cpp_spell_token + for efficiency - to avoid double-buffering. Also, outputs a space + if PREV_WHITE is flagged. */ +void +cpp_output_token (token, fp) + const cpp_token *token; + FILE *fp; +{ + if (token->flags & PREV_WHITE) + putc (' ', fp); + + switch (TOKEN_SPELL (token)) + { + case SPELL_OPERATOR: + { + const unsigned char *spelling; + + if (token->flags & DIGRAPH) + spelling + = digraph_spellings[(int) token->type - (int) CPP_FIRST_DIGRAPH]; + else if (token->flags & NAMED_OP) + goto spell_ident; + else + spelling = TOKEN_NAME (token); + + ufputs (spelling, fp); + } + break; + + spell_ident: + case SPELL_IDENT: + ufputs (NODE_NAME (token->val.node), fp); + break; + + case SPELL_STRING: + { + int left, right, tag; + switch (token->type) + { + case CPP_STRING: left = '"'; right = '"'; tag = '\0'; break; + case CPP_WSTRING: left = '"'; right = '"'; tag = 'L'; break; + case CPP_CHAR: left = '\''; right = '\''; tag = '\0'; break; + case CPP_WCHAR: left = '\''; right = '\''; tag = 'L'; break; + case CPP_HEADER_NAME: left = '<'; right = '>'; tag = '\0'; break; + default: left = '\0'; right = '\0'; tag = '\0'; break; + } + if (tag) putc (tag, fp); + if (left) putc (left, fp); + fwrite (token->val.str.text, 1, token->val.str.len, fp); + if (right) putc (right, fp); + } + break; + + case SPELL_CHAR: + putc (token->val.c, fp); + break; + + case SPELL_NONE: + /* An error, most probably. */ + break; + } +} + +/* Compare two tokens. */ +int +_cpp_equiv_tokens (a, b) + const cpp_token *a, *b; +{ + if (a->type == b->type && a->flags == b->flags) + switch (TOKEN_SPELL (a)) + { + default: /* Keep compiler happy. */ + case SPELL_OPERATOR: + return 1; + case SPELL_CHAR: + return a->val.c == b->val.c; /* Character. */ + case SPELL_NONE: + return (a->type != CPP_MACRO_ARG || a->val.arg_no == b->val.arg_no); + case SPELL_IDENT: + return a->val.node == b->val.node; + case SPELL_STRING: + return (a->val.str.len == b->val.str.len + && !memcmp (a->val.str.text, b->val.str.text, + a->val.str.len)); + } + + return 0; +} + +/* Determine whether two tokens can be pasted together, and if so, + what the resulting token is. Returns CPP_EOF if the tokens cannot + be pasted, or the appropriate type for the merged token if they + can. */ +enum cpp_ttype +cpp_can_paste (pfile, token1, token2, digraph) + cpp_reader * pfile; + const cpp_token *token1, *token2; + int* digraph; +{ + enum cpp_ttype a = token1->type, b = token2->type; + int cxx = CPP_OPTION (pfile, cplusplus); + + /* Treat named operators as if they were ordinary NAMEs. */ + if (token1->flags & NAMED_OP) + a = CPP_NAME; + if (token2->flags & NAMED_OP) + b = CPP_NAME; + + if ((int) a <= (int) CPP_LAST_EQ && b == CPP_EQ) + return (enum cpp_ttype) ((int) a + ((int) CPP_EQ_EQ - (int) CPP_EQ)); + + switch (a) + { + case CPP_GREATER: + if (b == a) return CPP_RSHIFT; + if (b == CPP_QUERY && cxx) return CPP_MAX; + if (b == CPP_GREATER_EQ) return CPP_RSHIFT_EQ; + break; + case CPP_LESS: + if (b == a) return CPP_LSHIFT; + if (b == CPP_QUERY && cxx) return CPP_MIN; + if (b == CPP_LESS_EQ) return CPP_LSHIFT_EQ; + if (CPP_OPTION (pfile, digraphs)) + { + if (b == CPP_COLON) + {*digraph = 1; return CPP_OPEN_SQUARE;} /* <: digraph */ + if (b == CPP_MOD) + {*digraph = 1; return CPP_OPEN_BRACE;} /* <% digraph */ + } + break; + + case CPP_PLUS: if (b == a) return CPP_PLUS_PLUS; break; + case CPP_AND: if (b == a) return CPP_AND_AND; break; + case CPP_OR: if (b == a) return CPP_OR_OR; break; + + case CPP_MINUS: + if (b == a) return CPP_MINUS_MINUS; + if (b == CPP_GREATER) return CPP_DEREF; + break; + case CPP_COLON: + if (b == a && cxx) return CPP_SCOPE; + if (b == CPP_GREATER && CPP_OPTION (pfile, digraphs)) + {*digraph = 1; return CPP_CLOSE_SQUARE;} /* :> digraph */ + break; + + case CPP_MOD: + if (CPP_OPTION (pfile, digraphs)) + { + if (b == CPP_GREATER) + {*digraph = 1; return CPP_CLOSE_BRACE;} /* %> digraph */ + if (b == CPP_COLON) + {*digraph = 1; return CPP_HASH;} /* %: digraph */ + } + break; + case CPP_DEREF: + if (b == CPP_MULT && cxx) return CPP_DEREF_STAR; + break; + case CPP_DOT: + if (b == CPP_MULT && cxx) return CPP_DOT_STAR; + if (b == CPP_NUMBER) return CPP_NUMBER; + break; + + case CPP_HASH: + if (b == a && (token1->flags & DIGRAPH) == (token2->flags & DIGRAPH)) + /* %:%: digraph */ + {*digraph = (token1->flags & DIGRAPH); return CPP_PASTE;} + break; + + case CPP_NAME: + if (b == CPP_NAME) return CPP_NAME; + if (b == CPP_NUMBER + && name_p (pfile, &token2->val.str)) return CPP_NAME; + if (b == CPP_CHAR + && token1->val.node == pfile->spec_nodes.n_L) return CPP_WCHAR; + if (b == CPP_STRING + && token1->val.node == pfile->spec_nodes.n_L) return CPP_WSTRING; + break; + + case CPP_NUMBER: + if (b == CPP_NUMBER) return CPP_NUMBER; + if (b == CPP_NAME) return CPP_NUMBER; + if (b == CPP_DOT) return CPP_NUMBER; + /* Numbers cannot have length zero, so this is safe. */ + if ((b == CPP_PLUS || b == CPP_MINUS) + && VALID_SIGN ('+', token1->val.str.text[token1->val.str.len - 1])) + return CPP_NUMBER; + break; + + default: + break; + } + + return CPP_EOF; +} + +/* Returns nonzero if a space should be inserted to avoid an + accidental token paste for output. For simplicity, it is + conservative, and occasionally advises a space where one is not + needed, e.g. "." and ".2". */ + +int +cpp_avoid_paste (pfile, token1, token2) + cpp_reader *pfile; + const cpp_token *token1, *token2; +{ + enum cpp_ttype a = token1->type, b = token2->type; + cppchar_t c; + + if (token1->flags & NAMED_OP) + a = CPP_NAME; + if (token2->flags & NAMED_OP) + b = CPP_NAME; + + c = EOF; + if (token2->flags & DIGRAPH) + c = digraph_spellings[(int) b - (int) CPP_FIRST_DIGRAPH][0]; + else if (token_spellings[b].category == SPELL_OPERATOR) + c = token_spellings[b].name[0]; + + /* Quickly get everything that can paste with an '='. */ + if ((int) a <= (int) CPP_LAST_EQ && c == '=') + return 1; + + switch (a) + { + case CPP_GREATER: return c == '>' || c == '?'; + case CPP_LESS: return c == '<' || c == '?' || c == '%' || c == ':'; + case CPP_PLUS: return c == '+'; + case CPP_MINUS: return c == '-' || c == '>'; + case CPP_DIV: return c == '/' || c == '*'; /* Comments. */ + case CPP_MOD: return c == ':' || c == '>'; + case CPP_AND: return c == '&'; + case CPP_OR: return c == '|'; + case CPP_COLON: return c == ':' || c == '>'; + case CPP_DEREF: return c == '*'; + case CPP_DOT: return c == '.' || c == '%' || b == CPP_NUMBER; + case CPP_HASH: return c == '#' || c == '%'; /* Digraph form. */ + case CPP_NAME: return ((b == CPP_NUMBER + && name_p (pfile, &token2->val.str)) + || b == CPP_NAME + || b == CPP_CHAR || b == CPP_STRING); /* L */ + case CPP_NUMBER: return (b == CPP_NUMBER || b == CPP_NAME + || c == '.' || c == '+' || c == '-'); + case CPP_OTHER: return (CPP_OPTION (pfile, objc) + && token1->val.c == '@' + && (b == CPP_NAME || b == CPP_STRING)); + default: break; + } + + return 0; +} + +/* Output all the remaining tokens on the current line, and a newline + character, to FP. Leading whitespace is removed. */ +void +cpp_output_line (pfile, fp) + cpp_reader *pfile; + FILE *fp; +{ + cpp_token token; + + cpp_get_token (pfile, &token); + token.flags &= ~PREV_WHITE; + while (token.type != CPP_EOF) + { + cpp_output_token (&token, fp); + cpp_get_token (pfile, &token); + } + + putc ('\n', fp); +} + +/* Returns the value of a hexadecimal digit. */ +static unsigned int +hex_digit_value (c) + unsigned int c; +{ + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + if (c >= '0' && c <= '9') + return c - '0'; + abort (); +} + +/* Parse a '\uNNNN' or '\UNNNNNNNN' sequence. Returns 1 to indicate + failure if cpplib is not parsing C++ or C99. Such failure is + silent, and no variables are updated. Otherwise returns 0, and + warns if -Wtraditional. + + [lex.charset]: The character designated by the universal character + name \UNNNNNNNN is that character whose character short name in + ISO/IEC 10646 is NNNNNNNN; the character designated by the + universal character name \uNNNN is that character whose character + short name in ISO/IEC 10646 is 0000NNNN. If the hexadecimal value + for a universal character name is less than 0x20 or in the range + 0x7F-0x9F (inclusive), or if the universal character name + designates a character in the basic source character set, then the + program is ill-formed. + + We assume that wchar_t is Unicode, so we don't need to do any + mapping. Is this ever wrong? + + PC points to the 'u' or 'U', PSTR is points to the byte after PC, + LIMIT is the end of the string or charconst. PSTR is updated to + point after the UCS on return, and the UCS is written into PC. */ + +static int +maybe_read_ucs (pfile, pstr, limit, pc) + cpp_reader *pfile; + const unsigned char **pstr; + const unsigned char *limit; + unsigned int *pc; +{ + const unsigned char *p = *pstr; + unsigned int code = 0; + unsigned int c = *pc, length; + + /* Only attempt to interpret a UCS for C++ and C99. */ + if (! (CPP_OPTION (pfile, cplusplus) || CPP_OPTION (pfile, c99))) + return 1; + + if (CPP_WTRADITIONAL (pfile)) + cpp_warning (pfile, "the meaning of '\\%c' varies with -traditional", c); + + length = (c == 'u' ? 4: 8); + + if ((size_t) (limit - p) < length) + { + cpp_error (pfile, "incomplete universal-character-name"); + /* Skip to the end to avoid more diagnostics. */ + p = limit; + } + else + { + for (; length; length--, p++) + { + c = *p; + if (ISXDIGIT (c)) + code = (code << 4) + hex_digit_value (c); + else + { + cpp_error (pfile, + "non-hex digit '%c' in universal-character-name", c); + /* We shouldn't skip in case there are multibyte chars. */ + break; + } + } + } + +#ifdef TARGET_EBCDIC + cpp_error (pfile, "universal-character-name on EBCDIC target"); + code = 0x3f; /* EBCDIC invalid character */ +#else + /* True extended characters are OK. */ + if (code >= 0xa0 + && !(code & 0x80000000) + && !(code >= 0xD800 && code <= 0xDFFF)) + ; + /* The standard permits $, @ and ` to be specified as UCNs. We use + hex escapes so that this also works with EBCDIC hosts. */ + else if (code == 0x24 || code == 0x40 || code == 0x60) + ; + /* Don't give another error if one occurred above. */ + else if (length == 0) + cpp_error (pfile, "universal-character-name out of range"); +#endif + + *pstr = p; + *pc = code; + return 0; +} + +/* Interpret an escape sequence, and return its value. PSTR points to + the input pointer, which is just after the backslash. LIMIT is how + much text we have. MASK is a bitmask for the precision for the + destination type (char or wchar_t). TRADITIONAL, if true, does not + interpret escapes that did not exist in traditional C. + + Handles all relevant diagnostics. */ + +unsigned int +cpp_parse_escape (pfile, pstr, limit, mask, traditional) + cpp_reader *pfile; + const unsigned char **pstr; + const unsigned char *limit; + unsigned HOST_WIDE_INT mask; + int traditional; +{ + int unknown = 0; + const unsigned char *str = *pstr; + unsigned int c = *str++; + + switch (c) + { + case '\\': case '\'': case '"': case '?': break; + case 'b': c = TARGET_BS; break; + case 'f': c = TARGET_FF; break; + case 'n': c = TARGET_NEWLINE; break; + case 'r': c = TARGET_CR; break; + case 't': c = TARGET_TAB; break; + case 'v': c = TARGET_VT; break; + + case '(': case '{': case '[': case '%': + /* '\(', etc, are used at beginning of line to avoid confusing Emacs. + '\%' is used to prevent SCCS from getting confused. */ + unknown = CPP_PEDANTIC (pfile); + break; + + case 'a': + if (CPP_WTRADITIONAL (pfile)) + cpp_warning (pfile, "the meaning of '\\a' varies with -traditional"); + if (!traditional) + c = TARGET_BELL; + break; + + case 'e': case 'E': + if (CPP_PEDANTIC (pfile)) + cpp_pedwarn (pfile, "non-ISO-standard escape sequence, '\\%c'", c); + c = TARGET_ESC; + break; + + case 'u': case 'U': + unknown = maybe_read_ucs (pfile, &str, limit, &c); + break; + + case 'x': + if (CPP_WTRADITIONAL (pfile)) + cpp_warning (pfile, "the meaning of '\\x' varies with -traditional"); + + if (!traditional) + { + unsigned int i = 0, overflow = 0; + int digits_found = 0; + + while (str < limit) + { + c = *str; + if (! ISXDIGIT (c)) + break; + str++; + overflow |= i ^ (i << 4 >> 4); + i = (i << 4) + hex_digit_value (c); + digits_found = 1; + } + + if (!digits_found) + cpp_error (pfile, "\\x used with no following hex digits"); + + if (overflow | (i != (i & mask))) + { + cpp_pedwarn (pfile, "hex escape sequence out of range"); + i &= mask; + } + c = i; + } + break; + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + { + unsigned int i = c - '0'; + int count = 0; + + while (str < limit && ++count < 3) + { + c = *str; + if (c < '0' || c > '7') + break; + str++; + i = (i << 3) + c - '0'; + } + + if (i != (i & mask)) + { + cpp_pedwarn (pfile, "octal escape sequence out of range"); + i &= mask; + } + c = i; + } + break; + + default: + unknown = 1; + break; + } + + if (unknown) + { + if (ISGRAPH (c)) + cpp_pedwarn (pfile, "unknown escape sequence '\\%c'", c); + else + cpp_pedwarn (pfile, "unknown escape sequence: '\\%03o'", c); + } + + if (c > mask) + cpp_pedwarn (pfile, "escape sequence out of range for character"); + + *pstr = str; + return c; +} + +#ifndef MAX_CHAR_TYPE_SIZE +#define MAX_CHAR_TYPE_SIZE CHAR_TYPE_SIZE +#endif + +#ifndef MAX_WCHAR_TYPE_SIZE +#define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE +#endif + +/* Interpret a (possibly wide) character constant in TOKEN. + WARN_MULTI warns about multi-character charconsts, if not + TRADITIONAL. TRADITIONAL also indicates not to interpret escapes + that did not exist in traditional C. PCHARS_SEEN points to a + variable that is filled in with the number of characters seen. */ +HOST_WIDE_INT +cpp_interpret_charconst (pfile, token, warn_multi, traditional, pchars_seen) + cpp_reader *pfile; + const cpp_token *token; + int warn_multi; + int traditional; + unsigned int *pchars_seen; +{ + const unsigned char *str = token->val.str.text; + const unsigned char *limit = str + token->val.str.len; + unsigned int chars_seen = 0; + unsigned int width, max_chars, c; + unsigned HOST_WIDE_INT mask; + HOST_WIDE_INT result = 0; + +#ifdef MULTIBYTE_CHARS + (void) local_mbtowc (NULL, NULL, 0); +#endif + + /* Width in bits. */ + if (token->type == CPP_CHAR) + width = MAX_CHAR_TYPE_SIZE; + else + width = MAX_WCHAR_TYPE_SIZE; + + if (width < HOST_BITS_PER_WIDE_INT) + mask = ((unsigned HOST_WIDE_INT) 1 << width) - 1; + else + mask = ~0; + max_chars = HOST_BITS_PER_WIDE_INT / width; + + while (str < limit) + { +#ifdef MULTIBYTE_CHARS + wchar_t wc; + int char_len; + + char_len = local_mbtowc (&wc, str, limit - str); + if (char_len == -1) + { + cpp_warning (pfile, "ignoring invalid multibyte character"); + c = *str++; + } + else + { + str += char_len; + c = wc; + } +#else + c = *str++; +#endif + + if (c == '\\') + c = cpp_parse_escape (pfile, &str, limit, mask, traditional); + +#ifdef MAP_CHARACTER + if (ISPRINT (c)) + c = MAP_CHARACTER (c); +#endif + + /* Merge character into result; ignore excess chars. */ + if (++chars_seen <= max_chars) + { + if (width < HOST_BITS_PER_WIDE_INT) + result = (result << width) | (c & mask); + else + result = c; + } + } + + if (chars_seen == 0) + cpp_error (pfile, "empty character constant"); + else if (chars_seen > max_chars) + { + chars_seen = max_chars; + cpp_warning (pfile, "character constant too long"); + } + else if (chars_seen > 1 && !traditional && warn_multi) + cpp_warning (pfile, "multi-character character constant"); + + /* If char type is signed, sign-extend the constant. The + __CHAR_UNSIGNED__ macro is set by the driver if appropriate. */ + if (token->type == CPP_CHAR && chars_seen) + { + unsigned int nbits = chars_seen * width; + unsigned int mask = (unsigned int) ~0 >> (HOST_BITS_PER_INT - nbits); + + if (pfile->spec_nodes.n__CHAR_UNSIGNED__->type == NT_MACRO + || ((result >> (nbits - 1)) & 1) == 0) + result &= mask; + else + result |= ~mask; + } + + *pchars_seen = chars_seen; + return result; +} + +/* Memory pools. */ + +struct dummy +{ + char c; + union + { + double d; + int *p; + } u; +}; + +#define DEFAULT_ALIGNMENT (offsetof (struct dummy, u)) + +static int +chunk_suitable (pool, chunk, size) + cpp_pool *pool; + cpp_chunk *chunk; + unsigned int size; +{ + /* Being at least twice SIZE means we can use memcpy in + _cpp_next_chunk rather than memmove. Besides, it's a good idea + anyway. */ + return (chunk && pool->locked != chunk + && (unsigned int) (chunk->limit - chunk->base) >= size * 2); +} + +/* Returns the end of the new pool. PTR points to a char in the old + pool, and is updated to point to the same char in the new pool. */ +unsigned char * +_cpp_next_chunk (pool, len, ptr) + cpp_pool *pool; + unsigned int len; + unsigned char **ptr; +{ + cpp_chunk *chunk = pool->cur->next; + + /* LEN is the minimum size we want in the new pool. */ + len += POOL_ROOM (pool); + if (! chunk_suitable (pool, chunk, len)) + { + chunk = new_chunk (POOL_SIZE (pool) * 2 + len); + + chunk->next = pool->cur->next; + pool->cur->next = chunk; + } + + /* Update the pointer before changing chunk's front. */ + if (ptr) + *ptr += chunk->base - POOL_FRONT (pool); + + memcpy (chunk->base, POOL_FRONT (pool), POOL_ROOM (pool)); + chunk->front = chunk->base; + + pool->cur = chunk; + return POOL_LIMIT (pool); +} + +static cpp_chunk * +new_chunk (size) + unsigned int size; +{ + unsigned char *base; + cpp_chunk *result; + + size = POOL_ALIGN (size, DEFAULT_ALIGNMENT); + base = (unsigned char *) xmalloc (size + sizeof (cpp_chunk)); + /* Put the chunk descriptor at the end. Then chunk overruns will + cause obvious chaos. */ + result = (cpp_chunk *) (base + size); + result->base = base; + result->front = base; + result->limit = base + size; + result->next = 0; + + return result; +} + +void +_cpp_init_pool (pool, size, align, temp) + cpp_pool *pool; + unsigned int size, align, temp; +{ + if (align == 0) + align = DEFAULT_ALIGNMENT; + if (align & (align - 1)) + abort (); + pool->align = align; + pool->cur = new_chunk (size); + pool->locked = 0; + pool->locks = 0; + if (temp) + pool->cur->next = pool->cur; +} + +void +_cpp_lock_pool (pool) + cpp_pool *pool; +{ + if (pool->locks++ == 0) + pool->locked = pool->cur; +} + +void +_cpp_unlock_pool (pool) + cpp_pool *pool; +{ + if (--pool->locks == 0) + pool->locked = 0; +} + +void +_cpp_free_pool (pool) + cpp_pool *pool; +{ + cpp_chunk *chunk = pool->cur, *next; + + do + { + next = chunk->next; + free (chunk->base); + chunk = next; + } + while (chunk && chunk != pool->cur); +} + +/* Reserve LEN bytes from a memory pool. */ +unsigned char * +_cpp_pool_reserve (pool, len) + cpp_pool *pool; + unsigned int len; +{ + len = POOL_ALIGN (len, pool->align); + if (len > (unsigned int) POOL_ROOM (pool)) + _cpp_next_chunk (pool, len, 0); + + return POOL_FRONT (pool); +} + +/* Allocate LEN bytes from a memory pool. */ +unsigned char * +_cpp_pool_alloc (pool, len) + cpp_pool *pool; + unsigned int len; +{ + unsigned char *result = _cpp_pool_reserve (pool, len); + + POOL_COMMIT (pool, len); + return result; +} diff --git a/support/cpp2/cpplib.c b/support/cpp2/cpplib.c new file mode 100644 index 00000000..cb493105 --- /dev/null +++ b/support/cpp2/cpplib.c @@ -0,0 +1,1926 @@ +/* CPP Library. (Directive handling.) + Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2001 Free Software Foundation, Inc. + Contributed by Per Bothner, 1994-95. + Based on CCCP program by Paul Rubin, June 1986 + Adapted to ANSI C, Richard Stallman, Jan 1987 + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "config.h" +#include "system.h" + +#include "cpplib.h" +#include "cpphash.h" +#include "intl.h" +#include "obstack.h" + +/* Chained list of answers to an assertion. */ +struct answer +{ + struct answer *next; + unsigned int count; + cpp_token first[1]; +}; + +/* Stack of conditionals currently in progress + (including both successful and failing conditionals). */ + +struct if_stack +{ + struct if_stack *next; + cpp_lexer_pos pos; /* line and column where condition started */ + const cpp_hashnode *mi_cmacro;/* macro name for #ifndef around entire file */ + unsigned char was_skipping; /* Value of pfile->skipping before this if. */ + int type; /* type of last directive seen in this group */ +}; + +/* Values for the origin field of struct directive. KANDR directives + come from traditional (K&R) C. STDC89 directives come from the + 1989 C standard. EXTENSION directives are extensions. */ +#define KANDR 0 +#define STDC89 1 +#define EXTENSION 2 + +/* Values for the flags field of struct directive. COND indicates a + conditional; IF_COND an opening conditional. INCL means to treat + "..." and <...> as q-char and h-char sequences respectively. IN_I + means this directive should be handled even if -fpreprocessed is in + effect (these are the directives with callback hooks). */ +#define COND (1 << 0) +#define IF_COND (1 << 1) +#define INCL (1 << 2) +#define IN_I (1 << 3) + +/* Defines one #-directive, including how to handle it. */ +typedef void (*directive_handler) PARAMS ((cpp_reader *)); +typedef struct directive directive; +struct directive +{ + directive_handler handler; /* Function to handle directive. */ + const U_CHAR *name; /* Name of directive. */ + unsigned short length; /* Length of name. */ + unsigned char origin; /* Origin of directive. */ + unsigned char flags; /* Flags describing this directive. */ +}; + +/* Forward declarations. */ + +static void skip_rest_of_line PARAMS ((cpp_reader *)); +static void check_eol PARAMS ((cpp_reader *)); +static void start_directive PARAMS ((cpp_reader *)); +static void end_directive PARAMS ((cpp_reader *, int)); +static void run_directive PARAMS ((cpp_reader *, int, + enum cpp_buffer_type, + const char *, size_t)); +static int glue_header_name PARAMS ((cpp_reader *, cpp_token *)); +static int parse_include PARAMS ((cpp_reader *, cpp_token *)); +static void push_conditional PARAMS ((cpp_reader *, int, int, + const cpp_hashnode *)); +static unsigned int read_flag PARAMS ((cpp_reader *, unsigned int)); +static int strtoul_for_line PARAMS ((const U_CHAR *, unsigned int, + unsigned long *)); +static void do_diagnostic PARAMS ((cpp_reader *, enum error_type, int)); +static cpp_hashnode *lex_macro_node PARAMS ((cpp_reader *)); +static void do_include_common PARAMS ((cpp_reader *, enum include_type)); +static void do_pragma_once PARAMS ((cpp_reader *)); +static void do_pragma_poison PARAMS ((cpp_reader *)); +static void do_pragma_system_header PARAMS ((cpp_reader *)); +static void do_pragma_dependency PARAMS ((cpp_reader *)); +static int get__Pragma_string PARAMS ((cpp_reader *, cpp_token *)); +static unsigned char *destringize PARAMS ((const cpp_string *, + unsigned int *)); +static int parse_answer PARAMS ((cpp_reader *, struct answer **, int)); +static cpp_hashnode *parse_assertion PARAMS ((cpp_reader *, struct answer **, + int)); +static struct answer ** find_answer PARAMS ((cpp_hashnode *, + const struct answer *)); +static void handle_assertion PARAMS ((cpp_reader *, const char *, int)); + +/* This is the table of directive handlers. It is ordered by + frequency of occurrence; the numbers at the end are directive + counts from all the source code I have lying around (egcs and libc + CVS as of 1999-05-18, plus grub-0.5.91, linux-2.2.9, and + pcmcia-cs-3.0.9). This is no longer important as directive lookup + is now O(1). All extensions other than #warning and #include_next + are deprecated. The name is where the extension appears to have + come from. */ + +#define DIRECTIVE_TABLE \ +D(define, T_DEFINE = 0, KANDR, IN_I) /* 270554 */ \ +D(include, T_INCLUDE, KANDR, INCL) /* 52262 */ \ +D(endif, T_ENDIF, KANDR, COND) /* 45855 */ \ +D(ifdef, T_IFDEF, KANDR, COND | IF_COND) /* 22000 */ \ +D(if, T_IF, KANDR, COND | IF_COND) /* 18162 */ \ +D(else, T_ELSE, KANDR, COND) /* 9863 */ \ +D(ifndef, T_IFNDEF, KANDR, COND | IF_COND) /* 9675 */ \ +D(undef, T_UNDEF, KANDR, IN_I) /* 4837 */ \ +D(line, T_LINE, KANDR, IN_I) /* 2465 */ \ +D(elif, T_ELIF, STDC89, COND) /* 610 */ \ +D(error, T_ERROR, STDC89, 0) /* 475 */ \ +D(pragma, T_PRAGMA, STDC89, IN_I) /* 195 */ \ +D(warning, T_WARNING, EXTENSION, 0) /* 22 */ \ +D(include_next, T_INCLUDE_NEXT, EXTENSION, INCL) /* 19 */ \ +D(ident, T_IDENT, EXTENSION, IN_I) /* 11 */ \ +D(import, T_IMPORT, EXTENSION, INCL) /* 0 ObjC */ \ +D(assert, T_ASSERT, EXTENSION, 0) /* 0 SVR4 */ \ +D(unassert, T_UNASSERT, EXTENSION, 0) /* 0 SVR4 */ \ +SCCS_ENTRY /* 0 SVR4? */ + +/* #sccs is not always recognized. */ +#ifdef SCCS_DIRECTIVE +# define SCCS_ENTRY D(sccs, T_SCCS, EXTENSION, 0) +#else +# define SCCS_ENTRY /* nothing */ +#endif + +/* Use the table to generate a series of prototypes, an enum for the + directive names, and an array of directive handlers. */ + +/* The directive-processing functions are declared to return int + instead of void, because some old compilers have trouble with + pointers to functions returning void. */ + +/* Don't invoke CONCAT2 with any whitespace or K&R cc will fail. */ +#define D(name, t, o, f) static void CONCAT2(do_,name) PARAMS ((cpp_reader *)); +DIRECTIVE_TABLE +#undef D + +#define D(n, tag, o, f) tag, +enum +{ + DIRECTIVE_TABLE + N_DIRECTIVES +}; +#undef D + +/* Don't invoke CONCAT2 with any whitespace or K&R cc will fail. */ +#define D(name, t, origin, flags) \ +{ CONCAT2(do_,name), (const U_CHAR *) STRINGX(name), \ + sizeof STRINGX(name) - 1, origin, flags }, +static const directive dtable[] = +{ +DIRECTIVE_TABLE +}; +#undef D +#undef DIRECTIVE_TABLE + +/* Skip any remaining tokens in a directive. */ +static void +skip_rest_of_line (pfile) + cpp_reader *pfile; +{ + cpp_token token; + + /* Discard all input lookaheads. */ + while (pfile->la_read) + _cpp_release_lookahead (pfile); + + /* Discard all stacked contexts. */ + while (pfile->context != &pfile->base_context) + _cpp_pop_context (pfile); + + /* Sweep up all tokens remaining on the line. */ + pfile->state.prevent_expansion++; + while (!pfile->state.next_bol) + _cpp_lex_token (pfile, &token); + pfile->state.prevent_expansion--; +} + +/* Ensure there are no stray tokens at the end of a directive. */ +static void +check_eol (pfile) + cpp_reader *pfile; +{ + if (!pfile->state.next_bol) + { + cpp_token token; + + _cpp_lex_token (pfile, &token); + if (token.type != CPP_EOF) + cpp_pedwarn (pfile, "extra tokens at end of #%s directive", + pfile->directive->name); + } +} + +/* Called when entering a directive, _Pragma or command-line directive. */ +static void +start_directive (pfile) + cpp_reader *pfile; +{ + cpp_buffer *buffer = pfile->buffer; + + /* Setup in-directive state. */ + pfile->state.in_directive = 1; + pfile->state.save_comments = 0; + + /* Some handlers need the position of the # for diagnostics. */ + pfile->directive_pos = pfile->lexer_pos; + + /* Don't save directive tokens for external clients. */ + pfile->la_saved = pfile->la_write; + pfile->la_write = 0; + + /* Turn off skipping. */ + buffer->was_skipping = pfile->skipping; + pfile->skipping = 0; +} + +/* Called when leaving a directive, _Pragma or command-line directive. */ +static void +end_directive (pfile, skip_line) + cpp_reader *pfile; + int skip_line; +{ + cpp_buffer *buffer = pfile->buffer; + + /* Restore pfile->skipping before skip_rest_of_line, so that e.g. + __VA_ARGS__ in the rest of the directive doesn't warn. */ + pfile->skipping = buffer->was_skipping; + + /* We don't skip for an assembler #. */ + if (skip_line) + skip_rest_of_line (pfile); + + /* Restore state. */ + pfile->la_write = pfile->la_saved; + pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments); + pfile->state.in_directive = 0; + pfile->state.angled_headers = 0; + pfile->state.line_extension = 0; + pfile->directive = 0; +} + +/* Check if a token's name matches that of a known directive. Put in + this file to save exporting dtable and other unneeded information. */ +int +_cpp_handle_directive (pfile, indented) + cpp_reader *pfile; + int indented; +{ + cpp_buffer *buffer = pfile->buffer; + const directive *dir = 0; + cpp_token dname; + int skip = 1; + + start_directive (pfile); + + /* Lex the directive name directly. */ + _cpp_lex_token (pfile, &dname); + + if (dname.type == CPP_NAME) + { + unsigned int index = dname.val.node->directive_index; + if (index) + dir = &dtable[index - 1]; + } + else if (dname.type == CPP_NUMBER) + { + /* # followed by a number is equivalent to #line. Do not + recognize this form in assembly language source files or + skipped conditional groups. Complain about this form if + we're being pedantic, but not if this is regurgitated input + (preprocessed or fed back in by the C++ frontend). */ + if (! buffer->was_skipping && CPP_OPTION (pfile, lang) != CLK_ASM) + { + dir = &dtable[T_LINE]; + pfile->state.line_extension = 1; + _cpp_push_token (pfile, &dname, &pfile->directive_pos); + if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, preprocessed)) + cpp_pedwarn (pfile, "# followed by integer"); + } + } + + pfile->directive = dir; + if (dir) + { + /* Make sure we lex headers correctly, whether skipping or not. */ + pfile->state.angled_headers = dir->flags & INCL; + + /* If we are rescanning preprocessed input, only directives tagged + with IN_I are honored, and the warnings below are suppressed. */ + if (CPP_OPTION (pfile, preprocessed)) + { + /* Kluge alert. In order to be sure that code like this + #define HASH # + HASH define foo bar + does not cause '#define foo bar' to get executed when + compiled with -save-temps, we recognize directives in + -fpreprocessed mode only if the # is in column 1 and the + directive name starts in column 2. This output can only + be generated by the directive callbacks in cppmain.c (see + also the special case in scan_buffer). */ + if (dir->flags & IN_I && !indented && !(dname.flags & PREV_WHITE)) + (*dir->handler) (pfile); + /* That check misses '# 123' linemarkers. Let them through too. */ + else if (dname.type == CPP_NUMBER) + (*dir->handler) (pfile); + else + { + /* We don't want to process this directive. Put back the + tokens so caller will see them (and issue an error, + probably). */ + _cpp_push_token (pfile, &dname, &pfile->directive_pos); + skip = 0; + } + } + else + { + /* Traditionally, a directive is ignored unless its # is in + column 1. Therefore in code intended to work with K+R + compilers, directives added by C89 must have their # + indented, and directives present in traditional C must + not. This is true even of directives in skipped + conditional blocks. */ + if (CPP_WTRADITIONAL (pfile)) + { + if (dir == &dtable[T_ELIF]) + cpp_warning (pfile, + "suggest not using #elif in traditional C"); + else if (indented && dir->origin == KANDR) + cpp_warning (pfile, + "traditional C ignores #%s with the # indented", + dir->name); + else if (!indented && dir->origin != KANDR) + cpp_warning (pfile, + "suggest hiding #%s from traditional C with an indented #", + dir->name); + } + + /* If we are skipping a failed conditional group, all + non-conditional directives are ignored. */ + if (! buffer->was_skipping || (dir->flags & COND)) + { + /* Issue -pedantic warnings for extensions. */ + if (CPP_PEDANTIC (pfile) && dir->origin == EXTENSION) + cpp_pedwarn (pfile, "#%s is a GCC extension", dir->name); + + /* If we have a directive that is not an opening + conditional, invalidate any control macro. */ + if (! (dir->flags & IF_COND)) + pfile->mi_state = MI_FAILED; + + (*dir->handler) (pfile); + } + } + } + else if (dname.type != CPP_EOF && ! buffer->was_skipping) + { + /* An unknown directive. Don't complain about it in assembly + source: we don't know where the comments are, and # may + introduce assembler pseudo-ops. Don't complain about invalid + directives in skipped conditional groups (6.10 p4). */ + if (CPP_OPTION (pfile, lang) == CLK_ASM) + { + /* Output the # and lookahead token for the assembler. */ + _cpp_push_token (pfile, &dname, &pfile->directive_pos); + skip = 0; + } + else + cpp_error (pfile, "invalid preprocessing directive #%s", + cpp_token_as_text (pfile, &dname)); + } + + end_directive (pfile, skip); + return skip; +} + +/* Directive handler wrapper used by the command line option + processor. */ +static void +run_directive (pfile, dir_no, type, buf, count) + cpp_reader *pfile; + int dir_no; + enum cpp_buffer_type type; + const char *buf; + size_t count; +{ + unsigned int output_line = pfile->lexer_pos.output_line; + cpp_buffer *buffer; + + buffer = cpp_push_buffer (pfile, (const U_CHAR *) buf, count, type, 0); + + if (dir_no == T_PRAGMA) + { + /* A kludge to avoid line markers for _Pragma. */ + pfile->lexer_pos.output_line = output_line; + /* Avoid interpretation of directives in a _Pragma string. */ + pfile->state.next_bol = 0; + } + + start_directive (pfile); + pfile->state.prevent_expansion++; + pfile->directive = &dtable[dir_no]; + (void) (*pfile->directive->handler) (pfile); + pfile->state.prevent_expansion--; + check_eol (pfile); + end_directive (pfile, 1); + + cpp_pop_buffer (pfile); +} + +/* Checks for validity the macro name in #define, #undef, #ifdef and + #ifndef directives. */ +static cpp_hashnode * +lex_macro_node (pfile) + cpp_reader *pfile; +{ + cpp_token token; + + /* Lex the macro name directly. */ + _cpp_lex_token (pfile, &token); + + /* The token immediately after #define must be an identifier. That + identifier is not allowed to be "defined". See predefined macro + names (6.10.8.4). In C++, it is not allowed to be any of the + macro names (which are keywords in C++) either. */ + + if (token.type != CPP_NAME) + { + if (token.type == CPP_EOF) + cpp_error (pfile, "no macro name given in #%s directive", + pfile->directive->name); + else if (token.flags & NAMED_OP) + cpp_error (pfile, + "\"%s\" cannot be used as a macro name as it is an operator in C++", + NODE_NAME (token.val.node)); + else + cpp_error (pfile, "macro names must be identifiers"); + } + else + { + cpp_hashnode *node = token.val.node; + + /* In Objective C, some keywords begin with '@', but general + identifiers do not, and you're not allowed to #define them. */ + if (node == pfile->spec_nodes.n_defined || NODE_NAME (node)[0] == '@') + cpp_error (pfile, "\"%s\" cannot be used as a macro name", + NODE_NAME (node)); + else if (!(node->flags & NODE_POISONED)) + return node; + } + + return 0; +} + +/* Process a #define directive. Most work is done in cppmacro.c. */ +static void +do_define (pfile) + cpp_reader *pfile; +{ + cpp_hashnode *node = lex_macro_node (pfile); + + if (node) + { + if (_cpp_create_definition (pfile, node)) + if (pfile->cb.define) + (*pfile->cb.define) (pfile, node); + } +} + +/* Handle #undef. Marks the identifier NT_VOID in the hash table. */ +static void +do_undef (pfile) + cpp_reader *pfile; +{ + cpp_hashnode *node = lex_macro_node (pfile); + + /* 6.10.3.5 paragraph 2: [#undef] is ignored if the specified identifier + is not currently defined as a macro name. */ + if (node && node->type == NT_MACRO) + { + if (pfile->cb.undef) + (*pfile->cb.undef) (pfile, node); + + if (node->flags & NODE_WARN) + cpp_warning (pfile, "undefining \"%s\"", NODE_NAME (node)); + + _cpp_free_definition (node); + } + check_eol (pfile); +} + +/* Helper routine used by parse_include. Reinterpret the current line + as an h-char-sequence (< ... >); we are looking at the first token + after the <. Returns zero on success. */ +static int +glue_header_name (pfile, header) + cpp_reader *pfile; + cpp_token *header; +{ + cpp_token token; + unsigned char *buffer, *token_mem; + size_t len, total_len = 0, capacity = 1024; + + /* To avoid lexed tokens overwriting our glued name, we can only + allocate from the string pool once we've lexed everything. */ + + buffer = (unsigned char *) xmalloc (capacity); + for (;;) + { + cpp_get_token (pfile, &token); + + if (token.type == CPP_GREATER || token.type == CPP_EOF) + break; + + len = cpp_token_len (&token); + if (total_len + len > capacity) + { + capacity = (capacity + len) * 2; + buffer = (unsigned char *) xrealloc (buffer, capacity); + } + + if (token.flags & PREV_WHITE) + buffer[total_len++] = ' '; + + total_len = cpp_spell_token (pfile, &token, &buffer[total_len]) - buffer; + } + + if (token.type == CPP_EOF) + cpp_error (pfile, "missing terminating > character"); + else + { + token_mem = _cpp_pool_alloc (&pfile->ident_pool, total_len + 1); + memcpy (token_mem, buffer, total_len); + token_mem[total_len] = '\0'; + + header->type = CPP_HEADER_NAME; + header->flags &= ~PREV_WHITE; + header->val.str.len = total_len; + header->val.str.text = token_mem; + } + + free ((PTR) buffer); + return token.type == CPP_EOF; +} + +/* Parse the header name of #include, #include_next, #import and + #pragma dependency. Returns zero on success. */ +static int +parse_include (pfile, header) + cpp_reader *pfile; + cpp_token *header; +{ + int is_pragma = pfile->directive == &dtable[T_PRAGMA]; + const unsigned char *dir; + + if (is_pragma) + dir = U"pragma dependency"; + else + dir = pfile->directive->name; + + /* Allow macro expansion. */ + cpp_get_token (pfile, header); + if (header->type != CPP_STRING && header->type != CPP_HEADER_NAME) + { + if (header->type != CPP_LESS) + { + cpp_error (pfile, "#%s expects \"FILENAME\" or ", dir); + return 1; + } + if (glue_header_name (pfile, header)) + return 1; + } + + if (header->val.str.len == 0) + { + cpp_error (pfile, "empty file name in #%s", dir); + return 1; + } + + if (!is_pragma) + { + check_eol (pfile); + /* Get out of macro context, if we are. */ + skip_rest_of_line (pfile); + if (pfile->cb.include) + (*pfile->cb.include) (pfile, dir, header); + } + + return 0; +} + +/* Handle #include, #include_next and #import. */ +static void +do_include_common (pfile, type) + cpp_reader *pfile; + enum include_type type; +{ + cpp_token header; + + if (!parse_include (pfile, &header)) + { + /* Prevent #include recursion. */ + if (pfile->buffer_stack_depth >= CPP_STACK_MAX) + cpp_fatal (pfile, "#include nested too deeply"); + else if (pfile->context->prev) + cpp_ice (pfile, "attempt to push file buffer with contexts stacked"); + else + { + /* For #include_next, if this is the primary source file, + warn and use the normal search logic. */ + if (type == IT_INCLUDE_NEXT && ! pfile->buffer->prev) + { + cpp_warning (pfile, "#include_next in primary source file"); + type = IT_INCLUDE; + } + + _cpp_execute_include (pfile, &header, type); + } + } +} + +static void +do_include (pfile) + cpp_reader *pfile; +{ + do_include_common (pfile, IT_INCLUDE); +} + +static void +do_import (pfile) + cpp_reader *pfile; +{ + if (!pfile->import_warning && CPP_OPTION (pfile, warn_import)) + { + pfile->import_warning = 1; + cpp_warning (pfile, + "#import is obsolete, use an #ifndef wrapper in the header file"); + } + + do_include_common (pfile, IT_IMPORT); +} + +static void +do_include_next (pfile) + cpp_reader *pfile; +{ + do_include_common (pfile, IT_INCLUDE_NEXT); +} + +/* Subroutine of do_line. Read possible flags after file name. LAST + is the last flag seen; 0 if this is the first flag. Return the flag + if it is valid, 0 at the end of the directive. Otherwise complain. */ + +static unsigned int +read_flag (pfile, last) + cpp_reader *pfile; + unsigned int last; +{ + cpp_token token; + + _cpp_lex_token (pfile, &token); + if (token.type == CPP_NUMBER && token.val.str.len == 1) + { + unsigned int flag = token.val.str.text[0] - '0'; + + if (flag > last && flag <= 4 + && (flag != 4 || last == 3) + && (flag != 2 || last == 0)) + return flag; + } + + if (token.type != CPP_EOF) + cpp_error (pfile, "invalid flag \"%s\" in line directive", + cpp_token_as_text (pfile, &token)); + return 0; +} + +/* Another subroutine of do_line. Convert a number in STR, of length + LEN, to binary; store it in NUMP, and return 0 if the number was + well-formed, 1 if not. Temporary, hopefully. */ +static int +strtoul_for_line (str, len, nump) + const U_CHAR *str; + unsigned int len; + unsigned long *nump; +{ + unsigned long reg = 0; + U_CHAR c; + while (len--) + { + c = *str++; + if (!ISDIGIT (c)) + return 1; + reg *= 10; + reg += c - '0'; + } + *nump = reg; + return 0; +} + +/* Interpret #line command. + Note that the filename string (if any) is treated as if it were an + include filename. That means no escape handling. */ + +static void +do_line (pfile) + cpp_reader *pfile; +{ + cpp_buffer *buffer = pfile->buffer; + const char *filename = buffer->nominal_fname; + unsigned int lineno = buffer->lineno; + enum cpp_fc_reason reason = FC_RENAME; + unsigned long new_lineno; + unsigned int cap; + cpp_token token; + + /* C99 raised the minimum limit on #line numbers. */ + cap = CPP_OPTION (pfile, c99) ? 2147483647 : 32767; + + /* #line commands expand macros. */ + cpp_get_token (pfile, &token); + if (token.type != CPP_NUMBER + || strtoul_for_line (token.val.str.text, token.val.str.len, &new_lineno)) + { + cpp_error (pfile, "\"%s\" after #line is not a positive integer", + cpp_token_as_text (pfile, &token)); + return; + } + + if (CPP_PEDANTIC (pfile) && (new_lineno == 0 || new_lineno > cap)) + cpp_pedwarn (pfile, "line number out of range"); + + cpp_get_token (pfile, &token); + if (token.type == CPP_STRING) + { + const char *fname = (const char *) token.val.str.text; + + /* Only accept flags for the # 55 form. */ + if (! pfile->state.line_extension) + check_eol (pfile); + else + { + int flag = 0, sysp = 0; + + flag = read_flag (pfile, flag); + if (flag == 1) + { + reason = FC_ENTER; + flag = read_flag (pfile, flag); + } + else if (flag == 2) + { + reason = FC_LEAVE; + flag = read_flag (pfile, flag); + } + if (flag == 3) + { + sysp = 1; + flag = read_flag (pfile, flag); + if (flag == 4) + sysp = 2, read_flag (pfile, flag); + } + + if (reason == FC_ENTER) + { + /* Fake a buffer stack for diagnostics. */ + cpp_push_buffer (pfile, 0, 0, BUF_FAKE, fname); + /* Fake an include for cpp_included. */ + _cpp_fake_include (pfile, fname); + buffer = pfile->buffer; + } + else if (reason == FC_LEAVE) + { + if (buffer->type != BUF_FAKE) + cpp_warning (pfile, "file \"%s\" left but not entered", + buffer->nominal_fname); + else + { + cpp_pop_buffer (pfile); + buffer = pfile->buffer; +#ifdef ENABLE_CHECKING + if (strcmp (buffer->nominal_fname, fname)) + cpp_warning (pfile, "expected to return to file \"%s\"", + buffer->nominal_fname); + if (buffer->lineno + 1 != new_lineno) + cpp_warning (pfile, "expected to return to line number %u", + buffer->lineno + 1); + if (buffer->sysp != sysp) + cpp_warning (pfile, "header flags for \"%s\" have changed", + buffer->nominal_fname); +#endif + } + } + buffer->sysp = sysp; + } + buffer->nominal_fname = fname; + } + else if (token.type != CPP_EOF) + { + cpp_error (pfile, "\"%s\" is not a valid filename", + cpp_token_as_text (pfile, &token)); + return; + } + + /* Our line number is incremented after the directive is processed. */ + buffer->lineno = new_lineno - 1; + _cpp_do_file_change (pfile, reason, filename, lineno); +} + +/* Arrange the file_change callback. */ +void +_cpp_do_file_change (pfile, reason, from_file, from_lineno) + cpp_reader *pfile; + enum cpp_fc_reason reason; + const char *from_file; + unsigned int from_lineno; +{ + if (pfile->cb.file_change) + { + cpp_file_change fc; + cpp_buffer *buffer = pfile->buffer; + + fc.reason = reason; + fc.to.filename = buffer->nominal_fname; + fc.to.lineno = buffer->lineno + 1; + fc.sysp = buffer->sysp; + fc.externc = CPP_OPTION (pfile, cplusplus) && buffer->sysp == 2; + + /* Caller doesn't need to handle FC_ENTER. */ + if (reason == FC_ENTER) + { + if (buffer->prev) + { + from_file = buffer->prev->nominal_fname; + from_lineno = buffer->prev->lineno; + } + else + from_file = 0; + } + /* Special case for file "foo.i" with "# 1 foo.c" on first line. */ + else if (reason == FC_RENAME && ! buffer->prev + && pfile->directive_pos.line == 1) + from_file = 0; + + fc.from.filename = from_file; + fc.from.lineno = from_lineno; + pfile->cb.file_change (pfile, &fc); + } +} + +/* + * Report a warning or error detected by the program we are + * processing. Use the directive's tokens in the error message. + */ + +static void +do_diagnostic (pfile, code, print_dir) + cpp_reader *pfile; + enum error_type code; + int print_dir; +{ + if (_cpp_begin_message (pfile, code, NULL, 0)) + { + if (print_dir) + fprintf (stderr, "#%s ", pfile->directive->name); + pfile->state.prevent_expansion++; + cpp_output_line (pfile, stderr); + pfile->state.prevent_expansion--; + } +} + +static void +do_error (pfile) + cpp_reader *pfile; +{ + do_diagnostic (pfile, ERROR, 1); +} + +static void +do_warning (pfile) + cpp_reader *pfile; +{ + /* We want #warning diagnostics to be emitted in system headers too. */ + do_diagnostic (pfile, WARNING_SYSHDR, 1); +} + +/* Report program identification. */ + +static void +do_ident (pfile) + cpp_reader *pfile; +{ + cpp_token str; + + cpp_get_token (pfile, &str); + if (str.type != CPP_STRING) + cpp_error (pfile, "invalid #ident"); + else if (pfile->cb.ident) + (*pfile->cb.ident) (pfile, &str.val.str); + + check_eol (pfile); +} + +/* Pragmata handling. We handle some of these, and pass the rest on + to the front end. C99 defines three pragmas and says that no macro + expansion is to be performed on them; whether or not macro + expansion happens for other pragmas is implementation defined. + This implementation never macro-expands the text after #pragma. */ + +/* Sub-handlers for the pragmas needing treatment here. + They return 1 if the token buffer is to be popped, 0 if not. */ +struct pragma_entry +{ + struct pragma_entry *next; + const char *name; + size_t len; + int isnspace; + union { + void (*handler) PARAMS ((cpp_reader *)); + struct pragma_entry *space; + } u; +}; + +void +cpp_register_pragma (pfile, space, name, handler) + cpp_reader *pfile; + const char *space; + const char *name; + void (*handler) PARAMS ((cpp_reader *)); +{ + struct pragma_entry **x, *new; + size_t len; + + x = &pfile->pragmas; + if (space) + { + struct pragma_entry *p = pfile->pragmas; + len = strlen (space); + while (p) + { + if (p->isnspace && p->len == len && !memcmp (p->name, space, len)) + { + x = &p->u.space; + goto found; + } + p = p->next; + } + cpp_ice (pfile, "unknown #pragma namespace %s", space); + return; + } + + found: + new = xnew (struct pragma_entry); + new->name = name; + new->len = strlen (name); + new->isnspace = 0; + new->u.handler = handler; + + new->next = *x; + *x = new; +} + +void +cpp_register_pragma_space (pfile, space) + cpp_reader *pfile; + const char *space; +{ + struct pragma_entry *new; + const struct pragma_entry *p = pfile->pragmas; + size_t len = strlen (space); + + while (p) + { + if (p->isnspace && p->len == len && !memcmp (p->name, space, len)) + /* Multiple different callers are allowed to register the same + namespace. */ + return; + p = p->next; + } + + new = xnew (struct pragma_entry); + new->name = space; + new->len = len; + new->isnspace = 1; + new->u.space = 0; + + new->next = pfile->pragmas; + pfile->pragmas = new; +} + +void +_cpp_init_internal_pragmas (pfile) + cpp_reader *pfile; +{ + /* top level */ + cpp_register_pragma (pfile, 0, "poison", do_pragma_poison); + cpp_register_pragma (pfile, 0, "once", do_pragma_once); + + /* GCC namespace */ + cpp_register_pragma_space (pfile, "GCC"); + + cpp_register_pragma (pfile, "GCC", "poison", do_pragma_poison); + cpp_register_pragma (pfile, "GCC", "system_header", do_pragma_system_header); + cpp_register_pragma (pfile, "GCC", "dependency", do_pragma_dependency); +} + +static void +do_pragma (pfile) + cpp_reader *pfile; +{ + const struct pragma_entry *p; + cpp_token tok; + int drop = 0; + + p = pfile->pragmas; + pfile->state.prevent_expansion++; + cpp_start_lookahead (pfile); + + new_space: + cpp_get_token (pfile, &tok); + if (tok.type == CPP_NAME) + { + const cpp_hashnode *node = tok.val.node; + size_t len = NODE_LEN (node); + + while (p) + { + if (strlen (p->name) == len + && !memcmp (p->name, NODE_NAME (node), len)) + { + if (p->isnspace) + { + p = p->u.space; + goto new_space; + } + else + { + (*p->u.handler) (pfile); + drop = 1; + break; + } + } + p = p->next; + } + } + + cpp_stop_lookahead (pfile, drop); + pfile->state.prevent_expansion--; + + if (!drop && pfile->cb.def_pragma) + (*pfile->cb.def_pragma) (pfile); +} + +static void +do_pragma_once (pfile) + cpp_reader *pfile; +{ + cpp_warning (pfile, "#pragma once is obsolete"); + + if (pfile->buffer->prev == NULL) + cpp_warning (pfile, "#pragma once in main file"); + else + _cpp_never_reread (pfile->buffer->inc); + + check_eol (pfile); +} + +static void +do_pragma_poison (pfile) + cpp_reader *pfile; +{ + /* Poison these symbols so that all subsequent usage produces an + error message. */ + cpp_token tok; + cpp_hashnode *hp; + + pfile->state.poisoned_ok = 1; + for (;;) + { + _cpp_lex_token (pfile, &tok); + if (tok.type == CPP_EOF) + break; + if (tok.type != CPP_NAME) + { + cpp_error (pfile, "invalid #pragma GCC poison directive"); + break; + } + + hp = tok.val.node; + if (hp->flags & NODE_POISONED) + continue; + + if (hp->type == NT_MACRO) + cpp_warning (pfile, "poisoning existing macro \"%s\"", NODE_NAME (hp)); + _cpp_free_definition (hp); + hp->flags |= NODE_POISONED | NODE_DIAGNOSTIC; + } + pfile->state.poisoned_ok = 0; + +#if 0 /* Doesn't quite work yet. */ + if (tok.type == CPP_EOF && pfile->cb.poison) + (*pfile->cb.poison) (pfile); +#endif +} + +/* Mark the current header as a system header. This will suppress + some categories of warnings (notably those from -pedantic). It is + intended for use in system libraries that cannot be implemented in + conforming C, but cannot be certain that their headers appear in a + system include directory. To prevent abuse, it is rejected in the + primary source file. */ +static void +do_pragma_system_header (pfile) + cpp_reader *pfile; +{ + cpp_buffer *buffer = pfile->buffer; + + if (buffer->prev == 0) + cpp_warning (pfile, "#pragma system_header ignored outside include file"); + else + cpp_make_system_header (pfile, 1, 0); + + check_eol (pfile); +} + +/* Check the modified date of the current include file against a specified + file. Issue a diagnostic, if the specified file is newer. We use this to + determine if a fixed header should be refixed. */ +static void +do_pragma_dependency (pfile) + cpp_reader *pfile; +{ + cpp_token header, msg; + int ordering; + + if (parse_include (pfile, &header)) + return; + + ordering = _cpp_compare_file_date (pfile, &header); + if (ordering < 0) + cpp_warning (pfile, "cannot find source %s", + cpp_token_as_text (pfile, &header)); + else if (ordering > 0) + { + cpp_warning (pfile, "current file is older than %s", + cpp_token_as_text (pfile, &header)); + cpp_start_lookahead (pfile); + cpp_get_token (pfile, &msg); + cpp_stop_lookahead (pfile, msg.type == CPP_EOF); + if (msg.type != CPP_EOF) + do_diagnostic (pfile, WARNING, 0); + } +} + +/* Check syntax is "(string-literal)". Returns 0 on success. */ +static int +get__Pragma_string (pfile, string) + cpp_reader *pfile; + cpp_token *string; +{ + cpp_token paren; + + cpp_get_token (pfile, &paren); + if (paren.type != CPP_OPEN_PAREN) + return 1; + + cpp_get_token (pfile, string); + if (string->type != CPP_STRING && string->type != CPP_WSTRING) + return 1; + + cpp_get_token (pfile, &paren); + return paren.type != CPP_CLOSE_PAREN; +} + +/* Returns a malloced buffer containing a destringized cpp_string by + removing the first \ of \" and \\ sequences. */ +static unsigned char * +destringize (in, len) + const cpp_string *in; + unsigned int *len; +{ + const unsigned char *src, *limit; + unsigned char *dest, *result; + + dest = result = (unsigned char *) xmalloc (in->len); + for (src = in->text, limit = src + in->len; src < limit;) + { + /* We know there is a character following the backslash. */ + if (*src == '\\' && (src[1] == '\\' || src[1] == '"')) + src++; + *dest++ = *src++; + } + + *len = dest - result; + return result; +} + +void +_cpp_do__Pragma (pfile) + cpp_reader *pfile; +{ + cpp_token string; + unsigned char *buffer; + unsigned int len; + + if (get__Pragma_string (pfile, &string)) + { + cpp_error (pfile, "_Pragma takes a parenthesized string literal"); + return; + } + + buffer = destringize (&string.val.str, &len); + run_directive (pfile, T_PRAGMA, BUF_PRAGMA, (char *) buffer, len); + free ((PTR) buffer); +} + +/* Just ignore #sccs, on systems where we define it at all. */ +#ifdef SCCS_DIRECTIVE +static void +do_sccs (pfile) + cpp_reader *pfile ATTRIBUTE_UNUSED; +{ +} +#endif + +static void +do_ifdef (pfile) + cpp_reader *pfile; +{ + int skip = 1; + + if (! pfile->buffer->was_skipping) + { + const cpp_hashnode *node = lex_macro_node (pfile); + + if (node) + skip = node->type != NT_MACRO; + + if (node) + check_eol (pfile); + } + + push_conditional (pfile, skip, T_IFDEF, 0); +} + +static void +do_ifndef (pfile) + cpp_reader *pfile; +{ + int skip = 1; + const cpp_hashnode *node = 0; + + if (! pfile->buffer->was_skipping) + { + node = lex_macro_node (pfile); + if (node) + skip = node->type == NT_MACRO; + + if (node) + check_eol (pfile); + } + + push_conditional (pfile, skip, T_IFNDEF, node); +} + +/* #if cooperates with parse_defined to handle multiple-include + optimisations. If macro expansions or identifiers appear in the + expression, we cannot treat it as a controlling conditional, since + their values could change in the future. */ + +static void +do_if (pfile) + cpp_reader *pfile; +{ + int skip = 1; + const cpp_hashnode *cmacro = 0; + + if (! pfile->buffer->was_skipping) + { + /* Controlling macro of #if ! defined () */ + pfile->mi_ind_cmacro = 0; + skip = _cpp_parse_expr (pfile) == 0; + cmacro = pfile->mi_ind_cmacro; + } + + push_conditional (pfile, skip, T_IF, cmacro); +} + +/* Flip skipping state if appropriate and continue without changing + if_stack; this is so that the error message for missing #endif's + etc. will point to the original #if. */ + +static void +do_else (pfile) + cpp_reader *pfile; +{ + cpp_buffer *buffer = pfile->buffer; + struct if_stack *ifs = buffer->if_stack; + + if (ifs == NULL) + cpp_error (pfile, "#else without #if"); + else + { + if (ifs->type == T_ELSE) + { + cpp_error (pfile, "#else after #else"); + cpp_error_with_line (pfile, ifs->pos.line, ifs->pos.col, + "the conditional began here"); + } + ifs->type = T_ELSE; + + /* Buffer->was_skipping is 1 if all conditionals in this chain + have been false, 2 if a conditional has been true. */ + if (! ifs->was_skipping && buffer->was_skipping != 2) + buffer->was_skipping = ! buffer->was_skipping; + + /* Invalidate any controlling macro. */ + ifs->mi_cmacro = 0; + } + + check_eol (pfile); +} + +/* handle a #elif directive by not changing if_stack either. see the + comment above do_else. */ + +static void +do_elif (pfile) + cpp_reader *pfile; +{ + cpp_buffer *buffer = pfile->buffer; + struct if_stack *ifs = buffer->if_stack; + + if (ifs == NULL) + cpp_error (pfile, "#elif without #if"); + else + { + if (ifs->type == T_ELSE) + { + cpp_error (pfile, "#elif after #else"); + cpp_error_with_line (pfile, ifs->pos.line, ifs->pos.col, + "the conditional began here"); + } + ifs->type = T_ELIF; + + /* Don't evaluate #elif if our higher level is skipping. */ + if (! ifs->was_skipping) + { + /* Buffer->was_skipping is 1 if all conditionals in this + chain have been false, 2 if a conditional has been true. */ + if (buffer->was_skipping == 1) + buffer->was_skipping = ! _cpp_parse_expr (pfile); + else + buffer->was_skipping = 2; + + /* Invalidate any controlling macro. */ + ifs->mi_cmacro = 0; + } + } +} + +/* #endif pops the if stack and resets pfile->skipping. */ + +static void +do_endif (pfile) + cpp_reader *pfile; +{ + cpp_buffer *buffer = pfile->buffer; + struct if_stack *ifs = buffer->if_stack; + + if (ifs == NULL) + cpp_error (pfile, "#endif without #if"); + else + { + /* If potential control macro, we go back outside again. */ + if (ifs->next == 0 && ifs->mi_cmacro) + { + pfile->mi_state = MI_OUTSIDE; + pfile->mi_cmacro = ifs->mi_cmacro; + } + + buffer->if_stack = ifs->next; + buffer->was_skipping = ifs->was_skipping; + obstack_free (&pfile->buffer_ob, ifs); + } + + check_eol (pfile); +} + +/* Push an if_stack entry and set pfile->skipping accordingly. + If this is a #ifndef starting at the beginning of a file, + CMACRO is the macro name tested by the #ifndef. */ + +static void +push_conditional (pfile, skip, type, cmacro) + cpp_reader *pfile; + int skip; + int type; + const cpp_hashnode *cmacro; +{ + struct if_stack *ifs; + cpp_buffer *buffer = pfile->buffer; + + ifs = xobnew (&pfile->buffer_ob, struct if_stack); + ifs->pos = pfile->directive_pos; + ifs->next = buffer->if_stack; + ifs->was_skipping = buffer->was_skipping; + ifs->type = type; + if (pfile->mi_state == MI_OUTSIDE && pfile->mi_cmacro == 0) + ifs->mi_cmacro = cmacro; + else + ifs->mi_cmacro = 0; + + buffer->was_skipping = skip; + buffer->if_stack = ifs; +} + +/* Read the tokens of the answer into the macro pool. Only commit the + memory if we intend it as permanent storage, i.e. the #assert case. + Returns 0 on success. */ + +static int +parse_answer (pfile, answerp, type) + cpp_reader *pfile; + struct answer **answerp; + int type; +{ + cpp_token paren, *token; + struct answer *answer; + + if (POOL_FRONT (&pfile->macro_pool) + sizeof (struct answer) > + POOL_LIMIT (&pfile->macro_pool)) + _cpp_next_chunk (&pfile->macro_pool, sizeof (struct answer), 0); + answer = (struct answer *) POOL_FRONT (&pfile->macro_pool); + answer->count = 0; + + /* In a conditional, it is legal to not have an open paren. We + should save the following token in this case. */ + if (type == T_IF) + cpp_start_lookahead (pfile); + cpp_get_token (pfile, &paren); + if (type == T_IF) + cpp_stop_lookahead (pfile, paren.type == CPP_OPEN_PAREN); + + /* If not a paren, see if we're OK. */ + if (paren.type != CPP_OPEN_PAREN) + { + /* In a conditional no answer is a test for any answer. It + could be followed by any token. */ + if (type == T_IF) + return 0; + + /* #unassert with no answer is valid - it removes all answers. */ + if (type == T_UNASSERT && paren.type == CPP_EOF) + return 0; + + cpp_error (pfile, "missing '(' after predicate"); + return 1; + } + + for (;;) + { + token = &answer->first[answer->count]; + /* Check we have room for the token. */ + if ((unsigned char *) (token + 1) >= POOL_LIMIT (&pfile->macro_pool)) + { + _cpp_next_chunk (&pfile->macro_pool, sizeof (cpp_token), + (unsigned char **) &answer); + token = &answer->first[answer->count]; + } + + cpp_get_token (pfile, token); + if (token->type == CPP_CLOSE_PAREN) + break; + + if (token->type == CPP_EOF) + { + cpp_error (pfile, "missing ')' to complete answer"); + return 1; + } + answer->count++; + } + + if (answer->count == 0) + { + cpp_error (pfile, "predicate's answer is empty"); + return 1; + } + + /* Drop whitespace at start. */ + answer->first->flags &= ~PREV_WHITE; + *answerp = answer; + + if (type == T_ASSERT || type == T_UNASSERT) + check_eol (pfile); + return 0; +} + +/* Parses an assertion, returning a pointer to the hash node of the + predicate, or 0 on error. If an answer was supplied, it is placed + in ANSWERP, otherwise it is set to 0. */ +static cpp_hashnode * +parse_assertion (pfile, answerp, type) + cpp_reader *pfile; + struct answer **answerp; + int type; +{ + cpp_hashnode *result = 0; + cpp_token predicate; + + /* We don't expand predicates or answers. */ + pfile->state.prevent_expansion++; + + *answerp = 0; + cpp_get_token (pfile, &predicate); + if (predicate.type == CPP_EOF) + cpp_error (pfile, "assertion without predicate"); + else if (predicate.type != CPP_NAME) + cpp_error (pfile, "predicate must be an identifier"); + else if (parse_answer (pfile, answerp, type) == 0) + { + unsigned int len = NODE_LEN (predicate.val.node); + unsigned char *sym = alloca (len + 1); + + /* Prefix '#' to get it out of macro namespace. */ + sym[0] = '#'; + memcpy (sym + 1, NODE_NAME (predicate.val.node), len); + result = cpp_lookup (pfile, sym, len + 1); + } + + pfile->state.prevent_expansion--; + return result; +} + +/* Returns a pointer to the pointer to the answer in the answer chain, + or a pointer to NULL if the answer is not in the chain. */ +static struct answer ** +find_answer (node, candidate) + cpp_hashnode *node; + const struct answer *candidate; +{ + unsigned int i; + struct answer **result; + + for (result = &node->value.answers; *result; result = &(*result)->next) + { + struct answer *answer = *result; + + if (answer->count == candidate->count) + { + for (i = 0; i < answer->count; i++) + if (! _cpp_equiv_tokens (&answer->first[i], &candidate->first[i])) + break; + + if (i == answer->count) + break; + } + } + + return result; +} + +/* Test an assertion within a preprocessor conditional. Returns + non-zero on failure, zero on success. On success, the result of + the test is written into VALUE. */ +int +_cpp_test_assertion (pfile, value) + cpp_reader *pfile; + int *value; +{ + struct answer *answer; + cpp_hashnode *node; + + node = parse_assertion (pfile, &answer, T_IF); + if (node) + *value = (node->type == NT_ASSERTION && + (answer == 0 || *find_answer (node, answer) != 0)); + + /* We don't commit the memory for the answer - it's temporary only. */ + return node == 0; +} + +static void +do_assert (pfile) + cpp_reader *pfile; +{ + struct answer *new_answer; + cpp_hashnode *node; + + node = parse_assertion (pfile, &new_answer, T_ASSERT); + if (node) + { + /* Place the new answer in the answer list. First check there + is not a duplicate. */ + new_answer->next = 0; + if (node->type == NT_ASSERTION) + { + if (*find_answer (node, new_answer)) + { + cpp_warning (pfile, "\"%s\" re-asserted", NODE_NAME (node) + 1); + return; + } + new_answer->next = node->value.answers; + } + node->type = NT_ASSERTION; + node->value.answers = new_answer; + POOL_COMMIT (&pfile->macro_pool, (sizeof (struct answer) + + (new_answer->count - 1) + * sizeof (cpp_token))); + } +} + +static void +do_unassert (pfile) + cpp_reader *pfile; +{ + cpp_hashnode *node; + struct answer *answer; + + node = parse_assertion (pfile, &answer, T_UNASSERT); + /* It isn't an error to #unassert something that isn't asserted. */ + if (node && node->type == NT_ASSERTION) + { + if (answer) + { + struct answer **p = find_answer (node, answer), *temp; + + /* Remove the answer from the list. */ + temp = *p; + if (temp) + *p = temp->next; + + /* Did we free the last answer? */ + if (node->value.answers == 0) + node->type = NT_VOID; + } + else + _cpp_free_definition (node); + } + + /* We don't commit the memory for the answer - it's temporary only. */ +} + +/* These are for -D, -U, -A. */ + +/* Process the string STR as if it appeared as the body of a #define. + If STR is just an identifier, define it with value 1. + If STR has anything after the identifier, then it should + be identifier=definition. */ + +void +cpp_define (pfile, str) + cpp_reader *pfile; + const char *str; +{ + char *buf, *p; + size_t count; + + /* Copy the entire option so we can modify it. + Change the first "=" in the string to a space. If there is none, + tack " 1" on the end. */ + + /* Length including the null. */ + count = strlen (str); + buf = (char *) alloca (count + 2); + memcpy (buf, str, count); + + p = strchr (str, '='); + if (p) + buf[p - str] = ' '; + else + { + buf[count++] = ' '; + buf[count++] = '1'; + } + + run_directive (pfile, T_DEFINE, BUF_CL_OPTION, buf, count); +} + +/* Slight variant of the above for use by initialize_builtins. */ +void +_cpp_define_builtin (pfile, str) + cpp_reader *pfile; + const char *str; +{ + run_directive (pfile, T_DEFINE, BUF_BUILTIN, str, strlen (str)); +} + +/* Process MACRO as if it appeared as the body of an #undef. */ +void +cpp_undef (pfile, macro) + cpp_reader *pfile; + const char *macro; +{ + run_directive (pfile, T_UNDEF, BUF_CL_OPTION, macro, strlen (macro)); +} + +/* Process the string STR as if it appeared as the body of a #assert. */ +void +cpp_assert (pfile, str) + cpp_reader *pfile; + const char *str; +{ + handle_assertion (pfile, str, T_ASSERT); +} + +/* Process STR as if it appeared as the body of an #unassert. */ +void +cpp_unassert (pfile, str) + cpp_reader *pfile; + const char *str; +{ + handle_assertion (pfile, str, T_UNASSERT); +} + +/* Common code for cpp_assert (-A) and cpp_unassert (-A-). */ +static void +handle_assertion (pfile, str, type) + cpp_reader *pfile; + const char *str; + int type; +{ + size_t count = strlen (str); + const char *p = strchr (str, '='); + + if (p) + { + /* Copy the entire option so we can modify it. Change the first + "=" in the string to a '(', and tack a ')' on the end. */ + char *buf = (char *) alloca (count + 1); + + memcpy (buf, str, count); + buf[p - str] = '('; + buf[count++] = ')'; + str = buf; + } + + run_directive (pfile, type, BUF_CL_OPTION, str, count); +} + +/* The number of errors for a given reader. */ +unsigned int +cpp_errors (pfile) + cpp_reader *pfile; +{ + return pfile->errors; +} + +/* The options structure. */ +cpp_options * +cpp_get_options (pfile) + cpp_reader *pfile; +{ + return &pfile->opts; +} + +/* The callbacks structure. */ +cpp_callbacks * +cpp_get_callbacks (pfile) + cpp_reader *pfile; +{ + return &pfile->cb; +} + +/* Copy the given callbacks structure to our own. */ +void +cpp_set_callbacks (pfile, cb) + cpp_reader *pfile; + cpp_callbacks *cb; +{ + pfile->cb = *cb; +} + +/* Push a new buffer on the buffer stack. Returns the new buffer; it + doesn't fail. It does not generate a file change call back; that + is the responsibility of the caller. */ +cpp_buffer * +cpp_push_buffer (pfile, buffer, len, type, filename) + cpp_reader *pfile; + const U_CHAR *buffer; + size_t len; + enum cpp_buffer_type type; + const char *filename; +{ + cpp_buffer *new = xobnew (&pfile->buffer_ob, cpp_buffer); + + if (type == BUF_FAKE) + { + /* A copy of the current buffer, just with a new name and type. */ + memcpy (new, pfile->buffer, sizeof (cpp_buffer)); + new->type = BUF_FAKE; + } + else + { + if (type == BUF_BUILTIN) + filename = _(""); + else if (type == BUF_CL_OPTION) + filename = _(""); + else if (type == BUF_PRAGMA) + filename = "<_Pragma>"; + + /* Clears, amongst other things, if_stack and mi_cmacro. */ + memset (new, 0, sizeof (cpp_buffer)); + + new->line_base = new->buf = new->cur = buffer; + new->rlimit = buffer + len; + new->sysp = 0; + + /* No read ahead or extra char initially. */ + new->read_ahead = EOF; + new->extra_char = EOF; + + /* Preprocessed files, builtins, _Pragma and command line + options don't do trigraph and escaped newline processing. */ + new->from_stage3 = type != BUF_FILE || CPP_OPTION (pfile, preprocessed); + + pfile->lexer_pos.output_line = 1; + } + + if (*filename == '\0') + new->nominal_fname = _(""); + else + new->nominal_fname = filename; + new->type = type; + new->prev = pfile->buffer; + new->pfile = pfile; + new->include_stack_listed = 0; + new->lineno = 1; + + pfile->state.next_bol = 1; + pfile->buffer_stack_depth++; + pfile->buffer = new; + + return new; +} + +/* If called from do_line, pops a single buffer. Otherwise pops all + buffers until a real file is reached. Generates appropriate + call-backs. */ +cpp_buffer * +cpp_pop_buffer (pfile) + cpp_reader *pfile; +{ + cpp_buffer *buffer; + struct if_stack *ifs; + + for (;;) + { + buffer = pfile->buffer; + /* Walk back up the conditional stack till we reach its level at + entry to this file, issuing error messages. */ + for (ifs = buffer->if_stack; ifs; ifs = ifs->next) + cpp_error_with_line (pfile, ifs->pos.line, ifs->pos.col, + "unterminated #%s", dtable[ifs->type].name); + + if (buffer->type == BUF_FAKE) + buffer->prev->cur = buffer->cur; + else if (buffer->type == BUF_FILE) + _cpp_pop_file_buffer (pfile, buffer); + + pfile->buffer = buffer->prev; + pfile->buffer_stack_depth--; + + /* Callbacks only generated for faked or real files. */ + if (buffer->type != BUF_FILE && buffer->type != BUF_FAKE) + break; + + /* No callback for EOF of last file. */ + if (!pfile->buffer) + break; + + /* do_line does its own call backs. */ + pfile->buffer->include_stack_listed = 0; + if (pfile->directive == &dtable[T_LINE]) + break; + + _cpp_do_file_change (pfile, FC_LEAVE, buffer->nominal_fname, + buffer->lineno); + if (pfile->buffer->type == BUF_FILE) + break; + + cpp_warning (pfile, "file \"%s\" entered but not left", + buffer->nominal_fname); + } + + obstack_free (&pfile->buffer_ob, buffer); + return pfile->buffer; +} + +void +_cpp_init_directives (pfile) + cpp_reader *pfile; +{ + unsigned int i; + cpp_hashnode *node; + + /* Register the directives. */ + for (i = 0; i < (unsigned int) N_DIRECTIVES; i++) + { + node = cpp_lookup (pfile, dtable[i].name, dtable[i].length); + node->directive_index = i + 1; + } +} diff --git a/support/cpp2/cpplib.h b/support/cpp2/cpplib.h new file mode 100644 index 00000000..c05b5e2e --- /dev/null +++ b/support/cpp2/cpplib.h @@ -0,0 +1,635 @@ +/* Definitions for CPP library. + Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001 + Free Software Foundation, Inc. + Written by Per Bothner, 1994-95. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! */ +#ifndef GCC_CPPLIB_H +#define GCC_CPPLIB_H + +#include +#include "hashtable.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* For complex reasons, cpp_reader is also typedefed in c-pragma.h. */ +#ifndef GCC_C_PRAGMA_H +typedef struct cpp_reader cpp_reader; +#endif +typedef struct cpp_buffer cpp_buffer; +typedef struct cpp_options cpp_options; +typedef struct cpp_token cpp_token; +typedef struct cpp_string cpp_string; +typedef struct cpp_hashnode cpp_hashnode; +typedef struct cpp_macro cpp_macro; +typedef struct cpp_lexer_pos cpp_lexer_pos; +typedef struct cpp_lookahead cpp_lookahead; +typedef struct cpp_callbacks cpp_callbacks; + +struct answer; +struct file_name_map_list; +struct ht; + +/* The first two groups, apart from '=', can appear in preprocessor + expressions. This allows a lookup table to be implemented in + _cpp_parse_expr. + + The first group, to CPP_LAST_EQ, can be immediately followed by an + '='. The lexer needs operators ending in '=', like ">>=", to be in + the same order as their counterparts without the '=', like ">>". */ + +/* Positions in the table. */ +#define CPP_LAST_EQ CPP_MAX +#define CPP_FIRST_DIGRAPH CPP_HASH +#define CPP_LAST_PUNCTUATOR CPP_DOT_STAR + +#define TTYPE_TABLE \ + OP(CPP_EQ = 0, "=") \ + OP(CPP_NOT, "!") \ + OP(CPP_GREATER, ">") /* compare */ \ + OP(CPP_LESS, "<") \ + OP(CPP_PLUS, "+") /* math */ \ + OP(CPP_MINUS, "-") \ + OP(CPP_MULT, "*") \ + OP(CPP_DIV, "/") \ + OP(CPP_MOD, "%") \ + OP(CPP_AND, "&") /* bit ops */ \ + OP(CPP_OR, "|") \ + OP(CPP_XOR, "^") \ + OP(CPP_RSHIFT, ">>") \ + OP(CPP_LSHIFT, "<<") \ + OP(CPP_MIN, "?") \ +\ + OP(CPP_COMPL, "~") \ + OP(CPP_AND_AND, "&&") /* logical */ \ + OP(CPP_OR_OR, "||") \ + OP(CPP_QUERY, "?") \ + OP(CPP_COLON, ":") \ + OP(CPP_COMMA, ",") /* grouping */ \ + OP(CPP_OPEN_PAREN, "(") \ + OP(CPP_CLOSE_PAREN, ")") \ + OP(CPP_EQ_EQ, "==") /* compare */ \ + OP(CPP_NOT_EQ, "!=") \ + OP(CPP_GREATER_EQ, ">=") \ + OP(CPP_LESS_EQ, "<=") \ +\ + OP(CPP_PLUS_EQ, "+=") /* math */ \ + OP(CPP_MINUS_EQ, "-=") \ + OP(CPP_MULT_EQ, "*=") \ + OP(CPP_DIV_EQ, "/=") \ + OP(CPP_MOD_EQ, "%=") \ + OP(CPP_AND_EQ, "&=") /* bit ops */ \ + OP(CPP_OR_EQ, "|=") \ + OP(CPP_XOR_EQ, "^=") \ + OP(CPP_RSHIFT_EQ, ">>=") \ + OP(CPP_LSHIFT_EQ, "<<=") \ + OP(CPP_MIN_EQ, "?=") \ + /* Digraphs together, beginning with CPP_FIRST_DIGRAPH. */ \ + OP(CPP_HASH, "#") /* digraphs */ \ + OP(CPP_PASTE, "##") \ + OP(CPP_OPEN_SQUARE, "[") \ + OP(CPP_CLOSE_SQUARE, "]") \ + OP(CPP_OPEN_BRACE, "{") \ + OP(CPP_CLOSE_BRACE, "}") \ + /* The remainder of the punctuation. Order is not significant. */ \ + OP(CPP_SEMICOLON, ";") /* structure */ \ + OP(CPP_ELLIPSIS, "...") \ + OP(CPP_PLUS_PLUS, "++") /* increment */ \ + OP(CPP_MINUS_MINUS, "--") \ + OP(CPP_DEREF, "->") /* accessors */ \ + OP(CPP_DOT, ".") \ + OP(CPP_SCOPE, "::") \ + OP(CPP_DEREF_STAR, "->*") \ + OP(CPP_DOT_STAR, ".*") \ + OP(CPP_ATSIGN, "@") /* used in Objective C */ \ +\ + TK(CPP_NAME, SPELL_IDENT) /* word */ \ + TK(CPP_INT, SPELL_STRING) /* 23 */ \ + TK(CPP_FLOAT, SPELL_STRING) /* 3.14159 */ \ + TK(CPP_NUMBER, SPELL_STRING) /* 34_be+ta */ \ +\ + TK(CPP_CHAR, SPELL_STRING) /* 'char' */ \ + TK(CPP_WCHAR, SPELL_STRING) /* L'char' */ \ + TK(CPP_OTHER, SPELL_CHAR) /* stray punctuation */ \ +\ + TK(CPP_STRING, SPELL_STRING) /* "string" */ \ + TK(CPP_WSTRING, SPELL_STRING) /* L"string" */ \ + TK(CPP_HEADER_NAME, SPELL_STRING) /* in #include */ \ +\ + TK(CPP_COMMENT, SPELL_STRING) /* Only if output comments. */ \ + TK(CPP_MACRO_ARG, SPELL_NONE) /* Macro argument. */ \ + OP(CPP_EOF, "EOL") /* End of line or file. */ + +#define OP(e, s) e, +#define TK(e, s) e, +enum cpp_ttype +{ + TTYPE_TABLE + N_TTYPES +}; +#undef OP +#undef TK + +/* C language kind, used when calling cpp_reader_init. */ +enum c_lang {CLK_GNUC89 = 0, CLK_GNUC99, CLK_STDC89, CLK_STDC94, CLK_STDC99, + CLK_GNUCXX, CLK_CXX98, CLK_OBJC, CLK_OBJCXX, CLK_ASM}; + +/* Payload of a NUMBER, FLOAT, STRING, or COMMENT token. */ +struct cpp_string +{ + unsigned int len; + const unsigned char *text; +}; + +/* Flags for the cpp_token structure. */ +#define PREV_WHITE (1 << 0) /* If whitespace before this token. */ +#define DIGRAPH (1 << 1) /* If it was a digraph. */ +#define STRINGIFY_ARG (1 << 2) /* If macro argument to be stringified. */ +#define PASTE_LEFT (1 << 3) /* If on LHS of a ## operator. */ +#define NAMED_OP (1 << 4) /* C++ named operators. */ +#define NO_EXPAND (1 << 5) /* Do not macro-expand this token. */ +#define AVOID_LPASTE (1 << 6) /* Check left for accidental pastes. */ + +/* A preprocessing token. This has been carefully packed and should + occupy 12 bytes on 32-bit hosts and 16 bytes on 64-bit hosts. */ +struct cpp_token +{ + ENUM_BITFIELD(cpp_ttype) type : CHAR_BIT; /* token type */ + unsigned char flags; /* flags - see above */ + + union + { + cpp_hashnode *node; /* An identifier. */ + struct cpp_string str; /* A string, or number. */ + unsigned int arg_no; /* Argument no. for a CPP_MACRO_ARG. */ + unsigned char c; /* Character represented by CPP_OTHER. */ + } val; +}; + +/* The position of a token in the current file. */ +struct cpp_lexer_pos +{ + unsigned int line; + unsigned int output_line; + unsigned short col; +}; + +typedef struct cpp_token_with_pos cpp_token_with_pos; +struct cpp_token_with_pos +{ + cpp_token token; + cpp_lexer_pos pos; +}; + +/* Token lookahead. */ +struct cpp_lookahead +{ + struct cpp_lookahead *next; + cpp_token_with_pos *tokens; + cpp_lexer_pos pos; + unsigned int cur, count, cap; +}; + +/* A standalone character. We may want to make it unsigned for the + same reason we use unsigned char - to avoid signedness issues. */ +typedef int cppchar_t; + +/* Values for opts.dump_macros. + dump_only means inhibit output of the preprocessed text + and instead output the definitions of all user-defined + macros in a form suitable for use as input to cpp. + dump_names means pass #define and the macro name through to output. + dump_definitions means pass the whole definition (plus #define) through +*/ +enum { dump_none = 0, dump_only, dump_names, dump_definitions }; + +/* This structure is nested inside struct cpp_reader, and + carries all the options visible to the command line. */ +struct cpp_options +{ + /* Name of input and output files. */ + const char *in_fname; + const char *out_fname; + + /* Characters between tab stops. */ + unsigned int tabstop; + + /* Pending options - -D, -U, -A, -I, -ixxx. */ + struct cpp_pending *pending; + + /* File name which deps are being written to. This is 0 if deps are + being written to stdout. */ + const char *deps_file; + + /* Search paths for include files. */ + struct search_path *quote_include; /* "" */ + struct search_path *bracket_include; /* <> */ + + /* Map between header names and file names, used only on DOS where + file names are limited in length. */ + struct file_name_map_list *map_list; + + /* Directory prefix that should replace `/usr/lib/gcc-lib/TARGET/VERSION' + in the standard include file directories. */ + const char *include_prefix; + unsigned int include_prefix_len; + + /* -fleading_underscore sets this to "_". */ + const char *user_label_prefix; + + /* The language we're preprocessing. */ + enum c_lang lang; + + /* Non-0 means -v, so print the full set of include dirs. */ + unsigned char verbose; + + /* Nonzero means use extra default include directories for C++. */ + unsigned char cplusplus; + + /* Nonzero means handle cplusplus style comments */ + unsigned char cplusplus_comments; + + /* Nonzero means handle #import, for objective C. */ + unsigned char objc; + + /* Nonzero means don't copy comments into the output file. */ + unsigned char discard_comments; + + /* Nonzero means process the ISO trigraph sequences. */ + unsigned char trigraphs; + + /* Nonzero means process the ISO digraph sequences. */ + unsigned char digraphs; + + /* Nonzero means to allow hexadecimal floats and LL suffixes. */ + unsigned char extended_numbers; + + /* Nonzero means print the names of included files rather than the + preprocessed output. 1 means just the #include "...", 2 means + #include <...> as well. */ + unsigned char print_deps; + + /* Nonzero if phony targets are created for each header. */ + unsigned char deps_phony_targets; + + /* Nonzero if missing .h files in -M output are assumed to be + generated files and not errors. */ + unsigned char print_deps_missing_files; + + /* If true, fopen (deps_file, "a") else fopen (deps_file, "w"). */ + unsigned char print_deps_append; + + /* Nonzero means print names of header files (-H). */ + unsigned char print_include_names; + + /* Nonzero means cpp_pedwarn causes a hard error. */ + unsigned char pedantic_errors; + + /* Nonzero means don't print warning messages. */ + unsigned char inhibit_warnings; + + /* Nonzero means don't suppress warnings from system headers. */ + unsigned char warn_system_headers; + + /* Nonzero means don't print error messages. Has no option to + select it, but can be set by a user of cpplib (e.g. fix-header). */ + unsigned char inhibit_errors; + + /* Nonzero means warn if slash-star appears in a comment. */ + unsigned char warn_comments; + + /* Nonzero means warn if there are any trigraphs. */ + unsigned char warn_trigraphs; + + /* Nonzero means warn if #import is used. */ + unsigned char warn_import; + + /* Nonzero means warn about various incompatibilities with + traditional C. */ + unsigned char warn_traditional; + + /* Nonzero means turn warnings into errors. */ + unsigned char warnings_are_errors; + + /* Nonzero causes output not to be done, but directives such as + #define that have side effects are still obeyed. */ + unsigned char no_output; + + /* Nonzero means we should look for header.gcc files that remap file + names. */ + unsigned char remap; + + /* Nonzero means don't output line number information. */ + unsigned char no_line_commands; + + /* Nonzero means -I- has been seen, so don't look for #include "foo" + the source-file directory. */ + unsigned char ignore_srcdir; + + /* Zero means dollar signs are punctuation. */ + unsigned char dollars_in_ident; + + /* Nonzero means warn if undefined identifiers are evaluated in an #if. */ + unsigned char warn_undef; + + /* Nonzero for the 1999 C Standard, including corrigenda and amendments. */ + unsigned char c99; + + /* Nonzero means give all the error messages the ANSI standard requires. */ + unsigned char pedantic; + + /* Nonzero means we're looking at already preprocessed code, so don't + bother trying to do macro expansion and whatnot. */ + unsigned char preprocessed; + + /* Nonzero disables all the standard directories for headers. */ + unsigned char no_standard_includes; + + /* Nonzero disables the C++-specific standard directories for headers. */ + unsigned char no_standard_cplusplus_includes; + + /* Nonzero means dump macros in some fashion - see above. */ + unsigned char dump_macros; + + /* Nonzero means pass #include lines through to the output. */ + unsigned char dump_includes; + + /* Print column number in error messages. */ + unsigned char show_column; + + /* Treat C++ alternate operator names special. */ + unsigned char operator_names; + + /* True if --help, --version or --target-help appeared in the + options. Stand-alone CPP should then bail out after option + parsing; drivers might want to continue printing help. */ + unsigned char help_only; +}; + +/* This structure is passed to the call back when changing file. */ +enum cpp_fc_reason {FC_ENTER = 0, FC_LEAVE, FC_RENAME}; + +struct cpp_file_loc +{ + const char *filename; + unsigned int lineno; +}; + +typedef struct cpp_file_change cpp_file_change; +struct cpp_file_change +{ + struct cpp_file_loc from; /* Line of #include or #line. */ + struct cpp_file_loc to; /* Line after #include or #line, or start. */ + enum cpp_fc_reason reason; /* Reason for change. */ + unsigned char sysp; /* Nonzero if system header. */ + unsigned char externc; /* Nonzero if wrapper needed. */ +}; + +/* Call backs. */ +struct cpp_callbacks +{ + void (*file_change) PARAMS ((cpp_reader *, const cpp_file_change *)); + void (*include) PARAMS ((cpp_reader *, const unsigned char *, + const cpp_token *)); + void (*define) PARAMS ((cpp_reader *, cpp_hashnode *)); + void (*undef) PARAMS ((cpp_reader *, cpp_hashnode *)); + void (*poison) PARAMS ((cpp_reader *)); + void (*ident) PARAMS ((cpp_reader *, const cpp_string *)); + void (*def_pragma) PARAMS ((cpp_reader *)); +}; + +#define CPP_FATAL_LIMIT 1000 +/* True if we have seen a "fatal" error. */ +#define CPP_FATAL_ERRORS(PFILE) (cpp_errors (PFILE) >= CPP_FATAL_LIMIT) + +/* Name under which this program was invoked. */ +extern const char *progname; + +/* Where does this buffer come from? A faked include, a source file, + a builtin macro, a command-line option, or a _Pragma operator. */ +enum cpp_buffer_type {BUF_FAKE, BUF_FILE, BUF_BUILTIN, + BUF_CL_OPTION, BUF_PRAGMA}; + +/* The structure of a node in the hash table. The hash table has + entries for all identifiers: either macros defined by #define + commands (type NT_MACRO), assertions created with #assert + (NT_ASSERTION), or neither of the above (NT_VOID). Builtin macros + like __LINE__ are flagged NODE_BUILTIN. Poisioned identifiers are + flagged NODE_POISONED. NODE_OPERATOR (C++ only) indicates an + identifier that behaves like an operator such as "xor". + NODE_DIAGNOSTIC is for speed in lex_token: it indicates a + diagnostic may be required for this node. Currently this only + applies to __VA_ARGS__ and poisoned identifiers. */ + +/* Hash node flags. */ +#define NODE_OPERATOR (1 << 0) /* C++ named operator. */ +#define NODE_POISONED (1 << 1) /* Poisoned identifier. */ +#define NODE_BUILTIN (1 << 2) /* Builtin macro. */ +#define NODE_DIAGNOSTIC (1 << 3) /* Possible diagnostic when lexed. */ +#define NODE_WARN (1 << 4) /* Warn if redefined or undefined. */ + +/* Different flavors of hash node. */ +enum node_type +{ + NT_VOID = 0, /* No definition yet. */ + NT_MACRO, /* A macro of some form. */ + NT_ASSERTION /* Predicate for #assert. */ +}; + +/* Different flavors of builtin macro. */ +enum builtin_type +{ + BT_SPECLINE = 0, /* `__LINE__' */ + BT_DATE, /* `__DATE__' */ + BT_FILE, /* `__FILE__' */ + BT_BASE_FILE, /* `__BASE_FILE__' */ + BT_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */ + BT_TIME, /* `__TIME__' */ + BT_STDC /* `__STDC__' */ +}; + +#define CPP_HASHNODE(HNODE) ((cpp_hashnode *) (HNODE)) +#define HT_NODE(NODE) ((ht_identifier *) (NODE)) +#define NODE_LEN(NODE) HT_LEN (&(NODE)->ident) +#define NODE_NAME(NODE) HT_STR (&(NODE)->ident) + +/* The common part of an identifier node shared amongst all 3 C front + ends. Also used to store CPP identifiers, which are a superset of + identifiers in the grammatical sense. */ +struct cpp_hashnode +{ + struct ht_identifier ident; + unsigned short arg_index; /* Macro argument index. */ + unsigned char directive_index; /* Index into directive table. */ + unsigned char rid_code; /* Rid code - for front ends. */ + ENUM_BITFIELD(node_type) type : 8; /* CPP node type. */ + unsigned char flags; /* CPP flags. */ + + union + { + cpp_macro *macro; /* If a macro. */ + struct answer *answers; /* Answers to an assertion. */ + enum cpp_ttype operator; /* Code for a named operator. */ + enum builtin_type builtin; /* Code for a builtin macro. */ + } value; +}; + +/* Call this first to get a handle to pass to other functions. If you + want cpplib to manage its own hashtable, pass in a NULL pointer. + Or you can pass in an initialised hash table that cpplib will use; + this technique is used by the C front ends. */ +extern cpp_reader *cpp_create_reader PARAMS ((struct ht *, + enum c_lang)); + +/* Call this to release the handle. Any use of the handle after this + function returns is invalid. Returns cpp_errors (pfile). */ +extern int cpp_destroy PARAMS ((cpp_reader *)); + +/* Call these to get pointers to the options and callback structures + for a given reader. These pointers are good until you call + cpp_finish on that reader. You can either edit the callbacks + through the pointer returned from cpp_get_callbacks, or set them + with cpp_set_callbacks. */ +extern cpp_options *cpp_get_options PARAMS ((cpp_reader *)); +extern cpp_callbacks *cpp_get_callbacks PARAMS ((cpp_reader *)); +extern void cpp_set_callbacks PARAMS ((cpp_reader *, cpp_callbacks *)); + +/* Now call cpp_handle_option[s] to handle 1[or more] switches. The + return value is the number of arguments used. If + cpp_handle_options returns without using all arguments, it couldn't + understand the next switch. When there are no switches left, you + must call cpp_post_options before calling cpp_start_read. Only + after cpp_post_options are the contents of the cpp_options + structure reliable. */ +extern int cpp_handle_options PARAMS ((cpp_reader *, int, char **)); +extern int cpp_handle_option PARAMS ((cpp_reader *, int, char **)); +extern void cpp_post_options PARAMS ((cpp_reader *)); + +/* Error count. */ +extern unsigned int cpp_errors PARAMS ((cpp_reader *)); + +extern unsigned int cpp_token_len PARAMS ((const cpp_token *)); +extern unsigned char *cpp_token_as_text PARAMS ((cpp_reader *, + const cpp_token *)); +extern unsigned char *cpp_spell_token PARAMS ((cpp_reader *, const cpp_token *, + unsigned char *)); +extern void cpp_register_pragma PARAMS ((cpp_reader *, + const char *, const char *, + void (*) PARAMS ((cpp_reader *)))); +extern void cpp_register_pragma_space PARAMS ((cpp_reader *, const char *)); + +extern int cpp_start_read PARAMS ((cpp_reader *, const char *)); +extern void cpp_finish PARAMS ((cpp_reader *)); +extern int cpp_avoid_paste PARAMS ((cpp_reader *, const cpp_token *, + const cpp_token *)); +extern enum cpp_ttype cpp_can_paste PARAMS ((cpp_reader *, const cpp_token *, + const cpp_token *, int *)); +extern void cpp_get_token PARAMS ((cpp_reader *, cpp_token *)); +extern const cpp_lexer_pos *cpp_get_line PARAMS ((cpp_reader *)); +extern const unsigned char *cpp_macro_definition PARAMS ((cpp_reader *, + const cpp_hashnode *)); + +/* Evaluate a CPP_CHAR or CPP_WCHAR token. */ +extern HOST_WIDE_INT +cpp_interpret_charconst PARAMS ((cpp_reader *, const cpp_token *, + int, int, unsigned int *)); + +extern void cpp_define PARAMS ((cpp_reader *, const char *)); +extern void cpp_assert PARAMS ((cpp_reader *, const char *)); +extern void cpp_undef PARAMS ((cpp_reader *, const char *)); +extern void cpp_unassert PARAMS ((cpp_reader *, const char *)); + +extern cpp_buffer *cpp_push_buffer PARAMS ((cpp_reader *, + const unsigned char *, size_t, + enum cpp_buffer_type, + const char *)); +extern cpp_buffer *cpp_pop_buffer PARAMS ((cpp_reader *)); +extern int cpp_defined PARAMS ((cpp_reader *, const unsigned char *, int)); + +/* N.B. The error-message-printer prototypes have not been nicely + formatted because exgettext needs to see 'msgid' on the same line + as the name of the function in order to work properly. Only the + string argument gets a name in an effort to keep the lines from + getting ridiculously oversized. */ + +extern void cpp_ice PARAMS ((cpp_reader *, const char *msgid, ...)) + ATTRIBUTE_PRINTF_2; +extern void cpp_fatal PARAMS ((cpp_reader *, const char *msgid, ...)) + ATTRIBUTE_PRINTF_2; +extern void cpp_error PARAMS ((cpp_reader *, const char *msgid, ...)) + ATTRIBUTE_PRINTF_2; +extern void cpp_warning PARAMS ((cpp_reader *, const char *msgid, ...)) + ATTRIBUTE_PRINTF_2; +extern void cpp_pedwarn PARAMS ((cpp_reader *, const char *msgid, ...)) + ATTRIBUTE_PRINTF_2; +extern void cpp_notice PARAMS ((cpp_reader *, const char *msgid, ...)) + ATTRIBUTE_PRINTF_2; +extern void cpp_error_with_line PARAMS ((cpp_reader *, int, int, const char *msgid, ...)) + ATTRIBUTE_PRINTF_4; +extern void cpp_warning_with_line PARAMS ((cpp_reader *, int, int, const char *msgid, ...)) + ATTRIBUTE_PRINTF_4; +extern void cpp_pedwarn_with_line PARAMS ((cpp_reader *, int, int, const char *msgid, ...)) + ATTRIBUTE_PRINTF_4; +extern void cpp_pedwarn_with_file_and_line PARAMS ((cpp_reader *, const char *, int, int, const char *msgid, ...)) + ATTRIBUTE_PRINTF_5; +extern void cpp_error_from_errno PARAMS ((cpp_reader *, const char *)); +extern void cpp_notice_from_errno PARAMS ((cpp_reader *, const char *)); + +/* In cpplex.c */ +extern int cpp_ideq PARAMS ((const cpp_token *, + const char *)); +extern void cpp_output_line PARAMS ((cpp_reader *, FILE *)); +extern void cpp_output_token PARAMS ((const cpp_token *, FILE *)); +extern const char *cpp_type2name PARAMS ((enum cpp_ttype)); +extern unsigned int cpp_parse_escape PARAMS ((cpp_reader *, + const unsigned char **, + const unsigned char *, + unsigned HOST_WIDE_INT, int)); + +/* In cpphash.c */ + +/* Lookup an identifier in the hashtable. Puts the identifier in the + table if it is not already there. */ +extern cpp_hashnode *cpp_lookup PARAMS ((cpp_reader *, + const unsigned char *, + unsigned int)); + +typedef int (*cpp_cb) PARAMS ((cpp_reader *, cpp_hashnode *, void *)); +extern void cpp_forall_identifiers PARAMS ((cpp_reader *, + cpp_cb, void *)); + +/* In cppmacro.c */ +extern void cpp_scan_buffer_nooutput PARAMS ((cpp_reader *, int)); +extern void cpp_start_lookahead PARAMS ((cpp_reader *)); +extern void cpp_stop_lookahead PARAMS ((cpp_reader *, int)); +extern int cpp_sys_macro_p PARAMS ((cpp_reader *)); + +/* In cppfiles.c */ +extern int cpp_included PARAMS ((cpp_reader *, const char *)); +extern void cpp_make_system_header PARAMS ((cpp_reader *, int, int)); + +#ifdef __cplusplus +} +#endif + +#endif /* ! GCC_CPPLIB_H */ diff --git a/support/cpp2/cppmacro.c b/support/cpp2/cppmacro.c new file mode 100644 index 00000000..e6308501 --- /dev/null +++ b/support/cpp2/cppmacro.c @@ -0,0 +1,1665 @@ +/* Part of CPP library. (Macro and #define handling.) + Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998, + 1999, 2000, 2001 Free Software Foundation, Inc. + Written by Per Bothner, 1994. + Based on CCCP program by Paul Rubin, June 1986 + Adapted to ANSI C, Richard Stallman, Jan 1987 + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! */ + +#include "config.h" +#include "system.h" +#include "intl.h" /* for _("") below. */ +#include "cpplib.h" +#include "cpphash.h" + +struct cpp_macro +{ + cpp_hashnode **params; /* Parameters, if any. */ + cpp_token *expansion; /* First token of replacement list. */ + const char *file; /* Defined in file name. */ + unsigned int line; /* Starting line number. */ + unsigned int count; /* Number of tokens in expansion. */ + unsigned short paramc; /* Number of parameters. */ + unsigned int fun_like : 1; /* If a function-like macro. */ + unsigned int variadic : 1; /* If a variadic macro. */ + unsigned int disabled : 1; /* If macro is disabled. */ + unsigned int syshdr : 1; /* If macro defined in system header. */ +}; + +typedef struct macro_arg macro_arg; +struct macro_arg +{ + cpp_token *first; /* First token in unexpanded argument. */ + cpp_token *expanded; /* Macro-expanded argument. */ + cpp_token *stringified; /* Stringified argument. */ + unsigned int count; /* # of tokens in argument. */ + unsigned int expanded_count; /* # of tokens in expanded argument. */ +}; + +/* Macro expansion. */ + +static void lock_pools PARAMS ((cpp_reader *)); +static void unlock_pools PARAMS ((cpp_reader *)); +static int enter_macro_context PARAMS ((cpp_reader *, cpp_hashnode *)); +static void builtin_macro PARAMS ((cpp_reader *, cpp_token *)); +static cpp_context *push_arg_context PARAMS ((cpp_reader *, macro_arg *)); +static enum cpp_ttype parse_arg PARAMS ((cpp_reader *, macro_arg *, int)); +static macro_arg *parse_args PARAMS ((cpp_reader *, const cpp_hashnode *)); +static cpp_context *next_context PARAMS ((cpp_reader *)); +static void expand_arg PARAMS ((cpp_reader *, macro_arg *)); +static unsigned char *quote_string PARAMS ((unsigned char *, + const unsigned char *, + unsigned int)); +static void make_string_token PARAMS ((cpp_pool *, cpp_token *, + const U_CHAR *, unsigned int)); +static void make_number_token PARAMS ((cpp_reader *, cpp_token *, int)); +static void stringify_arg PARAMS ((cpp_reader *, macro_arg *)); +static void paste_all_tokens PARAMS ((cpp_reader *, cpp_token *)); +static int paste_tokens PARAMS ((cpp_reader *, cpp_token *, cpp_token *)); +static int funlike_invocation_p PARAMS ((cpp_reader *, const cpp_hashnode *, + struct toklist *)); +static void replace_args PARAMS ((cpp_reader *, cpp_macro *, macro_arg *, + struct toklist *)); + +/* Lookaheads. */ + +static void save_lookahead_token PARAMS ((cpp_reader *, const cpp_token *)); +static void take_lookahead_token PARAMS ((cpp_reader *, cpp_token *)); +static cpp_lookahead *alloc_lookahead PARAMS ((cpp_reader *)); +static void free_lookahead PARAMS ((cpp_lookahead *)); + +/* #define directive parsing and handling. */ + +static cpp_token *lex_expansion_token PARAMS ((cpp_reader *, cpp_macro *)); +static int warn_of_redefinition PARAMS ((cpp_reader *, const cpp_hashnode *, + const cpp_macro *)); +static int save_parameter PARAMS ((cpp_reader *, cpp_macro *, cpp_hashnode *)); +static int parse_params PARAMS ((cpp_reader *, cpp_macro *)); +static void check_trad_stringification PARAMS ((cpp_reader *, + const cpp_macro *, + const cpp_string *)); + +/* Allocates a buffer to hold a token's TEXT, and converts TOKEN to a + CPP_STRING token containing TEXT in quoted form. */ +static void +make_string_token (pool, token, text, len) + cpp_pool *pool; + cpp_token *token; + const U_CHAR *text; + unsigned int len; +{ + U_CHAR *buf = _cpp_pool_alloc (pool, len * 4 + 1); + + token->type = CPP_STRING; + token->val.str.text = buf; + token->val.str.len = quote_string (buf, text, len) - buf; + buf[token->val.str.len] = '\0'; + token->flags = 0; +} + +/* Allocates and converts a temporary token to a CPP_NUMBER token, + evaluating to NUMBER. */ +static void +make_number_token (pfile, token, number) + cpp_reader *pfile; + cpp_token *token; + int number; +{ + unsigned char *buf = _cpp_pool_alloc (&pfile->ident_pool, 20); + + sprintf ((char *) buf, "%d", number); + token->type = CPP_NUMBER; + token->val.str.text = buf; + token->val.str.len = ustrlen (buf); + token->flags = 0; +} + +static const char * const monthnames[] = +{ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +/* Handle builtin macros like __FILE__. */ +static void +builtin_macro (pfile, token) + cpp_reader *pfile; + cpp_token *token; +{ + unsigned char flags = ((token->flags & PREV_WHITE) | AVOID_LPASTE); + cpp_hashnode *node = token->val.node; + + switch (node->value.builtin) + { + case BT_FILE: + case BT_BASE_FILE: + { + const char *name; + cpp_buffer *buffer = pfile->buffer; + + if (node->value.builtin == BT_BASE_FILE) + while (buffer->prev) + buffer = buffer->prev; + + name = buffer->nominal_fname; + make_string_token (&pfile->ident_pool, token, + (const unsigned char *) name, strlen (name)); + } + break; + + case BT_INCLUDE_LEVEL: + /* pfile->include_depth counts the primary source as level 1, + but historically __INCLUDE_DEPTH__ has called the primary + source level 0. */ + make_number_token (pfile, token, pfile->include_depth - 1); + break; + + case BT_SPECLINE: + /* If __LINE__ is embedded in a macro, it must expand to the + line of the macro's invocation, not its definition. + Otherwise things like assert() will not work properly. */ + make_number_token (pfile, token, cpp_get_line (pfile)->line); + break; + + case BT_STDC: + { + int stdc = (!CPP_IN_SYSTEM_HEADER (pfile) + || pfile->spec_nodes.n__STRICT_ANSI__->type != NT_VOID); + make_number_token (pfile, token, stdc); + } + break; + + case BT_DATE: + case BT_TIME: + if (pfile->date.type == CPP_EOF) + { + /* Allocate __DATE__ and __TIME__ from permanent storage, + and save them in pfile so we don't have to do this again. + We don't generate these strings at init time because + time() and localtime() are very slow on some systems. */ + time_t tt = time (NULL); + struct tm *tb = localtime (&tt); + + make_string_token (&pfile->ident_pool, &pfile->date, + DSC("Oct 11 1347")); + make_string_token (&pfile->ident_pool, &pfile->time, + DSC("12:34:56")); + + sprintf ((char *) pfile->date.val.str.text, "%s %2d %4d", + monthnames[tb->tm_mon], tb->tm_mday, tb->tm_year + 1900); + sprintf ((char *) pfile->time.val.str.text, "%02d:%02d:%02d", + tb->tm_hour, tb->tm_min, tb->tm_sec); + } + *token = node->value.builtin == BT_DATE ? pfile->date: pfile->time; + break; + + default: + cpp_ice (pfile, "invalid builtin macro \"%s\"", NODE_NAME (node)); + break; + } + + token->flags = flags; +} + +/* Used by cpperror.c to obtain the correct line and column to report + in a diagnostic. */ +const cpp_lexer_pos * +cpp_get_line (pfile) + cpp_reader *pfile; +{ + return &pfile->lexer_pos; +} + +static void +lock_pools (pfile) + cpp_reader *pfile; +{ + _cpp_lock_pool (&pfile->argument_pool); +} + +static void +unlock_pools (pfile) + cpp_reader *pfile; +{ + _cpp_unlock_pool (&pfile->argument_pool); +} + +/* Adds backslashes before all backslashes and double quotes appearing + in strings. Non-printable characters are converted to octal. */ +static U_CHAR * +quote_string (dest, src, len) + U_CHAR *dest; + const U_CHAR *src; + unsigned int len; +{ + while (len--) + { + U_CHAR c = *src++; + + if (c == '\\' || c == '"') + { + *dest++ = '\\'; + *dest++ = c; + } + else + { + if (ISPRINT (c)) + *dest++ = c; + else + { + sprintf ((char *) dest, "\\%03o", c); + dest += 4; + } + } + } + + return dest; +} + +/* Convert a token sequence to a single string token according to the + rules of the ISO C #-operator. */ +static void +stringify_arg (pfile, arg) + cpp_reader *pfile; + macro_arg *arg; +{ + cpp_pool *pool = &pfile->ident_pool; + unsigned char *start = POOL_FRONT (pool); + unsigned int i, escape_it, total_len = 0, backslash_count = 0; + + /* Loop, reading in the argument's tokens. */ + for (i = 0; i < arg->count; i++) + { + unsigned char *dest; + const cpp_token *token = &arg->first[i]; + unsigned int len = cpp_token_len (token); + + escape_it = (token->type == CPP_STRING || token->type == CPP_WSTRING + || token->type == CPP_CHAR || token->type == CPP_WCHAR); + + if (escape_it) + /* Worst case is each char is octal. */ + len *= 4; + len += 2; /* Room for initial space and final NUL. */ + + dest = &start[total_len]; + if (dest + len > POOL_LIMIT (pool)) + { + _cpp_next_chunk (pool, len, (unsigned char **) &start); + dest = &start[total_len]; + } + + /* No leading white space. */ + if (token->flags & PREV_WHITE && total_len > 0) + *dest++ = ' '; + + if (escape_it) + { + unsigned char *buf = (unsigned char *) xmalloc (len); + + len = cpp_spell_token (pfile, token, buf) - buf; + dest = quote_string (dest, buf, len); + free (buf); + } + else + dest = cpp_spell_token (pfile, token, dest); + total_len = dest - start; + + if (token->type == CPP_OTHER && token->val.c == '\\') + backslash_count++; + else + backslash_count = 0; + } + + /* Ignore the final \ of invalid string literals. */ + if (backslash_count & 1) + { + cpp_warning (pfile, "invalid string literal, ignoring final '\\'"); + total_len--; + } + + /* Null terminate, and commit the memory. */ + start[total_len] = '\0'; + POOL_COMMIT (pool, total_len + 1); + + arg->stringified = xnew (cpp_token); + arg->stringified->flags = 0; + arg->stringified->type = CPP_STRING; + arg->stringified->val.str.text = start; + arg->stringified->val.str.len = total_len; +} + +/* Try to paste two tokens. On success, the LHS becomes the pasted + token, and 0 is returned. For failure, we update the flags of the + RHS appropriately and return non-zero. */ +static int +paste_tokens (pfile, lhs, rhs) + cpp_reader *pfile; + cpp_token *lhs, *rhs; +{ + unsigned char flags; + int digraph = 0; + enum cpp_ttype type; + + type = cpp_can_paste (pfile, lhs, rhs, &digraph); + + if (type == CPP_EOF) + { + /* Mandatory warning for all apart from assembler. */ + if (CPP_OPTION (pfile, lang) != CLK_ASM) + cpp_warning (pfile, + "pasting \"%s\" and \"%s\" does not give a valid preprocessing token", + cpp_token_as_text (pfile, lhs), + cpp_token_as_text (pfile, rhs)); + + /* The standard states that behaviour is undefined. By the + principle of least surpise, we step back before the RHS, and + mark it to prevent macro expansion. Tests in the testsuite + rely on clearing PREV_WHITE here, though you could argue we + should actually set it. Assembler can have '.' in labels and + so requires that we don't insert spaces there. Maybe we should + change this to put out a space unless it's assembler. */ + rhs->flags &= ~PREV_WHITE; + rhs->flags |= NO_EXPAND; + return 1; + } + + flags = lhs->flags & ~DIGRAPH; + if (digraph) + flags |= DIGRAPH; + + /* Identifiers and numbers need spellings to be pasted. */ + if (type == CPP_NAME || type == CPP_NUMBER) + { + unsigned int total_len = cpp_token_len (lhs) + cpp_token_len (rhs); + unsigned char *result, *end; + + result = _cpp_pool_alloc (&pfile->ident_pool, total_len + 1); + + /* Paste the spellings and null terminate. */ + end = cpp_spell_token (pfile, rhs, cpp_spell_token (pfile, lhs, result)); + *end = '\0'; + total_len = end - result; + + if (type == CPP_NAME) + { + lhs->val.node = cpp_lookup (pfile, result, total_len); + if (lhs->val.node->flags & NODE_OPERATOR) + { + flags |= NAMED_OP; + lhs->type = lhs->val.node->value.operator; + } + } + else + { + lhs->val.str.text = result; + lhs->val.str.len = total_len; + } + } + else if (type == CPP_WCHAR || type == CPP_WSTRING) + lhs->val.str = rhs->val.str; + + /* Set type and flags after pasting spellings. */ + lhs->type = type; + lhs->flags = flags; + + return 0; +} + +/* Handles an arbitrarily long sequence of ## operators. This + implementation is left-associative, non-recursive, and finishes a + paste before handling succeeding ones. If the paste fails, we back + up a token to just after the ## operator, with the effect that it + appears in the output stream normally. */ +static void +paste_all_tokens (pfile, lhs) + cpp_reader *pfile; + cpp_token *lhs; +{ + cpp_token *rhs; + unsigned char orig_flags = lhs->flags; + + do + { + /* Take the token directly from the current context. We can do + this, because we are in the replacement list of either an + object-like macro, or a function-like macro with arguments + inserted. In either case, the constraints to #define + guarantee we have at least one more token. */ + rhs = pfile->context->list.first++; + if (paste_tokens (pfile, lhs, rhs)) + { + /* We failed. Step back so we read the RHS in next. */ + pfile->context->list.first--; + break; + } + } + while (rhs->flags & PASTE_LEFT); + + /* The pasted token has the PREV_WHITE flag of the LHS, is no longer + PASTE_LEFT, and is subject to macro expansion. */ + lhs->flags &= ~(PREV_WHITE | PASTE_LEFT | NO_EXPAND); + lhs->flags |= orig_flags & (PREV_WHITE | AVOID_LPASTE); +} + +/* Reads the unexpanded tokens of a macro argument into ARG. VAR_ARGS + is non-zero if this is a variadic macro. Returns the type of the + token that caused reading to finish. */ +static enum cpp_ttype +parse_arg (pfile, arg, variadic) + cpp_reader *pfile; + struct macro_arg *arg; + int variadic; +{ + enum cpp_ttype result; + unsigned int paren = 0; + unsigned int line; + + arg->first = (cpp_token *) POOL_FRONT (&pfile->argument_pool); + for (;; arg->count++) + { + cpp_token *token = &arg->first[arg->count]; + if ((unsigned char *) (token + 1) >= POOL_LIMIT (&pfile->argument_pool)) + { + _cpp_next_chunk (&pfile->argument_pool, sizeof (cpp_token), + (unsigned char **) &arg->first); + token = &arg->first[arg->count]; + } + + /* Newlines in arguments are white space (6.10.3.10). */ + line = pfile->lexer_pos.output_line; + cpp_get_token (pfile, token); + if (line != pfile->lexer_pos.output_line) + token->flags |= PREV_WHITE; + + result = token->type; + if (result == CPP_OPEN_PAREN) + paren++; + else if (result == CPP_CLOSE_PAREN && paren-- == 0) + break; + /* Commas are not terminators within parantheses or variadic. */ + else if (result == CPP_COMMA && paren == 0 && !variadic) + break; + else if (result == CPP_EOF) + break; /* Error reported by caller. */ + } + + /* Commit the memory used to store the arguments. */ + POOL_COMMIT (&pfile->argument_pool, arg->count * sizeof (cpp_token)); + + return result; +} + +/* Parse the arguments making up a macro invocation. */ +static macro_arg * +parse_args (pfile, node) + cpp_reader *pfile; + const cpp_hashnode *node; +{ + cpp_macro *macro = node->value.macro; + macro_arg *args, *cur; + enum cpp_ttype type; + int argc, error = 0; + + /* Allocate room for at least one argument, and zero it out. */ + argc = macro->paramc ? macro->paramc: 1; + args = xcnewvec (macro_arg, argc); + + for (cur = args, argc = 0; ;) + { + argc++; + + type = parse_arg (pfile, cur, argc == macro->paramc && macro->variadic); + if (type == CPP_CLOSE_PAREN || type == CPP_EOF) + break; + + /* Re-use the last argument for excess arguments. */ + if (argc < macro->paramc) + cur++; + } + + if (type == CPP_EOF) + { + cpp_error (pfile, "unterminated argument list invoking macro \"%s\"", + NODE_NAME (node)); + error = 1; + } + else if (argc < macro->paramc) + { + /* As an extension, a rest argument is allowed to not appear in + the invocation at all. + e.g. #define debug(format, args...) something + debug("string"); + + This is exactly the same as if there had been an empty rest + argument - debug("string", ). */ + + if (argc + 1 == macro->paramc && macro->variadic) + { + if (CPP_PEDANTIC (pfile) && ! macro->syshdr) + cpp_pedwarn (pfile, "ISO C99 requires rest arguments to be used"); + } + else + { + cpp_error (pfile, + "macro \"%s\" requires %u arguments, but only %u given", + NODE_NAME (node), macro->paramc, argc); + error = 1; + } + } + else if (argc > macro->paramc) + { + /* Empty argument to a macro taking no arguments is OK. */ + if (argc != 1 || cur->count) + { + cpp_error (pfile, + "macro \"%s\" passed %u arguments, but takes just %u", + NODE_NAME (node), argc, macro->paramc); + error = 1; + } + } + + if (error) + { + free (args); + args = 0; + } + + return args; +} + +static int +funlike_invocation_p (pfile, node, list) + cpp_reader *pfile; + const cpp_hashnode *node; + struct toklist *list; +{ + cpp_context *orig; + cpp_token maybe_paren; + macro_arg *args = 0; + cpp_lexer_pos macro_pos; + + macro_pos = pfile->lexer_pos; + pfile->state.parsing_args = 1; + pfile->state.prevent_expansion++; + orig = pfile->context; + + cpp_start_lookahead (pfile); + cpp_get_token (pfile, &maybe_paren); + cpp_stop_lookahead (pfile, maybe_paren.type == CPP_OPEN_PAREN); + pfile->state.parsing_args = 2; + + if (maybe_paren.type == CPP_OPEN_PAREN) + args = parse_args (pfile, node); + else if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr) + cpp_warning (pfile, + "function-like macro \"%s\" must be used with arguments in traditional C", + NODE_NAME (node)); + + /* Restore original context. */ + pfile->context = orig; + pfile->state.prevent_expansion--; + pfile->state.parsing_args = 0; + + /* Reset the position in case of failure. If success, the macro's + expansion appears where the name would have. */ + pfile->lexer_pos = macro_pos; + + if (args) + { + if (node->value.macro->paramc > 0) + { + /* Don't save tokens during pre-expansion. */ + struct cpp_lookahead *la_saved = pfile->la_write; + pfile->la_write = 0; + replace_args (pfile, node->value.macro, args, list); + pfile->la_write = la_saved; + } + free (args); + } + + return args != 0; +} + +/* Push the context of a macro onto the context stack. TOKEN is the + macro name. If we can successfully start expanding the macro, + TOKEN is replaced with the first token of the expansion, and we + return non-zero. */ +static int +enter_macro_context (pfile, node) + cpp_reader *pfile; + cpp_hashnode *node; +{ + cpp_context *context; + cpp_macro *macro = node->value.macro; + struct toklist list; + + /* Save the position of the outermost macro invocation. */ + if (!pfile->context->prev) + lock_pools (pfile); + + if (macro->fun_like && !funlike_invocation_p (pfile, node, &list)) + { + if (!pfile->context->prev) + unlock_pools (pfile); + return 0; + } + + if (macro->paramc == 0) + { + list.first = macro->expansion; + list.limit = macro->expansion + macro->count; + } + + /* Only push a macro context for non-empty replacement lists. */ + if (list.first != list.limit) + { + context = next_context (pfile); + context->list = list; + context->macro = macro; + + /* Disable the macro within its expansion. */ + macro->disabled = 1; + } + + return 1; +} + +/* Move to the next context. Create one if there is none. */ +static cpp_context * +next_context (pfile) + cpp_reader *pfile; +{ + cpp_context *prev = pfile->context; + cpp_context *result = prev->next; + + if (result == 0) + { + result = xnew (cpp_context); + prev->next = result; + result->prev = prev; + result->next = 0; + } + + pfile->context = result; + return result; +} + +static void +replace_args (pfile, macro, args, list) + cpp_reader *pfile; + cpp_macro *macro; + macro_arg *args; + struct toklist *list; +{ + unsigned char flags = 0; + unsigned int i, total; + const cpp_token *src, *limit; + cpp_token *dest; + macro_arg *arg; + + src = macro->expansion; + limit = src + macro->count; + + /* First, fully macro-expand arguments, calculating the number of + tokens in the final expansion as we go. This ensures that the + possible recursive use of argument_pool is fine. */ + total = limit - src; + for (; src < limit; src++) + if (src->type == CPP_MACRO_ARG) + { + /* We have an argument. If it is not being stringified or + pasted it is macro-replaced before insertion. */ + arg = &args[src->val.arg_no - 1]; + + if (src->flags & STRINGIFY_ARG) + { + if (!arg->stringified) + stringify_arg (pfile, arg); + } + else if ((src->flags & PASTE_LEFT) + || (src > macro->expansion && (src[-1].flags & PASTE_LEFT))) + total += arg->count - 1; + else + { + if (!arg->expanded) + { + arg->expanded_count = 0; + if (arg->count) + expand_arg (pfile, arg); + } + total += arg->expanded_count - 1; + } + } + + dest = (cpp_token *) _cpp_pool_alloc (&pfile->argument_pool, + total * sizeof (cpp_token)); + list->first = dest; + + for (src = macro->expansion; src < limit; src++) + if (src->type == CPP_MACRO_ARG) + { + unsigned int count; + const cpp_token *from; + + arg = &args[src->val.arg_no - 1]; + if (src->flags & STRINGIFY_ARG) + from = arg->stringified, count = 1; + else if (src->flags & PASTE_LEFT) + count = arg->count, from = arg->first; + else if (src > macro->expansion && (src[-1].flags & PASTE_LEFT)) + { + count = arg->count, from = arg->first; + if (dest != list->first) + { + /* GCC has special semantics for , ## b where b is a + varargs parameter: the comma disappears if b was + given no actual arguments (not merely if b is an + empty argument); otherwise pasting is turned off. */ + if (dest[-1].type == CPP_COMMA + && macro->variadic + && src->val.arg_no == macro->paramc) + { + if (count == 0) + dest--; + else + dest[-1].flags &= ~PASTE_LEFT; + } + /* Count == 0 is the RHS a placemarker case. */ + else if (count == 0) + dest[-1].flags &= ~PASTE_LEFT; + } + } + else + count = arg->expanded_count, from = arg->expanded; + + /* Count == 0 is the LHS a placemarker case. */ + if (count) + { + memcpy (dest, from, count * sizeof (cpp_token)); + + /* The first token gets PREV_WHITE of the CPP_MACRO_ARG. */ + dest->flags &= ~PREV_WHITE; + dest->flags |= src->flags & PREV_WHITE; + dest->flags |= AVOID_LPASTE; + + /* The last token gets the PASTE_LEFT of the CPP_MACRO_ARG. */ + dest[count - 1].flags |= src->flags & PASTE_LEFT; + + dest += count; + } + + /* The token after the argument must avoid an accidental paste. */ + flags = AVOID_LPASTE; + } + else + { + *dest = *src; + dest->flags |= flags; + dest++; + flags = 0; + } + + list->limit = dest; + + /* Free the expanded arguments. */ + for (i = 0; i < macro->paramc; i++) + { + if (args[i].expanded) + free (args[i].expanded); + if (args[i].stringified) + free (args[i].stringified); + } +} + +/* Subroutine of expand_arg to put the unexpanded tokens on the + context stack. */ +static cpp_context * +push_arg_context (pfile, arg) + cpp_reader *pfile; + macro_arg *arg; +{ + cpp_context *context = next_context (pfile); + context->macro = 0; + context->list.first = arg->first; + context->list.limit = arg->first + arg->count; + + return context; +} + +static void +expand_arg (pfile, arg) + cpp_reader *pfile; + macro_arg *arg; +{ + cpp_token *token; + unsigned int capacity = 256; + + /* Loop, reading in the arguments. */ + arg->expanded = (cpp_token *) xmalloc (capacity * sizeof (cpp_token)); + + push_arg_context (pfile, arg); + do + { + if (arg->expanded_count >= capacity) + { + capacity *= 2; + arg->expanded = (cpp_token *) + xrealloc (arg->expanded, capacity * sizeof (cpp_token)); + } + token = &arg->expanded[arg->expanded_count++]; + cpp_get_token (pfile, token); + } + while (token->type != CPP_EOF); + + arg->expanded_count--; + + /* Pop the context we pushed. */ + pfile->context = pfile->context->prev; +} + +void +_cpp_pop_context (pfile) + cpp_reader *pfile; +{ + cpp_context *context = pfile->context; + + pfile->context = context->prev; + if (!pfile->context->prev && !pfile->state.parsing_args) + unlock_pools (pfile); + + /* Re-enable a macro, temporarily if parsing_args, when leaving its + expansion. */ + context->macro->disabled = 0; +} + +/* Eternal routine to get a token. Also used nearly everywhere + internally, except for places where we know we can safely call + the lexer directly, such as lexing a directive name. + + Macro expansions and directives are transparently handled, + including entering included files. Thus tokens are post-macro + expansion, and after any intervening directives. External callers + see CPP_EOF only at EOF. Internal callers also see it when meeting + a directive inside a macro call, when at the end of a directive and + state.in_directive is still 1, and at the end of argument + pre-expansion. */ +void +cpp_get_token (pfile, token) + cpp_reader *pfile; + cpp_token *token; +{ + for (;;) + { + cpp_context *context = pfile->context; + + if (pfile->la_read) + take_lookahead_token (pfile, token); + /* Context->prev == 0 <=> base context. */ + else if (!context->prev) + _cpp_lex_token (pfile, token); + else if (context->list.first != context->list.limit) + { + *token = *context->list.first++; + token->flags |= pfile->buffer->saved_flags; + pfile->buffer->saved_flags = 0; + /* PASTE_LEFT tokens can only appear in macro expansions. */ + if (token->flags & PASTE_LEFT) + { + paste_all_tokens (pfile, token); + pfile->buffer->saved_flags = AVOID_LPASTE; + } + } + else + { + if (context->macro) + { + /* Avoid accidental paste at the end of a macro. */ + pfile->buffer->saved_flags |= AVOID_LPASTE; + _cpp_pop_context (pfile); + continue; + } + /* End of argument pre-expansion. */ + token->type = CPP_EOF; + token->flags = 0; + return; + } + + if (token->type != CPP_NAME) + break; + + /* Handle macros and the _Pragma operator. */ + if (token->val.node->type == NT_MACRO + && !pfile->state.prevent_expansion + && !(token->flags & NO_EXPAND)) + { + cpp_hashnode *node = token->val.node; + + /* Macros invalidate controlling macros. */ + pfile->mi_state = MI_FAILED; + + if (node->flags & NODE_BUILTIN) + { + builtin_macro (pfile, token); + pfile->buffer->saved_flags = AVOID_LPASTE; + break; + } + + if (node->value.macro->disabled) + token->flags |= NO_EXPAND; + else if (enter_macro_context (pfile, node)) + { + /* Pass AVOID_LPASTE and our PREV_WHITE to next token. */ + pfile->buffer->saved_flags = ((token->flags & PREV_WHITE) + | AVOID_LPASTE); + continue; + } + } + + /* Don't interpret _Pragma within directives. The standard is + not clear on this, but to me this makes most sense. */ + if (token->val.node != pfile->spec_nodes.n__Pragma + || pfile->state.in_directive) + break; + + /* Handle it, and loop back for another token. MI is cleared + since this token came from either the lexer or a macro. */ + _cpp_do__Pragma (pfile); + } + + if (pfile->la_write) + save_lookahead_token (pfile, token); +} + +/* Returns true if we're expanding an object-like macro that was + defined in a system header. Just checks the macro at the top of + the stack. Used for diagnostic suppression. */ +int +cpp_sys_macro_p (pfile) + cpp_reader *pfile; +{ + cpp_macro *macro = pfile->context->macro; + + return macro && macro->syshdr; +} + +/* Read each token in, until EOF. Directives are transparently + processed. */ +void +cpp_scan_buffer_nooutput (pfile, all_buffers) + cpp_reader *pfile; + int all_buffers; +{ + cpp_token token; + cpp_buffer *buffer = all_buffers ? 0: pfile->buffer->prev; + + do + do + cpp_get_token (pfile, &token); + while (token.type != CPP_EOF); + while (cpp_pop_buffer (pfile) != buffer); +} + +/* Lookahead handling. */ + +static void +save_lookahead_token (pfile, token) + cpp_reader *pfile; + const cpp_token *token; +{ + if (token->type != CPP_EOF) + { + cpp_lookahead *la = pfile->la_write; + cpp_token_with_pos *twp; + + if (la->count == la->cap) + { + la->cap += la->cap + 8; + la->tokens = (cpp_token_with_pos *) + xrealloc (la->tokens, la->cap * sizeof (cpp_token_with_pos)); + } + + twp = &la->tokens[la->count++]; + twp->token = *token; + twp->pos = *cpp_get_line (pfile); + } +} + +static void +take_lookahead_token (pfile, token) + cpp_reader *pfile; + cpp_token *token; +{ + cpp_lookahead *la = pfile->la_read; + cpp_token_with_pos *twp = &la->tokens[la->cur]; + + *token = twp->token; + pfile->lexer_pos = twp->pos; + + if (++la->cur == la->count) + _cpp_release_lookahead (pfile); +} + +/* Moves the lookahead at the front of the read list to the free store. */ +void +_cpp_release_lookahead (pfile) + cpp_reader *pfile; +{ + cpp_lookahead *la = pfile->la_read; + + pfile->la_read = la->next; + la->next = pfile->la_unused; + pfile->la_unused = la; + unlock_pools (pfile); +} + +/* Take a new lookahead from the free store, or allocate one if none. */ +static cpp_lookahead * +alloc_lookahead (pfile) + cpp_reader *pfile; +{ + cpp_lookahead *la = pfile->la_unused; + + if (la) + pfile->la_unused = la->next; + else + { + la = xnew (cpp_lookahead); + la->tokens = 0; + la->cap = 0; + } + + la->cur = la->count = 0; + return la; +} + +/* Free memory associated with a lookahead list. */ +static void +free_lookahead (la) + cpp_lookahead *la; +{ + if (la->tokens) + free ((PTR) la->tokens); + free ((PTR) la); +} + +/* Free all the lookaheads of a cpp_reader. */ +void +_cpp_free_lookaheads (pfile) + cpp_reader *pfile; +{ + cpp_lookahead *la, *lan; + + if (pfile->la_read) + free_lookahead (pfile->la_read); + if (pfile->la_write) + free_lookahead (pfile->la_write); + + for (la = pfile->la_unused; la; la = lan) + { + lan = la->next; + free_lookahead (la); + } +} + +/* Allocate a lookahead and move it to the front of the write list. */ +void +cpp_start_lookahead (pfile) + cpp_reader *pfile; +{ + cpp_lookahead *la = alloc_lookahead (pfile); + + la->next = pfile->la_write; + pfile->la_write = la; + + la->pos = *cpp_get_line (pfile); + + /* Don't allow memory pools to be re-used whilst we're reading ahead. */ + lock_pools (pfile); +} + +/* Stop reading ahead - either step back, or drop the read ahead. */ +void +cpp_stop_lookahead (pfile, drop) + cpp_reader *pfile; + int drop; +{ + cpp_lookahead *la = pfile->la_write; + + pfile->la_write = la->next; + la->next = pfile->la_read; + pfile->la_read = la; + + if (drop || la->count == 0) + _cpp_release_lookahead (pfile); + else + pfile->lexer_pos = la->pos; +} + +/* Push a single token back to the front of the queue. Only to be + used by cpplib, and only then when necessary. POS is the position + to report for the preceding token. */ +void +_cpp_push_token (pfile, token, pos) + cpp_reader *pfile; + const cpp_token *token; + const cpp_lexer_pos *pos; +{ + cpp_start_lookahead (pfile); + save_lookahead_token (pfile, token); + cpp_stop_lookahead (pfile, 0); + pfile->lexer_pos = *pos; +} + +/* #define directive parsing and handling. */ + +/* Returns non-zero if a macro redefinition warning is required. */ +static int +warn_of_redefinition (pfile, node, macro2) + cpp_reader *pfile; + const cpp_hashnode *node; + const cpp_macro *macro2; +{ + const cpp_macro *macro1; + unsigned int i; + + /* Some redefinitions need to be warned about regardless. */ + if (node->flags & NODE_WARN) + return 1; + + if (! CPP_PEDANTIC (pfile)) + return 0; + + /* Redefinition of a macro is allowed if and only if the old and new + definitions are the same. (6.10.3 paragraph 2). */ + macro1 = node->value.macro; + + /* The quick failures. */ + if (macro1->count != macro2->count + || macro1->paramc != macro2->paramc + || macro1->fun_like != macro2->fun_like + || macro1->variadic != macro2->variadic) + return 1; + + /* Check each token. */ + for (i = 0; i < macro1->count; i++) + if (! _cpp_equiv_tokens (¯o1->expansion[i], ¯o2->expansion[i])) + return 1; + + /* Check parameter spellings. */ + for (i = 0; i < macro1->paramc; i++) + if (macro1->params[i] != macro2->params[i]) + return 1; + + return 0; +} + +/* Free the definition of hashnode H. */ + +void +_cpp_free_definition (h) + cpp_hashnode *h; +{ + /* Macros and assertions no longer have anything to free. */ + h->type = NT_VOID; + /* Clear builtin flag in case of redefinition. */ + h->flags &= ~NODE_BUILTIN; +} + +static int +save_parameter (pfile, macro, node) + cpp_reader *pfile; + cpp_macro *macro; + cpp_hashnode *node; +{ + cpp_hashnode **dest; + + /* Constraint 6.10.3.6 - duplicate parameter names. */ + if (node->arg_index) + { + cpp_error (pfile, "duplicate macro parameter \"%s\"", NODE_NAME (node)); + return 1; + } + + dest = ¯o->params[macro->paramc]; + + /* Check we have room for the parameters. */ + if ((unsigned char *) (dest + 1) >= POOL_LIMIT (&pfile->macro_pool)) + { + _cpp_next_chunk (&pfile->macro_pool, sizeof (cpp_hashnode *), + (unsigned char **) ¯o->params); + dest = ¯o->params[macro->paramc]; + } + + *dest = node; + node->arg_index = ++macro->paramc; + return 0; +} + +static int +parse_params (pfile, macro) + cpp_reader *pfile; + cpp_macro *macro; +{ + cpp_token token; + unsigned int prev_ident = 0; + + macro->params = (cpp_hashnode **) POOL_FRONT (&pfile->macro_pool); + for (;;) + { + _cpp_lex_token (pfile, &token); + + switch (token.type) + { + default: + cpp_error (pfile, "\"%s\" may not appear in macro parameter list", + cpp_token_as_text (pfile, &token)); + return 0; + + case CPP_NAME: + if (prev_ident) + { + cpp_error (pfile, "macro parameters must be comma-separated"); + return 0; + } + prev_ident = 1; + + if (save_parameter (pfile, macro, token.val.node)) + return 0; + continue; + + case CPP_CLOSE_PAREN: + if (prev_ident || macro->paramc == 0) + break; + + /* Fall through to pick up the error. */ + case CPP_COMMA: + if (!prev_ident) + { + cpp_error (pfile, "parameter name missing"); + return 0; + } + prev_ident = 0; + continue; + + case CPP_ELLIPSIS: + macro->variadic = 1; + if (!prev_ident) + { + save_parameter (pfile, macro, pfile->spec_nodes.n__VA_ARGS__); + pfile->state.va_args_ok = 1; + if (! CPP_OPTION (pfile, c99) && CPP_OPTION (pfile, pedantic)) + cpp_pedwarn (pfile, + "anonymous variadic macros were introduced in C99"); + } + else if (CPP_OPTION (pfile, pedantic)) + cpp_pedwarn (pfile, "ISO C does not permit named variadic macros"); + + /* We're at the end, and just expect a closing parenthesis. */ + _cpp_lex_token (pfile, &token); + if (token.type == CPP_CLOSE_PAREN) + break; + /* Fall through. */ + + case CPP_EOF: + cpp_error (pfile, "missing ')' in macro parameter list"); + return 0; + } + + /* Success. Commit the parameter array. */ + POOL_COMMIT (&pfile->macro_pool, + macro->paramc * sizeof (cpp_hashnode *)); + return 1; + } +} + +/* Lex a token from a macro's replacement list. Translate it to a + CPP_MACRO_ARG if appropriate. */ +static cpp_token * +lex_expansion_token (pfile, macro) + cpp_reader *pfile; + cpp_macro *macro; +{ + cpp_token *token = ¯o->expansion[macro->count]; + + /* Check we have room for the token. */ + if ((unsigned char *) (token + 1) >= POOL_LIMIT (&pfile->macro_pool)) + { + _cpp_next_chunk (&pfile->macro_pool, sizeof (cpp_token), + (unsigned char **) ¯o->expansion); + token = ¯o->expansion[macro->count]; + } + + macro->count++; + _cpp_lex_token (pfile, token); + + /* Is this an argument? */ + if (token->type == CPP_NAME && token->val.node->arg_index) + { + token->type = CPP_MACRO_ARG; + token->val.arg_no = token->val.node->arg_index; + } + else if (CPP_WTRADITIONAL (pfile) && macro->paramc > 0 + && (token->type == CPP_STRING || token->type == CPP_CHAR)) + check_trad_stringification (pfile, macro, &token->val.str); + + return token; +} + +/* Parse a macro and save its expansion. Returns non-zero on success. */ +int +_cpp_create_definition (pfile, node) + cpp_reader *pfile; + cpp_hashnode *node; +{ + cpp_macro *macro; + cpp_token *token; + unsigned int i, ok = 1; + + macro = (cpp_macro *) _cpp_pool_alloc (&pfile->macro_pool, + sizeof (cpp_macro)); + macro->file = pfile->buffer->nominal_fname; + macro->line = pfile->directive_pos.line; + macro->params = 0; + macro->paramc = 0; + macro->fun_like = 0; + macro->variadic = 0; + macro->count = 0; + macro->expansion = (cpp_token *) POOL_FRONT (&pfile->macro_pool); + + /* Get the first token of the expansion (or the '(' of a + function-like macro). */ + token = lex_expansion_token (pfile, macro); + if (token->type == CPP_OPEN_PAREN && !(token->flags & PREV_WHITE)) + { + if (!(ok = parse_params (pfile, macro))) + goto cleanup; + macro->count = 0; + macro->fun_like = 1; + /* Some of the pool may have been used for the parameter store. */ + macro->expansion = (cpp_token *) POOL_FRONT (&pfile->macro_pool); + token = lex_expansion_token (pfile, macro); + } + else if (token->type != CPP_EOF && !(token->flags & PREV_WHITE)) + cpp_pedwarn (pfile, "ISO C requires whitespace after the macro name"); + + /* Setting it here means we don't catch leading comments. */ + pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments); + + for (;;) + { + /* Check the stringifying # constraint 6.10.3.2.1 of + function-like macros when lexing the subsequent token. */ + if (macro->count > 1 && token[-1].type == CPP_HASH && macro->fun_like) + { + if (token->type == CPP_MACRO_ARG) + { + token->flags &= ~PREV_WHITE; + token->flags |= STRINGIFY_ARG; + token->flags |= token[-1].flags & PREV_WHITE; + token[-1] = token[0]; + macro->count--; + } + /* Let assembler get away with murder. */ + else if (CPP_OPTION (pfile, lang) != CLK_ASM) + { + ok = 0; + cpp_error (pfile, "'#' is not followed by a macro parameter"); + goto cleanup; + } + } + + if (token->type == CPP_EOF) + break; + + /* Paste operator constraint 6.10.3.3.1. */ + if (token->type == CPP_PASTE) + { + /* Token-paste ##, can appear in both object-like and + function-like macros, but not at the ends. */ + if (--macro->count > 0) + token = lex_expansion_token (pfile, macro); + + if (macro->count == 0 || token->type == CPP_EOF) + { + ok = 0; + cpp_error (pfile, + "'##' cannot appear at either end of a macro expansion"); + goto cleanup; + } + + token[-1].flags |= PASTE_LEFT; + /* Give it a PREV_WHITE for -dM etc. */ + token->flags |= PREV_WHITE; + } + + token = lex_expansion_token (pfile, macro); + } + + /* Don't count the CPP_EOF. */ + macro->count--; + + /* Clear the whitespace flag from the leading token. */ + macro->expansion[0].flags &= ~PREV_WHITE; + + /* Implement the macro-defined-to-itself optimisation. */ + macro->disabled = (macro->count == 1 && !macro->fun_like + && macro->expansion[0].type == CPP_NAME + && macro->expansion[0].val.node == node); + + /* To suppress some diagnostics. */ + macro->syshdr = pfile->buffer->sysp != 0; + + /* Commit the memory. */ + POOL_COMMIT (&pfile->macro_pool, macro->count * sizeof (cpp_token)); + + if (node->type != NT_VOID) + { + if (warn_of_redefinition (pfile, node, macro)) + { + cpp_pedwarn_with_line (pfile, pfile->directive_pos.line, + pfile->directive_pos.col, + "\"%s\" redefined", NODE_NAME (node)); + + if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)) + cpp_pedwarn_with_file_and_line (pfile, + node->value.macro->file, + node->value.macro->line, 1, + "this is the location of the previous definition"); + } + _cpp_free_definition (node); + } + + /* Enter definition in hash table. */ + node->type = NT_MACRO; + node->value.macro = macro; + if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_"))) + node->flags |= NODE_WARN; + + cleanup: + + /* Stop the lexer accepting __VA_ARGS__. */ + pfile->state.va_args_ok = 0; + + /* Clear the fast argument lookup indices. */ + for (i = macro->paramc; i-- > 0; ) + macro->params[i]->arg_index = 0; + + return ok; +} + +/* Warn if a token in `string' matches one of the function macro + arguments in `info'. This function assumes that the macro is a + function macro and not an object macro. */ +static void +check_trad_stringification (pfile, macro, string) + cpp_reader *pfile; + const cpp_macro *macro; + const cpp_string *string; +{ + unsigned int i, len; + const U_CHAR *p, *q, *limit = string->text + string->len; + + /* Loop over the string. */ + for (p = string->text; p < limit; p = q) + { + /* Find the start of an identifier. */ + while (p < limit && !is_idstart (*p)) + p++; + + /* Find the end of the identifier. */ + q = p; + while (q < limit && is_idchar (*q)) + q++; + + len = q - p; + + /* Loop over the function macro arguments to see if the + identifier inside the string matches one of them. */ + for (i = 0; i < macro->paramc; i++) + { + const cpp_hashnode *node = macro->params[i]; + + if (NODE_LEN (node) == len + && !memcmp (p, NODE_NAME (node), len)) + { + cpp_warning (pfile, + "macro argument \"%s\" would be stringified with -traditional.", + NODE_NAME (node)); + break; + } + } + } +} + +/* Returns the name, arguments and expansion of a macro, in a format + suitable to be read back in again, and therefore also for DWARF 2 + debugging info. e.g. "PASTE(X, Y) X ## Y", or "MACNAME EXPANSION". + Caller is expected to generate the "#define" bit if needed. The + returned text is temporary, and automatically freed later. */ + +const unsigned char * +cpp_macro_definition (pfile, node) + cpp_reader *pfile; + const cpp_hashnode *node; +{ + unsigned int i, len; + const cpp_macro *macro = node->value.macro; + unsigned char *buffer; + + if (node->type != NT_MACRO || (node->flags & NODE_BUILTIN)) + { + cpp_ice (pfile, "invalid hash type %d in cpp_macro_definition", node->type); + return 0; + } + + /* Calculate length. */ + len = NODE_LEN (node) + 1; /* ' ' */ + if (macro->fun_like) + { + len += 3; /* "()" plus possible final "." of named + varargs (we have + 2 below). */ + for (i = 0; i < macro->paramc; i++) + len += NODE_LEN (macro->params[i]) + 2; /* ", " */ + } + + for (i = 0; i < macro->count; i++) + { + cpp_token *token = ¯o->expansion[i]; + + if (token->type == CPP_MACRO_ARG) + len += NODE_LEN (macro->params[token->val.arg_no - 1]); + else + len += cpp_token_len (token); /* Includes room for ' '. */ + if (token->flags & STRINGIFY_ARG) + len++; /* "#" */ + if (token->flags & PASTE_LEFT) + len += 3; /* " ##" */ + } + + if (len > pfile->macro_buffer_len) + { + pfile->macro_buffer = (U_CHAR *) xrealloc (pfile->macro_buffer, len); + pfile->macro_buffer_len = len; + } + + /* Fill in the buffer. Start with the macro name. */ + buffer = pfile->macro_buffer; + memcpy (buffer, NODE_NAME (node), NODE_LEN (node)); + buffer += NODE_LEN (node); + + /* Parameter names. */ + if (macro->fun_like) + { + *buffer++ = '('; + for (i = 0; i < macro->paramc; i++) + { + cpp_hashnode *param = macro->params[i]; + + if (param != pfile->spec_nodes.n__VA_ARGS__) + { + memcpy (buffer, NODE_NAME (param), NODE_LEN (param)); + buffer += NODE_LEN (param); + } + + if (i + 1 < macro->paramc) + *buffer++ = ',', *buffer++ = ' '; + else if (macro->variadic) + *buffer++ = '.', *buffer++ = '.', *buffer++ = '.'; + } + *buffer++ = ')'; + } + + /* Expansion tokens. */ + if (macro->count) + { + *buffer++ = ' '; + for (i = 0; i < macro->count; i++) + { + cpp_token *token = ¯o->expansion[i]; + + if (token->flags & PREV_WHITE) + *buffer++ = ' '; + if (token->flags & STRINGIFY_ARG) + *buffer++ = '#'; + + if (token->type == CPP_MACRO_ARG) + { + len = NODE_LEN (macro->params[token->val.arg_no - 1]); + memcpy (buffer, + NODE_NAME (macro->params[token->val.arg_no - 1]), len); + buffer += len; + } + else + buffer = cpp_spell_token (pfile, token, buffer); + + if (token->flags & PASTE_LEFT) + { + *buffer++ = ' '; + *buffer++ = '#'; + *buffer++ = '#'; + /* Next has PREV_WHITE; see _cpp_create_definition. */ + } + } + } + + *buffer = '\0'; + return pfile->macro_buffer; +} diff --git a/support/cpp2/cppmain.c b/support/cpp2/cppmain.c new file mode 100644 index 00000000..4d33e221 --- /dev/null +++ b/support/cpp2/cppmain.c @@ -0,0 +1,464 @@ +/* CPP main program, using CPP Library. + Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001 + Free Software Foundation, Inc. + Written by Per Bothner, 1994-95. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! */ + +#include "config.h" +#include "system.h" +#include "cpplib.h" +#include "intl.h" + +/* Encapsulates state used to convert the stream of tokens coming from + cpp_get_token back into a text file. */ +struct printer +{ + FILE *outf; /* stream to write to. */ + const char *last_fname; /* previous file name. */ + const char *syshdr_flags; /* system header flags, if any. */ + unsigned int lineno; /* line currently being written. */ + unsigned char printed; /* nonzero if something output at lineno. */ +}; + +int main PARAMS ((int, char **)); +static void general_init PARAMS ((const char *)); +static void do_preprocessing PARAMS ((int, char **)); +static void setup_callbacks PARAMS ((void)); + +/* General output routines. */ +static void scan_buffer PARAMS ((cpp_reader *)); +static void check_multiline_token PARAMS ((cpp_string *)); +static int printer_init PARAMS ((cpp_reader *)); +static int dump_macro PARAMS ((cpp_reader *, cpp_hashnode *, void *)); + +static void print_line PARAMS ((const char *)); +static void maybe_print_line PARAMS ((unsigned int)); + +/* Callback routines for the parser. Most of these are active only + in specific modes. */ +static void cb_define PARAMS ((cpp_reader *, cpp_hashnode *)); +static void cb_undef PARAMS ((cpp_reader *, cpp_hashnode *)); +static void cb_include PARAMS ((cpp_reader *, const unsigned char *, + const cpp_token *)); +static void cb_ident PARAMS ((cpp_reader *, const cpp_string *)); +static void cb_file_change PARAMS ((cpp_reader *, const cpp_file_change *)); +static void cb_def_pragma PARAMS ((cpp_reader *)); + +const char *progname; /* Needs to be global. */ +static cpp_reader *pfile; /* An opaque handle. */ +static cpp_options *options; /* Options of pfile. */ +static struct printer print; + +int +main (argc, argv) + int argc; + char **argv; +{ + general_init (argv[0]); + + /* Contruct a reader with default language GNU C89. */ + pfile = cpp_create_reader (NULL, CLK_GNUC89); + options = cpp_get_options (pfile); + + do_preprocessing (argc, argv); + + /* Call to cpp_destroy () omitted for performance reasons. */ + if (cpp_errors (pfile)) + return FATAL_EXIT_CODE; + + return SUCCESS_EXIT_CODE; +} + +/* Store the program name, and set the locale. */ +static void +general_init (argv0) + const char *argv0; +{ + progname = argv0 + strlen (argv0); + + while (progname != argv0 && ! IS_DIR_SEPARATOR (progname[-1])) + --progname; + + xmalloc_set_program_name (progname); + +/* LC_CTYPE determines the character set used by the terminal so it + has to be set to output messages correctly. */ + +#ifdef HAVE_LC_MESSAGES + setlocale (LC_CTYPE, ""); + setlocale (LC_MESSAGES, ""); +#else + setlocale (LC_ALL, ""); +#endif + + (void) bindtextdomain (PACKAGE, localedir); + (void) textdomain (PACKAGE); +} + +/* Handle switches, preprocess and output. */ +static void +do_preprocessing (argc, argv) + int argc; + char **argv; +{ + int argi = 1; /* Next argument to handle. */ + + argi += cpp_handle_options (pfile, argc - argi , argv + argi); + if (CPP_FATAL_ERRORS (pfile)) + return; + + if (argi < argc) + cpp_fatal (pfile, "Invalid option %s", argv[argi]); + else + cpp_post_options (pfile); + + if (CPP_FATAL_ERRORS (pfile)) + return; + + /* If cpp_handle_options saw --help or --version on the command + line, it will have set pfile->help_only to indicate this. Exit + successfully. [The library does not exit itself, because + e.g. cc1 needs to print its own --help message at this point.] */ + if (options->help_only) + return; + + /* Open the output now. We must do so even if no_output is on, + because there may be other output than from the actual + preprocessing (e.g. from -dM). */ + if (printer_init (pfile)) + return; + + setup_callbacks (); + + if (cpp_start_read (pfile, options->in_fname)) + { + /* A successful cpp_start_read guarantees that we can call + cpp_scan_buffer_nooutput or cpp_get_token next. */ + if (options->no_output) + cpp_scan_buffer_nooutput (pfile, 1); + else + scan_buffer (pfile); + + /* -dM command line option. Should this be in cpp_finish? */ + if (options->dump_macros == dump_only) + cpp_forall_identifiers (pfile, dump_macro, NULL); + + cpp_finish (pfile); + } + + /* Flush any pending output. */ + if (print.printed) + putc ('\n', print.outf); + + if (ferror (print.outf) || fclose (print.outf)) + cpp_notice_from_errno (pfile, options->out_fname); +} + +/* Set up the callbacks as appropriate. */ +static void +setup_callbacks () +{ + cpp_callbacks *cb = cpp_get_callbacks (pfile); + + if (! options->no_output) + { + cb->ident = cb_ident; + cb->def_pragma = cb_def_pragma; + if (! options->no_line_commands) + cb->file_change = cb_file_change; + } + + if (options->dump_includes) + cb->include = cb_include; + + if (options->dump_macros == dump_names + || options->dump_macros == dump_definitions) + { + cb->define = cb_define; + cb->undef = cb_undef; + cb->poison = cb_def_pragma; + } +} + +/* Writes out the preprocessed file. Alternates between two tokens, + so that we can avoid accidental token pasting. */ +static void +scan_buffer (pfile) + cpp_reader *pfile; +{ + unsigned int index, line; + cpp_token tokens[2], *token; + + do + { + for (index = 0;; index = 1 - index) + { + token = &tokens[index]; + cpp_get_token (pfile, token); + + if (token->type == CPP_EOF) + break; + + line = cpp_get_line (pfile)->output_line; + if (print.lineno != line) + { + unsigned int col = cpp_get_line (pfile)->col; + + /* Supply enough whitespace to put this token in its original + column. Don't bother trying to reconstruct tabs; we can't + get it right in general, and nothing ought to care. (Yes, + some things do care; the fault lies with them.) */ + maybe_print_line (line); + if (col > 1) + { + if (token->flags & PREV_WHITE) + col--; + while (--col) + putc (' ', print.outf); + } + } + else if ((token->flags & (PREV_WHITE | AVOID_LPASTE)) + == AVOID_LPASTE + && cpp_avoid_paste (pfile, &tokens[1 - index], token)) + token->flags |= PREV_WHITE; + /* Special case '# ': insert a space between + the # and the token. This will prevent it from being + treated as a directive when this code is re-preprocessed. + XXX Should do this only at the beginning of a line, but how? */ + else if (token->type == CPP_NAME && token->val.node->directive_index + && tokens[1 - index].type == CPP_HASH) + token->flags |= PREV_WHITE; + + cpp_output_token (token, print.outf); + print.printed = 1; + if (token->type == CPP_STRING || token->type == CPP_WSTRING + || token->type == CPP_COMMENT) + check_multiline_token (&token->val.str); + } + } + while (cpp_pop_buffer (pfile) != 0); +} + +/* Adjust print.lineno for newlines embedded in tokens. */ +static void +check_multiline_token (str) + cpp_string *str; +{ + unsigned int i; + + for (i = 0; i < str->len; i++) + if (str->text[i] == '\n') + print.lineno++; +} + +/* Initialize a cpp_printer structure. As a side effect, open the + output file. */ +static int +printer_init (pfile) + cpp_reader *pfile; +{ + print.last_fname = 0; + print.lineno = 0; + print.printed = 0; + + if (options->out_fname[0] == '\0') + print.outf = stdout; + else + { + print.outf = fopen (options->out_fname, "w"); + if (! print.outf) + { + cpp_notice_from_errno (pfile, options->out_fname); + return 1; + } + } + + return 0; +} + +/* Newline-terminate any output line currently in progress. If + appropriate, write the current line number to the output, or pad + with newlines so the output line matches the current line. */ +static void +maybe_print_line (line) + unsigned int line; +{ + /* End the previous line of text (probably only needed until we get + multi-line tokens fixed). */ + if (print.printed) + { + putc ('\n', print.outf); + print.lineno++; + print.printed = 0; + } + + if (options->no_line_commands) + { + print.lineno = line; + return; + } + + /* print.lineno is zero if this is the first token of the file. We + handle this specially, so that a first line of "# 1 "foo.c" in + file foo.i outputs just the foo.c line, and not a foo.i line. */ + if (line >= print.lineno && line < print.lineno + 8 && print.lineno) + { + while (line > print.lineno) + { + putc ('\n', print.outf); + print.lineno++; + } + } + else + { + print.lineno = line; + print_line (""); + } +} + +static void +print_line (special_flags) + const char *special_flags; +{ + /* End any previous line of text. */ + if (print.printed) + putc ('\n', print.outf); + print.printed = 0; + + /* SDCC likes #line, not # number. Should be fixed... */ +#if 0 + fprintf (print.outf, "# %u \"%s\"%s%s\n", + print.lineno, print.last_fname, special_flags, print.syshdr_flags); +#else + fprintf (print.outf, "#line %u \"%s\"%s%s\n", + print.lineno, print.last_fname, special_flags, print.syshdr_flags); +#endif +} + +/* Callbacks. */ + +static void +cb_ident (pfile, str) + cpp_reader *pfile ATTRIBUTE_UNUSED; + const cpp_string * str; +{ + maybe_print_line (cpp_get_line (pfile)->output_line); + fprintf (print.outf, "#ident \"%s\"\n", str->text); + print.lineno++; +} + +static void +cb_define (pfile, node) + cpp_reader *pfile; + cpp_hashnode *node; +{ + maybe_print_line (cpp_get_line (pfile)->output_line); + fputs ("#define ", print.outf); + + /* -dD command line option. */ + if (options->dump_macros == dump_definitions) + fputs ((const char *) cpp_macro_definition (pfile, node), print.outf); + else + fputs ((const char *) NODE_NAME (node), print.outf); + + putc ('\n', print.outf); + print.lineno++; +} + +static void +cb_undef (pfile, node) + cpp_reader *pfile; + cpp_hashnode *node; +{ + maybe_print_line (cpp_get_line (pfile)->output_line); + fprintf (print.outf, "#undef %s\n", NODE_NAME (node)); + print.lineno++; +} + +static void +cb_include (pfile, dir, header) + cpp_reader *pfile ATTRIBUTE_UNUSED; + const unsigned char *dir; + const cpp_token *header; +{ + maybe_print_line (cpp_get_line (pfile)->output_line); + fprintf (print.outf, "#%s %s\n", dir, cpp_token_as_text (pfile, header)); + print.lineno++; +} + +static void +cb_file_change (pfile, fc) + cpp_reader *pfile ATTRIBUTE_UNUSED; + const cpp_file_change *fc; +{ + /* Bring current file to correct line (except first file). */ + if (fc->reason == FC_ENTER && fc->from.filename) + maybe_print_line (fc->from.lineno); + + print.last_fname = fc->to.filename; + if (fc->externc) + print.syshdr_flags = " 3 4"; + else if (fc->sysp) + print.syshdr_flags = " 3"; + else + print.syshdr_flags = ""; + + if (print.lineno) + { + const char *flags = ""; + + print.lineno = fc->to.lineno; + if (fc->reason == FC_ENTER) + flags = " 1"; + else if (fc->reason == FC_LEAVE) + flags = " 2"; + + if (! options->no_line_commands) + print_line (flags); + } +} + +static void +cb_def_pragma (pfile) + cpp_reader *pfile; +{ + maybe_print_line (cpp_get_line (pfile)->output_line); + fputs ("#pragma ", print.outf); + cpp_output_line (pfile, print.outf); + print.lineno++; +} + +/* Dump out the hash table. */ +static int +dump_macro (pfile, node, v) + cpp_reader *pfile; + cpp_hashnode *node; + void *v ATTRIBUTE_UNUSED; +{ + if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)) + { + fputs ("#define ", print.outf); + fputs ((const char *) cpp_macro_definition (pfile, node), print.outf); + putc ('\n', print.outf); + print.lineno++; + } + + return 1; +} diff --git a/support/cpp2/hashtable.c b/support/cpp2/hashtable.c new file mode 100644 index 00000000..77868f88 --- /dev/null +++ b/support/cpp2/hashtable.c @@ -0,0 +1,315 @@ +/* Hash tables. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! */ + +#include "config.h" +#include "system.h" +#include "hashtable.h" + +/* The code below is a specialization of Vladimir Makarov's expandable + hash tables (see libiberty/hashtab.c). The abstraction penalty was + too high to continue using the generic form. This code knows + intrinsically how to calculate a hash value, and how to compare an + existing entry with a potential new one. Also, the ability to + delete members from the table has been removed. */ + +static unsigned int calc_hash PARAMS ((const unsigned char *, unsigned int)); +static void ht_expand PARAMS ((hash_table *)); + +/* Let particular systems override the size of a chunk. */ +#ifndef OBSTACK_CHUNK_SIZE +#define OBSTACK_CHUNK_SIZE 0 +#endif + /* Let them override the alloc and free routines too. */ +#ifndef OBSTACK_CHUNK_ALLOC +#define OBSTACK_CHUNK_ALLOC malloc +#endif +#ifndef OBSTACK_CHUNK_FREE +#define OBSTACK_CHUNK_FREE free +#endif + +/* Initialise an obstack. */ +void +gcc_obstack_init (obstack) + struct obstack *obstack; +{ + _obstack_begin (obstack, OBSTACK_CHUNK_SIZE, 0, + (void *(*) PARAMS ((long))) OBSTACK_CHUNK_ALLOC, + (void (*) PARAMS ((void *))) OBSTACK_CHUNK_FREE); +} + +/* Calculate the hash of the string STR of length LEN. */ + +static unsigned int +calc_hash (str, len) + const unsigned char *str; + unsigned int len; +{ + unsigned int n = len; + unsigned int r = 0; +#define HASHSTEP(r, c) ((r) * 67 + ((c) - 113)); + + while (n--) + r = HASHSTEP (r, *str++); + + return r + len; +#undef HASHSTEP +} + +/* Initialize an identifier hashtable. */ + +hash_table * +ht_create (order) + unsigned int order; +{ + unsigned int nslots = 1 << order; + hash_table *table; + + table = (hash_table *) xmalloc (sizeof (hash_table)); + memset (table, 0, sizeof (hash_table)); + + /* Strings need no alignment. */ + gcc_obstack_init (&table->stack); + obstack_alignment_mask (&table->stack) = 0; + + table->entries = (hashnode *) xcalloc (nslots, sizeof (hashnode)); + table->nslots = nslots; + return table; +} + +/* Returns the hash entry for the a STR of length LEN. If that string + already exists in the table, returns the existing entry, and, if + INSERT is CPP_ALLOCED, frees the last obstack object. If the + identifier hasn't been seen before, and INSERT is CPP_NO_INSERT, + returns NULL. Otherwise insert and returns a new entry. A new + string is alloced if INSERT is CPP_ALLOC, otherwise INSERT is + CPP_ALLOCED and the item is assumed to be at the top of the + obstack. */ +hashnode +ht_lookup (table, str, len, insert) + hash_table *table; + const unsigned char *str; + unsigned int len; + enum ht_lookup_option insert; +{ + unsigned int hash = calc_hash (str, len); + unsigned int hash2; + unsigned int index; + size_t sizemask; + hashnode node; + + sizemask = table->nslots - 1; + index = hash & sizemask; + + /* hash2 must be odd, so we're guaranteed to visit every possible + location in the table during rehashing. */ + hash2 = ((hash * 17) & sizemask) | 1; + table->searches++; + + for (;;) + { + node = table->entries[index]; + + if (node == NULL) + break; + + if (HT_LEN (node) == len && !memcmp (HT_STR (node), str, len)) + { + if (insert == HT_ALLOCED) + /* The string we search for was placed at the end of the + obstack. Release it. */ + obstack_free (&table->stack, (PTR) str); + return node; + } + + index = (index + hash2) & sizemask; + table->collisions++; + } + + if (insert == HT_NO_INSERT) + return NULL; + + node = (*table->alloc_node) (table); + table->entries[index] = node; + + HT_LEN (node) = len; + if (insert == HT_ALLOC) + HT_STR (node) = obstack_copy (&table->stack, str, len + 1); + else + HT_STR (node) = str; + + if (++table->nelements * 4 >= table->nslots * 3) + /* Must expand the string table. */ + ht_expand (table); + + return node; +} + +/* Double the size of a hash table, re-hashing existing entries. */ + +static void +ht_expand (table) + hash_table *table; +{ + hashnode *nentries, *p, *limit; + unsigned int size, sizemask; + + size = table->nslots * 2; + nentries = (hashnode *) xcalloc (size, sizeof (hashnode)); + sizemask = size - 1; + + p = table->entries; + limit = p + table->nslots; + do + if (*p) + { + unsigned int index, hash, hash2; + + hash = calc_hash (HT_STR (*p), HT_LEN (*p)); + hash2 = ((hash * 17) & sizemask) | 1; + index = hash & sizemask; + + for (;;) + { + if (! nentries[index]) + { + nentries[index] = *p; + break; + } + + index = (index + hash2) & sizemask; + } + } + while (++p < limit); + + free (table->entries); + table->entries = nentries; + table->nslots = size; +} + +/* For all nodes in TABLE, callback CB with parameters TABLE->PFILE, + the node, and V. */ +void +ht_forall (table, cb, v) + hash_table *table; + ht_cb cb; + const PTR v; +{ + hashnode *p, *limit; + + p = table->entries; + limit = p + table->nslots; + do + if (*p) + { + if ((*cb) (table->pfile, *p, v) == 0) + break; + } + while (++p < limit); +} + +/* Dump allocation statistics to stderr. */ + +void +ht_dump_statistics (table) + hash_table *table; +{ + size_t nelts, nids, overhead, headers; + size_t total_bytes, longest, sum_of_squares; + double exp_len, exp_len2, exp2_len; + hashnode *p, *limit; + +#define SCALE(x) ((unsigned long) ((x) < 1024*10 \ + ? (x) \ + : ((x) < 1024*1024*10 \ + ? (x) / 1024 \ + : (x) / (1024*1024)))) +#define LABEL(x) ((x) < 1024*10 ? ' ' : ((x) < 1024*1024*10 ? 'k' : 'M')) + + total_bytes = longest = sum_of_squares = nids = 0; + p = table->entries; + limit = p + table->nslots; + do + if (*p) + { + size_t n = HT_LEN (*p); + + total_bytes += n; + sum_of_squares += n * n; + if (n > longest) + longest = n; + nids++; + } + while (++p < limit); + + nelts = table->nelements; + overhead = obstack_memory_used (&table->stack) - total_bytes; + headers = table->nslots * sizeof (hashnode); + + fprintf (stderr, "\nString pool\nentries\t\t%lu\n", + (unsigned long) nelts); + fprintf (stderr, "identifiers\t%lu (%.2f%%)\n", + (unsigned long) nids, nids * 100.0 / nelts); + fprintf (stderr, "slots\t\t%lu\n", + (unsigned long) table->nslots); + fprintf (stderr, "bytes\t\t%lu%c (%lu%c overhead)\n", + SCALE (total_bytes), LABEL (total_bytes), + SCALE (overhead), LABEL (overhead)); + fprintf (stderr, "table size\t%lu%c\n", + SCALE (headers), LABEL (headers)); + + exp_len = (double)total_bytes / (double)nelts; + exp2_len = exp_len * exp_len; + exp_len2 = (double) sum_of_squares / (double) nelts; + + fprintf (stderr, "coll/search\t%.4f\n", + (double) table->collisions / (double) table->searches); + fprintf (stderr, "ins/search\t%.4f\n", + (double) nelts / (double) table->searches); + fprintf (stderr, "avg. entry\t%.2f bytes (+/- %.2f)\n", + exp_len, approx_sqrt (exp_len2 - exp2_len)); + fprintf (stderr, "longest entry\t%lu\n", + (unsigned long) longest); +#undef SCALE +#undef LABEL +} + +/* Return the approximate positive square root of a number N. This is for + statistical reports, not code generation. */ +double +approx_sqrt (x) + double x; +{ + double s, d; + + if (x < 0) + abort (); + if (x == 0) + return 0; + + s = x; + do + { + d = (s * s - x) / (2 * s); + s -= d; + } + while (d > .0001); + return s; +} diff --git a/support/cpp2/hashtable.h b/support/cpp2/hashtable.h new file mode 100644 index 00000000..5b08fde2 --- /dev/null +++ b/support/cpp2/hashtable.h @@ -0,0 +1,85 @@ +/* Hash tables. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef GCC_HASHTABLE_H +#define GCC_HASHTABLE_H + +#include "obstack.h" + +/* This is what each hash table entry points to. It may be embedded + deeply within another object. */ +typedef struct ht_identifier ht_identifier; +struct ht_identifier +{ + unsigned int len; + const unsigned char *str; +}; + +#define HT_LEN(NODE) ((NODE)->len) +#define HT_STR(NODE) ((NODE)->str) + +/* We want code outside cpplib, such as the compiler front-ends, to be + able to include this header, and to be able to link with + cpphashtbl.o without pulling in any other parts of cpplib. */ + +struct cpp_reader; +typedef struct ht hash_table; +typedef struct ht_identifier *hashnode; + +enum ht_lookup_option {HT_NO_INSERT = 0, HT_ALLOC, HT_ALLOCED}; + +/* An identifier hash table for cpplib and the front ends. */ +struct ht +{ + /* Identifiers are allocated from here. */ + struct obstack stack; + + hashnode *entries; + /* Call back. */ + hashnode (*alloc_node) PARAMS ((hash_table *)); + + unsigned int nslots; /* Total slots in the entries array. */ + unsigned int nelements; /* Number of live elements. */ + + /* Link to reader, if any. For the benefit of cpplib. */ + struct cpp_reader *pfile; + + /* Table usage statistics. */ + unsigned int searches; + unsigned int collisions; +}; + +extern void gcc_obstack_init PARAMS ((struct obstack *)); +/* Initialise the hashtable with 2 ^ order entries. */ +extern hash_table *ht_create PARAMS ((unsigned int order)); +extern hashnode ht_lookup PARAMS ((hash_table *, const unsigned char *, + unsigned int, enum ht_lookup_option)); + +/* For all nodes in TABLE, make a callback. The callback takes + TABLE->PFILE, the node, and a PTR, and the callback sequence stops + if the callback returns zero. */ +typedef int (*ht_cb) PARAMS ((struct cpp_reader *, hashnode, const void *)); +extern void ht_forall PARAMS ((hash_table *, ht_cb, const void *)); + +/* Dump allocation statistics to stderr. */ +extern void ht_dump_statistics PARAMS ((hash_table *)); + +/* Approximate positive square root of a host double. This is for + statistical reports, not code generation. */ +extern double approx_sqrt PARAMS ((double)); + +#endif /* GCC_HASHTABLE_H */ diff --git a/support/cpp2/hwint.h b/support/cpp2/hwint.h new file mode 100644 index 00000000..b624caf9 --- /dev/null +++ b/support/cpp2/hwint.h @@ -0,0 +1,149 @@ +/* HOST_WIDE_INT definitions for the GNU compiler. + Copyright (C) 1998 Free Software Foundation, Inc. + + This file is part of GNU CC. + + Provide definitions for macros which depend on HOST_BITS_PER_INT + and HOST_BITS_PER_LONG. */ + +#ifndef GCC_HWINT_H +#define GCC_HWINT_H + +/* This describes the machine the compiler is hosted on. */ +#define HOST_BITS_PER_CHAR CHAR_BIT +#define HOST_BITS_PER_SHORT (CHAR_BIT * SIZEOF_SHORT) +#define HOST_BITS_PER_INT (CHAR_BIT * SIZEOF_INT) +#define HOST_BITS_PER_LONG (CHAR_BIT * SIZEOF_LONG) + +#ifdef HAVE_LONG_LONG +# define HOST_BITS_PER_LONGLONG (CHAR_BIT * SIZEOF_LONG_LONG) +#else +/* If we're here and we're GCC, assume this is stage 2+ of a bootstrap + and 'long long' has the width of the *target*'s long long. */ +# if GCC_VERSION > 3000 +# define HOST_BITS_PER_LONGLONG LONG_LONG_TYPE_SIZE +# endif /* gcc */ +#endif /* no long long */ + +/* Find the largest host integer type and set its size and type. */ + +/* Use long long on the host if the target has a wider long type than + the host. */ + +#if ! defined HOST_BITS_PER_WIDE_INT \ + && defined HOST_BITS_PER_LONGLONG \ + && (HOST_BITS_PER_LONGLONG > HOST_BITS_PER_LONG) \ + && (defined (LONG_LONG_MAX) || defined (LONGLONG_MAX) \ + || defined (LLONG_MAX) || defined (__GNUC__)) + +# ifdef MAX_LONG_TYPE_SIZE +# if MAX_LONG_TYPE_SIZE > HOST_BITS_PER_LONG +# define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONGLONG +# define HOST_WIDE_INT long long +# endif +# else +# if LONG_TYPE_SIZE > HOST_BITS_PER_LONG +# define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONGLONG +# define HOST_WIDE_INT long long +# endif +# endif + +#endif + +#ifndef HOST_BITS_PER_WIDE_INT + +# if HOST_BITS_PER_LONG > HOST_BITS_PER_INT +# define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG +# define HOST_WIDE_INT long +# else +# define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT +# define HOST_WIDE_INT int +# endif + +#endif /* ! HOST_BITS_PER_WIDE_INT */ + +/* Provide defaults for the way to print a HOST_WIDE_INT + in various manners. */ + +#ifndef HOST_WIDE_INT_PRINT_DEC +# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT +# define HOST_WIDE_INT_PRINT_DEC "%d" +# else +# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG +# define HOST_WIDE_INT_PRINT_DEC "%ld" +# else +# define HOST_WIDE_INT_PRINT_DEC "%lld" +# endif +# endif +#endif /* ! HOST_WIDE_INT_PRINT_DEC */ + +#ifndef HOST_WIDE_INT_PRINT_UNSIGNED +# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT +# define HOST_WIDE_INT_PRINT_UNSIGNED "%u" +# else +# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG +# define HOST_WIDE_INT_PRINT_UNSIGNED "%lu" +# else +# define HOST_WIDE_INT_PRINT_UNSIGNED "%llu" +# endif +# endif +#endif /* ! HOST_WIDE_INT_PRINT_UNSIGNED */ + +#ifndef HOST_WIDE_INT_PRINT_HEX +# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT +# define HOST_WIDE_INT_PRINT_HEX "0x%x" +# else +# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG +# define HOST_WIDE_INT_PRINT_HEX "0x%lx" +# else +# define HOST_WIDE_INT_PRINT_HEX "0x%llx" +# endif +# endif +#endif /* ! HOST_WIDE_INT_PRINT_HEX */ + +#ifndef HOST_WIDE_INT_PRINT_DOUBLE_HEX +# if HOST_BITS_PER_WIDE_INT == 64 +# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT +# define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%x%016x" +# else +# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG +# define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%lx%016lx" +# else +# define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%llx%016llx" +# endif +# endif +# else +# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT +# define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%x%08x" +# else +# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG +# define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%lx%08lx" +# else +# define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%llx%08llx" +# endif +# endif +# endif +#endif /* ! HOST_WIDE_INT_PRINT_DOUBLE_HEX */ + +/* Find HOST_WIDEST_INT and set its bit size, type and print macros. + It will be the largest integer mode supported by the host which may + (or may not) be larger than HOST_WIDE_INT. */ + +#ifndef HOST_WIDEST_INT +#if defined HOST_BITS_PER_LONGLONG \ + && HOST_BITS_PER_LONGLONG > HOST_BITS_PER_LONG +# define HOST_BITS_PER_WIDEST_INT HOST_BITS_PER_LONGLONG +# define HOST_WIDEST_INT long long +# define HOST_WIDEST_INT_PRINT_DEC "%lld" +# define HOST_WIDEST_INT_PRINT_UNSIGNED "%llu" +# define HOST_WIDEST_INT_PRINT_HEX "0x%llx" +# else +# define HOST_BITS_PER_WIDEST_INT HOST_BITS_PER_LONG +# define HOST_WIDEST_INT long +# define HOST_WIDEST_INT_PRINT_DEC "%ld" +# define HOST_WIDEST_INT_PRINT_UNSIGNED "%lu" +# define HOST_WIDEST_INT_PRINT_HEX "0x%lx" +# endif /* long long wider than long */ +#endif /* ! HOST_WIDEST_INT */ + +#endif /* ! GCC_HWINT_H */ diff --git a/support/cpp2/intl.c b/support/cpp2/intl.c new file mode 100644 index 00000000..761daf33 --- /dev/null +++ b/support/cpp2/intl.c @@ -0,0 +1,6 @@ +/* intl.c - internationalization */ + +#include "ansidecl.h" +#include "intl.h" + +const char localedir[] = LOCALEDIR; diff --git a/support/cpp2/intl.h b/support/cpp2/intl.h new file mode 100644 index 00000000..56c075e6 --- /dev/null +++ b/support/cpp2/intl.h @@ -0,0 +1,52 @@ +/* intl.h - internationalization + Copyright 1998 Free Software Foundation, Inc. + + GCC 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. + + GCC is distributed in the hope that 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifdef HAVE_LOCALE_H +# include +#endif + +#ifndef HAVE_SETLOCALE +# define setlocale(category, locale) (locale) +#endif + +#ifdef ENABLE_NLS +# include + extern const char localedir[]; +#else +/* Stubs that do something close enough. */ +# ifdef textdomain +# undef textdomain +# endif +# define textdomain(domain) (domain) +# ifdef bindtextdomain +# undef bindtextdomain +# endif +# define bindtextdomain(domain, directory) (domain) +# ifdef gettext +# undef gettext +# endif +# define gettext(msgid) (msgid) +#endif + +#ifndef _ +# define _(msgid) gettext (msgid) +#endif + +#ifndef N_ +# define N_(msgid) (msgid) +#endif diff --git a/support/cpp2/libiberty.h b/support/cpp2/libiberty.h new file mode 100644 index 00000000..0e8b492e --- /dev/null +++ b/support/cpp2/libiberty.h @@ -0,0 +1 @@ +/* nada */ diff --git a/support/cpp2/libiberty/lbasename.c b/support/cpp2/libiberty/lbasename.c new file mode 100644 index 00000000..7f870497 --- /dev/null +++ b/support/cpp2/libiberty/lbasename.c @@ -0,0 +1,89 @@ +/* Libiberty basename. Like basename, but is not overridden by the + system C library. + Copyright (C) 2001 Free Software Foundation, Inc. + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* +NAME + lbasename -- return pointer to last component of a pathname + +SYNOPSIS + char *lbasename (const char *name) + +DESCRIPTION + Given a pointer to a string containing a typical pathname + (/usr/src/cmd/ls/ls.c for example), returns a pointer to the + last component of the pathname ("ls.c" in this case). The + returned pointer is guaranteed to lie within the original + string. This latter fact is not true of many vendor C + libraries, which return special strings or modify the passed + strings for particular input. + + In particular, the empty string returns the same empty string, + and a path ending in '/' returns the empty string after it. +*/ + +#include "ansidecl.h" +#include "libiberty.h" +#include "safe-ctype.h" + +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) \ + || defined (__DJGPP__) || defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +#endif + +/* Define IS_DIR_SEPARATOR. VMS uses '::', ':', '[...]' and '<...>' to + separate the different components of a file specification. It's a + bit of a stretch to call ':', ']' and '>' directory separators, so + just define the test to find the file name component. */ +#ifdef VMS +# define IS_DIR_SEPARATOR(ch) ((ch) == ':' || (ch) == ']' || (ch) == '>') +#else +# ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +# else +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +# endif +#endif + +char * +lbasename (name) + const char *name; +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over a possible disk name. */ + if (ISALPHA (name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + + return (char *) base; +} diff --git a/support/cpp2/libiberty/obstack.c b/support/cpp2/libiberty/obstack.c new file mode 100644 index 00000000..0d4a4c88 --- /dev/null +++ b/support/cpp2/libiberty/obstack.c @@ -0,0 +1,593 @@ +/* obstack.c - subroutines used implicitly by object stack macros + Copyright (C) 1988,89,90,91,92,93,94,96,97 Free Software Foundation, Inc. + + + NOTE: This source is derived from an old version taken from the GNU C + Library (glibc). + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "obstack.h" + +/* NOTE BEFORE MODIFYING THIS FILE: This version number must be + incremented whenever callers compiled using an old obstack.h can no + longer properly call the functions in this obstack.c. */ +#define OBSTACK_INTERFACE_VERSION 1 + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself, and the installed library + supports the same library interface we do. This code is part of the GNU + C Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object + files, it is simpler to just do this in the source for each such file. */ + +#include /* Random thing to get __GNU_LIBRARY__. */ +#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1 +#include +#if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION +#define ELIDE_CODE +#endif +#endif + + +#ifndef ELIDE_CODE + + +#if defined (__STDC__) && __STDC__ +#define POINTER void * +#else +#define POINTER char * +#endif + +/* Determine default alignment. */ +struct fooalign {char x; double d;}; +#define DEFAULT_ALIGNMENT \ + ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0)) +/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. + But in fact it might be less smart and round addresses to as much as + DEFAULT_ROUNDING. So we prepare for it to do that. */ +union fooround {long x; double d;}; +#define DEFAULT_ROUNDING (sizeof (union fooround)) + +/* When we copy a long block of data, this is the unit to do it with. + On some machines, copying successive ints does not work; + in such a case, redefine COPYING_UNIT to `long' (if that works) + or `char' as a last resort. */ +#ifndef COPYING_UNIT +#define COPYING_UNIT int +#endif + + +/* The functions allocating more room by calling `obstack_chunk_alloc' + jump to the handler pointed to by `obstack_alloc_failed_handler'. + This variable by default points to the internal function + `print_and_abort'. */ +#if defined (__STDC__) && __STDC__ +static void print_and_abort (void); +void (*obstack_alloc_failed_handler) (void) = print_and_abort; +#else +static void print_and_abort (); +void (*obstack_alloc_failed_handler) () = print_and_abort; +#endif + +/* Exit value used when `print_and_abort' is used. */ +#if defined __GNU_LIBRARY__ || defined HAVE_STDLIB_H +#include +#endif +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif +int obstack_exit_failure = EXIT_FAILURE; + +/* The non-GNU-C macros copy the obstack into this global variable + to avoid multiple evaluation. */ + +struct obstack *_obstack; + +/* Define a macro that either calls functions with the traditional malloc/free + calling interface, or calls functions with the mmalloc/mfree interface + (that adds an extra first argument), based on the state of use_extra_arg. + For free, do not use ?:, since some compilers, like the MIPS compilers, + do not allow (expr) ? void : void. */ + +#if defined (__STDC__) && __STDC__ +#define CALL_CHUNKFUN(h, size) \ + (((h) -> use_extra_arg) \ + ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ + : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size))) + +#define CALL_FREEFUN(h, old_chunk) \ + do { \ + if ((h) -> use_extra_arg) \ + (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ + else \ + (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \ + } while (0) +#else +#define CALL_CHUNKFUN(h, size) \ + (((h) -> use_extra_arg) \ + ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ + : (*(struct _obstack_chunk *(*) ()) (h)->chunkfun) ((size))) + +#define CALL_FREEFUN(h, old_chunk) \ + do { \ + if ((h) -> use_extra_arg) \ + (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ + else \ + (*(void (*) ()) (h)->freefun) ((old_chunk)); \ + } while (0) +#endif + + +/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). + Objects start on multiples of ALIGNMENT (0 means use default). + CHUNKFUN is the function to use to allocate chunks, + and FREEFUN the function to free them. + + Return nonzero if successful, zero if out of memory. + To recover from an out of memory error, + free up some memory, then call this again. */ + +int +_obstack_begin (h, size, alignment, chunkfun, freefun) + struct obstack *h; + int size; + int alignment; +#if defined (__STDC__) && __STDC__ + POINTER (*chunkfun) (long); + void (*freefun) (void *); +#else + POINTER (*chunkfun) (); + void (*freefun) (); +#endif +{ + register struct _obstack_chunk *chunk; /* points to new chunk */ + + if (alignment == 0) + alignment = (int) DEFAULT_ALIGNMENT; + if (size == 0) + /* Default size is what GNU malloc can fit in a 4096-byte block. */ + { + /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. + Use the values for range checking, because if range checking is off, + the extra bytes won't be missed terribly, but if range checking is on + and we used a larger request, a whole extra 4096 bytes would be + allocated. + + These number are irrelevant to the new GNU malloc. I suspect it is + less sensitive to the size of the request. */ + int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + + 4 + DEFAULT_ROUNDING - 1) + & ~(DEFAULT_ROUNDING - 1)); + size = 4096 - extra; + } + +#if defined (__STDC__) && __STDC__ + h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun; + h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; +#else + h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; + h->freefun = freefun; +#endif + h->chunk_size = size; + h->alignment_mask = alignment - 1; + h->use_extra_arg = 0; + + chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); + if (!chunk) + (*obstack_alloc_failed_handler) (); + h->next_free = h->object_base = chunk->contents; + h->chunk_limit = chunk->limit + = (char *) chunk + h->chunk_size; + chunk->prev = 0; + /* The initial chunk now contains no empty object. */ + h->maybe_empty_object = 0; + h->alloc_failed = 0; + return 1; +} + +int +_obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg) + struct obstack *h; + int size; + int alignment; +#if defined (__STDC__) && __STDC__ + POINTER (*chunkfun) (POINTER, long); + void (*freefun) (POINTER, POINTER); +#else + POINTER (*chunkfun) (); + void (*freefun) (); +#endif + POINTER arg; +{ + register struct _obstack_chunk *chunk; /* points to new chunk */ + + if (alignment == 0) + alignment = (int) DEFAULT_ALIGNMENT; + if (size == 0) + /* Default size is what GNU malloc can fit in a 4096-byte block. */ + { + /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. + Use the values for range checking, because if range checking is off, + the extra bytes won't be missed terribly, but if range checking is on + and we used a larger request, a whole extra 4096 bytes would be + allocated. + + These number are irrelevant to the new GNU malloc. I suspect it is + less sensitive to the size of the request. */ + int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + + 4 + DEFAULT_ROUNDING - 1) + & ~(DEFAULT_ROUNDING - 1)); + size = 4096 - extra; + } + +#if defined(__STDC__) && __STDC__ + h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun; + h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; +#else + h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun; + h->freefun = freefun; +#endif + h->chunk_size = size; + h->alignment_mask = alignment - 1; + h->extra_arg = arg; + h->use_extra_arg = 1; + + chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); + if (!chunk) + (*obstack_alloc_failed_handler) (); + h->next_free = h->object_base = chunk->contents; + h->chunk_limit = chunk->limit + = (char *) chunk + h->chunk_size; + chunk->prev = 0; + /* The initial chunk now contains no empty object. */ + h->maybe_empty_object = 0; + h->alloc_failed = 0; + return 1; +} + +/* Allocate a new current chunk for the obstack *H + on the assumption that LENGTH bytes need to be added + to the current object, or a new object of length LENGTH allocated. + Copies any partial object from the end of the old chunk + to the beginning of the new one. */ + +void +_obstack_newchunk (h, length) + struct obstack *h; + int length; +{ + register struct _obstack_chunk *old_chunk = h->chunk; + register struct _obstack_chunk *new_chunk; + register long new_size; + register long obj_size = h->next_free - h->object_base; + register long i; + long already; + + /* Compute size for new chunk. */ + new_size = (obj_size + length) + (obj_size >> 3) + 100; + if (new_size < h->chunk_size) + new_size = h->chunk_size; + + /* Allocate and initialize the new chunk. */ + new_chunk = CALL_CHUNKFUN (h, new_size); + if (!new_chunk) + (*obstack_alloc_failed_handler) (); + h->chunk = new_chunk; + new_chunk->prev = old_chunk; + new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; + + /* Move the existing object to the new chunk. + Word at a time is fast and is safe if the object + is sufficiently aligned. */ + if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT) + { + for (i = obj_size / sizeof (COPYING_UNIT) - 1; + i >= 0; i--) + ((COPYING_UNIT *)new_chunk->contents)[i] + = ((COPYING_UNIT *)h->object_base)[i]; + /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT, + but that can cross a page boundary on a machine + which does not do strict alignment for COPYING_UNITS. */ + already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT); + } + else + already = 0; + /* Copy remaining bytes one by one. */ + for (i = already; i < obj_size; i++) + new_chunk->contents[i] = h->object_base[i]; + + /* If the object just copied was the only data in OLD_CHUNK, + free that chunk and remove it from the chain. + But not if that chunk might contain an empty object. */ + if (h->object_base == old_chunk->contents && ! h->maybe_empty_object) + { + new_chunk->prev = old_chunk->prev; + CALL_FREEFUN (h, old_chunk); + } + + h->object_base = new_chunk->contents; + h->next_free = h->object_base + obj_size; + /* The new chunk certainly contains no empty object yet. */ + h->maybe_empty_object = 0; +} + +/* Return nonzero if object OBJ has been allocated from obstack H. + This is here for debugging. + If you use it in a program, you are probably losing. */ + +#if defined (__STDC__) && __STDC__ +/* Suppress -Wmissing-prototypes warning. We don't want to declare this in + obstack.h because it is just for debugging. */ +int _obstack_allocated_p (struct obstack *h, POINTER obj); +#endif + +int +_obstack_allocated_p (h, obj) + struct obstack *h; + POINTER obj; +{ + register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ + register struct _obstack_chunk *plp; /* point to previous chunk if any */ + + lp = (h)->chunk; + /* We use >= rather than > since the object cannot be exactly at + the beginning of the chunk but might be an empty object exactly + at the end of an adjacent chunk. */ + while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj)) + { + plp = lp->prev; + lp = plp; + } + return lp != 0; +} + +/* Free objects in obstack H, including OBJ and everything allocate + more recently than OBJ. If OBJ is zero, free everything in H. */ + +#undef obstack_free + +/* This function has two names with identical definitions. + This is the first one, called from non-ANSI code. */ + +void +_obstack_free (h, obj) + struct obstack *h; + POINTER obj; +{ + register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ + register struct _obstack_chunk *plp; /* point to previous chunk if any */ + + lp = h->chunk; + /* We use >= because there cannot be an object at the beginning of a chunk. + But there can be an empty object at that address + at the end of another chunk. */ + while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj)) + { + plp = lp->prev; + CALL_FREEFUN (h, lp); + lp = plp; + /* If we switch chunks, we can't tell whether the new current + chunk contains an empty object, so assume that it may. */ + h->maybe_empty_object = 1; + } + if (lp) + { + h->object_base = h->next_free = (char *) (obj); + h->chunk_limit = lp->limit; + h->chunk = lp; + } + else if (obj != 0) + /* obj is not in any of the chunks! */ + abort (); +} + +/* This function is used from ANSI code. */ + +void +obstack_free (h, obj) + struct obstack *h; + POINTER obj; +{ + register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ + register struct _obstack_chunk *plp; /* point to previous chunk if any */ + + lp = h->chunk; + /* We use >= because there cannot be an object at the beginning of a chunk. + But there can be an empty object at that address + at the end of another chunk. */ + while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj)) + { + plp = lp->prev; + CALL_FREEFUN (h, lp); + lp = plp; + /* If we switch chunks, we can't tell whether the new current + chunk contains an empty object, so assume that it may. */ + h->maybe_empty_object = 1; + } + if (lp) + { + h->object_base = h->next_free = (char *) (obj); + h->chunk_limit = lp->limit; + h->chunk = lp; + } + else if (obj != 0) + /* obj is not in any of the chunks! */ + abort (); +} + +int +_obstack_memory_used (h) + struct obstack *h; +{ + register struct _obstack_chunk* lp; + register int nbytes = 0; + + for (lp = h->chunk; lp != 0; lp = lp->prev) + { + nbytes += lp->limit - (char *) lp; + } + return nbytes; +} + +/* Define the error handler. */ +#ifndef _ +# ifdef HAVE_LIBINTL_H +# include +# ifndef _ +# define _(Str) gettext (Str) +# endif +# else +# define _(Str) (Str) +# endif +#endif + +static void +print_and_abort () +{ + fputs (_("memory exhausted\n"), stderr); + exit (obstack_exit_failure); +} + +#if 0 +/* These are now turned off because the applications do not use it + and it uses bcopy via obstack_grow, which causes trouble on sysV. */ + +/* Now define the functional versions of the obstack macros. + Define them to simply use the corresponding macros to do the job. */ + +#if defined (__STDC__) && __STDC__ +/* These function definitions do not work with non-ANSI preprocessors; + they won't pass through the macro names in parentheses. */ + +/* The function names appear in parentheses in order to prevent + the macro-definitions of the names from being expanded there. */ + +POINTER (obstack_base) (obstack) + struct obstack *obstack; +{ + return obstack_base (obstack); +} + +POINTER (obstack_next_free) (obstack) + struct obstack *obstack; +{ + return obstack_next_free (obstack); +} + +int (obstack_object_size) (obstack) + struct obstack *obstack; +{ + return obstack_object_size (obstack); +} + +int (obstack_room) (obstack) + struct obstack *obstack; +{ + return obstack_room (obstack); +} + +int (obstack_make_room) (obstack, length) + struct obstack *obstack; + int length; +{ + return obstack_make_room (obstack, length); +} + +void (obstack_grow) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + obstack_grow (obstack, pointer, length); +} + +void (obstack_grow0) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + obstack_grow0 (obstack, pointer, length); +} + +void (obstack_1grow) (obstack, character) + struct obstack *obstack; + int character; +{ + obstack_1grow (obstack, character); +} + +void (obstack_blank) (obstack, length) + struct obstack *obstack; + int length; +{ + obstack_blank (obstack, length); +} + +void (obstack_1grow_fast) (obstack, character) + struct obstack *obstack; + int character; +{ + obstack_1grow_fast (obstack, character); +} + +void (obstack_blank_fast) (obstack, length) + struct obstack *obstack; + int length; +{ + obstack_blank_fast (obstack, length); +} + +POINTER (obstack_finish) (obstack) + struct obstack *obstack; +{ + return obstack_finish (obstack); +} + +POINTER (obstack_alloc) (obstack, length) + struct obstack *obstack; + int length; +{ + return obstack_alloc (obstack, length); +} + +POINTER (obstack_copy) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + return obstack_copy (obstack, pointer, length); +} + +POINTER (obstack_copy0) (obstack, pointer, length) + struct obstack *obstack; + POINTER pointer; + int length; +{ + return obstack_copy0 (obstack, pointer, length); +} + +#endif /* __STDC__ */ + +#endif /* 0 */ + +#endif /* !ELIDE_CODE */ diff --git a/support/cpp2/libiberty/obstack.h b/support/cpp2/libiberty/obstack.h new file mode 100644 index 00000000..d86d9f2c --- /dev/null +++ b/support/cpp2/libiberty/obstack.h @@ -0,0 +1,599 @@ +/* obstack.h - object stack macros + Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, + 1999, 2000 + Free Software Foundation, Inc. + + + NOTE: The canonical source of this file is maintained with the GNU C Library. + Bugs can be reported to bug-glibc@gnu.org. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +/* Summary: + +All the apparent functions defined here are macros. The idea +is that you would use these pre-tested macros to solve a +very specific set of problems, and they would run fast. +Caution: no side-effects in arguments please!! They may be +evaluated MANY times!! + +These macros operate a stack of objects. Each object starts life +small, and may grow to maturity. (Consider building a word syllable +by syllable.) An object can move while it is growing. Once it has +been "finished" it never changes address again. So the "top of the +stack" is typically an immature growing object, while the rest of the +stack is of mature, fixed size and fixed address objects. + +These routines grab large chunks of memory, using a function you +supply, called `obstack_chunk_alloc'. On occasion, they free chunks, +by calling `obstack_chunk_free'. You must define them and declare +them before using any obstack macros. + +Each independent stack is represented by a `struct obstack'. +Each of the obstack macros expects a pointer to such a structure +as the first argument. + +One motivation for this package is the problem of growing char strings +in symbol tables. Unless you are "fascist pig with a read-only mind" +--Gosper's immortal quote from HAKMEM item 154, out of context--you +would not like to put any arbitrary upper limit on the length of your +symbols. + +In practice this often means you will build many short symbols and a +few long symbols. At the time you are reading a symbol you don't know +how long it is. One traditional method is to read a symbol into a +buffer, realloc()ating the buffer every time you try to read a symbol +that is longer than the buffer. This is beaut, but you still will +want to copy the symbol from the buffer to a more permanent +symbol-table entry say about half the time. + +With obstacks, you can work differently. Use one obstack for all symbol +names. As you read a symbol, grow the name in the obstack gradually. +When the name is complete, finalize it. Then, if the symbol exists already, +free the newly read name. + +The way we do this is to take a large chunk, allocating memory from +low addresses. When you want to build a symbol in the chunk you just +add chars above the current "high water mark" in the chunk. When you +have finished adding chars, because you got to the end of the symbol, +you know how long the chars are, and you can create a new object. +Mostly the chars will not burst over the highest address of the chunk, +because you would typically expect a chunk to be (say) 100 times as +long as an average object. + +In case that isn't clear, when we have enough chars to make up +the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed) +so we just point to it where it lies. No moving of chars is +needed and this is the second win: potentially long strings need +never be explicitly shuffled. Once an object is formed, it does not +change its address during its lifetime. + +When the chars burst over a chunk boundary, we allocate a larger +chunk, and then copy the partly formed object from the end of the old +chunk to the beginning of the new larger chunk. We then carry on +accreting characters to the end of the object as we normally would. + +A special macro is provided to add a single char at a time to a +growing object. This allows the use of register variables, which +break the ordinary 'growth' macro. + +Summary: + We allocate large chunks. + We carve out one object at a time from the current chunk. + Once carved, an object never moves. + We are free to append data of any size to the currently + growing object. + Exactly one object is growing in an obstack at any one time. + You can run one obstack per control block. + You may have as many control blocks as you dare. + Because of the way we do it, you can `unwind' an obstack + back to a previous state. (You may remove objects much + as you would with a stack.) +*/ + + +/* Don't do the contents of this file more than once. */ + +#ifndef _OBSTACK_H +#define _OBSTACK_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* We use subtraction of (char *) 0 instead of casting to int + because on word-addressable machines a simple cast to int + may ignore the byte-within-word field of the pointer. */ + +#ifndef __PTR_TO_INT +# define __PTR_TO_INT(P) ((P) - (char *) 0) +#endif + +#ifndef __INT_TO_PTR +# define __INT_TO_PTR(P) ((P) + (char *) 0) +#endif + +/* We need the type of the resulting object. If __PTRDIFF_TYPE__ is + defined, as with GNU C, use that; that way we don't pollute the + namespace with 's symbols. Otherwise, if is + available, include it and use ptrdiff_t. In traditional C, long is + the best that we can do. */ + +#ifdef __PTRDIFF_TYPE__ +# define PTR_INT_TYPE __PTRDIFF_TYPE__ +#else +# ifdef HAVE_STDDEF_H +# include +# define PTR_INT_TYPE ptrdiff_t +# else +# define PTR_INT_TYPE long +# endif +#endif + +#if defined _LIBC || defined HAVE_STRING_H +# include +# if defined __STDC__ && __STDC__ +# define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N)) +# else +# define _obstack_memcpy(To, From, N) memcpy ((To), (char *)(From), (N)) +# endif +#else +# ifdef memcpy +# define _obstack_memcpy(To, From, N) memcpy ((To), (char *)(From), (N)) +# else +# define _obstack_memcpy(To, From, N) bcopy ((char *)(From), (To), (N)) +# endif +#endif + +struct _obstack_chunk /* Lives at front of each chunk. */ +{ + char *limit; /* 1 past end of this chunk */ + struct _obstack_chunk *prev; /* address of prior chunk or NULL */ + char contents[4]; /* objects begin here */ +}; + +struct obstack /* control current object in current chunk */ +{ + long chunk_size; /* preferred size to allocate chunks in */ + struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */ + char *object_base; /* address of object we are building */ + char *next_free; /* where to add next char to current object */ + char *chunk_limit; /* address of char after current chunk */ + PTR_INT_TYPE temp; /* Temporary for some macros. */ + int alignment_mask; /* Mask of alignment for each object. */ +#if defined __STDC__ && __STDC__ + /* These prototypes vary based on `use_extra_arg', and we use + casts to the prototypeless function type in all assignments, + but having prototypes here quiets -Wstrict-prototypes. */ + struct _obstack_chunk *(*chunkfun) (void *, long); + void (*freefun) (void *, struct _obstack_chunk *); + void *extra_arg; /* first arg for chunk alloc/dealloc funcs */ +#else + struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */ + void (*freefun) (); /* User's function to free a chunk. */ + char *extra_arg; /* first arg for chunk alloc/dealloc funcs */ +#endif + unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */ + unsigned maybe_empty_object:1;/* There is a possibility that the current + chunk contains a zero-length object. This + prevents freeing the chunk if we allocate + a bigger chunk to replace it. */ + unsigned alloc_failed:1; /* No longer used, as we now call the failed + handler on error, but retained for binary + compatibility. */ +}; + +/* Declare the external functions we use; they are in obstack.c. */ + +#if defined __STDC__ && __STDC__ +extern void _obstack_newchunk (struct obstack *, int); +extern void _obstack_free (struct obstack *, void *); +extern int _obstack_begin (struct obstack *, int, int, + void *(*) (long), void (*) (void *)); +extern int _obstack_begin_1 (struct obstack *, int, int, + void *(*) (void *, long), + void (*) (void *, void *), void *); +extern int _obstack_memory_used (struct obstack *); +#else +extern void _obstack_newchunk (); +extern void _obstack_free (); +extern int _obstack_begin (); +extern int _obstack_begin_1 (); +extern int _obstack_memory_used (); +#endif + +#if defined __STDC__ && __STDC__ + +/* Do the function-declarations after the structs + but before defining the macros. */ + +void obstack_init (struct obstack *obstack); + +void * obstack_alloc (struct obstack *obstack, int size); + +void * obstack_copy (struct obstack *obstack, void *address, int size); +void * obstack_copy0 (struct obstack *obstack, void *address, int size); + +void obstack_free (struct obstack *obstack, void *block); + +void obstack_blank (struct obstack *obstack, int size); + +void obstack_grow (struct obstack *obstack, void *data, int size); +void obstack_grow0 (struct obstack *obstack, void *data, int size); + +void obstack_1grow (struct obstack *obstack, int data_char); +void obstack_ptr_grow (struct obstack *obstack, void *data); +void obstack_int_grow (struct obstack *obstack, int data); + +void * obstack_finish (struct obstack *obstack); + +int obstack_object_size (struct obstack *obstack); + +int obstack_room (struct obstack *obstack); +void obstack_make_room (struct obstack *obstack, int size); +void obstack_1grow_fast (struct obstack *obstack, int data_char); +void obstack_ptr_grow_fast (struct obstack *obstack, void *data); +void obstack_int_grow_fast (struct obstack *obstack, int data); +void obstack_blank_fast (struct obstack *obstack, int size); + +void * obstack_base (struct obstack *obstack); +void * obstack_next_free (struct obstack *obstack); +int obstack_alignment_mask (struct obstack *obstack); +int obstack_chunk_size (struct obstack *obstack); +int obstack_memory_used (struct obstack *obstack); + +#endif /* __STDC__ */ + +/* Non-ANSI C cannot really support alternative functions for these macros, + so we do not declare them. */ + +/* Error handler called when `obstack_chunk_alloc' failed to allocate + more memory. This can be set to a user defined function. The + default action is to print a message and abort. */ +#if defined __STDC__ && __STDC__ +extern void (*obstack_alloc_failed_handler) (void); +#else +extern void (*obstack_alloc_failed_handler) (); +#endif + +/* Exit value used when `print_and_abort' is used. */ +extern int obstack_exit_failure; + +/* Pointer to beginning of object being allocated or to be allocated next. + Note that this might not be the final address of the object + because a new chunk might be needed to hold the final size. */ + +#define obstack_base(h) ((h)->object_base) + +/* Size for allocating ordinary chunks. */ + +#define obstack_chunk_size(h) ((h)->chunk_size) + +/* Pointer to next byte not yet allocated in current chunk. */ + +#define obstack_next_free(h) ((h)->next_free) + +/* Mask specifying low bits that should be clear in address of an object. */ + +#define obstack_alignment_mask(h) ((h)->alignment_mask) + +/* To prevent prototype warnings provide complete argument list in + standard C version. */ +#if defined __STDC__ && __STDC__ + +# define obstack_init(h) \ + _obstack_begin ((h), 0, 0, \ + (void *(*) (long)) obstack_chunk_alloc, (void (*) (void *)) obstack_chunk_free) + +# define obstack_begin(h, size) \ + _obstack_begin ((h), (size), 0, \ + (void *(*) (long)) obstack_chunk_alloc, (void (*) (void *)) obstack_chunk_free) + +# define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ + _obstack_begin ((h), (size), (alignment), \ + (void *(*) (long)) (chunkfun), (void (*) (void *)) (freefun)) + +# define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ + _obstack_begin_1 ((h), (size), (alignment), \ + (void *(*) (void *, long)) (chunkfun), \ + (void (*) (void *, void *)) (freefun), (arg)) + +# define obstack_chunkfun(h, newchunkfun) \ + ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun)) + +# define obstack_freefun(h, newfreefun) \ + ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun)) + +#else + +# define obstack_init(h) \ + _obstack_begin ((h), 0, 0, \ + (void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free) + +# define obstack_begin(h, size) \ + _obstack_begin ((h), (size), 0, \ + (void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free) + +# define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ + _obstack_begin ((h), (size), (alignment), \ + (void *(*) ()) (chunkfun), (void (*) ()) (freefun)) + +# define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ + _obstack_begin_1 ((h), (size), (alignment), \ + (void *(*) ()) (chunkfun), (void (*) ()) (freefun), (arg)) + +# define obstack_chunkfun(h, newchunkfun) \ + ((h) -> chunkfun = (struct _obstack_chunk *(*)()) (newchunkfun)) + +# define obstack_freefun(h, newfreefun) \ + ((h) -> freefun = (void (*)()) (newfreefun)) + +#endif + +#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar) + +#define obstack_blank_fast(h,n) ((h)->next_free += (n)) + +#define obstack_memory_used(h) _obstack_memory_used (h) + +#if defined __GNUC__ && defined __STDC__ && __STDC__ +/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and + does not implement __extension__. But that compiler doesn't define + __GNUC_MINOR__. */ +# if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__) +# define __extension__ +# endif + +/* For GNU C, if not -traditional, + we can define these macros to compute all args only once + without using a global variable. + Also, we can avoid using the `temp' slot, to make faster code. */ + +# define obstack_object_size(OBSTACK) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ + (unsigned) (__o->next_free - __o->object_base); }) + +# define obstack_room(OBSTACK) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ + (unsigned) (__o->chunk_limit - __o->next_free); }) + +# define obstack_make_room(OBSTACK,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->chunk_limit - __o->next_free < __len) \ + _obstack_newchunk (__o, __len); \ + (void) 0; }) + +# define obstack_empty_p(OBSTACK) \ + __extension__ \ + ({ struct obstack *__o = (OBSTACK); \ + (__o->chunk->prev == 0 && __o->next_free - __o->chunk->contents == 0); }) + +# define obstack_grow(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->next_free + __len > __o->chunk_limit) \ + _obstack_newchunk (__o, __len); \ + _obstack_memcpy (__o->next_free, (where), __len); \ + __o->next_free += __len; \ + (void) 0; }) + +# define obstack_grow0(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->next_free + __len + 1 > __o->chunk_limit) \ + _obstack_newchunk (__o, __len + 1); \ + _obstack_memcpy (__o->next_free, (where), __len); \ + __o->next_free += __len; \ + *(__o->next_free)++ = 0; \ + (void) 0; }) + +# define obstack_1grow(OBSTACK,datum) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + if (__o->next_free + 1 > __o->chunk_limit) \ + _obstack_newchunk (__o, 1); \ + *(__o->next_free)++ = (datum); \ + (void) 0; }) + +/* These assume that the obstack alignment is good enough for pointers or ints, + and that the data added so far to the current object + shares that much alignment. */ + +# define obstack_ptr_grow(OBSTACK,datum) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + if (__o->next_free + sizeof (void *) > __o->chunk_limit) \ + _obstack_newchunk (__o, sizeof (void *)); \ + *((void **)__o->next_free)++ = ((void *)datum); \ + (void) 0; }) + +# define obstack_int_grow(OBSTACK,datum) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + if (__o->next_free + sizeof (int) > __o->chunk_limit) \ + _obstack_newchunk (__o, sizeof (int)); \ + *((int *)__o->next_free)++ = ((int)datum); \ + (void) 0; }) + +# define obstack_ptr_grow_fast(h,aptr) (*((void **) (h)->next_free)++ = (void *)aptr) +# define obstack_int_grow_fast(h,aint) (*((int *) (h)->next_free)++ = (int) aint) + +# define obstack_blank(OBSTACK,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->chunk_limit - __o->next_free < __len) \ + _obstack_newchunk (__o, __len); \ + __o->next_free += __len; \ + (void) 0; }) + +# define obstack_alloc(OBSTACK,length) \ +__extension__ \ +({ struct obstack *__h = (OBSTACK); \ + obstack_blank (__h, (length)); \ + obstack_finish (__h); }) + +# define obstack_copy(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__h = (OBSTACK); \ + obstack_grow (__h, (where), (length)); \ + obstack_finish (__h); }) + +# define obstack_copy0(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__h = (OBSTACK); \ + obstack_grow0 (__h, (where), (length)); \ + obstack_finish (__h); }) + +/* The local variable is named __o1 to avoid a name conflict + when obstack_blank is called. */ +# define obstack_finish(OBSTACK) \ +__extension__ \ +({ struct obstack *__o1 = (OBSTACK); \ + void *value; \ + value = (void *) __o1->object_base; \ + if (__o1->next_free == value) \ + __o1->maybe_empty_object = 1; \ + __o1->next_free \ + = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\ + & ~ (__o1->alignment_mask)); \ + if (__o1->next_free - (char *)__o1->chunk \ + > __o1->chunk_limit - (char *)__o1->chunk) \ + __o1->next_free = __o1->chunk_limit; \ + __o1->object_base = __o1->next_free; \ + value; }) + +# define obstack_free(OBSTACK, OBJ) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + void *__obj = (OBJ); \ + if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \ + __o->next_free = __o->object_base = __obj; \ + else (obstack_free) (__o, __obj); }) + +#else /* not __GNUC__ or not __STDC__ */ + +# define obstack_object_size(h) \ + (unsigned) ((h)->next_free - (h)->object_base) + +# define obstack_room(h) \ + (unsigned) ((h)->chunk_limit - (h)->next_free) + +# define obstack_empty_p(h) \ + ((h)->chunk->prev == 0 && (h)->next_free - (h)->chunk->contents == 0) + +/* Note that the call to _obstack_newchunk is enclosed in (..., 0) + so that we can avoid having void expressions + in the arms of the conditional expression. + Casting the third operand to void was tried before, + but some compilers won't accept it. */ + +# define obstack_make_room(h,length) \ +( (h)->temp = (length), \ + (((h)->next_free + (h)->temp > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp), 0) : 0)) + +# define obstack_grow(h,where,length) \ +( (h)->temp = (length), \ + (((h)->next_free + (h)->temp > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ + _obstack_memcpy ((h)->next_free, (where), (h)->temp), \ + (h)->next_free += (h)->temp) + +# define obstack_grow0(h,where,length) \ +( (h)->temp = (length), \ + (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \ + _obstack_memcpy ((h)->next_free, (where), (h)->temp), \ + (h)->next_free += (h)->temp, \ + *((h)->next_free)++ = 0) + +# define obstack_1grow(h,datum) \ +( (((h)->next_free + 1 > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), 1), 0) : 0), \ + (*((h)->next_free)++ = (datum))) + +# define obstack_ptr_grow(h,datum) \ +( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ + (*((char **) (((h)->next_free+=sizeof(char *))-sizeof(char *))) = ((char *) datum))) + +# define obstack_int_grow(h,datum) \ +( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ + (*((int *) (((h)->next_free+=sizeof(int))-sizeof(int))) = ((int) datum))) + +# define obstack_ptr_grow_fast(h,aptr) (*((char **) (h)->next_free)++ = (char *) aptr) +# define obstack_int_grow_fast(h,aint) (*((int *) (h)->next_free)++ = (int) aint) + +# define obstack_blank(h,length) \ +( (h)->temp = (length), \ + (((h)->chunk_limit - (h)->next_free < (h)->temp) \ + ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \ + ((h)->next_free += (h)->temp)) + +# define obstack_alloc(h,length) \ + (obstack_blank ((h), (length)), obstack_finish ((h))) + +# define obstack_copy(h,where,length) \ + (obstack_grow ((h), (where), (length)), obstack_finish ((h))) + +# define obstack_copy0(h,where,length) \ + (obstack_grow0 ((h), (where), (length)), obstack_finish ((h))) + +# define obstack_finish(h) \ +( ((h)->next_free == (h)->object_base \ + ? (((h)->maybe_empty_object = 1), 0) \ + : 0), \ + (h)->temp = __PTR_TO_INT ((h)->object_base), \ + (h)->next_free \ + = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \ + & ~ ((h)->alignment_mask)), \ + (((h)->next_free - (char *) (h)->chunk \ + > (h)->chunk_limit - (char *) (h)->chunk) \ + ? ((h)->next_free = (h)->chunk_limit) : 0), \ + (h)->object_base = (h)->next_free, \ + __INT_TO_PTR ((h)->temp)) + +# if defined __STDC__ && __STDC__ +# define obstack_free(h,obj) \ +( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \ + (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ + ? (int) ((h)->next_free = (h)->object_base \ + = (h)->temp + (char *) (h)->chunk) \ + : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0))) +# else +# define obstack_free(h,obj) \ +( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \ + (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\ + ? (int) ((h)->next_free = (h)->object_base \ + = (h)->temp + (char *) (h)->chunk) \ + : (_obstack_free ((h), (h)->temp + (char *) (h)->chunk), 0))) +# endif + +#endif /* not __GNUC__ or not __STDC__ */ + +#ifdef __cplusplus +} /* C++ */ +#endif + +#endif /* obstack.h */ diff --git a/support/cpp2/libiberty/safe-ctype.c b/support/cpp2/libiberty/safe-ctype.c new file mode 100644 index 00000000..0c2be3ed --- /dev/null +++ b/support/cpp2/libiberty/safe-ctype.c @@ -0,0 +1,163 @@ +/* replacement macros. + + Copyright (C) 2000 Free Software Foundation, Inc. + Contributed by Zack Weinberg . + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* This is a compatible replacement of the standard C library's + with the following properties: + + - Implements all isxxx() macros required by C99. + - Also implements some character classes useful when + parsing C-like languages. + - Does not change behavior depending on the current locale. + - Behaves properly for all values in the range of a signed or + unsigned char. */ + +#include "ansidecl.h" +#include +#include /* for EOF */ + +/* Shorthand */ +#define bl _sch_isblank +#define cn _sch_iscntrl +#define di _sch_isdigit +#define is _sch_isidst +#define lo _sch_islower +#define nv _sch_isnvsp +#define pn _sch_ispunct +#define pr _sch_isprint +#define sp _sch_isspace +#define up _sch_isupper +#define vs _sch_isvsp +#define xd _sch_isxdigit + +/* Masks. */ +#define L lo|is |pr /* lower case letter */ +#define XL lo|is|xd|pr /* lowercase hex digit */ +#define U up|is |pr /* upper case letter */ +#define XU up|is|xd|pr /* uppercase hex digit */ +#define D di |xd|pr /* decimal digit */ +#define P pn |pr /* punctuation */ +#define _ pn|is |pr /* underscore */ + +#define C cn /* control character */ +#define Z nv |cn /* NUL */ +#define M nv|sp |cn /* cursor movement: \f \v */ +#define V vs|sp |cn /* vertical space: \r \n */ +#define T nv|sp|bl|cn /* tab */ +#define S nv|sp|bl|pr /* space */ + +/* Are we ASCII? */ +#if '\n' == 0x0A && ' ' == 0x20 && '0' == 0x30 \ + && 'A' == 0x41 && 'a' == 0x61 && '!' == 0x21 \ + && EOF == -1 + +const unsigned short _sch_istable[256] = +{ + Z, C, C, C, C, C, C, C, /* NUL SOH STX ETX EOT ENQ ACK BEL */ + C, T, V, M, M, V, C, C, /* BS HT LF VT FF CR SO SI */ + C, C, C, C, C, C, C, C, /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */ + C, C, C, C, C, C, C, C, /* CAN EM SUB ESC FS GS RS US */ + S, P, P, P, P, P, P, P, /* SP ! " # $ % & ' */ + P, P, P, P, P, P, P, P, /* ( ) * + , - . / */ + D, D, D, D, D, D, D, D, /* 0 1 2 3 4 5 6 7 */ + D, D, P, P, P, P, P, P, /* 8 9 : ; < = > ? */ + P, XU, XU, XU, XU, XU, XU, U, /* @ A B C D E F G */ + U, U, U, U, U, U, U, U, /* H I J K L M N O */ + U, U, U, U, U, U, U, U, /* P Q R S T U V W */ + U, U, U, P, P, P, P, _, /* X Y Z [ \ ] ^ _ */ + P, XL, XL, XL, XL, XL, XL, L, /* ` a b c d e f g */ + L, L, L, L, L, L, L, L, /* h i j k l m n o */ + L, L, L, L, L, L, L, L, /* p q r s t u v w */ + L, L, L, P, P, P, P, C, /* x y z { | } ~ DEL */ + + /* high half of unsigned char is locale-specific, so all tests are + false in "C" locale */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +const unsigned char _sch_tolower[256] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, + + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + + 91, 92, 93, 94, 95, 96, + + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + + 123,124,125,126,127, + + 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143, + 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159, + 160,161,162,163, 164,165,166,167, 168,169,170,171, 172,173,174,175, + 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,190,191, + + 192,193,194,195, 196,197,198,199, 200,201,202,203, 204,205,206,207, + 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223, + 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239, + 240,241,242,243, 244,245,246,247, 248,249,250,251, 252,253,254,255, +}; + +const unsigned char _sch_toupper[256] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, + + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + + 91, 92, 93, 94, 95, 96, + + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + + 123,124,125,126,127, + + 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143, + 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159, + 160,161,162,163, 164,165,166,167, 168,169,170,171, 172,173,174,175, + 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,190,191, + + 192,193,194,195, 196,197,198,199, 200,201,202,203, 204,205,206,207, + 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223, + 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239, + 240,241,242,243, 244,245,246,247, 248,249,250,251, 252,253,254,255, +}; + +#else + #error "Unsupported host character set" +#endif /* not ASCII */ diff --git a/support/cpp2/libiberty/safe-ctype.h b/support/cpp2/libiberty/safe-ctype.h new file mode 100644 index 00000000..ccacda5b --- /dev/null +++ b/support/cpp2/libiberty/safe-ctype.h @@ -0,0 +1,100 @@ +/* replacement macros. + + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Contributed by Zack Weinberg . + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* This is a compatible replacement of the standard C library's + with the following properties: + + - Implements all isxxx() macros required by C99. + - Also implements some character classes useful when + parsing C-like languages. + - Does not change behavior depending on the current locale. + - Behaves properly for all values in the range of a signed or + unsigned char. + + To avoid conflicts, this header defines the isxxx functions in upper + case, e.g. ISALPHA not isalpha. */ + +#ifndef SAFE_CTYPE_H +#define SAFE_CTYPE_H + +#ifdef isalpha + #error "safe-ctype.h and ctype.h may not be used simultaneously" +#else + +/* Categories. */ + +enum { + /* In C99 */ + _sch_isblank = 0x0001, /* space \t */ + _sch_iscntrl = 0x0002, /* nonprinting characters */ + _sch_isdigit = 0x0004, /* 0-9 */ + _sch_islower = 0x0008, /* a-z */ + _sch_isprint = 0x0010, /* any printing character including ' ' */ + _sch_ispunct = 0x0020, /* all punctuation */ + _sch_isspace = 0x0040, /* space \t \n \r \f \v */ + _sch_isupper = 0x0080, /* A-Z */ + _sch_isxdigit = 0x0100, /* 0-9A-Fa-f */ + + /* Extra categories useful to cpplib. */ + _sch_isidst = 0x0200, /* A-Za-z_ */ + _sch_isvsp = 0x0400, /* \n \r */ + _sch_isnvsp = 0x0800, /* space \t \f \v \0 */ + + /* Combinations of the above. */ + _sch_isalpha = _sch_isupper|_sch_islower, /* A-Za-z */ + _sch_isalnum = _sch_isalpha|_sch_isdigit, /* A-Za-z0-9 */ + _sch_isidnum = _sch_isidst|_sch_isdigit, /* A-Za-z0-9_ */ + _sch_isgraph = _sch_isalnum|_sch_ispunct, /* isprint and not space */ + _sch_iscppsp = _sch_isvsp|_sch_isnvsp /* isspace + \0 */ +}; + +/* Character classification. */ +extern const unsigned short _sch_istable[256]; + +#define _sch_test(c, bit) (_sch_istable[(c) & 0xff] & (unsigned short)(bit)) + +#define ISALPHA(c) _sch_test(c, _sch_isalpha) +#define ISALNUM(c) _sch_test(c, _sch_isalnum) +#define ISBLANK(c) _sch_test(c, _sch_isblank) +#define ISCNTRL(c) _sch_test(c, _sch_iscntrl) +#define ISDIGIT(c) _sch_test(c, _sch_isdigit) +#define ISGRAPH(c) _sch_test(c, _sch_isgraph) +#define ISLOWER(c) _sch_test(c, _sch_islower) +#define ISPRINT(c) _sch_test(c, _sch_isprint) +#define ISPUNCT(c) _sch_test(c, _sch_ispunct) +#define ISSPACE(c) _sch_test(c, _sch_isspace) +#define ISUPPER(c) _sch_test(c, _sch_isupper) +#define ISXDIGIT(c) _sch_test(c, _sch_isxdigit) + +#define ISIDNUM(c) _sch_test(c, _sch_isidnum) +#define ISIDST(c) _sch_test(c, _sch_isidst) +#define IS_VSPACE(c) _sch_test(c, _sch_isvsp) +#define IS_NVSPACE(c) _sch_test(c, _sch_isnvsp) +#define IS_SPACE_OR_NUL(c) _sch_test(c, _sch_iscppsp) + +/* Character transformation. */ +extern const unsigned char _sch_toupper[256]; +extern const unsigned char _sch_tolower[256]; +#define TOUPPER(c) _sch_toupper[(c) & 0xff] +#define TOLOWER(c) _sch_tolower[(c) & 0xff] + +#endif /* no ctype.h */ +#endif /* SAFE_CTYPE_H */ diff --git a/support/cpp2/libiberty/splay-tree.c b/support/cpp2/libiberty/splay-tree.c new file mode 100644 index 00000000..a7123952 --- /dev/null +++ b/support/cpp2/libiberty/splay-tree.c @@ -0,0 +1,513 @@ +/* A splay-tree datatype. + Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Contributed by Mark Mitchell (mark@markmitchell.com). + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC is distributed in the hope that 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 CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* For an easily readable description of splay-trees, see: + + Lewis, Harry R. and Denenberg, Larry. Data Structures and Their + Algorithms. Harper-Collins, Inc. 1991. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#include + +#include "libiberty.h" +#include "splay-tree.h" + +static void splay_tree_delete_helper PARAMS((splay_tree, + splay_tree_node)); +static void splay_tree_splay PARAMS((splay_tree, + splay_tree_key)); +static splay_tree_node splay_tree_splay_helper + PARAMS((splay_tree, + splay_tree_key, + splay_tree_node*, + splay_tree_node*, + splay_tree_node*)); +static int splay_tree_foreach_helper PARAMS((splay_tree, + splay_tree_node, + splay_tree_foreach_fn, + void*)); + +/* Deallocate NODE (a member of SP), and all its sub-trees. */ + +static void +splay_tree_delete_helper (sp, node) + splay_tree sp; + splay_tree_node node; +{ + if (!node) + return; + + splay_tree_delete_helper (sp, node->left); + splay_tree_delete_helper (sp, node->right); + + if (sp->delete_key) + (*sp->delete_key)(node->key); + if (sp->delete_value) + (*sp->delete_value)(node->value); + + free ((char*) node); +} + +/* Help splay SP around KEY. PARENT and GRANDPARENT are the parent + and grandparent, respectively, of NODE. */ + +static splay_tree_node +splay_tree_splay_helper (sp, key, node, parent, grandparent) + splay_tree sp; + splay_tree_key key; + splay_tree_node *node; + splay_tree_node *parent; + splay_tree_node *grandparent; +{ + splay_tree_node *next; + splay_tree_node n; + int comparison; + + n = *node; + + if (!n) + return *parent; + + comparison = (*sp->comp) (key, n->key); + + if (comparison == 0) + /* We've found the target. */ + next = 0; + else if (comparison < 0) + /* The target is to the left. */ + next = &n->left; + else + /* The target is to the right. */ + next = &n->right; + + if (next) + { + /* Continue down the tree. */ + n = splay_tree_splay_helper (sp, key, next, node, parent); + + /* The recursive call will change the place to which NODE + points. */ + if (*node != n) + return n; + } + + if (!parent) + /* NODE is the root. We are done. */ + return n; + + /* First, handle the case where there is no grandparent (i.e., + *PARENT is the root of the tree.) */ + if (!grandparent) + { + if (n == (*parent)->left) + { + *node = n->right; + n->right = *parent; + } + else + { + *node = n->left; + n->left = *parent; + } + *parent = n; + return n; + } + + /* Next handle the cases where both N and *PARENT are left children, + or where both are right children. */ + if (n == (*parent)->left && *parent == (*grandparent)->left) + { + splay_tree_node p = *parent; + + (*grandparent)->left = p->right; + p->right = *grandparent; + p->left = n->right; + n->right = p; + *grandparent = n; + return n; + } + else if (n == (*parent)->right && *parent == (*grandparent)->right) + { + splay_tree_node p = *parent; + + (*grandparent)->right = p->left; + p->left = *grandparent; + p->right = n->left; + n->left = p; + *grandparent = n; + return n; + } + + /* Finally, deal with the case where N is a left child, but *PARENT + is a right child, or vice versa. */ + if (n == (*parent)->left) + { + (*parent)->left = n->right; + n->right = *parent; + (*grandparent)->right = n->left; + n->left = *grandparent; + *grandparent = n; + return n; + } + else + { + (*parent)->right = n->left; + n->left = *parent; + (*grandparent)->left = n->right; + n->right = *grandparent; + *grandparent = n; + return n; + } +} + +/* Splay SP around KEY. */ + +static void +splay_tree_splay (sp, key) + splay_tree sp; + splay_tree_key key; +{ + if (sp->root == 0) + return; + + splay_tree_splay_helper (sp, key, &sp->root, + /*grandparent=*/0, /*parent=*/0); +} + +/* Call FN, passing it the DATA, for every node below NODE, all of + which are from SP, following an in-order traversal. If FN every + returns a non-zero value, the iteration ceases immediately, and the + value is returned. Otherwise, this function returns 0. */ + +static int +splay_tree_foreach_helper (sp, node, fn, data) + splay_tree sp; + splay_tree_node node; + splay_tree_foreach_fn fn; + void* data; +{ + int val; + + if (!node) + return 0; + + val = splay_tree_foreach_helper (sp, node->left, fn, data); + if (val) + return val; + + val = (*fn)(node, data); + if (val) + return val; + + return splay_tree_foreach_helper (sp, node->right, fn, data); +} + +/* Allocate a new splay tree, using COMPARE_FN to compare nodes, + DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate + values. */ + +splay_tree +splay_tree_new (compare_fn, delete_key_fn, delete_value_fn) + splay_tree_compare_fn compare_fn; + splay_tree_delete_key_fn delete_key_fn; + splay_tree_delete_value_fn delete_value_fn; +{ + splay_tree sp = (splay_tree) xmalloc (sizeof (struct splay_tree_s)); + sp->root = 0; + sp->comp = compare_fn; + sp->delete_key = delete_key_fn; + sp->delete_value = delete_value_fn; + + return sp; +} + +/* Deallocate SP. */ + +void +splay_tree_delete (sp) + splay_tree sp; +{ + splay_tree_delete_helper (sp, sp->root); + free ((char*) sp); +} + +/* Insert a new node (associating KEY with DATA) into SP. If a + previous node with the indicated KEY exists, its data is replaced + with the new value. Returns the new node. */ + +splay_tree_node +splay_tree_insert (sp, key, value) + splay_tree sp; + splay_tree_key key; + splay_tree_value value; +{ + int comparison = 0; + + splay_tree_splay (sp, key); + + if (sp->root) + comparison = (*sp->comp)(sp->root->key, key); + + if (sp->root && comparison == 0) + { + /* If the root of the tree already has the indicated KEY, just + replace the value with VALUE. */ + if (sp->delete_value) + (*sp->delete_value)(sp->root->value); + sp->root->value = value; + } + else + { + /* Create a new node, and insert it at the root. */ + splay_tree_node node; + + node = (splay_tree_node) xmalloc (sizeof (struct splay_tree_node_s)); + node->key = key; + node->value = value; + + if (!sp->root) + node->left = node->right = 0; + else if (comparison < 0) + { + node->left = sp->root; + node->right = node->left->right; + node->left->right = 0; + } + else + { + node->right = sp->root; + node->left = node->right->left; + node->right->left = 0; + } + + sp->root = node; + } + + return sp->root; +} + +/* Remove KEY from SP. It is not an error if it did not exist. */ + +void +splay_tree_remove (sp, key) + splay_tree sp; + splay_tree_key key; +{ + splay_tree_splay (sp, key); + + if (sp->root && (*sp->comp) (sp->root->key, key) == 0) + { + splay_tree_node left, right; + + left = sp->root->left; + right = sp->root->right; + + /* Delete the root node itself. */ + if (sp->delete_value) + (*sp->delete_value) (sp->root->value); + free (sp->root); + + /* One of the children is now the root. Doesn't matter much + which, so long as we preserve the properties of the tree. */ + if (left) + { + sp->root = left; + + /* If there was a right child as well, hang it off the + right-most leaf of the left child. */ + if (right) + { + while (left->right) + left = left->right; + left->right = right; + } + } + else + sp->root = right; + } +} + +/* Lookup KEY in SP, returning VALUE if present, and NULL + otherwise. */ + +splay_tree_node +splay_tree_lookup (sp, key) + splay_tree sp; + splay_tree_key key; +{ + splay_tree_splay (sp, key); + + if (sp->root && (*sp->comp)(sp->root->key, key) == 0) + return sp->root; + else + return 0; +} + +/* Return the node in SP with the greatest key. */ + +splay_tree_node +splay_tree_max (sp) + splay_tree sp; +{ + splay_tree_node n = sp->root; + + if (!n) + return NULL; + + while (n->right) + n = n->right; + + return n; +} + +/* Return the node in SP with the smallest key. */ + +splay_tree_node +splay_tree_min (sp) + splay_tree sp; +{ + splay_tree_node n = sp->root; + + if (!n) + return NULL; + + while (n->left) + n = n->left; + + return n; +} + +/* Return the immediate predecessor KEY, or NULL if there is no + predecessor. KEY need not be present in the tree. */ + +splay_tree_node +splay_tree_predecessor (sp, key) + splay_tree sp; + splay_tree_key key; +{ + int comparison; + splay_tree_node node; + + /* If the tree is empty, there is certainly no predecessor. */ + if (!sp->root) + return NULL; + + /* Splay the tree around KEY. That will leave either the KEY + itself, its predecessor, or its successor at the root. */ + splay_tree_splay (sp, key); + comparison = (*sp->comp)(sp->root->key, key); + + /* If the predecessor is at the root, just return it. */ + if (comparison < 0) + return sp->root; + + /* Otherwise, find the leftmost element of the right subtree. */ + node = sp->root->left; + if (node) + while (node->right) + node = node->right; + + return node; +} + +/* Return the immediate successor KEY, or NULL if there is no + predecessor. KEY need not be present in the tree. */ + +splay_tree_node +splay_tree_successor (sp, key) + splay_tree sp; + splay_tree_key key; +{ + int comparison; + splay_tree_node node; + + /* If the tree is empty, there is certainly no predecessor. */ + if (!sp->root) + return NULL; + + /* Splay the tree around KEY. That will leave either the KEY + itself, its predecessor, or its successor at the root. */ + splay_tree_splay (sp, key); + comparison = (*sp->comp)(sp->root->key, key); + + /* If the successor is at the root, just return it. */ + if (comparison > 0) + return sp->root; + + /* Otherwise, find the rightmost element of the left subtree. */ + node = sp->root->right; + if (node) + while (node->left) + node = node->left; + + return node; +} + +/* Call FN, passing it the DATA, for every node in SP, following an + in-order traversal. If FN every returns a non-zero value, the + iteration ceases immediately, and the value is returned. + Otherwise, this function returns 0. */ + +int +splay_tree_foreach (sp, fn, data) + splay_tree sp; + splay_tree_foreach_fn fn; + void *data; +{ + return splay_tree_foreach_helper (sp, sp->root, fn, data); +} + +/* Splay-tree comparison function, treating the keys as ints. */ + +int +splay_tree_compare_ints (k1, k2) + splay_tree_key k1; + splay_tree_key k2; +{ + if ((int) k1 < (int) k2) + return -1; + else if ((int) k1 > (int) k2) + return 1; + else + return 0; +} + +/* Splay-tree comparison function, treating the keys as pointers. */ + +int +splay_tree_compare_pointers (k1, k2) + splay_tree_key k1; + splay_tree_key k2; +{ + if ((char*) k1 < (char*) k2) + return -1; + else if ((char*) k1 > (char*) k2) + return 1; + else + return 0; +} diff --git a/support/cpp2/libiberty/splay-tree.h b/support/cpp2/libiberty/splay-tree.h new file mode 100644 index 00000000..37e9a359 --- /dev/null +++ b/support/cpp2/libiberty/splay-tree.h @@ -0,0 +1,129 @@ +/* A splay-tree datatype. + Copyright 1998, 1999, 2000 Free Software Foundation, Inc. + Contributed by Mark Mitchell (mark@markmitchell.com). + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC is distributed in the hope that 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 CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* For an easily readable description of splay-trees, see: + + Lewis, Harry R. and Denenberg, Larry. Data Structures and Their + Algorithms. Harper-Collins, Inc. 1991. + + The major feature of splay trees is that all basic tree operations + are amortized O(log n) time for a tree with n nodes. */ + +#ifndef _SPLAY_TREE_H +#define _SPLAY_TREE_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + +/* Use typedefs for the key and data types to facilitate changing + these types, if necessary. These types should be sufficiently wide + that any pointer or scalar can be cast to these types, and then + cast back, without loss of precision. */ +typedef unsigned long int splay_tree_key; +typedef unsigned long int splay_tree_value; + +/* Forward declaration for a node in the tree. */ +typedef struct splay_tree_node_s *splay_tree_node; + +/* The type of a function which compares two splay-tree keys. The + function should return values as for qsort. */ +typedef int (*splay_tree_compare_fn) PARAMS((splay_tree_key, splay_tree_key)); + +/* The type of a function used to deallocate any resources associated + with the key. */ +typedef void (*splay_tree_delete_key_fn) PARAMS((splay_tree_key)); + +/* The type of a function used to deallocate any resources associated + with the value. */ +typedef void (*splay_tree_delete_value_fn) PARAMS((splay_tree_value)); + +/* The type of a function used to iterate over the tree. */ +typedef int (*splay_tree_foreach_fn) PARAMS((splay_tree_node, void*)); + +/* The nodes in the splay tree. */ +struct splay_tree_node_s +{ + /* The key. */ + splay_tree_key key; + + /* The value. */ + splay_tree_value value; + + /* The left and right children, respectively. */ + splay_tree_node left; + splay_tree_node right; +}; + +/* The splay tree itself. */ +typedef struct splay_tree_s +{ + /* The root of the tree. */ + splay_tree_node root; + + /* The comparision function. */ + splay_tree_compare_fn comp; + + /* The deallocate-key function. NULL if no cleanup is necessary. */ + splay_tree_delete_key_fn delete_key; + + /* The deallocate-value function. NULL if no cleanup is necessary. */ + splay_tree_delete_value_fn delete_value; +} *splay_tree; + +extern splay_tree splay_tree_new PARAMS((splay_tree_compare_fn, + splay_tree_delete_key_fn, + splay_tree_delete_value_fn)); +extern void splay_tree_delete PARAMS((splay_tree)); +extern splay_tree_node splay_tree_insert + PARAMS((splay_tree, + splay_tree_key, + splay_tree_value)); +extern void splay_tree_remove PARAMS((splay_tree, + splay_tree_key)); +extern splay_tree_node splay_tree_lookup + PARAMS((splay_tree, + splay_tree_key)); +extern splay_tree_node splay_tree_predecessor + PARAMS((splay_tree, + splay_tree_key)); +extern splay_tree_node splay_tree_successor + PARAMS((splay_tree, + splay_tree_key)); +extern splay_tree_node splay_tree_max + PARAMS((splay_tree)); +extern splay_tree_node splay_tree_min + PARAMS((splay_tree)); +extern int splay_tree_foreach PARAMS((splay_tree, + splay_tree_foreach_fn, + void*)); +extern int splay_tree_compare_ints PARAMS((splay_tree_key, + splay_tree_key)); +extern int splay_tree_compare_pointers PARAMS((splay_tree_key, + splay_tree_key)); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _SPLAY_TREE_H */ diff --git a/support/cpp2/mbchar.c b/support/cpp2/mbchar.c new file mode 100644 index 00000000..f5f7beca --- /dev/null +++ b/support/cpp2/mbchar.c @@ -0,0 +1,334 @@ +/* Multibyte Character Functions. + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC is distributed in the hope that 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 CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Note regarding cross compilation: + + In general, translation of multibyte characters to wide characters can + only work in a native compiler since the translation function (mbtowc) + needs to know about both the source and target character encoding. However, + this particular implementation for JIS, SJIS and EUCJP source characters + will work for any compiler with a newlib target. Other targets may also + work provided that their wchar_t implementation is 2 bytes and the encoding + leaves the source character values unchanged (except for removing the + state shifting markers). */ + +#include "config.h" +#ifdef MULTIBYTE_CHARS +#include "system.h" +#include "mbchar.h" +#include + +typedef enum {ESCAPE, DOLLAR, BRACKET, AT, B, J, NUL, JIS_CHAR, OTHER, + JIS_C_NUM} JIS_CHAR_TYPE; + +typedef enum {ASCII, A_ESC, A_ESC_DL, JIS, JIS_1, JIS_2, J_ESC, J_ESC_BR, + J2_ESC, J2_ESC_BR, INV, JIS_S_NUM} JIS_STATE; + +typedef enum {COPYA, COPYJ, COPYJ2, MAKE_A, MAKE_J, NOOP, + EMPTY, ERROR} JIS_ACTION; + +/* State/action tables for processing JIS encoding: + + Where possible, switches to JIS are grouped with proceding JIS characters + and switches to ASCII are grouped with preceding JIS characters. + Thus, maximum returned length is: + 2 (switch to JIS) + 2 (JIS characters) + 2 (switch back to ASCII) = 6. */ + +static JIS_STATE JIS_state_table[JIS_S_NUM][JIS_C_NUM] = { +/* ESCAPE DOLLAR BRACKET AT B J NUL JIS_CHAR OTH*/ +/*ASCII*/ { A_ESC, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,ASCII,ASCII}, +/*A_ESC*/ { ASCII, A_ESC_DL,ASCII, ASCII, ASCII, ASCII, ASCII,ASCII,ASCII}, +/*A_ESC_DL*/{ ASCII, ASCII, ASCII, JIS, JIS, ASCII, ASCII,ASCII,ASCII}, +/*JIS*/ { J_ESC, JIS_1, JIS_1, JIS_1, JIS_1, JIS_1, INV, JIS_1,INV }, +/*JIS_1*/ { INV, JIS_2, JIS_2, JIS_2, JIS_2, JIS_2, INV, JIS_2,INV }, +/*JIS_2*/ { J2_ESC,JIS, JIS, JIS, JIS, JIS, INV, JIS, JIS }, +/*J_ESC*/ { INV, INV, J_ESC_BR, INV, INV, INV, INV, INV, INV }, +/*J_ESC_BR*/{ INV, INV, INV, INV, ASCII, ASCII, INV, INV, INV }, +/*J2_ESC*/ { INV, INV, J2_ESC_BR,INV, INV, INV, INV, INV, INV }, +/*J2_ESC_BR*/{INV, INV, INV, INV, ASCII, ASCII, INV, INV, INV }, +}; + +static JIS_ACTION JIS_action_table[JIS_S_NUM][JIS_C_NUM] = { +/* ESCAPE DOLLAR BRACKET AT B J NUL JIS_CHAR OTH */ +/*ASCII */ {NOOP, COPYA, COPYA, COPYA, COPYA, COPYA, EMPTY, COPYA, COPYA}, +/*A_ESC */ {COPYA, NOOP, COPYA, COPYA, COPYA, COPYA, COPYA, COPYA, COPYA}, +/*A_ESC_DL */{COPYA, COPYA, COPYA, MAKE_J, MAKE_J, COPYA, COPYA, COPYA, COPYA}, +/*JIS */ {NOOP, NOOP, NOOP, NOOP, NOOP, NOOP, ERROR, NOOP, ERROR}, +/*JIS_1 */ {ERROR, NOOP, NOOP, NOOP, NOOP, NOOP, ERROR, NOOP, ERROR}, +/*JIS_2 */ {NOOP, COPYJ2,COPYJ2,COPYJ2, COPYJ2, COPYJ2,ERROR, COPYJ2,COPYJ2}, +/*J_ESC */ {ERROR, ERROR, NOOP, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR}, +/*J_ESC_BR */{ERROR, ERROR, ERROR, ERROR, NOOP, NOOP, ERROR, ERROR, ERROR}, +/*J2_ESC */ {ERROR, ERROR, NOOP, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR}, +/*J2_ESC_BR*/{ERROR, ERROR, ERROR, ERROR, COPYJ, COPYJ, ERROR, ERROR, ERROR}, +}; + + +const char *literal_codeset = NULL; + +/* Store into *PWC (if PWC is not null) the wide character + corresponding to the multibyte character at the start of the + buffer S of size N. Return the number of bytes in the multibyte + character. Return -1 if the bytes do not form a valid character, + or 0 if S is null or points to a null byte. + + This function behaves like the Standard C function mbtowc, except + it treats locale names of the form "C-..." specially. */ + +int +local_mbtowc (pwc, s, n) + wchar_t *pwc; + const char *s; + size_t n; +{ + static JIS_STATE save_state = ASCII; + JIS_STATE curr_state = save_state; + const unsigned char *t = (const unsigned char *) s; + + if (s != NULL && n == 0) + return -1; + + if (literal_codeset == NULL || strlen (literal_codeset) <= 1) + /* This must be the "C" locale or unknown locale -- fall thru */ + ; + else if (! strcmp (literal_codeset, "C-SJIS")) + { + int char1; + if (s == NULL) + /* Not state-dependent. */ + return 0; + + char1 = *t; + if (ISSJIS1 (char1)) + { + int char2 = t[1]; + + if (n <= 1) + return -1; + + if (ISSJIS2 (char2)) + { + if (pwc != NULL) + *pwc = (((wchar_t) *t) << 8) + (wchar_t) (*(t + 1)); + return 2; + } + + return -1; + } + + if (pwc != NULL) + *pwc = (wchar_t) *t; + + if (*t == '\0') + return 0; + + return 1; + } + else if (! strcmp (literal_codeset, "C-EUCJP")) + { + int char1; + + if (s == NULL) + /* Not state-dependent. */ + return 0; + + char1 = *t; + if (ISEUCJP (char1)) + { + int char2 = t[1]; + + if (n <= 1) + return -1; + + if (ISEUCJP (char2)) + { + if (pwc != NULL) + *pwc = (((wchar_t) *t) << 8) + (wchar_t) (*(t + 1)); + return 2; + } + + return -1; + } + + if (pwc != NULL) + *pwc = (wchar_t) *t; + + if (*t == '\0') + return 0; + + return 1; + } + else if (! strcmp (literal_codeset, "C-JIS")) + { + JIS_ACTION action; + JIS_CHAR_TYPE ch; + const unsigned char *ptr; + size_t i, curr_ch; + + if (s == NULL) + { + save_state = ASCII; + /* State-dependent. */ + return 1; + } + + ptr = t; + + for (i = 0; i < n; i++) + { + curr_ch = t[i]; + switch (curr_ch) + { + case JIS_ESC_CHAR: + ch = ESCAPE; + break; + case '$': + ch = DOLLAR; + break; + case '@': + ch = AT; + break; + case '(': + ch = BRACKET; + break; + case 'B': + ch = B; + break; + case 'J': + ch = J; + break; + case '\0': + ch = NUL; + break; + default: + if (ISJIS (curr_ch)) + ch = JIS_CHAR; + else + ch = OTHER; + } + + action = JIS_action_table[curr_state][ch]; + curr_state = JIS_state_table[curr_state][ch]; + + switch (action) + { + case NOOP: + break; + + case EMPTY: + if (pwc != NULL) + *pwc = (wchar_t) 0; + + save_state = curr_state; + return i; + + case COPYA: + if (pwc != NULL) + *pwc = (wchar_t) *ptr; + save_state = curr_state; + return i + 1; + + case COPYJ: + if (pwc != NULL) + *pwc = (((wchar_t) *ptr) << 8) + (wchar_t) (*(ptr + 1)); + + save_state = curr_state; + return i + 1; + + case COPYJ2: + if (pwc != NULL) + *pwc = (((wchar_t) *ptr) << 8) + (wchar_t) (*(ptr + 1)); + + save_state = curr_state; + return ptr - t + 2; + + case MAKE_A: + case MAKE_J: + ptr = (const unsigned char *) (t + i + 1); + break; + + case ERROR: + default: + return -1; + } + } + + /* More than n bytes needed. */ + return -1; + } + +#ifdef CROSS_COMPILE + if (s == NULL) + /* Not state-dependent. */ + return 0; + + if (pwc != NULL) + *pwc = *s; + return 1; +#else + + /* This must be the "C" locale or unknown locale. */ + return mbtowc (pwc, s, n); +#endif +} + +/* Return the number of bytes in the multibyte character at the start + of the buffer S of size N. Return -1 if the bytes do not form a + valid character, or 0 if S is null or points to a null byte. + + This function behaves like the Standard C function mblen, except + it treats locale names of the form "C-..." specially. */ + +int +local_mblen (s, n) + const char *s; + size_t n; +{ + return local_mbtowc (NULL, s, n); +} + +/* Return the maximum mumber of bytes in a multibyte character. + + This function returns the same value as the Standard C macro MB_CUR_MAX, + except it treats locale names of the form "C-..." specially. */ + +int +local_mb_cur_max () +{ + if (literal_codeset == NULL || strlen (literal_codeset) <= 1) + ; + else if (! strcmp (literal_codeset, "C-SJIS")) + return 2; + else if (! strcmp (literal_codeset, "C-EUCJP")) + return 2; + else if (! strcmp (literal_codeset, "C-JIS")) + return 8; /* 3 + 2 + 3 */ + +#ifdef CROSS_COMPILE + return 1; +#else + if (MB_CUR_MAX > 0) + return MB_CUR_MAX; + + return 1; /* default */ +#endif +} +#else /* MULTIBYTE_CHARS */ +extern int dummy; /* silence 'ANSI C forbids an empty source file' warning */ +#endif /* MULTIBYTE_CHARS */ diff --git a/support/cpp2/mbchar.h b/support/cpp2/mbchar.h new file mode 100644 index 00000000..ab58cbbb --- /dev/null +++ b/support/cpp2/mbchar.h @@ -0,0 +1,41 @@ +/* Various declarations for functions found in mbchar.c + Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC is distributed in the hope that 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 CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#ifndef GCC_MBCHAR_H +#define GCC_MBCHAR_H + +#ifdef MULTIBYTE_CHARS + +/* Escape character used for JIS encoding */ +#define JIS_ESC_CHAR 0x1b + +#define ISSJIS1(c) (((c) >= 0x81 && (c) <= 0x9f) || ((c) >= 0xe0 && (c) <= 0xef)) +#define ISSJIS2(c) (((c) >= 0x40 && (c) <= 0x7e) || ((c) >= 0x80 && (c) <= 0xfc)) +#define ISEUCJP(c) ((c) >= 0xa1 && (c) <= 0xfe) +#define ISJIS(c) ((c) >= 0x21 && (c) <= 0x7e) + +extern int local_mbtowc PARAMS ((wchar_t *, const char *, size_t)); +extern int local_mblen PARAMS ((const char *, size_t)); +extern int local_mb_cur_max PARAMS ((void)); + +/* The locale being used for multibyte characters in string/char literals. */ +extern const char *literal_codeset; +#endif /* MULTIBYTE_CHARS */ +#endif /* ! GCC_MBCHAR_H */ diff --git a/support/cpp2/mkdeps.c b/support/cpp2/mkdeps.c new file mode 100644 index 00000000..70c78f5d --- /dev/null +++ b/support/cpp2/mkdeps.c @@ -0,0 +1,291 @@ +/* Dependency generator for Makefile fragments. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Contributed by Zack Weinberg, Mar 2000 + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! */ + +#include "config.h" +#include "system.h" +#include "mkdeps.h" + +/* Keep this structure local to this file, so clients don't find it + easy to start making assumptions. */ +struct deps +{ + const char **targetv; + unsigned int ntargets; /* number of slots actually occupied */ + unsigned int targets_size; /* amt of allocated space - in words */ + + const char **depv; + unsigned int ndeps; + unsigned int deps_size; +}; + +static const char *munge PARAMS ((const char *)); + +/* Given a filename, quote characters in that filename which are + significant to Make. Note that it's not possible to quote all such + characters - e.g. \n, %, *, ?, [, \ (in some contexts), and ~ are + not properly handled. It isn't possible to get this right in any + current version of Make. (??? Still true? Old comment referred to + 3.76.1.) */ + +static const char * +munge (filename) + const char *filename; +{ + int len; + const char *p, *q; + char *dst, *buffer; + + for (p = filename, len = 0; *p; p++, len++) + { + switch (*p) + { + case ' ': + case '\t': + /* GNU make uses a weird quoting scheme for white space. + A space or tab preceded by 2N+1 backslashes represents + N backslashes followed by space; a space or tab + preceded by 2N backslashes represents N backslashes at + the end of a file name; and backslashes in other + contexts should not be doubled. */ + for (q = p - 1; filename <= q && *q == '\\'; q--) + len++; + len++; + break; + + case '$': + /* '$' is quoted by doubling it. */ + len++; + break; + } + } + + /* Now we know how big to make the buffer. */ + buffer = xmalloc (len + 1); + + for (p = filename, dst = buffer; *p; p++, dst++) + { + switch (*p) + { + case ' ': + case '\t': + for (q = p - 1; filename <= q && *q == '\\'; q--) + *dst++ = '\\'; + *dst++ = '\\'; + break; + + case '$': + *dst++ = '$'; + break; + + default: + /* nothing */; + } + *dst = *p; + } + + *dst = '\0'; + return buffer; +} + +/* Public routines. */ + +struct deps * +deps_init () +{ + struct deps *d = (struct deps *) xmalloc (sizeof (struct deps)); + + /* Allocate space for the vectors only if we need it. */ + + d->targetv = 0; + d->depv = 0; + + d->ntargets = 0; + d->targets_size = 0; + d->ndeps = 0; + d->deps_size = 0; + + return d; +} + +void +deps_free (d) + struct deps *d; +{ + unsigned int i; + + if (d->targetv) + { + for (i = 0; i < d->ntargets; i++) + free ((PTR) d->targetv[i]); + free (d->targetv); + } + + if (d->depv) + { + for (i = 0; i < d->ndeps; i++) + free ((PTR) d->depv[i]); + free (d->depv); + } + + free (d); +} + +/* Adds a target T. We make a copy, so it need not be a permanent + string. QUOTE is true if the string should be quoted. */ +void +deps_add_target (d, t, quote) + struct deps *d; + const char *t; + int quote; +{ + if (d->ntargets == d->targets_size) + { + d->targets_size = d->targets_size * 2 + 4; + d->targetv = (const char **) xrealloc (d->targetv, + d->targets_size * sizeof (const char *)); + } + + if (quote) + t = munge (t); /* Also makes permanent copy. */ + else + t = xstrdup (t); + + d->targetv[d->ntargets++] = t; +} + +/* Sets the default target if none has been given already. An empty + string as the default target in interpreted as stdin. The string + is quoted for MAKE. */ +void +deps_add_default_target (d, tgt) + struct deps *d; + const char *tgt; +{ + /* Only if we have no targets. */ + if (d->ntargets) + return; + + if (tgt[0] == '\0') + deps_add_target (d, "-", 1); + else + { +#ifndef TARGET_OBJECT_SUFFIX +# define TARGET_OBJECT_SUFFIX ".o" +#endif + char *start = lbasename (tgt); + char *o = (char *) alloca (strlen (start) + strlen (TARGET_OBJECT_SUFFIX) + 1); + char *suffix; + + strcpy (o, start); + + suffix = strrchr (o, '.'); + if (!suffix) + suffix = o + strlen (o); + strcpy (suffix, TARGET_OBJECT_SUFFIX); + + deps_add_target (d, o, 1); + } +} + +void +deps_add_dep (d, t) + struct deps *d; + const char *t; +{ + t = munge (t); /* Also makes permanent copy. */ + + if (d->ndeps == d->deps_size) + { + d->deps_size = d->deps_size * 2 + 8; + d->depv = (const char **) + xrealloc (d->depv, d->deps_size * sizeof (const char *)); + } + d->depv[d->ndeps++] = t; +} + +void +deps_write (d, fp, colmax) + const struct deps *d; + FILE *fp; + unsigned int colmax; +{ + unsigned int size, i, column; + + column = 0; + if (colmax && colmax < 34) + colmax = 34; + + for (i = 0; i < d->ntargets; i++) + { + size = strlen (d->targetv[i]); + column += size; + if (colmax && column > colmax) + { + fputs (" \\\n ", fp); + column = 1 + size; + } + if (i) + { + putc (' ', fp); + column++; + } + fputs (d->targetv[i], fp); + } + + putc (':', fp); + putc (' ', fp); + column += 2; + + for (i = 0; i < d->ndeps; i++) + { + size = strlen (d->depv[i]); + column += size; + if (colmax && column > colmax) + { + fputs (" \\\n ", fp); + column = 1 + size; + } + if (i) + { + putc (' ', fp); + column++; + } + fputs (d->depv[i], fp); + } + putc ('\n', fp); +} + +void +deps_phony_targets (d, fp) + const struct deps *d; + FILE *fp; +{ + unsigned int i; + + for (i = 1; i < d->ndeps; i++) + { + putc ('\n', fp); + fputs (d->depv[i], fp); + putc (':', fp); + putc ('\n', fp); + } +} diff --git a/support/cpp2/mkdeps.h b/support/cpp2/mkdeps.h new file mode 100644 index 00000000..fa79b865 --- /dev/null +++ b/support/cpp2/mkdeps.h @@ -0,0 +1,62 @@ +/* Dependency generator for Makefile fragments. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Contributed by Zack Weinberg, Mar 2000 + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! */ + +#ifndef GCC_MKDEPS_H +#define GCC_MKDEPS_H + +/* This is the data structure used by all the functions in mkdeps.c. + It's quite straightforward, but should be treated as opaque. */ + +struct deps; + +/* Create a deps buffer. */ +extern struct deps *deps_init PARAMS ((void)); + +/* Destroy a deps buffer. */ +extern void deps_free PARAMS ((struct deps *)); + +/* Add a target (appears on left side of the colon) to the deps list. Takes + a boolean indicating whether to quote the target for MAKE. */ +extern void deps_add_target PARAMS ((struct deps *, const char *, int)); + +/* Sets the default target if none has been given already. An empty + string as the default target in interpreted as stdin. */ +extern void deps_add_default_target PARAMS ((struct deps *, const char *)); + +/* Add a dependency (appears on the right side of the colon) to the + deps list. Dependencies will be printed in the order that they + were entered with this function. By convention, the first + dependency entered should be the primary source file. */ +extern void deps_add_dep PARAMS ((struct deps *, const char *)); + +/* Write out a deps buffer to a specified file. The third argument + is the number of columns to word-wrap at (0 means don't wrap). */ +extern void deps_write PARAMS ((const struct deps *, FILE *, + unsigned int)); + +/* For each dependency *except the first*, emit a dummy rule for that + file, causing it to depend on nothing. This is used to work around + the intermediate-file deletion misfeature in Make, in some + automatic dependency schemes. */ +extern void deps_phony_targets PARAMS ((const struct deps *, FILE *)); + +#endif /* ! GCC_MKDEPS_H */ diff --git a/support/cpp2/options.h b/support/cpp2/options.h new file mode 100644 index 00000000..e69de29b diff --git a/support/cpp2/output.h b/support/cpp2/output.h new file mode 100644 index 00000000..c8fa63c3 --- /dev/null +++ b/support/cpp2/output.h @@ -0,0 +1,450 @@ +/* Declarations for insn-output.c. These functions are defined in recog.c, + final.c, and varasm.c. + Copyright (C) 1987, 1991, 1994, 1997, 1998, + 1999, 2000 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC is distributed in the hope that 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 CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Initialize data in final at the beginning of a compilation. */ +extern void init_final PARAMS ((const char *)); + +/* Called at end of source file, + to output the block-profiling table for this entire compilation. */ +extern void end_final PARAMS ((const char *)); + +/* Enable APP processing of subsequent output. + Used before the output from an `asm' statement. */ +extern void app_enable PARAMS ((void)); + +/* Disable APP processing of subsequent output. + Called from varasm.c before most kinds of output. */ +extern void app_disable PARAMS ((void)); + +/* Return the number of slots filled in the current + delayed branch sequence (we don't count the insn needing the + delay slot). Zero if not in a delayed branch sequence. */ +extern int dbr_sequence_length PARAMS ((void)); + +/* Indicate that branch shortening hasn't yet been done. */ +extern void init_insn_lengths PARAMS ((void)); + +#ifdef RTX_CODE +/* Obtain the current length of an insn. If branch shortening has been done, + get its actual length. Otherwise, get its maximum length. */ +extern int get_attr_length PARAMS ((rtx)); + +/* Make a pass over all insns and compute their actual lengths by shortening + any branches of variable length if possible. */ +extern void shorten_branches PARAMS ((rtx)); + +/* Output assembler code for the start of a function, + and initialize some of the variables in this file + for the new function. The label for the function and associated + assembler pseudo-ops have already been output in + `assemble_start_function'. */ +extern void final_start_function PARAMS ((rtx, FILE *, int)); + +/* Output assembler code for the end of a function. + For clarity, args are same as those of `final_start_function' + even though not all of them are needed. */ +extern void final_end_function PARAMS ((rtx, FILE *, int)); + +/* Output assembler code for some insns: all or part of a function. */ +extern void final PARAMS ((rtx, FILE *, int, int)); + +/* The final scan for one insn, INSN. Args are same as in `final', except + that INSN is the insn being scanned. Value returned is the next insn to + be scanned. */ +extern rtx final_scan_insn PARAMS ((rtx, FILE *, int, int, int)); + +/* Replace a SUBREG with a REG or a MEM, based on the thing it is a + subreg of. */ +extern rtx alter_subreg PARAMS ((rtx)); + +/* Report inconsistency between the assembler template and the operands. + In an `asm', it's the user's fault; otherwise, the compiler's fault. */ +extern void output_operand_lossage PARAMS ((const char *)); + +/* Output a string of assembler code, substituting insn operands. + Defined in final.c. */ +extern void output_asm_insn PARAMS ((const char *, rtx *)); + +/* Compute a worst-case reference address of a branch so that it + can be safely used in the presence of aligned labels. + Defined in final.c. */ +extern int insn_current_reference_address PARAMS ((rtx)); + +/* Find the alignment associated with a CODE_LABEL. + Defined in final.c. */ +extern int label_to_alignment PARAMS ((rtx)); + +/* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */ +extern void output_asm_label PARAMS ((rtx)); + +/* Print a memory reference operand for address X + using machine-dependent assembler syntax. */ +extern void output_address PARAMS ((rtx)); + +/* Print an integer constant expression in assembler syntax. + Addition and subtraction are the only arithmetic + that may appear in these expressions. */ +extern void output_addr_const PARAMS ((FILE *, rtx)); + +/* Output a string of assembler code, substituting numbers, strings + and fixed syntactic prefixes. */ +extern void asm_fprintf PARAMS ((FILE *file, const char *p, ...)); + +/* Split up a CONST_DOUBLE or integer constant rtx into two rtx's for single + words. */ +extern void split_double PARAMS ((rtx, rtx *, rtx *)); + +/* Return nonzero if this function has no function calls. */ +extern int leaf_function_p PARAMS ((void)); + +/* Return 1 if this function uses only the registers that can be + safely renumbered. */ +extern int only_leaf_regs_used PARAMS ((void)); + +/* Scan IN_RTX and its subexpressions, and renumber all regs into those + available in leaf functions. */ +extern void leaf_renumber_regs_insn PARAMS ((rtx)); + +/* Locate the proper template for the given insn-code. */ +extern const char *get_insn_template PARAMS ((int, rtx)); + +/* Functions in flow.c */ +extern void allocate_for_life_analysis PARAMS ((void)); +extern int regno_uninitialized PARAMS ((int)); +extern int regno_clobbered_at_setjmp PARAMS ((int)); +extern void find_basic_blocks PARAMS ((rtx, int, FILE *)); +extern void cleanup_cfg PARAMS ((void)); +extern void check_function_return_warnings PARAMS ((void)); +#endif + +/* Functions in varasm.c. */ + +/* Tell assembler to switch to text section. */ +extern void text_section PARAMS ((void)); + +/* Tell assembler to switch to data section. */ +extern void data_section PARAMS ((void)); + +/* Tell assembler to make sure its in the data section. */ +extern void force_data_section PARAMS ((void)); + +/* Tell assembler to switch to read-only data section. This is normally + the text section. */ +extern void readonly_data_section PARAMS ((void)); + +/* Determine if we're in the text section. */ +extern int in_text_section PARAMS ((void)); + +#ifdef EH_FRAME_SECTION_ASM_OP +extern void eh_frame_section PARAMS ((void)); +#endif + +#ifdef CTORS_SECTION_ASM_OP +extern void ctors_section PARAMS ((void)); +#endif + +#ifdef DTORS_SECTION_ASM_OP +extern void dtors_section PARAMS ((void)); +#endif + +#ifdef BSS_SECTION_ASM_OP +extern void bss_section PARAMS ((void)); +#endif + +#ifdef CONST_SECTION_ASM_OP +extern void const_section PARAMS ((void)); +#endif + +#ifdef INIT_SECTION_ASM_OP +extern void init_section PARAMS ((void)); +#endif + +#ifdef FINI_SECTION_ASM_OP +extern void fini_section PARAMS ((void)); +#endif + +#ifdef TDESC_SECTION_ASM_OP +extern void tdesc_section PARAMS ((void)); +#endif + +#ifdef TREE_CODE +/* Tell assembler to change to section NAME for DECL. + If DECL is NULL, just switch to section NAME. + If NAME is NULL, get the name from DECL. + If RELOC is 1, the initializer for DECL contains relocs. */ +extern void named_section PARAMS ((tree, const char *, int)); + +/* Tell assembler to switch to the section for function DECL. */ +extern void function_section PARAMS ((tree)); + +/* Tell assembler to switch to the section for the exception table. */ +extern void exception_section PARAMS ((void)); + +/* Declare DECL to be a weak symbol. */ +extern void declare_weak PARAMS ((tree)); +#endif /* TREE_CODE */ + +/* Emit any pending weak declarations. */ +extern void weak_finish PARAMS ((void)); + +/* Decode an `asm' spec for a declaration as a register name. + Return the register number, or -1 if nothing specified, + or -2 if the ASMSPEC is not `cc' or `memory' and is not recognized, + or -3 if ASMSPEC is `cc' and is not recognized, + or -4 if ASMSPEC is `memory' and is not recognized. + Accept an exact spelling or a decimal number. + Prefixes such as % are optional. */ +extern int decode_reg_name PARAMS ((const char *)); + +#ifdef TREE_CODE +/* Make the rtl for variable VAR be volatile. + Use this only for static variables. */ +extern void make_var_volatile PARAMS ((tree)); + +/* Output alignment directive to align for constant expression EXP. */ +extern void assemble_constant_align PARAMS ((tree)); + +extern void assemble_alias PARAMS ((tree, tree)); + +/* Output a string of literal assembler code + for an `asm' keyword used between functions. */ +extern void assemble_asm PARAMS ((tree)); + +/* Output assembler code for the constant pool of a function and associated + with defining the name of the function. DECL describes the function. + NAME is the function's name. For the constant pool, we use the current + constant pool data. */ +extern void assemble_start_function PARAMS ((tree, const char *)); + +/* Output assembler code associated with defining the size of the + function. DECL describes the function. NAME is the function's name. */ +extern void assemble_end_function PARAMS ((tree, const char *)); + +/* Assemble everything that is needed for a variable or function declaration. + Not used for automatic variables, and not used for function definitions. + Should not be called for variables of incomplete structure type. + + TOP_LEVEL is nonzero if this variable has file scope. + AT_END is nonzero if this is the special handling, at end of compilation, + to define things that have had only tentative definitions. + DONT_OUTPUT_DATA if nonzero means don't actually output the + initial value (that will be done by the caller). */ +extern void assemble_variable PARAMS ((tree, int, int, int)); + +/* Output something to declare an external symbol to the assembler. + (Most assemblers don't need this, so we normally output nothing.) + Do nothing if DECL is not external. */ +extern void assemble_external PARAMS ((tree)); +#endif /* TREE_CODE */ + +/* Record an element in the table of global destructors. + How this is done depends on what sort of assembler and linker + are in use. + + NAME should be the name of a global function to be called + at exit time. This name is output using assemble_name. */ +extern void assemble_destructor PARAMS ((const char *)); + +/* Likewise for global constructors. */ +extern void assemble_constructor PARAMS ((const char *)); + +/* Likewise for entries we want to record for garbage collection. + Garbage collection is still under development. */ +extern void assemble_gc_entry PARAMS ((const char *)); + +/* Assemble code to leave SIZE bytes of zeros. */ +extern void assemble_zeros PARAMS ((int)); + +/* Assemble an alignment pseudo op for an ALIGN-bit boundary. */ +extern void assemble_align PARAMS ((int)); +extern void assemble_eh_align PARAMS ((int)); + +/* Assemble a string constant with the specified C string as contents. */ +extern void assemble_string PARAMS ((const char *, int)); + +#ifdef RTX_CODE +/* Similar, for calling a library function FUN. */ +extern void assemble_external_libcall PARAMS ((rtx)); +#endif + +/* Declare the label NAME global. */ +extern void assemble_global PARAMS ((const char *)); + +/* Assemble a label named NAME. */ +extern void assemble_label PARAMS ((const char *)); +extern void assemble_eh_label PARAMS ((const char *)); + +/* Output to FILE a reference to the assembler name of a C-level name NAME. + If NAME starts with a *, the rest of NAME is output verbatim. + Otherwise NAME is transformed in an implementation-defined way + (usually by the addition of an underscore). + Many macros in the tm file are defined to call this function. */ +extern void assemble_name PARAMS ((FILE *, const char *)); + +#ifdef RTX_CODE +/* Assemble the integer constant X into an object of SIZE bytes. + X must be either a CONST_INT or CONST_DOUBLE. + + Return 1 if we were able to output the constant, otherwise 0. If FORCE is + non-zero, abort if we can't output the constant. */ +extern int assemble_integer PARAMS ((rtx, int, int)); +extern int assemble_eh_integer PARAMS ((rtx, int, int)); + +#ifdef REAL_VALUE_TYPE +/* Assemble the floating-point constant D into an object of size MODE. */ +extern void assemble_real PARAMS ((REAL_VALUE_TYPE, + enum machine_mode)); +#endif +#endif + +/* At the end of a function, forget the memory-constants + previously made for CONST_DOUBLEs. Mark them as not on real_constant_chain. + Also clear out real_constant_chain and clear out all the chain-pointers. */ +extern void clear_const_double_mem PARAMS ((void)); + +/* Start deferring output of subconstants. */ +extern void defer_addressed_constants PARAMS ((void)); + +/* Stop deferring output of subconstants, + and output now all those that have been deferred. */ +extern void output_deferred_addressed_constants PARAMS ((void)); + +/* Return the size of the constant pool. */ +extern int get_pool_size PARAMS ((void)); + +#ifdef HAVE_peephole +extern rtx peephole PARAMS ((rtx)); +#endif + +#ifdef TREE_CODE +/* Write all the constants in the constant pool. */ +extern void output_constant_pool PARAMS ((const char *, tree)); + +/* Return nonzero if VALUE is a valid constant-valued expression + for use in initializing a static variable; one that can be an + element of a "constant" initializer. + + Return null_pointer_node if the value is absolute; + if it is relocatable, return the variable that determines the relocation. + We assume that VALUE has been folded as much as possible; + therefore, we do not need to check for such things as + arithmetic-combinations of integers. */ +extern tree initializer_constant_valid_p PARAMS ((tree, tree)); + +/* Output assembler code for constant EXP to FILE, with no label. + This includes the pseudo-op such as ".int" or ".byte", and a newline. + Assumes output_addressed_constants has been done on EXP already. + + Generate exactly SIZE bytes of assembler data, padding at the end + with zeros if necessary. SIZE must always be specified. */ +extern void output_constant PARAMS ((tree, int)); +#endif + +#ifdef RTX_CODE +/* When outputting delayed branch sequences, this rtx holds the + sequence being output. It is null when no delayed branch + sequence is being output, so it can be used as a test in the + insn output code. + + This variable is defined in final.c. */ +extern rtx final_sequence; +#endif + +/* The line number of the beginning of the current function. + sdbout.c needs this so that it can output relative linenumbers. */ + +#ifdef SDB_DEBUGGING_INFO /* Avoid undef sym in certain broken linkers. */ +extern int sdb_begin_function_line; +#endif + +/* File in which assembler code is being written. */ + +#ifdef BUFSIZ +extern FILE *asm_out_file; +#endif + +/* The first global object in the file. */ +extern const char *first_global_object_name; + +/* The first weak object in the file. */ +extern const char *weak_global_object_name; + +/* Nonzero if function being compiled doesn't contain any calls + (ignoring the prologue and epilogue). This is set prior to + local register allocation and is valid for the remaining + compiler passes. */ + +extern int current_function_is_leaf; + +/* Nonzero if function being compiled doesn't contain any instructions + that can throw an exception. This is set prior to final. */ + +extern int current_function_nothrow; + +/* Nonzero if function being compiled doesn't modify the stack pointer + (ignoring the prologue and epilogue). This is only valid after + life_analysis has run. */ + +extern int current_function_sp_is_unchanging; + +/* Nonzero if the function being compiled is a leaf function which only + uses leaf registers. This is valid after reload (specifically after + sched2) and is useful only if the port defines LEAF_REGISTERS. */ + +extern int current_function_uses_only_leaf_regs; + +/* Default file in which to dump debug output. */ + +#ifdef BUFSIZ +extern FILE *rtl_dump_file; +#endif + +/* Nonnull if the insn currently being emitted was a COND_EXEC pattern. */ +extern struct rtx_def *current_insn_predicate; + +/* Last insn processed by final_scan_insn. */ +extern struct rtx_def *current_output_insn; + +/* Decide whether DECL needs to be in a writable section. RELOC is the same + as for SELECT_SECTION. */ + +#define DECL_READONLY_SECTION(DECL,RELOC) \ + (TREE_READONLY (DECL) \ + && ! TREE_THIS_VOLATILE (DECL) \ + && DECL_INITIAL (DECL) \ + && (DECL_INITIAL (DECL) == error_mark_node \ + || TREE_CONSTANT (DECL_INITIAL (DECL))) \ + && ! (RELOC && (flag_pic || DECL_ONE_ONLY (DECL)))) + +/* User label prefix in effect for this compilation. */ +extern const char *user_label_prefix; + +/* This macro gets just the user-specified name + out of the string in a SYMBOL_REF. On most machines, + we discard the * if any and that's all. */ +#ifndef STRIP_NAME_ENCODING +#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \ + (VAR) = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*')) +#endif +/* Assign unique numbers to labels generated for profiling. */ + +extern int profile_label_no; diff --git a/support/cpp2/prefix.c b/support/cpp2/prefix.c new file mode 100644 index 00000000..bf421ba1 --- /dev/null +++ b/support/cpp2/prefix.c @@ -0,0 +1,338 @@ +/* Utility to update paths from internal to external forms. + Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with GCC; see the file COPYING. If not, write to the Free +Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* This file contains routines to update a path, both to canonicalize + the directory format and to handle any prefix translation. + + This file must be compiled with -DPREFIX= to specify the "prefix" + value used by configure. If a filename does not begin with this + prefix, it will not be affected other than by directory canonicalization. + + Each caller of 'update_path' may specify both a filename and + a translation prefix and consist of the name of the package that contains + the file ("@GCC", "@BINUTIL", "@GNU", etc). + + If the prefix is not specified, the filename will only undergo + directory canonicalization. + + If it is specified, the string given by PREFIX will be replaced + by the specified prefix (with a '@' in front unless the prefix begins + with a '$') and further translation will be done as follows + until none of the two conditions below are met: + + 1) If the filename begins with '@', the string between the '@' and + the end of the name or the first '/' or directory separator will + be considered a "key" and looked up as follows: + + -- If this is a Win32 OS, then the Registry will be examined for + an entry of "key" in + + HKEY_LOCAL_MACHINE\SOFTWARE\Free Software Foundation\ + + if found, that value will be used. defaults to GCC version + string, but can be overridden at configuration time. + + -- If not found (or not a Win32 OS), the environment variable + key_ROOT (the value of "key" concatenated with the constant "_ROOT") + is tried. If that fails, then PREFIX (see above) is used. + + 2) If the filename begins with a '$', the rest of the string up + to the end or the first '/' or directory separator will be used + as an environment variable, whose value will be returned. + + Once all this is done, any '/' will be converted to DIR_SEPARATOR, + if they are different. + + NOTE: using resolve_keyed_path under Win32 requires linking with + advapi32.dll. */ + + +#include "config.h" +#include "system.h" +#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY) +#include +#endif +#include "prefix.h" + +static const char *std_prefix = PREFIX; + +static const char *get_key_value PARAMS ((char *)); +static const char *translate_name PARAMS ((const char *)); +static char *save_string PARAMS ((const char *, int)); +char *concat VPARAMS ((const char *first, ...)); + +#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY) +static char *lookup_key PARAMS ((char *)); +static HKEY reg_key = (HKEY) INVALID_HANDLE_VALUE; +#endif + +/* Given KEY, as above, return its value. */ + +static const char * +get_key_value (key) + char *key; +{ + const char *prefix = 0; + char *temp = 0; + +#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY) + prefix = lookup_key (key); +#endif + + if (prefix == 0) + prefix = getenv (temp = concat (key, "_ROOT", NULL)); + + if (prefix == 0) + prefix = std_prefix; + + if (temp) + free (temp); + + return prefix; +} + +/* Concatenate a sequence of strings, returning the result. + + This function is based on the one in libiberty. */ + +char * +concat VPARAMS ((const char *first, ...)) +{ + register int length; + register char *newstr; + register char *end; + register const char *arg; + va_list args; +#ifndef ANSI_PROTOTYPES + const char *first; +#endif + + /* First compute the size of the result and get sufficient memory. */ + + VA_START (args, first); +#ifndef ANSI_PROTOTYPES + first = va_arg (args, const char *); +#endif + + arg = first; + length = 0; + + while (arg != 0) + { + length += strlen (arg); + arg = va_arg (args, const char *); + } + + newstr = (char *) xmalloc (length + 1); + va_end (args); + + /* Now copy the individual pieces to the result string. */ + + VA_START (args, first); +#ifndef ANSI_PROTOTYPES + first = va_arg (args, char *); +#endif + + end = newstr; + arg = first; + while (arg != 0) + { + while (*arg) + *end++ = *arg++; + arg = va_arg (args, const char *); + } + *end = '\000'; + va_end (args); + + return (newstr); +} + +/* Return a copy of a string that has been placed in the heap. */ + +static char * +save_string (s, len) + const char *s; + int len; +{ + register char *result = xmalloc (len + 1); + + memcpy (result, s, len); + result[len] = 0; + return result; +} + +#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY) + +/* Look up "key" in the registry, as above. */ + +static char * +lookup_key (key) + char *key; +{ + char *dst; + DWORD size; + DWORD type; + LONG res; + + if (reg_key == (HKEY) INVALID_HANDLE_VALUE) + { + res = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE", 0, + KEY_READ, ®_key); + + if (res == ERROR_SUCCESS) + res = RegOpenKeyExA (reg_key, "Free Software Foundation", 0, + KEY_READ, ®_key); + + if (res == ERROR_SUCCESS) + res = RegOpenKeyExA (reg_key, WIN32_REGISTRY_KEY, 0, + KEY_READ, ®_key); + + if (res != ERROR_SUCCESS) + { + reg_key = (HKEY) INVALID_HANDLE_VALUE; + return 0; + } + } + + size = 32; + dst = (char *) xmalloc (size); + + res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size); + if (res == ERROR_MORE_DATA && type == REG_SZ) + { + dst = (char *) xrealloc (dst, size); + res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size); + } + + if (type != REG_SZ || res != ERROR_SUCCESS) + { + free (dst); + dst = 0; + } + + return dst; +} +#endif + +/* If NAME starts with a '@' or '$', apply the translation rules above + and return a new name. Otherwise, return the given name. */ + +static const char * +translate_name (name) + const char *name; +{ + char code = name[0]; + char *key; + const char *prefix = 0; + int keylen; + + if (code != '@' && code != '$') + return name; + + for (keylen = 0; + (name[keylen + 1] != 0 && !IS_DIR_SEPARATOR (name[keylen + 1])); + keylen++) + ; + + key = (char *) alloca (keylen + 1); + strncpy (key, &name[1], keylen); + key[keylen] = 0; + + name = &name[keylen + 1]; + + if (code == '@') + { + prefix = get_key_value (key); + if (prefix == 0) + prefix = std_prefix; + } + else + prefix = getenv (key); + + if (prefix == 0) + prefix = PREFIX; + + /* We used to strip trailing DIR_SEPARATORs here, but that can + sometimes yield a result with no separator when one was coded + and intended by the user, causing two path components to run + together. */ + + return concat (prefix, name, NULL); +} + +/* Update PATH using KEY if PATH starts with PREFIX. */ + +const char * +update_path (path, key) + const char *path; + const char *key; +{ + if (! strncmp (path, std_prefix, strlen (std_prefix)) && key != 0) + { + if (key[0] != '$') + key = concat ("@", key, NULL); + + path = concat (key, &path[strlen (std_prefix)], NULL); + + while (path[0] == '@' || path[0] == '$') + path = translate_name (path); + } + +#ifdef UPDATE_PATH_HOST_CANONICALIZE +/* Perform host dependant canonicalization when needed. */ +UPDATE_PATH_HOST_CANONICALIZE (path, key); +#endif + +#ifdef DIR_SEPARATOR_2 + /* Convert DIR_SEPARATOR_2 to DIR_SEPARATOR. */ + if (DIR_SEPARATOR != DIR_SEPARATOR_2) + { + char *new_path = xstrdup (path); + path = new_path; + do { + if (*new_path == DIR_SEPARATOR_2) + *new_path = DIR_SEPARATOR; + } while (*new_path++); + } +#endif + +#if defined (DIR_SEPARATOR) && !defined (DIR_SEPARATOR_2) + if (DIR_SEPARATOR != '/') + { + char *new_path = xstrdup (path); + path = new_path; + do { + if (*new_path == '/') + *new_path = DIR_SEPARATOR; + } while (*new_path++); + } +#endif + + return path; +} + +/* Reset the standard prefix */ +void +set_std_prefix (prefix, len) + const char *prefix; + int len; +{ + std_prefix = save_string (prefix, len); +} diff --git a/support/cpp2/prefix.h b/support/cpp2/prefix.h new file mode 100644 index 00000000..03c0d191 --- /dev/null +++ b/support/cpp2/prefix.h @@ -0,0 +1,28 @@ +/* Provide prototypes for functions exported from prefix.c. + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with GCC; see the file COPYING. If not, write to the Free +Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + + +#ifndef GCC_PREFIX_H +#define GCC_PREFIX_H + +extern const char *update_path PARAMS ((const char *, const char *)); +extern void set_std_prefix PARAMS ((const char *, int)); + +#endif /* ! GCC_PREFIX_H */ diff --git a/support/cpp2/sdcc.h b/support/cpp2/sdcc.h new file mode 100644 index 00000000..dd680dcb --- /dev/null +++ b/support/cpp2/sdcc.h @@ -0,0 +1,23 @@ +/* Various stuff needed to hack the build for SDCC. */ +#define xmalloc(s) malloc(s) +#define xstrdup(s) strdup(s) +#define xrealloc(p,s) realloc(p,s) +#define xcalloc(n,e) calloc(n,e) +#define xmalloc_set_program_name(n) /* nada */ +#define xstrerror(e) strerror(e) + +extern char *lbasename(const char *path); + +/* Define results of standard character escape sequences. */ +#define TARGET_BELL 007 +#define TARGET_BS 010 +#define TARGET_TAB 011 +#define TARGET_NEWLINE 012 +#define TARGET_VT 013 +#define TARGET_FF 014 +#define TARGET_CR 015 + +#define CHAR_TYPE_SIZE 8 +#define WCHAR_TYPE_SIZE 32 /* ? maybe ? */ + +#define SUPPORTS_ONE_ONLY 0 diff --git a/support/cpp2/specs.h b/support/cpp2/specs.h new file mode 100644 index 00000000..e69de29b diff --git a/support/cpp2/splay-tree.c b/support/cpp2/splay-tree.c new file mode 100644 index 00000000..a7123952 --- /dev/null +++ b/support/cpp2/splay-tree.c @@ -0,0 +1,513 @@ +/* A splay-tree datatype. + Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Contributed by Mark Mitchell (mark@markmitchell.com). + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC is distributed in the hope that 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 CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* For an easily readable description of splay-trees, see: + + Lewis, Harry R. and Denenberg, Larry. Data Structures and Their + Algorithms. Harper-Collins, Inc. 1991. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#include + +#include "libiberty.h" +#include "splay-tree.h" + +static void splay_tree_delete_helper PARAMS((splay_tree, + splay_tree_node)); +static void splay_tree_splay PARAMS((splay_tree, + splay_tree_key)); +static splay_tree_node splay_tree_splay_helper + PARAMS((splay_tree, + splay_tree_key, + splay_tree_node*, + splay_tree_node*, + splay_tree_node*)); +static int splay_tree_foreach_helper PARAMS((splay_tree, + splay_tree_node, + splay_tree_foreach_fn, + void*)); + +/* Deallocate NODE (a member of SP), and all its sub-trees. */ + +static void +splay_tree_delete_helper (sp, node) + splay_tree sp; + splay_tree_node node; +{ + if (!node) + return; + + splay_tree_delete_helper (sp, node->left); + splay_tree_delete_helper (sp, node->right); + + if (sp->delete_key) + (*sp->delete_key)(node->key); + if (sp->delete_value) + (*sp->delete_value)(node->value); + + free ((char*) node); +} + +/* Help splay SP around KEY. PARENT and GRANDPARENT are the parent + and grandparent, respectively, of NODE. */ + +static splay_tree_node +splay_tree_splay_helper (sp, key, node, parent, grandparent) + splay_tree sp; + splay_tree_key key; + splay_tree_node *node; + splay_tree_node *parent; + splay_tree_node *grandparent; +{ + splay_tree_node *next; + splay_tree_node n; + int comparison; + + n = *node; + + if (!n) + return *parent; + + comparison = (*sp->comp) (key, n->key); + + if (comparison == 0) + /* We've found the target. */ + next = 0; + else if (comparison < 0) + /* The target is to the left. */ + next = &n->left; + else + /* The target is to the right. */ + next = &n->right; + + if (next) + { + /* Continue down the tree. */ + n = splay_tree_splay_helper (sp, key, next, node, parent); + + /* The recursive call will change the place to which NODE + points. */ + if (*node != n) + return n; + } + + if (!parent) + /* NODE is the root. We are done. */ + return n; + + /* First, handle the case where there is no grandparent (i.e., + *PARENT is the root of the tree.) */ + if (!grandparent) + { + if (n == (*parent)->left) + { + *node = n->right; + n->right = *parent; + } + else + { + *node = n->left; + n->left = *parent; + } + *parent = n; + return n; + } + + /* Next handle the cases where both N and *PARENT are left children, + or where both are right children. */ + if (n == (*parent)->left && *parent == (*grandparent)->left) + { + splay_tree_node p = *parent; + + (*grandparent)->left = p->right; + p->right = *grandparent; + p->left = n->right; + n->right = p; + *grandparent = n; + return n; + } + else if (n == (*parent)->right && *parent == (*grandparent)->right) + { + splay_tree_node p = *parent; + + (*grandparent)->right = p->left; + p->left = *grandparent; + p->right = n->left; + n->left = p; + *grandparent = n; + return n; + } + + /* Finally, deal with the case where N is a left child, but *PARENT + is a right child, or vice versa. */ + if (n == (*parent)->left) + { + (*parent)->left = n->right; + n->right = *parent; + (*grandparent)->right = n->left; + n->left = *grandparent; + *grandparent = n; + return n; + } + else + { + (*parent)->right = n->left; + n->left = *parent; + (*grandparent)->left = n->right; + n->right = *grandparent; + *grandparent = n; + return n; + } +} + +/* Splay SP around KEY. */ + +static void +splay_tree_splay (sp, key) + splay_tree sp; + splay_tree_key key; +{ + if (sp->root == 0) + return; + + splay_tree_splay_helper (sp, key, &sp->root, + /*grandparent=*/0, /*parent=*/0); +} + +/* Call FN, passing it the DATA, for every node below NODE, all of + which are from SP, following an in-order traversal. If FN every + returns a non-zero value, the iteration ceases immediately, and the + value is returned. Otherwise, this function returns 0. */ + +static int +splay_tree_foreach_helper (sp, node, fn, data) + splay_tree sp; + splay_tree_node node; + splay_tree_foreach_fn fn; + void* data; +{ + int val; + + if (!node) + return 0; + + val = splay_tree_foreach_helper (sp, node->left, fn, data); + if (val) + return val; + + val = (*fn)(node, data); + if (val) + return val; + + return splay_tree_foreach_helper (sp, node->right, fn, data); +} + +/* Allocate a new splay tree, using COMPARE_FN to compare nodes, + DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate + values. */ + +splay_tree +splay_tree_new (compare_fn, delete_key_fn, delete_value_fn) + splay_tree_compare_fn compare_fn; + splay_tree_delete_key_fn delete_key_fn; + splay_tree_delete_value_fn delete_value_fn; +{ + splay_tree sp = (splay_tree) xmalloc (sizeof (struct splay_tree_s)); + sp->root = 0; + sp->comp = compare_fn; + sp->delete_key = delete_key_fn; + sp->delete_value = delete_value_fn; + + return sp; +} + +/* Deallocate SP. */ + +void +splay_tree_delete (sp) + splay_tree sp; +{ + splay_tree_delete_helper (sp, sp->root); + free ((char*) sp); +} + +/* Insert a new node (associating KEY with DATA) into SP. If a + previous node with the indicated KEY exists, its data is replaced + with the new value. Returns the new node. */ + +splay_tree_node +splay_tree_insert (sp, key, value) + splay_tree sp; + splay_tree_key key; + splay_tree_value value; +{ + int comparison = 0; + + splay_tree_splay (sp, key); + + if (sp->root) + comparison = (*sp->comp)(sp->root->key, key); + + if (sp->root && comparison == 0) + { + /* If the root of the tree already has the indicated KEY, just + replace the value with VALUE. */ + if (sp->delete_value) + (*sp->delete_value)(sp->root->value); + sp->root->value = value; + } + else + { + /* Create a new node, and insert it at the root. */ + splay_tree_node node; + + node = (splay_tree_node) xmalloc (sizeof (struct splay_tree_node_s)); + node->key = key; + node->value = value; + + if (!sp->root) + node->left = node->right = 0; + else if (comparison < 0) + { + node->left = sp->root; + node->right = node->left->right; + node->left->right = 0; + } + else + { + node->right = sp->root; + node->left = node->right->left; + node->right->left = 0; + } + + sp->root = node; + } + + return sp->root; +} + +/* Remove KEY from SP. It is not an error if it did not exist. */ + +void +splay_tree_remove (sp, key) + splay_tree sp; + splay_tree_key key; +{ + splay_tree_splay (sp, key); + + if (sp->root && (*sp->comp) (sp->root->key, key) == 0) + { + splay_tree_node left, right; + + left = sp->root->left; + right = sp->root->right; + + /* Delete the root node itself. */ + if (sp->delete_value) + (*sp->delete_value) (sp->root->value); + free (sp->root); + + /* One of the children is now the root. Doesn't matter much + which, so long as we preserve the properties of the tree. */ + if (left) + { + sp->root = left; + + /* If there was a right child as well, hang it off the + right-most leaf of the left child. */ + if (right) + { + while (left->right) + left = left->right; + left->right = right; + } + } + else + sp->root = right; + } +} + +/* Lookup KEY in SP, returning VALUE if present, and NULL + otherwise. */ + +splay_tree_node +splay_tree_lookup (sp, key) + splay_tree sp; + splay_tree_key key; +{ + splay_tree_splay (sp, key); + + if (sp->root && (*sp->comp)(sp->root->key, key) == 0) + return sp->root; + else + return 0; +} + +/* Return the node in SP with the greatest key. */ + +splay_tree_node +splay_tree_max (sp) + splay_tree sp; +{ + splay_tree_node n = sp->root; + + if (!n) + return NULL; + + while (n->right) + n = n->right; + + return n; +} + +/* Return the node in SP with the smallest key. */ + +splay_tree_node +splay_tree_min (sp) + splay_tree sp; +{ + splay_tree_node n = sp->root; + + if (!n) + return NULL; + + while (n->left) + n = n->left; + + return n; +} + +/* Return the immediate predecessor KEY, or NULL if there is no + predecessor. KEY need not be present in the tree. */ + +splay_tree_node +splay_tree_predecessor (sp, key) + splay_tree sp; + splay_tree_key key; +{ + int comparison; + splay_tree_node node; + + /* If the tree is empty, there is certainly no predecessor. */ + if (!sp->root) + return NULL; + + /* Splay the tree around KEY. That will leave either the KEY + itself, its predecessor, or its successor at the root. */ + splay_tree_splay (sp, key); + comparison = (*sp->comp)(sp->root->key, key); + + /* If the predecessor is at the root, just return it. */ + if (comparison < 0) + return sp->root; + + /* Otherwise, find the leftmost element of the right subtree. */ + node = sp->root->left; + if (node) + while (node->right) + node = node->right; + + return node; +} + +/* Return the immediate successor KEY, or NULL if there is no + predecessor. KEY need not be present in the tree. */ + +splay_tree_node +splay_tree_successor (sp, key) + splay_tree sp; + splay_tree_key key; +{ + int comparison; + splay_tree_node node; + + /* If the tree is empty, there is certainly no predecessor. */ + if (!sp->root) + return NULL; + + /* Splay the tree around KEY. That will leave either the KEY + itself, its predecessor, or its successor at the root. */ + splay_tree_splay (sp, key); + comparison = (*sp->comp)(sp->root->key, key); + + /* If the successor is at the root, just return it. */ + if (comparison > 0) + return sp->root; + + /* Otherwise, find the rightmost element of the left subtree. */ + node = sp->root->right; + if (node) + while (node->left) + node = node->left; + + return node; +} + +/* Call FN, passing it the DATA, for every node in SP, following an + in-order traversal. If FN every returns a non-zero value, the + iteration ceases immediately, and the value is returned. + Otherwise, this function returns 0. */ + +int +splay_tree_foreach (sp, fn, data) + splay_tree sp; + splay_tree_foreach_fn fn; + void *data; +{ + return splay_tree_foreach_helper (sp, sp->root, fn, data); +} + +/* Splay-tree comparison function, treating the keys as ints. */ + +int +splay_tree_compare_ints (k1, k2) + splay_tree_key k1; + splay_tree_key k2; +{ + if ((int) k1 < (int) k2) + return -1; + else if ((int) k1 > (int) k2) + return 1; + else + return 0; +} + +/* Splay-tree comparison function, treating the keys as pointers. */ + +int +splay_tree_compare_pointers (k1, k2) + splay_tree_key k1; + splay_tree_key k2; +{ + if ((char*) k1 < (char*) k2) + return -1; + else if ((char*) k1 > (char*) k2) + return 1; + else + return 0; +} diff --git a/support/cpp2/splay-tree.h b/support/cpp2/splay-tree.h new file mode 100644 index 00000000..37e9a359 --- /dev/null +++ b/support/cpp2/splay-tree.h @@ -0,0 +1,129 @@ +/* A splay-tree datatype. + Copyright 1998, 1999, 2000 Free Software Foundation, Inc. + Contributed by Mark Mitchell (mark@markmitchell.com). + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC is distributed in the hope that 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 CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* For an easily readable description of splay-trees, see: + + Lewis, Harry R. and Denenberg, Larry. Data Structures and Their + Algorithms. Harper-Collins, Inc. 1991. + + The major feature of splay trees is that all basic tree operations + are amortized O(log n) time for a tree with n nodes. */ + +#ifndef _SPLAY_TREE_H +#define _SPLAY_TREE_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + +/* Use typedefs for the key and data types to facilitate changing + these types, if necessary. These types should be sufficiently wide + that any pointer or scalar can be cast to these types, and then + cast back, without loss of precision. */ +typedef unsigned long int splay_tree_key; +typedef unsigned long int splay_tree_value; + +/* Forward declaration for a node in the tree. */ +typedef struct splay_tree_node_s *splay_tree_node; + +/* The type of a function which compares two splay-tree keys. The + function should return values as for qsort. */ +typedef int (*splay_tree_compare_fn) PARAMS((splay_tree_key, splay_tree_key)); + +/* The type of a function used to deallocate any resources associated + with the key. */ +typedef void (*splay_tree_delete_key_fn) PARAMS((splay_tree_key)); + +/* The type of a function used to deallocate any resources associated + with the value. */ +typedef void (*splay_tree_delete_value_fn) PARAMS((splay_tree_value)); + +/* The type of a function used to iterate over the tree. */ +typedef int (*splay_tree_foreach_fn) PARAMS((splay_tree_node, void*)); + +/* The nodes in the splay tree. */ +struct splay_tree_node_s +{ + /* The key. */ + splay_tree_key key; + + /* The value. */ + splay_tree_value value; + + /* The left and right children, respectively. */ + splay_tree_node left; + splay_tree_node right; +}; + +/* The splay tree itself. */ +typedef struct splay_tree_s +{ + /* The root of the tree. */ + splay_tree_node root; + + /* The comparision function. */ + splay_tree_compare_fn comp; + + /* The deallocate-key function. NULL if no cleanup is necessary. */ + splay_tree_delete_key_fn delete_key; + + /* The deallocate-value function. NULL if no cleanup is necessary. */ + splay_tree_delete_value_fn delete_value; +} *splay_tree; + +extern splay_tree splay_tree_new PARAMS((splay_tree_compare_fn, + splay_tree_delete_key_fn, + splay_tree_delete_value_fn)); +extern void splay_tree_delete PARAMS((splay_tree)); +extern splay_tree_node splay_tree_insert + PARAMS((splay_tree, + splay_tree_key, + splay_tree_value)); +extern void splay_tree_remove PARAMS((splay_tree, + splay_tree_key)); +extern splay_tree_node splay_tree_lookup + PARAMS((splay_tree, + splay_tree_key)); +extern splay_tree_node splay_tree_predecessor + PARAMS((splay_tree, + splay_tree_key)); +extern splay_tree_node splay_tree_successor + PARAMS((splay_tree, + splay_tree_key)); +extern splay_tree_node splay_tree_max + PARAMS((splay_tree)); +extern splay_tree_node splay_tree_min + PARAMS((splay_tree)); +extern int splay_tree_foreach PARAMS((splay_tree, + splay_tree_foreach_fn, + void*)); +extern int splay_tree_compare_ints PARAMS((splay_tree_key, + splay_tree_key)); +extern int splay_tree_compare_pointers PARAMS((splay_tree_key, + splay_tree_key)); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _SPLAY_TREE_H */ diff --git a/support/cpp2/symcat.h b/support/cpp2/symcat.h new file mode 100644 index 00000000..61ce1e9b --- /dev/null +++ b/support/cpp2/symcat.h @@ -0,0 +1,49 @@ +/* Symbol concatenation utilities. + + Copyright (C) 1998, 2000 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 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef SYM_CAT_H +#define SYM_CAT_H + +#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE) +#define CONCAT2(a,b) a##b +#define CONCAT3(a,b,c) a##b##c +#define CONCAT4(a,b,c,d) a##b##c##d +#define STRINGX(s) #s +#else +/* Note one should never pass extra whitespace to the CONCATn macros, + e.g. CONCAT2(foo, bar) because traditonal C will keep the space between + the two labels instead of concatenating them. Instead, make sure to + write CONCAT2(foo,bar). */ +#define CONCAT2(a,b) a/**/b +#define CONCAT3(a,b,c) a/**/b/**/c +#define CONCAT4(a,b,c,d) a/**/b/**/c/**/d +#define STRINGX(s) "s" +#endif + +#define XCONCAT2(a,b) CONCAT2(a,b) +#define XCONCAT3(a,b,c) CONCAT3(a,b,c) +#define XCONCAT4(a,b,c,d) CONCAT4(a,b,c,d) + +/* Note the layer of indirection here is typically used to allow + stringification of the expansion of macros. I.e. "#define foo + bar", "XSTRING(foo)", to yield "bar". Be aware that this only + works for __STDC__, not for traditional C which will still resolve + to "foo". */ +#define XSTRING(s) STRINGX(s) + +#endif /* SYM_CAT_H */ diff --git a/support/cpp2/system.h b/support/cpp2/system.h new file mode 100644 index 00000000..8486185e --- /dev/null +++ b/support/cpp2/system.h @@ -0,0 +1,500 @@ +/* Get common system includes and various definitions and declarations based + on autoconf macros. + Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC is distributed in the hope that 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 CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + + +#ifndef GCC_SYSTEM_H +#define GCC_SYSTEM_H + +/* This is the location of the online document giving information how + to report bugs. If you change this string, also check for strings + not under control of the preprocessor. */ +#define GCCBUGURL "" + +#include "ansidecl.h" + +/* We must include stdarg.h/varargs.h before stdio.h. */ +#ifdef ANSI_PROTOTYPES +#include +#else +#include +#endif + +#ifndef va_copy +# ifdef __va_copy +# define va_copy(d,s) __va_copy((d),(s)) +# else +# define va_copy(d,s) ((d) = (s)) +# endif +#endif + +#ifdef HAVE_STDDEF_H +# include +#endif + +#include + +#define CHAR_BIT 8 + +/* Define a generic NULL if one hasn't already been defined. */ +#ifndef NULL +#define NULL 0 +#endif + +/* There are an extraordinary number of issues with . + The last straw is that it varies with the locale. Use libiberty's + replacement instead. */ +#include + +/* Define a default escape character; it's different for EBCDIC. */ +#ifndef TARGET_ESC +#define TARGET_ESC 033 +#endif + +#include + +#include + +#if !defined (errno) && defined (HAVE_DECL_ERRNO) && !HAVE_DECL_ERRNO +extern int errno; +#endif + +#ifdef STRING_WITH_STRINGS +# include +# include +#else +# ifdef HAVE_STRING_H +# include +# else +# ifdef HAVE_STRINGS_H +# include +# endif +# endif +#endif + +#ifdef HAVE_STDLIB_H +# include +#endif + +/* If we don't have an overriding definition, set SUCCESS_EXIT_CODE and + FATAL_EXIT_CODE to EXIT_SUCCESS and EXIT_FAILURE respectively, + or 0 and 1 if those macros are not defined. */ +#ifndef SUCCESS_EXIT_CODE +# ifdef EXIT_SUCCESS +# define SUCCESS_EXIT_CODE EXIT_SUCCESS +# else +# define SUCCESS_EXIT_CODE 0 +# endif +#endif + +#ifndef FATAL_EXIT_CODE +# ifdef EXIT_FAILURE +# define FATAL_EXIT_CODE EXIT_FAILURE +# else +# define FATAL_EXIT_CODE 1 +# endif +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_SYS_PARAM_H +# include +#endif + +#if HAVE_LIMITS_H +# include +#endif + +/* Get definitions of HOST_WIDE_INT and HOST_WIDEST_INT. */ +#include "hwint.h" + +/* Infrastructure for defining missing _MAX and _MIN macros. Note that + macros defined with these cannot be used in #if. */ + +/* The extra casts work around common compiler bugs. */ +#define INTTYPE_SIGNED(t) (! ((t) 0 < (t) -1)) +/* The outer cast is needed to work around a bug in Cray C 5.0.3.0. + It is necessary at least when t == time_t. */ +#define INTTYPE_MINIMUM(t) ((t) (INTTYPE_SIGNED (t) \ + ? ~ (t) 0 << (sizeof(t) * CHAR_BIT - 1) : (t) 0)) +#define INTTYPE_MAXIMUM(t) ((t) (~ (t) 0 - INTTYPE_MINIMUM (t))) + +/* Use that infrastructure to provide a few constants. */ +#ifndef UCHAR_MAX +# define UCHAR_MAX INTTYPE_MAXIMUM (unsigned char) +#endif + +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# ifdef HAVE_TIME_H +# include +# endif +# endif +#endif + +#ifdef HAVE_FCNTL_H +# include +#else +# ifdef HAVE_SYS_FILE_H +# include +# endif +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 +# define SEEK_CUR 1 +# define SEEK_END 2 +#endif +#ifndef F_OK +# define F_OK 0 +# define X_OK 1 +# define W_OK 2 +# define R_OK 4 +#endif +#ifndef O_RDONLY +# define O_RDONLY 0 +#endif +#ifndef O_WRONLY +# define O_WRONLY 1 +#endif + +/* Some systems define these in, e.g., param.h. We undefine these names + here to avoid the warnings. We prefer to use our definitions since we + know they are correct. */ + +#undef MIN +#undef MAX +#define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) +#define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) + +/* Returns the least number N such that N * Y >= X. */ +#define CEIL(x,y) (((x) + (y) - 1) / (y)) + +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +#ifndef WIFSIGNALED +#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f) +#endif +#ifndef WTERMSIG +#define WTERMSIG(S) ((S) & 0x7f) +#endif +#ifndef WIFEXITED +#define WIFEXITED(S) (((S) & 0xff) == 0) +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(S) (((S) & 0xff00) >> 8) +#endif +#ifndef WSTOPSIG +#define WSTOPSIG WEXITSTATUS +#endif + +/* The HAVE_DECL_* macros are three-state, undefined, 0 or 1. If they + are defined to 0 then we must provide the relevant declaration + here. These checks will be in the undefined state while configure + is running so be careful to test "defined (HAVE_DECL_*)". */ + +#if defined (HAVE_DECL_ATOF) && !HAVE_DECL_ATOF +extern double atof PARAMS ((const char *)); +#endif + +#if defined (HAVE_DECL_ATOL) && !HAVE_DECL_ATOL +extern long atol PARAMS ((const char *)); +#endif + +#if defined (HAVE_DECL_FREE) && !HAVE_DECL_FREE +extern void free PARAMS ((PTR)); +#endif + +#if defined (HAVE_DECL_GETCWD) && !HAVE_DECL_GETCWD +extern char *getcwd PARAMS ((char *, size_t)); +#endif + +#if defined (HAVE_DECL_GETENV) && !HAVE_DECL_GETENV +extern char *getenv PARAMS ((const char *)); +#endif + +#if defined (HAVE_DECL_GETOPT) && !HAVE_DECL_GETOPT +extern int getopt PARAMS ((int, char * const *, const char *)); +#endif + +#if defined (HAVE_DECL_GETWD) && !HAVE_DECL_GETWD +extern char *getwd PARAMS ((char *)); +#endif + +#if defined (HAVE_DECL_SBRK) && !HAVE_DECL_SBRK +extern PTR sbrk PARAMS ((int)); +#endif + +#if defined (HAVE_DECL_STRSTR) && !HAVE_DECL_STRSTR +extern char *strstr PARAMS ((const char *, const char *)); +#endif + +#ifdef HAVE_MALLOC_H +#include +#endif + +#if defined (HAVE_DECL_MALLOC) && !HAVE_DECL_MALLOC +extern PTR malloc PARAMS ((size_t)); +#endif + +#if defined (HAVE_DECL_CALLOC) && !HAVE_DECL_CALLOC +extern PTR calloc PARAMS ((size_t, size_t)); +#endif + +#if defined (HAVE_DECL_REALLOC) && !HAVE_DECL_REALLOC +extern PTR realloc PARAMS ((PTR, size_t)); +#endif + +#ifdef HAVE_GETRLIMIT +# if defined (HAVE_DECL_GETRLIMIT) && !HAVE_DECL_GETRLIMIT +# ifndef getrlimit +# ifdef ANSI_PROTOTYPES +struct rlimit; +# endif +extern int getrlimit PARAMS ((int, struct rlimit *)); +# endif +# endif +#endif + +#ifdef HAVE_SETRLIMIT +# if defined (HAVE_DECL_SETRLIMIT) && !HAVE_DECL_SETRLIMIT +# ifndef setrlimit +# ifdef ANSI_PROTOTYPES +struct rlimit; +# endif +extern int setrlimit PARAMS ((int, const struct rlimit *)); +# endif +# endif +#endif + +#if !defined(__STDC__) && !defined(volatile) +#define volatile +#endif + +#if defined (HAVE_DECL_ABORT) && !HAVE_DECL_ABORT +extern void abort PARAMS ((void)); +#endif + +/* 1 if we have C99 designated initializers. */ +#if !defined(HAVE_DESIGNATED_INITIALIZERS) +#define HAVE_DESIGNATED_INITIALIZERS \ + ((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L)) +#endif + +#if HAVE_SYS_STAT_H +# include +#endif + +/* Test if something is a normal file. */ +#ifndef S_ISREG +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#endif + +/* Test if something is a directory. */ +#ifndef S_ISDIR +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif + +/* Test if something is a character special file. */ +#ifndef S_ISCHR +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#endif + +/* Test if something is a block special file. */ +#ifndef S_ISBLK +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +#endif + +/* Test if something is a socket. */ +#ifndef S_ISSOCK +# ifdef S_IFSOCK +# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +# else +# define S_ISSOCK(m) 0 +# endif +#endif + +/* Test if something is a FIFO. */ +#ifndef S_ISFIFO +# ifdef S_IFIFO +# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +# else +# define S_ISFIFO(m) 0 +# endif +#endif + +/* Approximate O_NONBLOCK. */ +#ifndef O_NONBLOCK +#define O_NONBLOCK O_NDELAY +#endif + +/* Approximate O_NOCTTY. */ +#ifndef O_NOCTTY +#define O_NOCTTY 0 +#endif + +/* Define well known filenos if the system does not define them. */ +#ifndef STDIN_FILENO +# define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +# define STDOUT_FILENO 1 +#endif +#ifndef STDERR_FILENO +# define STDERR_FILENO 2 +#endif + +/* Some systems have mkdir that takes a single argument. */ +#ifdef MKDIR_TAKES_ONE_ARG +# define mkdir(a,b) mkdir(a) +#endif + +/* Provide a way to print an address via printf. */ +#ifndef HOST_PTR_PRINTF +# ifdef HAVE_PRINTF_PTR +# define HOST_PTR_PRINTF "%p" +# else +# define HOST_PTR_PRINTF \ + (sizeof (int) == sizeof (char *) ? "%x" \ + : sizeof (long) == sizeof (char *) ? "%lx" : "%llx") +# endif +#endif /* ! HOST_PTR_PRINTF */ + +/* By default, colon separates directories in a path. */ +#ifndef PATH_SEPARATOR +#define PATH_SEPARATOR ':' +#endif + +#ifndef DIR_SEPARATOR +#define DIR_SEPARATOR '/' +#endif + +/* Define IS_DIR_SEPARATOR. */ +#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 */ + +/* Say how to test for an absolute pathname. On Unix systems, this is if + it starts with a leading slash or a '$', the latter meaning the value of + an environment variable is to be used. On machien with DOS-based + file systems, it is also absolute if it starts with a drive identifier. */ +#ifdef HAVE_DOS_BASED_FILE_SYSTEM +#define IS_ABSOLUTE_PATHNAME(STR) \ + (IS_DIR_SEPARATOR ((STR)[0]) || (STR)[0] == '$' \ + || ((STR)[0] != '\0' && (STR)[1] == ':' && IS_DIR_SEPARATOR ((STR)[2]))) +#else +#define IS_ABSOLUTE_PATHNAME(STR) \ + (IS_DIR_SEPARATOR ((STR)[0]) || (STR)[0] == '$') +#endif + +/* Get libiberty declarations. */ +/* #include "libiberty.h" */ +#include "sdcc.h" +#include "symcat.h" + +/* Provide a default for the HOST_BIT_BUCKET. + This suffices for POSIX-like hosts. */ + +#ifndef HOST_BIT_BUCKET +#define HOST_BIT_BUCKET "/dev/null" +#endif + +/* Be conservative and only use enum bitfields with GCC. + FIXME: provide a complete autoconf test for buggy enum bitfields. */ + +#if (GCC_VERSION > 2000) +#define ENUM_BITFIELD(TYPE) enum TYPE +#else +#define ENUM_BITFIELD(TYPE) unsigned int +#endif + +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +/* Traditional C cannot initialize union members of structs. Provide + a macro which expands appropriately to handle it. This only works + if you intend to initalize the union member to zero since it relies + on default initialization to zero in the traditional C case. */ +#ifdef __STDC__ +#define UNION_INIT_ZERO , {0} +#else +#define UNION_INIT_ZERO +#endif + +/* Various error reporting routines want to use __FUNCTION__. */ +#if (GCC_VERSION < 2007) +#ifndef __FUNCTION__ +#define __FUNCTION__ "?" +#endif /* ! __FUNCTION__ */ +#endif + +/* As the last action in this file, we poison the identifiers that + shouldn't be used. Note, luckily gcc-3.0's token-based integrated + preprocessor won't trip on poisoned identifiers that arrive from + the expansion of macros. E.g. #define strrchr rindex, won't error + if rindex is poisoned after this directive is issued and later on + strrchr is called. + + Note: We define bypass macros for the few cases where we really + want to use the libc memory allocation routines. Otherwise we + insist you use the "x" versions from libiberty. */ + +#define really_call_malloc malloc +#define really_call_calloc calloc +#define really_call_realloc realloc + +#if (GCC_VERSION >= 3000) + +/* Note autoconf checks for prototype declarations and includes + system.h while doing so. Only poison these tokens if actually + compiling gcc, so that the autoconf declaration tests for malloc + etc don't spuriously fail. */ +#ifdef IN_GCC +#undef malloc +#undef realloc +#undef calloc +#undef strdup + #pragma GCC poison malloc realloc calloc strdup +#endif /* IN_GCC */ + +/* Note: not all uses of the `index' token (e.g. variable names and + structure members) have been eliminated. */ +#undef bcopy +#undef bzero +#undef bcmp +#undef rindex + #pragma GCC poison bcopy bzero bcmp rindex + +#endif /* GCC >= 3.0 */ + +#endif /* ! GCC_SYSTEM_H */ diff --git a/support/cpp2/version.c b/support/cpp2/version.c new file mode 100644 index 00000000..24bc2870 --- /dev/null +++ b/support/cpp2/version.c @@ -0,0 +1,4 @@ +#include "ansidecl.h" +#include "version.h" + +const char *const version_string = "3.1 20010625 (experimental) + SDCC"; diff --git a/support/cpp2/version.h b/support/cpp2/version.h new file mode 100644 index 00000000..99416495 --- /dev/null +++ b/support/cpp2/version.h @@ -0,0 +1,4 @@ +#ifndef GCC_VERSION_H +#define GCC_VERSION_H +extern const char *const version_string; +#endif /* ! GCC_VERSION_H */