OSDN Git Service

* cpphash.h (_cpp_digraph_spellings, _cpp_process_directive,
authorneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 25 Sep 2000 22:34:53 +0000 (22:34 +0000)
committerneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 25 Sep 2000 22:34:53 +0000 (22:34 +0000)
_cpp_can_paste): New library-internal prototypes.
* cpplex.c (dump_param_spelling, output_line_command,
output_token, cpp_scan_buffer, cpp_scan_buffer_nooutput,
cpp_printf, cpp_output_list): Move to cppoutput.c.
(process_directive, can_paste, digraph_spellings): Add _cpp_ prefix.
* cppmacro.c (dump_macro_args, cpp_dump_definition) Move to
cppoutput.c.
* cppoutput.c (dump_macro_args, cpp_dump_definition, output_token,
dump_param_spelling, output_line_command, cpp_scan_buffer,
cpp_scan_buffer_nooutput, cpp_printf, cpp_output_list): Moved
from elsewhere.
* Makefile.in: Add cppoutput.c.
* po/POTFILES.in: Add cppoutput.c.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@36634 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/Makefile.in
gcc/cpphash.h
gcc/cpplex.c
gcc/cppmacro.c
gcc/cppoutput.c [new file with mode: 0644]
gcc/po/POTFILES.in

index d80a03c..17a3315 100644 (file)
@@ -1,3 +1,20 @@
+Mon 25-Sep-2000 23:31:45 BST  Neil Booth  <neilb@earthling.net>
+
+       * cpphash.h (_cpp_digraph_spellings, _cpp_process_directive,
+       _cpp_can_paste): New library-internal prototypes.
+       * cpplex.c (dump_param_spelling, output_line_command,
+       output_token, cpp_scan_buffer, cpp_scan_buffer_nooutput,
+       cpp_printf, cpp_output_list): Move to cppoutput.c.
+       (process_directive, can_paste, digraph_spellings): Add _cpp_ prefix.
+       * cppmacro.c (dump_macro_args, cpp_dump_definition) Move to
+       cppoutput.c.
+       * cppoutput.c (dump_macro_args, cpp_dump_definition, output_token,
+       dump_param_spelling, output_line_command, cpp_scan_buffer,
+       cpp_scan_buffer_nooutput, cpp_printf, cpp_output_list): Moved
+       from elsewhere.
+       * Makefile.in: Add cppoutput.c.
+       * po/POTFILES.in: Add cppoutput.c.
+
 2000-09-25  Richard Henderson  <rth@cygnus.com>
 
        * config/ia64/ia64.c (ia64_print_operand): Define 'e' as 64-n.
index 953fab1..f5cd9dc 100644 (file)
@@ -1792,7 +1792,7 @@ PREPROCESSOR_DEFINES = \
   -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\"
 
 LIBCPP_OBJS =  cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o \
-               cpphash.o cpperror.o cppinit.o cppdefault.o \
+               cpphash.o cpperror.o cppinit.o cppdefault.o cppoutput.o \
                mkdeps.o prefix.o version.o mbchar.o @extra_cpp_objs@
 
 LIBCPP_DEPS =  cpplib.h cpphash.h intl.h system.h
@@ -1814,6 +1814,7 @@ cpperror.o: cpperror.c $(CONFIG_H) $(LIBCPP_DEPS)
 cppexp.o:   cppexp.c   $(CONFIG_H) $(LIBCPP_DEPS) defaults.h
 cpplex.o:   cpplex.c   $(CONFIG_H) $(LIBCPP_DEPS)
 cppmacro.o: cppmacro.c $(CONFIG_H) $(LIBCPP_DEPS)
+cppoutput.o: cppoutput.c $(CONFIG_H) $(LIBCPP_DEPS)
 cpplib.o:   cpplib.c   $(CONFIG_H) $(LIBCPP_DEPS) $(OBSTACK_H)
 cpphash.o:  cpphash.c  $(CONFIG_H) $(LIBCPP_DEPS) $(OBSTACK_H)
 cppfiles.o: cppfiles.c $(CONFIG_H) $(LIBCPP_DEPS) $(SPLAY_TREE_H) mkdeps.h
index 8f569e7..fed1cf4 100644 (file)
@@ -231,6 +231,7 @@ extern void _cpp_pop_file_buffer    PARAMS ((cpp_reader *, cpp_buffer *));
 extern int _cpp_parse_expr             PARAMS ((cpp_reader *));
 
 /* In cpplex.c */
