diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 38 | ||||
-rw-r--r-- | gcc/Makefile.in | 67 | ||||
-rw-r--r-- | gcc/aclocal.m4 | 36 | ||||
-rw-r--r-- | gcc/c-ppoutput.c | 2 | ||||
-rw-r--r-- | gcc/configure.ac | 18 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/Make-lang.in | 4 | ||||
-rw-r--r-- | gcc/cppcharset.c | 1411 | ||||
-rw-r--r-- | gcc/cpperror.c | 183 | ||||
-rw-r--r-- | gcc/cppexp.c | 1540 | ||||
-rw-r--r-- | gcc/cppfiles.c | 1565 | ||||
-rw-r--r-- | gcc/cpphash.c | 118 | ||||
-rw-r--r-- | gcc/cpphash.h | 651 | ||||
-rw-r--r-- | gcc/cppinit.c | 627 | ||||
-rw-r--r-- | gcc/cpplex.c | 1544 | ||||
-rw-r--r-- | gcc/cpplib.c | 1987 | ||||
-rw-r--r-- | gcc/cpplib.h | 773 | ||||
-rw-r--r-- | gcc/cppmacro.c | 1729 | ||||
-rw-r--r-- | gcc/cpppch.c | 724 | ||||
-rw-r--r-- | gcc/cpptrad.c | 1110 | ||||
-rw-r--r-- | gcc/cppucnid.h | 336 | ||||
-rw-r--r-- | gcc/cppucnid.pl | 130 | ||||
-rw-r--r-- | gcc/cppucnid.tab | 239 | ||||
-rw-r--r-- | gcc/hashtable.c | 310 | ||||
-rw-r--r-- | gcc/hashtable.h | 81 | ||||
-rw-r--r-- | gcc/java/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/java/Make-lang.in | 10 | ||||
-rw-r--r-- | gcc/line-map.c | 345 | ||||
-rw-r--r-- | gcc/line-map.h | 182 | ||||
-rw-r--r-- | gcc/mkdeps.c | 345 | ||||
-rw-r--r-- | gcc/mkdeps.h | 72 | ||||
-rw-r--r-- | gcc/stringpool.c | 4 | ||||
-rw-r--r-- | gcc/system.h | 10 | ||||
-rw-r--r-- | gcc/tree.h | 2 |
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 (¯o1->exp.tokens[i], ¯o2->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 *) ¯o->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 *) ¯o->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 = ¯o->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 = ¯o->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 *) ¯o->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, "e1); - len2 = canonicalize_text (p2, b2->text, b2->text_len, "e2); - 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, "e1); - len2 = canonicalize_text (p2, macro2->exp.text, macro2->count, "e2); - 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. */ |