Port of CPP from GCC 3.0
authorkvigor <kvigor@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Tue, 3 Jul 2001 17:51:28 +0000 (17:51 +0000)
committerkvigor <kvigor@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Tue, 3 Jul 2001 17:51:28 +0000 (17:51 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1009 4a8a32a2-be11-0410-ad9d-d568d2c75423

51 files changed:
support/cpp2/Makefile.in [new file with mode: 0644]
support/cpp2/acconfig.h [new file with mode: 0644]
support/cpp2/aclocal.m4 [new file with mode: 0644]
support/cpp2/ansidecl.h [new file with mode: 0644]
support/cpp2/config.h [new file with mode: 0644]
support/cpp2/config.in [new file with mode: 0644]
support/cpp2/configargs.h [new file with mode: 0644]
support/cpp2/configure [new file with mode: 0755]
support/cpp2/configure.in [new file with mode: 0644]
support/cpp2/cppdefault.c [new file with mode: 0644]
support/cpp2/cppdefault.h [new file with mode: 0644]
support/cpp2/cpperror.c [new file with mode: 0644]
support/cpp2/cppexp.c [new file with mode: 0644]
support/cpp2/cppfiles.c [new file with mode: 0644]
support/cpp2/cpphash.c [new file with mode: 0644]
support/cpp2/cpphash.h [new file with mode: 0644]
support/cpp2/cppinit.c [new file with mode: 0644]
support/cpp2/cpplex.c [new file with mode: 0644]
support/cpp2/cpplib.c [new file with mode: 0644]
support/cpp2/cpplib.h [new file with mode: 0644]
support/cpp2/cppmacro.c [new file with mode: 0644]
support/cpp2/cppmain.c [new file with mode: 0644]
support/cpp2/hashtable.c [new file with mode: 0644]
support/cpp2/hashtable.h [new file with mode: 0644]
support/cpp2/hwint.h [new file with mode: 0644]
support/cpp2/intl.c [new file with mode: 0644]
support/cpp2/intl.h [new file with mode: 0644]
support/cpp2/libiberty.h [new file with mode: 0644]
support/cpp2/libiberty/lbasename.c [new file with mode: 0644]
support/cpp2/libiberty/obstack.c [new file with mode: 0644]
support/cpp2/libiberty/obstack.h [new file with mode: 0644]
support/cpp2/libiberty/safe-ctype.c [new file with mode: 0644]
support/cpp2/libiberty/safe-ctype.h [new file with mode: 0644]
support/cpp2/libiberty/splay-tree.c [new file with mode: 0644]
support/cpp2/libiberty/splay-tree.h [new file with mode: 0644]
support/cpp2/mbchar.c [new file with mode: 0644]
support/cpp2/mbchar.h [new file with mode: 0644]
support/cpp2/mkdeps.c [new file with mode: 0644]
support/cpp2/mkdeps.h [new file with mode: 0644]
support/cpp2/options.h [new file with mode: 0644]
support/cpp2/output.h [new file with mode: 0644]
support/cpp2/prefix.c [new file with mode: 0644]
support/cpp2/prefix.h [new file with mode: 0644]
support/cpp2/sdcc.h [new file with mode: 0644]
support/cpp2/specs.h [new file with mode: 0644]
support/cpp2/splay-tree.c [new file with mode: 0644]
support/cpp2/splay-tree.h [new file with mode: 0644]
support/cpp2/symcat.h [new file with mode: 0644]
support/cpp2/system.h [new file with mode: 0644]
support/cpp2/version.c [new file with mode: 0644]
support/cpp2/version.h [new file with mode: 0644]

diff --git a/support/cpp2/Makefile.in b/support/cpp2/Makefile.in
new file mode 100644 (file)
index 0000000..bc76200
--- /dev/null
@@ -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 <limits.h> 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@
+#\f
+
+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
+
+#\f
+# 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 (file)
index 0000000..dec619b
--- /dev/null
@@ -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 <sys/types.h> 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 (file)
index 0000000..0cc940e
--- /dev/null
@@ -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 <string.h>
+#include <strings.h>], , 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 <string.h> and <strings.h>.])
+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_<FUNCTION> 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 <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_DIRECT_H
+# include <direct.h>
+#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 <sys/types.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <stdio.h>
+
+#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 <unistd.h>
+# 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 <sys/param.h>
+#   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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+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 <stdlib.h>
+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(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
+dnl The cache variable name.
+define(<<AC_CV_NAME>>, 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 <sys/types.h>
+$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 <limits.h>
+#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 <<EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+$1
+]EOF
+if AC_TRY_EVAL(ac_compile); 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
+  $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 <limits.h>
+#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 (file)
index 0000000..4ef6db8
--- /dev/null
@@ -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 (file)
index 0000000..476f7ac
--- /dev/null
@@ -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 (file)
index 0000000..1a3552c
--- /dev/null
@@ -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 <sys/types.h> doesn't define.  */
+#undef gid_t
+
+/* Define if you have the ANSI # stringizing operator in cpp. */
+#undef HAVE_STRINGIZE
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */
+#undef HAVE_SYS_WAIT_H
+
+/* Define if you have <vfork.h>.  */
+#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 <sys/types.h> doesn't define.  */
+#undef off_t
+
+/* Define to `int' if <sys/types.h> doesn't define.  */
+#undef pid_t
+
+/* Define to `unsigned' if <sys/types.h> 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 <sys/time.h> and <time.h>.  */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to `int' if <sys/types.h> 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 <sys/types.h> 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 <argz.h> header file.  */
+#undef HAVE_ARGZ_H
+
+/* Define if you have the <direct.h> header file.  */
+#undef HAVE_DIRECT_H
+
+/* Define if you have the <fcntl.h> header file.  */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <iconv.h> header file.  */
+#undef HAVE_ICONV_H
+
+/* Define if you have the <langinfo.h> header file.  */
+#undef HAVE_LANGINFO_H
+
+/* Define if you have the <limits.h> header file.  */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <locale.h> header file.  */
+#undef HAVE_LOCALE_H
+
+/* Define if you have the <malloc.h> header file.  */
+#undef HAVE_MALLOC_H
+
+/* Define if you have the <nl_types.h> header file.  */
+#undef HAVE_NL_TYPES_H
+
+/* Define if you have the <stddef.h> header file.  */
+#undef HAVE_STDDEF_H
+
+/* Define if you have the <stdlib.h> header file.  */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the <string.h> header file.  */
+#undef HAVE_STRING_H
+
+/* Define if you have the <strings.h> header file.  */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/file.h> header file.  */
+#undef HAVE_SYS_FILE_H
+
+/* Define if you have the <sys/param.h> header file.  */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <sys/resource.h> header file.  */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define if you have the <sys/stat.h> header file.  */
+#undef HAVE_SYS_STAT_H
+
+/* Define if you have the <sys/time.h> header file.  */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <sys/times.h> header file.  */
+#undef HAVE_SYS_TIMES_H
+
+/* Define if you have the <time.h> header file.  */
+#undef HAVE_TIME_H
+
+/* Define if you have the <unistd.h> 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 <stdbool.h> header file. */
+#undef HAVE_STDBOOL_H
+
+/* Define if you can safely include both <string.h> and <strings.h>. */
+#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 <inttypes.h> 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 <sys/times.h> defines struct tms. */
+#undef HAVE_STRUCT_TMS
+
+/* Define if <time.h> 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 (file)
index 0000000..d384cbb
--- /dev/null
@@ -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 (executable)
index 0000000..6d4e755
--- /dev/null
@@ -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 <<EOF
+#define DEFAULT_LINKER "$DEFAULT_LINKER"
+EOF
+
+fi
+
+# With GNU as
+# Check whether --with-gnu-as or --without-gnu-as was given.
+if test "${with_gnu_as+set}" = set; then
+  withval="$with_gnu_as"
+  gas_flag="$with_gnu_as"
+else
+  gas_flag=no
+fi
+
+
+# Check whether --with-as or --without-as was given.
+if test "${with_as+set}" = set; then
+  withval="$with_as"
+  DEFAULT_ASSEMBLER="$with_as"
+fi
+
+if test x"${DEFAULT_ASSEMBLER+set}" = x"set"; then
+  if test ! -x "$DEFAULT_ASSEMBLER"; then
+    echo "configure: warning: cannot execute: $DEFAULT_ASSEMBLER: check --with-as or env. var. DEFAULT_ASSEMBLER" 1>&2
+  elif $DEFAULT_ASSEMBLER -v < /dev/null 2>&1 | grep GNU > /dev/null; then
+    gas_flag=yes
+  fi
+  cat >> confdefs.h <<EOF
+#define DEFAULT_ASSEMBLER "$DEFAULT_ASSEMBLER"
+EOF
+
+fi
+
+# With stabs
+# Check whether --with-stabs or --without-stabs was given.
+if test "${with_stabs+set}" = set; then
+  withval="$with_stabs"
+  stabs="$with_stabs"
+else
+  stabs=no
+fi
+
+
+# With ELF
+# Check whether --with-elf or --without-elf was given.
+if test "${with_elf+set}" = set; then
+  withval="$with_elf"
+  elf="$with_elf"
+else
+  elf=no
+fi
+
+
+# Specify the local prefix
+local_prefix=
+# Check whether --with-local-prefix or --without-local-prefix was given.
+if test "${with_local_prefix+set}" = set; then
+  withval="$with_local_prefix"
+  case "${withval}" in
+yes)   { echo "configure: error: bad value ${withval} given for local include directory prefix" 1>&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 <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:835: \"$ac_try\") 1>&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 <<EOF
+#line 962 "configure"
+#include "confdefs.h"
+#include <assert.h>
+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 <<EOF
+#line 979 "configure"
+#include "confdefs.h"
+#include <assert.h>
+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 <<EOF
+#line 996 "configure"
+#include "confdefs.h"
+#include <assert.h>
+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 <<EOF
+#line 1034 "configure"
+#include "confdefs.h"
+
+int main() {
+} $ac_kw foo() {
+; return 0; }
+EOF
+if { (eval echo configure:1041: \"$ac_compile\") 1>&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 <<EOF
+#define inline $ac_cv_c_inline
+EOF
+ ;;
+esac
+
+
+# sizeof(char) is 1 by definition.
+echo $ac_n "checking size of short""... $ac_c" 1>&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 <<EOF
+#line 1075 "configure"
+#include "confdefs.h"
+#include "confdefs.h"
+#include <sys/types.h>
+
+
+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 <<EOF
+#define SIZEOF_SHORT $ac_cv_sizeof_short
+EOF
+
+
+echo $ac_n "checking size of int""... $ac_c" 1>&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 <<EOF
+#line 1114 "configure"
+#include "confdefs.h"
+#include "confdefs.h"
+#include <sys/types.h>
+
+
+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 <<EOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+EOF
+
+
+echo $ac_n "checking size of long""... $ac_c" 1>&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 <<EOF
+#line 1153 "configure"
+#include "confdefs.h"
+#include "confdefs.h"
+#include <sys/types.h>
+
+
+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 <<EOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+EOF
+
+
+
+echo $ac_n "checking execution character set""... $ac_c" 1>&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 <<EOF
+#line 1192 "configure"
+#include "confdefs.h"
+#if '\n' == 0x0A && ' ' == 0x20 && '0' == 0x30 \
+   && 'A' == 0x41 && 'a' == 0x61 && '!' == 0x21
+ASCII
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&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 <<EOF
+#line 1208 "configure"
+#include "confdefs.h"
+#if '\n' == 0x15 && ' ' == 0x40 && '0' == 0xF0 \
+   && 'A' == 0xC1 && 'a' == 0x81 && '!' == 0x5A
+EBCDIC
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&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 <<EOF
+#line 1305 "configure"
+#include "confdefs.h"
+#include <features.h>
+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 <<EOF
+#line 1516 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+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
+#line 1541 "configure"
+#include "confdefs.h"
+#include <string.h>
+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
+#line 1559 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+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 <<EOF
+#line 1580 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#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 <<EOF
+#line 1620 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+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 <<EOF
+#line 1655 "configure"
+#include "confdefs.h"
+#include <string.h>
+#include <strings.h>
+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 <<EOF
+#line 1689 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#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
+#line 1737 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+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 <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&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 <<EOF
+#line 1778 "configure"
+#include "confdefs.h"
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#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 <<EOF
+#line 1811 "configure"
+#include "confdefs.h"
+
+int main() {
+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)):
+  ; }
+; return 0; }
+EOF
+if { (eval echo configure:1821: \"$ac_compile\") 1>&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 <<EOF
+#define CHAR_BIT $gcc_cv_c_nbby
+EOF
+
+fi
+fi
+echo $ac_n "checking byte ordering""... $ac_c" 1>&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 <<EOF
+#line 1860 "configure"
+#include "confdefs.h"
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#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 <<EOF
+#line 1961 "configure"
+#include "confdefs.h"
+
+#define x(y) #y
+
+char *s = x(teststring);
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&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 <inttypes.h> only if it exists,
+# doesn't clash with <sys/types.h>, 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 <<EOF
+#line 1999 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <inttypes.h>
+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 <<EOF
+#line 2036 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* 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 <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&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 <<EOF
+#line 2090 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#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 <<EOF
+#line 2126 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* 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 <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&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 <sys/types.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <stdio.h>
+
+#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 <unistd.h>
+# 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 <sys/param.h>
+#   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 <<EOF
+#line 2436 "configure"
+#include "confdefs.h"
+#include "ct-mmap.inc"
+EOF
+if { (eval echo configure:2440: \"$ac_link\") 1>&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 <<EOF
+#line 2477 "configure"
+#include "confdefs.h"
+#define USE_MAP_ANON
+#include "ct-mmap.inc"
+EOF
+if { (eval echo configure:2482: \"$ac_link\") 1>&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 <<EOF
+#line 2525 "configure"
+#include "confdefs.h"
+
+/* 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+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 <<EOF
+#line 2598 "configure"
+#include "confdefs.h"
+#undef $ac_tr_decl
+#define $ac_tr_decl 1
+  
+#include "ansidecl.h"
+#include "system.h"
+
+int main() {
+#ifndef $ac_func
+char *(*pfn) = (char *(*)) $ac_func ;
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:2612: \"$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 <<EOF
+#define $ac_tr_decl 1
+EOF
+else
+  echo "$ac_t""no" 1>&6 ; cat >> confdefs.h <<EOF
+#define $ac_tr_decl 0
+EOF
+fi
+
+done
+if test x = y ; then
+  cat >> 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 <<EOF
+#line 2678 "configure"
+#include "confdefs.h"
+#undef $ac_tr_decl
+#define $ac_tr_decl 1
+  
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_SYS_TIMES_H
+#include <sys/times.h>
+#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 <<EOF
+#define $ac_tr_decl 1
+EOF
+else
+  echo "$ac_t""no" 1>&6 ; cat >> confdefs.h <<EOF
+#define $ac_tr_decl 0
+EOF
+fi
+
+done
+if test x = y ; then
+  cat >> 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 <<EOF
+#line 2736 "configure"
+#include "confdefs.h"
+
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_SYS_TIMES_H
+#include <sys/times.h>
+#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 <<EOF
+#line 2778 "configure"
+#include "confdefs.h"
+
+#include "ansidecl.h"
+#include "system.h"
+
+int main() {
+clock_t x;
+; return 0; }
+EOF
+if { (eval echo configure:2788: \"$ac_compile\") 1>&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 <<EOF
+#line 2818 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_DIRECT_H
+# include <direct.h>
+#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 <<EOF
+/* Generated automatically. */
+static const char configuration_arguments[] = "$gcc_config_arguments";
+static const char thread_model[] = "$thread_file";
+EOF
+
+# Internationalization
+PACKAGE=sdcc
+VERSION="$gcc_version"
+cat >> confdefs.h <<EOF
+#define PACKAGE "$PACKAGE"
+EOF
+
+cat >> confdefs.h <<EOF
+#define VERSION "$VERSION"
+EOF
+
+
+
+
+ALL_LINGUAS="sv"
+
+# Get an absolute path to the GCC top-level source directory
+holddir=`pwd`
+cd $srcdir
+topdir=`pwd`
+cd $holddir
+
+out_object_file=`basename $out_file .c`.o
+
+# Figure out what assembler we will be using.
+echo $ac_n "checking what assembler to use""... $ac_c" 1>&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 <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/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 <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > 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 <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"$all_outputs"}
+EOF
+cat >> $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 <<EOF
+  CONFIG_HEADERS="auto-host.h:config.in"
+EOF
+cat >> $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 <<CEOF' >> $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 <<EOF
+
+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}'
+
+EOF
+cat >> $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 (file)
index 0000000..0821743
--- /dev/null
@@ -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 <features.h>],[
+#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 <inttypes.h> only if it exists,
+# doesn't clash with <sys/types.h>, and declares intmax_t.
+AC_MSG_CHECKING(for inttypes.h)
+AC_CACHE_VAL(gcc_cv_header_inttypes_h,
+[AC_TRY_COMPILE(
+  [#include <sys/types.h>
+#include <inttypes.h>],
+  [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 <inttypes.h> 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 <sys/times.h>
+#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 <sys/times.h>
+#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 <sys/times.h> 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 <time.h> 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 <<EOF
+/* Generated automatically. */
+static const char configuration_arguments[] = "$gcc_config_arguments";
+static const char thread_model[] = "$thread_file";
+EOF
+changequote([,])dnl
+
+# Internationalization
+PACKAGE=sdcc
+VERSION="$gcc_version"
+AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE",
+       [Define to the name of the distribution.])
+AC_DEFINE_UNQUOTED(VERSION, "$VERSION",
+       [Define to the version of the distribution.])
+AC_SUBST(PACKAGE)
+AC_SUBST(VERSION)
+
+ALL_LINGUAS="sv"
+
+# Get an absolute path to the GCC top-level source directory
+holddir=`pwd`
+cd $srcdir
+topdir=`pwd`
+cd $holddir
+
+out_object_file=`basename $out_file .c`.o
+
+# Figure out what assembler we will be using.
+AC_MSG_CHECKING(what assembler to use)
+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
+changequote(,)dnl
+               gcc_cv_gas_version=`grep '^VERSION=[0-9]*\.[0-9]*' $f`
+changequote([,])dnl
+               if test x$gcc_cv_gas_version != x; then
+                       break
+               fi
+       done
+changequote(,)dnl
+       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]*\)"`
+changequote([,])dnl
+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
+  AC_MSG_RESULT("newly built gas")
+else
+  AC_MSG_RESULT($gcc_cv_as)
+fi
+
+# Figure out what nm we will be using.
+AC_MSG_CHECKING(what nm to use)
+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
+AC_MSG_RESULT($gcc_cv_nm)
+
+dnl Very limited version of automake's enable-maintainer-mode
+
+AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+  dnl maintainer-mode is disabled by default
+  AC_ARG_ENABLE(maintainer-mode,
+[  --enable-maintainer-mode
+                          enable make rules and dependencies not useful
+                          (and sometimes confusing) to the casual installer],
+      maintainer_mode=$enableval,
+      maintainer_mode=no)
+
+AC_MSG_RESULT($maintainer_mode)
+
+if test "$maintainer_mode" = "yes"; then
+  MAINT=''
+else
+  MAINT='#'
+fi
+AC_SUBST(MAINT)dnl
+
+# 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
+AC_SUBST(build_canonical)
+AC_SUBST(host_canonical)
+AC_SUBST(target_subdir)
+       
+# Nothing to do for FLOAT_H, float_format already handled.
+objdir=`pwd`
+AC_SUBST(objdir)
+
+# Substitute configuration variables
+AC_SUBST(all_stagestuff)
+AC_SUBST(build_exeext)
+AC_SUBST(build_install_headers_dir)
+AC_SUBST(build_xm_file_list)
+AC_SUBST(build_xm_file)
+AC_SUBST(build_xm_defines)
+AC_SUBST(check_languages)
+AC_SUBST(dep_host_xmake_file)
+AC_SUBST(dep_tmake_file)
+AC_SUBST(extra_c_flags)
+AC_SUBST(extra_headers_list)
+AC_SUBST(extra_objs)
+AC_SUBST(extra_parts)
+AC_SUBST(extra_passes)
+AC_SUBST(extra_programs)
+AC_SUBST(gcc_config_arguments)
+AC_SUBST(gcc_version)
+AC_SUBST(gcc_version_full)
+AC_SUBST(gcc_version_trigger)
+AC_SUBST(host_exeext)
+AC_SUBST(host_extra_gcc_objs)
+AC_SUBST(install)
+AC_SUBST(lang_tree_files)
+AC_SUBST(local_prefix)
+AC_SUBST(md_file)
+AC_SUBST(out_file)
+AC_SUBST(out_object_file)
+AC_SUBST(symbolic_link)
+AC_SUBST(thread_file)
+AC_SUBST(c_target_objs)
+
+AC_SUBST_FILE(target_overrides)
+AC_SUBST_FILE(host_overrides)
+AC_SUBST(cross_defines)
+AC_SUBST_FILE(cross_overrides)
+AC_SUBST_FILE(build_overrides)
+
+# Create the Makefile
+# and configure language subdirectories
+AC_OUTPUT($all_outputs,
+[
+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
+],
+[
+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 (file)
index 0000000..328971b
--- /dev/null
@@ -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 (file)
index 0000000..8ee6a1f
--- /dev/null
@@ -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 <file> 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 (file)
index 0000000..063489d
--- /dev/null
@@ -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: <error message here>
+
+          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 "<command line>:" 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 (file)
index 0000000..051551e
--- /dev/null
@@ -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;
+}
+\f
+/* 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 (file)
index 0000000..137882b
--- /dev/null
@@ -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 <sys/mman.h>
+# 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 <sys/types.h> 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 (file)
index 0000000..9e15ab4
--- /dev/null
@@ -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 (file)
index 0000000..56d9068
--- /dev/null
@@ -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 (file)
index 0000000..0d3d3a0
--- /dev/null
@@ -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 <file>           Include the contents of <file> before other files\n\
+  -imacros <file>           Accept definition of macros in <file>\n\
+  -iprefix <path>           Specify <path> as a prefix for next two options\n\
+  -iwithprefix <dir>        Add <dir> to the end of the system include path\n\
+  -iwithprefixbefore <dir>  Add <dir> to the end of the main include path\n\
+  -isystem <dir>            Add <dir> to the start of the system include path\n\
+"), stdout);
+  fputs (_("\
+  -idirafter <dir>          Add <dir> to the end of the system include path\n\
+  -I <dir>                  Add <dir> 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 <file>                 Put output into <file>\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=<std name>           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 <file>                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 <target>              Add a MAKE-quoted target\n\
+  -MT <target>              Add an unquoted target\n\
+"), stdout);
+  fputs (_("\
+  -D<macro>                 Define a <macro> with string '1' as its value\n\
+  -D<macro>=<val>           Define a <macro> with <val> as its value\n\
+  -A<question> (<answer>)   Assert the <answer> to <question>\n\
+  -A-<question> (<answer>)  Disable the <answer> to <question>\n\
+  -U<macro>                 Undefine <macro> \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=<number>        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 (file)
index 0000000..7424827
--- /dev/null
@@ -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 <locale.h>
+#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 (file)
index 0000000..cb49310
--- /dev/null
@@ -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
+     <iso646.h> 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 <FILENAME>", 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 = _("<builtin>");
+      else if (type == BUF_CL_OPTION)
+       filename = _("<command line>");
+      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 = _("<stdin>");
+  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 (file)
index 0000000..c05b5e2
--- /dev/null
@@ -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 <sys/types.h>
+#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,          "<?")   /* extension */ \
+  OP(CPP_MAX,          ">?")                   \
+\
+  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,       "<?=")  /* extension */ \
+  OP(CPP_MAX_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)   /* <stdio.h> 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 (file)
index 0000000..e630850
--- /dev/null
@@ -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 _("<command line>") 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 (&macro1->expansion[i], &macro2->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 = &macro->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 **) &macro->params);
+      dest = &macro->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 = &macro->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 **) &macro->expansion);
+      token = &macro->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 = &macro->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 = &macro->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 (file)
index 0000000..4d33e22
--- /dev/null
@@ -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 '# <directive name>': 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 (file)
index 0000000..77868f8
--- /dev/null
@@ -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 (file)
index 0000000..5b08fde
--- /dev/null
@@ -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 (file)
index 0000000..b624caf
--- /dev/null
@@ -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 (file)
index 0000000..761daf3
--- /dev/null
@@ -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 (file)
index 0000000..56c075e
--- /dev/null
@@ -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 <locale.h>
+#endif
+
+#ifndef HAVE_SETLOCALE
+# define setlocale(category, locale) (locale)
+#endif
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+  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 (file)
index 0000000..0e8b492
--- /dev/null
@@ -0,0 +1 @@
+/* nada */
diff --git a/support/cpp2/libiberty/lbasename.c b/support/cpp2/libiberty/lbasename.c
new file mode 100644 (file)
index 0000000..7f87049
--- /dev/null
@@ -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 (file)
index 0000000..0d4a4c8
--- /dev/null
@@ -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 <config.h>
+#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 <stdio.h>             /* Random thing to get __GNU_LIBRARY__.  */
+#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
+#include <gnu-versions.h>
+#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 <stdlib.h>
+#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
+
+\f
+/* 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;
+}
+\f
+/* 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 ();
+}
+\f
+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;
+}
+\f
+/* Define the error handler.  */
+#ifndef _
+# ifdef HAVE_LIBINTL_H
+#  include <libintl.h>
+#  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);
+}
+\f
+#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 (file)
index 0000000..d86d9f2
--- /dev/null
@@ -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
+\f
+/* 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 <stddef.h>'s symbols.  Otherwise, if <stddef.h> 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 <stddef.h>
+#  define PTR_INT_TYPE ptrdiff_t
+# else
+#  define PTR_INT_TYPE long
+# endif
+#endif
+
+#if defined _LIBC || defined HAVE_STRING_H
+# include <string.h>
+# 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
+\f
+#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;
+\f
+/* 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)
+\f
+#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); })
+\f
+#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 (file)
index 0000000..0c2be3e
--- /dev/null
@@ -0,0 +1,163 @@
+/* <ctype.h> replacement macros.
+
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   Contributed by Zack Weinberg <zackw@stanford.edu>.
+
+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 <ctype.h>
+   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 <safe-ctype.h>
+#include <stdio.h>  /* 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 (file)
index 0000000..ccacda5
--- /dev/null
@@ -0,0 +1,100 @@
+/* <ctype.h> replacement macros.
+
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   Contributed by Zack Weinberg <zackw@stanford.edu>.
+
+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 <ctype.h>
+   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 (file)
index 0000000..a712395
--- /dev/null
@@ -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 <stdlib.h>
+#endif
+
+#include <stdio.h>
+
+#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 (file)
index 0000000..37e9a35
--- /dev/null
@@ -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 <ansidecl.h>
+
+/* 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 (file)
index 0000000..f5f7bec
--- /dev/null
@@ -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 <locale.h>
+
+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 (file)
index 0000000..ab58cbb
--- /dev/null
@@ -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 (file)
index 0000000..70c78f5
--- /dev/null
@@ -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 (file)
index 0000000..fa79b86
--- /dev/null
@@ -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 (file)
index 0000000..e69de29
diff --git a/support/cpp2/output.h b/support/cpp2/output.h
new file mode 100644 (file)
index 0000000..c8fa63c
--- /dev/null
@@ -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 (file)
index 0000000..bf421ba
--- /dev/null
@@ -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\<KEY>
+
+      if found, that value will be used. <KEY> 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 <windows.h>
+#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, &reg_key);
+
+      if (res == ERROR_SUCCESS)
+       res = RegOpenKeyExA (reg_key, "Free Software Foundation", 0,
+                            KEY_READ, &reg_key);
+
+      if (res == ERROR_SUCCESS)
+       res = RegOpenKeyExA (reg_key, WIN32_REGISTRY_KEY, 0,
+                            KEY_READ, &reg_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 (file)
index 0000000..03c0d19
--- /dev/null
@@ -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 (file)
index 0000000..dd680dc
--- /dev/null
@@ -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 (file)
index 0000000..e69de29
diff --git a/support/cpp2/splay-tree.c b/support/cpp2/splay-tree.c
new file mode 100644 (file)
index 0000000..a712395
--- /dev/null
@@ -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 <stdlib.h>
+#endif
+
+#include <stdio.h>
+
+#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 (file)
index 0000000..37e9a35
--- /dev/null
@@ -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 <ansidecl.h>
+
+/* 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 (file)
index 0000000..61ce1e9
--- /dev/null
@@ -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 (file)
index 0000000..8486185
--- /dev/null
@@ -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 "<URL:http://www.gnu.org/software/gcc/bugs.html>"
+
+#include "ansidecl.h"
+
+/* We must include stdarg.h/varargs.h before stdio.h. */
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#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 <stddef.h>
+#endif
+
+#include <stdio.h>
+
+#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 <ctype.h>.
+   The last straw is that it varies with the locale.  Use libiberty's
+   replacement instead.  */
+#include <safe-ctype.h>
+
+/* Define a default escape character; it's different for EBCDIC.  */
+#ifndef TARGET_ESC
+#define TARGET_ESC 033
+#endif
+
+#include <sys/types.h>
+
+#include <errno.h>
+
+#if !defined (errno) && defined (HAVE_DECL_ERRNO) && !HAVE_DECL_ERRNO
+extern int errno;
+#endif
+
+#ifdef STRING_WITH_STRINGS
+# include <string.h>
+# include <strings.h>
+#else
+# ifdef HAVE_STRING_H
+#  include <string.h>
+# else
+#  ifdef HAVE_STRINGS_H
+#   include <strings.h>
+#  endif
+# endif
+#endif
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#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 <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#if HAVE_LIMITS_H
+# include <limits.h>
+#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 <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  ifdef HAVE_TIME_H
+#   include <time.h>
+#  endif
+# endif
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#else
+# ifdef HAVE_SYS_FILE_H
+#  include <sys/file.h>
+# 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 <sys/wait.h>
+#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 <malloc.h>
+#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 <sys/stat.h>
+#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 (file)
index 0000000..24bc287
--- /dev/null
@@ -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 (file)
index 0000000..9941649
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef GCC_VERSION_H
+#define GCC_VERSION_H
+extern const char *const version_string;
+#endif /* ! GCC_VERSION_H */