+extern const unsigned char *_cpp_digraph_spellings[];
 extern void _cpp_skip_rest_of_line     PARAMS ((cpp_reader *));
 extern void _cpp_free_temp_tokens      PARAMS ((cpp_reader *));
 extern void _cpp_init_input_buffer     PARAMS ((cpp_reader *));
@@ -247,6 +248,7 @@ extern void _cpp_reserve_name_space PARAMS ((cpp_toklist *, unsigned int));
 extern void _cpp_expand_name_space     PARAMS ((cpp_toklist *, unsigned int));
 extern int _cpp_equiv_tokens           PARAMS ((const cpp_token *,
                                                 const cpp_token *));
+extern void _cpp_process_directive PARAMS ((cpp_reader *, const cpp_token *));
 extern void _cpp_run_directive         PARAMS ((cpp_reader *,
                                                 const struct directive *,
                                                 const char *, size_t,
@@ -257,6 +259,8 @@ extern const cpp_token *_cpp_get_token PARAMS ((cpp_reader *));
 extern const cpp_token *_cpp_get_raw_token PARAMS ((cpp_reader *));
 extern void _cpp_push_token PARAMS ((cpp_reader *, const cpp_token*));
 extern const cpp_token *_cpp_glue_header_name PARAMS ((cpp_reader *));
+extern enum cpp_ttype _cpp_can_paste PARAMS ((cpp_reader *, const cpp_token *,
+                                             const cpp_token *, int *));
 
 /* In cpplib.c */
 extern const struct directive *_cpp_check_directive
index 720574b..c07c721 100644 (file)
@@ -41,6 +41,8 @@ o Correct pastability test for CPP_NAME and CPP_NUMBER.
 #include "cpphash.h"
 #include "symcat.h"
 
+const unsigned char *_cpp_digraph_spellings [] = {U"%:", U"%:%:", U"<:",
+                                                 U":>", U"<%", U"%>"};
 static const cpp_token placemarker_token = {0, 0, CPP_PLACEMARKER,
                                            0 UNION_INIT_ZERO};
 static const cpp_token eof_token = {0, 0, CPP_EOF, 0 UNION_INIT_ZERO};
@@ -90,10 +92,6 @@ static int pop_context PARAMS ((cpp_reader *));
 static int push_macro_context PARAMS ((cpp_reader *, const cpp_token *));
 static void push_arg_context PARAMS ((cpp_reader *, const cpp_token *));
 static void free_macro_args PARAMS ((macro_args *));
-static void dump_param_spelling PARAMS ((FILE *, const cpp_toklist *,
-                                        unsigned int));
-static void output_line_command PARAMS ((cpp_reader *, cpp_printer *,
-                                        unsigned int));
 
 static cppchar_t handle_newline PARAMS ((cpp_buffer *, cppchar_t));
 static cppchar_t skip_escaped_newlines PARAMS ((cpp_buffer *, cppchar_t));
@@ -115,7 +113,6 @@ static void lex_line PARAMS ((cpp_reader *, cpp_toklist *));
 static void lex_token PARAMS ((cpp_reader *, cpp_token *));
 static int lex_next PARAMS ((cpp_reader *, int));
 
-static void process_directive  PARAMS ((cpp_reader *, const cpp_token *));
 static int is_macro_disabled PARAMS ((cpp_reader *, const cpp_toklist *,
                                      const cpp_token *));
 
@@ -123,8 +120,6 @@ static cpp_token *stringify_arg PARAMS ((cpp_reader *, const cpp_token *));
 static void expand_context_stack PARAMS ((cpp_reader *));
 static unsigned char * spell_token PARAMS ((cpp_reader *, const cpp_token *,
                                            unsigned char *));
-static void output_token PARAMS ((cpp_reader *, FILE *, const cpp_token *,
-                                 const cpp_token *, int));
 typedef unsigned int (* speller) PARAMS ((unsigned char *, cpp_toklist *,
                                          cpp_token *));
 static cpp_token *make_string_token PARAMS ((cpp_token *, const U_CHAR *,
@@ -135,14 +130,11 @@ static const cpp_token *special_symbol PARAMS ((cpp_reader *, cpp_hashnode *,
 static cpp_token *duplicate_token PARAMS ((cpp_reader *, const cpp_token *));
 static const cpp_token *maybe_paste_with_next PARAMS ((cpp_reader *,
                                                       const cpp_token *));
-static enum cpp_ttype can_paste PARAMS ((cpp_reader *, const cpp_token *,
-                                        const cpp_token *, int *));
 static unsigned int prevent_macro_expansion    PARAMS ((cpp_reader *));
 static void restore_macro_expansion    PARAMS ((cpp_reader *, unsigned int));
 static cpp_token *get_temp_token       PARAMS ((cpp_reader *));
 static void release_temp_tokens                PARAMS ((cpp_reader *));
 static U_CHAR * quote_string PARAMS ((U_CHAR *, const U_CHAR *, unsigned int));
-static void process_directive PARAMS ((cpp_reader *, const cpp_token *));
 
 #define VALID_SIGN(c, prevc) \
   (((c) == '+' || (c) == '-') && \
@@ -194,167 +186,6 @@ _cpp_token_spellings [N_TTYPES] = {TTYPE_TABLE };
 #undef OP
 #undef TK
 
-/* Notify the compiler proper that the current line number has jumped,
-   or the current file name has changed.  */
-
-static void
-output_line_command (pfile, print, line)
-     cpp_reader *pfile;
-     cpp_printer *print;
-     unsigned int line;
-{
-  cpp_buffer *ip = CPP_BUFFER (pfile);
-
-  if (line == 0)
-    return;
-
-  /* End the previous line of text.  */
-  if (pfile->need_newline)
-    {
-      putc ('\n', print->outf);
-      print->lineno++;
-    }
-  pfile->need_newline = 0;
-
-  if (CPP_OPTION (pfile, no_line_commands))
-    return;
-
-  /* If the current file has not changed, we can output a few newlines
-     instead if we want to increase the line number by a small amount.
-     We cannot do this if print->lineno is zero, because that means we
-     haven't output any line commands yet.  (The very first line
-     command output is a `same_file' command.)
-
-     'nominal_fname' values are unique, so they can be compared by
-     comparing pointers.  */
-  if (ip->nominal_fname == print->last_fname && print->lineno > 0
-      && line >= print->lineno && line < print->lineno + 8)
-    {
-      while (line > print->lineno)
-       {
-         putc ('\n', print->outf);
-         print->lineno++;
-       }
-      return;
-    }
-
-  fprintf (print->outf, "# %u \"%s\"%s\n", line, ip->nominal_fname,
-          cpp_syshdr_flags (pfile, ip));
-
-  print->last_fname = ip->nominal_fname;
-  print->lineno = line;
-}
-
-/* Like fprintf, but writes to a printer object.  You should be sure
-   always to generate a complete line when you use this function.  */
-void
-cpp_printf VPARAMS ((cpp_reader *pfile, cpp_printer *print,
-                    const char *fmt, ...))
-{
-  va_list ap;
-#ifndef ANSI_PROTOTYPES
-  cpp_reader *pfile;
-  cpp_printer *print;
-  const char *fmt;
-#endif
-
-  VA_START (ap, fmt);
-
-#ifndef ANSI_PROTOTYPES
-  pfile = va_arg (ap, cpp_reader *);
-  print = va_arg (ap, cpp_printer *);
-  fmt = va_arg (ap, const char *);
-#endif
-
-  /* End the previous line of text.  */
-  if (pfile->need_newline)
-    {
-      putc ('\n', print->outf);
-      print->lineno++;
-    }
-  pfile->need_newline = 0;
-
-  vfprintf (print->outf, fmt, ap);
-  va_end (ap);
-}
-
-/* Scan until CPP_BUFFER (PFILE) is exhausted, discarding output.  */
-
-void
-cpp_scan_buffer_nooutput (pfile)
-     cpp_reader *pfile;
-{
-  cpp_buffer *stop = CPP_PREV_BUFFER (CPP_BUFFER (pfile));
-  const cpp_token *token;
-
-  /* In no-output mode, we can ignore everything but directives.  */
-  for (;;)
-    {
-      token = _cpp_get_token (pfile);
-
-      if (token->type == CPP_EOF)
-       {
-         cpp_pop_buffer (pfile);
-         if (CPP_BUFFER (pfile) == stop)
-           break;
-       }
-
-      if (token->type == CPP_HASH && token->flags & BOL
-         && pfile->token_list.directive)
-       {
-         process_directive (pfile, token);
-         continue;
-       }
-
-      _cpp_skip_rest_of_line (pfile);
-    }
-}
-
-/* Scan until CPP_BUFFER (pfile) is exhausted, writing output to PRINT.  */
-void
-cpp_scan_buffer (pfile, print)
-     cpp_reader *pfile;
-     cpp_printer *print;
-{
-  cpp_buffer *stop = CPP_PREV_BUFFER (CPP_BUFFER (pfile));
-  const cpp_token *token, *prev = 0;
-
-  for (;;)
-    {
-      token = _cpp_get_token (pfile);
-      if (token->type == CPP_EOF)
-       {
-         cpp_pop_buffer (pfile);
-
-         if (CPP_BUFFER (pfile) == stop)
-           return;
-
-         prev = 0;
-         continue;
-       }
-
-      if (token->flags & BOL)
-       {
-         output_line_command (pfile, print, token->line);
-         prev = 0;
-
-         if (token->type == CPP_HASH && pfile->token_list.directive)
-           {
-             process_directive (pfile, token);
-             continue;
-           }
-       }
-
-      if (token->type != CPP_PLACEMARKER)
-       {
-         output_token (pfile, print->outf, token, prev, 1);
-         pfile->need_newline = 1;
-       }
-
-      prev = token;
-    }
-}
-
 /* Helper routine used by parse_include, which can't see spell_token.
    Reinterpret the current line as an h-char-sequence (< ... >); we are
    looking at the first token after the <.  */
@@ -564,9 +395,6 @@ cpp_ideq (token, string)
   return !ustrcmp (token->val.node->name, (const U_CHAR *)string);
 }
 
-static const unsigned char *digraph_spellings [] = {U"%:", U"%:%:", U"<:",
-                                                   U":>", U"<%", U"%>"};
-
 /* Call when meeting a newline.  Returns the character after the newline
    (or carriage-return newline combination), or EOF.  */
 static cppchar_t
@@ -1714,152 +1542,6 @@ lex_line (pfile, list)
   pfile->state.in_lex_line = 0;
 }
 
-/* Write the spelling of a token TOKEN, with any appropriate
-   whitespace before it, to FP.  PREV is the previous token, which
-   is used to determine if we need to shove in an extra space in order
-   to avoid accidental token paste.  If WHITE is 0, do not insert any
-   leading whitespace.  */
-static void
-output_token (pfile, fp, token, prev, white)
-     cpp_reader *pfile;
-     FILE *fp;
-     const cpp_token *token, *prev;
-     int white;
-{
-  if (white)
-    {
-      int dummy;
-
-      if (token->col && (token->flags & BOL))
-       {
-         /* Supply enough whitespace to put this token in its original
-            column.  Don't bother trying to reconstruct tabs; we can't
-            get it right in general, and nothing ought to care.  (Yes,
-            some things do care; the fault lies with them.)  */
-         unsigned int spaces = token->col - 1;
-      
-         while (spaces--)
-           putc (' ', fp);
-       }
-      else if (token->flags & PREV_WHITE)
-       putc (' ', fp);
-      else
-      /* Check for and prevent accidental token pasting.
-        In addition to the cases handled by can_paste, consider
-
-        a + ++b - if there is not a space between the + and ++, it
-        will be misparsed as a++ + b.  But + ## ++ doesn't produce
-        a valid token.  */
-       if (prev
-           && (can_paste (pfile, prev, token, &dummy) != CPP_EOF
-               || (prev->type == CPP_PLUS && token->type == CPP_PLUS_PLUS)
-               || (prev->type == CPP_MINUS && token->type == CPP_MINUS_MINUS)))
-       putc (' ', fp);
-    }
-
-  switch (TOKEN_SPELL (token))
-    {
-    case SPELL_OPERATOR:
-      {
-       const unsigned char *spelling;
-
-       if (token->flags & DIGRAPH)
-         spelling = digraph_spellings[token->type - CPP_FIRST_DIGRAPH];
-       else if (token->flags & NAMED_OP)
-         goto spell_ident;
-       else
-         spelling = TOKEN_NAME (token);
-
-       ufputs (spelling, fp);
-      }
-      break;
-
-    case SPELL_IDENT:
-      spell_ident:
-      ufputs (token->val.node->name, fp);
-      break;
-
-    case SPELL_STRING:
-      {
-       int left, right, tag;
-       switch (token->type)
-         {
-         case CPP_STRING:      left = '"';  right = '"';  tag = '\0'; break;
-         case CPP_WSTRING:     left = '"';  right = '"';  tag = 'L';  break;
-         case CPP_OSTRING:     left = '"';  right = '"';  tag = '@';  break;
-         case CPP_CHAR:        left = '\''; right = '\''; tag = '\0'; break;
-         case CPP_WCHAR:       left = '\''; right = '\''; tag = 'L';  break;
-         case CPP_HEADER_NAME: left = '<';  right = '>';  tag = '\0'; break;
-         default:              left = '\0'; right = '\0'; tag = '\0'; break;
-         }
-       if (tag) putc (tag, fp);
-       if (left) putc (left, fp);
-       fwrite (token->val.str.text, 1, token->val.str.len, fp);
-       if (right) putc (right, fp);
-      }
-      break;
-
-    case SPELL_CHAR:
-      putc (token->val.aux, fp);
-      break;
-
-    case SPELL_NONE:
-      /* Placemarker or EOF - no output.  (Macro args are handled
-         elsewhere.  */
-      break;
-    }
-}
-
-/* Dump the original user's spelling of argument index ARG_NO to the
-   macro whose expansion is LIST.  */
-static void
-dump_param_spelling (fp, list, arg_no)
-     FILE *fp;
-     const cpp_toklist *list;
-     unsigned int arg_no;
-{
-  const U_CHAR *param = list->namebuf;
-
-  while (arg_no--)
-    param += ustrlen (param) + 1;
-  ufputs (param, fp);
-}
-
-/* Output all the tokens of LIST, starting at TOKEN, to FP.  */
-void
-cpp_output_list (pfile, fp, list, token)
-     cpp_reader *pfile;
-     FILE *fp;
-     const cpp_toklist *list;
-     const cpp_token *token;
-{
-  const cpp_token *limit = list->tokens + list->tokens_used;
-  const cpp_token *prev = 0;
-  int white = 0;
-
-  while (token < limit)
-    {
-      /* XXX Find some way we can write macro args from inside
-        output_token/spell_token.  */
-      if (token->type == CPP_MACRO_ARG)
-       {
-         if (white && token->flags & PREV_WHITE)
-           putc (' ', fp);
-         if (token->flags & STRINGIFY_ARG)
-           putc ('#', fp);
-         dump_param_spelling (fp, list, token->val.aux);
-       }
-      else
-       output_token (pfile, fp, token, prev, white);
-      if (token->flags & PASTE_LEFT)
-       fputs (" ##", fp);
-      prev = token;
-      token++;
-      white = 1;
-    }
-}
-
-
 /* 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
@@ -1879,7 +1561,7 @@ spell_token (pfile, token, buffer)
        unsigned char c;
 
        if (token->flags & DIGRAPH)
-         spelling = digraph_spellings[token->type - CPP_FIRST_DIGRAPH];
+         spelling = _cpp_digraph_spellings[token->type - CPP_FIRST_DIGRAPH];
        else if (token->flags & NAMED_OP)
          goto spell_ident;
        else
@@ -2501,8 +2183,8 @@ duplicate_token (pfile, token)
    what the resulting token is.  Returns CPP_EOF if the tokens cannot
    be pasted, or the appropriate type for the merged token if they
    can.  */
-static enum cpp_ttype
-can_paste (pfile, token1, token2, digraph)
+enum cpp_ttype
+_cpp_can_paste (pfile, token1, token2, digraph)
      cpp_reader * pfile;
      const cpp_token *token1, *token2;
      int* digraph;
@@ -2651,7 +2333,7 @@ maybe_paste_with_next (pfile, token)
       else
        {
          int digraph = 0;
-         enum cpp_ttype type = can_paste (pfile, token, second, &digraph);
+         enum cpp_ttype type = _cpp_can_paste (pfile, token, second, &digraph);
 
          if (type == CPP_EOF)
            {
@@ -2961,8 +2643,8 @@ _cpp_push_token (pfile, token)
 
 /* Handle a preprocessing directive.  TOKEN is the CPP_HASH token
    introducing the directive.  */
-static void
-process_directive (pfile, token)
+void
+_cpp_process_directive (pfile, token)
      cpp_reader *pfile;
      const cpp_token *token;
 {
@@ -3002,7 +2684,7 @@ cpp_get_token (pfile)
       if (token->type == CPP_HASH && token->flags & BOL
          && pfile->token_list.directive)
        {
-         process_directive (pfile, token);
+         _cpp_process_directive (pfile, token);
          continue;
        }
 
index 82dfd7f..321b318 100644 (file)
@@ -40,7 +40,6 @@ struct macro_info
   unsigned char flags;
 };
 
-static void dump_macro_args PARAMS ((FILE *, const cpp_toklist *));
 static void count_params PARAMS ((cpp_reader *, struct macro_info *));
 static int is__va_args__ PARAMS ((cpp_reader *, const cpp_token *));
 
@@ -577,57 +576,6 @@ _cpp_create_definition (pfile, hp)
   return 1;
 }
 
-/* Dump the definition of macro MACRO on FP.  The format is suitable
-   to be read back in again.  Caller is expected to generate the
-   "#define NAME" bit.  */
-
-void
-cpp_dump_definition (pfile, fp, hp)
-     cpp_reader *pfile;
-     FILE *fp;
-     const cpp_hashnode *hp;
-{
-  const cpp_toklist *list = hp->value.expansion;
-
-  if (hp->type != T_MACRO)
-    {
-      cpp_ice (pfile, "invalid hash type %d in dump_definition", hp->type);
-      return;
-    }
-
-  if (list->paramc >= 0)
-    dump_macro_args (fp, list);
-
-  putc (' ', fp);
-  cpp_output_list (pfile, fp, list, list->tokens);
-}
-
-static void
-dump_macro_args (fp, list)
-     FILE *fp;
-     const cpp_toklist *list;
-{
-  int i;
-  const U_CHAR *param = list->namebuf;
-
-  putc ('(', fp);
-  for (i = 0; i++ < list->paramc;)
-    {
-      unsigned int len;
-
-      len = ustrlen (param);
-      if (!(list->flags & VAR_ARGS) || ustrcmp (param, U"__VA_ARGS__"))
-       ufputs (param, fp);
-      if (i < list->paramc)
-       fputs (", ", fp);
-      else if (list->flags & VAR_ARGS)
-       fputs ("...", fp);
-
-      param += len + 1;
-    }
-  putc (')', fp);
-}
-
 /* Warn if a token in `string' matches one of the function macro
    arguments in `info'.  This function assumes that the macro is a
    function macro and not an object macro.  */
diff --git a/gcc/cppoutput.c b/gcc/cppoutput.c
new file mode 100644 (file)
index 0000000..53433ce
--- /dev/null
@@ -0,0 +1,390 @@
+/* CPP Library - non-diagnostic output.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   Contributed by Per Bothner, 1994-95.
+   Based on CCCP program by Paul Rubin, June 1986
+   Adapted to ANSI C, Richard Stallman, Jan 1987
+   Broken out to separate file, Sep 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 "intl.h"
+#include "cpplib.h"
+#include "cpphash.h"
+
+static void output_line_command PARAMS ((cpp_reader *, cpp_printer *,
+                                        unsigned int));
+static void output_token PARAMS ((cpp_reader *, FILE *, const cpp_token *,
+                                 const cpp_token *, int));
+static void dump_macro_args PARAMS ((FILE *, const cpp_toklist *));
+static void dump_param_spelling PARAMS ((FILE *, const cpp_toklist *,
+                                        unsigned int));
+
+/* Scan until CPP_BUFFER (PFILE) is exhausted, discarding output.  Used
+   for handling -imacros, -dM, -M and -MM.  */
+void
+cpp_scan_buffer_nooutput (pfile)
+     cpp_reader *pfile;
+{
+  cpp_buffer *stop = CPP_PREV_BUFFER (CPP_BUFFER (pfile));
+  const cpp_token *token;
+
+  /* In no-output mode, we can ignore everything but directives.  */
+  for (;;)
+    {
+      token = _cpp_get_token (pfile);
+
+      if (token->type == CPP_EOF)
+       {
+         cpp_pop_buffer (pfile);
+         if (CPP_BUFFER (pfile) == stop)
+           break;
+       }
+
+      if (token->type == CPP_HASH && token->flags & BOL
+         && pfile->token_list.directive)
+       {
+         _cpp_process_directive (pfile, token);
+         continue;
+       }
+
+      _cpp_skip_rest_of_line (pfile);
+    }
+}
+
+/* Scan until CPP_BUFFER (pfile) is exhausted, writing output to PRINT.  */
+void
+cpp_scan_buffer (pfile, print)
+     cpp_reader *pfile;
+     cpp_printer *print;
+{
+  cpp_buffer *stop = CPP_PREV_BUFFER (CPP_BUFFER (pfile));
+  const cpp_token *token, *prev = 0;
+
+  for (;;)
+    {
+      token = _cpp_get_token (pfile);
+      if (token->type == CPP_EOF)
+       {
+         cpp_pop_buffer (pfile);
+
+         if (CPP_BUFFER (pfile) == stop)
+           return;
+
+         prev = 0;
+         continue;
+       }
+
+      if (token->flags & BOL)
+       {
+         output_line_command (pfile, print, token->line);
+         prev = 0;
+
+         if (token->type == CPP_HASH && pfile->token_list.directive)
+           {
+             _cpp_process_directive (pfile, token);
+             continue;
+           }
+       }
+
+      if (token->type != CPP_PLACEMARKER)
+       {
+         output_token (pfile, print->outf, token, prev, 1);
+         pfile->need_newline = 1;
+       }
+
+      prev = token;
+    }
+}
+
+/* Notify the compiler proper that the current line number has jumped,
+   or the current file name has changed.  */
+static void
+output_line_command (pfile, print, line)
+     cpp_reader *pfile;
+     cpp_printer *print;
+     unsigned int line;
+{
+  cpp_buffer *ip = CPP_BUFFER (pfile);
+
+  if (line == 0)
+    return;
+
+  /* End the previous line of text.  */
+  if (pfile->need_newline)
+    {
+      putc ('\n', print->outf);
+      print->lineno++;
+    }
+  pfile->need_newline = 0;
+
+  if (CPP_OPTION (pfile, no_line_commands))
+    return;
+
+  /* If the current file has not changed, we can output a few newlines
+     instead if we want to increase the line number by a small amount.
+     We cannot do this if print->lineno is zero, because that means we
+     haven't output any line commands yet.  (The very first line
+     command output is a `same_file' command.)
+
+     'nominal_fname' values are unique, so they can be compared by
+     comparing pointers.  */
+  if (ip->nominal_fname == print->last_fname && print->lineno > 0
+      && line >= print->lineno && line < print->lineno + 8)
+    {
+      while (line > print->lineno)
+       {
+         putc ('\n', print->outf);
+         print->lineno++;
+       }
+      return;
+    }
+
+  fprintf (print->outf, "# %u \"%s\"%s\n", line, ip->nominal_fname,
+          cpp_syshdr_flags (pfile, ip));
+
+  print->last_fname = ip->nominal_fname;
+  print->lineno = line;
+}
+
+/* Output all the tokens of LIST, starting at TOKEN, to FP.  */
+void
+cpp_output_list (pfile, fp, list, token)
+     cpp_reader *pfile;
+     FILE *fp;
+     const cpp_toklist *list;
+     const cpp_token *token;
+{
+  const cpp_token *limit = list->tokens + list->tokens_used;
+  const cpp_token *prev = 0;
+  int white = 0;
+
+  while (token < limit)
+    {
+      /* XXX Find some way we can write macro args from inside
+        output_token/spell_token.  */
+      if (token->type == CPP_MACRO_ARG)
+       {
+         if (white && token->flags & PREV_WHITE)
+           putc (' ', fp);
+         if (token->flags & STRINGIFY_ARG)
+           putc ('#', fp);
+         dump_param_spelling (fp, list, token->val.aux);
+       }
+      else
+       output_token (pfile, fp, token, prev, white);
+      if (token->flags & PASTE_LEFT)
+       fputs (" ##", fp);
+      prev = token;
+      token++;
+      white = 1;
+    }
+}
+
+/* Write the spelling of a token TOKEN, with any appropriate
+   whitespace before it, to FP.  PREV is the previous token, which
+   is used to determine if we need to shove in an extra space in order
+   to avoid accidental token paste.  If WHITE is 0, do not insert any
+   leading whitespace.  */
+static void
+output_token (pfile, fp, token, prev, white)
+     cpp_reader *pfile;
+     FILE *fp;
+     const cpp_token *token, *prev;
+     int white;
+{
+  if (white)
+    {
+      int dummy;
+
+      if (token->col && (token->flags & BOL))
+       {
+         /* Supply enough whitespace to put this token in its original
+            column.  Don't bother trying to reconstruct tabs; we can't
+            get it right in general, and nothing ought to care.  (Yes,
+            some things do care; the fault lies with them.)  */
+         unsigned int spaces = token->col - 1;
+      
+         while (spaces--)
+           putc (' ', fp);
+       }
+      else if (token->flags & PREV_WHITE)
+       putc (' ', fp);
+      else
+      /* Check for and prevent accidental token pasting.
+        In addition to the cases handled by _cpp_can_paste, consider
+
+        a + ++b - if there is not a space between the + and ++, it
+        will be misparsed as a++ + b.  But + ## ++ doesn't produce
+        a valid token.  */
+       if (prev
+           && (_cpp_can_paste (pfile, prev, token, &dummy) != CPP_EOF
+               || (prev->type == CPP_PLUS && token->type == CPP_PLUS_PLUS)
+               || (prev->type == CPP_MINUS && token->type == CPP_MINUS_MINUS)))
+       putc (' ', fp);
+    }
+
+  switch (TOKEN_SPELL (token))
+    {
+    case SPELL_OPERATOR:
+      {
+       const unsigned char *spelling;
+
+       if (token->flags & DIGRAPH)
+         spelling = _cpp_digraph_spellings[token->type - CPP_FIRST_DIGRAPH];
+       else if (token->flags & NAMED_OP)
+         goto spell_ident;
+       else
+         spelling = TOKEN_NAME (token);
+
+       ufputs (spelling, fp);
+      }
+      break;
+
+    case SPELL_IDENT:
+      spell_ident:
+      ufputs (token->val.node->name, fp);
+      break;
+
+    case SPELL_STRING:
+      {
+       int left, right, tag;
+       switch (token->type)
+         {
+         case CPP_STRING:      left = '"';  right = '"';  tag = '\0'; break;
+         case CPP_WSTRING:     left = '"';  right = '"';  tag = 'L';  break;
+         case CPP_OSTRING:     left = '"';  right = '"';  tag = '@';  break;
+         case CPP_CHAR:        left = '\''; right = '\''; tag = '\0'; break;
+         case CPP_WCHAR:       left = '\''; right = '\''; tag = 'L';  break;
+         case CPP_HEADER_NAME: left = '<';  right = '>';  tag = '\0'; break;
+         default:              left = '\0'; right = '\0'; tag = '\0'; break;
+         }
+       if (tag) putc (tag, fp);
+       if (left) putc (left, fp);
+       fwrite (token->val.str.text, 1, token->val.str.len, fp);
+       if (right) putc (right, fp);
+      }
+      break;
+
+    case SPELL_CHAR:
+      putc (token->val.aux, fp);
+      break;
+
+    case SPELL_NONE:
+      /* Placemarker or EOF - no output.  (Macro args are handled
+         elsewhere.  */
+      break;
+    }
+}
+
+/* Dump the original user's spelling of argument index ARG_NO to the
+   macro whose expansion is LIST.  */
+static void
+dump_param_spelling (fp, list, arg_no)
+     FILE *fp;
+     const cpp_toklist *list;
+     unsigned int arg_no;
+{
+  const U_CHAR *param = list->namebuf;
+
+  while (arg_no--)
+    param += ustrlen (param) + 1;
+  ufputs (param, fp);
+}
+
+/* Dump the definition of macro MACRO on FP.  The format is suitable
+   to be read back in again.  Caller is expected to generate the
+   "#define NAME" bit.  */
+
+void
+cpp_dump_definition (pfile, fp, hp)
+     cpp_reader *pfile;
+     FILE *fp;
+     const cpp_hashnode *hp;
+{
+  const cpp_toklist *list = hp->value.expansion;
+
+  if (hp->type != T_MACRO)
+    {
+      cpp_ice (pfile, "invalid hash type %d in dump_definition", hp->type);
+      return;
+    }
+
+  if (list->paramc >= 0)
+    dump_macro_args (fp, list);
+
+  putc (' ', fp);
+  cpp_output_list (pfile, fp, list, list->tokens);
+}
+
+static void
+dump_macro_args (fp, list)
+     FILE *fp;
+     const cpp_toklist *list;
+{
+  int i;
+  const U_CHAR *param = list->namebuf;
+
+  putc ('(', fp);
+  for (i = 0; i++ < list->paramc;)
+    {
+      unsigned int len;
+
+      len = ustrlen (param);
+      if (!(list->flags & VAR_ARGS) || ustrcmp (param, U"__VA_ARGS__"))
+       ufputs (param, fp);
+      if (i < list->paramc)
+       fputs (", ", fp);
+      else if (list->flags & VAR_ARGS)
+       fputs ("...", fp);
+
+      param += len + 1;
+    }
+  putc (')', fp);
+}
+
+/* Like fprintf, but writes to a printer object.  You should be sure
+   always to generate a complete line when you use this function.  */
+void
+cpp_printf VPARAMS ((cpp_reader *pfile, cpp_printer *print,
+                    const char *fmt, ...))
+{
+  va_list ap;
+#ifndef ANSI_PROTOTYPES
+  cpp_reader *pfile;
+  cpp_printer *print;
+  const char *fmt;
+#endif
+
+  VA_START (ap, fmt);
+
+#ifndef ANSI_PROTOTYPES
+  pfile = va_arg (ap, cpp_reader *);
+  print = va_arg (ap, cpp_printer *);
+  fmt = va_arg (ap, const char *);
+#endif
+
+  /* End the previous line of text.  */
+  if (pfile->need_newline)
+    {
+      putc ('\n', print->outf);
+      print->lineno++;
+    }
+  pfile->need_newline = 0;
+
+  vfprintf (print->outf, fmt, ap);
+  va_end (ap);
+}
index 1621153..66eccf9 100644 (file)
@@ -599,6 +599,7 @@ cpplex.c
 cpplib.c
 cpplib.h
 cppmain.c
+cppoutput.c
 cppspec.c
 #crtstuff.c is part of the GCC library
 cse.c