summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog38
-rw-r--r--gcc/Makefile.in67
-rw-r--r--gcc/aclocal.m436
-rw-r--r--gcc/c-ppoutput.c2
-rw-r--r--gcc/configure.ac18
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/Make-lang.in4
-rw-r--r--gcc/cppcharset.c1411
-rw-r--r--gcc/cpperror.c183
-rw-r--r--gcc/cppexp.c1540
-rw-r--r--gcc/cppfiles.c1565
-rw-r--r--gcc/cpphash.c118
-rw-r--r--gcc/cpphash.h651
-rw-r--r--gcc/cppinit.c627
-rw-r--r--gcc/cpplex.c1544
-rw-r--r--gcc/cpplib.c1987
-rw-r--r--gcc/cpplib.h773
-rw-r--r--gcc/cppmacro.c1729
-rw-r--r--gcc/cpppch.c724
-rw-r--r--gcc/cpptrad.c1110
-rw-r--r--gcc/cppucnid.h336
-rw-r--r--gcc/cppucnid.pl130
-rw-r--r--gcc/cppucnid.tab239
-rw-r--r--gcc/hashtable.c310
-rw-r--r--gcc/hashtable.h81
-rw-r--r--gcc/java/ChangeLog4
-rw-r--r--gcc/java/Make-lang.in10
-rw-r--r--gcc/line-map.c345
-rw-r--r--gcc/line-map.h182
-rw-r--r--gcc/mkdeps.c345
-rw-r--r--gcc/mkdeps.h72
-rw-r--r--gcc/stringpool.c4
-rw-r--r--gcc/system.h10
-rw-r--r--gcc/tree.h2
34 files changed, 81 insertions, 16120 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c1d6b2b7702..7d5ddfbc8fc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,41 @@
+2004-05-23 Paolo Bonzini <bonzini@gnu.org>
+
+ Move libcpp to the toplevel.
+ * Makefile.in: Remove references to libcpp files,
+ use CPPLIBS instead of libcpp.a. Define SYMTAB_H
+ and change hashtable.h to that.
+ * aclocal.m4 (gcc_AC_HEADER_STDBOOL,
+ gcc_AC_HEADER_STRING, gcc_AC_C__BOOL): Remove.
+ * configure.ac (gcc_AC_C__BOOL, HAVE_UCHAR): Remove tests.
+ * configure: Regenerate.
+ * config.in: Regenerate.
+ * c-ppoutput.c: Include ../libcpp/internal.h instead of cpphash.h.
+ * cppcharset.c: Removed.
+ * cpperror.c: Removed.
+ * cppexp.c: Removed.
+ * cppfiles.c: Removed.
+ * cpphash.c: Removed.
+ * cpphash.h: Removed.
+ * cppinit.c: Removed.
+ * cpplex.c: Removed.
+ * cpplib.c: Removed.
+ * cpplib.h: Removed.
+ * cppmacro.c: Removed.
+ * cpppch.c: Removed.
+ * cpptrad.c: Removed.
+ * cppucnid.h: Removed.
+ * cppucnid.pl: Removed.
+ * cppucnid.tab: Removed.
+ * hashtable.c: Removed.
+ * hashtable.h: Removed.
+ * line-map.c: Removed.
+ * line-map.h: Removed.
+ * mkdeps.c: Removed.
+ * mkdeps.h: Removed.
+ * stringpool.h: Include symtab.h instead of hashtable.h.
+ * tree.h: Include symtab.h instead of hashtable.h.
+ * system.h (O_NONBLOCK, O_NOCTTY): Do not define.
+
2004-05-23 Paolo Bonzini <bonzini@gnu.org>
* gcc.c (struct prefix_list): Add forward declaration.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index de890c2c586..c39920d04da 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -284,6 +284,10 @@ GMPINC = @GMPINC@
BANSHEELIB = @BANSHEELIB@
BANSHEEINC = @BANSHEEINC@
+
+CPPLIBS = ../libcpp/libcpp.a
+CPPINC = -I$(srcdir)/../libcpp/include
+
# Substitution type for target's getgroups 2nd arg.
TARGET_GETGROUPS_T = @TARGET_GETGROUPS_T@
@@ -699,7 +703,9 @@ C_COMMON_H = c-common.h $(SPLAY_TREE_H) $(CPPLIB_H)
C_TREE_H = c-tree.h $(C_COMMON_H)
SYSTEM_H = system.h hwint.h $(srcdir)/../include/libiberty.h
PREDICT_H = predict.h predict.def
-CPPLIB_H = cpplib.h line-map.h
+CPPLIB_H = $(srcdir)/../libcpp/include/cpplib.h \
+ $(srcdir)/../libcpp/include/line-map.h
+SYMTAB_H = $(srcdir)/../libcpp/include/symtab.h
TREE_DUMP_H = tree-dump.h $(SPLAY_TREE_H)
TREE_GIMPLE_H = tree-gimple.h tree-iterator.h
TREE_FLOW_H = tree-flow.h tree-flow-inline.h tree-ssa-operands.h \
@@ -731,7 +737,7 @@ LIBIBERTY = ../libiberty/libiberty.a
BUILD_LIBIBERTY = @FORBUILD@/libiberty/libiberty.a
# Dependencies on the intl and portability libraries.
-LIBDEPS= $(LIBIBERTY) $(LIBINTL_DEP) $(LIBICONV_DEP) libcpp.a $(BANSHEELIB)
+LIBDEPS= $(LIBIBERTY) $(LIBINTL_DEP) $(LIBICONV_DEP) $(CPPLIB) $(BANSHEELIB)
# Likewise, for use in the tools that must run on this machine
# even if we are cross-building GCC.
@@ -739,7 +745,7 @@ BUILD_LIBDEPS= $(BUILD_LIBIBERTY)
# How to link with both our special library facilities
# and the system's installed libraries.
-LIBS = @LIBS@ libcpp.a $(LIBIBERTY) $(LIBINTL) $(LIBICONV) $(BANSHEELIB)
+LIBS = @LIBS@ $(LIBIBERTY) $(LIBINTL) $(LIBICONV) $(CPPLIB) $(BANSHEELIB)
# Any system libraries needed just for GNAT.
SYSLIBS = @GNAT_LIBEXC@
@@ -769,7 +775,7 @@ BUILD_VARRAY = $(BUILD_PREFIX)varray.o
# libintl.h will be found in ../intl if we are using the included libintl.
INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
-I$(srcdir)/../include @INCINTL@ \
- $(BANSHEEINC) $(GMPINC)
+ $(CPPINC) $(BANSHEEINC) $(GMPINC)
.c.o:
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
@@ -898,14 +904,14 @@ OBJS-common = \
rtl-profile.o tree-profile.o
OBJS-md = $(out_object_file)
-OBJS-archive = $(EXTRA_OBJS) $(host_hook_obj) hashtable.o tree-inline.o \
+OBJS-archive = $(EXTRA_OBJS) $(host_hook_obj) tree-inline.o \
cgraph.o cgraphunit.o tree-nomudflap.o
OBJS = $(OBJS-common) $(out_object_file) $(OBJS-archive)
OBJS-onestep = libbackend.o $(OBJS-archive)
-BACKEND = main.o @TREEBROWSER@ libbackend.a
+BACKEND = main.o @TREEBROWSER@ libbackend.a $(CPPLIBS)
# Files to be copied away after each stage in building.
STAGESTUFF = *$(objext) insn-flags.h insn-config.h insn-codes.h \
@@ -927,7 +933,7 @@ STAGESTUFF = *$(objext) insn-flags.h insn-config.h insn-codes.h \
protoize$(exeext) unprotoize$(exeext) \
$(SPECS) collect2$(exeext) \
gcov-iov$(build_exeext) gcov$(exeext) gcov-dump$(exeext) \
- *.[0-9][0-9].* *.[si] libcpp.a libbackend.a libgcc.mk \
+ *.[0-9][0-9].* *.[si] libbackend.a libgcc.mk \
$(LANG_STAGESTUFF)
# Defined in libgcc2.c, included only in the static library.
@@ -1121,7 +1127,7 @@ rest.cross: $(LIBGCC) specs
# This is used only if the user explicitly asks for it.
compilations: $(BACKEND)
-# Like libcpp.a, this archive is strictly for the host.
+# This archive is strictly for the host.
libbackend.a: $(OBJS@onestep@)
-rm -rf libbackend.a
$(AR) $(AR_FLAGS) libbackend.a $(OBJS@onestep@)
@@ -1351,7 +1357,7 @@ c-lex.o : c-lex.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
c-pragma.h input.h intl.h flags.h toplev.h output.h \
$(CPPLIB_H) $(EXPR_H) $(TM_P_H)
c-ppoutput.o : c-ppoutput.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(C_COMMON_H) $(TREE_H) $(CPPLIB_H) cpphash.h $(TM_P_H) c-pragma.h
+ $(C_COMMON_H) $(TREE_H) $(CPPLIB_H) $(srcdir)/../libcpp/internal.h $(TM_P_H) c-pragma.h
c-objc-common.o : c-objc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(C_TREE_H) $(RTL_H) insn-config.h $(INTEGRATE_H) $(EXPR_H) $(C_TREE_H) \
flags.h toplev.h tree-inline.h $(DIAGNOSTIC_H) $(VARRAY_H) \
@@ -2258,10 +2264,11 @@ s-preds: genpreds$(build_exeext)
$(SHELL) $(srcdir)/../move-if-change tmp-preds.h tm-preds.h
$(STAMP) s-preds
-GTFILES = $(srcdir)/input.h $(srcdir)/coretypes.h $(srcdir)/cpplib.h \
- $(host_xm_file_list) $(tm_file_list) $(HASHTAB_H) $(SPLAY_TREE_H) \
- $(srcdir)/bitmap.h $(srcdir)/coverage.c $(srcdir)/function.h $(srcdir)/rtl.h \
- $(srcdir)/optabs.h $(srcdir)/tree.h $(srcdir)/libfuncs.h $(srcdir)/hashtable.h \
+GTFILES = $(srcdir)/input.h $(srcdir)/coretypes.h \
+ $(srcdir)/../libcpp/include/cpplib.h $(host_xm_file_list) \
+ $(tm_file_list) $(HASHTAB_H) $(SPLAY_TREE_H) $(srcdir)/bitmap.h \
+ $(srcdir)/coverage.c $(srcdir)/function.h $(srcdir)/rtl.h \
+ $(srcdir)/optabs.h $(srcdir)/tree.h $(srcdir)/libfuncs.h $(SYMTAB_H) \
$(srcdir)/real.h $(srcdir)/varray.h $(srcdir)/insn-addr.h $(srcdir)/hwint.h \
$(srcdir)/cselib.h $(srcdir)/basic-block.h $(srcdir)/cgraph.h \
$(srcdir)/c-common.h $(srcdir)/c-tree.h $(srcdir)/reload.h \
@@ -2550,42 +2557,12 @@ PREPROCESSOR_DEFINES = \
-DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
@TARGET_SYSTEM_ROOT_DEFINE@
-LIBCPP_OBJS = cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o cpptrad.o \
- cpphash.o cpperror.o cppinit.o cppcharset.o \
- hashtable.o line-map.o mkdeps.o cpppch.o
-
-LIBCPP_DEPS = $(CPPLIB_H) cpphash.h line-map.h hashtable.h intl.h \
- $(OBSTACK_H) $(CONFIG_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
-
-cppcharset.o: cppcharset.c $(LIBCPP_DEPS) cppucnid.h
-cpperror.o: cpperror.c $(LIBCPP_DEPS)
-cppexp.o: cppexp.c $(LIBCPP_DEPS)
-cpplex.o: cpplex.c $(LIBCPP_DEPS)
-cppmacro.o: cppmacro.c $(LIBCPP_DEPS)
-cpplib.o: cpplib.c $(LIBCPP_DEPS)
-cpphash.o: cpphash.c $(LIBCPP_DEPS)
-cpptrad.o: cpptrad.c $(LIBCPP_DEPS)
-cppfiles.o: cppfiles.c $(LIBCPP_DEPS) $(HASHTAB_H) $(MD5_H) mkdeps.h
-cppinit.o: cppinit.c $(LIBCPP_DEPS) mkdeps.h
-cpppch.o: cpppch.c $(LIBCPP_DEPS) mkdeps.h
-
cppdefault.o: cppdefault.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
cppdefault.h Makefile
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(PREPROCESSOR_DEFINES) \
-c $(srcdir)/cppdefault.c $(OUTPUT_OPTION)
-mkdeps.o: mkdeps.c $(CONFIG_H) $(SYSTEM_H) mkdeps.h
-hashtable.o: hashtable.c hashtable.h $(CONFIG_H) $(SYSTEM_H) $(OBSTACK_H)
-line-map.o: line-map.c line-map.h intl.h $(CONFIG_H) $(SYSTEM_H)
-
# Note for the stamp targets, we run the program `true' instead of
# having an empty command (nothing following the semicolon).
@@ -2799,7 +2776,7 @@ xsys-protos.h: $(GCC_PASSES) $(srcdir)/sys-protos.h deduced.h gen-protos$(build_
# This is nominally a 'build' program, but it's run only when host==build,
# so we can (indeed, must) use $(LIBDEPS) and $(LIBS).
fix-header$(build_exeext): fix-header.o scan-decls.o scan.o xsys-protos.h \
- c-incpath.o cppdefault.o prefix.o $(LIBDEPS) libcpp.a
+ c-incpath.o cppdefault.o prefix.o $(LIBDEPS)
$(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ fix-header.o \
c-incpath.o cppdefault.o scan-decls.o prefix.o scan.o $(LIBS)
@@ -3537,7 +3514,7 @@ TAGS: lang.tags
# ------------------------------------------------------
# A list of files to be destroyed during "lean" builds.
-VOL_FILES=`echo $(BACKEND) $(OBJS) $(C_OBJS) $(LIBCPP_OBJS) *.c *.h gen*`
+VOL_FILES=`echo $(BACKEND) $(OBJS) $(C_OBJS) *.c *.h gen*`
# Flags to pass to stage2 and later recursive makes. Note that the
# WARN_CFLAGS setting can't be to the expansion of GCC_WARN_CFLAGS in
diff --git a/gcc/aclocal.m4 b/gcc/aclocal.m4
index 4ed2f083254..53dfd878ba8 100644
--- a/gcc/aclocal.m4
+++ b/gcc/aclocal.m4
@@ -3,30 +3,6 @@ sinclude(../config/accross.m4)
sinclude(../config/gettext.m4)
sinclude(../config/progtest.m4)
-dnl See if stdbool.h properly defines bool and true/false.
-AC_DEFUN([gcc_AC_HEADER_STDBOOL],
-[AC_CACHE_CHECK([for working stdbool.h],
- ac_cv_header_stdbool_h,
-[AC_TRY_COMPILE([#include <stdbool.h>],
-[bool foo = false;],
-ac_cv_header_stdbool_h=yes, ac_cv_header_stdbool_h=no)])
-if test $ac_cv_header_stdbool_h = yes; then
- AC_DEFINE(HAVE_STDBOOL_H, 1,
- [Define if you have a working <stdbool.h> header file.])
-fi
-])
-
-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
@@ -198,18 +174,6 @@ fi
AC_SUBST(LN)dnl
])
-dnl Check whether _Bool is built-in.
-AC_DEFUN([gcc_AC_C__BOOL],
-[AC_CACHE_CHECK(for built-in _Bool, gcc_cv_c__bool,
-[AC_TRY_COMPILE(,
-[_Bool foo;],
-gcc_cv_c__bool=yes, gcc_cv_c__bool=no)
-])
-if test $gcc_cv_c__bool = yes; then
- AC_DEFINE(HAVE__BOOL, 1, [Define if the \`_Bool' type is built-in.])
-fi
-])
-
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],
diff --git a/gcc/c-ppoutput.c b/gcc/c-ppoutput.c
index 4d83b5d01e2..ef6d8e6d4f3 100644
--- a/gcc/c-ppoutput.c
+++ b/gcc/c-ppoutput.c
@@ -22,7 +22,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "coretypes.h"
#include "tm.h"
#include "cpplib.h"
-#include "cpphash.h"
+#include "../libcpp/internal.h"
#include "tree.h"
#include "c-common.h" /* For flags. */
#include "c-pragma.h" /* For parse_in. */
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 33a9f0bc0a0..45e5da59b75 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -278,7 +278,6 @@ AC_PROG_CPP
AC_C_INLINE
gcc_AC_C_LONG_LONG
-gcc_AC_C__BOOL
# sizeof(char) is 1 by definition.
AC_COMPILE_CHECK_SIZEOF(void *)
@@ -806,8 +805,8 @@ AC_PROG_CPP_WERROR
AC_HEADER_STDC
AC_HEADER_TIME
-gcc_AC_HEADER_STDBOOL
-gcc_AC_HEADER_STRING
+ACX_HEADER_STDBOOL
+ACX_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/mman.h \
@@ -1039,19 +1038,6 @@ if test $gcc_cv_type_clock_t = yes; then
[Define if <time.h> defines clock_t.])
fi
-AC_CACHE_CHECK(for uchar, gcc_cv_type_uchar,
-[AC_TRY_COMPILE([
-#include "ansidecl.h"
-#include "system.h"
-],
-[if ((uchar *)0) return 0;
- if (sizeof(uchar)) return 0;],
-ac_cv_type_uchar=yes, ac_cv_type_uchar=no)])
-if test $ac_cv_type_uchar = yes; then
- AC_DEFINE(HAVE_UCHAR, 1,
- [Define if <sys/types.h> defines \`uchar'.])
-fi
-
# Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
CFLAGS="$saved_CFLAGS"
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8e5e03adcf9..34db8d64712 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,7 @@
+2004-05-23 Paolo Bonzini <bonzini@gnu.org>
+
+ * Make-lang.in: No need to specify $(LIBCPP).
+
2004-05-23 Mark Mitchell <mark@codesourcery.com>
PR c++/15044
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 12decae82f1..a928c389213 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -88,9 +88,9 @@ CXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
cp-warn = $(STRICT_WARN) $(WERROR)
cc1plus$(exeext): $(CXX_OBJS) $(CXX_C_OBJS) $(BACKEND) \
- libcpp.a $(LIBDEPS)
+ $(LIBDEPS)
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
- $(CXX_OBJS) $(CXX_C_OBJS) $(BACKEND) libcpp.a $(LIBS)
+ $(CXX_OBJS) $(CXX_C_OBJS) $(BACKEND) $(LIBS)
# Special build rules.
$(srcdir)/cp/cfns.h: $(srcdir)/cp/cfns.gperf
diff --git a/gcc/cppcharset.c b/gcc/cppcharset.c
deleted file mode 100644
index b46f47a1fe0..00000000000
--- a/gcc/cppcharset.c
+++ /dev/null
@@ -1,1411 +0,0 @@
-/* CPP Library - charsets
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
- Free Software Foundation, Inc.
-
- Broken out of c-lex.c Apr 2003, adding valid C99 UCN ranges.
-
-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 "cppucnid.h"
-
-/* Character set handling for C-family languages.
-
- Terminological note: In what follows, "charset" or "character set"
- will be taken to mean both an abstract set of characters and an
- encoding for that set.
-
- The C99 standard discusses two character sets: source and execution.
- The source character set is used for internal processing in translation
- phases 1 through 4; the execution character set is used thereafter.
- Both are required by 5.2.1.2p1 to be multibyte encodings, not wide
- character encodings (see 3.7.2, 3.7.3 for the standardese meanings
- of these terms). Furthermore, the "basic character set" (listed in
- 5.2.1p3) is to be encoded in each with values one byte wide, and is
- to appear in the initial shift state.
-
- It is not explicitly mentioned, but there is also a "wide execution
- character set" used to encode wide character constants and wide
- string literals; this is supposed to be the result of applying the
- standard library function mbstowcs() to an equivalent narrow string
- (6.4.5p5). However, the behavior of hexadecimal and octal
- \-escapes is at odds with this; they are supposed to be translated
- directly to wchar_t values (6.4.4.4p5,6).
-
- The source character set is not necessarily the character set used
- to encode physical source files on disk; translation phase 1 converts
- from whatever that encoding is to the source character set.
-
- The presence of universal character names in C99 (6.4.3 et seq.)
- forces the source character set to be isomorphic to ISO 10646,
- that is, Unicode. There is no such constraint on the execution
- character set; note also that the conversion from source to
- execution character set does not occur for identifiers (5.1.1.2p1#5).
-
- For convenience of implementation, the source character set's
- encoding of the basic character set should be identical to the
- execution character set OF THE HOST SYSTEM's encoding of the basic
- character set, and it should not be a state-dependent encoding.
-
- cpplib uses UTF-8 or UTF-EBCDIC for the source character set,
- depending on whether the host is based on ASCII or EBCDIC (see
- respectively Unicode section 2.3/ISO10646 Amendment 2, and Unicode
- Technical Report #16). With limited exceptions, it relies on the
- system library's iconv() primitive to do charset conversion
- (specified in SUSv2). */
-
-#if !HAVE_ICONV
-/* Make certain that the uses of iconv(), iconv_open(), iconv_close()
- below, which are guarded only by if statements with compile-time
- constant conditions, do not cause link errors. */
-#define iconv_open(x, y) (errno = EINVAL, (iconv_t)-1)
-#define iconv(a,b,c,d,e) (errno = EINVAL, (size_t)-1)
-#define iconv_close(x) (void)0
-#define ICONV_CONST
-#endif
-
-#if HOST_CHARSET == HOST_CHARSET_ASCII
-#define SOURCE_CHARSET "UTF-8"
-#elif HOST_CHARSET == HOST_CHARSET_EBCDIC
-#define SOURCE_CHARSET "UTF-EBCDIC"
-#else
-#error "Unrecognized basic host character set"
-#endif
-
-#ifndef EILSEQ
-#define EILSEQ EINVAL
-#endif
-
-/* This structure is used for a resizable string buffer throughout. */
-/* Don't call it strbuf, as that conflicts with unistd.h on systems
- such as DYNIX/ptx where unistd.h includes stropts.h. */
-struct _cpp_strbuf
-{
- uchar *text;
- size_t asize;
- size_t len;
-};
-
-/* This is enough to hold any string that fits on a single 80-column
- line, even if iconv quadruples its size (e.g. conversion from
- ASCII to UTF-32) rounded up to a power of two. */
-#define OUTBUF_BLOCK_SIZE 256
-
-/* Conversions between UTF-8 and UTF-16/32 are implemented by custom
- logic. This is because a depressing number of systems lack iconv,
- or have have iconv libraries that do not do these conversions, so
- we need a fallback implementation for them. To ensure the fallback
- doesn't break due to neglect, it is used on all systems.
-
- UTF-32 encoding is nice and simple: a four-byte binary number,
- constrained to the range 00000000-7FFFFFFF to avoid questions of
- signedness. We do have to cope with big- and little-endian
- variants.
-
- UTF-16 encoding uses two-byte binary numbers, again in big- and
- little-endian variants, for all values in the 00000000-0000FFFF
- range. Values in the 00010000-0010FFFF range are encoded as pairs
- of two-byte numbers, called "surrogate pairs": given a number S in
- this range, it is mapped to a pair (H, L) as follows:
-
- H = (S - 0x10000) / 0x400 + 0xD800
- L = (S - 0x10000) % 0x400 + 0xDC00
-
- Two-byte values in the D800...DFFF range are ill-formed except as a
- component of a surrogate pair. Even if the encoding within a
- two-byte value is little-endian, the H member of the surrogate pair
- comes first.
-
- There is no way to encode values in the 00110000-7FFFFFFF range,
- which is not currently a problem as there are no assigned code
- points in that range; however, the author expects that it will
- eventually become necessary to abandon UTF-16 due to this
- limitation. Note also that, because of these pairs, UTF-16 does
- not meet the requirements of the C standard for a wide character
- encoding (see 3.7.3 and 6.4.4.4p11).
-
- UTF-8 encoding looks like this:
-
- value range encoded as
- 00000000-0000007F 0xxxxxxx
- 00000080-000007FF 110xxxxx 10xxxxxx
- 00000800-0000FFFF 1110xxxx 10xxxxxx 10xxxxxx
- 00010000-001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- 00200000-03FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
- 04000000-7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
-
- Values in the 0000D800 ... 0000DFFF range (surrogates) are invalid,
- which means that three-byte sequences ED xx yy, with A0 <= xx <= BF,
- never occur. Note also that any value that can be encoded by a
- given row of the table can also be encoded by all successive rows,
- but this is not done; only the shortest possible encoding for any
- given value is valid. For instance, the character 07C0 could be
- encoded as any of DF 80, E0 9F 80, F0 80 9F 80, F8 80 80 9F 80, or
- FC 80 80 80 9F 80. Only the first is valid.
-
- An implementation note: the transformation from UTF-16 to UTF-8, or
- vice versa, is easiest done by using UTF-32 as an intermediary. */
-
-/* Internal primitives which go from an UTF-8 byte stream to native-endian
- UTF-32 in a cppchar_t, or vice versa; this avoids an extra marshal/unmarshal
- operation in several places below. */
-static inline int
-one_utf8_to_cppchar (const uchar **inbufp, size_t *inbytesleftp,
- cppchar_t *cp)
-{
- static const uchar masks[6] = { 0x7F, 0x1F, 0x0F, 0x07, 0x02, 0x01 };
- static const uchar patns[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
-
- cppchar_t c;
- const uchar *inbuf = *inbufp;
- size_t nbytes, i;
-
- if (*inbytesleftp < 1)
- return EINVAL;
-
- c = *inbuf;
- if (c < 0x80)
- {
- *cp = c;
- *inbytesleftp -= 1;
- *inbufp += 1;
- return 0;
- }
-
- /* The number of leading 1-bits in the first byte indicates how many
- bytes follow. */
- for (nbytes = 2; nbytes < 7; nbytes++)
- if ((c & ~masks[nbytes-1]) == patns[nbytes-1])
- goto found;
- return EILSEQ;
- found:
-
- if (*inbytesleftp < nbytes)
- return EINVAL;
-
- c = (c & masks[nbytes-1]);
- inbuf++;
- for (i = 1; i < nbytes; i++)
- {
- cppchar_t n = *inbuf++;
- if ((n & 0xC0) != 0x80)
- return EILSEQ;
- c = ((c << 6) + (n & 0x3F));
- }
-
- /* Make sure the shortest possible encoding was used. */
- if (c <= 0x7F && nbytes > 1) return EILSEQ;
- if (c <= 0x7FF && nbytes > 2) return EILSEQ;
- if (c <= 0xFFFF && nbytes > 3) return EILSEQ;
- if (c <= 0x1FFFFF && nbytes > 4) return EILSEQ;
- if (c <= 0x3FFFFFF && nbytes > 5) return EILSEQ;
-
- /* Make sure the character is valid. */
- if (c > 0x7FFFFFFF || (c >= 0xD800 && c <= 0xDFFF)) return EILSEQ;
-
- *cp = c;
- *inbufp = inbuf;
- *inbytesleftp -= nbytes;
- return 0;
-}
-
-static inline int
-one_cppchar_to_utf8 (cppchar_t c, uchar **outbufp, size_t *outbytesleftp)
-{
- static const uchar masks[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
- static const uchar limits[6] = { 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
- size_t nbytes;
- uchar buf[6], *p = &buf[6];
- uchar *outbuf = *outbufp;
-
- nbytes = 1;
- if (c < 0x80)
- *--p = c;
- else
- {
- do
- {
- *--p = ((c & 0x3F) | 0x80);
- c >>= 6;
- nbytes++;
- }
- while (c >= 0x3F || (c & limits[nbytes-1]));
- *--p = (c | masks[nbytes-1]);
- }
-
- if (*outbytesleftp < nbytes)
- return E2BIG;
-
- while (p < &buf[6])
- *outbuf++ = *p++;
- *outbytesleftp -= nbytes;
- *outbufp = outbuf;
- return 0;
-}
-
-/* The following four functions transform one character between the two
- encodings named in the function name. All have the signature
- int (*)(iconv_t bigend, const uchar **inbufp, size_t *inbytesleftp,
- uchar **outbufp, size_t *outbytesleftp)
-
- BIGEND must have the value 0 or 1, coerced to (iconv_t); it is
- interpreted as a boolean indicating whether big-endian or
- little-endian encoding is to be used for the member of the pair
- that is not UTF-8.
-
- INBUFP, INBYTESLEFTP, OUTBUFP, OUTBYTESLEFTP work exactly as they
- do for iconv.
-
- The return value is either 0 for success, or an errno value for
- failure, which may be E2BIG (need more space), EILSEQ (ill-formed
- input sequence), ir EINVAL (incomplete input sequence). */
-
-static inline int
-one_utf8_to_utf32 (iconv_t bigend, const uchar **inbufp, size_t *inbytesleftp,
- uchar **outbufp, size_t *outbytesleftp)
-{
- uchar *outbuf;
- cppchar_t s = 0;
- int rval;
-
- /* Check for space first, since we know exactly how much we need. */
- if (*outbytesleftp < 4)
- return E2BIG;
-
- rval = one_utf8_to_cppchar (inbufp, inbytesleftp, &s);
- if (rval)
- return rval;
-
- outbuf = *outbufp;
- outbuf[bigend ? 3 : 0] = (s & 0x000000FF);
- outbuf[bigend ? 2 : 1] = (s & 0x0000FF00) >> 8;
- outbuf[bigend ? 1 : 2] = (s & 0x00FF0000) >> 16;
- outbuf[bigend ? 0 : 3] = (s & 0xFF000000) >> 24;
-
- *outbufp += 4;
- *outbytesleftp -= 4;
- return 0;
-}
-
-static inline int
-one_utf32_to_utf8 (iconv_t bigend, const uchar **inbufp, size_t *inbytesleftp,
- uchar **outbufp, size_t *outbytesleftp)
-{
- cppchar_t s;
- int rval;
- const uchar *inbuf;
-
- if (*inbytesleftp < 4)
- return EINVAL;
-
- inbuf = *inbufp;
-
- s = inbuf[bigend ? 0 : 3] << 24;
- s += inbuf[bigend ? 1 : 2] << 16;
- s += inbuf[bigend ? 2 : 1] << 8;
- s += inbuf[bigend ? 3 : 0];
-
- if (s >= 0x7FFFFFFF || (s >= 0xD800 && s <= 0xDFFF))
- return EILSEQ;
-
- rval = one_cppchar_to_utf8 (s, outbufp, outbytesleftp);
- if (rval)
- return rval;
-
- *inbufp += 4;
- *inbytesleftp -= 4;
- return 0;
-}
-
-static inline int
-one_utf8_to_utf16 (iconv_t bigend, const uchar **inbufp, size_t *inbytesleftp,
- uchar **outbufp, size_t *outbytesleftp)
-{
- int rval;
- cppchar_t s = 0;
- const uchar *save_inbuf = *inbufp;
- size_t save_inbytesleft = *inbytesleftp;
- uchar *outbuf = *outbufp;
-
- rval = one_utf8_to_cppchar (inbufp, inbytesleftp, &s);
- if (rval)
- return rval;
-
- if (s > 0x0010FFFF)
- {
- *inbufp = save_inbuf;
- *inbytesleftp = save_inbytesleft;
- return EILSEQ;
- }
-
- if (s < 0xFFFF)
- {
- if (*outbytesleftp < 2)
- {
- *inbufp = save_inbuf;
- *inbytesleftp = save_inbytesleft;
- return E2BIG;
- }
- outbuf[bigend ? 1 : 0] = (s & 0x00FF);
- outbuf[bigend ? 0 : 1] = (s & 0xFF00) >> 8;
-
- *outbufp += 2;
- *outbytesleftp -= 2;
- return 0;
- }
- else
- {
- cppchar_t hi, lo;
-
- if (*outbytesleftp < 4)
- {
- *inbufp = save_inbuf;
- *inbytesleftp = save_inbytesleft;
- return E2BIG;
- }
-
- hi = (s - 0x10000) / 0x400 + 0xD800;
- lo = (s - 0x10000) % 0x400 + 0xDC00;
-
- /* Even if we are little-endian, put the high surrogate first.
- ??? Matches practice? */
- outbuf[bigend ? 1 : 0] = (hi & 0x00FF);
- outbuf[bigend ? 0 : 1] = (hi & 0xFF00) >> 8;
- outbuf[bigend ? 3 : 2] = (lo & 0x00FF);
- outbuf[bigend ? 2 : 3] = (lo & 0xFF00) >> 8;
-
- *outbufp += 4;
- *outbytesleftp -= 4;
- return 0;
- }
-}
-
-static inline int
-one_utf16_to_utf8 (iconv_t bigend, const uchar **inbufp, size_t *inbytesleftp,
- uchar **outbufp, size_t *outbytesleftp)
-{
- cppchar_t s;
- const uchar *inbuf = *inbufp;
- int rval;
-
- if (*inbytesleftp < 2)
- return EINVAL;
- s = inbuf[bigend ? 0 : 1] << 8;
- s += inbuf[bigend ? 1 : 0];
-
- /* Low surrogate without immediately preceding high surrogate is invalid. */
- if (s >= 0xDC00 && s <= 0xDFFF)
- return EILSEQ;
- /* High surrogate must have a following low surrogate. */
- else if (s >= 0xD800 && s <= 0xDBFF)
- {
- cppchar_t hi = s, lo;
- if (*inbytesleftp < 4)
- return EINVAL;
-
- lo = inbuf[bigend ? 2 : 3] << 8;
- lo += inbuf[bigend ? 3 : 2];
-
- if (lo < 0xDC00 || lo > 0xDFFF)
- return EILSEQ;
-
- s = (hi - 0xD800) * 0x400 + (lo - 0xDC00) + 0x10000;
- }
-
- rval = one_cppchar_to_utf8 (s, outbufp, outbytesleftp);
- if (rval)
- return rval;
-
- /* Success - update the input pointers (one_cppchar_to_utf8 has done
- the output pointers for us). */
- if (s <= 0xFFFF)
- {
- *inbufp += 2;
- *inbytesleftp -= 2;
- }
- else
- {
- *inbufp += 4;
- *inbytesleftp -= 4;
- }
- return 0;
-}
-
-/* Helper routine for the next few functions. The 'const' on
- one_conversion means that we promise not to modify what function is
- pointed to, which lets the inliner see through it. */
-
-static inline bool
-conversion_loop (int (*const one_conversion)(iconv_t, const uchar **, size_t *,
- uchar **, size_t *),
- iconv_t cd, const uchar *from, size_t flen, struct _cpp_strbuf *to)
-{
- const uchar *inbuf;
- uchar *outbuf;
- size_t inbytesleft, outbytesleft;
- int rval;
-
- inbuf = from;
- inbytesleft = flen;
- outbuf = to->text + to->len;
- outbytesleft = to->asize - to->len;
-
- for (;;)
- {
- do
- rval = one_conversion (cd, &inbuf, &inbytesleft,
- &outbuf, &outbytesleft);
- while (inbytesleft && !rval);
-
- if (__builtin_expect (inbytesleft == 0, 1))
- {
- to->len = to->asize - outbytesleft;
- return true;
- }
- if (rval != E2BIG)
- {
- errno = rval;
- return false;
- }
-
- outbytesleft += OUTBUF_BLOCK_SIZE;
- to->asize += OUTBUF_BLOCK_SIZE;
- to->text = xrealloc (to->text, to->asize);
- outbuf = to->text + to->asize - outbytesleft;
- }
-}
-
-
-/* These functions convert entire strings between character sets.
- They all have the signature
-
- bool (*)(iconv_t cd, const uchar *from, size_t flen, struct _cpp_strbuf *to);
-
- The input string FROM is converted as specified by the function
- name plus the iconv descriptor CD (which may be fake), and the
- result appended to TO. On any error, false is returned, otherwise true. */
-
-/* These four use the custom conversion code above. */
-static bool
-convert_utf8_utf16 (iconv_t cd, const uchar *from, size_t flen,
- struct _cpp_strbuf *to)
-{
- return conversion_loop (one_utf8_to_utf16, cd, from, flen, to);
-}
-
-static bool
-convert_utf8_utf32 (iconv_t cd, const uchar *from, size_t flen,
- struct _cpp_strbuf *to)
-{
- return conversion_loop (one_utf8_to_utf32, cd, from, flen, to);
-}
-
-static bool
-convert_utf16_utf8 (iconv_t cd, const uchar *from, size_t flen,
- struct _cpp_strbuf *to)
-{
- return conversion_loop (one_utf16_to_utf8, cd, from, flen, to);
-}
-
-static bool
-convert_utf32_utf8 (iconv_t cd, const uchar *from, size_t flen,
- struct _cpp_strbuf *to)
-{
- return conversion_loop (one_utf32_to_utf8, cd, from, flen, to);
-}
-
-/* Identity conversion, used when we have no alternative. */
-static bool
-convert_no_conversion (iconv_t cd ATTRIBUTE_UNUSED,
- const uchar *from, size_t flen, struct _cpp_strbuf *to)
-{
- if (to->len + flen > to->asize)
- {
- to->asize = to->len + flen;
- to->text = xrealloc (to->text, to->asize);
- }
- memcpy (to->text + to->len, from, flen);
- to->len += flen;
- return true;
-}
-
-/* And this one uses the system iconv primitive. It's a little
- different, since iconv's interface is a little different. */
-#if HAVE_ICONV
-static bool
-convert_using_iconv (iconv_t cd, const uchar *from, size_t flen,
- struct _cpp_strbuf *to)
-{
- ICONV_CONST char *inbuf;
- char *outbuf;
- size_t inbytesleft, outbytesleft;
-
- /* Reset conversion descriptor and check that it is valid. */
- if (iconv (cd, 0, 0, 0, 0) == (size_t)-1)
- return false;
-
- inbuf = (ICONV_CONST char *)from;
- inbytesleft = flen;
- outbuf = (char *)to->text + to->len;
- outbytesleft = to->asize - to->len;
-
- for (;;)
- {
- iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
- if (__builtin_expect (inbytesleft == 0, 1))
- {
- to->len = to->asize - outbytesleft;
- return true;
- }
- if (errno != E2BIG)
- return false;
-
- outbytesleft += OUTBUF_BLOCK_SIZE;
- to->asize += OUTBUF_BLOCK_SIZE;
- to->text = xrealloc (to->text, to->asize);
- outbuf = (char *)to->text + to->asize - outbytesleft;
- }
-}
-#else
-#define convert_using_iconv 0 /* prevent undefined symbol error below */
-#endif
-
-/* Arrange for the above custom conversion logic to be used automatically
- when conversion between a suitable pair of character sets is requested. */
-
-#define APPLY_CONVERSION(CONVERTER, FROM, FLEN, TO) \
- CONVERTER.func (CONVERTER.cd, FROM, FLEN, TO)
-
-struct conversion
-{
- const char *pair;
- convert_f func;
- iconv_t fake_cd;
-};
-static const struct conversion conversion_tab[] = {
- { "UTF-8/UTF-32LE", convert_utf8_utf32, (iconv_t)0 },
- { "UTF-8/UTF-32BE", convert_utf8_utf32, (iconv_t)1 },
- { "UTF-8/UTF-16LE", convert_utf8_utf16, (iconv_t)0 },
- { "UTF-8/UTF-16BE", convert_utf8_utf16, (iconv_t)1 },
- { "UTF-32LE/UTF-8", convert_utf32_utf8, (iconv_t)0 },
- { "UTF-32BE/UTF-8", convert_utf32_utf8, (iconv_t)1 },
- { "UTF-16LE/UTF-8", convert_utf16_utf8, (iconv_t)0 },
- { "UTF-16BE/UTF-8", convert_utf16_utf8, (iconv_t)1 },
-};
-
-/* Subroutine of cpp_init_iconv: initialize and return a
- cset_converter structure for conversion from FROM to TO. If
- iconv_open() fails, issue an error and return an identity
- converter. Silently return an identity converter if FROM and TO
- are identical. */
-static struct cset_converter
-init_iconv_desc (cpp_reader *pfile, const char *to, const char *from)
-{
- struct cset_converter ret;
- char *pair;
- size_t i;
-
- if (!strcasecmp (to, from))
- {
- ret.func = convert_no_conversion;
- ret.cd = (iconv_t) -1;
- return ret;
- }
-
- pair = alloca(strlen(to) + strlen(from) + 2);
-
- strcpy(pair, from);
- strcat(pair, "/");
- strcat(pair, to);
- for (i = 0; i < ARRAY_SIZE (conversion_tab); i++)
- if (!strcasecmp (pair, conversion_tab[i].pair))
- {
- ret.func = conversion_tab[i].func;
- ret.cd = conversion_tab[i].fake_cd;
- return ret;
- }
-
- /* No custom converter - try iconv. */
- if (HAVE_ICONV)
- {
- ret.func = convert_using_iconv;
- ret.cd = iconv_open (to, from);
-
- if (ret.cd == (iconv_t) -1)
- {
- if (errno == EINVAL)
- cpp_error (pfile, CPP_DL_ERROR, /* FIXME should be DL_SORRY */
- "conversion from %s to %s not supported by iconv",
- from, to);
- else
- cpp_errno (pfile, CPP_DL_ERROR, "iconv_open");
-
- ret.func = convert_no_conversion;
- }
- }
- else
- {
- cpp_error (pfile, CPP_DL_ERROR, /* FIXME: should be DL_SORRY */
- "no iconv implementation, cannot convert from %s to %s",
- from, to);
- ret.func = convert_no_conversion;
- ret.cd = (iconv_t) -1;
- }
- return ret;
-}
-
-/* If charset conversion is requested, initialize iconv(3) descriptors
- for conversion from the source character set to the execution
- character sets. If iconv is not present in the C library, and
- conversion is requested, issue an error. */
-
-void
-cpp_init_iconv (cpp_reader *pfile)
-{
- const char *ncset = CPP_OPTION (pfile, narrow_charset);
- const char *wcset = CPP_OPTION (pfile, wide_charset);
- const char *default_wcset;
-
- bool be = CPP_OPTION (pfile, bytes_big_endian);
-
- if (CPP_OPTION (pfile, wchar_precision) >= 32)
- default_wcset = be ? "UTF-32BE" : "UTF-32LE";
- else if (CPP_OPTION (pfile, wchar_precision) >= 16)
- default_wcset = be ? "UTF-16BE" : "UTF-16LE";
- else
- /* This effectively means that wide strings are not supported,
- so don't do any conversion at all. */
- default_wcset = SOURCE_CHARSET;
-
- if (!ncset)
- ncset = SOURCE_CHARSET;
- if (!wcset)
- wcset = default_wcset;
-
- pfile->narrow_cset_desc = init_iconv_desc (pfile, ncset, SOURCE_CHARSET);
- pfile->wide_cset_desc = init_iconv_desc (pfile, wcset, SOURCE_CHARSET);
-}
-
-void
-_cpp_destroy_iconv (cpp_reader *pfile)
-{
- if (HAVE_ICONV)
- {
- if (pfile->narrow_cset_desc.func == convert_using_iconv)
- iconv_close (pfile->narrow_cset_desc.cd);
- if (pfile->wide_cset_desc.func == convert_using_iconv)
- iconv_close (pfile->wide_cset_desc.cd);
- }
-}
-
-
-/* Utility routine that computes a mask of the form 0000...111... with
- WIDTH 1-bits. */
-static inline size_t
-width_to_mask (size_t width)
-{
- width = MIN (width, BITS_PER_CPPCHAR_T);
- if (width >= CHAR_BIT * sizeof (size_t))
- return ~(size_t) 0;
- else
- return ((size_t) 1 << width) - 1;
-}
-
-
-
-/* Returns 1 if C is valid in an identifier, 2 if C is valid except at
- the start of an identifier, and 0 if C is not valid in an
- identifier. We assume C has already gone through the checks of
- _cpp_valid_ucn. The algorithm is a simple binary search on the
- table defined in cppucnid.h. */
-
-static int
-ucn_valid_in_identifier (cpp_reader *pfile, cppchar_t c)
-{
- int mn, mx, md;
-
- mn = -1;
- mx = ARRAY_SIZE (ucnranges);
- while (mx - mn > 1)
- {
- md = (mn + mx) / 2;
- if (c < ucnranges[md].lo)
- mx = md;
- else if (c > ucnranges[md].hi)
- mn = md;
- else
- goto found;
- }
- return 0;
-
- found:
- /* When -pedantic, we require the character to have been listed by
- the standard for the current language. Otherwise, we accept the
- union of the acceptable sets for C++98 and C99. */
- if (CPP_PEDANTIC (pfile)
- && ((CPP_OPTION (pfile, c99) && !(ucnranges[md].flags & C99))
- || (CPP_OPTION (pfile, cplusplus)
- && !(ucnranges[md].flags & CXX))))
- return 0;
-
- /* In C99, UCN digits may not begin identifiers. */
- if (CPP_OPTION (pfile, c99) && (ucnranges[md].flags & DIG))
- return 2;
-
- return 1;
-}
-
-/* [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.
-
- *PSTR must be preceded by "\u" or "\U"; it is assumed that the
- buffer end is delimited by a non-hex digit. Returns zero if UCNs
- are not part of the relevant standard, or if the string beginning
- at *PSTR doesn't syntactically match the form 'NNNN' or 'NNNNNNNN'.
-
- Otherwise the nonzero value of the UCN, whether valid or invalid,
- is returned. Diagnostics are emitted for invalid values. PSTR
- is updated to point one beyond the UCN, or to the syntactically
- invalid character.
-
- IDENTIFIER_POS is 0 when not in an identifier, 1 for the start of
- an identifier, or 2 otherwise.
-*/
-
-cppchar_t
-_cpp_valid_ucn (cpp_reader *pfile, const uchar **pstr,
- const uchar *limit, int identifier_pos)
-{
- cppchar_t result, c;
- unsigned int length;
- const uchar *str = *pstr;
- const uchar *base = str - 2;
-
- if (!CPP_OPTION (pfile, cplusplus) && !CPP_OPTION (pfile, c99))
- cpp_error (pfile, CPP_DL_WARNING,
- "universal character names are only valid in C++ and C99");
- else if (CPP_WTRADITIONAL (pfile) && identifier_pos == 0)
- cpp_error (pfile, CPP_DL_WARNING,
- "the meaning of '\\%c' is different in traditional C",
- (int) str[-1]);
-
- if (str[-1] == 'u')
- length = 4;
- else if (str[-1] == 'U')
- length = 8;
- else
- abort();
-
- result = 0;
- do
- {
- c = *str;
- if (!ISXDIGIT (c))
- break;
- str++;
- result = (result << 4) + hex_value (c);
- }
- while (--length && str < limit);
-
- *pstr = str;
- if (length)
- {
- /* We'll error when we try it out as the start of an identifier. */
- cpp_error (pfile, CPP_DL_ERROR,
- "incomplete universal character name %.*s",
- (int) (str - base), base);
- result = 1;
- }
- /* The standard permits $, @ and ` to be specified as UCNs. We use
- hex escapes so that this also works with EBCDIC hosts. */
- else if ((result < 0xa0
- && (result != 0x24 && result != 0x40 && result != 0x60))
- || (result & 0x80000000)
- || (result >= 0xD800 && result <= 0xDFFF))
- {
- cpp_error (pfile, CPP_DL_ERROR,
- "%.*s is not a valid universal character",
- (int) (str - base), base);
- result = 1;
- }
- else if (identifier_pos)
- {
- int validity = ucn_valid_in_identifier (pfile, result);
-
- if (validity == 0)
- cpp_error (pfile, CPP_DL_ERROR,
- "universal character %.*s is not valid in an identifier",
- (int) (str - base), base);
- else if (validity == 2 && identifier_pos == 1)
- cpp_error (pfile, CPP_DL_ERROR,
- "universal character %.*s is not valid at the start of an identifier",
- (int) (str - base), base);
- }
-
- if (result == 0)
- result = 1;
-
- return result;
-}
-
-/* Convert an UCN, pointed to by FROM, to UTF-8 encoding, then translate
- it to the execution character set and write the result into TBUF.
- An advanced pointer is returned. Issues all relevant diagnostics. */
-
-
-static const uchar *
-convert_ucn (cpp_reader *pfile, const uchar *from, const uchar *limit,
- struct _cpp_strbuf *tbuf, bool wide)
-{
- cppchar_t ucn;
- uchar buf[6];
- uchar *bufp = buf;
- size_t bytesleft = 6;
- int rval;
- struct cset_converter cvt
- = wide ? pfile->wide_cset_desc : pfile->narrow_cset_desc;
-
- from++; /* Skip u/U. */
- ucn = _cpp_valid_ucn (pfile, &from, limit, 0);
-
- rval = one_cppchar_to_utf8 (ucn, &bufp, &bytesleft);
- if (rval)
- {
- errno = rval;
- cpp_errno (pfile, CPP_DL_ERROR,
- "converting UCN to source character set");
- }
- else if (!APPLY_CONVERSION (cvt, buf, 6 - bytesleft, tbuf))
- cpp_errno (pfile, CPP_DL_ERROR,
- "converting UCN to execution character set");
-
- return from;
-}
-
-static void
-emit_numeric_escape (cpp_reader *pfile, cppchar_t n,
- struct _cpp_strbuf *tbuf, bool wide)
-{
- if (wide)
- {
- /* We have to render this into the target byte order, which may not
- be our byte order. */
- bool bigend = CPP_OPTION (pfile, bytes_big_endian);
- size_t width = CPP_OPTION (pfile, wchar_precision);
- size_t cwidth = CPP_OPTION (pfile, char_precision);
- size_t cmask = width_to_mask (cwidth);
- size_t nbwc = width / cwidth;
- size_t i;
- size_t off = tbuf->len;
- cppchar_t c;
-
- if (tbuf->len + nbwc > tbuf->asize)
- {
- tbuf->asize += OUTBUF_BLOCK_SIZE;
- tbuf->text = xrealloc (tbuf->text, tbuf->asize);
- }
-
- for (i = 0; i < nbwc; i++)
- {
- c = n & cmask;
- n >>= cwidth;
- tbuf->text[off + (bigend ? nbwc - i - 1 : i)] = c;
- }
- tbuf->len += nbwc;
- }
- else
- {
- if (tbuf->len + 1 > tbuf->asize)
- {
- tbuf->asize += OUTBUF_BLOCK_SIZE;
- tbuf->text = xrealloc (tbuf->text, tbuf->asize);
- }
- tbuf->text[tbuf->len++] = n;
- }
-}
-
-/* Convert a hexadecimal escape, pointed to by FROM, to the execution
- character set and write it into the string buffer TBUF. Returns an
- advanced pointer, and issues diagnostics as necessary.
- No character set translation occurs; this routine always produces the
- execution-set character with numeric value equal to the given hex
- number. You can, e.g. generate surrogate pairs this way. */
-static const uchar *
-convert_hex (cpp_reader *pfile, const uchar *from, const uchar *limit,
- struct _cpp_strbuf *tbuf, bool wide)
-{
- cppchar_t c, n = 0, overflow = 0;
- int digits_found = 0;
- size_t width = (wide ? CPP_OPTION (pfile, wchar_precision)
- : CPP_OPTION (pfile, char_precision));
- size_t mask = width_to_mask (width);
-
- if (CPP_WTRADITIONAL (pfile))
- cpp_error (pfile, CPP_DL_WARNING,
- "the meaning of '\\x' is different in traditional C");
-
- from++; /* Skip 'x'. */
- while (from < limit)
- {
- c = *from;
- if (! hex_p (c))
- break;
- from++;
- overflow |= n ^ (n << 4 >> 4);
- n = (n << 4) + hex_value (c);
- digits_found = 1;
- }
-
- if (!digits_found)
- {
- cpp_error (pfile, CPP_DL_ERROR,
- "\\x used with no following hex digits");
- return from;
- }
-
- if (overflow | (n != (n & mask)))
- {
- cpp_error (pfile, CPP_DL_PEDWARN,
- "hex escape sequence out of range");
- n &= mask;
- }
-
- emit_numeric_escape (pfile, n, tbuf, wide);
-
- return from;
-}
-
-/* Convert an octal escape, pointed to by FROM, to the execution
- character set and write it into the string buffer TBUF. Returns an
- advanced pointer, and issues diagnostics as necessary.
- No character set translation occurs; this routine always produces the
- execution-set character with numeric value equal to the given octal
- number. */
-static const uchar *
-convert_oct (cpp_reader *pfile, const uchar *from, const uchar *limit,
- struct _cpp_strbuf *tbuf, bool wide)
-{
- size_t count = 0;
- cppchar_t c, n = 0;
- size_t width = (wide ? CPP_OPTION (pfile, wchar_precision)
- : CPP_OPTION (pfile, char_precision));
- size_t mask = width_to_mask (width);
- bool overflow = false;
-
- while (from < limit && count++ < 3)
- {
- c = *from;
- if (c < '0' || c > '7')
- break;
- from++;
- overflow |= n ^ (n << 3 >> 3);
- n = (n << 3) + c - '0';
- }
-
- if (n != (n & mask))
- {
- cpp_error (pfile, CPP_DL_PEDWARN,
- "octal escape sequence out of range");
- n &= mask;
- }
-
- emit_numeric_escape (pfile, n, tbuf, wide);
-
- return from;
-}
-
-/* Convert an escape sequence (pointed to by FROM) to its value on
- the target, and to the execution character set. Do not scan past
- LIMIT. Write the converted value into TBUF. Returns an advanced
- pointer. Handles all relevant diagnostics. */
-static const uchar *
-convert_escape (cpp_reader *pfile, const uchar *from, const uchar *limit,
- struct _cpp_strbuf *tbuf, bool wide)
-{
- /* Values of \a \b \e \f \n \r \t \v respectively. */
-#if HOST_CHARSET == HOST_CHARSET_ASCII
- static const uchar charconsts[] = { 7, 8, 27, 12, 10, 13, 9, 11 };
-#elif HOST_CHARSET == HOST_CHARSET_EBCDIC
- static const uchar charconsts[] = { 47, 22, 39, 12, 21, 13, 5, 11 };
-#else
-#error "unknown host character set"
-#endif
-
- uchar c;
- struct cset_converter cvt
- = wide ? pfile->wide_cset_desc : pfile->narrow_cset_desc;
-
- c = *from;
- switch (c)
- {
- /* UCNs, hex escapes, and octal escapes are processed separately. */
- case 'u': case 'U':
- return convert_ucn (pfile, from, limit, tbuf, wide);
-
- case 'x':
- return convert_hex (pfile, from, limit, tbuf, wide);
- break;
-
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- return convert_oct (pfile, from, limit, tbuf, wide);
-
- /* Various letter escapes. Get the appropriate host-charset
- value into C. */
- case '\\': case '\'': case '"': case '?': break;
-
- case '(': case '{': case '[': case '%':
- /* '\(', etc, can be used at the beginning of a line in a long
- string split onto multiple lines with \-newline, to prevent
- Emacs or other text editors from getting confused. '\%' can
- be used to prevent SCCS from mangling printf format strings. */
- if (CPP_PEDANTIC (pfile))
- goto unknown;
- break;
-
- case 'b': c = charconsts[1]; break;
- case 'f': c = charconsts[3]; break;
- case 'n': c = charconsts[4]; break;
- case 'r': c = charconsts[5]; break;
- case 't': c = charconsts[6]; break;
- case 'v': c = charconsts[7]; break;
-
- case 'a':
- if (CPP_WTRADITIONAL (pfile))
- cpp_error (pfile, CPP_DL_WARNING,
- "the meaning of '\\a' is different in traditional C");
- c = charconsts[0];
- break;
-
- case 'e': case 'E':
- if (CPP_PEDANTIC (pfile))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "non-ISO-standard escape sequence, '\\%c'", (int) c);
- c = charconsts[2];
- break;
-
- default:
- unknown:
- if (ISGRAPH (c))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "unknown escape sequence '\\%c'", (int) c);
- else
- cpp_error (pfile, CPP_DL_PEDWARN,
- "unknown escape sequence: '\\%03o'", (int) c);
- }
-
- /* Now convert what we have to the execution character set. */
- if (!APPLY_CONVERSION (cvt, &c, 1, tbuf))
- cpp_errno (pfile, CPP_DL_ERROR,
- "converting escape sequence to execution character set");
-
- return from + 1;
-}
-
-/* FROM is an array of cpp_string structures of length COUNT. These
- are to be converted from the source to the execution character set,
- escape sequences translated, and finally all are to be
- concatenated. WIDE indicates whether or not to produce a wide
- string. The result is written into TO. Returns true for success,
- false for failure. */
-bool
-cpp_interpret_string (cpp_reader *pfile, const cpp_string *from, size_t count,
- cpp_string *to, bool wide)
-{
- struct _cpp_strbuf tbuf;
- const uchar *p, *base, *limit;
- size_t i;
- struct cset_converter cvt
- = wide ? pfile->wide_cset_desc : pfile->narrow_cset_desc;
-
- tbuf.asize = MAX (OUTBUF_BLOCK_SIZE, from->len);
- tbuf.text = xmalloc (tbuf.asize);
- tbuf.len = 0;
-
- for (i = 0; i < count; i++)
- {
- p = from[i].text;
- if (*p == 'L') p++;
- p++; /* Skip leading quote. */
- limit = from[i].text + from[i].len - 1; /* Skip trailing quote. */
-
- for (;;)
- {
- base = p;
- while (p < limit && *p != '\\')
- p++;
- if (p > base)
- {
- /* We have a run of normal characters; these can be fed
- directly to convert_cset. */
- if (!APPLY_CONVERSION (cvt, base, p - base, &tbuf))
- goto fail;
- }
- if (p == limit)
- break;
-
- p = convert_escape (pfile, p + 1, limit, &tbuf, wide);
- }
- }
- /* NUL-terminate the 'to' buffer and translate it to a cpp_string
- structure. */
- emit_numeric_escape (pfile, 0, &tbuf, wide);
- tbuf.text = xrealloc (tbuf.text, tbuf.len);
- to->text = tbuf.text;
- to->len = tbuf.len;
- return true;
-
- fail:
- cpp_errno (pfile, CPP_DL_ERROR, "converting to execution character set");
- free (tbuf.text);
- return false;
-}
-
-/* Subroutine of do_line and do_linemarker. Convert escape sequences
- in a string, but do not perform character set conversion. */
-bool
-cpp_interpret_string_notranslate (cpp_reader *pfile, const cpp_string *from,
- size_t count, cpp_string *to, bool wide)
-{
- struct cset_converter save_narrow_cset_desc = pfile->narrow_cset_desc;
- bool retval;
-
- pfile->narrow_cset_desc.func = convert_no_conversion;
- pfile->narrow_cset_desc.cd = (iconv_t) -1;
-
- retval = cpp_interpret_string (pfile, from, count, to, wide);
-
- pfile->narrow_cset_desc = save_narrow_cset_desc;
- return retval;
-}
-
-
-/* Subroutine of cpp_interpret_charconst which performs the conversion
- to a number, for narrow strings. STR is the string structure returned
- by cpp_interpret_string. PCHARS_SEEN and UNSIGNEDP are as for
- cpp_interpret_charconst. */
-static cppchar_t
-narrow_str_to_charconst (cpp_reader *pfile, cpp_string str,
- unsigned int *pchars_seen, int *unsignedp)
-{
- size_t width = CPP_OPTION (pfile, char_precision);
- size_t max_chars = CPP_OPTION (pfile, int_precision) / width;
- size_t mask = width_to_mask (width);
- size_t i;
- cppchar_t result, c;
- bool unsigned_p;
-
- /* The value of a multi-character character constant, or a
- single-character character constant whose representation in the
- execution character set is more than one byte long, is
- implementation defined. This implementation defines it to be the
- number formed by interpreting the byte sequence in memory as a
- big-endian binary number. If overflow occurs, the high bytes are
- lost, and a warning is issued.
-
- We don't want to process the NUL terminator handed back by
- cpp_interpret_string. */
- result = 0;
- for (i = 0; i < str.len - 1; i++)
- {
- c = str.text[i] & mask;
- if (width < BITS_PER_CPPCHAR_T)
- result = (result << width) | c;
- else
- result = c;
- }
-
- if (i > max_chars)
- {
- i = max_chars;
- cpp_error (pfile, CPP_DL_WARNING,
- "character constant too long for its type");
- }
- else if (i > 1 && CPP_OPTION (pfile, warn_multichar))
- cpp_error (pfile, CPP_DL_WARNING, "multi-character character constant");
-
- /* Multichar constants are of type int and therefore signed. */
- if (i > 1)
- unsigned_p = 0;
- else
- unsigned_p = CPP_OPTION (pfile, unsigned_char);
-
- /* Truncate the constant to its natural width, and simultaneously
- sign- or zero-extend to the full width of cppchar_t.
- For single-character constants, the value is WIDTH bits wide.
- For multi-character constants, the value is INT_PRECISION bits wide. */
- if (i > 1)
- width = CPP_OPTION (pfile, int_precision);
- if (width < BITS_PER_CPPCHAR_T)
- {
- mask = ((cppchar_t) 1 << width) - 1;
- if (unsigned_p || !(result & (1 << (width - 1))))
- result &= mask;
- else
- result |= ~mask;
- }
- *pchars_seen = i;
- *unsignedp = unsigned_p;
- return result;
-}
-
-/* Subroutine of cpp_interpret_charconst which performs the conversion
- to a number, for wide strings. STR is the string structure returned
- by cpp_interpret_string. PCHARS_SEEN and UNSIGNEDP are as for
- cpp_interpret_charconst. */
-static cppchar_t
-wide_str_to_charconst (cpp_reader *pfile, cpp_string str,
- unsigned int *pchars_seen, int *unsignedp)
-{
- bool bigend = CPP_OPTION (pfile, bytes_big_endian);
- size_t width = CPP_OPTION (pfile, wchar_precision);
- size_t cwidth = CPP_OPTION (pfile, char_precision);
- size_t mask = width_to_mask (width);
- size_t cmask = width_to_mask (cwidth);
- size_t nbwc = width / cwidth;
- size_t off, i;
- cppchar_t result = 0, c;
-
- /* This is finicky because the string is in the target's byte order,
- which may not be our byte order. Only the last character, ignoring
- the NUL terminator, is relevant. */
- off = str.len - (nbwc * 2);
- result = 0;
- for (i = 0; i < nbwc; i++)
- {
- c = bigend ? str.text[off + i] : str.text[off + nbwc - i - 1];
- result = (result << cwidth) | (c & cmask);
- }
-
- /* Wide character constants have type wchar_t, and a single
- character exactly fills a wchar_t, so a multi-character wide
- character constant is guaranteed to overflow. */
- if (off > 0)
- cpp_error (pfile, CPP_DL_WARNING,
- "character constant too long for its type");
-
- /* Truncate the constant to its natural width, and simultaneously
- sign- or zero-extend to the full width of cppchar_t. */
- if (width < BITS_PER_CPPCHAR_T)
- {
- if (CPP_OPTION (pfile, unsigned_wchar) || !(result & (1 << (width - 1))))
- result &= mask;
- else
- result |= ~mask;
- }
-
- *unsignedp = CPP_OPTION (pfile, unsigned_wchar);
- *pchars_seen = 1;
- return result;
-}
-
-/* Interpret a (possibly wide) character constant in TOKEN.
- PCHARS_SEEN points to a variable that is filled in with the number
- of characters seen, and UNSIGNEDP to a variable that indicates
- whether the result has signed type. */
-cppchar_t
-cpp_interpret_charconst (cpp_reader *pfile, const cpp_token *token,
- unsigned int *pchars_seen, int *unsignedp)
-{
- cpp_string str = { 0, 0 };
- bool wide = (token->type == CPP_WCHAR);
- cppchar_t result;
-
- /* an empty constant will appear as L'' or '' */
- if (token->val.str.len == (size_t) (2 + wide))
- {
- cpp_error (pfile, CPP_DL_ERROR, "empty character constant");
- return 0;
- }
- else if (!cpp_interpret_string (pfile, &token->val.str, 1, &str, wide))
- return 0;
-
- if (wide)
- result = wide_str_to_charconst (pfile, str, pchars_seen, unsignedp);
- else
- result = narrow_str_to_charconst (pfile, str, pchars_seen, unsignedp);
-
- if (str.text != token->val.str.text)
- free ((void *)str.text);
-
- return result;
-}
-
-uchar *
-_cpp_convert_input (cpp_reader *pfile, const char *input_charset,
- uchar *input, size_t size, size_t len, off_t *st_size)
-{
- struct cset_converter input_cset;
- struct _cpp_strbuf to;
-
- input_cset = init_iconv_desc (pfile, SOURCE_CHARSET, input_charset);
- if (input_cset.func == convert_no_conversion)
- {
- to.text = input;
- to.asize = size;
- to.len = len;
- }
- else
- {
- to.asize = MAX (65536, len);
- to.text = xmalloc (to.asize);
- to.len = 0;
-
- if (!APPLY_CONVERSION (input_cset, input, len, &to))
- cpp_error (pfile, CPP_DL_ERROR,
- "failure to convert %s to %s",
- CPP_OPTION (pfile, input_charset), SOURCE_CHARSET);
-
- free (input);
- }
-
- /* Clean up the mess. */
- if (input_cset.func == convert_using_iconv)
- iconv_close (input_cset.cd);
-
- /* Resize buffer if we allocated substantially too much, or if we
- haven't enough space for the \n-terminator. */
- if (to.len + 4096 < to.asize || to.len >= to.asize)
- to.text = xrealloc (to.text, to.len + 1);
-
- to.text[to.len] = '\n';
- *st_size = to.len;
- return to.text;
-}
-
-const char *
-_cpp_default_encoding (void)
-{
- const char *current_encoding = NULL;
-
-#if defined (HAVE_LOCALE_H) && defined (HAVE_LANGINFO_CODESET)
- setlocale (LC_CTYPE, "");
- current_encoding = nl_langinfo (CODESET);
-#endif
- if (current_encoding == NULL || *current_encoding == '\0')
- current_encoding = SOURCE_CHARSET;
-
- return current_encoding;
-}
diff --git a/gcc/cpperror.c b/gcc/cpperror.c
deleted file mode 100644
index 362c1c5f2e0..00000000000
--- a/gcc/cpperror.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/* Default error handlers for CPP Library.
- Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998, 1999, 2000,
- 2001, 2002, 2004 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_location (cpp_reader *, source_location, unsigned int);
-
-/* Print the logical file location (LINE, COL) in preparation for a
- diagnostic. Outputs the #include chain if it has changed. A line
- of zero suppresses the include stack, and outputs the program name
- instead. */
-static void
-print_location (cpp_reader *pfile, source_location line, unsigned int col)
-{
- if (line == 0)
- fprintf (stderr, "%s: ", progname);
- else
- {
- const struct line_map *map;
- unsigned int lin;
-
- map = linemap_lookup (pfile->line_table, line);
- linemap_print_containing_files (pfile->line_table, map);
-
- lin = SOURCE_LINE (map, line);
- if (col == 0)
- {
- col = SOURCE_COLUMN (map, line);
- if (col == 0)
- col = 1;
- }
-
- if (lin == 0)
- fprintf (stderr, "%s:", map->to_file);
- else if (CPP_OPTION (pfile, show_column) == 0)
- fprintf (stderr, "%s:%u:", map->to_file, lin);
- else
- fprintf (stderr, "%s:%u:%u:", map->to_file, lin, col);
-
- fputc (' ', stderr);
- }
-}
-
-/* Set up for a diagnostic: print the file and line, bump the error
- counter, etc. SRC_LOC is the logical line number; zero means to print
- at the location of the previously lexed token, which tends to be
- the correct place by default. The column number can be specified either
- using COLUMN or (if COLUMN==0) extracting SOURCE_COLUMN from SRC_LOC.
- (This may seem redundant, but is useful when pre-scanning (cleaning) a line,
- when we haven't yet verified whether the current line_map has a
- big enough max_column_hint.)
-
- Returns 0 if the error has been suppressed. */
-int
-_cpp_begin_message (cpp_reader *pfile, int code,
- source_location src_loc, unsigned int column)
-{
- int level = CPP_DL_EXTRACT (code);
-
- switch (level)
- {
- case CPP_DL_WARNING:
- case CPP_DL_PEDWARN:
- if (cpp_in_system_header (pfile)
- && ! CPP_OPTION (pfile, warn_system_headers))
- return 0;
- /* Fall through. */
-
- case CPP_DL_WARNING_SYSHDR:
- if (CPP_OPTION (pfile, warnings_are_errors)
- || (level == CPP_DL_PEDWARN && CPP_OPTION (pfile, pedantic_errors)))
- {
- if (CPP_OPTION (pfile, inhibit_errors))
- return 0;
- level = CPP_DL_ERROR;
- pfile->errors++;
- }
- else if (CPP_OPTION (pfile, inhibit_warnings))
- return 0;
- break;
-
- case CPP_DL_ERROR:
- if (CPP_OPTION (pfile, inhibit_errors))
- return 0;
- /* ICEs cannot be inhibited. */
- case CPP_DL_ICE:
- pfile->errors++;
- break;
- }
-
- print_location (pfile, src_loc, column);
- if (CPP_DL_WARNING_P (level))
- fputs (_("warning: "), stderr);
- else if (level == CPP_DL_ICE)
- fputs (_("internal error: "), stderr);
-
- return 1;
-}
-
-/* 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)
-
-/* Exported interface. */
-
-/* Print an error at the location of the previously lexed token. */
-void
-cpp_error (cpp_reader * pfile, int level, const char *msgid, ...)
-{
- source_location src_loc;
- va_list ap;
-
- va_start (ap, msgid);
-
- if (CPP_OPTION (pfile, traditional))
- {
- if (pfile->state.in_directive)
- src_loc = pfile->directive_line;
- else
- src_loc = pfile->line_table->highest_line;
- }
- else
- {
- src_loc = pfile->cur_token[-1].src_loc;
- }
-
- if (_cpp_begin_message (pfile, level, src_loc, 0))
- v_message (msgid, ap);
-
- va_end (ap);
-}
-
-/* Print an error at a specific location. */
-void
-cpp_error_with_line (cpp_reader *pfile, int level,
- source_location src_loc, unsigned int column,
- const char *msgid, ...)
-{
- va_list ap;
-
- va_start (ap, msgid);
-
- if (_cpp_begin_message (pfile, level, src_loc, column))
- v_message (msgid, ap);
-
- va_end (ap);
-}
-
-void
-cpp_errno (cpp_reader *pfile, int level, const char *msgid)
-{
- if (msgid[0] == '\0')
- msgid = _("stdout");
-
- cpp_error (pfile, level, "%s: %s", msgid, xstrerror (errno));
-}
diff --git a/gcc/cppexp.c b/gcc/cppexp.c
deleted file mode 100644
index 22d34b69416..00000000000
--- a/gcc/cppexp.c
+++ /dev/null
@@ -1,1540 +0,0 @@
-/* Parse C expressions for cpplib.
- Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
- 2002, 2004 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"
-
-#define PART_PRECISION (sizeof (cpp_num_part) * CHAR_BIT)
-#define HALF_MASK (~(cpp_num_part) 0 >> (PART_PRECISION / 2))
-#define LOW_PART(num_part) (num_part & HALF_MASK)
-#define HIGH_PART(num_part) (num_part >> (PART_PRECISION / 2))
-
-struct op
-{
- const cpp_token *token; /* The token forming op (for diagnostics). */
- cpp_num value; /* The value logically "right" of op. */
- enum cpp_ttype op;
-};
-
-/* Some simple utility routines on double integers. */
-#define num_zerop(num) ((num.low | num.high) == 0)
-#define num_eq(num1, num2) (num1.low == num2.low && num1.high == num2.high)
-static bool num_positive (cpp_num, size_t);
-static bool num_greater_eq (cpp_num, cpp_num, size_t);
-static cpp_num num_trim (cpp_num, size_t);
-static cpp_num num_part_mul (cpp_num_part, cpp_num_part);
-
-static cpp_num num_unary_op (cpp_reader *, cpp_num, enum cpp_ttype);
-static cpp_num num_binary_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype);
-static cpp_num num_negate (cpp_num, size_t);
-static cpp_num num_bitwise_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype);
-static cpp_num num_inequality_op (cpp_reader *, cpp_num, cpp_num,
- enum cpp_ttype);
-static cpp_num num_equality_op (cpp_reader *, cpp_num, cpp_num,
- enum cpp_ttype);
-static cpp_num num_mul (cpp_reader *, cpp_num, cpp_num);
-static cpp_num num_div_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype);
-static cpp_num num_lshift (cpp_num, size_t, size_t);
-static cpp_num num_rshift (cpp_num, size_t, size_t);
-
-static cpp_num append_digit (cpp_num, int, int, size_t);
-static cpp_num parse_defined (cpp_reader *);
-static cpp_num eval_token (cpp_reader *, const cpp_token *);
-static struct op *reduce (cpp_reader *, struct op *, enum cpp_ttype);
-static unsigned int interpret_float_suffix (const uchar *, size_t);
-static unsigned int interpret_int_suffix (const uchar *, size_t);
-static void check_promotion (cpp_reader *, const struct op *);
-
-/* Token type abuse to create unary plus and minus operators. */
-#define CPP_UPLUS (CPP_LAST_CPP_OP + 1)
-#define CPP_UMINUS (CPP_LAST_CPP_OP + 2)
-
-/* With -O2, gcc appears to produce nice code, moving the error
- message load and subsequent jump completely out of the main path. */
-#define SYNTAX_ERROR(msgid) \
- do { cpp_error (pfile, CPP_DL_ERROR, msgid); goto syntax_error; } while(0)
-#define SYNTAX_ERROR2(msgid, arg) \
- do { cpp_error (pfile, CPP_DL_ERROR, msgid, arg); goto syntax_error; } \
- while(0)
-
-/* Subroutine of cpp_classify_number. S points to a float suffix of
- length LEN, possibly zero. Returns 0 for an invalid suffix, or a
- flag vector describing the suffix. */
-static unsigned int
-interpret_float_suffix (const uchar *s, size_t len)
-{
- size_t f = 0, l = 0, i = 0;
-
- while (len--)
- switch (s[len])
- {
- case 'f': case 'F': f++; break;
- case 'l': case 'L': l++; break;
- case 'i': case 'I':
- case 'j': case 'J': i++; break;
- default:
- return 0;
- }
-
- if (f + l > 1 || i > 1)
- return 0;
-
- return ((i ? CPP_N_IMAGINARY : 0)
- | (f ? CPP_N_SMALL :
- l ? CPP_N_LARGE : CPP_N_MEDIUM));
-}
-
-/* Subroutine of cpp_classify_number. S points to an integer suffix
- of length LEN, possibly zero. Returns 0 for an invalid suffix, or a
- flag vector describing the suffix. */
-static unsigned int
-interpret_int_suffix (const uchar *s, size_t len)
-{
- size_t u, l, i;
-
- u = l = i = 0;
-
- while (len--)
- switch (s[len])
- {
- case 'u': case 'U': u++; break;
- case 'i': case 'I':
- case 'j': case 'J': i++; break;
- case 'l': case 'L': l++;
- /* If there are two Ls, they must be adjacent and the same case. */
- if (l == 2 && s[len] != s[len + 1])
- return 0;
- break;
- default:
- return 0;
- }
-
- if (l > 2 || u > 1 || i > 1)
- return 0;
-
- return ((i ? CPP_N_IMAGINARY : 0)
- | (u ? CPP_N_UNSIGNED : 0)
- | ((l == 0) ? CPP_N_SMALL
- : (l == 1) ? CPP_N_MEDIUM : CPP_N_LARGE));
-}
-
-/* Categorize numeric constants according to their field (integer,
- floating point, or invalid), radix (decimal, octal, hexadecimal),
- and type suffixes. */
-unsigned int
-cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
-{
- const uchar *str = token->val.str.text;
- const uchar *limit;
- unsigned int max_digit, result, radix;
- enum {NOT_FLOAT = 0, AFTER_POINT, AFTER_EXPON} float_flag;
-
- /* If the lexer has done its job, length one can only be a single
- digit. Fast-path this very common case. */
- if (token->val.str.len == 1)
- return CPP_N_INTEGER | CPP_N_SMALL | CPP_N_DECIMAL;
-
- limit = str + token->val.str.len;
- float_flag = NOT_FLOAT;
- max_digit = 0;
- radix = 10;
-
- /* First, interpret the radix. */
- if (*str == '0')
- {
- radix = 8;
- str++;
-
- /* Require at least one hex digit to classify it as hex. */
- if ((*str == 'x' || *str == 'X')
- && (str[1] == '.' || ISXDIGIT (str[1])))
- {
- radix = 16;
- str++;
- }
- }
-
- /* Now scan for a well-formed integer or float. */
- for (;;)
- {
- unsigned int c = *str++;
-
- if (ISDIGIT (c) || (ISXDIGIT (c) && radix == 16))
- {
- c = hex_value (c);
- if (c > max_digit)
- max_digit = c;
- }
- else if (c == '.')
- {
- if (float_flag == NOT_FLOAT)
- float_flag = AFTER_POINT;
- else
- SYNTAX_ERROR ("too many decimal points in number");
- }
- else if ((radix <= 10 && (c == 'e' || c == 'E'))
- || (radix == 16 && (c == 'p' || c == 'P')))
- {
- float_flag = AFTER_EXPON;
- break;
- }
- else
- {
- /* Start of suffix. */
- str--;
- break;
- }
- }
-
- if (float_flag != NOT_FLOAT && radix == 8)
- radix = 10;
-
- if (max_digit >= radix)
- SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit);
-
- if (float_flag != NOT_FLOAT)
- {
- if (radix == 16 && CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, c99))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "use of C99 hexadecimal floating constant");
-
- if (float_flag == AFTER_EXPON)
- {
- if (*str == '+' || *str == '-')
- str++;
-
- /* Exponent is decimal, even if string is a hex float. */
- if (!ISDIGIT (*str))
- SYNTAX_ERROR ("exponent has no digits");
-
- do
- str++;
- while (ISDIGIT (*str));
- }
- else if (radix == 16)
- SYNTAX_ERROR ("hexadecimal floating constants require an exponent");
-
- result = interpret_float_suffix (str, limit - str);
- if (result == 0)
- {
- cpp_error (pfile, CPP_DL_ERROR,
- "invalid suffix \"%.*s\" on floating constant",
- (int) (limit - str), str);
- return CPP_N_INVALID;
- }
-
- /* Traditional C didn't accept any floating suffixes. */
- if (limit != str
- && CPP_WTRADITIONAL (pfile)
- && ! cpp_sys_macro_p (pfile))
- cpp_error (pfile, CPP_DL_WARNING,
- "traditional C rejects the \"%.*s\" suffix",
- (int) (limit - str), str);
-
- result |= CPP_N_FLOATING;
- }
- else
- {
- result = interpret_int_suffix (str, limit - str);
- if (result == 0)
- {
- cpp_error (pfile, CPP_DL_ERROR,
- "invalid suffix \"%.*s\" on integer constant",
- (int) (limit - str), str);
- return CPP_N_INVALID;
- }
-
- /* Traditional C only accepted the 'L' suffix.
- Suppress warning about 'LL' with -Wno-long-long. */
- if (CPP_WTRADITIONAL (pfile) && ! cpp_sys_macro_p (pfile))
- {
- int u_or_i = (result & (CPP_N_UNSIGNED|CPP_N_IMAGINARY));
- int large = (result & CPP_N_WIDTH) == CPP_N_LARGE;
-
- if (u_or_i || (large && CPP_OPTION (pfile, warn_long_long)))
- cpp_error (pfile, CPP_DL_WARNING,
- "traditional C rejects the \"%.*s\" suffix",
- (int) (limit - str), str);
- }
-
- if ((result & CPP_N_WIDTH) == CPP_N_LARGE
- && ! CPP_OPTION (pfile, c99)
- && CPP_OPTION (pfile, warn_long_long))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "use of C99 long long integer constant");
-
- result |= CPP_N_INTEGER;
- }
-
- if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "imaginary constants are a GCC extension");
-
- if (radix == 10)
- result |= CPP_N_DECIMAL;
- else if (radix == 16)
- result |= CPP_N_HEX;
- else
- result |= CPP_N_OCTAL;
-
- return result;
-
- syntax_error:
- return CPP_N_INVALID;
-}
-
-/* cpp_interpret_integer converts an integer constant into a cpp_num,
- of precision options->precision.
-
- We do not provide any interface for decimal->float conversion,
- because the preprocessor doesn't need it and we don't want to
- drag in GCC's floating point emulator. */
-cpp_num
-cpp_interpret_integer (cpp_reader *pfile, const cpp_token *token,
- unsigned int type)
-{
- const uchar *p, *end;
- cpp_num result;
-
- result.low = 0;
- result.high = 0;
- result.unsignedp = !!(type & CPP_N_UNSIGNED);
- result.overflow = false;
-
- p = token->val.str.text;
- end = p + token->val.str.len;
-
- /* Common case of a single digit. */
- if (token->val.str.len == 1)
- result.low = p[0] - '0';
- else
- {
- cpp_num_part max;
- size_t precision = CPP_OPTION (pfile, precision);
- unsigned int base = 10, c = 0;
- bool overflow = false;
-
- if ((type & CPP_N_RADIX) == CPP_N_OCTAL)
- {
- base = 8;
- p++;
- }
- else if ((type & CPP_N_RADIX) == CPP_N_HEX)
- {
- base = 16;
- p += 2;
- }
-
- /* We can add a digit to numbers strictly less than this without
- needing the precision and slowness of double integers. */
- max = ~(cpp_num_part) 0;
- if (precision < PART_PRECISION)
- max >>= PART_PRECISION - precision;
- max = (max - base + 1) / base + 1;
-
- for (; p < end; p++)
- {
- c = *p;
-
- if (ISDIGIT (c) || (base == 16 && ISXDIGIT (c)))
- c = hex_value (c);
- else
- break;
-
- /* Strict inequality for when max is set to zero. */
- if (result.low < max)
- result.low = result.low * base + c;
- else
- {
- result = append_digit (result, c, base, precision);
- overflow |= result.overflow;
- max = 0;
- }
- }
-
- if (overflow)
- cpp_error (pfile, CPP_DL_PEDWARN,
- "integer constant is too large for its type");
- /* If too big to be signed, consider it unsigned. Only warn for
- decimal numbers. Traditional numbers were always signed (but
- we still honor an explicit U suffix); but we only have
- traditional semantics in directives. */
- else if (!result.unsignedp
- && !(CPP_OPTION (pfile, traditional)
- && pfile->state.in_directive)
- && !num_positive (result, precision))
- {
- if (base == 10)
- cpp_error (pfile, CPP_DL_WARNING,
- "integer constant is so large that it is unsigned");
- result.unsignedp = true;
- }
- }
-
- return result;
-}
-
-/* Append DIGIT to NUM, a number of PRECISION bits being read in base BASE. */
-static cpp_num
-append_digit (cpp_num num, int digit, int base, size_t precision)
-{
- cpp_num result;
- unsigned int shift = 3 + (base == 16);
- bool overflow;
- cpp_num_part add_high, add_low;
-
- /* Multiply by 8 or 16. Catching this overflow here means we don't
- need to worry about add_high overflowing. */
- overflow = !!(num.high >> (PART_PRECISION - shift));
- result.high = num.high << shift;
- result.low = num.low << shift;
- result.high |= num.low >> (PART_PRECISION - shift);
- result.unsignedp = num.unsignedp;
-
- if (base == 10)
- {
- add_low = num.low << 1;
- add_high = (num.high << 1) + (num.low >> (PART_PRECISION - 1));
- }
- else
- add_high = add_low = 0;
-
- if (add_low + digit < add_low)
- add_high++;
- add_low += digit;
-
- if (result.low + add_low < result.low)
- add_high++;
- if (result.high + add_high < result.high)
- overflow = true;
-
- result.low += add_low;
- result.high += add_high;
- result.overflow = overflow;
-
- /* The above code catches overflow of a cpp_num type. This catches
- overflow of the (possibly shorter) target precision. */
- num.low = result.low;
- num.high = result.high;
- result = num_trim (result, precision);
- if (!num_eq (result, num))
- result.overflow = true;
-
- return result;
-}
-
-/* Handle meeting "defined" in a preprocessor expression. */
-static cpp_num
-parse_defined (cpp_reader *pfile)
-{
- cpp_num result;
- int paren = 0;
- cpp_hashnode *node = 0;
- const cpp_token *token;
- cpp_context *initial_context = pfile->context;
-
- /* Don't expand macros. */
- pfile->state.prevent_expansion++;
-
- token = cpp_get_token (pfile);
- if (token->type == CPP_OPEN_PAREN)
- {
- paren = 1;
- token = cpp_get_token (pfile);
- }
-
- if (token->type == CPP_NAME)
- {
- node = token->val.node;
- if (paren && cpp_get_token (pfile)->type != CPP_CLOSE_PAREN)
- {
- cpp_error (pfile, CPP_DL_ERROR, "missing ')' after \"defined\"");
- node = 0;
- }
- }
- else
- {
- cpp_error (pfile, CPP_DL_ERROR,
- "operator \"defined\" requires an identifier");
- if (token->flags & NAMED_OP)
- {
- cpp_token op;
-
- op.flags = 0;
- op.type = token->type;
- cpp_error (pfile, CPP_DL_ERROR,
- "(\"%s\" is an alternative token for \"%s\" in C++)",
- cpp_token_as_text (pfile, token),
- cpp_token_as_text (pfile, &op));
- }
- }
-
- if (node)
- {
- if (pfile->context != initial_context && CPP_PEDANTIC (pfile))
- cpp_error (pfile, CPP_DL_WARNING,
- "this use of \"defined\" may not be portable");
-
- _cpp_mark_macro_used (node);
-
- /* A possible controlling macro of the form #if !defined ().
- _cpp_parse_expr checks there was no other junk on the line. */
- pfile->mi_ind_cmacro = node;
- }
-
- pfile->state.prevent_expansion--;
-
- result.unsignedp = false;
- result.high = 0;
- result.overflow = false;
- result.low = node && node->type == NT_MACRO;
- return result;
-}
-
-/* Convert a token into a CPP_NUMBER (an interpreted preprocessing
- number or character constant, or the result of the "defined" or "#"
- operators). */
-static cpp_num
-eval_token (cpp_reader *pfile, const cpp_token *token)
-{
- cpp_num result;
- unsigned int temp;
- int unsignedp = 0;
-
- result.unsignedp = false;
- result.overflow = false;
-
- switch (token->type)
- {
- case CPP_NUMBER:
- temp = cpp_classify_number (pfile, token);
- switch (temp & CPP_N_CATEGORY)
- {
- case CPP_N_FLOATING:
- cpp_error (pfile, CPP_DL_ERROR,
- "floating constant in preprocessor expression");
- break;
- case CPP_N_INTEGER:
- if (!(temp & CPP_N_IMAGINARY))
- return cpp_interpret_integer (pfile, token, temp);
- cpp_error (pfile, CPP_DL_ERROR,
- "imaginary number in preprocessor expression");
- break;
-
- case CPP_N_INVALID:
- /* Error already issued. */
- break;
- }
- result.high = result.low = 0;
- break;
-
- case CPP_WCHAR:
- case CPP_CHAR:
- {
- cppchar_t cc = cpp_interpret_charconst (pfile, token,
- &temp, &unsignedp);
-
- result.high = 0;
- result.low = cc;
- /* Sign-extend the result if necessary. */
- if (!unsignedp && (cppchar_signed_t) cc < 0)
- {
- if (PART_PRECISION > BITS_PER_CPPCHAR_T)
- result.low |= ~(~(cpp_num_part) 0
- >> (PART_PRECISION - BITS_PER_CPPCHAR_T));
- result.high = ~(cpp_num_part) 0;
- result = num_trim (result, CPP_OPTION (pfile, precision));
- }
- }
- break;
-
- case CPP_NAME:
- if (token->val.node == pfile->spec_nodes.n_defined)
- 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))
- {
- result.high = 0;
- result.low = (token->val.node == pfile->spec_nodes.n_true);
- }
- else
- {
- result.high = 0;
- result.low = 0;
- if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval)
- cpp_error (pfile, CPP_DL_WARNING, "\"%s\" is not defined",
- NODE_NAME (token->val.node));
- }
- break;
-
- default: /* CPP_HASH */
- _cpp_test_assertion (pfile, &temp);
- result.high = 0;
- result.low = temp;
- }
-
- result.unsignedp = !!unsignedp;
- return result;
-}
-
-/* Operator precedence and flags table.
-
-After an operator is returned from the lexer, if it has priority less
-than the operator on the top of the stack, we reduce the stack by one
-operator and repeat the test. Since equal priorities do not reduce,
-this is naturally right-associative.
-
-We handle left-associative operators by decrementing the priority of
-just-lexed operators by one, but retaining the priority of operators
-already on the stack.
-
-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
-parenthesized expression. If there is a matching '(', the routine
-reduce() exits immediately. If the normal exit route sees a ')', then
-there cannot have been a matching '(' and an error message is output.
-
-The parser assumes all shifted operators require a left operand unless
-the flag NO_L_OPERAND is set. These semantics are automatic; any
-extra semantics need to be handled with operator-specific code. */
-
-/* Flags. If CHECK_PROMOTION, we warn if the effective sign of an
- operand changes because of integer promotions. */
-#define NO_L_OPERAND (1 << 0)
-#define LEFT_ASSOC (1 << 1)
-#define CHECK_PROMOTION (1 << 2)
-
-/* Operator to priority map. Must be in the same order as the first
- N entries of enum cpp_ttype. */
-static const struct operator
-{
- uchar prio;
- uchar flags;
-} optab[] =
-{
- /* EQ */ {0, 0}, /* Shouldn't happen. */
- /* NOT */ {16, NO_L_OPERAND},
- /* GREATER */ {12, LEFT_ASSOC | CHECK_PROMOTION},
- /* LESS */ {12, LEFT_ASSOC | CHECK_PROMOTION},
- /* PLUS */ {14, LEFT_ASSOC | CHECK_PROMOTION},
- /* MINUS */ {14, LEFT_ASSOC | CHECK_PROMOTION},
- /* MULT */ {15, LEFT_ASSOC | CHECK_PROMOTION},
- /* DIV */ {15, LEFT_ASSOC | CHECK_PROMOTION},
- /* MOD */ {15, LEFT_ASSOC | CHECK_PROMOTION},
- /* AND */ {9, LEFT_ASSOC | CHECK_PROMOTION},
- /* OR */ {7, LEFT_ASSOC | CHECK_PROMOTION},
- /* XOR */ {8, LEFT_ASSOC | CHECK_PROMOTION},
- /* RSHIFT */ {13, LEFT_ASSOC},
- /* LSHIFT */ {13, LEFT_ASSOC},
-
- /* MIN */ {10, LEFT_ASSOC | CHECK_PROMOTION},
- /* MAX */ {10, LEFT_ASSOC | CHECK_PROMOTION},
-
- /* COMPL */ {16, NO_L_OPERAND},
- /* AND_AND */ {6, LEFT_ASSOC},
- /* OR_OR */ {5, LEFT_ASSOC},
- /* QUERY */ {3, 0},
- /* COLON */ {4, LEFT_ASSOC | CHECK_PROMOTION},
- /* COMMA */ {2, LEFT_ASSOC},
- /* OPEN_PAREN */ {1, NO_L_OPERAND},
- /* CLOSE_PAREN */ {0, 0},
- /* EOF */ {0, 0},
- /* EQ_EQ */ {11, LEFT_ASSOC},
- /* NOT_EQ */ {11, LEFT_ASSOC},
- /* GREATER_EQ */ {12, LEFT_ASSOC | CHECK_PROMOTION},
- /* LESS_EQ */ {12, LEFT_ASSOC | CHECK_PROMOTION},
- /* UPLUS */ {16, NO_L_OPERAND},
- /* UMINUS */ {16, NO_L_OPERAND}
-};
-
-/* Parse and evaluate a C expression, reading from PFILE.
- Returns the truth value of the expression.
-
- 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 op_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. */
-bool
-_cpp_parse_expr (cpp_reader *pfile)
-{
- struct op *top = pfile->op_stack;
- unsigned int lex_count;
- bool saw_leading_not, want_value = true;
-
- pfile->state.skip_eval = 0;
-
- /* Set up detection of #if ! defined(). */
- pfile->mi_ind_cmacro = 0;
- saw_leading_not = false;
- lex_count = 0;
-
- /* Lowest priority operator prevents further reductions. */
- top->op = CPP_EOF;
-
- for (;;)
- {
- struct op op;
-
- lex_count++;
- op.token = cpp_get_token (pfile);
- op.op = op.token->type;
-
- switch (op.op)
- {
- /* These tokens convert into values. */
- case CPP_NUMBER:
- case CPP_CHAR:
- case CPP_WCHAR:
- case CPP_NAME:
- case CPP_HASH:
- if (!want_value)
- SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
- cpp_token_as_text (pfile, op.token));
- want_value = false;
- top->value = eval_token (pfile, op.token);
- continue;
-
- case CPP_NOT:
- saw_leading_not = lex_count == 1;
- break;
- case CPP_PLUS:
- if (want_value)
- op.op = CPP_UPLUS;
- break;
- case CPP_MINUS:
- if (want_value)
- op.op = CPP_UMINUS;
- break;
-
- default:
- if ((int) op.op <= (int) CPP_EQ || (int) op.op >= (int) CPP_PLUS_EQ)
- SYNTAX_ERROR2 ("token \"%s\" is not valid in preprocessor expressions",
- cpp_token_as_text (pfile, op.token));
- break;
- }
-
- /* Check we have a value or operator as appropriate. */
- if (optab[op.op].flags & NO_L_OPERAND)
- {
- if (!want_value)
- SYNTAX_ERROR2 ("missing binary operator before token \"%s\"",
- cpp_token_as_text (pfile, op.token));
- }
- else if (want_value)
- {
- /* Ordering here is subtle and intended to favor the
- missing parenthesis diagnostics over alternatives. */
- if (op.op == CPP_CLOSE_PAREN)
- {
- if (top->op == CPP_OPEN_PAREN)
- SYNTAX_ERROR ("void expression between '(' and ')'");
- }
- else if (top->op == CPP_EOF)
- SYNTAX_ERROR ("#if with no expression");
- if (top->op != CPP_EOF && top->op != CPP_OPEN_PAREN)
- SYNTAX_ERROR2 ("operator '%s' has no right operand",
- cpp_token_as_text (pfile, top->token));
- }
-
- top = reduce (pfile, top, op.op);
- if (!top)
- goto syntax_error;
-
- if (op.op == CPP_EOF)
- break;
-
- switch (op.op)
- {
- case CPP_CLOSE_PAREN:
- continue;
- case CPP_OR_OR:
- if (!num_zerop (top->value))
- pfile->state.skip_eval++;
- break;
- case CPP_AND_AND:
- case CPP_QUERY:
- if (num_zerop (top->value))
- pfile->state.skip_eval++;
- break;
- case CPP_COLON:
- if (top->op != CPP_QUERY)
- SYNTAX_ERROR (" ':' without preceding '?'");
- if (!num_zerop (top[-1].value)) /* Was '?' condition true? */
- pfile->state.skip_eval++;
- else
- pfile->state.skip_eval--;
- default:
- break;
- }
-
- want_value = true;
-
- /* Check for and handle stack overflow. */
- if (++top == pfile->op_limit)
- top = _cpp_expand_op_stack (pfile);
-
- top->op = op.op;
- top->token = op.token;
- }
-
- /* The controlling macro expression is only valid if we called lex 3
- times: <!> <defined expression> and <EOF>. push_conditional ()
- checks that we are at top-of-file. */
- if (pfile->mi_ind_cmacro && !(saw_leading_not && lex_count == 3))
- pfile->mi_ind_cmacro = 0;
-
- if (top != pfile->op_stack)
- {
- cpp_error (pfile, CPP_DL_ICE, "unbalanced stack in #if");
- syntax_error:
- return false; /* Return false on syntax error. */
- }
-
- return !num_zerop (top->value);
-}
-
-/* Reduce the operator / value stack if possible, in preparation for
- pushing operator OP. Returns NULL on error, otherwise the top of
- the stack. */
-static struct op *
-reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op)
-{
- unsigned int prio;
-
- if (top->op <= CPP_EQ || top->op > CPP_LAST_CPP_OP + 2)
- {
- bad_op:
- cpp_error (pfile, CPP_DL_ICE, "impossible operator '%u'", top->op);
- return 0;
- }
-
- if (op == CPP_OPEN_PAREN)
- return top;
-
- /* Decrement the priority of left-associative operators to force a
- reduction with operators of otherwise equal priority. */
- prio = optab[op].prio - ((optab[op].flags & LEFT_ASSOC) != 0);
- while (prio < optab[top->op].prio)
- {
- if (CPP_OPTION (pfile, warn_num_sign_change)
- && optab[top->op].flags & CHECK_PROMOTION)
- check_promotion (pfile, top);
-
- switch (top->op)
- {
- case CPP_UPLUS:
- case CPP_UMINUS:
- case CPP_NOT:
- case CPP_COMPL:
- top[-1].value = num_unary_op (pfile, top->value, top->op);
- break;
-
- case CPP_PLUS:
- case CPP_MINUS:
- case CPP_RSHIFT:
- case CPP_LSHIFT:
- case CPP_MIN:
- case CPP_MAX:
- case CPP_COMMA:
- top[-1].value = num_binary_op (pfile, top[-1].value,
- top->value, top->op);
- break;
-
- case CPP_GREATER:
- case CPP_LESS:
- case CPP_GREATER_EQ:
- case CPP_LESS_EQ:
- top[-1].value
- = num_inequality_op (pfile, top[-1].value, top->value, top->op);
- break;
-
- case CPP_EQ_EQ:
- case CPP_NOT_EQ:
- top[-1].value
- = num_equality_op (pfile, top[-1].value, top->value, top->op);
- break;
-
- case CPP_AND:
- case CPP_OR:
- case CPP_XOR:
- top[-1].value
- = num_bitwise_op (pfile, top[-1].value, top->value, top->op);
- break;
-
- case CPP_MULT:
- top[-1].value = num_mul (pfile, top[-1].value, top->value);
- break;
-
- case CPP_DIV:
- case CPP_MOD:
- top[-1].value = num_div_op (pfile, top[-1].value,
- top->value, top->op);
- break;
-
- case CPP_OR_OR:
- top--;
- if (!num_zerop (top->value))
- pfile->state.skip_eval--;
- top->value.low = (!num_zerop (top->value)
- || !num_zerop (top[1].value));
- top->value.high = 0;
- top->value.unsignedp = false;
- top->value.overflow = false;
- continue;
-
- case CPP_AND_AND:
- top--;
- if (num_zerop (top->value))
- pfile->state.skip_eval--;
- top->value.low = (!num_zerop (top->value)
- && !num_zerop (top[1].value));
- top->value.high = 0;
- top->value.unsignedp = false;
- top->value.overflow = false;
- continue;
-
- case CPP_OPEN_PAREN:
- if (op != CPP_CLOSE_PAREN)
- {
- cpp_error (pfile, CPP_DL_ERROR, "missing ')' in expression");
- return 0;
- }
- top--;
- top->value = top[1].value;
- return top;
-
- case CPP_COLON:
- top -= 2;
- if (!num_zerop (top->value))
- {
- pfile->state.skip_eval--;
- top->value = top[1].value;
- }
- else
- top->value = top[2].value;
- top->value.unsignedp = (top[1].value.unsignedp
- || top[2].value.unsignedp);
- continue;
-
- case CPP_QUERY:
- cpp_error (pfile, CPP_DL_ERROR, "'?' without following ':'");
- return 0;
-
- default:
- goto bad_op;
- }
-
- top--;
- if (top->value.overflow && !pfile->state.skip_eval)
- cpp_error (pfile, CPP_DL_PEDWARN,
- "integer overflow in preprocessor expression");
- }
-
- if (op == CPP_CLOSE_PAREN)
- {
- cpp_error (pfile, CPP_DL_ERROR, "missing '(' in expression");
- return 0;
- }
-
- return top;
-}
-
-/* Returns the position of the old top of stack after expansion. */
-struct op *
-_cpp_expand_op_stack (cpp_reader *pfile)
-{
- size_t old_size = (size_t) (pfile->op_limit - pfile->op_stack);
- size_t new_size = old_size * 2 + 20;
-
- pfile->op_stack = xrealloc (pfile->op_stack, new_size * sizeof (struct op));
- pfile->op_limit = pfile->op_stack + new_size;
-
- return pfile->op_stack + old_size;
-}
-
-/* Emits a warning if the effective sign of either operand of OP
- changes because of integer promotions. */
-static void
-check_promotion (cpp_reader *pfile, const struct op *op)
-{
- if (op->value.unsignedp == op[-1].value.unsignedp)
- return;
-
- if (op->value.unsignedp)
- {
- if (!num_positive (op[-1].value, CPP_OPTION (pfile, precision)))
- cpp_error (pfile, CPP_DL_WARNING,
- "the left operand of \"%s\" changes sign when promoted",
- cpp_token_as_text (pfile, op->token));
- }
- else if (!num_positive (op->value, CPP_OPTION (pfile, precision)))
- cpp_error (pfile, CPP_DL_WARNING,
- "the right operand of \"%s\" changes sign when promoted",
- cpp_token_as_text (pfile, op->token));
-}
-
-/* Clears the unused high order bits of the number pointed to by PNUM. */
-static cpp_num
-num_trim (cpp_num num, size_t precision)
-{
- if (precision > PART_PRECISION)
- {
- precision -= PART_PRECISION;
- if (precision < PART_PRECISION)
- num.high &= ((cpp_num_part) 1 << precision) - 1;
- }
- else
- {
- if (precision < PART_PRECISION)
- num.low &= ((cpp_num_part) 1 << precision) - 1;
- num.high = 0;
- }
-
- return num;
-}
-
-/* True iff A (presumed signed) >= 0. */
-static bool
-num_positive (cpp_num num, size_t precision)
-{
- if (precision > PART_PRECISION)
- {
- precision -= PART_PRECISION;
- return (num.high & (cpp_num_part) 1 << (precision - 1)) == 0;
- }
-
- return (num.low & (cpp_num_part) 1 << (precision - 1)) == 0;
-}
-
-/* Sign extend a number, with PRECISION significant bits and all
- others assumed clear, to fill out a cpp_num structure. */
-cpp_num
-cpp_num_sign_extend (cpp_num num, size_t precision)
-{
- if (!num.unsignedp)
- {
- if (precision > PART_PRECISION)
- {
- precision -= PART_PRECISION;
- if (precision < PART_PRECISION
- && (num.high & (cpp_num_part) 1 << (precision - 1)))
- num.high |= ~(~(cpp_num_part) 0 >> (PART_PRECISION - precision));
- }
- else if (num.low & (cpp_num_part) 1 << (precision - 1))
- {
- if (precision < PART_PRECISION)
- num.low |= ~(~(cpp_num_part) 0 >> (PART_PRECISION - precision));
- num.high = ~(cpp_num_part) 0;
- }
- }
-
- return num;
-}
-
-/* Returns the negative of NUM. */
-static cpp_num
-num_negate (cpp_num num, size_t precision)
-{
- cpp_num copy;
-
- copy = num;
- num.high = ~num.high;
- num.low = ~num.low;
- if (++num.low == 0)
- num.high++;
- num = num_trim (num, precision);
- num.overflow = (!num.unsignedp && num_eq (num, copy) && !num_zerop (num));
-
- return num;
-}
-
-/* Returns true if A >= B. */
-static bool
-num_greater_eq (cpp_num pa, cpp_num pb, size_t precision)
-{
- bool unsignedp;
-
- unsignedp = pa.unsignedp || pb.unsignedp;
-
- if (!unsignedp)
- {
- /* Both numbers have signed type. If they are of different
- sign, the answer is the sign of A. */
- unsignedp = num_positive (pa, precision);
-
- if (unsignedp != num_positive (pb, precision))
- return unsignedp;
-
- /* Otherwise we can do an unsigned comparison. */
- }
-
- return (pa.high > pb.high) || (pa.high == pb.high && pa.low >= pb.low);
-}
-
-/* Returns LHS OP RHS, where OP is a bit-wise operation. */
-static cpp_num
-num_bitwise_op (cpp_reader *pfile ATTRIBUTE_UNUSED,
- cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
-{
- lhs.overflow = false;
- lhs.unsignedp = lhs.unsignedp || rhs.unsignedp;
-
- /* As excess precision is zeroed, there is no need to num_trim () as
- these operations cannot introduce a set bit there. */
- if (op == CPP_AND)
- {
- lhs.low &= rhs.low;
- lhs.high &= rhs.high;
- }
- else if (op == CPP_OR)
- {
- lhs.low |= rhs.low;
- lhs.high |= rhs.high;
- }
- else
- {
- lhs.low ^= rhs.low;
- lhs.high ^= rhs.high;
- }
-
- return lhs;
-}
-
-/* Returns LHS OP RHS, where OP is an inequality. */
-static cpp_num
-num_inequality_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs,
- enum cpp_ttype op)
-{
- bool gte = num_greater_eq (lhs, rhs, CPP_OPTION (pfile, precision));
-
- if (op == CPP_GREATER_EQ)
- lhs.low = gte;
- else if (op == CPP_LESS)
- lhs.low = !gte;
- else if (op == CPP_GREATER)
- lhs.low = gte && !num_eq (lhs, rhs);
- else /* CPP_LESS_EQ. */
- lhs.low = !gte || num_eq (lhs, rhs);
-
- lhs.high = 0;
- lhs.overflow = false;
- lhs.unsignedp = false;
- return lhs;
-}
-
-/* Returns LHS OP RHS, where OP is == or !=. */
-static cpp_num
-num_equality_op (cpp_reader *pfile ATTRIBUTE_UNUSED,
- cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
-{
- /* Work around a 3.0.4 bug; see PR 6950. */
- bool eq = num_eq (lhs, rhs);
- if (op == CPP_NOT_EQ)
- eq = !eq;
- lhs.low = eq;
- lhs.high = 0;
- lhs.overflow = false;
- lhs.unsignedp = false;
- return lhs;
-}
-
-/* Shift NUM, of width PRECISION, right by N bits. */
-static cpp_num
-num_rshift (cpp_num num, size_t precision, size_t n)
-{
- cpp_num_part sign_mask;
- bool x = num_positive (num, precision);
-
- if (num.unsignedp || x)
- sign_mask = 0;
- else
- sign_mask = ~(cpp_num_part) 0;
-
- if (n >= precision)
- num.high = num.low = sign_mask;
- else
- {
- /* Sign-extend. */
- if (precision < PART_PRECISION)
- num.high = sign_mask, num.low |= sign_mask << precision;
- else if (precision < 2 * PART_PRECISION)
- num.high |= sign_mask << (precision - PART_PRECISION);
-
- if (n >= PART_PRECISION)
- {
- n -= PART_PRECISION;
- num.low = num.high;
- num.high = sign_mask;
- }
-
- if (n)
- {
- num.low = (num.low >> n) | (num.high << (PART_PRECISION - n));
- num.high = (num.high >> n) | (sign_mask << (PART_PRECISION - n));
- }
- }
-
- num = num_trim (num, precision);
- num.overflow = false;
- return num;
-}
-
-/* Shift NUM, of width PRECISION, left by N bits. */
-static cpp_num
-num_lshift (cpp_num num, size_t precision, size_t n)
-{
- if (n >= precision)
- {
- num.overflow = !num.unsignedp && !num_zerop (num);
- num.high = num.low = 0;
- }
- else
- {
- cpp_num orig, maybe_orig;
- size_t m = n;
-
- orig = num;
- if (m >= PART_PRECISION)
- {
- m -= PART_PRECISION;
- num.high = num.low;
- num.low = 0;
- }
- if (m)
- {
- num.high = (num.high << m) | (num.low >> (PART_PRECISION - m));
- num.low <<= m;
- }
- num = num_trim (num, precision);
-
- if (num.unsignedp)
- num.overflow = false;
- else
- {
- maybe_orig = num_rshift (num, precision, n);
- num.overflow = !num_eq (orig, maybe_orig);
- }
- }
-
- return num;
-}
-
-/* The four unary operators: +, -, ! and ~. */
-static cpp_num
-num_unary_op (cpp_reader *pfile, cpp_num num, enum cpp_ttype op)
-{
- switch (op)
- {
- case CPP_UPLUS:
- if (CPP_WTRADITIONAL (pfile) && !pfile->state.skip_eval)
- cpp_error (pfile, CPP_DL_WARNING,
- "traditional C rejects the unary plus operator");
- num.overflow = false;
- break;
-
- case CPP_UMINUS:
- num = num_negate (num, CPP_OPTION (pfile, precision));
- break;
-
- case CPP_COMPL:
- num.high = ~num.high;
- num.low = ~num.low;
- num = num_trim (num, CPP_OPTION (pfile, precision));
- num.overflow = false;
- break;
-
- default: /* case CPP_NOT: */
- num.low = num_zerop (num);
- num.high = 0;
- num.overflow = false;
- num.unsignedp = false;
- break;
- }
-
- return num;
-}
-
-/* The various binary operators. */
-static cpp_num
-num_binary_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
-{
- cpp_num result;
- size_t precision = CPP_OPTION (pfile, precision);
- bool gte;
- size_t n;
-
- switch (op)
- {
- /* Shifts. */
- case CPP_LSHIFT:
- case CPP_RSHIFT:
- if (!rhs.unsignedp && !num_positive (rhs, precision))
- {
- /* A negative shift is a positive shift the other way. */
- if (op == CPP_LSHIFT)
- op = CPP_RSHIFT;
- else
- op = CPP_LSHIFT;
- rhs = num_negate (rhs, precision);
- }
- if (rhs.high)
- n = ~0; /* Maximal. */
- else
- n = rhs.low;
- if (op == CPP_LSHIFT)
- lhs = num_lshift (lhs, precision, n);
- else
- lhs = num_rshift (lhs, precision, n);
- break;
-
- /* Min / Max. */
- case CPP_MIN:
- case CPP_MAX:
- {
- bool unsignedp = lhs.unsignedp || rhs.unsignedp;
-
- gte = num_greater_eq (lhs, rhs, precision);
- if (op == CPP_MIN)
- gte = !gte;
- if (!gte)
- lhs = rhs;
- lhs.unsignedp = unsignedp;
- }
- break;
-
- /* Arithmetic. */
- case CPP_MINUS:
- rhs = num_negate (rhs, precision);
- case CPP_PLUS:
- result.low = lhs.low + rhs.low;
- result.high = lhs.high + rhs.high;
- if (result.low < lhs.low)
- result.high++;
- result.unsignedp = lhs.unsignedp || rhs.unsignedp;
- result.overflow = false;
-
- result = num_trim (result, precision);
- if (!result.unsignedp)
- {
- bool lhsp = num_positive (lhs, precision);
- result.overflow = (lhsp == num_positive (rhs, precision)
- && lhsp != num_positive (result, precision));
- }
- return result;
-
- /* Comma. */
- default: /* case CPP_COMMA: */
- if (CPP_PEDANTIC (pfile) && (!CPP_OPTION (pfile, c99)
- || !pfile->state.skip_eval))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "comma operator in operand of #if");
- lhs = rhs;
- break;
- }
-
- return lhs;
-}
-
-/* Multiplies two unsigned cpp_num_parts to give a cpp_num. This
- cannot overflow. */
-static cpp_num
-num_part_mul (cpp_num_part lhs, cpp_num_part rhs)
-{
- cpp_num result;
- cpp_num_part middle[2], temp;
-
- result.low = LOW_PART (lhs) * LOW_PART (rhs);
- result.high = HIGH_PART (lhs) * HIGH_PART (rhs);
-
- middle[0] = LOW_PART (lhs) * HIGH_PART (rhs);
- middle[1] = HIGH_PART (lhs) * LOW_PART (rhs);
-
- temp = result.low;
- result.low += LOW_PART (middle[0]) << (PART_PRECISION / 2);
- if (result.low < temp)
- result.high++;
-
- temp = result.low;
- result.low += LOW_PART (middle[1]) << (PART_PRECISION / 2);
- if (result.low < temp)
- result.high++;
-
- result.high += HIGH_PART (middle[0]);
- result.high += HIGH_PART (middle[1]);
- result.unsignedp = true;
- result.overflow = false;
-
- return result;
-}
-
-/* Multiply two preprocessing numbers. */
-static cpp_num
-num_mul (cpp_reader *pfile, cpp_num lhs, cpp_num rhs)
-{
- cpp_num result, temp;
- bool unsignedp = lhs.unsignedp || rhs.unsignedp;
- bool overflow, negate = false;
- size_t precision = CPP_OPTION (pfile, precision);
-
- /* Prepare for unsigned multiplication. */
- if (!unsignedp)
- {
- if (!num_positive (lhs, precision))
- negate = !negate, lhs = num_negate (lhs, precision);
- if (!num_positive (rhs, precision))
- negate = !negate, rhs = num_negate (rhs, precision);
- }
-
- overflow = lhs.high && rhs.high;
- result = num_part_mul (lhs.low, rhs.low);
-
- temp = num_part_mul (lhs.high, rhs.low);
- result.high += temp.low;
- if (temp.high)
- overflow = true;
-
- temp = num_part_mul (lhs.low, rhs.high);
- result.high += temp.low;
- if (temp.high)
- overflow = true;
-
- temp.low = result.low, temp.high = result.high;
- result = num_trim (result, precision);
- if (!num_eq (result, temp))
- overflow = true;
-
- if (negate)
- result = num_negate (result, precision);
-
- if (unsignedp)
- result.overflow = false;
- else
- result.overflow = overflow || (num_positive (result, precision) ^ !negate
- && !num_zerop (result));
- result.unsignedp = unsignedp;
-
- return result;
-}
-
-/* Divide two preprocessing numbers, returning the answer or the
- remainder depending upon OP. */
-static cpp_num
-num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
-{
- cpp_num result, sub;
- cpp_num_part mask;
- bool unsignedp = lhs.unsignedp || rhs.unsignedp;
- bool negate = false, lhs_neg = false;
- size_t i, precision = CPP_OPTION (pfile, precision);
-
- /* Prepare for unsigned division. */
- if (!unsignedp)
- {
- if (!num_positive (lhs, precision))
- negate = !negate, lhs_neg = true, lhs = num_negate (lhs, precision);
- if (!num_positive (rhs, precision))
- negate = !negate, rhs = num_negate (rhs, precision);
- }
-
- /* Find the high bit. */
- if (rhs.high)
- {
- i = precision - 1;
- mask = (cpp_num_part) 1 << (i - PART_PRECISION);
- for (; ; i--, mask >>= 1)
- if (rhs.high & mask)
- break;
- }
- else if (rhs.low)
- {
- if (precision > PART_PRECISION)
- i = precision - PART_PRECISION - 1;
- else
- i = precision - 1;
- mask = (cpp_num_part) 1 << i;
- for (; ; i--, mask >>= 1)
- if (rhs.low & mask)
- break;
- }
- else
- {
- if (!pfile->state.skip_eval)
- cpp_error (pfile, CPP_DL_ERROR, "division by zero in #if");
- return lhs;
- }
-
- /* First nonzero bit of RHS is bit I. Do naive division by
- shifting the RHS fully left, and subtracting from LHS if LHS is
- at least as big, and then repeating but with one less shift.
- This is not very efficient, but is easy to understand. */
-
- rhs.unsignedp = true;
- lhs.unsignedp = true;
- i = precision - i - 1;
- sub = num_lshift (rhs, precision, i);
-
- result.high = result.low = 0;
- for (;;)
- {
- if (num_greater_eq (lhs, sub, precision))
- {
- lhs = num_binary_op (pfile, lhs, sub, CPP_MINUS);
- if (i >= PART_PRECISION)
- result.high |= (cpp_num_part) 1 << (i - PART_PRECISION);
- else
- result.low |= (cpp_num_part) 1 << i;
- }
- if (i-- == 0)
- break;
- sub.low = (sub.low >> 1) | (sub.high << (PART_PRECISION - 1));
- sub.high >>= 1;
- }
-
- /* We divide so that the remainder has the sign of the LHS. */
- if (op == CPP_DIV)
- {
- result.unsignedp = unsignedp;
- result.overflow = false;
- if (!unsignedp)
- {
- if (negate)
- result = num_negate (result, precision);
- result.overflow = num_positive (result, precision) ^ !negate;
- }
-
- return result;
- }
-
- /* CPP_MOD. */
- lhs.unsignedp = unsignedp;
- lhs.overflow = false;
- if (lhs_neg)
- lhs = num_negate (lhs, precision);
-
- return lhs;
-}
diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c
deleted file mode 100644
index 65db6db5d57..00000000000
--- a/gcc/cppfiles.c
+++ /dev/null
@@ -1,1565 +0,0 @@
-/* Part of CPP library. File handling.
- Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 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
- Reimplemented, Neil Booth, Jul 2003
-
-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 "hashtab.h"
-#include "md5.h"
-#include <dirent.h>
-
-/* Variable length record files on VMS will have a stat size that includes
- record control characters that won't be included in the read size. */
-#ifdef VMS
-# define FAB_C_VAR 2 /* variable length records (see Starlet fabdef.h) */
-# define STAT_SIZE_RELIABLE(ST) ((ST).st_fab_rfm != FAB_C_VAR)
-#else
-# define STAT_SIZE_RELIABLE(ST) true
-#endif
-
-#ifdef __DJGPP__
- /* For DJGPP redirected input is opened in text mode. */
-# define set_stdin_to_binary_mode() \
- if (! isatty (0)) setmode (0, O_BINARY)
-#else
-# define set_stdin_to_binary_mode() /* Nothing */
-#endif
-
-#ifndef O_BINARY
-# define O_BINARY 0
-#endif
-
-/* This structure represents a file searched for by CPP, whether it
- exists or not. An instance may be pointed to by more than one
- file_hash_entry; at present no reference count is kept. */
-struct _cpp_file
-{
- /* Filename as given to #include or command line switch. */
- const char *name;
-
- /* The full path used to find the file. */
- const char *path;
-
- /* The full path of the pch file. */
- const char *pchname;
-
- /* The file's path with the basename stripped. NULL if it hasn't
- been calculated yet. */
- const char *dir_name;
-
- /* Chain through all files. */
- struct _cpp_file *next_file;
-
- /* The contents of NAME after calling read_file(). */
- const uchar *buffer;
-
- /* The macro, if any, preventing re-inclusion. */
- const cpp_hashnode *cmacro;
-
- /* The directory in the search path where FILE was found. Used for
- #include_next and determining whether a header is a system
- header. */
- cpp_dir *dir;
-
- /* As filled in by stat(2) for the file. */
- struct stat st;
-
- /* File descriptor. Invalid if -1, otherwise open. */
- int fd;
-
- /* Zero if this file was successfully opened and stat()-ed,
- otherwise errno obtained from failure. */
- int err_no;
-
- /* Number of times the file has been stacked for preprocessing. */
- unsigned short stack_count;
-
- /* If opened with #import or contains #pragma once. */
- bool once_only;
-
- /* If read() failed before. */
- bool dont_read;
-
- /* If this file is the main file. */
- bool main_file;
-
- /* If BUFFER above contains the true contents of the file. */
- bool buffer_valid;
-
- /* File is a PCH (on return from find_include_file). */
- bool pch;
-};
-
-/* A singly-linked list for all searches for a given file name, with
- its head pointed to by a slot in FILE_HASH. The file name is what
- appeared between the quotes in a #include directive; it can be
- determined implicitly from the hash table location or explicitly
- from FILE->name.
-
- FILE is a structure containing details about the file that was
- found with that search, or details of how the search failed.
-
- START_DIR is the starting location of the search in the include
- chain. The current directories for "" includes are also hashed in
- the hash table and therefore unique. Files that are looked up
- without using a search path, such as absolute filenames and file
- names from the command line share a special starting directory so
- they don't cause cache hits with normal include-chain lookups.
-
- If START_DIR is NULL then the entry is for a directory, not a file,
- and the directory is in DIR. Since the starting point in a file
- lookup chain is never NULL, this means that simple pointer
- comparisons against START_DIR can be made to determine cache hits
- in file lookups.
-
- If a cache lookup fails because of e.g. an extra "./" in the path,
- then nothing will break. It is just less efficient as CPP will
- have to do more work re-preprocessing the file, and/or comparing
- its contents against earlier once-only files.
-*/
-struct file_hash_entry
-{
- struct file_hash_entry *next;
- cpp_dir *start_dir;
- union
- {
- _cpp_file *file;
- cpp_dir *dir;
- } u;
-};
-
-static bool open_file (_cpp_file *file);
-static bool pch_open_file (cpp_reader *pfile, _cpp_file *file,
- bool *invalid_pch);
-static bool find_file_in_dir (cpp_reader *pfile, _cpp_file *file,
- bool *invalid_pch);
-static bool read_file_guts (cpp_reader *pfile, _cpp_file *file);
-static bool read_file (cpp_reader *pfile, _cpp_file *file);
-static bool should_stack_file (cpp_reader *, _cpp_file *file, bool import);
-static struct cpp_dir *search_path_head (cpp_reader *, const char *fname,
- int angle_brackets, enum include_type);
-static const char *dir_name_of_file (_cpp_file *file);
-static void open_file_failed (cpp_reader *pfile, _cpp_file *file);
-static struct file_hash_entry *search_cache (struct file_hash_entry *head,
- const cpp_dir *start_dir);
-static _cpp_file *make_cpp_file (cpp_reader *, cpp_dir *, const char *fname);
-static cpp_dir *make_cpp_dir (cpp_reader *, const char *dir_name, int sysp);
-static void allocate_file_hash_entries (cpp_reader *pfile);
-static struct file_hash_entry *new_file_hash_entry (cpp_reader *pfile);
-static int report_missing_guard (void **slot, void *b);
-static hashval_t file_hash_hash (const void *p);
-static int file_hash_eq (const void *p, const void *q);
-static char *read_filename_string (int ch, FILE *f);
-static void read_name_map (cpp_dir *dir);
-static char *remap_filename (cpp_reader *pfile, _cpp_file *file);
-static char *append_file_to_dir (const char *fname, cpp_dir *dir);
-static bool validate_pch (cpp_reader *, _cpp_file *file, const char *pchname);
-static int pchf_adder (void **slot, void *data);
-static int pchf_save_compare (const void *e1, const void *e2);
-static int pchf_compare (const void *d_p, const void *e_p);
-static bool check_file_against_entries (cpp_reader *, _cpp_file *, bool);
-
-/* Given a filename in FILE->PATH, with the empty string interpreted
- as <stdin>, open it.
-
- On success FILE contains an open file descriptor and stat
- information for the file. On failure the file descriptor is -1 and
- the appropriate errno is also stored in FILE. Returns TRUE iff
- successful.
-
- 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. */
-static bool
-open_file (_cpp_file *file)
-{
- if (file->path[0] == '\0')
- {
- file->fd = 0;
- set_stdin_to_binary_mode ();
- }
- else
- file->fd = open (file->path, O_RDONLY | O_NOCTTY | O_BINARY, 0666);
-
- if (file->fd != -1)
- {
- if (fstat (file->fd, &file->st) == 0)
- {
- if (!S_ISDIR (file->st.st_mode))
- {
- file->err_no = 0;
- return true;
- }
-
- /* Ignore a directory and continue the search. The file we're
- looking for may be elsewhere in the search path. */
- errno = ENOENT;
- }
-
- close (file->fd);
- file->fd = -1;
- }
- else if (errno == ENOTDIR)
- errno = ENOENT;
-
- file->err_no = errno;
-
- return false;
-}
-
-/* Temporary PCH intercept of opening a file. Try to find a PCH file
- based on FILE->name and FILE->dir, and test those found for
- validity using PFILE->cb.valid_pch. Return true iff a valid file is
- found. Set *INVALID_PCH if a PCH file is found but wasn't valid. */
-
-static bool
-pch_open_file (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch)
-{
- static const char extension[] = ".gch";
- const char *path = file->path;
- size_t len, flen;
- char *pchname;
- struct stat st;
- bool valid = false;
-
- /* No PCH on <stdin> or if not requested. */
- if (file->name[0] == '\0' || !pfile->cb.valid_pch)
- return false;
-
- flen = strlen (path);
- len = flen + sizeof (extension);
- pchname = xmalloc (len);
- memcpy (pchname, path, flen);
- memcpy (pchname + flen, extension, sizeof (extension));
-
- if (stat (pchname, &st) == 0)
- {
- DIR *pchdir;
- struct dirent *d;
- size_t dlen, plen = len;
-
- if (!S_ISDIR (st.st_mode))
- valid = validate_pch (pfile, file, pchname);
- else if ((pchdir = opendir (pchname)) != NULL)
- {
- pchname[plen - 1] = '/';
- while ((d = readdir (pchdir)) != NULL)
- {
- dlen = strlen (d->d_name) + 1;
- if ((strcmp (d->d_name, ".") == 0)
- || (strcmp (d->d_name, "..") == 0))
- continue;
- if (dlen + plen > len)
- {
- len += dlen + 64;
- pchname = xrealloc (pchname, len);
- }
- memcpy (pchname + plen, d->d_name, dlen);
- valid = validate_pch (pfile, file, pchname);
- if (valid)
- break;
- }
- closedir (pchdir);
- }
- if (valid)
- file->pch = true;
- else
- *invalid_pch = true;
- }
-
- if (valid)
- file->pchname = pchname;
- else
- free (pchname);
-
- return valid;
-}
-
-/* Try to open the path FILE->name appended to FILE->dir. This is
- where remap and PCH intercept the file lookup process. Return true
- if the file was found, whether or not the open was successful.
- Set *INVALID_PCH to true if a PCH file is found but wasn't valid. */
-
-static bool
-find_file_in_dir (cpp_reader *pfile, _cpp_file *file, bool *invalid_pch)
-{
- char *path;
-
- if (CPP_OPTION (pfile, remap) && (path = remap_filename (pfile, file)))
- ;
- else
- if (file->dir->construct)
- path = file->dir->construct (file->name, file->dir);
- else
- path = append_file_to_dir (file->name, file->dir);
-
- if (path)
- {
- file->path = path;
- if (pch_open_file (pfile, file, invalid_pch))
- return true;
-
- if (open_file (file))
- return true;
-
- if (file->err_no != ENOENT)
- {
- open_file_failed (pfile, file);
- return true;
- }
-
- free (path);
- file->path = file->name;
- }
- else
- {
- file->err_no = ENOENT;
- file->path = NULL;
- }
-
- return false;
-}
-
-/* Return tue iff the missing_header callback found the given HEADER. */
-static bool
-search_path_exhausted (cpp_reader *pfile, const char *header, _cpp_file *file)
-{
- missing_header_cb func = pfile->cb.missing_header;
-
- /* When the regular search path doesn't work, try context dependent
- headers search paths. */
- if (func
- && file->dir == NULL)
- {
- if ((file->path = func (pfile, header, &file->dir)) != NULL)
- {
- if (open_file (file))
- return true;
- free ((void *)file->path);
- }
- file->path = file->name;
- }
-
- return false;
-}
-
-bool
-_cpp_find_failed (_cpp_file *file)
-{
- return file->err_no != 0;
-}
-
-/* Given a filename FNAME search for such a file in the include path
- starting from START_DIR. If FNAME is the empty string it is
- interpreted as STDIN if START_DIR is PFILE->no_search_path.
-
- If the file is not found in the file cache fall back to the O/S and
- add the result to our cache.
-
- If the file was not found in the filesystem, or there was an error
- opening it, then ERR_NO is nonzero and FD is -1. If the file was
- found, then ERR_NO is zero and FD could be -1 or an open file
- descriptor. FD can be -1 if the file was found in the cache and
- had previously been closed. To open it again pass the return value
- to open_file().
-*/
-_cpp_file *
-_cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir, bool fake)
-{
- struct file_hash_entry *entry, **hash_slot;
- _cpp_file *file;
- bool invalid_pch = false;
-
- /* Ensure we get no confusion between cached files and directories. */
- if (start_dir == NULL)
- cpp_error (pfile, CPP_DL_ICE, "NULL directory in find_file");
-
- hash_slot = (struct file_hash_entry **)
- htab_find_slot_with_hash (pfile->file_hash, fname,
- htab_hash_string (fname),
- INSERT);
-
- /* First check the cache before we resort to memory allocation. */
- entry = search_cache (*hash_slot, start_dir);
- if (entry)
- return entry->u.file;
-
- file = make_cpp_file (pfile, start_dir, fname);
-
- /* Try each path in the include chain. */
- for (; !fake ;)
- {
- if (find_file_in_dir (pfile, file, &invalid_pch))
- break;
-
- file->dir = file->dir->next;
- if (file->dir == NULL)
- {
- if (search_path_exhausted (pfile, fname, file))
- return file;
-
- open_file_failed (pfile, file);
- if (invalid_pch)
- {
- cpp_error (pfile, CPP_DL_ERROR,
- "one or more PCH files were found, but they were invalid");
- if (!cpp_get_options (pfile)->warn_invalid_pch)
- cpp_error (pfile, CPP_DL_ERROR,
- "use -Winvalid-pch for more information");
- }
- break;
- }
-
- /* Only check the cache for the starting location (done above)
- and the quote and bracket chain heads because there are no
- other possible starting points for searches. */
- if (file->dir != pfile->bracket_include
- && file->dir != pfile->quote_include)
- continue;
-
- entry = search_cache (*hash_slot, file->dir);
- if (entry)
- break;
- }
-
- if (entry)
- {
- /* Cache for START_DIR too, sharing the _cpp_file structure. */
- free ((char *) file->name);
- free (file);
- file = entry->u.file;
- }
- else
- {
- /* This is a new file; put it in the list. */
- file->next_file = pfile->all_files;
- pfile->all_files = file;
- }
-
- /* Store this new result in the hash table. */
- entry = new_file_hash_entry (pfile);
- entry->next = *hash_slot;
- entry->start_dir = start_dir;
- entry->u.file = file;
- *hash_slot = entry;
-
- return file;
-}
-
-/* Read a file into FILE->buffer, returning true on success.
-
- If FILE->fd is something weird, like a block device, we don't want
- to read it at all. Don't even try to figure out what something is,
- except for plain files and block devices, since there is no
- reliable portable way of doing this.
-
- FIXME: Flush file cache and try again if we run out of memory. */
-static bool
-read_file_guts (cpp_reader *pfile, _cpp_file *file)
-{
- ssize_t size, total, count;
- uchar *buf;
- bool regular;
-
- if (S_ISBLK (file->st.st_mode))
- {
- cpp_error (pfile, CPP_DL_ERROR, "%s is a block device", file->path);
- return false;
- }
-
- regular = S_ISREG (file->st.st_mode);
- if (regular)
- {
- /* 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 (file->st.st_size > INTTYPE_MAXIMUM (ssize_t))
- {
- cpp_error (pfile, CPP_DL_ERROR, "%s is too large", file->path);
- return false;
- }
-
- size = file->st.st_size;
- }
- 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 = xmalloc (size + 1);
- total = 0;
- while ((count = read (file->fd, buf + total, size - total)) > 0)
- {
- total += count;
-
- if (total == size)
- {
- if (regular)
- break;
- size *= 2;
- buf = xrealloc (buf, size + 1);
- }
- }
-
- if (count < 0)
- {
- cpp_errno (pfile, CPP_DL_ERROR, file->path);
- return false;
- }
-
- if (regular && total != size && STAT_SIZE_RELIABLE (file->st))
- cpp_error (pfile, CPP_DL_WARNING,
- "%s is shorter than expected", file->path);
-
- file->buffer = _cpp_convert_input (pfile, CPP_OPTION (pfile, input_charset),
- buf, size, total, &file->st.st_size);
- file->buffer_valid = true;
-
- return true;
-}
-
-/* Convenience wrapper around read_file_guts that opens the file if
- necessary and closes the file descriptor after reading. FILE must
- have been passed through find_file() at some stage. */
-static bool
-read_file (cpp_reader *pfile, _cpp_file *file)
-{
- /* If we already have its contents in memory, succeed immediately. */
- if (file->buffer_valid)
- return true;
-
- /* If an earlier read failed for some reason don't try again. */
- if (file->dont_read || file->err_no)
- return false;
-
- if (file->fd == -1 && !open_file (file))
- {
- open_file_failed (pfile, file);
- return false;
- }
-
- file->dont_read = !read_file_guts (pfile, file);
- close (file->fd);
- file->fd = -1;
-
- return !file->dont_read;
-}
-
-/* Returns TRUE if FILE's contents have been successfully placed in
- FILE->buffer and the file should be stacked, otherwise false. */
-static bool
-should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import)
-{
- _cpp_file *f;
-
- /* Skip once-only files. */
- if (file->once_only)
- return false;
-
- /* We must mark the file once-only if #import now, before header
- guard checks. Otherwise, undefining the header guard might
- cause the file to be re-stacked. */
- if (import)
- {
- _cpp_mark_file_once_only (pfile, file);
-
- /* Don't stack files that have been stacked before. */
- if (file->stack_count)
- return false;
- }
-
- /* Skip if the file had a header guard and the macro is defined.
- PCH relies on this appearing before the PCH handler below. */
- if (file->cmacro && file->cmacro->type == NT_MACRO)
- return false;
-
- /* Handle PCH files immediately; don't stack them. */
- if (file->pch)
- {
- pfile->cb.read_pch (pfile, file->path, file->fd, file->pchname);
- close (file->fd);
- file->fd = -1;
- return false;
- }
-
- if (!read_file (pfile, file))
- return false;
-
- /* Check the file against the PCH file. This is done before
- checking against files we've already seen, since it may save on
- I/O. */
- if (check_file_against_entries (pfile, file, import))
- {
- /* If this isn't a #import, but yet we can't include the file,
- that means that it was #import-ed in the PCH file,
- so we can never include it again. */
- if (! import)
- _cpp_mark_file_once_only (pfile, file);
- return false;
- }
-
- /* Now we've read the file's contents, we can stack it if there
- are no once-only files. */
- if (!pfile->seen_once_only)
- return true;
-
- /* We may have read the file under a different name. Look
- for likely candidates and compare file contents to be sure. */
- for (f = pfile->all_files; f; f = f->next_file)
- {
- if (f == file)
- continue;
-
- if ((import || f->once_only)
- && f->err_no == 0
- && f->st.st_mtime == file->st.st_mtime
- && f->st.st_size == file->st.st_size
- && read_file (pfile, f)
- /* Size might have changed in read_file(). */
- && f->st.st_size == file->st.st_size
- && !memcmp (f->buffer, file->buffer, f->st.st_size))
- break;
- }
-
- return f == NULL;
-}
-
-/* Place the file referenced by FILE into a new buffer on the buffer
- stack if possible. IMPORT is true if this stacking attempt is
- because of a #import directive. Returns true if a buffer is
- stacked. */
-bool
-_cpp_stack_file (cpp_reader *pfile, _cpp_file *file, bool import)
-{
- cpp_buffer *buffer;
- int sysp;
-
- if (!should_stack_file (pfile, file, import))
- return false;
-
- if (pfile->buffer == NULL || file->dir == NULL)
- sysp = 0;
- else
- sysp = MAX (pfile->buffer->sysp, file->dir->sysp);
-
- /* Add the file to the dependencies on its first inclusion. */
- if (CPP_OPTION (pfile, deps.style) > !!sysp && !file->stack_count)
- {
- if (!file->main_file || !CPP_OPTION (pfile, deps.ignore_main_file))
- deps_add_dep (pfile->deps, file->path);
- }
-
- /* Clear buffer_valid since _cpp_clean_line messes it up. */
- file->buffer_valid = false;
- file->stack_count++;
-
- /* Stack the buffer. */
- buffer = cpp_push_buffer (pfile, file->buffer, file->st.st_size,
- CPP_OPTION (pfile, preprocessed));
- buffer->file = file;
- buffer->sysp = sysp;
-
- /* Initialize controlling macro state. */
- pfile->mi_valid = true;
- pfile->mi_cmacro = 0;
-
- /* Generate the call back. */
- _cpp_do_file_change (pfile, LC_ENTER, file->path, 1, sysp);
-
- return true;
-}
-
-/* Mark FILE to be included once only. */
-void
-_cpp_mark_file_once_only (cpp_reader *pfile, _cpp_file *file)
-{
- pfile->seen_once_only = true;
- file->once_only = true;
-}
-
-/* Return the directory from which searching for FNAME should start,
- considering the directive TYPE and ANGLE_BRACKETS. If there is
- nothing left in the path, returns NULL. */
-static struct cpp_dir *
-search_path_head (cpp_reader *pfile, const char *fname, int angle_brackets,
- enum include_type type)
-{
- cpp_dir *dir;
- _cpp_file *file;
-
- if (IS_ABSOLUTE_PATH (fname))
- return &pfile->no_search_path;
-
- /* pfile->buffer is NULL when processing an -include command-line flag. */
- file = pfile->buffer == NULL ? pfile->main_file : pfile->buffer->file;
-
- /* 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 && file->dir)
- dir = file->dir->next;
- else if (angle_brackets)
- dir = pfile->bracket_include;
- else if (type == IT_CMDLINE)
- /* -include and -imacros use the #include "" chain with the
- preprocessor's cwd prepended. */
- return make_cpp_dir (pfile, "./", false);
- else if (pfile->quote_ignores_source_dir)
- dir = pfile->quote_include;
- else
- return make_cpp_dir (pfile, dir_name_of_file (file),
- pfile->buffer ? pfile->buffer->sysp : 0);
-
- if (dir == NULL)
- cpp_error (pfile, CPP_DL_ERROR,
- "no include path in which to search for %s", fname);
-
- return dir;
-}
-
-/* Strip the basename from the file's path. It ends with a slash if
- of nonzero length. Note that this procedure also works for
- <stdin>, which is represented by the empty string. */
-static const char *
-dir_name_of_file (_cpp_file *file)
-{
- if (!file->dir_name)
- {
- size_t len = lbasename (file->path) - file->path;
- char *dir_name = xmalloc (len + 1);
-
- memcpy (dir_name, file->path, len);
- dir_name[len] = '\0';
- file->dir_name = dir_name;
- }
-
- return file->dir_name;
-}
-
-/* Handles #include-family directives (distinguished by TYPE),
- including HEADER, and the command line -imacros and -include.
- Returns true if a buffer was stacked. */
-bool
-_cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets,
- enum include_type type)
-{
- struct cpp_dir *dir;
- _cpp_file *file;
-
- dir = search_path_head (pfile, fname, angle_brackets, type);
- if (!dir)
- return false;
-
- file = _cpp_find_file (pfile, fname, dir, false);
-
- /* Compensate for the increment in linemap_add. In the case of a
- normal #include, we're currently at the start of the line
- *following* the #include. A separate source_location for this
- location makes no sense (until we do the LC_LEAVE), and
- complicates LAST_SOURCE_LINE_LOCATION. This does not apply if we
- found a PCH file (in which case linemap_add is not called) or we
- were included from the command-line. */
- if (! file->pch && file->err_no == 0 && type != IT_CMDLINE)
- pfile->line_table->highest_location--;
-
- return _cpp_stack_file (pfile, file, type == IT_IMPORT);
-}
-
-/* Could not open FILE. The complication is dependency output. */
-static void
-open_file_failed (cpp_reader *pfile, _cpp_file *file)
-{
- int sysp = pfile->line_table->highest_line > 1 && pfile->buffer ? pfile->buffer->sysp : 0;
- bool print_dep = CPP_OPTION (pfile, deps.style) > !!sysp;
-
- errno = file->err_no;
- if (print_dep && CPP_OPTION (pfile, deps.missing_files) && errno == ENOENT)
- deps_add_dep (pfile->deps, file->name);
- else
- {
- /* If we are outputting dependencies but not for this file then
- don't error because we can still produce correct output. */
- if (CPP_OPTION (pfile, deps.style) && ! print_dep)
- cpp_errno (pfile, CPP_DL_WARNING, file->path);
- else
- cpp_errno (pfile, CPP_DL_ERROR, file->path);
- }
-}
-
-/* Search in the chain beginning at HEAD for a file whose search path
- started at START_DIR != NULL. */
-static struct file_hash_entry *
-search_cache (struct file_hash_entry *head, const cpp_dir *start_dir)
-{
- while (head && head->start_dir != start_dir)
- head = head->next;
-
- return head;
-}
-
-/* Allocate a new _cpp_file structure. */
-static _cpp_file *
-make_cpp_file (cpp_reader *pfile, cpp_dir *dir, const char *fname)
-{
- _cpp_file *file;
-
- file = xcalloc (1, sizeof (_cpp_file));
- file->main_file = !pfile->buffer;
- file->fd = -1;
- file->dir = dir;
- file->name = xstrdup (fname);
-
- return file;
-}
-
-/* A hash of directory names. The directory names are the path names
- of files which contain a #include "", the included file name is
- appended to this directories.
-
- To avoid duplicate entries we follow the convention that all
- non-empty directory names should end in a '/'. DIR_NAME must be
- stored in permanently allocated memory. */
-static cpp_dir *
-make_cpp_dir (cpp_reader *pfile, const char *dir_name, int sysp)
-{
- struct file_hash_entry *entry, **hash_slot;
- cpp_dir *dir;
-
- hash_slot = (struct file_hash_entry **)
- htab_find_slot_with_hash (pfile->file_hash, dir_name,
- htab_hash_string (dir_name),
- INSERT);
-
- /* Have we already hashed this directory? */
- for (entry = *hash_slot; entry; entry = entry->next)
- if (entry->start_dir == NULL)
- return entry->u.dir;
-
- dir = xcalloc (1, sizeof (cpp_dir));
- dir->next = pfile->quote_include;
- dir->name = (char *) dir_name;
- dir->len = strlen (dir_name);
- dir->sysp = sysp;
- dir->construct = 0;
-
- /* Store this new result in the hash table. */
- entry = new_file_hash_entry (pfile);
- entry->next = *hash_slot;
- entry->start_dir = NULL;
- entry->u.dir = dir;
- *hash_slot = entry;
-
- return dir;
-}
-
-/* Create a new block of memory for file hash entries. */
-static void
-allocate_file_hash_entries (cpp_reader *pfile)
-{
- pfile->file_hash_entries_used = 0;
- pfile->file_hash_entries_allocated = 127;
- pfile->file_hash_entries = xmalloc
- (pfile->file_hash_entries_allocated * sizeof (struct file_hash_entry));
-}
-
-/* Return a new file hash entry. */
-static struct file_hash_entry *
-new_file_hash_entry (cpp_reader *pfile)
-{
- if (pfile->file_hash_entries_used == pfile->file_hash_entries_allocated)
- allocate_file_hash_entries (pfile);
-
- return &pfile->file_hash_entries[pfile->file_hash_entries_used++];
-}
-
-/* Returns TRUE if a file FNAME has ever been successfully opened.
- This routine is not intended to correctly handle filenames aliased
- by links or redundant . or .. traversals etc. */
-bool
-cpp_included (cpp_reader *pfile, const char *fname)
-{
- struct file_hash_entry *entry;
-
- entry = htab_find_with_hash (pfile->file_hash, fname,
- htab_hash_string (fname));
-
- while (entry && (entry->start_dir == NULL || entry->u.file->err_no))
- entry = entry->next;
-
- return entry != NULL;
-}
-
-/* Calculate the hash value of a file hash entry P. */
-
-static hashval_t
-file_hash_hash (const void *p)
-{
- struct file_hash_entry *entry = (struct file_hash_entry *) p;
- const char *hname;
- if (entry->start_dir)
- hname = entry->u.file->name;
- else
- hname = entry->u.dir->name;
-
- return htab_hash_string (hname);
-}
-
-/* Compare a string Q against a file hash entry P. */
-static int
-file_hash_eq (const void *p, const void *q)
-{
- struct file_hash_entry *entry = (struct file_hash_entry *) p;
- const char *fname = (const char *) q;
- const char *hname;
-
- if (entry->start_dir)
- hname = entry->u.file->name;
- else
- hname = entry->u.dir->name;
-
- return strcmp (hname, fname) == 0;
-}
-
-/* Initialize everything in this source file. */
-void
-_cpp_init_files (cpp_reader *pfile)
-{
- pfile->file_hash = htab_create_alloc (127, file_hash_hash, file_hash_eq,
- NULL, xcalloc, free);
- allocate_file_hash_entries (pfile);
-}
-
-/* Finalize everything in this source file. */
-void
-_cpp_cleanup_files (cpp_reader *pfile)
-{
- htab_delete (pfile->file_hash);
-}
-
-/* Enter a file name in the hash for the sake of cpp_included. */
-void
-_cpp_fake_include (cpp_reader *pfile, const char *fname)
-{
- _cpp_find_file (pfile, fname, pfile->buffer->file->dir, true);
-}
-
-/* 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 (cpp_reader *pfile, int syshdr, int externc)
-{
- int flags = 0;
- const struct line_maps *line_table = pfile->line_table;
- const struct line_map *map = &line_table->maps[line_table->used-1];
-
- /* 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, LC_RENAME, map->to_file,
- SOURCE_LINE (map, pfile->line_table->highest_line), flags);
-}
-
-/* Allow the client to change the current file. Used by the front end
- to achieve pseudo-file names like <built-in>.
- If REASON is LC_LEAVE, then NEW_NAME must be NULL. */
-void
-cpp_change_file (cpp_reader *pfile, enum lc_reason reason,
- const char *new_name)
-{
- _cpp_do_file_change (pfile, reason, new_name, 1, 0);
-}
-
-/* Callback function for htab_traverse. */
-static int
-report_missing_guard (void **slot, void *b)
-{
- struct file_hash_entry *entry = (struct file_hash_entry *) *slot;
- int *bannerp = (int *) b;
-
- /* Skip directories. */
- if (entry->start_dir != NULL)
- {
- _cpp_file *file = entry->u.file;
-
- /* We don't want MI guard advice for the main file. */
- if (file->cmacro == NULL && file->stack_count == 1 && !file->main_file)
- {
- if (*bannerp == 0)
- {
- fputs (_("Multiple include guards may be useful for:\n"),
- stderr);
- *bannerp = 1;
- }
-
- fputs (entry->u.file->path, stderr);
- putc ('\n', stderr);
- }
- }
-
- return 0;
-}
-
-/* Report on all files that might benefit from a multiple include guard.
- Triggered by -H. */
-void
-_cpp_report_missing_guards (cpp_reader *pfile)
-{
- int banner = 0;
-
- htab_traverse (pfile->file_hash, report_missing_guard, &banner);
-}
-
-/* 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, return 1, otherwise 0. */
-int
-_cpp_compare_file_date (cpp_reader *pfile, const char *fname,
- int angle_brackets)
-{
- _cpp_file *file;
- struct cpp_dir *dir;
-
- dir = search_path_head (pfile, fname, angle_brackets, IT_INCLUDE);
- if (!dir)
- return -1;
-
- file = _cpp_find_file (pfile, fname, dir, false);
- if (file->err_no)
- return -1;
-
- if (file->fd != -1)
- {
- close (file->fd);
- file->fd = -1;
- }
-
- return file->st.st_mtime > pfile->buffer->file->st.st_mtime;
-}
-
-/* Pushes the given file onto the buffer stack. Returns nonzero if
- successful. */
-bool
-cpp_push_include (cpp_reader *pfile, const char *fname)
-{
- return _cpp_stack_include (pfile, fname, false, IT_CMDLINE);
-}
-
-/* Do appropriate cleanup when a file INC's buffer is popped off the
- input stack. */
-void
-_cpp_pop_file_buffer (cpp_reader *pfile, _cpp_file *file)
-{
- /* Record the inclusion-preventing macro, which could be NULL
- meaning no controlling macro. */
- if (pfile->mi_valid && file->cmacro == NULL)
- file->cmacro = pfile->mi_cmacro;
-
- /* Invalidate control macros in the #including file. */
- pfile->mi_valid = false;
-
- if (file->buffer)
- {
- free ((void *) file->buffer);
- file->buffer = NULL;
- }
-}
-
-/* Set the include chain for "" to QUOTE, for <> to BRACKET. If
- QUOTE_IGNORES_SOURCE_DIR, then "" includes do not look in the
- directory of the including file.
-
- If BRACKET does not lie in the QUOTE chain, it is set to QUOTE. */
-void
-cpp_set_include_chains (cpp_reader *pfile, cpp_dir *quote, cpp_dir *bracket,
- int quote_ignores_source_dir)
-{
- pfile->quote_include = quote;
- pfile->bracket_include = quote;
- pfile->quote_ignores_source_dir = quote_ignores_source_dir;
-
- for (; quote; quote = quote->next)
- {
- quote->name_map = NULL;
- quote->len = strlen (quote->name);
- if (quote == bracket)
- pfile->bracket_include = bracket;
- }
-}
-
-/* Append the file name to the directory to create the path, but don't
- turn / into // or // into ///; // may be a namespace escape. */
-static char *
-append_file_to_dir (const char *fname, cpp_dir *dir)
-{
- size_t dlen, flen;
- char *path;
-
- dlen = dir->len;
- flen = strlen (fname);
- path = xmalloc (dlen + 1 + flen + 1);
- memcpy (path, dir->name, dlen);
- if (dlen && path[dlen - 1] != '/')
- path[dlen++] = '/';
- memcpy (&path[dlen], fname, flen + 1);
-
- return path;
-}
-
-/* Read a space delimited string of unlimited length from a stdio
- file F. */
-static char *
-read_filename_string (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;
-}
-
-/* Read the file name map file for DIR. */
-static void
-read_name_map (cpp_dir *dir)
-{
- static const char FILE_NAME_MAP_FILE[] = "header.gcc";
- char *name;
- FILE *f;
- size_t len, count = 0, room = 9;
-
- len = dir->len;
- name = alloca (len + sizeof (FILE_NAME_MAP_FILE) + 1);
- memcpy (name, dir->name, len);
- if (len && name[len - 1] != '/')
- name[len++] = '/';
- strcpy (name + len, FILE_NAME_MAP_FILE);
- f = fopen (name, "r");
-
- dir->name_map = xmalloc (room * sizeof (char *));
-
- /* Silently return NULL if we cannot open. */
- if (f)
- {
- int ch;
-
- while ((ch = getc (f)) != EOF)
- {
- char *to;
-
- if (is_space (ch))
- continue;
-
- if (count + 2 > room)
- {
- room += 8;
- dir->name_map = xrealloc (dir->name_map, room * sizeof (char *));
- }
-
- dir->name_map[count] = read_filename_string (ch, f);
- while ((ch = getc (f)) != EOF && is_hspace (ch))
- ;
-
- to = read_filename_string (ch, f);
- if (IS_ABSOLUTE_PATH (to))
- dir->name_map[count + 1] = to;
- else
- {
- dir->name_map[count + 1] = append_file_to_dir (to, dir);
- free (to);
- }
-
- count += 2;
- while ((ch = getc (f)) != '\n')
- if (ch == EOF)
- break;
- }
-
- fclose (f);
- }
-
- /* Terminate the list of maps. */
- dir->name_map[count] = NULL;
-}
-
-/* Remap a FILE's name based on the file_name_map, if any, for
- FILE->dir. If the file name has any directory separators,
- recursively check those directories too. */
-static char *
-remap_filename (cpp_reader *pfile, _cpp_file *file)
-{
- const char *fname, *p;
- char *new_dir;
- cpp_dir *dir;
- size_t index, len;
-
- dir = file->dir;
- fname = file->name;
-
- for (;;)
- {
- if (!dir->name_map)
- read_name_map (dir);
-
- for (index = 0; dir->name_map[index]; index += 2)
- if (!strcmp (dir->name_map[index], fname))
- return xstrdup (dir->name_map[index + 1]);
-
- p = strchr (fname, '/');
- if (!p || p == fname)
- return NULL;
-
- len = dir->len + (p - fname + 1);
- new_dir = xmalloc (len + 1);
- memcpy (new_dir, dir->name, dir->len);
- memcpy (new_dir + dir->len, fname, p - fname + 1);
- new_dir[len] = '\0';
-
- dir = make_cpp_dir (pfile, new_dir, dir->sysp);
- fname = p + 1;
- }
-}
-
-/* Returns true if PCHNAME is a valid PCH file for FILE. */
-static bool
-validate_pch (cpp_reader *pfile, _cpp_file *file, const char *pchname)
-{
- const char *saved_path = file->path;
- bool valid = false;
-
- file->path = pchname;
- if (open_file (file))
- {
- valid = 1 & pfile->cb.valid_pch (pfile, pchname, file->fd);
-
- if (!valid)
- {
- close (file->fd);
- file->fd = -1;
- }
-
- if (CPP_OPTION (pfile, print_include_names))
- {
- unsigned int i;
- for (i = 1; i < pfile->line_table->depth; i++)
- putc ('.', stderr);
- fprintf (stderr, "%c %s\n",
- valid ? '!' : 'x', pchname);
- }
- }
-
- file->path = saved_path;
- return valid;
-}
-
-/* Get the path associated with the _cpp_file F. The path includes
- the base name from the include directive and the directory it was
- found in via the search path. */
-
-const char *
-cpp_get_path (struct _cpp_file *f)
-{
- return f->path;
-}
-
-/* Get the directory associated with the _cpp_file F. */
-
-cpp_dir *
-cpp_get_dir (struct _cpp_file *f)
-{
- return f->dir;
-}
-
-/* Get the cpp_buffer currently associated with the cpp_reader
- PFILE. */
-
-cpp_buffer *
-cpp_get_buffer (cpp_reader *pfile)
-{
- return pfile->buffer;
-}
-
-/* Get the _cpp_file associated with the cpp_buffer B. */
-
-_cpp_file *
-cpp_get_file (cpp_buffer *b)
-{
- return b->file;
-}
-
-/* Get the previous cpp_buffer given a cpp_buffer B. The previous
- buffer is the buffer that included the given buffer. */
-
-cpp_buffer *
-cpp_get_prev (cpp_buffer *b)
-{
- return b->prev;
-}
-
-/* This data structure holds the list of header files that were seen
- while the PCH was being built. The 'entries' field is kept sorted
- in memcmp() order; yes, this means that on little-endian systems,
- it's sorted initially by the least-significant byte of 'size', but
- that's OK. The code does rely on having entries with the same size
- next to each other. */
-
-struct pchf_data {
- /* Number of pchf_entry structures. */
- size_t count;
-
- /* Are there any values with once_only set?
- This is used as an optimisation, it means we don't have to search
- the structure if we're processing a regular #include. */
- bool have_once_only;
-
- struct pchf_entry {
- /* The size of this file. This is used to save running a MD5 checksum
- if the sizes don't match. */
- off_t size;
- /* The MD5 checksum of this file. */
- unsigned char sum[16];
- /* Is this file to be included only once? */
- bool once_only;
- } entries[1];
-};
-
-static struct pchf_data *pchf;
-
-/* Data for pchf_addr. */
-struct pchf_adder_info
-{
- cpp_reader *pfile;
- struct pchf_data *d;
-};
-
-/* A hash traversal function to add entries into DATA->D. */
-
-static int
-pchf_adder (void **slot, void *data)
-{
- struct file_hash_entry *h = (struct file_hash_entry *) *slot;
- struct pchf_adder_info *i = (struct pchf_adder_info *) data;
-
- if (h->start_dir != NULL && h->u.file->stack_count != 0)
- {
- struct pchf_data *d = i->d;
- _cpp_file *f = h->u.file;
- size_t count = d->count++;
-
- /* This should probably never happen, since if a read error occurred
- the PCH file shouldn't be written... */
- if (f->dont_read || f->err_no)
- return 1;
-
- d->entries[count].once_only = f->once_only;
- /* |= is avoided in the next line because of an HP C compiler bug */
- d->have_once_only = d->have_once_only | f->once_only;
- if (f->buffer_valid)
- md5_buffer ((const char *)f->buffer,
- f->st.st_size, d->entries[count].sum);
- else
- {
- FILE *ff;
- int oldfd = f->fd;
-
- if (!open_file (f))
- {
- open_file_failed (i->pfile, f);
- return 0;
- }
- ff = fdopen (f->fd, "rb");
- md5_stream (ff, d->entries[count].sum);
- fclose (ff);
- f->fd = oldfd;
- }
- d->entries[count].size = f->st.st_size;
- }
- return 1;
-}
-
-/* A qsort ordering function for pchf_entry structures. */
-
-static int
-pchf_save_compare (const void *e1, const void *e2)
-{
- return memcmp (e1, e2, sizeof (struct pchf_entry));
-}
-
-/* Create and write to F a pchf_data structure. */
-
-bool
-_cpp_save_file_entries (cpp_reader *pfile, FILE *f)
-{
- size_t count = 0;
- struct pchf_data *result;
- size_t result_size;
- struct pchf_adder_info pai;
-
- count = htab_elements (pfile->file_hash);
- result_size = (sizeof (struct pchf_data)
- + sizeof (struct pchf_entry) * (count - 1));
- result = xcalloc (result_size, 1);
-
- result->count = 0;
- result->have_once_only = false;
-
- pai.pfile = pfile;
- pai.d = result;
- htab_traverse (pfile->file_hash, pchf_adder, &pai);
-
- result_size = (sizeof (struct pchf_data)
- + sizeof (struct pchf_entry) * (result->count - 1));
-
- qsort (result->entries, result->count, sizeof (struct pchf_entry),
- pchf_save_compare);
-
- return fwrite (result, result_size, 1, f) == 1;
-}
-
-/* Read the pchf_data structure from F. */
-
-bool
-_cpp_read_file_entries (cpp_reader *pfile ATTRIBUTE_UNUSED, FILE *f)
-{
- struct pchf_data d;
-
- if (fread (&d, sizeof (struct pchf_data) - sizeof (struct pchf_entry), 1, f)
- != 1)
- return false;
-
- pchf = xmalloc (sizeof (struct pchf_data)
- + sizeof (struct pchf_entry) * (d.count - 1));
- memcpy (pchf, &d, sizeof (struct pchf_data) - sizeof (struct pchf_entry));
- if (fread (pchf->entries, sizeof (struct pchf_entry), d.count, f)
- != d.count)
- return false;
- return true;
-}
-
-/* The parameters for pchf_compare. */
-
-struct pchf_compare_data
-{
- /* The size of the file we're looking for. */
- off_t size;
-
- /* The MD5 checksum of the file, if it's been computed. */
- unsigned char sum[16];
-
- /* Is SUM valid? */
- bool sum_computed;
-
- /* Do we need to worry about entries that don't have ONCE_ONLY set? */
- bool check_included;
-
- /* The file that we're searching for. */
- _cpp_file *f;
-};
-
-/* bsearch comparison function; look for D_P in E_P. */
-
-static int
-pchf_compare (const void *d_p, const void *e_p)
-{
- const struct pchf_entry *e = (const struct pchf_entry *)e_p;
- struct pchf_compare_data *d = (struct pchf_compare_data *)d_p;
- int result;
-
- result = memcmp (&d->size, &e->size, sizeof (off_t));
- if (result != 0)
- return result;
-
- if (! d->sum_computed)
- {
- _cpp_file *const f = d->f;
-
- md5_buffer ((const char *)f->buffer, f->st.st_size, d->sum);
- d->sum_computed = true;
- }
-
- result = memcmp (d->sum, e->sum, 16);
- if (result != 0)
- return result;
-
- if (d->check_included || e->once_only)
- return 0;
- else
- return 1;
-}
-
-/* Check that F is not in a list read from a PCH file (if any).
- Assumes that f->buffer_valid is true. Return TRUE if the file
- should not be read. */
-
-static bool
-check_file_against_entries (cpp_reader *pfile ATTRIBUTE_UNUSED,
- _cpp_file *f,
- bool check_included)
-{
- struct pchf_compare_data d;
-
- if (pchf == NULL
- || (! check_included && ! pchf->have_once_only))
- return false;
-
- d.size = f->st.st_size;
- d.sum_computed = false;
- d.f = f;
- d.check_included = check_included;
- return bsearch (&d, pchf->entries, pchf->count, sizeof (struct pchf_entry),
- pchf_compare) != NULL;
-}
diff --git a/gcc/cpphash.c b/gcc/cpphash.c
deleted file mode 100644
index 1e07f41f7ac..00000000000
--- a/gcc/cpphash.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/* Hash tables for the CPP library.
- Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998,
- 1999, 2000, 2001, 2002 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 (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 (hash_table *table)
-{
- cpp_hashnode *node;
-
- node = obstack_alloc (&table->pfile->hash_ob, sizeof (cpp_hashnode));
- memset (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 (cpp_reader *pfile, hash_table *table)
-{
- struct spec_nodes *s;
-
- if (table == NULL)
- {
- pfile->our_hashtable = 1;
- table = ht_create (13); /* 8K (=2^13) entries. */
- table->alloc_node = (hashnode (*) (hash_table *)) alloc_node;
-
- _obstack_begin (&pfile->hash_ob, 0, 0,
- (void *(*) (long)) xmalloc,
- (void (*) (void *)) free);
- }
-
- table->pfile = pfile;
- pfile->hash_table = table;
-
- /* Now we can initialize things that use the hash table. */
- _cpp_init_directives (pfile);
- _cpp_init_internal_pragmas (pfile);
-
- s = &pfile->spec_nodes;
- 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__VA_ARGS__ = cpp_lookup (pfile, DSC("__VA_ARGS__"));
- s->n__VA_ARGS__->flags |= NODE_DIAGNOSTIC;
-}
-
-/* Tear down the identifier hash table. */
-void
-_cpp_destroy_hashtable (cpp_reader *pfile)
-{
- if (pfile->our_hashtable)
- {
- ht_destroy (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 (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 (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 (cpp_reader *pfile, cpp_cb cb, void *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/gcc/cpphash.h b/gcc/cpphash.h
deleted file mode 100644
index 1c5015173e0..00000000000
--- a/gcc/cpphash.h
+++ /dev/null
@@ -1,651 +0,0 @@
-/* Part of CPP library.
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
- 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"
-
-#if defined HAVE_ICONV_H && defined HAVE_ICONV
-#include <iconv.h>
-#else
-#define HAVE_ICONV 0
-typedef int iconv_t; /* dummy */
-#endif
-
-struct directive; /* Deliberately incomplete. */
-struct pending_option;
-struct op;
-struct _cpp_strbuf;
-
-typedef bool (*convert_f) (iconv_t, const unsigned char *, size_t,
- struct _cpp_strbuf *);
-struct cset_converter
-{
- convert_f func;
- iconv_t cd;
-};
-
-#ifndef HAVE_UCHAR
-typedef unsigned char uchar;
-#endif
-#define U (const uchar *) /* Intended use: U"string" */
-
-#define BITS_PER_CPPCHAR_T (CHAR_BIT * sizeof (cppchar_t))
-
-/* 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_COLUMN(BUF, CUR) ((CUR) - (BUF)->line_base)
-#define CPP_BUF_COL(BUF) CPP_BUF_COLUMN(BUF, (BUF)->cur)
-
-#define CPP_INCREMENT_LINE(PFILE, COLS_HINT) do { \
- const struct line_maps *line_table = PFILE->line_table; \
- const struct line_map *map = &line_table->maps[line_table->used-1]; \
- unsigned int line = SOURCE_LINE (map, line_table->highest_line); \
- linemap_line_start (PFILE->line_table, line + 1, COLS_HINT); \
- } while (0)
-
-/* Maximum nesting of cpp_buffers. We use a static limit, partly for
- efficiency, and partly to limit runaway recursion. */
-#define CPP_STACK_MAX 200
-
-/* Host alignment handling. */
-struct dummy
-{
- char c;
- union
- {
- double d;
- int *p;
- } u;
-};
-
-#define DEFAULT_ALIGNMENT offsetof (struct dummy, u)
-#define CPP_ALIGN2(size, align) (((size) + ((align) - 1)) & ~((align) - 1))
-#define CPP_ALIGN(size) CPP_ALIGN2 (size, DEFAULT_ALIGNMENT)
-
-/* Each macro definition is recorded in a cpp_macro structure.
- Variadic macros cannot occur with traditional cpp. */
-struct cpp_macro
-{
- /* Parameters, if any. */
- cpp_hashnode **params;
-
- /* Replacement tokens (ISO) or replacement text (traditional). See
- comment at top of cpptrad.c for how traditional function-like
- macros are encoded. */
- union
- {
- cpp_token *tokens;
- const uchar *text;
- } exp;
-
- /* Definition line number. */
- fileline line;
-
- /* Number of tokens in expansion, or bytes for traditional macros. */
- unsigned int count;
-
- /* Number of parameters. */
- unsigned short paramc;
-
- /* If a function-like macro. */
- unsigned int fun_like : 1;
-
- /* If a variadic macro. */
- unsigned int variadic : 1;
-
- /* If macro defined in system header. */
- unsigned int syshdr : 1;
-
- /* Nonzero if it has been expanded or had its existence tested. */
- unsigned int used : 1;
-};
-
-#define _cpp_mark_macro_used(NODE) do { \
- if ((NODE)->type == NT_MACRO && !((NODE)->flags & NODE_BUILTIN)) \
- (NODE)->value.macro->used = 1; } while (0)
-
-/* A generic memory buffer, and operations on it. */
-typedef struct _cpp_buff _cpp_buff;
-struct _cpp_buff
-{
- struct _cpp_buff *next;
- unsigned char *base, *cur, *limit;
-};
-
-extern _cpp_buff *_cpp_get_buff (cpp_reader *, size_t);
-extern void _cpp_release_buff (cpp_reader *, _cpp_buff *);
-extern void _cpp_extend_buff (cpp_reader *, _cpp_buff **, size_t);
-extern _cpp_buff *_cpp_append_extend_buff (cpp_reader *, _cpp_buff *, size_t);
-extern void _cpp_free_buff (_cpp_buff *);
-extern unsigned char *_cpp_aligned_alloc (cpp_reader *, size_t);
-extern unsigned char *_cpp_unaligned_alloc (cpp_reader *, size_t);
-
-#define BUFF_ROOM(BUFF) (size_t) ((BUFF)->limit - (BUFF)->cur)
-#define BUFF_FRONT(BUFF) ((BUFF)->cur)
-#define BUFF_LIMIT(BUFF) ((BUFF)->limit)
-
-/* #include types. */
-enum include_type {IT_INCLUDE, IT_INCLUDE_NEXT, IT_IMPORT, IT_CMDLINE};
-
-union utoken
-{
- const cpp_token *token;
- const cpp_token **ptoken;
-};
-
-/* A "run" of tokens; part of a chain of runs. */
-typedef struct tokenrun tokenrun;
-struct tokenrun
-{
- tokenrun *next, *prev;
- cpp_token *base, *limit;
-};
-
-/* Accessor macros for struct cpp_context. */
-#define FIRST(c) ((c)->u.iso.first)
-#define LAST(c) ((c)->u.iso.last)
-#define CUR(c) ((c)->u.trad.cur)
-#define RLIMIT(c) ((c)->u.trad.rlimit)
-
-typedef struct cpp_context cpp_context;
-struct cpp_context
-{
- /* Doubly-linked list. */
- cpp_context *next, *prev;
-
- union
- {
- /* For ISO macro expansion. Contexts other than the base context
- are contiguous tokens. e.g. macro expansions, expanded
- argument tokens. */
- struct
- {
- union utoken first;
- union utoken last;
- } iso;
-
- /* For traditional macro expansion. */
- struct
- {
- const uchar *cur;
- const uchar *rlimit;
- } trad;
- } u;
-
- /* If non-NULL, a buffer used for storage related to this context.
- When the context is popped, the buffer is released. */
- _cpp_buff *buff;
-
- /* For a macro context, the macro node, otherwise NULL. */
- cpp_hashnode *macro;
-
- /* True if utoken element is token, else ptoken. */
- bool direct_p;
-};
-
-struct lexer_state
-{
- /* Nonzero if first token on line is CPP_HASH. */
- unsigned char in_directive;
-
- /* Nonzero if in a directive that will handle padding tokens itself.
- #include needs this to avoid problems with computed include and
- spacing between tokens. */
- unsigned char directive_wants_padding;
-
- /* True if we are skipping a failed conditional group. */
- unsigned char skipping;
-
- /* Nonzero if in a directive that takes angle-bracketed headers. */
- unsigned char angled_headers;
-
- /* Nonzero if in a #if or #elif directive. */
- unsigned char in_expression;
-
- /* Nonzero to save comments. Turned off if discard_comments, and in
- all directives apart from #define. */
- unsigned char save_comments;
-
- /* 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 to skip evaluating part of an expression. */
- unsigned int skip_eval;
-};
-
-/* Special nodes - identifiers with predefined significance. */
-struct spec_nodes
-{
- cpp_hashnode *n_defined; /* defined operator */
- cpp_hashnode *n_true; /* C++ keyword true */
- cpp_hashnode *n_false; /* C++ keyword false */
- cpp_hashnode *n__VA_ARGS__; /* C99 vararg macros */
-};
-
-typedef struct _cpp_line_note _cpp_line_note;
-struct _cpp_line_note
-{
- /* Location in the clean line the note refers to. */
- const uchar *pos;
-
- /* Type of note. The 9 'from' trigraph characters represent those
- trigraphs, '\\' an escaped newline, ' ' an escaped newline with
- intervening space, and anything else is invalid. */
- unsigned int type;
-};
-
-/* Represents the contents of a file cpplib has read in. */
-struct cpp_buffer
-{
- const uchar *cur; /* Current location. */
- const uchar *line_base; /* Start of current physical line. */
- const uchar *next_line; /* Start of to-be-cleaned logical line. */
-
- const uchar *buf; /* Entire character buffer. */
- const uchar *rlimit; /* Writable byte at end of file. */
-
- _cpp_line_note *notes; /* Array of notes. */
- unsigned int cur_note; /* Next note to process. */
- unsigned int notes_used; /* Number of notes. */
- unsigned int notes_cap; /* Size of allocated array. */
-
- struct cpp_buffer *prev;
-
- /* Pointer into the file table; non-NULL if this is a file buffer.
- Used for include_next and to record control macros. */
- struct _cpp_file *file;
-
- /* Value of if_stack at start of this file.
- Used to prohibit unmatched #endif (etc) in an include file. */
- struct if_stack *if_stack;
-
- /* True if we need to get the next clean line. */
- bool need_line;
-
- /* 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 int warned_cplusplus_comments : 1;
-
- /* True if we don't process trigraphs and escaped newlines. True
- for preprocessed input, command line directives, and _Pragma
- buffers. */
- unsigned int from_stage3 : 1;
-
- /* At EOF, a buffer is automatically popped. If RETURN_AT_EOF is
- true, a CPP_EOF token is then returned. Otherwise, the next
- token from the enclosing buffer is returned. */
- unsigned int return_at_eof : 1;
-
- /* One for a system header, two for a C system header file that therefore
- needs to be extern "C" protected in C++, and zero otherwise. */
- unsigned char sysp;
-
- /* 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 cpp_dir dir;
-
- /* Descriptor for converting from the input character set to the
- source character set. */
- struct cset_converter input_cset_desc;
-};
-
-/* 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;
-
- /* Overlaid buffer (can be different after processing #include). */
- cpp_buffer *overlaid_buffer;
-
- /* Lexer state. */
- struct lexer_state state;
-
- /* Source line tracking. */
- struct line_maps *line_table;
-
- /* The line of the '#' of the current directive. */
- fileline directive_line;
-
- /* Memory buffers. */
- _cpp_buff *a_buff; /* Aligned permanent storage. */
- _cpp_buff *u_buff; /* Unaligned permanent storage. */
- _cpp_buff *free_buffs; /* Free buffer chain. */
-
- /* Context stack. */
- struct cpp_context base_context;
- struct cpp_context *context;
-
- /* If in_directive, the directive if known. */
- const struct directive *directive;
-
- /* Search paths for include files. */
- struct cpp_dir *quote_include; /* "" */
- struct cpp_dir *bracket_include; /* <> */
- struct cpp_dir no_search_path; /* No path. */
-
- /* Chain of all hashed _cpp_file instances. */
- struct _cpp_file *all_files;
-
- struct _cpp_file *main_file;
-
- /* File and directory hash table. */
- struct htab *file_hash;
- struct file_hash_entry *file_hash_entries;
- unsigned int file_hash_entries_allocated, file_hash_entries_used;
-
- /* Nonzero means don't look for #include "foo" the source-file
- directory. */
- bool quote_ignores_source_dir;
-
- /* Nonzero if any file has contained #pragma once or #import has
- been used. */
- bool seen_once_only;
-
- /* Multiple include optimization. */
- const cpp_hashnode *mi_cmacro;
- const cpp_hashnode *mi_ind_cmacro;
- bool mi_valid;
-
- /* Lexing. */
- cpp_token *cur_token;
- tokenrun base_run, *cur_run;
- unsigned int lookaheads;
-
- /* Nonzero prevents the lexer from re-using the token runs. */
- unsigned int keep_tokens;
-
- /* Error counter for exit code. */
- unsigned int errors;
-
- /* Buffer to hold macro definition string. */
- unsigned char *macro_buffer;
- unsigned int macro_buffer_len;
-
- /* Descriptor for converting from the source character set to the
- execution character set. */
- struct cset_converter narrow_cset_desc;
-
- /* Descriptor for converting from the source character set to the
- wide execution character set. */
- struct cset_converter wide_cset_desc;
-
- /* Date and time text. Calculated together if either is requested. */
- const uchar *date;
- const uchar *time;
-
- /* EOF token, and a token forcing paste avoidance. */
- cpp_token avoid_paste;
- cpp_token eof;
-
- /* Opaque handle to the dependencies of mkdeps.c. */
- 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 to cpplib client. */
- struct cpp_callbacks cb;
-
- /* Identifier hash table. */
- struct ht *hash_table;
-
- /* Expression parser stack. */
- struct op *op_stack, *op_limit;
-
- /* User visible options. */
- struct cpp_options opts;
-
- /* Special nodes - identifiers with predefined significance to the
- preprocessor. */
- struct spec_nodes spec_nodes;
-
- /* Whether cpplib owns the hashtable. */
- bool our_hashtable;
-
- /* Traditional preprocessing output buffer (a logical line). */
- struct
- {
- uchar *base;
- uchar *limit;
- uchar *cur;
- fileline first_line;
- } out;
-
- /* Used for buffer overlays by cpptrad.c. */
- const uchar *saved_cur, *saved_rlimit, *saved_line_base;
-
- /* A saved list of the defined macros, for dependency checking
- of precompiled headers. */
- struct cpp_savedstate *savedstate;
-};
-
-/* 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. */
-
-static inline int cpp_in_system_header (cpp_reader *);
-static inline int
-cpp_in_system_header (cpp_reader *pfile)
-{
- return pfile->buffer ? pfile->buffer->sysp : 0;
-}
-#define CPP_PEDANTIC(PF) CPP_OPTION (PF, pedantic)
-#define CPP_WTRADITIONAL(PF) CPP_OPTION (PF, warn_traditional)
-
-/* In cpperror.c */
-extern int _cpp_begin_message (cpp_reader *, int,
- source_location, unsigned int);
-
-/* In cppmacro.c */
-extern void _cpp_free_definition (cpp_hashnode *);
-extern bool _cpp_create_definition (cpp_reader *, cpp_hashnode *);
-extern void _cpp_pop_context (cpp_reader *);
-extern void _cpp_push_text_context (cpp_reader *, cpp_hashnode *,
- const uchar *, size_t);
-extern bool _cpp_save_parameter (cpp_reader *, cpp_macro *, cpp_hashnode *);
-extern bool _cpp_arguments_ok (cpp_reader *, cpp_macro *, const cpp_hashnode *,
- unsigned int);
-extern const uchar *_cpp_builtin_macro_text (cpp_reader *, cpp_hashnode *);
-int _cpp_warn_if_unused_macro (cpp_reader *, cpp_hashnode *, void *);
-/* In cpphash.c */
-extern void _cpp_init_hashtable (cpp_reader *, hash_table *);
-extern void _cpp_destroy_hashtable (cpp_reader *);
-
-/* In cppfiles.c */
-typedef struct _cpp_file _cpp_file;
-extern _cpp_file *_cpp_find_file (cpp_reader *, const char *fname,
- cpp_dir *start_dir, bool fake);
-extern bool _cpp_find_failed (_cpp_file *);
-extern void _cpp_mark_file_once_only (cpp_reader *, struct _cpp_file *);
-extern void _cpp_fake_include (cpp_reader *, const char *);
-extern bool _cpp_stack_file (cpp_reader *, _cpp_file*, bool);
-extern bool _cpp_stack_include (cpp_reader *, const char *, int,
- enum include_type);
-extern int _cpp_compare_file_date (cpp_reader *, const char *, int);
-extern void _cpp_report_missing_guards (cpp_reader *);
-extern void _cpp_init_files (cpp_reader *);
-extern void _cpp_cleanup_files (cpp_reader *);
-extern void _cpp_pop_file_buffer (cpp_reader *, struct _cpp_file *);
-extern bool _cpp_save_file_entries (cpp_reader *pfile, FILE *f);
-extern bool _cpp_read_file_entries (cpp_reader *, FILE *);
-
-/* In cppexp.c */
-extern bool _cpp_parse_expr (cpp_reader *);
-extern struct op *_cpp_expand_op_stack (cpp_reader *);
-
-/* In cpplex.c */
-extern void _cpp_process_line_notes (cpp_reader *, int);
-extern void _cpp_clean_line (cpp_reader *);
-extern bool _cpp_get_fresh_line (cpp_reader *);
-extern bool _cpp_skip_block_comment (cpp_reader *);
-extern cpp_token *_cpp_temp_token (cpp_reader *);
-extern const cpp_token *_cpp_lex_token (cpp_reader *);
-extern cpp_token *_cpp_lex_direct (cpp_reader *);
-extern int _cpp_equiv_tokens (const cpp_token *, const cpp_token *);
-extern void _cpp_init_tokenrun (tokenrun *, unsigned int);
-
-/* In cppinit.c. */
-extern void _cpp_maybe_push_include_file (cpp_reader *);
-
-/* In cpplib.c */
-extern int _cpp_test_assertion (cpp_reader *, unsigned int *);
-extern int _cpp_handle_directive (cpp_reader *, int);
-extern void _cpp_define_builtin (cpp_reader *, const char *);
-extern char ** _cpp_save_pragma_names (cpp_reader *);
-extern void _cpp_restore_pragma_names (cpp_reader *, char **);
-extern void _cpp_do__Pragma (cpp_reader *);
-extern void _cpp_init_directives (cpp_reader *);
-extern void _cpp_init_internal_pragmas (cpp_reader *);
-extern void _cpp_do_file_change (cpp_reader *, enum lc_reason, const char *,
- unsigned int, unsigned int);
-extern void _cpp_pop_buffer (cpp_reader *);
-
-/* In cpptrad.c. */
-extern bool _cpp_scan_out_logical_line (cpp_reader *, cpp_macro *);
-extern bool _cpp_read_logical_line_trad (cpp_reader *);
-extern void _cpp_overlay_buffer (cpp_reader *pfile, const uchar *, size_t);
-extern void _cpp_remove_overlay (cpp_reader *);
-extern bool _cpp_create_trad_definition (cpp_reader *, cpp_macro *);
-extern bool _cpp_expansions_different_trad (const cpp_macro *,
- const cpp_macro *);
-extern uchar *_cpp_copy_replacement_text (const cpp_macro *, uchar *);
-extern size_t _cpp_replacement_text_len (const cpp_macro *);
-
-/* In cppcharset.c. */
-extern cppchar_t _cpp_valid_ucn (cpp_reader *, const uchar **,
- const uchar *, int);
-extern void _cpp_destroy_iconv (cpp_reader *);
-extern uchar *_cpp_convert_input (cpp_reader *, const char *, uchar *,
- size_t, size_t, off_t *);
-extern const char *_cpp_default_encoding (void);
-
-/* Utility routines and macros. */
-#define DSC(str) (const uchar *)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. */
-static inline int ustrcmp (const uchar *, const uchar *);
-static inline int ustrncmp (const uchar *, const uchar *, size_t);
-static inline size_t ustrlen (const uchar *);
-static inline uchar *uxstrdup (const uchar *);
-static inline uchar *ustrchr (const uchar *, int);
-static inline int ufputs (const uchar *, FILE *);
-
-static inline int
-ustrcmp (const uchar *s1, const uchar *s2)
-{
- return strcmp ((const char *)s1, (const char *)s2);
-}
-
-static inline int
-ustrncmp (const uchar *s1, const uchar *s2, size_t n)
-{
- return strncmp ((const char *)s1, (const char *)s2, n);
-}
-
-static inline size_t
-ustrlen (const uchar *s1)
-{
- return strlen ((const char *)s1);
-}
-
-static inline uchar *
-uxstrdup (const uchar *s1)
-{
- return (uchar *) xstrdup ((const char *)s1);
-}
-
-static inline uchar *
-ustrchr (const uchar *s1, int c)
-{
- return (uchar *) strchr ((const char *)s1, c);
-}
-
-static inline int
-ufputs (const uchar *s, FILE *f)
-{
- return fputs ((const char *)s, f);
-}
-
-#endif /* ! GCC_CPPHASH_H */
diff --git a/gcc/cppinit.c b/gcc/cppinit.c
deleted file mode 100644
index 55323b4ea9b..00000000000
--- a/gcc/cppinit.c
+++ /dev/null
@@ -1,627 +0,0 @@
-/* CPP Library.
- Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 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 "mkdeps.h"
-
-static void init_library (void);
-static void mark_named_operators (cpp_reader *);
-static void read_original_filename (cpp_reader *);
-static void read_original_directory (cpp_reader *);
-static void post_options (cpp_reader *);
-
-/* 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 uchar _cpp_trigraph_map[UCHAR_MAX + 1] = {
-
-#define END };
-#define s(p, v) [p] = v,
-
-#else
-
-#define TRIGRAPH_MAP uchar _cpp_trigraph_map[UCHAR_MAX + 1] = { 0 }; \
- static void init_trigraph_map (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
-
-/* A set of booleans indicating what CPP features each source language
- requires. */
-struct lang_flags
-{
- char c99;
- char cplusplus;
- char extended_numbers;
- char std;
- char cplusplus_comments;
- char digraphs;
-};
-
-static const struct lang_flags lang_defaults[] =
-{ /* c99 c++ xnum std // digr */
- /* GNUC89 */ { 0, 0, 1, 0, 1, 1 },
- /* GNUC99 */ { 1, 0, 1, 0, 1, 1 },
- /* STDC89 */ { 0, 0, 0, 1, 0, 0 },
- /* STDC94 */ { 0, 0, 0, 1, 0, 1 },
- /* STDC99 */ { 1, 0, 1, 1, 1, 1 },
- /* GNUCXX */ { 0, 1, 1, 0, 1, 1 },
- /* CXX98 */ { 0, 1, 1, 1, 1, 1 },
- /* ASM */ { 0, 0, 1, 0, 1, 0 }
-};
-
-/* Sets internal flags correctly for a given language. */
-void
-cpp_set_lang (cpp_reader *pfile, enum c_lang lang)
-{
- const struct lang_flags *l = &lang_defaults[(int) lang];
-
- CPP_OPTION (pfile, lang) = lang;
-
- CPP_OPTION (pfile, c99) = l->c99;
- CPP_OPTION (pfile, cplusplus) = l->cplusplus;
- CPP_OPTION (pfile, extended_numbers) = l->extended_numbers;
- CPP_OPTION (pfile, std) = l->std;
- CPP_OPTION (pfile, trigraphs) = l->std;
- CPP_OPTION (pfile, cplusplus_comments) = l->cplusplus_comments;
- CPP_OPTION (pfile, digraphs) = l->digraphs;
-}
-
-/* Initialize library global state. */
-static void
-init_library (void)
-{
- static int initialized = 0;
-
- if (! initialized)
- {
- initialized = 1;
-
- /* 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 (enum c_lang lang, hash_table *table,
- struct line_maps *line_table)
-{
- cpp_reader *pfile;
-
- /* Initialize this instance of the library if it hasn't been already. */
- init_library ();
-
- pfile = xcalloc (1, sizeof (cpp_reader));
-
- cpp_set_lang (pfile, lang);
- CPP_OPTION (pfile, warn_multichar) = 1;
- CPP_OPTION (pfile, discard_comments) = 1;
- CPP_OPTION (pfile, discard_comments_in_macro_exp) = 1;
- CPP_OPTION (pfile, show_column) = 1;
- CPP_OPTION (pfile, tabstop) = 8;
- CPP_OPTION (pfile, operator_names) = 1;
- CPP_OPTION (pfile, warn_trigraphs) = 2;
- CPP_OPTION (pfile, warn_endif_labels) = 1;
- CPP_OPTION (pfile, warn_deprecated) = 1;
- CPP_OPTION (pfile, warn_long_long) = !CPP_OPTION (pfile, c99);
- CPP_OPTION (pfile, dollars_in_ident) = 1;
- CPP_OPTION (pfile, warn_dollars) = 1;
- CPP_OPTION (pfile, warn_variadic_macros) = 1;
-
- /* Default CPP arithmetic to something sensible for the host for the
- benefit of dumb users like fix-header. */
- CPP_OPTION (pfile, precision) = CHAR_BIT * sizeof (long);
- CPP_OPTION (pfile, char_precision) = CHAR_BIT;
- CPP_OPTION (pfile, wchar_precision) = CHAR_BIT * sizeof (int);
- CPP_OPTION (pfile, int_precision) = CHAR_BIT * sizeof (int);
- CPP_OPTION (pfile, unsigned_char) = 0;
- CPP_OPTION (pfile, unsigned_wchar) = 1;
- CPP_OPTION (pfile, bytes_big_endian) = 1; /* does not matter */
-
- /* Default to no charset conversion. */
- CPP_OPTION (pfile, narrow_charset) = _cpp_default_encoding ();
- CPP_OPTION (pfile, wide_charset) = 0;
-
- /* Default the input character set to UTF-8. */
- CPP_OPTION (pfile, input_charset) = _cpp_default_encoding ();
-
- /* A fake empty "directory" used as the starting point for files
- looked up without a search path. Name cannot be '/' because we
- don't want to prepend anything at all to filenames using it. All
- other entries are correct zero-initialized. */
- pfile->no_search_path.name = (char *) "";
-
- /* Initialize the line map. */
- pfile->line_table = line_table;
-
- /* Initialize lexer state. */
- pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
-
- /* Set up static tokens. */
- pfile->avoid_paste.type = CPP_PADDING;
- pfile->avoid_paste.val.source = NULL;
- pfile->eof.type = CPP_EOF;
- pfile->eof.flags = 0;
-
- /* Create a token buffer for the lexer. */
- _cpp_init_tokenrun (&pfile->base_run, 250);
- pfile->cur_run = &pfile->base_run;
- pfile->cur_token = pfile->base_run.base;
-
- /* Initialize the base context. */
- pfile->context = &pfile->base_context;
- pfile->base_context.macro = 0;
- pfile->base_context.prev = pfile->base_context.next = 0;
-
- /* Aligned and unaligned storage. */
- pfile->a_buff = _cpp_get_buff (pfile, 0);
- pfile->u_buff = _cpp_get_buff (pfile, 0);
-
- /* The expression parser stack. */
- _cpp_expand_op_stack (pfile);
-
- /* Initialize the buffer obstack. */
- _obstack_begin (&pfile->buffer_ob, 0, 0,
- (void *(*) (long)) xmalloc,
- (void (*) (void *)) free);
-
- _cpp_init_files (pfile);
-
- _cpp_init_hashtable (pfile, table);
-
- return pfile;
-}
-
-/* Free resources used by PFILE. Accessing PFILE after this function
- returns leads to undefined behavior. Returns the error count. */
-void
-cpp_destroy (cpp_reader *pfile)
-{
- cpp_context *context, *contextn;
- tokenrun *run, *runn;
-
- free (pfile->op_stack);
-
- while (CPP_BUFFER (pfile) != NULL)
- _cpp_pop_buffer (pfile);
-
- if (pfile->out.base)
- free (pfile->out.base);
-
- if (pfile->macro_buffer)
- {
- free (pfile->macro_buffer);
- pfile->macro_buffer = NULL;
- pfile->macro_buffer_len = 0;
- }
-
- if (pfile->deps)
- deps_free (pfile->deps);
- obstack_free (&pfile->buffer_ob, 0);
-
- _cpp_destroy_hashtable (pfile);
- _cpp_cleanup_files (pfile);
- _cpp_destroy_iconv (pfile);
-
- _cpp_free_buff (pfile->a_buff);
- _cpp_free_buff (pfile->u_buff);
- _cpp_free_buff (pfile->free_buffs);
-
- for (run = &pfile->base_run; run; run = runn)
- {
- runn = run->next;
- free (run->base);
- if (run != &pfile->base_run)
- free (run);
- }
-
- for (context = pfile->base_context.next; context; context = contextn)
- {
- contextn = context->next;
- free (context);
- }
-
- free (pfile);
-}
-
-/* This structure defines one built-in identifier. A node will be
- entered in the hash table under the name NAME, with value VALUE.
-
- There are two tables of these. builtin_array holds all the
- "builtin" macros: these are handled by builtin_macro() in
- cppmacro.c. Builtin is somewhat of a misnomer -- the property of
- interest is that these macros require special code to compute their
- expansions. The value is a "builtin_type" enumerator.
-
- operator_array holds the C++ named operators. These are keywords
- which act as aliases for punctuators. In C++, they cannot be
- altered through #define, and #if recognizes them as operators. In
- C, these are not entered into the hash table at all (but see
- <iso646.h>). The value is a token-type enumerator. */
-struct builtin
-{
- const uchar *name;
- unsigned short len;
- unsigned short value;
-};
-
-#define B(n, t) { DSC(n), t }
-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),
- /* Keep builtins not used for -traditional-cpp at the end, and
- update init_builtins() if any more are added. */
- B("_Pragma", BT_PRAGMA),
- B("__STDC__", BT_STDC),
-};
-
-static const struct builtin operator_array[] =
-{
- B("and", CPP_AND_AND),
- B("and_eq", CPP_AND_EQ),
- B("bitand", CPP_AND),
- B("bitor", CPP_OR),
- B("compl", CPP_COMPL),
- B("not", CPP_NOT),
- B("not_eq", CPP_NOT_EQ),
- B("or", CPP_OR_OR),
- B("or_eq", CPP_OR_EQ),
- B("xor", CPP_XOR),
- B("xor_eq", CPP_XOR_EQ)
-};
-#undef B
-
-/* Mark the C++ named operators in the hash table. */
-static void
-mark_named_operators (cpp_reader *pfile)
-{
- const struct builtin *b;
-
- for (b = operator_array;
- b < (operator_array + ARRAY_SIZE (operator_array));
- b++)
- {
- cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
- hp->flags |= NODE_OPERATOR;
- hp->is_directive = 0;
- hp->directive_index = b->value;
- }
-}
-
-/* Read the builtins table above and enter them, and language-specific
- macros, into the hash table. HOSTED is true if this is a hosted
- environment. */
-void
-cpp_init_builtins (cpp_reader *pfile, int hosted)
-{
- const struct builtin *b;
- size_t n = ARRAY_SIZE (builtin_array);
-
- if (CPP_OPTION (pfile, traditional))
- n -= 2;
-
- for(b = builtin_array; b < builtin_array + n; b++)
- {
- cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
- hp->type = NT_MACRO;
- hp->flags |= NODE_BUILTIN | NODE_WARN;
- hp->value.builtin = b->value;
- }
-
- if (CPP_OPTION (pfile, cplusplus))
- _cpp_define_builtin (pfile, "__cplusplus 1");
- else if (CPP_OPTION (pfile, lang) == CLK_ASM)
- _cpp_define_builtin (pfile, "__ASSEMBLER__ 1");
- else 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 (hosted)
- _cpp_define_builtin (pfile, "__STDC_HOSTED__ 1");
- else
- _cpp_define_builtin (pfile, "__STDC_HOSTED__ 0");
-
- if (CPP_OPTION (pfile, objc))
- _cpp_define_builtin (pfile, "__OBJC__ 1");
-}
-
-/* Sanity-checks are dependent on command-line options, so it is
- called as a subroutine of cpp_read_main_file (). */
-#if ENABLE_CHECKING
-static void sanity_checks (cpp_reader *);
-static void sanity_checks (cpp_reader *pfile)
-{
- cppchar_t test = 0;
- size_t max_precision = 2 * CHAR_BIT * sizeof (cpp_num_part);
-
- /* Sanity checks for assumptions about CPP arithmetic and target
- type precisions made by cpplib. */
- test--;
- if (test < 1)
- cpp_error (pfile, CPP_DL_ICE, "cppchar_t must be an unsigned type");
-
- if (CPP_OPTION (pfile, precision) > max_precision)
- cpp_error (pfile, CPP_DL_ICE,
- "preprocessor arithmetic has maximum precision of %lu bits;"
- " target requires %lu bits",
- (unsigned long) max_precision,
- (unsigned long) CPP_OPTION (pfile, precision));
-
- if (CPP_OPTION (pfile, precision) < CPP_OPTION (pfile, int_precision))
- cpp_error (pfile, CPP_DL_ICE,
- "CPP arithmetic must be at least as precise as a target int");
-
- if (CPP_OPTION (pfile, char_precision) < 8)
- cpp_error (pfile, CPP_DL_ICE, "target char is less than 8 bits wide");
-
- if (CPP_OPTION (pfile, wchar_precision) < CPP_OPTION (pfile, char_precision))
- cpp_error (pfile, CPP_DL_ICE,
- "target wchar_t is narrower than target char");
-
- if (CPP_OPTION (pfile, int_precision) < CPP_OPTION (pfile, char_precision))
- cpp_error (pfile, CPP_DL_ICE,
- "target int is narrower than target char");
-
- /* This is assumed in eval_token() and could be fixed if necessary. */
- if (sizeof (cppchar_t) > sizeof (cpp_num_part))
- cpp_error (pfile, CPP_DL_ICE,
- "CPP half-integer narrower than CPP character");
-
- if (CPP_OPTION (pfile, wchar_precision) > BITS_PER_CPPCHAR_T)
- cpp_error (pfile, CPP_DL_ICE,
- "CPP on this host cannot handle wide character constants over"
- " %lu bits, but the target requires %lu bits",
- (unsigned long) BITS_PER_CPPCHAR_T,
- (unsigned long) CPP_OPTION (pfile, wchar_precision));
-}
-#else
-# define sanity_checks(PFILE)
-#endif
-
-/* Add a dependency target. Can be called any number of times before
- cpp_read_main_file(). If no targets have been added before
- cpp_read_main_file(), then the default target is used. */
-void
-cpp_add_dependency_target (cpp_reader *pfile, const char *target, int quote)
-{
- if (!pfile->deps)
- pfile->deps = deps_init ();
-
- deps_add_target (pfile->deps, target, quote);
-}
-
-/* This is called after options have been parsed, and partially
- processed. */
-void
-cpp_post_options (cpp_reader *pfile)
-{
- sanity_checks (pfile);
-
- post_options (pfile);
-
- /* Mark named operators before handling command line macros. */
- if (CPP_OPTION (pfile, cplusplus) && CPP_OPTION (pfile, operator_names))
- mark_named_operators (pfile);
-}
-
-/* Setup for processing input from the file named FNAME, or stdin if
- it is the empty string. Return the original filename
- on success (e.g. foo.i->foo.c), or NULL on failure. */
-const char *
-cpp_read_main_file (cpp_reader *pfile, const char *fname)
-{
- if (CPP_OPTION (pfile, deps.style) != DEPS_NONE)
- {
- if (!pfile->deps)
- pfile->deps = deps_init ();
-
- /* Set the default target (if there is none already). */
- deps_add_default_target (pfile->deps, fname);
- }
-
- pfile->main_file
- = _cpp_find_file (pfile, fname, &pfile->no_search_path, false);
- if (_cpp_find_failed (pfile->main_file))
- return NULL;
-
- _cpp_stack_file (pfile, pfile->main_file, false);
-
- /* For foo.i, read the original filename foo.c now, for the benefit
- of the front ends. */
- if (CPP_OPTION (pfile, preprocessed))
- {
- read_original_filename (pfile);
- fname = pfile->line_table->maps[pfile->line_table->used-1].to_file;
- }
- return fname;
-}
-
-/* For preprocessed files, if the first tokens are of the form # NUM.
- handle the directive so we know the original file name. This will
- generate file_change callbacks, which the front ends must handle
- appropriately given their state of initialization. */
-static void
-read_original_filename (cpp_reader *pfile)
-{
- const cpp_token *token, *token1;
-
- /* Lex ahead; if the first tokens are of the form # NUM, then
- process the directive, otherwise back up. */
- token = _cpp_lex_direct (pfile);
- if (token->type == CPP_HASH)
- {
- token1 = _cpp_lex_direct (pfile);
- _cpp_backup_tokens (pfile, 1);
-
- /* If it's a #line directive, handle it. */
- if (token1->type == CPP_NUMBER)
- {
- _cpp_handle_directive (pfile, token->flags & PREV_WHITE);
- read_original_directory (pfile);
- return;
- }
- }
-
- /* Backup as if nothing happened. */
- _cpp_backup_tokens (pfile, 1);
-}
-
-/* For preprocessed files, if the tokens following the first filename
- line is of the form # <line> "/path/name//", handle the
- directive so we know the original current directory. */
-static void
-read_original_directory (cpp_reader *pfile)
-{
- const cpp_token *hash, *token;
-
- /* Lex ahead; if the first tokens are of the form # NUM, then
- process the directive, otherwise back up. */
- hash = _cpp_lex_direct (pfile);
- if (hash->type != CPP_HASH)
- {
- _cpp_backup_tokens (pfile, 1);
- return;
- }
-
- token = _cpp_lex_direct (pfile);
-
- if (token->type != CPP_NUMBER)
- {
- _cpp_backup_tokens (pfile, 2);
- return;
- }
-
- token = _cpp_lex_direct (pfile);
-
- if (token->type != CPP_STRING
- || ! (token->val.str.len >= 5
- && token->val.str.text[token->val.str.len-2] == '/'
- && token->val.str.text[token->val.str.len-3] == '/'))
- {
- _cpp_backup_tokens (pfile, 3);
- return;
- }
-
- if (pfile->cb.dir_change)
- {
- char *debugdir = alloca (token->val.str.len - 3);
-
- memcpy (debugdir, (const char *) token->val.str.text + 1,
- token->val.str.len - 4);
- debugdir[token->val.str.len - 4] = '\0';
-
- pfile->cb.dir_change (pfile, debugdir);
- }
-}
-
-/* This is called at the end of preprocessing. It pops the last
- buffer and writes dependency output, and returns the number of
- errors.
-
- Maybe it should also reset state, such that you could call
- cpp_start_read with a new filename to restart processing. */
-int
-cpp_finish (cpp_reader *pfile, FILE *deps_stream)
-{
- /* Warn about unused macros before popping the final buffer. */
- if (CPP_OPTION (pfile, warn_unused_macros))
- cpp_forall_identifiers (pfile, _cpp_warn_if_unused_macro, NULL);
-
- /* cpplex.c leaves the final buffer on the stack. This it so that
- it returns an unending stream of CPP_EOFs to the client. If we
- popped the buffer, we'd dereference a NULL buffer pointer and
- segfault. It's nice to allow the client to do worry-free excess
- cpp_get_token calls. */
- while (pfile->buffer)
- _cpp_pop_buffer (pfile);
-
- /* Don't write the deps file if there are errors. */
- if (CPP_OPTION (pfile, deps.style) != DEPS_NONE
- && deps_stream && pfile->errors == 0)
- {
- deps_write (pfile->deps, deps_stream, 72);
-
- if (CPP_OPTION (pfile, deps.phony_targets))
- deps_phony_targets (pfile->deps, deps_stream);
- }
-
- /* Report on headers that could use multiple include guards. */
- if (CPP_OPTION (pfile, print_include_names))
- _cpp_report_missing_guards (pfile);
-
- return pfile->errors;
-}
-
-static void
-post_options (cpp_reader *pfile)
-{
- /* -Wtraditional is not useful in C++ mode. */
- if (CPP_OPTION (pfile, cplusplus))
- CPP_OPTION (pfile, warn_traditional) = 0;
-
- /* Permanently disable macro expansion if we are rescanning
- preprocessed text. Read preprocesed source in ISO mode. */
- if (CPP_OPTION (pfile, preprocessed))
- {
- pfile->state.prevent_expansion = 1;
- CPP_OPTION (pfile, traditional) = 0;
- }
-
- if (CPP_OPTION (pfile, warn_trigraphs) == 2)
- CPP_OPTION (pfile, warn_trigraphs) = !CPP_OPTION (pfile, trigraphs);
-
- if (CPP_OPTION (pfile, traditional))
- {
- /* Traditional CPP does not accurately track column information. */
- CPP_OPTION (pfile, show_column) = 0;
- CPP_OPTION (pfile, trigraphs) = 0;
- CPP_OPTION (pfile, warn_trigraphs) = 0;
- }
-}
diff --git a/gcc/cpplex.c b/gcc/cpplex.c
deleted file mode 100644
index d03096cdc63..00000000000
--- a/gcc/cpplex.c
+++ /dev/null
@@ -1,1544 +0,0 @@
-/* CPP Library - lexical analysis.
- Copyright (C) 2000, 2001, 2002, 2003, 2004 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
-
-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"
-
-enum spell_type
-{
- SPELL_OPERATOR = 0,
- SPELL_IDENT,
- SPELL_LITERAL,
- SPELL_NONE
-};
-
-struct token_spelling
-{
- enum spell_type category;
- const unsigned char *name;
-};
-
-static const unsigned char *const digraph_spellings[] =
-{ U"%:", U"%:%:", U"<:", U":>", U"<%", U"%>" };
-
-#define OP(e, s) { SPELL_OPERATOR, U s },
-#define TK(e, s) { s, U #e },
-static 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 void add_line_note (cpp_buffer *, const uchar *, unsigned int);
-static int skip_line_comment (cpp_reader *);
-static void skip_whitespace (cpp_reader *, cppchar_t);
-static cpp_hashnode *lex_identifier (cpp_reader *, const uchar *);
-static void lex_number (cpp_reader *, cpp_string *);
-static bool forms_identifier_p (cpp_reader *, int);
-static void lex_string (cpp_reader *, cpp_token *, const uchar *);
-static void save_comment (cpp_reader *, cpp_token *, const uchar *, cppchar_t);
-static void create_literal (cpp_reader *, cpp_token *, const uchar *,
- unsigned int, enum cpp_ttype);
-static bool warn_in_comment (cpp_reader *, _cpp_line_note *);
-static int name_p (cpp_reader *, const cpp_string *);
-static tokenrun *next_tokenrun (tokenrun *);
-
-static _cpp_buff *new_buff (size_t);
-
-
-/* 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 (const cpp_token *token, const char *string)
-{
- if (token->type != CPP_NAME)
- return 0;
-
- return !ustrcmp (NODE_NAME (token->val.node), (const uchar *) string);
-}
-
-/* Record a note TYPE at byte POS into the current cleaned logical
- line. */
-static void
-add_line_note (cpp_buffer *buffer, const uchar *pos, unsigned int type)
-{
- if (buffer->notes_used == buffer->notes_cap)
- {
- buffer->notes_cap = buffer->notes_cap * 2 + 200;
- buffer->notes = xrealloc (buffer->notes,
- buffer->notes_cap * sizeof (_cpp_line_note));
- }
-
- buffer->notes[buffer->notes_used].pos = pos;
- buffer->notes[buffer->notes_used].type = type;
- buffer->notes_used++;
-}
-
-/* Returns with a logical line that contains no escaped newlines or
- trigraphs. This is a time-critical inner loop. */
-void
-_cpp_clean_line (cpp_reader *pfile)
-{
- cpp_buffer *buffer;
- const uchar *s;
- uchar c, *d, *p;
-
- buffer = pfile->buffer;
- buffer->cur_note = buffer->notes_used = 0;
- buffer->cur = buffer->line_base = buffer->next_line;
- buffer->need_line = false;
- s = buffer->next_line - 1;
-
- if (!buffer->from_stage3)
- {
- /* Short circuit for the common case of an un-escaped line with
- no trigraphs. The primary win here is by not writing any
- data back to memory until we have to. */
- for (;;)
- {
- c = *++s;
- if (c == '\n' || c == '\r')
- {
- d = (uchar *) s;
-
- if (s == buffer->rlimit)
- goto done;
-
- /* DOS line ending? */
- if (c == '\r' && s[1] == '\n')
- s++;
-
- if (s == buffer->rlimit)
- goto done;
-
- /* check for escaped newline */
- p = d;
- while (p != buffer->next_line && is_nvspace (p[-1]))
- p--;
- if (p == buffer->next_line || p[-1] != '\\')
- goto done;
-
- /* Have an escaped newline; process it and proceed to
- the slow path. */
- add_line_note (buffer, p - 1, p != d ? ' ' : '\\');
- d = p - 2;
- buffer->next_line = p - 1;
- break;
- }
- if (c == '?' && s[1] == '?' && _cpp_trigraph_map[s[2]])
- {
- /* Have a trigraph. We may or may not have to convert
- it. Add a line note regardless, for -Wtrigraphs. */
- add_line_note (buffer, s, s[2]);
- if (CPP_OPTION (pfile, trigraphs))
- {
- /* We do, and that means we have to switch to the
- slow path. */
- d = (uchar *) s;
- *d = _cpp_trigraph_map[s[2]];
- s += 2;
- break;
- }
- }
- }
-
-
- for (;;)
- {
- c = *++s;
- *++d = c;
-
- if (c == '\n' || c == '\r')
- {
- /* Handle DOS line endings. */
- if (c == '\r' && s != buffer->rlimit && s[1] == '\n')
- s++;
- if (s == buffer->rlimit)
- break;
-
- /* Escaped? */
- p = d;
- while (p != buffer->next_line && is_nvspace (p[-1]))
- p--;
- if (p == buffer->next_line || p[-1] != '\\')
- break;
-
- add_line_note (buffer, p - 1, p != d ? ' ': '\\');
- d = p - 2;
- buffer->next_line = p - 1;
- }
- else if (c == '?' && s[1] == '?' && _cpp_trigraph_map[s[2]])
- {
- /* Add a note regardless, for the benefit of -Wtrigraphs. */
- add_line_note (buffer, d, s[2]);
- if (CPP_OPTION (pfile, trigraphs))
- {
- *d = _cpp_trigraph_map[s[2]];
- s += 2;
- }
- }
- }
- }
- else
- {
- do
- s++;
- while (*s != '\n' && *s != '\r');
- d = (uchar *) s;
-
- /* Handle DOS line endings. */
- if (*s == '\r' && s != buffer->rlimit && s[1] == '\n')
- s++;
- }
-
- done:
- *d = '\n';
- /* A sentinel note that should never be processed. */
- add_line_note (buffer, d + 1, '\n');
- buffer->next_line = s + 1;
-}
-
-/* Return true if the trigraph indicated by NOTE should be warned
- about in a comment. */
-static bool
-warn_in_comment (cpp_reader *pfile, _cpp_line_note *note)
-{
- const uchar *p;
-
- /* Within comments we don't warn about trigraphs, unless the
- trigraph forms an escaped newline, as that may change
- behavior. */
- if (note->type != '/')
- return false;
-
- /* If -trigraphs, then this was an escaped newline iff the next note
- is coincident. */
- if (CPP_OPTION (pfile, trigraphs))
- return note[1].pos == note->pos;
-
- /* Otherwise, see if this forms an escaped newline. */
- p = note->pos + 3;
- while (is_nvspace (*p))
- p++;
-
- /* There might have been escaped newlines between the trigraph and the
- newline we found. Hence the position test. */
- return (*p == '\n' && p < note[1].pos);
-}
-
-/* Process the notes created by add_line_note as far as the current
- location. */
-void
-_cpp_process_line_notes (cpp_reader *pfile, int in_comment)
-{
- cpp_buffer *buffer = pfile->buffer;
-
- for (;;)
- {
- _cpp_line_note *note = &buffer->notes[buffer->cur_note];
- unsigned int col;
-
- if (note->pos > buffer->cur)
- break;
-
- buffer->cur_note++;
- col = CPP_BUF_COLUMN (buffer, note->pos + 1);
-
- if (note->type == '\\' || note->type == ' ')
- {
- if (note->type == ' ' && !in_comment)
- cpp_error_with_line (pfile, CPP_DL_WARNING, pfile->line_table->highest_line, col,
- "backslash and newline separated by space");
-
- if (buffer->next_line > buffer->rlimit)
- {
- cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->line_table->highest_line, col,
- "backslash-newline at end of file");
- /* Prevent "no newline at end of file" warning. */
- buffer->next_line = buffer->rlimit;
- }
-
- buffer->line_base = note->pos;
- CPP_INCREMENT_LINE (pfile, 0);
- }
- else if (_cpp_trigraph_map[note->type])
- {
- if (CPP_OPTION (pfile, warn_trigraphs)
- && (!in_comment || warn_in_comment (pfile, note)))
- {
- if (CPP_OPTION (pfile, trigraphs))
- cpp_error_with_line (pfile, CPP_DL_WARNING, pfile->line_table->highest_line, col,
- "trigraph ??%c converted to %c",
- note->type,
- (int) _cpp_trigraph_map[note->type]);
- else
- {
- cpp_error_with_line
- (pfile, CPP_DL_WARNING, pfile->line_table->highest_line, col,
- "trigraph ??%c ignored, use -trigraphs to enable",
- note->type);
- }
- }
- }
- else
- abort ();
- }
-}
-
-/* Skip a C-style block comment. We find the end of the comment by
- seeing if an asterisk is before every '/' we encounter. Returns
- nonzero if comment terminated by EOF, zero otherwise.
-
- Buffer->cur points to the initial asterisk of the comment. */
-bool
-_cpp_skip_block_comment (cpp_reader *pfile)
-{
- cpp_buffer *buffer = pfile->buffer;
- const uchar *cur = buffer->cur;
- uchar c;
-
- cur++;
- if (*cur == '/')
- cur++;
-
- for (;;)
- {
- /* People like decorating comments with '*', so check for '/'
- instead for efficiency. */
- c = *cur++;
-
- if (c == '/')
- {
- if (cur[-2] == '*')
- break;
-
- /* Warn about potential nested comments, but not if the '/'
- comes immediately before the true comment delimiter.
- Don't bother to get it right across escaped newlines. */
- if (CPP_OPTION (pfile, warn_comments)
- && cur[0] == '*' && cur[1] != '/')
- {
- buffer->cur = cur;
- cpp_error_with_line (pfile, CPP_DL_WARNING,
- pfile->line_table->highest_line, CPP_BUF_COL (buffer),
- "\"/*\" within comment");
- }
- }
- else if (c == '\n')
- {
- unsigned int cols;
- buffer->cur = cur - 1;
- _cpp_process_line_notes (pfile, true);
- if (buffer->next_line >= buffer->rlimit)
- return true;
- _cpp_clean_line (pfile);
-
- cols = buffer->next_line - buffer->line_base;
- CPP_INCREMENT_LINE (pfile, cols);
-
- cur = buffer->cur;
- }
- }
-
- buffer->cur = cur;
- _cpp_process_line_notes (pfile, true);
- return false;
-}
-
-/* Skip a C++ line comment, leaving buffer->cur pointing to the
- terminating newline. Handles escaped newlines. Returns nonzero
- if a multiline comment. */
-static int
-skip_line_comment (cpp_reader *pfile)
-{
- cpp_buffer *buffer = pfile->buffer;
- unsigned int orig_line = pfile->line_table->highest_line;
-
- while (*buffer->cur != '\n')
- buffer->cur++;
-
- _cpp_process_line_notes (pfile, true);
- return orig_line != pfile->line_table->highest_line;
-}
-
-/* Skips whitespace, saving the next non-whitespace character. */
-static void
-skip_whitespace (cpp_reader *pfile, cppchar_t c)
-{
- cpp_buffer *buffer = pfile->buffer;
- bool saw_NUL = false;
-
- do
- {
- /* Horizontal space always OK. */
- if (c == ' ' || c == '\t')
- ;
- /* Just \f \v or \0 left. */
- else if (c == '\0')
- saw_NUL = true;
- else if (pfile->state.in_directive && CPP_PEDANTIC (pfile))
- cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->line_table->highest_line,
- CPP_BUF_COL (buffer),
- "%s in preprocessing directive",
- c == '\f' ? "form feed" : "vertical tab");
-
- c = *buffer->cur++;
- }
- /* We only want non-vertical space, i.e. ' ' \t \f \v \0. */
- while (is_nvspace (c));
-
- if (saw_NUL)
- cpp_error (pfile, CPP_DL_WARNING, "null character(s) ignored");
-
- buffer->cur--;
-}
-
-/* See if the characters of a number token are valid in a name (no
- '.', '+' or '-'). */
-static int
-name_p (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;
-}
-
-/* Returns TRUE if the sequence starting at buffer->cur is invalid in
- an identifier. FIRST is TRUE if this starts an identifier. */
-static bool
-forms_identifier_p (cpp_reader *pfile, int first)
-{
- cpp_buffer *buffer = pfile->buffer;
-
- if (*buffer->cur == '$')
- {
- if (!CPP_OPTION (pfile, dollars_in_ident))
- return false;
-
- buffer->cur++;
- if (CPP_OPTION (pfile, warn_dollars) && !pfile->state.skipping)
- {
- CPP_OPTION (pfile, warn_dollars) = 0;
- cpp_error (pfile, CPP_DL_PEDWARN, "'$' in identifier or number");
- }
-
- return true;
- }
-
- /* Is this a syntactically valid UCN? */
- if (0 && *buffer->cur == '\\'
- && (buffer->cur[1] == 'u' || buffer->cur[1] == 'U'))
- {
- buffer->cur += 2;
- if (_cpp_valid_ucn (pfile, &buffer->cur, buffer->rlimit, 1 + !first))
- return true;
- buffer->cur -= 2;
- }
-
- return false;
-}
-
-/* Lex an identifier starting at BUFFER->CUR - 1. */
-static cpp_hashnode *
-lex_identifier (cpp_reader *pfile, const uchar *base)
-{
- cpp_hashnode *result;
- const uchar *cur;
-
- do
- {
- cur = pfile->buffer->cur;
-
- /* N.B. ISIDNUM does not include $. */
- while (ISIDNUM (*cur))
- cur++;
-
- pfile->buffer->cur = cur;
- }
- while (forms_identifier_p (pfile, false));
-
- result = (cpp_hashnode *)
- ht_lookup (pfile->hash_table, base, cur - base, HT_ALLOC);
-
- /* Rarely, identifiers require diagnostics when lexed. */
- if (__builtin_expect ((result->flags & NODE_DIAGNOSTIC)
- && !pfile->state.skipping, 0))
- {
- /* It is allowed to poison the same identifier twice. */
- if ((result->flags & NODE_POISONED) && !pfile->state.poisoned_ok)
- cpp_error (pfile, CPP_DL_ERROR, "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_error (pfile, CPP_DL_PEDWARN,
- "__VA_ARGS__ can only appear in the expansion"
- " of a C99 variadic macro");
- }
-
- return result;
-}
-
-/* Lex a number to NUMBER starting at BUFFER->CUR - 1. */
-static void
-lex_number (cpp_reader *pfile, cpp_string *number)
-{
- const uchar *cur;
- const uchar *base;
- uchar *dest;
-
- base = pfile->buffer->cur - 1;
- do
- {
- cur = pfile->buffer->cur;
-
- /* N.B. ISIDNUM does not include $. */
- while (ISIDNUM (*cur) || *cur == '.' || VALID_SIGN (*cur, cur[-1]))
- cur++;
-
- pfile->buffer->cur = cur;
- }
- while (forms_identifier_p (pfile, false));
-
- number->len = cur - base;
- dest = _cpp_unaligned_alloc (pfile, number->len + 1);
- memcpy (dest, base, number->len);
- dest[number->len] = '\0';
- number->text = dest;
-}
-
-/* Create a token of type TYPE with a literal spelling. */
-static void
-create_literal (cpp_reader *pfile, cpp_token *token, const uchar *base,
- unsigned int len, enum cpp_ttype type)
-{
- uchar *dest = _cpp_unaligned_alloc (pfile, len + 1);
-
- memcpy (dest, base, len);
- dest[len] = '\0';
- token->type = type;
- token->val.str.len = len;
- token->val.str.text = dest;
-}
-
-/* Lexes a string, character constant, or angle-bracketed header file
- name. The stored string contains the spelling, including opening
- quote and leading any leading 'L'. It returns the type of the
- literal, or CPP_OTHER if it was not properly terminated.
-
- The spelling is NUL-terminated, but it is not guaranteed that this
- is the first NUL since embedded NULs are preserved. */
-static void
-lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
-{
- bool saw_NUL = false;
- const uchar *cur;
- cppchar_t terminator;
- enum cpp_ttype type;
-
- cur = base;
- terminator = *cur++;
- if (terminator == 'L')
- terminator = *cur++;
- if (terminator == '\"')
- type = *base == 'L' ? CPP_WSTRING: CPP_STRING;
- else if (terminator == '\'')
- type = *base == 'L' ? CPP_WCHAR: CPP_CHAR;
- else
- terminator = '>', type = CPP_HEADER_NAME;
-
- for (;;)
- {
- cppchar_t c = *cur++;
-
- /* In #include-style directives, terminators are not escapable. */
- if (c == '\\' && !pfile->state.angled_headers && *cur != '\n')
- cur++;
- else if (c == terminator)
- break;
- else if (c == '\n')
- {
- cur--;
- type = CPP_OTHER;
- break;
- }
- else if (c == '\0')
- saw_NUL = true;
- }
-
- if (saw_NUL && !pfile->state.skipping)
- cpp_error (pfile, CPP_DL_WARNING,
- "null character(s) preserved in literal");
-
- pfile->buffer->cur = cur;
- create_literal (pfile, token, base, cur - base, type);
-}
-
-/* The stored comment includes the comment start and any terminator. */
-static void
-save_comment (cpp_reader *pfile, cpp_token *token, const unsigned char *from,
- cppchar_t type)
-{
- unsigned char *buffer;
- unsigned int len, clen;
-
- 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 (is_vspace (pfile->buffer->cur[-1]))
- len--;
-
- /* If we are currently in a directive, then we need to store all
- C++ comments as C comments internally, and so we need to
- allocate a little extra space in that case.
-
- Note that the only time we encounter a directive here is
- when we are saving comments in a "#define". */
- clen = (pfile->state.in_directive && type == '/') ? len + 2 : len;
-
- buffer = _cpp_unaligned_alloc (pfile, clen);
-
- token->type = CPP_COMMENT;
- token->val.str.len = clen;
- token->val.str.text = buffer;
-
- buffer[0] = '/';
- memcpy (buffer + 1, from, len - 1);
-
- /* Finish conversion to a C comment, if necessary. */
- if (pfile->state.in_directive && type == '/')
- {
- buffer[1] = '*';
- buffer[clen - 2] = '*';
- buffer[clen - 1] = '/';
- }
-}
-
-/* Allocate COUNT tokens for RUN. */
-void
-_cpp_init_tokenrun (tokenrun *run, unsigned int count)
-{
- run->base = xnewvec (cpp_token, count);
- run->limit = run->base + count;
- run->next = NULL;
-}
-
-/* Returns the next tokenrun, or creates one if there is none. */
-static tokenrun *
-next_tokenrun (tokenrun *run)
-{
- if (run->next == NULL)
- {
- run->next = xnew (tokenrun);
- run->next->prev = run;
- _cpp_init_tokenrun (run->next, 250);
- }
-
- return run->next;
-}
-
-/* Allocate a single token that is invalidated at the same time as the
- rest of the tokens on the line. Has its line and col set to the
- same as the last lexed token, so that diagnostics appear in the
- right place. */
-cpp_token *
-_cpp_temp_token (cpp_reader *pfile)
-{
- cpp_token *old, *result;
-
- old = pfile->cur_token - 1;
- if (pfile->cur_token == pfile->cur_run->limit)
- {
- pfile->cur_run = next_tokenrun (pfile->cur_run);
- pfile->cur_token = pfile->cur_run->base;
- }
-
- result = pfile->cur_token++;
- result->src_loc = old->src_loc;
- return result;
-}
-
-/* Lex a token into RESULT (external interface). Takes care of issues
- like directive handling, token lookahead, multiple include
- optimization and skipping. */
-const cpp_token *
-_cpp_lex_token (cpp_reader *pfile)
-{
- cpp_token *result;
-
- for (;;)
- {
- if (pfile->cur_token == pfile->cur_run->limit)
- {
- pfile->cur_run = next_tokenrun (pfile->cur_run);
- pfile->cur_token = pfile->cur_run->base;
- }
-
- if (pfile->lookaheads)
- {
- pfile->lookaheads--;
- result = pfile->cur_token++;
- }
- else
- result = _cpp_lex_direct (pfile);
-
- if (result->flags & BOL)
- {
- /* Is this a directive. If _cpp_handle_directive returns
- false, it is an assembler #. */
- if (result->type == CPP_HASH
- /* 6.10.3 p 11: Directives in a list of macro arguments
- gives undefined behavior. This implementation
- handles the directive as normal. */
- && pfile->state.parsing_args != 1
- && _cpp_handle_directive (pfile, result->flags & PREV_WHITE))
- continue;
- if (pfile->cb.line_change && !pfile->state.skipping)
- pfile->cb.line_change (pfile, result, pfile->state.parsing_args);
- }
-
- /* We don't skip tokens in directives. */
- if (pfile->state.in_directive)
- break;
-
- /* Outside a directive, invalidate controlling macros. At file
- EOF, _cpp_lex_direct takes care of popping the buffer, so we never
- get here and MI optimization works. */
- pfile->mi_valid = false;
-
- if (!pfile->state.skipping || result->type == CPP_EOF)
- break;
- }
-
- return result;
-}
-
-/* Returns true if a fresh line has been loaded. */
-bool
-_cpp_get_fresh_line (cpp_reader *pfile)
-{
- int return_at_eof;
-
- /* We can't get a new line until we leave the current directive. */
- if (pfile->state.in_directive)
- return false;
-
- for (;;)
- {
- cpp_buffer *buffer = pfile->buffer;
-
- if (!buffer->need_line)
- return true;
-
- if (buffer->next_line < buffer->rlimit)
- {
- _cpp_clean_line (pfile);
- return true;
- }
-
- /* First, get out of parsing arguments state. */
- if (pfile->state.parsing_args)
- return false;
-
- /* End of buffer. Non-empty files should end in a newline. */
- if (buffer->buf != buffer->rlimit
- && buffer->next_line > buffer->rlimit
- && !buffer->from_stage3)
- {
- /* Only warn once. */
- buffer->next_line = buffer->rlimit;
- cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->line_table->highest_line,
- CPP_BUF_COLUMN (buffer, buffer->cur),
- "no newline at end of file");
- }
-
- return_at_eof = buffer->return_at_eof;
- _cpp_pop_buffer (pfile);
- if (pfile->buffer == NULL || return_at_eof)
- return false;
- }
-}
-
-#define IF_NEXT_IS(CHAR, THEN_TYPE, ELSE_TYPE) \
- do \
- { \
- result->type = ELSE_TYPE; \
- if (*buffer->cur == CHAR) \
- buffer->cur++, result->type = THEN_TYPE; \
- } \
- while (0)
-
-/* Lex a token into pfile->cur_token, which is also incremented, to
- get diagnostics pointing to the correct location.
-
- Does not handle issues such as token lookahead, multiple-include
- optimization, directives, skipping etc. This function is only
- suitable for use by _cpp_lex_token, and in special cases like
- lex_expansion_token which doesn't care for any of these issues.
-
- When meeting a newline, returns CPP_EOF if parsing a directive,
- otherwise returns to the start of the token buffer if permissible.
- Returns the location of the lexed token. */
-cpp_token *
-_cpp_lex_direct (cpp_reader *pfile)
-{
- cppchar_t c;
- cpp_buffer *buffer;
- const unsigned char *comment_start;
- cpp_token *result = pfile->cur_token++;
-
- fresh_line:
- result->flags = 0;
- buffer = pfile->buffer;
- if (buffer->need_line)
- {
- if (!_cpp_get_fresh_line (pfile))
- {
- result->type = CPP_EOF;
- if (!pfile->state.in_directive)
- {
- /* Tell the compiler the line number of the EOF token. */
- result->src_loc = pfile->line_table->highest_line;
- result->flags = BOL;
- }
- return result;
- }
- if (!pfile->keep_tokens)
- {
- pfile->cur_run = &pfile->base_run;
- result = pfile->base_run.base;
- pfile->cur_token = result + 1;
- }
- result->flags = BOL;
- if (pfile->state.parsing_args == 2)
- result->flags |= PREV_WHITE;
- }
- buffer = pfile->buffer;
- update_tokens_line:
- result->src_loc = pfile->line_table->highest_line;
-
- skipped_white:
- if (buffer->cur >= buffer->notes[buffer->cur_note].pos
- && !pfile->overlaid_buffer)
- {
- _cpp_process_line_notes (pfile, false);
- result->src_loc = pfile->line_table->highest_line;
- }
- c = *buffer->cur++;
-
- LINEMAP_POSITION_FOR_COLUMN (result->src_loc, pfile->line_table,
- CPP_BUF_COLUMN (buffer, buffer->cur));
-
- switch (c)
- {
- case ' ': case '\t': case '\f': case '\v': case '\0':
- result->flags |= PREV_WHITE;
- skip_whitespace (pfile, c);
- goto skipped_white;
-
- case '\n':
- if (buffer->cur < buffer->rlimit)
- CPP_INCREMENT_LINE (pfile, 0);
- buffer->need_line = true;
- goto fresh_line;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- result->type = CPP_NUMBER;
- lex_number (pfile, &result->val.str);
- break;
-
- case 'L':
- /* 'L' may introduce wide characters or strings. */
- if (*buffer->cur == '\'' || *buffer->cur == '"')
- {
- lex_string (pfile, result, buffer->cur - 1);
- break;
- }
- /* 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 '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 = lex_identifier (pfile, buffer->cur - 1);
-
- /* Convert named operators to their proper types. */
- if (result->val.node->flags & NODE_OPERATOR)
- {
- result->flags |= NAMED_OP;
- result->type = result->val.node->directive_index;
- }
- break;
-
- case '\'':
- case '"':
- lex_string (pfile, result, buffer->cur - 1);
- break;
-
- case '/':
- /* A potential block or line comment. */
- comment_start = buffer->cur;
- c = *buffer->cur;
-
- if (c == '*')
- {
- if (_cpp_skip_block_comment (pfile))
- cpp_error (pfile, CPP_DL_ERROR, "unterminated comment");
- }
- else if (c == '/' && (CPP_OPTION (pfile, cplusplus_comments)
- || cpp_in_system_header (pfile)))
- {
- /* 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_error (pfile, CPP_DL_PEDWARN,
- "C++ style comments are not allowed in ISO C90");
- cpp_error (pfile, CPP_DL_PEDWARN,
- "(this will be reported only once per input file)");
- buffer->warned_cplusplus_comments = 1;
- }
-
- if (skip_line_comment (pfile) && CPP_OPTION (pfile, warn_comments))
- cpp_error (pfile, CPP_DL_WARNING, "multi-line comment");
- }
- else if (c == '=')
- {
- buffer->cur++;
- result->type = CPP_DIV_EQ;
- break;
- }
- else
- {
- result->type = CPP_DIV;
- break;
- }
-
- if (!pfile->state.save_comments)
- {
- result->flags |= PREV_WHITE;
- goto update_tokens_line;
- }
-
- /* Save the comment as a token in its own right. */
- save_comment (pfile, result, comment_start, c);
- break;
-
- case '<':
- if (pfile->state.angled_headers)
- {
- lex_string (pfile, result, buffer->cur - 1);
- break;
- }
-
- result->type = CPP_LESS;
- if (*buffer->cur == '=')
- buffer->cur++, result->type = CPP_LESS_EQ;
- else if (*buffer->cur == '<')
- {
- buffer->cur++;
- IF_NEXT_IS ('=', CPP_LSHIFT_EQ, CPP_LSHIFT);
- }
- else if (*buffer->cur == '?' && CPP_OPTION (pfile, cplusplus))
- {
- buffer->cur++;
- IF_NEXT_IS ('=', CPP_MIN_EQ, CPP_MIN);
- }
- else if (CPP_OPTION (pfile, digraphs))
- {
- if (*buffer->cur == ':')
- {
- buffer->cur++;
- result->flags |= DIGRAPH;
- result->type = CPP_OPEN_SQUARE;
- }
- else if (*buffer->cur == '%')
- {
- buffer->cur++;
- result->flags |= DIGRAPH;
- result->type = CPP_OPEN_BRACE;
- }
- }
- break;
-
- case '>':
- result->type = CPP_GREATER;
- if (*buffer->cur == '=')
- buffer->cur++, result->type = CPP_GREATER_EQ;
- else if (*buffer->cur == '>')
- {
- buffer->cur++;
- IF_NEXT_IS ('=', CPP_RSHIFT_EQ, CPP_RSHIFT);
- }
- else if (*buffer->cur == '?' && CPP_OPTION (pfile, cplusplus))
- {
- buffer->cur++;
- IF_NEXT_IS ('=', CPP_MAX_EQ, CPP_MAX);
- }
- break;
-
- case '%':
- result->type = CPP_MOD;
- if (*buffer->cur == '=')
- buffer->cur++, result->type = CPP_MOD_EQ;
- else if (CPP_OPTION (pfile, digraphs))
- {
- if (*buffer->cur == ':')
- {
- buffer->cur++;
- result->flags |= DIGRAPH;
- result->type = CPP_HASH;
- if (*buffer->cur == '%' && buffer->cur[1] == ':')
- buffer->cur += 2, result->type = CPP_PASTE;
- }
- else if (*buffer->cur == '>')
- {
- buffer->cur++;
- result->flags |= DIGRAPH;
- result->type = CPP_CLOSE_BRACE;
- }
- }
- break;
-
- case '.':
- result->type = CPP_DOT;
- if (ISDIGIT (*buffer->cur))
- {
- result->type = CPP_NUMBER;
- lex_number (pfile, &result->val.str);
- }
- else if (*buffer->cur == '.' && buffer->cur[1] == '.')
- buffer->cur += 2, result->type = CPP_ELLIPSIS;
- else if (*buffer->cur == '*' && CPP_OPTION (pfile, cplusplus))
- buffer->cur++, result->type = CPP_DOT_STAR;
- break;
-
- case '+':
- result->type = CPP_PLUS;
- if (*buffer->cur == '+')
- buffer->cur++, result->type = CPP_PLUS_PLUS;
- else if (*buffer->cur == '=')
- buffer->cur++, result->type = CPP_PLUS_EQ;
- break;
-
- case '-':
- result->type = CPP_MINUS;
- if (*buffer->cur == '>')
- {
- buffer->cur++;
- result->type = CPP_DEREF;
- if (*buffer->cur == '*' && CPP_OPTION (pfile, cplusplus))
- buffer->cur++, result->type = CPP_DEREF_STAR;
- }
- else if (*buffer->cur == '-')
- buffer->cur++, result->type = CPP_MINUS_MINUS;
- else if (*buffer->cur == '=')
- buffer->cur++, result->type = CPP_MINUS_EQ;
- break;
-
- case '&':
- result->type = CPP_AND;
- if (*buffer->cur == '&')
- buffer->cur++, result->type = CPP_AND_AND;
- else if (*buffer->cur == '=')
- buffer->cur++, result->type = CPP_AND_EQ;
- break;
-
- case '|':
- result->type = CPP_OR;
- if (*buffer->cur == '|')
- buffer->cur++, result->type = CPP_OR_OR;
- else if (*buffer->cur == '=')
- buffer->cur++, result->type = CPP_OR_EQ;
- break;
-
- case ':':
- result->type = CPP_COLON;
- if (*buffer->cur == ':' && CPP_OPTION (pfile, cplusplus))
- buffer->cur++, result->type = CPP_SCOPE;
- else if (*buffer->cur == '>' && CPP_OPTION (pfile, digraphs))
- {
- buffer->cur++;
- result->flags |= DIGRAPH;
- result->type = CPP_CLOSE_SQUARE;
- }
- break;
-
- case '*': IF_NEXT_IS ('=', CPP_MULT_EQ, CPP_MULT); break;
- case '=': IF_NEXT_IS ('=', CPP_EQ_EQ, CPP_EQ); break;
- case '!': IF_NEXT_IS ('=', CPP_NOT_EQ, CPP_NOT); break;
- case '^': IF_NEXT_IS ('=', CPP_XOR_EQ, CPP_XOR); break;
- case '#': IF_NEXT_IS ('#', CPP_PASTE, CPP_HASH); break;
-
- case '?': result->type = CPP_QUERY; 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;
-
- case '$':
- case '\\':
- {
- const uchar *base = --buffer->cur;
-
- if (forms_identifier_p (pfile, true))
- {
- result->type = CPP_NAME;
- result->val.node = lex_identifier (pfile, base);
- break;
- }
- buffer->cur++;
- }
-
- default:
- create_literal (pfile, result, buffer->cur - 1, 1, CPP_OTHER);
- break;
- }
-
- return result;
-}
-
-/* An upper bound on the number of bytes needed to spell TOKEN.
- Does not include preceding whitespace. */
-unsigned int
-cpp_token_len (const cpp_token *token)
-{
- unsigned int len;
-
- switch (TOKEN_SPELL (token))
- {
- default: len = 4; break;
- case SPELL_LITERAL: len = token->val.str.len; break;
- case SPELL_IDENT: len = NODE_LEN (token->val.node); break;
- }
-
- return len;
-}
-
-/* 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.
- FIXME: Would be nice if we didn't need the PFILE argument. */
-unsigned char *
-cpp_spell_token (cpp_reader *pfile, 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;
-
- spell_ident:
- case SPELL_IDENT:
- memcpy (buffer, NODE_NAME (token->val.node), NODE_LEN (token->val.node));
- buffer += NODE_LEN (token->val.node);
- break;
-
- case SPELL_LITERAL:
- memcpy (buffer, token->val.str.text, token->val.str.len);
- buffer += token->val.str.len;
- break;
-
- case SPELL_NONE:
- cpp_error (pfile, CPP_DL_ICE,
- "unspellable token %s", TOKEN_NAME (token));
- break;
- }
-
- return buffer;
-}
-
-/* Returns TOKEN spelt as a null-terminated string. The string is
- freed when the reader is destroyed. Useful for diagnostics. */
-unsigned char *
-cpp_token_as_text (cpp_reader *pfile, const cpp_token *token)
-{
- unsigned int len = cpp_token_len (token) + 1;
- unsigned char *start = _cpp_unaligned_alloc (pfile, len), *end;
-
- end = cpp_spell_token (pfile, token, start);
- end[0] = '\0';
-
- return start;
-}
-
-/* Used by C front ends, which really should move to using
- cpp_token_as_text. */
-const char *
-cpp_type2name (enum cpp_ttype type)
-{
- return (const char *) token_spellings[type].name;
-}
-
-/* Writes the spelling of token to FP, without any preceding space.
- Separated from cpp_spell_token for efficiency - to avoid stdio
- double-buffering. */
-void
-cpp_output_token (const cpp_token *token, FILE *fp)
-{
- switch (TOKEN_SPELL (token))
- {
- case SPELL_OPERATOR:
- {
- const unsigned char *spelling;
- int 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);
-
- c = *spelling;
- do
- putc (c, fp);
- while ((c = *++spelling) != '\0');
- }
- break;
-
- spell_ident:
- case SPELL_IDENT:
- fwrite (NODE_NAME (token->val.node), 1, NODE_LEN (token->val.node), fp);
- break;
-
- case SPELL_LITERAL:
- fwrite (token->val.str.text, 1, token->val.str.len, fp);
- break;
-
- case SPELL_NONE:
- /* An error, most probably. */
- break;
- }
-}
-
-/* Compare two tokens. */
-int
-_cpp_equiv_tokens (const cpp_token *a, const cpp_token *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_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_LITERAL:
- return (a->val.str.len == b->val.str.len
- && !memcmp (a->val.str.text, b->val.str.text,
- a->val.str.len));
- }
-
- return 0;
-}
-
-/* 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 (cpp_reader *pfile, const cpp_token *token1,
- const cpp_token *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 == '-');
- /* UCNs */
- case CPP_OTHER: return ((token1->val.str.text[0] == '\\'
- && b == CPP_NAME)
- || (CPP_OPTION (pfile, objc)
- && token1->val.str.text[0] == '@'
- && (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. If there are
- macros, special token padding is not performed. */
-void
-cpp_output_line (cpp_reader *pfile, FILE *fp)
-{
- const cpp_token *token;
-
- token = cpp_get_token (pfile);
- while (token->type != CPP_EOF)
- {
- cpp_output_token (token, fp);
- token = cpp_get_token (pfile);
- if (token->flags & PREV_WHITE)
- putc (' ', fp);
- }
-
- putc ('\n', fp);
-}
-
-/* Memory buffers. Changing these three constants can have a dramatic
- effect on performance. The values here are reasonable defaults,
- but might be tuned. If you adjust them, be sure to test across a
- range of uses of cpplib, including heavy nested function-like macro
- expansion. Also check the change in peak memory usage (NJAMD is a
- good tool for this). */
-#define MIN_BUFF_SIZE 8000
-#define BUFF_SIZE_UPPER_BOUND(MIN_SIZE) (MIN_BUFF_SIZE + (MIN_SIZE) * 3 / 2)
-#define EXTENDED_BUFF_SIZE(BUFF, MIN_EXTRA) \
- (MIN_EXTRA + ((BUFF)->limit - (BUFF)->cur) * 2)
-
-#if MIN_BUFF_SIZE > BUFF_SIZE_UPPER_BOUND (0)
- #error BUFF_SIZE_UPPER_BOUND must be at least as large as MIN_BUFF_SIZE!
-#endif
-
-/* Create a new allocation buffer. Place the control block at the end
- of the buffer, so that buffer overflows will cause immediate chaos. */
-static _cpp_buff *
-new_buff (size_t len)
-{
- _cpp_buff *result;
- unsigned char *base;
-
- if (len < MIN_BUFF_SIZE)
- len = MIN_BUFF_SIZE;
- len = CPP_ALIGN (len);
-
- base = xmalloc (len + sizeof (_cpp_buff));
- result = (_cpp_buff *) (base + len);
- result->base = base;
- result->cur = base;
- result->limit = base + len;
- result->next = NULL;
- return result;
-}
-
-/* Place a chain of unwanted allocation buffers on the free list. */
-void
-_cpp_release_buff (cpp_reader *pfile, _cpp_buff *buff)
-{
- _cpp_buff *end = buff;
-
- while (end->next)
- end = end->next;
- end->next = pfile->free_buffs;
- pfile->free_buffs = buff;
-}
-
-/* Return a free buffer of size at least MIN_SIZE. */
-_cpp_buff *
-_cpp_get_buff (cpp_reader *pfile, size_t min_size)
-{
- _cpp_buff *result, **p;
-
- for (p = &pfile->free_buffs;; p = &(*p)->next)
- {
- size_t size;
-
- if (*p == NULL)
- return new_buff (min_size);
- result = *p;
- size = result->limit - result->base;
- /* Return a buffer that's big enough, but don't waste one that's
- way too big. */
- if (size >= min_size && size <= BUFF_SIZE_UPPER_BOUND (min_size))
- break;
- }
-
- *p = result->next;
- result->next = NULL;
- result->cur = result->base;
- return result;
-}
-
-/* Creates a new buffer with enough space to hold the uncommitted
- remaining bytes of BUFF, and at least MIN_EXTRA more bytes. Copies
- the excess bytes to the new buffer. Chains the new buffer after
- BUFF, and returns the new buffer. */
-_cpp_buff *
-_cpp_append_extend_buff (cpp_reader *pfile, _cpp_buff *buff, size_t min_extra)
-{
- size_t size = EXTENDED_BUFF_SIZE (buff, min_extra);
- _cpp_buff *new_buff = _cpp_get_buff (pfile, size);
-
- buff->next = new_buff;
- memcpy (new_buff->base, buff->cur, BUFF_ROOM (buff));
- return new_buff;
-}
-
-/* Creates a new buffer with enough space to hold the uncommitted
- remaining bytes of the buffer pointed to by BUFF, and at least
- MIN_EXTRA more bytes. Copies the excess bytes to the new buffer.
- Chains the new buffer before the buffer pointed to by BUFF, and
- updates the pointer to point to the new buffer. */
-void
-_cpp_extend_buff (cpp_reader *pfile, _cpp_buff **pbuff, size_t min_extra)
-{
- _cpp_buff *new_buff, *old_buff = *pbuff;
- size_t size = EXTENDED_BUFF_SIZE (old_buff, min_extra);
-
- new_buff = _cpp_get_buff (pfile, size);
- memcpy (new_buff->base, old_buff->cur, BUFF_ROOM (old_buff));
- new_buff->next = old_buff;
- *pbuff = new_buff;
-}
-
-/* Free a chain of buffers starting at BUFF. */
-void
-_cpp_free_buff (_cpp_buff *buff)
-{
- _cpp_buff *next;
-
- for (; buff; buff = next)
- {
- next = buff->next;
- free (buff->base);
- }
-}
-
-/* Allocate permanent, unaligned storage of length LEN. */
-unsigned char *
-_cpp_unaligned_alloc (cpp_reader *pfile, size_t len)
-{
- _cpp_buff *buff = pfile->u_buff;
- unsigned char *result = buff->cur;
-
- if (len > (size_t) (buff->limit - result))
- {
- buff = _cpp_get_buff (pfile, len);
- buff->next = pfile->u_buff;
- pfile->u_buff = buff;
- result = buff->cur;
- }
-
- buff->cur = result + len;
- return result;
-}
-
-/* Allocate permanent, unaligned storage of length LEN from a_buff.
- That buffer is used for growing allocations when saving macro
- replacement lists in a #define, and when parsing an answer to an
- assertion in #assert, #unassert or #if (and therefore possibly
- whilst expanding macros). It therefore must not be used by any
- code that they might call: specifically the lexer and the guts of
- the macro expander.
-
- All existing other uses clearly fit this restriction: storing
- registered pragmas during initialization. */
-unsigned char *
-_cpp_aligned_alloc (cpp_reader *pfile, size_t len)
-{
- _cpp_buff *buff = pfile->a_buff;
- unsigned char *result = buff->cur;
-
- if (len > (size_t) (buff->limit - result))
- {
- buff = _cpp_get_buff (pfile, len);
- buff->next = pfile->a_buff;
- pfile->a_buff = buff;
- result = buff->cur;
- }
-
- buff->cur = result + len;
- return result;
-}
diff --git a/gcc/cpplib.c b/gcc/cpplib.c
deleted file mode 100644
index 808dcdaa2b1..00000000000
--- a/gcc/cpplib.c
+++ /dev/null
@@ -1,1987 +0,0 @@
-/* CPP Library. (Directive handling.)
- Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 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 "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;
- unsigned int line; /* Line where condition started. */
- const cpp_hashnode *mi_cmacro;/* macro name for #ifndef around entire file */
- bool skip_elses; /* Can future #else / #elif be skipped? */
- bool was_skipping; /* If were skipping on entry. */
- int type; /* Most recent conditional for diagnostics. */
-};
-
-/* Contains a registered pragma or pragma namespace. */
-typedef void (*pragma_cb) (cpp_reader *);
-struct pragma_entry
-{
- struct pragma_entry *next;
- const cpp_hashnode *pragma; /* Name and length. */
- int is_nspace;
- union {
- pragma_cb handler;
- struct pragma_entry *space;
- } u;
-};
-
-/* 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).
-
- EXPAND is set on directives that are always macro-expanded. */
-#define COND (1 << 0)
-#define IF_COND (1 << 1)
-#define INCL (1 << 2)
-#define IN_I (1 << 3)
-#define EXPAND (1 << 4)
-
-/* Defines one #-directive, including how to handle it. */
-typedef void (*directive_handler) (cpp_reader *);
-typedef struct directive directive;
-struct directive
-{
- directive_handler handler; /* Function to handle directive. */
- const uchar *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 (cpp_reader *);
-static void check_eol (cpp_reader *);
-static void start_directive (cpp_reader *);
-static void prepare_directive_trad (cpp_reader *);
-static void end_directive (cpp_reader *, int);
-static void directive_diagnostics (cpp_reader *, const directive *, int);
-static void run_directive (cpp_reader *, int, const char *, size_t);
-static char *glue_header_name (cpp_reader *);
-static const char *parse_include (cpp_reader *, int *);
-static void push_conditional (cpp_reader *, int, int, const cpp_hashnode *);
-static unsigned int read_flag (cpp_reader *, unsigned int);
-static int strtoul_for_line (const uchar *, unsigned int, unsigned long *);
-static void do_diagnostic (cpp_reader *, int, int);
-static cpp_hashnode *lex_macro_node (cpp_reader *);
-static int undefine_macros (cpp_reader *, cpp_hashnode *, void *);
-static void do_include_common (cpp_reader *, enum include_type);
-static struct pragma_entry *lookup_pragma_entry (struct pragma_entry *,
- const cpp_hashnode *);
-static struct pragma_entry *insert_pragma_entry (cpp_reader *,
- struct pragma_entry **,
- const cpp_hashnode *,
- pragma_cb);
-static int count_registered_pragmas (struct pragma_entry *);
-static char ** save_registered_pragmas (struct pragma_entry *, char **);
-static char ** restore_registered_pragmas (cpp_reader *, struct pragma_entry *,
- char **);
-static void do_pragma_once (cpp_reader *);
-static void do_pragma_poison (cpp_reader *);
-static void do_pragma_system_header (cpp_reader *);
-static void do_pragma_dependency (cpp_reader *);
-static void do_linemarker (cpp_reader *);
-static const cpp_token *get_token_no_padding (cpp_reader *);
-static const cpp_token *get__Pragma_string (cpp_reader *);
-static void destringize_and_run (cpp_reader *, const cpp_string *);
-static int parse_answer (cpp_reader *, struct answer **, int);
-static cpp_hashnode *parse_assertion (cpp_reader *, struct answer **, int);
-static struct answer ** find_answer (cpp_hashnode *, const struct answer *);
-static void handle_assertion (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 | EXPAND) /* 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 | EXPAND) /* 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, EXPAND) /* 2465 */ \
-D(elif, T_ELIF, STDC89, COND | EXPAND) /* 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 | EXPAND) /* 19 */ \
-D(ident, T_IDENT, EXTENSION, IN_I) /* 11 */ \
-D(import, T_IMPORT, EXTENSION, INCL | EXPAND) /* 0 ObjC */ \
-D(assert, T_ASSERT, EXTENSION, 0) /* 0 SVR4 */ \
-D(unassert, T_UNASSERT, EXTENSION, 0) /* 0 SVR4 */ \
-D(sccs, T_SCCS, EXTENSION, 0) /* 0 SVR4? */
-
-/* Use the table to generate a series of prototypes, an enum for the
- directive names, and an array of directive handlers. */
-
-#define D(name, t, o, f) static void do_##name (cpp_reader *);
-DIRECTIVE_TABLE
-#undef D
-
-#define D(n, tag, o, f) tag,
-enum
-{
- DIRECTIVE_TABLE
- N_DIRECTIVES
-};
-#undef D
-
-#define D(name, t, origin, flags) \
-{ do_##name, (const uchar *) #name, \
- sizeof #name - 1, origin, flags },
-static const directive dtable[] =
-{
-DIRECTIVE_TABLE
-};
-#undef D
-#undef DIRECTIVE_TABLE
-
-/* Wrapper struct directive for linemarkers.
- The origin is more or less true - the original K+R cpp
- did use this notation in its preprocessed output. */
-static const directive linemarker_dir =
-{
- do_linemarker, U"#", 1, KANDR, IN_I
-};
-
-#define SEEN_EOL() (pfile->cur_token[-1].type == CPP_EOF)
-
-/* Skip any remaining tokens in a directive. */
-static void
-skip_rest_of_line (cpp_reader *pfile)
-{
- /* Discard all stacked contexts. */
- while (pfile->context->prev)
- _cpp_pop_context (pfile);
-
- /* Sweep up all tokens remaining on the line. */
- if (! SEEN_EOL ())
- while (_cpp_lex_token (pfile)->type != CPP_EOF)
- ;
-}
-
-/* Ensure there are no stray tokens at the end of a directive. */
-static void
-check_eol (cpp_reader *pfile)
-{
- if (! SEEN_EOL () && _cpp_lex_token (pfile)->type != CPP_EOF)
- cpp_error (pfile, CPP_DL_PEDWARN, "extra tokens at end of #%s directive",
- pfile->directive->name);
-}
-
-/* Called when entering a directive, _Pragma or command-line directive. */
-static void
-start_directive (cpp_reader *pfile)
-{
- /* 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_line = pfile->line_table->highest_line;
-}
-
-/* Called when leaving a directive, _Pragma or command-line directive. */
-static void
-end_directive (cpp_reader *pfile, int skip_line)
-{
- if (CPP_OPTION (pfile, traditional))
- {
- /* Revert change of prepare_directive_trad. */
- pfile->state.prevent_expansion--;
-
- if (pfile->directive != &dtable[T_DEFINE])
- _cpp_remove_overlay (pfile);
- }
- /* We don't skip for an assembler #. */
- else if (skip_line)
- {
- skip_rest_of_line (pfile);
- if (!pfile->keep_tokens)
- {
- pfile->cur_run = &pfile->base_run;
- pfile->cur_token = pfile->base_run.base;
- }
- }
-
- /* Restore state. */
- pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
- pfile->state.in_directive = 0;
- pfile->state.in_expression = 0;
- pfile->state.angled_headers = 0;
- pfile->directive = 0;
-}
-
-/* Prepare to handle the directive in pfile->directive. */
-static void
-prepare_directive_trad (cpp_reader *pfile)
-{
- if (pfile->directive != &dtable[T_DEFINE])
- {
- bool no_expand = (pfile->directive
- && ! (pfile->directive->flags & EXPAND));
- bool was_skipping = pfile->state.skipping;
-
- pfile->state.in_expression = (pfile->directive == &dtable[T_IF]
- || pfile->directive == &dtable[T_ELIF]);
- if (pfile->state.in_expression)
- pfile->state.skipping = false;
-
- if (no_expand)
- pfile->state.prevent_expansion++;
- _cpp_scan_out_logical_line (pfile, NULL);
- if (no_expand)
- pfile->state.prevent_expansion--;
-
- pfile->state.skipping = was_skipping;
- _cpp_overlay_buffer (pfile, pfile->out.base,
- pfile->out.cur - pfile->out.base);
- }
-
- /* Stop ISO C from expanding anything. */
- pfile->state.prevent_expansion++;
-}
-
-/* Output diagnostics for a directive DIR. INDENTED is nonzero if
- the '#' was indented. */
-static void
-directive_diagnostics (cpp_reader *pfile, const directive *dir, int indented)
-{
- /* Issue -pedantic warnings for extensions. */
- if (CPP_PEDANTIC (pfile)
- && ! pfile->state.skipping
- && dir->origin == EXTENSION)
- cpp_error (pfile, CPP_DL_PEDWARN, "#%s is a GCC extension", dir->name);
-
- /* 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. #elif cannot be used at all. */
- if (CPP_WTRADITIONAL (pfile))
- {
- if (dir == &dtable[T_ELIF])
- cpp_error (pfile, CPP_DL_WARNING,
- "suggest not using #elif in traditional C");
- else if (indented && dir->origin == KANDR)
- cpp_error (pfile, CPP_DL_WARNING,
- "traditional C ignores #%s with the # indented",
- dir->name);
- else if (!indented && dir->origin != KANDR)
- cpp_error (pfile, CPP_DL_WARNING,
- "suggest hiding #%s from traditional C with an indented #",
- dir->name);
- }
-}
-
-/* Check if we have a known directive. INDENTED is nonzero if the
- '#' of the directive was indented. This function is in this file
- to save unnecessarily exporting dtable etc. to cpplex.c. Returns
- nonzero if the line of tokens has been handled, zero if we should
- continue processing the line. */
-int
-_cpp_handle_directive (cpp_reader *pfile, int indented)
-{
- const directive *dir = 0;
- const cpp_token *dname;
- bool was_parsing_args = pfile->state.parsing_args;
- int skip = 1;
-
- if (was_parsing_args)
- {
- if (CPP_OPTION (pfile, pedantic))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "embedding a directive within macro arguments is not portable");
- pfile->state.parsing_args = 0;
- pfile->state.prevent_expansion = 0;
- }
- start_directive (pfile);
- dname = _cpp_lex_token (pfile);
-
- if (dname->type == CPP_NAME)
- {
- if (dname->val.node->is_directive)
- dir = &dtable[dname->val.node->directive_index];
- }
- /* We do not recognize the # followed by a number extension in
- assembler code. */
- else if (dname->type == CPP_NUMBER && CPP_OPTION (pfile, lang) != CLK_ASM)
- {
- dir = &linemarker_dir;
- if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, preprocessed)
- && ! pfile->state.skipping)
- cpp_error (pfile, CPP_DL_PEDWARN,
- "style of line directive is a GCC extension");
- }
-
- if (dir)
- {
- /* If we have a directive that is not an opening conditional,
- invalidate any control macro. */
- if (! (dir->flags & IF_COND))
- pfile->mi_valid = false;
-
- /* 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. cppmacro.c
- puts a space in front of any '#' at the start of a macro. */
- if (CPP_OPTION (pfile, preprocessed)
- && (indented || !(dir->flags & IN_I)))
- {
- skip = 0;
- dir = 0;
- }
- else
- {
- /* In failed conditional groups, all non-conditional
- directives are ignored. Before doing that, whether
- skipping or not, we should lex angle-bracketed headers
- correctly, and maybe output some diagnostics. */
- pfile->state.angled_headers = dir->flags & INCL;
- pfile->state.directive_wants_padding = dir->flags & INCL;
- if (! CPP_OPTION (pfile, preprocessed))
- directive_diagnostics (pfile, dir, indented);
- if (pfile->state.skipping && !(dir->flags & COND))
- dir = 0;
- }
- }
- else if (dname->type == CPP_EOF)
- ; /* CPP_EOF is the "null directive". */
- else
- {
- /* 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)
- skip = 0;
- else if (!pfile->state.skipping)
- cpp_error (pfile, CPP_DL_ERROR, "invalid preprocessing directive #%s",
- cpp_token_as_text (pfile, dname));
- }
-
- pfile->directive = dir;
- if (CPP_OPTION (pfile, traditional))
- prepare_directive_trad (pfile);
-
- if (dir)
- pfile->directive->handler (pfile);
- else if (skip == 0)
- _cpp_backup_tokens (pfile, 1);
-
- end_directive (pfile, skip);
- if (was_parsing_args)
- {
- /* Restore state when within macro args. */
- pfile->state.parsing_args = 2;
- pfile->state.prevent_expansion = 1;
- }
- return skip;
-}
-
-/* Directive handler wrapper used by the command line option
- processor. BUF is \n terminated. */
-static void
-run_directive (cpp_reader *pfile, int dir_no, const char *buf, size_t count)
-{
- cpp_push_buffer (pfile, (const uchar *) buf, count,
- /* from_stage3 */ true);
- /* Disgusting hack. */
- if (dir_no == T_PRAGMA)
- pfile->buffer->file = pfile->buffer->prev->file;
- start_directive (pfile);
-
- /* This is a short-term fix to prevent a leading '#' being
- interpreted as a directive. */
- _cpp_clean_line (pfile);
-
- pfile->directive = &dtable[dir_no];
- if (CPP_OPTION (pfile, traditional))
- prepare_directive_trad (pfile);
- pfile->directive->handler (pfile);
- end_directive (pfile, 1);
- if (dir_no == T_PRAGMA)
- pfile->buffer->file = NULL;
- _cpp_pop_buffer (pfile);
-}
-
-/* Checks for validity the macro name in #define, #undef, #ifdef and
- #ifndef directives. */
-static cpp_hashnode *
-lex_macro_node (cpp_reader *pfile)
-{
- const cpp_token *token = _cpp_lex_token (pfile);
-
- /* The token immediately after #define must be an identifier. That
- identifier may not be "defined", per C99 6.10.8p4.
- In C++, it may not be any of the "named operators" either,
- per C++98 [lex.digraph], [lex.key].
- Finally, the identifier may not have been poisoned. (In that case
- the lexer has issued the error message for us.) */
-
- if (token->type == CPP_NAME)
- {
- cpp_hashnode *node = token->val.node;
-
- if (node == pfile->spec_nodes.n_defined)
- cpp_error (pfile, CPP_DL_ERROR,
- "\"defined\" cannot be used as a macro name");
- else if (! (node->flags & NODE_POISONED))
- return node;
- }
- else if (token->flags & NAMED_OP)
- cpp_error (pfile, CPP_DL_ERROR,
- "\"%s\" cannot be used as a macro name as it is an operator in C++",
- NODE_NAME (token->val.node));
- else if (token->type == CPP_EOF)
- cpp_error (pfile, CPP_DL_ERROR, "no macro name given in #%s directive",
- pfile->directive->name);
- else
- cpp_error (pfile, CPP_DL_ERROR, "macro names must be identifiers");
-
- return NULL;
-}
-
-/* Process a #define directive. Most work is done in cppmacro.c. */
-static void
-do_define (cpp_reader *pfile)
-{
- cpp_hashnode *node = lex_macro_node (pfile);
-
- if (node)
- {
- /* If we have been requested to expand comments into macros,
- then re-enable saving of comments. */
- pfile->state.save_comments =
- ! CPP_OPTION (pfile, discard_comments_in_macro_exp);
-
- if (_cpp_create_definition (pfile, node))
- if (pfile->cb.define)
- pfile->cb.define (pfile, pfile->directive_line, node);
- }
-}
-
-/* Handle #undef. Mark the identifier NT_VOID in the hash table. */
-static void
-do_undef (cpp_reader *pfile)
-{
- cpp_hashnode *node = lex_macro_node (pfile);
-
- if (node)
- {
- if (pfile->cb.undef)
- pfile->cb.undef (pfile, pfile->directive_line, node);
-
- /* 6.10.3.5 paragraph 2: [#undef] is ignored if the specified
- identifier is not currently defined as a macro name. */
- if (node->type == NT_MACRO)
- {
- if (node->flags & NODE_WARN)
- cpp_error (pfile, CPP_DL_WARNING,
- "undefining \"%s\"", NODE_NAME (node));
-
- if (CPP_OPTION (pfile, warn_unused_macros))
- _cpp_warn_if_unused_macro (pfile, node, NULL);
-
- _cpp_free_definition (node);
- }
- }
-
- check_eol (pfile);
-}
-
-/* Undefine a single macro/assertion/whatever. */
-
-static int
-undefine_macros (cpp_reader *pfile, cpp_hashnode *h,
- void *data_p ATTRIBUTE_UNUSED)
-{
- switch (h->type)
- {
- case NT_VOID:
- break;
-
- case NT_MACRO:
- if (pfile->cb.undef)
- (*pfile->cb.undef) (pfile, pfile->directive_line, h);
-
- if (CPP_OPTION (pfile, warn_unused_macros))
- _cpp_warn_if_unused_macro (pfile, h, NULL);
-
- /* And fall through.... */
- case NT_ASSERTION:
- _cpp_free_definition (h);
- break;
-
- default:
- abort ();
- }
- h->flags &= ~NODE_POISONED;
- return 1;
-}
-
-/* Undefine all macros and assertions. */
-
-void
-cpp_undef_all (cpp_reader *pfile)
-{
- cpp_forall_identifiers (pfile, undefine_macros, NULL);
-}
-
-
-/* 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 a malloced filename. */
-static char *
-glue_header_name (cpp_reader *pfile)
-{
- const cpp_token *token;
- char *buffer;
- 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 = xmalloc (capacity);
- for (;;)
- {
- token = get_token_no_padding (pfile);
-
- if (token->type == CPP_GREATER)
- break;
- if (token->type == CPP_EOF)
- {
- cpp_error (pfile, CPP_DL_ERROR, "missing terminating > character");
- break;
- }
-
- len = cpp_token_len (token) + 2; /* Leading space, terminating \0. */
- if (total_len + len > capacity)
- {
- capacity = (capacity + len) * 2;
- buffer = xrealloc (buffer, capacity);
- }
-
- if (token->flags & PREV_WHITE)
- buffer[total_len++] = ' ';
-
- total_len = (cpp_spell_token (pfile, token, (uchar *) &buffer[total_len])
- - (uchar *) buffer);
- }
-
- buffer[total_len] = '\0';
- return buffer;
-}
-
-/* Returns the file name of #include, #include_next, #import and
- #pragma dependency. The string is malloced and the caller should
- free it. Returns NULL on error. */
-static const char *
-parse_include (cpp_reader *pfile, int *pangle_brackets)
-{
- char *fname;
- const cpp_token *header;
-
- /* Allow macro expansion. */
- header = get_token_no_padding (pfile);
- if (header->type == CPP_STRING || header->type == CPP_HEADER_NAME)
- {
- fname = xmalloc (header->val.str.len - 1);
- memcpy (fname, header->val.str.text + 1, header->val.str.len - 2);
- fname[header->val.str.len - 2] = '\0';
- *pangle_brackets = header->type == CPP_HEADER_NAME;
- }
- else if (header->type == CPP_LESS)
- {
- fname = glue_header_name (pfile);
- *pangle_brackets = 1;
- }
- else
- {
- const unsigned char *dir;
-
- if (pfile->directive == &dtable[T_PRAGMA])
- dir = U"pragma dependency";
- else
- dir = pfile->directive->name;
- cpp_error (pfile, CPP_DL_ERROR, "#%s expects \"FILENAME\" or <FILENAME>",
- dir);
-
- return NULL;
- }
-
- check_eol (pfile);
- return fname;
-}
-
-/* Handle #include, #include_next and #import. */
-static void
-do_include_common (cpp_reader *pfile, enum include_type type)
-{
- const char *fname;
- int angle_brackets;
-
- fname = parse_include (pfile, &angle_brackets);
- if (!fname)
- return;
-
- /* Prevent #include recursion. */
- if (pfile->line_table->depth >= CPP_STACK_MAX)
- cpp_error (pfile, CPP_DL_ERROR, "#include nested too deeply");
- else
- {
- /* Get out of macro context, if we are. */
- skip_rest_of_line (pfile);
-
- if (pfile->cb.include)
- pfile->cb.include (pfile, pfile->directive_line,
- pfile->directive->name, fname, angle_brackets);
-
- _cpp_stack_include (pfile, fname, angle_brackets, type);
- }
-
- free ((void *) fname);
-}
-
-static void
-do_include (cpp_reader *pfile)
-{
- do_include_common (pfile, IT_INCLUDE);
-}
-
-static void
-do_import (cpp_reader *pfile)
-{
- do_include_common (pfile, IT_IMPORT);
-}
-
-static void
-do_include_next (cpp_reader *pfile)
-{
- enum include_type type = IT_INCLUDE_NEXT;
-
- /* If this is the primary source file, warn and use the normal
- search logic. */
- if (! pfile->buffer->prev)
- {
- cpp_error (pfile, CPP_DL_WARNING,
- "#include_next in primary source file");
- type = IT_INCLUDE;
- }
- do_include_common (pfile, type);
-}
-
-/* Subroutine of do_linemarker. 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 (cpp_reader *pfile, unsigned int last)
-{
- const cpp_token *token = _cpp_lex_token (pfile);
-
- 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, CPP_DL_ERROR, "invalid flag \"%s\" in line directive",
- cpp_token_as_text (pfile, token));
- return 0;
-}
-
-/* Subroutine of do_line and do_linemarker. 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 (const uchar *str, unsigned int len, long unsigned int *nump)
-{
- unsigned long reg = 0;
- uchar 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 a true string constant
- (escapes are interpreted), unlike in #line. */
-static void
-do_line (cpp_reader *pfile)
-{
- const struct line_maps *line_table = pfile->line_table;
- const struct line_map *map = &line_table->maps[line_table->used - 1];
- const cpp_token *token;
- const char *new_file = map->to_file;
- unsigned long new_lineno;
-
- /* C99 raised the minimum limit on #line numbers. */
- unsigned int cap = CPP_OPTION (pfile, c99) ? 2147483647 : 32767;
-
- /* #line commands expand macros. */
- token = cpp_get_token (pfile);
- if (token->type != CPP_NUMBER
- || strtoul_for_line (token->val.str.text, token->val.str.len,
- &new_lineno))
- {
- cpp_error (pfile, CPP_DL_ERROR,
- "\"%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_error (pfile, CPP_DL_PEDWARN, "line number out of range");
-
- token = cpp_get_token (pfile);
- if (token->type == CPP_STRING)
- {
- cpp_string s = { 0, 0 };
- if (cpp_interpret_string_notranslate (pfile, &token->val.str, 1,
- &s, false))
- new_file = (const char *)s.text;
- check_eol (pfile);
- }
- else if (token->type != CPP_EOF)
- {
- cpp_error (pfile, CPP_DL_ERROR, "\"%s\" is not a valid filename",
- cpp_token_as_text (pfile, token));
- return;
- }
-
- skip_rest_of_line (pfile);
- _cpp_do_file_change (pfile, LC_RENAME, new_file, new_lineno,
- map->sysp);
-}
-
-/* Interpret the # 44 "file" [flags] notation, which has slightly
- different syntax and semantics from #line: Flags are allowed,
- and we never complain about the line number being too big. */
-static void
-do_linemarker (cpp_reader *pfile)
-{
- const struct line_maps *line_table = pfile->line_table;
- const struct line_map *map = &line_table->maps[line_table->used - 1];
- const cpp_token *token;
- const char *new_file = map->to_file;
- unsigned long new_lineno;
- unsigned int new_sysp = map->sysp;
- enum lc_reason reason = LC_RENAME;
- int flag;
-
- /* Back up so we can get the number again. Putting this in
- _cpp_handle_directive risks two calls to _cpp_backup_tokens in
- some circumstances, which can segfault. */
- _cpp_backup_tokens (pfile, 1);
-
- /* #line commands expand macros. */
- token = cpp_get_token (pfile);
- if (token->type != CPP_NUMBER
- || strtoul_for_line (token->val.str.text, token->val.str.len,
- &new_lineno))
- {
- cpp_error (pfile, CPP_DL_ERROR,
- "\"%s\" after # is not a positive integer",
- cpp_token_as_text (pfile, token));
- return;
- }
-
- token = cpp_get_token (pfile);
- if (token->type == CPP_STRING)
- {
- cpp_string s = { 0, 0 };
- if (cpp_interpret_string_notranslate (pfile, &token->val.str,
- 1, &s, false))
- new_file = (const char *)s.text;
-
- new_sysp = 0;
- flag = read_flag (pfile, 0);
- if (flag == 1)
- {
- reason = LC_ENTER;
- /* Fake an include for cpp_included (). */
- _cpp_fake_include (pfile, new_file);
- flag = read_flag (pfile, flag);
- }
- else if (flag == 2)
- {
- reason = LC_LEAVE;
- flag = read_flag (pfile, flag);
- }
- if (flag == 3)
- {
- new_sysp = 1;
- flag = read_flag (pfile, flag);
- if (flag == 4)
- new_sysp = 2;
- pfile->buffer->sysp = new_sysp;
- }
-
- check_eol (pfile);
- }
- else if (token->type != CPP_EOF)
- {
- cpp_error (pfile, CPP_DL_ERROR, "\"%s\" is not a valid filename",
- cpp_token_as_text (pfile, token));
- return;
- }
-
- skip_rest_of_line (pfile);
- _cpp_do_file_change (pfile, reason, new_file, new_lineno, new_sysp);
-}
-
-/* Arrange the file_change callback. pfile->line has changed to
- FILE_LINE of TO_FILE, for reason REASON. SYSP is 1 for a system
- header, 2 for a system header that needs to be extern "C" protected,
- and zero otherwise. */
-void
-_cpp_do_file_change (cpp_reader *pfile, enum lc_reason reason,
- const char *to_file, unsigned int file_line,
- unsigned int sysp)
-{
- const struct line_map *map = linemap_add (pfile->line_table, reason, sysp,
- to_file, file_line);
- if (map != NULL)
- linemap_line_start (pfile->line_table, map->to_line, 127);
-
- if (pfile->cb.file_change)
- pfile->cb.file_change (pfile, map);
-}
-
-/* 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 (cpp_reader *pfile, int code, int print_dir)
-{
- if (_cpp_begin_message (pfile, code, pfile->cur_token[-1].src_loc, 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 (cpp_reader *pfile)
-{
- do_diagnostic (pfile, CPP_DL_ERROR, 1);
-}
-
-static void
-do_warning (cpp_reader *pfile)
-{
- /* We want #warning diagnostics to be emitted in system headers too. */
- do_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, 1);
-}
-
-/* Report program identification. */
-static void
-do_ident (cpp_reader *pfile)
-{
- const cpp_token *str = cpp_get_token (pfile);
-
- if (str->type != CPP_STRING)
- cpp_error (pfile, CPP_DL_ERROR, "invalid #ident directive");
- else if (pfile->cb.ident)
- pfile->cb.ident (pfile, pfile->directive_line, &str->val.str);
-
- check_eol (pfile);
-}
-
-/* Lookup a PRAGMA name in a singly-linked CHAIN. Returns the
- matching entry, or NULL if none is found. The returned entry could
- be the start of a namespace chain, or a pragma. */
-static struct pragma_entry *
-lookup_pragma_entry (struct pragma_entry *chain, const cpp_hashnode *pragma)
-{
- while (chain && chain->pragma != pragma)
- chain = chain->next;
-
- return chain;
-}
-
-/* Create and insert a pragma entry for NAME at the beginning of a
- singly-linked CHAIN. If handler is NULL, it is a namespace,
- otherwise it is a pragma and its handler. */
-static struct pragma_entry *
-insert_pragma_entry (cpp_reader *pfile, struct pragma_entry **chain,
- const cpp_hashnode *pragma, pragma_cb handler)
-{
- struct pragma_entry *new;
-
- new = (struct pragma_entry *)
- _cpp_aligned_alloc (pfile, sizeof (struct pragma_entry));
- new->pragma = pragma;
- if (handler)
- {
- new->is_nspace = 0;
- new->u.handler = handler;
- }
- else
- {
- new->is_nspace = 1;
- new->u.space = NULL;
- }
-
- new->next = *chain;
- *chain = new;
- return new;
-}
-
-/* Register a pragma NAME in namespace SPACE. If SPACE is null, it
- goes in the global namespace. HANDLER is the handler it will call,
- which must be non-NULL. */
-void
-cpp_register_pragma (cpp_reader *pfile, const char *space, const char *name,
- pragma_cb handler)
-{
- struct pragma_entry **chain = &pfile->pragmas;
- struct pragma_entry *entry;
- const cpp_hashnode *node;
-
- if (!handler)
- abort ();
-
- if (space)
- {
- node = cpp_lookup (pfile, U space, strlen (space));
- entry = lookup_pragma_entry (*chain, node);
- if (!entry)
- entry = insert_pragma_entry (pfile, chain, node, NULL);
- else if (!entry->is_nspace)
- goto clash;
- chain = &entry->u.space;
- }
-
- /* Check for duplicates. */
- node = cpp_lookup (pfile, U name, strlen (name));
- entry = lookup_pragma_entry (*chain, node);
- if (entry)
- {
- if (entry->is_nspace)
- clash:
- cpp_error (pfile, CPP_DL_ICE,
- "registering \"%s\" as both a pragma and a pragma namespace",
- NODE_NAME (node));
- else if (space)
- cpp_error (pfile, CPP_DL_ICE, "#pragma %s %s is already registered",
- space, name);
- else
- cpp_error (pfile, CPP_DL_ICE, "#pragma %s is already registered", name);
- }
- else
- insert_pragma_entry (pfile, chain, node, handler);
-}
-
-/* Register the pragmas the preprocessor itself handles. */
-void
-_cpp_init_internal_pragmas (cpp_reader *pfile)
-{
- /* Pragmas in the global namespace. */
- cpp_register_pragma (pfile, 0, "once", do_pragma_once);
-
- /* New GCC-specific pragmas should be put in the GCC namespace. */
- 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);
-}
-
-/* Return the number of registered pragmas in PE. */
-
-static int
-count_registered_pragmas (struct pragma_entry *pe)
-{
- int ct = 0;
- for (; pe != NULL; pe = pe->next)
- {
- if (pe->is_nspace)
- ct += count_registered_pragmas (pe->u.space);
- ct++;
- }
- return ct;
-}
-
-/* Save into SD the names of the registered pragmas referenced by PE,
- and return a pointer to the next free space in SD. */
-
-static char **
-save_registered_pragmas (struct pragma_entry *pe, char **sd)
-{
- for (; pe != NULL; pe = pe->next)
- {
- if (pe->is_nspace)
- sd = save_registered_pragmas (pe->u.space, sd);
- *sd++ = xmemdup (HT_STR (&pe->pragma->ident),
- HT_LEN (&pe->pragma->ident),
- HT_LEN (&pe->pragma->ident) + 1);
- }
- return sd;
-}
-
-/* Return a newly-allocated array which saves the names of the
- registered pragmas. */
-
-char **
-_cpp_save_pragma_names (cpp_reader *pfile)
-{
- int ct = count_registered_pragmas (pfile->pragmas);
- char **result = xnewvec (char *, ct);
- (void) save_registered_pragmas (pfile->pragmas, result);
- return result;
-}
-
-/* Restore from SD the names of the registered pragmas referenced by PE,
- and return a pointer to the next unused name in SD. */
-
-static char **
-restore_registered_pragmas (cpp_reader *pfile, struct pragma_entry *pe,
- char **sd)
-{
- for (; pe != NULL; pe = pe->next)
- {
- if (pe->is_nspace)
- sd = restore_registered_pragmas (pfile, pe->u.space, sd);
- pe->pragma = cpp_lookup (pfile, U *sd, strlen (*sd));
- free (*sd);
- sd++;
- }
- return sd;
-}
-
-/* Restore the names of the registered pragmas from SAVED. */
-
-void
-_cpp_restore_pragma_names (cpp_reader *pfile, char **saved)
-{
- (void) restore_registered_pragmas (pfile, pfile->pragmas, saved);
- free (saved);
-}
-
-/* Pragmata handling. We handle some, 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. */
-static void
-do_pragma (cpp_reader *pfile)
-{
- const struct pragma_entry *p = NULL;
- const cpp_token *token, *pragma_token = pfile->cur_token;
- unsigned int count = 1;
-
- pfile->state.prevent_expansion++;
-
- token = cpp_get_token (pfile);
- if (token->type == CPP_NAME)
- {
- p = lookup_pragma_entry (pfile->pragmas, token->val.node);
- if (p && p->is_nspace)
- {
- count = 2;
- token = cpp_get_token (pfile);
- if (token->type == CPP_NAME)
- p = lookup_pragma_entry (p->u.space, token->val.node);
- else
- p = NULL;
- }
- }
-
- if (p)
- {
- /* Since the handler below doesn't get the line number, that it
- might need for diagnostics, make sure it has the right
- numbers in place. */
- if (pfile->cb.line_change)
- (*pfile->cb.line_change) (pfile, pragma_token, false);
- (*p->u.handler) (pfile);
- }
- else if (pfile->cb.def_pragma)
- {
- _cpp_backup_tokens (pfile, count);
- pfile->cb.def_pragma (pfile, pfile->directive_line);
- }
-
- pfile->state.prevent_expansion--;
-}
-
-/* Handle #pragma once. */
-static void
-do_pragma_once (cpp_reader *pfile)
-{
- if (pfile->buffer->prev == NULL)
- cpp_error (pfile, CPP_DL_WARNING, "#pragma once in main file");
-
- check_eol (pfile);
- _cpp_mark_file_once_only (pfile, pfile->buffer->file);
-}
-
-/* Handle #pragma GCC poison, to poison one or more identifiers so
- that the lexer produces a hard error for each subsequent usage. */
-static void
-do_pragma_poison (cpp_reader *pfile)
-{
- const cpp_token *tok;
- cpp_hashnode *hp;
-
- pfile->state.poisoned_ok = 1;
- for (;;)
- {
- tok = _cpp_lex_token (pfile);
- if (tok->type == CPP_EOF)
- break;
- if (tok->type != CPP_NAME)
- {
- cpp_error (pfile, CPP_DL_ERROR,
- "invalid #pragma GCC poison directive");
- break;
- }
-
- hp = tok->val.node;
- if (hp->flags & NODE_POISONED)
- continue;
-
- if (hp->type == NT_MACRO)
- cpp_error (pfile, CPP_DL_WARNING, "poisoning existing macro \"%s\"",
- NODE_NAME (hp));
- _cpp_free_definition (hp);
- hp->flags |= NODE_POISONED | NODE_DIAGNOSTIC;
- }
- pfile->state.poisoned_ok = 0;
-}
-
-/* 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 (cpp_reader *pfile)
-{
- cpp_buffer *buffer = pfile->buffer;
-
- if (buffer->prev == 0)
- cpp_error (pfile, CPP_DL_WARNING,
- "#pragma system_header ignored outside include file");
- else
- {
- check_eol (pfile);
- skip_rest_of_line (pfile);
- cpp_make_system_header (pfile, 1, 0);
- }
-}
-
-/* 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 (cpp_reader *pfile)
-{
- const char *fname;
- int angle_brackets, ordering;
-
- fname = parse_include (pfile, &angle_brackets);
- if (!fname)
- return;
-
- ordering = _cpp_compare_file_date (pfile, fname, angle_brackets);
- if (ordering < 0)
- cpp_error (pfile, CPP_DL_WARNING, "cannot find source file %s", fname);
- else if (ordering > 0)
- {
- cpp_error (pfile, CPP_DL_WARNING,
- "current file is older than %s", fname);
- if (cpp_get_token (pfile)->type != CPP_EOF)
- {
- _cpp_backup_tokens (pfile, 1);
- do_diagnostic (pfile, CPP_DL_WARNING, 0);
- }
- }
-
- free ((void *) fname);
-}
-
-/* Get a token but skip padding. */
-static const cpp_token *
-get_token_no_padding (cpp_reader *pfile)
-{
- for (;;)
- {
- const cpp_token *result = cpp_get_token (pfile);
- if (result->type != CPP_PADDING)
- return result;
- }
-}
-
-/* Check syntax is "(string-literal)". Returns the string on success,
- or NULL on failure. */
-static const cpp_token *
-get__Pragma_string (cpp_reader *pfile)
-{
- const cpp_token *string;
-
- if (get_token_no_padding (pfile)->type != CPP_OPEN_PAREN)
- return NULL;
-
- string = get_token_no_padding (pfile);
- if (string->type != CPP_STRING && string->type != CPP_WSTRING)
- return NULL;
-
- if (get_token_no_padding (pfile)->type != CPP_CLOSE_PAREN)
- return NULL;
-
- return string;
-}
-
-/* Destringize IN into a temporary buffer, by removing the first \ of
- \" and \\ sequences, and process the result as a #pragma directive. */
-static void
-destringize_and_run (cpp_reader *pfile, const cpp_string *in)
-{
- const unsigned char *src, *limit;
- char *dest, *result;
-
- dest = result = alloca (in->len - 1);
- src = in->text + 1 + (in->text[0] == 'L');
- limit = in->text + in->len - 1;
- while (src < limit)
- {
- /* We know there is a character following the backslash. */
- if (*src == '\\' && (src[1] == '\\' || src[1] == '"'))
- src++;
- *dest++ = *src++;
- }
- *dest = '\n';
-
- /* Ugh; an awful kludge. We are really not set up to be lexing
- tokens when in the middle of a macro expansion. Use a new
- context to force cpp_get_token to lex, and so skip_rest_of_line
- doesn't go beyond the end of the text. Also, remember the
- current lexing position so we can return to it later.
-
- Something like line-at-a-time lexing should remove the need for
- this. */
- {
- cpp_context *saved_context = pfile->context;
- cpp_token *saved_cur_token = pfile->cur_token;
- tokenrun *saved_cur_run = pfile->cur_run;
-
- pfile->context = xnew (cpp_context);
- pfile->context->macro = 0;
- pfile->context->prev = 0;
- run_directive (pfile, T_PRAGMA, result, dest - result);
- free (pfile->context);
- pfile->context = saved_context;
- pfile->cur_token = saved_cur_token;
- pfile->cur_run = saved_cur_run;
- }
-
- /* See above comment. For the moment, we'd like
-
- token1 _Pragma ("foo") token2
-
- to be output as
-
- token1
- # 7 "file.c"
- #pragma foo
- # 7 "file.c"
- token2
-
- Getting the line markers is a little tricky. */
- if (pfile->cb.line_change)
- pfile->cb.line_change (pfile, pfile->cur_token, false);
-}
-
-/* Handle the _Pragma operator. */
-void
-_cpp_do__Pragma (cpp_reader *pfile)
-{
- const cpp_token *string = get__Pragma_string (pfile);
-
- if (string)
- destringize_and_run (pfile, &string->val.str);
- else
- cpp_error (pfile, CPP_DL_ERROR,
- "_Pragma takes a parenthesized string literal");
-}
-
-/* Ignore #sccs on all systems. */
-static void
-do_sccs (cpp_reader *pfile ATTRIBUTE_UNUSED)
-{
-}
-
-/* Handle #ifdef. */
-static void
-do_ifdef (cpp_reader *pfile)
-{
- int skip = 1;
-
- if (! pfile->state.skipping)
- {
- const cpp_hashnode *node = lex_macro_node (pfile);
-
- if (node)
- {
- skip = node->type != NT_MACRO;
- _cpp_mark_macro_used (node);
- check_eol (pfile);
- }
- }
-
- push_conditional (pfile, skip, T_IFDEF, 0);
-}
-
-/* Handle #ifndef. */
-static void
-do_ifndef (cpp_reader *pfile)
-{
- int skip = 1;
- const cpp_hashnode *node = 0;
-
- if (! pfile->state.skipping)
- {
- node = lex_macro_node (pfile);
-
- if (node)
- {
- skip = node->type == NT_MACRO;
- _cpp_mark_macro_used (node);
- check_eol (pfile);
- }
- }
-
- push_conditional (pfile, skip, T_IFNDEF, node);
-}
-
-/* _cpp_parse_expr puts a macro in a "#if !defined ()" expression in
- pfile->mi_ind_cmacro so we can handle multiple-include
- optimizations. If macro expansion occurs in the expression, we
- cannot treat it as a controlling conditional, since the expansion
- could change in the future. That is handled by cpp_get_token. */
-static void
-do_if (cpp_reader *pfile)
-{
- int skip = 1;
-
- if (! pfile->state.skipping)
- skip = _cpp_parse_expr (pfile) == false;
-
- push_conditional (pfile, skip, T_IF, pfile->mi_ind_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 (cpp_reader *pfile)
-{
- cpp_buffer *buffer = pfile->buffer;
- struct if_stack *ifs = buffer->if_stack;
-
- if (ifs == NULL)
- cpp_error (pfile, CPP_DL_ERROR, "#else without #if");
- else
- {
- if (ifs->type == T_ELSE)
- {
- cpp_error (pfile, CPP_DL_ERROR, "#else after #else");
- cpp_error_with_line (pfile, CPP_DL_ERROR, ifs->line, 0,
- "the conditional began here");
- }
- ifs->type = T_ELSE;
-
- /* Skip any future (erroneous) #elses or #elifs. */
- pfile->state.skipping = ifs->skip_elses;
- ifs->skip_elses = true;
-
- /* Invalidate any controlling macro. */
- ifs->mi_cmacro = 0;
-
- /* Only check EOL if was not originally skipping. */
- if (!ifs->was_skipping && CPP_OPTION (pfile, warn_endif_labels))
- check_eol (pfile);
- }
-}
-
-/* Handle a #elif directive by not changing if_stack either. See the
- comment above do_else. */
-static void
-do_elif (cpp_reader *pfile)
-{
- cpp_buffer *buffer = pfile->buffer;
- struct if_stack *ifs = buffer->if_stack;
-
- if (ifs == NULL)
- cpp_error (pfile, CPP_DL_ERROR, "#elif without #if");
- else
- {
- if (ifs->type == T_ELSE)
- {
- cpp_error (pfile, CPP_DL_ERROR, "#elif after #else");
- cpp_error_with_line (pfile, CPP_DL_ERROR, ifs->line, 0,
- "the conditional began here");
- }
- ifs->type = T_ELIF;
-
- /* Only evaluate this if we aren't skipping elses. During
- evaluation, set skipping to false to get lexer warnings. */
- if (ifs->skip_elses)
- pfile->state.skipping = 1;
- else
- {
- pfile->state.skipping = 0;
- pfile->state.skipping = ! _cpp_parse_expr (pfile);
- ifs->skip_elses = ! pfile->state.skipping;
- }
-
- /* Invalidate any controlling macro. */
- ifs->mi_cmacro = 0;
- }
-}
-
-/* #endif pops the if stack and resets pfile->state.skipping. */
-static void
-do_endif (cpp_reader *pfile)
-{
- cpp_buffer *buffer = pfile->buffer;
- struct if_stack *ifs = buffer->if_stack;
-
- if (ifs == NULL)
- cpp_error (pfile, CPP_DL_ERROR, "#endif without #if");
- else
- {
- /* Only check EOL if was not originally skipping. */
- if (!ifs->was_skipping && CPP_OPTION (pfile, warn_endif_labels))
- check_eol (pfile);
-
- /* If potential control macro, we go back outside again. */
- if (ifs->next == 0 && ifs->mi_cmacro)
- {
- pfile->mi_valid = true;
- pfile->mi_cmacro = ifs->mi_cmacro;
- }
-
- buffer->if_stack = ifs->next;
- pfile->state.skipping = ifs->was_skipping;
- obstack_free (&pfile->buffer_ob, ifs);
- }
-}
-
-/* Push an if_stack entry for a preprocessor conditional, and set
- pfile->state.skipping to SKIP. If TYPE indicates the conditional
- is #if or #ifndef, CMACRO is a potentially controlling macro, and
- we need to check here that we are at the top of the file. */
-static void
-push_conditional (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->line = pfile->directive_line;
- ifs->next = buffer->if_stack;
- ifs->skip_elses = pfile->state.skipping || !skip;
- ifs->was_skipping = pfile->state.skipping;
- ifs->type = type;
- /* This condition is effectively a test for top-of-file. */
- if (pfile->mi_valid && pfile->mi_cmacro == 0)
- ifs->mi_cmacro = cmacro;
- else
- ifs->mi_cmacro = 0;
-
- pfile->state.skipping = skip;
- buffer->if_stack = ifs;
-}
-
-/* Read the tokens of the answer into the macro pool, in a directive
- of type TYPE. Only commit the memory if we intend it as permanent
- storage, i.e. the #assert case. Returns 0 on success, and sets
- ANSWERP to point to the answer. */
-static int
-parse_answer (cpp_reader *pfile, struct answer **answerp, int type)
-{
- const cpp_token *paren;
- struct answer *answer;
- unsigned int acount;
-
- /* In a conditional, it is legal to not have an open paren. We
- should save the following token in this case. */
- paren = cpp_get_token (pfile);
-
- /* 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)
- {
- _cpp_backup_tokens (pfile, 1);
- 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, CPP_DL_ERROR, "missing '(' after predicate");
- return 1;
- }
-
- for (acount = 0;; acount++)
- {
- size_t room_needed;
- const cpp_token *token = cpp_get_token (pfile);
- cpp_token *dest;
-
- if (token->type == CPP_CLOSE_PAREN)
- break;
-
- if (token->type == CPP_EOF)
- {
- cpp_error (pfile, CPP_DL_ERROR, "missing ')' to complete answer");
- return 1;
- }
-
- /* struct answer includes the space for one token. */
- room_needed = (sizeof (struct answer) + acount * sizeof (cpp_token));
-
- if (BUFF_ROOM (pfile->a_buff) < room_needed)
- _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (struct answer));
-
- dest = &((struct answer *) BUFF_FRONT (pfile->a_buff))->first[acount];
- *dest = *token;
-
- /* Drop whitespace at start, for answer equivalence purposes. */
- if (acount == 0)
- dest->flags &= ~PREV_WHITE;
- }
-
- if (acount == 0)
- {
- cpp_error (pfile, CPP_DL_ERROR, "predicate's answer is empty");
- return 1;
- }
-
- answer = (struct answer *) BUFF_FRONT (pfile->a_buff);
- answer->count = acount;
- answer->next = NULL;
- *answerp = answer;
-
- return 0;
-}
-
-/* Parses an assertion directive of type TYPE, 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 (cpp_reader *pfile, struct answer **answerp, int type)
-{
- cpp_hashnode *result = 0;
- const cpp_token *predicate;
-
- /* We don't expand predicates or answers. */
- pfile->state.prevent_expansion++;
-
- *answerp = 0;
- predicate = cpp_get_token (pfile);
- if (predicate->type == CPP_EOF)
- cpp_error (pfile, CPP_DL_ERROR, "assertion without predicate");
- else if (predicate->type != CPP_NAME)
- cpp_error (pfile, CPP_DL_ERROR, "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 CANDIDATE in the answer chain,
- or a pointer to NULL if the answer is not in the chain. */
-static struct answer **
-find_answer (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
- nonzero on failure, zero on success. On success, the result of
- the test is written into VALUE, otherwise the value 0. */
-int
-_cpp_test_assertion (cpp_reader *pfile, unsigned int *value)
-{
- struct answer *answer;
- cpp_hashnode *node;
-
- node = parse_assertion (pfile, &answer, T_IF);
-
- /* For recovery, an erroneous assertion expression is handled as a
- failing assertion. */
- *value = 0;
-
- if (node)
- *value = (node->type == NT_ASSERTION &&
- (answer == 0 || *find_answer (node, answer) != 0));
- else if (pfile->cur_token[-1].type == CPP_EOF)
- _cpp_backup_tokens (pfile, 1);
-
- /* We don't commit the memory for the answer - it's temporary only. */
- return node == 0;
-}
-
-/* Handle #assert. */
-static void
-do_assert (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_error (pfile, CPP_DL_WARNING, "\"%s\" re-asserted",
- NODE_NAME (node) + 1);
- return;
- }
- new_answer->next = node->value.answers;
- }
-
- node->type = NT_ASSERTION;
- node->value.answers = new_answer;
- BUFF_FRONT (pfile->a_buff) += (sizeof (struct answer)
- + (new_answer->count - 1)
- * sizeof (cpp_token));
- check_eol (pfile);
- }
-}
-
-/* Handle #unassert. */
-static void
-do_unassert (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;
-
- check_eol (pfile);
- }
- 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 (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. */
-
- count = strlen (str);
- buf = alloca (count + 3);
- memcpy (buf, str, count);
-
- p = strchr (str, '=');
- if (p)
- buf[p - str] = ' ';
- else
- {
- buf[count++] = ' ';
- buf[count++] = '1';
- }
- buf[count] = '\n';
-
- run_directive (pfile, T_DEFINE, buf, count);
-}
-
-/* Slight variant of the above for use by initialize_builtins. */
-void
-_cpp_define_builtin (cpp_reader *pfile, const char *str)
-{
- size_t len = strlen (str);
- char *buf = alloca (len + 1);
- memcpy (buf, str, len);
- buf[len] = '\n';
- run_directive (pfile, T_DEFINE, buf, len);
-}
-
-/* Process MACRO as if it appeared as the body of an #undef. */
-void
-cpp_undef (cpp_reader *pfile, const char *macro)
-{
- size_t len = strlen (macro);
- char *buf = alloca (len + 1);
- memcpy (buf, macro, len);
- buf[len] = '\n';
- run_directive (pfile, T_UNDEF, buf, len);
-}
-
-/* Process the string STR as if it appeared as the body of a #assert. */
-void
-cpp_assert (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 (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 (cpp_reader *pfile, const char *str, int type)
-{
- size_t count = strlen (str);
- const char *p = strchr (str, '=');
-
- /* 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 = alloca (count + 2);
-
- memcpy (buf, str, count);
- if (p)
- {
- buf[p - str] = '(';
- buf[count++] = ')';
- }
- buf[count] = '\n';
- str = buf;
-
- run_directive (pfile, type, str, count);
-}
-
-/* The number of errors for a given reader. */
-unsigned int
-cpp_errors (cpp_reader *pfile)
-{
- return pfile->errors;
-}
-
-/* The options structure. */
-cpp_options *
-cpp_get_options (cpp_reader *pfile)
-{
- return &pfile->opts;
-}
-
-/* The callbacks structure. */
-cpp_callbacks *
-cpp_get_callbacks (cpp_reader *pfile)
-{
- return &pfile->cb;
-}
-
-/* Copy the given callbacks structure to our own. */
-void
-cpp_set_callbacks (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 (cpp_reader *pfile, const uchar *buffer, size_t len,
- int from_stage3)
-{
- cpp_buffer *new = xobnew (&pfile->buffer_ob, cpp_buffer);
-
- /* Clears, amongst other things, if_stack and mi_cmacro. */
- memset (new, 0, sizeof (cpp_buffer));
-
- new->next_line = new->buf = buffer;
- new->rlimit = buffer + len;
- new->from_stage3 = from_stage3;
- new->prev = pfile->buffer;
- new->need_line = true;
-
- pfile->buffer = new;
-
- return new;
-}
-
-/* Pops a single buffer, with a file change call-back if appropriate.
- Then pushes the next -include file, if any remain. */
-void
-_cpp_pop_buffer (cpp_reader *pfile)
-{
- cpp_buffer *buffer = pfile->buffer;
- struct _cpp_file *inc = buffer->file;
- struct if_stack *ifs;
-
- /* 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, CPP_DL_ERROR, ifs->line, 0,
- "unterminated #%s", dtable[ifs->type].name);
-
- /* In case of a missing #endif. */
- pfile->state.skipping = 0;
-
- /* _cpp_do_file_change expects pfile->buffer to be the new one. */
- pfile->buffer = buffer->prev;
-
- free (buffer->notes);
-
- /* Free the buffer object now; we may want to push a new buffer
- in _cpp_push_next_include_file. */
- obstack_free (&pfile->buffer_ob, buffer);
-
- if (inc)
- {
- _cpp_pop_file_buffer (pfile, inc);
-
- _cpp_do_file_change (pfile, LC_LEAVE, 0, 0, 0);
- }
-}
-
-/* Enter all recognized directives in the hash table. */
-void
-_cpp_init_directives (cpp_reader *pfile)
-{
- unsigned int i;
- cpp_hashnode *node;
-
- for (i = 0; i < (unsigned int) N_DIRECTIVES; i++)
- {
- node = cpp_lookup (pfile, dtable[i].name, dtable[i].length);
- node->is_directive = 1;
- node->directive_index = i;
- }
-}
diff --git a/gcc/cpplib.h b/gcc/cpplib.h
deleted file mode 100644
index d006192afb3..00000000000
--- a/gcc/cpplib.h
+++ /dev/null
@@ -1,773 +0,0 @@
-/* Definitions for CPP library.
- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
- 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"
-#include "line-map.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct cpp_reader cpp_reader;
-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_callbacks cpp_callbacks;
-typedef struct cpp_dir cpp_dir;
-
-struct answer;
-struct _cpp_file;
-
-/* The first three groups, apart from '=', can appear in preprocessor
- expressions (+= and -= are used to indicate unary + and - resp.).
- 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 CPP_LAST_CPP_OP CPP_LESS_EQ
-
-#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, ")") \
- TK(CPP_EOF, SPELL_NONE) \
- OP(CPP_EQ_EQ, "==") /* compare */ \
- OP(CPP_NOT_EQ, "!=") \
- OP(CPP_GREATER_EQ, ">=") \
- OP(CPP_LESS_EQ, "<=") \
-\
- /* These two are unary + / - in preprocessor expressions. */ \
- 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_AT_NAME, SPELL_IDENT) /* @word - Objective-C */ \
- TK(CPP_NUMBER, SPELL_LITERAL) /* 34_be+ta */ \
-\
- TK(CPP_CHAR, SPELL_LITERAL) /* 'char' */ \
- TK(CPP_WCHAR, SPELL_LITERAL) /* L'char' */ \
- TK(CPP_OTHER, SPELL_LITERAL) /* stray punctuation */ \
-\
- TK(CPP_STRING, SPELL_LITERAL) /* "string" */ \
- TK(CPP_WSTRING, SPELL_LITERAL) /* L"string" */ \
- TK(CPP_OBJC_STRING, SPELL_LITERAL) /* @"string" - Objective-C */ \
- TK(CPP_HEADER_NAME, SPELL_LITERAL) /* <stdio.h> in #include */ \
-\
- TK(CPP_COMMENT, SPELL_LITERAL) /* Only if output comments. */ \
- /* SPELL_LITERAL happens to DTRT. */ \
- TK(CPP_MACRO_ARG, SPELL_NONE) /* Macro argument. */ \
- TK(CPP_PADDING, SPELL_NONE) /* Whitespace for cpp0. */
-
-#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_ASM};
-
-/* Payload of a NUMBER, STRING, CHAR 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 BOL (1 << 6) /* Token at beginning of line. */
-
-/* A preprocessing token. This has been carefully packed and should
- occupy 16 bytes on 32-bit hosts and 24 bytes on 64-bit hosts. */
-struct cpp_token
-{
- source_location src_loc; /* Location of first char of token. */
- ENUM_BITFIELD(cpp_ttype) type : CHAR_BIT; /* token type */
- unsigned char flags; /* flags - see above */
-
- union
- {
- cpp_hashnode *node; /* An identifier. */
- const cpp_token *source; /* Inherit padding from this token. */
- struct cpp_string str; /* A string, or number. */
- unsigned int arg_no; /* Argument no. for a CPP_MACRO_ARG. */
- } val;
-};
-
-/* A type wide enough to hold any multibyte source character.
- cpplib's character constant interpreter requires an unsigned type.
- Also, a typedef for the signed equivalent.
- The width of this type is capped at 32 bits; there do exist targets
- where wchar_t is 64 bits, but only in a non-default mode, and there
- would be no meaningful interpretation for a wchar_t value greater
- than 2^32 anyway -- the widest wide-character encoding around is
- ISO 10646, which stops at 2^31. */
-#if CHAR_BIT * SIZEOF_INT >= 32
-# define CPPCHAR_SIGNED_T int
-#elif CHAR_BIT * SIZEOF_LONG >= 32
-# define CPPCHAR_SIGNED_T long
-#else
-# error "Cannot find a least-32-bit signed integer type"
-#endif
-typedef unsigned CPPCHAR_SIGNED_T cppchar_t;
-typedef CPPCHAR_SIGNED_T cppchar_signed_t;
-
-/* This structure is nested inside struct cpp_reader, and
- carries all the options visible to the command line. */
-struct cpp_options
-{
- /* Characters between tab stops. */
- unsigned int tabstop;
-
- /* The language we're preprocessing. */
- enum c_lang lang;
-
- /* Nonzero means use extra default include directories for C++. */
- unsigned char cplusplus;
-
- /* Nonzero means handle cplusplus style comments. */
- unsigned char cplusplus_comments;
-
- /* Nonzero means define __OBJC__, treat @ as a special token, and
- use the OBJC[PLUS]_INCLUDE_PATH environment variable. */
- unsigned char objc;
-
- /* Nonzero means don't copy comments into the output file. */
- unsigned char discard_comments;
-
- /* Nonzero means don't copy comments into the output file during
- macro expansion. */
- unsigned char discard_comments_in_macro_exp;
-
- /* 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 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 complain about deprecated features. */
- unsigned char warn_deprecated;
-
- /* 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 a user-supplied include directory does not
- exist. */
- unsigned char warn_missing_include_dirs;
-
- /* Nonzero means warn if there are any trigraphs. */
- unsigned char warn_trigraphs;
-
- /* Nonzero means warn about multicharacter charconsts. */
- unsigned char warn_multichar;
-
- /* Nonzero means warn about various incompatibilities with
- traditional C. */
- unsigned char warn_traditional;
-
- /* Nonzero means warn about long long numeric constants. */
- unsigned char warn_long_long;
-
- /* Nonzero means warn about text after an #endif (or #else). */
- unsigned char warn_endif_labels;
-
- /* Nonzero means warn about implicit sign changes owing to integer
- promotions. */
- unsigned char warn_num_sign_change;
-
- /* Zero means don't warn about __VA_ARGS__ usage in c89 pedantic mode.
- Presumably the usage is protected by the appropriate #ifdef. */
- unsigned char warn_variadic_macros;
-
- /* Nonzero means turn warnings into errors. */
- unsigned char warnings_are_errors;
-
- /* Nonzero means we should look for header.gcc files that remap file
- names. */
- unsigned char remap;
-
- /* Zero means dollar signs are punctuation. */
- unsigned char dollars_in_ident;
-
- /* True if we should warn about dollars in identifiers or numbers
- for this translation unit. */
- unsigned char warn_dollars;
-
- /* Nonzero means warn if undefined identifiers are evaluated in an #if. */
- unsigned char warn_undef;
-
- /* Nonzero means warn of unused macros from the main file. */
- unsigned char warn_unused_macros;
-
- /* Nonzero for the 1999 C Standard, including corrigenda and amendments. */
- unsigned char c99;
-
- /* Nonzero if we are conforming to a specific C or C++ standard. */
- unsigned char std;
-
- /* 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;
-
- /* Print column number in error messages. */
- unsigned char show_column;
-
- /* Nonzero means handle C++ alternate operator names. */
- unsigned char operator_names;
-
- /* True for traditional preprocessing. */
- unsigned char traditional;
-
- /* Holds the name of the target (execution) character set. */
- const char *narrow_charset;
-
- /* Holds the name of the target wide character set. */
- const char *wide_charset;
-
- /* Holds the name of the input character set. */
- const char *input_charset;
-
- /* True to warn about precompiled header files we couldn't use. */
- bool warn_invalid_pch;
-
- /* True if dependencies should be restored from a precompiled header. */
- bool restore_pch_deps;
-
- /* Dependency generation. */
- struct
- {
- /* Style of header dependencies to generate. */
- enum {DEPS_NONE = 0, DEPS_USER, DEPS_SYSTEM } style;
-
- /* Assume missing files are generated files. */
- bool missing_files;
-
- /* Generate phony targets for each dependency apart from the first
- one. */
- bool phony_targets;
-
- /* If true, no dependency is generated on the main file. */
- bool ignore_main_file;
- } deps;
-
- /* Target-specific features set by the front end or client. */
-
- /* Precision for target CPP arithmetic, target characters, target
- ints and target wide characters, respectively. */
- size_t precision, char_precision, int_precision, wchar_precision;
-
- /* True means chars (wide chars) are unsigned. */
- bool unsigned_char, unsigned_wchar;
-
- /* True if the most significant byte in a word has the lowest
- address in memory. */
- bool bytes_big_endian;
-
- /* Nonzero means __STDC__ should have the value 0 in system headers. */
- unsigned char stdc_0_in_system_headers;
-};
-
-/* Callback for header lookup for HEADER, which is the name of a
- source file. It is used as a method of last resort to find headers
- that are not otherwise found during the normal include processing.
- The return value is the malloced name of a header to try and open,
- if any, or NULL otherwise. This callback is called only if the
- header is otherwise unfound. */
-typedef const char *(*missing_header_cb)(cpp_reader *, const char *header, cpp_dir **);
-
-/* Call backs to cpplib client. */
-struct cpp_callbacks
-{
- /* Called when a new line of preprocessed output is started. */
- void (*line_change) (cpp_reader *, const cpp_token *, int);
-
- /* Called when switching to/from a new file.
- The line_map is for the new file. It is NULL if there is no new file.
- (In C this happens when done with <built-in>+<command line> and also
- when done with a main file.) This can be used for resource cleanup. */
- void (*file_change) (cpp_reader *, const struct line_map *);
-
- void (*dir_change) (cpp_reader *, const char *);
- void (*include) (cpp_reader *, unsigned int, const unsigned char *,
- const char *, int);
- void (*define) (cpp_reader *, unsigned int, cpp_hashnode *);
- void (*undef) (cpp_reader *, unsigned int, cpp_hashnode *);
- void (*ident) (cpp_reader *, unsigned int, const cpp_string *);
- void (*def_pragma) (cpp_reader *, unsigned int);
- int (*valid_pch) (cpp_reader *, const char *, int);
- void (*read_pch) (cpp_reader *, const char *, int, const char *);
- missing_header_cb missing_header;
-};
-
-/* Chain of directories to look for include files in. */
-struct cpp_dir
-{
- /* NULL-terminated singly-linked list. */
- struct cpp_dir *next;
-
- /* NAME of the directory, NUL-terminated. */
- char *name;
- unsigned int len;
-
- /* One if a system header, two if a system header that has extern
- "C" guards for C++. */
- unsigned char sysp;
-
- /* Mapping of file names for this directory for MS-DOS and related
- platforms. A NULL-terminated array of (from, to) pairs. */
- const char **name_map;
-
- /* Routine to construct pathname, given the search path name and the
- HEADER we are trying to find, return a constructed pathname to
- try and open. If this is NULL, the constructed pathname is as
- constructed by append_file_to_dir. */
- char *(*construct) (const char *header, cpp_dir *dir);
-
- /* The C front end uses these to recognize duplicated
- directories in the search path. */
- ino_t ino;
- dev_t dev;
-
- /* Is this a user-supplied directory? */
- bool user_supplied_p;
-};
-
-/* Name under which this program was invoked. */
-extern const char *progname;
-
-/* 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. Poisoned 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. */
-#define NODE_DISABLED (1 << 5) /* A disabled macro. */
-#define NODE_MACRO_ARG (1 << 6) /* Used during #define processing. */
-
-/* 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. _Pragma is an operator, but we
- handle it with the builtin code for efficiency reasons. */
-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__' */
- BT_PRAGMA /* `_Pragma' operator */
-};
-
-#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 GTY(())
-{
- struct ht_identifier ident;
- unsigned int is_directive : 1;
- unsigned int directive_index : 7; /* If is_directive,
- then index into directive table.
- Otherwise, a NODE_OPERATOR. */
- 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_hashnode_value
- {
- /* If a macro. */
- cpp_macro * GTY((skip)) macro;
- /* Answers to an assertion. */
- struct answer * GTY ((skip)) answers;
- /* Code for a builtin macro. */
- enum builtin_type GTY ((tag ("1"))) builtin;
- /* Macro argument index. */
- unsigned short GTY ((tag ("0"))) arg_index;
- } GTY ((desc ("0"))) 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. Otherwise you should pass in an initialized hash table
- that cpplib will share; this technique is used by the C front
- ends. */
-extern cpp_reader *cpp_create_reader (enum c_lang, struct ht *,
- struct line_maps *);
-
-/* Call this to change the selected language standard (e.g. because of
- command line options). */
-extern void cpp_set_lang (cpp_reader *, enum c_lang);
-
-/* Add a dependency TARGET. Quote it for "make" if QUOTE. Can be
- called any number of times before cpp_read_main_file(). If no
- targets have been added before cpp_read_main_file(), then the
- default target is used. */
-extern void cpp_add_dependency_target (cpp_reader *, const char *, int);
-
-/* Set the include paths. */
-extern void cpp_set_include_chains (cpp_reader *, cpp_dir *, cpp_dir *, int);
-
-/* 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 (cpp_reader *);
-extern cpp_callbacks *cpp_get_callbacks (cpp_reader *);
-extern void cpp_set_callbacks (cpp_reader *, cpp_callbacks *);
-
-/* This function reads the file, but does not start preprocessing. It
- returns the name of the original file; this is the same as the
- input file, except for preprocessed input. This will generate at
- least one file change callback, and possibly a line change callback
- too. If there was an error opening the file, it returns NULL. */
-extern const char *cpp_read_main_file (cpp_reader *, const char *);
-
-/* Set up built-ins like __FILE__. */
-extern void cpp_init_builtins (cpp_reader *, int);
-
-/* This is called after options have been parsed, and partially
- processed. */
-extern void cpp_post_options (cpp_reader *);
-
-/* Set up translation to the target character set. */
-extern void cpp_init_iconv (cpp_reader *);
-
-/* Call this to finish preprocessing. If you requested dependency
- generation, pass an open stream to write the information to,
- otherwise NULL. It is your responsibility to close the stream.
-
- Returns cpp_errors (pfile). */
-extern int cpp_finish (cpp_reader *, FILE *deps_stream);
-
-/* Call this to release the handle at the end of preprocessing. Any
- use of the handle after this function returns is invalid. Returns
- cpp_errors (pfile). */
-extern void cpp_destroy (cpp_reader *);
-
-/* Error count. */
-extern unsigned int cpp_errors (cpp_reader *);
-
-extern unsigned int cpp_token_len (const cpp_token *);
-extern unsigned char *cpp_token_as_text (cpp_reader *, const cpp_token *);
-extern unsigned char *cpp_spell_token (cpp_reader *, const cpp_token *,
- unsigned char *);
-extern void cpp_register_pragma (cpp_reader *, const char *, const char *,
- void (*) (cpp_reader *));
-extern int cpp_avoid_paste (cpp_reader *, const cpp_token *,
- const cpp_token *);
-extern const cpp_token *cpp_get_token (cpp_reader *);
-extern const unsigned char *cpp_macro_definition (cpp_reader *,
- const cpp_hashnode *);
-extern void _cpp_backup_tokens (cpp_reader *, unsigned int);
-
-/* Evaluate a CPP_CHAR or CPP_WCHAR token. */
-extern cppchar_t cpp_interpret_charconst (cpp_reader *, const cpp_token *,
- unsigned int *, int *);
-/* Evaluate a vector of CPP_STRING or CPP_WSTRING tokens. */
-extern bool cpp_interpret_string (cpp_reader *,
- const cpp_string *, size_t,
- cpp_string *, bool);
-extern bool cpp_interpret_string_notranslate (cpp_reader *,
- const cpp_string *, size_t,
- cpp_string *, bool);
-
-/* Used to register macros and assertions, perhaps from the command line.
- The text is the same as the command line argument. */
-extern void cpp_define (cpp_reader *, const char *);
-extern void cpp_assert (cpp_reader *, const char *);
-extern void cpp_undef (cpp_reader *, const char *);
-extern void cpp_unassert (cpp_reader *, const char *);
-
-/* Undefine all macros and assertions. */
-extern void cpp_undef_all (cpp_reader *);
-
-extern cpp_buffer *cpp_push_buffer (cpp_reader *, const unsigned char *,
- size_t, int);
-extern int cpp_defined (cpp_reader *, const unsigned char *, int);
-
-/* A preprocessing number. Code assumes that any unused high bits of
- the double integer are set to zero. */
-typedef unsigned HOST_WIDE_INT cpp_num_part;
-typedef struct cpp_num cpp_num;
-struct cpp_num
-{
- cpp_num_part high;
- cpp_num_part low;
- bool unsignedp; /* True if value should be treated as unsigned. */
- bool overflow; /* True if the most recent calculation overflowed. */
-};
-
-/* cpplib provides two interfaces for interpretation of preprocessing
- numbers.
-
- cpp_classify_number categorizes numeric constants according to
- their field (integer, floating point, or invalid), radix (decimal,
- octal, hexadecimal), and type suffixes. */
-
-#define CPP_N_CATEGORY 0x000F
-#define CPP_N_INVALID 0x0000
-#define CPP_N_INTEGER 0x0001
-#define CPP_N_FLOATING 0x0002
-
-#define CPP_N_WIDTH 0x00F0
-#define CPP_N_SMALL 0x0010 /* int, float. */
-#define CPP_N_MEDIUM 0x0020 /* long, double. */
-#define CPP_N_LARGE 0x0040 /* long long, long double. */
-
-#define CPP_N_RADIX 0x0F00
-#define CPP_N_DECIMAL 0x0100
-#define CPP_N_HEX 0x0200
-#define CPP_N_OCTAL 0x0400
-
-#define CPP_N_UNSIGNED 0x1000 /* Properties. */
-#define CPP_N_IMAGINARY 0x2000
-
-/* Classify a CPP_NUMBER token. The return value is a combination of
- the flags from the above sets. */
-extern unsigned cpp_classify_number (cpp_reader *, const cpp_token *);
-
-/* Evaluate a token classified as category CPP_N_INTEGER. */
-extern cpp_num cpp_interpret_integer (cpp_reader *, const cpp_token *,
- unsigned int type);
-
-/* Sign extend a number, with PRECISION significant bits and all
- others assumed clear, to fill out a cpp_num structure. */
-cpp_num cpp_num_sign_extend (cpp_num, size_t);
-
-/* Diagnostic levels. To get a diagnostic without associating a
- position in the translation unit with it, use cpp_error_with_line
- with a line number of zero. */
-
-/* Warning, an error with -Werror. */
-#define CPP_DL_WARNING 0x00
-/* Same as CPP_DL_WARNING, except it is not suppressed in system headers. */
-#define CPP_DL_WARNING_SYSHDR 0x01
-/* Warning, an error with -pedantic-errors or -Werror. */
-#define CPP_DL_PEDWARN 0x02
-/* An error. */
-#define CPP_DL_ERROR 0x03
-/* An internal consistency check failed. Prints "internal error: ",
- otherwise the same as CPP_DL_ERROR. */
-#define CPP_DL_ICE 0x04
-/* Extracts a diagnostic level from an int. */
-#define CPP_DL_EXTRACT(l) (l & 0xf)
-/* Nonzero if a diagnostic level is one of the warnings. */
-#define CPP_DL_WARNING_P(l) (CPP_DL_EXTRACT (l) >= CPP_DL_WARNING \
- && CPP_DL_EXTRACT (l) <= CPP_DL_PEDWARN)
-
-/* 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. */
-
-/* Output a diagnostic of some kind. */
-extern void cpp_error (cpp_reader *, int, const char *msgid, ...)
- ATTRIBUTE_PRINTF_3;
-
-/* Output a diagnostic with "MSGID: " preceding the
- error string of errno. No location is printed. */
-extern void cpp_errno (cpp_reader *, int, const char *msgid);
-
-/* Same as cpp_error, except additionally specifies a position as a
- (translation unit) physical line and physical column. If the line is
- zero, then no location is printed. */
-extern void cpp_error_with_line (cpp_reader *, int, source_location, unsigned,
- const char *msgid, ...) ATTRIBUTE_PRINTF_5;
-
-/* In cpplex.c */
-extern int cpp_ideq (const cpp_token *, const char *);
-extern void cpp_output_line (cpp_reader *, FILE *);
-extern void cpp_output_token (const cpp_token *, FILE *);
-extern const char *cpp_type2name (enum cpp_ttype);
-/* Returns the value of an escape sequence, truncated to the correct
- target precision. PSTR points to the input pointer, which is just
- after the backslash. LIMIT is how much text we have. WIDE is true
- if the escape sequence is part of a wide character constant or
- string literal. Handles all relevant diagnostics. */
-extern cppchar_t cpp_parse_escape (cpp_reader *, const unsigned char ** pstr,
- const unsigned char *limit, int wide);
-
-/* 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 (cpp_reader *, const unsigned char *,
- unsigned int);
-
-typedef int (*cpp_cb) (cpp_reader *, cpp_hashnode *, void *);
-extern void cpp_forall_identifiers (cpp_reader *, cpp_cb, void *);
-
-/* In cppmacro.c */
-extern void cpp_scan_nooutput (cpp_reader *);
-extern int cpp_sys_macro_p (cpp_reader *);
-extern unsigned char *cpp_quote_string (unsigned char *, const unsigned char *,
- unsigned int);
-
-/* In cppfiles.c */
-extern bool cpp_included (cpp_reader *, const char *);
-extern void cpp_make_system_header (cpp_reader *, int, int);
-extern bool cpp_push_include (cpp_reader *, const char *);
-extern void cpp_change_file (cpp_reader *, enum lc_reason, const char *);
-extern const char *cpp_get_path (struct _cpp_file *);
-extern cpp_dir *cpp_get_dir (struct _cpp_file *);
-extern cpp_buffer *cpp_get_buffer (cpp_reader *);
-extern struct _cpp_file *cpp_get_file (cpp_buffer *);
-extern cpp_buffer *cpp_get_prev (cpp_buffer *);
-
-/* In cpppch.c */
-struct save_macro_data;
-extern int cpp_save_state (cpp_reader *, FILE *);
-extern int cpp_write_pch_deps (cpp_reader *, FILE *);
-extern int cpp_write_pch_state (cpp_reader *, FILE *);
-extern int cpp_valid_state (cpp_reader *, const char *, int);
-extern void cpp_prepare_state (cpp_reader *, struct save_macro_data **);
-extern int cpp_read_state (cpp_reader *, const char *, FILE *,
- struct save_macro_data *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ! GCC_CPPLIB_H */
diff --git a/gcc/cppmacro.c b/gcc/cppmacro.c
deleted file mode 100644
index e3d0dc37b29..00000000000
--- a/gcc/cppmacro.c
+++ /dev/null
@@ -1,1729 +0,0 @@
-/* Part of CPP library. (Macro and #define handling.)
- Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 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"
-
-typedef struct macro_arg macro_arg;
-struct macro_arg
-{
- const cpp_token **first; /* First token in unexpanded argument. */
- const cpp_token **expanded; /* Macro-expanded argument. */
- const cpp_token *stringified; /* Stringified argument. */
- unsigned int count; /* # of tokens in argument. */
- unsigned int expanded_count; /* # of tokens in expanded argument. */
-};
-
-/* Macro expansion. */
-
-static int enter_macro_context (cpp_reader *, cpp_hashnode *);
-static int builtin_macro (cpp_reader *, cpp_hashnode *);
-static void push_token_context (cpp_reader *, cpp_hashnode *,
- const cpp_token *, unsigned int);
-static void push_ptoken_context (cpp_reader *, cpp_hashnode *, _cpp_buff *,
- const cpp_token **, unsigned int);
-static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *);
-static cpp_context *next_context (cpp_reader *);
-static const cpp_token *padding_token (cpp_reader *, const cpp_token *);
-static void expand_arg (cpp_reader *, macro_arg *);
-static const cpp_token *new_string_token (cpp_reader *, uchar *, unsigned int);
-static const cpp_token *stringify_arg (cpp_reader *, macro_arg *);
-static void paste_all_tokens (cpp_reader *, const cpp_token *);
-static bool paste_tokens (cpp_reader *, const cpp_token **, const cpp_token *);
-static void replace_args (cpp_reader *, cpp_hashnode *, cpp_macro *,
- macro_arg *);
-static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *);
-static bool create_iso_definition (cpp_reader *, cpp_macro *);
-
-/* #define directive parsing and handling. */
-
-static cpp_token *alloc_expansion_token (cpp_reader *, cpp_macro *);
-static cpp_token *lex_expansion_token (cpp_reader *, cpp_macro *);
-static bool warn_of_redefinition (cpp_reader *, const cpp_hashnode *,
- const cpp_macro *);
-static bool parse_params (cpp_reader *, cpp_macro *);
-static void check_trad_stringification (cpp_reader *, const cpp_macro *,
- const cpp_string *);
-
-/* Emits a warning if NODE is a macro defined in the main file that
- has not been used. */
-int
-_cpp_warn_if_unused_macro (cpp_reader *pfile, cpp_hashnode *node,
- void *v ATTRIBUTE_UNUSED)
-{
- if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
- {
- cpp_macro *macro = node->value.macro;
-
- if (!macro->used
- && MAIN_FILE_P (linemap_lookup (pfile->line_table, macro->line)))
- cpp_error_with_line (pfile, CPP_DL_WARNING, macro->line, 0,
- "macro \"%s\" is not used", NODE_NAME (node));
- }
-
- return 1;
-}
-
-/* Allocates and returns a CPP_STRING token, containing TEXT of length
- LEN, after null-terminating it. TEXT must be in permanent storage. */
-static const cpp_token *
-new_string_token (cpp_reader *pfile, unsigned char *text, unsigned int len)
-{
- cpp_token *token = _cpp_temp_token (pfile);
-
- text[len] = '\0';
- token->type = CPP_STRING;
- token->val.str.len = len;
- token->val.str.text = text;
- token->flags = 0;
- return token;
-}
-
-static const char * const monthnames[] =
-{
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-/* Handle builtin macros like __FILE__, and push the resulting token
- on the context stack. Also handles _Pragma, for which no new token
- is created. Returns 1 if it generates a new token context, 0 to
- return the token to the caller. */
-const uchar *
-_cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
-{
- const struct line_map *map;
- const uchar *result = NULL;
- unsigned int number = 1;
-
- switch (node->value.builtin)
- {
- default:
- cpp_error (pfile, CPP_DL_ICE, "invalid built-in macro \"%s\"",
- NODE_NAME (node));
- break;
-
- case BT_FILE:
- case BT_BASE_FILE:
- {
- unsigned int len;
- const char *name;
- uchar *buf;
- map = linemap_lookup (pfile->line_table, pfile->line_table->highest_line);
-
- if (node->value.builtin == BT_BASE_FILE)
- while (! MAIN_FILE_P (map))
- map = INCLUDED_FROM (pfile->line_table, map);
-
- name = map->to_file;
- len = strlen (name);
- buf = _cpp_unaligned_alloc (pfile, len * 4 + 3);
- result = buf;
- *buf = '"';
- buf = cpp_quote_string (buf + 1, (const unsigned char *) name, len);
- *buf++ = '"';
- *buf = '\0';
- }
- break;
-
- case BT_INCLUDE_LEVEL:
- /* The line map depth counts the primary source as level 1, but
- historically __INCLUDE_DEPTH__ has called the primary source
- level 0. */
- number = pfile->line_table->depth - 1;
- break;
-
- case BT_SPECLINE:
- map = &pfile->line_table->maps[pfile->line_table->used-1];
- /* 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. */
- if (CPP_OPTION (pfile, traditional))
- number = pfile->line_table->highest_line;
- else
- number = pfile->cur_token[-1].src_loc;
- number = SOURCE_LINE (map, number);
- break;
-
- /* __STDC__ has the value 1 under normal circumstances.
- However, if (a) we are in a system header, (b) the option
- stdc_0_in_system_headers is true (set by target config), and
- (c) we are not in strictly conforming mode, then it has the
- value 0. */
- case BT_STDC:
- {
- if (cpp_in_system_header (pfile)
- && CPP_OPTION (pfile, stdc_0_in_system_headers)
- && !CPP_OPTION (pfile,std))
- number = 0;
- else
- number = 1;
- }
- break;
-
- case BT_DATE:
- case BT_TIME:
- if (pfile->date == NULL)
- {
- /* Allocate __DATE__ and __TIME__ strings from permanent
- storage. We only do this once, and don't generate them
- at init time, because time() and localtime() are very
- slow on some systems. */
- time_t tt;
- struct tm *tb = NULL;
-
- /* (time_t) -1 is a legitimate value for "number of seconds
- since the Epoch", so we have to do a little dance to
- distinguish that from a genuine error. */
- errno = 0;
- tt = time(NULL);
- if (tt != (time_t)-1 || errno == 0)
- tb = localtime (&tt);
-
- if (tb)
- {
- pfile->date = _cpp_unaligned_alloc (pfile,
- sizeof ("\"Oct 11 1347\""));
- sprintf ((char *) pfile->date, "\"%s %2d %4d\"",
- monthnames[tb->tm_mon], tb->tm_mday,
- tb->tm_year + 1900);
-
- pfile->time = _cpp_unaligned_alloc (pfile,
- sizeof ("\"12:34:56\""));
- sprintf ((char *) pfile->time, "\"%02d:%02d:%02d\"",
- tb->tm_hour, tb->tm_min, tb->tm_sec);
- }
- else
- {
- cpp_errno (pfile, CPP_DL_WARNING,
- "could not determine date and time");
-
- pfile->date = U"\"??? ?? ????\"";
- pfile->time = U"\"??:??:??\"";
- }
- }
-
- if (node->value.builtin == BT_DATE)
- result = pfile->date;
- else
- result = pfile->time;
- break;
- }
-
- if (result == NULL)
- {
- /* 21 bytes holds all NUL-terminated unsigned 64-bit numbers. */
- result = _cpp_unaligned_alloc (pfile, 21);
- sprintf ((char *) result, "%u", number);
- }
-
- return result;
-}
-
-/* Convert builtin macros like __FILE__ to a token and push it on the
- context stack. Also handles _Pragma, for which no new token is
- created. Returns 1 if it generates a new token context, 0 to
- return the token to the caller. */
-static int
-builtin_macro (cpp_reader *pfile, cpp_hashnode *node)
-{
- const uchar *buf;
- size_t len;
- char *nbuf;
-
- if (node->value.builtin == BT_PRAGMA)
- {
- /* Don't interpret _Pragma within directives. The standard is
- not clear on this, but to me this makes most sense. */
- if (pfile->state.in_directive)
- return 0;
-
- _cpp_do__Pragma (pfile);
- return 1;
- }
-
- buf = _cpp_builtin_macro_text (pfile, node);
- len = ustrlen (buf);
- nbuf = alloca (len + 1);
- memcpy (nbuf, buf, len);
- nbuf[len]='\n';
-
- cpp_push_buffer (pfile, (uchar *) nbuf, len, /* from_stage3 */ true);
- _cpp_clean_line (pfile);
-
- /* Set pfile->cur_token as required by _cpp_lex_direct. */
- pfile->cur_token = _cpp_temp_token (pfile);
- push_token_context (pfile, NULL, _cpp_lex_direct (pfile), 1);
- if (pfile->buffer->cur != pfile->buffer->rlimit)
- cpp_error (pfile, CPP_DL_ICE, "invalid built-in macro \"%s\"",
- NODE_NAME (node));
- _cpp_pop_buffer (pfile);
-
- return 1;
-}
-
-/* Copies SRC, of length LEN, to DEST, adding backslashes before all
- backslashes and double quotes. Non-printable characters are
- converted to octal. DEST must be of sufficient size. Returns
- a pointer to the end of the string. */
-uchar *
-cpp_quote_string (uchar *dest, const uchar *src, unsigned int len)
-{
- while (len--)
- {
- uchar 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 ARG to a single string token according to
- the rules of the ISO C #-operator. */
-static const cpp_token *
-stringify_arg (cpp_reader *pfile, macro_arg *arg)
-{
- unsigned char *dest;
- unsigned int i, escape_it, backslash_count = 0;
- const cpp_token *source = NULL;
- size_t len;
-
- if (BUFF_ROOM (pfile->u_buff) < 3)
- _cpp_extend_buff (pfile, &pfile->u_buff, 3);
- dest = BUFF_FRONT (pfile->u_buff);
- *dest++ = '"';
-
- /* Loop, reading in the argument's tokens. */
- for (i = 0; i < arg->count; i++)
- {
- const cpp_token *token = arg->first[i];
-
- if (token->type == CPP_PADDING)
- {
- if (source == NULL)
- source = token->val.source;
- continue;
- }
-
- escape_it = (token->type == CPP_STRING || token->type == CPP_WSTRING
- || token->type == CPP_CHAR || token->type == CPP_WCHAR);
-
- /* Room for each char being written in octal, initial space and
- final quote and NUL. */
- len = cpp_token_len (token);
- if (escape_it)
- len *= 4;
- len += 3;
-
- if ((size_t) (BUFF_LIMIT (pfile->u_buff) - dest) < len)
- {
- size_t len_so_far = dest - BUFF_FRONT (pfile->u_buff);
- _cpp_extend_buff (pfile, &pfile->u_buff, len);
- dest = BUFF_FRONT (pfile->u_buff) + len_so_far;
- }
-
- /* Leading white space? */
- if (dest - 1 != BUFF_FRONT (pfile->u_buff))
- {
- if (source == NULL)
- source = token;
- if (source->flags & PREV_WHITE)
- *dest++ = ' ';
- }
- source = NULL;
-
- if (escape_it)
- {
- _cpp_buff *buff = _cpp_get_buff (pfile, len);
- unsigned char *buf = BUFF_FRONT (buff);
- len = cpp_spell_token (pfile, token, buf) - buf;
- dest = cpp_quote_string (dest, buf, len);
- _cpp_release_buff (pfile, buff);
- }
- else
- dest = cpp_spell_token (pfile, token, dest);
-
- if (token->type == CPP_OTHER && token->val.str.text[0] == '\\')
- backslash_count++;
- else
- backslash_count = 0;
- }
-
- /* Ignore the final \ of invalid string literals. */
- if (backslash_count & 1)
- {
- cpp_error (pfile, CPP_DL_WARNING,
- "invalid string literal, ignoring final '\\'");
- dest--;
- }
-
- /* Commit the memory, including NUL, and return the token. */
- *dest++ = '"';
- len = dest - BUFF_FRONT (pfile->u_buff);
- BUFF_FRONT (pfile->u_buff) = dest + 1;
- return new_string_token (pfile, dest - len, len);
-}
-
-/* Try to paste two tokens. On success, return nonzero. In any
- case, PLHS is updated to point to the pasted token, which is
- guaranteed to not have the PASTE_LEFT flag set. */
-static bool
-paste_tokens (cpp_reader *pfile, const cpp_token **plhs, const cpp_token *rhs)
-{
- unsigned char *buf, *end;
- const cpp_token *lhs;
- unsigned int len;
- bool valid;
-
- lhs = *plhs;
- len = cpp_token_len (lhs) + cpp_token_len (rhs) + 1;
- buf = alloca (len);
- end = cpp_spell_token (pfile, lhs, buf);
-
- /* Avoid comment headers, since they are still processed in stage 3.
- It is simpler to insert a space here, rather than modifying the
- lexer to ignore comments in some circumstances. Simply returning
- false doesn't work, since we want to clear the PASTE_LEFT flag. */
- if (lhs->type == CPP_DIV && rhs->type != CPP_EQ)
- *end++ = ' ';
- end = cpp_spell_token (pfile, rhs, end);
- *end = '\n';
-
- cpp_push_buffer (pfile, buf, end - buf, /* from_stage3 */ true);
- _cpp_clean_line (pfile);
-
- /* Set pfile->cur_token as required by _cpp_lex_direct. */
- pfile->cur_token = _cpp_temp_token (pfile);
- *plhs = _cpp_lex_direct (pfile);
- valid = pfile->buffer->cur == pfile->buffer->rlimit;
- _cpp_pop_buffer (pfile);
-
- return valid;
-}
-
-/* Handles an arbitrarily long sequence of ## operators, with initial
- operand LHS. This implementation is left-associative,
- non-recursive, and finishes a paste before handling succeeding
- ones. If a paste fails, we back up to the RHS of the failing ##
- operator before pushing the context containing the result of prior
- successful pastes, with the effect that the RHS appears in the
- output stream after the pasted LHS normally. */
-static void
-paste_all_tokens (cpp_reader *pfile, const cpp_token *lhs)
-{
- const cpp_token *rhs;
- cpp_context *context = pfile->context;
-
- 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. */
- if (context->direct_p)
- rhs = FIRST (context).token++;
- else
- rhs = *FIRST (context).ptoken++;
-
- if (rhs->type == CPP_PADDING)
- abort ();
-
- if (!paste_tokens (pfile, &lhs, rhs))
- {
- _cpp_backup_tokens (pfile, 1);
-
- /* Mandatory error for all apart from assembler. */
- if (CPP_OPTION (pfile, lang) != CLK_ASM)
- cpp_error (pfile, CPP_DL_ERROR,
- "pasting \"%s\" and \"%s\" does not give a valid preprocessing token",
- cpp_token_as_text (pfile, lhs),
- cpp_token_as_text (pfile, rhs));
- break;
- }
- }
- while (rhs->flags & PASTE_LEFT);
-
- /* Put the resulting token in its own context. */
- push_token_context (pfile, NULL, lhs, 1);
-}
-
-/* Returns TRUE if the number of arguments ARGC supplied in an
- invocation of the MACRO referenced by NODE is valid. An empty
- invocation to a macro with no parameters should pass ARGC as zero.
-
- Note that MACRO cannot necessarily be deduced from NODE, in case
- NODE was redefined whilst collecting arguments. */
-bool
-_cpp_arguments_ok (cpp_reader *pfile, cpp_macro *macro, const cpp_hashnode *node, unsigned int argc)
-{
- if (argc == macro->paramc)
- return true;
-
- 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_error (pfile, CPP_DL_PEDWARN,
- "ISO C99 requires rest arguments to be used");
- return true;
- }
-
- cpp_error (pfile, CPP_DL_ERROR,
- "macro \"%s\" requires %u arguments, but only %u given",
- NODE_NAME (node), macro->paramc, argc);
- }
- else
- cpp_error (pfile, CPP_DL_ERROR,
- "macro \"%s\" passed %u arguments, but takes just %u",
- NODE_NAME (node), argc, macro->paramc);
-
- return false;
-}
-
-/* Reads and returns the arguments to a function-like macro
- invocation. Assumes the opening parenthesis has been processed.
- If there is an error, emits an appropriate diagnostic and returns
- NULL. Each argument is terminated by a CPP_EOF token, for the
- future benefit of expand_arg(). */
-static _cpp_buff *
-collect_args (cpp_reader *pfile, const cpp_hashnode *node)
-{
- _cpp_buff *buff, *base_buff;
- cpp_macro *macro;
- macro_arg *args, *arg;
- const cpp_token *token;
- unsigned int argc;
-
- macro = node->value.macro;
- if (macro->paramc)
- argc = macro->paramc;
- else
- argc = 1;
- buff = _cpp_get_buff (pfile, argc * (50 * sizeof (cpp_token *)
- + sizeof (macro_arg)));
- base_buff = buff;
- args = (macro_arg *) buff->base;
- memset (args, 0, argc * sizeof (macro_arg));
- buff->cur = (unsigned char *) &args[argc];
- arg = args, argc = 0;
-
- /* Collect the tokens making up each argument. We don't yet know
- how many arguments have been supplied, whether too many or too
- few. Hence the slightly bizarre usage of "argc" and "arg". */
- do
- {
- unsigned int paren_depth = 0;
- unsigned int ntokens = 0;
-
- argc++;
- arg->first = (const cpp_token **) buff->cur;
-
- for (;;)
- {
- /* Require space for 2 new tokens (including a CPP_EOF). */
- if ((unsigned char *) &arg->first[ntokens + 2] > buff->limit)
- {
- buff = _cpp_append_extend_buff (pfile, buff,
- 1000 * sizeof (cpp_token *));
- arg->first = (const cpp_token **) buff->cur;
- }
-
- token = cpp_get_token (pfile);
-
- if (token->type == CPP_PADDING)
- {
- /* Drop leading padding. */
- if (ntokens == 0)
- continue;
- }
- else if (token->type == CPP_OPEN_PAREN)
- paren_depth++;
- else if (token->type == CPP_CLOSE_PAREN)
- {
- if (paren_depth-- == 0)
- break;
- }
- else if (token->type == CPP_COMMA)
- {
- /* A comma does not terminate an argument within
- parentheses or as part of a variable argument. */
- if (paren_depth == 0
- && ! (macro->variadic && argc == macro->paramc))
- break;
- }
- else if (token->type == CPP_EOF
- || (token->type == CPP_HASH && token->flags & BOL))
- break;
-
- arg->first[ntokens++] = token;
- }
-
- /* Drop trailing padding. */
- while (ntokens > 0 && arg->first[ntokens - 1]->type == CPP_PADDING)
- ntokens--;
-
- arg->count = ntokens;
- arg->first[ntokens] = &pfile->eof;
-
- /* Terminate the argument. Excess arguments loop back and
- overwrite the final legitimate argument, before failing. */
- if (argc <= macro->paramc)
- {
- buff->cur = (unsigned char *) &arg->first[ntokens + 1];
- if (argc != macro->paramc)
- arg++;
- }
- }
- while (token->type != CPP_CLOSE_PAREN && token->type != CPP_EOF);
-
- if (token->type == CPP_EOF)
- {
- /* We still need the CPP_EOF to end directives, and to end
- pre-expansion of a macro argument. Step back is not
- unconditional, since we don't want to return a CPP_EOF to our
- callers at the end of an -include-d file. */
- if (pfile->context->prev || pfile->state.in_directive)
- _cpp_backup_tokens (pfile, 1);
- cpp_error (pfile, CPP_DL_ERROR,
- "unterminated argument list invoking macro \"%s\"",
- NODE_NAME (node));
- }
- else
- {
- /* A single empty argument is counted as no argument. */
- if (argc == 1 && macro->paramc == 0 && args[0].count == 0)
- argc = 0;
- if (_cpp_arguments_ok (pfile, macro, node, argc))
- {
- /* GCC has special semantics for , ## b where b is a varargs
- parameter: we remove the comma if b was omitted entirely.
- If b was merely an empty argument, the comma is retained.
- If the macro takes just one (varargs) parameter, then we
- retain the comma only if we are standards conforming.
-
- If FIRST is NULL replace_args () swallows the comma. */
- if (macro->variadic && (argc < macro->paramc
- || (argc == 1 && args[0].count == 0
- && !CPP_OPTION (pfile, std))))
- args[macro->paramc - 1].first = NULL;
- return base_buff;
- }
- }
-
- /* An error occurred. */
- _cpp_release_buff (pfile, base_buff);
- return NULL;
-}
-
-/* Search for an opening parenthesis to the macro of NODE, in such a
- way that, if none is found, we don't lose the information in any
- intervening padding tokens. If we find the parenthesis, collect
- the arguments and return the buffer containing them. */
-static _cpp_buff *
-funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node)
-{
- const cpp_token *token, *padding = NULL;
-
- for (;;)
- {
- token = cpp_get_token (pfile);
- if (token->type != CPP_PADDING)
- break;
- if (padding == NULL
- || (!(padding->flags & PREV_WHITE) && token->val.source == NULL))
- padding = token;
- }
-
- if (token->type == CPP_OPEN_PAREN)
- {
- pfile->state.parsing_args = 2;
- return collect_args (pfile, node);
- }
-
- /* CPP_EOF can be the end of macro arguments, or the end of the
- file. We mustn't back up over the latter. Ugh. */
- if (token->type != CPP_EOF || token == &pfile->eof)
- {
- /* Back up. We may have skipped padding, in which case backing
- up more than one token when expanding macros is in general
- too difficult. We re-insert it in its own context. */
- _cpp_backup_tokens (pfile, 1);
- if (padding)
- push_token_context (pfile, NULL, padding, 1);
- }
-
- return NULL;
-}
-
-/* Push the context of a macro with hash entry NODE onto the context
- stack. If we can successfully expand the macro, we push a context
- containing its yet-to-be-rescanned replacement list and return one.
- Otherwise, we don't push a context and return zero. */
-static int
-enter_macro_context (cpp_reader *pfile, cpp_hashnode *node)
-{
- /* The presence of a macro invalidates a file's controlling macro. */
- pfile->mi_valid = false;
-
- pfile->state.angled_headers = false;
-
- /* Handle standard macros. */
- if (! (node->flags & NODE_BUILTIN))
- {
- cpp_macro *macro = node->value.macro;
-
- if (macro->fun_like)
- {
- _cpp_buff *buff;
-
- pfile->state.prevent_expansion++;
- pfile->keep_tokens++;
- pfile->state.parsing_args = 1;
- buff = funlike_invocation_p (pfile, node);
- pfile->state.parsing_args = 0;
- pfile->keep_tokens--;
- pfile->state.prevent_expansion--;
-
- if (buff == NULL)
- {
- if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr)
- cpp_error (pfile, CPP_DL_WARNING,
- "function-like macro \"%s\" must be used with arguments in traditional C",
- NODE_NAME (node));
-
- return 0;
- }
-
- if (macro->paramc > 0)
- replace_args (pfile, node, macro, (macro_arg *) buff->base);
- _cpp_release_buff (pfile, buff);
- }
-
- /* Disable the macro within its expansion. */
- node->flags |= NODE_DISABLED;
-
- macro->used = 1;
-
- if (macro->paramc == 0)
- push_token_context (pfile, node, macro->exp.tokens, macro->count);
-
- return 1;
- }
-
- /* Handle built-in macros and the _Pragma operator. */
- return builtin_macro (pfile, node);
-}
-
-/* Replace the parameters in a function-like macro of NODE with the
- actual ARGS, and place the result in a newly pushed token context.
- Expand each argument before replacing, unless it is operated upon
- by the # or ## operators. */
-static void
-replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, macro_arg *args)
-{
- unsigned int i, total;
- const cpp_token *src, *limit;
- const cpp_token **dest, **first;
- macro_arg *arg;
- _cpp_buff *buff;
-
- /* First, fully macro-expand arguments, calculating the number of
- tokens in the final expansion as we go. The ordering of the if
- statements below is subtle; we must handle stringification before
- pasting. */
- total = macro->count;
- limit = macro->exp.tokens + macro->count;
-
- for (src = macro->exp.tokens; src < limit; src++)
- if (src->type == CPP_MACRO_ARG)
- {
- /* Leading and trailing padding tokens. */
- total += 2;
-
- /* 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)
- arg->stringified = stringify_arg (pfile, arg);
- }
- else if ((src->flags & PASTE_LEFT)
- || (src > macro->exp.tokens && (src[-1].flags & PASTE_LEFT)))
- total += arg->count - 1;
- else
- {
- if (!arg->expanded)
- expand_arg (pfile, arg);
- total += arg->expanded_count - 1;
- }
- }
-
- /* Now allocate space for the expansion, copy the tokens and replace
- the arguments. */
- buff = _cpp_get_buff (pfile, total * sizeof (cpp_token *));
- first = (const cpp_token **) buff->base;
- dest = first;
-
- for (src = macro->exp.tokens; src < limit; src++)
- {
- unsigned int count;
- const cpp_token **from, **paste_flag;
-
- if (src->type != CPP_MACRO_ARG)
- {
- *dest++ = src;
- continue;
- }
-
- paste_flag = 0;
- arg = &args[src->val.arg_no - 1];
- if (src->flags & STRINGIFY_ARG)
- count = 1, from = &arg->stringified;
- else if (src->flags & PASTE_LEFT)
- count = arg->count, from = arg->first;
- else if (src != macro->exp.tokens && (src[-1].flags & PASTE_LEFT))
- {
- count = arg->count, from = arg->first;
- if (dest != first)
- {
- if (dest[-1]->type == CPP_COMMA
- && macro->variadic
- && src->val.arg_no == macro->paramc)
- {
- /* Swallow a pasted comma if from == NULL, otherwise
- drop the paste flag. */
- if (from == NULL)
- dest--;
- else
- paste_flag = dest - 1;
- }
- /* Remove the paste flag if the RHS is a placemarker. */
- else if (count == 0)
- paste_flag = dest - 1;
- }
- }
- else
- count = arg->expanded_count, from = arg->expanded;
-
- /* Padding on the left of an argument (unless RHS of ##). */
- if ((!pfile->state.in_directive || pfile->state.directive_wants_padding)
- && src != macro->exp.tokens && !(src[-1].flags & PASTE_LEFT))
- *dest++ = padding_token (pfile, src);
-
- if (count)
- {
- memcpy (dest, from, count * sizeof (cpp_token *));
- dest += count;
-
- /* With a non-empty argument on the LHS of ##, the last
- token should be flagged PASTE_LEFT. */
- if (src->flags & PASTE_LEFT)
- paste_flag = dest - 1;
- }
-
- /* Avoid paste on RHS (even case count == 0). */
- if (!pfile->state.in_directive && !(src->flags & PASTE_LEFT))
- *dest++ = &pfile->avoid_paste;
-
- /* Add a new paste flag, or remove an unwanted one. */
- if (paste_flag)
- {
- cpp_token *token = _cpp_temp_token (pfile);
- token->type = (*paste_flag)->type;
- token->val.str = (*paste_flag)->val.str;
- if (src->flags & PASTE_LEFT)
- token->flags = (*paste_flag)->flags | PASTE_LEFT;
- else
- token->flags = (*paste_flag)->flags & ~PASTE_LEFT;
- *paste_flag = token;
- }
- }
-
- /* Free the expanded arguments. */
- for (i = 0; i < macro->paramc; i++)
- if (args[i].expanded)
- free (args[i].expanded);
-
- push_ptoken_context (pfile, node, buff, first, dest - first);
-}
-
-/* Return a special padding token, with padding inherited from SOURCE. */
-static const cpp_token *
-padding_token (cpp_reader *pfile, const cpp_token *source)
-{
- cpp_token *result = _cpp_temp_token (pfile);
-
- result->type = CPP_PADDING;
- result->val.source = source;
- result->flags = 0;
- return result;
-}
-
-/* Get a new uninitialized context. Create a new one if we cannot
- re-use an old one. */
-static cpp_context *
-next_context (cpp_reader *pfile)
-{
- cpp_context *result = pfile->context->next;
-
- if (result == 0)
- {
- result = xnew (cpp_context);
- result->prev = pfile->context;
- result->next = 0;
- pfile->context->next = result;
- }
-
- pfile->context = result;
- return result;
-}
-
-/* Push a list of pointers to tokens. */
-static void
-push_ptoken_context (cpp_reader *pfile, cpp_hashnode *macro, _cpp_buff *buff,
- const cpp_token **first, unsigned int count)
-{
- cpp_context *context = next_context (pfile);
-
- context->direct_p = false;
- context->macro = macro;
- context->buff = buff;
- FIRST (context).ptoken = first;
- LAST (context).ptoken = first + count;
-}
-
-/* Push a list of tokens. */
-static void
-push_token_context (cpp_reader *pfile, cpp_hashnode *macro,
- const cpp_token *first, unsigned int count)
-{
- cpp_context *context = next_context (pfile);
-
- context->direct_p = true;
- context->macro = macro;
- context->buff = NULL;
- FIRST (context).token = first;
- LAST (context).token = first + count;
-}
-
-/* Push a traditional macro's replacement text. */
-void
-_cpp_push_text_context (cpp_reader *pfile, cpp_hashnode *macro,
- const uchar *start, size_t len)
-{
- cpp_context *context = next_context (pfile);
-
- context->direct_p = true;
- context->macro = macro;
- context->buff = NULL;
- CUR (context) = start;
- RLIMIT (context) = start + len;
- macro->flags |= NODE_DISABLED;
-}
-
-/* Expand an argument ARG before replacing parameters in a
- function-like macro. This works by pushing a context with the
- argument's tokens, and then expanding that into a temporary buffer
- as if it were a normal part of the token stream. collect_args()
- has terminated the argument's tokens with a CPP_EOF so that we know
- when we have fully expanded the argument. */
-static void
-expand_arg (cpp_reader *pfile, macro_arg *arg)
-{
- unsigned int capacity;
- bool saved_warn_trad;
-
- if (arg->count == 0)
- return;
-
- /* Don't warn about funlike macros when pre-expanding. */
- saved_warn_trad = CPP_WTRADITIONAL (pfile);
- CPP_WTRADITIONAL (pfile) = 0;
-
- /* Loop, reading in the arguments. */
- capacity = 256;
- arg->expanded = xmalloc (capacity * sizeof (cpp_token *));
-
- push_ptoken_context (pfile, NULL, NULL, arg->first, arg->count + 1);
- for (;;)
- {
- const cpp_token *token;
-
- if (arg->expanded_count + 1 >= capacity)
- {
- capacity *= 2;
- arg->expanded = xrealloc (arg->expanded,
- capacity * sizeof (cpp_token *));
- }
-
- token = cpp_get_token (pfile);
-
- if (token->type == CPP_EOF)
- break;
-
- arg->expanded[arg->expanded_count++] = token;
- }
-
- _cpp_pop_context (pfile);
-
- CPP_WTRADITIONAL (pfile) = saved_warn_trad;
-}
-
-/* Pop the current context off the stack, re-enabling the macro if the
- context represented a macro's replacement list. The context
- structure is not freed so that we can re-use it later. */
-void
-_cpp_pop_context (cpp_reader *pfile)
-{
- cpp_context *context = pfile->context;
-
- if (context->macro)
- context->macro->flags &= ~NODE_DISABLED;
-
- if (context->buff)
- _cpp_release_buff (pfile, context->buff);
-
- pfile->context = context->prev;
-}
-
-/* External routine to get a token. Also used nearly everywhere
- internally, except for places where we know we can safely call
- _cpp_lex_token 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. */
-const cpp_token *
-cpp_get_token (cpp_reader *pfile)
-{
- const cpp_token *result;
-
- for (;;)
- {
- cpp_hashnode *node;
- cpp_context *context = pfile->context;
-
- /* Context->prev == 0 <=> base context. */
- if (!context->prev)
- result = _cpp_lex_token (pfile);
- else if (FIRST (context).token != LAST (context).token)
- {
- if (context->direct_p)
- result = FIRST (context).token++;
- else
- result = *FIRST (context).ptoken++;
-
- if (result->flags & PASTE_LEFT)
- {
- paste_all_tokens (pfile, result);
- if (pfile->state.in_directive)
- continue;
- return padding_token (pfile, result);
- }
- }
- else
- {
- _cpp_pop_context (pfile);
- if (pfile->state.in_directive)
- continue;
- return &pfile->avoid_paste;
- }
-
- if (pfile->state.in_directive && result->type == CPP_COMMENT)
- continue;
-
- if (result->type != CPP_NAME)
- break;
-
- node = result->val.node;
-
- if (node->type != NT_MACRO || (result->flags & NO_EXPAND))
- break;
-
- if (!(node->flags & NODE_DISABLED))
- {
- if (!pfile->state.prevent_expansion
- && enter_macro_context (pfile, node))
- {
- if (pfile->state.in_directive)
- continue;
- return padding_token (pfile, result);
- }
- }
- else
- {
- /* Flag this token as always unexpandable. FIXME: move this
- to collect_args()?. */
- cpp_token *t = _cpp_temp_token (pfile);
- t->type = result->type;
- t->flags = result->flags | NO_EXPAND;
- t->val.str = result->val.str;
- result = t;
- }
-
- break;
- }
-
- return result;
-}
-
-/* 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 (cpp_reader *pfile)
-{
- cpp_hashnode *node = pfile->context->macro;
-
- return node && node->value.macro && node->value.macro->syshdr;
-}
-
-/* Read each token in, until end of the current file. Directives are
- transparently processed. */
-void
-cpp_scan_nooutput (cpp_reader *pfile)
-{
- /* Request a CPP_EOF token at the end of this file, rather than
- transparently continuing with the including file. */
- pfile->buffer->return_at_eof = true;
-
- if (CPP_OPTION (pfile, traditional))
- while (_cpp_read_logical_line_trad (pfile))
- ;
- else
- while (cpp_get_token (pfile)->type != CPP_EOF)
- ;
-}
-
-/* Step back one (or more) tokens. Can only step mack more than 1 if
- they are from the lexer, and not from macro expansion. */
-void
-_cpp_backup_tokens (cpp_reader *pfile, unsigned int count)
-{
- if (pfile->context->prev == NULL)
- {
- pfile->lookaheads += count;
- while (count--)
- {
- pfile->cur_token--;
- if (pfile->cur_token == pfile->cur_run->base
- /* Possible with -fpreprocessed and no leading #line. */
- && pfile->cur_run->prev != NULL)
- {
- pfile->cur_run = pfile->cur_run->prev;
- pfile->cur_token = pfile->cur_run->limit;
- }
- }
- }
- else
- {
- if (count != 1)
- abort ();
- if (pfile->context->direct_p)
- FIRST (pfile->context).token--;
- else
- FIRST (pfile->context).ptoken--;
- }
-}
-
-/* #define directive parsing and handling. */
-
-/* Returns nonzero if a macro redefinition warning is required. */
-static bool
-warn_of_redefinition (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 true;
-
- /* 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;
-
- /* Don't check count here as it can be different in valid
- traditional redefinitions with just whitespace differences. */
- if (macro1->paramc != macro2->paramc
- || macro1->fun_like != macro2->fun_like
- || macro1->variadic != macro2->variadic)
- return true;
-
- /* Check parameter spellings. */
- for (i = 0; i < macro1->paramc; i++)
- if (macro1->params[i] != macro2->params[i])
- return true;
-
- /* Check the replacement text or tokens. */
- if (CPP_OPTION (pfile, traditional))
- return _cpp_expansions_different_trad (macro1, macro2);
-
- if (macro1->count != macro2->count)
- return true;
-
- for (i = 0; i < macro1->count; i++)
- if (!_cpp_equiv_tokens (&macro1->exp.tokens[i], &macro2->exp.tokens[i]))
- return true;
-
- return false;
-}
-
-/* Free the definition of hashnode H. */
-void
-_cpp_free_definition (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 | NODE_DISABLED);
-}
-
-/* Save parameter NODE to the parameter list of macro MACRO. Returns
- zero on success, nonzero if the parameter is a duplicate. */
-bool
-_cpp_save_parameter (cpp_reader *pfile, cpp_macro *macro, cpp_hashnode *node)
-{
- unsigned int len;
- /* Constraint 6.10.3.6 - duplicate parameter names. */
- if (node->flags & NODE_MACRO_ARG)
- {
- cpp_error (pfile, CPP_DL_ERROR, "duplicate macro parameter \"%s\"",
- NODE_NAME (node));
- return true;
- }
-
- if (BUFF_ROOM (pfile->a_buff)
- < (macro->paramc + 1) * sizeof (cpp_hashnode *))
- _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_hashnode *));
-
- ((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[macro->paramc++] = node;
- node->flags |= NODE_MACRO_ARG;
- len = macro->paramc * sizeof (union _cpp_hashnode_value);
- if (len > pfile->macro_buffer_len)
- {
- pfile->macro_buffer = xrealloc (pfile->macro_buffer, len);
- pfile->macro_buffer_len = len;
- }
- ((union _cpp_hashnode_value *) pfile->macro_buffer)[macro->paramc - 1]
- = node->value;
-
- node->value.arg_index = macro->paramc;
- return false;
-}
-
-/* Check the syntax of the parameters in a MACRO definition. Returns
- false if an error occurs. */
-static bool
-parse_params (cpp_reader *pfile, cpp_macro *macro)
-{
- unsigned int prev_ident = 0;
-
- for (;;)
- {
- const cpp_token *token = _cpp_lex_token (pfile);
-
- switch (token->type)
- {
- default:
- /* Allow/ignore comments in parameter lists if we are
- preserving comments in macro expansions. */
- if (token->type == CPP_COMMENT
- && ! CPP_OPTION (pfile, discard_comments_in_macro_exp))
- continue;
-
- cpp_error (pfile, CPP_DL_ERROR,
- "\"%s\" may not appear in macro parameter list",
- cpp_token_as_text (pfile, token));
- return false;
-
- case CPP_NAME:
- if (prev_ident)
- {
- cpp_error (pfile, CPP_DL_ERROR,
- "macro parameters must be comma-separated");
- return false;
- }
- prev_ident = 1;
-
- if (_cpp_save_parameter (pfile, macro, token->val.node))
- return false;
- continue;
-
- case CPP_CLOSE_PAREN:
- if (prev_ident || macro->paramc == 0)
- return true;
-
- /* Fall through to pick up the error. */
- case CPP_COMMA:
- if (!prev_ident)
- {
- cpp_error (pfile, CPP_DL_ERROR, "parameter name missing");
- return false;
- }
- prev_ident = 0;
- continue;
-
- case CPP_ELLIPSIS:
- macro->variadic = 1;
- if (!prev_ident)
- {
- _cpp_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_OPTION (pfile, warn_variadic_macros))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "anonymous variadic macros were introduced in C99");
- }
- else if (CPP_OPTION (pfile, pedantic)
- && CPP_OPTION (pfile, warn_variadic_macros))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "ISO C does not permit named variadic macros");
-
- /* We're at the end, and just expect a closing parenthesis. */
- token = _cpp_lex_token (pfile);
- if (token->type == CPP_CLOSE_PAREN)
- return true;
- /* Fall through. */
-
- case CPP_EOF:
- cpp_error (pfile, CPP_DL_ERROR, "missing ')' in macro parameter list");
- return false;
- }
- }
-}
-
-/* Allocate room for a token from a macro's replacement list. */
-static cpp_token *
-alloc_expansion_token (cpp_reader *pfile, cpp_macro *macro)
-{
- if (BUFF_ROOM (pfile->a_buff) < (macro->count + 1) * sizeof (cpp_token))
- _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_token));
-
- return &((cpp_token *) BUFF_FRONT (pfile->a_buff))[macro->count++];
-}
-
-/* Lex a token from the expansion of MACRO, but mark parameters as we
- find them and warn of traditional stringification. */
-static cpp_token *
-lex_expansion_token (cpp_reader *pfile, cpp_macro *macro)
-{
- cpp_token *token;
-
- pfile->cur_token = alloc_expansion_token (pfile, macro);
- token = _cpp_lex_direct (pfile);
-
- /* Is this a parameter? */
- if (token->type == CPP_NAME
- && (token->val.node->flags & NODE_MACRO_ARG) != 0)
- {
- token->type = CPP_MACRO_ARG;
- token->val.arg_no = token->val.node->value.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;
-}
-
-static bool
-create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
-{
- cpp_token *token;
- const cpp_token *ctoken;
-
- /* Get the first token of the expansion (or the '(' of a
- function-like macro). */
- ctoken = _cpp_lex_token (pfile);
-
- if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE))
- {
- bool ok = parse_params (pfile, macro);
- macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
- if (!ok)
- return false;
-
- /* Success. Commit the parameter array. */
- BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc];
- macro->fun_like = 1;
- }
- else if (ctoken->type != CPP_EOF && !(ctoken->flags & PREV_WHITE))
- cpp_error (pfile, CPP_DL_PEDWARN,
- "ISO C requires whitespace after the macro name");
-
- if (macro->fun_like)
- token = lex_expansion_token (pfile, macro);
- else
- {
- token = alloc_expansion_token (pfile, macro);
- *token = *ctoken;
- }
-
- 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)
- {
- cpp_error (pfile, CPP_DL_ERROR,
- "'#' is not followed by a macro parameter");
- return false;
- }
- }
-
- 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)
- {
- cpp_error (pfile, CPP_DL_ERROR,
- "'##' cannot appear at either end of a macro expansion");
- return false;
- }
-
- token[-1].flags |= PASTE_LEFT;
- }
-
- token = lex_expansion_token (pfile, macro);
- }
-
- macro->exp.tokens = (cpp_token *) BUFF_FRONT (pfile->a_buff);
-
- /* Don't count the CPP_EOF. */
- macro->count--;
-
- /* Clear whitespace on first token for warn_of_redefinition(). */
- if (macro->count)
- macro->exp.tokens[0].flags &= ~PREV_WHITE;
-
- /* Commit the memory. */
- BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->exp.tokens[macro->count];
-
- return true;
-}
-
-/* Parse a macro and save its expansion. Returns nonzero on success. */
-bool
-_cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
-{
- cpp_macro *macro;
- unsigned int i;
- bool ok;
-
- macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro));
- macro->line = pfile->directive_line;
- macro->params = 0;
- macro->paramc = 0;
- macro->variadic = 0;
- macro->used = !CPP_OPTION (pfile, warn_unused_macros);
- macro->count = 0;
- macro->fun_like = 0;
- /* To suppress some diagnostics. */
- macro->syshdr = pfile->buffer && pfile->buffer->sysp != 0;
-
- if (CPP_OPTION (pfile, traditional))
- ok = _cpp_create_trad_definition (pfile, macro);
- else
- {
- cpp_token *saved_cur_token = pfile->cur_token;
-
- ok = create_iso_definition (pfile, macro);
-
- /* Restore lexer position because of games lex_expansion_token()
- plays lexing the macro. We set the type for SEEN_EOL() in
- cpplib.c.
-
- Longer term we should lex the whole line before coming here,
- and just copy the expansion. */
- saved_cur_token[-1].type = pfile->cur_token[-1].type;
- pfile->cur_token = saved_cur_token;
-
- /* Stop the lexer accepting __VA_ARGS__. */
- pfile->state.va_args_ok = 0;
- }
-
- /* Clear the fast argument lookup indices. */
- for (i = macro->paramc; i-- > 0; )
- {
- struct cpp_hashnode *node = macro->params[i];
- node->flags &= ~ NODE_MACRO_ARG;
- node->value = ((union _cpp_hashnode_value *) pfile->macro_buffer)[i];
- }
-
- if (!ok)
- return ok;
-
- if (node->type == NT_MACRO)
- {
- if (CPP_OPTION (pfile, warn_unused_macros))
- _cpp_warn_if_unused_macro (pfile, node, NULL);
-
- if (warn_of_redefinition (pfile, node, macro))
- {
- cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->directive_line, 0,
- "\"%s\" redefined", NODE_NAME (node));
-
- if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
- cpp_error_with_line (pfile, CPP_DL_PEDWARN,
- node->value.macro->line, 0,
- "this is the location of the previous definition");
- }
- }
-
- if (node->type != NT_VOID)
- _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;
-
- return ok;
-}
-
-/* Warn if a token in STRING matches one of a function-like MACRO's
- parameters. */
-static void
-check_trad_stringification (cpp_reader *pfile, const cpp_macro *macro,
- const cpp_string *string)
-{
- unsigned int i, len;
- const uchar *p, *q, *limit;
-
- /* Loop over the string. */
- limit = string->text + string->len - 1;
- for (p = string->text + 1; 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_error (pfile, CPP_DL_WARNING,
- "macro argument \"%s\" would be stringified in traditional C",
- 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 (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_error (pfile, CPP_DL_ICE,
- "invalid hash type %d in cpp_macro_definition", node->type);
- return 0;
- }
-
- /* Calculate length. */
- len = NODE_LEN (node) + 2; /* ' ' and NUL. */
- if (macro->fun_like)
- {
- len += 4; /* "()" plus possible final ".." of named
- varargs (we have + 1 below). */
- for (i = 0; i < macro->paramc; i++)
- len += NODE_LEN (macro->params[i]) + 1; /* "," */
- }
-
- if (CPP_OPTION (pfile, traditional))
- len += _cpp_replacement_text_len (macro);
- else
- {
- for (i = 0; i < macro->count; i++)
- {
- cpp_token *token = &macro->exp.tokens[i];
-
- if (token->type == CPP_MACRO_ARG)
- len += NODE_LEN (macro->params[token->val.arg_no - 1]);
- else
- len += cpp_token_len (token) + 1; /* 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 = 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)
- /* Don't emit a space after the comma here; we're trying
- to emit a Dwarf-friendly definition, and the Dwarf spec
- forbids spaces in the argument list. */
- *buffer++ = ',';
- else if (macro->variadic)
- *buffer++ = '.', *buffer++ = '.', *buffer++ = '.';
- }
- *buffer++ = ')';
- }
-
- /* The Dwarf spec requires a space after the macro name, even if the
- definition is the empty string. */
- *buffer++ = ' ';
-
- if (CPP_OPTION (pfile, traditional))
- buffer = _cpp_copy_replacement_text (macro, buffer);
- else if (macro->count)
- /* Expansion tokens. */
- {
- for (i = 0; i < macro->count; i++)
- {
- cpp_token *token = &macro->exp.tokens[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/gcc/cpppch.c b/gcc/cpppch.c
deleted file mode 100644
index 815235c6c40..00000000000
--- a/gcc/cpppch.c
+++ /dev/null
@@ -1,724 +0,0 @@
-/* Part of CPP library. (Precompiled header reading/writing.)
- Copyright (C) 2000, 2001, 2002, 2003, 2004 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. */
-
-#include "config.h"
-#include "system.h"
-#include "cpplib.h"
-#include "cpphash.h"
-#include "intl.h"
-#include "hashtab.h"
-#include "mkdeps.h"
-
-static int write_macdef (cpp_reader *, cpp_hashnode *, void *);
-static int save_idents (cpp_reader *, cpp_hashnode *, void *);
-static hashval_t hashmem (const void *, size_t);
-static hashval_t cpp_string_hash (const void *);
-static int cpp_string_eq (const void *, const void *);
-static int count_defs (cpp_reader *, cpp_hashnode *, void *);
-static int comp_hashnodes (const void *, const void *);
-static int collect_ht_nodes (cpp_reader *, cpp_hashnode *, void *);
-static int write_defs (cpp_reader *, cpp_hashnode *, void *);
-static int save_macros (cpp_reader *, cpp_hashnode *, void *);
-
-/* This structure represents a macro definition on disk. */
-struct macrodef_struct
-{
- unsigned int definition_length;
- unsigned short name_length;
- unsigned short flags;
-};
-
-/* This is how we write out a macro definition.
- Suitable for being called by cpp_forall_identifiers. */
-
-static int
-write_macdef (cpp_reader *pfile, cpp_hashnode *hn, void *file_p)
-{
- FILE *f = (FILE *) file_p;
- switch (hn->type)
- {
- case NT_VOID:
- if (! (hn->flags & NODE_POISONED))
- return 1;
-
- case NT_MACRO:
- if ((hn->flags & NODE_BUILTIN))
- return 1;
-
- {
- struct macrodef_struct s;
- const unsigned char *defn;
-
- s.name_length = NODE_LEN (hn);
- s.flags = hn->flags & NODE_POISONED;
-
- if (hn->type == NT_MACRO)
- {
- defn = cpp_macro_definition (pfile, hn);
- s.definition_length = ustrlen (defn);
- }
- else
- {
- defn = NODE_NAME (hn);
- s.definition_length = s.name_length;
- }
-
- if (fwrite (&s, sizeof (s), 1, f) != 1
- || fwrite (defn, 1, s.definition_length, f) != s.definition_length)
- {
- cpp_errno (pfile, CPP_DL_ERROR,
- "while writing precompiled header");
- return 0;
- }
- }
- return 1;
-
- case NT_ASSERTION:
- /* Not currently implemented. */
- return 1;
-
- default:
- abort ();
- }
-}
-
-/* This structure records the names of the defined macros.
- It's also used as a callback structure for size_initial_idents
- and save_idents. */
-
-struct cpp_savedstate
-{
- /* A hash table of the defined identifiers. */
- htab_t definedhash;
- /* The size of the definitions of those identifiers (the size of
- 'definedstrs'). */
- size_t hashsize;
- /* Number of definitions */
- size_t n_defs;
- /* Array of definitions. In cpp_write_pch_deps it is used for sorting. */
- cpp_hashnode **defs;
- /* Space for the next definition. Definitions are null-terminated
- strings. */
- unsigned char *definedstrs;
-};
-
-/* Save this identifier into the state: put it in the hash table,
- put the definition in 'definedstrs'. */
-
-static int
-save_idents (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, void *ss_p)
-{
- struct cpp_savedstate *const ss = (struct cpp_savedstate *)ss_p;
-
- if (hn->type != NT_VOID)
- {
- struct cpp_string news;
- void **slot;
-
- news.len = NODE_LEN (hn);
- news.text= NODE_NAME (hn);
- slot = htab_find_slot (ss->definedhash, &news, INSERT);
- if (*slot == NULL)
- {
- struct cpp_string *sp;
- unsigned char *text;
-
- sp = xmalloc (sizeof (struct cpp_string));
- *slot = sp;
-
- sp->len = NODE_LEN (hn);
- sp->text = text = xmalloc (NODE_LEN (hn));
- memcpy (text, NODE_NAME (hn), NODE_LEN (hn));
- }
- }
-
- return 1;
-}
-
-/* Hash some memory in a generic way. */
-
-static hashval_t
-hashmem (const void *p_p, size_t sz)
-{
- const unsigned char *p = (const unsigned char *)p_p;
- size_t i;
- hashval_t h;
-
- h = 0;
- for (i = 0; i < sz; i++)
- h = h * 67 - (*p++ - 113);
- return h;
-}
-
-/* Hash a cpp string for the hashtable machinery. */
-
-static hashval_t
-cpp_string_hash (const void *a_p)
-{
- const struct cpp_string *a = (const struct cpp_string *) a_p;
- return hashmem (a->text, a->len);
-}
-
-/* Compare two cpp strings for the hashtable machinery. */
-
-static int
-cpp_string_eq (const void *a_p, const void *b_p)
-{
- const struct cpp_string *a = (const struct cpp_string *) a_p;
- const struct cpp_string *b = (const struct cpp_string *) b_p;
- return (a->len == b->len
- && memcmp (a->text, b->text, a->len) == 0);
-}
-
-/* Save the current definitions of the cpp_reader for dependency
- checking purposes. When writing a precompiled header, this should
- be called at the same point in the compilation as cpp_valid_state
- would be called when reading the precompiled header back in. */
-
-int
-cpp_save_state (cpp_reader *r, FILE *f)
-{
- /* Save the list of non-void identifiers for the dependency checking. */
- r->savedstate = xmalloc (sizeof (struct cpp_savedstate));
- r->savedstate->definedhash = htab_create (100, cpp_string_hash,
- cpp_string_eq, NULL);
- cpp_forall_identifiers (r, save_idents, r->savedstate);
-
- /* Write out the list of defined identifiers. */
- cpp_forall_identifiers (r, write_macdef, f);
-
- return 0;
-}
-
-/* Calculate the 'hashsize' field of the saved state. */
-
-static int
-count_defs (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, void *ss_p)
-{
- struct cpp_savedstate *const ss = (struct cpp_savedstate *)ss_p;
-
- switch (hn->type)
- {
- case NT_MACRO:
- if (hn->flags & NODE_BUILTIN)
- return 1;
-
- /* else fall through. */
-
- case NT_VOID:
- {
- struct cpp_string news;
- void **slot;
-
- news.len = NODE_LEN (hn);
- news.text = NODE_NAME (hn);
- slot = htab_find (ss->definedhash, &news);
- if (slot == NULL)
- {
- ss->hashsize += NODE_LEN (hn) + 1;
- ss->n_defs += 1;
- }
- }
- return 1;
-
- case NT_ASSERTION:
- /* Not currently implemented. */
- return 1;
-
- default:
- abort ();
- }
-}
-
-/* Collect the identifiers into the state's string table. */
-static int
-write_defs (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn, void *ss_p)
-{
- struct cpp_savedstate *const ss = (struct cpp_savedstate *)ss_p;
-
- switch (hn->type)
- {
- case NT_MACRO:
- if (hn->flags & NODE_BUILTIN)
- return 1;
-
- /* else fall through. */
-
- case NT_VOID:
- {
- struct cpp_string news;
- void **slot;
-
- news.len = NODE_LEN (hn);
- news.text = NODE_NAME (hn);
- slot = htab_find (ss->definedhash, &news);
- if (slot == NULL)
- {
- ss->defs[ss->n_defs] = hn;
- ss->n_defs += 1;
- }
- }
- return 1;
-
- case NT_ASSERTION:
- /* Not currently implemented. */
- return 1;
-
- default:
- abort ();
- }
-}
-
-/* Comparison function for qsort. The arguments point to pointers of
- type ht_hashnode *. */
-static int
-comp_hashnodes (const void *px, const void *py)
-{
- cpp_hashnode *x = *(cpp_hashnode **) px;
- cpp_hashnode *y = *(cpp_hashnode **) py;
- return ustrcmp (NODE_NAME (x), NODE_NAME (y));
-}
-
-/* Write out the remainder of the dependency information. This should be
- called after the PCH is ready to be saved. */
-
-int
-cpp_write_pch_deps (cpp_reader *r, FILE *f)
-{
- struct macrodef_struct z;
- struct cpp_savedstate *const ss = r->savedstate;
- unsigned char *definedstrs;
- size_t i;
-
- /* Collect the list of identifiers which have been seen and
- weren't defined to anything previously. */
- ss->hashsize = 0;
- ss->n_defs = 0;
- cpp_forall_identifiers (r, count_defs, ss);
-
- ss->defs = xmalloc (ss->n_defs * sizeof (cpp_hashnode *));
- ss->n_defs = 0;
- cpp_forall_identifiers (r, write_defs, ss);
-
- /* Sort the list, copy it into a buffer, and write it out. */
- qsort (ss->defs, ss->n_defs, sizeof (cpp_hashnode *), &comp_hashnodes);
- definedstrs = ss->definedstrs = xmalloc (ss->hashsize);
- for (i = 0; i < ss->n_defs; ++i)
- {
- size_t len = NODE_LEN (ss->defs[i]);
- memcpy (definedstrs, NODE_NAME (ss->defs[i]), len + 1);
- definedstrs += len + 1;
- }
-
- memset (&z, 0, sizeof (z));
- z.definition_length = ss->hashsize;
- if (fwrite (&z, sizeof (z), 1, f) != 1
- || fwrite (ss->definedstrs, ss->hashsize, 1, f) != 1)
- {
- cpp_errno (r, CPP_DL_ERROR, "while writing precompiled header");
- return -1;
- }
- free (ss->definedstrs);
-
- /* Free the saved state. */
- free (ss);
- r->savedstate = NULL;
- return 0;
-}
-
-/* Write out the definitions of the preprocessor, in a form suitable for
- cpp_read_state. */
-
-int
-cpp_write_pch_state (cpp_reader *r, FILE *f)
-{
- struct macrodef_struct z;
-
- /* Write out the list of defined identifiers. */
- cpp_forall_identifiers (r, write_macdef, f);
- memset (&z, 0, sizeof (z));
- if (fwrite (&z, sizeof (z), 1, f) != 1)
- {
- cpp_errno (r, CPP_DL_ERROR, "while writing precompiled header");
- return -1;
- }
-
- if (!r->deps)
- r->deps = deps_init ();
-
- if (deps_save (r->deps, f) != 0)
- {
- cpp_errno (r, CPP_DL_ERROR, "while writing precompiled header");
- return -1;
- }
-
- if (! _cpp_save_file_entries (r, f))
- {
- cpp_errno (r, CPP_DL_ERROR, "while writing precompiled header");
- return -1;
- }
-
- return 0;
-}
-
-
-/* Data structure to transform hash table nodes into a sorted list */
-
-struct ht_node_list
-{
- /* Array of nodes */
- cpp_hashnode **defs;
- /* Number of nodes in the array */
- size_t n_defs;
- /* Size of the allocated array */
- size_t asize;
-};
-
-/* Callback for collecting identifiers from hash table */
-
-static int
-collect_ht_nodes (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *hn,
- void *nl_p)
-{
- struct ht_node_list *const nl = (struct ht_node_list *)nl_p;
-
- if (hn->type != NT_VOID || hn->flags & NODE_POISONED)
- {
- if (nl->n_defs == nl->asize)
- {
- nl->asize *= 2;
- nl->defs = xrealloc (nl->defs, nl->asize * sizeof (cpp_hashnode *));
- }
-
- nl->defs[nl->n_defs] = hn;
- ++nl->n_defs;
- }
- return 1;
-}
-
-
-/* Return nonzero if FD is a precompiled header which is consistent
- with the preprocessor's current definitions. It will be consistent
- when:
-
- - anything that was defined just before the PCH was generated
- is defined the same way now; and
- - anything that was not defined then, but is defined now, was not
- used by the PCH.
-
- NAME is used to print warnings if `warn_invalid_pch' is set in the
- reader's flags.
-*/
-
-int
-cpp_valid_state (cpp_reader *r, const char *name, int fd)
-{
- struct macrodef_struct m;
- size_t namebufsz = 256;
- unsigned char *namebuf = xmalloc (namebufsz);
- unsigned char *undeftab = NULL;
- struct ht_node_list nl = { 0, 0, 0 };
- unsigned char *first, *last;
- unsigned int i;
-
- /* Read in the list of identifiers that must be defined
- Check that they are defined in the same way. */
- for (;;)
- {
- cpp_hashnode *h;
- const unsigned char *newdefn;
-
- if (read (fd, &m, sizeof (m)) != sizeof (m))
- goto error;
-
- if (m.name_length == 0)
- break;
-
- if (m.definition_length > namebufsz)
- {
- free (namebuf);
- namebufsz = m.definition_length + 256;
- namebuf = xmalloc (namebufsz);
- }
-
- if ((size_t)read (fd, namebuf, m.definition_length)
- != m.definition_length)
- goto error;
-
- h = cpp_lookup (r, namebuf, m.name_length);
- if (m.flags & NODE_POISONED
- || h->type != NT_MACRO
- || h->flags & NODE_POISONED)
- {
- if (CPP_OPTION (r, warn_invalid_pch))
- cpp_error (r, CPP_DL_WARNING_SYSHDR,
- "%s: not used because `%.*s' not defined",
- name, m.name_length, namebuf);
- goto fail;
- }
-
- newdefn = cpp_macro_definition (r, h);
-
- if (m.definition_length != ustrlen (newdefn)
- || memcmp (namebuf, newdefn, m.definition_length) != 0)
- {
- if (CPP_OPTION (r, warn_invalid_pch))
- cpp_error (r, CPP_DL_WARNING_SYSHDR,
- "%s: not used because `%.*s' defined as `%s' not `%.*s'",
- name, m.name_length, namebuf, newdefn + m.name_length,
- m.definition_length - m.name_length,
- namebuf + m.name_length);
- goto fail;
- }
- }
- free (namebuf);
- namebuf = NULL;
-
- /* Read in the list of identifiers that must not be defined.
- Check that they really aren't. */
- undeftab = xmalloc (m.definition_length);
- if ((size_t) read (fd, undeftab, m.definition_length) != m.definition_length)
- goto error;
-
- /* Collect identifiers from the current hash table. */
- nl.n_defs = 0;
- nl.asize = 10;
- nl.defs = xmalloc (nl.asize * sizeof (cpp_hashnode *));
- cpp_forall_identifiers (r, &collect_ht_nodes, &nl);
- qsort (nl.defs, nl.n_defs, sizeof (cpp_hashnode *), &comp_hashnodes);
-
- /* Loop through nl.defs and undeftab, both of which are sorted lists.
- There should be no matches. */
- first = undeftab;
- last = undeftab + m.definition_length;
- i = 0;
-
- while (first < last && i < nl.n_defs)
- {
- int cmp = ustrcmp (first, NODE_NAME (nl.defs[i]));
-
- if (cmp < 0)
- first += ustrlen (first) + 1;
- else if (cmp > 0)
- ++i;
- else
- {
- if (CPP_OPTION (r, warn_invalid_pch))
- cpp_error (r, CPP_DL_WARNING_SYSHDR,
- "%s: not used because `%s' is defined",
- name, first);
- goto fail;
- }
- }
-
- free(nl.defs);
- free (undeftab);
-
- /* We win! */
- return 0;
-
- error:
- cpp_errno (r, CPP_DL_ERROR, "while reading precompiled header");
- return -1;
-
- fail:
- if (namebuf != NULL)
- free (namebuf);
- if (undeftab != NULL)
- free (undeftab);
- if (nl.defs != NULL)
- free (nl.defs);
- return 1;
-}
-
-/* Save all the existing macros and assertions.
- This code assumes that there might be hundreds, but not thousands of
- existing definitions. */
-
-struct save_macro_item {
- struct save_macro_item *next;
- struct cpp_hashnode macs[64];
-};
-
-struct save_macro_data
-{
- struct save_macro_item *macros;
- size_t count;
- char **saved_pragmas;
-};
-
-/* Save the definition of a single macro, so that it will persist across
- a PCH restore. */
-
-static int
-save_macros (cpp_reader *r ATTRIBUTE_UNUSED, cpp_hashnode *h, void *data_p)
-{
- struct save_macro_data *data = (struct save_macro_data *)data_p;
- if (h->type != NT_VOID
- && (h->flags & NODE_BUILTIN) == 0)
- {
- cpp_hashnode *save;
- if (data->count == ARRAY_SIZE (data->macros->macs))
- {
- struct save_macro_item *d = data->macros;
- data->macros = xmalloc (sizeof (struct save_macro_item));
- data->macros->next = d;
- data->count = 0;
- }
- save = data->macros->macs + data->count;
- data->count++;
- memcpy (save, h, sizeof (struct cpp_hashnode));
- HT_STR (&save->ident) = xmemdup (HT_STR (HT_NODE (save)),
- HT_LEN (HT_NODE (save)),
- HT_LEN (HT_NODE (save)) + 1);
- }
- return 1;
-}
-
-/* Prepare to restore the state, by saving the currently-defined
- macros in 'data'. */
-
-void
-cpp_prepare_state (cpp_reader *r, struct save_macro_data **data)
-{
- struct save_macro_data *d = xmalloc (sizeof (struct save_macro_data));
-
- d->macros = NULL;
- d->count = ARRAY_SIZE (d->macros->macs);
- cpp_forall_identifiers (r, save_macros, d);
- d->saved_pragmas = _cpp_save_pragma_names (r);
- *data = d;
-}
-
-/* Given a precompiled header that was previously determined to be valid,
- apply all its definitions (and undefinitions) to the current state.
- DEPNAME is passed to deps_restore. */
-
-int
-cpp_read_state (cpp_reader *r, const char *name, FILE *f,
- struct save_macro_data *data)
-{
- struct macrodef_struct m;
- size_t defnlen = 256;
- unsigned char *defn = xmalloc (defnlen);
- struct lexer_state old_state;
- struct save_macro_item *d;
- size_t i, mac_count;
-
- /* Restore spec_nodes, which will be full of references to the old
- hashtable entries and so will now be invalid. */
- {
- struct spec_nodes *s = &r->spec_nodes;
- s->n_defined = cpp_lookup (r, DSC("defined"));
- s->n_true = cpp_lookup (r, DSC("true"));
- s->n_false = cpp_lookup (r, DSC("false"));
- s->n__VA_ARGS__ = cpp_lookup (r, DSC("__VA_ARGS__"));
- }
-
- /* Run through the carefully-saved macros, insert them. */
- d = data->macros;
- mac_count = data->count;
- while (d)
- {
- struct save_macro_item *nextd;
- for (i = 0; i < mac_count; i++)
- {
- cpp_hashnode *h;
-
- h = cpp_lookup (r, HT_STR (HT_NODE (&d->macs[i])),
- HT_LEN (HT_NODE (&d->macs[i])));
- h->type = d->macs[i].type;
- h->flags = d->macs[i].flags;
- h->value = d->macs[i].value;
- free ((void *)HT_STR (HT_NODE (&d->macs[i])));
- }
- nextd = d->next;
- free (d);
- d = nextd;
- mac_count = ARRAY_SIZE (d->macs);
- }
-
- _cpp_restore_pragma_names (r, data->saved_pragmas);
-
- free (data);
-
- old_state = r->state;
-
- r->state.in_directive = 1;
- r->state.prevent_expansion = 1;
- r->state.angled_headers = 0;
-
- /* Read in the identifiers that must be defined. */
- for (;;)
- {
- cpp_hashnode *h;
-
- if (fread (&m, sizeof (m), 1, f) != 1)
- goto error;
-
- if (m.name_length == 0)
- break;
-
- if (defnlen < m.definition_length + 1)
- {
- defnlen = m.definition_length + 256;
- defn = xrealloc (defn, defnlen);
- }
-
- if (fread (defn, 1, m.definition_length, f) != m.definition_length)
- goto error;
- defn[m.definition_length] = '\n';
-
- h = cpp_lookup (r, defn, m.name_length);
-
- if (h->type == NT_MACRO)
- _cpp_free_definition (h);
- if (m.flags & NODE_POISONED)
- h->flags |= NODE_POISONED | NODE_DIAGNOSTIC;
- else if (m.name_length != m.definition_length)
- {
- if (cpp_push_buffer (r, defn + m.name_length,
- m.definition_length - m.name_length, true)
- != NULL)
- {
- _cpp_clean_line (r);
- if (!_cpp_create_definition (r, h))
- abort ();
- _cpp_pop_buffer (r);
- }
- else
- abort ();
- }
- }
-
- r->state = old_state;
- free (defn);
- defn = NULL;
-
- if (deps_restore (r->deps, f, CPP_OPTION (r, restore_pch_deps) ? name : NULL)
- != 0)
- goto error;
-
- if (! _cpp_read_file_entries (r, f))
- goto error;
-
- return 0;
-
- error:
- cpp_errno (r, CPP_DL_ERROR, "while reading precompiled header");
- return -1;
-}
diff --git a/gcc/cpptrad.c b/gcc/cpptrad.c
deleted file mode 100644
index e2b11cb4115..00000000000
--- a/gcc/cpptrad.c
+++ /dev/null
@@ -1,1110 +0,0 @@
-/* CPP Library - traditional lexical analysis and macro expansion.
- Copyright (C) 2002, 2004 Free Software Foundation, Inc.
- Contributed by Neil Booth, May 2002
-
-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"
-
-/* The replacement text of a function-like macro is stored as a
- contiguous sequence of aligned blocks, each representing the text
- between subsequent parameters.
-
- Each block comprises the text between its surrounding parameters,
- the length of that text, and the one-based index of the following
- parameter. The final block in the replacement text is easily
- recognizable as it has an argument index of zero. */
-
-struct block
-{
- unsigned int text_len;
- unsigned short arg_index;
- uchar text[1];
-};
-
-#define BLOCK_HEADER_LEN offsetof (struct block, text)
-#define BLOCK_LEN(TEXT_LEN) CPP_ALIGN (BLOCK_HEADER_LEN + (TEXT_LEN))
-
-/* Structure holding information about a function-like macro
- invocation. */
-struct fun_macro
-{
- /* Memory buffer holding the trad_arg array. */
- _cpp_buff *buff;
-
- /* An array of size the number of macro parameters + 1, containing
- the offsets of the start of each macro argument in the output
- buffer. The argument continues until the character before the
- start of the next one. */
- size_t *args;
-
- /* The hashnode of the macro. */
- cpp_hashnode *node;
-
- /* The offset of the macro name in the output buffer. */
- size_t offset;
-
- /* The line the macro name appeared on. */
- unsigned int line;
-
- /* Zero-based index of argument being currently lexed. */
- unsigned int argc;
-};
-
-/* Lexing state. It is mostly used to prevent macro expansion. */
-enum ls {ls_none = 0, /* Normal state. */
- ls_fun_open, /* When looking for '('. */
- ls_fun_close, /* When looking for ')'. */
- ls_defined, /* After defined. */
- ls_defined_close, /* Looking for ')' of defined(). */
- ls_hash, /* After # in preprocessor conditional. */
- ls_predicate, /* After the predicate, maybe paren? */
- ls_answer}; /* In answer to predicate. */
-
-/* Lexing TODO: Maybe handle space in escaped newlines. Stop cpplex.c
- from recognizing comments and directives during its lexing pass. */
-
-static const uchar *skip_whitespace (cpp_reader *, const uchar *, int);
-static cpp_hashnode *lex_identifier (cpp_reader *, const uchar *);
-static const uchar *copy_comment (cpp_reader *, const uchar *, int);
-static void check_output_buffer (cpp_reader *, size_t);
-static void push_replacement_text (cpp_reader *, cpp_hashnode *);
-static bool scan_parameters (cpp_reader *, cpp_macro *);
-static bool recursive_macro (cpp_reader *, cpp_hashnode *);
-static void save_replacement_text (cpp_reader *, cpp_macro *, unsigned int);
-static void maybe_start_funlike (cpp_reader *, cpp_hashnode *, const uchar *,
- struct fun_macro *);
-static void save_argument (struct fun_macro *, size_t);
-static void replace_args_and_push (cpp_reader *, struct fun_macro *);
-static size_t canonicalize_text (uchar *, const uchar *, size_t, uchar *);
-
-/* Ensures we have N bytes' space in the output buffer, and
- reallocates it if not. */
-static void
-check_output_buffer (cpp_reader *pfile, size_t n)
-{
- /* We might need two bytes to terminate an unterminated comment, and
- one more to terminate the line with a NUL. */
- n += 2 + 1;
-
- if (n > (size_t) (pfile->out.limit - pfile->out.cur))
- {
- size_t size = pfile->out.cur - pfile->out.base;
- size_t new_size = (size + n) * 3 / 2;
-
- pfile->out.base = xrealloc (pfile->out.base, new_size);
- pfile->out.limit = pfile->out.base + new_size;
- pfile->out.cur = pfile->out.base + size;
- }
-}
-
-/* Skip a C-style block comment in a macro as a result of -CC.
- Buffer->cur points to the initial asterisk of the comment. */
-static void
-skip_macro_block_comment (cpp_reader *pfile)
-{
- const uchar *cur = pfile->buffer->cur;
-
- cur++;
- if (*cur == '/')
- cur++;
-
- /* People like decorating comments with '*', so check for '/'
- instead for efficiency. */
- while(! (*cur++ == '/' && cur[-2] == '*') )
- ;
-
- pfile->buffer->cur = cur;
-}
-
-/* CUR points to the asterisk introducing a comment in the current
- context. IN_DEFINE is true if we are in the replacement text of a
- macro.
-
- The asterisk and following comment is copied to the buffer pointed
- to by pfile->out.cur, which must be of sufficient size.
- Unterminated comments are diagnosed, and correctly terminated in
- the output. pfile->out.cur is updated depending upon IN_DEFINE,
- -C, -CC and pfile->state.in_directive.
-
- Returns a pointer to the first character after the comment in the
- input buffer. */
-static const uchar *
-copy_comment (cpp_reader *pfile, const uchar *cur, int in_define)
-{
- bool unterminated, copy = false;
- source_location src_loc = pfile->line_table->highest_line;
- cpp_buffer *buffer = pfile->buffer;
-
- buffer->cur = cur;
- if (pfile->context->prev)
- unterminated = false, skip_macro_block_comment (pfile);
- else
- unterminated = _cpp_skip_block_comment (pfile);
-
- if (unterminated)
- cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0,
- "unterminated comment");
-
- /* Comments in directives become spaces so that tokens are properly
- separated when the ISO preprocessor re-lexes the line. The
- exception is #define. */
- if (pfile->state.in_directive)
- {
- if (in_define)
- {
- if (CPP_OPTION (pfile, discard_comments_in_macro_exp))
- pfile->out.cur--;
- else
- copy = true;
- }
- else
- pfile->out.cur[-1] = ' ';
- }
- else if (CPP_OPTION (pfile, discard_comments))
- pfile->out.cur--;
- else
- copy = true;
-
- if (copy)
- {
- size_t len = (size_t) (buffer->cur - cur);
- memcpy (pfile->out.cur, cur, len);
- pfile->out.cur += len;
- if (unterminated)
- {
- *pfile->out.cur++ = '*';
- *pfile->out.cur++ = '/';
- }
- }
-
- return buffer->cur;
-}
-
-/* CUR points to any character in the input buffer. Skips over all
- contiguous horizontal white space and NULs, including comments if
- SKIP_COMMENTS, until reaching the first non-horizontal-whitespace
- character or the end of the current context. Escaped newlines are
- removed.
-
- The whitespace is copied verbatim to the output buffer, except that
- comments are handled as described in copy_comment().
- pfile->out.cur is updated.
-
- Returns a pointer to the first character after the whitespace in
- the input buffer. */
-static const uchar *
-skip_whitespace (cpp_reader *pfile, const uchar *cur, int skip_comments)
-{
- uchar *out = pfile->out.cur;
-
- for (;;)
- {
- unsigned int c = *cur++;
- *out++ = c;
-
- if (is_nvspace (c))
- continue;
-
- if (c == '/' && *cur == '*' && skip_comments)
- {
- pfile->out.cur = out;
- cur = copy_comment (pfile, cur, false /* in_define */);
- out = pfile->out.cur;
- continue;
- }
-
- out--;
- break;
- }
-
- pfile->out.cur = out;
- return cur - 1;
-}
-
-/* Lexes and outputs an identifier starting at CUR, which is assumed
- to point to a valid first character of an identifier. Returns
- the hashnode, and updates out.cur. */
-static cpp_hashnode *
-lex_identifier (cpp_reader *pfile, const uchar *cur)
-{
- size_t len;
- uchar *out = pfile->out.cur;
- cpp_hashnode *result;
-
- do
- *out++ = *cur++;
- while (is_numchar (*cur));
-
- CUR (pfile->context) = cur;
- len = out - pfile->out.cur;
- result = (cpp_hashnode *) ht_lookup (pfile->hash_table, pfile->out.cur,
- len, HT_ALLOC);
- pfile->out.cur = out;
- return result;
-}
-
-/* Overlays the true file buffer temporarily with text of length LEN
- starting at START. The true buffer is restored upon calling
- restore_buff(). */
-void
-_cpp_overlay_buffer (cpp_reader *pfile, const uchar *start, size_t len)
-{
- cpp_buffer *buffer = pfile->buffer;
-
- pfile->overlaid_buffer = buffer;
- pfile->saved_cur = buffer->cur;
- pfile->saved_rlimit = buffer->rlimit;
- pfile->saved_line_base = buffer->next_line;
- buffer->need_line = false;
-
- buffer->cur = start;
- buffer->line_base = start;
- buffer->rlimit = start + len;
-}
-
-/* Restores a buffer overlaid by _cpp_overlay_buffer(). */
-void
-_cpp_remove_overlay (cpp_reader *pfile)
-{
- cpp_buffer *buffer = pfile->overlaid_buffer;
-
- buffer->cur = pfile->saved_cur;
- buffer->rlimit = pfile->saved_rlimit;
- buffer->line_base = pfile->saved_line_base;
- buffer->need_line = true;
-
- pfile->overlaid_buffer = NULL;
-}
-
-/* Reads a logical line into the output buffer. Returns TRUE if there
- is more text left in the buffer. */
-bool
-_cpp_read_logical_line_trad (cpp_reader *pfile)
-{
- do
- {
- if (pfile->buffer->need_line && !_cpp_get_fresh_line (pfile))
- return false;
- }
- while (!_cpp_scan_out_logical_line (pfile, NULL) || pfile->state.skipping);
-
- return pfile->buffer != NULL;
-}
-
-/* Set up state for finding the opening '(' of a function-like
- macro. */
-static void
-maybe_start_funlike (cpp_reader *pfile, cpp_hashnode *node, const uchar *start, struct fun_macro *macro)
-{
- unsigned int n = node->value.macro->paramc + 1;
-
- if (macro->buff)
- _cpp_release_buff (pfile, macro->buff);
- macro->buff = _cpp_get_buff (pfile, n * sizeof (size_t));
- macro->args = (size_t *) BUFF_FRONT (macro->buff);
- macro->node = node;
- macro->offset = start - pfile->out.base;
- macro->argc = 0;
-}
-
-/* Save the OFFSET of the start of the next argument to MACRO. */
-static void
-save_argument (struct fun_macro *macro, size_t offset)
-{
- macro->argc++;
- if (macro->argc <= macro->node->value.macro->paramc)
- macro->args[macro->argc] = offset;
-}
-
-/* Copies the next logical line in the current buffer (starting at
- buffer->cur) to the output buffer. The output is guaranteed to
- terminate with a NUL character. buffer->cur is updated.
-
- If MACRO is non-NULL, then we are scanning the replacement list of
- MACRO, and we call save_replacement_text() every time we meet an
- argument. */
-bool
-_cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro)
-{
- bool result = true;
- cpp_context *context;
- const uchar *cur;
- uchar *out;
- struct fun_macro fmacro;
- unsigned int c, paren_depth = 0, quote;
- enum ls lex_state = ls_none;
- bool header_ok;
- const uchar *start_of_input_line;
-
- fmacro.buff = NULL;
-
- quote = 0;
- header_ok = pfile->state.angled_headers;
- CUR (pfile->context) = pfile->buffer->cur;
- RLIMIT (pfile->context) = pfile->buffer->rlimit;
- pfile->out.cur = pfile->out.base;
- pfile->out.first_line = pfile->line_table->highest_line;
- /* start_of_input_line is needed to make sure that directives really,
- really start at the first character of the line. */
- start_of_input_line = pfile->buffer->cur;
- new_context:
- context = pfile->context;
- cur = CUR (context);
- check_output_buffer (pfile, RLIMIT (context) - cur);
- out = pfile->out.cur;
-
- for (;;)
- {
- if (!context->prev
- && cur >= pfile->buffer->notes[pfile->buffer->cur_note].pos)
- {
- pfile->buffer->cur = cur;
- _cpp_process_line_notes (pfile, false);
- }
- c = *cur++;
- *out++ = c;
-
- /* Whitespace should "continue" out of the switch,
- non-whitespace should "break" out of it. */
- switch (c)
- {
- case ' ':
- case '\t':
- case '\f':
- case '\v':
- case '\0':
- continue;
-
- case '\n':
- /* If this is a macro's expansion, pop it. */
- if (context->prev)
- {
- pfile->out.cur = out - 1;
- _cpp_pop_context (pfile);
- goto new_context;
- }
-
- /* Omit the newline from the output buffer. */
- pfile->out.cur = out - 1;
- pfile->buffer->cur = cur;
- pfile->buffer->need_line = true;
- CPP_INCREMENT_LINE (pfile, 0);
-
- if ((lex_state == ls_fun_open || lex_state == ls_fun_close)
- && !pfile->state.in_directive
- && _cpp_get_fresh_line (pfile))
- {
- /* Newlines in arguments become a space, but we don't
- clear any in-progress quote. */
- if (lex_state == ls_fun_close)
- out[-1] = ' ';
- cur = pfile->buffer->cur;
- continue;
- }
- goto done;
-
- case '<':
- if (header_ok)
- quote = '>';
- break;
- case '>':
- if (c == quote)
- quote = 0;
- break;
-
- case '"':
- case '\'':
- if (c == quote)
- quote = 0;
- else if (!quote)
- quote = c;
- break;
-
- case '\\':
- /* Skip escaped quotes here, it's easier than above. */
- if (*cur == '\\' || *cur == '"' || *cur == '\'')
- *out++ = *cur++;
- break;
-
- case '/':
- /* Traditional CPP does not recognize comments within
- literals. */
- if (!quote && *cur == '*')
- {
- pfile->out.cur = out;
- cur = copy_comment (pfile, cur, macro != 0);
- out = pfile->out.cur;
- continue;
- }
- break;
-
- 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':
- if (!pfile->state.skipping && (quote == 0 || macro))
- {
- cpp_hashnode *node;
- uchar *out_start = out - 1;
-
- pfile->out.cur = out_start;
- node = lex_identifier (pfile, cur - 1);
- out = pfile->out.cur;
- cur = CUR (context);
-
- if (node->type == NT_MACRO
- /* Should we expand for ls_answer? */
- && (lex_state == ls_none || lex_state == ls_fun_open)
- && !pfile->state.prevent_expansion)
- {
- /* Macros invalidate MI optimization. */
- pfile->mi_valid = false;
- if (! (node->flags & NODE_BUILTIN)
- && node->value.macro->fun_like)
- {
- maybe_start_funlike (pfile, node, out_start, &fmacro);
- lex_state = ls_fun_open;
- fmacro.line = pfile->line_table->highest_line;
- continue;
- }
- else if (!recursive_macro (pfile, node))
- {
- /* Remove the object-like macro's name from the
- output, and push its replacement text. */
- pfile->out.cur = out_start;
- push_replacement_text (pfile, node);
- lex_state = ls_none;
- goto new_context;
- }
- }
- else if (macro && (node->flags & NODE_MACRO_ARG) != 0)
- {
- /* Found a parameter in the replacement text of a
- #define. Remove its name from the output. */
- pfile->out.cur = out_start;
- save_replacement_text (pfile, macro, node->value.arg_index);
- out = pfile->out.base;
- }
- else if (lex_state == ls_hash)
- {
- lex_state = ls_predicate;
- continue;
- }
- else if (pfile->state.in_expression
- && node == pfile->spec_nodes.n_defined)
- {
- lex_state = ls_defined;
- continue;
- }
- }
- break;
-
- case '(':
- if (quote == 0)
- {
- paren_depth++;
- if (lex_state == ls_fun_open)
- {
- if (recursive_macro (pfile, fmacro.node))
- lex_state = ls_none;
- else
- {
- lex_state = ls_fun_close;
- paren_depth = 1;
- out = pfile->out.base + fmacro.offset;
- fmacro.args[0] = fmacro.offset;
- }
- }
- else if (lex_state == ls_predicate)
- lex_state = ls_answer;
- else if (lex_state == ls_defined)
- lex_state = ls_defined_close;
- }
- break;
-
- case ',':
- if (quote == 0 && lex_state == ls_fun_close && paren_depth == 1)
- save_argument (&fmacro, out - pfile->out.base);
- break;
-
- case ')':
- if (quote == 0)
- {
- paren_depth--;
- if (lex_state == ls_fun_close && paren_depth == 0)
- {
- cpp_macro *m = fmacro.node->value.macro;
-
- m->used = 1;
- lex_state = ls_none;
- save_argument (&fmacro, out - pfile->out.base);
-
- /* A single zero-length argument is no argument. */
- if (fmacro.argc == 1
- && m->paramc == 0
- && out == pfile->out.base + fmacro.offset + 1)
- fmacro.argc = 0;
-
- if (_cpp_arguments_ok (pfile, m, fmacro.node, fmacro.argc))
- {
- /* Remove the macro's invocation from the
- output, and push its replacement text. */
- pfile->out.cur = (pfile->out.base
- + fmacro.offset);
- CUR (context) = cur;
- replace_args_and_push (pfile, &fmacro);
- goto new_context;
- }
- }
- else if (lex_state == ls_answer || lex_state == ls_defined_close)
- lex_state = ls_none;
- }
- break;
-
- case '#':
- if (cur - 1 == start_of_input_line
- /* A '#' from a macro doesn't start a directive. */
- && !pfile->context->prev
- && !pfile->state.in_directive)
- {
- /* A directive. With the way _cpp_handle_directive
- currently works, we only want to call it if either we
- know the directive is OK, or we want it to fail and
- be removed from the output. If we want it to be
- passed through (the assembler case) then we must not
- call _cpp_handle_directive. */
- pfile->out.cur = out;
- cur = skip_whitespace (pfile, cur, true /* skip_comments */);
- out = pfile->out.cur;
-
- if (*cur == '\n')
- {
- /* Null directive. Ignore it and don't invalidate
- the MI optimization. */
- pfile->buffer->need_line = true;
- CPP_INCREMENT_LINE (pfile, 0);
- result = false;
- goto done;
- }
- else
- {
- bool do_it = false;
-
- if (is_numstart (*cur)
- && CPP_OPTION (pfile, lang) != CLK_ASM)
- do_it = true;
- else if (is_idstart (*cur))
- /* Check whether we know this directive, but don't
- advance. */
- do_it = lex_identifier (pfile, cur)->is_directive;
-
- if (do_it || CPP_OPTION (pfile, lang) != CLK_ASM)
- {
- /* This is a kludge. We want to have the ISO
- preprocessor lex the next token. */
- pfile->buffer->cur = cur;
- _cpp_handle_directive (pfile, false /* indented */);
- result = false;
- goto done;
- }
- }
- }
-
- if (pfile->state.in_expression)
- {
- lex_state = ls_hash;
- continue;
- }
- break;
-
- default:
- break;
- }
-
- /* Non-whitespace disables MI optimization and stops treating
- '<' as a quote in #include. */
- header_ok = false;
- if (!pfile->state.in_directive)
- pfile->mi_valid = false;
-
- if (lex_state == ls_none)
- continue;
-
- /* Some of these transitions of state are syntax errors. The
- ISO preprocessor will issue errors later. */
- if (lex_state == ls_fun_open)
- /* Missing '('. */
- lex_state = ls_none;
- else if (lex_state == ls_hash
- || lex_state == ls_predicate
- || lex_state == ls_defined)
- lex_state = ls_none;
-
- /* ls_answer and ls_defined_close keep going until ')'. */
- }
-
- done:
- if (fmacro.buff)
- _cpp_release_buff (pfile, fmacro.buff);
-
- if (lex_state == ls_fun_close)
- cpp_error_with_line (pfile, CPP_DL_ERROR, fmacro.line, 0,
- "unterminated argument list invoking macro \"%s\"",
- NODE_NAME (fmacro.node));
- return result;
-}
-
-/* Push a context holding the replacement text of the macro NODE on
- the context stack. NODE is either object-like, or a function-like
- macro with no arguments. */
-static void
-push_replacement_text (cpp_reader *pfile, cpp_hashnode *node)
-{
- size_t len;
- const uchar *text;
- uchar *buf;
-
- if (node->flags & NODE_BUILTIN)
- {
- text = _cpp_builtin_macro_text (pfile, node);
- len = ustrlen (text);
- buf = _cpp_unaligned_alloc (pfile, len + 1);
- memcpy (buf, text, len);
- buf[len]='\n';
- text = buf;
- }
- else
- {
- cpp_macro *macro = node->value.macro;
- macro->used = 1;
- text = macro->exp.text;
- len = macro->count;
- }
-
- _cpp_push_text_context (pfile, node, text, len);
-}
-
-/* Returns TRUE if traditional macro recursion is detected. */
-static bool
-recursive_macro (cpp_reader *pfile, cpp_hashnode *node)
-{
- bool recursing = !!(node->flags & NODE_DISABLED);
-
- /* Object-like macros that are already expanding are necessarily
- recursive.
-
- However, it is possible to have traditional function-like macros
- that are not infinitely recursive but recurse to any given depth.
- Further, it is easy to construct examples that get ever longer
- until the point they stop recursing. So there is no easy way to
- detect true recursion; instead we assume any expansion more than
- 20 deep since the first invocation of this macro must be
- recursing. */
- if (recursing && node->value.macro->fun_like)
- {
- size_t depth = 0;
- cpp_context *context = pfile->context;
-
- do
- {
- depth++;
- if (context->macro == node && depth > 20)
- break;
- context = context->prev;
- }
- while (context);
- recursing = context != NULL;
- }
-
- if (recursing)
- cpp_error (pfile, CPP_DL_ERROR,
- "detected recursion whilst expanding macro \"%s\"",
- NODE_NAME (node));
-
- return recursing;
-}
-
-/* Return the length of the replacement text of a function-like or
- object-like non-builtin macro. */
-size_t
-_cpp_replacement_text_len (const cpp_macro *macro)
-{
- size_t len;
-
- if (macro->fun_like && (macro->paramc != 0))
- {
- const uchar *exp;
-
- len = 0;
- for (exp = macro->exp.text;;)
- {
- struct block *b = (struct block *) exp;
-
- len += b->text_len;
- if (b->arg_index == 0)
- break;
- len += NODE_LEN (macro->params[b->arg_index - 1]);
- exp += BLOCK_LEN (b->text_len);
- }
- }
- else
- len = macro->count;
-
- return len;
-}
-
-/* Copy the replacement text of MACRO to DEST, which must be of
- sufficient size. It is not NUL-terminated. The next character is
- returned. */
-uchar *
-_cpp_copy_replacement_text (const cpp_macro *macro, uchar *dest)
-{
- if (macro->fun_like && (macro->paramc != 0))
- {
- const uchar *exp;
-
- for (exp = macro->exp.text;;)
- {
- struct block *b = (struct block *) exp;
- cpp_hashnode *param;
-
- memcpy (dest, b->text, b->text_len);
- dest += b->text_len;
- if (b->arg_index == 0)
- break;
- param = macro->params[b->arg_index - 1];
- memcpy (dest, NODE_NAME (param), NODE_LEN (param));
- dest += NODE_LEN (param);
- exp += BLOCK_LEN (b->text_len);
- }
- }
- else
- {
- memcpy (dest, macro->exp.text, macro->count);
- dest += macro->count;
- }
-
- return dest;
-}
-
-/* Push a context holding the replacement text of the macro NODE on
- the context stack. NODE is either object-like, or a function-like
- macro with no arguments. */
-static void
-replace_args_and_push (cpp_reader *pfile, struct fun_macro *fmacro)
-{
- cpp_macro *macro = fmacro->node->value.macro;
-
- if (macro->paramc == 0)
- push_replacement_text (pfile, fmacro->node);
- else
- {
- const uchar *exp;
- uchar *p;
- _cpp_buff *buff;
- size_t len = 0;
-
- /* Calculate the length of the argument-replaced text. */
- for (exp = macro->exp.text;;)
- {
- struct block *b = (struct block *) exp;
-
- len += b->text_len;
- if (b->arg_index == 0)
- break;
- len += (fmacro->args[b->arg_index]
- - fmacro->args[b->arg_index - 1] - 1);
- exp += BLOCK_LEN (b->text_len);
- }
-
- /* Allocate room for the expansion plus \n. */
- buff = _cpp_get_buff (pfile, len + 1);
-
- /* Copy the expansion and replace arguments. */
- p = BUFF_FRONT (buff);
- for (exp = macro->exp.text;;)
- {
- struct block *b = (struct block *) exp;
- size_t arglen;
-
- memcpy (p, b->text, b->text_len);
- p += b->text_len;
- if (b->arg_index == 0)
- break;
- arglen = (fmacro->args[b->arg_index]
- - fmacro->args[b->arg_index - 1] - 1);
- memcpy (p, pfile->out.base + fmacro->args[b->arg_index - 1],
- arglen);
- p += arglen;
- exp += BLOCK_LEN (b->text_len);
- }
-
- /* \n-terminate. */
- *p = '\n';
- _cpp_push_text_context (pfile, fmacro->node, BUFF_FRONT (buff), len);
-
- /* So we free buffer allocation when macro is left. */
- pfile->context->buff = buff;
- }
-}
-
-/* Read and record the parameters, if any, of a function-like macro
- definition. Destroys pfile->out.cur.
-
- Returns true on success, false on failure (syntax error or a
- duplicate parameter). On success, CUR (pfile->context) is just
- past the closing parenthesis. */
-static bool
-scan_parameters (cpp_reader *pfile, cpp_macro *macro)
-{
- const uchar *cur = CUR (pfile->context) + 1;
- bool ok;
-
- for (;;)
- {
- cur = skip_whitespace (pfile, cur, true /* skip_comments */);
-
- if (is_idstart (*cur))
- {
- ok = false;
- if (_cpp_save_parameter (pfile, macro, lex_identifier (pfile, cur)))
- break;
- cur = skip_whitespace (pfile, CUR (pfile->context),
- true /* skip_comments */);
- if (*cur == ',')
- {
- cur++;
- continue;
- }
- ok = (*cur == ')');
- break;
- }
-
- ok = (*cur == ')' && macro->paramc == 0);
- break;
- }
-
- if (!ok)
- cpp_error (pfile, CPP_DL_ERROR, "syntax error in macro parameter list");
-
- CUR (pfile->context) = cur + (*cur == ')');
-
- return ok;
-}
-
-/* Save the text from pfile->out.base to pfile->out.cur as
- the replacement text for the current macro, followed by argument
- ARG_INDEX, with zero indicating the end of the replacement
- text. */
-static void
-save_replacement_text (cpp_reader *pfile, cpp_macro *macro,
- unsigned int arg_index)
-{
- size_t len = pfile->out.cur - pfile->out.base;
- uchar *exp;
-
- if (macro->paramc == 0)
- {
- /* Object-like and function-like macros without parameters
- simply store their \n-terminated replacement text. */
- exp = _cpp_unaligned_alloc (pfile, len + 1);
- memcpy (exp, pfile->out.base, len);
- exp[len] = '\n';
- macro->exp.text = exp;
- macro->count = len;
- }
- else
- {
- /* Store the text's length (unsigned int), the argument index
- (unsigned short, base 1) and then the text. */
- size_t blen = BLOCK_LEN (len);
- struct block *block;
-
- if (macro->count + blen > BUFF_ROOM (pfile->a_buff))
- _cpp_extend_buff (pfile, &pfile->a_buff, macro->count + blen);
-
- exp = BUFF_FRONT (pfile->a_buff);
- block = (struct block *) (exp + macro->count);
- macro->exp.text = exp;
-
- /* Write out the block information. */
- block->text_len = len;
- block->arg_index = arg_index;
- memcpy (block->text, pfile->out.base, len);
-
- /* Lex the rest into the start of the output buffer. */
- pfile->out.cur = pfile->out.base;
-
- macro->count += blen;
-
- /* If we've finished, commit the memory. */
- if (arg_index == 0)
- BUFF_FRONT (pfile->a_buff) += macro->count;
- }
-}
-
-/* Analyze and save the replacement text of a macro. Returns true on
- success. */
-bool
-_cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro)
-{
- const uchar *cur;
- uchar *limit;
- cpp_context *context = pfile->context;
-
- /* The context has not been set up for command line defines, and CUR
- has not been updated for the macro name for in-file defines. */
- pfile->out.cur = pfile->out.base;
- CUR (context) = pfile->buffer->cur;
- RLIMIT (context) = pfile->buffer->rlimit;
- check_output_buffer (pfile, RLIMIT (context) - CUR (context));
-
- /* Is this a function-like macro? */
- if (* CUR (context) == '(')
- {
- bool ok = scan_parameters (pfile, macro);
-
- /* Remember the params so we can clear NODE_MACRO_ARG flags. */
- macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
-
- /* Setting macro to NULL indicates an error occurred, and
- prevents unnecessary work in _cpp_scan_out_logical_line. */
- if (!ok)
- macro = NULL;
- else
- {
- BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc];
- macro->fun_like = 1;
- }
- }
-
- /* Skip leading whitespace in the replacement text. */
- pfile->buffer->cur
- = skip_whitespace (pfile, CUR (context),
- CPP_OPTION (pfile, discard_comments_in_macro_exp));
-
- pfile->state.prevent_expansion++;
- _cpp_scan_out_logical_line (pfile, macro);
- pfile->state.prevent_expansion--;
-
- if (!macro)
- return false;
-
- /* Skip trailing white space. */
- cur = pfile->out.base;
- limit = pfile->out.cur;
- while (limit > cur && is_space (limit[-1]))
- limit--;
- pfile->out.cur = limit;
- save_replacement_text (pfile, macro, 0);
-
- return true;
-}
-
-/* Copy SRC of length LEN to DEST, but convert all contiguous
- whitespace to a single space, provided it is not in quotes. The
- quote currently in effect is pointed to by PQUOTE, and is updated
- by the function. Returns the number of bytes copied. */
-static size_t
-canonicalize_text (uchar *dest, const uchar *src, size_t len, uchar *pquote)
-{
- uchar *orig_dest = dest;
- uchar quote = *pquote;
-
- while (len)
- {
- if (is_space (*src) && !quote)
- {
- do
- src++, len--;
- while (len && is_space (*src));
- *dest++ = ' ';
- }
- else
- {
- if (*src == '\'' || *src == '"')
- {
- if (!quote)
- quote = *src;
- else if (quote == *src)
- quote = 0;
- }
- *dest++ = *src++, len--;
- }
- }
-
- *pquote = quote;
- return dest - orig_dest;
-}
-
-/* Returns true if MACRO1 and MACRO2 have expansions different other
- than in the form of their whitespace. */
-bool
-_cpp_expansions_different_trad (const cpp_macro *macro1,
- const cpp_macro *macro2)
-{
- uchar *p1 = xmalloc (macro1->count + macro2->count);
- uchar *p2 = p1 + macro1->count;
- uchar quote1 = 0, quote2 = 0;
- bool mismatch;
- size_t len1, len2;
-
- if (macro1->paramc > 0)
- {
- const uchar *exp1 = macro1->exp.text, *exp2 = macro2->exp.text;
-
- mismatch = true;
- for (;;)
- {
- struct block *b1 = (struct block *) exp1;
- struct block *b2 = (struct block *) exp2;
-
- if (b1->arg_index != b2->arg_index)
- break;
-
- len1 = canonicalize_text (p1, b1->text, b1->text_len, &quote1);
- len2 = canonicalize_text (p2, b2->text, b2->text_len, &quote2);
- if (len1 != len2 || memcmp (p1, p2, len1))
- break;
- if (b1->arg_index == 0)
- {
- mismatch = false;
- break;
- }
- exp1 += BLOCK_LEN (b1->text_len);
- exp2 += BLOCK_LEN (b2->text_len);
- }
- }
- else
- {
- len1 = canonicalize_text (p1, macro1->exp.text, macro1->count, &quote1);
- len2 = canonicalize_text (p2, macro2->exp.text, macro2->count, &quote2);
- mismatch = (len1 != len2 || memcmp (p1, p2, len1));
- }
-
- free (p1);
- return mismatch;
-}
diff --git a/gcc/cppucnid.h b/gcc/cppucnid.h
deleted file mode 100644
index 1cac7df0a94..00000000000
--- a/gcc/cppucnid.h
+++ /dev/null
@@ -1,336 +0,0 @@
-/* Table of UCNs which are valid in identifiers.
- Copyright (C) 2003 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. */
-
-/* Automatically generated from cppucnid.tab, do not edit */
-
-/* This file reproduces the table in ISO/IEC 9899:1999 (C99) Annex
- D, which is itself a reproduction from ISO/IEC TR 10176:1998, and
- the similar table from ISO/IEC 14882:1988 (C++98) Annex E, which is
- a reproduction of ISO/IEC PDTR 10176. Unfortunately these tables
- are not identical. */
-
-#ifndef CPPUCNID_H
-#define CPPUCNID_H
-
-#define C99 1
-#define CXX 2
-#define DIG 4
-
-struct ucnrange
-{
- unsigned short lo, hi;
- unsigned short flags;
-};
-
-static const struct ucnrange ucnranges[] = {
- { 0x00aa, 0x00aa, C99 }, /* Latin */
- { 0x00b5, 0x00b5, C99 }, /* Special characters */
- { 0x00b7, 0x00b7, C99 },
- { 0x00ba, 0x00ba, C99 }, /* Latin */
- { 0x00c0, 0x00d6, CXX|C99 },
- { 0x00d8, 0x00f6, CXX|C99 },
- { 0x00f8, 0x01f5, CXX|C99 },
- { 0x01fa, 0x0217, CXX|C99 },
- { 0x0250, 0x02a8, CXX|C99 },
- { 0x02b0, 0x02b8, C99 }, /* Special characters */
- { 0x02bb, 0x02bb, C99 },
- { 0x02bd, 0x02c1, C99 },
- { 0x02d0, 0x02d1, C99 },
- { 0x02e0, 0x02e4, C99 },
- { 0x037a, 0x037a, C99 },
- { 0x0384, 0x0384, CXX }, /* Greek */
- { 0x0386, 0x0386, C99 },
- { 0x0388, 0x038a, CXX|C99 },
- { 0x038c, 0x038c, CXX|C99 },
- { 0x038e, 0x03a1, CXX|C99 },
- { 0x03a3, 0x03ce, CXX|C99 },
- { 0x03d0, 0x03d6, CXX|C99 },
- { 0x03da, 0x03da, CXX|C99 },
- { 0x03dc, 0x03dc, CXX|C99 },
- { 0x03de, 0x03de, CXX|C99 },
- { 0x03e0, 0x03e0, CXX|C99 },
- { 0x03e2, 0x03f3, CXX|C99 },
- { 0x0401, 0x040c, CXX|C99 }, /* Cyrillic */
- { 0x040d, 0x040d, CXX },
- { 0x040e, 0x040e, C99 },
- { 0x040f, 0x044f, CXX|C99 },
- { 0x0451, 0x045c, CXX|C99 },
- { 0x045e, 0x0481, CXX|C99 },
- { 0x0490, 0x04c4, CXX|C99 },
- { 0x04c7, 0x04c8, CXX|C99 },
- { 0x04cb, 0x04cc, CXX|C99 },
- { 0x04d0, 0x04eb, CXX|C99 },
- { 0x04ee, 0x04f5, CXX|C99 },
- { 0x04f8, 0x04f9, CXX|C99 },
- { 0x0531, 0x0556, CXX|C99 }, /* Armenian */
- { 0x0559, 0x0559, C99 }, /* Special characters */
- { 0x0561, 0x0587, CXX|C99 }, /* Armenian */
- { 0x05b0, 0x05b9, C99 }, /* Hebrew */
- { 0x05bb, 0x05bd, C99 },
- { 0x05bf, 0x05bf, C99 },
- { 0x05c1, 0x05c2, C99 },
- { 0x05d0, 0x05ea, CXX|C99 },
- { 0x05f0, 0x05f2, CXX|C99 },
- { 0x05f3, 0x05f4, CXX },
- { 0x0621, 0x063a, CXX|C99 }, /* Arabic */
- { 0x0640, 0x0652, CXX|C99 },
- { 0x0660, 0x0669, C99|DIG }, /* Digits */
- { 0x0670, 0x06b7, CXX|C99 }, /* Arabic */
- { 0x06ba, 0x06be, CXX|C99 },
- { 0x06c0, 0x06ce, CXX|C99 },
- { 0x06d0, 0x06dc, C99 },
- { 0x06e5, 0x06e7, CXX|C99 },
- { 0x06e8, 0x06e8, C99 },
- { 0x06ea, 0x06ed, C99 },
- { 0x06f0, 0x06f9, C99|DIG }, /* Digits */
- { 0x0901, 0x0903, C99 }, /* Devanagari */
- { 0x0905, 0x0939, CXX|C99 },
- { 0x093d, 0x093d, C99 }, /* Special characters */
- { 0x093e, 0x094d, C99 }, /* Devanagari */
- { 0x0950, 0x0952, C99 },
- { 0x0958, 0x0962, CXX|C99 },
- { 0x0963, 0x0963, C99 },
- { 0x0966, 0x096f, C99|DIG }, /* Digits */
- { 0x0981, 0x0983, C99 }, /* Bengali */
- { 0x0985, 0x098c, CXX|C99 },
- { 0x098f, 0x0990, CXX|C99 },
- { 0x0993, 0x09a8, CXX|C99 },
- { 0x09aa, 0x09b0, CXX|C99 },
- { 0x09b2, 0x09b2, CXX|C99 },
- { 0x09b6, 0x09b9, CXX|C99 },
- { 0x09be, 0x09c4, C99 },
- { 0x09c7, 0x09c8, C99 },
- { 0x09cb, 0x09cd, C99 },
- { 0x09dc, 0x09dd, CXX|C99 },
- { 0x09df, 0x09e1, CXX|C99 },
- { 0x09e2, 0x09e3, C99 },
- { 0x09e6, 0x09ef, C99|DIG }, /* Digits */
- { 0x09f0, 0x09f1, CXX|C99 }, /* Bengali */
- { 0x0a02, 0x0a02, C99 }, /* Gurmukhi */
- { 0x0a05, 0x0a0a, CXX|C99 },
- { 0x0a0f, 0x0a10, CXX|C99 },
- { 0x0a13, 0x0a28, CXX|C99 },
- { 0x0a2a, 0x0a30, CXX|C99 },
- { 0x0a32, 0x0a33, CXX|C99 },
- { 0x0a35, 0x0a36, CXX|C99 },
- { 0x0a38, 0x0a39, CXX|C99 },
- { 0x0a3e, 0x0a42, C99 },
- { 0x0a47, 0x0a48, C99 },
- { 0x0a4b, 0x0a4d, C99 },
- { 0x0a59, 0x0a5c, CXX|C99 },
- { 0x0a5e, 0x0a5e, CXX|C99 },
- { 0x0a66, 0x0a6f, C99|DIG }, /* Digits */
- { 0x0a74, 0x0a74, C99 }, /* Gurmukhi */
- { 0x0a81, 0x0a83, C99 }, /* Gujarati */
- { 0x0a85, 0x0a8b, CXX|C99 },
- { 0x0a8d, 0x0a8d, CXX|C99 },
- { 0x0a8f, 0x0a91, CXX|C99 },
- { 0x0a93, 0x0aa8, CXX|C99 },
- { 0x0aaa, 0x0ab0, CXX|C99 },
- { 0x0ab2, 0x0ab3, CXX|C99 },
- { 0x0ab5, 0x0ab9, CXX|C99 },
- { 0x0abd, 0x0ac5, C99 },
- { 0x0ac7, 0x0ac9, C99 },
- { 0x0acb, 0x0acd, C99 },
- { 0x0ad0, 0x0ad0, C99 },
- { 0x0ae0, 0x0ae0, CXX|C99 },
- { 0x0ae6, 0x0aef, C99|DIG }, /* Digits */
- { 0x0b01, 0x0b03, C99 }, /* Oriya */
- { 0x0b05, 0x0b0c, CXX|C99 },
- { 0x0b0f, 0x0b10, CXX|C99 },
- { 0x0b13, 0x0b28, CXX|C99 },
- { 0x0b2a, 0x0b30, CXX|C99 },
- { 0x0b32, 0x0b33, CXX|C99 },
- { 0x0b36, 0x0b39, CXX|C99 },
- { 0x0b3d, 0x0b3d, C99 }, /* Special characters */
- { 0x0b3e, 0x0b43, C99 }, /* Oriya */
- { 0x0b47, 0x0b48, C99 },
- { 0x0b4b, 0x0b4d, C99 },
- { 0x0b5c, 0x0b5d, CXX|C99 },
- { 0x0b5f, 0x0b61, CXX|C99 },
- { 0x0b66, 0x0b6f, C99|DIG }, /* Digits */
- { 0x0b82, 0x0b83, C99 }, /* Tamil */
- { 0x0b85, 0x0b8a, CXX|C99 },
- { 0x0b8e, 0x0b90, CXX|C99 },
- { 0x0b92, 0x0b95, CXX|C99 },
- { 0x0b99, 0x0b9a, CXX|C99 },
- { 0x0b9c, 0x0b9c, CXX|C99 },
- { 0x0b9e, 0x0b9f, CXX|C99 },
- { 0x0ba3, 0x0ba4, CXX|C99 },
- { 0x0ba8, 0x0baa, CXX|C99 },
- { 0x0bae, 0x0bb5, CXX|C99 },
- { 0x0bb7, 0x0bb9, CXX|C99 },
- { 0x0bbe, 0x0bc2, C99 },
- { 0x0bc6, 0x0bc8, C99 },
- { 0x0bca, 0x0bcd, C99 },
- { 0x0be7, 0x0bef, C99|DIG }, /* Digits */
- { 0x0c01, 0x0c03, C99 }, /* Telugu */
- { 0x0c05, 0x0c0c, CXX|C99 },
- { 0x0c0e, 0x0c10, CXX|C99 },
- { 0x0c12, 0x0c28, CXX|C99 },
- { 0x0c2a, 0x0c33, CXX|C99 },
- { 0x0c35, 0x0c39, CXX|C99 },
- { 0x0c3e, 0x0c44, C99 },
- { 0x0c46, 0x0c48, C99 },
- { 0x0c4a, 0x0c4d, C99 },
- { 0x0c60, 0x0c61, CXX|C99 },
- { 0x0c66, 0x0c6f, C99|DIG }, /* Digits */
- { 0x0c82, 0x0c83, C99 }, /* Kannada */
- { 0x0c85, 0x0c8c, CXX|C99 },
- { 0x0c8e, 0x0c90, CXX|C99 },
- { 0x0c92, 0x0ca8, CXX|C99 },
- { 0x0caa, 0x0cb3, CXX|C99 },
- { 0x0cb5, 0x0cb9, CXX|C99 },
- { 0x0cbe, 0x0cc4, C99 },
- { 0x0cc6, 0x0cc8, C99 },
- { 0x0cca, 0x0ccd, C99 },
- { 0x0cde, 0x0cde, C99 },
- { 0x0ce0, 0x0ce1, CXX|C99 },
- { 0x0ce6, 0x0cef, C99|DIG }, /* Digits */
- { 0x0d02, 0x0d03, C99 }, /* Malayalam */
- { 0x0d05, 0x0d0c, CXX|C99 },
- { 0x0d0e, 0x0d10, CXX|C99 },
- { 0x0d12, 0x0d28, CXX|C99 },
- { 0x0d2a, 0x0d39, CXX|C99 },
- { 0x0d3e, 0x0d43, C99 },
- { 0x0d46, 0x0d48, C99 },
- { 0x0d4a, 0x0d4d, C99 },
- { 0x0d60, 0x0d61, CXX|C99 },
- { 0x0d66, 0x0d6f, C99|DIG }, /* Digits */
- { 0x0e01, 0x0e30, CXX|C99 }, /* Thai */
- { 0x0e31, 0x0e31, C99 },
- { 0x0e32, 0x0e33, CXX|C99 },
- { 0x0e34, 0x0e3a, C99 },
- { 0x0e40, 0x0e46, CXX|C99 },
- { 0x0e47, 0x0e49, C99 },
- { 0x0e50, 0x0e59, CXX|C99|DIG }, /* Digits */
- { 0x0e5a, 0x0e5b, CXX|C99 }, /* Thai */
- { 0x0e81, 0x0e82, CXX|C99 }, /* Lao */
- { 0x0e84, 0x0e84, CXX|C99 },
- { 0x0e87, 0x0e88, CXX|C99 },
- { 0x0e8a, 0x0e8a, CXX|C99 },
- { 0x0e8d, 0x0e8d, CXX|C99 },
- { 0x0e94, 0x0e97, CXX|C99 },
- { 0x0e99, 0x0e9f, CXX|C99 },
- { 0x0ea1, 0x0ea3, CXX|C99 },
- { 0x0ea5, 0x0ea5, CXX|C99 },
- { 0x0ea7, 0x0ea7, CXX|C99 },
- { 0x0eaa, 0x0eab, CXX|C99 },
- { 0x0ead, 0x0eae, CXX|C99 },
- { 0x0eaf, 0x0eaf, CXX },
- { 0x0eb0, 0x0eb0, CXX|C99 },
- { 0x0eb1, 0x0eb1, C99 },
- { 0x0eb2, 0x0eb3, CXX|C99 },
- { 0x0eb4, 0x0eb9, C99 },
- { 0x0ebb, 0x0ebc, C99 },
- { 0x0ebd, 0x0ebd, CXX|C99 },
- { 0x0ec0, 0x0ec4, CXX|C99 },
- { 0x0ec6, 0x0ec6, CXX|C99 },
- { 0x0ec8, 0x0ecd, C99 },
- { 0x0ed0, 0x0ed9, C99|DIG }, /* Digits */
- { 0x0edc, 0x0edd, C99 }, /* Lao */
- { 0x0f00, 0x0f00, C99 }, /* Tibetan */
- { 0x0f18, 0x0f19, C99 },
- { 0x0f20, 0x0f33, C99|DIG }, /* Digits */
- { 0x0f35, 0x0f35, C99 }, /* Tibetan */
- { 0x0f37, 0x0f37, C99 },
- { 0x0f39, 0x0f39, C99 },
- { 0x0f3e, 0x0f47, C99 },
- { 0x0f49, 0x0f69, C99 },
- { 0x0f71, 0x0f84, C99 },
- { 0x0f86, 0x0f8b, C99 },
- { 0x0f90, 0x0f95, C99 },
- { 0x0f97, 0x0f97, C99 },
- { 0x0f99, 0x0fad, C99 },
- { 0x0fb1, 0x0fb7, C99 },
- { 0x0fb9, 0x0fb9, C99 },
- { 0x10a0, 0x10c5, CXX|C99 }, /* Georgian */
- { 0x10d0, 0x10f6, CXX|C99 },
- { 0x1100, 0x1159, CXX }, /* Hangul */
- { 0x1161, 0x11a2, CXX },
- { 0x11a8, 0x11f9, CXX },
- { 0x1e00, 0x1e9a, CXX|C99 }, /* Latin */
- { 0x1e9b, 0x1e9b, C99 },
- { 0x1ea0, 0x1ef9, CXX|C99 },
- { 0x1f00, 0x1f15, CXX|C99 }, /* Greek */
- { 0x1f18, 0x1f1d, CXX|C99 },
- { 0x1f20, 0x1f45, CXX|C99 },
- { 0x1f48, 0x1f4d, CXX|C99 },
- { 0x1f50, 0x1f57, CXX|C99 },
- { 0x1f59, 0x1f59, CXX|C99 },
- { 0x1f5b, 0x1f5b, CXX|C99 },
- { 0x1f5d, 0x1f5d, CXX|C99 },
- { 0x1f5f, 0x1f7d, CXX|C99 },
- { 0x1f80, 0x1fb4, CXX|C99 },
- { 0x1fb6, 0x1fbc, CXX|C99 },
- { 0x1fbe, 0x1fbe, C99 }, /* Special characters */
- { 0x1fc2, 0x1fc4, CXX|C99 }, /* Greek */
- { 0x1fc6, 0x1fcc, CXX|C99 },
- { 0x1fd0, 0x1fd3, CXX|C99 },
- { 0x1fd6, 0x1fdb, CXX|C99 },
- { 0x1fe0, 0x1fec, CXX|C99 },
- { 0x1ff2, 0x1ff4, CXX|C99 },
- { 0x1ff6, 0x1ffc, CXX|C99 },
- { 0x203f, 0x2040, C99 }, /* Special characters */
- { 0x207f, 0x207f, C99 }, /* Latin */
- { 0x2102, 0x2102, C99 }, /* Special characters */
- { 0x2107, 0x2107, C99 },
- { 0x210a, 0x2113, C99 },
- { 0x2115, 0x2115, C99 },
- { 0x2118, 0x211d, C99 },
- { 0x2124, 0x2124, C99 },
- { 0x2126, 0x2126, C99 },
- { 0x2128, 0x2128, C99 },
- { 0x212a, 0x2131, C99 },
- { 0x2133, 0x2138, C99 },
- { 0x2160, 0x2182, C99 },
- { 0x3005, 0x3007, C99 },
- { 0x3021, 0x3029, C99 },
- { 0x3041, 0x3093, CXX|C99 }, /* Hiragana */
- { 0x3094, 0x3094, CXX },
- { 0x309b, 0x309c, CXX|C99 },
- { 0x309d, 0x309e, CXX },
- { 0x30a1, 0x30f6, CXX|C99 }, /* Katakana */
- { 0x30f7, 0x30fa, CXX },
- { 0x30fb, 0x30fc, CXX|C99 },
- { 0x30fd, 0x30fe, CXX },
- { 0x3105, 0x312c, CXX|C99 }, /* Bopomofo */
- { 0x4e00, 0x9fa5, CXX|C99 }, /* CJK Unified Ideographs */
- { 0xac00, 0xd7a3, C99 }, /* Hangul */
- { 0xf900, 0xfa2d, CXX }, /* CJK Unified Ideographs */
- { 0xfb1f, 0xfb36, CXX },
- { 0xfb38, 0xfb3c, CXX },
- { 0xfb3e, 0xfb3e, CXX },
- { 0xfb40, 0xfb44, CXX },
- { 0xfb46, 0xfbb1, CXX },
- { 0xfbd3, 0xfd3f, CXX },
- { 0xfd50, 0xfd8f, CXX },
- { 0xfd92, 0xfdc7, CXX },
- { 0xfdf0, 0xfdfb, CXX },
- { 0xfe70, 0xfe72, CXX },
- { 0xfe74, 0xfe74, CXX },
- { 0xfe76, 0xfefc, CXX },
- { 0xff21, 0xff3a, CXX },
- { 0xff41, 0xff5a, CXX },
- { 0xff66, 0xffbe, CXX },
- { 0xffc2, 0xffc7, CXX },
- { 0xffca, 0xffcf, CXX },
- { 0xffd2, 0xffd7, CXX },
- { 0xffda, 0xffdc, CXX },
-};
-
-#endif /* cppucnid.h */
diff --git a/gcc/cppucnid.pl b/gcc/cppucnid.pl
deleted file mode 100644
index eb8bbcac627..00000000000
--- a/gcc/cppucnid.pl
+++ /dev/null
@@ -1,130 +0,0 @@
-#! /usr/bin/perl -w
-use strict;
-
-# Convert cppucnid.tab to cppucnid.h. We use two arrays of length
-# 65536 to represent the table, since this is nice and simple. The
-# first array holds the tags indicating which ranges are valid in
-# which contexts. The second array holds the language name associated
-# with each element.
-
-our(@tags, @names);
-@tags = ("") x 65536;
-@names = ("") x 65536;
-
-
-# Array mapping tag numbers to standard #defines
-our @stds;
-
-# Current standard and language
-our($curstd, $curlang);
-
-# First block of the file is a template to be saved for later.
-our @template;
-
-while (<>) {
- chomp;
- last if $_ eq '%%';
- push @template, $_;
-};
-
-# Second block of the file is the UCN tables.
-# The format looks like this:
-#
-# [std]
-#
-# ; language
-# xxxx-xxxx xxxx xxxx-xxxx ....
-#
-# with comment lines starting with #.
-
-while (<>) {
- chomp;
- /^#/ and next;
- /^\s*$/ and next;
- /^\[(.+)\]$/ and do {
- $curstd = $1;
- next;
- };
- /^; (.+)$/ and do {
- $curlang = $1;
- next;
- };
-
- process_range(split);
-}
-
-# Print out the template, inserting as requested.
-$\ = "\n";
-for (@template) {
- print("/* Automatically generated from cppucnid.tab, do not edit */"),
- next if $_ eq "[dne]";
- print_table(), next if $_ eq "[table]";
- print;
-}
-
-sub print_table {
- my($lo, $hi);
- my $prevname = "";
-
- for ($lo = 0; $lo <= $#tags; $lo = $hi) {
- $hi = $lo;
- $hi++ while $hi <= $#tags
- && $tags[$hi] eq $tags[$lo]
- && $names[$hi] eq $names[$lo];
-
- # Range from $lo to $hi-1.
- # Don't make entries for ranges that are not valid idchars.
- next if ($tags[$lo] eq "");
- my $tag = $tags[$lo];
- $tag = " ".$tag if $tag =~ /^C99/;
-
- if ($names[$lo] eq $prevname) {
- printf(" { 0x%04x, 0x%04x, %-11s },\n",
- $lo, $hi-1, $tag);
- } else {
- printf(" { 0x%04x, 0x%04x, %-11s }, /* %s */\n",
- $lo, $hi-1, $tag, $names[$lo]);
- }
- $prevname = $names[$lo];
- }
-}
-
-# The line is a list of four-digit hexadecimal numbers or
-# pairs of such numbers. Each is a valid identifier character
-# from the given language, under the given standard.
-sub process_range {
- for my $range (@_) {
- if ($range =~ /^[0-9a-f]{4}$/) {
- my $i = hex($range);
- if ($tags[$i] eq "") {
- $tags[$i] = $curstd;
- } else {
- $tags[$i] = $curstd . "|" . $tags[$i];
- }
- if ($names[$i] ne "" && $names[$i] ne $curlang) {
- warn sprintf ("language overlap: %s/%s at %x (tag %d)",
- $names[$i], $curlang, $i, $tags[$i]);
- next;
- }
- $names[$i] = $curlang;
- } elsif ($range =~ /^ ([0-9a-f]{4}) - ([0-9a-f]{4}) $/x) {
- my ($start, $end) = (hex($1), hex($2));
- my $i;
- for ($i = $start; $i <= $end; $i++) {
- if ($tags[$i] eq "") {
- $tags[$i] = $curstd;
- } else {
- $tags[$i] = $curstd . "|" . $tags[$i];
- }
- if ($names[$i] ne "" && $names[$i] ne $curlang) {
- warn sprintf ("language overlap: %s/%s at %x (tag %d)",
- $names[$i], $curlang, $i, $tags[$i]);
- next;
- }
- $names[$i] = $curlang;
- }
- } else {
- warn "malformed range expression $range";
- }
- }
-}
diff --git a/gcc/cppucnid.tab b/gcc/cppucnid.tab
deleted file mode 100644
index 4a7a0f4094c..00000000000
--- a/gcc/cppucnid.tab
+++ /dev/null
@@ -1,239 +0,0 @@
-/* Table of UCNs which are valid in identifiers.
- Copyright (C) 2003 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. */
-
-[dne]
-
-/* This file reproduces the table in ISO/IEC 9899:1999 (C99) Annex
- D, which is itself a reproduction from ISO/IEC TR 10176:1998, and
- the similar table from ISO/IEC 14882:1988 (C++98) Annex E, which is
- a reproduction of ISO/IEC PDTR 10176. Unfortunately these tables
- are not identical. */
-
-#ifndef CPPUCNID_H
-#define CPPUCNID_H
-
-#define C99 1
-#define CXX 2
-#define DIG 4
-
-struct ucnrange
-{
- unsigned short lo, hi;
- unsigned short flags;
-};
-
-static const struct ucnrange ucnranges[] = {
-[table]
-};
-
-#endif /* cppucnid.h */
-%%
-
-[C99]
-
-; Latin
-00aa 00ba 00c0-00d6 00d8-00f6 00f8-01f5 01fa-0217 0250-02a8 1e00-1e9b
-1ea0-1ef9 207f
-
-; Greek
-0386 0388-038a 038c 038e-03a1 03a3-03ce 03d0-03d6 03da 03dc 03de 03e0
-03e2-03f3 1f00-1f15 1f18-1f1d 1f20-1f45 1f48-1f4d 1f50-1f57 1f59 1f5b
-1f5d 1f5f-1f7d 1f80-1fb4 1fb6-1fbc 1fc2-1fc4 1fc6-1fcc 1fd0-1fd3
-1fd6-1fdb 1fe0-1fec 1ff2-1ff4 1ff6-1ffc
-
-; Cyrillic
-0401-040c 040e-044f 0451-045c 045e-0481 0490-04c4 04c7-04c8 04cb-04cc
-04d0-04eb 04ee-04f5 04f8-04f9
-
-; Armenian
-0531-0556 0561-0587
-
-; Hebrew
-05b0-05b9 05bb-05bd 05bf 05c1-05c2 05d0-05ea 05f0-05f2
-
-; Arabic
-0621-063a 0640-0652 0670-06b7 06ba-06be 06c0-06ce 06d0-06dc 06e5-06e8
-06ea-06ed
-
-; Devanagari
-0901-0903 0905-0939 093e-094d 0950-0952 0958-0963
-
-; Bengali
-0981-0983 0985-098c 098f-0990 0993-09a8 09aa-09b0 09b2 09b6-09b9
-09be-09c4 09c7-09c8 09cb-09cd 09dc-09dd 09df-09e3 09f0-09f1
-
-; Gurmukhi
-0a02 0a05-0a0a 0a0f-0a10 0a13-0a28 0a2a-0a30 0a32-0a33 0a35-0a36
-0a38-0a39 0a3e-0a42 0a47-0a48 0a4b-0a4d 0a59-0a5c 0a5e 0a74
-
-; Gujarati
-0a81-0a83 0a85-0a8b 0a8d 0a8f-0a91 0a93-0aa8 0aaa-0ab0 0ab2-0ab3
-0ab5-0ab9 0abd-0ac5 0ac7-0ac9 0acb-0acd 0ad0 0ae0
-
-; Oriya
-0b01-0b03 0b05-0b0c 0b0f-0b10 0b13-0b28 0b2a-0b30 0b32-0b33 0b36-0b39
-0b3e-0b43 0b47-0b48 0b4b-0b4d 0b5c-0b5d 0b5f-0b61
-
-; Tamil
-0b82-0b83 0b85-0b8a 0b8e-0b90 0b92-0b95 0b99-0b9a 0b9c 0b9e-0b9f
-0ba3-0ba4 0ba8-0baa 0bae-0bb5 0bb7-0bb9 0bbe-0bc2 0bc6-0bc8 0bca-0bcd
-
-; Telugu
-0c01-0c03 0c05-0c0c 0c0e-0c10 0c12-0c28 0c2a-0c33 0c35-0c39 0c3e-0c44
-0c46-0c48 0c4a-0c4d 0c60-0c61
-
-; Kannada
-0c82-0c83 0c85-0c8c 0c8e-0c90 0c92-0ca8 0caa-0cb3 0cb5-0cb9 0cbe-0cc4
-0cc6-0cc8 0cca-0ccd 0cde 0ce0-0ce1
-
-; Malayalam
-0d02-0d03 0d05-0d0c 0d0e-0d10 0d12-0d28 0d2a-0d39 0d3e-0d43 0d46-0d48
-0d4a-0d4d 0d60-0d61
-
-# CORRECTION: exclude 0e50-0e59 from the Thai range as it also appears
-# in the Digits range below.
-; Thai
-0e01-0e3a 0e40-0e49 0e5a-0e5b
-
-; Lao
-0e81-0e82 0e84 0e87-0e88 0e8a 0e8d 0e94-0e97 0e99-0e9f 0ea1-0ea3 0ea5
-0ea7 0eaa-0eab 0ead-0eae 0eb0-0eb9 0ebb-0ebd 0ec0-0ec4 0ec6 0ec8-0ecd
-0edc-0edd
-
-; Tibetan
-0f00 0f18-0f19 0f35 0f37 0f39 0f3e-0f47 0f49-0f69 0f71-0f84 0f86-0f8b
-0f90-0f95 0f97 0f99-0fad 0fb1-0fb7 0fb9
-
-; Georgian
-10a0-10c5 10d0-10f6
-
-; Hiragana
-3041-3093 309b-309c
-
-; Katakana
-30a1-30f6 30fb-30fc
-
-; Bopomofo
-3105-312c
-
-; CJK Unified Ideographs
-4e00-9fa5
-
-; Hangul
-ac00-d7a3
-
-; Special characters
-00b5 00b7 02b0-02b8 02bb 02bd-02c1 02d0-02d1 02e0-02e4 037a 0559 093d
-0b3d 1fbe 203f-2040 2102 2107 210a-2113 2115 2118-211d 2124 2126 2128
-212a-2131 2133-2138 2160-2182 3005-3007 3021-3029
-
-[C99|DIG]
-; Digits
-0660-0669 06f0-06f9 0966-096f 09e6-09ef 0a66-0a6f 0ae6-0aef 0b66-0b6f
-0be7-0bef 0c66-0c6f 0ce6-0cef 0d66-0d6f 0e50-0e59 0ed0-0ed9 0f20-0f33
-
-[CXX]
-
-; Latin
-00c0-00d6 00d8-00f6 00f8-01f5 01fa-0217 0250-02a8 1e00-1e9a 1ea0-1ef9
-
-; Greek
-0384 0388-038a 038c 038e-03a1 03a3-03ce 03d0-03d6 03da 03dc 03de 03e0
-03e2-03f3 1f00-1f15 1f18-1f1d 1f20-1f45 1f48-1f4d 1f50-1f57 1f59 1f5b
-1f5d 1f5f-1f7d 1f80-1fb4 1fb6-1fbc 1fc2-1fc4 1fc6-1fcc 1fd0-1fd3
-1fd6-1fdb 1fe0-1fec 1ff2-1ff4 1ff6-1ffc
-
-; Cyrillic
-0401-040d 040f-044f 0451-045c 045e-0481 0490-04c4 04c7-04c8 04cb-04cc
-04d0-04eb 04ee-04f5 04f8-04f9
-
-; Armenian
-0531-0556 0561-0587
-
-; Hebrew
-05d0-05ea 05f0-05f4
-
-; Arabic
-0621-063a 0640-0652 0670-06b7 06ba-06be 06c0-06ce 06e5-06e7
-
-; Devanagari
-0905-0939 0958-0962
-
-; Bengali
-0985-098c 098f-0990 0993-09a8 09aa-09b0 09b2 09b6-09b9 09dc-09dd
-09df-09e1 09f0-09f1
-
-; Gurmukhi
-0a05-0a0a 0a0f-0a10 0a13-0a28 0a2a-0a30 0a32-0a33 0a35-0a36 0a38-0a39
-0a59-0a5c 0a5e
-
-; Gujarati
-0a85-0a8b 0a8d 0a8f-0a91 0a93-0aa8 0aaa-0ab0 0ab2-0ab3 0ab5-0ab9 0ae0
-
-; Oriya
-0b05-0b0c 0b0f-0b10 0b13-0b28 0b2a-0b30 0b32-0b33 0b36-0b39 0b5c-0b5d
-0b5f-0b61
-
-; Tamil
-0b85-0b8a 0b8e-0b90 0b92-0b95 0b99-0b9a 0b9c 0b9e-0b9f 0ba3-0ba4
-0ba8-0baa 0bae-0bb5 0bb7-0bb9
-
-; Telugu
-0c05-0c0c 0c0e-0c10 0c12-0c28 0c2a-0c33 0c35-0c39 0c60-0c61
-
-; Kannada
-0c85-0c8c 0c8e-0c90 0c92-0ca8 0caa-0cb3 0cb5-0cb9 0ce0-0ce1
-
-; Malayalam
-0d05-0d0c 0d0e-0d10 0d12-0d28 0d2a-0d39 0d60-0d61
-
-# CORRECTION: Exclude 0e50-0e59 from the Thai range and make a fake
-# Digits range for it, to match C99. cppcharset.c knows that C++
-# doesn't distinguish digits from other UCNs valid in identifiers.
-; Thai
-0e01-0e30 0e32-0e33 0e40-0e46 0e4f-0e49 0e5a-0e5b
-
-; Digits
-0e50-0e59
-
-# CORRECTION: Change 0e0d to 0e8d (typo in standard; see C++ DR 131)
-; Lao
-0e81-0e82 0e84 0e87-0e88 0e8a 0e8d 0e94-0e97 0e99-0e9f 0ea1-0ea3 0ea5
-0ea7 0eaa-0eab 0ead-0eb0 0eb2 0eb3 0ebd 0ec0-0ec4 0ec6
-
-; Georgian
-10a0-10c5 10d0-10f6
-
-; Hiragana
-3041-3094 309b-309e
-
-; Katakana
-30a1-30fe
-
-# CORRECTION: language spelled "Bopmofo" in C++98.
-; Bopomofo
-3105-312c
-
-; Hangul
-1100-1159 1161-11a2 11a8-11f9
-
-; CJK Unified Ideographs
-f900-fa2d fb1f-fb36 fb38-fb3c fb3e fb40-fb41 fb42-fb44 fb46-fbb1
-fbd3-fd3f fd50-fd8f fd92-fdc7 fdf0-fdfb fe70-fe72 fe74 fe76-fefc
-ff21-ff3a ff41-ff5a ff66-ffbe ffc2-ffc7 ffca-ffcf ffd2-ffd7
-ffda-ffdc 4e00-9fa5
-
diff --git a/gcc/hashtable.c b/gcc/hashtable.c
deleted file mode 100644
index 58f19d055fc..00000000000
--- a/gcc/hashtable.c
+++ /dev/null
@@ -1,310 +0,0 @@
-/* Hash tables.
- Copyright (C) 2000, 2001, 2003 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 (const unsigned char *, size_t);
-static void ht_expand (hash_table *);
-static double approx_sqrt (double);
-
-/* Calculate the hash of the string STR of length LEN. */
-
-static unsigned int
-calc_hash (const unsigned char *str, size_t len)
-{
- size_t 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 (unsigned int order)
-{
- unsigned int nslots = 1 << order;
- hash_table *table;
-
- table = xcalloc (1, sizeof (hash_table));
-
- /* Strings need no alignment. */
- _obstack_begin (&table->stack, 0, 0,
- (void *(*) (long)) xmalloc,
- (void (*) (void *)) free);
-
- obstack_alignment_mask (&table->stack) = 0;
-
- table->entries = xcalloc (nslots, sizeof (hashnode));
- table->nslots = nslots;
- return table;
-}
-
-/* Frees all memory associated with a hash table. */
-
-void
-ht_destroy (hash_table *table)
-{
- obstack_free (&table->stack, NULL);
- free (table->entries);
- free (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 (hash_table *table, const unsigned char *str, size_t 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;
- table->searches++;
-
- node = table->entries[index];
-
- if (node != NULL)
- {
- if (node->hash_value == hash
- && HT_LEN (node) == (unsigned int) 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, (void *) str);
- return node;
- }
-
- /* hash2 must be odd, so we're guaranteed to visit every possible
- location in the table during rehashing. */
- hash2 = ((hash * 17) & sizemask) | 1;
-
- for (;;)
- {
- table->collisions++;
- index = (index + hash2) & sizemask;
- node = table->entries[index];
- if (node == NULL)
- break;
-
- if (node->hash_value == hash
- && HT_LEN (node) == (unsigned int) 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, (void *) str);
- return node;
- }
- }
- }
-
- if (insert == HT_NO_INSERT)
- return NULL;
-
- node = (*table->alloc_node) (table);
- table->entries[index] = node;
-
- HT_LEN (node) = (unsigned int) len;
- node->hash_value = hash;
- if (insert == HT_ALLOC)
- HT_STR (node) = obstack_copy0 (&table->stack, str, len);
- 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 (hash_table *table)
-{
- hashnode *nentries, *p, *limit;
- unsigned int size, sizemask;
-
- size = table->nslots * 2;
- nentries = xcalloc (size, sizeof (hashnode));
- sizemask = size - 1;
-
- p = table->entries;
- limit = p + table->nslots;
- do
- if (*p)
- {
- unsigned int index, hash, hash2;
-
- hash = (*p)->hash_value;
- index = hash & sizemask;
-
- if (nentries[index])
- {
- hash2 = ((hash * 17) & sizemask) | 1;
- do
- {
- index = (index + hash2) & sizemask;
- }
- while (nentries[index]);
- }
- nentries[index] = *p;
- }
- 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 (hash_table *table, ht_cb cb, const void *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 (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. */
-static double
-approx_sqrt (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/gcc/hashtable.h b/gcc/hashtable.h
deleted file mode 100644
index 8efbf5c50e2..00000000000
--- a/gcc/hashtable.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* Hash tables.
- Copyright (C) 2000, 2001, 2003 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"
-#define GTY(x) /* nothing */
-
-/* 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 GTY(())
-{
- const unsigned char *str;
- unsigned int len;
- unsigned int hash_value;
-};
-
-#define HT_LEN(NODE) ((NODE)->len)
-#define HT_STR(NODE) ((NODE)->str)
-
-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) (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;
-};
-
-/* Initialize the hashtable with 2 ^ order entries. */
-extern hash_table *ht_create (unsigned int order);
-
-/* Frees all memory associated with a hash table. */
-extern void ht_destroy (hash_table *);
-
-extern hashnode ht_lookup (hash_table *, const unsigned char *,
- size_t, 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) (struct cpp_reader *, hashnode, const void *);
-extern void ht_forall (hash_table *, ht_cb, const void *);
-
-/* Dump allocation statistics to stderr. */
-extern void ht_dump_statistics (hash_table *);
-
-#endif /* GCC_HASHTABLE_H */
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index c63678023ac..2b6ada67561 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,7 @@
+2004-05-23 Paolo Bonzini <bonzini@gnu.org>
+
+ * Make-lang.in: Link in $(LIBCPP) instead of mkdeps.o.
+
2004-05-21 Mark Wielaard <mark@klomp.org>
* gjavah.c (print_stub_or_jni): Mark functions only JNIEXPORT, not
diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in
index 367627362dc..84b3d568ec6 100644
--- a/gcc/java/Make-lang.in
+++ b/gcc/java/Make-lang.in
@@ -105,16 +105,16 @@ JAVA_OBJS = java/parse.o java/class.o java/decl.o java/expr.o \
java/zextract.o java/jcf-io.o java/win32-host.o java/jcf-parse.o java/mangle.o \
java/mangle_name.o java/builtins.o java/resource.o \
java/jcf-write.o java/buffer.o java/check-init.o java/jcf-depend.o \
- java/jcf-path.o java/xref.o java/boehm.o java/java-gimplify.o mkdeps.o
+ java/jcf-path.o java/xref.o java/boehm.o java/java-gimplify.o
GCJH_OBJS = java/gjavah.o java/jcf-io.o java/jcf-depend.o java/jcf-path.o \
- java/win32-host.o java/zextract.o version.o mkdeps.o errors.o ggc-none.o \
+ java/win32-host.o java/zextract.o version.o errors.o ggc-none.o \
intl.o
JVSCAN_OBJS = java/parse-scan.o java/jv-scan.o version.o intl.o
JCFDUMP_OBJS = java/jcf-dump.o java/jcf-io.o java/jcf-depend.o java/jcf-path.o \
- java/win32-host.o java/zextract.o errors.o version.o mkdeps.o ggc-none.o intl.o
+ java/win32-host.o java/zextract.o errors.o version.o ggc-none.o intl.o
JVGENMAIN_OBJS = java/jvgenmain.o java/mangle_name.o errors.o intl.o
@@ -130,7 +130,7 @@ jc1$(exeext): $(JAVA_OBJS) $(BACKEND) $(LIBDEPS)
gcjh$(exeext): $(GCJH_OBJS) $(LIBDEPS)
rm -f $@
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(GCJH_OBJS) $(ZLIB) $(LIBS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(GCJH_OBJS) $(CPPLIBS) $(ZLIB) $(LIBS)
jv-scan$(exeext): $(JVSCAN_OBJS) $(LIBDEPS)
rm -f $@
@@ -139,7 +139,7 @@ jv-scan$(exeext): $(JVSCAN_OBJS) $(LIBDEPS)
jcf-dump$(exeext): $(JCFDUMP_OBJS) $(LIBDEPS)
rm -f $@
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(JCFDUMP_OBJS) \
- $(ZLIB) $(LDEXP_LIB) $(LIBS)
+ $(CPPLIBS) $(ZLIB) $(LDEXP_LIB) $(LIBS)
jvgenmain$(exeext): $(JVGENMAIN_OBJS) $(LIBDEPS)
rm -f $@
diff --git a/gcc/line-map.c b/gcc/line-map.c
deleted file mode 100644
index e7d41b652e0..00000000000
--- a/gcc/line-map.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/* Map logical line numbers to (source file, line number) pairs.
- Copyright (C) 2001, 2003, 2004
- 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 "line-map.h"
-#include "intl.h"
-
-static void trace_include (const struct line_maps *, const struct line_map *);
-
-/* Initialize a line map set. */
-
-void
-linemap_init (struct line_maps *set)
-{
- set->maps = NULL;
- set->allocated = 0;
- set->used = 0;
- set->last_listed = -1;
- set->trace_includes = false;
- set->depth = 0;
- set->cache = 0;
- set->highest_location = 0;
- set->highest_line = 0;
- set->max_column_hint = 0;
-}
-
-/* Check for and warn about line_maps entered but not exited. */
-
-void
-linemap_check_files_exited (struct line_maps *set)
-{
- struct line_map *map;
- /* Depending upon whether we are handling preprocessed input or
- not, this can be a user error or an ICE. */
- for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map);
- map = INCLUDED_FROM (set, map))
- fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
- map->to_file);
-}
-
-/* Free a line map set. */
-
-void
-linemap_free (struct line_maps *set)
-{
- if (set->maps)
- {
- linemap_check_files_exited (set);
-
- free (set->maps);
- }
-}
-
-/* Add a mapping of logical source line to physical source file and
- line number.
-
- The text pointed to by TO_FILE must have a lifetime
- at least as long as the final call to lookup_line (). An empty
- TO_FILE means standard input. If reason is LC_LEAVE, and
- TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their
- natural values considering the file we are returning to.
-
- FROM_LINE should be monotonic increasing across calls to this
- function. A call to this function can relocate the previous set of
- A call to this function can relocate the previous set of
- maps, so any stored line_map pointers should not be used. */
-
-const struct line_map *
-linemap_add (struct line_maps *set, enum lc_reason reason,
- unsigned int sysp, const char *to_file, unsigned int to_line)
-{
- struct line_map *map;
- source_location start_location = set->highest_location + 1;
-
- if (set->used && start_location < set->maps[set->used - 1].start_location)
- abort ();
-
- if (set->used == set->allocated)
- {
- set->allocated = 2 * set->allocated + 256;
- set->maps = xrealloc (set->maps, set->allocated * sizeof (struct line_map));
- }
-
- map = &set->maps[set->used];
-
- if (to_file && *to_file == '\0')
- to_file = "<stdin>";
-
- /* If we don't keep our line maps consistent, we can easily
- segfault. Don't rely on the client to do it for us. */
- if (set->depth == 0)
- reason = LC_ENTER;
- else if (reason == LC_LEAVE)
- {
- struct line_map *from;
- bool error;
-
- if (MAIN_FILE_P (map - 1))
- {
- if (to_file == NULL)
- {
- set->depth--;
- return NULL;
- }
- error = true;
- reason = LC_RENAME;
- from = map - 1;
- }
- else
- {
- from = INCLUDED_FROM (set, map - 1);
- error = to_file && strcmp (from->to_file, to_file);
- }
-
- /* Depending upon whether we are handling preprocessed input or
- not, this can be a user error or an ICE. */
- if (error)
- fprintf (stderr, "line-map.c: file \"%s\" left but not entered\n",
- to_file);
-
- /* A TO_FILE of NULL is special - we use the natural values. */
- if (error || to_file == NULL)
- {
- to_file = from->to_file;
- to_line = SOURCE_LINE (from, from[1].start_location);
- sysp = from->sysp;
- }
- }
-
- map->reason = reason;
- map->sysp = sysp;
- map->start_location = start_location;
- map->to_file = to_file;
- map->to_line = to_line;
- set->cache = set->used++;
- map->column_bits = 0;
- set->highest_location = start_location;
- set->highest_line = start_location;
- set->max_column_hint = 0;
-
- if (reason == LC_ENTER)
- {
- map->included_from = set->depth == 0 ? -1 : (int) (set->used - 2);
- set->depth++;
- if (set->trace_includes)
- trace_include (set, map);
- }
- else if (reason == LC_RENAME)
- map->included_from = map[-1].included_from;
- else if (reason == LC_LEAVE)
- {
- set->depth--;
- map->included_from = INCLUDED_FROM (set, map - 1)->included_from;
- }
-
- return map;
-}
-
-source_location
-linemap_line_start (struct line_maps *set, unsigned int to_line,
- unsigned int max_column_hint)
-{
- struct line_map *map = &set->maps[set->used - 1];
- source_location highest = set->highest_location;
- source_location r;
- unsigned int last_line = SOURCE_LINE (map, set->highest_line);
- int line_delta = to_line - last_line;
- bool add_map = false;
- if (line_delta < 0
- || (line_delta > 10 && line_delta * map->column_bits > 1000)
- || (max_column_hint >= (1U << map->column_bits))
- || (max_column_hint <= 80 && map->column_bits >= 10))
- {
- add_map = true;
- }
- else
- max_column_hint = set->max_column_hint;
- if (add_map)
- {
- int column_bits;
- if (max_column_hint > 100000 || highest > 0xC0000000)
- {
- max_column_hint = 0;
- if (highest >0xF0000000)
- return 0;
- column_bits = 0;
- }
- else
- {
- column_bits = 7;
- while (max_column_hint >= (1U << column_bits))
- column_bits++;
- max_column_hint = 1U << column_bits;
- }
- if (line_delta < 0
- || last_line != map->to_line
- || SOURCE_COLUMN (map, highest) >= (1U << column_bits))
- map = (struct line_map*) linemap_add (set, LC_RENAME, map->sysp,
- map->to_file, to_line);
- map->column_bits = column_bits;
- r = map->start_location;
- }
- else
- r = highest - SOURCE_COLUMN (map, highest)
- + (line_delta << map->column_bits);
- set->highest_line = r;
- if (r > set->highest_location)
- set->highest_location = r;
- set->max_column_hint = max_column_hint;
- return r;
-}
-
-source_location
-linemap_position_for_column (struct line_maps *set, unsigned int to_column)
-{
- source_location r = set->highest_line;
- if (to_column >= set->max_column_hint)
- {
- if (r >= 0xC000000 || to_column > 100000)
- {
- /* Running low on source_locations - disable column numbers. */
- return r;
- }
- else
- {
- struct line_map *map = &set->maps[set->used - 1];
- r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50);
- }
- }
- r = r + to_column;
- if (r >= set->highest_location)
- set->highest_location = r;
- return r;
-}
-
-/* Given a logical line, returns the map from which the corresponding
- (source file, line) pair can be deduced. Since the set is built
- chronologically, the logical lines are monotonic increasing, and so
- the list is sorted and we can use a binary search. */
-
-const struct line_map *
-linemap_lookup (struct line_maps *set, source_location line)
-{
- unsigned int md, mn, mx;
- const struct line_map *cached;
-
- mn = set->cache;
- mx = set->used;
-
- cached = &set->maps[mn];
- /* We should get a segfault if no line_maps have been added yet. */
- if (line >= cached->start_location)
- {
- if (mn + 1 == mx || line < cached[1].start_location)
- return cached;
- }
- else
- {
- mx = mn;
- mn = 0;
- }
-
- while (mx - mn > 1)
- {
- md = (mn + mx) / 2;
- if (set->maps[md].start_location > line)
- mx = md;
- else
- mn = md;
- }
-
- set->cache = mn;
- return &set->maps[mn];
-}
-
-/* Print the file names and line numbers of the #include commands
- which led to the map MAP, if any, to stderr. Nothing is output if
- the most recently listed stack is the same as the current one. */
-
-void
-linemap_print_containing_files (struct line_maps *set,
- const struct line_map *map)
-{
- if (MAIN_FILE_P (map) || set->last_listed == map->included_from)
- return;
-
- set->last_listed = map->included_from;
- map = INCLUDED_FROM (set, map);
-
- fprintf (stderr, _("In file included from %s:%u"),
- map->to_file, LAST_SOURCE_LINE (map));
-
- while (! MAIN_FILE_P (map))
- {
- map = INCLUDED_FROM (set, map);
- /* 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"),
- map->to_file, LAST_SOURCE_LINE (map));
- }
-
- fputs (":\n", stderr);
-}
-
-/* Print an include trace, for e.g. the -H option of the preprocessor. */
-
-static void
-trace_include (const struct line_maps *set, const struct line_map *map)
-{
- unsigned int i = set->depth;
-
- while (--i)
- putc ('.', stderr);
- fprintf (stderr, " %s\n", map->to_file);
-}
diff --git a/gcc/line-map.h b/gcc/line-map.h
deleted file mode 100644
index 73631be229f..00000000000
--- a/gcc/line-map.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/* Map logical line numbers to (source file, line number) pairs.
- Copyright (C) 2001, 2003, 2004
- 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! */
-
-#ifndef GCC_LINE_MAP_H
-#define GCC_LINE_MAP_H
-
-/* Reason for adding a line change with add_line_map (). LC_ENTER is
- when including a new file, e.g. a #include directive in C.
- LC_LEAVE is when reaching a file's end. LC_RENAME is when a file
- name or line number changes for neither of the above reasons
- (e.g. a #line directive in C). */
-enum lc_reason {LC_ENTER = 0, LC_LEAVE, LC_RENAME};
-
-/* A logical line/column number, i.e. an "index" into a line_map. */
-/* Long-term, we want to use this to replace struct location_s (in input.h),
- and effectively typedef source_location location_t. */
-typedef unsigned int source_location;
-typedef source_location fileline; /* deprecated name */
-
-/* Physical source file TO_FILE at line TO_LINE at column 0 is represented
- by the logical START_LOCATION. TO_LINE+L at column C is represented by
- START_LOCATION+(L*(1<<column_bits))+C, as long as C<(1<<column_bits),
- and the result_location is less than the next line_map's start_location.
- (The top line is line 1 and the leftmost column is column 1; line/column 0
- means "entire file/line" or "unknown line/column" or "not applicable".)
- INCLUDED_FROM is an index into the set that gives the line mapping
- at whose end the current one was included. File(s) at the bottom
- of the include stack have this set to -1. REASON is the reason for
- creation of this line map, SYSP is one for a system header, two for
- a C system header file that therefore needs to be extern "C"
- protected in C++, and zero otherwise. */
-struct line_map
-{
- const char *to_file;
- unsigned int to_line;
- source_location start_location;
- int included_from;
- ENUM_BITFIELD (lc_reason) reason : CHAR_BIT;
- /* The sysp field isn't really needed now that it's in cpp_buffer. */
- unsigned char sysp;
- /* Number of the low-order source_location bits used for a column number. */
- unsigned int column_bits : 8;
-};
-
-/* A set of chronological line_map structures. */
-struct line_maps
-{
- struct line_map *maps;
- unsigned int allocated;
- unsigned int used;
-
- unsigned int cache;
-
- /* The most recently listed include stack, if any, starts with
- LAST_LISTED as the topmost including file. -1 indicates nothing
- has been listed yet. */
- int last_listed;
-
- /* Depth of the include stack, including the current file. */
- unsigned int depth;
-
- /* If true, prints an include trace a la -H. */
- bool trace_includes;
-
- /* Highest source_location "given out". */
- source_location highest_location;
-
- /* Start of line of highest source_location "given out". */
- source_location highest_line;
-
- /* The maximum column number we can quickly allocate. Higher numbers
- may require allocating a new line_map. */
- unsigned int max_column_hint;
-};
-
-/* Initialize a line map set. */
-extern void linemap_init (struct line_maps *);
-
-/* Free a line map set. */
-extern void linemap_free (struct line_maps *);
-
-/* Check for and warn about line_maps entered but not exited. */
-
-extern void linemap_check_files_exited (struct line_maps *);
-
-/* Return a source_location for the start (i.e. column==0) of
- (physical) line TO_LINE in the current source file (as in the
- most recent linemap_add). MAX_COLUMN_HINT is the highest column
- number we expect to use in this line (but it does not change
- the highest_location). */
-
-extern source_location linemap_line_start
-(struct line_maps *, unsigned int, unsigned int);
-
-/* Add a mapping of logical source line to physical source file and
- line number.
-
- The text pointed to by TO_FILE must have a lifetime
- at least as long as the final call to lookup_line (). An empty
- TO_FILE means standard input. If reason is LC_LEAVE, and
- TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their
- natural values considering the file we are returning to.
-
- START_LOCATION should be monotonic increasing across calls to this
- function. A call to this function can relocate the previous set of
- maps, so any stored line_map pointers should not be used. */
-extern const struct line_map *linemap_add
- (struct line_maps *, enum lc_reason, unsigned int sysp,
- const char *to_file, unsigned int to_line);
-
-/* Given a logical line, returns the map from which the corresponding
- (source file, line) pair can be deduced. */
-extern const struct line_map *linemap_lookup
- (struct line_maps *, source_location);
-
-/* Print the file names and line numbers of the #include commands
- which led to the map MAP, if any, to stderr. Nothing is output if
- the most recently listed stack is the same as the current one. */
-extern void linemap_print_containing_files (struct line_maps *,
- const struct line_map *);
-
-/* Converts a map and a source_location to source line. */
-#define SOURCE_LINE(MAP, LINE) \
- ((((LINE) - (MAP)->start_location) >> (MAP)->column_bits) + (MAP)->to_line)
-
-#define SOURCE_COLUMN(MAP, LINE) \
- (((LINE) - (MAP)->start_location) & ((1 << (MAP)->column_bits) - 1))
-
-/* Returns the last source line within a map. This is the (last) line
- of the #include, or other directive, that caused a map change. */
-#define LAST_SOURCE_LINE(MAP) \
- SOURCE_LINE (MAP, LAST_SOURCE_LINE_LOCATION (MAP))
-#define LAST_SOURCE_LINE_LOCATION(MAP) \
- ((((MAP)[1].start_location - 1 - (MAP)->start_location) \
- & ~((1 << (MAP)->column_bits) - 1)) \
- + (MAP)->start_location)
-
-/* Returns the map a given map was included from. */
-#define INCLUDED_FROM(SET, MAP) (&(SET)->maps[(MAP)->included_from])
-
-/* Nonzero if the map is at the bottom of the include stack. */
-#define MAIN_FILE_P(MAP) ((MAP)->included_from < 0)
-
-/* Set LOC to a source position that is the same line as the most recent
- linemap_line_start, but with the specified TO_COLUMN column number. */
-
-#define LINEMAP_POSITION_FOR_COLUMN(LOC, SET, TO_COLUMN) { \
- unsigned int to_column = (TO_COLUMN); \
- struct line_maps *set = (SET); \
- if (__builtin_expect (to_column >= set->max_column_hint, 0)) \
- (LOC) = linemap_position_for_column (set, to_column); \
- else { \
- source_location r = set->highest_line; \
- r = r + to_column; \
- if (r >= set->highest_location) \
- set->highest_location = r; \
- (LOC) = r; \
- }}
-
-
-extern source_location
-linemap_position_for_column (struct line_maps *set, unsigned int to_column);
-#endif /* !GCC_LINE_MAP_H */
diff --git a/gcc/mkdeps.c b/gcc/mkdeps.c
deleted file mode 100644
index 23af9d83f78..00000000000
--- a/gcc/mkdeps.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/* Dependency generator for Makefile fragments.
- Copyright (C) 2000, 2001, 2003 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 (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 (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 (void)
-{
- struct deps *d = 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 (struct deps *d)
-{
- unsigned int i;
-
- if (d->targetv)
- {
- for (i = 0; i < d->ntargets; i++)
- free ((void *) d->targetv[i]);
- free (d->targetv);
- }
-
- if (d->depv)
- {
- for (i = 0; i < d->ndeps; i++)
- free ((void *) 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 (struct deps *d, const char *t, int quote)
-{
- if (d->ntargets == d->targets_size)
- {
- d->targets_size = d->targets_size * 2 + 4;
- d->targetv = 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 (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
- const char *start = lbasename (tgt);
- char *o = 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 (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 = xrealloc (d->depv, d->deps_size * sizeof (const char *));
- }
- d->depv[d->ndeps++] = t;
-}
-
-void
-deps_write (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 (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);
- }
-}
-
-/* Write out a deps buffer to a file, in a form that can be read back
- with deps_restore. Returns nonzero on error, in which case the
- error number will be in errno. */
-
-int
-deps_save (struct deps *deps, FILE *f)
-{
- unsigned int i;
-
- /* The cppreader structure contains makefile dependences. Write out this
- structure. */
-
- /* The number of dependences. */
- if (fwrite (&deps->ndeps, sizeof (deps->ndeps), 1, f) != 1)
- return -1;
- /* The length of each dependence followed by the string. */
- for (i = 0; i < deps->ndeps; i++)
- {
- size_t num_to_write = strlen (deps->depv[i]);
- if (fwrite (&num_to_write, sizeof (size_t), 1, f) != 1)
- return -1;
- if (fwrite (deps->depv[i], num_to_write, 1, f) != 1)
- return -1;
- }
-
- return 0;
-}
-
-/* Read back dependency information written with deps_save into
- the deps buffer. The third argument may be NULL, in which case
- the dependency information is just skipped, or it may be a filename,
- in which case that filename is skipped. */
-
-int
-deps_restore (struct deps *deps, FILE *fd, const char *self)
-{
- unsigned int i, count;
- size_t num_to_read;
- size_t buf_size = 512;
- char *buf = xmalloc (buf_size);
-
- /* Number of dependences. */
- if (fread (&count, 1, sizeof (count), fd) != sizeof (count))
- return -1;
-
- /* The length of each dependence string, followed by the string. */
- for (i = 0; i < count; i++)
- {
- /* Read in # bytes in string. */
- if (fread (&num_to_read, 1, sizeof (size_t), fd) != sizeof (size_t))
- return -1;
- if (buf_size < num_to_read + 1)
- {
- buf_size = num_to_read + 1 + 127;
- buf = xrealloc (buf, buf_size);
- }
- if (fread (buf, 1, num_to_read, fd) != num_to_read)
- return -1;
- buf[num_to_read] = '\0';
-
- /* Generate makefile dependencies from .pch if -nopch-deps. */
- if (self != NULL && strcmp (buf, self) != 0)
- deps_add_dep (deps, buf);
- }
-
- free (buf);
- return 0;
-}
diff --git a/gcc/mkdeps.h b/gcc/mkdeps.h
deleted file mode 100644
index 745ba1f5041..00000000000
--- a/gcc/mkdeps.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Dependency generator for Makefile fragments.
- Copyright (C) 2000, 2001, 2003 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 (void);
-
-/* Destroy a deps buffer. */
-extern void deps_free (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 (struct deps *, const char *, int);
-
-/* Sets the default target if none has been given already. An empty
- string as the default target is interpreted as stdin. */
-extern void deps_add_default_target (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 (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 (const struct deps *, FILE *, unsigned int);
-
-/* Write out a deps buffer to a file, in a form that can be read back
- with deps_restore. Returns nonzero on error, in which case the
- error number will be in errno. */
-extern int deps_save (struct deps *, FILE *);
-
-/* Read back dependency information written with deps_save into
- the deps buffer. The third argument may be NULL, in which case
- the dependency information is just skipped, or it may be a filename,
- in which case that filename is skipped. */
-extern int deps_restore (struct deps *, FILE *, const char *);
-
-/* 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 (const struct deps *, FILE *);
-
-#endif /* ! GCC_MKDEPS_H */
diff --git a/gcc/stringpool.c b/gcc/stringpool.c
index 0cf3be14f88..3592d4e36a4 100644
--- a/gcc/stringpool.c
+++ b/gcc/stringpool.c
@@ -22,7 +22,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
allocated by ggc_alloc_string are stored in an obstack which is
never shrunk. Identifiers are uniquely stored in a hash table.
- We have our own private hash table implementation. libiberty's
+ We use cpplib's hash table implementation. libiberty's
hashtab.c is not used because it requires 100% average space
overhead per string, which is unacceptable. Also, this algorithm
is faster. */
@@ -33,7 +33,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tm.h"
#include "ggc.h"
#include "tree.h"
-#include "hashtable.h"
+#include "symtab.h"
#include "cpplib.h"
/* The "" allocated string. */
diff --git a/gcc/system.h b/gcc/system.h
index 53754660f58..58b2bf7caa0 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -421,16 +421,6 @@ extern int snprintf (char *, size_t, const char *, ...);
# 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
diff --git a/gcc/tree.h b/gcc/tree.h
index f667a7974a0..1bf3cd24ced 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -957,7 +957,7 @@ struct tree_vector GTY(())
tree elements;
};
-#include "hashtable.h"
+#include "symtab.h"
/* Define fields and accessors for some special-purpose tree nodes. */