* SDCPP synchronized with GCC CPP release version 4.1.1,
authorborutr <borutr@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 31 Dec 2006 16:29:37 +0000 (16:29 +0000)
committerborutr <borutr@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 31 Dec 2006 16:29:37 +0000 (16:29 +0000)
 currently the latest release:
* support/cpp2/libcpp, support/cpp2/libcpp/include,
  support/cpp2/libcpp/include/cpp-id-data.h
  support/cpp2/libiberty/fopen_unlocked.c
  support/cpp2/libiberty/md5.c
  support/cpp2/md5.h
  support/cpp2/opt-functions.awk
  support/cpp2/opt-gather.awk
  support/cpp2/optc-gen.awk
  support/cpp2/opth-gen.awk:
  added
* support/cpp2/Makefile.in, support/cpp2/auto-host_vc_in.h,
  support/cpp2/c-incpath.c, support/cpp2/c-incpath.h,
  support/cpp2/c-ppoutput.c, support/cpp2/c-pretty-print.c,
  support/cpp2/c-pretty-print.h, support/cpp2/cppdefault.c,
  support/cpp2/cppdefault.h, support/cpp2/diagnostic.c,
  support/cpp2/diagnostic.h, support/cpp2/except.h,
  support/cpp2/hwint.h, support/cpp2/input.h,
  support/cpp2/intl.h, support/cpp2/move-if-change,
  support/cpp2/opts.c, support/cpp2/opts.h,
  support/cpp2/output.h, support/cpp2/prefix.c,
  support/cpp2/prefix.h, support/cpp2/pretty-print.c,
  support/cpp2/pretty-print.h, support/cpp2/sdcpp-opts.c,
  support/cpp2/sdcpp.c, support/cpp2/sdcpp.dsp,
  support/cpp2/sdcpp.h, support/cpp2/sdcpp.opt,
  support/cpp2/sdcppa.dsp, support/cpp2/symcat.h,
  support/cpp2/version.c:
  modified
* support/cpp2/libcpp/charset.c, support/cpp2/libcpp/directives.c,
  support/cpp2/libcpp/errors.c, support/cpp2/libcpp/expr.c,
  support/cpp2/libcpp/files.c, support/cpp2/libcpp/identifiers.c,
  support/cpp2/libcpp/include/cpplib.h, support/cpp2/libcpp/include/line-map.h,
  support/cpp2/libcpp/include/mkdeps.h, support/cpp2/libcpp/include/symtab.h,
  support/cpp2/libcpp/init.c, support/cpp2/libcpp/internal.h,
  support/cpp2/libcpp/lex.c, support/cpp2/libcpp/line-map.c,
  support/cpp2/libcpp/macro.c, support/cpp2/libcpp/mkdeps.c,
  support/cpp2/libcpp/symtab.c, support/cpp2/libcpp/system.h,
  support/cpp2/libcpp/traditional.c, support/cpp2/libcpp/ucnid.h,
  support/cpp2/libiberty/hashtab.c, support/cpp2/libiberty/hashtab.h:
  moved
* support/cpp2/cppcharset.c, support/cpp2/cpperror.c,
  support/cpp2/cppexp.c, support/cpp2/cppfiles.c,
  support/cpp2/cpphash.c, support/cpp2/cpphash.h,
  support/cpp2/cppinit.c, support/cpp2/cpplex.c,
  support/cpp2/cpplib.c, support/cpp2/cpplib.h,
  support/cpp2/cppmacro.c, support/cpp2/cpptrad.c,
  support/cpp2/cppucnid.h, support/cpp2/hashtab.c,
  support/cpp2/hashtab.h, support/cpp2/hashtable.c,
  support/cpp2/hashtable.h, support/cpp2/line-map.c,
  support/cpp2/line-map.h, support/cpp2/mkdeps.c,
  support/cpp2/mkdeps.h, support/cpp2/options_vc_in.c,
  support/cpp2/options_vc_in.h, support/cpp2/opts.sh,
  support/cpp2/system.h:
  deleted / moved

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@4543 4a8a32a2-be11-0410-ad9d-d568d2c75423

87 files changed:
ChangeLog
support/cpp2/Makefile.in
support/cpp2/auto-host_vc_in.h
support/cpp2/c-incpath.c
support/cpp2/c-incpath.h
support/cpp2/c-ppoutput.c
support/cpp2/c-pretty-print.c
support/cpp2/c-pretty-print.h
support/cpp2/cppcharset.c [deleted file]
support/cpp2/cppdefault.c
support/cpp2/cppdefault.h
support/cpp2/cpperror.c [deleted file]
support/cpp2/cppexp.c [deleted file]
support/cpp2/cppfiles.c [deleted file]
support/cpp2/cpphash.c [deleted file]
support/cpp2/cpphash.h [deleted file]
support/cpp2/cppinit.c [deleted file]
support/cpp2/cpplex.c [deleted file]
support/cpp2/cpplib.c [deleted file]
support/cpp2/cpplib.h [deleted file]
support/cpp2/cppmacro.c [deleted file]
support/cpp2/cpptrad.c [deleted file]
support/cpp2/cppucnid.h [deleted file]
support/cpp2/diagnostic.c
support/cpp2/diagnostic.h
support/cpp2/except.h
support/cpp2/hashtab.c [deleted file]
support/cpp2/hashtab.h [deleted file]
support/cpp2/hashtable.c [deleted file]
support/cpp2/hashtable.h [deleted file]
support/cpp2/hwint.h
support/cpp2/input.h
support/cpp2/intl.h
support/cpp2/libcpp/charset.c [new file with mode: 0644]
support/cpp2/libcpp/directives.c [new file with mode: 0644]
support/cpp2/libcpp/errors.c [new file with mode: 0644]
support/cpp2/libcpp/expr.c [new file with mode: 0644]
support/cpp2/libcpp/files.c [new file with mode: 0644]
support/cpp2/libcpp/identifiers.c [new file with mode: 0644]
support/cpp2/libcpp/include/cpp-id-data.h [new file with mode: 0644]
support/cpp2/libcpp/include/cpplib.h [new file with mode: 0644]
support/cpp2/libcpp/include/line-map.h [new file with mode: 0644]
support/cpp2/libcpp/include/mkdeps.h [new file with mode: 0644]
support/cpp2/libcpp/include/symtab.h [new file with mode: 0644]
support/cpp2/libcpp/init.c [new file with mode: 0644]
support/cpp2/libcpp/internal.h [new file with mode: 0644]
support/cpp2/libcpp/lex.c [new file with mode: 0644]
support/cpp2/libcpp/line-map.c [new file with mode: 0644]
support/cpp2/libcpp/macro.c [new file with mode: 0644]
support/cpp2/libcpp/mkdeps.c [new file with mode: 0644]
support/cpp2/libcpp/symtab.c [new file with mode: 0644]
support/cpp2/libcpp/system.h [new file with mode: 0644]
support/cpp2/libcpp/traditional.c [new file with mode: 0644]
support/cpp2/libcpp/ucnid.h [new file with mode: 0644]
support/cpp2/libiberty/fopen_unlocked.c [new file with mode: 0644]
support/cpp2/libiberty/hashtab.c [new file with mode: 0644]
support/cpp2/libiberty/hashtab.h [new file with mode: 0644]
support/cpp2/libiberty/md5.c [new file with mode: 0644]
support/cpp2/line-map.c [deleted file]
support/cpp2/line-map.h [deleted file]
support/cpp2/md5.h [new file with mode: 0644]
support/cpp2/mkdeps.c [deleted file]
support/cpp2/mkdeps.h [deleted file]
support/cpp2/move-if-change
support/cpp2/opt-functions.awk [new file with mode: 0644]
support/cpp2/opt-gather.awk [new file with mode: 0644]
support/cpp2/optc-gen.awk [new file with mode: 0644]
support/cpp2/opth-gen.awk [new file with mode: 0644]
support/cpp2/options_vc_in.c [deleted file]
support/cpp2/options_vc_in.h [deleted file]
support/cpp2/opts.c
support/cpp2/opts.h
support/cpp2/opts.sh [deleted file]
support/cpp2/output.h
support/cpp2/prefix.c
support/cpp2/prefix.h
support/cpp2/pretty-print.c
support/cpp2/pretty-print.h
support/cpp2/sdcpp-opts.c
support/cpp2/sdcpp.c
support/cpp2/sdcpp.dsp
support/cpp2/sdcpp.h
support/cpp2/sdcpp.opt
support/cpp2/sdcppa.dsp
support/cpp2/symcat.h
support/cpp2/system.h [deleted file]
support/cpp2/version.c

index acb6b0daef28e5fdfb237898c068240d9ad4084c..73bb2c4081985da0f25d2230d9ea51224726eb6a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,61 @@
+2006-12-31 Borut Razem <borut.razem AT siol.net>
+
+       * SDCPP synchronized with GCC CPP release version 4.1.1,
+         currently the latest release:
+       * support/cpp2/libcpp, support/cpp2/libcpp/include,
+         support/cpp2/libcpp/include/cpp-id-data.h
+         support/cpp2/libiberty/fopen_unlocked.c
+         support/cpp2/libiberty/md5.c
+         support/cpp2/md5.h
+         support/cpp2/opt-functions.awk
+         support/cpp2/opt-gather.awk
+         support/cpp2/optc-gen.awk
+         support/cpp2/opth-gen.awk:
+         added
+       * support/cpp2/Makefile.in, support/cpp2/auto-host_vc_in.h,
+         support/cpp2/c-incpath.c, support/cpp2/c-incpath.h,
+         support/cpp2/c-ppoutput.c, support/cpp2/c-pretty-print.c,
+         support/cpp2/c-pretty-print.h, support/cpp2/cppdefault.c,
+         support/cpp2/cppdefault.h, support/cpp2/diagnostic.c,
+         support/cpp2/diagnostic.h, support/cpp2/except.h,
+         support/cpp2/hwint.h, support/cpp2/input.h,
+         support/cpp2/intl.h, support/cpp2/move-if-change,
+         support/cpp2/opts.c, support/cpp2/opts.h,
+         support/cpp2/output.h, support/cpp2/prefix.c,
+         support/cpp2/prefix.h, support/cpp2/pretty-print.c,
+         support/cpp2/pretty-print.h, support/cpp2/sdcpp-opts.c,
+         support/cpp2/sdcpp.c, support/cpp2/sdcpp.dsp,
+         support/cpp2/sdcpp.h, support/cpp2/sdcpp.opt,
+         support/cpp2/sdcppa.dsp, support/cpp2/symcat.h,
+         support/cpp2/version.c:
+         modified
+       * support/cpp2/libcpp/charset.c, support/cpp2/libcpp/directives.c,
+         support/cpp2/libcpp/errors.c, support/cpp2/libcpp/expr.c,
+         support/cpp2/libcpp/files.c, support/cpp2/libcpp/identifiers.c,
+         support/cpp2/libcpp/include/cpplib.h, support/cpp2/libcpp/include/line-map.h,
+         support/cpp2/libcpp/include/mkdeps.h, support/cpp2/libcpp/include/symtab.h,
+         support/cpp2/libcpp/init.c, support/cpp2/libcpp/internal.h,
+         support/cpp2/libcpp/lex.c, support/cpp2/libcpp/line-map.c,
+         support/cpp2/libcpp/macro.c, support/cpp2/libcpp/mkdeps.c,
+         support/cpp2/libcpp/symtab.c, support/cpp2/libcpp/system.h,
+         support/cpp2/libcpp/traditional.c, support/cpp2/libcpp/ucnid.h,
+         support/cpp2/libiberty/hashtab.c, support/cpp2/libiberty/hashtab.h:
+         moved
+       * support/cpp2/cppcharset.c, support/cpp2/cpperror.c,
+         support/cpp2/cppexp.c, support/cpp2/cppfiles.c,
+         support/cpp2/cpphash.c, support/cpp2/cpphash.h,
+         support/cpp2/cppinit.c, support/cpp2/cpplex.c,
+         support/cpp2/cpplib.c, support/cpp2/cpplib.h,
+         support/cpp2/cppmacro.c, support/cpp2/cpptrad.c,
+         support/cpp2/cppucnid.h, support/cpp2/hashtab.c,
+         support/cpp2/hashtab.h, support/cpp2/hashtable.c,
+         support/cpp2/hashtable.h, support/cpp2/line-map.c,
+         support/cpp2/line-map.h, support/cpp2/mkdeps.c,
+         support/cpp2/mkdeps.h, support/cpp2/options_vc_in.c,
+         support/cpp2/options_vc_in.h, support/cpp2/opts.sh,
+         support/cpp2/system.h:
+         deleted / moved
+
 2006-12-31 Borut Razem <borut.razem AT siol.net>
 
        * configure.in, configure: fixed bug #1538756: configure dies if bison
index 12d10400412cb23f90a84b01d39df3b75e90f208..46980540105ace453c097aae7ecafffae18f8642 100644 (file)
@@ -70,6 +70,7 @@ STAMP = echo timestamp >
 
 # Where to find some libiberty headers.
 LIBIBERTY_DIR = $(srcdir)/libiberty
+LIBCPP_DIR = $(srcdir)/libcpp
 OBSTACK_H   = $(LIBIBERTY_DIR)/obstack.h
 SPLAY_TREE_H= $(LIBIBERTY_DIR)/splay-tree.h
 
@@ -95,6 +96,9 @@ exeext = @host_exeext@
 transform       = @program_transform_name@
 lang_opt_files=$(srcdir)/sdcpp.opt
 
+# All option source files
+ALL_OPT_FILES=$(lang_opt_files) $(extra_opt_files)
+
 # Top build directory, relative to here.
 top_builddir = @top_builddir@
 
@@ -148,7 +152,7 @@ SYSTEM_H = system.h hwint.h
 #@build_overrides@
 #\f
 
-INCLUDES = -I$(srcdir) -I$(LIBIBERTY_DIR) -I.
+INCLUDES = -I$(srcdir) -I$(LIBCPP_DIR) -I$(LIBCPP_DIR)/include -I$(LIBIBERTY_DIR) -I.
 
 # Always use -I$(srcdir)/config when compiling.
 .c.o:
@@ -183,19 +187,28 @@ config.status: $(srcdir)/configure  version.c
          LANGUAGES="$(CONFIG_LANGUAGES)" $(SHELL) config.status --recheck; \
        fi
 
-options.c: $(lang_opt_files) $(srcdir)/opts.sh options.h intl.h
 
-options.h: $(lang_opt_files) $(srcdir)/opts.sh Makefile
-       AWK=$(AWK) $(SHELL) $(srcdir)/opts.sh \
-               '$(SHELL) $(srcdir)/move-if-change' \
-               options.c options.h $(lang_opt_files)
+optionlist: s-options ; @true
+s-options: $(ALL_OPT_FILES) Makefile $(srcdir)/opt-gather.awk
+       $(AWK) -f $(srcdir)/opt-gather.awk $(ALL_OPT_FILES) > tmp-optionlist
+       $(SHELL) $(srcdir)/move-if-change tmp-optionlist optionlist
+       $(STAMP) s-options
+
+options.c: optionlist $(srcdir)/opt-functions.awk $(srcdir)/optc-gen.awk
+       $(AWK) -f $(srcdir)/opt-functions.awk -f $(srcdir)/optc-gen.awk \
+              -v header_name="config.h system.h options.h" < $< > $@
+
+options.h: s-options-h ; @true
+s-options-h: optionlist $(srcdir)/opt-functions.awk $(srcdir)/opth-gen.awk
+       $(AWK) -f $(srcdir)/opt-functions.awk -f $(srcdir)/opth-gen.awk \
+              < $< > tmp-options.h
+       $(SHELL) $(srcdir)/move-if-change tmp-options.h options.h
+       $(STAMP) $@
 
 version.o: version.c version.h
 
 hashtable.o: hashtable.c hashtable.h $(CONFIG_H) $(SYSTEM_H) $(OBSTACK_H)
 
-hashtab.o: hashtab.c hashtab.h $(CONFIG_H)
-
 cppcharset.o: cppcharset.c $(CONFIG_H) $(SYSTEM_H)
 
 prefix.o: prefix.c $(CONFIG_H) $(SYSTEM_H) Makefile prefix.h
@@ -215,13 +228,14 @@ PREPROCESSOR_DEFINES = \
   -DCROSS_INCLUDE_DIR=\"$(gcc_tooldir)/sys-include\" \
   -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\"
 
-LIBCPP_OBJS =  c-ppoutput.o cppinit.o cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o \
-               cpphash.o cpperror.o cppdefault.o \
-               hashtable.o mkdeps.o prefix.o version.o \
-               line-map.o cpptrad.o cppcharset.o hashtab.o \
-               opts.o options.o diagnostic.o pretty-print.o c-incpath.o
+##########################
+# Libcpp
+
+LIBCPP_OBJS =  charset.o directives.o errors.o expr.o files.o identifiers.o \
+               init.o lex.o line-map.o macro.o mkdeps.o symtab.o traditional.o
 
-LIBCPP_DEPS =  cpplib.h cpphash.h hashtable.h intl.h options.h $(OBSTACK_H) $(SYSTEM_H)
+
+##LIBCPP_DEPS =        cpplib.h cpphash.h hashtable.h intl.h options.h $(OBSTACK_H) $(SYSTEM_H)
 
 # Most of the other archives built/used by this makefile are for
 # targets.  This one is strictly for the host.
@@ -230,53 +244,72 @@ libcpp.a: $(LIBCPP_OBJS)
        $(AR) $(AR_FLAGS) libcpp.a $(LIBCPP_OBJS)
        -$(RANLIB) libcpp.a
 
-MY_LIBIBERTY_BITS = concat.o getpwd.o hex.o lbasename.o obstack.o \
-                   safe-ctype.o splay-tree.o vasprintf.o xexit.o xmalloc.o \
-                   xmemdup.o xstrdup.o xstrerror.o
+charset.o: $(LIBCPP_DIR)/charset.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
 
-$(TARGET): sdcpp.o sdcpp-opts.o $(MY_LIBIBERTY_BITS) libcpp.a $(LIBDEPS)
-       mkdir -p $(dir $@)
-       $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ sdcpp.o sdcpp-opts.o \
-       $(MY_LIBIBERTY_BITS) libcpp.a $(LIBS)
+directives.o: $(LIBCPP_DIR)/directives.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
 
-sdcpp.o:      sdcpp.c  $(CONFIG_H) cpplib.h $(SYSTEM_H) options.h
-sdcpp-opts.o: sdcpp-opts.c $(CONFIG_H) $(LIBCPP_DEPS) options.h
+errors.o: $(LIBCPP_DIR)/errors.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
 
-c-ppoutput.o:  c-ppoutput.c  $(CONFIG_H) cpplib.h intl.h $(SYSTEM_H)
-cppinit.o:  cppinit.c  $(CONFIG_H) $(LIBCPP_DEPS) cppdefault.h \
-               mkdeps.h prefix.h output.h version.h
-cpperror.o: cpperror.c $(CONFIG_H) $(LIBCPP_DEPS)
-cppexp.o:   cppexp.c   $(CONFIG_H) $(LIBCPP_DEPS)
-cpplex.o:   cpplex.c   $(CONFIG_H) $(LIBCPP_DEPS)
-cppmacro.o: cppmacro.c $(CONFIG_H) $(LIBCPP_DEPS)
-cpplib.o:   cpplib.c   $(CONFIG_H) $(LIBCPP_DEPS)
-cpphash.o:  cpphash.c  $(CONFIG_H) $(LIBCPP_DEPS)
-cppfiles.o: cppfiles.c $(CONFIG_H) $(LIBCPP_DEPS) $(SPLAY_TREE_H) mkdeps.h
-cpptrad.o:  cpptrad.c  $(CONFIG_H) $(LIBCPP_DEPS)
-opts.o:     opts.c     $(CONFIG_H) $(LIBCPP_DEPS) options.h
-diagnostic.o: diagnostic.c $(CONFIG_H) $(LIBCPP_DEPS) diagnostic.h
-pretty-print.o: pretty-print.c $(CONFIG_H) $(LIBCPP_DEPS) pretty-print.h
-c-incpath.o: $(CONFIG_H) $(LIBCPP_DEPS) c-incpath.h
+expr.o: $(LIBCPP_DIR)/expr.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
 
-cppdefault.o: cppdefault.c $(CONFIG_H) $(SYSTEM_H) cppdefault.h Makefile
-       $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-         $(PREPROCESSOR_DEFINES) \
-         -c $(srcdir)/cppdefault.c
+files.o: $(LIBCPP_DIR)/files.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+
+identifiers.o: $(LIBCPP_DIR)/identifiers.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+
+init.o: $(LIBCPP_DIR)/init.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+
+lex.o: $(LIBCPP_DIR)/lex.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+
+line-map.o: $(LIBCPP_DIR)/line-map.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+
+macro.o: $(LIBCPP_DIR)/macro.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+
+mkdeps.o: $(LIBCPP_DIR)/mkdeps.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
 
-mkdeps.o: mkdeps.c $(CONFIG_H) $(SYSTEM_H) mkdeps.h
+symtab.o: $(LIBCPP_DIR)/symtab.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
 
+traditional.o: $(LIBCPP_DIR)/traditional.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+
+##########################
 # Libiberty
 
-concat.o: $(LIBIBERTY_DIR)/concat.c  $(CONFIG_H) $(LIBCPP_DEPS)
+MY_LIBIBERTY_BITS = concat.o fopen_unlocked.o getpwd.o hashtab.o hex.o \
+                   lbasename.o md5.o obstack.o safe-ctype.o splay-tree.o \
+                   vasprintf.o xexit.o xmalloc.o xmemdup.o xstrdup.o \
+                   xstrerror.o
+
+concat.o: $(LIBIBERTY_DIR)/concat.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+
+fopen_unlocked.o: $(LIBIBERTY_DIR)/fopen_unlocked.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+
+getpwd.o: $(LIBIBERTY_DIR)/getpwd.c $(CONFIG_H) $(LIBCPP_DEPS)
        $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
 
-getpwd.o: $(LIBIBERTY_DIR)/getpwd.c  $(CONFIG_H) $(LIBCPP_DEPS)
+hashtab.o: $(LIBIBERTY_DIR)/hashtab.c $(CONFIG_H) $(LIBCPP_DEPS)
        $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
 
-hex.o: $(LIBIBERTY_DIR)/hex.c  $(CONFIG_H) $(LIBCPP_DEPS)
+hex.o: $(LIBIBERTY_DIR)/hex.c $(CONFIG_H) $(LIBCPP_DEPS)
        $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
 
-lbasename.o: $(LIBIBERTY_DIR)/lbasename.c  $(CONFIG_H) $(LIBCPP_DEPS)
+lbasename.o: $(LIBIBERTY_DIR)/lbasename.c $(CONFIG_H) $(LIBCPP_DEPS)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+
+md5.o: $(LIBIBERTY_DIR)/md5.c $(LIBIBERTY_DIR)/obstack.h $(CONFIG_H) $(LIBCPP_DEPS)
        $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
 
 obstack.o: $(LIBIBERTY_DIR)/obstack.c $(LIBIBERTY_DIR)/obstack.h $(CONFIG_H) $(LIBCPP_DEPS)
@@ -305,3 +338,32 @@ xstrdup.o: $(LIBIBERTY_DIR)/xstrdup.c  $(CONFIG_H) $(LIBCPP_DEPS)
 
 xstrerror.o: $(LIBIBERTY_DIR)/xstrerror.c  $(CONFIG_H) $(LIBCPP_DEPS)
        $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+
+##########################
+# Sdcpp
+
+SDCC_OBJS =    sdcpp.o sdcpp-opts.o c-ppoutput.o cppdefault.o prefix.o version.o opts.o options.o diagnostic.o pretty-print.o c-incpath.o
+
+$(TARGET): $(SDCC_OBJS) $(MY_LIBIBERTY_BITS) libcpp.a $(LIBDEPS)
+       mkdir -p $(dir $@)
+       $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(SDCC_OBJS) \
+       $(MY_LIBIBERTY_BITS) libcpp.a $(LIBS)
+
+sdcpp.o:      sdcpp.c  $(CONFIG_H) $(SYSTEM_H) options.h
+
+sdcpp-opts.o: sdcpp-opts.c $(CONFIG_H) $(LIBCPP_DEPS) options.h
+
+c-ppoutput.o:  c-ppoutput.c  $(CONFIG_H) $(SYSTEM_H)
+
+opts.o:     opts.c     $(CONFIG_H) $(LIBCPP_DEPS) options.h
+
+diagnostic.o: diagnostic.c $(CONFIG_H) $(LIBCPP_DEPS) diagnostic.h
+
+pretty-print.o: pretty-print.c $(CONFIG_H) $(LIBCPP_DEPS) pretty-print.h
+
+c-incpath.o: $(CONFIG_H) $(LIBCPP_DEPS) c-incpath.h
+
+cppdefault.o: cppdefault.c $(CONFIG_H) $(SYSTEM_H) cppdefault.h Makefile
+       $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+         $(PREPROCESSOR_DEFINES) \
+         -c $(srcdir)/cppdefault.c
index a2b61ca70845892aa3b4425be16e07f40d577dfc..4e3ddad98426f0f0da055f5f46ab886e9de24421 100644 (file)
@@ -23,9 +23,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/
 #include <sys/stat.h>
 #include <io.h>
 #include <malloc.h>
+#include <stdio.h>
 
 #define HAVE_STRINGIZE
-#define STDC_HEADERS
+#define STDC_HEADERS           1
 #define PACKAGE "sdcc"
 #define LOCALEDIR ""
 #define PREFIX ""
index 4b0bf54576d4ba4b3c8c5f5c189f38059886b0bc..8ae9e554f97d77cea393d7e652e108f1a52bb0bb 100644 (file)
@@ -1,6 +1,6 @@
 /* Set up combined include path chain for the preprocessor.\r
    Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,\r
-   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.\r
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.\r
 \r
    Broken out of cppinit.c and cppfiles.c and rewritten Mar 2003.\r
 \r
@@ -16,7 +16,7 @@ GNU General Public License for more details.
 \r
 You should have received a copy of the GNU General Public License\r
 along with this program; if not, write to the Free Software\r
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */\r
+Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */\r
 \r
 #include "config.h"\r
 #include "system.h"\r
@@ -33,7 +33,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 # define INO_T_EQ(A, B) (!memcmp (&(A), &(B), sizeof (A)))\r
 # define INO_T_COPY(DEST, SRC) memcpy(&(DEST), &(SRC), sizeof (SRC))\r
 #else\r
-# if (defined _WIN32 && ! defined (_UWIN)) || defined __MSDOS__\r
+# if (defined _WIN32 && !defined (_UWIN)) || defined __MSDOS__\r
 #  define INO_T_EQ(A, B) 0\r
 # else\r
 #  define INO_T_EQ(A, B) ((A) == (B))\r
@@ -110,7 +110,7 @@ add_env_var_paths (const char *env_var, int chain)
          path[q - p] = '\0';\r
        }\r
 \r
-      add_path (path, chain, chain == SYSTEM);\r
+      add_path (path, chain, chain == SYSTEM, false);\r
     }\r
 }\r
 \r
@@ -124,7 +124,7 @@ add_standard_paths (const char *sysroot, const char *iprefix, int cxx_stdinc)
   if (iprefix && (len = cpp_GCC_INCLUDE_DIR_len) != 0)\r
     {\r
       /* Look for directories that start with the standard prefix.\r
-        "Translate" them, ie. replace /usr/local/lib/gcc... with\r
+        "Translate" them, i.e. replace /usr/local/lib/gcc... with\r
         IPREFIX and search them first.  */\r
       for (p = cpp_include_defaults; p->fname; p++)\r
        {\r
@@ -138,7 +138,7 @@ add_standard_paths (const char *sysroot, const char *iprefix, int cxx_stdinc)
              if (!strncmp (p->fname, cpp_GCC_INCLUDE_DIR, len))\r
                {\r
                  char *str = concat (iprefix, p->fname + len, NULL);\r
-                 add_path (str, SYSTEM, p->cxx_aware);\r
+                 add_path (str, SYSTEM, p->cxx_aware, false);\r
                }\r
            }\r
        }\r
@@ -156,7 +156,7 @@ add_standard_paths (const char *sysroot, const char *iprefix, int cxx_stdinc)
          else\r
            str = update_path (p->fname, p->component);\r
 \r
-         add_path (str, SYSTEM, p->cxx_aware);\r
+         add_path (str, SYSTEM, p->cxx_aware, false);\r
        }\r
     }\r
 }\r
@@ -167,6 +167,7 @@ add_standard_paths (const char *sysroot, const char *iprefix, int cxx_stdinc)
    JOIN, unless it duplicates JOIN in which case the last path is\r
    removed.  Return the head of the resulting chain.  Any of HEAD,\r
    JOIN and SYSTEM can be NULL.  */\r
+\r
 static struct cpp_dir *\r
 remove_duplicates (cpp_reader *pfile, struct cpp_dir *head,\r
                   struct cpp_dir *system, struct cpp_dir *join,\r
@@ -187,7 +188,13 @@ remove_duplicates (cpp_reader *pfile, struct cpp_dir *head,
          if (errno != ENOENT)\r
            cpp_errno (pfile, CPP_DL_ERROR, cur->name);\r
          else\r
-           reason = REASON_NOENT;\r
+           {\r
+             /* If -Wmissing-include-dirs is given, warn.  */\r
+             cpp_options *opts = cpp_get_options (pfile);\r
+             if (opts->warn_missing_include_dirs && cur->user_supplied_p)\r
+               cpp_errno (pfile, CPP_DL_WARNING, cur->name);\r
+             reason = REASON_NOENT;\r
+           }\r
        }\r
       else if (!S_ISDIR (st.st_mode))\r
        cpp_error_with_line (pfile, CPP_DL_ERROR, 0, 0,\r
@@ -200,7 +207,8 @@ remove_duplicates (cpp_reader *pfile, struct cpp_dir *head,
          /* Remove this one if it is in the system chain.  */\r
          reason = REASON_DUP_SYS;\r
          for (tmp = system; tmp; tmp = tmp->next)\r
-           if (INO_T_EQ (tmp->ino, cur->ino) && tmp->dev == cur->dev)\r
+           if (INO_T_EQ (tmp->ino, cur->ino) && tmp->dev == cur->dev\r
+               && cur->construct == tmp->construct)\r
              break;\r
 \r
          if (!tmp)\r
@@ -208,14 +216,16 @@ remove_duplicates (cpp_reader *pfile, struct cpp_dir *head,
              /* Duplicate of something earlier in the same chain?  */\r
              reason = REASON_DUP;\r
              for (tmp = head; tmp != cur; tmp = tmp->next)\r
-               if (INO_T_EQ (cur->ino, tmp->ino) && cur->dev == tmp->dev)\r
+               if (INO_T_EQ (cur->ino, tmp->ino) && cur->dev == tmp->dev\r
+                   && cur->construct == tmp->construct)\r
                  break;\r
 \r
              if (tmp == cur\r
                  /* Last in the chain and duplicate of JOIN?  */\r
                  && !(cur->next == NULL && join\r
                       && INO_T_EQ (cur->ino, join->ino)\r
-                      && cur->dev == join->dev))\r
+                      && cur->dev == join->dev\r
+                      && cur->construct == join->construct))\r
                {\r
                  /* Unique, so keep this directory.  */\r
                  pcur = &cur->next;\r
@@ -239,9 +249,10 @@ remove_duplicates (cpp_reader *pfile, struct cpp_dir *head,
 \r
    We can't just merge the lists and then uniquify them because then\r
    we may lose directories from the <> search path that should be\r
-   there; consider -Ifoo -Ibar -I- -Ifoo -Iquux.  It is however safe\r
-   to treat -Ibar -Ifoo -I- -Ifoo -Iquux as if written -Ibar -I- -Ifoo\r
-   -Iquux.  */\r
+   there; consider -iquote foo -iquote bar -Ifoo -Iquux.  It is\r
+   however safe to treat -iquote bar -iquote foo -Ifoo -Iquux as if\r
+   written -iquote bar -Ifoo -Iquux.  */\r
+\r
 static void\r
 merge_include_chains (cpp_reader *pfile, int verbose)\r
 {\r
@@ -296,16 +307,28 @@ split_quote_chain (void)
   quote_ignores_source_dir = true;\r
 }\r
 \r
+/* Add P to the chain specified by CHAIN.  */\r
+\r
+void\r
+add_cpp_dir_path (cpp_dir *p, int chain)\r
+{\r
+  if (tails[chain])\r
+    tails[chain]->next = p;\r
+  else\r
+    heads[chain] = p;\r
+  tails[chain] = p;\r
+}\r
+\r
 /* Add PATH to the include chain CHAIN. PATH must be malloc-ed and\r
    NUL-terminated.  */\r
 void\r
-add_path (char *path, int chain, int cxx_aware)\r
+add_path (char *path, int chain, int cxx_aware, bool user_supplied_p)\r
 {\r
-  struct cpp_dir *p;\r
+  cpp_dir *p;\r
 \r
 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)\r
   /* Convert all backslashes to slashes.  The native CRT stat()\r
-     function does not recognise a directory that ends in a backslash\r
+     function does not recognize a directory that ends in a backslash\r
      (unless it is a drive root dir, such "c:\").  Forward slashes,\r
      trailing or otherwise, cause no problems for stat().  */\r
   char* c;\r
@@ -313,19 +336,17 @@ add_path (char *path, int chain, int cxx_aware)
     if (*c == '\\') *c = '/';\r
 #endif\r
 \r
-  p = xmalloc (sizeof (struct cpp_dir));\r
+  p = xmalloc (sizeof (cpp_dir));\r
   p->next = NULL;\r
   p->name = path;\r
   if (chain == SYSTEM || chain == AFTER)\r
     p->sysp = 1 + !cxx_aware;\r
   else\r
     p->sysp = 0;\r
+  p->construct = 0;\r
+  p->user_supplied_p = user_supplied_p;\r
 \r
-  if (tails[chain])\r
-    tails[chain]->next = p;\r
-  else\r
-    heads[chain] = p;\r
-  tails[chain] = p;\r
+  add_cpp_dir_path (p, chain);\r
 }\r
 \r
 /* Exported function to handle include chain merging, duplicate\r
@@ -351,12 +372,33 @@ register_include_chains (cpp_reader *pfile, const char *sysroot,
   add_env_var_paths ("CPATH", BRACKET);\r
   add_env_var_paths (lang_env_vars[idx], SYSTEM);\r
 \r
+  target_c_incpath.extra_pre_includes (sysroot, iprefix, stdinc);\r
+\r
   /* Finally chain on the standard directories.  */\r
   if (stdinc)\r
     add_standard_paths (sysroot, iprefix, cxx_stdinc);\r
 \r
+  target_c_incpath.extra_includes (sysroot, iprefix, stdinc);\r
+\r
   merge_include_chains (pfile, verbose);\r
 \r
   cpp_set_include_chains (pfile, heads[QUOTE], heads[BRACKET],\r
                          quote_ignores_source_dir);\r
 }\r
+#if !(defined TARGET_EXTRA_INCLUDES) || !(defined TARGET_EXTRA_PRE_INCLUDES)\r
+static void hook_void_charptr_charptr_int (const char *sysroot ATTRIBUTE_UNUSED,\r
+                                          const char *iprefix ATTRIBUTE_UNUSED,\r
+                                          int stdinc ATTRIBUTE_UNUSED)\r
+{\r
+}\r
+#endif\r
+\r
+#ifndef TARGET_EXTRA_INCLUDES\r
+#define TARGET_EXTRA_INCLUDES hook_void_charptr_charptr_int\r
+#endif\r
+#ifndef TARGET_EXTRA_PRE_INCLUDES\r
+#define TARGET_EXTRA_PRE_INCLUDES hook_void_charptr_charptr_int\r
+#endif\r
+\r
+struct target_c_incpath_s target_c_incpath = { TARGET_EXTRA_PRE_INCLUDES, TARGET_EXTRA_INCLUDES };\r
+\r
index 31ed657da2a5bcb5f600fc6da466c3cf1631c3fa..c309844cf0add45b3e6b98817ae3b6190b74abed 100644 (file)
@@ -1,5 +1,5 @@
 /* Set up combined include path for the preprocessor.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005 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
@@ -13,11 +13,20 @@ 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.  */
+Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 extern void split_quote_chain (void);
-extern void add_path (char *, int, int);
+extern void add_path (char *, int, int, bool);
 extern void register_include_chains (cpp_reader *, const char *,
                                     const char *, int, int, int);
+extern void add_cpp_dir_path (struct cpp_dir *, int);
+
+struct target_c_incpath_s {
+  /* Do extra includes processing.  STDINC is false iff -nostdinc was given.  */
+  void (*extra_pre_includes) (const char *, const char *, int);
+  void (*extra_includes) (const char *, const char *, int);
+};
+
+extern struct target_c_incpath_s target_c_incpath;
 
 enum { QUOTE = 0, BRACKET, SYSTEM, AFTER };
index f564dfe11d697b5b1e610e41325aa8d735ed76c4..9a5434311ae6d9dbc2169cd97e1a546b64a01ef2 100644 (file)
@@ -15,23 +15,23 @@ 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.  */
+Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
 #include "cpplib.h"
-#include "cpphash.h"
+#include "../libcpp/internal.h"
 
 /* Encapsulates state used to convert a stream of tokens into a text
    file.  */
 static struct
 {
   FILE *outf;                  /* Stream to write to.  */
-  const struct line_map *map;  /* Logical to physical line mappings.  */
   const cpp_token *prev;       /* Previous token.  */
   const cpp_token *source;     /* Source token for spacing.  */
-  fileline line;               /* Line currently being written.  */
+  int src_line;                        /* Line number currently being written.  */
   unsigned char printed;       /* Nonzero if something output at line.  */
+  bool first_time;             /* pp_file_change hasn't been called yet.  */
 } print;
 
 /* General output routines.  */
@@ -40,18 +40,22 @@ static void scan_translation_unit_trad (cpp_reader *);
 static void account_for_newlines (const unsigned char *, size_t);
 static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
 
-static void print_line (const struct line_map *, fileline, const char *);
-static void maybe_print_line (const struct line_map *, fileline);
+static void print_line (source_location, const char *);
+static void maybe_print_line (source_location);
 
 /* Callback routines for the parser.   Most of these are active only
    in specific modes.  */
 static void cb_line_change (cpp_reader *, const cpp_token *, int);
-static void cb_define (cpp_reader *, fileline, cpp_hashnode *);
-static void cb_undef (cpp_reader *, fileline, cpp_hashnode *);
-static void cb_include (cpp_reader *, fileline, const unsigned char *,
-                       const char *, int);
-static void cb_ident (cpp_reader *, fileline, const cpp_string *);
-static void cb_def_pragma (cpp_reader *, fileline);
+static void cb_define (cpp_reader *, source_location, cpp_hashnode *);
+static void cb_undef (cpp_reader *, source_location, cpp_hashnode *);
+static void cb_include (cpp_reader *, source_location, const unsigned char *,
+                       const char *, int, const cpp_token **);
+static void cb_ident (cpp_reader *, source_location, const cpp_string *);
+static void cb_def_pragma (cpp_reader *, source_location);
+#if 0
+static void cb_read_pch (cpp_reader *pfile, const char *name,
+                        int fd, const char *orig_name);
+#endif
 
 /* Preprocess and output.  */
 void
@@ -101,20 +105,28 @@ init_pp_output (FILE *out_stream)
   if (flag_dump_includes)
     cb->include  = cb_include;
 
+#if 0
+  if (flag_pch_preprocess)
+    {
+      cb->valid_pch = c_common_valid_pch;
+      cb->read_pch = cb_read_pch;
+    }
+#endif
+
   if (flag_dump_macros == 'N' || flag_dump_macros == 'D')
     {
       cb->define = cb_define;
       cb->undef  = cb_undef;
     }
 
-  /* Initialize the print structure.  Setting print.line to -1 here is
+  /* Initialize the print structure.  Setting print.src_line to -1 here is
      a trick to guarantee that the first token of the file will cause
      a linemarker to be output by maybe_print_line.  */
-  print.line = (fileline) -1;
+  print.src_line = -1;
   print.printed = 0;
   print.prev = 0;
-  print.map = 0;
   print.outf = out_stream;
+  print.first_time = 1;
 }
 
 /* Writes out the preprocessed file, handling spacing and paste
@@ -166,13 +178,13 @@ scan_translation_unit (cpp_reader *pfile)
     }
 }
 
-/* Adjust print.line for newlines embedded in output.  */
+/* Adjust print.src_line for newlines embedded in output.  */
 static void
 account_for_newlines (const unsigned char *str, size_t len)
 {
   while (len--)
     if (*str++ == '\n')
-      print.line++;
+      print.src_line++;
 }
 
 /* Writes out a traditionally preprocessed file.  */
@@ -182,7 +194,7 @@ scan_translation_unit_trad (cpp_reader *pfile)
   while (_cpp_read_logical_line_trad (pfile))
     {
       size_t len = pfile->out.cur - pfile->out.base;
-      maybe_print_line (print.map, pfile->out.first_line);
+      maybe_print_line (pfile->out.first_line);
       fwrite (pfile->out.base, 1, len, print.outf);
       print.printed = 1;
       if (!CPP_OPTION (pfile, discard_comments))
@@ -194,52 +206,57 @@ scan_translation_unit_trad (cpp_reader *pfile)
    different line to the current one, output the required newlines or
    a line marker, and return 1.  Otherwise return 0.  */
 static void
-maybe_print_line (const struct line_map *map, fileline line)
+maybe_print_line (source_location src_loc)
 {
+  const struct line_map *map = linemap_lookup (&line_table, src_loc);
+  int src_line = SOURCE_LINE (map, src_loc);
   /* End the previous line of text.  */
   if (print.printed)
     {
       putc ('\n', print.outf);
-      print.line++;
+      print.src_line++;
       print.printed = 0;
     }
 
-  if (line >= print.line && line < print.line + 8)
+  if (src_line >= print.src_line && src_line < print.src_line + 8)
     {
-      while (line > print.line)
+      while (src_line > print.src_line)
        {
          putc ('\n', print.outf);
-         print.line++;
+         print.src_line++;
        }
     }
   else
-    print_line (map, line, "");
+    print_line (src_loc, "");
 }
 
 /* Output a line marker for logical line LINE.  Special flags are "1"
    or "2" indicating entering or leaving a file.  */
 static void
-print_line (const struct line_map *map, fileline line, const char *special_flags)
+print_line (source_location src_loc, const char *special_flags)
 {
   /* End any previous line of text.  */
   if (print.printed)
     putc ('\n', print.outf);
   print.printed = 0;
 
-  print.line = line;
   if (!flag_no_line_commands)
     {
+      const struct line_map *map = linemap_lookup (&line_table, src_loc);
+
       size_t to_file_len = strlen (map->to_file);
       unsigned char *to_file_quoted = alloca (to_file_len * 4 + 1);
       unsigned char *p;
 
+      print.src_line = SOURCE_LINE (map, src_loc);
+
       /* cpp_quote_string does not nul-terminate, so we have to do it
         ourselves.  */
       p = cpp_quote_string (to_file_quoted,
-                           (unsigned char *)map->to_file, to_file_len);
+                           (unsigned char *) map->to_file, to_file_len);
       *p = '\0';
       fprintf (print.outf, "# %u \"%s\"%s",
-              SOURCE_LINE (map, print.line),
+              print.src_line == 0 ? 1 : print.src_line,
               to_file_quoted, special_flags);
 
       if (map->sysp == 2)
@@ -257,10 +274,12 @@ static void
 cb_line_change (cpp_reader *pfile, const cpp_token *token,
                int parsing_args)
 {
+  source_location src_loc = token->src_loc;
+
   if (token->type == CPP_EOF || parsing_args)
     return;
 
-  maybe_print_line (print.map, token->line);
+  maybe_print_line (src_loc);
   print.prev = 0;
   print.source = 0;
 
@@ -271,30 +290,28 @@ cb_line_change (cpp_reader *pfile, const cpp_token *token,
      ought to care.  Some things do care; the fault lies with them.  */
   if (!CPP_OPTION (pfile, traditional))
     {
+      const struct line_map *map = linemap_lookup (&line_table, src_loc);
+      int spaces = SOURCE_COLUMN (map, src_loc) - 2;
       print.printed = 1;
-      if (token->col > 2)
-       {
-         unsigned int spaces = token->col - 2;
 
-         while (spaces--)
-           putc (' ', print.outf);
-       }
+      while (-- spaces >= 0)
+       putc (' ', print.outf);
     }
 }
 
 static void
-cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, fileline line,
+cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
          const cpp_string *str)
 {
-  maybe_print_line (print.map, line);
+  maybe_print_line (line);
   fprintf (print.outf, "#ident %s\n", str->text);
-  print.line++;
+  print.src_line++;
 }
 
 static void
-cb_define (cpp_reader *pfile, fileline line, cpp_hashnode *node)
+cb_define (cpp_reader *pfile, source_location line, cpp_hashnode *node)
 {
-  maybe_print_line (print.map, line);
+  maybe_print_line (line);
   fputs ("#define ", print.outf);
 
   /* 'D' is whole definition; 'N' is name only.  */
@@ -305,32 +322,46 @@ cb_define (cpp_reader *pfile, fileline line, cpp_hashnode *node)
     fputs ((const char *) NODE_NAME (node), print.outf);
 
   putc ('\n', print.outf);
-  print.line++;
+  print.src_line++;
 }
 
 static void
-cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, fileline line,
+cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
          cpp_hashnode *node)
 {
-  maybe_print_line (print.map, line);
+  maybe_print_line (line);
   fprintf (print.outf, "#undef %s\n", NODE_NAME (node));
-  print.line++;
+  print.src_line++;
 }
 
 static void
-cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, fileline line,
-           const unsigned char *dir, const char *header, int angle_brackets)
+cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
+           const unsigned char *dir, const char *header, int angle_brackets,
+           const cpp_token **comments)
 {
-  maybe_print_line (print.map, line);
+  maybe_print_line (line);
   if (angle_brackets)
-    fprintf (print.outf, "#%s <%s>\n", dir, header);
+    fprintf (print.outf, "#%s <%s>", dir, header);
   else
-    fprintf (print.outf, "#%s \"%s\"\n", dir, header);
-  print.line++;
+    fprintf (print.outf, "#%s \"%s\"", dir, header);
+
+  if (comments != NULL)
+    {
+      while (*comments != NULL)
+       {
+         if ((*comments)->flags & PREV_WHITE)
+           putc (' ', print.outf);
+         cpp_output_token (*comments, print.outf);
+         ++comments;
+       }
+    }
+
+  putc ('\n', print.outf);
+  print.src_line++;
 }
 
 /* Callback called when -fworking-director and -E to emit working
-   diretory in cpp output file. */
+   directory in cpp output file.  */
 
 void
 pp_dir_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const char *dir)
@@ -339,15 +370,14 @@ pp_dir_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const char *dir)
   unsigned char *to_file_quoted = alloca (to_file_len * 4 + 1);
   unsigned char *p;
 
-  /* cpp_quote_string does not nul-terminate, so we have to do it ourselves. */
+  /* cpp_quote_string does not nul-terminate, so we have to do it ourselves.  */
   p = cpp_quote_string (to_file_quoted, (unsigned char *) dir, to_file_len);
   *p = '\0';
   fprintf (print.outf, "# 1 \"%s//\"\n", to_file_quoted);
 }
 
 /* The file name, line number or system header flags have changed, as
-   described in MAP.  From this point on, the old print.map might be
-   pointing to freed memory, and so must not be dereferenced.  */
+   described in MAP.  */
 
 void
 pp_file_change (const struct line_map *map)
@@ -359,38 +389,38 @@ pp_file_change (const struct line_map *map)
 
   if (map != NULL)
     {
-      /* First time?  */
-      if (print.map == NULL)
+      if (print.first_time)
        {
          /* Avoid printing foo.i when the main file is foo.c.  */
          if (!cpp_get_options (parse_in)->preprocessed)
-           print_line (map, map->from_line, flags);
+           print_line (map->start_location, flags);
+         print.first_time = 0;
        }
       else
        {
          /* Bring current file to correct line when entering a new file.  */
          if (map->reason == LC_ENTER)
-           maybe_print_line (map - 1, map->from_line - 1);
-
+           {
+             const struct line_map *from = INCLUDED_FROM (&line_table, map);
+             maybe_print_line (LAST_SOURCE_LINE_LOCATION (from));
+           }
          if (map->reason == LC_ENTER)
            flags = " 1";
          else if (map->reason == LC_LEAVE)
            flags = " 2";
-         print_line (map, map->from_line, flags);
+         print_line (map->start_location, flags);
        }
     }
-
-  print.map = map;
 }
 
 /* Copy a #pragma directive to the preprocessed output.  */
 static void
-cb_def_pragma (cpp_reader *pfile, fileline line)
+cb_def_pragma (cpp_reader *pfile, source_location line)
 {
-  maybe_print_line (print.map, line);
+  maybe_print_line (line);
   fputs ("#pragma ", print.outf);
   cpp_output_line (pfile, print.outf);
-  print.line++;
+  print.src_line++;
 }
 
 /* Dump out the hash table.  */
@@ -403,8 +433,24 @@ dump_macro (cpp_reader *pfile, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED)
       fputs ((const char *) cpp_macro_definition (pfile, node),
             print.outf);
       putc ('\n', print.outf);
-      print.line++;
+      print.src_line++;
     }
 
   return 1;
 }
+
+#if 0
+/* Load in the PCH file NAME, open on FD.  It was originally searched for
+   by ORIG_NAME.  Also, print out a #include command so that the PCH
+   file can be loaded when the preprocessed output is compiled.  */
+
+static void
+cb_read_pch (cpp_reader *pfile, const char *name,
+            int fd, const char *orig_name ATTRIBUTE_UNUSED)
+{
+  c_common_read_pch (pfile, name, fd, orig_name);
+
+  fprintf (print.outf, "#pragma GCC pch_preprocess \"%s\"\n", name);
+  print.src_line++;
+}
+#endif
\ No newline at end of file
index f4b744e0706c58793eef3c950b83f1589d8ce7e8..45f62ad40e90a6d0fb419f53c03893041d615916 100644 (file)
@@ -1,5 +1,5 @@
 /* Subroutines common to both C and C++ pretty-printers.
-   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
 
 This file is part of GCC.
@@ -16,11 +16,12 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "real.h"
 #include "c-pretty-print.h"
 
 /* The pretty-printer code is primarily designed to closely follow
@@ -37,24 +38,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
        pp_c_whitespace (PP);                 \
    } while (0)
 
-#define pp_c_left_bracket(PP)         \
-  do {                                \
-    pp_left_bracket (PP);             \
-    pp_base (PP)->padding = pp_none;  \
-  } while (0)
-
-#define pp_c_right_bracket(PP)        \
-  do {                                \
-    pp_right_bracket (PP);            \
-    pp_base (PP)->padding = pp_none;  \
-  } while (0)
-
-#define pp_c_star(PP)                 \
-  do {                                \
-    pp_star (PP);                     \
-    pp_base (PP)->padding = pp_none;  \
-  } while (0)
-
 /* literal  */
 static void pp_c_char (c_pretty_printer *, int);
 
@@ -114,6 +97,20 @@ pp_c_right_brace (c_pretty_printer *pp)
   pp_base (pp)->padding = pp_none;
 }
 
+void
+pp_c_left_bracket (c_pretty_printer *pp)
+{
+  pp_left_bracket (pp);
+  pp_base (pp)->padding = pp_none;
+}
+
+void
+pp_c_right_bracket (c_pretty_printer *pp)
+{
+  pp_right_bracket (pp);
+  pp_base (pp)->padding = pp_none;
+}
+
 void
 pp_c_dot (c_pretty_printer *pp)
 {
@@ -128,6 +125,13 @@ pp_c_ampersand (c_pretty_printer *pp)
   pp_base (pp)->padding = pp_none;
 }
 
+void
+pp_c_star (c_pretty_printer *pp)
+{
+  pp_star (pp);
+  pp_base (pp)->padding = pp_none;
+}
+
 void
 pp_c_arrow (c_pretty_printer *pp)
 {
@@ -136,17 +140,36 @@ pp_c_arrow (c_pretty_printer *pp)
 }
 
 void
-pp_c_semicolon(c_pretty_printer *pp)
+pp_c_semicolon (c_pretty_printer *pp)
 {
   pp_semicolon (pp);
   pp_base (pp)->padding = pp_none;
 }
 
+void
+pp_c_complement (c_pretty_printer *pp)
+{
+  pp_complement (pp);
+  pp_base (pp)->padding = pp_none;
+}
+
+void
+pp_c_exclamation (c_pretty_printer *pp)
+{
+  pp_exclamation (pp);
+  pp_base (pp)->padding = pp_none;
+}
+
+/* Print out the external representation of CV-QUALIFIER.  */
+
 static void
 pp_c_cv_qualifier (c_pretty_printer *pp, const char *cv)
 {
   const char *p = pp_last_position_in_text (pp);
-  if (p != NULL && *p == '*')
+  /* The C programming language does not have references, but it is much
+     simpler to handle those here rather than going through the same
+     logic in the C++ pretty-printer.  */
+  if (p != NULL && (*p == '*' || *p == '&'))
     pp_c_whitespace (pp);
   pp_c_identifier (pp, cv);
 }
@@ -161,6 +184,9 @@ pp_c_type_cast (c_pretty_printer *pp, tree t)
   pp_c_right_paren (pp);
 }
 
+/* We're about to pretty-print a pointer type as indicated by T.
+   Output a whitespace, if needed, preparing for subsequent output.  */
+
 void
 pp_c_space_for_pointer_operator (c_pretty_printer *pp, tree t)
 {
@@ -194,7 +220,7 @@ void
 pp_c_type_qualifier_list (c_pretty_printer *pp, tree t)
 {
    int qualifiers;
-   
+
   if (!TYPE_P (t))
     t = TREE_TYPE (t);
 
@@ -230,6 +256,13 @@ pp_c_pointer (c_pretty_printer *pp, tree t)
       pp_c_type_qualifier_list (pp, t);
       break;
 
+      /* ??? This node is now in GENERIC and so shouldn't be here.  But
+        we'll fix that later.  */
+    case DECL_EXPR:
+      pp_declaration (pp, DECL_EXPR_DECL (t));
+      pp_needs_newline (pp) = true;
+      break;
+
     default:
       pp_unsupported_tree (pp, t);
     }
@@ -268,7 +301,7 @@ pp_c_type_specifier (c_pretty_printer *pp, tree t)
       break;
 
     case IDENTIFIER_NODE:
-      pp_c_tree_identifier (pp, t);
+      pp_c_tree_decl_identifier (pp, t);
       break;
 
     case VOID_TYPE:
@@ -277,10 +310,42 @@ pp_c_type_specifier (c_pretty_printer *pp, tree t)
     case INTEGER_TYPE:
     case REAL_TYPE:
       if (TYPE_NAME (t))
-        t = TYPE_NAME (t);
+       {
+         t = TYPE_NAME (t);
+         pp_c_type_specifier (pp, t);
+       }
       else
-        t = c_common_type_for_mode (TYPE_MODE (t), TREE_UNSIGNED (t));
-      pp_c_type_specifier (pp, t);
+       {
+         int prec = TYPE_PRECISION (t);
+         t = c_common_type_for_mode (TYPE_MODE (t), TYPE_UNSIGNED (t));
+         if (TYPE_NAME (t))
+           {
+             pp_c_type_specifier (pp, t);
+             if (TYPE_PRECISION (t) != prec)
+               {
+                 pp_string (pp, ":");
+                 pp_decimal_int (pp, prec);
+               }
+           }
+         else
+           {
+             switch (code)
+               {
+               case INTEGER_TYPE:
+                 pp_string (pp, (TYPE_UNSIGNED (t)
+                                 ? "<unnamed-unsigned:"
+                                 : "<unnamed-signed:"));
+                 break;
+               case REAL_TYPE:
+                 pp_string (pp, "<unnamed-float:");
+                 break;
+               default:
+                 gcc_unreachable ();
+               }
+             pp_decimal_int (pp, prec);
+             pp_string (pp, ">");
+           }
+       }
       break;
 
     case TYPE_DECL:
@@ -346,6 +411,8 @@ pp_c_specifier_qualifier_list (c_pretty_printer *pp, tree t)
             pp_c_whitespace (pp);
             pp_c_left_paren (pp);
           }
+       else if (!c_dialect_cxx ())
+         pp_c_whitespace (pp);
         pp_ptr_operator (pp, t);
       }
       break;
@@ -441,7 +508,7 @@ pp_c_direct_abstract_declarator (c_pretty_printer *pp, tree t)
     case POINTER_TYPE:
       pp_abstract_declarator (pp, t);
       break;
-      
+
     case FUNCTION_TYPE:
       pp_c_parameter_type_list (pp, t);
       pp_direct_abstract_declarator (pp, TREE_TYPE (t));
@@ -449,7 +516,7 @@ pp_c_direct_abstract_declarator (c_pretty_printer *pp, tree t)
 
     case ARRAY_TYPE:
       pp_c_left_bracket (pp);
-      if (TYPE_DOMAIN (t))
+      if (TYPE_DOMAIN (t) && TYPE_MAX_VALUE (TYPE_DOMAIN (t)))
         pp_expression (pp, TYPE_MAX_VALUE (TYPE_DOMAIN (t)));
       pp_c_right_bracket (pp);
       pp_direct_abstract_declarator (pp, TREE_TYPE (t));
@@ -467,7 +534,7 @@ pp_c_direct_abstract_declarator (c_pretty_printer *pp, tree t)
     case COMPLEX_TYPE:
     case TYPE_DECL:
       break;
-      
+
     default:
       pp_unsupported_tree (pp, t);
       break;
@@ -536,7 +603,7 @@ pp_c_declaration_specifiers (c_pretty_printer *pp, tree t)
       direct-declarator [ static type-qualifier-list(opt) assignment-expression(opt)]
       direct-declarator [ type-qualifier-list static assignment-expression ]
       direct-declarator [ type-qualifier-list * ]
-      direct-declaratpr ( parameter-type-list )
+      direct-declarator ( parameter-type-list )
       direct-declarator ( identifier-list(opt) )  */
 
 void
@@ -549,11 +616,10 @@ pp_c_direct_declarator (c_pretty_printer *pp, tree t)
     case TYPE_DECL:
     case FIELD_DECL:
     case LABEL_DECL:
-      if (DECL_NAME (t))
-        {
-          pp_c_space_for_pointer_operator (pp, TREE_TYPE (t));
-          pp_c_tree_identifier (pp, DECL_NAME (t));
-        }
+      pp_c_space_for_pointer_operator (pp, TREE_TYPE (t));
+      pp_c_tree_decl_identifier (pp, t);
+      break;
+
     case ARRAY_TYPE:
     case POINTER_TYPE:
       pp_abstract_declarator (pp, TREE_TYPE (t));
@@ -566,7 +632,7 @@ pp_c_direct_declarator (c_pretty_printer *pp, tree t)
 
     case FUNCTION_DECL:
       pp_c_space_for_pointer_operator (pp, TREE_TYPE (TREE_TYPE (t)));
-      pp_c_tree_identifier (pp, DECL_NAME (t));
+      pp_c_tree_decl_identifier (pp, t);
       if (pp_c_base (pp)->flags & pp_c_flag_abstract)
         pp_abstract_declarator (pp, TREE_TYPE (t));
       else
@@ -615,7 +681,7 @@ pp_c_declarator (c_pretty_printer *pp, tree t)
       pp_direct_declarator (pp, t);
     break;
 
-    
+
     default:
       pp_unsupported_tree (pp, t);
       break;
@@ -673,50 +739,37 @@ pp_c_function_definition (c_pretty_printer *pp, tree t)
 \f
 /* Expressions.  */
 
-/* Print out a c-char.  */
+/* Print out a c-char.  This is called solely for characters which are
+   in the *target* execution character set.  We ought to convert them
+   back to the *host* execution character set before printing, but we
+   have no way to do this at present.  A decent compromise is to print
+   all characters as if they were in the host execution character set,
+   and not attempt to recover any named escape characters, but render
+   all unprintables as octal escapes.  If the host and target character
+   sets are the same, this produces relatively readable output.  If they
+   are not the same, strings may appear as gibberish, but that's okay
+   (in fact, it may well be what the reader wants, e.g. if they are looking
+   to see if conversion to the target character set happened correctly).
+
+   A special case: we need to prefix \, ", and ' with backslashes.  It is
+   correct to do so for the *host*'s \, ", and ', because the rest of the
+   file appears in the host character set.  */
 
 static void
 pp_c_char (c_pretty_printer *pp, int c)
 {
-  switch (c)
+  if (ISPRINT (c))
     {
-    case TARGET_NEWLINE:
-      pp_string (pp, "\\n");
-      break;
-    case TARGET_TAB:
-      pp_string (pp, "\\t");
-      break;
-    case TARGET_VT:
-      pp_string (pp, "\\v");
-      break;
-    case TARGET_BS:
-      pp_string (pp, "\\b");
-      break;
-    case TARGET_CR:
-      pp_string (pp, "\\r");
-      break;
-    case TARGET_FF:
-      pp_string (pp, "\\f");
-      break;
-    case TARGET_BELL:
-      pp_string (pp, "\\a");
-      break;
-    case '\\':
-      pp_string (pp, "\\\\");
-      break;
-    case '\'':
-      pp_string (pp, "\\'");
-      break;
-    case '\"':
-      pp_string (pp, "\\\"");
-      break;
-    default:
-      if (ISPRINT (c))
-       pp_character (pp, c);
-      else
-       pp_scalar (pp, "\\%03o", (unsigned) c);
-      break;
+      switch (c)
+       {
+       case '\\': pp_string (pp, "\\\\"); break;
+       case '\'': pp_string (pp, "\\\'"); break;
+       case '\"': pp_string (pp, "\\\""); break;
+       default:   pp_character (pp, c);
+       }
     }
+  else
+    pp_scalar (pp, "\\%03o", (unsigned) c);
 }
 
 /* Print out a STRING literal.  */
@@ -733,6 +786,8 @@ pp_c_string_literal (c_pretty_printer *pp, tree s)
   pp_doublequote (pp);
 }
 
+/* Pretty-print an INTEGER literal.  */
+
 static void
 pp_c_integer_constant (c_pretty_printer *pp, tree i)
 {
@@ -744,16 +799,18 @@ pp_c_integer_constant (c_pretty_printer *pp, tree i)
     {
       if (tree_int_cst_sgn (i) < 0)
         {
-          pp_c_char (pp, '-');
-          i = build_int_2 (-TREE_INT_CST_LOW (i),
-                           ~TREE_INT_CST_HIGH (i) + !TREE_INT_CST_LOW (i));
+          pp_character (pp, '-');
+          i = build_int_cst_wide (NULL_TREE,
+                                 -TREE_INT_CST_LOW (i),
+                                 ~TREE_INT_CST_HIGH (i)
+                                 + !TREE_INT_CST_LOW (i));
         }
       sprintf (pp_buffer (pp)->digit_buffer,
                HOST_WIDE_INT_PRINT_DOUBLE_HEX,
                TREE_INT_CST_HIGH (i), TREE_INT_CST_LOW (i));
       pp_string (pp, pp_buffer (pp)->digit_buffer);
     }
-  if (TREE_UNSIGNED (type))
+  if (TYPE_UNSIGNED (type))
     pp_character (pp, 'u');
   if (type == long_integer_type_node || type == long_unsigned_type_node)
     pp_character (pp, 'l');
@@ -769,10 +826,10 @@ pp_c_character_constant (c_pretty_printer *pp, tree c)
 {
   tree type = TREE_TYPE (c);
   if (type == wchar_type_node)
-    pp_character (pp, 'L'); 
+    pp_character (pp, 'L');
   pp_quote (pp);
-  if (host_integerp (c, TREE_UNSIGNED (type)))
-    pp_c_char (pp, tree_low_cst (c, TREE_UNSIGNED (type)));
+  if (host_integerp (c, TYPE_UNSIGNED (type)))
+    pp_c_char (pp, tree_low_cst (c, TYPE_UNSIGNED (type)));
   else
     pp_scalar (pp, "\\x%x", (unsigned) TREE_INT_CST_LOW (c));
   pp_quote (pp);
@@ -852,12 +909,12 @@ pp_c_floating_constant (c_pretty_printer *pp, tree r)
 }
 
 /* Pretty-print a compound literal expression.  GNU extensions include
-   vector constants.  */ 
+   vector constants.  */
 
 static void
 pp_c_compound_literal (c_pretty_printer *pp, tree e)
 {
-  tree type = TREE_TYPE (e);  
+  tree type = TREE_TYPE (e);
   pp_c_type_cast (pp, type);
 
   switch (TREE_CODE (type))
@@ -898,8 +955,8 @@ pp_c_constant (c_pretty_printer *pp, tree e)
           pp_c_character_constant (pp, e);
         else if (TREE_CODE (type) == ENUMERAL_TYPE
                  && pp_c_enumeration_constant (pp, e))
-          ; 
-        else 
+          ;
+        else
           pp_c_integer_constant (pp, e);
       }
       break;
@@ -918,11 +975,13 @@ pp_c_constant (c_pretty_printer *pp, tree e)
     }
 }
 
+/* Pretty-print an IDENTIFIER_NODE, preceded by whitespace is necessary.  */
+
 void
 pp_c_identifier (c_pretty_printer *pp, const char *id)
 {
-  pp_c_maybe_whitespace (pp);            
-  pp_identifier (pp, id);  
+  pp_c_maybe_whitespace (pp);
+  pp_identifier (pp, id);
   pp_base (pp)->padding = pp_before;
 }
 
@@ -944,8 +1003,9 @@ pp_c_primary_expression (c_pretty_printer *pp, tree e)
     case CONST_DECL:
     case FUNCTION_DECL:
     case LABEL_DECL:
-      e = DECL_NAME (e);
-      /* Fall through.  */
+      pp_c_tree_decl_identifier (pp, e);
+      break;
+
     case IDENTIFIER_NODE:
       pp_c_tree_identifier (pp, e);
       break;
@@ -964,9 +1024,19 @@ pp_c_primary_expression (c_pretty_printer *pp, tree e)
       pp_c_constant (pp, e);
       break;
 
-    case STMT_EXPR:
+    case TARGET_EXPR:
+      pp_c_identifier (pp, "__builtin_memcpy");
       pp_c_left_paren (pp);
-      pp_statement (pp, STMT_EXPR_STMT (e));
+      pp_ampersand (pp);
+      pp_primary_expression (pp, TREE_OPERAND (e, 0));
+      pp_separate_with (pp, ',');
+      pp_ampersand (pp);
+      pp_initializer (pp, TREE_OPERAND (e, 1));
+      if (TREE_OPERAND (e, 2))
+       {
+         pp_separate_with (pp, ',');
+         pp_c_expression (pp, TREE_OPERAND (e, 2));
+       }
       pp_c_right_paren (pp);
       break;
 
@@ -989,13 +1059,7 @@ static void
 pp_c_initializer (c_pretty_printer *pp, tree e)
 {
   if (TREE_CODE (e) == CONSTRUCTOR)
-    {
-      enum tree_code code = TREE_CODE (TREE_TYPE (e));
-      if (code == RECORD_TYPE || code == UNION_TYPE || code == ARRAY_TYPE)
-        pp_c_brace_enclosed_initializer_list (pp, e);
-      else
-       pp_unsupported_tree (pp, TREE_OPERAND (e, 1));
-    }
+    pp_c_brace_enclosed_initializer_list (pp, e);
   else
     pp_expression (pp, e);
 }
@@ -1008,7 +1072,9 @@ void
 pp_c_init_declarator (c_pretty_printer *pp, tree t)
 {
   pp_declarator (pp, t);
-  if (DECL_INITIAL (t))
+  /* We don't want to output function definitions here.  There are handled
+     elsewhere (and the syntactic form is bogus anyway).  */
+  if (TREE_CODE (t) != FUNCTION_DECL && DECL_INITIAL (t))
     {
       tree init = DECL_INITIAL (t);
       /* This C++ bit is handled here because it is easier to do so.
@@ -1081,25 +1147,36 @@ pp_c_initializer_list (c_pretty_printer *pp, tree e)
               pp_separate_with (pp, ',');
           }
       }
-      break;
+      return;
 
     case VECTOR_TYPE:
-      pp_c_expression_list (pp, TREE_VECTOR_CST_ELTS (e));
-      break;
+      if (TREE_CODE (e) == VECTOR_CST)
+        pp_c_expression_list (pp, TREE_VECTOR_CST_ELTS (e));
+      else if (TREE_CODE (e) == CONSTRUCTOR)
+        pp_c_constructor_elts (pp, CONSTRUCTOR_ELTS (e));
+      else
+        break;
+      return;
 
     case COMPLEX_TYPE:
-      {
-        const bool cst = TREE_CODE (e) == COMPLEX_CST;
-        pp_expression (pp, cst ? TREE_REALPART (e) : TREE_OPERAND (e, 0));
-        pp_separate_with (pp, ',');
-        pp_expression (pp, cst ? TREE_IMAGPART (e) : TREE_OPERAND (e, 1));
-      }
-      break;
+      if (TREE_CODE (e) == CONSTRUCTOR)
+       pp_c_constructor_elts (pp, CONSTRUCTOR_ELTS (e));
+      else if (TREE_CODE (e) == COMPLEX_CST || TREE_CODE (e) == COMPLEX_EXPR)
+       {
+         const bool cst = TREE_CODE (e) == COMPLEX_CST;
+         pp_expression (pp, cst ? TREE_REALPART (e) : TREE_OPERAND (e, 0));
+         pp_separate_with (pp, ',');
+         pp_expression (pp, cst ? TREE_IMAGPART (e) : TREE_OPERAND (e, 1));
+       }
+      else
+       break;
+      return;
 
     default:
-      pp_unsupported_tree (pp, type);
       break;
     }
+
+  pp_unsupported_tree (pp, type);
 }
 
 /* Pretty-print a brace-enclosed initializer-list.  */
@@ -1131,7 +1208,9 @@ pp_c_id_expression (c_pretty_printer *pp, tree t)
     case FUNCTION_DECL:
     case FIELD_DECL:
     case LABEL_DECL:
-      t = DECL_NAME (t);
+      pp_c_tree_decl_identifier (pp, t);
+      break;
+
     case IDENTIFIER_NODE:
       pp_c_tree_identifier (pp, t);
       break;
@@ -1165,11 +1244,6 @@ pp_c_postfix_expression (c_pretty_printer *pp, tree e)
       pp_identifier (pp, code == POSTINCREMENT_EXPR ? "++" : "--");
       break;
 
-    case ARROW_EXPR:
-      pp_postfix_expression (pp, TREE_OPERAND (e, 0));
-      pp_c_arrow (pp);
-      break;
-
     case ARRAY_REF:
       pp_postfix_expression (pp, TREE_OPERAND (e, 0));
       pp_c_left_bracket (pp);
@@ -1182,6 +1256,62 @@ pp_c_postfix_expression (c_pretty_printer *pp, tree e)
       pp_c_call_argument_list (pp, TREE_OPERAND (e, 1));
       break;
 
+    case UNORDERED_EXPR:
+      pp_c_identifier (pp, flag_isoc99
+                          ? "isunordered"
+                          : "__builtin_isunordered");
+      goto two_args_fun;
+
+    case ORDERED_EXPR:
+      pp_c_identifier (pp, flag_isoc99
+                          ? "!isunordered"
+                          : "!__builtin_isunordered");
+      goto two_args_fun;
+
+    case UNLT_EXPR:
+      pp_c_identifier (pp, flag_isoc99
+                          ? "!isgreaterequal"
+                          : "!__builtin_isgreaterequal");
+      goto two_args_fun;
+
+    case UNLE_EXPR:
+      pp_c_identifier (pp, flag_isoc99
+                          ? "!isgreater"
+                          : "!__builtin_isgreater");
+      goto two_args_fun;
+
+    case UNGT_EXPR:
+      pp_c_identifier (pp, flag_isoc99
+                          ? "!islessequal"
+                          : "!__builtin_islessequal");
+      goto two_args_fun;
+
+    case UNGE_EXPR:
+      pp_c_identifier (pp, flag_isoc99
+                          ? "!isless"
+                          : "!__builtin_isless");
+      goto two_args_fun;
+
+    case UNEQ_EXPR:
+      pp_c_identifier (pp, flag_isoc99
+                          ? "!islessgreater"
+                          : "!__builtin_islessgreater");
+      goto two_args_fun;
+
+    case LTGT_EXPR:
+      pp_c_identifier (pp, flag_isoc99
+                          ? "islessgreater"
+                          : "__builtin_islessgreater");
+      goto two_args_fun;
+
+    two_args_fun:
+      pp_c_left_paren (pp);
+      pp_expression (pp, TREE_OPERAND (e, 0));
+      pp_separate_with (pp, ',');
+      pp_expression (pp, TREE_OPERAND (e, 1));
+      pp_c_right_paren (pp);
+      break;
+
     case ABS_EXPR:
       pp_c_identifier (pp, "__builtin_abs");
       pp_c_left_paren (pp);
@@ -1255,6 +1385,22 @@ pp_c_expression_list (c_pretty_printer *pp, tree e)
     }
 }
 
+/* Print out V, which contains the elements of a constructor.  */
+
+void
+pp_c_constructor_elts (c_pretty_printer *pp, VEC(constructor_elt,gc) *v)
+{
+  unsigned HOST_WIDE_INT ix;
+  tree value;
+
+  FOR_EACH_CONSTRUCTOR_VALUE (v, ix, value)
+    {
+      pp_expression (pp, value);
+      if (ix != VEC_length (constructor_elt, v) - 1)
+       pp_separate_with (pp, ',');
+    }
+}
+
 /* Print out an expression-list in parens, as in a function call.  */
 
 void
@@ -1276,7 +1422,7 @@ pp_c_call_argument_list (c_pretty_printer *pp, tree t)
 
   unary-operator: one of
       * &  + - ! ~
-      
+
    GNU extensions.
    unary-expression:
       __alignof__ unary-expression
@@ -1316,16 +1462,6 @@ pp_c_unary_expression (c_pretty_printer *pp, tree e)
       pp_c_cast_expression (pp, TREE_OPERAND (e, 0));
       break;
 
-    case SIZEOF_EXPR:
-    case ALIGNOF_EXPR:
-      pp_c_identifier (pp, code == SIZEOF_EXPR ? "sizeof" : "__alignof__");
-      pp_c_whitespace (pp);
-      if (TYPE_P (TREE_OPERAND (e, 0)))
-        pp_c_type_cast (pp, TREE_OPERAND (e, 0));
-      else
-       pp_unary_expression (pp, TREE_OPERAND (e, 0));
-      break;
-
     case REALPART_EXPR:
     case IMAGPART_EXPR:
       pp_c_identifier (pp, code == REALPART_EXPR ? "__real__" : "__imag__");
@@ -1413,7 +1549,7 @@ pp_c_additive_expression (c_pretty_printer *pp, tree e)
       else
        pp_minus (pp);
       pp_c_whitespace (pp);
-      pp_multiplicative_expression (pp, TREE_OPERAND (e, 1)); 
+      pp_multiplicative_expression (pp, TREE_OPERAND (e, 1));
       break;
 
     default:
@@ -1631,7 +1767,7 @@ pp_c_conditional_expression (c_pretty_printer *pp, tree e)
 
 /* assignment-expression:
       conditional-expression
-      unary-expression assignment-operator  assignment-expression 
+      unary-expression assignment-operator  assignment-expression
 
    assignment-expression: one of
       =    *=    /=    %=    +=    -=    >>=    <<=    &=    ^=    |=  */
@@ -1687,19 +1823,25 @@ pp_c_expression (c_pretty_printer *pp, tree e)
     case FIELD_DECL:
     case LABEL_DECL:
     case ERROR_MARK:
-    case STMT_EXPR:
       pp_primary_expression (pp, e);
       break;
 
     case POSTINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
-    case ARROW_EXPR:
     case ARRAY_REF:
     case CALL_EXPR:
     case COMPONENT_REF:
     case COMPLEX_CST:
     case COMPLEX_EXPR:
     case VECTOR_CST:
+    case ORDERED_EXPR:
+    case UNORDERED_EXPR:
+    case LTGT_EXPR:
+    case UNEQ_EXPR:
+    case UNLE_EXPR:
+    case UNLT_EXPR:
+    case UNGE_EXPR:
+    case UNGT_EXPR:
     case ABS_EXPR:
     case CONSTRUCTOR:
     case COMPOUND_LITERAL_EXPR:
@@ -1715,8 +1857,6 @@ pp_c_expression (c_pretty_printer *pp, tree e)
     case TRUTH_NOT_EXPR:
     case PREINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
-    case SIZEOF_EXPR:
-    case ALIGNOF_EXPR:
     case REALPART_EXPR:
     case IMAGPART_EXPR:
       pp_c_unary_expression (pp, e);
@@ -1770,7 +1910,7 @@ pp_c_expression (c_pretty_printer *pp, tree e)
     case NE_EXPR:
       pp_c_equality_expression (pp, e);
       break;
-      
+
     case COND_EXPR:
       pp_conditional_expression (pp, e);
       break;
@@ -1796,14 +1936,13 @@ pp_c_expression (c_pretty_printer *pp, tree e)
     case NOP_EXPR:
     case NON_LVALUE_EXPR:
     case SAVE_EXPR:
-    case UNSAVE_EXPR:
       pp_expression (pp, TREE_OPERAND (e, 0));
       break;
 
     case TARGET_EXPR:
       pp_postfix_expression (pp, TREE_OPERAND (e, 1));
       break;
-      
+
     default:
       pp_unsupported_tree (pp, e);
       break;
@@ -1814,308 +1953,16 @@ pp_c_expression (c_pretty_printer *pp, tree e)
 \f
 /* Statements.  */
 
-/* statement:
-      labeled-statement
-      compound-statement
-      expression-statement
-      selection-statement
-      iteration-statement
-      jump-statement   */
-
 void
 pp_c_statement (c_pretty_printer *pp, tree stmt)
 {
-  enum tree_code code;
-
   if (stmt == NULL)
     return;
-  
-  code = TREE_CODE (stmt);
-  switch (code)
-    {
-       /* labeled-statement:
-             identifier : statement
-             case constant-expression : statement
-             default : statement   */
-    case LABEL_STMT:
-    case CASE_LABEL:
-      if (pp_needs_newline (pp))
-        pp_newline_and_indent (pp, -3);
-      else
-        pp_indentation (pp) -= 3;
-      if (code == LABEL_STMT)
-       pp_tree_identifier (pp, DECL_NAME (LABEL_STMT_LABEL (stmt)));
-      else if (code == CASE_LABEL)
-       {
-         if (CASE_LOW (stmt) == NULL_TREE)
-           pp_identifier (pp, "default");
-         else
-           {
-             pp_c_identifier (pp, "case");
-             pp_c_whitespace (pp);
-             pp_conditional_expression (pp, CASE_LOW (stmt));
-             if (CASE_HIGH (stmt))
-               {
-                 pp_identifier (pp, "...");
-                 pp_conditional_expression (pp, CASE_HIGH (stmt));
-               }
-           }
-       }
-      pp_colon (pp);
-      pp_indentation (pp) += 3;
-      pp_needs_newline (pp) = true;
-      break;
 
-      /* compound-statement:
-            {  block-item-list(opt) }
-
-         block-item-list:
-            block-item
-            block-item-list block-item
-
-         block-item:
-            declaration
-            statement   */
-    case COMPOUND_STMT:
-      if (pp_needs_newline (pp))
-        pp_newline_and_indent (pp, 0);
-      pp_c_left_brace (pp);
-      pp_newline_and_indent (pp, 3);
-      for (stmt = COMPOUND_BODY (stmt); stmt; stmt = TREE_CHAIN (stmt))
-       pp_statement (pp, stmt);
-      pp_newline_and_indent (pp, -3);
-      pp_c_right_brace (pp);
-      pp_needs_newline (pp) = true;
-      break;
+  if (pp_needs_newline (pp))
+    pp_newline_and_indent (pp, 0);
 
-      /* expression-statement:
-            expression(opt) ;  */
-    case EXPR_STMT:
-    case CLEANUP_STMT:
-      if (pp_needs_newline (pp))
-        pp_newline_and_indent (pp, 0);
-      {
-        tree e = code == EXPR_STMT
-          ? EXPR_STMT_EXPR (stmt)
-          : CLEANUP_EXPR (stmt);
-        if (e)
-          pp_expression (pp, e);
-      }
-      pp_c_semicolon (pp);
-      pp_needs_newline (pp) = true;
-      break;
-
-      /* selection-statement:
-            if ( expression ) statement
-            if ( expression ) statement else statement
-            switch ( expression ) statement   */
-    case IF_STMT:
-      if (pp_needs_newline (pp))
-        pp_newline_and_indent (pp, 0);
-      pp_c_identifier (pp, "if");
-      pp_c_whitespace (pp);
-      pp_c_left_paren (pp);
-      pp_expression (pp, IF_COND (stmt));
-      pp_c_right_paren (pp);
-      pp_newline_and_indent (pp, 3);
-      pp_statement (pp, THEN_CLAUSE (stmt));
-      pp_newline_and_indent (pp, -3);
-      if (ELSE_CLAUSE (stmt))
-       {
-         tree else_clause = ELSE_CLAUSE (stmt);
-         pp_c_identifier (pp, "else");
-         if (TREE_CODE (else_clause) == IF_STMT)
-           pp_c_whitespace (pp);
-         else
-           pp_newline_and_indent (pp, 3);
-         pp_statement (pp, else_clause);
-         if (TREE_CODE (else_clause) != IF_STMT)
-           pp_newline_and_indent (pp, -3);
-       }
-      break;
-
-    case SWITCH_STMT:
-      if (pp_needs_newline (pp))
-        pp_newline_and_indent (pp, 0);
-      pp_c_identifier (pp, "switch");
-      pp_space (pp);
-      pp_c_left_paren (pp);
-      pp_expression (pp, SWITCH_COND (stmt));
-      pp_c_right_paren (pp);
-      pp_indentation (pp) += 3;
-      pp_needs_newline (pp) = true;
-      pp_statement (pp, SWITCH_BODY (stmt));
-      pp_newline_and_indent (pp, -3);
-      break;
-
-      /* iteration-statement:
-            while ( expression ) statement
-            do statement while ( expression ) ;
-            for ( expression(opt) ; expression(opt) ; expression(opt) ) statement
-            for ( declaration expression(opt) ; expression(opt) ) statement  */
-    case WHILE_STMT:
-      if (pp_needs_newline (pp))
-        pp_newline_and_indent (pp, 0);
-      pp_c_identifier (pp, "while");
-      pp_space (pp);
-      pp_c_left_paren (pp);
-      pp_expression (pp, WHILE_COND (stmt));
-      pp_c_right_paren (pp);
-      pp_newline_and_indent (pp, 3);
-      pp_statement (pp, WHILE_BODY (stmt));
-      pp_indentation (pp) -= 3;
-      pp_needs_newline (pp) = true;
-      break;
-
-    case DO_STMT:
-      if (pp_needs_newline (pp))
-        pp_newline_and_indent (pp, 0);
-      pp_c_identifier (pp, "do");
-      pp_newline_and_indent (pp, 3);
-      pp_statement (pp, DO_BODY (stmt));
-      pp_newline_and_indent (pp, -3);
-      pp_c_identifier (pp, "while");
-      pp_space (pp);
-      pp_c_left_paren (pp);
-      pp_expression (pp, DO_COND (stmt));
-      pp_c_right_paren (pp);
-      pp_c_semicolon (pp);
-      pp_needs_newline (pp) = true;
-      break;
-
-    case FOR_STMT:
-      if (pp_needs_newline (pp))
-        pp_newline_and_indent (pp, 0);
-      pp_c_identifier (pp, "for");
-      pp_space (pp);
-      pp_c_left_paren (pp);
-      if (FOR_INIT_STMT (stmt))
-        pp_statement (pp, FOR_INIT_STMT (stmt));
-      else
-        pp_c_semicolon (pp);
-      pp_needs_newline (pp) = false;
-      pp_c_whitespace (pp);
-      if (FOR_COND (stmt))
-       pp_expression (pp, FOR_COND (stmt));
-      pp_c_semicolon (pp);
-      pp_needs_newline (pp) = false;
-      pp_c_whitespace (pp);
-      if (FOR_EXPR (stmt))
-       pp_expression (pp, FOR_EXPR (stmt));
-      pp_c_right_paren (pp);
-      pp_newline_and_indent (pp, 3);
-      pp_statement (pp, FOR_BODY (stmt));
-      pp_indentation (pp) -= 3;
-      pp_needs_newline (pp) = true;
-      break;
-
-      /* jump-statement:
-            goto identifier;
-            continue ;
-            return expression(opt) ;  */
-    case BREAK_STMT:
-    case CONTINUE_STMT:
-      if (pp_needs_newline (pp))
-        pp_newline_and_indent (pp, 0);
-      pp_identifier (pp, code == BREAK_STMT ? "break" : "continue");
-      pp_c_semicolon (pp);
-      pp_needs_newline (pp) = true;
-      break;
-
-    case RETURN_STMT:
-    case GOTO_STMT:
-      {
-       tree e = code == RETURN_STMT
-         ? RETURN_STMT_EXPR (stmt)
-         : GOTO_DESTINATION (stmt);
-        if (pp_needs_newline (pp))
-          pp_newline_and_indent (pp, 0);
-       pp_c_identifier (pp, code == RETURN_STMT ? "return" : "goto");
-        pp_c_whitespace (pp);
-       if (e)
-          {
-            if (TREE_CODE (e) == INIT_EXPR
-                && TREE_CODE (TREE_OPERAND (e, 0)) == RESULT_DECL)
-              e = TREE_OPERAND (e, 1);
-            pp_expression (pp, e);
-          }
-       pp_c_semicolon (pp);
-       pp_needs_newline (pp) = true;
-      }
-      break;
-
-    case SCOPE_STMT:
-      if (!SCOPE_NULLIFIED_P (stmt) && SCOPE_NO_CLEANUPS_P (stmt))
-        {
-          int i = 0;
-          if (pp_needs_newline (pp))
-            pp_newline_and_indent (pp, 0);
-          if (SCOPE_BEGIN_P (stmt))
-            {
-              pp_left_brace (pp);
-              i = 3;
-            }
-          else if (SCOPE_END_P (stmt))
-            {
-              pp_right_brace (pp);
-              i = -3;
-            }
-          pp_indentation (pp) += i;
-          pp_needs_newline (pp) = true;
-        }
-      break;
-
-    case DECL_STMT:
-      if (pp_needs_newline (pp))
-        pp_newline_and_indent (pp, 0);
-      pp_declaration (pp, DECL_STMT_DECL (stmt));
-      pp_needs_newline (pp) = true;
-      break;
-
-    case ASM_STMT:
-      {
-       bool has_volatile_p = ASM_VOLATILE_P (stmt);
-       bool is_extended = has_volatile_p || ASM_INPUTS (stmt)
-         || ASM_OUTPUTS (stmt) || ASM_CLOBBERS (stmt);
-       pp_c_identifier (pp, is_extended ? "__asm__" : "asm");
-       if (has_volatile_p)
-         pp_c_identifier (pp, "__volatile__");
-       pp_space (pp);
-       pp_c_left_paren (pp);
-       pp_c_string_literal (pp, ASM_STRING (stmt));
-       if (is_extended)
-         {
-           pp_space (pp);
-           pp_separate_with (pp, ':');
-           if (ASM_OUTPUTS (stmt))
-             pp_expression (pp, ASM_OUTPUTS (stmt));
-           pp_space (pp);
-           pp_separate_with (pp, ':');
-           if (ASM_INPUTS (stmt))
-             pp_expression (pp, ASM_INPUTS (stmt));
-           pp_space (pp);
-           pp_separate_with (pp, ':');
-           if (ASM_CLOBBERS (stmt))
-             pp_expression (pp, ASM_CLOBBERS (stmt));
-         }
-       pp_c_right_paren (pp);
-       pp_newline (pp);
-      }
-      break;
-
-    case FILE_STMT:
-      pp_c_identifier (pp, "__FILE__");
-      pp_space (pp);
-      pp_equal (pp);
-      pp_c_whitespace (pp);
-      pp_c_identifier (pp, FILE_STMT_FILENAME (stmt));
-      pp_c_semicolon (pp);
-      pp_needs_newline (pp) = true;
-      break;
-
-    default:
-      pp_unsupported_tree (pp, stmt);
-    }
+  dump_generic_node (pp_base (pp), stmt, pp_indentation (pp), 0, true);
 }
 
 \f
@@ -2152,3 +1999,59 @@ pp_c_pretty_printer_init (c_pretty_printer *pp)
   pp->assignment_expression     = pp_c_assignment_expression;
   pp->expression                = pp_c_expression;
 }
+
+
+/* Print the tree T in full, on file FILE.  */
+
+void
+print_c_tree (FILE *file, tree t)
+{
+  static c_pretty_printer pp_rec;
+  static bool initialized = 0;
+  c_pretty_printer *pp = &pp_rec;
+
+  if (!initialized)
+    {
+      initialized = 1;
+      pp_construct (pp_base (pp), NULL, 0);
+      pp_c_pretty_printer_init (pp);
+      pp_needs_newline (pp) = true;
+    }
+  pp_base (pp)->buffer->stream = file;
+
+  pp_statement (pp, t);
+
+  pp_newline (pp);
+  pp_flush (pp);
+}
+
+/* Print the tree T in full, on stderr.  */
+
+void
+debug_c_tree (tree t)
+{
+  print_c_tree (stderr, t);
+  fputc ('\n', stderr);
+}
+
+/* Output the DECL_NAME of T.  If T has no DECL_NAME, output a string made
+   up of T's memory address.  */
+
+void
+pp_c_tree_decl_identifier (c_pretty_printer *pp, tree t)
+{
+  const char *name;
+
+  gcc_assert (DECL_P (t));
+
+  if (DECL_NAME (t))
+    name = IDENTIFIER_POINTER (DECL_NAME (t));
+  else
+    {
+      static char xname[8];
+      sprintf (xname, "<U%4x>", ((unsigned)((unsigned long)(t) & 0xffff)));
+      name = xname;
+    }
+
+  pp_c_identifier (pp, name);
+}
index e9084b3ef711248bb34e0028b57f7c87ef7119d5..2b9add61b1fa1c5ef02c894c33b68fe066eabccd 100644 (file)
@@ -1,5 +1,5 @@
 /* Various declarations for the C and C++ pretty-printers.
-   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
 
 This file is part of GCC.
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #ifndef GCC_C_PRETTY_PRINTER
 #define GCC_C_PRETTY_PRINTER
@@ -28,7 +28,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 typedef enum
   {
      pp_c_flag_abstract = 1 << 1,
-     pp_c_flag_last_bit = 2    
+     pp_c_flag_last_bit = 2
   } pp_c_pretty_print_flags;
 
 
@@ -58,7 +58,7 @@ struct c_pretty_print_info
   int *offset_list;
 
   pp_flags flags;
-   
+
   /* These must be overridden by each of the C and C++ front-end to
      reflect their understanding of syntactic productions when they differ.  */
   c_pretty_print_fn declaration;
@@ -93,7 +93,7 @@ struct c_pretty_print_info
 #undef pp_base
 #define pp_base(PP)  (&pp_c_base (PP)->base)
 
-     
+
 #define pp_c_tree_identifier(PPI, ID)              \
    pp_c_identifier (PPI, IDENTIFIER_POINTER (ID))
 
@@ -157,13 +157,19 @@ void pp_c_left_paren (c_pretty_printer *);
 void pp_c_right_paren (c_pretty_printer *);
 void pp_c_left_brace (c_pretty_printer *);
 void pp_c_right_brace (c_pretty_printer *);
+void pp_c_left_bracket (c_pretty_printer *);
+void pp_c_right_bracket (c_pretty_printer *);
 void pp_c_dot (c_pretty_printer *);
 void pp_c_ampersand (c_pretty_printer *);
+void pp_c_star (c_pretty_printer *);
 void pp_c_arrow (c_pretty_printer *);
 void pp_c_semicolon (c_pretty_printer *);
+void pp_c_complement (c_pretty_printer *);
+void pp_c_exclamation (c_pretty_printer *);
 void pp_c_space_for_pointer_operator (c_pretty_printer *, tree);
 
 /* Declarations.  */
+void pp_c_tree_decl_identifier (c_pretty_printer *, tree);
 void pp_c_function_definition (c_pretty_printer *, tree);
 void pp_c_attributes (c_pretty_printer *, tree);
 void pp_c_type_qualifier_list (c_pretty_printer *, tree);
@@ -184,6 +190,7 @@ void pp_c_statement (c_pretty_printer *, tree);
 void pp_c_expression (c_pretty_printer *, tree);
 void pp_c_logical_or_expression (c_pretty_printer *, tree);
 void pp_c_expression_list (c_pretty_printer *, tree);
+////void pp_c_constructor_elts (c_pretty_printer *, VEC(constructor_elt,gc) *);
 void pp_c_call_argument_list (c_pretty_printer *, tree);
 void pp_c_unary_expression (c_pretty_printer *, tree);
 void pp_c_cast_expression (c_pretty_printer *, tree);
@@ -195,4 +202,6 @@ void pp_c_id_expression (c_pretty_printer *, tree);
 void pp_c_identifier (c_pretty_printer *, const char *);
 void pp_c_string_literal (c_pretty_printer *, tree);
 
+void print_c_tree (FILE *file, tree t);
+
 #endif /* GCC_C_PRETTY_PRINTER */
diff --git a/support/cpp2/cppcharset.c b/support/cpp2/cppcharset.c
deleted file mode 100644 (file)
index a6a65ed..0000000
+++ /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, /* XXX 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, /* XXX 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;
-}
-
-\f
-
-/* 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;
-}
-\f
-/* 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 *in,
-                                  cpp_string *out)
-{
-  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, in, 1, out, false);
-
-  pfile->narrow_cset_desc = save_narrow_cset_desc;
-  return retval;
-}
-
-\f
-/* 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;
-}
index 60b215372a73b29bd7d12b02c8a3696033f1f7ea..862ea12e9efff61cd19b2b2eb3db6c68f471af40 100644 (file)
@@ -1,6 +1,6 @@
 /* CPP Library.
    Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2003 Free Software Foundation, Inc.
+   1999, 2000, 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
@@ -17,7 +17,7 @@ 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.  */
+Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -94,9 +94,3 @@ const size_t cpp_GCC_INCLUDE_DIR_len = sizeof GCC_INCLUDE_DIR - 8;
 const char cpp_GCC_INCLUDE_DIR[] = "";
 const size_t cpp_GCC_INCLUDE_DIR_len = 0;
 #endif
-
-#ifdef TARGET_SYSTEM_ROOT
-const char *cpp_SYSROOT = TARGET_SYSTEM_ROOT;
-#else
-const char *cpp_SYSROOT = "";
-#endif
index 368e082c79d9cd3756773a8db7d8df2e8ffb0749..f5b38884de6e361084d4ca0a78e1c9beaf9e6d2a 100644 (file)
@@ -1,6 +1,6 @@
 /* CPP Library.
    Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2003 Free Software Foundation, Inc.
+   1999, 2000, 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
@@ -17,7 +17,7 @@ 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.  */
+Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 #ifndef GCC_CPPDEFAULT_H
 #define GCC_CPPDEFAULT_H
@@ -49,6 +49,4 @@ extern const struct default_include cpp_include_defaults[];
 extern const char cpp_GCC_INCLUDE_DIR[];
 extern const size_t cpp_GCC_INCLUDE_DIR_len;
 
-extern const char *cpp_SYSROOT;
-
 #endif /* ! GCC_CPPDEFAULT_H */
diff --git a/support/cpp2/cpperror.c b/support/cpp2/cpperror.c
deleted file mode 100644 (file)
index 61763cc..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/* Default error handlers for CPP Library.
-   Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 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"
-#include "intl.h"
-
-static void print_location (cpp_reader *, fileline, 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, fileline 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_maps, line);
-      linemap_print_containing_files (&pfile->line_maps, map);
-
-      lin = SOURCE_LINE (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.  LINE 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.  Returns 0 if the error has been
-   suppressed.  */
-int
-_cpp_begin_message (cpp_reader *pfile, int code, fileline line,
-                   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, line, 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, ...)
-{
-  fileline line;
-  unsigned int column;
-  va_list ap;
-  
-  va_start (ap, msgid);
-
-  if (CPP_OPTION (pfile, traditional))
-    {
-      if (pfile->state.in_directive)
-       line = pfile->directive_line;
-      else
-       line = pfile->line;
-      column = 0;
-    }
-  else
-    {
-      line = pfile->cur_token[-1].line;
-      column = pfile->cur_token[-1].col;
-    }
-
-  if (_cpp_begin_message (pfile, level, line, column))
-    v_message (msgid, ap);
-
-  va_end (ap);
-}
-
-/* Print an error at a specific location.  */
-void
-cpp_error_with_line (cpp_reader *pfile, int level,
-                    fileline line, unsigned int column,
-                    const char *msgid, ...)
-{
-  va_list ap;
-  
-  va_start (ap, msgid);
-
-  if (_cpp_begin_message (pfile, level, line, 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/support/cpp2/cppexp.c b/support/cpp2/cppexp.c
deleted file mode 100644 (file)
index cb35b6c..0000000
+++ /dev/null
@@ -1,1542 +0,0 @@
-/* Parse C expressions for cpplib.
-   Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
-   2002 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);
-
-  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;
-
-  /* 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))
-    overflow = true;
-
-  result.unsignedp = num.unsignedp;
-  result.overflow = overflow;
-  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;
-
-  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;
-  result.overflow = false;
-  return result;
-}
-\f
-/* 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)
-       {
-         /* We want a number (or expression) and haven't got one.
-            Try to emit a specific diagnostic.  */
-         if (op.op == CPP_CLOSE_PAREN && top->op == CPP_OPEN_PAREN)
-           SYNTAX_ERROR ("missing expression between '(' and ')'");
-
-         if (op.op == CPP_EOF && 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));
-         else if (op.op == CPP_CLOSE_PAREN || op.op == CPP_EOF)
-           /* Complain about missing paren during reduction.  */;
-         else
-           SYNTAX_ERROR2 ("operator '%s' has no left operand",
-                          cpp_token_as_text (pfile, op.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;
-
-  if (num.unsignedp || num_positive (num, precision))
-    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 = num_trim (result, precision);
-      result.unsignedp = lhs.unsignedp || rhs.unsignedp;
-      if (result.unsignedp)
-       result.overflow = false;
-      else
-       {
-         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 = 1;
-
-  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;
-      if (unsignedp)
-       result.overflow = false;
-      else
-       {
-         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/support/cpp2/cppfiles.c b/support/cpp2/cppfiles.c
deleted file mode 100644 (file)
index e757a40..0000000
+++ /dev/null
@@ -1,1297 +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 <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;
-
-  /* 0: file not known to be a PCH.
-     1: file is a PCH (on return from find_include_file).
-     2: file is not and never will be a valid precompiled header.
-     3: file is always a valid precompiled header.  */
-  uchar 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, int);
-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 void destroy_cpp_file (_cpp_file *);
-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 bool include_pch_p (_cpp_file *file);
-
-/* 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
-    path = append_file_to_dir (file->name, file->dir);
-
-  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, 0);
-      return true;
-    }
-
-  free (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_seach_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, int angle_brackets)
-{
-  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)
-       {
-         open_file_failed (pfile, file, angle_brackets);
-         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.  */
-#ifndef __BORLANDC__
-      if (file->st.st_size > INTTYPE_MAXIMUM (ssize_t))
-       {
-         cpp_error (pfile, CPP_DL_ERROR, "%s is too large", file->path);
-         return false;
-       }
-#endif
-
-      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;
-    }
-
-#ifndef __BORLANDC__
-  /* For some reason, even though we opened with O_BINARY,
-   * Borland C++ seems to insist on doing CR/LF -> LF
-   * translations for us, which results in the file appearing
-   * shorter than stat told us it should be.
-   *
-   * This sucks, but don't bother throwing a warning.
-   */
-  if (regular && total != size && STAT_SIZE_RELIABLE (file->st))
-    cpp_error (pfile, CPP_DL_WARNING,
-              "%s is shorter than expected", file->path);
-#endif
-
-  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, 0);
-      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 (include_pch_p (file))
-    {
-      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;
-
-  /* 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)
-       {
-         _cpp_file *ref_file;
-         bool same_file_p = false;
-
-         if (f->buffer && !f->buffer_valid)
-           {
-             /* We already have a buffer but it is not valid, because
-                the file is still stacked.  Make a new one.  */
-             ref_file = make_cpp_file (pfile, f->dir, f->name);
-             ref_file->path = f->path;
-           }
-         else
-           /* The file is not stacked anymore.  We can reuse it.  */
-           ref_file = f;
-
-         same_file_p = read_file (pfile, ref_file)
-                       /* Size might have changed in read_file().  */
-                       && ref_file->st.st_size == file->st.st_size
-                       && !memcmp (ref_file->buffer,
-                                   file->buffer,
-                                   file->st.st_size);
-
-         if (f->buffer && !f->buffer_valid)
-           {
-             ref_file->path = 0;
-             destroy_cpp_file (ref_file);
-           }
-
-         if (same_file_p)
-           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;
-
-  sysp = MAX ((pfile->map ? pfile->map->sysp : 0),
-             (file->dir ? file->dir->sysp : 0));
-
-  /* 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;
-
-  /* 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->map->sysp);
-
-  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;
-
-  dir = search_path_head (pfile, fname, angle_brackets, type);
-  if (!dir)
-    return false;
-
-  return _cpp_stack_file (pfile, _cpp_find_file (pfile, fname, dir, false,
-                                                angle_brackets),
-                    type == IT_IMPORT);
-}
-
-/* Could not open FILE.  The complication is dependency output.  */
-static void
-open_file_failed (cpp_reader *pfile, _cpp_file *file, int angle_brackets)
-{
-  int sysp = pfile->map ? pfile->map->sysp: 0;
-  bool print_dep = CPP_OPTION (pfile, deps.style) > (angle_brackets || !!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;
-}
-
-/* Release a _cpp_file structure.  */
-static void
-destroy_cpp_file (_cpp_file *file)
-{
-  if (file->buffer)
-    free ((void *) file->buffer);
-  free ((void *) file->name);
-  free (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->dir_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;
-
-  /* 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);
-  pfile->dir_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);
-  htab_delete (pfile->dir_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, 0);
-}
-
-/* Not everyone who wants to set system-header-ness on a buffer can
-   see the details of a buffer.  This is an exported interface because
-   fix-header needs it.  */
-void
-cpp_make_system_header (cpp_reader *pfile, int syshdr, int externc)
-{
-  int flags = 0;
-
-  /* 1 = system header, 2 = system header to be treated as C.  */
-  if (syshdr)
-    flags = 1 + (externc != 0);
-  _cpp_do_file_change (pfile, LC_RENAME, pfile->map->to_file,
-                      SOURCE_LINE (pfile->map, pfile->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, angle_brackets);
-  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)
-{
-  /* Make the command line directive take up a line.  */
-  pfile->line++;
-  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;
-      file->buffer_valid = false;
-    }
-}
-
-/* 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;
-    }
-}
-
-/* Return true if FILE is usable by PCH.  */
-static bool
-include_pch_p (_cpp_file *file)
-{
-  return file->pch & 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_maps.depth; i++)
-           putc ('.', stderr);
-         fprintf (stderr, "%c %s\n",
-                  valid ? '!' : 'x', pchname);
-       }
-    }
-
-  file->path = saved_path;
-  return valid;
-}
diff --git a/support/cpp2/cpphash.c b/support/cpp2/cpphash.c
deleted file mode 100644 (file)
index 9d2f51a..0000000
+++ /dev/null
@@ -1,121 +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;
-  /* SDCC _asm specific */
-  s->n__asm             = cpp_lookup (pfile, DSC("_asm"));
-
-}
-
-/* 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/support/cpp2/cpphash.h b/support/cpp2/cpphash.h
deleted file mode 100644 (file)
index afe4c83..0000000
+++ /dev/null
@@ -1,641 +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)
-
-/* 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 */
-  /* SDCC _asm specific */
-  cpp_hashnode *n__asm;                /* _asm ... _endasm ; */
-};
-
-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 char warned_cplusplus_comments;
-
-  /* True if we don't process trigraphs and escaped newlines.  True
-     for preprocessed input, command line directives, and _Pragma
-     buffers.  */
-  unsigned char from_stage3;
-
-  /* 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;
-
-  /* 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;
-
-  /* Used for buffer overlays by cpptrad.c.  */
-  const uchar *saved_cur, *saved_rlimit;
-};
-
-/* 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_maps;
-  const struct line_map *map;
-  fileline line;
-
-  /* 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 htab *dir_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 to save the original line number during traditional
-     preprocessing.  */
-  unsigned int saved_line;
-
-  /* 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.  */
-
-#define CPP_IN_SYSTEM_HEADER(PFILE) ((PFILE)->map && (PFILE)->map->sysp)
-#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, fileline, 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, int);
-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 *);
-
-/* 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 bool _cpp_interpret_string_notranslate (cpp_reader *,
-                                              const cpp_string *,
-                                              cpp_string *);
-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/support/cpp2/cppinit.c b/support/cpp2/cppinit.c
deleted file mode 100644 (file)
index fab2da2..0000000
+++ /dev/null
@@ -1,637 +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)
-{
-  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;
-
-  /* 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 locale/UTF-8.  */
-  CPP_OPTION (pfile, narrow_charset) = _cpp_default_encoding ();
-  CPP_OPTION (pfile, wide_charset) = 0;
-  CPP_OPTION (pfile, input_charset) = _cpp_default_encoding ();
-
-  /* SDCC specific */
-  CPP_OPTION (pfile, preproc_asm) = 1;
-  CPP_OPTION (pfile, pedantic_parse_number) = 0;
-  CPP_OPTION (pfile, obj_ext) = NULL;
-
-  /* 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.  Start at logical line 1, so we can use
-     a line number of zero for special states.  */
-  linemap_init (&pfile->line_maps);
-  pfile->line = 1;
-
-  /* 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);
-    }
-
-  linemap_free (&pfile->line_maps);
-  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, fname);
-    }
-
-  pfile->main_file
-    = _cpp_find_file (pfile, fname, &pfile->no_search_path, false, 0);
-  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);
-      if (!pfile->map)
-       return NULL;
-      fname = pfile->map->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)
-    {
-      pfile->state.in_directive = 1;
-      token1 = _cpp_lex_direct (pfile);
-      _cpp_backup_tokens (pfile, 1);
-      pfile->state.in_directive = 0;
-
-      /* 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))
-    {
-      CPP_OPTION (pfile, cplusplus_comments) = 0;
-
-      /* 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/support/cpp2/cpplex.c b/support/cpp2/cpplex.c
deleted file mode 100644 (file)
index 610d5b1..0000000
+++ /dev/null
@@ -1,1896 +0,0 @@
-/* CPP Library - lexical analysis.
-   Copyright (C) 2000, 2001, 2002, 2003 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"
-#include <assert.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, col,
-                                "backslash and newline separated by space");
-
-         if (buffer->next_line > buffer->rlimit)
-           {
-             cpp_error_with_line (pfile, CPP_DL_PEDWARN, pfile->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;
-         pfile->line++;
-       }
-      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, 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, col,
-                    "trigraph ??%c ignored, use -trigraphs to enable",
-                    note->type);
-               }
-           }
-       }
-      else
-       abort ();
-    }
-}
-
-/* SDCC _asm specific */
-/* Skip an _asm ... _endasm block.  We find the end of the comment by
-   seeing _endasm.  Returns non-zero if _asm terminated by EOF, zero
-   otherwise.  */
-static int
-skip_asm_block (cpp_reader *pfile)
-{
-#define _ENDASM_STR "endasm"
-#define _ENDASM_LEN ((sizeof _ENDASM_STR) - 1)
-
-  cpp_buffer *buffer = pfile->buffer;
-  cppchar_t c = EOF;
-  int prev_space = 0;
-  int ret = 1;
-
-  while (buffer->cur != buffer->rlimit)
-    {
-      prev_space = is_space(c);
-      c = *buffer->cur++;
-
-      if (prev_space && c == '_')
-       {
-          if (buffer->cur + _ENDASM_LEN <= buffer->rlimit &&
-            strncmp(buffer->cur, _ENDASM_STR, _ENDASM_LEN) == 0)
-            {
-              buffer->cur += _ENDASM_LEN;
-              ret = 0;
-             break;
-            }
-       }
-      else if (c == '\n')
-       {
-         --buffer->cur;
-         _cpp_process_line_notes (pfile, true);
-         if (buffer->next_line >= buffer->rlimit)
-           return true;
-         _cpp_clean_line (pfile);
-         pfile->line++;
-       }
-    }
-
-  _cpp_process_line_notes (pfile, true);
-  return ret;
-}
-
-/* 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, CPP_BUF_COL (buffer),
-                                  "\"/*\" within comment");
-           }
-       }
-      else if (c == '\n')
-       {
-         buffer->cur = cur - 1;
-         _cpp_process_line_notes (pfile, true);
-         if (buffer->next_line >= buffer->rlimit)
-           return true;
-         _cpp_clean_line (pfile);
-         pfile->line++;
-         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;
-
-  while (*buffer->cur != '\n')
-    buffer->cur++;
-
-  _cpp_process_line_notes (pfile, true);
-  return orig_line != pfile->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,
-                            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;
-}
-
-/* SDCC specific */
-/* Pedantic parse a number, beginning with character C, skipping embedded
-   backslash-newlines.  LEADING_PERIOD is nonzero if there was a "."
-   before C.  Place the result in NUMBER.  */
-static void
-pedantic_lex_number (cpp_reader *pfile, cpp_string *number)
-{
-#define get_effective_char(pfile) (*pfile->buffer->cur++)
-#define BACKUP() (--pfile->buffer->cur)
-
-  enum num_type_e { NT_DEC, NT_HEX } num_type = NT_DEC;
-  enum num_part_e { NP_WHOLE, NP_FRACT, NP_EXP, NP_INT_SUFFIX, NP_FLOAT_SUFFIX } num_part = NP_WHOLE;
-
-  uchar c = *(pfile->buffer->cur - 1);
-  struct obstack *stack = &pfile->hash_table->stack;
-  cpp_buffer *buffer = pfile->buffer;
-  int len = 0;
-  int has_whole = 0;
-  int has_fract = 0;
-
-  if ('.' == c)
-    {
-      num_part = NP_FRACT;
-      ++len;
-      obstack_1grow (stack, '.');
-      c = get_effective_char(pfile);
-    }
-  else
-    {
-      if ('0' == c)  
-        {
-          has_whole = 1;
-          ++len;
-          obstack_1grow (stack, c);
-          c = get_effective_char(pfile);
-
-          switch (c)
-            {
-            case 'X':
-            case 'x':
-              num_type = NT_HEX;
-              ++len;
-              obstack_1grow (stack, c);
-              c = get_effective_char(pfile);
-              break;
-
-            case '.':
-              num_part = NP_FRACT;
-              ++len;
-              obstack_1grow (stack, c);
-              c = get_effective_char(pfile);
-              break;
-            }
-        }
-    }
-
-  for (; ; )
-    {
-      switch (num_part)
-        {
-        case NP_WHOLE:
-          if (NT_DEC == num_type)
-            {
-              while (ISDIGIT (c))
-                {
-                  has_whole = 1;
-                  ++len;
-                  obstack_1grow (stack, c);
-                  c = get_effective_char(pfile);
-                }
-
-              if ('.' == c)
-                {
-                  num_part = NP_FRACT;
-                  ++len;
-                  obstack_1grow (stack, c);
-                  c = get_effective_char(pfile);
-                  continue;
-                }
-              else if ('E' == c || 'e' == c)
-                {
-                  if (has_whole || has_fract)
-                  {
-                    num_part = NP_EXP;
-                    ++len;
-                    obstack_1grow (stack, c);
-                    c = get_effective_char(pfile);
-                    continue;
-                  }
-                  else
-                    break;
-                }
-            }
-          else
-            {
-              while (ISXDIGIT (c))
-                {
-                  has_whole = 1;
-                  ++len;
-                  obstack_1grow (stack, c);
-                  c = get_effective_char(pfile);
-                }
-
-              if ('.' == c)
-                {
-                  num_part = NP_FRACT;
-                  ++len;
-                  obstack_1grow (stack, c);
-                  c = get_effective_char(pfile);
-                  continue;
-                }
-              else if ('P' == c || 'p' == c)
-                {
-                  if (has_whole || has_fract)
-                    {
-                      num_part = NP_EXP;
-                      ++len;
-                      obstack_1grow (stack, c);
-                      c = get_effective_char(pfile);
-                      continue;
-                    }
-                  else
-                    break;
-                }
-            }
-          num_part = NP_INT_SUFFIX;
-          continue;
-
-        case NP_FRACT:
-          if (NT_DEC == num_type)
-            {
-              while (ISDIGIT (c))
-                {
-                  has_fract = 1;
-                  ++len;
-                  obstack_1grow (stack, c);
-                  c = get_effective_char(pfile);
-                }
-
-              if ('E' == c || 'e' == c)
-                {
-                  if (has_whole || has_fract)
-                    {
-                      num_part = NP_EXP;
-                      ++len;
-                      obstack_1grow (stack, c);
-                      c = get_effective_char(pfile);
-                      continue;
-                    }
-                }
-            }
-          else
-            {
-              while (ISXDIGIT (c))
-                {
-                  has_fract = 1;
-                  ++len;
-                  obstack_1grow (stack, c);
-                  c = get_effective_char(pfile);
-                }
-
-              if ('P' == c || 'p' == c)
-                {
-                  if (has_whole || has_fract)
-                    {
-                      num_part = NP_EXP;
-                      ++len;
-                      obstack_1grow (stack, c);
-                      c = get_effective_char(pfile);
-                      continue;
-                    }
-                }
-            }
-          num_part = NP_FLOAT_SUFFIX;
-          continue;
-            
-        case NP_EXP:
-          if ('+' == c || '-' == c)
-            {
-              ++len;
-              obstack_1grow (stack, c);
-              c = get_effective_char(pfile);
-            }
-
-          while (ISDIGIT (c))
-            {
-              ++len;
-              obstack_1grow (stack, c);
-              c = get_effective_char(pfile);
-            }
-
-          num_part = NP_FLOAT_SUFFIX;
-          continue;
-
-        case NP_INT_SUFFIX:
-           if ('L' == c || 'l' == c)
-            {
-              uchar prevc = c;
-
-              ++len;
-              obstack_1grow (stack, c);
-              c = get_effective_char(pfile);
-
-              if (c == prevc)
-                {
-                  ++len;
-                  obstack_1grow (stack, c);
-                  c = get_effective_char(pfile);
-                }
-            }
-          else if ('U' == c || 'u' == c)
-            {
-              ++len;
-              obstack_1grow (stack, c);
-              c = get_effective_char(pfile);
-            }
-          break;
-
-        case NP_FLOAT_SUFFIX:
-           if ('F' == c || 'f' == c)
-            {
-              ++len;
-              obstack_1grow (stack, c);
-              c = get_effective_char(pfile);
-            }
-          else if ('L' == c || 'l' == c)
-            {
-              ++len;
-              obstack_1grow (stack, c);
-              c = get_effective_char(pfile);
-            }
-          break;
-        }
-      break;
-    }
-
-  /* Step back over the unwanted char.  */
-  BACKUP ();
-
-  number->text = obstack_finish (stack);
-  number->len = len;
-}
-
-/* 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);
-}
-
-/* Fixed _WIN32 problem with CR-CR-LF sequences when outputting
-   comment blocks (when executed with -C option) and
-   _asm (SDCPP specific) blocks */
-
-/* Count and copy characters from src to dest, excluding CRs:
-   CRs are automatically generated, because the output is
-   opened in TEXT mode. If dest == NULL, only count chars */
-static unsigned int
-copy_text_chars (char *dest, const char *src, unsigned int len)
-{
-  unsigned int n = 0;
-  const char *p;
-
-  for (p = src; p != src + len; ++p)
-    {
-      assert(*p != '\0');
-
-      if (*p != '\r')
-        {
-          if (dest != NULL)
-            *dest++ = *p;
-          ++n;
-        }
-    }
-
-    return n;
-}
-
-/* SDCC _asm specific */
-/* The stored comment includes the comment start and any terminator.  */
-static void
-save_asm (cpp_reader *pfile, cpp_token *token, const unsigned char *from)
-{
-#define _ASM_STR  "_asm"
-#define _ASM_LEN  ((sizeof _ASM_STR) - 1)
-
-  unsigned char *buffer;
-  unsigned int text_len, len;
-
-  len = pfile->buffer->cur - from;
-  /* + _ASM_LEN for the initial '_asm'.  */
-  text_len = copy_text_chars (NULL, from, len) + _ASM_LEN;
-  buffer = _cpp_unaligned_alloc (pfile, text_len);
-
-
-  token->type = CPP_ASM;
-  token->val.str.len = text_len;
-  token->val.str.text = buffer;
-
-  memcpy (buffer, _ASM_STR, _ASM_LEN);
-  copy_text_chars (buffer + _ASM_LEN, from, len);
-}
-
-/* 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] = '/';
-  copy_text_chars (buffer + 1, from, len);
-
-  /* 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->line = old->line;
-  result->col = old->col;
-  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 - 1,
-                              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->line = pfile->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->line = pfile->line;
-
- skipped_white:
-  if (buffer->cur >= buffer->notes[buffer->cur_note].pos
-      && !pfile->overlaid_buffer)
-    {
-      _cpp_process_line_notes (pfile, false);
-      result->line = pfile->line;
-    }
-  c = *buffer->cur++;
-  result->col = 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':
-      pfile->line++;
-      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;
-      if (CPP_OPTION(pfile, pedantic_parse_number))
-        pedantic_lex_number (pfile, &result->val.str);
-      else
-        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);
-
-      /* SDCC _asm specific */
-      /* handle _asm ... _endasm ;  */
-      if (CPP_OPTION(pfile, preproc_asm) == 0 && result->val.node == pfile->spec_nodes.n__asm)
-        {
-          comment_start = buffer->cur;
-          result->type = CPP_ASM;
-          skip_asm_block (pfile);
-          /* Save the _asm block as a token in its own right.  */
-          save_asm (pfile, result, comment_start);
-        }
-      /* Convert named operators to their proper types.  */
-      else 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;
-          if (CPP_OPTION(pfile, pedantic_parse_number))
-            pedantic_lex_number (pfile, &result->val.str);
-          else
-            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/support/cpp2/cpplib.c b/support/cpp2/cpplib.c
deleted file mode 100644 (file)
index 8a29112..0000000
+++ /dev/null
@@ -1,2071 +0,0 @@
-/* CPP Library. (Directive handling.)
-   Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003 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_pragma_sdcc_hash (cpp_reader *pfile);
-static void do_pragma_preproc_asm (cpp_reader *pfile);
-static void do_pragma_pedantic_parse_number (cpp_reader *pfile);
-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;
-}
-
-/* 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;
-
-  if (!*fname)
-  {
-    cpp_error (pfile, CPP_DL_ERROR, "empty filename in #%s",
-               pfile->directive->name);
-    free ((void *) fname);
-    return;
-  }
-
-  /* Prevent #include recursion.  */
-  if (pfile->line_maps.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 cpp_token *token;
-  const char *new_file = pfile->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, &s))
-       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,
-                      pfile->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 cpp_token *token;
-  const char *new_file = pfile->map->to_file;
-  unsigned long new_lineno;
-  unsigned int new_sysp = pfile->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, &s))
-       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;
-       }
-
-      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)
-{
-  pfile->map = linemap_add (&pfile->line_maps, reason, sysp,
-                           pfile->line, to_file, file_line);
-
-  if (pfile->cb.file_change)
-    pfile->cb.file_change (pfile, 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].line,
-                         pfile->cur_token[-1].col))
-    {
-      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);
-
-  /* Kevin abuse for SDCC. */
-  cpp_register_pragma(pfile, 0, "sdcc_hash", do_pragma_sdcc_hash);
-  /* SDCC _asm specific */
-  cpp_register_pragma(pfile, 0, "preproc_asm", do_pragma_preproc_asm);
-  /* SDCC specific */
-  cpp_register_pragma(pfile, 0, "pedantic_parse_number", do_pragma_pedantic_parse_number);
-}
-
-/* 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;
-}
-
-/* SDCC specific
-   sdcc_hash pragma */
-static void
-do_pragma_sdcc_hash (cpp_reader *pfile)
-{
-    const cpp_token *tok = _cpp_lex_token (pfile);
-
-    if (tok->type == CPP_PLUS)
-    {
-       CPP_OPTION(pfile, allow_naked_hash)++;
-    }
-    else if (tok->type == CPP_MINUS)
-    {
-       CPP_OPTION(pfile, allow_naked_hash)--;
-    }
-    else
-    {
-       cpp_error (pfile, CPP_DL_ERROR,
-                  "invalid #pragma sdcc_hash directive, need '+' or '-'");
-    }
-}
-
-/* SDCC specific
-   pedantic_parse_number pragma */
-static void
-do_pragma_pedantic_parse_number (cpp_reader *pfile)
-{
-    const cpp_token *tok = _cpp_lex_token (pfile);
-
-  if (tok->type == CPP_PLUS)
-    {
-      CPP_OPTION(pfile, pedantic_parse_number)++;
-    }
-  else if (tok->type == CPP_MINUS)
-    {
-      CPP_OPTION(pfile, pedantic_parse_number)--;
-    }
-  else
-    {
-      cpp_error (pfile, CPP_DL_ERROR,
-                 "invalid #pragma pedantic_parse_number directive, need '+' or '-'");
-    }
-}
-
-/* SDCC _asm specific
-   switch _asm block preprocessing on / off */
-static void
-do_pragma_preproc_asm (cpp_reader *pfile)
-{
-  const cpp_token *tok = _cpp_lex_token (pfile);
-
-  if (tok->type == CPP_PLUS)
-    {
-      CPP_OPTION(pfile, preproc_asm)++;
-    }
-  else if (tok->type == CPP_MINUS)
-    {
-      CPP_OPTION(pfile, preproc_asm)--;
-    }
-  else
-    {
-      cpp_error (pfile, CPP_DL_ERROR,
-                "invalid #pragma preproc_asm directive, need '+' or '-'");
-    }
-}
-
-/* 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;
-    pfile->line--;
-  }
-
-  /* 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;
-}
-
-/* The line map set.  */
-struct line_maps *
-cpp_get_line_maps (cpp_reader *pfile)
-{
-  return &pfile->line_maps;
-}
-
-/* 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/support/cpp2/cpplib.h b/support/cpp2/cpplib.h
deleted file mode 100644 (file)
index 4ce262c..0000000
+++ /dev/null
@@ -1,758 +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;
-
-/* 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.  */     \
-\
-  /* SDCC _asm specific */                                             \
-  TK(CPP_ASM,          SPELL_LITERAL)   /* _asm ... _endasm ; */
-#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
-{
-  fileline line;               /* Logical line of first char of token.  */
-  unsigned short col;          /* Column 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 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;
-
-  /* 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;
-
-  /* SDCC abuse by Kevin: allow naked '#' characters in expanded macros
-   * (see _cpp_create_definition in cppmacro.c)
-   */
-  unsigned char allow_naked_hash;
-
-  /* SDCC _asm specific
-     switch _asm block preprocessing on / off */
-  unsigned char preproc_asm;
-
-  /* SDCC specific
-     object file exetnsion */
-  const char *obj_ext;
-
-  /* SDCC specific
-     pedantic_parse_number */
-  unsigned char pedantic_parse_number;
-
-  /* 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;
-};
-
-/* 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 *);
-};
-
-/* 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;
-
-  /* The C front end uses these to recognize duplicated
-     directories in the search path.  */
-  ino_t ino;
-  dev_t dev;
-};
-
-/* 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 *);
-
-/* 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 struct line_maps *cpp_get_line_maps (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);
-
-/* 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, fileline, 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 *);
-
-/* 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/support/cpp2/cppmacro.c b/support/cpp2/cppmacro.c
deleted file mode 100644 (file)
index 59e3f58..0000000
+++ /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 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_maps, 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 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;
-       const struct line_map *map = pfile->map;
-
-       if (node->value.builtin == BT_BASE_FILE)
-         while (! MAIN_FILE_P (map))
-           map = INCLUDED_FROM (&pfile->line_maps, 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_maps.depth - 1;
-      break;
-
-    case BT_SPECLINE:
-      /* If __LINE__ is embedded in a macro, it must expand to the
-        line of the macro's invocation, not its definition.
-        Otherwise things like assert() will not work properly.  */
-      if (CPP_OPTION (pfile, traditional))
-       number = pfile->line;
-      else
-       number = pfile->cur_token[-1].line;
-      number = SOURCE_LINE (pfile->map, number);
-      break;
-
-      /* __STDC__ has the value 1 under normal circumstances.
-        However, if (a) we are in a system header, (b) the option
-        stdc_0_in_system_headers is true (set by target config), and
-        (c) we are not in strictly conforming mode, then it has the
-        value 0.  */
-    case BT_STDC:
-      {
-       if (CPP_IN_SYSTEM_HEADER (pfile)
-           && CPP_OPTION (pfile, stdc_0_in_system_headers)
-           && !CPP_OPTION (pfile,std))
-         number = 0;
-       else
-         number = 1;
-      }
-      break;
-
-    case BT_DATE:
-    case BT_TIME:
-      if (pfile->date == NULL)
-       {
-         /* Allocate __DATE__ and __TIME__ strings from permanent
-            storage.  We only do this once, and don't generate them
-            at init time, because time() and localtime() are very
-            slow on some systems.  */
-         time_t tt;
-         struct tm *tb = NULL;
-
-         /* (time_t) -1 is a legitimate value for "number of seconds
-            since the Epoch", so we have to do a little dance to
-            distinguish that from a genuine error.  */
-         errno = 0;
-         tt = time(NULL);
-         if (tt != (time_t)-1 || errno == 0)
-           tb = localtime (&tt);
-
-         if (tb)
-           {
-             pfile->date = _cpp_unaligned_alloc (pfile,
-                                                 sizeof ("\"Oct 11 1347\""));
-             sprintf ((char *) pfile->date, "\"%s %2d %4d\"",
-                      monthnames[tb->tm_mon], tb->tm_mday,
-                      tb->tm_year + 1900);
-
-             pfile->time = _cpp_unaligned_alloc (pfile,
-                                                 sizeof ("\"12:34:56\""));
-             sprintf ((char *) pfile->time, "\"%02d:%02d:%02d\"",
-                      tb->tm_hour, tb->tm_min, tb->tm_sec);
-           }
-         else
-           {
-             cpp_errno (pfile, CPP_DL_WARNING,
-                        "could not determine date and time");
-               
-             pfile->date = U"\"??? ?? ????\"";
-             pfile->time = U"\"??:??:??\"";
-           }
-       }
-
-      if (node->value.builtin == BT_DATE)
-       result = pfile->date;
-      else
-       result = pfile->time;
-      break;
-    }
-
-  if (result == NULL)
-    {
-      /* 21 bytes holds all NUL-terminated unsigned 64-bit numbers.  */
-      result = _cpp_unaligned_alloc (pfile, 21);
-      sprintf ((char *) result, "%u", number);
-    }
-
-  return result;      
-}
-
-/* Convert builtin macros like __FILE__ to a token and push it on the
-   context stack.  Also handles _Pragma, for which no new token is
-   created.  Returns 1 if it generates a new token context, 0 to
-   return the token to the caller.  */
-static int
-builtin_macro (cpp_reader *pfile, cpp_hashnode *node)
-{
-  const uchar *buf;
-  size_t len;
-  char *nbuf;
-
-  if (node->value.builtin == BT_PRAGMA)
-    {
-      /* Don't interpret _Pragma within directives.  The standard is
-         not clear on this, but to me this makes most sense.  */
-      if (pfile->state.in_directive)
-       return 0;
-
-      _cpp_do__Pragma (pfile);
-      return 1;
-    }
-
-  buf = _cpp_builtin_macro_text (pfile, node);
-  len = ustrlen (buf);
-  nbuf = alloca (len + 1);
-  memcpy (nbuf, buf, len);
-  nbuf[len]='\n';
-
-  cpp_push_buffer (pfile, (uchar *) nbuf, len, /* from_stage3 */ true);
-  _cpp_clean_line (pfile);
-
-  /* Set pfile->cur_token as required by _cpp_lex_direct.  */
-  pfile->cur_token = _cpp_temp_token (pfile);
-  push_token_context (pfile, NULL, _cpp_lex_direct (pfile), 1);
-  if (pfile->buffer->cur != pfile->buffer->rlimit)
-    cpp_error (pfile, CPP_DL_ICE, "invalid built-in macro \"%s\"",
-              NODE_NAME (node));
-  _cpp_pop_buffer (pfile);
-
-  return 1;
-}
-
-/* Copies SRC, of length LEN, to DEST, adding backslashes before all
-   backslashes and double quotes.  Non-printable characters are
-   converted to octal.  DEST must be of sufficient size.  Returns
-   a pointer to the end of the string.  */
-uchar *
-cpp_quote_string (uchar *dest, const uchar *src, unsigned int len)
-{
-  while (len--)
-    {
-      uchar c = *src++;
-
-      if (c == '\\' || c == '"')
-       {
-         *dest++ = '\\';
-         *dest++ = c;
-       }
-      else
-       {
-         if (ISPRINT (c))
-           *dest++ = c;
-         else
-           {
-             sprintf ((char *) dest, "\\%03o", c);
-             dest += 4;
-           }
-       }
-    }
-
-  return dest;
-}
-
-/* Convert a token sequence ARG to a single string token according to
-   the rules of the ISO C #-operator.  */
-static const cpp_token *
-stringify_arg (cpp_reader *pfile, macro_arg *arg)
-{
-  unsigned char *dest;
-  unsigned int i, escape_it, backslash_count = 0;
-  const cpp_token *source = NULL;
-  size_t len;
-
-  if (BUFF_ROOM (pfile->u_buff) < 3)
-    _cpp_extend_buff (pfile, &pfile->u_buff, 3);
-  dest = BUFF_FRONT (pfile->u_buff);
-  *dest++ = '"';
-
-  /* Loop, reading in the argument's tokens.  */
-  for (i = 0; i < arg->count; i++)
-    {
-      const cpp_token *token = arg->first[i];
-
-      if (token->type == CPP_PADDING)
-       {
-         if (source == NULL)
-           source = token->val.source;
-         continue;
-       }
-
-      escape_it = (token->type == CPP_STRING || token->type == CPP_WSTRING
-                  || token->type == CPP_CHAR || token->type == CPP_WCHAR);
-
-      /* Room for each char being written in octal, initial space and
-        final quote and NUL.  */
-      len = cpp_token_len (token);
-      if (escape_it)
-       len *= 4;
-      len += 3;
-
-      if ((size_t) (BUFF_LIMIT (pfile->u_buff) - dest) < len)
-       {
-         size_t len_so_far = dest - BUFF_FRONT (pfile->u_buff);
-         _cpp_extend_buff (pfile, &pfile->u_buff, len);
-         dest = BUFF_FRONT (pfile->u_buff) + len_so_far;
-       }
-
-      /* Leading white space?  */
-      if (dest - 1 != BUFF_FRONT (pfile->u_buff))
-       {
-         if (source == NULL)
-           source = token;
-         if (source->flags & PREV_WHITE)
-           *dest++ = ' ';
-       }
-      source = NULL;
-
-      if (escape_it)
-       {
-         _cpp_buff *buff = _cpp_get_buff (pfile, len);
-         unsigned char *buf = BUFF_FRONT (buff);
-         len = cpp_spell_token (pfile, token, buf) - buf;
-         dest = cpp_quote_string (dest, buf, len);
-         _cpp_release_buff (pfile, buff);
-       }
-      else
-       dest = cpp_spell_token (pfile, token, dest);
-
-      if (token->type == CPP_OTHER && token->val.str.text[0] == '\\')
-       backslash_count++;
-      else
-       backslash_count = 0;
-    }
-
-  /* Ignore the final \ of invalid string literals.  */
-  if (backslash_count & 1)
-    {
-      cpp_error (pfile, CPP_DL_WARNING,
-                "invalid string literal, ignoring final '\\'");
-      dest--;
-    }
-
-  /* Commit the memory, including NUL, and return the token.  */
-  *dest++ = '"';
-  len = dest - BUFF_FRONT (pfile->u_buff);
-  BUFF_FRONT (pfile->u_buff) = dest + 1;
-  return new_string_token (pfile, dest - len, len);
-}
-
-/* Try to paste two tokens.  On success, return nonzero.  In any
-   case, PLHS is updated to point to the pasted token, which is
-   guaranteed to not have the PASTE_LEFT flag set.  */
-static bool
-paste_tokens (cpp_reader *pfile, const cpp_token **plhs, const cpp_token *rhs)
-{
-  unsigned char *buf, *end;
-  const cpp_token *lhs;
-  unsigned int len;
-  bool valid;
-
-  lhs = *plhs;
-  len = cpp_token_len (lhs) + cpp_token_len (rhs) + 1;
-  buf = alloca (len);
-  end = cpp_spell_token (pfile, lhs, buf);
-
-  /* Avoid comment headers, since they are still processed in stage 3.
-     It is simpler to insert a space here, rather than modifying the
-     lexer to ignore comments in some circumstances.  Simply returning
-     false doesn't work, since we want to clear the PASTE_LEFT flag.  */
-  if (lhs->type == CPP_DIV && rhs->type != CPP_EQ)
-    *end++ = ' ';
-  end = cpp_spell_token (pfile, rhs, end);
-  *end = '\n';
-
-  cpp_push_buffer (pfile, buf, end - buf, /* from_stage3 */ true);
-  _cpp_clean_line (pfile);
-
-  /* Set pfile->cur_token as required by _cpp_lex_direct.  */
-  pfile->cur_token = _cpp_temp_token (pfile);
-  *plhs = _cpp_lex_direct (pfile);
-  valid = pfile->buffer->cur == pfile->buffer->rlimit;
-  _cpp_pop_buffer (pfile);
-
-  return valid;
-}
-
-/* Handles an arbitrarily long sequence of ## operators, with initial
-   operand LHS.  This implementation is left-associative,
-   non-recursive, and finishes a paste before handling succeeding
-   ones.  If a paste fails, we back up to the RHS of the failing ##
-   operator before pushing the context containing the result of prior
-   successful pastes, with the effect that the RHS appears in the
-   output stream after the pasted LHS normally.  */
-static void
-paste_all_tokens (cpp_reader *pfile, const cpp_token *lhs)
-{
-  const cpp_token *rhs;
-  cpp_context *context = pfile->context;
-
-  do
-    {
-      /* Take the token directly from the current context.  We can do
-        this, because we are in the replacement list of either an
-        object-like macro, or a function-like macro with arguments
-        inserted.  In either case, the constraints to #define
-        guarantee we have at least one more token.  */
-      if (context->direct_p)
-       rhs = FIRST (context).token++;
-      else
-       rhs = *FIRST (context).ptoken++;
-
-      if (rhs->type == CPP_PADDING)
-       abort ();
-
-      if (!paste_tokens (pfile, &lhs, rhs))
-       {
-         _cpp_backup_tokens (pfile, 1);
-
-         /* Mandatory error for all apart from assembler.  */
-         if (CPP_OPTION (pfile, lang) != CLK_ASM)
-           cpp_error (pfile, CPP_DL_ERROR,
-        "pasting \"%s\" and \"%s\" does not give a valid preprocessing token",
-                      cpp_token_as_text (pfile, lhs),
-                      cpp_token_as_text (pfile, rhs));
-         break;
-       }
-    }
-  while (rhs->flags & PASTE_LEFT);
-
-  /* Put the resulting token in its own context.  */
-  push_token_context (pfile, NULL, lhs, 1);
-}
-
-/* Returns TRUE if the number of arguments ARGC supplied in an
-   invocation of the MACRO referenced by NODE is valid.  An empty
-   invocation to a macro with no parameters should pass ARGC as zero.
-
-   Note that MACRO cannot necessarily be deduced from NODE, in case
-   NODE was redefined whilst collecting arguments.  */
-bool
-_cpp_arguments_ok (cpp_reader *pfile, cpp_macro *macro, const cpp_hashnode *node, unsigned int argc)
-{
-  if (argc == macro->paramc)
-    return true;
-
-  if (argc < macro->paramc)
-    {
-      /* As an extension, a rest argument is allowed to not appear in
-        the invocation at all.
-        e.g. #define debug(format, args...) something
-        debug("string");
-
-        This is exactly the same as if there had been an empty rest
-        argument - debug("string", ).  */
-
-      if (argc + 1 == macro->paramc && macro->variadic)
-       {
-         if (CPP_PEDANTIC (pfile) && ! macro->syshdr)
-           cpp_error (pfile, CPP_DL_PEDWARN,
-                      "ISO C99 requires rest arguments to be used");
-         return true;
-       }
-
-      cpp_error (pfile, CPP_DL_ERROR,
-                "macro \"%s\" requires %u arguments, but only %u given",
-                NODE_NAME (node), macro->paramc, argc);
-    }
-  else
-    cpp_error (pfile, CPP_DL_ERROR,
-              "macro \"%s\" passed %u arguments, but takes just %u",
-              NODE_NAME (node), argc, macro->paramc);
-
-  return false;
-}
-
-/* Reads and returns the arguments to a function-like macro
-   invocation.  Assumes the opening parenthesis has been processed.
-   If there is an error, emits an appropriate diagnostic and returns
-   NULL.  Each argument is terminated by a CPP_EOF token, for the
-   future benefit of expand_arg().  */
-static _cpp_buff *
-collect_args (cpp_reader *pfile, const cpp_hashnode *node)
-{
-  _cpp_buff *buff, *base_buff;
-  cpp_macro *macro;
-  macro_arg *args, *arg;
-  const cpp_token *token;
-  unsigned int argc;
-
-  macro = node->value.macro;
-  if (macro->paramc)
-    argc = macro->paramc;
-  else
-    argc = 1;
-  buff = _cpp_get_buff (pfile, argc * (50 * sizeof (cpp_token *)
-                                      + sizeof (macro_arg)));
-  base_buff = buff;
-  args = (macro_arg *) buff->base;
-  memset (args, 0, argc * sizeof (macro_arg));
-  buff->cur = (unsigned char *) &args[argc];
-  arg = args, argc = 0;
-
-  /* Collect the tokens making up each argument.  We don't yet know
-     how many arguments have been supplied, whether too many or too
-     few.  Hence the slightly bizarre usage of "argc" and "arg".  */
-  do
-    {
-      unsigned int paren_depth = 0;
-      unsigned int ntokens = 0;
-
-      argc++;
-      arg->first = (const cpp_token **) buff->cur;
-
-      for (;;)
-       {
-         /* Require space for 2 new tokens (including a CPP_EOF).  */
-         if ((unsigned char *) &arg->first[ntokens + 2] > buff->limit)
-           {
-             buff = _cpp_append_extend_buff (pfile, buff,
-                                             1000 * sizeof (cpp_token *));
-             arg->first = (const cpp_token **) buff->cur;
-           }
-
-         token = cpp_get_token (pfile);
-
-         if (token->type == CPP_PADDING)
-           {
-             /* Drop leading padding.  */
-             if (ntokens == 0)
-               continue;
-           }
-         else if (token->type == CPP_OPEN_PAREN)
-           paren_depth++;
-         else if (token->type == CPP_CLOSE_PAREN)
-           {
-             if (paren_depth-- == 0)
-               break;
-           }
-         else if (token->type == CPP_COMMA)
-           {
-             /* A comma does not terminate an argument within
-                parentheses or as part of a variable argument.  */
-             if (paren_depth == 0
-                 && ! (macro->variadic && argc == macro->paramc))
-               break;
-           }
-         else if (token->type == CPP_EOF
-                  || (token->type == CPP_HASH && token->flags & BOL))
-           break;
-
-         arg->first[ntokens++] = token;
-       }
-
-      /* Drop trailing padding.  */
-      while (ntokens > 0 && arg->first[ntokens - 1]->type == CPP_PADDING)
-       ntokens--;
-
-      arg->count = ntokens;
-      arg->first[ntokens] = &pfile->eof;
-
-      /* Terminate the argument.  Excess arguments loop back and
-        overwrite the final legitimate argument, before failing.  */
-      if (argc <= macro->paramc)
-       {
-         buff->cur = (unsigned char *) &arg->first[ntokens + 1];
-         if (argc != macro->paramc)
-           arg++;
-       }
-    }
-  while (token->type != CPP_CLOSE_PAREN && token->type != CPP_EOF);
-
-  if (token->type == CPP_EOF)
-    {
-      /* We still need the CPP_EOF to end directives, and to end
-        pre-expansion of a macro argument.  Step back is not
-        unconditional, since we don't want to return a CPP_EOF to our
-        callers at the end of an -include-d file.  */
-      if (pfile->context->prev || pfile->state.in_directive)
-       _cpp_backup_tokens (pfile, 1);
-      cpp_error (pfile, CPP_DL_ERROR,
-                "unterminated argument list invoking macro \"%s\"",
-                NODE_NAME (node));
-    }
-  else
-    {
-      /* A single empty argument is counted as no argument.  */
-      if (argc == 1 && macro->paramc == 0 && args[0].count == 0)
-       argc = 0;
-      if (_cpp_arguments_ok (pfile, macro, node, argc))
-       {
-         /* GCC has special semantics for , ## b where b is a varargs
-            parameter: we remove the comma if b was omitted entirely.
-            If b was merely an empty argument, the comma is retained.
-            If the macro takes just one (varargs) parameter, then we
-            retain the comma only if we are standards conforming.
-
-            If FIRST is NULL replace_args () swallows the comma.  */
-         if (macro->variadic && (argc < macro->paramc
-                                 || (argc == 1 && args[0].count == 0
-                                     && !CPP_OPTION (pfile, std))))
-           args[macro->paramc - 1].first = NULL;
-         return base_buff;
-       }
-    }
-
-  /* An error occurred.  */
-  _cpp_release_buff (pfile, base_buff);
-  return NULL;
-}
-
-/* Search for an opening parenthesis to the macro of NODE, in such a
-   way that, if none is found, we don't lose the information in any
-   intervening padding tokens.  If we find the parenthesis, collect
-   the arguments and return the buffer containing them.  */
-static _cpp_buff *
-funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node)
-{
-  const cpp_token *token, *padding = NULL;
-
-  for (;;)
-    {
-      token = cpp_get_token (pfile);
-      if (token->type != CPP_PADDING)
-       break;
-      if (padding == NULL
-         || (!(padding->flags & PREV_WHITE) && token->val.source == NULL))
-       padding = token;
-    }
-
-  if (token->type == CPP_OPEN_PAREN)
-    {
-      pfile->state.parsing_args = 2;
-      return collect_args (pfile, node);
-    }
-
-  /* CPP_EOF can be the end of macro arguments, or the end of the
-     file.  We mustn't back up over the latter.  Ugh.  */
-  if (token->type != CPP_EOF || token == &pfile->eof)
-    {
-      /* Back up.  We may have skipped padding, in which case backing
-        up more than one token when expanding macros is in general
-        too difficult.  We re-insert it in its own context.  */
-      _cpp_backup_tokens (pfile, 1);
-      if (padding)
-       push_token_context (pfile, NULL, padding, 1);
-    }
-
-  return NULL;
-}
-
-/* Push the context of a macro with hash entry NODE onto the context
-   stack.  If we can successfully expand the macro, we push a context
-   containing its yet-to-be-rescanned replacement list and return one.
-   Otherwise, we don't push a context and return zero.  */
-static int
-enter_macro_context (cpp_reader *pfile, cpp_hashnode *node)
-{
-  /* The presence of a macro invalidates a file's controlling macro.  */
-  pfile->mi_valid = false;
-
-  pfile->state.angled_headers = false;
-
-  /* Handle standard macros.  */
-  if (! (node->flags & NODE_BUILTIN))
-    {
-      cpp_macro *macro = node->value.macro;
-
-      if (macro->fun_like)
-       {
-         _cpp_buff *buff;
-
-         pfile->state.prevent_expansion++;
-         pfile->keep_tokens++;
-         pfile->state.parsing_args = 1;
-         buff = funlike_invocation_p (pfile, node);
-         pfile->state.parsing_args = 0;
-         pfile->keep_tokens--;
-         pfile->state.prevent_expansion--;
-
-         if (buff == NULL)
-           {
-             if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr)
-               cpp_error (pfile, CPP_DL_WARNING,
- "function-like macro \"%s\" must be used with arguments in traditional C",
-                          NODE_NAME (node));
-
-             return 0;
-           }
-
-         if (macro->paramc > 0)
-           replace_args (pfile, node, macro, (macro_arg *) buff->base);
-         _cpp_release_buff (pfile, buff);
-       }
-
-      /* Disable the macro within its expansion.  */
-      node->flags |= NODE_DISABLED;
-
-      macro->used = 1;
-
-      if (macro->paramc == 0)
-       push_token_context (pfile, node, macro->exp.tokens, macro->count);
-
-      return 1;
-    }
-
-  /* Handle built-in macros and the _Pragma operator.  */
-  return builtin_macro (pfile, node);
-}
-
-/* Replace the parameters in a function-like macro of NODE with the
-   actual ARGS, and place the result in a newly pushed token context.
-   Expand each argument before replacing, unless it is operated upon
-   by the # or ## operators.  */
-static void
-replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, macro_arg *args)
-{
-  unsigned int i, total;
-  const cpp_token *src, *limit;
-  const cpp_token **dest, **first;
-  macro_arg *arg;
-  _cpp_buff *buff;
-
-  /* First, fully macro-expand arguments, calculating the number of
-     tokens in the final expansion as we go.  The ordering of the if
-     statements below is subtle; we must handle stringification before
-     pasting.  */
-  total = macro->count;
-  limit = macro->exp.tokens + macro->count;
-
-  for (src = macro->exp.tokens; src < limit; src++)
-    if (src->type == CPP_MACRO_ARG)
-      {
-       /* Leading and trailing padding tokens.  */
-       total += 2;
-
-       /* We have an argument.  If it is not being stringified or
-          pasted it is macro-replaced before insertion.  */
-       arg = &args[src->val.arg_no - 1];
-
-       if (src->flags & STRINGIFY_ARG)
-         {
-           if (!arg->stringified)
-             arg->stringified = stringify_arg (pfile, arg);
-         }
-       else if ((src->flags & PASTE_LEFT)
-                || (src > macro->exp.tokens && (src[-1].flags & PASTE_LEFT)))
-         total += arg->count - 1;
-       else
-         {
-           if (!arg->expanded)
-             expand_arg (pfile, arg);
-           total += arg->expanded_count - 1;
-         }
-      }
-
-  /* Now allocate space for the expansion, copy the tokens and replace
-     the arguments.  */
-  buff = _cpp_get_buff (pfile, total * sizeof (cpp_token *));
-  first = (const cpp_token **) buff->base;
-  dest = first;
-
-  for (src = macro->exp.tokens; src < limit; src++)
-    {
-      unsigned int count;
-      const cpp_token **from, **paste_flag;
-
-      if (src->type != CPP_MACRO_ARG)
-       {
-         *dest++ = src;
-         continue;
-       }
-
-      paste_flag = 0;
-      arg = &args[src->val.arg_no - 1];
-      if (src->flags & STRINGIFY_ARG)
-       count = 1, from = &arg->stringified;
-      else if (src->flags & PASTE_LEFT)
-       count = arg->count, from = arg->first;
-      else if (src != macro->exp.tokens && (src[-1].flags & PASTE_LEFT))
-       {
-         count = arg->count, from = arg->first;
-         if (dest != first)
-           {
-             if (dest[-1]->type == CPP_COMMA
-                 && macro->variadic
-                 && src->val.arg_no == macro->paramc)
-               {
-                 /* Swallow a pasted comma if from == NULL, otherwise
-                    drop the paste flag.  */
-                 if (from == NULL)
-                   dest--;
-                 else
-                   paste_flag = dest - 1;
-               }
-             /* Remove the paste flag if the RHS is a placemarker.  */
-             else if (count == 0)
-               paste_flag = dest - 1;
-           }
-       }
-      else
-       count = arg->expanded_count, from = arg->expanded;
-
-      /* Padding on the left of an argument (unless RHS of ##).  */
-      if ((!pfile->state.in_directive || pfile->state.directive_wants_padding)
-         && src != macro->exp.tokens && !(src[-1].flags & PASTE_LEFT))
-       *dest++ = padding_token (pfile, src);
-
-      if (count)
-       {
-         memcpy (dest, from, count * sizeof (cpp_token *));
-         dest += count;
-
-         /* With a non-empty argument on the LHS of ##, the last
-            token should be flagged PASTE_LEFT.  */
-         if (src->flags & PASTE_LEFT)
-           paste_flag = dest - 1;
-       }
-
-      /* Avoid paste on RHS (even case count == 0).  */
-      if (!pfile->state.in_directive && !(src->flags & PASTE_LEFT))
-       *dest++ = &pfile->avoid_paste;
-
-      /* Add a new paste flag, or remove an unwanted one.  */
-      if (paste_flag)
-       {
-         cpp_token *token = _cpp_temp_token (pfile);
-         token->type = (*paste_flag)->type;
-         token->val.str = (*paste_flag)->val.str;
-         if (src->flags & PASTE_LEFT)
-           token->flags = (*paste_flag)->flags | PASTE_LEFT;
-         else
-           token->flags = (*paste_flag)->flags & ~PASTE_LEFT;
-         *paste_flag = token;
-       }
-    }
-
-  /* Free the expanded arguments.  */
-  for (i = 0; i < macro->paramc; i++)
-    if (args[i].expanded)
-      free (args[i].expanded);
-
-  push_ptoken_context (pfile, node, buff, first, dest - first);
-}
-
-/* Return a special padding token, with padding inherited from SOURCE.  */
-static const cpp_token *
-padding_token (cpp_reader *pfile, const cpp_token *source)
-{
-  cpp_token *result = _cpp_temp_token (pfile);
-
-  result->type = CPP_PADDING;
-  result->val.source = source;
-  result->flags = 0;
-  return result;
-}
-
-/* Get a new uninitialized context.  Create a new one if we cannot
-   re-use an old one.  */
-static cpp_context *
-next_context (cpp_reader *pfile)
-{
-  cpp_context *result = pfile->context->next;
-
-  if (result == 0)
-    {
-      result = xnew (cpp_context);
-      result->prev = pfile->context;
-      result->next = 0;
-      pfile->context->next = result;
-    }
-
-  pfile->context = result;
-  return result;
-}
-
-/* Push a list of pointers to tokens.  */
-static void
-push_ptoken_context (cpp_reader *pfile, cpp_hashnode *macro, _cpp_buff *buff,
-                    const cpp_token **first, unsigned int count)
-{
-  cpp_context *context = next_context (pfile);
-
-  context->direct_p = false;
-  context->macro = macro;
-  context->buff = buff;
-  FIRST (context).ptoken = first;
-  LAST (context).ptoken = first + count;
-}
-
-/* Push a list of tokens.  */
-static void
-push_token_context (cpp_reader *pfile, cpp_hashnode *macro,
-                   const cpp_token *first, unsigned int count)
-{
-  cpp_context *context = next_context (pfile);
-
-  context->direct_p = true;
-  context->macro = macro;
-  context->buff = NULL;
-  FIRST (context).token = first;
-  LAST (context).token = first + count;
-}
-
-/* Push a traditional macro's replacement text.  */
-void
-_cpp_push_text_context (cpp_reader *pfile, cpp_hashnode *macro,
-                       const uchar *start, size_t len)
-{
-  cpp_context *context = next_context (pfile);
-
-  context->direct_p = true;
-  context->macro = macro;
-  context->buff = NULL;
-  CUR (context) = start;
-  RLIMIT (context) = start + len;
-  macro->flags |= NODE_DISABLED;
-}
-
-/* Expand an argument ARG before replacing parameters in a
-   function-like macro.  This works by pushing a context with the
-   argument's tokens, and then expanding that into a temporary buffer
-   as if it were a normal part of the token stream.  collect_args()
-   has terminated the argument's tokens with a CPP_EOF so that we know
-   when we have fully expanded the argument.  */
-static void
-expand_arg (cpp_reader *pfile, macro_arg *arg)
-{
-  unsigned int capacity;
-  bool saved_warn_trad;
-
-  if (arg->count == 0)
-    return;
-
-  /* Don't warn about funlike macros when pre-expanding.  */
-  saved_warn_trad = CPP_WTRADITIONAL (pfile);
-  CPP_WTRADITIONAL (pfile) = 0;
-
-  /* Loop, reading in the arguments.  */
-  capacity = 256;
-  arg->expanded = xmalloc (capacity * sizeof (cpp_token *));
-
-  push_ptoken_context (pfile, NULL, NULL, arg->first, arg->count + 1);
-  for (;;)
-    {
-      const cpp_token *token;
-
-      if (arg->expanded_count + 1 >= capacity)
-       {
-         capacity *= 2;
-         arg->expanded = xrealloc (arg->expanded,
-                                   capacity * sizeof (cpp_token *));
-       }
-
-      token = cpp_get_token (pfile);
-
-      if (token->type == CPP_EOF)
-       break;
-
-      arg->expanded[arg->expanded_count++] = token;
-    }
-
-  _cpp_pop_context (pfile);
-
-  CPP_WTRADITIONAL (pfile) = saved_warn_trad;
-}
-
-/* Pop the current context off the stack, re-enabling the macro if the
-   context represented a macro's replacement list.  The context
-   structure is not freed so that we can re-use it later.  */
-void
-_cpp_pop_context (cpp_reader *pfile)
-{
-  cpp_context *context = pfile->context;
-
-  if (context->macro)
-    context->macro->flags &= ~NODE_DISABLED;
-
-  if (context->buff)
-    _cpp_release_buff (pfile, context->buff);
-
-  pfile->context = context->prev;
-}
-
-/* External routine to get a token.  Also used nearly everywhere
-   internally, except for places where we know we can safely call
-   _cpp_lex_token directly, such as lexing a directive name.
-
-   Macro expansions and directives are transparently handled,
-   including entering included files.  Thus tokens are post-macro
-   expansion, and after any intervening directives.  External callers
-   see CPP_EOF only at EOF.  Internal callers also see it when meeting
-   a directive inside a macro call, when at the end of a directive and
-   state.in_directive is still 1, and at the end of argument
-   pre-expansion.  */
-const cpp_token *
-cpp_get_token (cpp_reader *pfile)
-{
-  const cpp_token *result;
-
-  for (;;)
-    {
-      cpp_hashnode *node;
-      cpp_context *context = pfile->context;
-
-      /* Context->prev == 0 <=> base context.  */
-      if (!context->prev)
-       result = _cpp_lex_token (pfile);
-      else if (FIRST (context).token != LAST (context).token)
-       {
-         if (context->direct_p)
-           result = FIRST (context).token++;
-         else
-           result = *FIRST (context).ptoken++;
-
-         if (result->flags & PASTE_LEFT)
-           {
-             paste_all_tokens (pfile, result);
-             if (pfile->state.in_directive)
-               continue;
-             return padding_token (pfile, result);
-           }
-       }
-      else
-       {
-         _cpp_pop_context (pfile);
-         if (pfile->state.in_directive)
-           continue;
-         return &pfile->avoid_paste;
-       }
-
-      if (pfile->state.in_directive && result->type == CPP_COMMENT)
-       continue;
-
-      if (result->type != CPP_NAME)
-       break;
-
-      node = result->val.node;
-
-      if (node->type != NT_MACRO || (result->flags & NO_EXPAND))
-       break;
-
-      if (!(node->flags & NODE_DISABLED))
-       {
-         if (!pfile->state.prevent_expansion
-             && enter_macro_context (pfile, node))
-           {
-             if (pfile->state.in_directive)
-               continue;
-             return padding_token (pfile, result);
-           }
-       }
-      else
-       {
-         /* Flag this token as always unexpandable.  FIXME: move this
-            to collect_args()?.  */
-         cpp_token *t = _cpp_temp_token (pfile);
-         t->type = result->type;
-         t->flags = result->flags | NO_EXPAND;
-         t->val.str = result->val.str;
-         result = t;
-       }
-
-      break;
-    }
-
-  return result;
-}
-
-/* Returns true if we're expanding an object-like macro that was
-   defined in a system header.  Just checks the macro at the top of
-   the stack.  Used for diagnostic suppression.  */
-int
-cpp_sys_macro_p (cpp_reader *pfile)
-{
-  cpp_hashnode *node = pfile->context->macro;
-
-  return node && node->value.macro && node->value.macro->syshdr;
-}
-
-/* Read each token in, until end of the current file.  Directives are
-   transparently processed.  */
-void
-cpp_scan_nooutput (cpp_reader *pfile)
-{
-  /* Request a CPP_EOF token at the end of this file, rather than
-     transparently continuing with the including file.  */
-  pfile->buffer->return_at_eof = true;
-
-  if (CPP_OPTION (pfile, traditional))
-    while (_cpp_read_logical_line_trad (pfile))
-      ;
-  else
-    while (cpp_get_token (pfile)->type != CPP_EOF)
-      ;
-}
-
-/* Step back one (or more) tokens.  Can only step mack more than 1 if
-   they are from the lexer, and not from macro expansion.  */
-void
-_cpp_backup_tokens (cpp_reader *pfile, unsigned int count)
-{
-  if (pfile->context->prev == NULL)
-    {
-      pfile->lookaheads += count;
-      while (count--)
-       {
-         pfile->cur_token--;
-         if (pfile->cur_token == pfile->cur_run->base
-             /* Possible with -fpreprocessed and no leading #line.  */
-             && pfile->cur_run->prev != NULL)
-           {
-             pfile->cur_run = pfile->cur_run->prev;
-             pfile->cur_token = pfile->cur_run->limit;
-           }
-       }
-    }
-  else
-    {
-      if (count != 1)
-       abort ();
-      if (pfile->context->direct_p)
-       FIRST (pfile->context).token--;
-      else
-       FIRST (pfile->context).ptoken--;
-    }
-}
-
-/* #define directive parsing and handling.  */
-
-/* Returns nonzero if a macro redefinition warning is required.  */
-static bool
-warn_of_redefinition (cpp_reader *pfile, const cpp_hashnode *node,
-                     const cpp_macro *macro2)
-{
-  const cpp_macro *macro1;
-  unsigned int i;
-
-  /* Some redefinitions need to be warned about regardless.  */
-  if (node->flags & NODE_WARN)
-    return true;
-
-  /* Redefinition of a macro is allowed if and only if the old and new
-     definitions are the same.  (6.10.3 paragraph 2).  */
-  macro1 = node->value.macro;
-
-  /* Don't check count here as it can be different in valid
-     traditional redefinitions with just whitespace differences.  */
-  if (macro1->paramc != macro2->paramc
-      || macro1->fun_like != macro2->fun_like
-      || macro1->variadic != macro2->variadic)
-    return true;
-
-  /* Check parameter spellings.  */
-  for (i = 0; i < macro1->paramc; i++)
-    if (macro1->params[i] != macro2->params[i])
-      return true;
-
-  /* Check the replacement text or tokens.  */
-  if (CPP_OPTION (pfile, traditional))
-    return _cpp_expansions_different_trad (macro1, macro2);
-
-  if (macro1->count != macro2->count)
-    return true;
-
-  for (i = 0; i < macro1->count; i++)
-    if (!_cpp_equiv_tokens (&macro1->exp.tokens[i], &macro2->exp.tokens[i]))
-      return true;
-
-  return false;
-}
-
-/* Free the definition of hashnode H.  */
-void
-_cpp_free_definition (cpp_hashnode *h)
-{
-  /* Macros and assertions no longer have anything to free.  */
-  h->type = NT_VOID;
-  /* Clear builtin flag in case of redefinition.  */
-  h->flags &= ~(NODE_BUILTIN | NODE_DISABLED);
-}
-
-/* Save parameter NODE to the parameter list of macro MACRO.  Returns
-   zero on success, nonzero if the parameter is a duplicate.  */
-bool
-_cpp_save_parameter (cpp_reader *pfile, cpp_macro *macro, cpp_hashnode *node)
-{
-  unsigned int len;
-  /* Constraint 6.10.3.6 - duplicate parameter names.  */
-  if (node->flags & NODE_MACRO_ARG)
-    {
-      cpp_error (pfile, CPP_DL_ERROR, "duplicate macro parameter \"%s\"",
-                NODE_NAME (node));
-      return true;
-    }
-
-  if (BUFF_ROOM (pfile->a_buff)
-      < (macro->paramc + 1) * sizeof (cpp_hashnode *))
-    _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_hashnode *));
-
-  ((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[macro->paramc++] = node;
-  node->flags |= NODE_MACRO_ARG;
-  len = macro->paramc * sizeof (union _cpp_hashnode_value);
-  if (len > pfile->macro_buffer_len)
-    {
-      pfile->macro_buffer = xrealloc (pfile->macro_buffer, len);
-      pfile->macro_buffer_len = len;
-    }
-  ((union _cpp_hashnode_value *) pfile->macro_buffer)[macro->paramc - 1]
-    = node->value;
-  
-  node->value.arg_index  = macro->paramc;
-  return false;
-}
-
-/* Check the syntax of the parameters in a MACRO definition.  Returns
-   false if an error occurs.  */
-static bool
-parse_params (cpp_reader *pfile, cpp_macro *macro)
-{
-  unsigned int prev_ident = 0;
-
-  for (;;)
-    {
-      const cpp_token *token = _cpp_lex_token (pfile);
-
-      switch (token->type)
-       {
-       default:
-         /* Allow/ignore comments in parameter lists if we are
-            preserving comments in macro expansions.  */
-         if (token->type == CPP_COMMENT
-             && ! CPP_OPTION (pfile, discard_comments_in_macro_exp))
-           continue;
-
-         cpp_error (pfile, CPP_DL_ERROR,
-                    "\"%s\" may not appear in macro parameter list",
-                    cpp_token_as_text (pfile, token));
-         return false;
-
-       case CPP_NAME:
-         if (prev_ident)
-           {
-             cpp_error (pfile, CPP_DL_ERROR,
-                        "macro parameters must be comma-separated");
-             return false;
-           }
-         prev_ident = 1;
-
-         if (_cpp_save_parameter (pfile, macro, token->val.node))
-           return false;
-         continue;
-
-       case CPP_CLOSE_PAREN:
-         if (prev_ident || macro->paramc == 0)
-           return true;
-
-         /* Fall through to pick up the error.  */
-       case CPP_COMMA:
-         if (!prev_ident)
-           {
-             cpp_error (pfile, CPP_DL_ERROR, "parameter name missing");
-             return false;
-           }
-         prev_ident = 0;
-         continue;
-
-       case CPP_ELLIPSIS:
-         macro->variadic = 1;
-         if (!prev_ident)
-           {
-             _cpp_save_parameter (pfile, macro,
-                                  pfile->spec_nodes.n__VA_ARGS__);
-             pfile->state.va_args_ok = 1;
-             if (! CPP_OPTION (pfile, c99) && CPP_OPTION (pfile, pedantic))
-               cpp_error (pfile, CPP_DL_PEDWARN,
-                          "anonymous variadic macros were introduced in C99");
-           }
-         else if (CPP_OPTION (pfile, pedantic))
-           cpp_error (pfile, CPP_DL_PEDWARN,
-                      "ISO C does not permit named variadic macros");
-
-         /* We're at the end, and just expect a closing parenthesis.  */
-         token = _cpp_lex_token (pfile);
-         if (token->type == CPP_CLOSE_PAREN)
-           return true;
-         /* Fall through.  */
-
-       case CPP_EOF:
-         cpp_error (pfile, CPP_DL_ERROR, "missing ')' in macro parameter list");
-         return false;
-       }
-    }
-}
-
-/* Allocate room for a token from a macro's replacement list.  */
-static cpp_token *
-alloc_expansion_token (cpp_reader *pfile, cpp_macro *macro)
-{
-  if (BUFF_ROOM (pfile->a_buff) < (macro->count + 1) * sizeof (cpp_token))
-    _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_token));
-
-  return &((cpp_token *) BUFF_FRONT (pfile->a_buff))[macro->count++];
-}
-
-/* Lex a token from the expansion of MACRO, but mark parameters as we
-   find them and warn of traditional stringification.  */
-static cpp_token *
-lex_expansion_token (cpp_reader *pfile, cpp_macro *macro)
-{
-  cpp_token *token;
-
-  pfile->cur_token = alloc_expansion_token (pfile, macro);
-  token = _cpp_lex_direct (pfile);
-
-  /* Is this a parameter?  */
-  if (token->type == CPP_NAME
-      && (token->val.node->flags & NODE_MACRO_ARG) != 0)
-    {
-      token->type = CPP_MACRO_ARG;
-      token->val.arg_no = token->val.node->value.arg_index;
-    }
-  else if (CPP_WTRADITIONAL (pfile) && macro->paramc > 0
-          && (token->type == CPP_STRING || token->type == CPP_CHAR))
-    check_trad_stringification (pfile, macro, &token->val.str);
-
-  return token;
-}
-
-static bool
-create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
-{
-  cpp_token *token;
-  const cpp_token *ctoken;
-
-  /* Get the first token of the expansion (or the '(' of a
-     function-like macro).  */
-  ctoken = _cpp_lex_token (pfile);
-
-  if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE))
-    {
-      bool ok = parse_params (pfile, macro);
-      macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
-      if (!ok)
-       return false;
-
-      /* Success.  Commit the parameter array.  */
-      BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc];
-      macro->fun_like = 1;
-    }
-  else if (ctoken->type != CPP_EOF && !(ctoken->flags & PREV_WHITE))
-    cpp_error (pfile, CPP_DL_PEDWARN,
-              "ISO C requires whitespace after the macro name");
-
-  if (macro->fun_like)
-    token = lex_expansion_token (pfile, macro);
-  else
-    {
-      token = alloc_expansion_token (pfile, macro);
-      *token = *ctoken;
-    }
-
-  for (;;)
-    {
-      /* Check the stringifying # constraint 6.10.3.2.1 of
-        function-like macros when lexing the subsequent token.  */
-      if (macro->count > 1 && token[-1].type == CPP_HASH && macro->fun_like)
-       {
-         if (token->type == CPP_MACRO_ARG)
-           {
-             token->flags &= ~PREV_WHITE;
-             token->flags |= STRINGIFY_ARG;
-             token->flags |= token[-1].flags & PREV_WHITE;
-             token[-1] = token[0];
-             macro->count--;
-           }
-         /* Let assembler get away with murder.  */
-         else if ((CPP_OPTION (pfile, lang) != CLK_ASM)
-               && (!CPP_OPTION(pfile, allow_naked_hash)))
-           {
-             cpp_error (pfile, CPP_DL_ERROR,
-                        "'#' is not followed by a macro parameter");
-             return false;
-           }
-       }
-
-      if (token->type == CPP_EOF)
-       break;
-
-      /* Paste operator constraint 6.10.3.3.1.  */
-      if (token->type == CPP_PASTE)
-       {
-         /* Token-paste ##, can appear in both object-like and
-            function-like macros, but not at the ends.  */
-         if (--macro->count > 0)
-           token = lex_expansion_token (pfile, macro);
-
-         if (macro->count == 0 || token->type == CPP_EOF)
-           {
-             cpp_error (pfile, CPP_DL_ERROR,
-                "'##' cannot appear at either end of a macro expansion");
-             return false;
-           }
-
-         token[-1].flags |= PASTE_LEFT;
-       }
-
-      token = lex_expansion_token (pfile, macro);
-    }
-
-  macro->exp.tokens = (cpp_token *) BUFF_FRONT (pfile->a_buff);
-
-  /* Don't count the CPP_EOF.  */
-  macro->count--;
-
-  /* Clear whitespace on first token for warn_of_redefinition().  */
-  if (macro->count)
-    macro->exp.tokens[0].flags &= ~PREV_WHITE;
-
-  /* Commit the memory.  */
-  BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->exp.tokens[macro->count];
-
-  return true;
-}
-
-/* Parse a macro and save its expansion.  Returns nonzero on success.  */
-bool
-_cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
-{
-  cpp_macro *macro;
-  unsigned int i;
-  bool ok;
-
-  macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro));
-  macro->line = pfile->directive_line;
-  macro->params = 0;
-  macro->paramc = 0;
-  macro->variadic = 0;
-  macro->used = !CPP_OPTION (pfile, warn_unused_macros);
-  macro->count = 0;
-  macro->fun_like = 0;
-  /* To suppress some diagnostics.  */
-  macro->syshdr = pfile->map->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; /* "," */
-    }
-
-  /* This should match below where we fill in the buffer.  */
-  if (CPP_OPTION (pfile, traditional))
-    len += _cpp_replacement_text_len (macro);
-  else
-    {
-      for (i = 0; i < macro->count; i++)
-       {
-         cpp_token *token = &macro->exp.tokens[i];
-
-         if (token->type == CPP_MACRO_ARG)
-           len += NODE_LEN (macro->params[token->val.arg_no - 1]);
-         else
-           len += cpp_token_len (token);
-
-         if (token->flags & STRINGIFY_ARG)
-           len++;                      /* "#" */
-         if (token->flags & PASTE_LEFT)
-           len += 3;           /* " ##" */
-         if (token->flags & PREV_WHITE)
-           len++;              /* " " */
-       }
-    }
-
-  if (len > pfile->macro_buffer_len)
-    {
-      pfile->macro_buffer = xrealloc (pfile->macro_buffer, len);
-      pfile->macro_buffer_len = len;
-    }
-
-  /* Fill in the buffer.  Start with the macro name.  */
-  buffer = pfile->macro_buffer;
-  memcpy (buffer, NODE_NAME (node), NODE_LEN (node));
-  buffer += NODE_LEN (node);
-
-  /* Parameter names.  */
-  if (macro->fun_like)
-    {
-      *buffer++ = '(';
-      for (i = 0; i < macro->paramc; i++)
-       {
-         cpp_hashnode *param = macro->params[i];
-
-         if (param != pfile->spec_nodes.n__VA_ARGS__)
-           {
-             memcpy (buffer, NODE_NAME (param), NODE_LEN (param));
-             buffer += NODE_LEN (param);
-           }
-
-         if (i + 1 < macro->paramc)
-           /* Don't emit a space after the comma here; we're trying
-              to emit a Dwarf-friendly definition, and the Dwarf spec
-              forbids spaces in the argument list.  */
-           *buffer++ = ',';
-         else if (macro->variadic)
-           *buffer++ = '.', *buffer++ = '.', *buffer++ = '.';
-       }
-      *buffer++ = ')';
-    }
-
-  /* The Dwarf spec requires a space after the macro name, even if the
-     definition is the empty string.  */
-  *buffer++ = ' ';
-
-  if (CPP_OPTION (pfile, traditional))
-    buffer = _cpp_copy_replacement_text (macro, buffer);
-  else if (macro->count)
-  /* Expansion tokens.  */
-    {
-      for (i = 0; i < macro->count; i++)
-       {
-         cpp_token *token = &macro->exp.tokens[i];
-
-         if (token->flags & PREV_WHITE)
-           *buffer++ = ' ';
-         if (token->flags & STRINGIFY_ARG)
-           *buffer++ = '#';
-
-         if (token->type == CPP_MACRO_ARG)
-           {
-             memcpy (buffer,
-                     NODE_NAME (macro->params[token->val.arg_no - 1]),
-                     NODE_LEN (macro->params[token->val.arg_no - 1]));
-             buffer += NODE_LEN (macro->params[token->val.arg_no - 1]);
-           }
-         else
-           buffer = cpp_spell_token (pfile, token, buffer);
-
-         if (token->flags & PASTE_LEFT)
-           {
-             *buffer++ = ' ';
-             *buffer++ = '#';
-             *buffer++ = '#';
-             /* Next has PREV_WHITE; see _cpp_create_definition.  */
-           }
-       }
-    }
-
-  *buffer = '\0';
-  return pfile->macro_buffer;
-}
diff --git a/support/cpp2/cpptrad.c b/support/cpp2/cpptrad.c
deleted file mode 100644 (file)
index 6315b10..0000000
+++ /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;
-  unsigned int from_line = pfile->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, from_line, 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;
-  buffer->saved_cur = buffer->cur;
-  buffer->saved_rlimit = buffer->rlimit;
-  /* Prevent the ISO lexer from scanning a fresh line.  */
-  pfile->saved_line = pfile->line--;
-  buffer->need_line = false;
-
-  buffer->cur = 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 = buffer->saved_cur;
-  buffer->rlimit = buffer->saved_rlimit;
-  buffer->need_line = true;
-
-  pfile->overlaid_buffer = NULL;
-  pfile->line = pfile->saved_line;
-}
-
-/* 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;
-  /* 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;
-         pfile->line++;
-
-         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;
-                     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;
-                 pfile->line++;
-                 result = false;
-                 goto done;
-               }
-             else
-               {
-                 bool do_it = false;
-
-                 if (is_numstart (*cur)
-                     && CPP_OPTION (pfile, lang) != CLK_ASM)
-                   do_it = true;
-                 else if (is_idstart (*cur))
-                   /* Check whether we know this directive, but don't
-                      advance.  */
-                   do_it = lex_identifier (pfile, cur)->is_directive;
-
-                 if (do_it || CPP_OPTION (pfile, lang) != CLK_ASM)
-                   {
-                     /* This is a kludge.  We want to have the ISO
-                        preprocessor lex the next token.  */
-                     pfile->buffer->cur = cur;
-                     _cpp_handle_directive (pfile, false /* indented */);
-                     result = false;
-                     goto done;
-                   }
-               }
-           }
-
-         if (pfile->state.in_expression)
-           {
-             lex_state = ls_hash;
-             continue;
-           }
-         break;
-
-       default:
-         break;
-       }
-
-      /* Non-whitespace disables MI optimization and stops treating
-        '<' as a quote in #include.  */
-      header_ok = false;
-      if (!pfile->state.in_directive)
-       pfile->mi_valid = false;
-
-      if (lex_state == ls_none)
-       continue;
-
-      /* Some of these transitions of state are syntax errors.  The
-        ISO preprocessor will issue errors later.  */
-      if (lex_state == ls_fun_open)
-       /* Missing '('.  */
-       lex_state = ls_none;
-      else if (lex_state == ls_hash
-              || lex_state == ls_predicate
-              || lex_state == ls_defined)
-       lex_state = ls_none;
-
-      /* ls_answer and ls_defined_close keep going until ')'.  */
-    }
-
- done:
-  if (fmacro.buff)
-    _cpp_release_buff (pfile, fmacro.buff);
-
-  if (lex_state == ls_fun_close)
-    cpp_error_with_line (pfile, CPP_DL_ERROR, fmacro.line, 0,
-                        "unterminated argument list invoking macro \"%s\"",
-                        NODE_NAME (fmacro.node));
-  return result;
-}
-
-/* Push a context holding the replacement text of the macro NODE on
-   the context stack.  NODE is either object-like, or a function-like
-   macro with no arguments.  */
-static void
-push_replacement_text (cpp_reader *pfile, cpp_hashnode *node)
-{
-  size_t len;
-  const uchar *text;
-  uchar *buf;
-
-  if (node->flags & NODE_BUILTIN)
-    {
-      text = _cpp_builtin_macro_text (pfile, node);
-      len = ustrlen (text);
-      buf = _cpp_unaligned_alloc (pfile, len + 1);
-      memcpy (buf, text, len);
-      buf[len]='\n';
-      text = buf;
-    }
-  else
-    {
-      cpp_macro *macro = node->value.macro;
-      macro->used = 1;
-      text = macro->exp.text;
-      len = macro->count;
-    }
-
-  _cpp_push_text_context (pfile, node, text, len);
-}
-
-/* Returns TRUE if traditional macro recursion is detected.  */
-static bool
-recursive_macro (cpp_reader *pfile, cpp_hashnode *node)
-{
-  bool recursing = !!(node->flags & NODE_DISABLED);
-
-  /* Object-like macros that are already expanding are necessarily
-     recursive.
-
-     However, it is possible to have traditional function-like macros
-     that are not infinitely recursive but recurse to any given depth.
-     Further, it is easy to construct examples that get ever longer
-     until the point they stop recursing.  So there is no easy way to
-     detect true recursion; instead we assume any expansion more than
-     20 deep since the first invocation of this macro must be
-     recursing.  */
-  if (recursing && node->value.macro->fun_like)
-    {
-      size_t depth = 0;
-      cpp_context *context = pfile->context;
-
-      do
-       {
-         depth++;
-         if (context->macro == node && depth > 20)
-           break;
-         context = context->prev;
-       }
-      while (context);
-      recursing = context != NULL;
-    }
-
-  if (recursing)
-    cpp_error (pfile, CPP_DL_ERROR,
-              "detected recursion whilst expanding macro \"%s\"",
-              NODE_NAME (node));
-
-  return recursing;
-}
-
-/* Return the length of the replacement text of a function-like or
-   object-like non-builtin macro.  */
-size_t
-_cpp_replacement_text_len (const cpp_macro *macro)
-{
-  size_t len;
-
-  if (macro->fun_like && (macro->paramc != 0))
-    {
-      const uchar *exp;
-
-      len = 0;
-      for (exp = macro->exp.text;;)
-       {
-         struct block *b = (struct block *) exp;
-
-         len += b->text_len;
-         if (b->arg_index == 0)
-           break;
-         len += NODE_LEN (macro->params[b->arg_index - 1]);
-         exp += BLOCK_LEN (b->text_len);
-       }
-    }
-  else
-    len = macro->count;
-  
-  return len;
-}
-
-/* Copy the replacement text of MACRO to DEST, which must be of
-   sufficient size.  It is not NUL-terminated.  The next character is
-   returned.  */
-uchar *
-_cpp_copy_replacement_text (const cpp_macro *macro, uchar *dest)
-{
-  if (macro->fun_like && (macro->paramc != 0))
-    {
-      const uchar *exp;
-
-      for (exp = macro->exp.text;;)
-       {
-         struct block *b = (struct block *) exp;
-         cpp_hashnode *param;
-
-         memcpy (dest, b->text, b->text_len);
-         dest += b->text_len;
-         if (b->arg_index == 0)
-           break;
-         param = macro->params[b->arg_index - 1];
-         memcpy (dest, NODE_NAME (param), NODE_LEN (param));
-         dest += NODE_LEN (param);
-         exp += BLOCK_LEN (b->text_len);
-       }
-    }
-  else
-    {
-      memcpy (dest, macro->exp.text, macro->count);
-      dest += macro->count;
-    }
-
-  return dest;
-}
-
-/* Push a context holding the replacement text of the macro NODE on
-   the context stack.  NODE is either object-like, or a function-like
-   macro with no arguments.  */
-static void
-replace_args_and_push (cpp_reader *pfile, struct fun_macro *fmacro)
-{
-  cpp_macro *macro = fmacro->node->value.macro;
-
-  if (macro->paramc == 0)
-    push_replacement_text (pfile, fmacro->node);
-  else
-    {
-      const uchar *exp;
-      uchar *p;
-      _cpp_buff *buff;
-      size_t len = 0;
-
-      /* Calculate the length of the argument-replaced text.  */
-      for (exp = macro->exp.text;;)
-       {
-         struct block *b = (struct block *) exp;
-
-         len += b->text_len;
-         if (b->arg_index == 0)
-           break;
-         len += (fmacro->args[b->arg_index]
-                 - fmacro->args[b->arg_index - 1] - 1);
-         exp += BLOCK_LEN (b->text_len);
-       }
-
-      /* Allocate room for the expansion plus \n.  */
-      buff = _cpp_get_buff (pfile, len + 1);
-
-      /* Copy the expansion and replace arguments.  */
-      p = BUFF_FRONT (buff);
-      for (exp = macro->exp.text;;)
-       {
-         struct block *b = (struct block *) exp;
-         size_t arglen;
-
-         memcpy (p, b->text, b->text_len);
-         p += b->text_len;
-         if (b->arg_index == 0)
-           break;
-         arglen = (fmacro->args[b->arg_index]
-                   - fmacro->args[b->arg_index - 1] - 1);
-         memcpy (p, pfile->out.base + fmacro->args[b->arg_index - 1],
-                 arglen);
-         p += arglen;
-         exp += BLOCK_LEN (b->text_len);
-       }
-
-      /* \n-terminate.  */
-      *p = '\n';
-      _cpp_push_text_context (pfile, fmacro->node, BUFF_FRONT (buff), len);
-
-      /* So we free buffer allocation when macro is left.  */
-      pfile->context->buff = buff;
-    }
-}
-
-/* Read and record the parameters, if any, of a function-like macro
-   definition.  Destroys pfile->out.cur.
-
-   Returns true on success, false on failure (syntax error or a
-   duplicate parameter).  On success, CUR (pfile->context) is just
-   past the closing parenthesis.  */
-static bool
-scan_parameters (cpp_reader *pfile, cpp_macro *macro)
-{
-  const uchar *cur = CUR (pfile->context) + 1;
-  bool ok;
-
-  for (;;)
-    {
-      cur = skip_whitespace (pfile, cur, true /* skip_comments */);
-
-      if (is_idstart (*cur))
-       {
-         ok = false;
-         if (_cpp_save_parameter (pfile, macro, lex_identifier (pfile, cur)))
-           break;
-         cur = skip_whitespace (pfile, CUR (pfile->context),
-                                true /* skip_comments */);
-         if (*cur == ',')
-           {
-             cur++;
-             continue;
-           }
-         ok = (*cur == ')');
-         break;
-       }
-
-      ok = (*cur == ')' && macro->paramc == 0);
-      break;
-    }
-
-  if (!ok)
-    cpp_error (pfile, CPP_DL_ERROR, "syntax error in macro parameter list");
-
-  CUR (pfile->context) = cur + (*cur == ')');
-
-  return ok;
-}
-
-/* Save the text from pfile->out.base to pfile->out.cur as
-   the replacement text for the current macro, followed by argument
-   ARG_INDEX, with zero indicating the end of the replacement
-   text.  */
-static void
-save_replacement_text (cpp_reader *pfile, cpp_macro *macro,
-                      unsigned int arg_index)
-{
-  size_t len = pfile->out.cur - pfile->out.base;
-  uchar *exp;
-
-  if (macro->paramc == 0)
-    {
-      /* Object-like and function-like macros without parameters
-        simply store their \n-terminated replacement text.  */
-      exp = _cpp_unaligned_alloc (pfile, len + 1);
-      memcpy (exp, pfile->out.base, len);
-      exp[len] = '\n';
-      macro->exp.text = exp;
-      macro->count = len;
-    }
-  else
-    {
-      /* Store the text's length (unsigned int), the argument index
-        (unsigned short, base 1) and then the text.  */
-      size_t blen = BLOCK_LEN (len);
-      struct block *block;
-
-      if (macro->count + blen > BUFF_ROOM (pfile->a_buff))
-       _cpp_extend_buff (pfile, &pfile->a_buff, macro->count + blen);
-
-      exp = BUFF_FRONT (pfile->a_buff);
-      block = (struct block *) (exp + macro->count);
-      macro->exp.text = exp;
-
-      /* Write out the block information.  */
-      block->text_len = len;
-      block->arg_index = arg_index;
-      memcpy (block->text, pfile->out.base, len);
-
-      /* Lex the rest into the start of the output buffer.  */
-      pfile->out.cur = pfile->out.base;
-
-      macro->count += blen;
-
-      /* If we've finished, commit the memory.  */
-      if (arg_index == 0)
-       BUFF_FRONT (pfile->a_buff) += macro->count;
-    }
-}
-
-/* Analyze and save the replacement text of a macro.  Returns true on
-   success.  */
-bool
-_cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro)
-{
-  const uchar *cur;
-  uchar *limit;
-  cpp_context *context = pfile->context;
-
-  /* The context has not been set up for command line defines, and CUR
-     has not been updated for the macro name for in-file defines.  */
-  pfile->out.cur = pfile->out.base;
-  CUR (context) = pfile->buffer->cur;
-  RLIMIT (context) = pfile->buffer->rlimit;
-  check_output_buffer (pfile, RLIMIT (context) - CUR (context));
-
-  /* Is this a function-like macro?  */
-  if (* CUR (context) == '(')
-    {
-      bool ok = scan_parameters (pfile, macro);
-
-      /* Remember the params so we can clear NODE_MACRO_ARG flags.  */
-      macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
-
-      /* Setting macro to NULL indicates an error occurred, and
-        prevents unnecessary work in _cpp_scan_out_logical_line.  */
-      if (!ok)
-       macro = NULL;
-      else
-       {
-         BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc];
-         macro->fun_like = 1;
-       }
-    }
-
-  /* Skip leading whitespace in the replacement text.  */
-  pfile->buffer->cur
-    = skip_whitespace (pfile, CUR (context),
-                      CPP_OPTION (pfile, discard_comments_in_macro_exp));
-
-  pfile->state.prevent_expansion++;
-  _cpp_scan_out_logical_line (pfile, macro);
-  pfile->state.prevent_expansion--;
-
-  if (!macro)
-    return false;
-
-  /* Skip trailing white space.  */
-  cur = pfile->out.base;
-  limit = pfile->out.cur;
-  while (limit > cur && is_space (limit[-1]))
-    limit--;
-  pfile->out.cur = limit;
-  save_replacement_text (pfile, macro, 0);
-
-  return true;
-}
-
-/* Copy SRC of length LEN to DEST, but convert all contiguous
-   whitespace to a single space, provided it is not in quotes.  The
-   quote currently in effect is pointed to by PQUOTE, and is updated
-   by the function.  Returns the number of bytes copied.  */
-static size_t
-canonicalize_text (uchar *dest, const uchar *src, size_t len, uchar *pquote)
-{
-  uchar *orig_dest = dest;
-  uchar quote = *pquote;
-
-  while (len)
-    {
-      if (is_space (*src) && !quote)
-       {
-         do
-           src++, len--;
-         while (len && is_space (*src));
-         *dest++ = ' ';
-       }
-      else
-       {
-         if (*src == '\'' || *src == '"')
-           {
-             if (!quote)
-               quote = *src;
-             else if (quote == *src)
-               quote = 0;
-           }
-         *dest++ = *src++, len--;
-       }
-    }
-
-  *pquote = quote;
-  return dest - orig_dest;
-}
-
-/* Returns true if MACRO1 and MACRO2 have expansions different other
-   than in the form of their whitespace.  */
-bool
-_cpp_expansions_different_trad (const cpp_macro *macro1,
-                               const cpp_macro *macro2)
-{
-  uchar *p1 = xmalloc (macro1->count + macro2->count);
-  uchar *p2 = p1 + macro1->count;
-  uchar quote1 = 0, quote2 = 0;
-  bool mismatch;
-  size_t len1, len2;
-
-  if (macro1->paramc > 0)
-    {
-      const uchar *exp1 = macro1->exp.text, *exp2 = macro2->exp.text;
-
-      mismatch = true;
-      for (;;)
-       {
-         struct block *b1 = (struct block *) exp1;
-         struct block *b2 = (struct block *) exp2;
-
-         if (b1->arg_index != b2->arg_index)
-           break;
-
-         len1 = canonicalize_text (p1, b1->text, b1->text_len, &quote1);
-         len2 = canonicalize_text (p2, b2->text, b2->text_len, &quote2);
-         if (len1 != len2 || memcmp (p1, p2, len1))
-           break;
-         if (b1->arg_index == 0)
-           {
-             mismatch = false;
-             break;
-           }
-         exp1 += BLOCK_LEN (b1->text_len);
-         exp2 += BLOCK_LEN (b2->text_len);
-       }
-    }
-  else
-    {
-      len1 = canonicalize_text (p1, macro1->exp.text, macro1->count, &quote1);
-      len2 = canonicalize_text (p2, macro2->exp.text, macro2->count, &quote2);
-      mismatch = (len1 != len2 || memcmp (p1, p2, len1));
-    }
-
-  free (p1);
-  return mismatch;
-}
diff --git a/support/cpp2/cppucnid.h b/support/cpp2/cppucnid.h
deleted file mode 100644 (file)
index 1cac7df..0000000
+++ /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 */
index 7b1155b9ebe1a5dfcbc236d0977ba2b2145260dd..8dc988fdd99ed070ca940bbdd00314ccaf14e974 100644 (file)
@@ -1,5 +1,6 @@
 /* Language-independent diagnostic subroutines for the GNU Compiler Collection
-   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Free Software Foundation, Inc.
    Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
 
 This file is part of GCC.
@@ -16,8 +17,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 
 /* This file implements the language independent aspect of diagnostic
@@ -27,11 +28,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #undef FLOAT /* This is for hpux. They should change hpux.  */
 #undef FFS  /* Some systems define this in param.h.  */
 #include "system.h"
-#include "input.h"
+#include "options.h"
 #include "version.h"
 #include "input.h"
 #include "intl.h"
 #include "diagnostic.h"
+#include "opts.h"
 
 
 /* Prototypes.  */
@@ -43,25 +45,15 @@ static void default_diagnostic_finalizer (diagnostic_context *,
                                          diagnostic_info *);
 
 static void error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
-static bool text_specifies_location (text_info *, location_t *);
 static bool diagnostic_count_diagnostic (diagnostic_context *,
                                         diagnostic_info *);
 static void diagnostic_action_after_output (diagnostic_context *,
                                            diagnostic_info *);
 static void real_abort (void) ATTRIBUTE_NORETURN;
 
-extern int rtl_dump_and_exit;
-
 /* A diagnostic_context surrogate for stderr.  */
 static diagnostic_context global_diagnostic_context;
 diagnostic_context *global_dc = &global_diagnostic_context;
-
-/* Boilerplate text used in two locations.  */
-#define bug_report_request \
-"Please submit a full bug report,\n\
-with preprocessed source if appropriate.\n\
-See %s for instructions.\n"
-
 \f
 /* Return a malloc'd string containing MSG formatted a la printf.  The
    caller is responsible for freeing the memory.  */
@@ -98,10 +90,12 @@ diagnostic_initialize (diagnostic_context *context)
   /* By default, diagnostics are sent to stderr.  */
   context->printer->buffer->stream = stderr;
   /* By default, we emit prefixes once per message.  */
-  context->printer->prefixing_rule = DIAGNOSTICS_SHOW_PREFIX_ONCE;
+  context->printer->wrapping.rule = DIAGNOSTICS_SHOW_PREFIX_ONCE;
 
   memset (context->diagnostic_count, 0, sizeof context->diagnostic_count);
-  context->warnings_are_errors_message = warnings_are_errors;
+  context->issue_warnings_are_errors_message = true;
+  context->warning_as_error_requested = false;
+  context->show_option_requested = false;
   context->abort_on_error = false;
   context->internal_error = NULL;
   diagnostic_starter (context) = default_diagnostic_starter;
@@ -109,51 +103,31 @@ diagnostic_initialize (diagnostic_context *context)
   context->last_module = 0;
   context->last_function = NULL;
   context->lock = 0;
-  context->x_data = NULL;
 }
 
-/* Returns true if the next format specifier in TEXT is a format specifier
-   for a location_t.  If so, update the object pointed by LOCUS to reflect
-   the specified location in *TEXT->args_ptr.  */
-static bool
-text_specifies_location (text_info *text, location_t *locus)
+/* Initialize DIAGNOSTIC, where the message MSG has already been
+   translated.  */
+void
+diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
+                               va_list *args, location_t location,
+                               diagnostic_t kind)
 {
-  const char *p;
-  /* Skip any leading text.  */
-  for (p = text->format_spec; *p && *p != '%'; ++p)
-    ;
-
-  /* Extract the location information if any.  */
-  if (p[0] == '%' && p[1] == 'H')
-    {
-      *locus = *va_arg (*text->args_ptr, location_t *);
-      text->format_spec = p + 2;
-      return true;
-    }
-  else if (p[0] == '%' && p[1] == 'J')
-    {
-      tree t = va_arg (*text->args_ptr, tree);
-      *locus = DECL_SOURCE_LOCATION (t);
-      text->format_spec = p + 2;
-      return true;
-    }
-
-  return false;
+  diagnostic->message.err_no = errno;
+  diagnostic->message.args_ptr = args;
+  diagnostic->message.format_spec = msg;
+  diagnostic->location = location;
+  diagnostic->kind = kind;
+  diagnostic->option_index = 0;
 }
 
+/* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
+   translated.  */
 void
-diagnostic_set_info (diagnostic_info *diagnostic, const char *msgid,
+diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
                     va_list *args, location_t location,
                     diagnostic_t kind)
 {
-  diagnostic->message.err_no = errno;
-  diagnostic->message.args_ptr = args;
-  diagnostic->message.format_spec = _(msgid);
-  /* If the diagnostic message doesn't specify a location,
-     use LOCATION.  */
-  if (!text_specifies_location (&diagnostic->message, &diagnostic->location))
-    diagnostic->location = location;
-  diagnostic->kind = kind;
+  diagnostic_set_info_translated (diagnostic, _(gmsgid), args, location, kind);
 }
 
 /* Return a malloc'd string describing a location.  The caller is
@@ -167,16 +141,18 @@ diagnostic_build_prefix (diagnostic_info *diagnostic)
 #undef DEFINE_DIAGNOSTIC_KIND
     "must-not-happen"
   };
-   if (diagnostic->kind >= DK_LAST_DIAGNOSTIC_KIND)
-     abort();
-
-  return diagnostic->location.file
-    ? build_message_string ("%s:%d: %s",
-                            diagnostic->location.file,
-                            diagnostic->location.line,
-                            _(diagnostic_kind_text[diagnostic->kind]))
-    : build_message_string ("%s: %s", progname,
-                            _(diagnostic_kind_text[diagnostic->kind]));
+  const char *text = _(diagnostic_kind_text[diagnostic->kind]);
+  expanded_location s = expand_location (diagnostic->location);
+  gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
+
+  return
+    (s.file == NULL
+     ? build_message_string ("%s: %s", progname, text)
+#ifdef USE_MAPPED_LOCATION
+     : flag_show_column && s.column != 0
+     ? build_message_string ("%s:%d:%d: %s", s.file, s.line, s.column, text)
+#endif
+     : build_message_string ("%s:%d: %s", s.file, s.line, text));
 }
 
 /* Count a diagnostic.  Return true if the message should be printed.  */
@@ -188,8 +164,7 @@ diagnostic_count_diagnostic (diagnostic_context *context,
   switch (kind)
     {
     default:
-      abort();
-      break;
+      gcc_unreachable ();
 
     case DK_ICE:
 #ifndef ENABLE_CHECKING
@@ -200,8 +175,9 @@ diagnostic_count_diagnostic (diagnostic_context *context,
           || diagnostic_kind_count (context, DK_SORRY) > 0)
          && !context->abort_on_error)
        {
+         expanded_location s = expand_location (diagnostic->location);
          fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
-                  diagnostic->location.file, diagnostic->location.line);
+                  s.file, s.line);
          exit (FATAL_EXIT_CODE);
        }
 #endif
@@ -219,17 +195,16 @@ diagnostic_count_diagnostic (diagnostic_context *context,
       if (!diagnostic_report_warnings_p ())
         return false;
 
-      if (!warnings_are_errors)
+      if (!context->warning_as_error_requested)
         {
           ++diagnostic_kind_count (context, DK_WARNING);
           break;
         }
-
-      if (context->warnings_are_errors_message)
+      else if (context->issue_warnings_are_errors_message)
         {
          pp_verbatim (context->printer,
                        "%s: warnings being treated as errors\n", progname);
-          context->warnings_are_errors_message = false;
+          context->issue_warnings_are_errors_message = false;
         }
 
       /* And fall through.  */
@@ -259,13 +234,20 @@ diagnostic_action_after_output (diagnostic_context *context,
     case DK_SORRY:
       if (context->abort_on_error)
        real_abort ();
+      if (flag_fatal_errors)
+       {
+         fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
+         exit (FATAL_EXIT_CODE);
+       }
       break;
 
     case DK_ICE:
       if (context->abort_on_error)
        real_abort ();
 
-      fnotice (stderr, bug_report_request, bug_report_url);
+      fnotice (stderr, "Please submit a full bug report,\n"
+              "with preprocessed source if appropriate.\n"
+              "See %s for instructions.\n", bug_report_url);
       exit (FATAL_EXIT_CODE);
 
     case DK_FATAL:
@@ -276,19 +258,17 @@ diagnostic_action_after_output (diagnostic_context *context,
       exit (FATAL_EXIT_CODE);
 
     default:
-      real_abort ();
+      gcc_unreachable ();
     }
 }
 
 /* Prints out, if necessary, the name of the current function
-  that caused an error.  Called from all error and warning functions.
-  We ignore the FILE parameter, as it cannot be relied upon.  */
-
+   that caused an error.  Called from all error and warning functions.  */
 void
 diagnostic_report_current_function (diagnostic_context *context)
 {
   diagnostic_report_current_module (context);
-  (*lang_hooks.print_error_function) (context, input_filename);
+  lang_hooks.print_error_function (context, input_filename);
 }
 
 void
@@ -302,18 +282,23 @@ diagnostic_report_current_module (diagnostic_context *context)
       pp_needs_newline (context->printer) = false;
     }
 
-  if (input_file_stack && diagnostic_last_module_changed (context))
+  p = input_file_stack;
+  if (p && diagnostic_last_module_changed (context))
     {
-      p = input_file_stack;
+      expanded_location xloc = expand_location (p->location);
       pp_verbatim (context->printer,
                    "In file included from %s:%d",
-                   p->location.file, p->location.line);
+                  xloc.file, xloc.line);
       while ((p = p->next) != NULL)
-       pp_verbatim (context->printer,
-                     ",\n                 from %s:%d",
-                     p->location.file, p->location.line);
-      pp_verbatim (context->printer, ":\n");
+       {
+         xloc = expand_location (p->location);
+         pp_verbatim (context->printer,
+                      ",\n                 from %s:%d",
+                      xloc.file, xloc.line);
+       }
+      pp_verbatim (context->printer, ":");
       diagnostic_set_last_module (context);
+      pp_newline (context->printer);
     }
 }
 
@@ -327,7 +312,7 @@ default_diagnostic_starter (diagnostic_context *context,
 
 static void
 default_diagnostic_finalizer (diagnostic_context *context,
-                             diagnostic_info *diagnostic __attribute__((unused)))
+                             diagnostic_info *diagnostic ATTRIBUTE_UNUSED)
 {
   pp_destroy_prefix (context->printer);
 }
@@ -342,16 +327,40 @@ void
 diagnostic_report_diagnostic (diagnostic_context *context,
                              diagnostic_info *diagnostic)
 {
-  if (context->lock++ && diagnostic->kind < DK_SORRY)
-    error_recursion (context);
+  if (context->lock > 0)
+    {
+      /* If we're reporting an ICE in the middle of some other error,
+        try to flush out the previous error, then let this one
+        through.  Don't do this more than once.  */
+      if (diagnostic->kind == DK_ICE && context->lock == 1)
+       pp_flush (context->printer);
+      else
+       error_recursion (context);
+    }
+
+  if (diagnostic->option_index
+      && ! option_enabled (diagnostic->option_index))
+    return;
+
+  context->lock++;
 
   if (diagnostic_count_diagnostic (context, diagnostic))
     {
+      const char *saved_format_spec = diagnostic->message.format_spec;
+
+      if (context->show_option_requested && diagnostic->option_index)
+       diagnostic->message.format_spec
+         = ACONCAT ((diagnostic->message.format_spec,
+                     " [", cl_options[diagnostic->option_index].opt_text, "]", NULL));
+
+      diagnostic->message.locus = &diagnostic->location;
+      pp_format (context->printer, &diagnostic->message);
       (*diagnostic_starter (context)) (context, diagnostic);
-      pp_format_text (context->printer, &diagnostic->message);
+      pp_output_formatted_text (context->printer);
       (*diagnostic_finalizer (context)) (context, diagnostic);
       pp_flush (context->printer);
       diagnostic_action_after_output (context, diagnostic);
+      diagnostic->message.format_spec = saved_format_spec;
     }
 
   context->lock--;
@@ -370,20 +379,10 @@ trim_filename (const char *name)
 
   /* First skip any "../" in each filename.  This allows us to give a proper
      reference to a file in a subdirectory.  */
-  while (p[0] == '.' && p[1] == '.'
-        && (p[2] == DIR_SEPARATOR
-#ifdef DIR_SEPARATOR_2
-            || p[2] == DIR_SEPARATOR_2
-#endif
-            ))
+  while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
     p += 3;
 
-  while (q[0] == '.' && q[1] == '.'
-        && (q[2] == DIR_SEPARATOR
-#ifdef DIR_SEPARATOR_2
-            || p[2] == DIR_SEPARATOR_2
-#endif
-            ))
+  while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
     q += 3;
 
   /* Now skip any parts the two filenames have in common.  */
@@ -391,11 +390,7 @@ trim_filename (const char *name)
     p++, q++;
 
   /* Now go backwards until the previous directory separator.  */
-  while (p > name && p[-1] != DIR_SEPARATOR
-#ifdef DIR_SEPARATOR_2
-        && p[-1] != DIR_SEPARATOR_2
-#endif
-        )
+  while (p > name && !IS_DIR_SEPARATOR (p[-1]))
     p--;
 
   return p;
@@ -407,15 +402,16 @@ trim_filename (const char *name)
 /* Text to be emitted verbatim to the error message stream; this
    produces no prefix and disables line-wrapping.  Use rarely.  */
 void
-verbatim (const char *msgid, ...)
+verbatim (const char *gmsgid, ...)
 {
   text_info text;
   va_list ap;
 
-  va_start (ap, msgid);
+  va_start (ap, gmsgid);
   text.err_no = errno;
   text.args_ptr = &ap;
-  text.format_spec = _(msgid);
+  text.format_spec = _(gmsgid);
+  text.locus = NULL;
   pp_format_verbatim (global_dc->printer, &text);
   pp_flush (global_dc->printer);
   va_end (ap);
@@ -424,13 +420,13 @@ verbatim (const char *msgid, ...)
 /* An informative note.  Use this for additional details on an error
    message.  */
 void
-inform (const char *msgid, ...)
+inform (const char *gmsgid, ...)
 {
   diagnostic_info diagnostic;
   va_list ap;
 
-  va_start (ap, msgid);
-  diagnostic_set_info (&diagnostic, msgid, &ap, input_location, DK_NOTE);
+  va_start (ap, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_NOTE);
   report_diagnostic (&diagnostic);
   va_end (ap);
 }
@@ -438,13 +434,27 @@ inform (const char *msgid, ...)
 /* A warning.  Use this for code which is correct according to the
    relevant language specification but is likely to be buggy anyway.  */
 void
-warning (const char *msgid, ...)
+warning (int opt, const char *gmsgid, ...)
 {
   diagnostic_info diagnostic;
   va_list ap;
 
-  va_start (ap, msgid);
-  diagnostic_set_info (&diagnostic, msgid, &ap, input_location, DK_WARNING);
+  va_start (ap, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_WARNING);
+  diagnostic.option_index = opt;
+
+  report_diagnostic (&diagnostic);
+  va_end (ap);
+}
+
+void
+warning0 (const char *gmsgid, ...)
+{
+  diagnostic_info diagnostic;
+  va_list ap;
+
+  va_start (ap, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_WARNING);
   report_diagnostic (&diagnostic);
   va_end (ap);
 }
@@ -458,13 +468,13 @@ warning (const char *msgid, ...)
    of the -pedantic command-line switch.  To get a warning enabled
    only with that switch, write "if (pedantic) pedwarn (...);"  */
 void
-pedwarn (const char *msgid, ...)
+pedwarn (const char *gmsgid, ...)
 {
   diagnostic_info diagnostic;
   va_list ap;
 
-  va_start (ap, msgid);
-  diagnostic_set_info (&diagnostic, msgid, &ap, input_location,
+  va_start (ap, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location,
                       pedantic_error_kind ());
   report_diagnostic (&diagnostic);
   va_end (ap);
@@ -473,13 +483,13 @@ pedwarn (const char *msgid, ...)
 /* A hard error: the code is definitely ill-formed, and an object file
    will not be produced.  */
 void
-error (const char *msgid, ...)
+error (const char *gmsgid, ...)
 {
   diagnostic_info diagnostic;
   va_list ap;
 
-  va_start (ap, msgid);
-  diagnostic_set_info (&diagnostic, msgid, &ap, input_location, DK_ERROR);
+  va_start (ap, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_ERROR);
   report_diagnostic (&diagnostic);
   va_end (ap);
 }
@@ -488,13 +498,13 @@ error (const char *msgid, ...)
    required by the relevant specification but not implemented by GCC.
    An object file will not be produced.  */
 void
-sorry (const char *msgid, ...)
+sorry (const char *gmsgid, ...)
 {
   diagnostic_info diagnostic;
   va_list ap;
 
-  va_start (ap, msgid);
-  diagnostic_set_info (&diagnostic, msgid, &ap, input_location, DK_SORRY);
+  va_start (ap, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_SORRY);
   report_diagnostic (&diagnostic);
   va_end (ap);
 }
@@ -503,18 +513,17 @@ sorry (const char *msgid, ...)
    continue.  Do not use this for internal consistency checks; that's
    internal_error.  Use of this function should be rare.  */
 void
-fatal_error (const char *msgid, ...)
+fatal_error (const char *gmsgid, ...)
 {
   diagnostic_info diagnostic;
   va_list ap;
 
-  va_start (ap, msgid);
-  diagnostic_set_info (&diagnostic, msgid, &ap, input_location, DK_FATAL);
+  va_start (ap, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_FATAL);
   report_diagnostic (&diagnostic);
   va_end (ap);
 
-  /* NOTREACHED */
-  real_abort ();
+  gcc_unreachable ();
 }
 
 /* An internal consistency check has failed.  We make no attempt to
@@ -522,18 +531,17 @@ fatal_error (const char *msgid, ...)
    a more specific message, or some other good reason, you should use
    abort () instead of calling this function directly.  */
 void
-internal_error (const char *msgid, ...)
+internal_error (const char *gmsgid, ...)
 {
   diagnostic_info diagnostic;
   va_list ap;
 
-  va_start (ap, msgid);
-  diagnostic_set_info (&diagnostic, msgid, &ap, input_location, DK_ICE);
+  va_start (ap, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_ICE);
   report_diagnostic (&diagnostic);
   va_end (ap);
 
-  /* NOTREACHED */
-  real_abort ();
+  gcc_unreachable ();
 }
 \f
 /* Special case error functions.  Most are implemented in terms of the
@@ -542,12 +550,12 @@ internal_error (const char *msgid, ...)
 /* Print a diagnostic MSGID on FILE.  This is just fprintf, except it
    runs its second argument through gettext.  */
 void
-fnotice (FILE *file, const char *msgid, ...)
+fnotice (FILE *file, const char *cmsgid, ...)
 {
   va_list ap;
 
-  va_start (ap, msgid);
-  vfprintf (file, _(msgid), ap);
+  va_start (ap, cmsgid);
+  vfprintf (file, _(cmsgid), ap);
   va_end (ap);
 }
 
@@ -559,13 +567,22 @@ fnotice (FILE *file, const char *msgid, ...)
 static void
 error_recursion (diagnostic_context *context)
 {
+  diagnostic_info diagnostic;
+
   if (context->lock < 3)
     pp_flush (context->printer);
 
   fnotice (stderr,
           "Internal compiler error: Error reporting routines re-entered.\n");
-  fnotice (stderr, bug_report_request, bug_report_url);
-  exit (FATAL_EXIT_CODE);
+
+  /* Call diagnostic_action_after_output to get the "please submit a bug
+     report" message.  It only looks at the kind field of diagnostic_info.  */
+  diagnostic.kind = DK_ICE;
+  diagnostic_action_after_output (context, &diagnostic);
+
+  /* Do not use gcc_unreachable here; that goes through internal_error
+     and therefore would cause infinite recursion.  */
+  real_abort ();
 }
 
 /* Report an internal compiler error in a friendly manner.  This is
index daf24279d5e9016c0ab10061c15f0d6bfff7a768..3a3204bdcc3599f96b4e313576ca5df3c9931644 100644 (file)
@@ -1,5 +1,6 @@
 /* Various declarations for language-independent diagnostics subroutines.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+   Free Software Foundation, Inc.
    Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
 
 This file is part of GCC.
@@ -16,8 +17,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #ifndef GCC_DIAGNOSTIC_H
 #define GCC_DIAGNOSTIC_H
@@ -42,6 +43,8 @@ typedef struct
   location_t location;
   /* The kind of diagnostic it is about.  */
   diagnostic_t kind;
+  /* Which OPT_* directly controls this diagnostic.  */
+  int option_index;
 } diagnostic_info;
 
 #define pedantic_error_kind() (flag_pedantic_errors ? DK_ERROR : DK_WARNING)
@@ -65,7 +68,14 @@ struct diagnostic_context
 
   /* True if we should display the "warnings are being tread as error"
      message, usually displayed once per compiler run.  */
-  bool warnings_are_errors_message;
+  bool issue_warnings_are_errors_message;
+  
+  /* True if it has been requested that warnings be treated as errors.  */
+  bool warning_as_error_requested;
+
+  /* True if we should print the command line option which controls
+     each diagnostic, if known.  */
+  bool show_option_requested;
 
   /* True if we should raise a SIGABRT on errors.  */
   bool abort_on_error;
@@ -94,9 +104,6 @@ struct diagnostic_context
   int last_module;
 
   int lock;
-  
-  /* Hook for front-end extensions.  */
-  void *x_data;
 };
 
 /* Client supplied function to announce a diagnostic.  */
@@ -113,11 +120,11 @@ struct diagnostic_context
 #define diagnostic_format_decoder(DC) ((DC)->printer->format_decoder)
 
 /* Same as output_prefixing_rule.  Works on 'diagnostic_context *'.  */
-#define diagnostic_prefixing_rule(DC) ((DC)->printer->prefixing_rule)
+#define diagnostic_prefixing_rule(DC) ((DC)->printer->wrapping.rule)
 
 /* Maximum characters per line in automatic line wrapping mode.
    Zero means don't wrap lines.  */
-#define diagnostic_line_cutoff(DC) ((DC)->printer->ideal_maximum_length)
+#define diagnostic_line_cutoff(DC) ((DC)->printer->wrapping.line_cutoff)
 
 #define diagnostic_flush_buffer(DC) pp_base_flush ((DC)->printer)
 
@@ -174,12 +181,27 @@ extern void diagnostic_report_current_module (diagnostic_context *);
 extern void diagnostic_report_current_function (diagnostic_context *);
 extern void diagnostic_report_diagnostic (diagnostic_context *,
                                          diagnostic_info *);
+#ifdef ATTRIBUTE_GCC_DIAG
 extern void diagnostic_set_info (diagnostic_info *, const char *, va_list *,
-                                location_t, diagnostic_t);
+                                location_t, diagnostic_t) ATTRIBUTE_GCC_DIAG(2,0);
+extern void diagnostic_set_info_translated (diagnostic_info *, const char *,
+                                           va_list *, location_t,
+                                           diagnostic_t)
+     ATTRIBUTE_GCC_DIAG(2,0);
+#endif
 extern char *diagnostic_build_prefix (diagnostic_info *);
 
 /* Pure text formatting support functions.  */
-extern void verbatim (const char *, ...);
 extern char *file_name_as_prefix (const char *);
 
+/* In tree-pretty-print.c  */
+extern int dump_generic_node (pretty_printer *, tree, int, int, bool);
+extern void print_generic_stmt (FILE *, tree, int);
+extern void print_generic_stmt_indented (FILE *, tree, int, int);
+extern void print_generic_expr (FILE *, tree, int);
+extern void print_generic_decl (FILE *, tree, int);
+
+extern void debug_generic_expr (tree);
+extern void debug_generic_stmt (tree);
+extern void debug_c_tree (tree);
 #endif /* ! GCC_DIAGNOSTIC_H */
index 5093a65059a8fbd1316886a8c563c3911089ddab..d5e391d9c77bbad3de31aa95681b6899160280d4 100644 (file)
@@ -1,5 +1,5 @@
 /* Exception Handling interface routines.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
    Contributed by Mike Stump <mrs@cygnus.com>.
 
@@ -17,14 +17,12 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 
 struct function;
 
-struct inline_remap;
-
 /* Per-function EH data.  Used only in except.c, but GC and others
    manipulate pointers to the opaque type.  */
 struct eh_status;
@@ -35,62 +33,25 @@ struct eh_region;
 /* Test: is exception handling turned on?  */
 extern int doing_eh (int);
 
-/* Start an exception handling region.  All instructions emitted after
-   this point are considered to be part of the region until an
-   expand_eh_region_end variant is invoked.  */
-extern void expand_eh_region_start (void);
-
-/* End an exception handling region for a cleanup.  HANDLER is an
-   expression to expand for the cleanup.  */
-extern void expand_eh_region_end_cleanup (tree);
-
-/* End an exception handling region for a try block, and prepares
-   for subsequent calls to expand_start_catch.  */
-extern void expand_start_all_catch (void);
-
-/* Begin a catch clause.  TYPE is an object to be matched by the
-   runtime, or a list of such objects, or null if this is a catch-all
-   clause.  */
-extern void expand_start_catch (tree);
-
-/* End a catch clause.  Control will resume after the try/catch block.  */
-extern void expand_end_catch (void);
-
-/* End a sequence of catch handlers for a try block.  */
-extern void expand_end_all_catch (void);
-
-/* End an exception region for an exception type filter.  ALLOWED is a
-   TREE_LIST of TREE_VALUE objects to be matched by the runtime.
-   FAILURE is a function to invoke if a mismatch occurs.  */
-extern void expand_eh_region_end_allowed (tree, tree);
-
-/* End an exception region for a must-not-throw filter.  FAILURE is a
-   function to invoke if an uncaught exception propagates this far.  */
-extern void expand_eh_region_end_must_not_throw (tree);
-
-/* End an exception region for a throw.  No handling goes on here,
-   but it's the easiest way for the front-end to indicate what type
-   is being thrown.  */
-extern void expand_eh_region_end_throw (tree);
-
-/* End a fixup region.  Within this region the cleanups for the immediately
-   enclosing region are _not_ run.  This is used for goto cleanup to avoid
-   destroying an object twice.  */
-extern void expand_eh_region_end_fixup (tree);
-
 /* Note that the current EH region (if any) may contain a throw, or a
    call to a function which itself may contain a throw.  */
-extern void note_eh_region_may_contain_throw (void);
+extern void note_eh_region_may_contain_throw (struct eh_region *);
+extern void note_current_region_may_contain_throw (void);
 
 /* Invokes CALLBACK for every exception handler label.  Only used by old
    loop hackery; should not be used by new code.  */
 extern void for_each_eh_label (void (*) (rtx));
 
+/* Invokes CALLBACK for every exception region in the current function.  */
+extern void for_each_eh_region (void (*) (struct eh_region *));
+
 /* Determine if the given INSN can throw an exception.  */
+extern bool can_throw_internal_1 (int, bool);
 extern bool can_throw_internal (rtx);
+extern bool can_throw_external_1 (int, bool);
 extern bool can_throw_external (rtx);
 
-/* Set current_function_nothrow and cfun->all_throwers_are_sibcalls.  */
+/* Set TREE_NOTHROW and cfun->all_throwers_are_sibcalls.  */
 extern void set_nothrow_function_flags (void);
 
 /* After initial rtl generation, call back to finish generating
@@ -119,10 +80,39 @@ extern void expand_builtin_eh_return (tree, tree);
 extern void expand_eh_return (void);
 extern rtx expand_builtin_extend_pointer (tree);
 extern rtx get_exception_pointer (struct function *);
-extern int duplicate_eh_regions (struct function *, struct inline_remap *);
+extern rtx get_exception_filter (struct function *);
+typedef tree (*duplicate_eh_regions_map) (tree, void *);
+extern int duplicate_eh_regions (struct function *, duplicate_eh_regions_map, void *, int);
 
 extern void sjlj_emit_function_exit_after (rtx);
-
+extern void default_init_unwind_resume_libfunc (void);
+
+extern struct eh_region *gen_eh_region_cleanup (struct eh_region *,
+                                               struct eh_region *);
+extern struct eh_region *gen_eh_region_try (struct eh_region *);
+extern struct eh_region *gen_eh_region_catch (struct eh_region *, tree);
+extern struct eh_region *gen_eh_region_allowed (struct eh_region *, tree);
+extern struct eh_region *gen_eh_region_must_not_throw (struct eh_region *);
+extern int get_eh_region_number (struct eh_region *);
+extern bool get_eh_region_may_contain_throw (struct eh_region *);
+extern tree get_eh_region_tree_label (struct eh_region *);
+extern void set_eh_region_tree_label (struct eh_region *, tree);
+
+extern void foreach_reachable_handler (int, bool,
+                                      void (*) (struct eh_region *, void *),
+                                      void *);
+
+extern void collect_eh_region_array (void);
+extern void expand_resx_expr (tree);
+extern void verify_eh_tree (struct function *);
+extern void dump_eh_tree (FILE *, struct function *);
+
+/* tree-eh.c */
+extern void add_stmt_to_eh_region_fn (struct function *, tree, int);
+extern bool remove_stmt_from_eh_region_fn (struct function *, tree);
+extern int lookup_stmt_eh_region_fn (struct function *, tree);
+extern int lookup_stmt_eh_region (tree);
+extern bool verify_eh_edges (tree);
 
 /* If non-NULL, this is a function that returns an expression to be
    executed if an unhandled exception is propagated out of a cleanup
@@ -145,7 +135,7 @@ extern tree (*lang_eh_runtime_type) (tree);
 
 #ifndef MUST_USE_SJLJ_EXCEPTIONS
 # if !(defined (EH_RETURN_DATA_REGNO)                  \
-       && (defined (IA64_UNWIND_INFO)                  \
+       && (defined (TARGET_UNWIND_INFO)                        \
           || (DWARF2_UNWIND_INFO                       \
               && (defined (EH_RETURN_HANDLER_RTX)      \
                   || defined (HAVE_eh_return)))))
@@ -167,10 +157,19 @@ extern tree (*lang_eh_runtime_type) (tree);
 #  if !defined(EH_RETURN_HANDLER_RTX) && !defined(HAVE_eh_return)
     #error "EH_RETURN_HANDLER_RTX or eh_return required"
 #  endif
-#  if !defined(DWARF2_UNWIND_INFO) && !defined(IA64_UNWIND_INFO)
-    #error "{DWARF2,IA64}_UNWIND_INFO required"
+#  if !defined(DWARF2_UNWIND_INFO) && !defined(TARGET_UNWIND_INFO)
+    #error "{DWARF2,TARGET}_UNWIND_INFO required"
 #  endif
 # endif
 #else
 # define USING_SJLJ_EXCEPTIONS         MUST_USE_SJLJ_EXCEPTIONS
 #endif
+
+struct throw_stmt_node GTY(())
+{
+  tree stmt;
+  int region_nr;
+};
+
+extern struct htab *get_eh_throw_stmt_table (struct function *);
+extern void set_eh_throw_stmt_table (struct function *, struct htab *);
diff --git a/support/cpp2/hashtab.c b/support/cpp2/hashtab.c
deleted file mode 100644 (file)
index 231fbc0..0000000
+++ /dev/null
@@ -1,853 +0,0 @@
-/* An expandable hash tables datatype.  
-   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
-   Contributed by Vladimir Makarov (vmakarov@cygnus.com).
-
-This file is part of the libiberty library.
-Libiberty is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public
-License as published by the Free Software Foundation; either
-version 2 of the License, or (at your option) any later version.
-
-Libiberty is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with libiberty; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* This package implements basic hash table functionality.  It is possible
-   to search for an entry, create an entry and destroy an entry.
-
-   Elements in the table are generic pointers.
-
-   The size of the table is not fixed; if the occupancy of the table
-   grows too high the hash table will be expanded.
-
-   The abstract data implementation is based on generalized Algorithm D
-   from Knuth's book "The art of computer programming".  Hash table is
-   expanded by creation of new hash table and transferring elements from
-   the old table to the new table. */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <sys/types.h>
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-
-#include <stdio.h>
-
-#include "libiberty.h"
-#include "hashtab.h"
-
-/* This macro defines reserved value for empty table entry. */
-
-#define EMPTY_ENTRY    ((PTR) 0)
-
-/* This macro defines reserved value for table entry which contained
-   a deleted element. */
-
-#define DELETED_ENTRY  ((PTR) 1)
-
-static unsigned long higher_prime_number PARAMS ((unsigned long));
-static hashval_t hash_pointer PARAMS ((const void *));
-static int eq_pointer PARAMS ((const void *, const void *));
-static int htab_expand PARAMS ((htab_t));
-static PTR *find_empty_slot_for_expand  PARAMS ((htab_t, hashval_t));
-
-/* At some point, we could make these be NULL, and modify the
-   hash-table routines to handle NULL specially; that would avoid
-   function-call overhead for the common case of hashing pointers.  */
-htab_hash htab_hash_pointer = hash_pointer;
-htab_eq htab_eq_pointer = eq_pointer;
-
-/* The following function returns a nearest prime number which is
-   greater than N, and near a power of two. */
-
-static unsigned long
-higher_prime_number (n)
-     unsigned long n;
-{
-  /* These are primes that are near, but slightly smaller than, a
-     power of two.  */
-  static const unsigned long primes[] = {
-    (unsigned long) 7,
-    (unsigned long) 13,
-    (unsigned long) 31,
-    (unsigned long) 61,
-    (unsigned long) 127,
-    (unsigned long) 251,
-    (unsigned long) 509,
-    (unsigned long) 1021,
-    (unsigned long) 2039,
-    (unsigned long) 4093,
-    (unsigned long) 8191,
-    (unsigned long) 16381,
-    (unsigned long) 32749,
-    (unsigned long) 65521,
-    (unsigned long) 131071,
-    (unsigned long) 262139,
-    (unsigned long) 524287,
-    (unsigned long) 1048573,
-    (unsigned long) 2097143,
-    (unsigned long) 4194301,
-    (unsigned long) 8388593,
-    (unsigned long) 16777213,
-    (unsigned long) 33554393,
-    (unsigned long) 67108859,
-    (unsigned long) 134217689,
-    (unsigned long) 268435399,
-    (unsigned long) 536870909,
-    (unsigned long) 1073741789,
-    (unsigned long) 2147483647,
-                                       /* 4294967291L */
-    ((unsigned long) 2147483647) + ((unsigned long) 2147483644),
-  };
-
-  const unsigned long *low = &primes[0];
-  const unsigned long *high = &primes[sizeof(primes) / sizeof(primes[0])];
-
-  while (low != high)
-    {
-      const unsigned long *mid = low + (high - low) / 2;
-      if (n > *mid)
-       low = mid + 1;
-      else
-       high = mid;
-    }
-
-  /* If we've run out of primes, abort.  */
-  if (n > *low)
-    {
-      fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
-      abort ();
-    }
-
-  return *low;
-}
-
-/* Returns a hash code for P.  */
-
-static hashval_t
-hash_pointer (p)
-     const PTR p;
-{
-  return (hashval_t) ((long)p >> 3);
-}
-
-/* Returns non-zero if P1 and P2 are equal.  */
-
-static int
-eq_pointer (p1, p2)
-     const PTR p1;
-     const PTR p2;
-{
-  return p1 == p2;
-}
-
-/* This function creates table with length slightly longer than given
-   source length.  Created hash table is initiated as empty (all the
-   hash table entries are EMPTY_ENTRY).  The function returns the
-   created hash table, or NULL if memory allocation fails.  */
-
-htab_t
-htab_create_alloc (size, hash_f, eq_f, del_f, alloc_f, free_f)
-     size_t size;
-     htab_hash hash_f;
-     htab_eq eq_f;
-     htab_del del_f;
-     htab_alloc alloc_f;
-     htab_free free_f;
-{
-  htab_t result;
-
-  size = higher_prime_number (size);
-  result = (htab_t) (*alloc_f) (1, sizeof (struct htab));
-  if (result == NULL)
-    return NULL;
-  result->entries = (PTR *) (*alloc_f) (size, sizeof (PTR));
-  if (result->entries == NULL)
-    {
-      if (free_f != NULL)
-       (*free_f) (result);
-      return NULL;
-    }
-  result->size = size;
-  result->hash_f = hash_f;
-  result->eq_f = eq_f;
-  result->del_f = del_f;
-  result->alloc_f = alloc_f;
-  result->free_f = free_f;
-  return result;
-}
-
-/* As above, but use the variants of alloc_f and free_f which accept
-   an extra argument.  */
-
-htab_t
-htab_create_alloc_ex (size, hash_f, eq_f, del_f, alloc_arg, alloc_f,
-                     free_f)
-     size_t size;
-     htab_hash hash_f;
-     htab_eq eq_f;
-     htab_del del_f;
-     PTR alloc_arg;
-     htab_alloc_with_arg alloc_f;
-     htab_free_with_arg free_f;
-{
-  htab_t result;
-
-  size = higher_prime_number (size);
-  result = (htab_t) (*alloc_f) (alloc_arg, 1, sizeof (struct htab));
-  if (result == NULL)
-    return NULL;
-  result->entries = (PTR *) (*alloc_f) (alloc_arg, size, sizeof (PTR));
-  if (result->entries == NULL)
-    {
-      if (free_f != NULL)
-       (*free_f) (alloc_arg, result);
-      return NULL;
-    }
-  result->size = size;
-  result->hash_f = hash_f;
-  result->eq_f = eq_f;
-  result->del_f = del_f;
-  result->alloc_arg = alloc_arg;
-  result->alloc_with_arg_f = alloc_f;
-  result->free_with_arg_f = free_f;
-  return result;
-}
-
-/* Update the function pointers and allocation parameter in the htab_t.  */
-
-void
-htab_set_functions_ex (htab, hash_f, eq_f, del_f, alloc_arg, alloc_f, free_f)
-     htab_t htab;
-     htab_hash hash_f;
-     htab_eq eq_f;
-     htab_del del_f;
-     PTR alloc_arg;
-     htab_alloc_with_arg alloc_f;
-     htab_free_with_arg free_f;
-{
-  htab->hash_f = hash_f;
-  htab->eq_f = eq_f;
-  htab->del_f = del_f;
-  htab->alloc_arg = alloc_arg;
-  htab->alloc_with_arg_f = alloc_f;
-  htab->free_with_arg_f = free_f;
-}
-
-/* These functions exist solely for backward compatibility.  */
-
-#undef htab_create
-htab_t
-htab_create (size, hash_f, eq_f, del_f)
-     size_t size;
-     htab_hash hash_f;
-     htab_eq eq_f;
-     htab_del del_f;
-{
-  return htab_create_alloc (size, hash_f, eq_f, del_f, xcalloc, free);
-}
-
-htab_t
-htab_try_create (size, hash_f, eq_f, del_f)
-     size_t size;
-     htab_hash hash_f;
-     htab_eq eq_f;
-     htab_del del_f;
-{
-  return htab_create_alloc (size, hash_f, eq_f, del_f, calloc, free);
-}
-
-/* This function frees all memory allocated for given hash table.
-   Naturally the hash table must already exist. */
-
-void
-htab_delete (htab)
-     htab_t htab;
-{
-  int i;
-
-  if (htab->del_f)
-    for (i = htab->size - 1; i >= 0; i--)
-      if (htab->entries[i] != EMPTY_ENTRY
-         && htab->entries[i] != DELETED_ENTRY)
-       (*htab->del_f) (htab->entries[i]);
-
-  if (htab->free_f != NULL)
-    {
-      (*htab->free_f) (htab->entries);
-      (*htab->free_f) (htab);
-    }
-  else if (htab->free_with_arg_f != NULL)
-    {
-      (*htab->free_with_arg_f) (htab->alloc_arg, htab->entries);
-      (*htab->free_with_arg_f) (htab->alloc_arg, htab);
-    }
-}
-
-/* This function clears all entries in the given hash table.  */
-
-void
-htab_empty (htab)
-     htab_t htab;
-{
-  int i;
-
-  if (htab->del_f)
-    for (i = htab->size - 1; i >= 0; i--)
-      if (htab->entries[i] != EMPTY_ENTRY
-         && htab->entries[i] != DELETED_ENTRY)
-       (*htab->del_f) (htab->entries[i]);
-
-  memset (htab->entries, 0, htab->size * sizeof (PTR));
-}
-
-/* Similar to htab_find_slot, but without several unwanted side effects:
-    - Does not call htab->eq_f when it finds an existing entry.
-    - Does not change the count of elements/searches/collisions in the
-      hash table.
-   This function also assumes there are no deleted entries in the table.
-   HASH is the hash value for the element to be inserted.  */
-
-static PTR *
-find_empty_slot_for_expand (htab, hash)
-     htab_t htab;
-     hashval_t hash;
-{
-  size_t size = htab->size;
-  unsigned int index = hash % size;
-  PTR *slot = htab->entries + index;
-  hashval_t hash2;
-
-  if (*slot == EMPTY_ENTRY)
-    return slot;
-  else if (*slot == DELETED_ENTRY)
-    abort ();
-
-  hash2 = 1 + hash % (size - 2);
-  for (;;)
-    {
-      index += hash2;
-      if (index >= size)
-       index -= size;
-
-      slot = htab->entries + index;
-      if (*slot == EMPTY_ENTRY)
-       return slot;
-      else if (*slot == DELETED_ENTRY)
-       abort ();
-    }
-}
-
-/* The following function changes size of memory allocated for the
-   entries and repeatedly inserts the table elements.  The occupancy
-   of the table after the call will be about 50%.  Naturally the hash
-   table must already exist.  Remember also that the place of the
-   table entries is changed.  If memory allocation failures are allowed,
-   this function will return zero, indicating that the table could not be
-   expanded.  If all goes well, it will return a non-zero value.  */
-
-static int
-htab_expand (htab)
-     htab_t htab;
-{
-  PTR *oentries;
-  PTR *olimit;
-  PTR *p;
-  PTR *nentries;
-  size_t nsize;
-
-  oentries = htab->entries;
-  olimit = oentries + htab->size;
-
-  /* Resize only when table after removal of unused elements is either
-     too full or too empty.  */
-  if ((htab->n_elements - htab->n_deleted) * 2 > htab->size
-      || ((htab->n_elements - htab->n_deleted) * 8 < htab->size
-         && htab->size > 32))
-    nsize = higher_prime_number ((htab->n_elements - htab->n_deleted) * 2);
-  else
-    nsize = htab->size;
-
-  if (htab->alloc_with_arg_f != NULL)
-    nentries = (PTR *) (*htab->alloc_with_arg_f) (htab->alloc_arg, nsize,
-                                                 sizeof (PTR *));
-  else
-    nentries = (PTR *) (*htab->alloc_f) (nsize, sizeof (PTR *));
-  if (nentries == NULL)
-    return 0;
-  htab->entries = nentries;
-  htab->size = nsize;
-
-  htab->n_elements -= htab->n_deleted;
-  htab->n_deleted = 0;
-
-  p = oentries;
-  do
-    {
-      PTR x = *p;
-
-      if (x != EMPTY_ENTRY && x != DELETED_ENTRY)
-       {
-         PTR *q = find_empty_slot_for_expand (htab, (*htab->hash_f) (x));
-
-         *q = x;
-       }
-
-      p++;
-    }
-  while (p < olimit);
-
-  if (htab->free_f != NULL)
-    (*htab->free_f) (oentries);
-  else if (htab->free_with_arg_f != NULL)
-    (*htab->free_with_arg_f) (htab->alloc_arg, oentries);
-  return 1;
-}
-
-/* This function searches for a hash table entry equal to the given
-   element.  It cannot be used to insert or delete an element.  */
-
-PTR
-htab_find_with_hash (htab, element, hash)
-     htab_t htab;
-     const PTR element;
-     hashval_t hash;
-{
-  unsigned int index;
-  hashval_t hash2;
-  size_t size;
-  PTR entry;
-
-  htab->searches++;
-  size = htab->size;
-  index = hash % size;
-
-  entry = htab->entries[index];
-  if (entry == EMPTY_ENTRY
-      || (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element)))
-    return entry;
-
-  hash2 = 1 + hash % (size - 2);
-
-  for (;;)
-    {
-      htab->collisions++;
-      index += hash2;
-      if (index >= size)
-       index -= size;
-
-      entry = htab->entries[index];
-      if (entry == EMPTY_ENTRY
-         || (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element)))
-       return entry;
-    }
-}
-
-/* Like htab_find_slot_with_hash, but compute the hash value from the
-   element.  */
-
-PTR
-htab_find (htab, element)
-     htab_t htab;
-     const PTR element;
-{
-  return htab_find_with_hash (htab, element, (*htab->hash_f) (element));
-}
-
-/* This function searches for a hash table slot containing an entry
-   equal to the given element.  To delete an entry, call this with
-   INSERT = 0, then call htab_clear_slot on the slot returned (possibly
-   after doing some checks).  To insert an entry, call this with
-   INSERT = 1, then write the value you want into the returned slot.
-   When inserting an entry, NULL may be returned if memory allocation
-   fails.  */
-
-PTR *
-htab_find_slot_with_hash (htab, element, hash, insert)
-     htab_t htab;
-     const PTR element;
-     hashval_t hash;
-     enum insert_option insert;
-{
-  PTR *first_deleted_slot;
-  unsigned int index;
-  hashval_t hash2;
-  size_t size;
-  PTR entry;
-
-  if (insert == INSERT && htab->size * 3 <= htab->n_elements * 4
-      && htab_expand (htab) == 0)
-    return NULL;
-
-  size = htab->size;
-  index = hash % size;
-
-  htab->searches++;
-  first_deleted_slot = NULL;
-
-  entry = htab->entries[index];
-  if (entry == EMPTY_ENTRY)
-    goto empty_entry;
-  else if (entry == DELETED_ENTRY)
-    first_deleted_slot = &htab->entries[index];
-  else if ((*htab->eq_f) (entry, element))
-    return &htab->entries[index];
-      
-  hash2 = 1 + hash % (size - 2);
-  for (;;)
-    {
-      htab->collisions++;
-      index += hash2;
-      if (index >= size)
-       index -= size;
-      
-      entry = htab->entries[index];
-      if (entry == EMPTY_ENTRY)
-       goto empty_entry;
-      else if (entry == DELETED_ENTRY)
-       {
-         if (!first_deleted_slot)
-           first_deleted_slot = &htab->entries[index];
-       }
-      else if ((*htab->eq_f) (entry, element))
-       return &htab->entries[index];
-    }
-
- empty_entry:
-  if (insert == NO_INSERT)
-    return NULL;
-
-  if (first_deleted_slot)
-    {
-      htab->n_deleted--;
-      *first_deleted_slot = EMPTY_ENTRY;
-      return first_deleted_slot;
-    }
-
-  htab->n_elements++;
-  return &htab->entries[index];
-}
-
-/* Like htab_find_slot_with_hash, but compute the hash value from the
-   element.  */
-
-PTR *
-htab_find_slot (htab, element, insert)
-     htab_t htab;
-     const PTR element;
-     enum insert_option insert;
-{
-  return htab_find_slot_with_hash (htab, element, (*htab->hash_f) (element),
-                                  insert);
-}
-
-/* This function deletes an element with the given value from hash
-   table.  If there is no matching element in the hash table, this
-   function does nothing.  */
-
-void
-htab_remove_elt (htab, element)
-     htab_t htab;
-     PTR element;
-{
-  PTR *slot;
-
-  slot = htab_find_slot (htab, element, NO_INSERT);
-  if (*slot == EMPTY_ENTRY)
-    return;
-
-  if (htab->del_f)
-    (*htab->del_f) (*slot);
-
-  *slot = DELETED_ENTRY;
-  htab->n_deleted++;
-}
-
-/* This function clears a specified slot in a hash table.  It is
-   useful when you've already done the lookup and don't want to do it
-   again.  */
-
-void
-htab_clear_slot (htab, slot)
-     htab_t htab;
-     PTR *slot;
-{
-  if (slot < htab->entries || slot >= htab->entries + htab->size
-      || *slot == EMPTY_ENTRY || *slot == DELETED_ENTRY)
-    abort ();
-
-  if (htab->del_f)
-    (*htab->del_f) (*slot);
-
-  *slot = DELETED_ENTRY;
-  htab->n_deleted++;
-}
-
-/* This function scans over the entire hash table calling
-   CALLBACK for each live entry.  If CALLBACK returns false,
-   the iteration stops.  INFO is passed as CALLBACK's second
-   argument.  */
-
-void
-htab_traverse_noresize (htab, callback, info)
-     htab_t htab;
-     htab_trav callback;
-     PTR info;
-{
-  PTR *slot;
-  PTR *limit;
-
-  slot = htab->entries;
-  limit = slot + htab->size;
-
-  do
-    {
-      PTR x = *slot;
-
-      if (x != EMPTY_ENTRY && x != DELETED_ENTRY)
-       if (!(*callback) (slot, info))
-         break;
-    }
-  while (++slot < limit);
-}
-
-/* Like htab_traverse_noresize, but does resize the table when it is
-   too empty to improve effectivity of subsequent calls.  */
-
-void
-htab_traverse (htab, callback, info)
-     htab_t htab;
-     htab_trav callback;
-     PTR info;
-{
-  if ((htab->n_elements - htab->n_deleted) * 8 < htab->size)
-    htab_expand (htab);
-
-  htab_traverse_noresize (htab, callback, info);
-}
-
-/* Return the current size of given hash table. */
-
-size_t
-htab_size (htab)
-     htab_t htab;
-{
-  return htab->size;
-}
-
-/* Return the current number of elements in given hash table. */
-
-size_t
-htab_elements (htab)
-     htab_t htab;
-{
-  return htab->n_elements - htab->n_deleted;
-}
-
-/* Return the fraction of fixed collisions during all work with given
-   hash table. */
-
-double
-htab_collisions (htab)
-     htab_t htab;
-{
-  if (htab->searches == 0)
-    return 0.0;
-
-  return (double) htab->collisions / (double) htab->searches;
-}
-
-/* Hash P as a null-terminated string.
-
-   Copied from gcc/hashtable.c.  Zack had the following to say with respect
-   to applicability, though note that unlike hashtable.c, this hash table
-   implementation re-hashes rather than chain buckets.
-
-   http://gcc.gnu.org/ml/gcc-patches/2001-08/msg01021.html
-   From: Zack Weinberg <zackw@panix.com>
-   Date: Fri, 17 Aug 2001 02:15:56 -0400
-
-   I got it by extracting all the identifiers from all the source code
-   I had lying around in mid-1999, and testing many recurrences of
-   the form "H_n = H_{n-1} * K + c_n * L + M" where K, L, M were either
-   prime numbers or the appropriate identity.  This was the best one.
-   I don't remember exactly what constituted "best", except I was
-   looking at bucket-length distributions mostly.
-   
-   So it should be very good at hashing identifiers, but might not be
-   as good at arbitrary strings.
-   
-   I'll add that it thoroughly trounces the hash functions recommended
-   for this use at http://burtleburtle.net/bob/hash/index.html, both
-   on speed and bucket distribution.  I haven't tried it against the
-   function they just started using for Perl's hashes.  */
-
-hashval_t
-htab_hash_string (p)
-     const PTR p;
-{
-  const unsigned char *str = (const unsigned char *) p;
-  hashval_t r = 0;
-  unsigned char c;
-
-  while ((c = *str++) != 0)
-    r = r * 67 + c - 113;
-
-  return r;
-}
-
-/* DERIVED FROM:
---------------------------------------------------------------------
-lookup2.c, by Bob Jenkins, December 1996, Public Domain.
-hash(), hash2(), hash3, and mix() are externally useful functions.
-Routines to test the hash are included if SELF_TEST is defined.
-You can use this free for any purpose.  It has no warranty.
---------------------------------------------------------------------
-*/
-
-/*
---------------------------------------------------------------------
-mix -- mix 3 32-bit values reversibly.
-For every delta with one or two bit set, and the deltas of all three
-  high bits or all three low bits, whether the original value of a,b,c
-  is almost all zero or is uniformly distributed,
-* If mix() is run forward or backward, at least 32 bits in a,b,c
-  have at least 1/4 probability of changing.
-* If mix() is run forward, every bit of c will change between 1/3 and
-  2/3 of the time.  (Well, 22/100 and 78/100 for some 2-bit deltas.)
-mix() was built out of 36 single-cycle latency instructions in a 
-  structure that could supported 2x parallelism, like so:
-      a -= b; 
-      a -= c; x = (c>>13);
-      b -= c; a ^= x;
-      b -= a; x = (a<<8);
-      c -= a; b ^= x;
-      c -= b; x = (b>>13);
-      ...
-  Unfortunately, superscalar Pentiums and Sparcs can't take advantage 
-  of that parallelism.  They've also turned some of those single-cycle
-  latency instructions into multi-cycle latency instructions.  Still,
-  this is the fastest good hash I could find.  There were about 2^^68
-  to choose from.  I only looked at a billion or so.
---------------------------------------------------------------------
-*/
-/* same, but slower, works on systems that might have 8 byte hashval_t's */
-#define mix(a,b,c) \
-{ \
-  a -= b; a -= c; a ^= (c>>13); \
-  b -= c; b -= a; b ^= (a<< 8); \
-  c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \
-  a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \
-  b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \
-  c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \
-  a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \
-  b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \
-  c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
-}
-
-/*
---------------------------------------------------------------------
-hash() -- hash a variable-length key into a 32-bit value
-  k     : the key (the unaligned variable-length array of bytes)
-  len   : the length of the key, counting by bytes
-  level : can be any 4-byte value
-Returns a 32-bit value.  Every bit of the key affects every bit of
-the return value.  Every 1-bit and 2-bit delta achieves avalanche.
-About 36+6len instructions.
-
-The best hash table sizes are powers of 2.  There is no need to do
-mod a prime (mod is sooo slow!).  If you need less than 32 bits,
-use a bitmask.  For example, if you need only 10 bits, do
-  h = (h & hashmask(10));
-In which case, the hash table should have hashsize(10) elements.
-
-If you are hashing n strings (ub1 **)k, do it like this:
-  for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
-
-By Bob Jenkins, 1996.  bob_jenkins@burtleburtle.net.  You may use this
-code any way you wish, private, educational, or commercial.  It's free.
-
-See http://burtleburtle.net/bob/hash/evahash.html
-Use for hash table lookup, or anything where one collision in 2^32 is
-acceptable.  Do NOT use for cryptographic purposes.
---------------------------------------------------------------------
-*/
-
-hashval_t iterative_hash (k_in, length, initval)
-     const PTR k_in;               /* the key */
-     register size_t  length;      /* the length of the key */
-     register hashval_t  initval;  /* the previous hash, or an arbitrary value */
-{
-  register const unsigned char *k = (const unsigned char *)k_in;
-  register hashval_t a,b,c,len;
-
-  /* Set up the internal state */
-  len = length;
-  a = b = 0x9e3779b9;  /* the golden ratio; an arbitrary value */
-  c = initval;           /* the previous hash value */
-
-  /*---------------------------------------- handle most of the key */
-#ifndef WORDS_BIGENDIAN
-  /* On a little-endian machine, if the data is 4-byte aligned we can hash
-     by word for better speed.  This gives nondeterministic results on
-     big-endian machines.  */
-  if (sizeof (hashval_t) == 4 && (((size_t)k)&3) == 0)
-    while (len >= 12)    /* aligned */
-      {
-       a += *(hashval_t *)(k+0);
-       b += *(hashval_t *)(k+4);
-       c += *(hashval_t *)(k+8);
-       mix(a,b,c);
-       k += 12; len -= 12;
-      }
-  else /* unaligned */
-#endif
-    while (len >= 12)
-      {
-       a += (k[0] +((hashval_t)k[1]<<8) +((hashval_t)k[2]<<16) +((hashval_t)k[3]<<24));
-       b += (k[4] +((hashval_t)k[5]<<8) +((hashval_t)k[6]<<16) +((hashval_t)k[7]<<24));
-       c += (k[8] +((hashval_t)k[9]<<8) +((hashval_t)k[10]<<16)+((hashval_t)k[11]<<24));
-       mix(a,b,c);
-       k += 12; len -= 12;
-      }
-
-  /*------------------------------------- handle the last 11 bytes */
-  c += length;
-  switch(len)              /* all the case statements fall through */
-    {
-    case 11: c+=((hashval_t)k[10]<<24);
-    case 10: c+=((hashval_t)k[9]<<16);
-    case 9 : c+=((hashval_t)k[8]<<8);
-      /* the first byte of c is reserved for the length */
-    case 8 : b+=((hashval_t)k[7]<<24);
-    case 7 : b+=((hashval_t)k[6]<<16);
-    case 6 : b+=((hashval_t)k[5]<<8);
-    case 5 : b+=k[4];
-    case 4 : a+=((hashval_t)k[3]<<24);
-    case 3 : a+=((hashval_t)k[2]<<16);
-    case 2 : a+=((hashval_t)k[1]<<8);
-    case 1 : a+=k[0];
-      /* case 0: nothing left to add */
-    }
-  mix(a,b,c);
-  /*-------------------------------------------- report the result */
-  return c;
-}
diff --git a/support/cpp2/hashtab.h b/support/cpp2/hashtab.h
deleted file mode 100644 (file)
index f7bd4ae..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/* An expandable hash tables datatype.  
-   Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
-   Contributed by Vladimir Makarov (vmakarov@cygnus.com).
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-/* This package implements basic hash table functionality.  It is possible
-   to search for an entry, create an entry and destroy an entry.
-
-   Elements in the table are generic pointers.
-
-   The size of the table is not fixed; if the occupancy of the table
-   grows too high the hash table will be expanded.
-
-   The abstract data implementation is based on generalized Algorithm D
-   from Knuth's book "The art of computer programming".  Hash table is
-   expanded by creation of new hash table and transferring elements from
-   the old table to the new table.  */
-
-#ifndef __HASHTAB_H__
-#define __HASHTAB_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-#include "ansidecl.h"
-
-#ifndef GTY
-#define GTY(X)
-#endif
-
-/* The type for a hash code.  */
-typedef unsigned int hashval_t;
-
-/* Callback function pointer types.  */
-
-/* Calculate hash of a table entry.  */
-typedef hashval_t (*htab_hash) PARAMS ((const void *));
-
-/* Compare a table entry with a possible entry.  The entry already in
-   the table always comes first, so the second element can be of a
-   different type (but in this case htab_find and htab_find_slot
-   cannot be used; instead the variants that accept a hash value
-   must be used).  */
-typedef int (*htab_eq) PARAMS ((const void *, const void *));
-
-/* Cleanup function called whenever a live element is removed from
-   the hash table.  */
-typedef void (*htab_del) PARAMS ((void *));
-  
-/* Function called by htab_traverse for each live element.  The first
-   arg is the slot of the element (which can be passed to htab_clear_slot
-   if desired), the second arg is the auxiliary pointer handed to
-   htab_traverse.  Return 1 to continue scan, 0 to stop.  */
-typedef int (*htab_trav) PARAMS ((void **, void *));
-
-/* Memory-allocation function, with the same functionality as calloc().
-   Iff it returns NULL, the hash table implementation will pass an error
-   code back to the user, so if your code doesn't handle errors,
-   best if you use xcalloc instead.  */
-typedef PTR (*htab_alloc) PARAMS ((size_t, size_t));
-
-/* We also need a free() routine.  */
-typedef void (*htab_free) PARAMS ((PTR));
-
-/* Memory allocation and deallocation; variants which take an extra
-   argument.  */
-typedef PTR (*htab_alloc_with_arg) PARAMS ((void *, size_t, size_t));
-typedef void (*htab_free_with_arg) PARAMS ((void *, void *));
-
-/* Hash tables are of the following type.  The structure
-   (implementation) of this type is not needed for using the hash
-   tables.  All work with hash table should be executed only through
-   functions mentioned below.  The size of this structure is subject to
-   change.  */
-
-struct htab GTY(())
-{
-  /* Pointer to hash function.  */
-  htab_hash hash_f;
-
-  /* Pointer to comparison function.  */
-  htab_eq eq_f;
-
-  /* Pointer to cleanup function.  */
-  htab_del del_f;
-
-  /* Table itself.  */
-  PTR * GTY ((use_param (""), length ("%h.size"))) entries;
-
-  /* Current size (in entries) of the hash table */
-  size_t size;
-
-  /* Current number of elements including also deleted elements */
-  size_t n_elements;
-
-  /* Current number of deleted elements in the table */
-  size_t n_deleted;
-
-  /* The following member is used for debugging. Its value is number
-     of all calls of `htab_find_slot' for the hash table. */
-  unsigned int searches;
-
-  /* The following member is used for debugging.  Its value is number
-     of collisions fixed for time of work with the hash table. */
-  unsigned int collisions;
-
-  /* Pointers to allocate/free functions.  */
-  htab_alloc alloc_f;
-  htab_free free_f;
-
-  /* Alternate allocate/free functions, which take an extra argument.  */
-  PTR GTY((skip (""))) alloc_arg;
-  htab_alloc_with_arg alloc_with_arg_f;
-  htab_free_with_arg free_with_arg_f;
-};
-
-typedef struct htab *htab_t;
-
-/* An enum saying whether we insert into the hash table or not.  */
-enum insert_option {NO_INSERT, INSERT};
-
-/* The prototypes of the package functions. */
-
-extern htab_t  htab_create_alloc       PARAMS ((size_t, htab_hash,
-                                                htab_eq, htab_del,
-                                                htab_alloc, htab_free));
-
-extern htab_t  htab_create_alloc_ex    PARAMS ((size_t, htab_hash,
-                                                   htab_eq, htab_del,
-                                                   PTR, htab_alloc_with_arg,
-                                                   htab_free_with_arg));
-
-/* Backward-compatibility functions.  */
-extern htab_t htab_create PARAMS ((size_t, htab_hash, htab_eq, htab_del));
-extern htab_t htab_try_create PARAMS ((size_t, htab_hash, htab_eq, htab_del));
-
-extern void    htab_set_functions_ex   PARAMS ((htab_t, htab_hash,
-                                                htab_eq, htab_del,
-                                                PTR, htab_alloc_with_arg,
-                                                htab_free_with_arg));
-
-extern void    htab_delete     PARAMS ((htab_t));
-extern void    htab_empty      PARAMS ((htab_t));
-
-extern PTR     htab_find       PARAMS ((htab_t, const void *));
-extern PTR     *htab_find_slot PARAMS ((htab_t, const void *,
-                                        enum insert_option));
-extern PTR     htab_find_with_hash       PARAMS ((htab_t, const void *,
-                                                  hashval_t));
-extern PTR     *htab_find_slot_with_hash  PARAMS ((htab_t, const void *,
-                                                  hashval_t,
-                                                  enum insert_option));
-extern void    htab_clear_slot PARAMS ((htab_t, void **));
-extern void    htab_remove_elt PARAMS ((htab_t, void *));
-
-extern void    htab_traverse   PARAMS ((htab_t, htab_trav, void *));
-extern void    htab_traverse_noresize  PARAMS ((htab_t, htab_trav, void *));
-
-extern size_t  htab_size       PARAMS ((htab_t));
-extern size_t  htab_elements   PARAMS ((htab_t));
-extern double  htab_collisions PARAMS ((htab_t));
-
-/* A hash function for pointers.  */
-extern htab_hash htab_hash_pointer;
-
-/* An equality function for pointers.  */
-extern htab_eq htab_eq_pointer;
-
-/* A hash function for null-terminated strings.  */
-extern hashval_t htab_hash_string PARAMS ((const PTR));
-
-/* An iterative hash function for arbitrary data.  */
-extern hashval_t iterative_hash PARAMS ((const PTR, size_t, hashval_t));
-/* Shorthand for hashing something with an intrinsic size.  */
-#define iterative_hash_object(OB,INIT) iterative_hash (&OB, sizeof (OB), INIT)
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __HASHTAB_H */
diff --git a/support/cpp2/hashtable.c b/support/cpp2/hashtable.c
deleted file mode 100644 (file)
index 58f19d0..0000000
+++ /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/support/cpp2/hashtable.h b/support/cpp2/hashtable.h
deleted file mode 100644 (file)
index 068341c..0000000
+++ /dev/null
@@ -1,85 +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
-
-#if defined(__APPLE__) && defined(__MACH__)
-#include "libiberty/obstack.h"
-#else
-#include "obstack.h"
-#endif
-#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 */
index 4fed004cbf6cdcf9c6001b9b26411d5d8a040fdf..9b28a3ada0783d80a44854bbc1c5a6357299493c 100644 (file)
@@ -1,5 +1,5 @@
 /* HOST_WIDE_INT definitions for the GNU compiler.
-   Copyright (C) 1998, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1998, 2002, 2004 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
 #define HOST_BITS_PER_INT   (CHAR_BIT * SIZEOF_INT)
 #define HOST_BITS_PER_LONG  (CHAR_BIT * SIZEOF_LONG)
 
+/* The string that should be inserted into a printf style format to
+   indicate a "long long" operand.  */
+#ifndef HOST_LONG_LONG_FORMAT 
+#define HOST_LONG_LONG_FORMAT "ll"
+#endif
+
 /* If HAVE_LONG_LONG and SIZEOF_LONG_LONG aren't defined, but
    GCC_VERSION >= 3000, assume this is the second or later stage of a
    bootstrap, we do have long long, and it's 64 bits.  (This is
@@ -74,10 +80,11 @@ extern char sizeof_long_long_must_be_8[sizeof(long long) == 8 ? 1 : -1];
 #  define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%lx%08lx"
 # endif
 #else
-# define HOST_WIDE_INT_PRINT "ll"
+# define HOST_WIDE_INT_PRINT HOST_LONG_LONG_FORMAT
 # define HOST_WIDE_INT_PRINT_C "LL"
   /* We can assume that 'long long' is at least 64 bits.  */
-# define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%llx%016llx"
+# define HOST_WIDE_INT_PRINT_DOUBLE_HEX \
+    "0x%" HOST_LONG_LONG_FORMAT "x%016" HOST_LONG_LONG_FORMAT "x"
 #endif /* HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG */
 
 #define HOST_WIDE_INT_PRINT_DEC "%" HOST_WIDE_INT_PRINT "d"
@@ -109,11 +116,35 @@ extern char sizeof_long_long_must_be_8[sizeof(long long) == 8 ? 1 : -1];
     #error "This line should be impossible to reach"
 #  endif
 # endif
-# define HOST_WIDEST_INT_PRINT_DEC           "%lld"
-# define HOST_WIDEST_INT_PRINT_DEC_C         "%lldLL"
-# define HOST_WIDEST_INT_PRINT_UNSIGNED              "%llu"
-# define HOST_WIDEST_INT_PRINT_HEX           "0x%llx"
-# define HOST_WIDEST_INT_PRINT_DOUBLE_HEX     "0x%llx%016llx"
+# define HOST_WIDEST_INT_PRINT_DEC           "%" HOST_LONG_LONG_FORMAT "d"
+# define HOST_WIDEST_INT_PRINT_DEC_C         "%" HOST_LONG_LONG_FORMAT "dLL"
+# define HOST_WIDEST_INT_PRINT_UNSIGNED              "%" HOST_LONG_LONG_FORMAT "u"
+# define HOST_WIDEST_INT_PRINT_HEX           "0x%" HOST_LONG_LONG_FORMAT "x"
+# define HOST_WIDEST_INT_PRINT_DOUBLE_HEX     \
+    "0x%" HOST_LONG_LONG_FORMAT "x%016" HOST_LONG_LONG_FORMAT "x"
+#endif
+
+/* Define HOST_WIDEST_FAST_INT to the widest integer type supported
+   efficiently in hardware.  (That is, the widest integer type that fits
+   in a hardware register.)  Normally this is "long" but on some hosts it
+   should be "long long" or "__int64".  This is no convenient way to
+   autodect this, so such systems must set a flag in config.host; see there
+   for details.  */
+
+#ifdef USE_LONG_LONG_FOR_WIDEST_FAST_INT
+#  ifdef HAVE_LONG_LONG
+#    define HOST_WIDEST_FAST_INT long long
+#    define HOST_BITS_PER_WIDEST_FAST_INT HOST_BITS_PER_LONGLONG
+#  elif defined (HAVE___INT64)
+#    define HOST_WIDEST_FAST_INT __int64
+#    define HOST_BITS_PER_WIDEST_FAST_INT HOST_BITS_PER___INT64
+#  else
+#    error "Your host said it wantted to use long long or __int64 but neither"
+#    error "exist"
+#  endif
+#else
+#  define HOST_WIDEST_FAST_INT long
+#  define HOST_BITS_PER_WIDEST_FAST_INT HOST_BITS_PER_LONG
 #endif
 
 #endif /* ! GCC_HWINT_H */
index ff014f6d664f58ed8002d761ed65319aef9a79bd..0ca3ccfd7338d862375fb46a1a11852a1b0315a8 100644 (file)
@@ -1,6 +1,6 @@
 /* Declarations for variables relating to reading the source file.
    Used by parsers, lexical analyzers, and error message routines.
-   Copyright (C) 1993, 1997, 1998, 2000, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1993, 1997, 1998, 2000, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -16,15 +16,40 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #ifndef GCC_INPUT_H
 #define GCC_INPUT_H
 
-/* The data structure used to record a location in a translation unit.  */
-/* Long-term, we want to get rid of this and typedef fileline location_t.  */
-struct location_s GTY (())
+#include "line-map.h"
+extern struct line_maps line_table;
+
+/* The location for declarations in "<built-in>" */
+#define BUILTINS_LOCATION ((source_location) 2)
+
+#ifdef USE_MAPPED_LOCATION
+
+typedef struct
+{
+  /* The name of the source file involved.  */
+  const char *file;
+
+  /* The line-location in the source file.  */
+  int line;
+
+  int column;
+} expanded_location;
+
+extern expanded_location expand_location (source_location);
+
+#define UNKNOWN_LOCATION ((source_location) 0)
+typedef source_location location_t; /* deprecated typedef */
+typedef source_location source_locus; /* to be removed */
+
+#else /* ! USE_MAPPED_LOCATION */
+
+struct location_s GTY(())
 {
   /* The name of the source file involved.  */
   const char *file;
@@ -32,7 +57,16 @@ struct location_s GTY (())
   /* The line-location in the source file.  */
   int line;
 };
+
+typedef struct location_s expanded_location;
 typedef struct location_s location_t;
+typedef location_t *source_locus;
+
+#define expand_location(FILELINE) (FILELINE)
+extern location_t unknown_location;
+#define UNKNOWN_LOCATION unknown_location
+
+#endif /* ! USE_MAPPED_LOCATION */
 
 struct file_stack
 {
@@ -44,20 +78,24 @@ struct file_stack
 extern const char *main_input_filename;
 
 extern location_t input_location;
-#define input_line (input_location.line)
-#define input_filename (input_location.file)
+#ifdef USE_MAPPED_LOCATION
+extern void push_srcloc (location_t);
+#else /* ! USE_MAPPED_LOCATION */
+extern void push_srcloc (const char *name, int line);
+#endif /* ! USE_MAPPED_LOCATION */
+extern void pop_srcloc (void);
+
+#define LOCATION_FILE(LOC) ((expand_location (LOC)).file)
+#define LOCATION_LINE(LOC) ((expand_location (LOC)).line)
+
+#define input_line LOCATION_LINE(input_location)
+#define input_filename LOCATION_FILE(input_location)
 
 /* Stack of currently pending input files.
    The line member is not accurate for the innermost file on the stack.  */
 extern struct file_stack *input_file_stack;
 
-/* Stack of EXPR_WITH_FILE_LOCATION nested expressions.  */
-extern struct file_stack *expr_wfl_stack;
-
 /* Incremented on each change to input_file_stack.  */
 extern int input_file_stack_tick;
 
-extern void push_srcloc (const char *name, int line);
-extern void pop_srcloc (void);
-
 #endif
index 80a945b45f8e0cea175757d3358c82dcb8e10a9a..a118c0a98d1bd2714831358b7c0e06b470a31e32 100644 (file)
@@ -1,5 +1,5 @@
 /* intl.h - internationalization
-   Copyright 1998, 2001, 2003 Free Software Foundation, Inc.
+   Copyright 1998, 2001, 2003, 2004 Free Software Foundation, Inc.
 
    GCC is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -13,8 +13,8 @@
 
    You should have received a copy of the GNU General Public License
    along with GCC; see the file COPYING.  If not, write to the Free
-   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 
 #ifndef GCC_INTL_H
 #define GCC_INTL_H
@@ -51,4 +51,11 @@ extern size_t gcc_gettext_width (const char *);
 # define N_(msgid) msgid
 #endif
 
+#ifndef G_
+# define G_(gmsgid) gmsgid
+#endif
+
+extern const char *open_quote;
+extern const char *close_quote;
+
 #endif /* intl.h */
diff --git a/support/cpp2/libcpp/charset.c b/support/cpp2/libcpp/charset.c
new file mode 100644 (file)
index 0000000..78c8981
--- /dev/null
@@ -0,0 +1,1672 @@
+/* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "cpplib.h"
+#include "internal.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"
+#define LAST_POSSIBLY_BASIC_SOURCE_CHAR 0x7e
+#elif HOST_CHARSET == HOST_CHARSET_EBCDIC
+#define SOURCE_CHARSET "UTF-EBCDIC"
+#define LAST_POSSIBLY_BASIC_SOURCE_CHAR 0xFF
+#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 = XRESIZEVEC (uchar, 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 = XRESIZEVEC (uchar, 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 = XRESIZEVEC (uchar, 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 = (char *) 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);
+}
+
+/* Destroy iconv(3) descriptors set up by cpp_init_iconv, if necessary.  */
+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 for use by a full compiler.  C is a character taken
+   from the *basic* source character set, encoded in the host's
+   execution encoding.  Convert it to (the target's) execution
+   encoding, and return that value.
+
+   Issues an internal error if C's representation in the narrow
+   execution character set fails to be a single-byte value (C99
+   5.2.1p3: "The representation of each member of the source and
+   execution character sets shall fit in a byte.")  May also issue an
+   internal error if C fails to be a member of the basic source
+   character set (testing this exactly is too hard, especially when
+   the host character set is EBCDIC).  */
+cppchar_t
+cpp_host_to_exec_charset (cpp_reader *pfile, cppchar_t c)
+{
+  uchar sbuf[1];
+  struct _cpp_strbuf tbuf;
+
+  /* This test is merely an approximation, but it suffices to catch
+     the most important thing, which is that we don't get handed a
+     character outside the unibyte range of the host character set.  */
+  if (c > LAST_POSSIBLY_BASIC_SOURCE_CHAR)
+    {
+      cpp_error (pfile, CPP_DL_ICE,
+                "character 0x%lx is not in the basic source character set\n",
+                (unsigned long)c);
+      return 0;
+    }
+
+  /* Being a character in the unibyte range of the host character set,
+     we can safely splat it into a one-byte buffer and trust that that
+     is a well-formed string.  */
+  sbuf[0] = c;
+
+  /* This should never need to reallocate, but just in case... */
+  tbuf.asize = 1;
+  tbuf.text = XNEWVEC (uchar, tbuf.asize);
+  tbuf.len = 0;
+
+  if (!APPLY_CONVERSION (pfile->narrow_cset_desc, sbuf, 1, &tbuf))
+    {
+      cpp_errno (pfile, CPP_DL_ICE, "converting to execution character set");
+      return 0;
+    }
+  if (tbuf.len != 1)
+    {
+      cpp_error (pfile, CPP_DL_ICE,
+                "character 0x%lx is not unibyte in execution character set",
+                (unsigned long)c);
+      return 0;
+    }
+  c = tbuf.text[0];
+  free(tbuf.text);
+  return c;
+}
+
+\f
+
+/* 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;
+}
+
+/* A large table of unicode character information.  */
+enum {
+  /* Valid in a C99 identifier?  */
+  C99 = 1,
+  /* Valid in a C99 identifier, but not as the first character?  */
+  DIG = 2,
+  /* Valid in a C++ identifier?  */
+  CXX = 4,
+  /* NFC representation is not valid in an identifier?  */
+  CID = 8,
+  /* Might be valid NFC form?  */
+  NFC = 16,
+  /* Might be valid NFKC form?  */
+  NKC = 32,
+  /* Certain preceding characters might make it not valid NFC/NKFC form?  */
+  CTX = 64
+};
+
+static const struct {
+  /* Bitmap of flags above.  */
+  unsigned char flags;
+  /* Combining class of the character.  */
+  unsigned char combine;
+  /* Last character in the range described by this entry.  */
+  unsigned short end;
+} ucnranges[] = {
+#include "ucnid.h"
+};
+
+/* 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.  Also update NST for C if returning nonzero.  The
+   algorithm is a simple binary search on the table defined in
+   ucnid.h.  */
+
+static int
+ucn_valid_in_identifier (cpp_reader *pfile, cppchar_t c,
+                        struct normalize_state *nst)
+{
+  int mn, mx, md;
+
+  if (c > 0xFFFF)
+    return 0;
+
+  mn = 0;
+  mx = ARRAY_SIZE (ucnranges) - 1;
+  while (mx != mn)
+    {
+      md = (mn + mx) / 2;
+      if (c <= ucnranges[md].end)
+       mx = md;
+      else
+       mn = md + 1;
+    }
+
+  /* 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 (! (ucnranges[mn].flags & (C99 | CXX)))
+      return 0;
+
+  if (CPP_PEDANTIC (pfile)
+      && ((CPP_OPTION (pfile, c99) && !(ucnranges[mn].flags & C99))
+         || (CPP_OPTION (pfile, cplusplus)
+             && !(ucnranges[mn].flags & CXX))))
+    return 0;
+
+  /* Update NST.  */
+  if (ucnranges[mn].combine != 0 && ucnranges[mn].combine < nst->prev_class)
+    nst->level = normalized_none;
+  else if (ucnranges[mn].flags & CTX)
+    {
+      bool safe;
+      cppchar_t p = nst->previous;
+
+      /* Easy cases from Bengali, Oriya, Tamil, Jannada, and Malayalam.  */
+      if (c == 0x09BE)
+       safe = p != 0x09C7;  /* Use 09CB instead of 09C7 09BE.  */
+      else if (c == 0x0B3E)
+       safe = p != 0x0B47;  /* Use 0B4B instead of 0B47 0B3E.  */
+      else if (c == 0x0BBE)
+       safe = p != 0x0BC6 && p != 0x0BC7;  /* Use 0BCA/0BCB instead.  */
+      else if (c == 0x0CC2)
+       safe = p != 0x0CC6;  /* Use 0CCA instead of 0CC6 0CC2.  */
+      else if (c == 0x0D3E)
+       safe = p != 0x0D46 && p != 0x0D47;  /* Use 0D4A/0D4B instead.  */
+      /* For Hangul, characters in the range AC00-D7A3 are NFC/NFKC,
+        and are combined algorithmically from a sequence of the form
+        1100-1112 1161-1175 11A8-11C2
+        (if the third is not present, it is treated as 11A7, which is not
+        really a valid character).
+        Unfortunately, C99 allows (only) the NFC form, but C++ allows
+        only the combining characters.  */
+      else if (c >= 0x1161 && c <= 0x1175)
+       safe = p < 0x1100 || p > 0x1112;
+      else if (c >= 0x11A8 && c <= 0x11C2)
+       safe = (p < 0xAC00 || p > 0xD7A3 || (p - 0xAC00) % 28 != 0);
+      else
+       {
+         /* Uh-oh, someone updated ucnid.h without updating this code.  */
+         cpp_error (pfile, CPP_DL_ICE, "Character %x might not be NFKC", c);
+         safe = true;
+       }
+      if (!safe && c < 0x1161)
+       nst->level = normalized_none;
+      else if (!safe)
+       nst->level = MAX (nst->level, normalized_identifier_C);
+    }
+  else if (ucnranges[mn].flags & NKC)
+    ;
+  else if (ucnranges[mn].flags & NFC)
+    nst->level = MAX (nst->level, normalized_C);
+  else if (ucnranges[mn].flags & CID)
+    nst->level = MAX (nst->level, normalized_identifier_C);
+  else
+    nst->level = normalized_none;
+  nst->previous = c;
+  nst->prev_class = ucnranges[mn].combine;
+
+  /* In C99, UCN digits may not begin identifiers.  */
+  if (CPP_OPTION (pfile, c99) && (ucnranges[mn].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 the
+   UCN has not been consumed.
+
+   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,
+               struct normalize_state *nst)
+{
+  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
+    {
+      cpp_error (pfile, CPP_DL_ICE, "In _cpp_valid_ucn but not a UCN");
+      length = 4;
+    }
+
+  result = 0;
+  do
+    {
+      c = *str;
+      if (!ISXDIGIT (c))
+       break;
+      str++;
+      result = (result << 4) + hex_value (c);
+    }
+  while (--length && str < limit);
+
+  /* Partial UCNs are not valid in strings, but decompose into
+     multiple tokens in identifiers, so we can't give a helpful
+     error message in that case.  */
+  if (length && identifier_pos)
+    return 0;
+  
+  *pstr = str;
+  if (length)
+    {
+      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 && result == 0x24 
+          && CPP_OPTION (pfile, dollars_in_ident))
+    {
+      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");
+       }
+      NORMALIZE_STATE_UPDATE_IDNUM (nst);
+    }
+  else if (identifier_pos)
+    {
+      int validity = ucn_valid_in_identifier (pfile, result, nst);
+
+      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;
+  struct normalize_state nst = INITIAL_NORMALIZE_STATE;
+
+  from++;  /* Skip u/U.  */
+  ucn = _cpp_valid_ucn (pfile, &from, limit, 0, &nst);
+
+  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;
+}
+
+/* Subroutine of convert_hex and convert_oct.  N is the representation
+   in the execution character set of a numeric escape; write it into the
+   string buffer TBUF and update the end-of-string pointer therein.  WIDE
+   is true if it's a wide string that's being assembled in TBUF.  This
+   function issues no diagnostics and never fails.  */
+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 = XRESIZEVEC (uchar, 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
+    {
+      /* Note: this code does not handle the case where the target
+        and host have a different number of bits in a byte.  */
+      if (tbuf->len + 1 > tbuf->asize)
+       {
+         tbuf->asize += OUTBUF_BLOCK_SIZE;
+         tbuf->text = XRESIZEVEC (uchar, 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
+       {
+         /* diagnostic.c does not support "%03o".  When it does, this
+            code can use %03o directly in the diagnostic again.  */
+         char buf[32];
+         sprintf(buf, "%03o", (int) c);
+         cpp_error (pfile, CPP_DL_PEDWARN,
+                    "unknown escape sequence: '\\%s'", buf);
+       }
+    }
+
+  /* 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;
+}
+\f
+/* 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 = XNEWVEC (uchar, 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 = XRESIZEVEC (uchar, 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;
+}
+
+\f
+/* 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;
+}
+\f
+/* Convert an identifier denoted by ID and LEN, which might contain
+   UCN escapes, to the source character set, either UTF-8 or
+   UTF-EBCDIC.  Assumes that the identifier is actually a valid identifier.  */
+cpp_hashnode *
+_cpp_interpret_identifier (cpp_reader *pfile, const uchar *id, size_t len)
+{
+  /* It turns out that a UCN escape always turns into fewer characters
+     than the escape itself, so we can allocate a temporary in advance.  */
+  uchar * buf = (uchar *) alloca (len + 1);
+  uchar * bufp = buf;
+  size_t idp;
+  
+  for (idp = 0; idp < len; idp++)
+    if (id[idp] != '\\')
+      *bufp++ = id[idp];
+    else
+      {
+       unsigned length = id[idp+1] == 'u' ? 4 : 8;
+       cppchar_t value = 0;
+       size_t bufleft = len - (bufp - buf);
+       int rval;
+
+       idp += 2;
+       while (length && idp < len && ISXDIGIT (id[idp]))
+         {
+           value = (value << 4) + hex_value (id[idp]);
+           idp++;
+           length--;
+         }
+       idp--;
+
+       /* Special case for EBCDIC: if the identifier contains
+          a '$' specified using a UCN, translate it to EBCDIC.  */
+       if (value == 0x24)
+         {
+           *bufp++ = '$';
+           continue;
+         }
+
+       rval = one_cppchar_to_utf8 (value, &bufp, &bufleft);
+       if (rval)
+         {
+           errno = rval;
+           cpp_errno (pfile, CPP_DL_ERROR,
+                      "converting UCN to source character set");
+           break;
+         }
+      }
+
+  return CPP_HASHNODE (ht_lookup (pfile->hash_table, 
+                                 buf, bufp - buf, HT_ALLOC));
+}
+\f
+/* Convert an input buffer (containing the complete contents of one
+   source file) from INPUT_CHARSET to the source character set.  INPUT
+   points to the input buffer, SIZE is its allocated size, and LEN is
+   the length of the meaningful data within the buffer.  The
+   translated buffer is returned, and *ST_SIZE is set to the length of
+   the meaningful data within the translated buffer.
+
+   INPUT is expected to have been allocated with xmalloc.  This function
+   will either return INPUT, or free it and return a pointer to another
+   xmalloc-allocated block of memory.  */
+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 = XNEWVEC (uchar, 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 = XRESIZEVEC (uchar, to.text, to.len + 1);
+
+  /* If the file is using old-school Mac line endings (\r only),
+     terminate with another \r, not an \n, so that we do not mistake
+     the \r\n sequence for a single DOS line ending and erroneously
+     issue the "No newline at end of file" diagnostic.  */
+  if (to.text[to.len - 1] == '\r')
+    to.text[to.len] = '\r';
+  else
+    to.text[to.len] = '\n';
+
+  *st_size = to.len;
+  return to.text;
+}
+
+/* Decide on the default encoding to assume for input files.  */
+const char *
+_cpp_default_encoding (void)
+{
+  const char *current_encoding = NULL;
+
+  /* We disable this because the default codeset is 7-bit ASCII on
+     most platforms, and this causes conversion failures on every
+     file in GCC that happens to have one of the upper 128 characters
+     in it -- most likely, as part of the name of a contributor.
+     We should definitely recognize in-band markers of file encoding,
+     like:
+     - the appropriate Unicode byte-order mark (FE FF) to recognize
+       UTF16 and UCS4 (in both big-endian and little-endian flavors)
+       and UTF8
+     - a "#i", "#d", "/ *", "//", " #p" or "#p" (for #pragma) to
+       distinguish ASCII and EBCDIC.
+     - now we can parse something like "#pragma GCC encoding <xyz>
+       on the first line, or even Emacs/VIM's mode line tags (there's
+       a problem here in that VIM uses the last line, and Emacs has
+       its more elaborate "local variables" convention).
+     - investigate whether Java has another common convention, which
+       would be friendly to support.
+     (Zack Weinberg and Paolo Bonzini, May 20th 2004)  */
+#if defined (HAVE_LOCALE_H) && defined (HAVE_LANGINFO_CODESET) && 0
+  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/support/cpp2/libcpp/directives.c b/support/cpp2/libcpp/directives.c
new file mode 100644 (file)
index 0000000..2602922
--- /dev/null
@@ -0,0 +1,2288 @@
+/* CPP Library. (Directive handling.)
+   Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "cpplib.h"
+#include "internal.h"
+#include "mkdeps.h"
+#include "obstack.h"
+
+/* 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.  */
+  bool is_nspace;
+  bool allow_expansion;
+  bool is_internal;
+  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 *, const cpp_token ***);
+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,
+                                                bool, bool);
+static void register_pragma (cpp_reader *, const char *, const char *,
+                            pragma_cb, bool, bool);
+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_pragma_sdcc_hash (cpp_reader *pfile);
+static void do_pragma_preproc_asm (cpp_reader *pfile);
+static void do_pragma_pedantic_parse_number (cpp_reader *pfile);
+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, IN_I)           /* 0 SVR4? */
+
+/* #sccs is synonymous with #ident.  */
+#define do_sccs do_ident
+
+/* 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);
+}
+
+/* Ensure there are no stray tokens other than comments at the end of
+   a directive, and gather the comments.  */
+static const cpp_token **
+check_eol_return_comments (cpp_reader *pfile)
+{
+  size_t c;
+  size_t capacity = 8;
+  const cpp_token **buf;
+
+  buf = XNEWVEC (const cpp_token *, capacity);
+  c = 0;
+  if (! SEEN_EOL ())
+    {
+      while (1)
+       {
+         const cpp_token *tok;
+
+         tok = _cpp_lex_token (pfile);
+         if (tok->type == CPP_EOF)
+           break;
+         if (tok->type != CPP_COMMENT)
+           cpp_error (pfile, CPP_DL_PEDWARN,
+                      "extra tokens at end of #%s directive",
+                      pfile->directive->name);
+         else
+           {
+             if (c + 1 >= capacity)
+               {
+                 capacity *= 2;
+                 buf = XRESIZEVEC (const cpp_token *, buf, capacity);
+               }
+             buf[c] = tok;
+             ++c;
+           }
+       }
+    }
+  buf[c] = NULL;
+  return buf;
+}
+
+/* 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;
+  pfile->directive_result.type = CPP_PADDING;
+
+  /* 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 lex.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;
+  bool was_discarding_output = pfile->state.discarding_output;
+  int skip = 1;
+
+  if (was_discarding_output)
+    pfile->state.prevent_expansion = 0;
+
+  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.  macro.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;
+    }
+  if (was_discarding_output)
+    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->prev)
+    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 macro.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 ATTRIBUTE_UNUSED, cpp_hashnode *h,
+                void *data_p ATTRIBUTE_UNUSED)
+{
+  /* Body of _cpp_free_definition inlined here for speed.
+     Macros and assertions no longer have anything to free.  */
+  h->type = NT_VOID;
+  h->flags &= ~(NODE_POISONED|NODE_BUILTIN|NODE_DISABLED);
+  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 = XNEWVEC (char, 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 = XRESIZEVEC (char, buffer, capacity);
+       }
+
+      if (token->flags & PREV_WHITE)
+       buffer[total_len++] = ' ';
+
+      total_len = (cpp_spell_token (pfile, token, (uchar *) &buffer[total_len],
+                                   true)
+                  - (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,
+              const cpp_token ***buf)
+{
+  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 = XNEWVEC (char, 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;
+    }
+
+  if (buf == NULL || CPP_OPTION (pfile, discard_comments))
+    check_eol (pfile);
+  else
+    {
+      /* If we are not discarding comments, then gather them while
+        doing the eol check.  */
+      *buf = check_eol_return_comments (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;
+  const cpp_token **buf = NULL;
+
+  /* Re-enable saving of comments if requested, so that the include
+     callback can dump comments which follow #include.  */
+  pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
+
+  fname = parse_include (pfile, &angle_brackets, &buf);
+  if (!fname)
+    {
+      if (buf)
+       XDELETEVEC (buf);
+      return;
+    }
+
+  if (!*fname)
+  {
+    cpp_error (pfile, CPP_DL_ERROR, "empty filename in #%s",
+               pfile->directive->name);
+    XDELETEVEC (fname);
+    if (buf)
+      XDELETEVEC (buf);
+    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,
+                          buf);
+
+      _cpp_stack_include (pfile, fname, angle_brackets, type);
+    }
+
+  XDELETEVEC (fname);
+  if (buf)
+    XDELETEVEC (buf);
+}
+
+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];
+
+  /* skip_rest_of_line() may cause line table to be realloc()ed so note down
+     sysp right now.  */
+
+  unsigned char map_sysp = map->sysp;
+  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 #%s directive",
+              pfile->directive->name);
+  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.  If INTERNAL is true
+   this pragma is being inserted by libcpp itself. */
+static struct pragma_entry *
+insert_pragma_entry (cpp_reader *pfile, struct pragma_entry **chain,
+                    const cpp_hashnode *pragma, pragma_cb handler,
+                    bool allow_expansion, bool internal)
+{
+  struct pragma_entry *new_entry;
+
+  new_entry = (struct pragma_entry *)
+    _cpp_aligned_alloc (pfile, sizeof (struct pragma_entry));
+  new_entry->pragma = pragma;
+  if (handler)
+    {
+      new_entry->is_nspace = 0;
+      new_entry->u.handler = handler;
+    }
+  else
+    {
+      new_entry->is_nspace = 1;
+      new_entry->u.space = NULL;
+    }
+
+  new_entry->allow_expansion = allow_expansion;
+  new_entry->is_internal = internal;
+  new_entry->next = *chain;
+  *chain = new_entry;
+  return new_entry;
+}
+
+/* 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.  If ALLOW_EXPANSION is set, allow macro
+   expansion while parsing pragma NAME.  INTERNAL is true if this is a
+   pragma registered by cpplib itself, false if it is registered via
+   cpp_register_pragma */
+static void
+register_pragma (cpp_reader *pfile, const char *space, const char *name,
+                pragma_cb handler, bool allow_expansion, bool internal)
+{
+  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,
+                                    allow_expansion, internal);
+      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, allow_expansion,
+                        internal);
+}
+
+/* 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.  If ALLOW_EXPANSION is set, allow macro
+   expansion while parsing pragma NAME.  This function is exported
+   from libcpp. */
+void
+cpp_register_pragma (cpp_reader *pfile, const char *space, const char *name,
+                    pragma_cb handler, bool allow_expansion)
+{
+  register_pragma (pfile, space, name, handler, allow_expansion, false);
+}
+
+/* Register the pragmas the preprocessor itself handles.  */
+void
+_cpp_init_internal_pragmas (cpp_reader *pfile)
+{
+  /* Pragmas in the global namespace.  */
+  register_pragma (pfile, 0, "once", do_pragma_once, false, true);
+
+  /* New GCC-specific pragmas should be put in the GCC namespace.  */
+  register_pragma (pfile, "GCC", "poison", do_pragma_poison, false, true);
+  register_pragma (pfile, "GCC", "system_header", do_pragma_system_header,
+                  false, true);
+  register_pragma (pfile, "GCC", "dependency", do_pragma_dependency,
+                  false, true);
+
+  /* Kevin abuse for SDCC. */
+  cpp_register_pragma(pfile, 0, "sdcc_hash", do_pragma_sdcc_hash, false);
+  /* SDCC _asm specific */
+  cpp_register_pragma(pfile, 0, "preproc_asm", do_pragma_preproc_asm, false);
+  /* SDCC specific */
+  cpp_register_pragma(pfile, 0, "pedantic_parse_number", do_pragma_pedantic_parse_number, false);
+}
+
+/* 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++ = (char *) 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.
+
+   The library user has the option of deferring execution of
+   #pragmas not handled by cpplib, in which case they are converted
+   to CPP_PRAGMA tokens and inserted into the output stream.  */
+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;
+
+  /* Save the current position so that defer_pragmas mode can
+     copy the entire current line to a string.  It will not work
+     to use _cpp_backup_tokens as that does not reverse buffer->cur.  */
+  const uchar *line_start = CPP_BUFFER (pfile)->cur;
+
+  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)
+    {
+      if (p->is_internal || !CPP_OPTION (pfile, defer_pragmas))
+       {
+         /* 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);
+         /* Never expand macros if handling a deferred pragma, since
+            the macro definitions now applicable may be different
+            from those at the point the pragma appeared.  */
+         if (p->allow_expansion && !pfile->state.in_deferred_pragma)
+           pfile->state.prevent_expansion--;
+         (*p->u.handler) (pfile);
+         if (p->allow_expansion && !pfile->state.in_deferred_pragma)
+           pfile->state.prevent_expansion++;
+       }
+      else
+       {
+         /* Squirrel away the pragma text.  Pragmas are
+            newline-terminated. */
+         const uchar *line_end;
+         uchar *s, c, cc;
+         cpp_string body;
+         cpp_token *ptok;
+
+         for (line_end = line_start; (c = *line_end) != '\n'; line_end++)
+           if (c == '"' || c == '\'')
+             {
+               /* Skip over string literal.  */
+               do
+                 {
+                   cc = *++line_end;
+                   if (cc == '\\' && line_end[1] != '\n')
+                     line_end++;
+                   else if (cc == '\n')
+                     {
+                       line_end--;
+                       break;
+                     }
+                 }
+               while (cc != c);
+             }
+           else if (c == '/')
+             {
+               if (line_end[1] == '*')
+                 {
+                   /* Skip over C block comment, unless it is multi-line.
+                      When encountering multi-line block comment, terminate
+                      the pragma token right before that block comment.  */
+                   const uchar *le = line_end + 2;
+                   while (*le != '\n')
+                     if (*le++ == '*' && *le == '/')
+                       {
+                         line_end = le;
+                         break;
+                       }
+                   if (line_end < le)
+                     break;
+                 }
+               else if (line_end[1] == '/'
+                        && (CPP_OPTION (pfile, cplusplus_comments)
+                            || cpp_in_system_header (pfile)))
+                 {
+                   line_end += 2;
+                   while (*line_end != '\n')
+                     line_end++;
+                   break;
+                 }
+             }
+
+         body.len = (line_end - line_start) + 1;
+         s = _cpp_unaligned_alloc (pfile, body.len + 1);
+         memcpy (s, line_start, body.len - 1);
+         s[body.len - 1] = '\n';
+         s[body.len] = '\0';
+         body.text = s;
+
+         /* Create a CPP_PRAGMA token.  */
+         ptok = &pfile->directive_result;
+         ptok->src_loc = pragma_token->src_loc;
+         ptok->type = CPP_PRAGMA;
+         ptok->flags = pragma_token->flags | NO_EXPAND;
+         ptok->val.str = body;
+       }
+    }
+  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;
+}
+
+/* SDCC specific
+   sdcc_hash pragma */
+static void
+do_pragma_sdcc_hash (cpp_reader *pfile)
+{
+    const cpp_token *tok = _cpp_lex_token (pfile);
+
+    if (tok->type == CPP_PLUS)
+    {
+       CPP_OPTION(pfile, allow_naked_hash)++;
+    }
+    else if (tok->type == CPP_MINUS)
+    {
+       CPP_OPTION(pfile, allow_naked_hash)--;
+    }
+    else
+    {
+       cpp_error (pfile, CPP_DL_ERROR,
+                  "invalid #pragma sdcc_hash directive, need '+' or '-'");
+    }
+}
+
+/* SDCC specific
+   pedantic_parse_number pragma */
+static void
+do_pragma_pedantic_parse_number (cpp_reader *pfile)
+{
+    const cpp_token *tok = _cpp_lex_token (pfile);
+
+  if (tok->type == CPP_PLUS)
+    {
+      CPP_OPTION(pfile, pedantic_parse_number)++;
+    }
+  else if (tok->type == CPP_MINUS)
+    {
+      CPP_OPTION(pfile, pedantic_parse_number)--;
+    }
+  else
+    {
+      cpp_error (pfile, CPP_DL_ERROR,
+                 "invalid #pragma pedantic_parse_number directive, need '+' or '-'");
+    }
+}
+
+/* SDCC _asm specific
+   switch _asm block preprocessing on / off */
+static void
+do_pragma_preproc_asm (cpp_reader *pfile)
+{
+  const cpp_token *tok = _cpp_lex_token (pfile);
+
+  if (tok->type == CPP_PLUS)
+    {
+      CPP_OPTION(pfile, preproc_asm)++;
+    }
+  else if (tok->type == CPP_MINUS)
+    {
+      CPP_OPTION(pfile, preproc_asm)--;
+    }
+  else
+    {
+      cpp_error (pfile, CPP_DL_ERROR,
+                "invalid #pragma preproc_asm directive, need '+' or '-'");
+    }
+}
+
+/* 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, NULL);
+  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 = (char *) 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);
+    XDELETE (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);
+  pfile->directive_result.type = CPP_PADDING;
+
+  if (string)
+    destringize_and_run (pfile, &string->val.str);
+  else
+    cpp_error (pfile, CPP_DL_ERROR,
+              "_Pragma takes a parenthesized string literal");
+}
+
+/* Handle a pragma that the front end deferred until now. */
+void
+cpp_handle_deferred_pragma (cpp_reader *pfile, const cpp_string *s)
+{
+  cpp_context *saved_context = pfile->context;
+  cpp_token *saved_cur_token = pfile->cur_token;
+  tokenrun *saved_cur_run = pfile->cur_run;
+  bool saved_defer_pragmas = CPP_OPTION (pfile, defer_pragmas);
+  void (*saved_line_change) (cpp_reader *, const cpp_token *, int)
+    = pfile->cb.line_change;
+
+  pfile->context = XNEW (cpp_context);
+  pfile->context->macro = 0;
+  pfile->context->prev = 0;
+  pfile->cb.line_change = NULL;
+  pfile->state.in_deferred_pragma = true;
+  CPP_OPTION (pfile, defer_pragmas) = false;
+
+  run_directive (pfile, T_PRAGMA, (const char *)s->text, s->len);
+
+  XDELETE (pfile->context);
+  pfile->context = saved_context;
+  pfile->cur_token = saved_cur_token;
+  pfile->cur_run = saved_cur_run;
+  pfile->cb.line_change = saved_line_change;
+  pfile->state.in_deferred_pragma = false;
+  CPP_OPTION (pfile, defer_pragmas) = saved_defer_pragmas;
+}
+
+/* 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 = (unsigned char *) 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)
+    {
+      size_t answer_size;
+
+      /* 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;
+       }
+
+      answer_size = sizeof (struct answer) + ((new_answer->count - 1)
+                                             * sizeof (cpp_token));
+      /* Commit or allocate storage for the object.  */
+      if (pfile->hash_table->alloc_subobject)
+       {
+         struct answer *temp_answer = new_answer;
+         new_answer = (struct answer *) pfile->hash_table->alloc_subobject
+            (answer_size);
+         memcpy (new_answer, temp_answer, answer_size);
+       }
+      else
+       BUFF_FRONT (pfile->a_buff) += answer_size;
+
+      node->type = NT_ASSERTION;
+      node->value.answers = new_answer;
+      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 = (char *) 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 = (char *) 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 = (char *) 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 = (char *) 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;
+}
+
+/* The dependencies structure.  (Creates one if it hasn't already been.)  */
+struct deps *
+cpp_get_deps (cpp_reader *pfile)
+{
+  if (!pfile->deps)
+    pfile->deps = deps_init ();
+  return pfile->deps;
+}
+
+/* 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_buffer = XOBNEW (&pfile->buffer_ob, cpp_buffer);
+
+  /* Clears, amongst other things, if_stack and mi_cmacro.  */
+  memset (new_buffer, 0, sizeof (cpp_buffer));
+
+  new_buffer->next_line = new_buffer->buf = buffer;
+  new_buffer->rlimit = buffer + len;
+  new_buffer->from_stage3 = from_stage3;
+  new_buffer->prev = pfile->buffer;
+  new_buffer->need_line = true;
+
+  pfile->buffer = new_buffer;
+
+  return new_buffer;
+}
+
+/* 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/support/cpp2/libcpp/errors.c b/support/cpp2/libcpp/errors.c
new file mode 100644 (file)
index 0000000..97de490
--- /dev/null
@@ -0,0 +1,189 @@
+/* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "internal.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);
+  else
+    fputs (_("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, client_diagnostic))
+    pfile->cb.error (pfile, level, _(msgid), &ap);
+  else
+    {
+      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/support/cpp2/libcpp/expr.c b/support/cpp2/libcpp/expr.c
new file mode 100644 (file)
index 0000000..32b1723
--- /dev/null
@@ -0,0 +1,1544 @@
+/* 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, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "cpplib.h"
+#include "internal.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 ((enum cpp_ttype) (CPP_LAST_CPP_OP + 1))
+#define CPP_UMINUS ((enum cpp_ttype) (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;
+}
+\f
+/* 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 cpp_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)
+       {
+         /* We want a number (or expression) and haven't got one.
+            Try to emit a specific diagnostic.  */
+         if (op.op == CPP_CLOSE_PAREN && top->op == CPP_OPEN_PAREN)
+           SYNTAX_ERROR ("missing expression between '(' and ')'");
+
+         if (op.op == CPP_EOF && 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));
+         else if (op.op == CPP_CLOSE_PAREN || op.op == CPP_EOF)
+           /* Complain about missing paren during reduction.  */;
+         else
+           SYNTAX_ERROR2 ("operator '%s' has no left operand",
+                          cpp_token_as_text (pfile, op.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 = XRESIZEVEC (struct op, pfile->op_stack, new_size);
+  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/support/cpp2/libcpp/files.c b/support/cpp2/libcpp/files.c
new file mode 100644 (file)
index 0000000..702aa4c
--- /dev/null
@@ -0,0 +1,1606 @@
+/* Part of CPP library.  File handling.
+   Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "cpplib.h"
+#include "internal.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__
+#include <io.h>
+  /* 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
+
+/* 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, int);
+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 void destroy_cpp_file (_cpp_file *);
+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_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 = XNEWVEC (char, 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 = XRESIZEVEC (char, 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, 0);
+         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, int angle_brackets)
+{
+  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))
+           {
+             /* Although this file must not go in the cache, because
+                the file found might depend on things (like the current file)
+                that aren't represented in the cache, it still has to go in
+                the list of all files so that #import works.  */
+             file->next_file = pfile->all_files;
+             pfile->all_files = file;
+             return file;
+           }
+
+         open_file_failed (pfile, file, angle_brackets);
+         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.  */
+#ifndef __BORLANDC__
+      if (file->st.st_size > INTTYPE_MAXIMUM (ssize_t))
+       {
+         cpp_error (pfile, CPP_DL_ERROR, "%s is too large", file->path);
+         return false;
+       }
+#endif
+
+      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 = XNEWVEC (uchar, 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 = XRESIZEVEC (uchar, buf, size + 1);
+       }
+    }
+
+  if (count < 0)
+    {
+      cpp_errno (pfile, CPP_DL_ERROR, file->path);
+      return false;
+    }
+
+#ifndef __BORLANDC__
+  /* For some reason, even though we opened with O_BINARY,
+   * Borland C++ seems to insist on doing CR/LF -> LF
+   * translations for us, which results in the file appearing
+   * shorter than stat told us it should be.
+   *
+   * This sucks, but don't bother throwing a warning.
+   */
+  if (regular && total != size && STAT_SIZE_RELIABLE (file->st))
+    cpp_error (pfile, CPP_DL_WARNING,
+              "%s is shorter than expected", file->path);
+#endif
+
+  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, 0);
+      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->pchname, file->fd, file->path);
+      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)
+       {
+         _cpp_file *ref_file;
+         bool same_file_p = false;
+
+         if (f->buffer && !f->buffer_valid)
+           {
+             /* We already have a buffer but it is not valid, because
+                the file is still stacked.  Make a new one.  */
+             ref_file = make_cpp_file (pfile, f->dir, f->name);
+             ref_file->path = f->path;
+           }
+         else
+           /* The file is not stacked anymore.  We can reuse it.  */
+           ref_file = f;
+
+         same_file_p = read_file (pfile, ref_file)
+                       /* Size might have changed in read_file().  */
+                       && ref_file->st.st_size == file->st.st_size
+                       && !memcmp (ref_file->buffer,
+                                   file->buffer,
+                                   file->st.st_size);
+
+         if (f->buffer && !f->buffer_valid)
+           {
+             ref_file->path = 0;
+             destroy_cpp_file (ref_file);
+           }
+
+         if (same_file_p)
+           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 = XNEWVEC (char, 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, angle_brackets);
+
+  /* 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 angle_brackets)
+{
+  int sysp = pfile->line_table->highest_line > 1 && pfile->buffer ? pfile->buffer->sysp : 0;
+  bool print_dep = CPP_OPTION (pfile, deps.style) > (angle_brackets || !!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 = XCNEW (_cpp_file);
+  file->main_file = !pfile->buffer;
+  file->fd = -1;
+  file->dir = dir;
+  file->name = xstrdup (fname);
+
+  return file;
+}
+
+/* Release a _cpp_file structure.  */
+static void
+destroy_cpp_file (_cpp_file *file)
+{
+  if (file->buffer)
+    free ((void *) file->buffer);
+  free ((void *) file->name);
+  free (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->dir_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 = XCNEW (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 = XNEWVEC (struct file_hash_entry,
+                                      pfile->file_hash_entries_allocated);
+}
+
+/* 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 = (struct file_hash_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);
+  pfile->dir_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);
+  htab_delete (pfile->dir_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, 0);
+}
+
+/* Not everyone who wants to set system-header-ness on a buffer can
+   see the details of a buffer.  This is an exported interface because
+   fix-header needs it.  */
+void
+cpp_make_system_header (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, angle_brackets);
+  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;
+      file->buffer_valid = false;
+    }
+}
+
+/* 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 = XNEWVEC (char, 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 = XNEWVEC (char, len + 1);
+  if (! is_space (ch))
+    {
+      *set++ = ch;
+      while ((ch = getc (f)) != EOF && ! is_space (ch))
+       {
+         if (set - alloc == len)
+           {
+             len *= 2;
+             alloc = XRESIZEVEC (char, 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 = (char *) 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 = XNEWVEC (const char *, room);
+
+  /* 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 = XRESIZEVEC (const char *, dir->name_map, room);
+           }
+
+         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 = XNEWVEC (char, 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;
+}
+\f
+/* 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_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;
+};
+
+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 entries[1];
+};
+
+static struct pchf_data *pchf;
+
+/* 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 *fp)
+{
+  size_t count = 0;
+  struct pchf_data *result;
+  size_t result_size;
+  _cpp_file *f;
+
+  for (f = pfile->all_files; f; f = f->next_file)
+    ++count;
+
+  result_size = (sizeof (struct pchf_data)
+                + sizeof (struct pchf_entry) * (count - 1));
+  result = XCNEWVAR (struct pchf_data, result_size);
+
+  result->count = 0;
+  result->have_once_only = false;
+
+  for (f = pfile->all_files; f; f = f->next_file)
+    {
+      size_t 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)
+       continue;
+
+      if (f->stack_count == 0)
+       continue;
+
+      count = result->count++;
+
+      result->entries[count].once_only = f->once_only;
+      /* |= is avoided in the next line because of an HP C compiler bug */
+      result->have_once_only = result->have_once_only | f->once_only;
+      if (f->buffer_valid)
+       md5_buffer ((const char *)f->buffer,
+                   f->st.st_size, result->entries[count].sum);
+      else
+       {
+         FILE *ff;
+         int oldfd = f->fd;
+
+         if (!open_file (f))
+           {
+             open_file_failed (pfile, f, 0);
+             return false;
+           }
+         ff = fdopen (f->fd, "rb");
+         md5_stream (ff, result->entries[count].sum);
+         fclose (ff);
+         f->fd = oldfd;
+       }
+      result->entries[count].size = f->st.st_size;
+    }
+
+  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, fp) == 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 = XNEWVAR (struct pchf_data, 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/support/cpp2/libcpp/identifiers.c b/support/cpp2/libcpp/identifiers.c
new file mode 100644 (file)
index 0000000..18070b1
--- /dev/null
@@ -0,0 +1,120 @@
+/* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "internal.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 = XOBNEW (&table->pfile->hash_ob, 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;
+  /* SDCC _asm specific */
+  s->n__asm             = cpp_lookup (pfile, DSC("_asm"));
+}
+
+/* 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/support/cpp2/libcpp/include/cpp-id-data.h b/support/cpp2/libcpp/include/cpp-id-data.h
new file mode 100644 (file)
index 0000000..2445186
--- /dev/null
@@ -0,0 +1,78 @@
+/* Structures that hang off cpp_identifier, for PCH.
+   Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include "cpplib.h"
+
+#if !defined (HAVE_UCHAR) && !defined (IN_GCC)
+typedef unsigned char uchar;
+#endif
+
+#define U (const unsigned char *)  /* Intended use: U"string" */
+
+/* Chained list of answers to an assertion.  */
+struct answer GTY(())
+{
+  struct answer *next;
+  unsigned int count;
+  cpp_token GTY ((length ("%h.count"))) first[1];
+};
+
+/* Each macro definition is recorded in a cpp_macro structure.
+   Variadic macros cannot occur with traditional cpp.  */
+struct cpp_macro GTY(())
+{
+  /* Parameters, if any.  */
+  cpp_hashnode ** GTY ((nested_ptr (union tree_node,
+               "%h ? CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (%h)) : NULL",
+                       "%h ? HT_IDENT_TO_GCC_IDENT (HT_NODE (%h)) : NULL"),
+                       length ("%h.paramc")))
+    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_macro_u
+  {
+    cpp_token * GTY ((tag ("0"), length ("%0.count"))) tokens;
+    const unsigned char * GTY ((tag ("1"))) text;
+  } GTY ((desc ("%1.traditional"))) exp;
+
+  /* Definition line number.  */
+  source_location 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;
+
+  /* Indicate which field of 'exp' is in use.  */
+  unsigned int traditional : 1;
+};
diff --git a/support/cpp2/libcpp/include/cpplib.h b/support/cpp2/libcpp/include/cpplib.h
new file mode 100644 (file)
index 0000000..4e879b9
--- /dev/null
@@ -0,0 +1,868 @@
+/* Definitions for CPP library.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+   2004, 2005
+   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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LIBCPP_CPPLIB_H
+#define LIBCPP_CPPLIB_H
+
+#include <sys/types.h>
+#include "symtab.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 ">>".  */
+
+#define TTYPE_TABLE                                                    \
+  OP(EQ,               "=")                                            \
+  OP(NOT,              "!")                                            \
+  OP(GREATER,          ">")    /* compare */                           \
+  OP(LESS,             "<")                                            \
+  OP(PLUS,             "+")    /* math */                              \
+  OP(MINUS,            "-")                                            \
+  OP(MULT,             "*")                                            \
+  OP(DIV,              "/")                                            \
+  OP(MOD,              "%")                                            \
+  OP(AND,              "&")    /* bit ops */                           \
+  OP(OR,               "|")                                            \
+  OP(XOR,              "^")                                            \
+  OP(RSHIFT,           ">>")                                           \
+  OP(LSHIFT,           "<<")                                           \
+  OP(MIN,              "<?")   /* extension */                         \
+  OP(MAX,              ">?")                                           \
+                                                                       \
+  OP(COMPL,            "~")                                            \
+  OP(AND_AND,          "&&")   /* logical */                           \
+  OP(OR_OR,            "||")                                           \
+  OP(QUERY,            "?")                                            \
+  OP(COLON,            ":")                                            \
+  OP(COMMA,            ",")    /* grouping */                          \
+  OP(OPEN_PAREN,       "(")                                            \
+  OP(CLOSE_PAREN,      ")")                                            \
+  TK(EOF,              NONE)                                           \
+  OP(EQ_EQ,            "==")   /* compare */                           \
+  OP(NOT_EQ,           "!=")                                           \
+  OP(GREATER_EQ,       ">=")                                           \
+  OP(LESS_EQ,          "<=")                                           \
+                                                                       \
+  /* These two are unary + / - in preprocessor expressions.  */                \
+  OP(PLUS_EQ,          "+=")   /* math */                              \
+  OP(MINUS_EQ,         "-=")                                           \
+                                                                       \
+  OP(MULT_EQ,          "*=")                                           \
+  OP(DIV_EQ,           "/=")                                           \
+  OP(MOD_EQ,           "%=")                                           \
+  OP(AND_EQ,           "&=")   /* bit ops */                           \
+  OP(OR_EQ,            "|=")                                           \
+  OP(XOR_EQ,           "^=")                                           \
+  OP(RSHIFT_EQ,                ">>=")                                          \
+  OP(LSHIFT_EQ,                "<<=")                                          \
+  OP(MIN_EQ,           "<?=")  /* extension */                         \
+  OP(MAX_EQ,           ">?=")                                          \
+  /* Digraphs together, beginning with CPP_FIRST_DIGRAPH.  */          \
+  OP(HASH,             "#")    /* digraphs */                          \
+  OP(PASTE,            "##")                                           \
+  OP(OPEN_SQUARE,      "[")                                            \
+  OP(CLOSE_SQUARE,     "]")                                            \
+  OP(OPEN_BRACE,       "{")                                            \
+  OP(CLOSE_BRACE,      "}")                                            \
+  /* The remainder of the punctuation. Order is not significant.  */   \
+  OP(SEMICOLON,                ";")    /* structure */                         \
+  OP(ELLIPSIS,         "...")                                          \
+  OP(PLUS_PLUS,                "++")   /* increment */                         \
+  OP(MINUS_MINUS,      "--")                                           \
+  OP(DEREF,            "->")   /* accessors */                         \
+  OP(DOT,              ".")                                            \
+  OP(SCOPE,            "::")                                           \
+  OP(DEREF_STAR,       "->*")                                          \
+  OP(DOT_STAR,         ".*")                                           \
+  OP(ATSIGN,           "@")  /* used in Objective-C */                 \
+                                                                       \
+  TK(NAME,             IDENT)   /* word */                             \
+  TK(AT_NAME,          IDENT)   /* @word - Objective-C */              \
+  TK(NUMBER,           LITERAL) /* 34_be+ta  */                        \
+                                                                       \
+  TK(CHAR,             LITERAL) /* 'char' */                           \
+  TK(WCHAR,            LITERAL) /* L'char' */                          \
+  TK(OTHER,            LITERAL) /* stray punctuation */                \
+                                                                       \
+  TK(STRING,           LITERAL) /* "string" */                         \
+  TK(WSTRING,          LITERAL) /* L"string" */                        \
+  TK(OBJC_STRING,      LITERAL) /* @"string" - Objective-C */          \
+  TK(HEADER_NAME,      LITERAL) /* <stdio.h> in #include */            \
+                                                                       \
+  TK(COMMENT,          LITERAL) /* Only if output comments.  */        \
+                                /* SPELL_LITERAL happens to DTRT.  */  \
+  TK(MACRO_ARG,                NONE)    /* Macro argument.  */                 \
+  TK(PRAGMA,           NONE)    /* Only if deferring pragmas */        \
+  TK(PADDING,          NONE)    /* Whitespace for -E.  */              \
+\
+  /* SDCC _asm specific */                                             \
+  TK(ASM,              LITERAL)   /* _asm ... _endasm ; */
+
+#define OP(e, s) CPP_ ## e,
+#define TK(e, s) CPP_ ## e,
+enum cpp_ttype
+{
+  TTYPE_TABLE
+  N_TTYPES,
+
+  /* Positions in the table.  */
+  CPP_LAST_EQ        = CPP_MAX,
+  CPP_FIRST_DIGRAPH  = CPP_HASH,
+  CPP_LAST_PUNCTUATOR= CPP_DOT_STAR,
+  CPP_LAST_CPP_OP    = CPP_LESS_EQ
+};
+#undef OP
+#undef TK
+
+/* C language kind, used when calling cpp_create_reader.  */
+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 GTY(())
+{
+  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.  */
+
+/* Specify which field, if any, of the cpp_token union is used.  */
+
+enum cpp_token_fld_kind {
+  CPP_TOKEN_FLD_NODE,
+  CPP_TOKEN_FLD_SOURCE,
+  CPP_TOKEN_FLD_STR,
+  CPP_TOKEN_FLD_ARG_NO,
+  CPP_TOKEN_FLD_NONE
+};
+
+/* 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 GTY(())
+{
+  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_token_u
+  {
+    /* An identifier.  */
+    cpp_hashnode *
+      GTY ((nested_ptr (union tree_node,
+               "%h ? CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (%h)) : NULL",
+                       "%h ? HT_IDENT_TO_GCC_IDENT (HT_NODE (%h)) : NULL"),
+           tag ("CPP_TOKEN_FLD_NODE")))
+        node;
+
+    /* Inherit padding from this token.  */
+    cpp_token * GTY ((tag ("CPP_TOKEN_FLD_SOURCE"))) source;
+
+    /* A string, or number.  */
+    struct cpp_string GTY ((tag ("CPP_TOKEN_FLD_STR"))) str;
+
+    /* Argument no. for a CPP_MACRO_ARG.  */
+    unsigned int GTY ((tag ("CPP_TOKEN_FLD_ARG_NO"))) arg_no;
+  } GTY ((desc ("cpp_token_val_index (&%1)"))) val;
+};
+
+/* Say which field is in use.  */
+extern enum cpp_token_fld_kind cpp_token_val_index (cpp_token *tok);
+
+/* 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;
+
+/* Style of header dependencies to generate.  */
+enum cpp_deps_style { DEPS_NONE = 0, DEPS_USER, DEPS_SYSTEM };
+
+/* The possible normalization levels, from most restrictive to least.  */
+enum cpp_normalize_level {
+  /* In NFKC.  */
+  normalized_KC = 0,
+  /* In NFC.  */
+  normalized_C,
+  /* In NFC, except for subsequences where being in NFC would make
+     the identifier invalid.  */
+  normalized_identifier_C,
+  /* Not normalized at all.  */
+  normalized_none
+};
+
+/* 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;
+
+  /* Nonzero means UCNs are accepted in identifiers.  */
+  unsigned char extended_identifiers;
+
+  /* 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;
+
+  /* The minimum permitted level of normalization before a warning
+     is generated.  */
+  enum cpp_normalize_level warn_normalize;
+
+  /* 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;
+
+  /* SDCC abuse by Kevin: allow naked '#' characters in expanded macros
+   * (see _cpp_create_definition in cppmacro.c)
+   */
+  unsigned char allow_naked_hash;
+
+  /* SDCC _asm specific
+     switch _asm block preprocessing on / off */
+  unsigned char preproc_asm;
+
+  /* SDCC specific
+     object file exetnsion */
+  const char *obj_ext;
+
+  /* SDCC specific
+     pedantic_parse_number */
+  unsigned char pedantic_parse_number;
+
+  /* Dependency generation.  */
+  struct
+  {
+    /* Style of header dependencies to generate.  */
+    enum cpp_deps_style 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;
+
+  /* True means return pragmas as tokens rather than processing
+     them directly. */
+  bool defer_pragmas;
+
+  /* True means error callback should be used for diagnostics.  */
+  bool client_diagnostic;
+};
+
+/* 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, const cpp_token **);
+  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;
+
+  /* Called to emit a diagnostic if client_diagnostic option is true.
+     This callback receives the translated message.  */
+  void (*error) (cpp_reader *, int, const char *, va_list *)
+       ATTRIBUTE_FPTR_PRINTF(3,0);
+};
+
+/* 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)
+
+/* Specify which field, if any, of the union is used.  */
+
+enum {
+  NTV_MACRO,
+  NTV_ANSWER,
+  NTV_BUILTIN,
+  NTV_ARGUMENT,
+  NTV_NONE
+};
+
+#define CPP_HASHNODE_VALUE_IDX(HNODE)                          \
+  ((HNODE.flags & NODE_MACRO_ARG) ? NTV_ARGUMENT               \
+   : HNODE.type == NT_MACRO ? ((HNODE.flags & NODE_BUILTIN)    \
+                              ? NTV_BUILTIN : NTV_MACRO)       \
+   : HNODE.type == NT_ASSERTION ? NTV_ANSWER                   \
+   : NTV_NONE)
+
+/* 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.  */
+
+union _cpp_hashnode_value GTY(())
+{
+  /* If a macro.  */
+  cpp_macro * GTY((tag ("NTV_MACRO"))) macro;
+  /* Answers to an assertion.  */
+  struct answer * GTY ((tag ("NTV_ANSWER"))) answers;
+  /* Code for a builtin macro.  */
+  enum builtin_type GTY ((tag ("NTV_BUILTIN"))) builtin;
+  /* Macro argument index.  */
+  unsigned short GTY ((tag ("NTV_ARGUMENT"))) arg_index;
+};
+
+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 GTY ((desc ("CPP_HASHNODE_VALUE_IDX (%1)"))) 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);
+
+/* 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, callback, and deps
+   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 *);
+extern struct deps *cpp_get_deps (cpp_reader *);
+
+/* 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 *, bool);
+extern void cpp_register_pragma (cpp_reader *, const char *, const char *,
+                                void (*) (cpp_reader *), bool);
+extern void cpp_handle_deferred_pragma (cpp_reader *, const cpp_string *);
+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);
+
+/* Convert a host character constant to the execution character set.  */
+extern cppchar_t cpp_host_to_exec_charset (cpp_reader *, cppchar_t);
+
+/* 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)
+
+/* 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 /* ! LIBCPP_CPPLIB_H */
diff --git a/support/cpp2/libcpp/include/line-map.h b/support/cpp2/libcpp/include/line-map.h
new file mode 100644 (file)
index 0000000..7e9ede0
--- /dev/null
@@ -0,0 +1,180 @@
+/* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LIBCPP_LINE_MAP_H
+#define LIBCPP_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;
+
+/* 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 *set, unsigned int to_line,  unsigned int max_column_hint);
+
+/* 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.
+
+   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 /* !LIBCPP_LINE_MAP_H  */
diff --git a/support/cpp2/libcpp/include/mkdeps.h b/support/cpp2/libcpp/include/mkdeps.h
new file mode 100644 (file)
index 0000000..0264970
--- /dev/null
@@ -0,0 +1,80 @@
+/* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 LIBCPP_MKDEPS_H
+#define LIBCPP_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;
+struct cpp_reader;
+
+/* Create a deps buffer.  */
+extern struct deps *deps_init (void);
+
+/* Destroy a deps buffer.  */
+extern void deps_free (struct deps *);
+
+/* Add a set of "vpath" directories. The second argument is a colon-
+   separated list of pathnames, like you would set Make's VPATH
+   variable to.  If a dependency or target name begins with any of
+   these pathnames (and the next path element is not "..") that
+   pathname is stripped off.  */
+extern void deps_add_vpath (struct deps *, const char *);
+
+/* 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 cpp_reader *, 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 /* ! LIBCPP_MKDEPS_H */
diff --git a/support/cpp2/libcpp/include/symtab.h b/support/cpp2/libcpp/include/symtab.h
new file mode 100644 (file)
index 0000000..cbcf230
--- /dev/null
@@ -0,0 +1,100 @@
+/* Hash tables.
+   Copyright (C) 2000, 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef LIBCPP_SYMTAB_H
+#define LIBCPP_SYMTAB_H
+
+#if defined(__APPLE__) && defined(__MACH__)
+#include "libiberty/obstack.h"
+#else
+#include "obstack.h"
+#endif
+#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, allocate a node.  */
+  hashnode (*alloc_node) (hash_table *);
+  /* Call back, allocate something that hangs off a node like a cpp_macro.
+     NULL means use the usual allocator.  */
+  void * (*alloc_subobject) (size_t);
+
+  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;
+
+  /* Should 'entries' be freed when it is no longer needed?  */
+  bool entries_owned;
+};
+
+/* 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);
+extern hashnode ht_lookup_with_hash (hash_table *, const unsigned char *,
+                                     size_t, unsigned int,
+                                     enum ht_lookup_option);
+#define HT_HASHSTEP(r, c) ((r) * 67 + ((c) - 113));
+#define HT_HASHFINISH(r, len) ((r) + (len))
+
+/* 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 *);
+
+/* Restore the hash table.  */
+extern void ht_load (hash_table *ht, hashnode *entries,
+                    unsigned int nslots, unsigned int nelements, bool own);
+
+/* Dump allocation statistics to stderr.  */
+extern void ht_dump_statistics (hash_table *);
+
+#endif /* LIBCPP_SYMTAB_H */
diff --git a/support/cpp2/libcpp/init.c b/support/cpp2/libcpp/init.c
new file mode 100644 (file)
index 0000000..726dafd
--- /dev/null
@@ -0,0 +1,644 @@
+/* CPP Library.
+   Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "cpplib.h"
+#include "internal.h"
+#include "mkdeps.h"
+#ifdef ENABLE_NLS
+#include "localedir.h"
+#endif
+
+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 extended_identifiers;
+  char std;
+  char cplusplus_comments;
+  char digraphs;
+};
+
+static const struct lang_flags lang_defaults[] =
+{ /*              c99 c++ xnum xid std  //   digr  */
+  /* GNUC89 */  { 0,  0,  1,   0,  0,   1,   1     },
+  /* GNUC99 */  { 1,  0,  1,   0,  0,   1,   1     },
+  /* STDC89 */  { 0,  0,  0,   0,  1,   0,   0     },
+  /* STDC94 */  { 0,  0,  0,   0,  1,   0,   1     },
+  /* STDC99 */  { 1,  0,  1,   0,  1,   1,   1     },
+  /* GNUCXX */  { 0,  1,  1,   0,  0,   1,   1     },
+  /* CXX98  */  { 0,  1,  1,   0,  1,   1,   1     },
+  /* ASM    */  { 0,  0,  1,   0,  0,   1,   0     }
+  /* xid should be 1 for GNUC99, STDC99, GNUCXX and CXX98 when no
+     longer experimental (when all uses of identifiers in the compiler
+     have been audited for correct handling of extended
+     identifiers).  */
+};
+
+/* 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, extended_identifiers)      = l->extended_identifiers;
+  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 ();
+
+#ifdef ENABLE_NLS
+       (void) bindtextdomain (PACKAGE, LOCALEDIR);
+#endif
+    }
+}
+
+/* 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 = XCNEW (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;
+  CPP_OPTION (pfile, warn_normalize) = normalized_C;
+
+  /* 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 ();
+
+  /* SDCC specific */
+  CPP_OPTION (pfile, preproc_asm) = 1;
+  CPP_OPTION (pfile, pedantic_parse_number) = 0;
+  CPP_OPTION (pfile, obj_ext) = NULL;
+
+  /* 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
+   macro.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;
+  else if (! CPP_OPTION (pfile, stdc_0_in_system_headers)
+          || CPP_OPTION (pfile, std))
+    {
+      n--;
+      _cpp_define_builtin (pfile, "__STDC__ 1");
+    }
+
+  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 = (enum builtin_type) 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
+
+/* 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, fname);
+    }
+
+  pfile->main_file
+    = _cpp_find_file (pfile, fname, &pfile->no_search_path, false, 0);
+  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)
+    {
+      pfile->state.in_directive = 1;
+      token1 = _cpp_lex_direct (pfile);
+      _cpp_backup_tokens (pfile, 1);
+      pfile->state.in_directive = 0;
+
+      /* 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 = (char *) 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);
+
+  /* lex.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))
+    {
+      CPP_OPTION (pfile, cplusplus_comments) = 0;
+
+      /* 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/support/cpp2/libcpp/internal.h b/support/cpp2/libcpp/internal.h
new file mode 100644 (file)
index 0000000..960f153
--- /dev/null
@@ -0,0 +1,661 @@
+/* Part of CPP library.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* This header defines all the internal data structures and functions
+   that need to be visible across files.  It should not be used outside
+   cpplib.  */
+
+#ifndef LIBCPP_INTERNAL_H
+#define LIBCPP_INTERNAL_H
+
+#include "symtab.h"
+#include "cpp-id-data.h"
+
+#ifndef HAVE_ICONV_H
+#undef HAVE_ICONV
+#endif
+
+#if 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;
+};
+
+#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)
+
+#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 unsigned char *cur;
+      const unsigned char *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 handling a deferred pragma.  */
+  unsigned char in_deferred_pragma;
+
+  /* Nonzero when parsing arguments to a function-like macro.  */
+  unsigned char parsing_args;
+
+  /* Nonzero if prevent_expansion is true only because output is
+     being discarded.  */
+  unsigned char discarding_output;
+
+  /* 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 */
+  /* SDCC _asm specific */
+  cpp_hashnode *n__asm;                /* _asm ... _endasm ; */
+};
+
+typedef struct _cpp_line_note _cpp_line_note;
+struct _cpp_line_note
+{
+  /* Location in the clean line the note refers to.  */
+  const unsigned char *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 unsigned char *cur;        /* Current location.  */
+  const unsigned char *line_base;  /* Start of current physical line.  */
+  const unsigned char *next_line;  /* Start of to-be-cleaned logical line.  */
+
+  const unsigned char *buf;        /* Entire character buffer.  */
+  const unsigned char *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.  */
+  source_location 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;
+
+  /* Token generated while handling a directive, if any. */
+  cpp_token directive_result;
+
+  /* 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 htab *dir_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 unsigned char *date;
+  const unsigned char *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 identifiers.c */
+  struct obstack hash_ob;
+
+  /* Obstack holding buffer and conditional structures.  This is a
+     real stack.  See directives.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
+  {
+    unsigned char *base;
+    unsigned char *limit;
+    unsigned char *cur;
+    source_location first_line;
+  } out;
+
+  /* Used for buffer overlays by traditional.c.  */
+  const unsigned char *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 lex.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 errors.c  */
+extern int _cpp_begin_message (cpp_reader *, int,
+                              source_location, unsigned int);
+
+/* In macro.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 unsigned char *, 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 unsigned char *_cpp_builtin_macro_text (cpp_reader *,
+                                                    cpp_hashnode *);
+int _cpp_warn_if_unused_macro (cpp_reader *, cpp_hashnode *, void *);
+/* In identifiers.c */
+extern void _cpp_init_hashtable (cpp_reader *, hash_table *);
+extern void _cpp_destroy_hashtable (cpp_reader *);
+
+/* In files.c */
+typedef struct _cpp_file _cpp_file;
+extern _cpp_file *_cpp_find_file (cpp_reader *, const char *, cpp_dir *,
+                                 bool, int);
+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 expr.c */
+extern bool _cpp_parse_expr (cpp_reader *);
+extern struct op *_cpp_expand_op_stack (cpp_reader *);
+
+/* In lex.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 init.c.  */
+extern void _cpp_maybe_push_include_file (cpp_reader *);
+
+/* In directives.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 traditional.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 unsigned char *,
+                                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 unsigned char *_cpp_copy_replacement_text (const cpp_macro *,
+                                                 unsigned char *);
+extern size_t _cpp_replacement_text_len (const cpp_macro *);
+
+/* In charset.c.  */
+
+/* The normalization state at this point in the sequence.
+   It starts initialized to all zeros, and at the end
+   'level' is the normalization level of the sequence.  */
+
+struct normalize_state
+{
+  /* The previous character.  */
+  cppchar_t previous;
+  /* The combining class of the previous character.  */
+  unsigned char prev_class;
+  /* The lowest normalization level so far.  */
+  enum cpp_normalize_level level;
+};
+#define INITIAL_NORMALIZE_STATE { 0, 0, normalized_KC }
+#define NORMALIZE_STATE_RESULT(st) ((st)->level)
+
+/* We saw a character that matches ISIDNUM(), update a
+   normalize_state appropriately.  */
+#define NORMALIZE_STATE_UPDATE_IDNUM(st) \
+  ((st)->previous = 0, (st)->prev_class = 0)
+
+extern cppchar_t _cpp_valid_ucn (cpp_reader *, const unsigned char **,
+                                const unsigned char *, int,
+                                struct normalize_state *state);
+extern void _cpp_destroy_iconv (cpp_reader *);
+extern unsigned char *_cpp_convert_input (cpp_reader *, const char *,
+                                         unsigned char *, size_t, size_t,
+                                         off_t *);
+extern const char *_cpp_default_encoding (void);
+extern cpp_hashnode * _cpp_interpret_identifier (cpp_reader *pfile,
+                                                const unsigned char *id,
+                                                size_t len);
+
+/* Utility routines and macros.  */
+#define DSC(str) (const unsigned char *)str, sizeof str - 1
+
+/* These are inline functions instead of macros so we can get type
+   checking.  */
+static inline int ustrcmp (const unsigned char *, const unsigned char *);
+static inline int ustrncmp (const unsigned char *, const unsigned char *,
+                           size_t);
+static inline size_t ustrlen (const unsigned char *);
+static inline unsigned char *uxstrdup (const unsigned char *);
+static inline unsigned char *ustrchr (const unsigned char *, int);
+static inline int ufputs (const unsigned char *, FILE *);
+
+/* Use a const char for the second parameter since it is usually a literal.  */
+static inline int ustrcspn (const unsigned char *, const char *);
+
+static inline int
+ustrcmp (const unsigned char *s1, const unsigned char *s2)
+{
+  return strcmp ((const char *)s1, (const char *)s2);
+}
+
+static inline int
+ustrncmp (const unsigned char *s1, const unsigned char *s2, size_t n)
+{
+  return strncmp ((const char *)s1, (const char *)s2, n);
+}
+
+static inline int
+ustrcspn (const unsigned char *s1, const char *s2)
+{
+  return strcspn ((const char *)s1, s2);
+}
+
+static inline size_t
+ustrlen (const unsigned char *s1)
+{
+  return strlen ((const char *)s1);
+}
+
+static inline unsigned char *
+uxstrdup (const unsigned char *s1)
+{
+  return (unsigned char *) xstrdup ((const char *)s1);
+}
+
+static inline unsigned char *
+ustrchr (const unsigned char *s1, int c)
+{
+  return (unsigned char *) strchr ((const char *)s1, c);
+}
+
+static inline int
+ufputs (const unsigned char *s, FILE *f)
+{
+  return fputs ((const char *)s, f);
+}
+
+#endif /* ! LIBCPP_INTERNAL_H */
diff --git a/support/cpp2/libcpp/lex.c b/support/cpp2/libcpp/lex.c
new file mode 100644 (file)
index 0000000..c4a5638
--- /dev/null
@@ -0,0 +1,2066 @@
+/* CPP Library - lexical analysis.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "cpplib.h"
+#include "internal.h"
+#include <assert.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) { SPELL_ ## 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 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 = XRESIZEVEC (_cpp_line_note, buffer->notes,
+                                  buffer->notes_cap);
+    }
+
+  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 ();
+    }
+}
+
+/* SDCC _asm specific */
+/* Skip an _asm ... _endasm block.  We find the end of the comment by
+   seeing _endasm.  Returns non-zero if _asm terminated by EOF, zero
+   otherwise.  */
+static int
+skip_asm_block (cpp_reader *pfile)
+{
+#define _ENDASM_STR "endasm"
+#define _ENDASM_LEN ((sizeof _ENDASM_STR) - 1)
+
+  cpp_buffer *buffer = pfile->buffer;
+  cppchar_t c = EOF;
+  int prev_space = 0;
+  int ret = 1;
+
+  while (buffer->cur != buffer->rlimit)
+    {
+      prev_space = is_space(c);
+      c = *buffer->cur++;
+
+      if (prev_space && c == '_')
+       {
+          if (buffer->cur + _ENDASM_LEN <= buffer->rlimit &&
+            strncmp(buffer->cur, _ENDASM_STR, _ENDASM_LEN) == 0)
+            {
+              buffer->cur += _ENDASM_LEN;
+              ret = 0;
+             break;
+            }
+       }
+      else if (c == '\n')
+       {
+         unsigned int cols;
+         --buffer->cur;
+         _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);
+       }
+    }
+
+  _cpp_process_line_notes (pfile, true);
+  return ret;
+}
+
+/* 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;
+}
+
+/* After parsing an identifier or other sequence, produce a warning about
+   sequences not in NFC/NFKC.  */
+static void
+warn_about_normalization (cpp_reader *pfile,
+                         const cpp_token *token,
+                         const struct normalize_state *s)
+{
+  if (CPP_OPTION (pfile, warn_normalize) < NORMALIZE_STATE_RESULT (s)
+      && !pfile->state.skipping)
+    {
+      /* Make sure that the token is printed using UCNs, even
+        if we'd otherwise happily print UTF-8.  */
+      unsigned char *buf = XNEWVEC (unsigned char, cpp_token_len (token));
+      size_t sz;
+
+      sz = cpp_spell_token (pfile, token, buf, false) - buf;
+      if (NORMALIZE_STATE_RESULT (s) == normalized_C)
+       cpp_error_with_line (pfile, CPP_DL_WARNING, token->src_loc, 0,
+                            "`%.*s' is not in NFKC", (int) sz, buf);
+      else
+       cpp_error_with_line (pfile, CPP_DL_WARNING, token->src_loc, 0,
+                            "`%.*s' is not in NFC", (int) sz, buf);
+    }
+}
+
+/* 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,
+                   struct normalize_state *state)
+{
+  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 (CPP_OPTION (pfile, extended_identifiers)
+      && *buffer->cur == '\\'
+      && (buffer->cur[1] == 'u' || buffer->cur[1] == 'U'))
+    {
+      buffer->cur += 2;
+      if (_cpp_valid_ucn (pfile, &buffer->cur, buffer->rlimit, 1 + !first,
+                         state))
+       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, bool starts_ucn,
+               struct normalize_state *nst)
+{
+  cpp_hashnode *result;
+  const uchar *cur;
+  unsigned int len;
+  unsigned int hash = HT_HASHSTEP (0, *base);
+
+  cur = pfile->buffer->cur;
+  if (! starts_ucn)
+    while (ISIDNUM (*cur))
+      {
+       hash = HT_HASHSTEP (hash, *cur);
+       cur++;
+      }
+  pfile->buffer->cur = cur;
+  if (starts_ucn || forms_identifier_p (pfile, false, nst))
+    {
+      /* Slower version for identifiers containing UCNs (or $).  */
+      do {
+       while (ISIDNUM (*pfile->buffer->cur))
+         {
+           pfile->buffer->cur++;
+           NORMALIZE_STATE_UPDATE_IDNUM (nst);
+         }
+      } while (forms_identifier_p (pfile, false, nst));
+      result = _cpp_interpret_identifier (pfile, base,
+                                         pfile->buffer->cur - base);
+    }
+  else
+    {
+      len = cur - base;
+      hash = HT_HASHFINISH (hash, len);
+
+      result = (cpp_hashnode *)
+       ht_lookup_with_hash (pfile->hash_table, base, len, hash, 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;
+}
+
+/* SDCC specific */
+/* Pedantic parse a number, beginning with character C, skipping embedded
+   backslash-newlines.  LEADING_PERIOD is nonzero if there was a "."
+   before C.  Place the result in NUMBER.  */
+static void
+pedantic_lex_number (cpp_reader *pfile, cpp_string *number)
+{
+#define get_effective_char(pfile) (*pfile->buffer->cur++)
+#define BACKUP() (--pfile->buffer->cur)
+
+  enum num_type_e { NT_DEC, NT_HEX } num_type = NT_DEC;
+  enum num_part_e { NP_WHOLE, NP_FRACT, NP_EXP, NP_INT_SUFFIX, NP_FLOAT_SUFFIX } num_part = NP_WHOLE;
+
+  uchar c = *(pfile->buffer->cur - 1);
+  struct obstack *stack = &pfile->hash_table->stack;
+  cpp_buffer *buffer = pfile->buffer;
+  int len = 0;
+  int has_whole = 0;
+  int has_fract = 0;
+
+  if ('.' == c)
+    {
+      num_part = NP_FRACT;
+      ++len;
+      obstack_1grow (stack, '.');
+      c = get_effective_char(pfile);
+    }
+  else
+    {
+      if ('0' == c)
+        {
+          has_whole = 1;
+          ++len;
+          obstack_1grow (stack, c);
+          c = get_effective_char(pfile);
+
+          switch (c)
+            {
+            case 'X':
+            case 'x':
+              num_type = NT_HEX;
+              ++len;
+              obstack_1grow (stack, c);
+              c = get_effective_char(pfile);
+              break;
+
+            case '.':
+              num_part = NP_FRACT;
+              ++len;
+              obstack_1grow (stack, c);
+              c = get_effective_char(pfile);
+              break;
+            }
+        }
+    }
+
+  for (; ; )
+    {
+      switch (num_part)
+        {
+        case NP_WHOLE:
+          if (NT_DEC == num_type)
+            {
+              while (ISDIGIT (c))
+                {
+                  has_whole = 1;
+                  ++len;
+                  obstack_1grow (stack, c);
+                  c = get_effective_char(pfile);
+                }
+
+              if ('.' == c)
+                {
+                  num_part = NP_FRACT;
+                  ++len;
+                  obstack_1grow (stack, c);
+                  c = get_effective_char(pfile);
+                  continue;
+                }
+              else if ('E' == c || 'e' == c)
+                {
+                  if (has_whole || has_fract)
+                  {
+                    num_part = NP_EXP;
+                    ++len;
+                    obstack_1grow (stack, c);
+                    c = get_effective_char(pfile);
+                    continue;
+                  }
+                  else
+                    break;
+                }
+            }
+          else
+            {
+              while (ISXDIGIT (c))
+                {
+                  has_whole = 1;
+                  ++len;
+                  obstack_1grow (stack, c);
+                  c = get_effective_char(pfile);
+                }
+
+              if ('.' == c)
+                {
+                  num_part = NP_FRACT;
+                  ++len;
+                  obstack_1grow (stack, c);
+                  c = get_effective_char(pfile);
+                  continue;
+                }
+              else if ('P' == c || 'p' == c)
+                {
+                  if (has_whole || has_fract)
+                    {
+                      num_part = NP_EXP;
+                      ++len;
+                      obstack_1grow (stack, c);
+                      c = get_effective_char(pfile);
+                      continue;
+                    }
+                  else
+                    break;
+                }
+            }
+          num_part = NP_INT_SUFFIX;
+          continue;
+
+        case NP_FRACT:
+          if (NT_DEC == num_type)
+            {
+              while (ISDIGIT (c))
+                {
+                  has_fract = 1;
+                  ++len;
+                  obstack_1grow (stack, c);
+                  c = get_effective_char(pfile);
+                }
+
+              if ('E' == c || 'e' == c)
+                {
+                  if (has_whole || has_fract)
+                    {
+                      num_part = NP_EXP;
+                      ++len;
+                      obstack_1grow (stack, c);
+                      c = get_effective_char(pfile);
+                      continue;
+                    }
+                }
+            }
+          else
+            {
+              while (ISXDIGIT (c))
+                {
+                  has_fract = 1;
+                  ++len;
+                  obstack_1grow (stack, c);
+                  c = get_effective_char(pfile);
+                }
+
+              if ('P' == c || 'p' == c)
+                {
+                  if (has_whole || has_fract)
+                    {
+                      num_part = NP_EXP;
+                      ++len;
+                      obstack_1grow (stack, c);
+                      c = get_effective_char(pfile);
+                      continue;
+                    }
+                }
+            }
+          num_part = NP_FLOAT_SUFFIX;
+          continue;
+
+        case NP_EXP:
+          if ('+' == c || '-' == c)
+            {
+              ++len;
+              obstack_1grow (stack, c);
+              c = get_effective_char(pfile);
+            }
+
+          while (ISDIGIT (c))
+            {
+              ++len;
+              obstack_1grow (stack, c);
+              c = get_effective_char(pfile);
+            }
+
+          num_part = NP_FLOAT_SUFFIX;
+          continue;
+
+        case NP_INT_SUFFIX:
+           if ('L' == c || 'l' == c)
+            {
+              uchar prevc = c;
+
+              ++len;
+              obstack_1grow (stack, c);
+              c = get_effective_char(pfile);
+
+              if (c == prevc)
+                {
+                  ++len;
+                  obstack_1grow (stack, c);
+                  c = get_effective_char(pfile);
+                }
+            }
+          else if ('U' == c || 'u' == c)
+            {
+              ++len;
+              obstack_1grow (stack, c);
+              c = get_effective_char(pfile);
+            }
+          break;
+
+        case NP_FLOAT_SUFFIX:
+           if ('F' == c || 'f' == c)
+            {
+              ++len;
+              obstack_1grow (stack, c);
+              c = get_effective_char(pfile);
+            }
+          else if ('L' == c || 'l' == c)
+            {
+              ++len;
+              obstack_1grow (stack, c);
+              c = get_effective_char(pfile);
+            }
+          break;
+        }
+      break;
+    }
+
+  /* Step back over the unwanted char.  */
+  BACKUP ();
+
+  number->text = obstack_finish (stack);
+  number->len = len;
+}
+
+/* Lex a number to NUMBER starting at BUFFER->CUR - 1.  */
+static void
+lex_number (cpp_reader *pfile, cpp_string *number,
+           struct normalize_state *nst)
+{
+  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++;
+         NORMALIZE_STATE_UPDATE_IDNUM (nst);
+       }
+
+      pfile->buffer->cur = cur;
+    }
+  while (forms_identifier_p (pfile, false, nst));
+
+  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);
+}
+
+/* Fixed _WIN32 problem with CR-CR-LF sequences when outputting
+   comment blocks (when executed with -C option) and
+   _asm (SDCPP specific) blocks */
+
+/* Count and copy characters from src to dest, excluding CRs:
+   CRs are automatically generated, because the output is
+   opened in TEXT mode. If dest == NULL, only count chars */
+static unsigned int
+copy_text_chars (char *dest, const char *src, unsigned int len)
+{
+  unsigned int n = 0;
+  const char *p;
+
+  for (p = src; p != src + len; ++p)
+    {
+      assert(*p != '\0');
+
+      if (*p != '\r')
+        {
+          if (dest != NULL)
+            *dest++ = *p;
+          ++n;
+        }
+    }
+
+    return n;
+}
+
+/* SDCC _asm specific */
+/* The stored comment includes the comment start and any terminator.  */
+static void
+save_asm (cpp_reader *pfile, cpp_token *token, const unsigned char *from)
+{
+#define _ASM_STR  "_asm"
+#define _ASM_LEN  ((sizeof _ASM_STR) - 1)
+
+  unsigned char *buffer;
+  unsigned int text_len, len;
+
+  len = pfile->buffer->cur - from;
+  /* + _ASM_LEN for the initial '_asm'.  */
+  text_len = copy_text_chars (NULL, from, len) + _ASM_LEN;
+  buffer = _cpp_unaligned_alloc (pfile, text_len);
+
+
+  token->type = CPP_ASM;
+  token->val.str.len = text_len;
+  token->val.str.text = buffer;
+
+  memcpy (buffer, _ASM_STR, _ASM_LEN);
+  copy_text_chars (buffer + _ASM_LEN, from, len);
+}
+
+/* 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] = '/';
+  copy_text_chars (buffer + 1, from, len);
+
+  /* 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))
+           {
+             if (pfile->directive_result.type == CPP_PADDING)
+               continue;
+             else
+               {
+                 result = &pfile->directive_result;
+                 break;
+               }
+           }
+
+         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':
+      {
+       struct normalize_state nst = INITIAL_NORMALIZE_STATE;
+       result->type = CPP_NUMBER;
+       if (CPP_OPTION(pfile, pedantic_parse_number))
+         pedantic_lex_number (pfile, &result->val.str);
+       else
+         lex_number (pfile, &result->val.str, &nst);
+       warn_about_normalization (pfile, result, &nst);
+       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;
+      {
+       struct normalize_state nst = INITIAL_NORMALIZE_STATE;
+       result->val.node = lex_identifier (pfile, buffer->cur - 1, false,
+                                          &nst);
+       warn_about_normalization (pfile, result, &nst);
+      }
+
+      /* SDCC _asm specific */
+      /* handle _asm ... _endasm ;  */
+      if (CPP_OPTION(pfile, preproc_asm) == 0 && result->val.node == pfile->spec_nodes.n__asm)
+        {
+          comment_start = buffer->cur;
+          result->type = CPP_ASM;
+          skip_asm_block (pfile);
+          /* Save the _asm block as a token in its own right.  */
+          save_asm (pfile, result, comment_start);
+        }
+      /* Convert named operators to their proper types.  */
+      else if (result->val.node->flags & NODE_OPERATOR)
+       {
+         result->flags |= NAMED_OP;
+         result->type = (enum cpp_ttype) 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))
+       {
+         struct normalize_state nst = INITIAL_NORMALIZE_STATE;
+         result->type = CPP_NUMBER;
+         if (CPP_OPTION(pfile, pedantic_parse_number))
+           pedantic_lex_number (pfile, &result->val.str);
+         else
+           lex_number (pfile, &result->val.str, &nst);
+         warn_about_normalization (pfile, result, &nst);
+       }
+      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;
+       struct normalize_state nst = INITIAL_NORMALIZE_STATE;
+
+       if (forms_identifier_p (pfile, true, &nst))
+         {
+           result->type = CPP_NAME;
+           result->val.node = lex_identifier (pfile, base, true, &nst);
+           warn_about_normalization (pfile, result, &nst);
+           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) * 10;  break;
+    }
+
+  return len;
+}
+
+/* Parse UTF-8 out of NAMEP and place a \U escape in BUFFER.
+   Return the number of bytes read out of NAME.  (There are always
+   10 bytes written to BUFFER.)  */
+
+static size_t
+utf8_to_ucn (unsigned char *buffer, const unsigned char *name)
+{
+  int j;
+  int ucn_len = 0;
+  int ucn_len_c;
+  unsigned t;
+  unsigned long utf32;
+
+  /* Compute the length of the UTF-8 sequence.  */
+  for (t = *name; t & 0x80; t <<= 1)
+    ucn_len++;
+
+  utf32 = *name & (0x7F >> ucn_len);
+  for (ucn_len_c = 1; ucn_len_c < ucn_len; ucn_len_c++)
+    {
+      utf32 = (utf32 << 6) | (*++name & 0x3F);
+
+      /* Ill-formed UTF-8.  */
+      if ((*name & ~0x3F) != 0x80)
+       abort ();
+    }
+
+  *buffer++ = '\\';
+  *buffer++ = 'U';
+  for (j = 7; j >= 0; j--)
+    *buffer++ = "0123456789abcdef"[(utf32 >> (4 * j)) & 0xF];
+  return ucn_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.
+   FORSTRING is true if this is to be the spelling after translation
+   phase 1 (this is different for UCNs).
+   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, bool forstring)
+{
+  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:
+      if (forstring)
+       {
+         memcpy (buffer, NODE_NAME (token->val.node),
+                 NODE_LEN (token->val.node));
+         buffer += NODE_LEN (token->val.node);
+       }
+      else
+       {
+         size_t i;
+         const unsigned char * name = NODE_NAME (token->val.node);
+
+         for (i = 0; i < NODE_LEN (token->val.node); i++)
+           if (name[i] & ~0x7F)
+             {
+               i += utf8_to_ucn (buffer, name + i) - 1;
+               buffer += 10;
+             }
+           else
+             *buffer++ = NODE_NAME (token->val.node)[i];
+       }
+      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, false);
+  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:
+      {
+       size_t i;
+       const unsigned char * name = NODE_NAME (token->val.node);
+
+       for (i = 0; i < NODE_LEN (token->val.node); i++)
+         if (name[i] & ~0x7F)
+           {
+             unsigned char buffer[10];
+             i += utf8_to_ucn (buffer, name + i) - 1;
+             fwrite (buffer, 1, 10, fp);
+           }
+         else
+           fputc (NODE_NAME (token->val.node)[i], 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 = XNEWVEC (unsigned char, 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;
+}
+
+/* Say which field of TOK is in use.  */
+
+enum cpp_token_fld_kind
+cpp_token_val_index (cpp_token *tok)
+{
+  switch (TOKEN_SPELL (tok))
+    {
+    case SPELL_IDENT:
+      return CPP_TOKEN_FLD_NODE;
+    case SPELL_LITERAL:
+      return CPP_TOKEN_FLD_STR;
+    case SPELL_NONE:
+      if (tok->type == CPP_MACRO_ARG)
+       return CPP_TOKEN_FLD_ARG_NO;
+      else if (tok->type == CPP_PADDING)
+       return CPP_TOKEN_FLD_SOURCE;
+      else if (tok->type == CPP_PRAGMA)
+       return CPP_TOKEN_FLD_STR;
+      /* else fall through */
+    default:
+      return CPP_TOKEN_FLD_NONE;
+    }
+}
diff --git a/support/cpp2/libcpp/line-map.c b/support/cpp2/libcpp/line-map.c
new file mode 100644 (file)
index 0000000..c95eacd
--- /dev/null
@@ -0,0 +1,348 @@
+/* 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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"
+
+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 = XRESIZEVEC (struct line_map, set->maps, set->allocated);
+    }
+
+  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)
+       {
+         /* If the column number is ridiculous or we've allocated a huge
+            number of source_locations, give up on column numbers. */
+         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;
+       }
+      /* Allocate the new line_map.  However, if the current map only has a
+        single line we can sometimes just increase its column_bits instead. */
+      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 + ((to_line - map->to_line) << column_bits);
+    }
+  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/support/cpp2/libcpp/macro.c b/support/cpp2/libcpp/macro.c
new file mode 100644 (file)
index 0000000..b414311
--- /dev/null
@@ -0,0 +1,1792 @@
+/* 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, 2005 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "internal.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"
+};
+
+/* Helper function for builtin_macro.  Returns the text generated by
+   a builtin macro. */
+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 * 2 + 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.  (b) and (c) are already checked in cpp_init_builtins.  */
+    case BT_STDC:
+      if (cpp_in_system_header (pfile))
+       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 a new token may not
+   be 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);
+      if (pfile->directive_result.type == CPP_PRAGMA)
+       {
+         cpp_token *tok = _cpp_temp_token (pfile);
+         *tok = pfile->directive_result;
+         push_token_context (pfile, NULL, tok, 1);
+       }
+
+      return 1;
+    }
+
+  buf = _cpp_builtin_macro_text (pfile, node);
+  len = ustrlen (buf);
+  nbuf = (char *) 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. 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
+         *dest++ = c;
+    }
+
+  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, true) - buf;
+         dest = cpp_quote_string (dest, buf, len);
+         _cpp_release_buff (pfile, buff);
+       }
+      else
+       dest = cpp_spell_token (pfile, token, dest, true);
+
+      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 = (unsigned char *) alloca (len);
+  end = cpp_spell_token (pfile, lhs, buf, false);
+
+  /* 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, false);
+  *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 = (*paste_flag)->val;
+         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;
+
+  /* Data in GCed data structures cannot be made const so far, so we
+     need a cast here.  */
+  result->val.source = (cpp_token *) 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 = XNEWVEC (const cpp_token *, capacity);
+
+  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 = XRESIZEVEC (const cpp_token *, arg->expanded,
+                                      capacity);
+       }
+
+      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 = result->val;
+         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;
+
+  pfile->state.discarding_output++;
+  pfile->state.prevent_expansion++;
+
+  if (CPP_OPTION (pfile, traditional))
+    while (_cpp_read_logical_line_trad (pfile))
+      ;
+  else
+    while (cpp_get_token (pfile)->type != CPP_EOF)
+      ;
+
+  pfile->state.discarding_output--;
+  pfile->state.prevent_expansion--;
+}
+
+/* Step back one (or more) tokens.  Can only step mack more than 1 if
+   they are from the lexer, and not from macro expansion.  */
+void
+_cpp_backup_tokens (cpp_reader *pfile, unsigned int count)
+{
+  if (pfile->context->prev == NULL)
+    {
+      pfile->lookaheads += count;
+      while (count--)
+       {
+         pfile->cur_token--;
+         if (pfile->cur_token == pfile->cur_run->base
+             /* Possible with -fpreprocessed and no leading #line.  */
+             && pfile->cur_run->prev != NULL)
+           {
+             pfile->cur_run = pfile->cur_run->prev;
+             pfile->cur_token = pfile->cur_run->limit;
+           }
+       }
+    }
+  else
+    {
+      if (count != 1)
+       abort ();
+      if (pfile->context->direct_p)
+       FIRST (pfile->context).token--;
+      else
+       FIRST (pfile->context).ptoken--;
+    }
+}
+
+/* #define directive parsing and handling.  */
+
+/* Returns nonzero if a macro redefinition warning is required.  */
+static bool
+warn_of_redefinition (cpp_reader *pfile, const cpp_hashnode *node,
+                     const cpp_macro *macro2)
+{
+  const cpp_macro *macro1;
+  unsigned int i;
+
+  /* Some redefinitions need to be warned about regardless.  */
+  if (node->flags & NODE_WARN)
+    return true;
+
+  /* Redefinition of a macro is allowed if and only if the old and new
+     definitions are the same.  (6.10.3 paragraph 2).  */
+  macro1 = node->value.macro;
+
+  /* Don't check count here as it can be different in valid
+     traditional redefinitions with just whitespace differences.  */
+  if (macro1->paramc != macro2->paramc
+      || macro1->fun_like != macro2->fun_like
+      || macro1->variadic != macro2->variadic)
+    return true;
+
+  /* Check parameter spellings.  */
+  for (i = 0; i < macro1->paramc; i++)
+    if (macro1->params[i] != macro2->params[i])
+      return true;
+
+  /* Check the replacement text or tokens.  */
+  if (CPP_OPTION (pfile, traditional))
+    return _cpp_expansions_different_trad (macro1, macro2);
+
+  if (macro1->count != macro2->count)
+    return true;
+
+  for (i = 0; i < macro1->count; i++)
+    if (!_cpp_equiv_tokens (&macro1->exp.tokens[i], &macro2->exp.tokens[i]))
+      return true;
+
+  return false;
+}
+
+/* Free the definition of hashnode H.  */
+void
+_cpp_free_definition (cpp_hashnode *h)
+{
+  /* Macros and assertions no longer have anything to free.  */
+  h->type = NT_VOID;
+  /* Clear builtin flag in case of redefinition.  */
+  h->flags &= ~(NODE_BUILTIN | NODE_DISABLED);
+}
+
+/* Save parameter NODE to the parameter list of macro MACRO.  Returns
+   zero on success, nonzero if the parameter is a duplicate.  */
+bool
+_cpp_save_parameter (cpp_reader *pfile, cpp_macro *macro, cpp_hashnode *node)
+{
+  unsigned int len;
+  /* Constraint 6.10.3.6 - duplicate parameter names.  */
+  if (node->flags & NODE_MACRO_ARG)
+    {
+      cpp_error (pfile, CPP_DL_ERROR, "duplicate macro parameter \"%s\"",
+                NODE_NAME (node));
+      return true;
+    }
+
+  if (BUFF_ROOM (pfile->a_buff)
+      < (macro->paramc + 1) * sizeof (cpp_hashnode *))
+    _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_hashnode *));
+
+  ((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[macro->paramc++] = node;
+  node->flags |= NODE_MACRO_ARG;
+  len = macro->paramc * sizeof (union _cpp_hashnode_value);
+  if (len > pfile->macro_buffer_len)
+    {
+      pfile->macro_buffer = XRESIZEVEC (unsigned char, 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 or allocate the parameter array.  */
+      if (pfile->hash_table->alloc_subobject)
+       {
+         cpp_hashnode **params =
+            (cpp_hashnode **) pfile->hash_table->alloc_subobject
+            (sizeof (cpp_hashnode *) * macro->paramc);
+         memcpy (params, macro->params,
+                 sizeof (cpp_hashnode *) * macro->paramc);
+         macro->params = params;
+       }
+      else
+       BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc];
+      macro->fun_like = 1;
+    }
+  else if (ctoken->type != CPP_EOF && !(ctoken->flags & PREV_WHITE))
+    {
+      /* While ISO C99 requires whitespace before replacement text
+        in a macro definition, ISO C90 with TC1 allows there characters
+        from the basic source character set.  */
+      if (CPP_OPTION (pfile, c99))
+       cpp_error (pfile, CPP_DL_PEDWARN,
+                  "ISO C99 requires whitespace after the macro name");
+      else
+       {
+         int warntype = CPP_DL_WARNING;
+         switch (ctoken->type)
+           {
+           case CPP_ATSIGN:
+           case CPP_AT_NAME:
+           case CPP_OBJC_STRING:
+             /* '@' is not in basic character set.  */
+             warntype = CPP_DL_PEDWARN;
+             break;
+           case CPP_OTHER:
+             /* Basic character set sans letters, digits and _.  */
+             if (strchr ("!\"#%&'()*+,-./:;<=>?[\\]^{|}~",
+                         ctoken->val.str.text[0]) == NULL)
+               warntype = CPP_DL_PEDWARN;
+             break;
+           default:
+             /* All other tokens start with a character from basic
+                character set.  */
+             break;
+           }
+         cpp_error (pfile, warntype,
+                    "missing 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_OPTION(pfile, allow_naked_hash)))
+           {
+             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);
+  macro->traditional = 0;
+
+  /* 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 or allocate the memory.  */
+  if (pfile->hash_table->alloc_subobject)
+    {
+      cpp_token *tokns =
+        (cpp_token *) pfile->hash_table->alloc_subobject (sizeof (cpp_token)
+                                                          * macro->count);
+      memcpy (tokns, macro->exp.tokens, sizeof (cpp_token) * macro->count);
+      macro->exp.tokens = tokns;
+    }
+  else
+    BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->exp.tokens[macro->count];
+
+  return true;
+}
+
+/* Parse a macro and save its expansion.  Returns nonzero on success.  */
+bool
+_cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
+{
+  cpp_macro *macro;
+  unsigned int i;
+  bool ok;
+
+  if (pfile->hash_table->alloc_subobject)
+    macro = (cpp_macro *) pfile->hash_table->alloc_subobject
+      (sizeof (cpp_macro));
+  else
+    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
+        directives.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; /* "," */
+    }
+
+  /* This should match below where we fill in the buffer.  */
+  if (CPP_OPTION (pfile, traditional))
+    len += _cpp_replacement_text_len (macro);
+  else
+    {
+      for (i = 0; i < macro->count; i++)
+       {
+         cpp_token *token = &macro->exp.tokens[i];
+
+         if (token->type == CPP_MACRO_ARG)
+           len += NODE_LEN (macro->params[token->val.arg_no - 1]);
+         else
+           len += cpp_token_len (token);
+
+         if (token->flags & STRINGIFY_ARG)
+           len++;                      /* "#" */
+         if (token->flags & PASTE_LEFT)
+           len += 3;           /* " ##" */
+         if (token->flags & PREV_WHITE)
+           len++;              /* " " */
+       }
+    }
+
+  if (len > pfile->macro_buffer_len)
+    {
+      pfile->macro_buffer = XRESIZEVEC (unsigned char,
+                                        pfile->macro_buffer, len);
+      pfile->macro_buffer_len = len;
+    }
+
+  /* Fill in the buffer.  Start with the macro name.  */
+  buffer = pfile->macro_buffer;
+  memcpy (buffer, NODE_NAME (node), NODE_LEN (node));
+  buffer += NODE_LEN (node);
+
+  /* Parameter names.  */
+  if (macro->fun_like)
+    {
+      *buffer++ = '(';
+      for (i = 0; i < macro->paramc; i++)
+       {
+         cpp_hashnode *param = macro->params[i];
+
+         if (param != pfile->spec_nodes.n__VA_ARGS__)
+           {
+             memcpy (buffer, NODE_NAME (param), NODE_LEN (param));
+             buffer += NODE_LEN (param);
+           }
+
+         if (i + 1 < macro->paramc)
+           /* Don't emit a space after the comma here; we're trying
+              to emit a Dwarf-friendly definition, and the Dwarf spec
+              forbids spaces in the argument list.  */
+           *buffer++ = ',';
+         else if (macro->variadic)
+           *buffer++ = '.', *buffer++ = '.', *buffer++ = '.';
+       }
+      *buffer++ = ')';
+    }
+
+  /* The Dwarf spec requires a space after the macro name, even if the
+     definition is the empty string.  */
+  *buffer++ = ' ';
+
+  if (CPP_OPTION (pfile, traditional))
+    buffer = _cpp_copy_replacement_text (macro, buffer);
+  else if (macro->count)
+  /* Expansion tokens.  */
+    {
+      for (i = 0; i < macro->count; i++)
+       {
+         cpp_token *token = &macro->exp.tokens[i];
+
+         if (token->flags & PREV_WHITE)
+           *buffer++ = ' ';
+         if (token->flags & STRINGIFY_ARG)
+           *buffer++ = '#';
+
+         if (token->type == CPP_MACRO_ARG)
+           {
+             memcpy (buffer,
+                     NODE_NAME (macro->params[token->val.arg_no - 1]),
+                     NODE_LEN (macro->params[token->val.arg_no - 1]));
+             buffer += NODE_LEN (macro->params[token->val.arg_no - 1]);
+           }
+         else
+           buffer = cpp_spell_token (pfile, token, buffer, false);
+
+         if (token->flags & PASTE_LEFT)
+           {
+             *buffer++ = ' ';
+             *buffer++ = '#';
+             *buffer++ = '#';
+             /* Next has PREV_WHITE; see _cpp_create_definition.  */
+           }
+       }
+    }
+
+  *buffer = '\0';
+  return pfile->macro_buffer;
+}
diff --git a/support/cpp2/libcpp/mkdeps.c b/support/cpp2/libcpp/mkdeps.c
new file mode 100644 (file)
index 0000000..31feb82
--- /dev/null
@@ -0,0 +1,363 @@
+/* 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"
+#include "internal.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 (cpp_reader *pfile, const char *tgt)
+{
+  struct deps *d = pfile->deps;
+
+  /* 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;
+      char *suffix;
+      const char *obj_ext;
+
+      if (NULL == CPP_OPTION (pfile, obj_ext))
+        obj_ext = TARGET_OBJECT_SUFFIX;
+      else if (CPP_OPTION (pfile, obj_ext)[0] != '.')
+        {
+          char *t = alloca (strlen (CPP_OPTION (pfile, obj_ext)) + 2);
+          t[0] = '.';
+          strcpy (&t[1], CPP_OPTION (pfile, obj_ext));
+          obj_ext = t;
+        }
+      else
+        obj_ext = CPP_OPTION (pfile, obj_ext);
+
+      o = (char *) alloca (strlen (start) + strlen (obj_ext) + 1);
+
+      strcpy (o, start);
+
+      suffix = strrchr (o, '.');
+      if (!suffix)
+        suffix = o + strlen (o);
+      strcpy (suffix, obj_ext);
+
+      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/support/cpp2/libcpp/symtab.c b/support/cpp2/libcpp/symtab.c
new file mode 100644 (file)
index 0000000..ffa28f5
--- /dev/null
@@ -0,0 +1,335 @@
+/* Hash tables.
+   Copyright (C) 2000, 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "symtab.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;
+
+  while (n--)
+    r = HT_HASHSTEP (r, *str++);
+
+  return HT_HASHFINISH (r, len);
+}
+
+/* Initialize an identifier hashtable.  */
+
+hash_table *
+ht_create (unsigned int order)
+{
+  unsigned int nslots = 1 << order;
+  hash_table *table;
+
+  table = XCNEW (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 = XCNEWVEC (hashnode, nslots);
+  table->entries_owned = true;
+  table->nslots = nslots;
+  return table;
+}
+
+/* Frees all memory associated with a hash table.  */
+
+void
+ht_destroy (hash_table *table)
+{
+  obstack_free (&table->stack, NULL);
+  if (table->entries_owned)
+    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)
+{
+  return ht_lookup_with_hash (table, str, len, calc_hash (str, len),
+                             insert);
+}
+
+hashnode
+ht_lookup_with_hash (hash_table *table, const unsigned char *str,
+                    size_t len, unsigned int hash,
+                    enum ht_lookup_option insert)
+{
+  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) = (const unsigned char *) 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 = XCNEWVEC (hashnode, size);
+  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);
+
+  if (table->entries_owned)
+    free (table->entries);
+  table->entries_owned = true;
+  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);
+}
+
+/* Restore the hash table.  */
+void
+ht_load (hash_table *ht, hashnode *entries,
+        unsigned int nslots, unsigned int nelements,
+        bool own)
+{
+  if (ht->entries_owned)
+    free (ht->entries);
+  ht->entries = entries;
+  ht->nslots = nslots;
+  ht->nelements = nelements;
+  ht->entries_owned = own;
+}
+
+/* Dump allocation statistics to stderr.  */
+
+void
+ht_dump_statistics (hash_table *table)
+{
+  size_t nelts, nids, overhead, headers;
+  size_t total_bytes, longest;
+  double sum_of_squares, 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 += (double) 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/support/cpp2/libcpp/system.h b/support/cpp2/libcpp/system.h
new file mode 100644 (file)
index 0000000..3e0d89d
--- /dev/null
@@ -0,0 +1,437 @@
+/* Get common system includes and various definitions and declarations based
+   on autoconf macros.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Free Software Foundation, Inc.
+
+This file is part of libcpp (aka cpplib).
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+
+#ifndef LIBCPP_SYSTEM_H
+#define LIBCPP_SYSTEM_H
+
+/* We must include stdarg.h before stdio.h.  */
+#include <stdarg.h>
+
+#ifdef HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+
+#include <stdio.h>
+
+/* Define a generic NULL if one hasn't already been defined.  */
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* Use the unlocked open routines from libiberty.  */
+#define fopen(PATH,MODE) fopen_unlocked(PATH,MODE)
+#define fdopen(FILDES,MODE) fdopen_unlocked(FILDES,MODE)
+#define freopen(PATH,MODE,STREAM) freopen_unlocked(PATH,MODE,STREAM)
+
+/* The compiler is not a multi-threaded application and therefore we
+   do not have to use the locking functions.  In fact, using the locking
+   functions can cause the compiler to be significantly slower under
+   I/O bound conditions (such as -g -O0 on very large source files).
+
+   HAVE_DECL_PUTC_UNLOCKED actually indicates whether or not the stdio
+   code is multi-thread safe by default.  If it is set to 0, then do
+   not worry about using the _unlocked functions.
+
+   fputs_unlocked, fwrite_unlocked, and fprintf_unlocked are
+   extensions and need to be prototyped by hand (since we do not
+   define _GNU_SOURCE).  */
+
+#if defined HAVE_DECL_PUTC_UNLOCKED && HAVE_DECL_PUTC_UNLOCKED
+
+# ifdef HAVE_PUTC_UNLOCKED
+#  undef putc
+#  define putc(C, Stream) putc_unlocked (C, Stream)
+# endif
+# ifdef HAVE_PUTCHAR_UNLOCKED
+#  undef putchar
+#  define putchar(C) putchar_unlocked (C)
+# endif
+# ifdef HAVE_GETC_UNLOCKED
+#  undef getc
+#  define getc(Stream) getc_unlocked (Stream)
+# endif
+# ifdef HAVE_GETCHAR_UNLOCKED
+#  undef getchar
+#  define getchar() getchar_unlocked ()
+# endif
+# ifdef HAVE_FPUTC_UNLOCKED
+#  undef fputc
+#  define fputc(C, Stream) fputc_unlocked (C, Stream)
+# endif
+
+# ifdef HAVE_CLEARERR_UNLOCKED
+#  undef clearerr
+#  define clearerr(Stream) clearerr_unlocked (Stream)
+#  if defined (HAVE_DECL_CLEARERR_UNLOCKED) && !HAVE_DECL_CLEARERR_UNLOCKED
+extern void clearerr_unlocked (FILE *);
+#  endif
+# endif
+# ifdef HAVE_FEOF_UNLOCKED
+#  undef feof
+#  define feof(Stream) feof_unlocked (Stream)
+#  if defined (HAVE_DECL_FEOF_UNLOCKED) && !HAVE_DECL_FEOF_UNLOCKED
+extern int feof_unlocked (FILE *);
+#  endif
+# endif
+# ifdef HAVE_FILENO_UNLOCKED
+#  undef fileno
+#  define fileno(Stream) fileno_unlocked (Stream)
+#  if defined (HAVE_DECL_FILENO_UNLOCKED) && !HAVE_DECL_FILENO_UNLOCKED
+extern int fileno_unlocked (FILE *);
+#  endif
+# endif
+# ifdef HAVE_FFLUSH_UNLOCKED
+#  undef fflush
+#  define fflush(Stream) fflush_unlocked (Stream)
+#  if defined (HAVE_DECL_FFLUSH_UNLOCKED) && !HAVE_DECL_FFLUSH_UNLOCKED
+extern int fflush_unlocked (FILE *);
+#  endif
+# endif
+# ifdef HAVE_FGETC_UNLOCKED
+#  undef fgetc
+#  define fgetc(Stream) fgetc_unlocked (Stream)
+#  if defined (HAVE_DECL_FGETC_UNLOCKED) && !HAVE_DECL_FGETC_UNLOCKED
+extern int fgetc_unlocked (FILE *);
+#  endif
+# endif
+# ifdef HAVE_FGETS_UNLOCKED
+#  undef fgets
+#  define fgets(S, n, Stream) fgets_unlocked (S, n, Stream)
+#  if defined (HAVE_DECL_FGETS_UNLOCKED) && !HAVE_DECL_FGETS_UNLOCKED
+extern char *fgets_unlocked (char *, int, FILE *);
+#  endif
+# endif
+# ifdef HAVE_FPUTS_UNLOCKED
+#  undef fputs
+#  define fputs(String, Stream) fputs_unlocked (String, Stream)
+#  if defined (HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED
+extern int fputs_unlocked (const char *, FILE *);
+#  endif
+# endif
+# ifdef HAVE_FERROR_UNLOCKED
+#  undef ferror
+#  define ferror(Stream) ferror_unlocked (Stream)
+#  if defined (HAVE_DECL_FERROR_UNLOCKED) && !HAVE_DECL_FERROR_UNLOCKED
+extern int ferror_unlocked (FILE *);
+#  endif
+# endif
+# ifdef HAVE_FREAD_UNLOCKED
+#  undef fread
+#  define fread(Ptr, Size, N, Stream) fread_unlocked (Ptr, Size, N, Stream)
+#  if defined (HAVE_DECL_FREAD_UNLOCKED) && !HAVE_DECL_FREAD_UNLOCKED
+extern size_t fread_unlocked (void *, size_t, size_t, FILE *);
+#  endif
+# endif
+# ifdef HAVE_FWRITE_UNLOCKED
+#  undef fwrite
+#  define fwrite(Ptr, Size, N, Stream) fwrite_unlocked (Ptr, Size, N, Stream)
+#  if defined (HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED
+extern size_t fwrite_unlocked (const void *, size_t, size_t, FILE *);
+#  endif
+# endif
+# ifdef HAVE_FPRINTF_UNLOCKED
+#  undef fprintf
+/* We can't use a function-like macro here because we don't know if
+   we have varargs macros.  */
+#  define fprintf fprintf_unlocked
+#  if defined (HAVE_DECL_FPRINTF_UNLOCKED) && !HAVE_DECL_FPRINTF_UNLOCKED
+extern int fprintf_unlocked (FILE *, const char *, ...);
+#  endif
+# endif
+
+#endif
+
+/* ??? Glibc's fwrite/fread_unlocked macros cause
+   "warning: signed and unsigned type in conditional expression".  */
+#undef fread_unlocked
+#undef fwrite_unlocked
+
+#include <sys/types.h>
+#include <errno.h>
+
+#if !defined (errno) && defined (HAVE_DECL_ERRNO) && !HAVE_DECL_ERRNO
+extern int errno;
+#endif
+
+/* Some of glibc's string inlines cause warnings.  Plus we'd rather
+   rely on (and therefore test) GCC's string builtins.  */
+#define __NO_STRING_INLINES
+
+#ifdef STRING_WITH_STRINGS
+# include <string.h>
+# include <strings.h>
+#else
+# ifdef HAVE_STRING_H
+#  include <string.h>
+# else
+#  ifdef HAVE_STRINGS_H
+#   include <strings.h>
+#  endif
+# endif
+#endif
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+/* Infrastructure for defining missing _MAX and _MIN macros.  Note that
+   macros defined with these cannot be used in #if.  */
+
+/* The extra casts work around common compiler bugs.  */
+#define INTTYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+/* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
+   It is necessary at least when t == time_t.  */
+#define INTTYPE_MINIMUM(t) ((t) (INTTYPE_SIGNED (t) \
+                             ? ~ (t) 0 << (sizeof(t) * CHAR_BIT - 1) : (t) 0))
+#define INTTYPE_MAXIMUM(t) ((t) (~ (t) 0 - INTTYPE_MINIMUM (t)))
+
+/* Use that infrastructure to provide a few constants.  */
+#ifndef UCHAR_MAX
+# define UCHAR_MAX INTTYPE_MAXIMUM (unsigned char)
+#endif
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  ifdef HAVE_TIME_H
+#   include <time.h>
+#  endif
+# endif
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#else
+# ifdef HAVE_SYS_FILE_H
+#  include <sys/file.h>
+# endif
+#endif
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#ifdef HAVE_LANGINFO_CODESET
+# include <langinfo.h>
+#endif
+
+#ifndef HAVE_SETLOCALE
+# define setlocale(category, locale) (locale)
+#endif
+
+#ifdef ENABLE_NLS
+#include <libintl.h>
+#else
+/* Stubs.  */
+# undef dgettext
+# define dgettext(package, msgid) (msgid)
+#endif
+
+#ifndef _
+# define _(msgid) dgettext (PACKAGE, msgid)
+#endif
+
+#ifndef N_
+# define N_(msgid) msgid
+#endif
+
+/* Some systems define these in, e.g., param.h.  We undefine these names
+   here to avoid the warnings.  We prefer to use our definitions since we
+   know they are correct.  */
+
+#undef MIN
+#undef MAX
+#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+
+/* The HAVE_DECL_* macros are three-state, undefined, 0 or 1.  If they
+   are defined to 0 then we must provide the relevant declaration
+   here.  These checks will be in the undefined state while configure
+   is running so be careful to test "defined (HAVE_DECL_*)".  */
+
+#if defined (HAVE_DECL_ABORT) && !HAVE_DECL_ABORT
+extern void abort (void);
+#endif
+
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+/* Test if something is a normal file.  */
+#ifndef S_ISREG
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+
+/* Test if something is a directory.  */
+#ifndef S_ISDIR
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+
+/* Test if something is a character special file.  */
+#ifndef S_ISCHR
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#endif
+
+/* Test if something is a block special file.  */
+#ifndef S_ISBLK
+#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#endif
+
+/* Test if something is a socket.  */
+#ifndef S_ISSOCK
+# ifdef S_IFSOCK
+#   define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+# else
+#   define S_ISSOCK(m) 0
+# endif
+#endif
+
+/* Test if something is a FIFO.  */
+#ifndef S_ISFIFO
+# ifdef S_IFIFO
+#  define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+# else
+#  define S_ISFIFO(m) 0
+# endif
+#endif
+
+/* Approximate O_NOCTTY and O_BINARY.  */
+#ifndef O_NOCTTY
+#define O_NOCTTY 0
+#endif
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+/* Filename handling macros.  */
+#include "filenames.h"
+
+/* Get libiberty declarations.  */
+#include "libiberty.h"
+#if defined(__APPLE__) && defined(__MACH__)
+#include <libiberty/safe-ctype.h>
+#else
+#include <safe-ctype.h>
+#endif
+
+/* 1 if we have C99 designated initializers.
+
+   ??? C99 designated initializers are not supported by most C++
+   compilers, including G++.  -- gdr, 2005-05-18  */
+#if !defined(HAVE_DESIGNATED_INITIALIZERS)
+#if defined(__APPLE__) && (__MACH__)
+#define HAVE_DESIGNATED_INITIALIZERS 0
+#else
+#define HAVE_DESIGNATED_INITIALIZERS \
+  ((!defined(__cplusplus) && (GCC_VERSION >= 2007)) \
+   || (__STDC_VERSION__ >= 199901L))
+#endif
+#endif
+
+/* Be conservative and only use enum bitfields with GCC.
+   FIXME: provide a complete autoconf test for buggy enum bitfields.  */
+
+#if (GCC_VERSION > 2000)
+#define ENUM_BITFIELD(TYPE) __extension__ enum TYPE
+#else
+#define ENUM_BITFIELD(TYPE) unsigned int
+#endif
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER)
+#endif
+
+/* __builtin_expect(A, B) evaluates to A, but notifies the compiler that
+   the most likely value of A is B.  This feature was added at some point
+   between 2.95 and 3.0.  Let's use 3.0 as the lower bound for now.  */
+#if (GCC_VERSION < 3000)
+#define __builtin_expect(a, b) (a)
+#endif
+
+/* Provide a fake boolean type.  We make no attempt to use the
+   C99 _Bool, as it may not be available in the bootstrap compiler,
+   and even if it is, it is liable to be buggy.
+   This must be after all inclusion of system headers, as some of
+   them will mess us up.  */
+#undef bool
+#undef true
+#undef false
+#undef TRUE
+#undef FALSE
+
+#ifndef __cplusplus
+#define bool unsigned char
+#endif
+#define true 1
+#define false 0
+
+/* Some compilers do not allow the use of unsigned char in bitfields.  */
+#define BOOL_BITFIELD unsigned int
+
+/* Poison identifiers we do not want to use.  */
+#if (GCC_VERSION >= 3000)
+#undef calloc
+#undef strdup
+#undef malloc
+#undef realloc
+ #pragma GCC poison calloc strdup
+ #pragma GCC poison malloc realloc
+
+/* Libiberty macros that are no longer used in GCC.  */
+#undef ANSI_PROTOTYPES
+#undef PTR_CONST
+#undef LONG_DOUBLE
+#undef VPARAMS
+#undef VA_OPEN
+#undef VA_FIXEDARG
+#undef VA_CLOSE
+#undef VA_START
+ #pragma GCC poison ANSI_PROTOTYPES PTR_CONST LONG_DOUBLE VPARAMS VA_OPEN \
+  VA_FIXEDARG VA_CLOSE VA_START
+
+/* Note: not all uses of the `index' token (e.g. variable names and
+   structure members) have been eliminated.  */
+#undef bcopy
+#undef bzero
+#undef bcmp
+#undef rindex
+ #pragma GCC poison bcopy bzero bcmp rindex
+
+#endif /* GCC >= 3.0 */
+
+/* SDCC specific */
+#include "sdcpp.h"
+
+#endif /* ! LIBCPP_SYSTEM_H */
diff --git a/support/cpp2/libcpp/traditional.c b/support/cpp2/libcpp/traditional.c
new file mode 100644 (file)
index 0000000..a543348
--- /dev/null
@@ -0,0 +1,1113 @@
+/* CPP Library - traditional lexical analysis and macro expansion.
+   Copyright (C) 2002, 2004, 2005 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "cpplib.h"
+#include "internal.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 lex.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 = XRESIZEVEC (unsigned char, 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;
+      macro->traditional = 1;
+      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->traditional = 1;
+      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;
+      macro->traditional = 1;
+
+      /* Write out the block information.  */
+      block->text_len = len;
+      block->arg_index = arg_index;
+      memcpy (block->text, pfile->out.base, len);
+
+      /* Lex the rest into the start of the output buffer.  */
+      pfile->out.cur = pfile->out.base;
+
+      macro->count += blen;
+
+      /* If we've finished, commit the memory.  */
+      if (arg_index == 0)
+       BUFF_FRONT (pfile->a_buff) += macro->count;
+    }
+}
+
+/* Analyze and save the replacement text of a macro.  Returns true on
+   success.  */
+bool
+_cpp_create_trad_definition (cpp_reader *pfile, cpp_macro *macro)
+{
+  const uchar *cur;
+  uchar *limit;
+  cpp_context *context = pfile->context;
+
+  /* The context has not been set up for command line defines, and CUR
+     has not been updated for the macro name for in-file defines.  */
+  pfile->out.cur = pfile->out.base;
+  CUR (context) = pfile->buffer->cur;
+  RLIMIT (context) = pfile->buffer->rlimit;
+  check_output_buffer (pfile, RLIMIT (context) - CUR (context));
+
+  /* Is this a function-like macro?  */
+  if (* CUR (context) == '(')
+    {
+      bool ok = scan_parameters (pfile, macro);
+
+      /* Remember the params so we can clear NODE_MACRO_ARG flags.  */
+      macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
+
+      /* Setting macro to NULL indicates an error occurred, and
+        prevents unnecessary work in _cpp_scan_out_logical_line.  */
+      if (!ok)
+       macro = NULL;
+      else
+       {
+         BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc];
+         macro->fun_like = 1;
+       }
+    }
+
+  /* Skip leading whitespace in the replacement text.  */
+  pfile->buffer->cur
+    = skip_whitespace (pfile, CUR (context),
+                      CPP_OPTION (pfile, discard_comments_in_macro_exp));
+
+  pfile->state.prevent_expansion++;
+  _cpp_scan_out_logical_line (pfile, macro);
+  pfile->state.prevent_expansion--;
+
+  if (!macro)
+    return false;
+
+  /* Skip trailing white space.  */
+  cur = pfile->out.base;
+  limit = pfile->out.cur;
+  while (limit > cur && is_space (limit[-1]))
+    limit--;
+  pfile->out.cur = limit;
+  save_replacement_text (pfile, macro, 0);
+
+  return true;
+}
+
+/* Copy SRC of length LEN to DEST, but convert all contiguous
+   whitespace to a single space, provided it is not in quotes.  The
+   quote currently in effect is pointed to by PQUOTE, and is updated
+   by the function.  Returns the number of bytes copied.  */
+static size_t
+canonicalize_text (uchar *dest, const uchar *src, size_t len, uchar *pquote)
+{
+  uchar *orig_dest = dest;
+  uchar quote = *pquote;
+
+  while (len)
+    {
+      if (is_space (*src) && !quote)
+       {
+         do
+           src++, len--;
+         while (len && is_space (*src));
+         *dest++ = ' ';
+       }
+      else
+       {
+         if (*src == '\'' || *src == '"')
+           {
+             if (!quote)
+               quote = *src;
+             else if (quote == *src)
+               quote = 0;
+           }
+         *dest++ = *src++, len--;
+       }
+    }
+
+  *pquote = quote;
+  return dest - orig_dest;
+}
+
+/* Returns true if MACRO1 and MACRO2 have expansions different other
+   than in the form of their whitespace.  */
+bool
+_cpp_expansions_different_trad (const cpp_macro *macro1,
+                               const cpp_macro *macro2)
+{
+  uchar *p1 = XNEWVEC (uchar, macro1->count + macro2->count);
+  uchar *p2 = p1 + macro1->count;
+  uchar quote1 = 0, quote2 = 0;
+  bool mismatch;
+  size_t len1, len2;
+
+  if (macro1->paramc > 0)
+    {
+      const uchar *exp1 = macro1->exp.text, *exp2 = macro2->exp.text;
+
+      mismatch = true;
+      for (;;)
+       {
+         struct block *b1 = (struct block *) exp1;
+         struct block *b2 = (struct block *) exp2;
+
+         if (b1->arg_index != b2->arg_index)
+           break;
+
+         len1 = canonicalize_text (p1, b1->text, b1->text_len, &quote1);
+         len2 = canonicalize_text (p2, b2->text, b2->text_len, &quote2);
+         if (len1 != len2 || memcmp (p1, p2, len1))
+           break;
+         if (b1->arg_index == 0)
+           {
+             mismatch = false;
+             break;
+           }
+         exp1 += BLOCK_LEN (b1->text_len);
+         exp2 += BLOCK_LEN (b2->text_len);
+       }
+    }
+  else
+    {
+      len1 = canonicalize_text (p1, macro1->exp.text, macro1->count, &quote1);
+      len2 = canonicalize_text (p2, macro2->exp.text, macro2->count, &quote2);
+      mismatch = (len1 != len2 || memcmp (p1, p2, len1));
+    }
+
+  free (p1);
+  return mismatch;
+}
diff --git a/support/cpp2/libcpp/ucnid.h b/support/cpp2/libcpp/ucnid.h
new file mode 100644 (file)
index 0000000..7323dcc
--- /dev/null
@@ -0,0 +1,801 @@
+/* Unicode characters and various properties.
+   Copyright (C) 2003, 2005 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+   Copyright (C) 1991-2005 Unicode, Inc.  All rights reserved.
+   Distributed under the Terms of Use in
+   http://www.unicode.org/copyright.html.
+
+   Permission is hereby granted, free of charge, to any person
+   obtaining a copy of the Unicode data files and any associated
+   documentation (the "Data Files") or Unicode software and any
+   associated documentation (the "Software") to deal in the Data Files
+   or Software without restriction, including without limitation the
+   rights to use, copy, modify, merge, publish, distribute, and/or
+   sell copies of the Data Files or Software, and to permit persons to
+   whom the Data Files or Software are furnished to do so, provided
+   that (a) the above copyright notice(s) and this permission notice
+   appear with all copies of the Data Files or Software, (b) both the
+   above copyright notice(s) and this permission notice appear in
+   associated documentation, and (c) there is clear notice in each
+   modified Data File or in the Software as well as in the
+   documentation associated with the Data File(s) or Software that the
+   data or software has been modified.
+
+   THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY
+   OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+   WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE
+   COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR
+   ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY
+   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+   WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+   ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+   OF THE DATA FILES OR SOFTWARE.
+
+   Except as contained in this notice, the name of a copyright holder
+   shall not be used in advertising or otherwise to promote the sale,
+   use or other dealings in these Data Files or Software without prior
+   written authorization of the copyright holder.  */
+
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x00a9 },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x00aa },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x00b4 },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x00b5 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x00b6 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x00b7 },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0x00b9 },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x00ba },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x00bf },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x00d6 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x00d7 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x00f6 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x00f7 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0131 },
+{ C99|  0|CXX|CID|NFC|  0|  0,   0, 0x0133 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x013e },
+{ C99|  0|CXX|CID|NFC|  0|  0,   0, 0x0140 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0148 },
+{ C99|  0|CXX|CID|NFC|  0|  0,   0, 0x0149 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x017e },
+{ C99|  0|CXX|CID|NFC|  0|  0,   0, 0x017f },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x01c3 },
+{ C99|  0|CXX|CID|NFC|  0|  0,   0, 0x01cc },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x01f0 },
+{ C99|  0|CXX|CID|NFC|  0|  0,   0, 0x01f3 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x01f5 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x01f9 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0217 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x024f },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x02a8 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x02af },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x02b8 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x02ba },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x02bb },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x02bc },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x02c1 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x02cf },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x02d1 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x02df },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x02e4 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0379 },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x037a },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0383 },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0x0384 },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0x0385 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0386 },
+{   0|  0|  0|CID|  0|  0|  0,   0, 0x0387 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x038a },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x038b },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x038c },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x038d },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x03a1 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x03a2 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x03ce },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x03cf },
+{ C99|  0|CXX|CID|NFC|  0|  0,   0, 0x03d6 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x03d9 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x03da },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x03db },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x03dc },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x03dd },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x03de },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x03df },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x03e0 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x03e1 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x03ef },
+{ C99|  0|CXX|CID|NFC|  0|  0,   0, 0x03f2 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x03f3 },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0x0400 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x040c },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0x040d },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x040e },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x044f },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0450 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x045c },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x045d },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0481 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x048f },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x04c4 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x04c6 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x04c8 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x04ca },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x04cc },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x04cf },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x04eb },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x04ed },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x04f5 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x04f7 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x04f9 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0530 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0556 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0558 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0559 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0560 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0586 },
+{ C99|  0|CXX|CID|NFC|  0|  0,   0, 0x0587 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x05af },
+{ C99|  0|  0|CID|NFC|NKC|  0,  10, 0x05b0 },
+{ C99|  0|  0|CID|NFC|NKC|  0,  11, 0x05b1 },
+{ C99|  0|  0|CID|NFC|NKC|  0,  12, 0x05b2 },
+{ C99|  0|  0|CID|NFC|NKC|  0,  13, 0x05b3 },
+{ C99|  0|  0|CID|NFC|NKC|  0,  14, 0x05b4 },
+{ C99|  0|  0|CID|NFC|NKC|  0,  15, 0x05b5 },
+{ C99|  0|  0|CID|NFC|NKC|  0,  16, 0x05b6 },
+{ C99|  0|  0|CID|NFC|NKC|  0,  17, 0x05b7 },
+{ C99|  0|  0|CID|NFC|NKC|  0,  18, 0x05b8 },
+{ C99|  0|  0|CID|NFC|NKC|  0,  19, 0x05b9 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x05ba },
+{ C99|  0|  0|CID|NFC|NKC|  0,  20, 0x05bb },
+{ C99|  0|  0|CID|NFC|NKC|  0,  21, 0x05bc },
+{ C99|  0|  0|CID|NFC|NKC|  0,  22, 0x05bd },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x05be },
+{ C99|  0|  0|CID|NFC|NKC|  0,  23, 0x05bf },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x05c0 },
+{ C99|  0|  0|CID|NFC|NKC|  0,  24, 0x05c1 },
+{ C99|  0|  0|CID|NFC|NKC|  0,  25, 0x05c2 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x05cf },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x05ea },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x05ef },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x05f2 },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0x05f4 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0620 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x063a },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x063f },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x064a },
+{ C99|  0|CXX|CID|NFC|NKC|  0,  27, 0x064b },
+{ C99|  0|CXX|CID|NFC|NKC|  0,  28, 0x064c },
+{ C99|  0|CXX|CID|NFC|NKC|  0,  29, 0x064d },
+{ C99|  0|CXX|CID|NFC|NKC|  0,  30, 0x064e },
+{ C99|  0|CXX|CID|NFC|NKC|  0,  31, 0x064f },
+{ C99|  0|CXX|CID|NFC|NKC|  0,  32, 0x0650 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,  33, 0x0651 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,  34, 0x0652 },
+{   0|  0|  0|CID|NFC|NKC|CTX,   0, 0x065f },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x0669 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x066f },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0674 },
+{ C99|  0|CXX|CID|NFC|  0|  0,   0, 0x0678 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x06b7 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x06b9 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x06be },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x06bf },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x06ce },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x06cf },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x06d5 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 230, 0x06d6 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 230, 0x06d7 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 230, 0x06d8 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 230, 0x06d9 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 230, 0x06da },
+{ C99|  0|  0|CID|NFC|NKC|  0, 230, 0x06db },
+{ C99|  0|  0|CID|NFC|NKC|  0, 230, 0x06dc },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x06e4 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x06e6 },
+{ C99|  0|CXX|CID|NFC|NKC|  0, 230, 0x06e7 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 230, 0x06e8 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x06e9 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 220, 0x06ea },
+{ C99|  0|  0|CID|NFC|NKC|  0, 230, 0x06eb },
+{ C99|  0|  0|CID|NFC|NKC|  0, 230, 0x06ec },
+{ C99|  0|  0|CID|NFC|NKC|  0, 220, 0x06ed },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x06ef },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x06f9 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0900 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0903 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0904 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0939 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x093c },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x094c },
+{ C99|  0|  0|CID|NFC|NKC|  0,   9, 0x094d },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x094f },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0950 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 230, 0x0951 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 220, 0x0952 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0957 },
+{ C99|  0|CXX|CID|  0|  0|  0,   0, 0x095f },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0962 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0963 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0965 },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x096f },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0980 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0983 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0984 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x098c },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x098e },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0990 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0992 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x09a8 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x09a9 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x09b0 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x09b1 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x09b2 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x09b5 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x09b9 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x09bd },
+{ C99|  0|  0|CID|NFC|NKC|CTX,   0, 0x09be },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x09c4 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x09c6 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x09c8 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x09ca },
+{ C99|  0|  0|  0|NFC|NKC|  0,   0, 0x09cb },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x09cc },
+{ C99|  0|  0|CID|NFC|NKC|  0,   9, 0x09cd },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x09db },
+{ C99|  0|CXX|CID|  0|  0|  0,   0, 0x09dd },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x09de },
+{ C99|  0|CXX|CID|  0|  0|  0,   0, 0x09df },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x09e1 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x09e3 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x09e5 },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x09ef },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x09f1 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a01 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0a02 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a04 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0a0a },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a0e },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0a10 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a12 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0a28 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a29 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0a30 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a31 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0a32 },
+{ C99|  0|CXX|CID|  0|  0|  0,   0, 0x0a33 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a34 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0a35 },
+{ C99|  0|CXX|CID|  0|  0|  0,   0, 0x0a36 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a37 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0a39 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a3d },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0a42 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a46 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0a48 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a4a },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0a4c },
+{ C99|  0|  0|CID|NFC|NKC|  0,   9, 0x0a4d },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a58 },
+{ C99|  0|CXX|CID|  0|  0|  0,   0, 0x0a5b },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0a5c },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a5d },
+{ C99|  0|CXX|CID|  0|  0|  0,   0, 0x0a5e },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a65 },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x0a6f },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a73 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0a74 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a80 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0a83 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a84 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0a8b },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a8c },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0a8d },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a8e },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0a91 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0a92 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0aa8 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0aa9 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0ab0 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ab1 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0ab3 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ab4 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0ab9 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0abc },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0ac5 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ac6 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0ac9 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0aca },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0acc },
+{ C99|  0|  0|CID|NFC|NKC|  0,   9, 0x0acd },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0acf },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0ad0 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0adf },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0ae0 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ae5 },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x0aef },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b00 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0b03 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b04 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0b0c },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b0e },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0b10 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b12 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0b28 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b29 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0b30 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b31 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0b33 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b35 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0b39 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b3c },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0b3d },
+{ C99|  0|  0|CID|NFC|NKC|CTX,   0, 0x0b3e },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0b43 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b46 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0b48 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b4a },
+{ C99|  0|  0|  0|NFC|NKC|  0,   0, 0x0b4b },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0b4c },
+{ C99|  0|  0|CID|NFC|NKC|  0,   9, 0x0b4d },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b5b },
+{ C99|  0|CXX|CID|  0|  0|  0,   0, 0x0b5d },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b5e },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0b61 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b65 },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x0b6f },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b81 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0b83 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b84 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0b8a },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b8d },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0b90 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b91 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0b95 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b98 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0b9a },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b9b },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0b9c },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0b9d },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0b9f },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ba2 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0ba4 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ba7 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0baa },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0bad },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0bb5 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0bb6 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0bb9 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0bbd },
+{ C99|  0|  0|CID|NFC|NKC|CTX,   0, 0x0bbe },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0bc2 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0bc5 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0bc8 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0bc9 },
+{ C99|  0|  0|  0|NFC|NKC|  0,   0, 0x0bcb },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0bcc },
+{ C99|  0|  0|CID|NFC|NKC|  0,   9, 0x0bcd },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0be6 },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x0bef },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0c00 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0c03 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0c04 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0c0c },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0c0d },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0c10 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0c11 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0c28 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0c29 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0c33 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0c34 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0c39 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0c3d },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0c44 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0c45 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0c48 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0c49 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0c4c },
+{ C99|  0|  0|CID|NFC|NKC|  0,   9, 0x0c4d },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0c5f },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0c61 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0c65 },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x0c6f },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0c81 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0c83 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0c84 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0c8c },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0c8d },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0c90 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0c91 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0ca8 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ca9 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0cb3 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0cb4 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0cb9 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0cbd },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0cc1 },
+{ C99|  0|  0|CID|NFC|NKC|CTX,   0, 0x0cc2 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0cc4 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0cc5 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0cc8 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0cc9 },
+{ C99|  0|  0|  0|NFC|NKC|  0,   0, 0x0cca },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0ccc },
+{ C99|  0|  0|CID|NFC|NKC|  0,   9, 0x0ccd },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0cdd },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0cde },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0cdf },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0ce1 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ce5 },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x0cef },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0d01 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0d03 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0d04 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0d0c },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0d0d },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0d10 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0d11 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0d28 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0d29 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0d39 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0d3d },
+{ C99|  0|  0|CID|NFC|NKC|CTX,   0, 0x0d3e },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0d43 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0d45 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0d48 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0d49 },
+{ C99|  0|  0|  0|NFC|NKC|  0,   0, 0x0d4b },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0d4c },
+{ C99|  0|  0|CID|NFC|NKC|  0,   9, 0x0d4d },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0d5f },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0d61 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0d65 },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x0d6f },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0e00 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0e30 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0e31 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0e32 },
+{ C99|  0|CXX|CID|NFC|  0|  0,   0, 0x0e33 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0e37 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 103, 0x0e38 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 103, 0x0e39 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   9, 0x0e3a },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0e3f },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0e46 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0e47 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 107, 0x0e48 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 107, 0x0e49 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0e4e },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0x0e4f },
+{ C99|DIG|CXX|CID|NFC|NKC|  0,   0, 0x0e59 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0e5b },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0e80 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0e82 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0e83 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0e84 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0e86 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0e88 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0e89 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0e8a },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0e8c },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0e8d },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0e93 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0e97 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0e98 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0e9f },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ea0 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0ea3 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ea4 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0ea5 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ea6 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0ea7 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ea9 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0eab },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0eac },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0eae },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0x0eaf },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0eb0 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0eb1 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0eb2 },
+{ C99|  0|CXX|CID|NFC|  0|  0,   0, 0x0eb3 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0eb7 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 118, 0x0eb8 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 118, 0x0eb9 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0eba },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0ebc },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0ebd },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ebf },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0ec4 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ec5 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x0ec6 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ec7 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 122, 0x0ec8 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 122, 0x0ec9 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 122, 0x0eca },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0ecd },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0ecf },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x0ed9 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0edb },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x0edd },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0eff },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0f00 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0f17 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 220, 0x0f18 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 220, 0x0f19 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0f1f },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x0f33 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0f34 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 220, 0x0f35 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0f36 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 220, 0x0f37 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0f38 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 216, 0x0f39 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0f3d },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0f42 },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0f43 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0f47 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0f48 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0f4c },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0f4d },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0f51 },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0f52 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0f56 },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0f57 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0f5b },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0f5c },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0f68 },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0f69 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0f70 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 129, 0x0f71 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 130, 0x0f72 },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0f73 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 132, 0x0f74 },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0f76 },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x0f77 },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0f78 },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x0f79 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 130, 0x0f7a },
+{ C99|  0|  0|CID|NFC|NKC|  0, 130, 0x0f7b },
+{ C99|  0|  0|CID|NFC|NKC|  0, 130, 0x0f7c },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0f7f },
+{ C99|  0|  0|CID|NFC|NKC|  0, 130, 0x0f80 },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0f81 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 230, 0x0f82 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 230, 0x0f83 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   9, 0x0f84 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0f85 },
+{ C99|  0|  0|CID|NFC|NKC|  0, 230, 0x0f86 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0f8b },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0f8f },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0f92 },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0f93 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0f95 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0f96 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0f97 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0f98 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0f9c },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0f9d },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0fa1 },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0fa2 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0fa6 },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0fa7 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0fab },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0fac },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0fad },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0fb0 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x0fb7 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x0fb8 },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x0fb9 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x109f },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x10c5 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x10cf },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x10f6 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x10ff },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0x1159 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1160 },
+{   0|  0|CXX|CID|NFC|NKC|CTX,   0, 0x1175 },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0x11a2 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x11a7 },
+{   0|  0|CXX|CID|NFC|NKC|CTX,   0, 0x11c2 },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0x11f9 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1dff },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1e99 },
+{ C99|  0|CXX|CID|NFC|  0|  0,   0, 0x1e9a },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x1e9b },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1e9f },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1ef9 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1eff },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1f15 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1f17 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1f1d },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1f1f },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1f45 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1f47 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1f4d },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1f4f },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1f57 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1f58 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1f59 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1f5a },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1f5b },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1f5c },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1f5d },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1f5e },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1f70 },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1f71 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1f72 },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1f73 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1f74 },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1f75 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1f76 },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1f77 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1f78 },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1f79 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1f7a },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1f7b },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1f7c },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1f7d },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1f7f },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1fb4 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1fb5 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1fba },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1fbb },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1fbc },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0x1fbd },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x1fbe },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0x1fc1 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1fc4 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1fc5 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1fc8 },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1fc9 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1fca },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1fcb },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1fcc },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0x1fcf },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1fd2 },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1fd3 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1fd5 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1fda },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1fdb },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1fdf },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1fe2 },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1fe3 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1fea },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1feb },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1fec },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0x1ff1 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1ff4 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x1ff5 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1ff8 },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1ff9 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1ffa },
+{ C99|  0|CXX|  0|  0|  0|  0,   0, 0x1ffb },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x1ffc },
+{   0|  0|  0|CID|  0|  0|  0,   0, 0x203e },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x2040 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x207e },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x207f },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0x2101 },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x2102 },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0x2106 },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x2107 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x2109 },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x2113 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x2114 },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x2115 },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0x2117 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x2118 },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x211d },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x2123 },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x2124 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x2125 },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x2126 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x2127 },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x2128 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x2129 },
+{ C99|  0|  0|CID|  0|  0|  0,   0, 0x212a },
+{ C99|  0|  0|  0|  0|  0|  0,   0, 0x212b },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x212d },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x212e },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x2131 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x2132 },
+{ C99|  0|  0|CID|NFC|  0|  0,   0, 0x2138 },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0x215f },
+{ C99|DIG|  0|CID|NFC|  0|  0,   0, 0x217f },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x2182 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x3004 },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0x3006 },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x3007 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x3020 },
+{ C99|DIG|  0|CID|NFC|NKC|  0,   0, 0x3029 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x3040 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x3093 },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0x3094 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x309a },
+{ C99|  0|CXX|CID|NFC|  0|  0,   0, 0x309c },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0x309e },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0x30a0 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x30f6 },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0x30fa },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x30fc },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0x30fe },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0x3104 },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x312c },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0x4dff },
+{ C99|  0|CXX|CID|NFC|NKC|  0,   0, 0x9fa5 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xabff },
+{ C99|  0|  0|CID|NFC|NKC|  0,   0, 0xd7a3 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xf8ff },
+{   0|  0|CXX|  0|  0|  0|  0,   0, 0xfa0d },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0xfa0f },
+{   0|  0|CXX|  0|  0|  0|  0,   0, 0xfa10 },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0xfa11 },
+{   0|  0|CXX|  0|  0|  0|  0,   0, 0xfa12 },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0xfa14 },
+{   0|  0|CXX|  0|  0|  0|  0,   0, 0xfa1e },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0xfa1f },
+{   0|  0|CXX|  0|  0|  0|  0,   0, 0xfa20 },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0xfa21 },
+{   0|  0|CXX|  0|  0|  0|  0,   0, 0xfa22 },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0xfa24 },
+{   0|  0|CXX|  0|  0|  0|  0,   0, 0xfa26 },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0xfa29 },
+{   0|  0|CXX|  0|  0|  0|  0,   0, 0xfa2d },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xfb1e },
+{   0|  0|CXX|CID|  0|  0|  0,   0, 0xfb1f },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xfb29 },
+{   0|  0|CXX|CID|  0|  0|  0,   0, 0xfb36 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xfb37 },
+{   0|  0|CXX|CID|  0|  0|  0,   0, 0xfb3c },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xfb3d },
+{   0|  0|CXX|CID|  0|  0|  0,   0, 0xfb3e },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xfb3f },
+{   0|  0|CXX|CID|  0|  0|  0,   0, 0xfb41 },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0xfb42 },
+{   0|  0|CXX|CID|  0|  0|  0,   0, 0xfb44 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xfb45 },
+{   0|  0|CXX|CID|  0|  0|  0,   0, 0xfb4e },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xfbb1 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xfbd2 },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xfd3d },
+{   0|  0|CXX|CID|NFC|NKC|  0,   0, 0xfd3f },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xfd4f },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xfd8f },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xfd91 },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xfdc7 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xfdef },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xfdfb },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0xfe6f },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xfe72 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xfe73 },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xfe74 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xfe75 },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xfefc },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xff20 },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xff3a },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0xff40 },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xff5a },
+{   0|  0|  0|CID|NFC|  0|  0,   0, 0xff65 },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xffbe },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xffc1 },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xffc7 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xffc9 },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xffcf },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xffd1 },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xffd7 },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xffd9 },
+{   0|  0|CXX|CID|NFC|  0|  0,   0, 0xffdc },
+{   0|  0|  0|CID|NFC|NKC|  0,   0, 0xffff },
diff --git a/support/cpp2/libiberty/fopen_unlocked.c b/support/cpp2/libiberty/fopen_unlocked.c
new file mode 100644 (file)
index 0000000..3c3cefe
--- /dev/null
@@ -0,0 +1,126 @@
+/* Implement fopen_unlocked and related functions.
+   Copyright (C) 2005 Free Software Foundation, Inc.
+   Written by Kaveh R. Ghazi <ghazi@caip.rutgers.edu>.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+/*
+
+@deftypefn Extension void unlock_stream (FILE * @var{stream})
+
+If the OS supports it, ensure that the supplied stream is setup to
+avoid any multi-threaded locking.  Otherwise leave the @code{FILE}
+pointer unchanged.  If the @var{stream} is @code{NULL} do nothing.
+
+@end deftypefn
+
+@deftypefn Extension void unlock_std_streams (void)
+
+If the OS supports it, ensure that the standard I/O streams,
+@code{stdin}, @code{stdout} and @code{stderr} are setup to avoid any
+multi-threaded locking.  Otherwise do nothing.
+
+@end deftypefn
+
+@deftypefn Extension {FILE *} fopen_unlocked (const char *@var{path}, const char * @var{mode})
+
+Opens and returns a @code{FILE} pointer via @code{fopen}.  If the
+operating system supports it, ensure that the stream is setup to avoid
+any multi-threaded locking.  Otherwise return the @code{FILE} pointer
+unchanged.
+
+@end deftypefn
+
+@deftypefn Extension {FILE *} fdopen_unlocked (int @var{fildes}, const char * @var{mode})
+
+Opens and returns a @code{FILE} pointer via @code{fdopen}.  If the
+operating system supports it, ensure that the stream is setup to avoid
+any multi-threaded locking.  Otherwise return the @code{FILE} pointer
+unchanged.
+
+@end deftypefn
+
+@deftypefn Extension {FILE *} freopen_unlocked (const char * @var{path}, const char * @var{mode}, FILE * @var{stream})
+
+Opens and returns a @code{FILE} pointer via @code{freopen}.  If the
+operating system supports it, ensure that the stream is setup to avoid
+any multi-threaded locking.  Otherwise return the @code{FILE} pointer
+unchanged.
+
+@end deftypefn
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDIO_EXT_H
+#include <stdio_ext.h>
+#endif
+
+#include "libiberty.h"
+
+/* This is an inline helper function to consolidate attempts to unlock
+   a stream.  */
+
+static inline void
+unlock_1 (FILE *const fp ATTRIBUTE_UNUSED)
+{
+#if defined(HAVE___FSETLOCKING) && defined(FSETLOCKING_BYCALLER)
+  if (fp)
+    __fsetlocking (fp, FSETLOCKING_BYCALLER);
+#endif
+}
+
+void
+unlock_stream (FILE *fp)
+{
+  unlock_1 (fp);
+}
+
+void
+unlock_std_streams (void)
+{
+  unlock_1 (stdin);
+  unlock_1 (stdout);
+  unlock_1 (stderr);
+}
+
+FILE *
+fopen_unlocked (const char *path, const char *mode)            
+{
+  FILE *const fp = fopen (path, mode);
+  unlock_1 (fp);
+  return fp;
+}
+
+FILE *
+fdopen_unlocked (int fildes, const char *mode)
+{
+  FILE *const fp = fdopen (fildes, mode);
+  unlock_1 (fp);
+  return fp;
+}
+
+FILE *
+freopen_unlocked (const char *path, const char *mode, FILE *stream)
+{
+  FILE *const fp = freopen (path, mode, stream);
+  unlock_1 (fp);
+  return fp;
+}
diff --git a/support/cpp2/libiberty/hashtab.c b/support/cpp2/libiberty/hashtab.c
new file mode 100644 (file)
index 0000000..a5671a0
--- /dev/null
@@ -0,0 +1,934 @@
+/* An expandable hash tables datatype.  
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+   Free Software Foundation, Inc.
+   Contributed by Vladimir Makarov (vmakarov@cygnus.com).
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+/* This package implements basic hash table functionality.  It is possible
+   to search for an entry, create an entry and destroy an entry.
+
+   Elements in the table are generic pointers.
+
+   The size of the table is not fixed; if the occupancy of the table
+   grows too high the hash table will be expanded.
+
+   The abstract data implementation is based on generalized Algorithm D
+   from Knuth's book "The art of computer programming".  Hash table is
+   expanded by creation of new hash table and transferring elements from
+   the old table to the new table. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include <stdio.h>
+
+#include "libiberty.h"
+#include "ansidecl.h"
+#include "hashtab.h"
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+static unsigned int higher_prime_index (unsigned long);
+static hashval_t htab_mod_1 (hashval_t, hashval_t, hashval_t, int);
+static hashval_t htab_mod (hashval_t, htab_t);
+static hashval_t htab_mod_m2 (hashval_t, htab_t);
+static hashval_t hash_pointer (const void *);
+static int eq_pointer (const void *, const void *);
+static int htab_expand (htab_t);
+static PTR *find_empty_slot_for_expand (htab_t, hashval_t);
+
+/* At some point, we could make these be NULL, and modify the
+   hash-table routines to handle NULL specially; that would avoid
+   function-call overhead for the common case of hashing pointers.  */
+htab_hash htab_hash_pointer = hash_pointer;
+htab_eq htab_eq_pointer = eq_pointer;
+
+/* Table of primes and multiplicative inverses.
+
+   Note that these are not minimally reduced inverses.  Unlike when generating
+   code to divide by a constant, we want to be able to use the same algorithm
+   all the time.  All of these inverses (are implied to) have bit 32 set.
+
+   For the record, here's the function that computed the table; it's a 
+   vastly simplified version of the function of the same name from gcc.  */
+
+#if 0
+unsigned int
+ceil_log2 (unsigned int x)
+{
+  int i;
+  for (i = 31; i >= 0 ; --i)
+    if (x > (1u << i))
+      return i+1;
+  abort ();
+}
+
+unsigned int
+choose_multiplier (unsigned int d, unsigned int *mlp, unsigned char *shiftp)
+{
+  unsigned long long mhigh;
+  double nx;
+  int lgup, post_shift;
+  int pow, pow2;
+  int n = 32, precision = 32;
+
+  lgup = ceil_log2 (d);
+  pow = n + lgup;
+  pow2 = n + lgup - precision;
+
+  nx = ldexp (1.0, pow) + ldexp (1.0, pow2);
+  mhigh = nx / d;
+
+  *shiftp = lgup - 1;
+  *mlp = mhigh;
+  return mhigh >> 32;
+}
+#endif
+
+struct prime_ent
+{
+  hashval_t prime;
+  hashval_t inv;
+  hashval_t inv_m2;    /* inverse of prime-2 */
+  hashval_t shift;
+};
+
+static struct prime_ent const prime_tab[] = {
+  {          7, 0x24924925, 0x9999999b, 2 },
+  {         13, 0x3b13b13c, 0x745d1747, 3 },
+  {         31, 0x08421085, 0x1a7b9612, 4 },
+  {         61, 0x0c9714fc, 0x15b1e5f8, 5 },
+  {        127, 0x02040811, 0x0624dd30, 6 },
+  {        251, 0x05197f7e, 0x073260a5, 7 },
+  {        509, 0x01824366, 0x02864fc8, 8 },
+  {       1021, 0x00c0906d, 0x014191f7, 9 },
+  {       2039, 0x0121456f, 0x0161e69e, 10 },
+  {       4093, 0x00300902, 0x00501908, 11 },
+  {       8191, 0x00080041, 0x00180241, 12 },
+  {      16381, 0x000c0091, 0x00140191, 13 },
+  {      32749, 0x002605a5, 0x002a06e6, 14 },
+  {      65521, 0x000f00e2, 0x00110122, 15 },
+  {     131071, 0x00008001, 0x00018003, 16 },
+  {     262139, 0x00014002, 0x0001c004, 17 },
+  {     524287, 0x00002001, 0x00006001, 18 },
+  {    1048573, 0x00003001, 0x00005001, 19 },
+  {    2097143, 0x00004801, 0x00005801, 20 },
+  {    4194301, 0x00000c01, 0x00001401, 21 },
+  {    8388593, 0x00001e01, 0x00002201, 22 },
+  {   16777213, 0x00000301, 0x00000501, 23 },
+  {   33554393, 0x00001381, 0x00001481, 24 },
+  {   67108859, 0x00000141, 0x000001c1, 25 },
+  {  134217689, 0x000004e1, 0x00000521, 26 },
+  {  268435399, 0x00000391, 0x000003b1, 27 },
+  {  536870909, 0x00000019, 0x00000029, 28 },
+  { 1073741789, 0x0000008d, 0x00000095, 29 },
+  { 2147483647, 0x00000003, 0x00000007, 30 },
+  /* Avoid "decimal constant so large it is unsigned" for 4294967291.  */
+  { 0xfffffffb, 0x00000006, 0x00000008, 31 }
+};
+
+/* The following function returns an index into the above table of the
+   nearest prime number which is greater than N, and near a power of two. */
+
+static unsigned int
+higher_prime_index (unsigned long n)
+{
+  unsigned int low = 0;
+  unsigned int high = sizeof(prime_tab) / sizeof(prime_tab[0]);
+
+  while (low != high)
+    {
+      unsigned int mid = low + (high - low) / 2;
+      if (n > prime_tab[mid].prime)
+       low = mid + 1;
+      else
+       high = mid;
+    }
+
+  /* If we've run out of primes, abort.  */
+  if (n > prime_tab[low].prime)
+    {
+      fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
+      abort ();
+    }
+
+  return low;
+}
+
+/* Returns a hash code for P.  */
+
+static hashval_t
+hash_pointer (const PTR p)
+{
+  return (hashval_t) ((long)p >> 3);
+}
+
+/* Returns non-zero if P1 and P2 are equal.  */
+
+static int
+eq_pointer (const PTR p1, const PTR p2)
+{
+  return p1 == p2;
+}
+
+
+/* The parens around the function names in the next two definitions
+   are essential in order to prevent macro expansions of the name.
+   The bodies, however, are expanded as expected, so they are not
+   recursive definitions.  */
+
+/* Return the current size of given hash table.  */
+
+#define htab_size(htab)  ((htab)->size)
+
+size_t
+(htab_size) (htab_t htab)
+{
+  return htab_size (htab);
+}
+
+/* Return the current number of elements in given hash table. */
+
+#define htab_elements(htab)  ((htab)->n_elements - (htab)->n_deleted)
+
+size_t
+(htab_elements) (htab_t htab)
+{
+  return htab_elements (htab);
+}
+
+/* Return X % Y.  */
+
+static inline hashval_t
+htab_mod_1 (hashval_t x, hashval_t y, hashval_t inv, int shift)
+{
+  /* The multiplicative inverses computed above are for 32-bit types, and
+     requires that we be able to compute a highpart multiply.  */
+#ifdef UNSIGNED_64BIT_TYPE
+  __extension__ typedef UNSIGNED_64BIT_TYPE ull;
+  if (sizeof (hashval_t) * CHAR_BIT <= 32)
+    {
+      hashval_t t1, t2, t3, t4, q, r;
+
+      t1 = ((ull)x * inv) >> 32;
+      t2 = x - t1;
+      t3 = t2 >> 1;
+      t4 = t1 + t3;
+      q  = t4 >> shift;
+      r  = x - (q * y);
+
+      return r;
+    }
+#endif
+
+  /* Otherwise just use the native division routines.  */
+  return x % y;
+}
+
+/* Compute the primary hash for HASH given HTAB's current size.  */
+
+static inline hashval_t
+htab_mod (hashval_t hash, htab_t htab)
+{
+  const struct prime_ent *p = &prime_tab[htab->size_prime_index];
+  return htab_mod_1 (hash, p->prime, p->inv, p->shift);
+}
+
+/* Compute the secondary hash for HASH given HTAB's current size.  */
+
+static inline hashval_t
+htab_mod_m2 (hashval_t hash, htab_t htab)
+{
+  const struct prime_ent *p = &prime_tab[htab->size_prime_index];
+  return 1 + htab_mod_1 (hash, p->prime - 2, p->inv_m2, p->shift);
+}
+
+/* This function creates table with length slightly longer than given
+   source length.  Created hash table is initiated as empty (all the
+   hash table entries are HTAB_EMPTY_ENTRY).  The function returns the
+   created hash table, or NULL if memory allocation fails.  */
+
+htab_t
+htab_create_alloc (size_t size, htab_hash hash_f, htab_eq eq_f,
+                   htab_del del_f, htab_alloc alloc_f, htab_free free_f)
+{
+  htab_t result;
+  unsigned int size_prime_index;
+
+  size_prime_index = higher_prime_index (size);
+  size = prime_tab[size_prime_index].prime;
+
+  result = (htab_t) (*alloc_f) (1, sizeof (struct htab));
+  if (result == NULL)
+    return NULL;
+  result->entries = (PTR *) (*alloc_f) (size, sizeof (PTR));
+  if (result->entries == NULL)
+    {
+      if (free_f != NULL)
+       (*free_f) (result);
+      return NULL;
+    }
+  result->size = size;
+  result->size_prime_index = size_prime_index;
+  result->hash_f = hash_f;
+  result->eq_f = eq_f;
+  result->del_f = del_f;
+  result->alloc_f = alloc_f;
+  result->free_f = free_f;
+  return result;
+}
+
+/* As above, but use the variants of alloc_f and free_f which accept
+   an extra argument.  */
+
+htab_t
+htab_create_alloc_ex (size_t size, htab_hash hash_f, htab_eq eq_f,
+                      htab_del del_f, void *alloc_arg,
+                      htab_alloc_with_arg alloc_f,
+                     htab_free_with_arg free_f)
+{
+  htab_t result;
+  unsigned int size_prime_index;
+
+  size_prime_index = higher_prime_index (size);
+  size = prime_tab[size_prime_index].prime;
+
+  result = (htab_t) (*alloc_f) (alloc_arg, 1, sizeof (struct htab));
+  if (result == NULL)
+    return NULL;
+  result->entries = (PTR *) (*alloc_f) (alloc_arg, size, sizeof (PTR));
+  if (result->entries == NULL)
+    {
+      if (free_f != NULL)
+       (*free_f) (alloc_arg, result);
+      return NULL;
+    }
+  result->size = size;
+  result->size_prime_index = size_prime_index;
+  result->hash_f = hash_f;
+  result->eq_f = eq_f;
+  result->del_f = del_f;
+  result->alloc_arg = alloc_arg;
+  result->alloc_with_arg_f = alloc_f;
+  result->free_with_arg_f = free_f;
+  return result;
+}
+
+/* Update the function pointers and allocation parameter in the htab_t.  */
+
+void
+htab_set_functions_ex (htab_t htab, htab_hash hash_f, htab_eq eq_f,
+                       htab_del del_f, PTR alloc_arg,
+                       htab_alloc_with_arg alloc_f, htab_free_with_arg free_f)
+{
+  htab->hash_f = hash_f;
+  htab->eq_f = eq_f;
+  htab->del_f = del_f;
+  htab->alloc_arg = alloc_arg;
+  htab->alloc_with_arg_f = alloc_f;
+  htab->free_with_arg_f = free_f;
+}
+
+/* These functions exist solely for backward compatibility.  */
+
+#undef htab_create
+htab_t
+htab_create (size_t size, htab_hash hash_f, htab_eq eq_f, htab_del del_f)
+{
+  return htab_create_alloc (size, hash_f, eq_f, del_f, xcalloc, free);
+}
+
+htab_t
+htab_try_create (size_t size, htab_hash hash_f, htab_eq eq_f, htab_del del_f)
+{
+  return htab_create_alloc (size, hash_f, eq_f, del_f, calloc, free);
+}
+
+/* This function frees all memory allocated for given hash table.
+   Naturally the hash table must already exist. */
+
+void
+htab_delete (htab_t htab)
+{
+  size_t size = htab_size (htab);
+  PTR *entries = htab->entries;
+  int i;
+
+  if (htab->del_f)
+    for (i = size - 1; i >= 0; i--)
+      if (entries[i] != HTAB_EMPTY_ENTRY && entries[i] != HTAB_DELETED_ENTRY)
+       (*htab->del_f) (entries[i]);
+
+  if (htab->free_f != NULL)
+    {
+      (*htab->free_f) (entries);
+      (*htab->free_f) (htab);
+    }
+  else if (htab->free_with_arg_f != NULL)
+    {
+      (*htab->free_with_arg_f) (htab->alloc_arg, entries);
+      (*htab->free_with_arg_f) (htab->alloc_arg, htab);
+    }
+}
+
+/* This function clears all entries in the given hash table.  */
+
+void
+htab_empty (htab_t htab)
+{
+  size_t size = htab_size (htab);
+  PTR *entries = htab->entries;
+  int i;
+
+  if (htab->del_f)
+    for (i = size - 1; i >= 0; i--)
+      if (entries[i] != HTAB_EMPTY_ENTRY && entries[i] != HTAB_DELETED_ENTRY)
+       (*htab->del_f) (entries[i]);
+
+  memset (entries, 0, size * sizeof (PTR));
+}
+
+/* Similar to htab_find_slot, but without several unwanted side effects:
+    - Does not call htab->eq_f when it finds an existing entry.
+    - Does not change the count of elements/searches/collisions in the
+      hash table.
+   This function also assumes there are no deleted entries in the table.
+   HASH is the hash value for the element to be inserted.  */
+
+static PTR *
+find_empty_slot_for_expand (htab_t htab, hashval_t hash)
+{
+  hashval_t index = htab_mod (hash, htab);
+  size_t size = htab_size (htab);
+  PTR *slot = htab->entries + index;
+  hashval_t hash2;
+
+  if (*slot == HTAB_EMPTY_ENTRY)
+    return slot;
+  else if (*slot == HTAB_DELETED_ENTRY)
+    abort ();
+
+  hash2 = htab_mod_m2 (hash, htab);
+  for (;;)
+    {
+      index += hash2;
+      if (index >= size)
+       index -= size;
+
+      slot = htab->entries + index;
+      if (*slot == HTAB_EMPTY_ENTRY)
+       return slot;
+      else if (*slot == HTAB_DELETED_ENTRY)
+       abort ();
+    }
+}
+
+/* The following function changes size of memory allocated for the
+   entries and repeatedly inserts the table elements.  The occupancy
+   of the table after the call will be about 50%.  Naturally the hash
+   table must already exist.  Remember also that the place of the
+   table entries is changed.  If memory allocation failures are allowed,
+   this function will return zero, indicating that the table could not be
+   expanded.  If all goes well, it will return a non-zero value.  */
+
+static int
+htab_expand (htab_t htab)
+{
+  PTR *oentries;
+  PTR *olimit;
+  PTR *p;
+  PTR *nentries;
+  size_t nsize, osize, elts;
+  unsigned int oindex, nindex;
+
+  oentries = htab->entries;
+  oindex = htab->size_prime_index;
+  osize = htab->size;
+  olimit = oentries + osize;
+  elts = htab_elements (htab);
+
+  /* Resize only when table after removal of unused elements is either
+     too full or too empty.  */
+  if (elts * 2 > osize || (elts * 8 < osize && osize > 32))
+    {
+      nindex = higher_prime_index (elts * 2);
+      nsize = prime_tab[nindex].prime;
+    }
+  else
+    {
+      nindex = oindex;
+      nsize = osize;
+    }
+
+  if (htab->alloc_with_arg_f != NULL)
+    nentries = (PTR *) (*htab->alloc_with_arg_f) (htab->alloc_arg, nsize,
+                                                 sizeof (PTR *));
+  else
+    nentries = (PTR *) (*htab->alloc_f) (nsize, sizeof (PTR *));
+  if (nentries == NULL)
+    return 0;
+  htab->entries = nentries;
+  htab->size = nsize;
+  htab->size_prime_index = nindex;
+  htab->n_elements -= htab->n_deleted;
+  htab->n_deleted = 0;
+
+  p = oentries;
+  do
+    {
+      PTR x = *p;
+
+      if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
+       {
+         PTR *q = find_empty_slot_for_expand (htab, (*htab->hash_f) (x));
+
+         *q = x;
+       }
+
+      p++;
+    }
+  while (p < olimit);
+
+  if (htab->free_f != NULL)
+    (*htab->free_f) (oentries);
+  else if (htab->free_with_arg_f != NULL)
+    (*htab->free_with_arg_f) (htab->alloc_arg, oentries);
+  return 1;
+}
+
+/* This function searches for a hash table entry equal to the given
+   element.  It cannot be used to insert or delete an element.  */
+
+PTR
+htab_find_with_hash (htab_t htab, const PTR element, hashval_t hash)
+{
+  hashval_t index, hash2;
+  size_t size;
+  PTR entry;
+
+  htab->searches++;
+  size = htab_size (htab);
+  index = htab_mod (hash, htab);
+
+  entry = htab->entries[index];
+  if (entry == HTAB_EMPTY_ENTRY
+      || (entry != HTAB_DELETED_ENTRY && (*htab->eq_f) (entry, element)))
+    return entry;
+
+  hash2 = htab_mod_m2 (hash, htab);
+  for (;;)
+    {
+      htab->collisions++;
+      index += hash2;
+      if (index >= size)
+       index -= size;
+
+      entry = htab->entries[index];
+      if (entry == HTAB_EMPTY_ENTRY
+         || (entry != HTAB_DELETED_ENTRY && (*htab->eq_f) (entry, element)))
+       return entry;
+    }
+}
+
+/* Like htab_find_slot_with_hash, but compute the hash value from the
+   element.  */
+
+PTR
+htab_find (htab_t htab, const PTR element)
+{
+  return htab_find_with_hash (htab, element, (*htab->hash_f) (element));
+}
+
+/* This function searches for a hash table slot containing an entry
+   equal to the given element.  To delete an entry, call this with
+   insert=NO_INSERT, then call htab_clear_slot on the slot returned
+   (possibly after doing some checks).  To insert an entry, call this
+   with insert=INSERT, then write the value you want into the returned
+   slot.  When inserting an entry, NULL may be returned if memory
+   allocation fails.  */
+
+PTR *
+htab_find_slot_with_hash (htab_t htab, const PTR element,
+                          hashval_t hash, enum insert_option insert)
+{
+  PTR *first_deleted_slot;
+  hashval_t index, hash2;
+  size_t size;
+  PTR entry;
+
+  size = htab_size (htab);
+  if (insert == INSERT && size * 3 <= htab->n_elements * 4)
+    {
+      if (htab_expand (htab) == 0)
+       return NULL;
+      size = htab_size (htab);
+    }
+
+  index = htab_mod (hash, htab);
+
+  htab->searches++;
+  first_deleted_slot = NULL;
+
+  entry = htab->entries[index];
+  if (entry == HTAB_EMPTY_ENTRY)
+    goto empty_entry;
+  else if (entry == HTAB_DELETED_ENTRY)
+    first_deleted_slot = &htab->entries[index];
+  else if ((*htab->eq_f) (entry, element))
+    return &htab->entries[index];
+      
+  hash2 = htab_mod_m2 (hash, htab);
+  for (;;)
+    {
+      htab->collisions++;
+      index += hash2;
+      if (index >= size)
+       index -= size;
+      
+      entry = htab->entries[index];
+      if (entry == HTAB_EMPTY_ENTRY)
+       goto empty_entry;
+      else if (entry == HTAB_DELETED_ENTRY)
+       {
+         if (!first_deleted_slot)
+           first_deleted_slot = &htab->entries[index];
+       }
+      else if ((*htab->eq_f) (entry, element))
+       return &htab->entries[index];
+    }
+
+ empty_entry:
+  if (insert == NO_INSERT)
+    return NULL;
+
+  if (first_deleted_slot)
+    {
+      htab->n_deleted--;
+      *first_deleted_slot = HTAB_EMPTY_ENTRY;
+      return first_deleted_slot;
+    }
+
+  htab->n_elements++;
+  return &htab->entries[index];
+}
+
+/* Like htab_find_slot_with_hash, but compute the hash value from the
+   element.  */
+
+PTR *
+htab_find_slot (htab_t htab, const PTR element, enum insert_option insert)
+{
+  return htab_find_slot_with_hash (htab, element, (*htab->hash_f) (element),
+                                  insert);
+}
+
+/* This function deletes an element with the given value from hash
+   table (the hash is computed from the element).  If there is no matching
+   element in the hash table, this function does nothing.  */
+
+void
+htab_remove_elt (htab_t htab, PTR element)
+{
+  htab_remove_elt_with_hash (htab, element, (*htab->hash_f) (element));
+}
+
+
+/* This function deletes an element with the given value from hash
+   table.  If there is no matching element in the hash table, this
+   function does nothing.  */
+
+void
+htab_remove_elt_with_hash (htab_t htab, PTR element, hashval_t hash)
+{
+  PTR *slot;
+
+  slot = htab_find_slot_with_hash (htab, element, hash, NO_INSERT);
+  if (*slot == HTAB_EMPTY_ENTRY)
+    return;
+
+  if (htab->del_f)
+    (*htab->del_f) (*slot);
+
+  *slot = HTAB_DELETED_ENTRY;
+  htab->n_deleted++;
+}
+
+/* This function clears a specified slot in a hash table.  It is
+   useful when you've already done the lookup and don't want to do it
+   again.  */
+
+void
+htab_clear_slot (htab_t htab, PTR *slot)
+{
+  if (slot < htab->entries || slot >= htab->entries + htab_size (htab)
+      || *slot == HTAB_EMPTY_ENTRY || *slot == HTAB_DELETED_ENTRY)
+    abort ();
+
+  if (htab->del_f)
+    (*htab->del_f) (*slot);
+
+  *slot = HTAB_DELETED_ENTRY;
+  htab->n_deleted++;
+}
+
+/* This function scans over the entire hash table calling
+   CALLBACK for each live entry.  If CALLBACK returns false,
+   the iteration stops.  INFO is passed as CALLBACK's second
+   argument.  */
+
+void
+htab_traverse_noresize (htab_t htab, htab_trav callback, PTR info)
+{
+  PTR *slot;
+  PTR *limit;
+  
+  slot = htab->entries;
+  limit = slot + htab_size (htab);
+
+  do
+    {
+      PTR x = *slot;
+
+      if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
+       if (!(*callback) (slot, info))
+         break;
+    }
+  while (++slot < limit);
+}
+
+/* Like htab_traverse_noresize, but does resize the table when it is
+   too empty to improve effectivity of subsequent calls.  */
+
+void
+htab_traverse (htab_t htab, htab_trav callback, PTR info)
+{
+  if (htab_elements (htab) * 8 < htab_size (htab))
+    htab_expand (htab);
+
+  htab_traverse_noresize (htab, callback, info);
+}
+
+/* Return the fraction of fixed collisions during all work with given
+   hash table. */
+
+double
+htab_collisions (htab_t htab)
+{
+  if (htab->searches == 0)
+    return 0.0;
+
+  return (double) htab->collisions / (double) htab->searches;
+}
+
+/* Hash P as a null-terminated string.
+
+   Copied from gcc/hashtable.c.  Zack had the following to say with respect
+   to applicability, though note that unlike hashtable.c, this hash table
+   implementation re-hashes rather than chain buckets.
+
+   http://gcc.gnu.org/ml/gcc-patches/2001-08/msg01021.html
+   From: Zack Weinberg <zackw@panix.com>
+   Date: Fri, 17 Aug 2001 02:15:56 -0400
+
+   I got it by extracting all the identifiers from all the source code
+   I had lying around in mid-1999, and testing many recurrences of
+   the form "H_n = H_{n-1} * K + c_n * L + M" where K, L, M were either
+   prime numbers or the appropriate identity.  This was the best one.
+   I don't remember exactly what constituted "best", except I was
+   looking at bucket-length distributions mostly.
+   
+   So it should be very good at hashing identifiers, but might not be
+   as good at arbitrary strings.
+   
+   I'll add that it thoroughly trounces the hash functions recommended
+   for this use at http://burtleburtle.net/bob/hash/index.html, both
+   on speed and bucket distribution.  I haven't tried it against the
+   function they just started using for Perl's hashes.  */
+
+hashval_t
+htab_hash_string (const PTR p)
+{
+  const unsigned char *str = (const unsigned char *) p;
+  hashval_t r = 0;
+  unsigned char c;
+
+  while ((c = *str++) != 0)
+    r = r * 67 + c - 113;
+
+  return r;
+}
+
+/* DERIVED FROM:
+--------------------------------------------------------------------
+lookup2.c, by Bob Jenkins, December 1996, Public Domain.
+hash(), hash2(), hash3, and mix() are externally useful functions.
+Routines to test the hash are included if SELF_TEST is defined.
+You can use this free for any purpose.  It has no warranty.
+--------------------------------------------------------------------
+*/
+
+/*
+--------------------------------------------------------------------
+mix -- mix 3 32-bit values reversibly.
+For every delta with one or two bit set, and the deltas of all three
+  high bits or all three low bits, whether the original value of a,b,c
+  is almost all zero or is uniformly distributed,
+* If mix() is run forward or backward, at least 32 bits in a,b,c
+  have at least 1/4 probability of changing.
+* If mix() is run forward, every bit of c will change between 1/3 and
+  2/3 of the time.  (Well, 22/100 and 78/100 for some 2-bit deltas.)
+mix() was built out of 36 single-cycle latency instructions in a 
+  structure that could supported 2x parallelism, like so:
+      a -= b; 
+      a -= c; x = (c>>13);
+      b -= c; a ^= x;
+      b -= a; x = (a<<8);
+      c -= a; b ^= x;
+      c -= b; x = (b>>13);
+      ...
+  Unfortunately, superscalar Pentiums and Sparcs can't take advantage 
+  of that parallelism.  They've also turned some of those single-cycle
+  latency instructions into multi-cycle latency instructions.  Still,
+  this is the fastest good hash I could find.  There were about 2^^68
+  to choose from.  I only looked at a billion or so.
+--------------------------------------------------------------------
+*/
+/* same, but slower, works on systems that might have 8 byte hashval_t's */
+#define mix(a,b,c) \
+{ \
+  a -= b; a -= c; a ^= (c>>13); \
+  b -= c; b -= a; b ^= (a<< 8); \
+  c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \
+  a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \
+  b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \
+  c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \
+  a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \
+  b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \
+  c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
+}
+
+/*
+--------------------------------------------------------------------
+hash() -- hash a variable-length key into a 32-bit value
+  k     : the key (the unaligned variable-length array of bytes)
+  len   : the length of the key, counting by bytes
+  level : can be any 4-byte value
+Returns a 32-bit value.  Every bit of the key affects every bit of
+the return value.  Every 1-bit and 2-bit delta achieves avalanche.
+About 36+6len instructions.
+
+The best hash table sizes are powers of 2.  There is no need to do
+mod a prime (mod is sooo slow!).  If you need less than 32 bits,
+use a bitmask.  For example, if you need only 10 bits, do
+  h = (h & hashmask(10));
+In which case, the hash table should have hashsize(10) elements.
+
+If you are hashing n strings (ub1 **)k, do it like this:
+  for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
+
+By Bob Jenkins, 1996.  bob_jenkins@burtleburtle.net.  You may use this
+code any way you wish, private, educational, or commercial.  It's free.
+
+See http://burtleburtle.net/bob/hash/evahash.html
+Use for hash table lookup, or anything where one collision in 2^32 is
+acceptable.  Do NOT use for cryptographic purposes.
+--------------------------------------------------------------------
+*/
+
+hashval_t
+iterative_hash (const PTR k_in /* the key */,
+                register size_t  length /* the length of the key */,
+                register hashval_t initval /* the previous hash, or
+                                              an arbitrary value */)
+{
+  register const unsigned char *k = (const unsigned char *)k_in;
+  register hashval_t a,b,c,len;
+
+  /* Set up the internal state */
+  len = length;
+  a = b = 0x9e3779b9;  /* the golden ratio; an arbitrary value */
+  c = initval;           /* the previous hash value */
+
+  /*---------------------------------------- handle most of the key */
+#ifndef WORDS_BIGENDIAN
+  /* On a little-endian machine, if the data is 4-byte aligned we can hash
+     by word for better speed.  This gives nondeterministic results on
+     big-endian machines.  */
+  if (sizeof (hashval_t) == 4 && (((size_t)k)&3) == 0)
+    while (len >= 12)    /* aligned */
+      {
+       a += *(hashval_t *)(k+0);
+       b += *(hashval_t *)(k+4);
+       c += *(hashval_t *)(k+8);
+       mix(a,b,c);
+       k += 12; len -= 12;
+      }
+  else /* unaligned */
+#endif
+    while (len >= 12)
+      {
+       a += (k[0] +((hashval_t)k[1]<<8) +((hashval_t)k[2]<<16) +((hashval_t)k[3]<<24));
+       b += (k[4] +((hashval_t)k[5]<<8) +((hashval_t)k[6]<<16) +((hashval_t)k[7]<<24));
+       c += (k[8] +((hashval_t)k[9]<<8) +((hashval_t)k[10]<<16)+((hashval_t)k[11]<<24));
+       mix(a,b,c);
+       k += 12; len -= 12;
+      }
+
+  /*------------------------------------- handle the last 11 bytes */
+  c += length;
+  switch(len)              /* all the case statements fall through */
+    {
+    case 11: c+=((hashval_t)k[10]<<24);
+    case 10: c+=((hashval_t)k[9]<<16);
+    case 9 : c+=((hashval_t)k[8]<<8);
+      /* the first byte of c is reserved for the length */
+    case 8 : b+=((hashval_t)k[7]<<24);
+    case 7 : b+=((hashval_t)k[6]<<16);
+    case 6 : b+=((hashval_t)k[5]<<8);
+    case 5 : b+=k[4];
+    case 4 : a+=((hashval_t)k[3]<<24);
+    case 3 : a+=((hashval_t)k[2]<<16);
+    case 2 : a+=((hashval_t)k[1]<<8);
+    case 1 : a+=k[0];
+      /* case 0: nothing left to add */
+    }
+  mix(a,b,c);
+  /*-------------------------------------------- report the result */
+  return c;
+}
diff --git a/support/cpp2/libiberty/hashtab.h b/support/cpp2/libiberty/hashtab.h
new file mode 100644 (file)
index 0000000..77eee14
--- /dev/null
@@ -0,0 +1,206 @@
+/* An expandable hash tables datatype.  
+   Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Contributed by Vladimir Makarov (vmakarov@cygnus.com).
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* This package implements basic hash table functionality.  It is possible
+   to search for an entry, create an entry and destroy an entry.
+
+   Elements in the table are generic pointers.
+
+   The size of the table is not fixed; if the occupancy of the table
+   grows too high the hash table will be expanded.
+
+   The abstract data implementation is based on generalized Algorithm D
+   from Knuth's book "The art of computer programming".  Hash table is
+   expanded by creation of new hash table and transferring elements from
+   the old table to the new table.  */
+
+#ifndef __HASHTAB_H__
+#define __HASHTAB_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "ansidecl.h"
+
+#ifndef GTY
+#define GTY(X)
+#endif
+
+/* The type for a hash code.  */
+typedef unsigned int hashval_t;
+
+/* Callback function pointer types.  */
+
+/* Calculate hash of a table entry.  */
+typedef hashval_t (*htab_hash) (const void *);
+
+/* Compare a table entry with a possible entry.  The entry already in
+   the table always comes first, so the second element can be of a
+   different type (but in this case htab_find and htab_find_slot
+   cannot be used; instead the variants that accept a hash value
+   must be used).  */
+typedef int (*htab_eq) (const void *, const void *);
+
+/* Cleanup function called whenever a live element is removed from
+   the hash table.  */
+typedef void (*htab_del) (void *);
+  
+/* Function called by htab_traverse for each live element.  The first
+   arg is the slot of the element (which can be passed to htab_clear_slot
+   if desired), the second arg is the auxiliary pointer handed to
+   htab_traverse.  Return 1 to continue scan, 0 to stop.  */
+typedef int (*htab_trav) (void **, void *);
+
+/* Memory-allocation function, with the same functionality as calloc().
+   Iff it returns NULL, the hash table implementation will pass an error
+   code back to the user, so if your code doesn't handle errors,
+   best if you use xcalloc instead.  */
+typedef void *(*htab_alloc) (size_t, size_t);
+
+/* We also need a free() routine.  */
+typedef void (*htab_free) (void *);
+
+/* Memory allocation and deallocation; variants which take an extra
+   argument.  */
+typedef void *(*htab_alloc_with_arg) (void *, size_t, size_t);
+typedef void (*htab_free_with_arg) (void *, void *);
+
+/* This macro defines reserved value for empty table entry.  */
+
+#define HTAB_EMPTY_ENTRY    ((PTR) 0)
+
+/* This macro defines reserved value for table entry which contained
+   a deleted element. */
+
+#define HTAB_DELETED_ENTRY  ((PTR) 1)
+
+/* Hash tables are of the following type.  The structure
+   (implementation) of this type is not needed for using the hash
+   tables.  All work with hash table should be executed only through
+   functions mentioned below.  The size of this structure is subject to
+   change.  */
+
+struct htab GTY(())
+{
+  /* Pointer to hash function.  */
+  htab_hash hash_f;
+
+  /* Pointer to comparison function.  */
+  htab_eq eq_f;
+
+  /* Pointer to cleanup function.  */
+  htab_del del_f;
+
+  /* Table itself.  */
+  void ** GTY ((use_param, length ("%h.size"))) entries;
+
+  /* Current size (in entries) of the hash table.  */
+  size_t size;
+
+  /* Current number of elements including also deleted elements.  */
+  size_t n_elements;
+
+  /* Current number of deleted elements in the table.  */
+  size_t n_deleted;
+
+  /* The following member is used for debugging. Its value is number
+     of all calls of `htab_find_slot' for the hash table. */
+  unsigned int searches;
+
+  /* The following member is used for debugging.  Its value is number
+     of collisions fixed for time of work with the hash table. */
+  unsigned int collisions;
+
+  /* Pointers to allocate/free functions.  */
+  htab_alloc alloc_f;
+  htab_free free_f;
+
+  /* Alternate allocate/free functions, which take an extra argument.  */
+  void * GTY((skip)) alloc_arg;
+  htab_alloc_with_arg alloc_with_arg_f;
+  htab_free_with_arg free_with_arg_f;
+
+  /* Current size (in entries) of the hash table, as an index into the
+     table of primes.  */
+  unsigned int size_prime_index;
+};
+
+typedef struct htab *htab_t;
+
+/* An enum saying whether we insert into the hash table or not.  */
+enum insert_option {NO_INSERT, INSERT};
+
+/* The prototypes of the package functions. */
+
+extern htab_t  htab_create_alloc  (size_t, htab_hash,
+                                    htab_eq, htab_del,
+                                    htab_alloc, htab_free);
+
+extern htab_t  htab_create_alloc_ex (size_t, htab_hash,
+                                      htab_eq, htab_del,
+                                      void *, htab_alloc_with_arg,
+                                      htab_free_with_arg);
+
+/* Backward-compatibility functions.  */
+extern htab_t htab_create (size_t, htab_hash, htab_eq, htab_del);
+extern htab_t htab_try_create (size_t, htab_hash, htab_eq, htab_del);
+
+extern void    htab_set_functions_ex (htab_t, htab_hash,
+                                       htab_eq, htab_del,
+                                       void *, htab_alloc_with_arg,
+                                       htab_free_with_arg);
+
+extern void    htab_delete (htab_t);
+extern void    htab_empty (htab_t);
+
+extern void *  htab_find (htab_t, const void *);
+extern void ** htab_find_slot (htab_t, const void *, enum insert_option);
+extern void *  htab_find_with_hash (htab_t, const void *, hashval_t);
+extern void ** htab_find_slot_with_hash (htab_t, const void *,
+                                         hashval_t, enum insert_option);
+extern void    htab_clear_slot (htab_t, void **);
+extern void    htab_remove_elt (htab_t, void *);
+extern void    htab_remove_elt_with_hash (htab_t, void *, hashval_t);
+
+extern void    htab_traverse (htab_t, htab_trav, void *);
+extern void    htab_traverse_noresize (htab_t, htab_trav, void *);
+
+extern size_t  htab_size (htab_t);
+extern size_t  htab_elements (htab_t);
+extern double  htab_collisions (htab_t);
+
+/* A hash function for pointers.  */
+extern htab_hash htab_hash_pointer;
+
+/* An equality function for pointers.  */
+extern htab_eq htab_eq_pointer;
+
+/* A hash function for null-terminated strings.  */
+extern hashval_t htab_hash_string (const void *);
+
+/* An iterative hash function for arbitrary data.  */
+extern hashval_t iterative_hash (const void *, size_t, hashval_t);
+/* Shorthand for hashing something with an intrinsic size.  */
+#define iterative_hash_object(OB,INIT) iterative_hash (&OB, sizeof (OB), INIT)
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __HASHTAB_H */
diff --git a/support/cpp2/libiberty/md5.c b/support/cpp2/libiberty/md5.c
new file mode 100644 (file)
index 0000000..83e0beb
--- /dev/null
@@ -0,0 +1,430 @@
+/* md5.c - Functions to compute MD5 message digest of files or memory blocks
+   according to the definition of MD5 in RFC 1321 from April 1992.
+   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+   NOTE: This source is derived from an old version taken from the GNU C
+   Library (glibc).
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if STDC_HEADERS || defined _LIBC
+# include <stdlib.h>
+# include <string.h>
+#else
+# ifndef HAVE_MEMCPY
+#  define memcpy(d, s, n) bcopy ((s), (d), (n))
+# endif
+#endif
+
+#include "ansidecl.h"
+#include "md5.h"
+
+#ifdef _LIBC
+# include <endian.h>
+# if __BYTE_ORDER == __BIG_ENDIAN
+#  define WORDS_BIGENDIAN 1
+# endif
+#endif
+
+#ifdef WORDS_BIGENDIAN
+# define SWAP(n)                                                       \
+    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+#else
+# define SWAP(n) (n)
+#endif
+
+
+/* This array contains the bytes used to pad the buffer to the next
+   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
+
+
+/* Initialize structure containing state of computation.
+   (RFC 1321, 3.3: Step 3)  */
+void
+md5_init_ctx (struct md5_ctx *ctx)
+{
+  ctx->A = (md5_uint32) 0x67452301;
+  ctx->B = (md5_uint32) 0xefcdab89;
+  ctx->C = (md5_uint32) 0x98badcfe;
+  ctx->D = (md5_uint32) 0x10325476;
+
+  ctx->total[0] = ctx->total[1] = 0;
+  ctx->buflen = 0;
+}
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result
+   must be in little endian byte order.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+md5_read_ctx (const struct md5_ctx *ctx, void *resbuf)
+{
+  ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
+  ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
+  ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
+  ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
+
+  return resbuf;
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+md5_finish_ctx (struct md5_ctx *ctx, void *resbuf)
+{
+  /* Take yet unprocessed bytes into account.  */
+  md5_uint32 bytes = ctx->buflen;
+  size_t pad;
+
+  /* Now count remaining bytes.  */
+  ctx->total[0] += bytes;
+  if (ctx->total[0] < bytes)
+    ++ctx->total[1];
+
+  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+  memcpy (&ctx->buffer[bytes], fillbuf, pad);
+
+  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
+  *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
+  *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
+                                                       (ctx->total[0] >> 29));
+
+  /* Process last bytes.  */
+  md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
+
+  return md5_read_ctx (ctx, resbuf);
+}
+
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+int
+md5_stream (FILE *stream, void *resblock)
+{
+  /* Important: BLOCKSIZE must be a multiple of 64.  */
+#define BLOCKSIZE 4096
+  struct md5_ctx ctx;
+  char buffer[BLOCKSIZE + 72];
+  size_t sum;
+
+  /* Initialize the computation context.  */
+  md5_init_ctx (&ctx);
+
+  /* Iterate over full file contents.  */
+  while (1)
+    {
+      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
+        computation function processes the whole buffer so that with the
+        next round of the loop another block can be read.  */
+      size_t n;
+      sum = 0;
+
+      /* Read block.  Take care for partial reads.  */
+      do
+       {
+         n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+         sum += n;
+       }
+      while (sum < BLOCKSIZE && n != 0);
+      if (n == 0 && ferror (stream))
+        return 1;
+
+      /* If end of file is reached, end the loop.  */
+      if (n == 0)
+       break;
+
+      /* Process buffer with BLOCKSIZE bytes.  Note that
+                       BLOCKSIZE % 64 == 0
+       */
+      md5_process_block (buffer, BLOCKSIZE, &ctx);
+    }
+
+  /* Add the last bytes if necessary.  */
+  if (sum > 0)
+    md5_process_bytes (buffer, sum, &ctx);
+
+  /* Construct result in desired memory.  */
+  md5_finish_ctx (&ctx, resblock);
+  return 0;
+}
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+void *
+md5_buffer (const char *buffer, size_t len, void *resblock)
+{
+  struct md5_ctx ctx;
+
+  /* Initialize the computation context.  */
+  md5_init_ctx (&ctx);
+
+  /* Process whole buffer but last len % 64 bytes.  */
+  md5_process_bytes (buffer, len, &ctx);
+
+  /* Put result in desired memory area.  */
+  return md5_finish_ctx (&ctx, resblock);
+}
+
+
+void
+md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx)
+{
+  /* When we already have some bits in our internal buffer concatenate
+     both inputs first.  */
+  if (ctx->buflen != 0)
+    {
+      size_t left_over = ctx->buflen;
+      size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+      memcpy (&ctx->buffer[left_over], buffer, add);
+      ctx->buflen += add;
+
+      if (left_over + add > 64)
+       {
+         md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx);
+         /* The regions in the following copy operation cannot overlap.  */
+         memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
+                 (left_over + add) & 63);
+         ctx->buflen = (left_over + add) & 63;
+       }
+
+      buffer = (const void *) ((const char *) buffer + add);
+      len -= add;
+    }
+
+  /* Process available complete blocks.  */
+  if (len > 64)
+    {
+#if !_STRING_ARCH_unaligned
+/* To check alignment gcc has an appropriate operator.  Other
+   compilers don't.  */
+# if __GNUC__ >= 2
+#  define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0)
+# else
+#  define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0)
+# endif
+      if (UNALIGNED_P (buffer))
+        while (len > 64)
+          {
+            md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
+            buffer = (const char *) buffer + 64;
+            len -= 64;
+          }
+      else
+#endif
+      md5_process_block (buffer, len & ~63, ctx);
+      buffer = (const void *) ((const char *) buffer + (len & ~63));
+      len &= 63;
+    }
+
+  /* Move remaining bytes in internal buffer.  */
+  if (len > 0)
+    {
+      memcpy (ctx->buffer, buffer, len);
+      ctx->buflen = len;
+    }
+}
+
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+   and defined in the RFC 1321.  The first function is a little bit optimized
+   (as found in Colin Plumbs public domain implementation).  */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+   It is assumed that LEN % 64 == 0.  */
+
+void
+md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx)
+{
+  md5_uint32 correct_words[16];
+  const md5_uint32 *words = (const md5_uint32 *) buffer;
+  size_t nwords = len / sizeof (md5_uint32);
+  const md5_uint32 *endp = words + nwords;
+  md5_uint32 A = ctx->A;
+  md5_uint32 B = ctx->B;
+  md5_uint32 C = ctx->C;
+  md5_uint32 D = ctx->D;
+
+  /* First increment the byte count.  RFC 1321 specifies the possible
+     length of the file up to 2^64 bits.  Here we only compute the
+     number of bytes.  Do a double word increment.  */
+  ctx->total[0] += len;
+  if (ctx->total[0] < len)
+    ++ctx->total[1];
+
+  /* Process all bytes in the buffer with 64 bytes in each round of
+     the loop.  */
+  while (words < endp)
+    {
+      md5_uint32 *cwp = correct_words;
+      md5_uint32 A_save = A;
+      md5_uint32 B_save = B;
+      md5_uint32 C_save = C;
+      md5_uint32 D_save = D;
+
+      /* First round: using the given function, the context and a constant
+        the next context is computed.  Because the algorithms processing
+        unit is a 32-bit word and it is determined to work on words in
+        little endian byte order we perhaps have to change the byte order
+        before the computation.  To reduce the work for the next steps
+        we store the swapped words in the array CORRECT_WORDS.  */
+
+#define OP(a, b, c, d, s, T)                                           \
+      do                                                               \
+        {                                                              \
+         a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T;             \
+         ++words;                                                      \
+         CYCLIC (a, s);                                                \
+         a += b;                                                       \
+        }                                                              \
+      while (0)
+
+      /* It is unfortunate that C does not provide an operator for
+        cyclic rotation.  Hope the C compiler is smart enough.  */
+#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+
+      /* Before we start, one word to the strange constants.
+        They are defined in RFC 1321 as
+
+        T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
+       */
+
+      /* Round 1.  */
+      OP (A, B, C, D,  7, (md5_uint32) 0xd76aa478);
+      OP (D, A, B, C, 12, (md5_uint32) 0xe8c7b756);
+      OP (C, D, A, B, 17, (md5_uint32) 0x242070db);
+      OP (B, C, D, A, 22, (md5_uint32) 0xc1bdceee);
+      OP (A, B, C, D,  7, (md5_uint32) 0xf57c0faf);
+      OP (D, A, B, C, 12, (md5_uint32) 0x4787c62a);
+      OP (C, D, A, B, 17, (md5_uint32) 0xa8304613);
+      OP (B, C, D, A, 22, (md5_uint32) 0xfd469501);
+      OP (A, B, C, D,  7, (md5_uint32) 0x698098d8);
+      OP (D, A, B, C, 12, (md5_uint32) 0x8b44f7af);
+      OP (C, D, A, B, 17, (md5_uint32) 0xffff5bb1);
+      OP (B, C, D, A, 22, (md5_uint32) 0x895cd7be);
+      OP (A, B, C, D,  7, (md5_uint32) 0x6b901122);
+      OP (D, A, B, C, 12, (md5_uint32) 0xfd987193);
+      OP (C, D, A, B, 17, (md5_uint32) 0xa679438e);
+      OP (B, C, D, A, 22, (md5_uint32) 0x49b40821);
+
+      /* For the second to fourth round we have the possibly swapped words
+        in CORRECT_WORDS.  Redefine the macro to take an additional first
+        argument specifying the function to use.  */
+#undef OP
+#define OP(a, b, c, d, k, s, T)                                                \
+      do                                                               \
+       {                                                               \
+         a += FX (b, c, d) + correct_words[k] + T;                     \
+         CYCLIC (a, s);                                                \
+         a += b;                                                       \
+       }                                                               \
+      while (0)
+
+#define FX(b, c, d) FG (b, c, d)
+
+      /* Round 2.  */
+      OP (A, B, C, D,  1,  5, (md5_uint32) 0xf61e2562);
+      OP (D, A, B, C,  6,  9, (md5_uint32) 0xc040b340);
+      OP (C, D, A, B, 11, 14, (md5_uint32) 0x265e5a51);
+      OP (B, C, D, A,  0, 20, (md5_uint32) 0xe9b6c7aa);
+      OP (A, B, C, D,  5,  5, (md5_uint32) 0xd62f105d);
+      OP (D, A, B, C, 10,  9, (md5_uint32) 0x02441453);
+      OP (C, D, A, B, 15, 14, (md5_uint32) 0xd8a1e681);
+      OP (B, C, D, A,  4, 20, (md5_uint32) 0xe7d3fbc8);
+      OP (A, B, C, D,  9,  5, (md5_uint32) 0x21e1cde6);
+      OP (D, A, B, C, 14,  9, (md5_uint32) 0xc33707d6);
+      OP (C, D, A, B,  3, 14, (md5_uint32) 0xf4d50d87);
+      OP (B, C, D, A,  8, 20, (md5_uint32) 0x455a14ed);
+      OP (A, B, C, D, 13,  5, (md5_uint32) 0xa9e3e905);
+      OP (D, A, B, C,  2,  9, (md5_uint32) 0xfcefa3f8);
+      OP (C, D, A, B,  7, 14, (md5_uint32) 0x676f02d9);
+      OP (B, C, D, A, 12, 20, (md5_uint32) 0x8d2a4c8a);
+
+#undef FX
+#define FX(b, c, d) FH (b, c, d)
+
+      /* Round 3.  */
+      OP (A, B, C, D,  5,  4, (md5_uint32) 0xfffa3942);
+      OP (D, A, B, C,  8, 11, (md5_uint32) 0x8771f681);
+      OP (C, D, A, B, 11, 16, (md5_uint32) 0x6d9d6122);
+      OP (B, C, D, A, 14, 23, (md5_uint32) 0xfde5380c);
+      OP (A, B, C, D,  1,  4, (md5_uint32) 0xa4beea44);
+      OP (D, A, B, C,  4, 11, (md5_uint32) 0x4bdecfa9);
+      OP (C, D, A, B,  7, 16, (md5_uint32) 0xf6bb4b60);
+      OP (B, C, D, A, 10, 23, (md5_uint32) 0xbebfbc70);
+      OP (A, B, C, D, 13,  4, (md5_uint32) 0x289b7ec6);
+      OP (D, A, B, C,  0, 11, (md5_uint32) 0xeaa127fa);
+      OP (C, D, A, B,  3, 16, (md5_uint32) 0xd4ef3085);
+      OP (B, C, D, A,  6, 23, (md5_uint32) 0x04881d05);
+      OP (A, B, C, D,  9,  4, (md5_uint32) 0xd9d4d039);
+      OP (D, A, B, C, 12, 11, (md5_uint32) 0xe6db99e5);
+      OP (C, D, A, B, 15, 16, (md5_uint32) 0x1fa27cf8);
+      OP (B, C, D, A,  2, 23, (md5_uint32) 0xc4ac5665);
+
+#undef FX
+#define FX(b, c, d) FI (b, c, d)
+
+      /* Round 4.  */
+      OP (A, B, C, D,  0,  6, (md5_uint32) 0xf4292244);
+      OP (D, A, B, C,  7, 10, (md5_uint32) 0x432aff97);
+      OP (C, D, A, B, 14, 15, (md5_uint32) 0xab9423a7);
+      OP (B, C, D, A,  5, 21, (md5_uint32) 0xfc93a039);
+      OP (A, B, C, D, 12,  6, (md5_uint32) 0x655b59c3);
+      OP (D, A, B, C,  3, 10, (md5_uint32) 0x8f0ccc92);
+      OP (C, D, A, B, 10, 15, (md5_uint32) 0xffeff47d);
+      OP (B, C, D, A,  1, 21, (md5_uint32) 0x85845dd1);
+      OP (A, B, C, D,  8,  6, (md5_uint32) 0x6fa87e4f);
+      OP (D, A, B, C, 15, 10, (md5_uint32) 0xfe2ce6e0);
+      OP (C, D, A, B,  6, 15, (md5_uint32) 0xa3014314);
+      OP (B, C, D, A, 13, 21, (md5_uint32) 0x4e0811a1);
+      OP (A, B, C, D,  4,  6, (md5_uint32) 0xf7537e82);
+      OP (D, A, B, C, 11, 10, (md5_uint32) 0xbd3af235);
+      OP (C, D, A, B,  2, 15, (md5_uint32) 0x2ad7d2bb);
+      OP (B, C, D, A,  9, 21, (md5_uint32) 0xeb86d391);
+
+      /* Add the starting values of the context.  */
+      A += A_save;
+      B += B_save;
+      C += C_save;
+      D += D_save;
+    }
+
+  /* Put checksum in context given as argument.  */
+  ctx->A = A;
+  ctx->B = B;
+  ctx->C = C;
+  ctx->D = D;
+}
diff --git a/support/cpp2/line-map.c b/support/cpp2/line-map.c
deleted file mode 100644 (file)
index 521c4e5..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/* Map logical line numbers to (source file, line number) pairs.
-   Copyright (C) 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 "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 = 0;
-  set->allocated = 0;
-  set->used = 0;
-  set->last_listed = -1;
-  set->trace_includes = false;
-  set->depth = 0;
-}
-
-/* Free a line map set.  */
-
-void
-linemap_free (struct line_maps *set)
-{
-  if (set->maps)
-    {
-      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 = CURRENT_LINE_MAP (set); ! 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 (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
-   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, source_location from_line,
-            const char *to_file, unsigned int to_line)
-{
-  struct line_map *map;
-
-  if (set->used && from_line < set->maps[set->used - 1].from_line)
-    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--;
-             set->used--;
-             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 = LAST_SOURCE_LINE (from) + 1;
-         sysp = from->sysp;
-       }
-    }
-
-  map->reason = reason;
-  map->sysp = sysp;
-  map->from_line = from_line;
-  map->to_file = to_file;
-  map->to_line = to_line;
-
-  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;
-}
-
-/* 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 = 0, mx = set->used;
-
-  if (mx == 0)
-    abort ();
-
-  while (mx - mn > 1)
-    {
-      md = (mn + mx) / 2;
-      if (set->maps[md].from_line > line)
-       mx = md;
-      else
-       mn = md;
-    }
-
-  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/support/cpp2/line-map.h b/support/cpp2/line-map.h
deleted file mode 100644 (file)
index c57f51a..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/* Map logical line numbers to (source file, line number) pairs.
-   Copyright (C) 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!  */
-
-#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 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 */
-
-/* The logical line FROM_LINE maps to physical source file TO_FILE at
-   line TO_LINE, and subsequently one-to-one until the next line_map
-   structure in the set.  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 from_line;
-  int included_from;
-  ENUM_BITFIELD (lc_reason) reason : CHAR_BIT;
-  unsigned char sysp;
-};
-
-/* A set of chronological line_map structures.  */
-struct line_maps
-{
-  struct line_map *maps;
-  unsigned int allocated;
-  unsigned int used;
-
-  /* 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;
-};
-
-/* Initialize a line map set.  */
-extern void linemap_init (struct line_maps *);
-
-/* Free a line map set.  */
-extern void linemap_free (struct line_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
-   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,
-   source_location from_line, 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 logical line to source line.  */
-#define SOURCE_LINE(MAP, LINE) ((LINE) + (MAP)->to_line - (MAP)->from_line)
-
-/* 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), (MAP)[1].from_line - 1)
-
-/* 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)
-
-/* The current line map.  Saves a call to lookup_line if the caller is
-   sure he is in the scope of the current map.  */
-#define CURRENT_LINE_MAP(MAPS) ((MAPS)->maps + (MAPS)->used - 1)
-
-#endif /* !GCC_LINE_MAP_H  */
diff --git a/support/cpp2/md5.h b/support/cpp2/md5.h
new file mode 100644 (file)
index 0000000..e357893
--- /dev/null
@@ -0,0 +1,139 @@
+/* md5.h - Declaration of functions and data types used for MD5 sum
+   computing library functions.
+   Copyright 1995, 1996, 2000 Free Software Foundation, Inc.
+   NOTE: The canonical source of this file is maintained with the GNU C
+   Library.  Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _MD5_H
+#define _MD5_H 1
+
+#include <stdio.h>
+
+#if defined HAVE_LIMITS_H || _LIBC
+# include <limits.h>
+#endif
+
+/* The following contortions are an attempt to use the C preprocessor
+   to determine an unsigned integral type that is 32 bits wide.  An
+   alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
+   doing that would require that the configure script compile and *run*
+   the resulting executable.  Locally running cross-compiled executables
+   is usually not possible.  */
+
+#ifdef _LIBC
+# include <sys/types.h>
+typedef u_int32_t md5_uint32;
+typedef uintptr_t md5_uintptr;
+#else
+#  define INT_MAX_32_BITS 2147483647
+
+/* If UINT_MAX isn't defined, assume it's a 32-bit type.
+   This should be valid for all systems GNU cares about because
+   that doesn't include 16-bit systems, and only modern systems
+   (that certainly have <limits.h>) have 64+-bit integral types.  */
+
+# ifndef INT_MAX
+#  define INT_MAX INT_MAX_32_BITS
+# endif
+
+# if INT_MAX == INT_MAX_32_BITS
+   typedef unsigned int md5_uint32;
+# else
+#  if SHRT_MAX == INT_MAX_32_BITS
+    typedef unsigned short md5_uint32;
+#  else
+#   if LONG_MAX == INT_MAX_32_BITS
+     typedef unsigned long md5_uint32;
+#   else
+     /* The following line is intended to evoke an error.
+        Using #error is not portable enough.  */
+     "Cannot determine unsigned 32-bit data type."
+#   endif
+#  endif
+# endif
+/* We have to make a guess about the integer type equivalent in size
+   to pointers which should always be correct.  */
+typedef unsigned long int md5_uintptr;
+#endif
+
+/* Structure to save state of computation between the single steps.  */
+struct md5_ctx
+{
+  md5_uint32 A;
+  md5_uint32 B;
+  md5_uint32 C;
+  md5_uint32 D;
+
+  md5_uint32 total[2];
+  md5_uint32 buflen;
+  char buffer[128] ATTRIBUTE_ALIGNED_ALIGNOF(md5_uint32);
+};
+
+/*
+ * The following three functions are build up the low level used in
+ * the functions `md5_stream' and `md5_buffer'.
+ */
+
+/* Initialize structure containing state of computation.
+   (RFC 1321, 3.3: Step 3)  */
+extern void md5_init_ctx (struct md5_ctx *ctx);
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is necessary that LEN is a multiple of 64!!! */
+extern void md5_process_block (const void *buffer, size_t len,
+                               struct md5_ctx *ctx);
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is NOT required that LEN is a multiple of 64.  */
+extern void md5_process_bytes (const void *buffer, size_t len,
+                               struct md5_ctx *ctx);
+
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 16 bytes following RESBUF.  The result is always in little
+   endian byte order, so that a byte-wise output yields to the wanted
+   ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *md5_finish_ctx (struct md5_ctx *ctx, void *resbuf);
+
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result is
+   always in little endian byte order, so that a byte-wise output yields
+   to the wanted ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *md5_read_ctx (const struct md5_ctx *ctx, void *resbuf);
+
+
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+extern int md5_stream (FILE *stream, void *resblock);
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+extern void *md5_buffer (const char *buffer, size_t len, void *resblock);
+
+#endif
diff --git a/support/cpp2/mkdeps.c b/support/cpp2/mkdeps.c
deleted file mode 100644 (file)
index d50d2bf..0000000
+++ /dev/null
@@ -1,364 +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"
-#include "cpplib.h"
-#include "cpphash.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 (cpp_reader *pfile, const char *tgt)
-{
-  struct deps *d = pfile->deps;
-
-  /* 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;
-      char *suffix;
-      const char *obj_ext;
-
-      if (NULL == CPP_OPTION (pfile, obj_ext))
-        obj_ext = TARGET_OBJECT_SUFFIX;
-      else if (CPP_OPTION (pfile, obj_ext)[0] != '.')
-        {
-          char *t = alloca (strlen (CPP_OPTION (pfile, obj_ext)) + 2);
-          t[0] = '.';
-          strcpy (&t[1], CPP_OPTION (pfile, obj_ext));
-          obj_ext = t;
-        }
-      else
-        obj_ext = CPP_OPTION (pfile, obj_ext);
-
-      o = (char *) alloca (strlen (start) + strlen (obj_ext) + 1);
-
-      strcpy (o, start);
-
-      suffix = strrchr (o, '.');
-      if (!suffix)
-        suffix = o + strlen (o);
-      strcpy (suffix, obj_ext);
-
-      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/support/cpp2/mkdeps.h b/support/cpp2/mkdeps.h
deleted file mode 100644 (file)
index db2e00e..0000000
+++ /dev/null
@@ -1,73 +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;
-struct cpp_reader;
-
-/* 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 cpp_reader *, 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 */
index 66d8b8adc7fbcada50bc93f3b1f0390c39d73135..d267e7212a825d18b4c1e9f7adb1d8f521efa25e 100644 (file)
@@ -1,11 +1,26 @@
 #!/bin/sh
-# Like mv $1 $2, but if the files are the same, just delete $1.
-# Status is 0 if $2 is changed, 1 otherwise.
+
+# Copyright (C) 1996 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
 if
 test -r $2
 then
 if
-cmp -s $1 $2
+cmp $1 $2 > /dev/null
 then
 echo $2 is unchanged
 rm -f $1
diff --git a/support/cpp2/opt-functions.awk b/support/cpp2/opt-functions.awk
new file mode 100644 (file)
index 0000000..f392060
--- /dev/null
@@ -0,0 +1,169 @@
+#  Copyright (C) 2003,2004 Free Software Foundation, Inc.\r
+#  Contributed by Kelley Cook, June 2004.\r
+#  Original code from Neil Booth, May 2003.\r
+#\r
+# This program is free software; you can redistribute it and/or modify it\r
+# under the terms of the GNU General Public License as published by the\r
+# Free Software Foundation; either version 2, or (at your option) any\r
+# later version.\r
+# \r
+# This program is distributed in the hope that it will be useful,\r
+# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+# GNU General Public License for more details.\r
+# \r
+# You should have received a copy of the GNU General Public License\r
+# along with this program; if not, write to the Free Software\r
+# Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+\r
+# Some common subroutines for use by opt[ch]-gen.awk.\r
+\r
+# Return nonzero if FLAGS contains a flag matching REGEX.\r
+function flag_set_p(regex, flags)\r
+{\r
+       return (" " flags " ") ~ (" " regex " ")\r
+}\r
+\r
+# Return STRING if FLAGS contains a flag matching regexp REGEX,\r
+# otherwise return the empty string.\r
+function test_flag(regex, flags, string)\r
+{\r
+       if (flag_set_p(regex, flags))\r
+               return string\r
+       return ""\r
+}\r
+\r
+# If FLAGS contains a "NAME(...argument...)" flag, return the value\r
+# of the argument.  Return the empty string otherwise.\r
+function opt_args(name, flags)\r
+{\r
+       flags = " " flags\r
+       if (flags !~ " " name "\\(")\r
+               return ""\r
+       sub(".* " name "\\(", "", flags)\r
+       sub("\\).*", "", flags)\r
+\r
+       return flags\r
+}\r
+\r
+# Return the Nth comma-separated element of S.  Return the empty string\r
+# if S does not contain N elements.\r
+function nth_arg(n, s)\r
+{\r
+       while (n-- > 0) {\r
+               if (s !~ ",")\r
+                       return ""\r
+               sub("[^,]*, *", "", s)\r
+       }\r
+       sub(",.*", "", s)\r
+       return s\r
+}\r
+\r
+# Return a bitmask of CL_* values for option flags FLAGS.\r
+function switch_flags (flags)\r
+{\r
+       result = "0"\r
+       for (j = 0; j < n_langs; j++) {\r
+               regex = langs[j]\r
+               gsub ( "\\+", "\\+", regex )\r
+               result = result test_flag(regex, flags, " | " macros[j])\r
+       }\r
+       result = result \\r
+         test_flag("Common", flags, " | CL_COMMON") \\r
+         test_flag("Target", flags, " | CL_TARGET") \\r
+         test_flag("Joined", flags, " | CL_JOINED") \\r
+         test_flag("JoinedOrMissing", flags, " | CL_JOINED | CL_MISSING_OK") \\r
+         test_flag("Separate", flags, " | CL_SEPARATE") \\r
+         test_flag("RejectNegative", flags, " | CL_REJECT_NEGATIVE") \\r
+         test_flag("UInteger", flags, " | CL_UINTEGER") \\r
+         test_flag("Undocumented", flags,  " | CL_UNDOCUMENTED") \\r
+         test_flag("Report", flags, " | CL_REPORT")\r
+       sub( "^0 \\| ", "", result )\r
+       return result\r
+}\r
+\r
+# If FLAGS includes a Var flag, return the name of the variable it specifies.\r
+# Return the empty string otherwise.\r
+function var_name(flags)\r
+{\r
+       return nth_arg(0, opt_args("Var", flags))\r
+}\r
+\r
+# Return true if the option described by FLAGS has a globally-visible state.\r
+function global_state_p(flags)\r
+{\r
+       return (var_name(flags) != "" \\r
+               || opt_args("Mask", flags) != "" \\r
+               || opt_args("InverseMask", flags) != "")\r
+}\r
+\r
+# Return true if the option described by FLAGS must have some state\r
+# associated with it.\r
+function needs_state_p(flags)\r
+{\r
+       return flag_set_p("Target", flags)\r
+}\r
+\r
+# If FLAGS describes an option that needs a static state variable,\r
+# return the name of that variable, otherwise return "".  NAME is\r
+# the name of the option.\r
+function static_var(name, flags)\r
+{\r
+       if (global_state_p(flags) || !needs_state_p(flags))\r
+               return ""\r
+       gsub ("[^A-Za-z0-9]", "_", name)\r
+       return "VAR_" name\r
+}\r
+\r
+# Return the type of variable that should be associated with the given flags.\r
+function var_type(flags)\r
+{\r
+       if (!flag_set_p("Joined.*", flags))\r
+               return "int "\r
+       else if (flag_set_p("UInteger", flags))\r
+               return "int "\r
+       else\r
+               return "const char *"\r
+}\r
+\r
+# Given that an option has flags FLAGS, return an initializer for the\r
+# "var_cond" and "var_value" fields of its cl_options[] entry.\r
+function var_set(flags)\r
+{\r
+       s = nth_arg(1, opt_args("Var", flags))\r
+       if (s != "")\r
+               return "CLVC_EQUAL, " s\r
+       s = opt_args("Mask", flags);\r
+       if (s != "") {\r
+               vn = var_name(flags);\r
+               if (vn)\r
+                       return "CLVC_BIT_SET, OPTION_MASK_" s\r
+               else\r
+                       return "CLVC_BIT_SET, MASK_" s\r
+       }\r
+       s = nth_arg(0, opt_args("InverseMask", flags));\r
+       if (s != "") {\r
+               vn = var_name(flags);\r
+               if (vn)\r
+                       return "CLVC_BIT_CLEAR, OPTION_MASK_" s\r
+               else\r
+                       return "CLVC_BIT_CLEAR, MASK_" s\r
+       }\r
+       if (var_type(flags) == "const char *")\r
+               return "CLVC_STRING, 0"\r
+       return "CLVC_BOOLEAN, 0"\r
+}\r
+\r
+# Given that an option called NAME has flags FLAGS, return an initializer\r
+# for the "flag_var" field of its cl_options[] entry.\r
+function var_ref(name, flags)\r
+{\r
+       name = var_name(flags) static_var(name, flags)\r
+       if (name != "")\r
+               return "&" name\r
+       if (opt_args("Mask", flags) != "")\r
+               return "&target_flags"\r
+       if (opt_args("InverseMask", flags) != "")\r
+               return "&target_flags"\r
+       return "0"\r
+}\r
diff --git a/support/cpp2/opt-gather.awk b/support/cpp2/opt-gather.awk
new file mode 100644 (file)
index 0000000..87dd37a
--- /dev/null
@@ -0,0 +1,54 @@
+#  Copyright (C) 2003,2004 Free Software Foundation, Inc.\r
+#  Contributed by Kelley Cook, June 2004.\r
+#  Original code from Neil Booth, May 2003.\r
+#\r
+# This program is free software; you can redistribute it and/or modify it\r
+# under the terms of the GNU General Public License as published by the\r
+# Free Software Foundation; either version 2, or (at your option) any\r
+# later version.\r
+# \r
+# This program is distributed in the hope that it will be useful,\r
+# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+# GNU General Public License for more details.\r
+# \r
+# You should have received a copy of the GNU General Public License\r
+# along with this program; if not, write to the Free Software\r
+# Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+\r
+# This Awk script takes a list of *.opt files and combines them into \r
+# a three-field sorted list suitable for input into opt[ch]-gen.awk.\r
+#\r
+# Usage: awk -f opt-gather.awk file1.opt [...] > outputfile\r
+\r
+function sort(ARRAY, ELEMENTS)\r
+{\r
+       for (i = 2; i <= ELEMENTS; ++i) {\r
+               for (j = i; ARRAY[j-1] > ARRAY[j]; --j) {\r
+                       temp = ARRAY[j]\r
+                       ARRAY[j] = ARRAY[j-1]\r
+                       ARRAY[j-1] = temp\r
+               }\r
+       }\r
+       return\r
+}\r
+\r
+BEGIN {        numrec = 0 }\r
+\r
+# Ignore comments and blank lines\r
+/^[ \t]*(;|$)/  { flag = 0; next }\r
+/^[^ \t]/       { if (flag == 0) {\r
+                    record[++numrec] = $0\r
+                   flag = 1 }\r
+                 else {\r
+                   record[numrec] = record[numrec] SUBSEP $0\r
+                 }\r
+}\r
+\r
+# Sort it and output it\r
+END {\r
+       sort(record,numrec)\r
+       \r
+       for (i = 1; i <= numrec; i++) {\r
+               print record[i] }\r
+}\r
diff --git a/support/cpp2/optc-gen.awk b/support/cpp2/optc-gen.awk
new file mode 100644 (file)
index 0000000..08232f3
--- /dev/null
@@ -0,0 +1,168 @@
+#  Copyright (C) 2003,2004 Free Software Foundation, Inc.\r
+#  Contributed by Kelley Cook, June 2004.\r
+#  Original code from Neil Booth, May 2003.\r
+#\r
+# This program is free software; you can redistribute it and/or modify it\r
+# under the terms of the GNU General Public License as published by the\r
+# Free Software Foundation; either version 2, or (at your option) any\r
+# later version.\r
+# \r
+# This program is distributed in the hope that it will be useful,\r
+# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+# GNU General Public License for more details.\r
+# \r
+# You should have received a copy of the GNU General Public License\r
+# along with this program; if not, write to the Free Software\r
+# Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+\r
+# This Awk script reads in the option records generated from \r
+# opt-gather.awk, combines the flags of duplicat options and generates a\r
+# C file.\r
+#\r
+# This program uses functions from opt-functions.awk\r
+#\r
+# Usage: awk -f opt-functions.awk -f optc-gen.awk \\r
+#            [-v header_name=header.h] < inputfile > options.c\r
+\r
+BEGIN {\r
+       n_opts = 0\r
+       n_langs = 0\r
+        quote = "\042"\r
+       comma = ","\r
+       FS=SUBSEP\r
+       # Default the name of header created from opth-gen.awk to options.h\r
+       if (header_name == "") header_name="options.h"\r
+}\r
+\r
+# Collect the text and flags of each option into an array\r
+       {\r
+               if ($1 == "Language") {\r
+                       langs[n_langs] = $2\r
+                       n_langs++;\r
+               }\r
+               else {\r
+                       name = opt_args("Mask", $1)\r
+                       if (name == "") {\r
+                               opts[n_opts]  = $1\r
+                               flags[n_opts] = $2\r
+                               help[n_opts]  = $3\r
+                               n_opts++;\r
+                       }\r
+               }\r
+       }\r
+\r
+# Dump that array of options into a C file.\r
+END {\r
+print "/* This file is auto-generated by opts.sh.  */"\r
+print ""\r
+n_headers = split(header_name, headers, " ")\r
+for (i = 1; i <= n_headers; i++)\r
+       print "#include " quote headers[i] quote\r
+print "#include " quote "opts.h" quote\r
+print "#include " quote "intl.h" quote\r
+print ""\r
+\r
+for (i = 0; i < n_opts; i++) {\r
+       name = var_name(flags[i]);\r
+       if (name == "")\r
+               continue;\r
+\r
+       if (flag_set_p("VarExists", flags[i]))\r
+               continue;\r
+\r
+       init = opt_args("Init", flags[i])\r
+       if (init != "")\r
+               init = " = " init;\r
+       else if (name in var_seen)\r
+               continue;\r
+\r
+       print "/* Set by -" opts[i] "."\r
+       print "   " help[i] "  */"\r
+       print var_type(flags[i]) name init ";"\r
+       print ""\r
+\r
+       var_seen[name] = 1;\r
+}\r
+\r
+print ""\r
+print "/* Local state variables.  */"\r
+for (i = 0; i < n_opts; i++) {\r
+       name = static_var(opts[i], flags[i]);\r
+       if (name != "")\r
+               print "static " var_type(flags[i]) name ";"\r
+}\r
+print ""\r
+\r
+print "const char * const lang_names[] =\n{"\r
+for (i = 0; i < n_langs; i++) {\r
+       macros[i] = "CL_" langs[i]\r
+       gsub( "[^A-Za-z0-9_]", "X", macros[i] )\r
+       s = substr("         ", length (macros[i]))\r
+       print "  " quote langs[i] quote ","\r
+    }\r
+\r
+print "  0\n};\n"\r
+print "const unsigned int cl_options_count = N_OPTS;\n"\r
+\r
+print "const struct cl_option cl_options[] =\n{"\r
+\r
+for (i = 0; i < n_opts; i++)\r
+       back_chain[i] = "N_OPTS";\r
+\r
+for (i = 0; i < n_opts; i++) {\r
+       # Combine the flags of identical switches.  Switches\r
+       # appear many times if they are handled by many front\r
+       # ends, for example.\r
+       while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {\r
+               flags[i + 1] = flags[i] " " flags[i + 1];\r
+               i++;\r
+       }\r
+\r
+       len = length (opts[i]);\r
+       enum = "OPT_" opts[i]\r
+       if (opts[i] == "finline-limit=")\r
+               enum = enum "eq"\r
+       gsub ("[^A-Za-z0-9]", "_", enum)\r
+\r
+       # If this switch takes joined arguments, back-chain all\r
+       # subsequent switches to it for which it is a prefix.  If\r
+       # a later switch S is a longer prefix of a switch T, T\r
+       # will be back-chained to S in a later iteration of this\r
+       # for() loop, which is what we want.\r
+       if (flag_set_p("Joined.*", flags[i])) {\r
+               for (j = i + 1; j < n_opts; j++) {\r
+                       if (substr (opts[j], 1, len) != opts[i])\r
+                               break;\r
+                       back_chain[j] = enum;\r
+               }\r
+       }\r
+\r
+       s = substr("                                  ", length (opts[i]))\r
+       if (i + 1 == n_opts)\r
+               comma = ""\r
+\r
+       if (help[i] == "")\r
+               hlp = "0"\r
+       else\r
+               hlp = quote help[i] quote;\r
+\r
+       printf("  { %c-%s%c,\n    %s,\n    %s, %u,\n",\r
+              quote, opts[i], quote, hlp, back_chain[i], len)\r
+       condition = opt_args("Condition", flags[i])\r
+       cl_flags = switch_flags(flags[i])\r
+       if (condition != "")\r
+               printf("#if %s\n" \\r
+                      "    %s,\n" \\r
+                      "#else\n" \\r
+                      "    CL_DISABLED,\n" \\r
+                      "#endif\n",\r
+                      condition, cl_flags, cl_flags)\r
+       else\r
+               printf("    %s,\n", cl_flags)\r
+       printf("    %s, %s }%s\n", var_ref(opts[i], flags[i]),\r
+              var_set(flags[i]), comma)\r
+}\r
+\r
+print "};"\r
+}\r
diff --git a/support/cpp2/opth-gen.awk b/support/cpp2/opth-gen.awk
new file mode 100644 (file)
index 0000000..09d1a9a
--- /dev/null
@@ -0,0 +1,185 @@
+#  Copyright (C) 2003,2004 Free Software Foundation, Inc.\r
+#  Contributed by Kelley Cook, June 2004.\r
+#  Original code from Neil Booth, May 2003.\r
+#\r
+# This program is free software; you can redistribute it and/or modify it\r
+# under the terms of the GNU General Public License as published by the\r
+# Free Software Foundation; either version 2, or (at your option) any\r
+# later version.\r
+# \r
+# This program is distributed in the hope that it will be useful,\r
+# but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+# GNU General Public License for more details.\r
+# \r
+# You should have received a copy of the GNU General Public License\r
+# along with this program; if not, write to the Free Software\r
+# Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+\r
+# This Awk script reads in the option records generated from \r
+# opt-gather.awk, combines the flags of duplicate options and generates a\r
+# C header file.\r
+#\r
+# This program uses functions from opt-functions.awk\r
+# Usage: awk -f opt-functions.awk -f opth-gen.awk < inputfile > options.h\r
+\r
+BEGIN {\r
+       n_opts = 0\r
+       n_langs = 0\r
+       n_extra_masks = 0\r
+       quote = "\042"\r
+       comma = ","\r
+       FS=SUBSEP\r
+}\r
+\r
+# Collect the text and flags of each option into an array\r
+       {\r
+               if ($1 == "Language") {\r
+                       langs[n_langs] = $2\r
+                       n_langs++;\r
+               }\r
+               else {\r
+                       name = opt_args("Mask", $1)\r
+                       if (name == "") {\r
+                               opts[n_opts]  = $1\r
+                               flags[n_opts] = $2\r
+                               help[n_opts]  = $3\r
+                               n_opts++;\r
+                       }\r
+                       else {\r
+                               extra_masks[n_extra_masks++] = name\r
+                       }\r
+               }\r
+       }\r
+\r
+# Dump out an enumeration into a .h file.\r
+# Combine the flags of duplicate options.\r
+END {\r
+print "/* This file is auto-generated by opts.sh.  */"\r
+print ""\r
+print "#ifndef OPTIONS_H"\r
+print "#define OPTIONS_H"\r
+print ""\r
+print "extern int target_flags;"\r
+print ""\r
+\r
+for (i = 0; i < n_opts; i++) {\r
+       name = var_name(flags[i]);\r
+       if (name == "")\r
+               continue;\r
+\r
+       print "extern " var_type(flags[i]) name ";"\r
+}\r
+print ""\r
+\r
+for (i = 0; i < n_opts; i++) {\r
+       name = opt_args("Mask", flags[i])\r
+       vname = var_name(flags[i])\r
+       mask = "MASK_"\r
+       if (vname != "") {\r
+               mask = "OPTION_MASK_"\r
+       }\r
+       if (name != "" && !flag_set_p("MaskExists", flags[i]))\r
+               print "#define " mask name " (1 << " masknum[vname]++ ")"\r
+}\r
+for (i = 0; i < n_extra_masks; i++) {\r
+       print "#define MASK_" extra_masks[i] " (1 << " masknum[""]++ ")"\r
+}\r
+\r
+for (var in masknum) {\r
+       if (masknum[var] > 31) {\r
+               if (var == "")\r
+                       print "#error too many target masks"\r
+               else\r
+                       print "#error too many masks for " var\r
+       }\r
+}\r
+print ""\r
+\r
+for (i = 0; i < n_opts; i++) {\r
+       name = opt_args("Mask", flags[i])\r
+       vname = var_name(flags[i])\r
+       macro = "OPTION_"\r
+       mask = "OPTION_MASK_"\r
+       if (vname == "") {\r
+               vname = "target_flags"\r
+               macro = "TARGET_"\r
+               mask = "MASK_"\r
+       }\r
+       if (name != "" && !flag_set_p("MaskExists", flags[i]))\r
+               print "#define " macro name \\r
+                     " ((" vname " & " mask name ") != 0)"\r
+}\r
+for (i = 0; i < n_extra_masks; i++) {\r
+       print "#define TARGET_" extra_masks[i] \\r
+             " ((target_flags & MASK_" extra_masks[i] ") != 0)"\r
+}\r
+print ""\r
+\r
+for (i = 0; i < n_opts; i++) {\r
+       opt = opt_args("InverseMask", flags[i])\r
+       if (opt ~ ",")\r
+               print "#define TARGET_" nth_arg(1, opt) \\r
+                     " ((target_flags & MASK_" nth_arg(0, opt) ") == 0)"\r
+}\r
+print ""\r
+\r
+for (i = 0; i < n_langs; i++) {\r
+       macros[i] = "CL_" langs[i]\r
+       gsub( "[^A-Za-z0-9_]", "X", macros[i] )\r
+       s = substr("            ", length (macros[i]))\r
+       print "#define " macros[i] s " (1 << " i ")"\r
+    }\r
+\r
+print ""\r
+print "enum opt_code"\r
+print "{"\r
+       \r
+for (i = 0; i < n_opts; i++)\r
+       back_chain[i] = "N_OPTS";\r
+\r
+for (i = 0; i < n_opts; i++) {\r
+       # Combine the flags of identical switches.  Switches\r
+       # appear many times if they are handled by many front\r
+       # ends, for example.\r
+       while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {\r
+               flags[i + 1] = flags[i] " " flags[i + 1];\r
+               i++;\r
+       }\r
+\r
+       len = length (opts[i]);\r
+       enum = "OPT_" opts[i]\r
+       if (opts[i] == "finline-limit=")\r
+               enum = enum "eq"\r
+       gsub ("[^A-Za-z0-9]", "_", enum)\r
+\r
+       # If this switch takes joined arguments, back-chain all\r
+       # subsequent switches to it for which it is a prefix.  If\r
+       # a later switch S is a longer prefix of a switch T, T\r
+       # will be back-chained to S in a later iteration of this\r
+       # for() loop, which is what we want.\r
+       if (flag_set_p("Joined.*", flags[i])) {\r
+               for (j = i + 1; j < n_opts; j++) {\r
+                       if (substr (opts[j], 1, len) != opts[i])\r
+                               break;\r
+                       back_chain[j] = enum;\r
+               }\r
+       }\r
+\r
+       s = substr("                                     ", length (opts[i]))\r
+       if (i + 1 == n_opts)\r
+               comma = ""\r
+\r
+       if (help[i] == "")\r
+               hlp = "0"\r
+       else\r
+               hlp = "N_(\"" help[i] "\")";\r
+\r
+       print "  " enum "," s "/* -" opts[i] " */"\r
+}\r
+\r
+print "  N_OPTS"\r
+print "};"\r
+print ""\r
+print "#endif /* OPTIONS_H */"\r
+}\r
diff --git a/support/cpp2/options_vc_in.c b/support/cpp2/options_vc_in.c
deleted file mode 100644 (file)
index ab232e7..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/* This file is auto-generated by opts.sh.  */
-
-#include <intl.h>
-#include "options.h"
-#include "opts.h"
-
-const char * const lang_names[] =
-{
-  "SDCPP",
-  0
-};
-
-const unsigned int cl_options_count = N_OPTS;
-
-const struct cl_option cl_options[] =
-{
-  { "--help",
-    N_("Display this information"),
-    N_OPTS, 5, CL_COMMON },
-  { "--version",
-    N_("Display the compiler's version"),
-    N_OPTS, 8, CL_COMMON },
-  { "-A",
-    N_("-A<question>=<answer>  Assert the <answer> to <question>.  Putting '-' before <question> disables the <answer> to <question>"),
-    N_OPTS, 1, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-C",
-    N_("Do not discard comments"),
-    N_OPTS, 1, CL_SDCPP },
-  { "-CC",
-    N_("Do not discard comments in macro expansions"),
-    N_OPTS, 2, CL_SDCPP },
-  { "-D",
-    N_("-D<macro>[=<val>]      Define a <macro> with <val> as its value.  If just <macro> is given, <val> is taken to be 1"),
-    N_OPTS, 1, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-H",
-    N_("Print the name of header files as they are used"),
-    N_OPTS, 1, CL_SDCPP },
-  { "-I",
-    N_("-I <dir>       Add <dir> to the end of the main include path.  -I- gives more include path control; see info documentation"),
-    N_OPTS, 1, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-M",
-    N_("Generate make dependencies"),
-    N_OPTS, 1, CL_SDCPP },
-  { "-MD",
-    N_("Generate make dependencies and compile"),
-    N_OPTS, 2, CL_SDCPP | CL_SEPARATE },
-  { "-MF",
-    N_("-MF <file>     Write dependency output to the given file"),
-    N_OPTS, 2, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-MG",
-    N_("Treat missing header files as generated files"),
-    N_OPTS, 2, CL_SDCPP },
-  { "-MM",
-    N_("Like -M but ignore system header files"),
-    N_OPTS, 2, CL_SDCPP },
-  { "-MMD",
-    N_("Like -MD but ignore system header files"),
-    N_OPTS, 3, CL_SDCPP | CL_SEPARATE },
-  { "-MP",
-    N_("Generate phony targets for all headers"),
-    N_OPTS, 2, CL_SDCPP },
-  { "-MQ",
-    N_("-MQ <target>   Add a MAKE-quoted target"),
-    N_OPTS, 2, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-MT",
-    N_("-MT <target>   Add an unquoted target"),
-    N_OPTS, 2, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-P",
-    N_("Do not generate #line directives"),
-    N_OPTS, 1, CL_SDCPP },
-  { "-U",
-    N_("-U<macro>      Undefine <macro>"),
-    N_OPTS, 1, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-Wall",
-    N_("Enable most warning messages"),
-    N_OPTS, 4, CL_SDCPP },
-  { "-Wcomment",
-    N_("Warn about possibly nested block comments, and C++ comments spanning more than one physical line"),
-    N_OPTS, 8, CL_SDCPP },
-  { "-Wcomments",
-    N_("Synonym for -Wcomment"),
-    N_OPTS, 9, CL_SDCPP },
-  { "-Wdeprecated",
-    N_("Warn about deprecated compiler features"),
-    N_OPTS, 11, CL_SDCPP },
-  { "-Wendif-labels",
-    N_("Warn about stray tokens after #elif and #endif"),
-    N_OPTS, 13, CL_SDCPP },
-  { "-Werror",
-    N_("Treat all warnings as errors"),
-    N_OPTS, 6, CL_SDCPP },
-  { "-Wimport",
-    N_("Deprecated.  This switch has no effect."),
-    N_OPTS, 7, CL_SDCPP },
-  { "-Wsystem-headers",
-    N_("Do not suppress warnings from system headers"),
-    N_OPTS, 15, CL_SDCPP },
-  { "-Wtrigraphs",
-    N_("Warn if trigraphs are encountered that might affect the meaning of the program"),
-    N_OPTS, 10, CL_SDCPP },
-  { "-Wundef",
-    N_("Warn if an undefined macro is used in an #if directive"),
-    N_OPTS, 6, CL_SDCPP },
-  { "-Wunused-macros",
-    N_("Warn about macros defined in the main file that are not used"),
-    N_OPTS, 14, CL_SDCPP },
-  { "-ansi",
-    N_("A synonym for -std=c89."),
-    N_OPTS, 4, CL_SDCPP },
-  { "-d",
-    N_("-d<letters>    Enable dumps from specific passes of the compiler"),
-    N_OPTS, 1, CL_SDCPP | CL_JOINED },
-  { "-fdollars-in-identifiers",
-    N_("Permit '$' as an identifier character"),
-    N_OPTS, 23, CL_SDCPP },
-  { "-fexec-charset=",
-    N_("-fexec-charset=<cset>  Convert all strings and character constants to character set <cset>"),
-    N_OPTS, 14, CL_SDCPP | CL_JOINED | CL_REJECT_NEGATIVE },
-  { "-finput-charset=",
-    N_("-finput-charset=<cset>      Specify the default character set for source files."),
-    N_OPTS, 15, CL_SDCPP | CL_JOINED | CL_REJECT_NEGATIVE },
-  { "-fpreprocessed",
-    N_("Treat the input file as already preprocessed"),
-    N_OPTS, 13, CL_SDCPP },
-  { "-fshow-column",
-    0,
-    N_OPTS, 12, CL_SDCPP },
-  { "-fsigned-char",
-    N_("Make \"char\" signed by default"),
-    N_OPTS, 12, CL_SDCPP },
-  { "-ftabstop=",
-    N_("-ftabstop=<number>     Distance between tab stops for column reporting"),
-    N_OPTS, 9, CL_SDCPP | CL_JOINED | CL_REJECT_NEGATIVE | CL_UINTEGER },
-  { "-funsigned-char",
-    N_("Make \"char\" unsigned by default"),
-    N_OPTS, 14, CL_SDCPP },
-  { "-fwide-exec-charset=",
-    N_("-fwide-exec-charset=<cset>     Convert all wide strings and character constants to character set <cset>"),
-    N_OPTS, 19, CL_SDCPP | CL_JOINED | CL_REJECT_NEGATIVE },
-  { "-fworking-directory",
-    N_("Generate a #line directive pointing at the current working directory"),
-    N_OPTS, 18, CL_SDCPP },
-  { "-idirafter",
-    N_("-idirafter <dir>       Add <dir> to the end of the system include path"),
-    N_OPTS, 9, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-imacros",
-    N_("-imacros <file>        Accept definition of macros in <file>"),
-    N_OPTS, 7, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-include",
-    N_("-include <file>        Include the contents of <file> before other files"),
-    N_OPTS, 7, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-iprefix",
-    N_("-iprefix <path>        Specify <path> as a prefix for next two options"),
-    N_OPTS, 7, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-isysroot",
-    N_("-isysroot <dir>        Set <dir> to be the system root directory"),
-    N_OPTS, 8, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-isystem",
-    N_("-isystem <dir> Add <dir> to the start of the system include path"),
-    N_OPTS, 7, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-iwithprefix",
-    N_("-iwithprefix <dir>     Add <dir> to the end of the system include path"),
-    N_OPTS, 11, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-iwithprefixbefore",
-    N_("-iwithprefixbefore <dir>       Add <dir> to the end of the main include path"),
-    OPT_iwithprefix, 17, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-lang-asm",
-    0,
-    N_OPTS, 8, CL_UNDOCUMENTED },
-  { "-lang-objc",
-    0,
-    N_OPTS, 9, CL_SDCPP | CL_UNDOCUMENTED },
-  { "-nostdinc",
-    N_("Do not search standard system include directories (those specified with -isystem will still be used)"),
-    N_OPTS, 8, CL_SDCPP },
-  { "-o",
-    N_("-o <file>      Place output into <file>"),
-    N_OPTS, 1, CL_SDCPP | CL_JOINED | CL_SEPARATE },
-  { "-obj-ext=",
-    N_("-obj-ext=<extension>   Define object file extension, used for generation of make dependencies"),
-    OPT_o, 8, CL_SDCPP | CL_JOINED },
-  { "-pedantic",
-    N_("Issue warnings needed for strict compliance to the standard"),
-    N_OPTS, 8, CL_SDCPP },
-  { "-pedantic-errors",
-    N_("Like -pedantic but issue them as errors"),
-    N_OPTS, 15, CL_SDCPP },
-  { "-pedantic-parse-number",
-    N_("Pedantic parse number"),
-    N_OPTS, 21, CL_SDCPP },
-  { "-remap",
-    N_("Remap file names when including files"),
-    N_OPTS, 5, CL_SDCPP },
-  { "-std=c89",
-    N_("Conform to the ISO 1990 C standard"),
-    N_OPTS, 7, CL_SDCPP },
-  { "-std=c99",
-    N_("Conform to the ISO 1999 C standard"),
-    N_OPTS, 7, CL_SDCPP },
-  { "-std=iso9899:1990",
-    N_("Conform to the ISO 1990 C standard"),
-    N_OPTS, 16, 0 },
-  { "-std=iso9899:199409",
-    N_("Conform to the ISO 1990 C standard as amended in 1994"),
-    N_OPTS, 18, CL_SDCPP },
-  { "-std=iso9899:1999",
-    N_("Conform to the ISO 1999 C standard"),
-    N_OPTS, 16, 0 },
-  { "-traditional-cpp",
-    N_("Enable traditional preprocessing"),
-    N_OPTS, 15, CL_SDCPP },
-  { "-trigraphs",
-    N_("-trigraphs     Support ISO C trigraphs"),
-    N_OPTS, 9, CL_SDCPP },
-  { "-v",
-    N_("Enable verbose output"),
-    N_OPTS, 1, CL_SDCPP },
-  { "-w",
-    N_("Suppress warnings"),
-    N_OPTS, 1, CL_SDCPP }
-};
diff --git a/support/cpp2/options_vc_in.h b/support/cpp2/options_vc_in.h
deleted file mode 100644 (file)
index 142b24c..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/* This file is auto-generated by opts.sh.  */
-
-#define CL_SDCPP   (1 << 0)
-
-enum opt_code
-{
-  OPT__help,                              /* --help */
-  OPT__version,                           /* --version */
-  OPT_A,                                  /* -A */
-  OPT_C,                                  /* -C */
-  OPT_CC,                                 /* -CC */
-  OPT_D,                                  /* -D */
-  OPT_H,                                  /* -H */
-  OPT_I,                                  /* -I */
-  OPT_M,                                  /* -M */
-  OPT_MD,                                 /* -MD */
-  OPT_MF,                                 /* -MF */
-  OPT_MG,                                 /* -MG */
-  OPT_MM,                                 /* -MM */
-  OPT_MMD,                                /* -MMD */
-  OPT_MP,                                 /* -MP */
-  OPT_MQ,                                 /* -MQ */
-  OPT_MT,                                 /* -MT */
-  OPT_P,                                  /* -P */
-  OPT_U,                                  /* -U */
-  OPT_Wall,                               /* -Wall */
-  OPT_Wcomment,                           /* -Wcomment */
-  OPT_Wcomments,                          /* -Wcomments */
-  OPT_Wdeprecated,                        /* -Wdeprecated */
-  OPT_Wendif_labels,                      /* -Wendif-labels */
-  OPT_Werror,                             /* -Werror */
-  OPT_Wimport,                            /* -Wimport */
-  OPT_Wsystem_headers,                    /* -Wsystem-headers */
-  OPT_Wtrigraphs,                         /* -Wtrigraphs */
-  OPT_Wundef,                             /* -Wundef */
-  OPT_Wunused_macros,                     /* -Wunused-macros */
-  OPT_ansi,                               /* -ansi */
-  OPT_d,                                  /* -d */
-  OPT_fdollars_in_identifiers,            /* -fdollars-in-identifiers */
-  OPT_fexec_charset_,                     /* -fexec-charset= */
-  OPT_finput_charset_,                    /* -finput-charset= */
-  OPT_fpreprocessed,                      /* -fpreprocessed */
-  OPT_fshow_column,                       /* -fshow-column */
-  OPT_fsigned_char,                       /* -fsigned-char */
-  OPT_ftabstop_,                          /* -ftabstop= */
-  OPT_funsigned_char,                     /* -funsigned-char */
-  OPT_fwide_exec_charset_,                /* -fwide-exec-charset= */
-  OPT_fworking_directory,                 /* -fworking-directory */
-  OPT_idirafter,                          /* -idirafter */
-  OPT_imacros,                            /* -imacros */
-  OPT_include,                            /* -include */
-  OPT_iprefix,                            /* -iprefix */
-  OPT_isysroot,                           /* -isysroot */
-  OPT_isystem,                            /* -isystem */
-  OPT_iwithprefix,                        /* -iwithprefix */
-  OPT_iwithprefixbefore,                  /* -iwithprefixbefore */
-  OPT_lang_asm,                           /* -lang-asm */
-  OPT_lang_objc,                          /* -lang-objc */
-  OPT_nostdinc,                           /* -nostdinc */
-  OPT_o,                                  /* -o */
-  OPT_obj_ext_,                           /* -obj-ext= */
-  OPT_pedantic,                           /* -pedantic */
-  OPT_pedantic_errors,                    /* -pedantic-errors */
-  OPT_pedantic_parse_number,              /* -pedantic-parse-number */
-  OPT_remap,                              /* -remap */
-  OPT_std_c89,                            /* -std=c89 */
-  OPT_std_c99,                            /* -std=c99 */
-  OPT_std_iso9899_1990,                   /* -std=iso9899:1990 */
-  OPT_std_iso9899_199409,                 /* -std=iso9899:199409 */
-  OPT_std_iso9899_1999,                   /* -std=iso9899:1999 */
-  OPT_traditional_cpp,                    /* -traditional-cpp */
-  OPT_trigraphs,                          /* -trigraphs */
-  OPT_v,                                  /* -v */
-  OPT_w,                                  /* -w */
-  N_OPTS
-};
index 5323a32aeab12ae6c7d6b80f3395b2349f476839..20e8cb9545995df8b291210a92bee28e5e32ab34 100644 (file)
@@ -29,9 +29,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 /* True if we should exit after parsing options.  */
 bool exit_after_options;
 
-/* Don't print warning messages.  -w.  */
-bool inhibit_warnings;
-
 /* Treat warnings as errors.  -Werror.  */
 bool warnings_are_errors;
 
@@ -119,14 +116,14 @@ find_opt (const char *input, int lang_mask)
     {
       const struct cl_option *opt = &cl_options[mn];
 
-      /* Is this switch a prefix of the input?  */
-      if (!strncmp (input, opt->opt_text + 1, opt->opt_len))
+      /* Is the input either an exact match or a prefix that takes a
+        joined argument?  */
+      if (!strncmp (input, opt->opt_text + 1, opt->opt_len)
+         && (input[opt->opt_len] == '\0' || (opt->flags & CL_JOINED)))
        {
-         /* If language is OK, and the match is exact or the switch
-            takes a joined argument, return it.  */
-         if ((opt->flags & lang_mask)
-             && (input[opt->opt_len] == '\0' || (opt->flags & CL_JOINED)))
-           return mn;
+         /* If language is OK, return it.  */
+         if (opt->flags & lang_mask)
+
 
          /* If we haven't remembered a prior match, remember this
             one.  Any prior match is necessarily better.  */
@@ -199,7 +196,7 @@ complain_wrong_lang (const char *text, const struct cl_option *option,
   bad_lang = write_langs (lang_mask);
 
   /* Eventually this should become a hard error IMO.  */
-  warning ("command line option \"%s\" is valid for %s but not for %s",
+  warning (0, "command line option \"%s\" is valid for %s but not for %s",
           text, ok_langs, bad_lang);
 
   free (ok_langs);
@@ -220,10 +217,12 @@ handle_option (const char **argv, unsigned int lang_mask)
 
   opt = argv[0];
 
-  /* Drop the "no-" from negative switches.  */
-  if ((opt[1] == 'W' || opt[1] == 'f')
+  opt_index = find_opt (opt + 1, lang_mask | CL_COMMON | CL_TARGET);
+  if (opt_index == cl_options_count
+      && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm')
       && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
     {
+      /* Drop the "no-" from negative switches.  */
       size_t len = strlen (opt) - 3;
 
       dup = xmalloc (len + 1);
@@ -232,9 +231,9 @@ handle_option (const char **argv, unsigned int lang_mask)
       memcpy (dup + 2, opt + 5, len - 2 + 1);
       opt = dup;
       value = 0;
+      opt_index = find_opt (opt + 1, lang_mask | CL_COMMON | CL_TARGET);
     }
 
-  opt_index = find_opt (opt + 1, lang_mask | CL_COMMON);
   if (opt_index == cl_options_count)
     goto done;
 
@@ -248,6 +247,14 @@ handle_option (const char **argv, unsigned int lang_mask)
   /* We've recognized this switch.  */
   result = 1;
 
+  /* Check to see if the option is disabled for this configuration.  */
+  if (option->flags & CL_DISABLED)
+    {
+      error ("command line option %qs"
+            " is not supported by this configuration", opt);
+      goto done;
+    }
+
   /* Sort out any argument the switch takes.  */
   if (option->flags & CL_JOINED)
     {
@@ -278,7 +285,7 @@ handle_option (const char **argv, unsigned int lang_mask)
 
   /* Now we've swallowed any potential argument, complain if this
      is a switch for a different front end.  */
-  if (!(option->flags & (lang_mask | CL_COMMON)))
+  if (!(option->flags & (lang_mask | CL_COMMON | CL_TARGET)))
     {
       complain_wrong_lang (argv[0], option, lang_mask);
       goto done;
@@ -286,7 +293,7 @@ handle_option (const char **argv, unsigned int lang_mask)
 
   if (arg == NULL && (option->flags & (CL_JOINED | CL_SEPARATE)))
     {
-      if (!(*lang_hooks.missing_argument) (opt, opt_index))
+      if (!lang_hooks.missing_argument (opt, opt_index))
        error ("missing argument to \"%s\"", opt);
       goto done;
     }
@@ -303,6 +310,34 @@ handle_option (const char **argv, unsigned int lang_mask)
        }
     }
 
+  if (option->flag_var)
+    switch (option->var_type)
+      {
+      case CLVC_BOOLEAN:
+       *(int *) option->flag_var = value;
+       break;
+
+      case CLVC_EQUAL:
+       *(int *) option->flag_var = (value
+                                    ? option->var_value
+                                    : !option->var_value);
+       break;
+
+      case CLVC_BIT_CLEAR:
+      case CLVC_BIT_SET:
+       if ((value != 0) == (option->var_type == CLVC_BIT_SET))
+         *(int *) option->flag_var |= option->var_value;
+       else
+         *(int *) option->flag_var &= ~option->var_value;
+       ////if (option->flag_var == &target_flags)
+       ////  target_flags_explicit |= option->var_value;
+       break;
+
+      case CLVC_STRING:
+       *(const char **) option->flag_var = arg;
+       break;
+      }
+
   if (option->flags & lang_mask)
     if ((*lang_hooks.handle_option) (opt_index, arg, value) == 0)
       result = 0;
@@ -311,12 +346,25 @@ handle_option (const char **argv, unsigned int lang_mask)
     if (common_handle_option (opt_index, arg, value) == 0)
       result = 0;
 
+  ////if (result && (option->flags & CL_TARGET))
+  ////  if (!targetm.handle_option (opt_index, arg, value))
+  ////    result = 0;
+
  done:
   if (dup)
     free (dup);
   return result;
 }
 
+/* Handle FILENAME from the command line.  */
+void
+add_input_filename (const char *filename)
+{
+  num_in_fnames++;
+  in_fnames = xrealloc (in_fnames, num_in_fnames * sizeof (in_fnames[0]));
+  in_fnames[num_in_fnames - 1] = filename;
+}
+
 /* Decode and handle the vector of command line options.  LANG_MASK
    contains has a single bit set representing the current
    language.  */
@@ -349,15 +397,6 @@ handle_options (unsigned int argc, const char **argv, unsigned int lang_mask)
     }
 }
 
-/* Handle FILENAME from the command line.  */
-void
-add_input_filename (const char *filename)
-{
-  num_in_fnames++;
-  in_fnames = xrealloc (in_fnames, num_in_fnames * sizeof (in_fnames[0]));
-  in_fnames[num_in_fnames - 1] = filename;
-}
-
 /* Parse command line options and set default flag values.  Do minimal
    options processing.  */
 void
@@ -366,7 +405,7 @@ decode_options (unsigned int argc, const char **argv)
   unsigned int lang_mask;
 
   /* Perform language-specific options initialization.  */
-  lang_mask = (*lang_hooks.init_options) (argc, argv);
+  lang_mask = lang_hooks.init_options (argc, argv);
 
   lang_hooks.initialize_diagnostics (global_dc);
 
@@ -377,7 +416,10 @@ decode_options (unsigned int argc, const char **argv)
 }
 
 /* Handle target- and language-independent options.  Return zero to
-   generate an "unknown option" message.  */
+   generate an "unknown option" message.  Only options that need
+   extra handling need to be listed here; if you simply want
+   VALUE assigned to a variable, it happens automatically.  */
+
 static int
 common_handle_option (size_t scode, const char *arg,
                      int value ATTRIBUTE_UNUSED)
@@ -459,7 +501,7 @@ print_filtered_help (unsigned int flag)
   const char *help, *opt, *tab;
   static char *printed;
 
-  if (flag == CL_COMMON)
+  if (flag == CL_COMMON || flag == CL_TARGET)
     {
       filter = flag;
       if (!printed)
@@ -606,3 +648,65 @@ wrap_help (const char *help, const char *item, unsigned int item_width)
     }
   while (remaining);
 }
+
+/* Return 1 if OPTION is enabled, 0 if it is disabled, or -1 if it isn't
+   a simple on-off switch.  */
+
+int
+option_enabled (int opt_idx)
+{
+  const struct cl_option *option = &(cl_options[opt_idx]);
+  if (option->flag_var)
+    switch (option->var_type)
+      {
+      case CLVC_BOOLEAN:
+       return *(int *) option->flag_var != 0;
+
+      case CLVC_EQUAL:
+       return *(int *) option->flag_var == option->var_value;
+
+      case CLVC_BIT_CLEAR:
+       return (*(int *) option->flag_var & option->var_value) == 0;
+
+      case CLVC_BIT_SET:
+       return (*(int *) option->flag_var & option->var_value) != 0;
+
+      case CLVC_STRING:
+       break;
+      }
+  return -1;
+}
+
+/* Fill STATE with the current state of option OPTION.  Return true if
+   there is some state to store.  */
+
+bool
+get_option_state (int option, struct cl_option_state *state)
+{
+  if (cl_options[option].flag_var == 0)
+    return false;
+
+  switch (cl_options[option].var_type)
+    {
+    case CLVC_BOOLEAN:
+    case CLVC_EQUAL:
+      state->data = cl_options[option].flag_var;
+      state->size = sizeof (int);
+      break;
+
+    case CLVC_BIT_CLEAR:
+    case CLVC_BIT_SET:
+      state->ch = option_enabled (option);
+      state->data = &state->ch;
+      state->size = 1;
+      break;
+
+    case CLVC_STRING:
+      state->data = *(const char **) cl_options[option].flag_var;
+      if (state->data == 0)
+       state->data = "";
+      state->size = strlen (state->data) + 1;
+      break;
+    }
+  return true;
+}
index eb7c868120be271f20410f7cef610cec8ef254c7..2c2340c3bdd18c0062f01fa6784eb2a7f8adf1ea 100644 (file)
@@ -1,5 +1,5 @@
 /* Command line option handling.
-   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -15,14 +15,30 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #ifndef GCC_OPTS_H
 #define GCC_OPTS_H
 
-extern void decode_options (unsigned int argc, const char **argv);
-extern void add_input_filename (const char *filename);
+/* Specifies how a switch's VAR_VALUE relates to its FLAG_VAR.  */
+enum cl_var_type {
+  /* The switch is enabled when FLAG_VAR is nonzero.  */
+  CLVC_BOOLEAN,
+
+  /* The switch is enabled when FLAG_VAR == VAR_VALUE.  */
+  CLVC_EQUAL,
+
+  /* The switch is enabled when VAR_VALUE is not set in FLAG_VAR.  */
+  CLVC_BIT_CLEAR,
+
+  /* The switch is enabled when VAR_VALUE is set in FLAG_VAR.  */
+  CLVC_BIT_SET,
+
+  /* The switch takes a string argument and FLAG_VAR points to that
+     argument.  */
+  CLVC_STRING
+};
 
 struct cl_option
 {
@@ -31,12 +47,26 @@ struct cl_option
   unsigned short back_chain;
   unsigned char opt_len;
   unsigned int flags;
+  void *flag_var;
+  enum cl_var_type var_type;
+  int var_value;
+};
+
+/* Records that the state of an option consists of SIZE bytes starting
+   at DATA.  DATA might point to CH in some cases.  */
+struct cl_option_state {
+  const void *data;
+  size_t size;
+  char ch;
 };
 
 extern const struct cl_option cl_options[];
 extern const unsigned int cl_options_count;
 extern const char *const lang_names[];
 
+#define CL_DISABLED            (1 << 21) /* Disabled in this configuration.  */
+#define CL_TARGET              (1 << 22) /* Target-specific option.  */
+#define CL_REPORT              (1 << 23) /* Report argument with -fverbose-asm  */
 #define CL_JOINED              (1 << 24) /* If takes joined argument.  */
 #define CL_SEPARATE            (1 << 25) /* If takes a separate argument.  */
 #define CL_REJECT_NEGATIVE     (1 << 26) /* Reject no- form.  */
@@ -53,4 +83,8 @@ extern const char **in_fnames;
 
 extern unsigned num_in_fnames;
 
+extern void decode_options (unsigned int argc, const char **argv);
+extern int option_enabled (int opt_idx);
+extern bool get_option_state (int, struct cl_option_state *);
+
 #endif
diff --git a/support/cpp2/opts.sh b/support/cpp2/opts.sh
deleted file mode 100755 (executable)
index 871c855..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-#!/bin/sh
-#
-#  Copyright (C) 2003 Free Software Foundation, Inc.
-#  Contributed by Neil Booth, May 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.
-#
-# Usage: opts.sh moveifchange srcdir outfile.c outfile.h file1.opt [ ...]
-
-# Always operate in the C locale.
-LANG=C
-LANGUAGE=C
-LC_ALL=C
-export LANG LANGUAGE LC_ALL
-
-# Set AWK if environment has not already set it.
-AWK=${AWK-awk}
-
-SORT=sort              # Could be /bin/sort or /usr/bin/sort
-
-MOVEIFCHANGE=$1; shift
-C_FILE=$1; shift
-H_FILE=$1; shift
-TMP_C_FILE=tmp-${C_FILE}
-TMP_H_FILE=tmp-${H_FILE}
-
-${AWK} '
-       # Ignore comments and blank lines
-       /^[ \t]*(;|$)/  { next }
-       # Note that RS="" falls foul of gawk 3.1.2 bugs
-       /^[^ \t]/       { record = $0
-                         do { getline tmp;
-                              if (!(tmp ~ "^[ \t]*(;|$)"))
-                                 record = record "\034" tmp
-                         } while (tmp != "")
-                         print record
-                       }
-' "$@" | ${SORT} | ${AWK} '
-    function switch_flags (flags,   result)
-    {
-       flags = " " flags " "
-       result = "0"
-       for (j = 0; j < n_langs; j++) {
-           regex = " " langs[j] " "
-           gsub ( "\\+", "\\+", regex )
-           if (flags ~ regex)
-               result = result " | " macros[j]
-       }
-        if (flags ~ " Common ") result = result " | CL_COMMON"
-        if (flags ~ " Joined ") result = result " | CL_JOINED"
-        if (flags ~ " JoinedOrMissing ") \
-               result = result " | CL_JOINED | CL_MISSING_OK"
-        if (flags ~ " Separate ") result = result " | CL_SEPARATE"
-        if (flags ~ " RejectNegative ") result = result " | CL_REJECT_NEGATIVE"
-        if (flags ~ " UInteger ") result = result " | CL_UINTEGER"
-        if (flags ~ " Undocumented ") result = result " | CL_UNDOCUMENTED"
-       sub( "^0 \\| ", "", result )
-       return result
-    }
-
-    BEGIN {
-       FS = "\034"
-       n_opts = 0
-       n_langs = 0
-    }
-
-# Collect the text and flags of each option into an array
-    {
-       if ($1 == "Language") {
-               langs[n_langs] = $2
-               n_langs++;
-       } else {
-               opts[n_opts] = $1
-               flags[n_opts] = $2
-               help[n_opts] = $3
-               n_opts++;
-       }
-    }
-
-# Dump out an enumeration into a .h file, and an array of options into a
-# C file.  Combine the flags of duplicate options.
-    END {
-       c_file = "'${TMP_C_FILE}'"
-       h_file = "'${TMP_H_FILE}'"
-       realh_file = "'${H_FILE}'"
-       comma = ","
-
-       print "/* This file is auto-generated by opts.sh.  */\n" > c_file
-       print "#include <intl.h>"                       >> c_file
-       print "#include \"" realh_file "\""             >> c_file
-       print "#include \"opts.h\"\n"                   >> c_file
-       print "const char * const lang_names[] =\n{"    >> c_file
-
-       print "/* This file is auto-generated by opts.sh.  */\n" > h_file
-       for (i = 0; i < n_langs; i++) {
-           macros[i] = "CL_" langs[i]
-           gsub( "[^A-Za-z0-9_]", "X", macros[i] )
-           s = substr("         ", length (macros[i]))
-           print "#define " macros[i] s " (1 << " i ")" >> h_file
-           print "  \"" langs[i] "\","                 >> c_file
-       }
-
-       print "  0\n};\n"                               >> c_file
-       print "const unsigned int cl_options_count = N_OPTS;\n" >> c_file
-       print "const struct cl_option cl_options[] =\n{" >> c_file
-
-       print "\nenum opt_code\n{"                      >> h_file
-
-       for (i = 0; i < n_opts; i++)
-           back_chain[i] = "N_OPTS";
-
-       for (i = 0; i < n_opts; i++) {
-           # Combine the flags of identical switches.  Switches
-           # appear many times if they are handled by many front
-           # ends, for example.
-           while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {
-               flags[i + 1] = flags[i] " " flags[i + 1];
-               i++;
-           }
-
-           len = length (opts[i]);
-           enum = "OPT_" opts[i]
-           if (opts[i] == "finline-limit=")
-               enum = enum "eq"
-           gsub ("[^A-Za-z0-9]", "_", enum)
-
-           # If this switch takes joined arguments, back-chain all
-           # subsequent switches to it for which it is a prefix.  If
-           # a later switch S is a longer prefix of a switch T, T
-           # will be back-chained to S in a later iteration of this
-           # for() loop, which is what we want.
-           if (flags[i] ~ "Joined") {
-               for (j = i + 1; j < n_opts; j++) {
-                   if (substr (opts[j], 1, len) != opts[i])
-                       break;
-                   back_chain[j] = enum;
-               }
-           }
-
-           s = substr("                                  ", length (opts[i]))
-           if (i + 1 == n_opts)
-               comma = ""
-
-           if (help[i] == "")
-               hlp = "0"
-           else
-               hlp = "N_(\"" help[i] "\")";
-
-           printf("  %s,%s/* -%s */\n", enum, s, opts[i]) >> h_file
-           printf("  { \"-%s\",\n    %s,\n    %s, %u, %s }%s\n",
-                  opts[i], hlp, back_chain[i], len,
-                  switch_flags(flags[i]), comma)       >> c_file
-       }
-
-       print "  N_OPTS\n};"                            >> h_file
-       print "};"                                      >> c_file
-    }
-'
-
-# Copy the newly generated files back to the correct names only if different.
-# This is to prevent a cascade of file rebuilds when not necessary.
-${MOVEIFCHANGE} ${TMP_H_FILE} ${H_FILE}
-${MOVEIFCHANGE} ${TMP_C_FILE} ${C_FILE}
index 05a3743726f5057e1ce21d7a4a3bb4dfc25ad60a..3cb091fcf931a0099f186deb67556a85dfc6ff82 100644 (file)
@@ -1,7 +1,7 @@
 /* Declarations for insn-output.c.  These functions are defined in recog.c,
    final.c, and varasm.c.
    Copyright (C) 1987, 1991, 1994, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -17,8 +17,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #ifndef GCC_OUTPUT_H
 #define GCC_OUTPUT_H
@@ -49,6 +49,10 @@ extern void init_insn_lengths (void);
    get its actual length.  Otherwise, get its maximum length.  */
 extern int get_attr_length (rtx);
 
+/* Obtain the current length of an insn.  If branch shortening has been done,
+   get its actual length.  Otherwise, get its minimum length.  */
+extern int get_attr_min_length (rtx);
+
 /* Make a pass over all insns and compute their actual lengths by shortening
    any branches of variable length if possible.  */
 extern void shorten_branches (rtx);
@@ -66,12 +70,12 @@ extern void final_start_function (rtx, FILE *, int);
 extern void final_end_function (void);
 
 /* Output assembler code for some insns: all or part of a function.  */
-extern void final (rtx, FILE *, int, int);
+extern void final (rtx, FILE *, int);
 
 /* The final scan for one insn, INSN.  Args are same as in `final', except
    that INSN is the insn being scanned.  Value returned is the next insn to
    be scanned.  */
-extern rtx final_scan_insn (rtx, FILE *, int, int, int, int *);
+extern rtx final_scan_insn (rtx, FILE *, int, int, int *);
 
 /* Replace a SUBREG with a REG or a MEM, based on the thing it is a
    subreg of.  */
@@ -144,24 +148,17 @@ extern void leaf_renumber_regs_insn (rtx);
 /* Locate the proper template for the given insn-code.  */
 extern const char *get_insn_template (int, rtx);
 
-/* Add function NAME to the weak symbols list.  VALUE is a weak alias
-   associated with NAME.  */
-extern int add_weak (tree, const char *, const char *);
-
 /* Functions in flow.c */
-extern void allocate_for_life_analysis (void);
-extern int regno_uninitialized (unsigned int);
 extern int regno_clobbered_at_setjmp (int);
-extern void find_basic_blocks (rtx, int, FILE *);
-extern bool cleanup_cfg (int);
-extern bool delete_unreachable_blocks (void);
-extern void check_function_return_warnings (void);
 
 /* Functions in varasm.c.  */
 
 /* Tell assembler to switch to text section.  */
 extern void text_section (void);
 
+/* Tell assembler to switch to unlikely-to-be-executed text section.  */
+extern void unlikely_text_section (void);
+
 /* Tell assembler to switch to data section.  */
 extern void data_section (void);
 
@@ -172,6 +169,9 @@ extern void readonly_data_section (void);
 /* Determine if we're in the text section.  */
 extern int in_text_section (void);
 
+/* Determine if we're in the unlikely-to-be-executed text section.  */
+extern int in_unlikely_text_section (void);
+
 #ifdef CTORS_SECTION_ASM_OP
 extern void ctors_section (void);
 #endif
@@ -213,6 +213,9 @@ extern void named_section (tree, const char *, int);
 /* Tell assembler to switch to the section for function DECL.  */
 extern void function_section (tree);
 
+/* Tell assembler to switch to the most recently used text section.  */
+extern void current_function_section (tree);
+
 /* Tell assembler to switch to the section for string merging.  */
 extern void mergeable_string_section (tree, unsigned HOST_WIDE_INT,
                                      unsigned int);
@@ -281,7 +284,6 @@ extern void assemble_zeros (unsigned HOST_WIDE_INT);
 
 /* Assemble an alignment pseudo op for an ALIGN-bit boundary.  */
 extern void assemble_align (int);
-extern void assemble_eh_align (int);
 
 /* Assemble a string constant with the specified C string as contents.  */
 extern void assemble_string (const char *, int);
@@ -291,13 +293,17 @@ extern void assemble_external_libcall (rtx);
 
 /* Assemble a label named NAME.  */
 extern void assemble_label (const char *);
-extern void assemble_eh_label (const char *);
 
-/* Output to FILE a reference to the assembler name of a C-level name NAME.
-   If NAME starts with a *, the rest of NAME is output verbatim.
-   Otherwise NAME is transformed in an implementation-defined way
-   (usually by the addition of an underscore).
-   Many macros in the tm file are defined to call this function.  */
+/* Output to FILE (an assembly file) a reference to NAME.  If NAME
+   starts with a *, the rest of NAME is output verbatim.  Otherwise
+   NAME is transformed in a target-specific way (usually by the
+   addition of an underscore).  */
+extern void assemble_name_raw (FILE *, const char *);
+
+/* Like assemble_name_raw, but should be used when NAME might refer to
+   an entity that is also represented as a tree (like a function or
+   variable).  If NAME does refer to such an entity, that entity will
+   be marked as referenced.  */
 extern void assemble_name (FILE *, const char *);
 
 /* Return the assembler directive for creating a given kind of integer
@@ -318,8 +324,8 @@ extern bool default_assemble_integer (rtx, unsigned int, int);
 
 /* Assemble the integer constant X into an object of SIZE bytes.  ALIGN is
    the alignment of the integer in bits.  Return 1 if we were able to output
-   the constant, otherwise 0.  If FORCE is nonzero, abort if we can't output
-   the constant.  */
+   the constant, otherwise 0.  If FORCE is nonzero the constant must
+   be outputable. */
 extern bool assemble_integer (rtx, unsigned, unsigned, int);
 
 /* An interface to assemble_integer for the common case in which a value is
@@ -398,11 +404,6 @@ extern const char *weak_global_object_name;
 
 extern int current_function_is_leaf;
 
-/* Nonzero if function being compiled doesn't contain any instructions
-   that can throw an exception.  This is set prior to final.  */
-
-extern int current_function_nothrow;
-
 /* Nonzero if function being compiled doesn't modify the stack pointer
    (ignoring the prologue and epilogue).  This is only valid after
    life_analysis has run.  */
@@ -418,7 +419,7 @@ extern int current_function_uses_only_leaf_regs;
 /* Default file in which to dump debug output.  */
 
 #ifdef BUFSIZ
-extern FILE *rtl_dump_file;
+extern FILE *dump_file;
 #endif
 
 /* Nonnull if the insn currently being emitted was a COND_EXEC pattern.  */
@@ -428,10 +429,38 @@ extern rtx current_insn_predicate;
 extern rtx current_output_insn;
 
 /* Nonzero while outputting an `asm' with operands.
-   This means that inconsistencies are the user's fault, so don't abort.
+   This means that inconsistencies are the user's fault, so don't die.
    The precise value is the insn being output, to pass to error_for_asm.  */
 extern rtx this_is_asm_operands;
 
+/* Carry information from ASM_DECLARE_OBJECT_NAME
+   to ASM_FINISH_DECLARE_OBJECT.  */
+extern int size_directive_output;
+extern tree last_assemble_variable_decl;
+
+enum in_section { no_section, in_text, in_unlikely_executed_text, in_data,
+                 in_named
+#ifdef BSS_SECTION_ASM_OP
+  , in_bss
+#endif
+#ifdef CTORS_SECTION_ASM_OP
+  , in_ctors
+#endif
+#ifdef DTORS_SECTION_ASM_OP
+  , in_dtors
+#endif
+#ifdef READONLY_DATA_SECTION_ASM_OP
+  , in_readonly_data
+#endif
+#ifdef EXTRA_SECTIONS
+  , EXTRA_SECTIONS
+#endif
+};
+
+extern const char *last_text_section_name;
+extern enum in_section last_text_section;
+extern bool first_function_block_is_cold;
+
 /* Decide whether DECL needs to be in a writable section.
    RELOC is the same as for SELECT_SECTION.  */
 extern bool decl_readonly_section (tree, int);
@@ -475,17 +504,57 @@ extern void no_asm_to_stream (FILE *);
 #define SECTION_NOTYPE  0x80000        /* don't output @progbits */
 #define SECTION_MACH_DEP 0x100000      /* subsequent bits reserved for target */
 
-extern unsigned int get_named_section_flags (const char *);
+/* A helper function for default_elf_select_section and
+   default_elf_unique_section.  Categorizes the DECL.  */
+
+enum section_category
+{
+  SECCAT_TEXT,
+
+  SECCAT_RODATA,
+  SECCAT_RODATA_MERGE_STR,
+  SECCAT_RODATA_MERGE_STR_INIT,
+  SECCAT_RODATA_MERGE_CONST,
+  SECCAT_SRODATA,
+
+  SECCAT_DATA,
+
+  /* To optimize loading of shared programs, define following subsections
+     of data section:
+       _REL    Contains data that has relocations, so they get grouped
+               together and dynamic linker will visit fewer pages in memory.
+       _RO     Contains data that is otherwise read-only.  This is useful
+               with prelinking as most relocations won't be dynamically
+               linked and thus stay read only.
+       _LOCAL  Marks data containing relocations only to local objects.
+               These relocations will get fully resolved by prelinking.  */
+  SECCAT_DATA_REL,
+  SECCAT_DATA_REL_LOCAL,
+  SECCAT_DATA_REL_RO,
+  SECCAT_DATA_REL_RO_LOCAL,
+
+  SECCAT_SDATA,
+  SECCAT_TDATA,
+
+  SECCAT_BSS,
+  SECCAT_SBSS,
+  SECCAT_TBSS
+};
+
+
 extern bool set_named_section_flags (const char *, unsigned int);
-extern void named_section_flags (const char *, unsigned int);
+#define named_section_flags(NAME, FLAGS) \
+  named_section_real((NAME), (FLAGS), /*decl=*/NULL_TREE)
+extern void named_section_real (const char *, unsigned int, tree);
 extern bool named_section_first_declaration (const char *);
 extern unsigned int default_section_type_flags (tree, const char *, int);
 extern unsigned int default_section_type_flags_1 (tree, const char *, int, int);
 
-extern void default_no_named_section (const char *, unsigned int);
-extern void default_elf_asm_named_section (const char *, unsigned int);
-extern void default_coff_asm_named_section (const char *, unsigned int);
-extern void default_pe_asm_named_section (const char *, unsigned int);
+extern void default_no_named_section (const char *, unsigned int, tree);
+extern void default_elf_asm_named_section (const char *, unsigned int, tree);
+extern enum section_category categorize_decl_for_section (tree, int, int);
+extern void default_coff_asm_named_section (const char *, unsigned int, tree);
+extern void default_pe_asm_named_section (const char *, unsigned int, tree);
 
 extern void default_stabs_asm_out_destructor (rtx, int);
 extern void default_named_section_asm_out_destructor (rtx, int);
@@ -500,6 +569,8 @@ extern void default_elf_select_section_1 (tree, int,
                                          unsigned HOST_WIDE_INT, int);
 extern void default_unique_section (tree, int);
 extern void default_unique_section_1 (tree, int, int);
+extern void default_function_rodata_section (tree);
+extern void default_no_function_rodata_section (tree);
 extern void default_select_rtx_section (enum machine_mode, rtx,
                                        unsigned HOST_WIDE_INT);
 extern void default_elf_select_rtx_section (enum machine_mode, rtx,
@@ -509,6 +580,7 @@ extern const char *default_strip_name_encoding (const char *);
 extern bool default_binds_local_p (tree);
 extern bool default_binds_local_p_1 (tree, int);
 extern void default_globalize_label (FILE *, const char *);
+extern void default_emit_unwind_label (FILE *, tree, int, int);
 extern void default_internal_label (FILE *, const char *, unsigned long);
 extern void default_file_start (void);
 extern void file_end_indicate_exec_stack (void);
@@ -516,4 +588,24 @@ extern bool default_valid_pointer_mode (enum machine_mode);
 
 extern int default_address_cost (rtx);
 
+/* dbxout helper functions */
+#if defined DBX_DEBUGGING_INFO || defined XCOFF_DEBUGGING_INFO
+
+extern void dbxout_int (int);
+extern void dbxout_stabd (int, int);
+extern void dbxout_begin_stabn (int);
+extern void dbxout_begin_stabn_sline (int);
+extern void dbxout_begin_empty_stabs (int);
+extern void dbxout_begin_simple_stabs (const char *, int);
+extern void dbxout_begin_simple_stabs_desc (const char *, int, int);
+
+extern void dbxout_stab_value_zero (void);
+extern void dbxout_stab_value_label (const char *);
+extern void dbxout_stab_value_label_diff (const char *, const char *);
+extern void dbxout_stab_value_internal_label (const char *, int *);
+extern void dbxout_stab_value_internal_label_diff (const char *, int *,
+                                                  const char *);
+
+#endif
+
 #endif /* ! GCC_OUTPUT_H */
index 6204ee925e41be564e41be3e0c8c8068f5bea875..a559bcd3a39a3942b9d1e1e22c1ab99ba84093d5 100644 (file)
@@ -1,5 +1,5 @@
 /* Utility to update paths from internal to external forms.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -16,8 +16,8 @@ Library General Public License for more details.
 
 You should have received a copy of the GNU Library General Public
 License along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 /* This file contains routines to update a path, both to canonicalize
    the directory format and to handle any prefix translation.
@@ -122,6 +122,10 @@ save_string (const char *s, int len)
 
 #if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY)
 
+#ifndef WIN32_REGISTRY_KEY
+# define WIN32_REGISTRY_KEY BASEVER
+#endif
+
 /* Look up "key" in the registry, as above.  */
 
 static char *
@@ -155,11 +159,11 @@ lookup_key (char *key)
   size = 32;
   dst = xmalloc (size);
 
-  res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size);
+  res = RegQueryValueExA (reg_key, key, 0, &type, (LPBYTE) dst, &size);
   if (res == ERROR_MORE_DATA && type == REG_SZ)
     {
       dst = xrealloc (dst, size);
-      res = RegQueryValueExA (reg_key, key, 0, &type, dst, &size);
+      res = RegQueryValueExA (reg_key, key, 0, &type, (LPBYTE) dst, &size);
     }
 
   if (type != REG_SZ || res != ERROR_SUCCESS)
@@ -236,16 +240,20 @@ tr (char *string, int c1, int c2)
   while (*string++);
 }
 
-/* Update PATH using KEY if PATH starts with PREFIX.  The returned
-   string is always malloc-ed, and the caller is responsible for
-   freeing it.  */
+/* Update PATH using KEY if PATH starts with PREFIX as a directory.
+   The returned string is always malloc-ed, and the caller is
+   responsible for freeing it.  */
 
 char *
 update_path (const char *path, const char *key)
 {
   char *result, *p;
+  const int len = strlen (std_prefix);
 
-  if (! strncmp (path, std_prefix, strlen (std_prefix)) && key != 0)
+  if (! strncmp (path, std_prefix, len)
+      && (IS_DIR_SEPARATOR(path[len])
+          || path[len] == '\0')
+      && key != 0)
     {
       bool free_key = false;
 
@@ -255,7 +263,7 @@ update_path (const char *path, const char *key)
          free_key = true;
        }
 
-      result = concat (key, &path[strlen (std_prefix)], NULL);
+      result = concat (key, &path[len], NULL);
       if (free_key)
        free ((char *) key);
       result = translate_name (result);
index 25f2115962b899c3fcd3f7d7d78298f9a5b2bbfa..e6e653ad0ce9711619385ce371b7481d86d17fe8 100644 (file)
@@ -15,8 +15,8 @@ Library General Public License for more details.
 
 You should have received a copy of the GNU Library General Public
 License along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 
 #ifndef GCC_PREFIX_H
index 9ef12f23baad3b718a49c5fed554790a82fa979c..ca8d7a91c94edf88ff3726bed89cd50b44aeb60a 100644 (file)
@@ -1,5 +1,5 @@
 /* Various declarations for language-independent pretty-print subroutines.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
    Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
 
 This file is part of GCC.
@@ -16,13 +16,14 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #include "config.h"
 #undef FLOAT /* This is for hpux. They should change hpux.  */
 #undef FFS  /* Some systems define this in param.h.  */
 #include "system.h"
+#include "intl.h"
 #include "pretty-print.h"
 
 #define obstack_chunk_alloc xmalloc
@@ -30,7 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 /* A pointer to the formatted diagnostic message.  */
 #define pp_formatted_text_data(PP) \
-   ((const char *) obstack_base (&pp_base (PP)->buffer->obstack))
+   ((const char *) obstack_base (pp_base (PP)->buffer->obstack))
 
 /* Format an integer given by va_arg (ARG, type-specifier T) where
    type-specifier is a precision modifier as indicated by PREC.  F is
@@ -90,7 +91,7 @@ pp_clear_state (pretty_printer *pp)
 }
 
 /* Flush the formatted text of PRETTY-PRINTER onto the attached stream.  */
-static inline void
+void
 pp_write_text_to_stream (pretty_printer *pp)
 {
   const char *text = pp_formatted_text (pp);
@@ -146,7 +147,7 @@ pp_maybe_wrap_text (pretty_printer *pp, const char *start, const char *end)
 static inline void
 pp_append_r (pretty_printer *pp, const char *start, int length)
 {
-  obstack_grow (&pp->buffer->obstack, start, length);
+  obstack_grow (pp->buffer->obstack, start, length);
   pp->buffer->line_length += length;
 }
 
@@ -163,8 +164,7 @@ pp_base_indent (pretty_printer *pp)
     pp_space (pp);
 }
 
-/* Format a message pointed to by TEXT.  The following format specifiers are
-   recognized as being client independent:
+/* The following format specifiers are recognized as being client independent:
    %d, %i: (signed) integer in base ten.
    %u: unsigned integer in base ten.
    %o: unsigned integer in base eight.
@@ -176,51 +176,250 @@ pp_base_indent (pretty_printer *pp)
    %s: string.
    %p: pointer.
    %m: strerror(text->err_no) - does not consume a value from args_ptr.
-   %%: `%'.
-   %.*s: a substring the length of which is specified by an integer.
-   %H: location_t.  */
+   %%: '%'.
+   %<: opening quote.
+   %>: closing quote.
+   %': apostrophe (should only be used in untranslated messages;
+       translations should use appropriate punctuation directly).
+   %.*s: a substring the length of which is specified by an argument
+        integer.
+   %Ns: likewise, but length specified as constant in the format string.
+   %H: location_t.
+   %J: a decl tree, from which DECL_SOURCE_LOCATION will be recorded.
+   Flag 'q': quote formatted text (must come immediately after '%').
+
+   Arguments can be used sequentially, or through %N$ resp. *N$
+   notation Nth argument after the format string.  If %N$ / *N$
+   notation is used, it must be used for all arguments, except %m, %%,
+   %<, %> and %', which may not have a number, as they do not consume
+   an argument.  When %M$.*N$s is used, M must be N + 1.  (This may
+   also be written %M$.*s, provided N is not otherwise used.)  The
+   format string must have conversion specifiers with argument numbers
+   1 up to highest argument; each argument may only be used once.
+   A format string can have at most 30 arguments.  */
+
+/* Formatting phases 1 and 2: render TEXT->format_spec plus
+   TEXT->args_ptr into a series of chunks in PP->buffer->args[].
+   Phase 3 is in pp_base_format_text.  */
+
 void
-pp_base_format_text (pretty_printer *pp, text_info *text)
+pp_base_format (pretty_printer *pp, text_info *text)
 {
-  for (; *text->format_spec; ++text->format_spec)
+  output_buffer *buffer = pp->buffer;
+  const char *p;
+  const char **args;
+  struct chunk_info *new_chunk_array;
+
+  unsigned int curarg = 0, chunk = 0, argno;
+  pp_wrapping_mode_t old_wrapping_mode;
+  bool any_unnumbered = false, any_numbered = false;
+  const char **formatters[PP_NL_ARGMAX];
+
+  /* Allocate a new chunk structure.  */
+  new_chunk_array = XOBNEW (&buffer->chunk_obstack, struct chunk_info);
+  new_chunk_array->prev = buffer->cur_chunk_array;
+  buffer->cur_chunk_array = new_chunk_array;
+  args = new_chunk_array->args;
+
+  /* Formatting phase 1: split up TEXT->format_spec into chunks in
+     PP->buffer->args[].  Even-numbered chunks are to be output
+     verbatim, odd-numbered chunks are format specifiers.
+     %m, %%, %<, %>, and %' are replaced with the appropriate text at
+     this point.  */
+
+  memset (formatters, 0, sizeof formatters);
+
+  for (p = text->format_spec; *p; )
+    {
+      while (*p != '\0' && *p != '%')
+       {
+         obstack_1grow (&buffer->chunk_obstack, *p);
+         p++;
+       }
+
+      if (*p == '\0')
+       break;
+
+      switch (*++p)
+       {
+       case '\0':
+         gcc_unreachable ();
+
+       case '%':
+         obstack_1grow (&buffer->chunk_obstack, '%');
+         p++;
+         continue;
+
+       case '<':
+         obstack_grow (&buffer->chunk_obstack,
+                       open_quote, strlen (open_quote));
+         p++;
+         continue;
+
+       case '>':
+       case '\'':
+         obstack_grow (&buffer->chunk_obstack,
+                       close_quote, strlen (close_quote));
+         p++;
+         continue;
+
+       case 'm':
+         {
+           const char *errstr = xstrerror (text->err_no);
+           obstack_grow (&buffer->chunk_obstack, errstr, strlen (errstr));
+         }
+         p++;
+         continue;
+
+       default:
+         /* Handled in phase 2.  Terminate the plain chunk here.  */
+         obstack_1grow (&buffer->chunk_obstack, '\0');
+         gcc_assert (chunk < PP_NL_ARGMAX * 2);
+         args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
+         break;
+       }
+
+      if (ISDIGIT (*p))
+       {
+         char *end;
+         argno = strtoul (p, &end, 10) - 1;
+         p = end;
+         gcc_assert (*p == '$');
+         p++;
+
+         any_numbered = true;
+         gcc_assert (!any_unnumbered);
+       }
+      else
+       {
+         argno = curarg++;
+         any_unnumbered = true;
+         gcc_assert (!any_numbered);
+       }
+      gcc_assert (argno < PP_NL_ARGMAX);
+      gcc_assert (!formatters[argno]);
+      formatters[argno] = &args[chunk];
+      do
+       {
+         obstack_1grow (&buffer->chunk_obstack, *p);
+         p++;
+       }
+      while (strchr ("qwl+#", p[-1]));
+
+      if (p[-1] == '.')
+       {
+         /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
+            (where M == N + 1).  */
+         if (ISDIGIT (*p))
+           {
+             do
+               {
+                 obstack_1grow (&buffer->chunk_obstack, *p);
+                 p++;
+               }
+             while (ISDIGIT (p[-1]));
+             gcc_assert (p[-1] == 's');
+           }
+         else
+           {
+             gcc_assert (*p == '*');
+             obstack_1grow (&buffer->chunk_obstack, '*');
+             p++;
+
+             if (ISDIGIT (*p))
+               {
+                 char *end;
+                 unsigned int argno2 = strtoul (p, &end, 10) - 1;
+                 p = end;
+                 gcc_assert (argno2 == argno - 1);
+                 gcc_assert (!any_unnumbered);
+                 gcc_assert (*p == '$');
+
+                 p++;
+                 formatters[argno2] = formatters[argno];
+               }
+             else
+               {
+                 gcc_assert (!any_numbered);
+                 formatters[argno+1] = formatters[argno];
+                 curarg++;
+               }
+             gcc_assert (*p == 's');
+             obstack_1grow (&buffer->chunk_obstack, 's');
+             p++;
+           }
+       }
+      if (*p == '\0')
+       break;
+
+      obstack_1grow (&buffer->chunk_obstack, '\0');
+      gcc_assert (chunk < PP_NL_ARGMAX * 2);
+      args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
+    }
+
+  obstack_1grow (&buffer->chunk_obstack, '\0');
+  gcc_assert (chunk < PP_NL_ARGMAX * 2);
+  args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
+  args[chunk] = 0;
+
+  /* Set output to the argument obstack, and switch line-wrapping and
+     prefixing off.  */
+  buffer->obstack = &buffer->chunk_obstack;
+  old_wrapping_mode = pp_set_verbatim_wrapping (pp);
+
+  /* Second phase.  Replace each formatter with the formatted text it
+     corresponds to.  */
+
+  for (argno = 0; formatters[argno]; argno++)
     {
       int precision = 0;
       bool wide = false;
+      bool plus = false;
+      bool hash = false;
+      bool quote = false;
 
-      /* Ignore text.  */
-      {
-       const char *p = text->format_spec;
-       while (*p && *p != '%')
-         ++p;
-       pp_wrap_text (pp, text->format_spec, p);
-        text->format_spec = p;
-      }
+      /* We do not attempt to enforce any ordering on the modifier
+        characters.  */
 
-      if (*text->format_spec == '\0')
-       break;
+      for (p = *formatters[argno];; p++)
+       {
+         switch (*p)
+           {
+           case 'q':
+             gcc_assert (!quote);
+             quote = true;
+             continue;
+
+           case '+':
+             gcc_assert (!plus);
+             plus = true;
+             continue;
+
+           case '#':
+             gcc_assert (!hash);
+             hash = true;
+             continue;
+
+           case 'w':
+             gcc_assert (!wide);
+             wide = true;
+             continue;
+
+           case 'l':
+             /* We don't support precision beyond that of "long long".  */
+             gcc_assert (precision < 2);
+             precision++;
+             continue;
+           }
+         break;
+       }
+
+      gcc_assert (!wide || precision == 0);
 
-      /* We got a '%'.  Parse precision modifiers, if any.  */
-      switch (*++text->format_spec)
-        {
-        case 'w':
-          wide = true;
-          ++text->format_spec;
-          break;
-
-        case 'l':
-          do
-            ++precision;
-          while (*++text->format_spec == 'l');
-          break;
-
-        default:
-          break;
-        }
-      /* We don't support precision beyond that of "long long".  */
-      if (precision > 2)
-        abort();
-
-      switch (*text->format_spec)
+      if (quote)
+       pp_string (pp, open_quote);
+
+      switch (*p)
        {
        case 'c':
          pp_character (pp, va_arg (*text->args_ptr, int));
@@ -228,92 +427,148 @@ pp_base_format_text (pretty_printer *pp, text_info *text)
 
        case 'd':
        case 'i':
-          if (wide)
-            pp_wide_integer (pp, va_arg (*text->args_ptr, HOST_WIDE_INT));
-          else
-            pp_integer_with_precision
-              (pp, *text->args_ptr, precision, int, "d");
+         if (wide)
+           pp_wide_integer (pp, va_arg (*text->args_ptr, HOST_WIDE_INT));
+         else
+           pp_integer_with_precision
+             (pp, *text->args_ptr, precision, int, "d");
          break;
 
        case 'o':
-          if (wide)
-            pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
-                       va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
-          else
-            pp_integer_with_precision
-              (pp, *text->args_ptr, precision, unsigned, "u");
+         if (wide)
+           pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
+                      va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
+         else
+           pp_integer_with_precision
+             (pp, *text->args_ptr, precision, unsigned, "o");
          break;
 
        case 's':
          pp_string (pp, va_arg (*text->args_ptr, const char *));
          break;
 
-        case 'p':
-          pp_pointer (pp, va_arg (*text->args_ptr, void *));
-          break;
+       case 'p':
+         pp_pointer (pp, va_arg (*text->args_ptr, void *));
+         break;
 
        case 'u':
-          if (wide)
-            pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
-                       va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
-          else
-            pp_integer_with_precision
-              (pp, *text->args_ptr, precision, unsigned, "u");
+         if (wide)
+           pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
+                      va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
+         else
+           pp_integer_with_precision
+             (pp, *text->args_ptr, precision, unsigned, "u");
          break;
 
        case 'x':
-          if (wide)
-            pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
-                       va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
-          else
-            pp_integer_with_precision
-              (pp, *text->args_ptr, precision, unsigned, "x");
+         if (wide)
+           pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
+                      va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
+         else
+           pp_integer_with_precision
+             (pp, *text->args_ptr, precision, unsigned, "x");
          break;
 
-       case 'm':
-         pp_string (pp, xstrerror (text->err_no));
+       case 'H':
+         {
+           location_t *locus = va_arg (*text->args_ptr, location_t *);
+           gcc_assert (text->locus != NULL);
+           *text->locus = *locus;
+         }
          break;
 
-       case '%':
-         pp_character (pp, '%');
+       case 'J':
+         {
+           tree t = va_arg (*text->args_ptr, tree);
+           gcc_assert (text->locus != NULL);
+           *text->locus = DECL_SOURCE_LOCATION (t);
+         }
          break;
 
-        case 'H':
-          {
-            const location_t *locus = va_arg (*text->args_ptr, location_t *);
-            pp_string (pp, "file '");
-            pp_string (pp, locus->file);
-            pp_string (pp, "', line ");
-            pp_decimal_int (pp, locus->line);
-          }
-          break;
-
        case '.':
          {
            int n;
            const char *s;
-           /* We handle no precision specifier but `%.*s'.  */
-           if (*++text->format_spec != '*')
-             abort ();
-           else if (*++text->format_spec != 's')
-             abort ();
-           n = va_arg (*text->args_ptr, int);
+
+           /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
+              (where M == N + 1).  The format string should be verified
+              already from the first phase.  */
+           p++;
+           if (ISDIGIT (*p))
+             {
+               char *end;
+               n = strtoul (p, &end, 10);
+               p = end;
+               gcc_assert (*p == 's');
+             }
+           else
+             {
+               gcc_assert (*p == '*');
+               p++;
+               gcc_assert (*p == 's');
+               n = va_arg (*text->args_ptr, int);
+
+               /* This consumes a second entry in the formatters array.  */
+               gcc_assert (formatters[argno] == formatters[argno+1]);
+               argno++;
+             }
+
            s = va_arg (*text->args_ptr, const char *);
            pp_append_text (pp, s, s + n);
          }
          break;
 
        default:
-          if (!pp_format_decoder (pp) || !(*pp_format_decoder (pp)) (pp, text))
-           {
-             /* Hmmm.  The client failed to install a format translator
-                 but called us with an unrecognized format.  Or, maybe, the
-                 translated string just contains an invalid format, or
-                 has formats in the wrong order.  Sorry.  */
-             abort ();
-           }
+         {
+           bool ok;
+
+           gcc_assert (pp_format_decoder (pp));
+           ok = pp_format_decoder (pp) (pp, text, p,
+                                        precision, wide, plus, hash);
+           gcc_assert (ok);
+         }
        }
+
+      if (quote)
+       pp_string (pp, close_quote);
+
+      obstack_1grow (&buffer->chunk_obstack, '\0');
+      *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *);
     }
+
+#ifdef ENABLE_CHECKING
+  for (; argno < PP_NL_ARGMAX; argno++)
+    gcc_assert (!formatters[argno]);
+#endif
+
+  /* Revert to normal obstack and wrapping mode.  */
+  buffer->obstack = &buffer->formatted_obstack;
+  buffer->line_length = 0;
+  pp_wrapping_mode (pp) = old_wrapping_mode;
+  pp_clear_state (pp);
+}
+
+/* Format of a message pointed to by TEXT.  */
+void
+pp_base_output_formatted_text (pretty_printer *pp)
+{
+  unsigned int chunk;
+  output_buffer *buffer = pp_buffer (pp);
+  struct chunk_info *chunk_array = buffer->cur_chunk_array;
+  const char **args = chunk_array->args;
+
+  gcc_assert (buffer->obstack == &buffer->formatted_obstack);
+  gcc_assert (buffer->line_length == 0);
+
+  /* This is a third phase, first 2 phases done in pp_base_format_args.
+     Now we actually print it.  */
+  for (chunk = 0; args[chunk]; chunk++)
+    pp_string (pp, args[chunk]);
+
+  /* Deallocate the chunk structure and everything after it (i.e. the
+     associated series of formatted strings).  */
+  buffer->cur_chunk_array = chunk_array->prev;
+  obstack_free (&buffer->chunk_obstack, chunk_array);
 }
 
 /* Helper subroutine of output_verbatim and verbatim. Do the appropriate
@@ -321,17 +576,15 @@ pp_base_format_text (pretty_printer *pp, text_info *text)
 void
 pp_base_format_verbatim (pretty_printer *pp, text_info *text)
 {
-  diagnostic_prefixing_rule_t rule = pp_prefixing_rule (pp);
-  int line_cutoff = pp_line_cutoff (pp);
-
   /* Set verbatim mode.  */
-  pp->prefixing_rule = DIAGNOSTICS_SHOW_PREFIX_NEVER;
-  pp_line_cutoff (pp) = 0;
+  pp_wrapping_mode_t oldmode = pp_set_verbatim_wrapping (pp);
+
   /* Do the actual formatting.  */
-  pp_format_text (pp, text);
+  pp_format (pp, text);
+  pp_output_formatted_text (pp);
+
   /* Restore previous settings.  */
-  pp_prefixing_rule (pp) = rule;
-  pp_line_cutoff (pp) = line_cutoff;
+  pp_wrapping_mode (pp) = oldmode;
 }
 
 /* Flush the content of BUFFER onto the attached stream.  */
@@ -359,7 +612,7 @@ pp_base_set_line_maximum_length (pretty_printer *pp, int length)
 void
 pp_base_clear_output_area (pretty_printer *pp)
 {
-  obstack_free (&pp->buffer->obstack, obstack_base (&pp->buffer->obstack));
+  obstack_free (pp->buffer->obstack, obstack_base (pp->buffer->obstack));
   pp->buffer->line_length = 0;
 }
 
@@ -423,7 +676,9 @@ pp_construct (pretty_printer *pp, const char *prefix, int maximum_length)
 {
   memset (pp, 0, sizeof (pretty_printer));
   pp->buffer = xcalloc (1, sizeof (output_buffer));
-  obstack_init (&pp->buffer->obstack);
+  obstack_init (&pp->buffer->chunk_obstack);
+  obstack_init (&pp->buffer->formatted_obstack);
+  pp->buffer->obstack = &pp->buffer->formatted_obstack;
   pp->buffer->stream = stderr;
   pp_line_cutoff (pp) = maximum_length;
   pp_prefixing_rule (pp) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
@@ -454,7 +709,7 @@ pp_base_append_text (pretty_printer *pp, const char *start, const char *end)
 const char *
 pp_base_formatted_text (pretty_printer *pp)
 {
-  obstack_1grow (&pp->buffer->obstack, '\0');
+  obstack_1grow (pp->buffer->obstack, '\0');
   return pp_formatted_text_data (pp);
 }
 
@@ -464,7 +719,7 @@ const char *
 pp_base_last_position_in_text (const pretty_printer *pp)
 {
   const char *p = NULL;
-  struct obstack *text = &pp->buffer->obstack;
+  struct obstack *text = pp->buffer->obstack;
 
   if (obstack_base (text) != obstack_next_free (text))
     p = ((const char *) obstack_next_free (text)) - 1;
@@ -491,7 +746,9 @@ pp_printf (pretty_printer *pp, const char *msg, ...)
   text.err_no = errno;
   text.args_ptr = &ap;
   text.format_spec = msg;
-  pp_format_text (pp, &text);
+  text.locus = NULL;
+  pp_format (pp, &text);
+  pp_output_formatted_text (pp);
   va_end (ap);
 }
 
@@ -507,6 +764,7 @@ pp_verbatim (pretty_printer *pp, const char *msg, ...)
   text.err_no = errno;
   text.args_ptr = &ap;
   text.format_spec = msg;
+  text.locus = NULL;
   pp_format_verbatim (pp, &text);
   va_end (ap);
 }
@@ -517,7 +775,7 @@ pp_verbatim (pretty_printer *pp, const char *msg, ...)
 void
 pp_base_newline (pretty_printer *pp)
 {
-  obstack_1grow (&pp->buffer->obstack, '\n');
+  obstack_1grow (pp->buffer->obstack, '\n');
   pp->buffer->line_length = 0;
 }
 
@@ -532,7 +790,7 @@ pp_base_character (pretty_printer *pp, int c)
       if (ISSPACE (c))
         return;
     }
-  obstack_1grow (&pp->buffer->obstack, c);
+  obstack_1grow (pp->buffer->obstack, c);
   ++pp->buffer->line_length;
 }
 
@@ -544,4 +802,14 @@ pp_base_string (pretty_printer *pp, const char *str)
   pp_maybe_wrap_text (pp, str, str + (str ? strlen (str) : 0));
 }
 
+/* Maybe print out a whitespace if needed.  */
 
+void
+pp_base_maybe_space (pretty_printer *pp)
+{
+  if (pp_base (pp)->padding != pp_none)
+    {
+      pp_space (pp);
+      pp_base (pp)->padding = pp_none;
+    }
+}
index 1691aec274a9a753544bff097f40141538a0db38..b2c6772b7c04f0d7ddb69bfa4acc6ae86813587f 100644 (file)
@@ -1,5 +1,5 @@
 /* Various declarations for language-independent pretty-print subroutines.
-   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
 
 This file is part of GCC.
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #ifndef GCC_PRETTY_PRINT_H
 #define GCC_PRETTY_PRINT_H
@@ -25,6 +25,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "obstack.h"
 #include "input.h"
 
+/* Maximum number of format string arguments.  */
+#define PP_NL_ARGMAX   30
+
 /* The type of a text to be formatted according a format specification
    along with a list of things.  */
 typedef struct
@@ -32,6 +35,7 @@ typedef struct
   const char *format_spec;
   va_list *args_ptr;
   int err_no;  /* for %m */
+  location_t *locus;
 } text_info;
 
 /* How often diagnostics are prefixed by their locations:
@@ -46,12 +50,42 @@ typedef enum
   DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE = 0x2
 } diagnostic_prefixing_rule_t;
 
+/* The chunk_info data structure forms a stack of the results from the
+   first phase of formatting (pp_base_format) which have not yet been
+   output (pp_base_output_formatted_text).  A stack is necessary because
+   the diagnostic starter may decide to generate its own output by way
+   of the formatter.  */
+struct chunk_info
+{
+  /* Pointer to previous chunk on the stack.  */
+  struct chunk_info *prev;
+
+  /* Array of chunks to output.  Each chunk is a NUL-terminated string.
+     In the first phase of formatting, even-numbered chunks are
+     to be output verbatim, odd-numbered chunks are format specifiers.
+     The second phase replaces all odd-numbered chunks with formatted
+     text, and the third phase simply emits all the chunks in sequence
+     with appropriate line-wrapping.  */
+  const char *args[PP_NL_ARGMAX * 2];
+};
+
 /* The output buffer datatype.  This is best seen as an abstract datatype
    whose fields should not be accessed directly by clients.  */
 typedef struct 
 {
-  /* The obstack where the text is built up.  */  
-  struct obstack obstack;
+  /* Obstack where the text is built up.  */  
+  struct obstack formatted_obstack;
+
+  /* Obstack containing a chunked representation of the format
+     specification plus arguments.  */
+  struct obstack chunk_obstack;
+
+  /* Currently active obstack: one of the above two.  This is used so
+     that the text formatters don't need to know which phase we're in.  */
+  struct obstack *obstack;
+
+  /* Stack of chunk arrays.  These come from the chunk_obstack.  */
+  struct chunk_info *cur_chunk_array;
 
   /* Where to output formatted text.  */
   FILE *stream;
@@ -72,11 +106,34 @@ typedef enum
   pp_none, pp_before, pp_after
 } pp_padding;
 
+/* Structure for switching in and out of verbatim mode in a convenient
+   manner.  */
+typedef struct
+{
+  /* Current prefixing rule.  */
+  diagnostic_prefixing_rule_t rule;
+
+  /* The ideal upper bound of number of characters per line, as suggested
+     by front-end.  */  
+  int line_cutoff;
+} pp_wrapping_mode_t;
+
+/* Maximum characters per line in automatic line wrapping mode.
+   Zero means don't wrap lines.  */
+#define pp_line_cutoff(PP)  pp_base (PP)->wrapping.line_cutoff
+
+/* Prefixing rule used in formatting a diagnostic message.  */
+#define pp_prefixing_rule(PP)  pp_base (PP)->wrapping.rule
+
+/* Get or set the wrapping mode as a single entity.  */
+#define pp_wrapping_mode(PP) pp_base (PP)->wrapping
+
 /* The type of a hook that formats client-specific data onto a pretty_pinter.
    A client-supplied formatter returns true if everything goes well,
    otherwise it returns false.  */
 typedef struct pretty_print_info pretty_printer;
-typedef bool (*printer_fn) (pretty_printer *, text_info *);
+typedef bool (*printer_fn) (pretty_printer *, text_info *, const char *,
+                           int, bool, bool, bool);
 
 /* Client supplied function used to decode formats.  */
 #define pp_format_decoder(PP) pp_base (PP)->format_decoder
@@ -85,16 +142,9 @@ typedef bool (*printer_fn) (pretty_printer *, text_info *);
    formatting.  */
 #define pp_needs_newline(PP)  pp_base (PP)->need_newline 
 
-/* Maximum characters per line in automatic line wrapping mode.
-   Zero means don't wrap lines.  */
-#define pp_line_cutoff(PP)  pp_base (PP)->ideal_maximum_length
-
 /* True if PRETTY-PTINTER is in line-wrapping mode.  */
 #define pp_is_wrapping_line(PP) (pp_line_cutoff (PP) > 0)
 
-/* Prefixing rule used in formatting a diagnostic message.  */
-#define pp_prefixing_rule(PP)  pp_base (PP)->prefixing_rule
-
 /* The amount of whitespace to be emitted when starting a new line.  */
 #define pp_indentation(PP) pp_base (PP)->indent_skip
 
@@ -116,15 +166,11 @@ struct pretty_print_info
      account the case of a very very looong prefix.  */  
   int maximum_length;
 
-  /* The ideal upper bound of number of characters per line, as suggested
-     by front-end.  */  
-  int ideal_maximum_length;
-
   /* Indentation count.  */
   int indent_skip;
 
-  /* Current prefixing rule.  */
-  diagnostic_prefixing_rule_t prefixing_rule;
+  /* Current wrapping mode.  */
+  pp_wrapping_mode_t wrapping;
 
   /* If non-NULL, this function formats a TEXT into the BUFFER.  When called,
      TEXT->format_spec points to a format code.  FORMAT_DECODER should call
@@ -158,7 +204,9 @@ struct pretty_print_info
 #define pp_append_text(PP, B, E) \
   pp_base_append_text (pp_base (PP), B, E)
 #define pp_flush(PP)            pp_base_flush (pp_base (PP))
-#define pp_format_text(PP, TI)  pp_base_format_text (pp_base (PP), TI)
+#define pp_format(PP, TI)       pp_base_format (pp_base (PP), TI)
+#define pp_output_formatted_text(PP) \
+  pp_base_output_formatted_text (pp_base (PP))
 #define pp_format_verbatim(PP, TI) \
   pp_base_format_verbatim (pp_base (PP), TI)
 
@@ -205,6 +253,7 @@ struct pretty_print_info
   } while (0)
 #define pp_maybe_newline_and_indent(PP, N) \
   if (pp_needs_newline (PP)) pp_newline_and_indent (PP, N)
+#define pp_maybe_space(PP)   pp_base_maybe_space (pp_base (PP))
 #define pp_separate_with(PP, C)     \
    do {                             \
      pp_character (PP, C);          \
@@ -220,6 +269,8 @@ struct pretty_print_info
 #define pp_decimal_int(PP, I)  pp_scalar (PP, "%d", I)
 #define pp_wide_integer(PP, I) \
    pp_scalar (PP, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) I)
+#define pp_widest_integer(PP, I) \
+   pp_scalar (PP, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT) I)
 #define pp_pointer(PP, P)      pp_scalar (PP, "%p", P)
 
 #define pp_identifier(PP, ID)  pp_string (PP, ID)
@@ -228,7 +279,7 @@ struct pretty_print_info
                  IDENTIFIER_POINTER (T) + IDENTIFIER_LENGTH (T))
 
 #define pp_unsupported_tree(PP, T)                         \
-  pp_verbatim (pp_base (PP), "#`%s' not supported by %s#", \
+  pp_verbatim (pp_base (PP), "#%qs not supported by %s#", \
                tree_code_name[(int) TREE_CODE (T)], __FUNCTION__)
 
 
@@ -247,15 +298,40 @@ extern const char *pp_base_formatted_text (pretty_printer *);
 extern const char *pp_base_last_position_in_text (const pretty_printer *);
 extern void pp_base_emit_prefix (pretty_printer *);
 extern void pp_base_append_text (pretty_printer *, const char *, const char *);
-extern void pp_printf (pretty_printer *, const char *, ...) ATTRIBUTE_PRINTF_2;
-extern void pp_verbatim (pretty_printer *, const char *, ...);
+
+/* This header may be included before toplev.h, hence the duplicate
+   definitions to allow for GCC-specific formats.  */
+#if GCC_VERSION >= 3005
+#define ATTRIBUTE_GCC_PPDIAG(m, n) __attribute__ ((__format__ (__gcc_diag__, m ,n))) ATTRIBUTE_NONNULL(m)
+#else
+#define ATTRIBUTE_GCC_PPDIAG(m, n) ATTRIBUTE_NONNULL(m)
+#endif
+extern void pp_printf (pretty_printer *, const char *, ...)
+     ATTRIBUTE_GCC_PPDIAG(2,3);
+
+extern void pp_verbatim (pretty_printer *, const char *, ...)
+     ATTRIBUTE_GCC_PPDIAG(2,3);
 extern void pp_base_flush (pretty_printer *);
-extern void pp_base_format_text (pretty_printer *, text_info *);
+extern void pp_base_format (pretty_printer *, text_info *);
+extern void pp_base_output_formatted_text (pretty_printer *);
 extern void pp_base_format_verbatim (pretty_printer *, text_info *);
 
 extern void pp_base_indent (pretty_printer *);
 extern void pp_base_newline (pretty_printer *);
 extern void pp_base_character (pretty_printer *, int);
 extern void pp_base_string (pretty_printer *, const char *);
+extern void pp_write_text_to_stream (pretty_printer *pp);
+extern void pp_base_maybe_space (pretty_printer *);
+
+/* Switch into verbatim mode and return the old mode.  */
+static inline pp_wrapping_mode_t
+pp_set_verbatim_wrapping_ (pretty_printer *pp)
+{
+  pp_wrapping_mode_t oldmode = pp_wrapping_mode (pp);
+  pp_line_cutoff (pp) = 0;
+  pp_prefixing_rule (pp) = DIAGNOSTICS_SHOW_PREFIX_NEVER;
+  return oldmode;
+}
+#define pp_set_verbatim_wrapping(PP) pp_set_verbatim_wrapping_ (pp_base (PP))
 
 #endif /* GCC_PRETTY_PRINT_H */
index 8f8e85e024116c6231b289402fb4bfd0dd24b7dd..56d7439963faa1454833d41b912db4c8153e1b8d 100644 (file)
@@ -1,5 +1,5 @@
 /* C/ObjC/C++ command line option handling.
-   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    Contributed by Neil Booth.
 
 This file is part of GCC.
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -27,6 +27,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "c-incpath.h"
 #include "opts.h"
 #include "options.h"
+#include "mkdeps.h"
 
 #ifndef DOLLARS_IN_IDENTIFIERS
 # define DOLLARS_IN_IDENTIFIERS true
@@ -75,6 +76,9 @@ static bool quote_chain_split;
 /* If -Wunused-macros.  */
 static bool warn_unused_macros;
 
+/* If -Wvariadic-macros.  */
+static bool warn_variadic_macros = true;
+
 /* Number of deferred options.  */
 static size_t deferred_count;
 
@@ -132,6 +136,7 @@ sdcpp_common_missing_argument (const char *opt, size_t code)
     case OPT_idirafter:
     case OPT_isysroot:
     case OPT_isystem:
+    case OPT_iquote:
       error ("missing path after \"%s\"", opt);
       break;
 
@@ -166,7 +171,7 @@ defer_opt (enum opt_code code, const char *arg)
 unsigned int
 sdcpp_common_init_options (unsigned int argc, const char **argv ATTRIBUTE_UNUSED)
 {
-  parse_in = cpp_create_reader (CLK_GNUC89, NULL);
+  parse_in = cpp_create_reader (CLK_GNUC89, NULL, &line_table);
 
   cpp_opts = cpp_get_options (parse_in);
   cpp_opts->dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
@@ -176,7 +181,7 @@ sdcpp_common_init_options (unsigned int argc, const char **argv ATTRIBUTE_UNUSED
      before passing on command-line options to cpplib.  */
   cpp_opts->warn_dollars = 0;
 
-  deferred_opts = xmalloc (argc * sizeof (struct deferred_opt));
+  deferred_opts = XNEWVEC (struct deferred_opt, argc);
 
   return CL_SDCPP;
 }
@@ -227,13 +232,14 @@ sdcpp_common_handle_option (size_t scode, const char *arg, int value)
 
     case OPT_I:
       if (strcmp (arg, "-"))
-       add_path (xstrdup (arg), BRACKET, 0);
+       add_path (xstrdup (arg), BRACKET, 0, true);
       else
        {
          if (quote_chain_split)
            error ("-I- specified twice");
          quote_chain_split = true;
          split_quote_chain ();
+         inform ("obsolete option -I- used, please use -iquote instead");
        }
       break;
 
@@ -309,6 +315,7 @@ sdcpp_common_handle_option (size_t scode, const char *arg, int value)
 
     case OPT_Werror:
       cpp_opts->warnings_are_errors = value;
+      global_dc->warning_as_error_requested = value;
       break;
 
     case OPT_Wimport:
@@ -325,6 +332,10 @@ sdcpp_common_handle_option (size_t scode, const char *arg, int value)
       cpp_opts->warn_system_headers = value;
       break;
 
+    case OPT_Wtraditional:
+      cpp_opts->warn_traditional = value;
+      break;
+
     case OPT_Wtrigraphs:
       cpp_opts->warn_trigraphs = value;
       break;
@@ -337,6 +348,10 @@ sdcpp_common_handle_option (size_t scode, const char *arg, int value)
       warn_unused_macros = value;
       break;
 
+    case OPT_Wvariadic_macros:
+      warn_variadic_macros = value;
+      break;
+
     case OPT_ansi:
       set_std_c89 (false, true);
       break;
@@ -361,6 +376,10 @@ sdcpp_common_handle_option (size_t scode, const char *arg, int value)
     case OPT_fpch_deps:
       cpp_opts->restore_pch_deps = value;
       break;
+
+    case OPT_fpch_preprocess:
+      flag_pch_preprocess = value;
+      break;
 #endif
 
     case OPT_fpreprocessed:
@@ -390,7 +409,7 @@ sdcpp_common_handle_option (size_t scode, const char *arg, int value)
       break;
 
     case OPT_idirafter:
-      add_path (xstrdup (arg), AFTER, 0);
+      add_path (xstrdup (arg), AFTER, 0, true);
       break;
 
     case OPT_imacros:
@@ -402,12 +421,16 @@ sdcpp_common_handle_option (size_t scode, const char *arg, int value)
       iprefix = arg;
       break;
 
+    case OPT_iquote:
+      add_path (xstrdup (arg), QUOTE, 0, true);
+      break;
+
     case OPT_isysroot:
       sysroot = arg;
       break;
 
     case OPT_isystem:
-      add_path (xstrdup (arg), SYSTEM, 0);
+      add_path (xstrdup (arg), SYSTEM, 0, true);
       break;
 
     case OPT_iwithprefix:
@@ -459,6 +482,13 @@ sdcpp_common_handle_option (size_t scode, const char *arg, int value)
       cpp_opts->pedantic_parse_number = 1;
       break;
 
+#if 0 // pch not supported by sdcpp
+    case OPT_print_pch_checksum:
+      c_common_print_pch_checksum (stdout);
+      exit_after_options = true;
+      break;
+#endif
+
     case OPT_remap:
       cpp_opts->remap = 1;
       break;
@@ -503,7 +533,7 @@ sdcpp_common_post_options (const char **pfilename)
   /* Canonicalize the input and output filenames.  */
   if (in_fnames == NULL)
     {
-      in_fnames = xmalloc (sizeof (in_fnames[0]));
+      in_fnames = XNEWVEC (const char *, 1);
       in_fnames[0] = "";
     }
   else if (strcmp (in_fnames[0], "-") == 0)
@@ -547,8 +577,7 @@ sdcpp_common_post_options (const char **pfilename)
   cb->dir_change = cb_dir_change;
   cpp_post_options (parse_in);
 
-  saved_lineno = input_line;
-  input_line = 0;
+  input_location = UNKNOWN_LOCATION;
 
   /* If an error has occurred in cpplib, note it so we fail
      immediately.  */
@@ -563,7 +592,7 @@ sdcpp_common_post_options (const char **pfilename)
       return false;
     }
 
-  if (flag_working_directory && ! flag_no_line_commands)
+  if (flag_working_directory && !flag_no_line_commands)
     pp_dir_change (parse_in, get_src_pwd ());
 
   return 1;
@@ -573,8 +602,6 @@ sdcpp_common_post_options (const char **pfilename)
 bool
 sdcpp_common_init (void)
 {
-  input_line = saved_lineno;
-
   /* Default CPP arithmetic to something sensible for the host for the
      benefit of dumb users like fix-header.  */
   cpp_opts->precision = CHAR_BIT * sizeof (long);
@@ -588,6 +615,11 @@ sdcpp_common_init (void)
      are known.  */
   cpp_init_iconv (parse_in);
 
+#if 0
+  if (version_flag)
+    c_common_print_pch_checksum (stderr);
+#endif
+
   finish_options ();
   preprocess_file (parse_in);
   return false;
@@ -666,6 +698,7 @@ check_deps_environment_vars (void)
        deps_file = spec;
 
       deps_append = 1;
+      deps_seen = true;
     }
 }
 
@@ -674,13 +707,22 @@ static void
 handle_deferred_opts (void)
 {
   size_t i;
+  struct deps *deps;
+
+  /* Avoid allocating the deps buffer if we don't need it.
+     (This flag may be true without there having been -MT or -MQ
+     options, but we'll still need the deps buffer.)  */
+  if (!deps_seen)
+    return;
+
+  deps = cpp_get_deps (parse_in);
 
   for (i = 0; i < deferred_count; i++)
     {
       struct deferred_opt *opt = &deferred_opts[i];
 
       if (opt->code == OPT_MT || opt->code == OPT_MQ)
-       cpp_add_dependency_target (parse_in, opt->arg, opt->code == OPT_MQ);
+       deps_add_target (deps, opt->arg, opt->code == OPT_MQ);
     }
 }
 
@@ -713,6 +755,11 @@ sanitize_cpp_opts (void)
   cpp_opts->unsigned_char = !flag_signed_char;
   cpp_opts->stdc_0_in_system_headers = STDC_0_IN_SYSTEM_HEADERS;
 
+  /* Similarly with -Wno-variadic-macros.  No check for c99 here, since
+     this also turns off warnings about GCCs extension.  */
+  cpp_opts->warn_variadic_macros
+    = warn_variadic_macros && (pedantic || warn_traditional);
+
   /* If we're generating preprocessor output, emit current directory
      if explicitly requested  */
   if (flag_working_directory == -1)
@@ -731,12 +778,12 @@ add_prefixed_path (const char *suffix, size_t chain)
   prefix     = iprefix ? iprefix : cpp_GCC_INCLUDE_DIR;
   prefix_len = iprefix ? strlen (iprefix) : cpp_GCC_INCLUDE_DIR_len;
 
-  path = xmalloc (prefix_len + suffix_len + 1);
+  path = (char *) xmalloc (prefix_len + suffix_len + 1);
   memcpy (path, prefix, prefix_len);
   memcpy (path + prefix_len, suffix, suffix_len);
   path[prefix_len + suffix_len] = '\0';
 
-  add_path (path, chain, 0);
+  add_path (path, chain, 0, false);
 }
 
 /* Handle -D, -U, -A, -imacros, and the first -include.  */
@@ -747,7 +794,10 @@ finish_options (void)
     {
       size_t i;
 
-      cpp_change_file (parse_in, LC_RENAME, _("<built-in>"));
+      cb_file_change (parse_in,
+                     linemap_add (&line_table, LC_RENAME, 0,
+                                  _("<built-in>"), 0));
+
       cpp_init_builtins (parse_in, 0 /*flag_hosted*/);
 
       /* We're about to send user input to cpplib, so make it warn for
@@ -806,7 +856,7 @@ push_command_line_include (void)
     {
       struct deferred_opt *opt = &deferred_opts[include_cursor++];
 
-      if (! cpp_opts->preprocessed && opt->code == OPT_include
+      if (!cpp_opts->preprocessed && opt->code == OPT_include
          && cpp_push_include (parse_in, opt->arg))
        return;
     }
@@ -817,19 +867,18 @@ push_command_line_include (void)
       /* -Wunused-macros should only warn about macros defined hereafter.  */
       cpp_opts->warn_unused_macros = warn_unused_macros;
       /* Restore the line map from <command line>.  */
-      if (! cpp_opts->preprocessed)
-       cpp_change_file (parse_in, LC_RENAME, main_input_filename);
+      if (!cpp_opts->preprocessed)
+       cpp_change_file (parse_in, LC_RENAME, this_input_filename);
 
       /* Set this here so the client can change the option if it wishes,
         and after stacking the main file so we don't trace the main file.  */
-      cpp_get_line_maps (parse_in)->trace_includes
-       = cpp_opts->print_include_names;
+      line_table.trace_includes = cpp_opts->print_include_names;
     }
 }
 
 /* File change callback.  Has to handle -include files.  */
 static void
-cb_file_change (cpp_reader *pfile ATTRIBUTE_UNUSED,
+cb_file_change (cpp_reader * ARG_UNUSED (pfile),
                const struct line_map *new_map)
 {
   pp_file_change (new_map);
@@ -839,10 +888,10 @@ cb_file_change (cpp_reader *pfile ATTRIBUTE_UNUSED,
 }
 
 void
-cb_dir_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const char *dir)
+cb_dir_change (cpp_reader * ARG_UNUSED (pfile), const char *dir)
 {
-  if (! set_src_pwd (dir))
-    warning ("too late for # directive to set debug directory");
+  if (!set_src_pwd (dir))
+    warning (0, "too late for # directive to set debug directory");
 }
 
 /* Set the C 89 standard (with 1994 amendments if C94, without GNU
index def45e24128752e965771d27a898558fd9d262b9..794879efd5faa6fcccc288c7997321edcbfb15b4 100644 (file)
@@ -25,7 +25,7 @@
 #include "config.h"
 #include "system.h"
 #include "cpplib.h"
-#include "cpphash.h"
+#include "internal.h"
 #include "version.h"
 #include "mkdeps.h"
 #include "opts.h"
@@ -74,10 +74,16 @@ const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
 
 const char *main_input_filename;
 
+#ifndef USE_MAPPED_LOCATION
+location_t unknown_location = { NULL, 0 };
+#endif
+
 /* Current position in real source file.  */
 
 location_t input_location;
 
+struct line_maps line_table;
+
 /* Stack of currently pending input files.  */
 
 struct file_stack *input_file_stack;
@@ -137,6 +143,14 @@ static const char *src_pwd;
    be called with a NULL argument to test whether src_pwd has NOT been
    initialized yet.  */
 
+/* From intl.c */
+/* Opening quotation mark for diagnostics.  */
+const char *open_quote = "'";
+
+/* Closing quotation mark for diagnostics.  */
+const char *close_quote = "'";
+/* ----------- */
+
 bool
 set_src_pwd (const char *pwd)
 {
@@ -292,7 +306,7 @@ decode_d_option (const char *arg)
        break;
 
       default:
-       warning ("unrecognized gcc debugging option: %c", c);
+       warning (0, "unrecognized gcc debugging option: %c", c);
        break;
       }
 }
index 5b145663b6a0c0d27b94ce46f01529b6fd3a3b4a..75aa885aa4bdf614db933e58d1db67d456f44f72 100644 (file)
@@ -43,7 +43,7 @@ RSC=rc.exe
 # PROP Ignore_Export_Lib 0\r
 # PROP Target_Dir ""\r
 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "." /I ".\libiberty" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FR /FD /D /GZ "HAVE_CONFIG_H" /c\r
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "." /I ".\libiberty" /I ".\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_CONFIG_H" /FR /FD /GZ /c\r
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "." /I ".\libiberty" /I ".\win32" /I ".\sdcpp" /I ".\sdcpp\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_CONFIG_H" /FR /FD /GZ /c\r
 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
 # ADD BASE RSC /l 0x409 /d "_DEBUG"\r
@@ -70,7 +70,7 @@ LINK32=link.exe
 # PROP Ignore_Export_Lib 0\r
 # PROP Target_Dir ""\r
 # ADD BASE CPP /nologo /W3 /GX /O2 /I "." /I ".\libiberty" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c\r
-# ADD CPP /nologo /W3 /GX /O2 /I "." /I ".\libiberty" /I ".\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_CONFIG_H" /D "_WIN32" /FD /c\r
+# ADD CPP /nologo /W3 /GX /O2 /I "." /I ".\libiberty" /I ".\win32" /I ".\sdcpp" /I ".\sdcpp\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_CONFIG_H" /D "_WIN32" /FD /c\r
 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
 # ADD BASE RSC /l 0x409 /d "NDEBUG"\r
@@ -90,82 +90,89 @@ LINK32=link.exe
 # Name "sdcpp - Win32 Release"\r
 # Begin Group "Source Files"\r
 \r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Group "libcpp"\r
+\r
 # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
 # Begin Source File\r
 \r
-SOURCE=".\c-incpath.c"\r
+SOURCE=.\libcpp\charset.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=".\c-ppoutput.c"\r
+SOURCE=.\libcpp\directives.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\libiberty\concat.c\r
+SOURCE=.\libcpp\errors.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\cppcharset.c\r
+SOURCE=.\libcpp\expr.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\cppdefault.c\r
+SOURCE=.\libcpp\files.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\cpperror.c\r
+SOURCE=.\libcpp\identifiers.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\cppexp.c\r
+SOURCE=.\libcpp\init.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\cppfiles.c\r
+SOURCE=.\libcpp\internal.h\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\cpphash.c\r
+SOURCE=.\libcpp\lex.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\cppinit.c\r
+SOURCE=".\libcpp\line-map.c"\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\cpplex.c\r
+SOURCE=.\libcpp\macro.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\cpplib.c\r
+SOURCE=.\libcpp\makeucnid.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\cppmacro.c\r
+SOURCE=.\libcpp\mkdeps.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\cpptrad.c\r
+SOURCE=.\libcpp\symtab.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\diagnostic.c\r
+SOURCE=.\libcpp\system.h\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\win32\dirent.c\r
+SOURCE=.\libcpp\traditional.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\libiberty\getpwd.c\r
+SOURCE=.\libcpp\ucnid.h\r
 # End Source File\r
+# End Group\r
+# Begin Group "libiberty"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
 # Begin Source File\r
 \r
-SOURCE=.\hashtab.c\r
+SOURCE=.\libiberty\concat.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\hashtable.c\r
+SOURCE=.\libiberty\getpwd.c\r
 # End Source File\r
 # Begin Source File\r
 \r
@@ -177,75 +184,92 @@ SOURCE=.\libiberty\lbasename.c
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=".\line-map.c"\r
+SOURCE=.\libiberty\obstack.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\mkdeps.c\r
+SOURCE=".\libiberty\safe-ctype.c"\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\libiberty\obstack.c\r
+SOURCE=".\libiberty\splay-tree.c"\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\options.c\r
+SOURCE=.\libiberty\vasprintf.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\opts.c\r
+SOURCE=.\libiberty\xexit.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\prefix.c\r
+SOURCE=.\libiberty\xmalloc.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=".\pretty-print.c"\r
+SOURCE=.\libiberty\xmemdup.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=".\libiberty\safe-ctype.c"\r
+SOURCE=.\libiberty\xstrdup.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=".\sdcpp-opts.c"\r
+SOURCE=.\libiberty\xstrerror.c\r
+# End Source File\r
+# End Group\r
+# Begin Group "win32"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\win32\dirent.c\r
 # End Source File\r
+# End Group\r
 # Begin Source File\r
 \r
-SOURCE=.\sdcpp.c\r
+SOURCE=".\c-incpath.c"\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=".\libiberty\splay-tree.c"\r
+SOURCE=".\c-ppoutput.c"\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\libiberty\vasprintf.c\r
+SOURCE=.\cppdefault.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\version.c\r
+SOURCE=.\diagnostic.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\libiberty\xexit.c\r
+SOURCE=.\options.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\libiberty\xmalloc.c\r
+SOURCE=.\opts.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\libiberty\xmemdup.c\r
+SOURCE=.\prefix.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\libiberty\xstrdup.c\r
+SOURCE=".\pretty-print.c"\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\libiberty\xstrerror.c\r
+SOURCE=".\sdcpp-opts.c"\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\sdcpp.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\version.c\r
 # End Source File\r
 # End Group\r
 # Begin Group "Header Files"\r
index 9f7ece7592fb120668a7592cfeaa292cdfc9fd23..8b7e7c8c6b75b33bc13050947896e1e3d3e82f55 100644 (file)
@@ -119,7 +119,6 @@ extern const struct lang_hooks lang_hooks;
 #ifndef GCC_DIAG_STYLE
 #define GCC_DIAG_STYLE __gcc_diag__
 #endif
-
 /* None of these functions are suitable for ATTRIBUTE_PRINTF, because
    each language front end can extend them with its own set of format
    specifiers.  We must use custom format checks.  */
@@ -128,10 +127,26 @@ extern const struct lang_hooks lang_hooks;
 #else
 #define ATTRIBUTE_GCC_DIAG(m, n) ATTRIBUTE_NONNULL(m)
 #endif
-extern void warning (const char *, ...);
-extern void error (const char *, ...);
+/* None of these functions are suitable for ATTRIBUTE_PRINTF, because
+   each language front end can extend them with its own set of format
+   specifiers.  We must use custom format checks.  */
+#if GCC_VERSION >= 4001
+#define ATTRIBUTE_GCC_DIAG(m, n) __attribute__ ((__format__ (GCC_DIAG_STYLE, m, n))) ATTRIBUTE_NONNULL(m)
+#else
+#define ATTRIBUTE_GCC_DIAG(m, n) ATTRIBUTE_NONNULL(m)
+#endif
+extern void internal_error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2)
+     ATTRIBUTE_NORETURN;
+extern void warning0 (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
+/* Pass one of the OPT_W* from options.h as the first parameter.  */
+extern void warning (int, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
+extern void error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
 extern void fatal_error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2)
      ATTRIBUTE_NORETURN;
+extern void pedwarn (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
+extern void sorry (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
+extern void inform (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
+extern void verbatim (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
 
 #ifdef BUFSIZ
   /* N.B. Unlike all the others, fnotice is just gettext+fprintf, and
@@ -181,13 +196,10 @@ extern int flag_signed_char;
 
 extern int flag_pedantic_errors;
 
-/* Don't print warning messages.  -w.  */
-
-extern bool inhibit_warnings;
-
 /*
  * From c-common.h
  */
+#include "hwint.h"
 #include "cpplib.h"
 
 /* Nonzero means don't output line number information.  */
index fe06f28a01ddc27939785e8890133d346bb20564..b4d655ad785e02be3f94868e8766059376cfa510 100644 (file)
@@ -1,5 +1,5 @@
 ; Options for the SDCPP front end.
-; Copyright (C) 2003 Free Software Foundation, Inc.
+; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 ;
 ; This file is part of GCC.
 ;
 ;
 ; You should have received a copy of the GNU General Public License
 ; along with GCC; see the file COPYING.  If not, write to the Free
-; Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-; 02111-1307, USA.
-
-
-; This file is processed by the script opts.sh.  It is a database of
-; command line options, with each record separated by a blank line,
-; and each field appearing on its own line.  The first field is the
-; command-line switch with the leading "-" removed.  All options
-; beginning with "f" or "W" are implicitly assumed to take a "no-"
-; form; this form should not be listed.  If you do not want this
-; negative form and you want it to be automatically rejected, add
-; RejectNegative to the second field.
-
-; The second field is a space-separated list of which parts of the
-; compiler recognize the switch, as declared by "Language" entries.
-; If the switch takes an argument, then you should also specify
-; "Joined" and/or "Separate" to indicate where the argument can
-; appear.  If a Joined argument can legitimately be omitted, specify
-; "JoinedOrMissing" instead of "Joined".  If the argument to a switch
-; is a non-negative integer, you can specify "UInteger" and the switch
-; decoder will convert the argument for you, or complain to the user
-; if the argument is invalid.
-
-; The third field is the help text to output with --help.  This is
-; automatically line-wrapped on output.  Normally the switch is output
-; automatically, with the help text on the right hand side of the
-; output.  However, if the help text contains a tab character, the
-; text to the left of the tab is output instead of the switch, and the
-; text to its right forms the help.  This is useful for elaborating on
-; what type of argument a switch takes, for example.  If the second
-; field contains "Undocumented" then nothing is output with --help.
-; Only do this with good reason like the switch being internal between
-; the driver and the front end - it is not an excuse to leave a switch
-; undocumented.
-
-; Comments can appear on their own line anwhere in the file, preceded
-; by a semicolon.  Whitespace is permitted before the semicolon.
-
-; For each switch XXX below, an enumeration constant is created by the
-; script opts.sh spelt OPT_XXX, but with all non-alphanumeric
-; characters replaced with an underscore.
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+; See the GCC internals manual for a description of this file's format.
 
 ; Please try to keep this file in ASCII collating order.
 
@@ -165,6 +128,10 @@ Werror
 SDCPP
 Treat all warnings as errors
 
+Wfatal-errors
+SDCPP Var(flag_fatal_errors)
+Exit on the first error occurred
+
 Wimport
 SDCPP
 Deprecated.  This switch has no effect.
@@ -177,6 +144,10 @@ Wsystem-headers
 SDCPP
 Do not suppress warnings from system headers
 
+Wtraditional
+SDCPP Var(warn_traditional)
+Warn about features not present in traditional C
+
 Wtrigraphs
 SDCPP
 Warn if trigraphs are encountered that might affect the meaning of the program
@@ -189,6 +160,10 @@ Wunused-macros
 SDCPP
 Warn about macros defined in the main file that are not used
 
+Wvariadic-macros
+SDCPP
+Do not warn about using variadic macros when -pedantic
+
 ansi
 SDCPP
 A synonym for -std=c89.
@@ -263,6 +238,10 @@ isystem
 SDCPP Joined Separate
 -isystem <dir> Add <dir> to the start of the system include path
 
+iquote
+SDCPP Joined Separate
+-iquote <dir>  Add <dir> to the end of the quote include path
+
 iwithprefix
 SDCPP Joined Separate
 -iwithprefix <dir>     Add <dir> to the end of the system include path
@@ -290,7 +269,7 @@ SDCPP Joined
 -obj-ext=<extension>   Define object file extension, used for generation of make dependencies
 
 pedantic
-SDCPP
+SDCPP Var(pedantic)
 Issue warnings needed for strict compliance to the standard
 
 pedantic-errors
@@ -337,8 +316,12 @@ v
 SDCPP
 Enable verbose output
 
+;***version
+;***SDCPP Var(version_flag)
+;***Display the compiler's version
+
 w
-SDCPP
+SDCPP Var(inhibit_warnings)
 Suppress warnings
 
 ; This comment is to ensure we retain the blank line above.
index fc97e827511dd9ec493de722aaaeb00cf9013263..6d14bd0a93462faacec74ab2845f4f02d087a015 100644 (file)
@@ -66,7 +66,7 @@ SOURCE=".\auto-host_vc_in.h"
 !IF  "$(CFG)" == "sdcppa - Win32 Release"\r
 \r
 # Begin Custom Build\r
-InputPath=.\auto-host_vc_in.h\r
+InputPath=".\auto-host_vc_in.h"\r
 \r
 "auto-host.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
        copy auto-host_vc_in.h auto-host.h > nul\r
@@ -76,7 +76,7 @@ InputPath=.\auto-host_vc_in.h
 !ELSEIF  "$(CFG)" == "sdcppa - Win32 Debug"\r
 \r
 # Begin Custom Build\r
-InputPath=.\auto-host_vc_in.h\r
+InputPath=".\auto-host_vc_in.h"\r
 \r
 "auto-host.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
        copy auto-host_vc_in.h auto-host.h > nul\r
@@ -88,53 +88,40 @@ InputPath=.\auto-host_vc_in.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=.\options_vc_in.c\r
+SOURCE=.\sdcpp.opt\r
 \r
 !IF  "$(CFG)" == "sdcppa - Win32 Release"\r
 \r
 # Begin Custom Build\r
-InputPath=.\options_vc_in.c\r
+InputPath=.\sdcpp.opt\r
 \r
-"options.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
-       copy options_vc_in.c options.c > nul\r
-\r
-# End Custom Build\r
-\r
-!ELSEIF  "$(CFG)" == "sdcppa - Win32 Debug"\r
-\r
-# Begin Custom Build\r
-InputPath=.\options_vc_in.c\r
+BuildCmds= \\r
+       gawk -f opt-gather.awk sdcpp.opt | gawk -f opt-functions.awk -f optc-gen.awk -v header_name="config.h system.h options.h" > options.c \\r
+       gawk -f opt-gather.awk sdcpp.opt | gawk -f opt-functions.awk -f opth-gen.awk > options.h \\r
+       \r
 \r
 "options.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
-       copy options_vc_in.c options.c > nul\r
-\r
-# End Custom Build\r
-\r
-!ENDIF \r
-\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\options_vc_in.h\r
-\r
-!IF  "$(CFG)" == "sdcppa - Win32 Release"\r
-\r
-# Begin Custom Build\r
-InputPath=.\options_vc_in.h\r
+   $(BuildCmds)\r
 \r
 "options.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
-       copy options_vc_in.h options.h > nul\r
-\r
+   $(BuildCmds)\r
 # End Custom Build\r
 \r
 !ELSEIF  "$(CFG)" == "sdcppa - Win32 Debug"\r
 \r
 # Begin Custom Build\r
-InputPath=.\options_vc_in.h\r
+InputPath=.\sdcpp.opt\r
 \r
-"options.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
-       copy options_vc_in.h options.h > nul\r
+BuildCmds= \\r
+       gawk -f opt-gather.awk sdcpp.opt | gawk -f opt-functions.awk -f optc-gen.awk -v header_name="config.h system.h options.h" > options.c \\r
+       gawk -f opt-gather.awk sdcpp.opt | gawk -f opt-functions.awk -f opth-gen.awk > options.h \\r
+       \r
 \r
+"options.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+   $(BuildCmds)\r
+\r
+"options.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+   $(BuildCmds)\r
 # End Custom Build\r
 \r
 !ENDIF \r
index 61ce1e9b3413244a000045810a9e343f1a99bc96..03a12921042e55db76de39baa0dbd700dcadbb25 100644 (file)
@@ -14,7 +14,7 @@
  
    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 #ifndef SYM_CAT_H
 #define SYM_CAT_H
diff --git a/support/cpp2/system.h b/support/cpp2/system.h
deleted file mode 100644 (file)
index 7226e38..0000000
+++ /dev/null
@@ -1,676 +0,0 @@
-/* Get common system includes and various definitions and declarations based
-   on autoconf macros.
-   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
-   Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
-
-
-#ifndef GCC_SYSTEM_H
-#define GCC_SYSTEM_H
-
-/* We must include stdarg.h before stdio.h.  */
-#include <stdarg.h>
-
-#ifndef va_copy
-# ifdef __va_copy
-#   define va_copy(d,s)  __va_copy((d),(s))
-# else
-#   define va_copy(d,s)  ((d) = (s))
-# endif
-#endif
-
-#ifdef HAVE_STDDEF_H
-# include <stddef.h>
-#endif
-
-#include <stdio.h>
-
-/* Define a generic NULL if one hasn't already been defined.  */
-#ifndef NULL
-#define NULL 0
-#endif
-
-/* The compiler is not a multi-threaded application and therefore we
-   do not have to use the locking functions.  In fact, using the locking
-   functions can cause the compiler to be significantly slower under
-   I/O bound conditions (such as -g -O0 on very large source files).
-
-   HAVE_DECL_PUTC_UNLOCKED actually indicates whether or not the stdio
-   code is multi-thread safe by default.  If it is set to 0, then do
-   not worry about using the _unlocked functions.
-
-   fputs_unlocked, fwrite_unlocked, and fprintf_unlocked are
-   extensions and need to be prototyped by hand (since we do not
-   define _GNU_SOURCE).  */
-
-#if defined HAVE_DECL_PUTC_UNLOCKED && HAVE_DECL_PUTC_UNLOCKED
-
-# ifdef HAVE_PUTC_UNLOCKED
-#  undef putc
-#  define putc(C, Stream) putc_unlocked (C, Stream)
-# endif
-# ifdef HAVE_FPUTC_UNLOCKED
-#  undef fputc
-#  define fputc(C, Stream) fputc_unlocked (C, Stream)
-# endif
-
-# ifdef HAVE_FPUTS_UNLOCKED
-#  undef fputs
-#  define fputs(String, Stream) fputs_unlocked (String, Stream)
-#  if defined (HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED
-extern int fputs_unlocked (const char *, FILE *);
-#  endif
-# endif
-# ifdef HAVE_FWRITE_UNLOCKED
-#  undef fwrite
-#  define fwrite(Ptr, Size, N, Stream) fwrite_unlocked (Ptr, Size, N, Stream)
-#  if defined (HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED
-extern int fwrite_unlocked (const void *, size_t, size_t, FILE *);
-#  endif
-# endif
-# ifdef HAVE_FPRINTF_UNLOCKED
-#  undef fprintf
-/* We can't use a function-like macro here because we don't know if
-   we have varargs macros.  */
-#  define fprintf fprintf_unlocked
-#  if defined (HAVE_DECL_FPRINTF_UNLOCKED) && !HAVE_DECL_FPRINTF_UNLOCKED
-extern int fprintf_unlocked (FILE *, const char *, ...);
-#  endif
-# endif
-
-#endif
-
-/* ??? Glibc's fwrite/fread_unlocked macros cause
-   "warning: signed and unsigned type in conditional expression".  */
-#undef fread_unlocked
-#undef fwrite_unlocked
-
-/* There are an extraordinary number of issues with <ctype.h>.
-   The last straw is that it varies with the locale.  Use libiberty's
-   replacement instead.  */
-#if defined(__APPLE__) && defined(__MACH__)
-#include <libiberty/safe-ctype.h>
-#else
-#include <safe-ctype.h>
-#endif
-
-#include <sys/types.h>
-
-#include <errno.h>
-
-#if !defined (errno) && defined (HAVE_DECL_ERRNO) && !HAVE_DECL_ERRNO
-extern int errno;
-#endif
-
-/* Some of glibc's string inlines cause warnings.  Plus we'd rather
-   rely on (and therefore test) GCC's string builtins.  */
-#define __NO_STRING_INLINES
-
-#ifdef STRING_WITH_STRINGS
-# include <string.h>
-# include <strings.h>
-#else
-# ifdef HAVE_STRING_H
-#  include <string.h>
-# else
-#  ifdef HAVE_STRINGS_H
-#   include <strings.h>
-#  endif
-# endif
-#endif
-
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#endif
-
-/* If we don't have an overriding definition, set SUCCESS_EXIT_CODE and
-   FATAL_EXIT_CODE to EXIT_SUCCESS and EXIT_FAILURE respectively,
-   or 0 and 1 if those macros are not defined.  */
-#ifndef SUCCESS_EXIT_CODE
-# ifdef EXIT_SUCCESS
-#  define SUCCESS_EXIT_CODE EXIT_SUCCESS
-# else
-#  define SUCCESS_EXIT_CODE 0
-# endif
-#endif
-
-#ifndef FATAL_EXIT_CODE
-# ifdef EXIT_FAILURE
-#  define FATAL_EXIT_CODE EXIT_FAILURE
-# else
-#  define FATAL_EXIT_CODE 1
-# endif
-#endif
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-/* We use this identifier later and it appears in some vendor param.h's.  */
-# undef PREFETCH
-#endif
-
-#if HAVE_LIMITS_H
-# include <limits.h>
-#endif
-
-/* Get definitions of HOST_WIDE_INT and HOST_WIDEST_INT.  */
-#include "hwint.h"
-
-/* A macro to determine whether a VALUE lies inclusively within a
-   certain range without evaluating the VALUE more than once.  This
-   macro won't warn if the VALUE is unsigned and the LOWER bound is
-   zero, as it would e.g. with "VALUE >= 0 && ...".  Note the LOWER
-   bound *is* evaluated twice, and LOWER must not be greater than
-   UPPER.  However the bounds themselves can be either positive or
-   negative.  */
-#define IN_RANGE(VALUE, LOWER, UPPER) \
-  ((unsigned HOST_WIDE_INT) ((VALUE) - (LOWER)) <= ((UPPER) - (LOWER)))
-
-/* Infrastructure for defining missing _MAX and _MIN macros.  Note that
-   macros defined with these cannot be used in #if.  */
-
-/* The extra casts work around common compiler bugs.  */
-#define INTTYPE_SIGNED(t) (! ((t) 0 < (t) -1))
-/* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
-   It is necessary at least when t == time_t.  */
-#define INTTYPE_MINIMUM(t) ((t) (INTTYPE_SIGNED (t) \
-                             ? ~ (t) 0 << (sizeof(t) * CHAR_BIT - 1) : (t) 0))
-#define INTTYPE_MAXIMUM(t) ((t) (~ (t) 0 - INTTYPE_MINIMUM (t)))
-
-/* Use that infrastructure to provide a few constants.  */
-#ifndef UCHAR_MAX
-# define UCHAR_MAX INTTYPE_MAXIMUM (unsigned char)
-#endif
-
-#ifdef TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-#  include <sys/time.h>
-# else
-#  ifdef HAVE_TIME_H
-#   include <time.h>
-#  endif
-# endif
-#endif
-
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#else
-# ifdef HAVE_SYS_FILE_H
-#  include <sys/file.h>
-# endif
-#endif
-
-#ifndef SEEK_SET
-# define SEEK_SET 0
-# define SEEK_CUR 1
-# define SEEK_END 2
-#endif
-#ifndef F_OK
-# define F_OK 0
-# define X_OK 1
-# define W_OK 2
-# define R_OK 4
-#endif
-#ifndef O_RDONLY
-# define O_RDONLY 0
-#endif
-#ifndef O_WRONLY
-# define O_WRONLY 1
-#endif
-
-/* Some systems define these in, e.g., param.h.  We undefine these names
-   here to avoid the warnings.  We prefer to use our definitions since we
-   know they are correct.  */
-
-#undef MIN
-#undef MAX
-#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
-#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
-
-/* Returns the least number N such that N * Y >= X.  */
-#define CEIL(x,y) (((x) + (y) - 1) / (y))
-
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-
-#ifndef WIFSIGNALED
-#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
-#endif
-#ifndef WTERMSIG
-#define WTERMSIG(S) ((S) & 0x7f)
-#endif
-#ifndef WIFEXITED
-#define WIFEXITED(S) (((S) & 0xff) == 0)
-#endif
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
-#endif
-#ifndef WSTOPSIG
-#define WSTOPSIG WEXITSTATUS
-#endif
-#ifndef WCOREDUMP
-#define WCOREDUMP(S) ((S) & WCOREFLG)
-#endif
-#ifndef WCOREFLG
-#define WCOREFLG 0200
-#endif
-
-/* The HAVE_DECL_* macros are three-state, undefined, 0 or 1.  If they
-   are defined to 0 then we must provide the relevant declaration
-   here.  These checks will be in the undefined state while configure
-   is running so be careful to test "defined (HAVE_DECL_*)".  */
-
-#if defined (HAVE_DECL_ATOF) && !HAVE_DECL_ATOF
-extern double atof (const char *);
-#endif
-
-#if defined (HAVE_DECL_ATOL) && !HAVE_DECL_ATOL
-extern long atol (const char *);
-#endif
-
-#if defined (HAVE_DECL_FREE) && !HAVE_DECL_FREE
-extern void free (void *);
-#endif
-
-#if defined (HAVE_DECL_GETCWD) && !HAVE_DECL_GETCWD
-extern char *getcwd (char *, size_t);
-#endif
-
-#if defined (HAVE_DECL_GETENV) && !HAVE_DECL_GETENV
-extern char *getenv (const char *);
-#endif
-
-#if defined (HAVE_DECL_GETOPT) && !HAVE_DECL_GETOPT
-extern int getopt (int, char * const *, const char *);
-#endif
-
-#if defined (HAVE_DECL_GETWD) && !HAVE_DECL_GETWD
-extern char *getwd (char *);
-#endif
-
-#if defined (HAVE_DECL_SBRK) && !HAVE_DECL_SBRK
-extern void *sbrk (int);
-#endif
-
-#if defined (HAVE_DECL_STRSTR) && !HAVE_DECL_STRSTR
-extern char *strstr (const char *, const char *);
-#endif
-
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-
-#if defined (HAVE_DECL_MALLOC) && !HAVE_DECL_MALLOC
-extern void *malloc (size_t);
-#endif
-
-#if defined (HAVE_DECL_CALLOC) && !HAVE_DECL_CALLOC
-extern void *calloc (size_t, size_t);
-#endif
-
-#if defined (HAVE_DECL_REALLOC) && !HAVE_DECL_REALLOC
-extern void *realloc (void *, size_t);
-#endif
-
-/* If the system doesn't provide strsignal, we get it defined in
-   libiberty but no declaration is supplied.  */
-/* Disabled since it causes errors on solaris
-#if !defined (HAVE_STRSIGNAL) \
-    || (defined (HAVE_DECL_STRSIGNAL) && !HAVE_DECL_STRSIGNAL)
-# ifndef strsignal
-extern const char *strsignal (int);
-# endif
-#endif
-*/
-
-#ifdef HAVE_GETRLIMIT
-# if defined (HAVE_DECL_GETRLIMIT) && !HAVE_DECL_GETRLIMIT
-#  ifndef getrlimit
-struct rlimit;
-extern int getrlimit (int, struct rlimit *);
-#  endif
-# endif
-#endif
-
-#ifdef HAVE_SETRLIMIT
-# if defined (HAVE_DECL_SETRLIMIT) && !HAVE_DECL_SETRLIMIT
-#  ifndef setrlimit
-struct rlimit;
-extern int setrlimit (int, const struct rlimit *);
-#  endif
-# endif
-#endif
-
-#if defined (HAVE_DECL_ABORT) && !HAVE_DECL_ABORT
-extern void abort (void);
-#endif
-
-#if defined (HAVE_DECL_SNPRINTF) && !HAVE_DECL_SNPRINTF
-extern int snprintf (char *, size_t, const char *, ...);
-#endif
-
-/* 1 if we have C99 designated initializers.  */
-#if !defined(HAVE_DESIGNATED_INITIALIZERS)
-#if defined(__APPLE__) && (__MACH__)
-#define HAVE_DESIGNATED_INITIALIZERS 0
-#else
-#define HAVE_DESIGNATED_INITIALIZERS \
-  ((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L))
-#endif
-#endif
-
-/* 1 if we have _Bool.  */
-#ifndef HAVE__BOOL
-# define HAVE__BOOL \
-   ((GCC_VERSION >= 3000) || (__STDC_VERSION__ >= 199901L))
-#endif
-
-
-#if HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-
-/* Test if something is a normal file.  */
-#ifndef S_ISREG
-#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-#endif
-
-/* Test if something is a directory.  */
-#ifndef S_ISDIR
-#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
-#endif
-
-/* Test if something is a character special file.  */
-#ifndef S_ISCHR
-#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
-#endif
-
-/* Test if something is a block special file.  */
-#ifndef S_ISBLK
-#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
-#endif
-
-/* Test if something is a socket.  */
-#ifndef S_ISSOCK
-# ifdef S_IFSOCK
-#   define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
-# else
-#   define S_ISSOCK(m) 0
-# endif
-#endif
-
-/* Test if something is a FIFO.  */
-#ifndef S_ISFIFO
-# ifdef S_IFIFO
-#  define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
-# else
-#  define S_ISFIFO(m) 0
-# endif
-#endif
-
-/* Approximate O_NONBLOCK.  */
-#ifndef O_NONBLOCK
-#define O_NONBLOCK O_NDELAY
-#endif
-
-/* Approximate O_NOCTTY.  */
-#ifndef O_NOCTTY
-#define O_NOCTTY 0
-#endif
-
-/* Define well known filenos if the system does not define them.  */
-#ifndef STDIN_FILENO
-# define STDIN_FILENO   0
-#endif
-#ifndef STDOUT_FILENO
-# define STDOUT_FILENO  1
-#endif
-#ifndef STDERR_FILENO
-# define STDERR_FILENO  2
-#endif
-
-/* Some systems have mkdir that takes a single argument.  */
-#ifdef MKDIR_TAKES_ONE_ARG
-# define mkdir(a,b) mkdir(a)
-#endif
-
-/* Provide a way to print an address via printf.  */
-#ifndef HOST_PTR_PRINTF
-# ifdef HAVE_PRINTF_PTR
-#  define HOST_PTR_PRINTF "%p"
-# elif SIZEOF_INT == SIZEOF_VOID_P
-#  define HOST_PTR_PRINTF "%x"
-# elif SIZEOF_LONG == SIZEOF_VOID_P
-#  define HOST_PTR_PRINTF "%lx"
-# else
-#  define HOST_PTR_PRINTF "%llx"
-# endif
-#endif /* ! HOST_PTR_PRINTF */
-
-/* By default, colon separates directories in a path.  */
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR ':'
-#endif
-
-/* Filename handling macros.  */
-#include "filenames.h"
-
-/* These should be phased out in favor of IS_DIR_SEPARATOR, where possible.  */
-#ifndef DIR_SEPARATOR
-# define DIR_SEPARATOR '/'
-# ifdef HAVE_DOS_BASED_FILE_SYSTEM
-#  define DIR_SEPARATOR_2 '\\'
-# endif
-#endif
-
-/* Get libiberty declarations.  */
-#include "libiberty.h"
-
-/* Provide a default for the HOST_BIT_BUCKET.
-   This suffices for POSIX-like hosts.  */
-
-#ifndef HOST_BIT_BUCKET
-#define HOST_BIT_BUCKET "/dev/null"
-#endif
-
-/* Be conservative and only use enum bitfields with GCC.
-   FIXME: provide a complete autoconf test for buggy enum bitfields.  */
-
-#if (GCC_VERSION > 2000)
-#define ENUM_BITFIELD(TYPE) __extension__ enum TYPE
-#else
-#define ENUM_BITFIELD(TYPE) unsigned int
-#endif
-
-/* We only use bool bitfields with gcc3.  Some supposedly C99
-   compilers don't handle them correctly.  */
-#if (GCC_VERSION >= 3000)
-#define BOOL_BITFIELD _Bool
-#else
-#define BOOL_BITFIELD unsigned int
-#endif
-
-#ifndef offsetof
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER)
-#endif
-
-/* Various error reporting routines want to use __FUNCTION__.  */
-#if (GCC_VERSION < 2007)
-#ifndef __FUNCTION__
-#define __FUNCTION__ "?"
-#endif /* ! __FUNCTION__ */
-#endif
-
-/* __builtin_expect(A, B) evaluates to A, but notifies the compiler that
-   the most likely value of A is B.  This feature was added at some point
-   between 2.95 and 3.0.  Let's use 3.0 as the lower bound for now.  */
-#if (GCC_VERSION < 3000)
-#define __builtin_expect(a, b) (a)
-#endif
-
-/* Provide some sort of boolean type.  We use stdbool.h if it's
-  available.  This must be after all inclusion of system headers,
-  as some of them will mess us up.  */
-#undef bool
-#undef true
-#undef false
-#undef TRUE
-#undef FALSE
-
-#ifdef HAVE_STDBOOL_H
-# include <stdbool.h>
-#else
-# if !HAVE__BOOL
-typedef char _Bool;
-# endif
-# define bool _Bool
-# define true 1
-# define false 0
-#endif
-
-#define TRUE true
-#define FALSE false
-
-/* As the last action in this file, we poison the identifiers that
-   shouldn't be used.  Note, luckily gcc-3.0's token-based integrated
-   preprocessor won't trip on poisoned identifiers that arrive from
-   the expansion of macros.  E.g. #define strrchr rindex, won't error
-   if rindex is poisoned after this directive is issued and later on
-   strrchr is called.
-
-   Note: We define bypass macros for the few cases where we really
-   want to use the libc memory allocation routines.  Otherwise we
-   insist you use the "x" versions from libiberty.  */
-
-#define really_call_malloc malloc
-#define really_call_calloc calloc
-#define really_call_realloc realloc
-
-#if defined(FLEX_SCANNER) || defined(YYBISON) || defined(YYBYACC)
-/* Flex and bison use malloc and realloc.  Yuk.  Note that this means
-   really_call_* cannot be used in a .l or .y file.  */
-#define malloc xmalloc
-#define realloc xrealloc
-#endif
-
-#if (GCC_VERSION >= 3000)
-
-/* Note autoconf checks for prototype declarations and includes
-   system.h while doing so.  Only poison these tokens if actually
-   compiling gcc, so that the autoconf declaration tests for malloc
-   etc don't spuriously fail.  */
-#ifdef IN_GCC
-#undef calloc
-#undef strdup
- #pragma GCC poison calloc strdup
-
-#if !defined(FLEX_SCANNER) && !defined(YYBISON)
-#undef malloc
-#undef realloc
- #pragma GCC poison malloc realloc
-#endif
-
-/* Old target macros that have moved to the target hooks structure.  */
- #pragma GCC poison ASM_OPEN_PAREN ASM_CLOSE_PAREN                     \
-       FUNCTION_PROLOGUE FUNCTION_EPILOGUE                             \
-       FUNCTION_END_PROLOGUE FUNCTION_BEGIN_EPILOGUE                   \
-       DECL_MACHINE_ATTRIBUTES COMP_TYPE_ATTRIBUTES INSERT_ATTRIBUTES  \
-       VALID_MACHINE_DECL_ATTRIBUTE VALID_MACHINE_TYPE_ATTRIBUTE       \
-       SET_DEFAULT_TYPE_ATTRIBUTES SET_DEFAULT_DECL_ATTRIBUTES         \
-       MERGE_MACHINE_TYPE_ATTRIBUTES MERGE_MACHINE_DECL_ATTRIBUTES     \
-       MD_INIT_BUILTINS MD_EXPAND_BUILTIN ASM_OUTPUT_CONSTRUCTOR       \
-       ASM_OUTPUT_DESTRUCTOR SIGNED_CHAR_SPEC MAX_CHAR_TYPE_SIZE       \
-       WCHAR_UNSIGNED UNIQUE_SECTION SELECT_SECTION SELECT_RTX_SECTION \
-       ENCODE_SECTION_INFO STRIP_NAME_ENCODING ASM_GLOBALIZE_LABEL     \
-       ASM_OUTPUT_MI_THUNK CONST_COSTS RTX_COSTS DEFAULT_RTX_COSTS     \
-       ADDRESS_COST MACHINE_DEPENDENT_REORG ASM_FILE_START ASM_FILE_END \
-       ASM_SIMPLIFY_DWARF_ADDR INIT_TARGET_OPTABS INIT_SUBTARGET_OPTABS \
-       INIT_GOFAST_OPTABS MULSI3_LIBCALL MULDI3_LIBCALL DIVSI3_LIBCALL \
-       DIVDI3_LIBCALL UDIVSI3_LIBCALL UDIVDI3_LIBCALL MODSI3_LIBCALL   \
-       MODDI3_LIBCALL UMODSI3_LIBCALL UMODDI3_LIBCALL BUILD_VA_LIST_TYPE \
-       PRETEND_OUTGOING_VARARGS_NAMED STRUCT_VALUE_INCOMING_REGNUM     \
-       SPLIT_COMPLEX_ARGS
-
-/* Other obsolete target macros, or macros that used to be in target
-   headers and were not used, and may be obsolete or may never have
-   been used.  */
- #pragma GCC poison INT_ASM_OP ASM_OUTPUT_EH_REGION_BEG CPP_PREDEFINES    \
-       ASM_OUTPUT_EH_REGION_END ASM_OUTPUT_LABELREF_AS_INT SMALL_STACK    \
-       DOESNT_NEED_UNWINDER EH_TABLE_LOOKUP OBJC_SELECTORS_WITHOUT_LABELS \
-       OMIT_EH_TABLE EASY_DIV_EXPR IMPLICIT_FIX_EXPR                      \
-       LONGJMP_RESTORE_FROM_STACK MAX_INT_TYPE_SIZE ASM_IDENTIFY_GCC      \
-       STDC_VALUE TRAMPOLINE_ALIGN ASM_IDENTIFY_GCC_AFTER_SOURCE          \
-       SLOW_ZERO_EXTEND SUBREG_REGNO_OFFSET DWARF_LINE_MIN_INSTR_LENGTH   \
-       TRADITIONAL_RETURN_FLOAT NO_BUILTIN_SIZE_TYPE                      \
-       NO_BUILTIN_PTRDIFF_TYPE NO_BUILTIN_WCHAR_TYPE NO_BUILTIN_WINT_TYPE \
-       BLOCK_PROFILER BLOCK_PROFILER_CODE FUNCTION_BLOCK_PROFILER         \
-       FUNCTION_BLOCK_PROFILER_EXIT MACHINE_STATE_SAVE                    \
-       MACHINE_STATE_RESTORE SCCS_DIRECTIVE SECTION_ASM_OP                \
-       ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL ASM_OUTPUT_INTERNAL_LABEL \
-       OBJC_PROLOGUE ALLOCATE_TRAMPOLINE HANDLE_PRAGMA ROUND_TYPE_SIZE    \
-       ROUND_TYPE_SIZE_UNIT CONST_SECTION_ASM_OP CRT_GET_RFIB_TEXT        \
-       DBX_LBRAC_FIRST DBX_OUTPUT_ENUM DBX_OUTPUT_SOURCE_FILENAME         \
-       DBX_WORKING_DIRECTORY INSN_CACHE_DEPTH INSN_CACHE_SIZE             \
-       INSN_CACHE_LINE_WIDTH INIT_SECTION_PREAMBLE NEED_ATEXIT ON_EXIT    \
-       EXIT_BODY OBJECT_FORMAT_ROSE MULTIBYTE_CHARS MAP_CHARACTER         \
-       LIBGCC_NEEDS_DOUBLE FINAL_PRESCAN_LABEL DEFAULT_CALLER_SAVES       \
-       LOAD_ARGS_REVERSED MAX_INTEGER_COMPUTATION_MODE                    \
-       CONVERT_HARD_REGISTER_TO_SSA_P ASM_OUTPUT_MAIN_SOURCE_FILENAME     \
-       FIRST_INSN_ADDRESS TEXT_SECTION SHARED_BSS_SECTION_ASM_OP          \
-       PROMOTED_MODE EXPAND_BUILTIN_VA_END                                \
-       LINKER_DOES_NOT_WORK_WITH_DWARF2
-
-/* Hooks that are no longer used.  */
- #pragma GCC poison LANG_HOOKS_FUNCTION_MARK LANG_HOOKS_FUNCTION_FREE  \
-       LANG_HOOKS_MARK_TREE LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES
-
-/* Libiberty macros that are no longer used in GCC.  */
-#undef ANSI_PROTOTYPES
-#undef PTR_CONST
-#undef LONG_DOUBLE
-#undef VPARAMS
-#undef VA_OPEN
-#undef VA_FIXEDARG
-#undef VA_CLOSE
-#undef VA_START
- #pragma GCC poison ANSI_PROTOTYPES PTR_CONST LONG_DOUBLE VPARAMS VA_OPEN \
-  VA_FIXEDARG VA_CLOSE VA_START
-#endif /* IN_GCC */
-
-/* Note: not all uses of the `index' token (e.g. variable names and
-   structure members) have been eliminated.  */
-#undef bcopy
-#undef bzero
-#undef bcmp
-#undef rindex
- #pragma GCC poison bcopy bzero bcmp rindex
-
-#endif /* GCC >= 3.0 */
-
-/* SDCC specific */
-#include "sdcpp.h"
-
-#endif /* ! GCC_SYSTEM_H */
index 1918d6960a4bb9202445f3169314838c1ca781c4..661dce94e694d3d3aa0cb06909eefdc08f958f40 100644 (file)
@@ -5,7 +5,7 @@
    please modify this string to indicate that, e.g. by putting your
    organization's name in parentheses at the end of the string.  */
 
-const char version_string[] = "3.4.6 + SDCC";
+const char version_string[] = "4.1.1 + SDCC";
 
 /* This is the location of the online document giving instructions for
    reporting bugs.  If you distribute a modified version of GCC,