OSDN Git Service

* Makefile.in (LIBCPP_OBJS): Add cpplex.o.
authorzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 13 Mar 2000 22:01:08 +0000 (22:01 +0000)
committerzack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 13 Mar 2000 22:01:08 +0000 (22:01 +0000)
(cpplex.o): New target.
* po/POTFILES.in: Add cpplex.c.

* cpplex.c (_cpp_grow_token_buffer, null_cleanup,
cpp_push_buffer, cpp_pop_buffer, cpp_scan_buffer,
cpp_expand_to_buffer, cpp_buf_line_and_col, cpp_file_buffer,
skip_block_comment, skip_line_comment, skip_comment,
copy_comment, _cpp_skip_hspace, _cpp_skip_rest_of_line,
_cpp_parse_name, skip_string, parse_string,
_cpp_parse_assertion, cpp_get_token, cpp_get_non_space_token,
_cpp_get_directive_token, find_position,
_cpp_read_and_prescan, _cpp_init_input_buffer): Move here.
(maybe_macroexpand, _cpp_lex_token): New functions.

* cpplib.c (SKIP_WHITE_SPACE, eval_if_expr, parse_set_mark,
parse_goto_mark): Delete.
(_cpp_handle_eof): New function.
(_cpp_handle_directive): Rename from handle_directive.
(_cpp_output_line_command): Rename from output_line_command.
(do_if, do_elif): Call _cpp_parse_expr directly.
* cppfiles.c (_cpp_read_include_file): Don't call
init_input_buffer here.
* cpphash.c (quote_string): Move here, rename _cpp_quote_string.
* cppexp.c (_cpp_parse_expr): Diddle parsing_if_directive
here; pop the token_buffer and skip the rest of the line here.
* cppinit.c (cpp_start_read): Call _cpp_init_input_buffer
here.

* cpphash.h (CPP_RESERVE, CPP_IS_MACRO_BUFFER, ACTIVE_MARK_P):
Define here.
(CPP_SET_BUF_MARK, CPP_GOTO_BUF_MARK, CPP_SET_MARK,
CPP_GOTO_MARK): New macros.
(_cpp_quote_string, _cpp_parse_name, _cpp_skip_rest_of_line,
_cpp_skip_hspace, _cpp_parse_assertion, _cpp_lex_token,
_cpp_read_and_prescan, _cpp_init_input_buffer,
_cpp_grow_token_buffer, _cpp_get_directive_token,
_cpp_handle_directive, _cpp_handle_eof,
_cpp_output_line_command): Prototype them here.
* cpplib.h (enum cpp_token): Add CPP_MACRO.
(CPP_RESERVE, get_directive_token, cpp_grow_buffer,
quote_string, output_line_command): Remove.

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

gcc/ChangeLog
gcc/Makefile.in
gcc/cppexp.c
gcc/cppfiles.c
gcc/cpphash.c
gcc/cpphash.h
gcc/cppinit.c
gcc/cpplex.c [new file with mode: 0644]
gcc/cpplib.c
gcc/cpplib.h
gcc/po/POTFILES.in

index 1589abd..0abf7f5 100644 (file)
@@ -1,3 +1,48 @@
+2000-03-13  Zack Weinberg  <zack@wolery.cumb.org>
+
+       * Makefile.in (LIBCPP_OBJS): Add cpplex.o.
+       (cpplex.o): New target.
+       * po/POTFILES.in: Add cpplex.c.
+
+       * cpplex.c (_cpp_grow_token_buffer, null_cleanup,
+       cpp_push_buffer, cpp_pop_buffer, cpp_scan_buffer,
+       cpp_expand_to_buffer, cpp_buf_line_and_col, cpp_file_buffer,
+       skip_block_comment, skip_line_comment, skip_comment,
+       copy_comment, _cpp_skip_hspace, _cpp_skip_rest_of_line,
+       _cpp_parse_name, skip_string, parse_string,
+       _cpp_parse_assertion, cpp_get_token, cpp_get_non_space_token,
+       _cpp_get_directive_token, find_position,
+       _cpp_read_and_prescan, _cpp_init_input_buffer): Move here.
+       (maybe_macroexpand, _cpp_lex_token): New functions.
+
+       * cpplib.c (SKIP_WHITE_SPACE, eval_if_expr, parse_set_mark,
+       parse_goto_mark): Delete.
+       (_cpp_handle_eof): New function.
+       (_cpp_handle_directive): Rename from handle_directive.
+       (_cpp_output_line_command): Rename from output_line_command.
+       (do_if, do_elif): Call _cpp_parse_expr directly.
+       * cppfiles.c (_cpp_read_include_file): Don't call
+       init_input_buffer here.
+       * cpphash.c (quote_string): Move here, rename _cpp_quote_string.
+       * cppexp.c (_cpp_parse_expr): Diddle parsing_if_directive
+       here; pop the token_buffer and skip the rest of the line here.
+       * cppinit.c (cpp_start_read): Call _cpp_init_input_buffer
+       here.
+
+       * cpphash.h (CPP_RESERVE, CPP_IS_MACRO_BUFFER, ACTIVE_MARK_P):
+       Define here.
+       (CPP_SET_BUF_MARK, CPP_GOTO_BUF_MARK, CPP_SET_MARK,
+       CPP_GOTO_MARK): New macros.
+       (_cpp_quote_string, _cpp_parse_name, _cpp_skip_rest_of_line,
+       _cpp_skip_hspace, _cpp_parse_assertion, _cpp_lex_token,
+       _cpp_read_and_prescan, _cpp_init_input_buffer,
+       _cpp_grow_token_buffer, _cpp_get_directive_token,
+       _cpp_handle_directive, _cpp_handle_eof,
+       _cpp_output_line_command): Prototype them here.
+       * cpplib.h (enum cpp_token): Add CPP_MACRO.
+       (CPP_RESERVE, get_directive_token, cpp_grow_buffer,
+       quote_string, output_line_command): Remove.
+
 2000-03-13  Bernd Schmidt  <bernds@cygnus.co.uk>
 
        * stmt.c (expand_end_case): RANGE may be signed, and when checking
index 9fff80b..3da6452 100644 (file)
@@ -2025,7 +2025,7 @@ cccp.o: cccp.c $(CONFIG_H) intl.h pcp.h version.c config.status system.h \
          -c `echo $(srcdir)/cccp.c | sed 's,^\./,,'`
 
 LIBCPP_OBJS =  cpplib.o cpphash.o cpperror.o cppexp.o cppfiles.o \
-               cppinit.o cppulp.o mkdeps.o \
+               cppinit.o cppulp.o cpplex.o mkdeps.o \
                prefix.o version.o mbchar.o @extra_cpp_objs@
 
 LIBCPP_DEPS = cpplib.h cpphash.h intl.h system.h
@@ -2048,6 +2048,7 @@ cppmain.o:  cppmain.c  $(CONFIG_H) cpplib.h intl.h system.h
 cppulp.o:   cppulp.c   $(CONFIG_H) system.h output.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)
 cppfiles.o: cppfiles.c $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H)
 cpphash.o:  cpphash.c  $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H)
 cpplib.o:   cpplib.c   $(CONFIG_H) $(LIBCPP_DEPS) $(HASHTAB_H) mkdeps.h
index bb2ae7a..4d1cf10 100644 (file)
@@ -352,12 +352,12 @@ parse_defined (pfile)
   op.op = INT;
 
   pfile->no_macro_expand++;
-  token = get_directive_token (pfile);
+  token = _cpp_get_directive_token (pfile);
   if (token == CPP_LPAREN)
     {
       paren++;
       CPP_SET_WRITTEN (pfile, old_written);
-      token = get_directive_token (pfile);
+      token = _cpp_get_directive_token (pfile);
     }
 
   if (token != CPP_NAME)
@@ -369,7 +369,7 @@ parse_defined (pfile)
 
   if (paren)
     {
-      if (get_directive_token (pfile) != CPP_RPAREN)
+      if (_cpp_get_directive_token (pfile) != CPP_RPAREN)
        goto oops;
     }
   CPP_SET_WRITTEN (pfile, old_written);
@@ -419,7 +419,7 @@ lex (pfile, skip_evaluation)
   long old_written;
 
   old_written = CPP_WRITTEN (pfile);
-  token = get_directive_token (pfile);
+  token = _cpp_get_directive_token (pfile);
 
   tok_start = pfile->token_buffer + old_written;
   tok_end = CPP_PWRITTEN (pfile);
@@ -689,7 +689,10 @@ _cpp_parse_expr (pfile)
   register struct operation *top = stack;
   unsigned int lprio, rprio = 0;
   int skip_evaluation = 0;
+  long old_written = CPP_WRITTEN (pfile);
+  int result;
 
+  pfile->parsing_if_directive++;
   top->rprio = 0;
   top->flags = 0;
   for (;;)
@@ -999,9 +1002,8 @@ _cpp_parse_expr (pfile)
        {
          if (top != stack)
            cpp_ice (pfile, "unbalanced stack in #if expression");
-         if (stack != init_stack)
-           free (stack);
-         return (top->value != 0);
+         result = (top->value != 0);
+         goto done;
        }
       top++;
       
@@ -1041,7 +1043,12 @@ _cpp_parse_expr (pfile)
        }
     }
  syntax_error:
+  _cpp_skip_rest_of_line (pfile);
+  result = 0;
+ done:
+  pfile->parsing_if_directive--;
+  CPP_SET_WRITTEN (pfile, old_written);
   if (stack != init_stack)
     free (stack);
-  return 0;
+  return result;
 }
index 3354663..ec7529f 100644 (file)
@@ -38,17 +38,13 @@ static struct file_name_map *read_name_map
 static char *read_filename_string PARAMS ((int, FILE *));
 static char *remap_filename    PARAMS ((cpp_reader *, char *,
                                         struct file_name_list *));
-static long read_and_prescan   PARAMS ((cpp_reader *, cpp_buffer *,
-                                        int, size_t));
 static struct file_name_list *actual_directory
                                PARAMS ((cpp_reader *, const char *));
 
 static unsigned int hash_IHASH PARAMS ((const void *));
 static int eq_IHASH            PARAMS ((const void *, const void *));
 
-static void init_input_buffer  PARAMS ((cpp_reader *, int, struct stat *));
 static int file_cleanup                PARAMS ((cpp_buffer *, cpp_reader *));
-static U_CHAR *find_position   PARAMS ((U_CHAR *, U_CHAR *, unsigned long *));
 
 #if 0
 static void hack_vms_include_specification PARAMS ((char *));
@@ -587,14 +583,11 @@ _cpp_read_include_file (pfile, fd, ihash)
       goto fail;
     }
 
-  if (pfile->input_buffer == NULL)
-    init_input_buffer (pfile, fd, &st);
-
   /* Read the file, converting end-of-line characters and trigraphs
      (if enabled). */
   fp->ihash = ihash;
   fp->nominal_fname = ihash->name;
-  length = read_and_prescan (pfile, fp, fd, st_size);
+  length = _cpp_read_and_prescan (pfile, fp, fd, st_size);
   if (length < 0)
     goto fail;
   if (length == 0)
@@ -687,402 +680,6 @@ actual_directory (pfile, fname)
   return x;
 }
 
-/* Determine the current line and column.  Used only by read_and_prescan. */
-static U_CHAR *
-find_position (start, limit, linep)
-     U_CHAR *start;
-     U_CHAR *limit;
-     unsigned long *linep;
-{
-  unsigned long line = *linep;
-  U_CHAR *lbase = start;
-  while (start < limit)
-    {
-      U_CHAR ch = *start++;
-      if (ch == '\n' || ch == '\r')
-       {
-         line++;
-         lbase = start;
-       }
-    }
-  *linep = line;
-  return lbase;
-}
-
-/* Read the entire contents of file DESC into buffer BUF.  LEN is how
-   much memory to allocate initially; more will be allocated if
-   necessary.  Convert end-of-line markers (\n, \r, \r\n, \n\r) to
-   canonical form (\n).  If enabled, convert and/or warn about
-   trigraphs.  Convert backslash-newline to a one-character escape
-   (\r) and remove it from "embarrassing" places (i.e. the middle of a
-   token).  If there is no newline at the end of the file, add one and
-   warn.  Returns -1 on failure, or the actual length of the data to
-   be scanned.
-
-   This function does a lot of work, and can be a serious performance
-   bottleneck.  It has been tuned heavily; make sure you understand it
-   before hacking.  The common case - no trigraphs, Unix style line
-   breaks, backslash-newline set off by whitespace, newline at EOF -
-   has been optimized at the expense of the others.  The performance
-   penalty for DOS style line breaks (\r\n) is about 15%.
-   
-   Warnings lose particularly heavily since we have to determine the
-   line number, which involves scanning from the beginning of the file
-   or from the last warning.  The penalty for the absence of a newline
-   at the end of reload1.c is about 60%.  (reload1.c is 329k.)
-
-   If your file has more than one kind of end-of-line marker, you
-   will get messed-up line numbering.  */
-
-/* Table of characters that can't be handled in the inner loop.
-   Keep these contiguous to optimize the performance of the code generated
-   for the switch that uses them.  */
-#define SPECCASE_EMPTY     0
-#define SPECCASE_NUL       1
-#define SPECCASE_CR        2
-#define SPECCASE_BACKSLASH 3
-#define SPECCASE_QUESTION  4
-
-static long
-read_and_prescan (pfile, fp, desc, len)
-     cpp_reader *pfile;
-     cpp_buffer *fp;
-     int desc;
-     size_t len;
-{
-  U_CHAR *buf = (U_CHAR *) xmalloc (len);
-  U_CHAR *ip, *op, *line_base;
-  U_CHAR *ibase;
-  U_CHAR *speccase = pfile->input_speccase;
-  unsigned long line;
-  unsigned int deferred_newlines;
-  int count;
-  size_t offset;
-
-  offset = 0;
-  op = buf;
-  line_base = buf;
-  line = 1;
-  ibase = pfile->input_buffer + 2;
-  deferred_newlines = 0;
-
-  for (;;)
-    {
-    read_next:
-
-      count = read (desc, pfile->input_buffer + 2, pfile->input_buffer_len);
-      if (count < 0)
-       goto error;
-      else if (count == 0)
-       break;
-
-      offset += count;
-      ip = ibase;
-      ibase = pfile->input_buffer + 2;
-      ibase[count] = ibase[count+1] = '\0';
-
-      if (offset > len)
-       {
-         size_t delta_op;
-         size_t delta_line_base;
-         len *= 2;
-         if (offset > len)
-           /* len overflowed.
-              This could happen if the file is larger than half the
-              maximum address space of the machine. */
-           goto too_big;
-
-         delta_op = op - buf;
-         delta_line_base = line_base - buf;
-         buf = (U_CHAR *) xrealloc (buf, len);
-         op = buf + delta_op;
-         line_base = buf + delta_line_base;
-       }
-
-      for (;;)
-       {
-         unsigned int span = 0;
-
-         /* Deal with \-newline in the middle of a token. */
-         if (deferred_newlines)
-           {
-             while (speccase[ip[span]] == SPECCASE_EMPTY
-                    && ip[span] != '\n'
-                    && ip[span] != '\t'
-                    && ip[span] != ' ')
-               span++;
-             memcpy (op, ip, span);
-             op += span;
-             ip += span;
-             /* If ip[0] is SPECCASE_EMPTY, we have hit white space.
-                Dump out the remaining deferred \-newlines.  */
-             if (speccase[ip[0]] == SPECCASE_EMPTY)
-               while (deferred_newlines)
-                 deferred_newlines--, *op++ = '\r';
-             span = 0;
-           }
-
-         /* Copy as much as we can without special treatment. */
-         while (speccase[ip[span]] == SPECCASE_EMPTY) span++;
-         memcpy (op, ip, span);
-         op += span;
-         ip += span;
-
-         switch (speccase[*ip++])
-           {
-           case SPECCASE_NUL:  /* \0 */
-             ibase[-1] = op[-1];
-             goto read_next;
-
-           case SPECCASE_CR:  /* \r */
-             if (ip[-2] == '\n')
-               continue;
-             else if (*ip == '\n')
-               ip++;
-             else if (*ip == '\0')
-               {
-                 *--ibase = '\r';
-                 goto read_next;
-               }
-             *op++ = '\n';
-             break;
-
-           case SPECCASE_BACKSLASH:  /* \ */
-           backslash:
-           {
-             /* If we're at the end of the intermediate buffer,
-                we have to shift the backslash down to the start
-                and come back next pass. */
-             if (*ip == '\0')
-               {
-                 *--ibase = '\\';
-                 goto read_next;
-               }
-             else if (*ip == '\n')
-               {
-                 ip++;
-                 if (*ip == '\r') ip++;
-                 if (*ip == '\n' || *ip == '\t' || *ip == ' ')
-                   *op++ = '\r';
-                 else if (op[-1] == '\t' || op[-1] == ' '
-                          || op[-1] == '\r' || op[-1] == '\n')
-                   *op++ = '\r';
-                 else
-                   deferred_newlines++;
-               }
-             else if (*ip == '\r')
-               {
-                 ip++;
-                 if (*ip == '\n') ip++;
-                 else if (*ip == '\0')
-                   {
-                     *--ibase = '\r';
-                     *--ibase = '\\';
-                     goto read_next;
-                   }
-                 else if (*ip == '\r' || *ip == '\t' || *ip == ' ')
-                   *op++ = '\r';
-                 else
-                   deferred_newlines++;
-               }
-             else
-               *op++ = '\\';
-           }
-           break;
-
-           case SPECCASE_QUESTION: /* ? */
-             {
-               unsigned int d, t;
-               /* If we're at the end of the intermediate buffer,
-                  we have to shift the ?'s down to the start and
-                  come back next pass. */
-               d = ip[0];
-               if (d == '\0')
-                 {
-                   *--ibase = '?';
-                   goto read_next;
-                 }
-               if (d != '?')
-                 {
-                   *op++ = '?';
-                   break;
-                 }
-               d = ip[1];
-               if (d == '\0')
-                 {
-                   *--ibase = '?';
-                   *--ibase = '?';
-                   goto read_next;
-                 }
-
-               /* Trigraph map:
-                *      from    to      from    to      from    to
-                *      ?? =    #       ?? )    ]       ?? !    |
-                *      ?? (    [       ?? '    ^       ?? >    }
-                *      ?? /    \       ?? <    {       ?? -    ~
-                */
-               if (d == '=') t = '#';
-               else if (d == ')') t = ']';
-               else if (d == '!') t = '|';
-               else if (d == '(') t = '[';
-               else if (d == '\'') t = '^';
-               else if (d == '>') t = '}';
-               else if (d == '/') t = '\\';
-               else if (d == '<') t = '{';
-               else if (d == '-') t = '~';
-               else
-                 {
-                   *op++ = '?';
-                   break;
-                 }
-               ip += 2;
-               if (CPP_OPTIONS (pfile)->warn_trigraphs)
-                 {
-                   unsigned long col;
-                   line_base = find_position (line_base, op, &line);
-                   col = op - line_base + 1;
-                   if (CPP_OPTIONS (pfile)->trigraphs)
-                     cpp_warning_with_line (pfile, line, col,
-                            "trigraph ??%c converted to %c", d, t);
-                   else
-                     cpp_warning_with_line (pfile, line, col,
-                            "trigraph ??%c ignored", d);
-                 }
-               if (CPP_OPTIONS (pfile)->trigraphs)
-                 {
-                   if (t == '\\')
-                     goto backslash;
-                   else
-                     *op++ = t;
-                 }
-               else
-                 {
-                   *op++ = '?';
-                   *op++ = '?';
-                   *op++ = d;
-                 }
-             }
-           }
-       }
-    }
-
-  if (offset == 0)
-    return 0;
-
-  /* Deal with pushed-back chars at true EOF.
-     This may be any of:  ?? ? \ \r \n \\r \\n.
-     \r must become \n, \\r or \\n must become \r.
-     We know we have space already. */
-  if (ibase == pfile->input_buffer)
-    {
-      if (*ibase == '?')
-       {
-         *op++ = '?';
-         *op++ = '?';
-       }
-      else
-       *op++ = '\r';
-    }
-  else if (ibase == pfile->input_buffer + 1)
-    {
-      if (*ibase == '\r')
-       *op++ = '\n';
-      else
-       *op++ = *ibase;
-    }
-
-  if (op[-1] != '\n')
-    {
-      unsigned long col;
-      line_base = find_position (line_base, op, &line);
-      col = op - line_base + 1;
-      cpp_warning_with_line (pfile, line, col, "no newline at end of file\n");
-      if (offset + 1 > len)
-       {
-         len += 1;
-         if (offset + 1 > len)
-           goto too_big;
-         buf = (U_CHAR *) xrealloc (buf, len);
-         op = buf + offset;
-       }
-      *op++ = '\n';
-    }
-
-  fp->buf = ((len - offset < 20) ? buf : (U_CHAR *)xrealloc (buf, op - buf));
-  return op - buf;
-
- too_big:
-  cpp_error (pfile, "file is too large (>%lu bytes)\n", (unsigned long)offset);
-  free (buf);
-  return -1;
-
- error:
-  cpp_error_from_errno (pfile, fp->ihash->name);
-  free (buf);
-  return -1;
-}
-
-/* Initialize the `input_buffer' and `input_speccase' tables.
-   These are only used by read_and_prescan, but they're large and
-   somewhat expensive to set up, so we want them allocated once for
-   the duration of the cpp run.  */
-
-static void
-init_input_buffer (pfile, fd, st)
-     cpp_reader *pfile;
-     int fd;
-     struct stat *st;
-{
-  long pipe_buf;
-  U_CHAR *tmp;
-
-  /* Table of characters that cannot be handled by the
-     read_and_prescan inner loop.  The number of non-EMPTY entries
-     should be as small as humanly possible.  */
-
-  tmp = (U_CHAR *) xmalloc (1 << CHAR_BIT);
-  memset (tmp, SPECCASE_EMPTY, 1 << CHAR_BIT);
-  tmp['\0'] = SPECCASE_NUL;
-  tmp['\r'] = SPECCASE_CR;
-  tmp['\\'] = SPECCASE_BACKSLASH;
-  if (CPP_OPTIONS (pfile)->trigraphs || CPP_OPTIONS (pfile)->warn_trigraphs)
-    tmp['?'] = SPECCASE_QUESTION;
-
-  pfile->input_speccase = tmp;
-
-  /* Determine the appropriate size for the input buffer.  Normal C
-     source files are smaller than eight K.  If we are reading a pipe,
-     we want to make sure the input buffer is bigger than the kernel's
-     pipe buffer.  */
-  pipe_buf = -1;
-
-  if (! S_ISREG (st->st_mode))
-    {
-#ifdef _PC_PIPE_BUF
-      pipe_buf = fpathconf (fd, _PC_PIPE_BUF);
-#endif
-      if (pipe_buf == -1)
-       {
-#ifdef PIPE_BUF
-         pipe_buf = PIPE_BUF;
-#else
-         pipe_buf = 8192;
-#endif
-       }
-    }
-
-  if (pipe_buf < 8192)
-    pipe_buf = 8192;
-  /* PIPE_BUF bytes of buffer proper, 2 to detect running off the end
-     without address arithmetic all the time, and 2 for pushback in
-     the case there's a potential trigraph or end-of-line digraph at
-     the end of a block. */
-
-  tmp = (U_CHAR *) xmalloc (pipe_buf + 2 + 2);
-  pfile->input_buffer = tmp;
-  pfile->input_buffer_len = pipe_buf;
-}
-
 /* Simplify a path name in place, deleting redundant components.  This
    reduces OS overhead and guarantees that equivalent paths compare
    the same (modulo symlinks).
index 3d48e8c..d3dac0b 100644 (file)
@@ -307,7 +307,7 @@ collect_expansion (pfile, arglist)
   last -= 2;  /* two extra chars for the leading escape */
   for (;;)
     {
-      /* We use cpp_get_token because get_directive_token would
+      /* We use cpp_get_token because _cpp_get_directive_token would
         discard whitespace and we can't cope with that yet.  Macro
         expansion is off, so we are guaranteed not to see POP or EOF.  */
 
@@ -570,7 +570,7 @@ collect_formal_parameters (pfile)
   long old_written;
 
   old_written = CPP_WRITTEN (pfile);
-  token = get_directive_token (pfile);
+  token = _cpp_get_directive_token (pfile);
   if (token != CPP_LPAREN)
     {
       cpp_ice (pfile, "first token = %d not %d in collect_formal_parameters",
@@ -584,7 +584,7 @@ collect_formal_parameters (pfile)
   for (;;)
     {
       CPP_SET_WRITTEN (pfile, old_written);
-      token = get_directive_token (pfile);
+      token = _cpp_get_directive_token (pfile);
       switch (token)
        {
        case CPP_NAME:
@@ -660,7 +660,7 @@ collect_formal_parameters (pfile)
 
   argv[argc].rest_arg = 1;
   
-  token = get_directive_token (pfile);
+  token = _cpp_get_directive_token (pfile);
   if (token != CPP_RPAREN)
     {
       cpp_error (pfile, "another parameter follows `...'");
@@ -826,6 +826,43 @@ static const char * const monthnames[] =
   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
 };
 
+/* Place into PFILE a quoted string representing the string SRC.
+   Caller must reserve enough space in pfile->token_buffer.  */
+
+void
+_cpp_quote_string (pfile, src)
+     cpp_reader *pfile;
+     const char *src;
+{
+  U_CHAR c;
+
+  CPP_PUTC_Q (pfile, '\"');
+  for (;;)
+    switch ((c = *src++))
+      {
+      default:
+        if (ISPRINT (c))
+         CPP_PUTC_Q (pfile, c);
+       else
+         {
+           sprintf ((char *)CPP_PWRITTEN (pfile), "\\%03o", c);
+           CPP_ADJUST_WRITTEN (pfile, 4);
+         }
+       break;
+
+      case '\"':
+      case '\\':
+       CPP_PUTC_Q (pfile, '\\');
+       CPP_PUTC_Q (pfile, c);
+       break;
+      
+      case '\0':
+       CPP_PUTC_Q (pfile, '\"');
+       CPP_NUL_TERMINATE_Q (pfile);
+       return;
+      }
+}
+
 /*
  * expand things like __FILE__.  Place the expansion into the output
  * buffer *without* rescanning.
@@ -857,7 +894,7 @@ special_symbol (hp, pfile)
        if (!buf)
          buf = "";
        CPP_RESERVE (pfile, 3 + 4 * strlen (buf));
-       quote_string (pfile, buf);
+       _cpp_quote_string (pfile, buf);
        return;
       }
 
@@ -1597,7 +1634,7 @@ _cpp_dump_definition (pfile, sym, len, defn)
      DEFINITION *defn;
 {
   if (pfile->lineno == 0)
-    output_line_command (pfile, same_file);
+    _cpp_output_line_command (pfile, same_file);
 
   CPP_RESERVE (pfile, len + sizeof "#define ");
   CPP_PUTS_Q (pfile, "#define ", sizeof "#define " -1);
index c842ea6..4468d42 100644 (file)
@@ -217,6 +217,11 @@ extern unsigned char _cpp_IStable[256];
   ((BUFFER)->cur < (BUFFER)->rlimit ? *(BUFFER)->cur++ : EOF)
 #define CPP_FORWARD(BUFFER, N) ((BUFFER)->cur += (N))
 
+/* Make sure PFILE->token_buffer has space for at least N more characters. */
+#define CPP_RESERVE(PFILE, N) \
+  (CPP_WRITTEN (PFILE) + (size_t)(N) > (PFILE)->token_buffer_size \
+   && (_cpp_grow_token_buffer (PFILE, N), 0))
+
 /* Append string STR (of length N) to PFILE's output buffer.
    Assume there is enough space. */
 #define CPP_PUTS_Q(PFILE, STR, N) \
@@ -242,6 +247,29 @@ extern unsigned char _cpp_IStable[256];
 #define CPP_PEDANTIC(PFILE) \
   (CPP_OPTIONS (PFILE)->pedantic && !CPP_BUFFER (pfile)->system_header_p)
 
+/* CPP_IS_MACRO_BUFFER is true if the buffer contains macro expansion.
+   (Note that it is false while we're expanding macro *arguments*.) */
+#define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->data != NULL)
+
+/* Remember the current position of PFILE so it may be returned to
+   after looking ahead a bit.
+
+   Note that when you set a mark, you _must_ return to that mark.  You
+   may not forget about it and continue parsing.  You may not pop a
+   buffer with an active mark.  You may not call CPP_BUMP_LINE while a
+   mark is active.  */
+#define CPP_SET_BUF_MARK(IP)   ((IP)->mark = (IP)->cur - (IP)->buf)
+#define CPP_GOTO_BUF_MARK(IP)  ((IP)->cur = (IP)->buf + (IP)->mark, \
+                               (IP)->mark = -1)
+#define CPP_SET_MARK(PFILE)  CPP_SET_BUF_MARK(CPP_BUFFER(PFILE))
+#define CPP_GOTO_MARK(PFILE) CPP_GOTO_BUF_MARK(CPP_BUFFER(PFILE))
+
+/* ACTIVE_MARK_P is true if there's a live mark in the buffer.  */
+#define ACTIVE_MARK_P(PFILE) (CPP_BUFFER (PFILE)->mark != -1)
+
+/* Last arg to output_line_command.  */
+enum file_change_code {same_file, rename_file, enter_file, leave_file};
+
 /* In cpphash.c */
 extern HASHNODE *_cpp_make_hashnode    PARAMS ((const U_CHAR *, size_t,
                                                 enum node_type,
@@ -257,6 +285,7 @@ extern void _cpp_dump_definition    PARAMS ((cpp_reader *, const U_CHAR *,
                                                 long, DEFINITION *));
 extern int _cpp_compare_defs           PARAMS ((cpp_reader *, DEFINITION *,
                                                 DEFINITION *));
+extern void _cpp_quote_string          PARAMS ((cpp_reader *, const char *));
 extern void _cpp_macroexpand           PARAMS ((cpp_reader *, HASHNODE *));
 extern void _cpp_init_macro_hash       PARAMS ((cpp_reader *));
 extern void _cpp_dump_macro_hash       PARAMS ((cpp_reader *));
@@ -272,4 +301,24 @@ extern void _cpp_init_include_hash PARAMS ((cpp_reader *));
 /* In cppexp.c */
 extern int _cpp_parse_expr             PARAMS ((cpp_reader *));
 
+/* In cpplex.c */
+extern void _cpp_parse_name            PARAMS ((cpp_reader *, int));
+extern void _cpp_skip_rest_of_line     PARAMS ((cpp_reader *));
+extern void _cpp_skip_hspace           PARAMS ((cpp_reader *));
+extern int _cpp_parse_assertion                PARAMS ((cpp_reader *));
+extern enum cpp_token _cpp_lex_token   PARAMS ((cpp_reader *));
+extern long _cpp_read_and_prescan      PARAMS ((cpp_reader *, cpp_buffer *,
+                                                int, size_t));
+extern void _cpp_init_input_buffer     PARAMS ((cpp_reader *));
+extern void _cpp_grow_token_buffer     PARAMS ((cpp_reader *, long));
+extern enum cpp_token _cpp_get_directive_token
+                                       PARAMS ((cpp_reader *));
+
+/* In cpplib.c */
+extern int _cpp_handle_directive       PARAMS ((cpp_reader *));
+extern void _cpp_handle_eof            PARAMS ((cpp_reader *));
+extern void _cpp_output_line_command   PARAMS ((cpp_reader *,
+                                                enum file_change_code));
+
+
 #endif
index 0eb2a29..674e140 100644 (file)
@@ -519,7 +519,7 @@ dump_special_to_buffer (pfile, macro_name)
 {
   static const char define_directive[] = "#define ";
   int macro_name_length = strlen (macro_name);
-  output_line_command (pfile, same_file);
+  _cpp_output_line_command (pfile, same_file);
   CPP_RESERVE (pfile, sizeof(define_directive) + macro_name_length);
   CPP_PUTS_Q (pfile, define_directive, sizeof(define_directive)-1);
   CPP_PUTS_Q (pfile, macro_name, macro_name_length);
@@ -872,6 +872,9 @@ cpp_start_read (pfile, fname)
      with a compiler that supports C99 designated initializers.  */
   init_IStable ();
 
+  /* Set up the tables used by read_and_prescan.  */
+  _cpp_init_input_buffer (pfile);
+  
   /* Set up the include search path now.  */
   if (! opts->no_standard_includes)
     initialize_standard_includes (pfile);
@@ -933,7 +936,7 @@ cpp_start_read (pfile, fname)
        counter accordingly.  */
     pfile->lineno = CPP_BUFFER (pfile)->lineno;
   else
-    output_line_command (pfile, same_file);
+    _cpp_output_line_command (pfile, same_file);
   pfile->only_seen_white = 2;
 
   /* The -imacros files can be scanned now, but the -include files
@@ -957,7 +960,7 @@ cpp_start_read (pfile, fname)
   while (p)
     {
       if (cpp_read_file (pfile, p->arg))
-       output_line_command (pfile, enter_file);
+       _cpp_output_line_command (pfile, enter_file);
 
       q = p->next;
       free (p);
diff --git a/gcc/cpplex.c b/gcc/cpplex.c
new file mode 100644 (file)
index 0000000..674db90
--- /dev/null
@@ -0,0 +1,1620 @@
+/* CPP Library - lexical analysis.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   Contributed by Per Bothner, 1994-95.
+   Based on CCCP program by Paul Rubin, June 1986
+   Adapted to ANSI C, Richard Stallman, Jan 1987
+   Broken out to separate file, Zack Weinberg, Mar 2000
+
+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"
+
+#define PEEKN(N) (CPP_BUFFER (pfile)->rlimit - CPP_BUFFER (pfile)->cur >= (N) \
+                 ? CPP_BUFFER (pfile)->cur[N] : EOF)
+#define FORWARD(N) CPP_FORWARD (CPP_BUFFER (pfile), (N))
+#define GETC() CPP_BUF_GET (CPP_BUFFER (pfile))
+#define PEEKC() CPP_BUF_PEEK (CPP_BUFFER (pfile))
+
+static void skip_block_comment PARAMS ((cpp_reader *));
+static void skip_line_comment  PARAMS ((cpp_reader *));
+static int maybe_macroexpand   PARAMS ((cpp_reader *, long));
+static int skip_comment                PARAMS ((cpp_reader *, int));
+static int copy_comment                PARAMS ((cpp_reader *, int));
+static void skip_string                PARAMS ((cpp_reader *, int));
+static void parse_string       PARAMS ((cpp_reader *, int));
+static U_CHAR *find_position   PARAMS ((U_CHAR *, U_CHAR *, unsigned long *));
+static int null_cleanup                PARAMS ((cpp_buffer *, cpp_reader *));
+
+/* Re-allocates PFILE->token_buffer so it will hold at least N more chars.  */
+
+void
+_cpp_grow_token_buffer (pfile, n)
+     cpp_reader *pfile;
+     long n;
+{
+  long old_written = CPP_WRITTEN (pfile);
+  pfile->token_buffer_size = n + 2 * pfile->token_buffer_size;
+  pfile->token_buffer = (U_CHAR *)
+    xrealloc(pfile->token_buffer, pfile->token_buffer_size);
+  CPP_SET_WRITTEN (pfile, old_written);
+}
+
+static int
+null_cleanup (pbuf, pfile)
+     cpp_buffer *pbuf ATTRIBUTE_UNUSED;
+     cpp_reader *pfile ATTRIBUTE_UNUSED;
+{
+  return 0;
+}
+
+/* Allocate a new cpp_buffer for PFILE, and push it on the input buffer stack.
+   If BUFFER != NULL, then use the LENGTH characters in BUFFER
+   as the new input buffer.
+   Return the new buffer, or NULL on failure.  */
+
+cpp_buffer *
+cpp_push_buffer (pfile, buffer, length)
+     cpp_reader *pfile;
+     const U_CHAR *buffer;
+     long length;
+{
+  cpp_buffer *buf = CPP_BUFFER (pfile);
+  cpp_buffer *new;
+  if (++pfile->buffer_stack_depth == CPP_STACK_MAX)
+    {
+      cpp_fatal (pfile, "macro or `#include' recursion too deep");
+      return NULL;
+    }
+
+  new = (cpp_buffer *) xcalloc (1, sizeof (cpp_buffer));
+
+  new->if_stack = pfile->if_stack;
+  new->cleanup = null_cleanup;
+  new->buf = new->cur = buffer;
+  new->alimit = new->rlimit = buffer + length;
+  new->prev = buf;
+  new->mark = -1;
+  new->line_base = NULL;
+
+  CPP_BUFFER (pfile) = new;
+  return new;
+}
+
+cpp_buffer *
+cpp_pop_buffer (pfile)
+     cpp_reader *pfile;
+{
+  cpp_buffer *buf = CPP_BUFFER (pfile);
+  if (ACTIVE_MARK_P (pfile))
+    cpp_ice (pfile, "mark active in cpp_pop_buffer");
+  (*buf->cleanup) (buf, pfile);
+  CPP_BUFFER (pfile) = CPP_PREV_BUFFER (buf);
+  free (buf);
+  pfile->buffer_stack_depth--;
+  return CPP_BUFFER (pfile);
+}
+
+/* Scan until CPP_BUFFER (PFILE) is exhausted into PFILE->token_buffer.
+   Pop the buffer when done.  */
+
+void
+cpp_scan_buffer (pfile)
+     cpp_reader *pfile;
+{
+  cpp_buffer *buffer = CPP_BUFFER (pfile);
+  enum cpp_token token;
+  if (CPP_OPTIONS (pfile)->no_output)
+    {
+      long old_written = CPP_WRITTEN (pfile);
+      /* In no-output mode, we can ignore everything but directives.  */
+      for (;;)
+       {
+         if (! pfile->only_seen_white)
+           _cpp_skip_rest_of_line (pfile);
+         token = cpp_get_token (pfile);
+         if (token == CPP_EOF) /* Should not happen ...  */
+           break;
+         if (token == CPP_POP && CPP_BUFFER (pfile) == buffer)
+           {
+             if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) != NULL)
+               cpp_pop_buffer (pfile);
+             break;
+           }
+       }
+      CPP_SET_WRITTEN (pfile, old_written);
+    }
+  else
+    {
+      for (;;)
+       {
+         token = cpp_get_token (pfile);
+         if (token == CPP_EOF) /* Should not happen ...  */
+           break;
+         if (token == CPP_POP && CPP_BUFFER (pfile) == buffer)
+           {
+             if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) != NULL)
+               cpp_pop_buffer (pfile);
+             break;
+           }
+       }
+    }
+}
+
+/*
+ * Rescan a string (which may have escape marks) into pfile's buffer.
+ * Place the result in pfile->token_buffer.
+ *
+ * The input is copied before it is scanned, so it is safe to pass
+ * it something from the token_buffer that will get overwritten
+ * (because it follows CPP_WRITTEN).  This is used by do_include.
+ */
+
+void
+cpp_expand_to_buffer (pfile, buf, length)
+     cpp_reader *pfile;
+     const U_CHAR *buf;
+     int length;
+{
+  register cpp_buffer *ip;
+  U_CHAR *buf1;
+  int save_no_output;
+
+  if (length < 0)
+    {
+      cpp_ice (pfile, "length < 0 in cpp_expand_to_buffer");
+      return;
+    }
+
+  /* Set up the input on the input stack.  */
+
+  buf1 = (U_CHAR *) alloca (length + 1);
+  memcpy (buf1, buf, length);
+  buf1[length] = 0;
+
+  ip = cpp_push_buffer (pfile, buf1, length);
+  if (ip == NULL)
+    return;
+  ip->has_escapes = 1;
+
+  /* Scan the input, create the output.  */
+  save_no_output = CPP_OPTIONS (pfile)->no_output;
+  CPP_OPTIONS (pfile)->no_output = 0;
+  CPP_OPTIONS (pfile)->no_line_commands++;
+  cpp_scan_buffer (pfile);
+  CPP_OPTIONS (pfile)->no_line_commands--;
+  CPP_OPTIONS (pfile)->no_output = save_no_output;
+
+  CPP_NUL_TERMINATE (pfile);
+}
+
+void
+cpp_buf_line_and_col (pbuf, linep, colp)
+     register cpp_buffer *pbuf;
+     long *linep, *colp;
+{
+  if (pbuf)
+    {
+      *linep = pbuf->lineno;
+      if (colp)
+       *colp = pbuf->cur - pbuf->line_base;
+    }
+  else
+    {
+      *linep = 0;
+      if (colp)
+       *colp = 0;
+    }
+}
+
+/* Return the topmost cpp_buffer that corresponds to a file (not a macro).  */
+
+cpp_buffer *
+cpp_file_buffer (pfile)
+     cpp_reader *pfile;
+{
+  cpp_buffer *ip;
+
+  for (ip = CPP_BUFFER (pfile); ip; ip = CPP_PREV_BUFFER (ip))
+    if (ip->ihash != NULL)
+      return ip;
+  return NULL;
+}
+
+/* Skip a C-style block comment.  We know it's a comment, and point is
+   at the second character of the starter.  */
+static void
+skip_block_comment (pfile)
+     cpp_reader *pfile;
+{
+  int c, prev_c = -1;
+  long line, col;
+
+  FORWARD(1);
+  cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
+  for (;;)
+    {
+      c = GETC ();
+      if (c == EOF)
+       {
+         cpp_error_with_line (pfile, line, col, "unterminated comment");
+         return;
+       }
+      else if (c == '\n' || c == '\r')
+       {
+         /* \r cannot be a macro escape marker here. */
+         if (!ACTIVE_MARK_P (pfile))
+           CPP_BUMP_LINE (pfile);
+       }
+      else if (c == '/' && prev_c == '*')
+       return;
+      else if (c == '*' && prev_c == '/'
+              && CPP_OPTIONS (pfile)->warn_comments)
+       cpp_warning (pfile, "`/*' within comment");
+
+      prev_c = c;
+    }
+}
+
+/* Skip a C++/Chill line comment.  We know it's a comment, and point
+   is at the second character of the initiator.  */
+static void
+skip_line_comment (pfile)
+     cpp_reader *pfile;
+{
+  FORWARD(1);
+  for (;;)
+    {
+      int c = GETC ();
+
+      /* We don't have to worry about EOF in here.  */
+      if (c == '\n')
+       {
+         /* Don't consider final '\n' to be part of comment.  */
+         FORWARD(-1);
+         return;
+       }
+      else if (c == '\r')
+       {
+         /* \r cannot be a macro escape marker here. */
+         if (!ACTIVE_MARK_P (pfile))
+           CPP_BUMP_LINE (pfile);
+         if (CPP_OPTIONS (pfile)->warn_comments)
+           cpp_warning (pfile, "backslash-newline within line comment");
+       }
+    }
+}
+
+/* Skip a comment - C, C++, or Chill style.  M is the first character
+   of the comment marker.  If this really is a comment, skip to its
+   end and return ' '.  If this is not a comment, return M (which will
+   be '/' or '-').  */
+
+static int
+skip_comment (pfile, m)
+     cpp_reader *pfile;
+     int m;
+{
+  if (m == '/' && PEEKC() == '*')
+    {
+      skip_block_comment (pfile);
+      return ' ';
+    }
+  else if (m == '/' && PEEKC() == '/')
+    {
+      if (CPP_BUFFER (pfile)->system_header_p)
+       {
+         /* We silently allow C++ comments in system headers, irrespective
+            of conformance mode, because lots of busted systems do that
+            and trying to clean it up in fixincludes is a nightmare.  */
+         skip_line_comment (pfile);
+         return ' ';
+       }
+      else if (CPP_OPTIONS (pfile)->cplusplus_comments)
+       {
+         if (CPP_OPTIONS (pfile)->c89
+             && CPP_PEDANTIC (pfile)
+             && ! CPP_BUFFER (pfile)->warned_cplusplus_comments)
+           {
+             cpp_pedwarn (pfile,
+                          "C++ style comments are not allowed in ISO C89");
+             cpp_pedwarn (pfile,
+                          "(this will be reported only once per input file)");
+             CPP_BUFFER (pfile)->warned_cplusplus_comments = 1;
+           }
+         skip_line_comment (pfile);
+         return ' ';
+       }
+      else
+       return m;
+    }
+  else if (m == '-' && PEEKC() == '-'
+          && CPP_OPTIONS (pfile)->chill)
+    {
+      skip_line_comment (pfile);
+      return ' ';
+    }
+  else
+    return m;
+}
+
+/* Identical to skip_comment except that it copies the comment into the
+   token_buffer.  This is used if !discard_comments.  */
+static int
+copy_comment (pfile, m)
+     cpp_reader *pfile;
+     int m;
+{
+  const U_CHAR *start = CPP_BUFFER (pfile)->cur;  /* XXX Layering violation */
+  const U_CHAR *limit;
+
+  if (skip_comment (pfile, m) == m)
+    return m;
+
+  limit = CPP_BUFFER (pfile)->cur;
+  CPP_RESERVE (pfile, limit - start + 2);
+  CPP_PUTC_Q (pfile, m);
+  for (; start <= limit; start++)
+    if (*start != '\r')
+      CPP_PUTC_Q (pfile, *start);
+
+  return ' ';
+}
+
+/* Skip whitespace \-newline and comments.  Does not macro-expand.  */
+
+void
+_cpp_skip_hspace (pfile)
+     cpp_reader *pfile;
+{
+  int c;
+  while (1)
+    {
+      c = GETC();
+      if (c == EOF)
+       return;
+      else if (is_hspace(c))
+       {
+         if ((c == '\f' || c == '\v') && CPP_PEDANTIC (pfile))
+           cpp_pedwarn (pfile, "%s in preprocessing directive",
+                        c == '\f' ? "formfeed" : "vertical tab");
+       }
+      else if (c == '\r')
+       {
+         /* \r is a backslash-newline marker if !has_escapes, and
+            a deletable-whitespace or no-reexpansion marker otherwise. */
+         if (CPP_BUFFER (pfile)->has_escapes)
+           {
+             if (PEEKC() == ' ')
+               FORWARD(1);
+             else
+               break;
+           }
+         else
+           CPP_BUMP_LINE (pfile);
+       }
+      else if (c == '/' || c == '-')
+       {
+         c = skip_comment (pfile, c);
+         if (c  != ' ')
+           break;
+       }
+      else
+       break;
+    }
+  FORWARD(-1);
+}
+
+/* Read and discard the rest of the current line.  */
+
+void
+_cpp_skip_rest_of_line (pfile)
+     cpp_reader *pfile;
+{
+  for (;;)
+    {
+      int c = GETC();
+      switch (c)
+       {
+       case '\n':
+         FORWARD(-1);
+       case EOF:
+         return;
+
+       case '\r':
+         if (! CPP_BUFFER (pfile)->has_escapes)
+           CPP_BUMP_LINE (pfile);
+         break;
+         
+       case '\'':
+       case '\"':
+         skip_string (pfile, c);
+         break;
+
+       case '/':
+       case '-':
+         skip_comment (pfile, c);
+         break;
+
+       case '\f':
+       case '\v':
+         if (CPP_PEDANTIC (pfile))
+           cpp_pedwarn (pfile, "%s in preprocessing directive",
+                        c == '\f' ? "formfeed" : "vertical tab");
+         break;
+
+       }
+    }
+}
+
+/* Parse an identifier starting with C.  */
+
+void
+_cpp_parse_name (pfile, c)
+     cpp_reader *pfile;
+     int c;
+{
+  for (;;)
+  {
+      if (! is_idchar(c))
+      {
+         FORWARD (-1);
+         break;
+      }
+
+      if (c == '$' && CPP_PEDANTIC (pfile))
+       cpp_pedwarn (pfile, "`$' in identifier");
+
+      CPP_RESERVE(pfile, 2); /* One more for final NUL.  */
+      CPP_PUTC_Q (pfile, c);
+      c = GETC();
+      if (c == EOF)
+       break;
+  }
+  CPP_NUL_TERMINATE_Q (pfile);
+  return;
+}
+
+/* Parse and skip over a string starting with C.  A single quoted
+   string is treated like a double -- some programs (e.g., troff) are
+   perverse this way.  (However, a single quoted string is not allowed
+   to extend over multiple lines.)  */
+static void
+skip_string (pfile, c)
+     cpp_reader *pfile;
+     int c;
+{
+  long start_line, start_column;
+  cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column);
+
+  while (1)
+    {
+      int cc = GETC();
+      switch (cc)
+       {
+       case EOF:
+         cpp_error_with_line (pfile, start_line, start_column,
+                              "unterminated string or character constant");
+         if (pfile->multiline_string_line != start_line
+             && pfile->multiline_string_line != 0)
+           cpp_error_with_line (pfile,
+                                pfile->multiline_string_line, -1,
+                        "possible real start of unterminated constant");
+         pfile->multiline_string_line = 0;
+         return;
+
+       case '\n':
+         CPP_BUMP_LINE (pfile);
+         /* In Fortran and assembly language, silently terminate
+            strings of either variety at end of line.  This is a
+            kludge around not knowing where comments are in these
+            languages.  */
+         if (CPP_OPTIONS (pfile)->lang_fortran
+             || CPP_OPTIONS (pfile)->lang_asm)
+           {
+             FORWARD(-1);
+             return;
+           }
+         /* Character constants may not extend over multiple lines.
+            In Standard C, neither may strings.  We accept multiline
+            strings as an extension.  */
+         if (c == '\'')
+           {
+             cpp_error_with_line (pfile, start_line, start_column,
+                                  "unterminated character constant");
+             FORWARD(-1);
+             return;
+           }
+         if (CPP_PEDANTIC (pfile) && pfile->multiline_string_line == 0)
+           cpp_pedwarn_with_line (pfile, start_line, start_column,
+                                  "string constant runs past end of line");
+         if (pfile->multiline_string_line == 0)
+           pfile->multiline_string_line = start_line;
+         break;
+
+       case '\r':
+         if (CPP_BUFFER (pfile)->has_escapes)
+           {
+             cpp_ice (pfile, "\\r escape inside string constant");
+             FORWARD(1);
+           }
+         else
+           /* Backslash newline is replaced by nothing at all.  */
+           CPP_BUMP_LINE (pfile);
+         break;
+
+       case '\\':
+         FORWARD(1);
+         break;
+
+       case '\"':
+       case '\'':
+         if (cc == c)
+           return;
+         break;
+       }
+    }
+}
+
+/* Parse a string and copy it to the output.  */
+
+static void
+parse_string (pfile, c)
+     cpp_reader *pfile;
+     int c;
+{
+  const U_CHAR *start = CPP_BUFFER (pfile)->cur;  /* XXX Layering violation */
+  const U_CHAR *limit;
+
+  skip_string (pfile, c);
+
+  limit = CPP_BUFFER (pfile)->cur;
+  CPP_RESERVE (pfile, limit - start + 2);
+  CPP_PUTC_Q (pfile, c);
+  for (; start < limit; start++)
+    if (*start != '\r')
+      CPP_PUTC_Q (pfile, *start);
+}
+
+/* Read an assertion into the token buffer, converting to
+   canonical form: `#predicate(a n swe r)'  The next non-whitespace
+   character to read should be the first letter of the predicate.
+   Returns 0 for syntax error, 1 for bare predicate, 2 for predicate
+   with answer (see callers for why). In case of 0, an error has been
+   printed. */
+int
+_cpp_parse_assertion (pfile)
+     cpp_reader *pfile;
+{
+  int c, dropwhite;
+  _cpp_skip_hspace (pfile);
+  c = PEEKC();
+  if (! is_idstart(c))
+    {
+      cpp_error (pfile, "assertion predicate is not an identifier");
+      return 0;
+    }
+  CPP_PUTC(pfile, '#');
+  FORWARD(1);
+  _cpp_parse_name (pfile, c);
+
+  c = PEEKC();
+  if (c != '(')
+    {
+      if (is_hspace(c) || c == '\r')
+       _cpp_skip_hspace (pfile);
+      c = PEEKC();
+    }
+  if (c != '(')
+    return 1;
+
+  CPP_PUTC(pfile, '(');
+  FORWARD(1);
+  dropwhite = 1;
+  while ((c = GETC()) != ')')
+    {
+      if (is_space(c))
+       {
+         if (! dropwhite)
+           {
+             CPP_PUTC(pfile, ' ');
+             dropwhite = 1;
+           }
+       }
+      else if (c == '\n' || c == EOF)
+       {
+         if (c == '\n') FORWARD(-1);
+         cpp_error (pfile, "un-terminated assertion answer");
+         return 0;
+       }
+      else if (c == '\r')
+       /* \r cannot be a macro escape here. */
+       CPP_BUMP_LINE (pfile);
+      else
+       {
+         CPP_PUTC (pfile, c);
+         dropwhite = 0;
+       }
+    }
+
+  if (pfile->limit[-1] == ' ')
+    pfile->limit[-1] = ')';
+  else if (pfile->limit[-1] == '(')
+    {
+      cpp_error (pfile, "empty token sequence in assertion");
+      return 0;
+    }
+  else
+    CPP_PUTC (pfile, ')');
+
+  CPP_NUL_TERMINATE (pfile);
+  return 2;
+}
+
+/* Get the next token, and add it to the text in pfile->token_buffer.
+   Return the kind of token we got.  */
+
+enum cpp_token
+_cpp_lex_token (pfile)
+     cpp_reader *pfile;
+{
+  register int c, c2, c3;
+  enum cpp_token token;
+  struct cpp_options *opts = CPP_OPTIONS (pfile);
+
+ get_next:
+  c = GETC();
+  switch (c)
+    {
+    case EOF:
+      return CPP_EOF;
+
+    case '/':
+      if (PEEKC () == '=')
+       goto op2;
+
+    comment:
+      if (opts->discard_comments)
+       c = skip_comment (pfile, c);
+      else
+       c = copy_comment (pfile, c);
+      if (c != ' ')
+       goto randomchar;
+         
+      /* Comments are equivalent to spaces.
+        For -traditional, a comment is equivalent to nothing.  */
+      if (opts->traditional || !opts->discard_comments)
+       return CPP_COMMENT;
+      else
+       {
+         CPP_PUTC (pfile, c);
+         return CPP_HSPACE;
+       }
+
+    case '#':
+      if (pfile->parsing_if_directive)
+       {
+         _cpp_skip_hspace (pfile);
+         _cpp_parse_assertion (pfile);
+         return CPP_ASSERTION;
+       }
+
+      if (pfile->parsing_define_directive && ! CPP_TRADITIONAL (pfile))
+       {
+         CPP_RESERVE (pfile, 3);
+         CPP_PUTC_Q (pfile, '#');
+         CPP_NUL_TERMINATE_Q (pfile);
+         if (PEEKC () != '#')
+           return CPP_STRINGIZE;
+             
+         FORWARD (1);
+         CPP_PUTC_Q (pfile, '#');
+         CPP_NUL_TERMINATE_Q (pfile);
+         return CPP_TOKPASTE;
+       }
+
+      if (!pfile->only_seen_white)
+       goto randomchar;
+      /* -traditional directives are recognized only with the # in
+        column 1.
+        XXX Layering violation.  */
+      if (CPP_TRADITIONAL (pfile)
+         && CPP_BUFFER (pfile)->cur - CPP_BUFFER (pfile)->line_base != 1)
+       goto randomchar;
+      return CPP_DIRECTIVE;
+
+    case '\"':
+    case '\'':
+      parse_string (pfile, c);
+      pfile->only_seen_white = 0;
+      return c == '\'' ? CPP_CHAR : CPP_STRING;
+
+    case '$':
+      if (!opts->dollars_in_ident)
+       goto randomchar;
+      goto letter;
+
+    case ':':
+      if (opts->cplusplus && PEEKC () == ':')
+       goto op2;
+      goto randomchar;
+
+    case '&':
+    case '+':
+    case '|':
+      c2 = PEEKC ();
+      if (c2 == c || c2 == '=')
+       goto op2;
+      goto randomchar;
+
+    case '*':
+    case '!':
+    case '%':
+    case '=':
+    case '^':
+      if (PEEKC () == '=')
+       goto op2;
+      goto randomchar;
+
+    case '-':
+      c2 = PEEKC ();
+      if (c2 == '-')
+       {
+         if (opts->chill)
+           goto comment;  /* Chill style comment */
+         else
+           goto op2;
+       }
+      else if (c2 == '=')
+       goto op2;
+      else if (c2 == '>')
+       {
+         if (opts->cplusplus && PEEKN (1) == '*')
+           {
+             /* In C++, there's a ->* operator.  */
+             token = CPP_OTHER;
+             pfile->only_seen_white = 0;
+             CPP_RESERVE (pfile, 4);
+             CPP_PUTC_Q (pfile, c);
+             CPP_PUTC_Q (pfile, GETC ());
+             CPP_PUTC_Q (pfile, GETC ());
+             CPP_NUL_TERMINATE_Q (pfile);
+             return token;
+           }
+         goto op2;
+       }
+      goto randomchar;
+
+    case '<':
+      if (pfile->parsing_include_directive)
+       {
+         for (;;)
+           {
+             CPP_PUTC (pfile, c);
+             if (c == '>')
+               break;
+             c = GETC ();
+             if (c == '\n' || c == EOF)
+               {
+                 cpp_error (pfile,
+                            "missing '>' in `#include <FILENAME>'");
+                 break;
+               }
+             else if (c == '\r')
+               {
+                 if (!CPP_BUFFER (pfile)->has_escapes)
+                   {
+                     /* Backslash newline is replaced by nothing. */
+                     CPP_ADJUST_WRITTEN (pfile, -1);
+                     CPP_BUMP_LINE (pfile);
+                   }
+                 else
+                   {
+                     /* We might conceivably get \r- or \r<space> in
+                        here.  Just delete 'em. */
+                     int d = GETC();
+                     if (d != '-' && d != ' ')
+                       cpp_ice (pfile, "unrecognized escape \\r%c", d);
+                     CPP_ADJUST_WRITTEN (pfile, -1);
+                   }                     
+               }
+           }
+         return CPP_STRING;
+       }
+      /* else fall through */
+    case '>':
+      c2 = PEEKC ();
+      if (c2 == '=')
+       goto op2;
+      /* GNU C++ supports MIN and MAX operators <? and >?.  */
+      if (c2 != c && (!opts->cplusplus || c2 != '?'))
+       goto randomchar;
+      FORWARD(1);
+      CPP_RESERVE (pfile, 4);
+      CPP_PUTC (pfile, c);
+      CPP_PUTC (pfile, c2);
+      c3 = PEEKC ();
+      if (c3 == '=')
+       CPP_PUTC_Q (pfile, GETC ());
+      CPP_NUL_TERMINATE_Q (pfile);
+      pfile->only_seen_white = 0;
+      return CPP_OTHER;
+
+    case '.':
+      c2 = PEEKC ();
+      if (ISDIGIT(c2))
+       {
+         CPP_RESERVE(pfile, 2);
+         CPP_PUTC_Q (pfile, '.');
+         c = GETC ();
+         goto number;
+       }
+
+      /* In C++ there's a .* operator.  */
+      if (opts->cplusplus && c2 == '*')
+       goto op2;
+
+      if (c2 == '.' && PEEKN(1) == '.')
+       {
+         CPP_RESERVE(pfile, 4);
+         CPP_PUTC_Q (pfile, '.');
+         CPP_PUTC_Q (pfile, '.');
+         CPP_PUTC_Q (pfile, '.');
+         FORWARD (2);
+         CPP_NUL_TERMINATE_Q (pfile);
+         pfile->only_seen_white = 0;
+         return CPP_3DOTS;
+       }
+      goto randomchar;
+
+    op2:
+      token = CPP_OTHER;
+      pfile->only_seen_white = 0;
+      CPP_RESERVE(pfile, 3);
+      CPP_PUTC_Q (pfile, c);
+      CPP_PUTC_Q (pfile, GETC ());
+      CPP_NUL_TERMINATE_Q (pfile);
+      return token;
+
+    case 'L':
+      c2 = PEEKC ();
+      if ((c2 == '\'' || c2 == '\"') && !CPP_TRADITIONAL (pfile))
+       {
+         CPP_PUTC (pfile, c);
+         c = GETC ();
+         parse_string (pfile, c);
+         pfile->only_seen_white = 0;
+         return c == '\'' ? CPP_WCHAR : CPP_WSTRING;
+       }
+      goto letter;
+
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+    number:
+    c2  = '.';
+    for (;;)
+      {
+       CPP_RESERVE (pfile, 2);
+       CPP_PUTC_Q (pfile, c);
+       c = PEEKC ();
+       if (c == EOF)
+         break;
+       if (!is_numchar(c) && c != '.'
+           && ((c2 != 'e' && c2 != 'E'
+                && ((c2 != 'p' && c2 != 'P')
+                    || CPP_OPTIONS (pfile)->c89))
+               || (c != '+' && c != '-')))
+         break;
+       FORWARD(1);
+       c2= c;
+      }
+    CPP_NUL_TERMINATE_Q (pfile);
+    pfile->only_seen_white = 0;
+    return CPP_NUMBER;
+    case 'b': case 'c': case 'd': case 'h': case 'o':
+    case 'B': case 'C': case 'D': case 'H': case 'O':
+      if (opts->chill && PEEKC () == '\'')
+       {
+         pfile->only_seen_white = 0;
+         CPP_RESERVE (pfile, 2);
+         CPP_PUTC_Q (pfile, c);
+         CPP_PUTC_Q (pfile, '\'');
+         FORWARD(1);
+         for (;;)
+           {
+             c = GETC();
+             if (c == EOF)
+               goto chill_number_eof;
+             if (!is_numchar(c))
+               break;
+             CPP_PUTC (pfile, c);
+           }
+         if (c == '\'')
+           {
+             CPP_RESERVE (pfile, 2);
+             CPP_PUTC_Q (pfile, c);
+             CPP_NUL_TERMINATE_Q (pfile);
+             return CPP_STRING;
+           }
+         else
+           {
+             FORWARD(-1);
+           chill_number_eof:
+             CPP_NUL_TERMINATE (pfile);
+             return CPP_NUMBER;
+           }
+       }
+      else
+       goto letter;
+    case '_':
+    case 'a': case 'e': case 'f': case 'g': case 'i': case 'j':
+    case 'k': case 'l': case 'm': case 'n': 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 'E': case 'F': case 'G': case 'I': case 'J':
+    case 'K': case 'M': case 'N': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    letter:
+    pfile->only_seen_white = 0;
+    _cpp_parse_name (pfile, c);
+    return CPP_MACRO;
+
+    case ' ':  case '\t':  case '\v':
+      for (;;)
+       {
+         CPP_PUTC (pfile, c);
+         c = PEEKC ();
+         if (c == EOF || !is_hspace(c))
+           break;
+         FORWARD(1);
+       }
+      return CPP_HSPACE;
+
+    case '\r':
+      if (CPP_BUFFER (pfile)->has_escapes)
+       {
+         c = GETC ();
+         if (c == '-')
+           {
+             if (pfile->output_escapes)
+               CPP_PUTS (pfile, "\r-", 2);
+             _cpp_parse_name (pfile, GETC ());
+             return CPP_NAME;
+           }
+         else if (c == ' ')
+           {
+             CPP_RESERVE (pfile, 2);
+             if (pfile->output_escapes)
+               CPP_PUTC_Q (pfile, '\r');
+             CPP_PUTC_Q (pfile, c);
+             return CPP_HSPACE;
+           }
+         else
+           {
+             cpp_ice (pfile, "unrecognized escape \\r%c", c);
+             goto get_next;
+           }
+       }
+      else
+       {
+         /* Backslash newline is ignored. */
+         CPP_BUMP_LINE (pfile);
+         goto get_next;
+       }
+
+    case '\n':
+      CPP_PUTC (pfile, c);
+      if (pfile->only_seen_white == 0)
+       pfile->only_seen_white = 1;
+      CPP_BUMP_LINE (pfile);
+      if (! CPP_OPTIONS (pfile)->no_line_commands)
+       {
+         pfile->lineno++;
+         if (CPP_BUFFER (pfile)->lineno != pfile->lineno)
+           _cpp_output_line_command (pfile, same_file);
+       }
+      return CPP_VSPACE;
+
+    case '(': token = CPP_LPAREN;    goto char1;
+    case ')': token = CPP_RPAREN;    goto char1;
+    case '{': token = CPP_LBRACE;    goto char1;
+    case '}': token = CPP_RBRACE;    goto char1;
+    case ',': token = CPP_COMMA;     goto char1;
+    case ';': token = CPP_SEMICOLON; goto char1;
+
+    randomchar:
+    default:
+      token = CPP_OTHER;
+    char1:
+      pfile->only_seen_white = 0;
+      CPP_PUTC (pfile, c);
+      return token;
+    }
+}
+
+/* Check for and expand a macro, which is from WRITTEN to CPP_WRITTEN (pfile).
+   Caller is expected to have checked no_macro_expand.  */
+static int
+maybe_macroexpand (pfile, written)
+     cpp_reader *pfile;
+     long written;
+{
+  U_CHAR *macro = pfile->token_buffer + written;
+  size_t len = CPP_WRITTEN (pfile) - written;
+  HASHNODE *hp = _cpp_lookup (pfile, macro, len);
+
+  if (!hp)
+    return 0;
+  if (hp->type == T_DISABLED)
+    {
+      if (pfile->output_escapes)
+       {
+         /* Insert a no-reexpand marker before IDENT.  */
+         CPP_RESERVE (pfile, 2);
+         CPP_ADJUST_WRITTEN (pfile, 2);
+         macro = pfile->token_buffer + written;
+
+         memmove (macro + 2, macro, len);
+         macro[0] = '\r';
+         macro[1] = '-';
+       }
+      return 0;
+    }
+
+  /* If macro wants an arglist, verify that a '(' follows.  */
+  if (hp->type == T_MACRO && hp->value.defn->nargs >= 0)
+    {
+      int macbuf_whitespace = 0;
+      int c;
+
+      while (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
+       {
+         const U_CHAR *point = CPP_BUFFER (pfile)->cur;
+         for (;;)
+           {
+             _cpp_skip_hspace (pfile);
+             c = PEEKC ();
+             if (c == '\n')
+               FORWARD(1);
+             else
+               break;
+           }
+         if (point != CPP_BUFFER (pfile)->cur)
+           macbuf_whitespace = 1;
+         if (c == '(')
+           goto is_macro_call;
+         else if (c != EOF)
+           goto not_macro_call;
+         cpp_pop_buffer (pfile);
+       }
+
+      CPP_SET_MARK (pfile);
+      for (;;)
+       {
+         _cpp_skip_hspace (pfile);
+         c = PEEKC ();
+         if (c == '\n')
+           FORWARD(1);
+         else
+           break;
+       }
+      CPP_GOTO_MARK (pfile);
+
+      if (c != '(')
+       {
+       not_macro_call:
+         if (macbuf_whitespace)
+           CPP_PUTC (pfile, ' ');
+         return 0;
+       }
+    }
+
+ is_macro_call:
+  /* This is now known to be a macro call.
+     Expand the macro, reading arguments as needed,
+     and push the expansion on the input stack.  */
+  _cpp_macroexpand (pfile, hp);
+  CPP_SET_WRITTEN (pfile, written);
+  return 1;
+}
+
+enum cpp_token
+cpp_get_token (pfile)
+     cpp_reader *pfile;
+{
+  enum cpp_token token;
+  long written = CPP_WRITTEN (pfile);
+
+ get_next:
+  token = _cpp_lex_token (pfile);
+
+  switch (token)
+    {
+    default:
+      return token;
+
+    case CPP_DIRECTIVE:
+      if (_cpp_handle_directive (pfile))
+       return CPP_DIRECTIVE;
+      pfile->only_seen_white = 0;
+      CPP_PUTC (pfile, '#');
+      return CPP_OTHER;
+
+    case CPP_MACRO:
+      if (! pfile->no_macro_expand
+         && maybe_macroexpand (pfile, written))
+       goto get_next;
+      return CPP_NAME;
+
+    case CPP_EOF:
+      if (CPP_BUFFER (pfile)->manual_pop)
+       /* If we've been reading from redirected input, the
+          frontend will pop the buffer.  */
+       return CPP_EOF;
+      else if (CPP_BUFFER (pfile)->seen_eof)
+       {
+         if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) == NULL)
+           return CPP_EOF;
+
+         cpp_pop_buffer (pfile);
+         goto get_next;
+       }
+      else
+       {
+         _cpp_handle_eof (pfile);
+         return CPP_POP;
+       }
+    }
+}
+
+/* Like cpp_get_token, but skip spaces and comments.  */
+
+enum cpp_token
+cpp_get_non_space_token (pfile)
+     cpp_reader *pfile;
+{
+  int old_written = CPP_WRITTEN (pfile);
+  for (;;)
+    {
+      enum cpp_token token = cpp_get_token (pfile);
+      if (token != CPP_COMMENT && token != CPP_POP
+         && token != CPP_HSPACE && token != CPP_VSPACE)
+       return token;
+      CPP_SET_WRITTEN (pfile, old_written);
+    }
+}
+
+/* Like cpp_get_token, except that it does not read past end-of-line.
+   Also, horizontal space is skipped, and macros are popped.  */
+
+enum cpp_token
+_cpp_get_directive_token (pfile)
+     cpp_reader *pfile;
+{
+  long old_written = CPP_WRITTEN (pfile);
+  enum cpp_token token;
+
+  for (;;)
+    {
+      _cpp_skip_hspace (pfile);
+      if (PEEKC () == '\n')
+       return CPP_VSPACE;
+
+      token = cpp_get_token (pfile);
+      /* token could be hspace at the beginning of a macro.  */
+      if (token == CPP_HSPACE || token == CPP_COMMENT)
+       {
+         CPP_SET_WRITTEN (pfile, old_written);
+         continue;
+       }
+
+      /* token cannot be vspace, it would have been caught above.  */
+      if (token == CPP_VSPACE)
+       {
+         cpp_ice (pfile, "VSPACE in get_directive_token");
+         return token;
+       }
+
+      /* token cannot be POP unless the buffer is a macro buffer.  */
+      if (token != CPP_POP)
+       return token;
+
+      if (! CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
+       {
+         cpp_ice (pfile, "POP of file buffer in get_directive_token");
+         return token;
+       }
+
+      /* We must pop the buffer by hand, or else cpp_get_token might
+        hand us white space or newline on the next invocation.  */
+      cpp_pop_buffer (pfile);
+    }
+}
+
+/* Determine the current line and column.  Used only by read_and_prescan. */
+static U_CHAR *
+find_position (start, limit, linep)
+     U_CHAR *start;
+     U_CHAR *limit;
+     unsigned long *linep;
+{
+  unsigned long line = *linep;
+  U_CHAR *lbase = start;
+  while (start < limit)
+    {
+      U_CHAR ch = *start++;
+      if (ch == '\n' || ch == '\r')
+       {
+         line++;
+         lbase = start;
+       }
+    }
+  *linep = line;
+  return lbase;
+}
+
+/* Read the entire contents of file DESC into buffer BUF.  LEN is how
+   much memory to allocate initially; more will be allocated if
+   necessary.  Convert end-of-line markers (\n, \r, \r\n, \n\r) to
+   canonical form (\n).  If enabled, convert and/or warn about
+   trigraphs.  Convert backslash-newline to a one-character escape
+   (\r) and remove it from "embarrassing" places (i.e. the middle of a
+   token).  If there is no newline at the end of the file, add one and
+   warn.  Returns -1 on failure, or the actual length of the data to
+   be scanned.
+
+   This function does a lot of work, and can be a serious performance
+   bottleneck.  It has been tuned heavily; make sure you understand it
+   before hacking.  The common case - no trigraphs, Unix style line
+   breaks, backslash-newline set off by whitespace, newline at EOF -
+   has been optimized at the expense of the others.  The performance
+   penalty for DOS style line breaks (\r\n) is about 15%.
+   
+   Warnings lose particularly heavily since we have to determine the
+   line number, which involves scanning from the beginning of the file
+   or from the last warning.  The penalty for the absence of a newline
+   at the end of reload1.c is about 60%.  (reload1.c is 329k.)
+
+   If your file has more than one kind of end-of-line marker, you
+   will get messed-up line numbering.  */
+
+/* Table of characters that can't be handled in the inner loop.
+   Keep these contiguous to optimize the performance of the code generated
+   for the switch that uses them.  */
+#define SPECCASE_EMPTY     0
+#define SPECCASE_NUL       1
+#define SPECCASE_CR        2
+#define SPECCASE_BACKSLASH 3
+#define SPECCASE_QUESTION  4
+
+long
+_cpp_read_and_prescan (pfile, fp, desc, len)
+     cpp_reader *pfile;
+     cpp_buffer *fp;
+     int desc;
+     size_t len;
+{
+  U_CHAR *buf = (U_CHAR *) xmalloc (len);
+  U_CHAR *ip, *op, *line_base;
+  U_CHAR *ibase;
+  U_CHAR *speccase = pfile->input_speccase;
+  unsigned long line;
+  unsigned int deferred_newlines;
+  int count;
+  size_t offset;
+
+  offset = 0;
+  op = buf;
+  line_base = buf;
+  line = 1;
+  ibase = pfile->input_buffer + 2;
+  deferred_newlines = 0;
+
+  for (;;)
+    {
+    read_next:
+
+      count = read (desc, pfile->input_buffer + 2, pfile->input_buffer_len);
+      if (count < 0)
+       goto error;
+      else if (count == 0)
+       break;
+
+      offset += count;
+      ip = ibase;
+      ibase = pfile->input_buffer + 2;
+      ibase[count] = ibase[count+1] = '\0';
+
+      if (offset > len)
+       {
+         size_t delta_op;
+         size_t delta_line_base;
+         len *= 2;
+         if (offset > len)
+           /* len overflowed.
+              This could happen if the file is larger than half the
+              maximum address space of the machine. */
+           goto too_big;
+
+         delta_op = op - buf;
+         delta_line_base = line_base - buf;
+         buf = (U_CHAR *) xrealloc (buf, len);
+         op = buf + delta_op;
+         line_base = buf + delta_line_base;
+       }
+
+      for (;;)
+       {
+         unsigned int span = 0;
+
+         /* Deal with \-newline in the middle of a token. */
+         if (deferred_newlines)
+           {
+             while (speccase[ip[span]] == SPECCASE_EMPTY
+                    && ip[span] != '\n'
+                    && ip[span] != '\t'
+                    && ip[span] != ' ')
+               span++;
+             memcpy (op, ip, span);
+             op += span;
+             ip += span;
+             /* If ip[0] is SPECCASE_EMPTY, we have hit white space.
+                Dump out the remaining deferred \-newlines.  */
+             if (speccase[ip[0]] == SPECCASE_EMPTY)
+               while (deferred_newlines)
+                 deferred_newlines--, *op++ = '\r';
+             span = 0;
+           }
+
+         /* Copy as much as we can without special treatment. */
+         while (speccase[ip[span]] == SPECCASE_EMPTY) span++;
+         memcpy (op, ip, span);
+         op += span;
+         ip += span;
+
+         switch (speccase[*ip++])
+           {
+           case SPECCASE_NUL:  /* \0 */
+             ibase[-1] = op[-1];
+             goto read_next;
+
+           case SPECCASE_CR:  /* \r */
+             if (ip[-2] == '\n')
+               continue;
+             else if (*ip == '\n')
+               ip++;
+             else if (*ip == '\0')
+               {
+                 *--ibase = '\r';
+                 goto read_next;
+               }
+             *op++ = '\n';
+             break;
+
+           case SPECCASE_BACKSLASH:  /* \ */
+           backslash:
+           {
+             /* If we're at the end of the intermediate buffer,
+                we have to shift the backslash down to the start
+                and come back next pass. */
+             if (*ip == '\0')
+               {
+                 *--ibase = '\\';
+                 goto read_next;
+               }
+             else if (*ip == '\n')
+               {
+                 ip++;
+                 if (*ip == '\r') ip++;
+                 if (*ip == '\n' || *ip == '\t' || *ip == ' ')
+                   *op++ = '\r';
+                 else if (op[-1] == '\t' || op[-1] == ' '
+                          || op[-1] == '\r' || op[-1] == '\n')
+                   *op++ = '\r';
+                 else
+                   deferred_newlines++;
+               }
+             else if (*ip == '\r')
+               {
+                 ip++;
+                 if (*ip == '\n') ip++;
+                 else if (*ip == '\0')
+                   {
+                     *--ibase = '\r';
+                     *--ibase = '\\';
+                     goto read_next;
+                   }
+                 else if (*ip == '\r' || *ip == '\t' || *ip == ' ')
+                   *op++ = '\r';
+                 else
+                   deferred_newlines++;
+               }
+             else
+               *op++ = '\\';
+           }
+           break;
+
+           case SPECCASE_QUESTION: /* ? */
+             {
+               unsigned int d, t;
+               /* If we're at the end of the intermediate buffer,
+                  we have to shift the ?'s down to the start and
+                  come back next pass. */
+               d = ip[0];
+               if (d == '\0')
+                 {
+                   *--ibase = '?';
+                   goto read_next;
+                 }
+               if (d != '?')
+                 {
+                   *op++ = '?';
+                   break;
+                 }
+               d = ip[1];
+               if (d == '\0')
+                 {
+                   *--ibase = '?';
+                   *--ibase = '?';
+                   goto read_next;
+                 }
+
+               /* Trigraph map:
+                *      from    to      from    to      from    to
+                *      ?? =    #       ?? )    ]       ?? !    |
+                *      ?? (    [       ?? '    ^       ?? >    }
+                *      ?? /    \       ?? <    {       ?? -    ~
+                */
+               if (d == '=') t = '#';
+               else if (d == ')') t = ']';
+               else if (d == '!') t = '|';
+               else if (d == '(') t = '[';
+               else if (d == '\'') t = '^';
+               else if (d == '>') t = '}';
+               else if (d == '/') t = '\\';
+               else if (d == '<') t = '{';
+               else if (d == '-') t = '~';
+               else
+                 {
+                   *op++ = '?';
+                   break;
+                 }
+               ip += 2;
+               if (CPP_OPTIONS (pfile)->warn_trigraphs)
+                 {
+                   unsigned long col;
+                   line_base = find_position (line_base, op, &line);
+                   col = op - line_base + 1;
+                   if (CPP_OPTIONS (pfile)->trigraphs)
+                     cpp_warning_with_line (pfile, line, col,
+                            "trigraph ??%c converted to %c", d, t);
+                   else
+                     cpp_warning_with_line (pfile, line, col,
+                            "trigraph ??%c ignored", d);
+                 }
+               if (CPP_OPTIONS (pfile)->trigraphs)
+                 {
+                   if (t == '\\')
+                     goto backslash;
+                   else
+                     *op++ = t;
+                 }
+               else
+                 {
+                   *op++ = '?';
+                   *op++ = '?';
+                   *op++ = d;
+                 }
+             }
+           }
+       }
+    }
+
+  if (offset == 0)
+    return 0;
+
+  /* Deal with pushed-back chars at true EOF.
+     This may be any of:  ?? ? \ \r \n \\r \\n.
+     \r must become \n, \\r or \\n must become \r.
+     We know we have space already. */
+  if (ibase == pfile->input_buffer)
+    {
+      if (*ibase == '?')
+       {
+         *op++ = '?';
+         *op++ = '?';
+       }
+      else
+       *op++ = '\r';
+    }
+  else if (ibase == pfile->input_buffer + 1)
+    {
+      if (*ibase == '\r')
+       *op++ = '\n';
+      else
+       *op++ = *ibase;
+    }
+
+  if (op[-1] != '\n')
+    {
+      unsigned long col;
+      line_base = find_position (line_base, op, &line);
+      col = op - line_base + 1;
+      cpp_warning_with_line (pfile, line, col, "no newline at end of file\n");
+      if (offset + 1 > len)
+       {
+         len += 1;
+         if (offset + 1 > len)
+           goto too_big;
+         buf = (U_CHAR *) xrealloc (buf, len);
+         op = buf + offset;
+       }
+      *op++ = '\n';
+    }
+
+  fp->buf = ((len - offset < 20) ? buf : (U_CHAR *)xrealloc (buf, op - buf));
+  return op - buf;
+
+ too_big:
+  cpp_error (pfile, "file is too large (>%lu bytes)\n", (unsigned long)offset);
+  free (buf);
+  return -1;
+
+ error:
+  cpp_error_from_errno (pfile, fp->ihash->name);
+  free (buf);
+  return -1;
+}
+
+/* Initialize the `input_buffer' and `input_speccase' tables.
+   These are only used by read_and_prescan, but they're large and
+   somewhat expensive to set up, so we want them allocated once for
+   the duration of the cpp run.  */
+
+void
+_cpp_init_input_buffer (pfile)
+     cpp_reader *pfile;
+{
+  U_CHAR *tmp;
+
+  /* Table of characters that cannot be handled by the
+     read_and_prescan inner loop.  The number of non-EMPTY entries
+     should be as small as humanly possible.  */
+
+  tmp = (U_CHAR *) xmalloc (1 << CHAR_BIT);
+  memset (tmp, SPECCASE_EMPTY, 1 << CHAR_BIT);
+  tmp['\0'] = SPECCASE_NUL;
+  tmp['\r'] = SPECCASE_CR;
+  tmp['\\'] = SPECCASE_BACKSLASH;
+  if (CPP_OPTIONS (pfile)->trigraphs || CPP_OPTIONS (pfile)->warn_trigraphs)
+    tmp['?'] = SPECCASE_QUESTION;
+
+  pfile->input_speccase = tmp;
+
+  /* Determine the appropriate size for the input buffer.  Normal C
+     source files are smaller than eight K.  */
+  /* 8Kbytes of buffer proper, 2 to detect running off the end without
+     address arithmetic all the time, and 2 for pushback in the case
+     there's a potential trigraph or end-of-line digraph at the end of
+     a block. */
+
+  tmp = (U_CHAR *) xmalloc (8192 + 2 + 2);
+  pfile->input_buffer = tmp;
+  pfile->input_buffer_len = 8192;
+}
index 02a9318..1de14d3 100644 (file)
@@ -28,19 +28,11 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "intl.h"
 #include "mkdeps.h"
 
-#define SKIP_WHITE_SPACE(p) do { while (is_hspace(*p)) p++; } while (0)
-
-#define PEEKN(N) (CPP_BUFFER (pfile)->rlimit - CPP_BUFFER (pfile)->cur >= (N) ? CPP_BUFFER (pfile)->cur[N] : EOF)
+#define PEEKN(N) (CPP_BUFFER (pfile)->rlimit - CPP_BUFFER (pfile)->cur >= (N) \
+                 ? CPP_BUFFER (pfile)->cur[N] : EOF)
 #define FORWARD(N) CPP_FORWARD (CPP_BUFFER (pfile), (N))
 #define GETC() CPP_BUF_GET (CPP_BUFFER (pfile))
 #define PEEKC() CPP_BUF_PEEK (CPP_BUFFER (pfile))
-/* CPP_IS_MACRO_BUFFER is true if the buffer contains macro expansion.
-   (Note that it is false while we're expanding macro *arguments*.) */
-#define CPP_IS_MACRO_BUFFER(PBUF) ((PBUF)->data != NULL)
-
-/* ACTIVE_MARK_P is true if there's a live mark in the buffer, in which
-   case CPP_BUMP_LINE must not be called.  */
-#define ACTIVE_MARK_P() (CPP_BUFFER (pfile)->mark != -1)
 
 /* `struct directive' defines one #-directive, including how to handle it.  */
 
@@ -93,22 +85,9 @@ static int do_warning PARAMS ((cpp_reader *, const struct directive *));
 /* Forward declarations.  */
 
 static void validate_else              PARAMS ((cpp_reader *, const char *));
-static int eval_if_expr                        PARAMS ((cpp_reader *));
 static void conditional_skip           PARAMS ((cpp_reader *, int,
                                                enum node_type, U_CHAR *));
 static void skip_if_group              PARAMS ((cpp_reader *));
-static void parse_name                 PARAMS ((cpp_reader *, int));
-static void parse_string               PARAMS ((cpp_reader *, int));
-static int parse_assertion             PARAMS ((cpp_reader *));
-static const char *if_directive_name   PARAMS ((cpp_reader *,
-                                                struct if_stack *));
-static int null_cleanup                        PARAMS ((cpp_buffer *, cpp_reader *));
-static int skip_comment                        PARAMS ((cpp_reader *, int));
-static int copy_comment                        PARAMS ((cpp_reader *, int));
-static void skip_string                        PARAMS ((cpp_reader *, int));
-static void skip_rest_of_line          PARAMS ((cpp_reader *));
-static void cpp_skip_hspace            PARAMS ((cpp_reader *));
-static int handle_directive            PARAMS ((cpp_reader *));
 static void pass_thru_directive                PARAMS ((const U_CHAR *, size_t,
                                                 cpp_reader *,
                                                 const struct directive *));
@@ -116,11 +95,9 @@ static int read_line_number         PARAMS ((cpp_reader *, int *));
 static U_CHAR *detect_if_not_defined   PARAMS ((cpp_reader *));
 static int consider_directive_while_skipping
                                        PARAMS ((cpp_reader *, IF_STACK *));
-static void skip_block_comment         PARAMS ((cpp_reader *));
-static void skip_line_comment          PARAMS ((cpp_reader *));
-static void parse_set_mark             PARAMS ((cpp_reader *));
-static void parse_goto_mark            PARAMS ((cpp_reader *));
 static int get_macro_name              PARAMS ((cpp_reader *));
+static const char *if_directive_name   PARAMS ((cpp_reader *,
+                                                struct if_stack *));
 
 /* Here is the actual list of #-directives.
    This table is ordered by frequency of occurrence; the numbers
@@ -156,367 +133,11 @@ static const struct directive directive_table[] = {
   {  -1, 0, "", T_UNUSED }
 };
 
-/* Place into PFILE a quoted string representing the string SRC.
-   Caller must reserve enough space in pfile->token_buffer.  */
-
-void
-quote_string (pfile, src)
-     cpp_reader *pfile;
-     const char *src;
-{
-  U_CHAR c;
-
-  CPP_PUTC_Q (pfile, '\"');
-  for (;;)
-    switch ((c = *src++))
-      {
-      default:
-        if (ISPRINT (c))
-         CPP_PUTC_Q (pfile, c);
-       else
-         {
-           sprintf ((char *)CPP_PWRITTEN (pfile), "\\%03o", c);
-           CPP_ADJUST_WRITTEN (pfile, 4);
-         }
-       break;
-
-      case '\"':
-      case '\\':
-       CPP_PUTC_Q (pfile, '\\');
-       CPP_PUTC_Q (pfile, c);
-       break;
-      
-      case '\0':
-       CPP_PUTC_Q (pfile, '\"');
-       CPP_NUL_TERMINATE_Q (pfile);
-       return;
-      }
-}
-
-/* Re-allocates PFILE->token_buffer so it will hold at least N more chars.  */
-
-void
-cpp_grow_buffer (pfile, n)
-     cpp_reader *pfile;
-     long n;
-{
-  long old_written = CPP_WRITTEN (pfile);
-  pfile->token_buffer_size = n + 2 * pfile->token_buffer_size;
-  pfile->token_buffer = (U_CHAR *)
-    xrealloc(pfile->token_buffer, pfile->token_buffer_size);
-  CPP_SET_WRITTEN (pfile, old_written);
-}
-
-/* Process the string STR as if it appeared as the body of a #define.
-   If STR is just an identifier, define it with value 1.
-   If STR has anything after the identifier, then it should
-   be identifier=definition. */
-
-void
-cpp_define (pfile, str)
-     cpp_reader *pfile;
-     const char *str;
-{
-  char *buf, *p;
-  size_t count;
-
-  p = strchr (str, '=');
-  /* 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.  Then add a newline and a NUL.  */
-  
-  if (p)
-    {
-      count = strlen (str) + 2;
-      buf = alloca (count);
-      memcpy (buf, str, count - 2);
-      buf[p - str] = ' ';
-      buf[count - 2] = '\n';
-      buf[count - 1] = '\0';
-    }
-  else
-    {
-      count = strlen (str) + 4;
-      buf = alloca (count);
-      memcpy (buf, str, count - 4);
-      strcpy (&buf[count-4], " 1\n");
-    }
-
-  if (cpp_push_buffer (pfile, buf, count - 1) != NULL)
-    {
-      do_define (pfile, NULL);
-      cpp_pop_buffer (pfile);
-    }
-}
-
-/* Process the string STR as if it appeared as the body of a #assert. */
-void
-cpp_assert (pfile, str)
-     cpp_reader *pfile;
-     const char *str;
-{
-  if (cpp_push_buffer (pfile, str, strlen (str)) != NULL)
-    {
-      do_assert (pfile, NULL);
-      cpp_pop_buffer (pfile);
-    }
-}
-
-/* Determine whether the identifier ID, of length LEN, is a defined macro.  */
-int
-cpp_defined (pfile, id, len)
-     cpp_reader *pfile;
-     const U_CHAR *id;
-     int len;
-{
-  HASHNODE *hp = _cpp_lookup (pfile, id, len);
-  if (hp && hp->type == T_POISON)
-    {
-      cpp_error (pfile, "attempt to use poisoned `%s'", hp->name);
-      return 0;
-    }
-  return (hp != NULL);
-}
-
-static int
-null_cleanup (pbuf, pfile)
-     cpp_buffer *pbuf ATTRIBUTE_UNUSED;
-     cpp_reader *pfile ATTRIBUTE_UNUSED;
-{
-  return 0;
-}
-
-/* Skip a C-style block comment.  We know it's a comment, and point is
-   at the second character of the starter.  */
-static void
-skip_block_comment (pfile)
-     cpp_reader *pfile;
-{
-  int c, prev_c = -1;
-  long line, col;
-
-  FORWARD(1);
-  cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
-  for (;;)
-    {
-      c = GETC ();
-      if (c == EOF)
-       {
-         cpp_error_with_line (pfile, line, col, "unterminated comment");
-         return;
-       }
-      else if (c == '\n' || c == '\r')
-       {
-         /* \r cannot be a macro escape marker here. */
-         if (!ACTIVE_MARK_P())
-           CPP_BUMP_LINE (pfile);
-       }
-      else if (c == '/' && prev_c == '*')
-       return;
-      else if (c == '*' && prev_c == '/'
-              && CPP_OPTIONS (pfile)->warn_comments)
-       cpp_warning (pfile, "`/*' within comment");
-
-      prev_c = c;
-    }
-}
-
-/* Skip a C++/Chill line comment.  We know it's a comment, and point
-   is at the second character of the initiator.  */
-static void
-skip_line_comment (pfile)
-     cpp_reader *pfile;
-{
-  FORWARD(1);
-  for (;;)
-    {
-      int c = GETC ();
-
-      /* We don't have to worry about EOF in here.  */
-      if (c == '\n')
-       {
-         /* Don't consider final '\n' to be part of comment.  */
-         FORWARD(-1);
-         return;
-       }
-      else if (c == '\r')
-       {
-         /* \r cannot be a macro escape marker here. */
-         if (!ACTIVE_MARK_P())
-           CPP_BUMP_LINE (pfile);
-         if (CPP_OPTIONS (pfile)->warn_comments)
-           cpp_warning (pfile, "backslash-newline within line comment");
-       }
-    }
-}
-
-/* Skip a comment - C, C++, or Chill style.  M is the first character
-   of the comment marker.  If this really is a comment, skip to its
-   end and return ' '.  If this is not a comment, return M (which will
-   be '/' or '-').  */
-
-static int
-skip_comment (pfile, m)
-     cpp_reader *pfile;
-     int m;
-{
-  if (m == '/' && PEEKC() == '*')
-    {
-      skip_block_comment (pfile);
-      return ' ';
-    }
-  else if (m == '/' && PEEKC() == '/')
-    {
-      if (CPP_BUFFER (pfile)->system_header_p)
-       {
-         /* We silently allow C++ comments in system headers, irrespective
-            of conformance mode, because lots of busted systems do that
-            and trying to clean it up in fixincludes is a nightmare.  */
-         skip_line_comment (pfile);
-         return ' ';
-       }
-      else if (CPP_OPTIONS (pfile)->cplusplus_comments)
-       {
-         if (CPP_OPTIONS (pfile)->c89
-             && CPP_PEDANTIC (pfile)
-             && ! CPP_BUFFER (pfile)->warned_cplusplus_comments)
-           {
-             cpp_pedwarn (pfile,
-                          "C++ style comments are not allowed in ISO C89");
-             cpp_pedwarn (pfile,
-                          "(this will be reported only once per input file)");
-             CPP_BUFFER (pfile)->warned_cplusplus_comments = 1;
-           }
-         skip_line_comment (pfile);
-         return ' ';
-       }
-      else
-       return m;
-    }
-  else if (m == '-' && PEEKC() == '-'
-          && CPP_OPTIONS (pfile)->chill)
-    {
-      skip_line_comment (pfile);
-      return ' ';
-    }
-  else
-    return m;
-}
-
-/* Identical to skip_comment except that it copies the comment into the
-   token_buffer.  This is used if !discard_comments.  */
-static int
-copy_comment (pfile, m)
-     cpp_reader *pfile;
-     int m;
-{
-  const U_CHAR *start = CPP_BUFFER (pfile)->cur;  /* XXX Layering violation */
-  const U_CHAR *limit;
-
-  if (skip_comment (pfile, m) == m)
-    return m;
-
-  limit = CPP_BUFFER (pfile)->cur;
-  CPP_RESERVE (pfile, limit - start + 2);
-  CPP_PUTC_Q (pfile, m);
-  for (; start <= limit; start++)
-    if (*start != '\r')
-      CPP_PUTC_Q (pfile, *start);
-
-  return ' ';
-}
-
-/* Skip whitespace \-newline and comments.  Does not macro-expand.  */
-
-static void
-cpp_skip_hspace (pfile)
-     cpp_reader *pfile;
-{
-  int c;
-  while (1)
-    {
-      c = GETC();
-      if (c == EOF)
-       return;
-      else if (is_hspace(c))
-       {
-         if ((c == '\f' || c == '\v') && CPP_PEDANTIC (pfile))
-           cpp_pedwarn (pfile, "%s in preprocessing directive",
-                        c == '\f' ? "formfeed" : "vertical tab");
-       }
-      else if (c == '\r')
-       {
-         /* \r is a backslash-newline marker if !has_escapes, and
-            a deletable-whitespace or no-reexpansion marker otherwise. */
-         if (CPP_BUFFER (pfile)->has_escapes)
-           {
-             if (PEEKC() == ' ')
-               FORWARD(1);
-             else
-               break;
-           }
-         else
-           CPP_BUMP_LINE (pfile);
-       }
-      else if (c == '/' || c == '-')
-       {
-         c = skip_comment (pfile, c);
-         if (c  != ' ')
-           break;
-       }
-      else
-       break;
-    }
-  FORWARD(-1);
-}
-
-/* Read and discard the rest of the current line.  */
-
-static void
-skip_rest_of_line (pfile)
-     cpp_reader *pfile;
-{
-  for (;;)
-    {
-      int c = GETC();
-      switch (c)
-       {
-       case '\n':
-         FORWARD(-1);
-       case EOF:
-         return;
-
-       case '\r':
-         if (! CPP_BUFFER (pfile)->has_escapes)
-           CPP_BUMP_LINE (pfile);
-         break;
-         
-       case '\'':
-       case '\"':
-         skip_string (pfile, c);
-         break;
-
-       case '/':
-       case '-':
-         skip_comment (pfile, c);
-         break;
-
-       case '\f':
-       case '\v':
-         if (CPP_PEDANTIC (pfile))
-           cpp_pedwarn (pfile, "%s in preprocessing directive",
-                        c == '\f' ? "formfeed" : "vertical tab");
-         break;
-
-       }
-    }
-}
-
 /* Handle a possible # directive.
    '#' has already been read.  */
 
-static int
-handle_directive (pfile)
+int
+_cpp_handle_directive (pfile)
      cpp_reader *pfile;
 {
   int c;
@@ -531,7 +152,7 @@ handle_directive (pfile)
       return 0;
     }
 
-  cpp_skip_hspace (pfile);
+  _cpp_skip_hspace (pfile);
 
   c = PEEKC ();
   /* # followed by a number is equivalent to #line.  Do not recognize
@@ -558,7 +179,7 @@ handle_directive (pfile)
 
   /* Now find the directive name.  */
   CPP_PUTC (pfile, '#');
-  parse_name (pfile, GETC());
+  _cpp_parse_name (pfile, GETC());
   ident = pfile->token_buffer + old_written + 1;
   ident_length = CPP_PWRITTEN (pfile) - ident;
   if (ident_length == 0)
@@ -588,7 +209,7 @@ handle_directive (pfile)
     {
       cpp_error (pfile, "`#%s' may not be used inside a macro argument",
                 kt->name);
-      skip_rest_of_line (pfile);
+      _cpp_skip_rest_of_line (pfile);
     }
   else
     (*kt->func) (pfile, kt);
@@ -629,7 +250,7 @@ get_macro_name (pfile)
 
   here = CPP_WRITTEN (pfile);
   pfile->no_macro_expand++;
-  if (get_directive_token (pfile) != CPP_NAME)
+  if (_cpp_get_directive_token (pfile) != CPP_NAME)
     {
       cpp_error (pfile, "`#define' must be followed by an identifier");
       goto invalid;
@@ -646,7 +267,7 @@ get_macro_name (pfile)
   return len;
 
  invalid:
-  skip_rest_of_line (pfile);
+  _cpp_skip_rest_of_line (pfile);
   pfile->no_macro_expand--;
   return 0;
 }
@@ -748,222 +369,48 @@ do_define (pfile, keyword)
   return 0;
 }
 
+/*
+ * write out a #line command, for instance, after an #include file.
+ * FILE_CHANGE says whether we are entering a file, leaving, or neither.
+ */
 
-/* Allocate a new cpp_buffer for PFILE, and push it on the input buffer stack.
-   If BUFFER != NULL, then use the LENGTH characters in BUFFER
-   as the new input buffer.
-   Return the new buffer, or NULL on failure.  */
-
-cpp_buffer *
-cpp_push_buffer (pfile, buffer, length)
+void
+_cpp_output_line_command (pfile, file_change)
      cpp_reader *pfile;
-     const U_CHAR *buffer;
-     long length;
+     enum file_change_code file_change;
 {
-  cpp_buffer *buf = CPP_BUFFER (pfile);
-  cpp_buffer *new;
-  if (++pfile->buffer_stack_depth == CPP_STACK_MAX)
-    {
-      cpp_fatal (pfile, "macro or `#include' recursion too deep");
-      return NULL;
-    }
-
-  new = (cpp_buffer *) xcalloc (1, sizeof (cpp_buffer));
-
-  new->if_stack = pfile->if_stack;
-  new->cleanup = null_cleanup;
-  new->buf = new->cur = buffer;
-  new->alimit = new->rlimit = buffer + length;
-  new->prev = buf;
-  new->mark = -1;
-  new->line_base = NULL;
-
-  CPP_BUFFER (pfile) = new;
-  return new;
-}
+  long line;
+  cpp_buffer *ip;
 
-cpp_buffer *
-cpp_pop_buffer (pfile)
-     cpp_reader *pfile;
-{
-  cpp_buffer *buf = CPP_BUFFER (pfile);
-  if (ACTIVE_MARK_P())
-    cpp_ice (pfile, "mark active in cpp_pop_buffer");
-  (*buf->cleanup) (buf, pfile);
-  CPP_BUFFER (pfile) = CPP_PREV_BUFFER (buf);
-  free (buf);
-  pfile->buffer_stack_depth--;
-  return CPP_BUFFER (pfile);
-}
+  if (CPP_OPTIONS (pfile)->no_line_commands
+      || CPP_OPTIONS (pfile)->no_output)
+    return;
 
-/* Scan until CPP_BUFFER (PFILE) is exhausted into PFILE->token_buffer.
-   Pop the buffer when done.  */
+  ip = cpp_file_buffer (pfile);
+  cpp_buf_line_and_col (ip, &line, NULL);
 
-void
-cpp_scan_buffer (pfile)
-     cpp_reader *pfile;
-{
-  cpp_buffer *buffer = CPP_BUFFER (pfile);
-  enum cpp_token token;
-  if (CPP_OPTIONS (pfile)->no_output)
+  /* If the current file has not changed, we omit the #line if it would
+     appear to be a no-op, and we output a few newlines instead
+     if we want to increase the line number by a small amount.
+     We cannot do this if pfile->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.)  */
+  if (file_change == same_file && pfile->lineno != 0)
     {
-      long old_written = CPP_WRITTEN (pfile);
-      /* In no-output mode, we can ignore everything but directives.  */
-      for (;;)
+      if (line == pfile->lineno)
+       return;
+
+      /* If the inherited line number is a little too small,
+        output some newlines instead of a #line command.  */
+      if (line > pfile->lineno && line < pfile->lineno + 8)
        {
-         if (! pfile->only_seen_white)
-           skip_rest_of_line (pfile);
-         token = cpp_get_token (pfile);
-         if (token == CPP_EOF) /* Should not happen ...  */
-           break;
-         if (token == CPP_POP && CPP_BUFFER (pfile) == buffer)
+         CPP_RESERVE (pfile, 20);
+         while (line > pfile->lineno)
            {
-             if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) != NULL)
-               cpp_pop_buffer (pfile);
-             break;
+             CPP_PUTC_Q (pfile, '\n');
+             pfile->lineno++;
            }
-       }
-      CPP_SET_WRITTEN (pfile, old_written);
-    }
-  else
-    {
-      for (;;)
-       {
-         token = cpp_get_token (pfile);
-         if (token == CPP_EOF) /* Should not happen ...  */
-           break;
-         if (token == CPP_POP && CPP_BUFFER (pfile) == buffer)
-           {
-             if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) != NULL)
-               cpp_pop_buffer (pfile);
-             break;
-           }
-       }
-    }
-}
-
-/*
- * Rescan a string (which may have escape marks) into pfile's buffer.
- * Place the result in pfile->token_buffer.
- *
- * The input is copied before it is scanned, so it is safe to pass
- * it something from the token_buffer that will get overwritten
- * (because it follows CPP_WRITTEN).  This is used by do_include.
- */
-
-void
-cpp_expand_to_buffer (pfile, buf, length)
-     cpp_reader *pfile;
-     const U_CHAR *buf;
-     int length;
-{
-  register cpp_buffer *ip;
-  U_CHAR *buf1;
-  int save_no_output;
-
-  if (length < 0)
-    {
-      cpp_ice (pfile, "length < 0 in cpp_expand_to_buffer");
-      return;
-    }
-
-  /* Set up the input on the input stack.  */
-
-  buf1 = (U_CHAR *) alloca (length + 1);
-  memcpy (buf1, buf, length);
-  buf1[length] = 0;
-
-  ip = cpp_push_buffer (pfile, buf1, length);
-  if (ip == NULL)
-    return;
-  ip->has_escapes = 1;
-
-  /* Scan the input, create the output.  */
-  save_no_output = CPP_OPTIONS (pfile)->no_output;
-  CPP_OPTIONS (pfile)->no_output = 0;
-  CPP_OPTIONS (pfile)->no_line_commands++;
-  cpp_scan_buffer (pfile);
-  CPP_OPTIONS (pfile)->no_line_commands--;
-  CPP_OPTIONS (pfile)->no_output = save_no_output;
-
-  CPP_NUL_TERMINATE (pfile);
-}
-
-void
-cpp_buf_line_and_col (pbuf, linep, colp)
-     register cpp_buffer *pbuf;
-     long *linep, *colp;
-{
-  if (pbuf)
-    {
-      *linep = pbuf->lineno;
-      if (colp)
-       *colp = pbuf->cur - pbuf->line_base;
-    }
-  else
-    {
-      *linep = 0;
-      if (colp)
-       *colp = 0;
-    }
-}
-
-/* Return the cpp_buffer that corresponds to a file (not a macro).  */
-
-cpp_buffer *
-cpp_file_buffer (pfile)
-     cpp_reader *pfile;
-{
-  cpp_buffer *ip;
-
-  for (ip = CPP_BUFFER (pfile); ip; ip = CPP_PREV_BUFFER (ip))
-    if (ip->ihash != NULL)
-      return ip;
-  return NULL;
-}
-
-/*
- * write out a #line command, for instance, after an #include file.
- * FILE_CHANGE says whether we are entering a file, leaving, or neither.
- */
-
-void
-output_line_command (pfile, file_change)
-     cpp_reader *pfile;
-     enum file_change_code file_change;
-{
-  long line;
-  cpp_buffer *ip;
-
-  if (CPP_OPTIONS (pfile)->no_line_commands
-      || CPP_OPTIONS (pfile)->no_output)
-    return;
-
-  ip = cpp_file_buffer (pfile);
-  cpp_buf_line_and_col (ip, &line, NULL);
-
-  /* If the current file has not changed, we omit the #line if it would
-     appear to be a no-op, and we output a few newlines instead
-     if we want to increase the line number by a small amount.
-     We cannot do this if pfile->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.)  */
-  if (file_change == same_file && pfile->lineno != 0)
-    {
-      if (line == pfile->lineno)
-       return;
-
-      /* If the inherited line number is a little too small,
-        output some newlines instead of a #line command.  */
-      if (line > pfile->lineno && line < pfile->lineno + 8)
-       {
-         CPP_RESERVE (pfile, 20);
-         while (line > pfile->lineno)
-           {
-             CPP_PUTC_Q (pfile, '\n');
-             pfile->lineno++;
-           }
-         return;
+         return;
        }
     }
 
@@ -973,7 +420,7 @@ output_line_command (pfile, file_change)
   sprintf ((char *) CPP_PWRITTEN (pfile), "%ld ", line);
   CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
 
-  quote_string (pfile, ip->nominal_fname); 
+  _cpp_quote_string (pfile, ip->nominal_fname); 
   if (file_change != same_file && file_change != rename_file)
     {
       CPP_PUTC_Q (pfile, ' ');
@@ -997,61 +444,7 @@ output_line_command (pfile, file_change)
   pfile->lineno = line;
 }
 
-
-/* Like cpp_get_token, except that it does not read past end-of-line.
-   Also, horizontal space is skipped, and macros are popped.  */
-
-enum cpp_token
-get_directive_token (pfile)
-     cpp_reader *pfile;
-{
-  long old_written = CPP_WRITTEN (pfile);
-  enum cpp_token token;
-
-  for (;;)
-    {
-      cpp_skip_hspace (pfile);
-      if (PEEKC () == '\n')
-       return CPP_VSPACE;
-
-      token = cpp_get_token (pfile);
-      /* token could be hspace at the beginning of a macro.  */
-      if (token == CPP_HSPACE || token == CPP_COMMENT)
-       {
-         CPP_SET_WRITTEN (pfile, old_written);
-         continue;
-       }
-
-      /* token cannot be vspace, it would have been caught above.  */
-      if (token == CPP_VSPACE)
-       {
-         cpp_ice (pfile, "VSPACE in get_directive_token");
-         return token;
-       }
-
-      /* token cannot be POP unless the buffer is a macro buffer.  */
-      if (token != CPP_POP)
-       return token;
-
-      if (! CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
-       {
-         cpp_ice (pfile, "POP of file buffer in get_directive_token");
-         return token;
-       }
-
-      /* We must pop the buffer by hand, or else cpp_get_token might
-        hand us white space or newline on the next invocation.  */
-      cpp_pop_buffer (pfile);
-    }
-}
-\f
-/* Handle #include and #import.
-   This function expects to see "fname" or <fname> on the input.
-
-   The input is normally in part of the output_buffer following
-   CPP_WRITTEN, and will get overwritten by output_line_command.
-   I.e. in input file specification has been popped by handle_directive.
-   This is safe.  */
+/* Handle #include and #import.  */
 
 static int
 do_include (pfile, keyword)
@@ -1094,7 +487,7 @@ do_include (pfile, keyword)
     }
 
   pfile->parsing_include_directive++;
-  token = get_directive_token (pfile);
+  token = _cpp_get_directive_token (pfile);
   pfile->parsing_include_directive--;
 
   if (token == CPP_STRING)
@@ -1120,7 +513,7 @@ do_include (pfile, keyword)
       cpp_error (pfile,
                 "`#%s' expects \"FILENAME\" or <FILENAME>", keyword->name);
       CPP_SET_WRITTEN (pfile, old_written);
-      skip_rest_of_line (pfile);
+      _cpp_skip_rest_of_line (pfile);
       return 0;
     }
 
@@ -1129,10 +522,10 @@ do_include (pfile, keyword)
   memcpy (ftok, pfile->token_buffer + old_written, flen);
   ftok[flen] = '\0';
 
-  if (get_directive_token (pfile) != CPP_VSPACE)
+  if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
     {
       cpp_error (pfile, "junk at end of `#include'");
-      skip_rest_of_line (pfile);
+      _cpp_skip_rest_of_line (pfile);
     }
 
   CPP_SET_WRITTEN (pfile, old_written);
@@ -1270,7 +663,7 @@ do_include (pfile, keyword)
   
   if (_cpp_read_include_file (pfile, fd, ihash))
     {
-      output_line_command (pfile, enter_file);
+      _cpp_output_line_command (pfile, enter_file);
       if (angle_brackets)
        pfile->system_include_depth++;   /* Decremented in file_cleanup. */
     }
@@ -1288,9 +681,10 @@ read_line_number (pfile, num)
      int *num;
 {
   long save_written = CPP_WRITTEN (pfile);
-  U_CHAR *p = pfile->token_buffer + save_written;
-  enum cpp_token token = get_directive_token (pfile);
+  U_CHAR *p;
+  enum cpp_token token = _cpp_get_directive_token (pfile);
   CPP_SET_WRITTEN (pfile, save_written);
+  p = pfile->token_buffer + save_written;
 
   if (token == CPP_NUMBER && *p >= '1' && *p <= '4' && p[1] == '\0')
     {
@@ -1321,7 +715,7 @@ do_line (pfile, keyword)
   enum cpp_token token;
   char *x;
 
-  token = get_directive_token (pfile);
+  token = _cpp_get_directive_token (pfile);
 
   if (token != CPP_NUMBER)
     {
@@ -1340,7 +734,7 @@ do_line (pfile, keyword)
   if (CPP_PEDANTIC (pfile) && (new_lineno <= 0 || new_lineno > 32767))
     cpp_pedwarn (pfile, "line number out of range in `#line' command");
 
-  token = get_directive_token (pfile);
+  token = _cpp_get_directive_token (pfile);
 
   if (token == CPP_STRING)
     {
@@ -1416,11 +810,11 @@ do_line (pfile, keyword)
      we must store a line number now that is one less.  */
   ip->lineno = new_lineno - 1;
   CPP_SET_WRITTEN (pfile, old_written);
-  output_line_command (pfile, file_change);
+  _cpp_output_line_command (pfile, file_change);
   return 0;
 
  bad_line_directive:
-  skip_rest_of_line (pfile);
+  _cpp_skip_rest_of_line (pfile);
   CPP_SET_WRITTEN (pfile, old_written);
   return 0;
 }
@@ -1440,16 +834,16 @@ do_undef (pfile, keyword)
   long here = CPP_WRITTEN (pfile);
   enum cpp_token token;
 
-  cpp_skip_hspace (pfile);
+  _cpp_skip_hspace (pfile);
   c = GETC();
   if (! is_idstart(c))
   {
       cpp_error (pfile, "token after #undef is not an identifier");
-      skip_rest_of_line (pfile);
+      _cpp_skip_rest_of_line (pfile);
       return 1;
   }
 
-  parse_name (pfile, c);
+  _cpp_parse_name (pfile, c);
   buf = pfile->token_buffer + here;
   limit = CPP_PWRITTEN(pfile);
 
@@ -1459,11 +853,11 @@ do_undef (pfile, keyword)
   memcpy (name, buf, len);
   name[len] = '\0';
 
-  token = get_directive_token (pfile);
+  token = _cpp_get_directive_token (pfile);
   if (token != CPP_VSPACE)
   {
       cpp_pedwarn (pfile, "junk on line after #undef");
-      skip_rest_of_line (pfile);
+      _cpp_skip_rest_of_line (pfile);
   }
   CPP_SET_WRITTEN (pfile, here);
 
@@ -1489,25 +883,6 @@ do_undef (pfile, keyword)
   return 0;
 }
 
-/* Wrap do_undef for -U processing. */
-void
-cpp_undef (pfile, macro)
-     cpp_reader *pfile;
-     const char *macro;
-{
-  /* Copy the string so we can append a newline.  */
-  size_t len = strlen (macro);
-  char *buf = alloca (len + 2);
-  memcpy (buf, macro, len);
-  buf[len]     = '\n';
-  buf[len + 1] = '\0';
-  if (cpp_push_buffer (pfile, buf, len + 1))
-    {
-      do_undef (pfile, NULL);
-      cpp_pop_buffer (pfile);
-    }
-}
-
 /*
  * Report an error detected by the program we are processing.
  * Use the text of the line in the error message.
@@ -1521,9 +896,9 @@ do_error (pfile, keyword)
 {
   const U_CHAR *text, *limit;
 
-  cpp_skip_hspace (pfile);
+  _cpp_skip_hspace (pfile);
   text = CPP_BUFFER (pfile)->cur;
-  skip_rest_of_line (pfile);
+  _cpp_skip_rest_of_line (pfile);
   limit = CPP_BUFFER (pfile)->cur;
 
   cpp_error (pfile, "#error %.*s", (int)(limit - text), text);
@@ -1542,9 +917,9 @@ do_warning (pfile, keyword)
 {
   const U_CHAR *text, *limit;
 
-  cpp_skip_hspace (pfile);
+  _cpp_skip_hspace (pfile);
   text = CPP_BUFFER (pfile)->cur;
-  skip_rest_of_line (pfile);
+  _cpp_skip_rest_of_line (pfile);
   limit = CPP_BUFFER (pfile)->cur;
 
   if (CPP_PEDANTIC (pfile))
@@ -1570,14 +945,14 @@ do_ident (pfile, keyword)
   CPP_PUTS (pfile, "#ident ", 7);
 
   /* Next token should be a string constant.  */
-  if (get_directive_token (pfile) == CPP_STRING)
+  if (_cpp_get_directive_token (pfile) == CPP_STRING)
     /* And then a newline.  */
-    if (get_directive_token (pfile) == CPP_VSPACE)
+    if (_cpp_get_directive_token (pfile) == CPP_VSPACE)
       /* Good - ship it.  */
       return 0;
 
   cpp_error (pfile, "invalid #ident");
-  skip_rest_of_line (pfile);
+  _cpp_skip_rest_of_line (pfile);
   CPP_SET_WRITTEN (pfile, old_written);  /* discard directive */
 
   return 0;
@@ -1616,7 +991,7 @@ do_pragma (pfile, keyword)
 
   key = CPP_WRITTEN (pfile);
   pfile->no_macro_expand++;
-  token = get_directive_token (pfile);
+  token = _cpp_get_directive_token (pfile);
   if (token != CPP_NAME)
     {
       if (token == CPP_VSPACE)
@@ -1639,7 +1014,7 @@ do_pragma (pfile, keyword)
     pop = do_pragma_default (pfile);
 #undef tokis
 
-  if (get_directive_token (pfile) != CPP_VSPACE)
+  if (_cpp_get_directive_token (pfile) != CPP_VSPACE)
     goto skip;
 
   if (pop)
@@ -1649,7 +1024,7 @@ do_pragma (pfile, keyword)
 
  skip:
   cpp_error (pfile, "malformed #pragma directive");
-  skip_rest_of_line (pfile);
+  _cpp_skip_rest_of_line (pfile);
  empty:
   CPP_SET_WRITTEN (pfile, here);
   pfile->no_macro_expand--;
@@ -1660,7 +1035,7 @@ static int
 do_pragma_default (pfile)
      cpp_reader *pfile;
 {
-  while (get_directive_token (pfile) != CPP_VSPACE)
+  while (_cpp_get_directive_token (pfile) != CPP_VSPACE)
     CPP_PUTC (pfile, ' ');
   return 0;
 }
@@ -1696,7 +1071,7 @@ do_pragma_implementation (pfile)
   U_CHAR *copy;
   size_t len;
 
-  token = get_directive_token (pfile);
+  token = _cpp_get_directive_token (pfile);
   if (token == CPP_VSPACE)
     return 0;
   else if (token != CPP_STRING)
@@ -1742,13 +1117,13 @@ do_pragma_poison (pfile)
   for (;;)
     {
       written = CPP_WRITTEN (pfile);
-      token = get_directive_token (pfile);
+      token = _cpp_get_directive_token (pfile);
       if (token == CPP_VSPACE)
        break;
       if (token != CPP_NAME)
        {
          cpp_error (pfile, "invalid #pragma poison directive");
-         skip_rest_of_line (pfile);
+         _cpp_skip_rest_of_line (pfile);
          return 1;
        }
 
@@ -1789,7 +1164,7 @@ do_sccs (pfile, keyword)
 {
   if (CPP_PEDANTIC (pfile))
     cpp_pedwarn (pfile, "ANSI C does not allow `#sccs'");
-  skip_rest_of_line (pfile);
+  _cpp_skip_rest_of_line (pfile);
   return 0;
 }
 #endif
@@ -1817,18 +1192,18 @@ detect_if_not_defined (pfile)
 
       /* Save state required for restore.  */
       pfile->no_macro_expand++;
-      parse_set_mark (pfile);
+      CPP_SET_MARK (pfile);
       base_offset = CPP_WRITTEN (pfile);
 
       /* Look for `!', */
-      if (get_directive_token (pfile) != CPP_OTHER
+      if (_cpp_get_directive_token (pfile) != CPP_OTHER
          || CPP_WRITTEN (pfile) != (size_t) base_offset + 1
          || CPP_PWRITTEN (pfile)[-1] != '!')
        goto restore;
 
       /* ...then `defined', */
       token_offset = CPP_WRITTEN (pfile);
-      token = get_directive_token (pfile);
+      token = _cpp_get_directive_token (pfile);
       if (token != CPP_NAME)
        goto restore;
       ident = pfile->token_buffer + token_offset;
@@ -1838,11 +1213,11 @@ detect_if_not_defined (pfile)
 
       /* ...then an optional '(' and the name, */
       token_offset = CPP_WRITTEN (pfile);
-      token = get_directive_token (pfile);
+      token = _cpp_get_directive_token (pfile);
       if (token == CPP_LPAREN)
        {
          token_offset = CPP_WRITTEN (pfile);
-         token = get_directive_token (pfile);
+         token = _cpp_get_directive_token (pfile);
          if (token != CPP_NAME)
            goto restore;
          need_rparen = 1;
@@ -1854,22 +1229,22 @@ detect_if_not_defined (pfile)
       CPP_NUL_TERMINATE (pfile);
 
       /* ...then the ')', if necessary, */
-      if ((!need_rparen || get_directive_token (pfile) == CPP_RPAREN)
+      if ((!need_rparen || _cpp_get_directive_token (pfile) == CPP_RPAREN)
          /* ...and make sure there's nothing else on the line.  */
-         && get_directive_token (pfile) == CPP_VSPACE)
+         && _cpp_get_directive_token (pfile) == CPP_VSPACE)
        control_macro = (U_CHAR *) xstrdup (ident);
 
     restore:
       CPP_SET_WRITTEN (pfile, base_offset);
       pfile->no_macro_expand--;
-      parse_goto_mark (pfile);
+      CPP_GOTO_MARK (pfile);
     }
 
   return control_macro;
 }
 
 /*
- * #if is straightforward; just call eval_if_expr, then conditional_skip.
+ * #if is straightforward; just call _cpp_parse_expr, then conditional_skip.
  * Also, check for a reinclude preventer of the form #if !defined (MACRO).
  */
 
@@ -1879,7 +1254,7 @@ do_if (pfile, keyword)
      const struct directive *keyword ATTRIBUTE_UNUSED;
 {
   U_CHAR *control_macro = detect_if_not_defined (pfile);
-  int value = eval_if_expr (pfile);
+  int value = _cpp_parse_expr (pfile);
   conditional_skip (pfile, value == 0, T_IF, control_macro);
   return 0;
 }
@@ -1914,39 +1289,17 @@ do_elif (pfile, keyword)
     skip_if_group (pfile);
   else
     {
-      int value = eval_if_expr (pfile);
-      if (value == 0)
+      if (_cpp_parse_expr (pfile) == 0)
        skip_if_group (pfile);
       else
        {
          ++pfile->if_stack->if_succeeded;      /* continue processing input */
-         output_line_command (pfile, same_file);
+         _cpp_output_line_command (pfile, same_file);
        }
     }
   return 0;
 }
 
-/* Thin wrapper around _cpp_parse_expr, which doesn't have access to
- * skip_rest_of_line.  Also centralizes toggling parsing_if_directive.
- */
-
-static int
-eval_if_expr (pfile)
-     cpp_reader *pfile;
-{
-  int value;
-  long old_written = CPP_WRITTEN (pfile);
-
-  pfile->parsing_if_directive++;
-  value = _cpp_parse_expr (pfile);
-  pfile->parsing_if_directive--;
-
-  skip_rest_of_line (pfile);
-  CPP_SET_WRITTEN (pfile, old_written); /* Pop */
-
-  return value;
-}
-
 /*
  * routine to handle ifdef/ifndef.  Try to look up the symbol,
  * then do or don't skip to the #endif/#else/#elif depending
@@ -1971,7 +1324,7 @@ do_ifdef (pfile, keyword)
     start_of_file = pfile->only_seen_white == 2;
 
   pfile->no_macro_expand++;
-  token = get_directive_token (pfile);
+  token = _cpp_get_directive_token (pfile);
   pfile->no_macro_expand--;
 
   ident = pfile->token_buffer + old_written;
@@ -2005,12 +1358,12 @@ do_ifdef (pfile, keyword)
 
   if (!CPP_TRADITIONAL (pfile))
     { int c;
-      cpp_skip_hspace (pfile);
+      _cpp_skip_hspace (pfile);
       c = PEEKC ();
       if (c != EOF && c != '\n')
        cpp_pedwarn (pfile, "garbage at end of `#%s' argument", keyword->name);
     }
-  skip_rest_of_line (pfile);
+  _cpp_skip_rest_of_line (pfile);
 
   conditional_skip (pfile, skip, T_IF, control_macro);
   return 0;
@@ -2043,7 +1396,7 @@ conditional_skip (pfile, skip, type, control_macro)
     return;
   } else {
     ++pfile->if_stack->if_succeeded;
-    output_line_command (pfile, same_file);
+    _cpp_output_line_command (pfile, same_file);
   }
 }
 
@@ -2061,10 +1414,10 @@ consider_directive_while_skipping (pfile, stack)
   const struct directive *kt;
   IF_STACK *temp;
     
-  cpp_skip_hspace (pfile);
+  _cpp_skip_hspace (pfile);
 
   ident = CPP_WRITTEN (pfile);
-  parse_name (pfile, GETC());
+  _cpp_parse_name (pfile, GETC());
   ident_len = CPP_WRITTEN (pfile) - ident;
 
   CPP_SET_WRITTEN (pfile, ident);
@@ -2137,7 +1490,7 @@ skip_if_group (pfile)
       beg_of_line = CPP_BUFFER (pfile)->cur;
 
       if (! CPP_TRADITIONAL (pfile))
-       cpp_skip_hspace (pfile);
+       _cpp_skip_hspace (pfile);
       c = GETC();
       if (c == '\n')
        {
@@ -2153,7 +1506,7 @@ skip_if_group (pfile)
        return;  /* Caller will issue error. */
 
       FORWARD(-1);
-      skip_rest_of_line (pfile);
+      _cpp_skip_rest_of_line (pfile);
 
       c = GETC();
       if (c == EOF)
@@ -2181,7 +1534,7 @@ do_else (pfile, keyword)
      const struct directive *keyword ATTRIBUTE_UNUSED;
 {
   validate_else (pfile, "#else");
-  skip_rest_of_line (pfile);
+  _cpp_skip_rest_of_line (pfile);
 
   if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack)
     {
@@ -2208,7 +1561,7 @@ do_else (pfile, keyword)
   else
     {
       ++pfile->if_stack->if_succeeded; /* continue processing input */
-      output_line_command (pfile, same_file);
+      _cpp_output_line_command (pfile, same_file);
     }
   return 0;
 }
@@ -2223,7 +1576,7 @@ do_endif (pfile, keyword)
      const struct directive *keyword ATTRIBUTE_UNUSED;
 {
   validate_else (pfile, "#endif");
-  skip_rest_of_line (pfile);
+  _cpp_skip_rest_of_line (pfile);
 
   if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack)
     cpp_error (pfile, "`#endif' not within a conditional");
@@ -2237,16 +1590,16 @@ do_endif (pfile, keyword)
             See if it is at the end of the file.  */
          int c;
 
-         parse_set_mark (pfile);
+         CPP_SET_MARK (pfile);
 
          for (;;)
            {
-             cpp_skip_hspace (pfile);
+             _cpp_skip_hspace (pfile);
              c = GETC ();
              if (c != '\n')
                break;
            }
-         parse_goto_mark (pfile);
+         CPP_GOTO_MARK (pfile);
 
          if (c == EOF)
            {
@@ -2258,7 +1611,7 @@ do_endif (pfile, keyword)
            }
         }
       free (temp);
-      output_line_command (pfile, same_file);
+      _cpp_output_line_command (pfile, same_file);
     }
   return 0;
 }
@@ -2275,7 +1628,7 @@ validate_else (pfile, directive)
   if (! CPP_PEDANTIC (pfile))
     return;
 
-  cpp_skip_hspace (pfile);
+  _cpp_skip_hspace (pfile);
   if (PEEKC () != '\n')
     cpp_pedwarn (pfile,
                 "text following `%s' violates ANSI standard", directive);
@@ -2300,734 +1653,40 @@ if_directive_name (pfile, ifs)
     }
 }
 
-/* Get the next token, and add it to the text in pfile->token_buffer.
-   Return the kind of token we got.  */
-
-enum cpp_token
-cpp_get_token (pfile)
-     cpp_reader *pfile;
-{
-  register int c, c2, c3;
-  enum cpp_token token;
-  struct cpp_options *opts = CPP_OPTIONS (pfile);
-
- get_next:
-  c = GETC();
-  if (c == EOF)
-    {
-      if (CPP_BUFFER (pfile)->manual_pop)
-       /* If we've been reading from redirected input, the
-          frontend will pop the buffer.  */
-       return CPP_EOF;
-      else if (CPP_BUFFER (pfile)->seen_eof)
-       {
-         if (CPP_PREV_BUFFER (CPP_BUFFER (pfile)) == NULL)
-           return CPP_EOF;
-
-         cpp_pop_buffer (pfile);
-         goto get_next;
-       }
-      else
-       {
-         cpp_buffer *next_buf = CPP_PREV_BUFFER (CPP_BUFFER (pfile));
-         struct if_stack *ifs, *nifs;
-
-         /* Unwind the conditional stack and generate error messages.  */
-         for (ifs = pfile->if_stack;
-              ifs != CPP_BUFFER (pfile)->if_stack;
-              ifs = nifs)
-           {
-             cpp_error_with_line (pfile, ifs->lineno, -1,
-                                  "unterminated `%s' conditional",
-                                  if_directive_name (pfile, ifs));
-
-             nifs = ifs->next;
-             free (ifs);
-           }
-         pfile->if_stack = ifs;
-
-         if (CPP_BUFFER (pfile)->nominal_fname && next_buf != NULL)
-           {
-             /* We're about to return from an #include file.
-                Emit #line information now (as part of the CPP_POP) result.
-                But the #line refers to the file we will pop to.  */
-             cpp_buffer *cur_buffer = CPP_BUFFER (pfile);
-             CPP_BUFFER (pfile) = next_buf;
-             pfile->input_stack_listing_current = 0;
-             output_line_command (pfile, leave_file);
-             CPP_BUFFER (pfile) = cur_buffer;
-           }
-
-         CPP_BUFFER (pfile)->seen_eof = 1;
-         return CPP_POP;
-       }
-    }
-  else
-    {
-      switch (c)
-       {
-       case '/':
-         if (PEEKC () == '=')
-           goto op2;
-
-       comment:
-         if (opts->discard_comments)
-           c = skip_comment (pfile, c);
-         else
-           c = copy_comment (pfile, c);
-         if (c != ' ')
-           goto randomchar;
-         
-         /* Comments are equivalent to spaces.
-            For -traditional, a comment is equivalent to nothing.  */
-         if (opts->traditional || !opts->discard_comments)
-           return CPP_COMMENT;
-         else
-           {
-             CPP_PUTC (pfile, c);
-             return CPP_HSPACE;
-           }
-
-       case '#':
-         if (pfile->parsing_if_directive)
-           {
-             cpp_skip_hspace (pfile);
-             parse_assertion (pfile);
-             return CPP_ASSERTION;
-           }
-
-         if (pfile->parsing_define_directive && ! CPP_TRADITIONAL (pfile))
-           {
-             CPP_RESERVE (pfile, 3);
-             CPP_PUTC_Q (pfile, '#');
-             CPP_NUL_TERMINATE_Q (pfile);
-             if (PEEKC () != '#')
-               return CPP_STRINGIZE;
-             
-             FORWARD (1);
-             CPP_PUTC_Q (pfile, '#');
-             CPP_NUL_TERMINATE_Q (pfile);
-             return CPP_TOKPASTE;
-           }
-
-         if (!pfile->only_seen_white)
-           goto randomchar;
-         /* -traditional directives are recognized only with the # in
-            column 1.
-            XXX Layering violation.  */
-         if (CPP_TRADITIONAL (pfile)
-             && CPP_BUFFER (pfile)->cur - CPP_BUFFER (pfile)->line_base != 1)
-           goto randomchar;
-         if (handle_directive (pfile))
-           return CPP_DIRECTIVE;
-         pfile->only_seen_white = 0;
-         goto randomchar;
-
-       case '\"':
-       case '\'':
-         parse_string (pfile, c);
-         pfile->only_seen_white = 0;
-         return c == '\'' ? CPP_CHAR : CPP_STRING;
-
-       case '$':
-         if (!opts->dollars_in_ident)
-           goto randomchar;
-         goto letter;
-
-       case ':':
-         if (opts->cplusplus && PEEKC () == ':')
-           goto op2;
-         goto randomchar;
-
-       case '&':
-       case '+':
-       case '|':
-         c2 = PEEKC ();
-         if (c2 == c || c2 == '=')
-           goto op2;
-         goto randomchar;
-
-       case '*':
-       case '!':
-       case '%':
-       case '=':
-       case '^':
-         if (PEEKC () == '=')
-           goto op2;
-         goto randomchar;
-
-       case '-':
-         c2 = PEEKC ();
-         if (c2 == '-' && opts->chill)
-           goto comment;  /* Chill style comment */
-         if (c2 == '-' || c2 == '=')
-           goto op2;
-         if (c2 == '>')
-           {
-             if (opts->cplusplus && PEEKN (1) == '*')
-               {
-                 /* In C++, there's a ->* operator.  */
-                 token = CPP_OTHER;
-                 pfile->only_seen_white = 0;
-                 CPP_RESERVE (pfile, 4);
-                 CPP_PUTC_Q (pfile, c);
-                 CPP_PUTC_Q (pfile, GETC ());
-                 CPP_PUTC_Q (pfile, GETC ());
-                 CPP_NUL_TERMINATE_Q (pfile);
-                 return token;
-               }
-             goto op2;
-           }
-         goto randomchar;
-
-       case '<':
-         if (pfile->parsing_include_directive)
-           {
-             for (;;)
-               {
-                 CPP_PUTC (pfile, c);
-                 if (c == '>')
-                   break;
-                 c = GETC ();
-                 if (c == '\n' || c == EOF)
-                   {
-                     cpp_error (pfile,
-                                "missing '>' in `#include <FILENAME>'");
-                     break;
-                   }
-                 else if (c == '\r')
-                   {
-                     if (!CPP_BUFFER (pfile)->has_escapes)
-                       {
-                         /* Backslash newline is replaced by nothing. */
-                         CPP_ADJUST_WRITTEN (pfile, -1);
-                         CPP_BUMP_LINE (pfile);
-                       }
-                     else
-                       {
-                         /* We might conceivably get \r- or \r<space> in
-                            here.  Just delete 'em. */
-                         int d = GETC();
-                         if (d != '-' && d != ' ')
-                           cpp_ice (pfile, "unrecognized escape \\r%c", d);
-                         CPP_ADJUST_WRITTEN (pfile, -1);
-                       }                         
-                   }
-               }
-             return CPP_STRING;
-           }
-         /* else fall through */
-       case '>':
-         c2 = PEEKC ();
-         if (c2 == '=')
-           goto op2;
-         /* GNU C++ supports MIN and MAX operators <? and >?.  */
-         if (c2 != c && (!opts->cplusplus || c2 != '?'))
-           goto randomchar;
-         FORWARD(1);
-         CPP_RESERVE (pfile, 4);
-         CPP_PUTC (pfile, c);
-         CPP_PUTC (pfile, c2);
-         c3 = PEEKC ();
-         if (c3 == '=')
-           CPP_PUTC_Q (pfile, GETC ());
-         CPP_NUL_TERMINATE_Q (pfile);
-         pfile->only_seen_white = 0;
-         return CPP_OTHER;
-
-       case '.':
-         c2 = PEEKC ();
-         if (ISDIGIT(c2))
-           {
-             CPP_RESERVE(pfile, 2);
-             CPP_PUTC_Q (pfile, '.');
-             c = GETC ();
-             goto number;
-           }
-
-         /* In C++ there's a .* operator.  */
-         if (opts->cplusplus && c2 == '*')
-           goto op2;
-
-         if (c2 == '.' && PEEKN(1) == '.')
-           {
-             CPP_RESERVE(pfile, 4);
-             CPP_PUTC_Q (pfile, '.');
-             CPP_PUTC_Q (pfile, '.');
-             CPP_PUTC_Q (pfile, '.');
-             FORWARD (2);
-             CPP_NUL_TERMINATE_Q (pfile);
-             pfile->only_seen_white = 0;
-             return CPP_3DOTS;
-           }
-         goto randomchar;
-
-       op2:
-         token = CPP_OTHER;
-         pfile->only_seen_white = 0;
-         CPP_RESERVE(pfile, 3);
-         CPP_PUTC_Q (pfile, c);
-         CPP_PUTC_Q (pfile, GETC ());
-         CPP_NUL_TERMINATE_Q (pfile);
-         return token;
-
-       case 'L':
-         c2 = PEEKC ();
-         if ((c2 == '\'' || c2 == '\"') && !CPP_TRADITIONAL (pfile))
-           {
-             CPP_PUTC (pfile, c);
-             c = GETC ();
-             parse_string (pfile, c);
-             pfile->only_seen_white = 0;
-             return c == '\'' ? CPP_WCHAR : CPP_WSTRING;
-           }
-         goto letter;
-
-       case '0': case '1': case '2': case '3': case '4':
-       case '5': case '6': case '7': case '8': case '9':
-       number:
-         c2  = '.';
-         for (;;)
-           {
-             CPP_RESERVE (pfile, 2);
-             CPP_PUTC_Q (pfile, c);
-             c = PEEKC ();
-             if (c == EOF)
-               break;
-             if (!is_numchar(c) && c != '.'
-                 && ((c2 != 'e' && c2 != 'E'
-                      && ((c2 != 'p' && c2 != 'P')
-                          || CPP_OPTIONS (pfile)->c89))
-                     || (c != '+' && c != '-')))
-               break;
-             FORWARD(1);
-             c2= c;
-           }
-         CPP_NUL_TERMINATE_Q (pfile);
-         pfile->only_seen_white = 0;
-         return CPP_NUMBER;
-       case 'b': case 'c': case 'd': case 'h': case 'o':
-       case 'B': case 'C': case 'D': case 'H': case 'O':
-         if (opts->chill && PEEKC () == '\'')
-           {
-             pfile->only_seen_white = 0;
-             CPP_RESERVE (pfile, 2);
-             CPP_PUTC_Q (pfile, c);
-             CPP_PUTC_Q (pfile, '\'');
-             FORWARD(1);
-             for (;;)
-               {
-                 c = GETC();
-                 if (c == EOF)
-                   goto chill_number_eof;
-                 if (!is_numchar(c))
-                   break;
-                 CPP_PUTC (pfile, c);
-               }
-             if (c == '\'')
-               {
-                 CPP_RESERVE (pfile, 2);
-                 CPP_PUTC_Q (pfile, c);
-                 CPP_NUL_TERMINATE_Q (pfile);
-                 return CPP_STRING;
-               }
-             else
-               {
-                 FORWARD(-1);
-               chill_number_eof:
-                 CPP_NUL_TERMINATE (pfile);
-                 return CPP_NUMBER;
-               }
-           }
-         else
-           goto letter;
-       case '_':
-       case 'a': case 'e': case 'f': case 'g': case 'i': case 'j':
-       case 'k': case 'l': case 'm': case 'n': 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 'E': case 'F': case 'G': case 'I': case 'J':
-       case 'K': case 'M': case 'N': case 'P': case 'Q': case 'R':
-       case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
-       case 'Y': case 'Z':
-        letter:
-          {
-           HASHNODE *hp;
-           unsigned char *ident;
-           int before_name_written = CPP_WRITTEN (pfile);
-           int ident_len;
-           parse_name (pfile, c);
-           pfile->only_seen_white = 0;
-           if (pfile->no_macro_expand)
-             return CPP_NAME;
-           ident = pfile->token_buffer + before_name_written;
-           ident_len = CPP_PWRITTEN (pfile) - ident;
-           hp = _cpp_lookup (pfile, ident, ident_len);
-           if (!hp)
-             return CPP_NAME;
-           if (hp->type == T_DISABLED)
-             {
-               if (pfile->output_escapes)
-                 { /* Return "\r-IDENT", followed by '\0'.  */
-                   int i;
-                   CPP_RESERVE (pfile, 3);
-                   ident = pfile->token_buffer + before_name_written;
-                   CPP_ADJUST_WRITTEN (pfile, 2);
-                   for (i = ident_len; i >= 0; i--) ident[i+2] = ident[i];
-                   ident[0] = '\r';
-                   ident[1] = '-';
-                 }
-               return CPP_NAME;
-             }
-
-           /* If macro wants an arglist, verify that a '(' follows.  */
-           if (hp->type == T_MACRO && hp->value.defn->nargs >= 0)
-           {
-             int macbuf_whitespace = 0;
-
-             while (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
-               {
-                 const U_CHAR *point = CPP_BUFFER (pfile)->cur;
-                 for (;;)
-                   {
-                     cpp_skip_hspace (pfile);
-                     c = PEEKC ();
-                     if (c == '\n')
-                       FORWARD(1);
-                     else
-                       break;
-                   }
-                 if (point != CPP_BUFFER (pfile)->cur)
-                   macbuf_whitespace = 1;
-                 if (c == '(')
-                   goto is_macro_call;
-                 else if (c != EOF)
-                   goto not_macro_call;
-                 cpp_pop_buffer (pfile);
-               }
-
-             parse_set_mark (pfile);
-             for (;;)
-               {
-                 cpp_skip_hspace (pfile);
-                 c = PEEKC ();
-                 if (c == '\n')
-                   FORWARD(1);
-                 else
-                   break;
-               }
-             parse_goto_mark (pfile);
-
-             if (c == '(')
-               goto is_macro_call;
-
-           not_macro_call:
-             if (macbuf_whitespace)
-               CPP_PUTC (pfile, ' ');
-             return CPP_NAME;
-           }
-         is_macro_call:
-           /* This is now known to be a macro call.
-              Expand the macro, reading arguments as needed,
-              and push the expansion on the input stack.  */
-           _cpp_macroexpand (pfile, hp);
-           CPP_SET_WRITTEN (pfile, before_name_written);
-         }
-         goto get_next;
-
-       case ' ':  case '\t':  case '\v':
-         for (;;)
-           {
-             CPP_PUTC (pfile, c);
-             c = PEEKC ();
-             if (c == EOF || !is_hspace(c))
-               break;
-             FORWARD(1);
-           }
-         return CPP_HSPACE;
-
-       case '\r':
-         if (CPP_BUFFER (pfile)->has_escapes)
-           {
-             c = GETC ();
-             if (c == '-')
-               {
-                 if (pfile->output_escapes)
-                   CPP_PUTS (pfile, "\r-", 2);
-                 parse_name (pfile, GETC ());
-                 return CPP_NAME;
-               }
-             else if (c == ' ')
-               {
-                 CPP_RESERVE (pfile, 2);
-                 if (pfile->output_escapes)
-                   CPP_PUTC_Q (pfile, '\r');
-                 CPP_PUTC_Q (pfile, c);
-                 return CPP_HSPACE;
-               }
-             else
-               {
-                 cpp_ice (pfile, "unrecognized escape \\r%c", c);
-                 goto get_next;
-               }
-           }
-         else
-           {
-             /* Backslash newline is ignored. */
-             CPP_BUMP_LINE (pfile);
-             goto get_next;
-           }
-
-       case '\n':
-         CPP_PUTC (pfile, c);
-         if (pfile->only_seen_white == 0)
-           pfile->only_seen_white = 1;
-         CPP_BUMP_LINE (pfile);
-         if (! CPP_OPTIONS (pfile)->no_line_commands)
-           {
-             pfile->lineno++;
-             if (CPP_BUFFER (pfile)->lineno != pfile->lineno)
-               output_line_command (pfile, same_file);
-           }
-         return CPP_VSPACE;
-
-       case '(': token = CPP_LPAREN;    goto char1;
-       case ')': token = CPP_RPAREN;    goto char1;
-       case '{': token = CPP_LBRACE;    goto char1;
-       case '}': token = CPP_RBRACE;    goto char1;
-       case ',': token = CPP_COMMA;     goto char1;
-       case ';': token = CPP_SEMICOLON; goto char1;
-
-       randomchar:
-       default:
-         token = CPP_OTHER;
-       char1:
-         pfile->only_seen_white = 0;
-         CPP_PUTC (pfile, c);
-         return token;
-       }
-    }
-}
-
-/* Like cpp_get_token, but skip spaces and comments.  */
-
-enum cpp_token
-cpp_get_non_space_token (pfile)
-     cpp_reader *pfile;
-{
-  int old_written = CPP_WRITTEN (pfile);
-  for (;;)
-    {
-      enum cpp_token token = cpp_get_token (pfile);
-      if (token != CPP_COMMENT && token != CPP_POP
-         && token != CPP_HSPACE && token != CPP_VSPACE)
-       return token;
-      CPP_SET_WRITTEN (pfile, old_written);
-    }
-}
-
-/* Parse an identifier starting with C.  */
-
-static void
-parse_name (pfile, c)
-     cpp_reader *pfile;
-     int c;
-{
-  for (;;)
-  {
-      if (! is_idchar(c))
-      {
-         FORWARD (-1);
-         break;
-      }
-
-      if (c == '$' && CPP_PEDANTIC (pfile))
-       cpp_pedwarn (pfile, "`$' in identifier");
-
-      CPP_RESERVE(pfile, 2); /* One more for final NUL.  */
-      CPP_PUTC_Q (pfile, c);
-      c = GETC();
-      if (c == EOF)
-       break;
-  }
-  CPP_NUL_TERMINATE_Q (pfile);
-  return;
-}
-
-/* Parse and skip over a string starting with C.  A single quoted
-   string is treated like a double -- some programs (e.g., troff) are
-   perverse this way.  (However, a single quoted string is not allowed
-   to extend over multiple lines.)  */
-static void
-skip_string (pfile, c)
-     cpp_reader *pfile;
-     int c;
-{
-  long start_line, start_column;
-  cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column);
-
-  while (1)
-    {
-      int cc = GETC();
-      switch (cc)
-       {
-       case EOF:
-         cpp_error_with_line (pfile, start_line, start_column,
-                              "unterminated string or character constant");
-         if (pfile->multiline_string_line != start_line
-             && pfile->multiline_string_line != 0)
-           cpp_error_with_line (pfile,
-                                pfile->multiline_string_line, -1,
-                        "possible real start of unterminated constant");
-         pfile->multiline_string_line = 0;
-         return;
-
-       case '\n':
-         CPP_BUMP_LINE (pfile);
-         /* In Fortran and assembly language, silently terminate
-            strings of either variety at end of line.  This is a
-            kludge around not knowing where comments are in these
-            languages.  */
-         if (CPP_OPTIONS (pfile)->lang_fortran
-             || CPP_OPTIONS (pfile)->lang_asm)
-           {
-             FORWARD(-1);
-             return;
-           }
-         /* Character constants may not extend over multiple lines.
-            In Standard C, neither may strings.  We accept multiline
-            strings as an extension.  */
-         if (c == '\'')
-           {
-             cpp_error_with_line (pfile, start_line, start_column,
-                                  "unterminated character constant");
-             FORWARD(-1);
-             return;
-           }
-         if (CPP_PEDANTIC (pfile) && pfile->multiline_string_line == 0)
-           cpp_pedwarn_with_line (pfile, start_line, start_column,
-                                  "string constant runs past end of line");
-         if (pfile->multiline_string_line == 0)
-           pfile->multiline_string_line = start_line;
-         break;
-
-       case '\r':
-         if (CPP_BUFFER (pfile)->has_escapes)
-           {
-             cpp_ice (pfile, "\\r escape inside string constant");
-             FORWARD(1);
-           }
-         else
-           /* Backslash newline is replaced by nothing at all.  */
-           CPP_BUMP_LINE (pfile);
-         break;
-
-       case '\\':
-         FORWARD(1);
-         break;
-
-       case '\"':
-       case '\'':
-         if (cc == c)
-           return;
-         break;
-       }
-    }
-}
-
-/* Parse a string and copy it to the output.  */
-
-static void
-parse_string (pfile, c)
+void
+_cpp_handle_eof (pfile)
      cpp_reader *pfile;
-     int c;
 {
-  const U_CHAR *start = CPP_BUFFER (pfile)->cur;  /* XXX Layering violation */
-  const U_CHAR *limit;
+  cpp_buffer *next_buf = CPP_PREV_BUFFER (CPP_BUFFER (pfile));
+  struct if_stack *ifs, *nifs;
 
-  skip_string (pfile, c);
-
-  limit = CPP_BUFFER (pfile)->cur;
-  CPP_RESERVE (pfile, limit - start + 2);
-  CPP_PUTC_Q (pfile, c);
-  for (; start < limit; start++)
-    if (*start != '\r')
-      CPP_PUTC_Q (pfile, *start);
-}
-
-/* Read an assertion into the token buffer, converting to
-   canonical form: `#predicate(a n swe r)'  The next non-whitespace
-   character to read should be the first letter of the predicate.
-   Returns 0 for syntax error, 1 for bare predicate, 2 for predicate
-   with answer (see callers for why). In case of 0, an error has been
-   printed. */
-static int
-parse_assertion (pfile)
-     cpp_reader *pfile;
-{
-  int c, dropwhite;
-  cpp_skip_hspace (pfile);
-  c = PEEKC();
-  if (! is_idstart(c))
+  /* Unwind the conditional stack and generate error messages.  */
+  for (ifs = pfile->if_stack;
+       ifs != CPP_BUFFER (pfile)->if_stack;
+       ifs = nifs)
     {
-      cpp_error (pfile, "assertion predicate is not an identifier");
-      return 0;
-    }
-  CPP_PUTC(pfile, '#');
-  FORWARD(1);
-  parse_name(pfile, c);
+      cpp_error_with_line (pfile, ifs->lineno, -1,
+                          "unterminated `%s' conditional",
+                          if_directive_name (pfile, ifs));
 
-  c = PEEKC();
-  if (c != '(')
-    {
-      if (is_hspace(c) || c == '\r')
-       cpp_skip_hspace (pfile);
-      c = PEEKC();
+      nifs = ifs->next;
+      free (ifs);
     }
-  if (c != '(')
-    return 1;
+  pfile->if_stack = ifs;
 
-  CPP_PUTC(pfile, '(');
-  FORWARD(1);
-  dropwhite = 1;
-  while ((c = GETC()) != ')')
+  if (CPP_BUFFER (pfile)->nominal_fname && next_buf != NULL)
     {
-      if (is_space(c))
-       {
-         if (! dropwhite)
-           {
-             CPP_PUTC(pfile, ' ');
-             dropwhite = 1;
-           }
-       }
-      else if (c == '\n' || c == EOF)
-       {
-         if (c == '\n') FORWARD(-1);
-         cpp_error (pfile, "un-terminated assertion answer");
-         return 0;
-       }
-      else if (c == '\r')
-       /* \r cannot be a macro escape here. */
-       CPP_BUMP_LINE (pfile);
-      else
-       {
-         CPP_PUTC (pfile, c);
-         dropwhite = 0;
-       }
+      /* We're about to return from an #include file.
+        Emit #line information now (as part of the CPP_POP) result.
+        But the #line refers to the file we will pop to.  */
+      cpp_buffer *cur_buffer = CPP_BUFFER (pfile);
+      CPP_BUFFER (pfile) = next_buf;
+      pfile->input_stack_listing_current = 0;
+      _cpp_output_line_command (pfile, leave_file);
+      CPP_BUFFER (pfile) = cur_buffer;
     }
 
-  if (pfile->limit[-1] == ' ')
-    pfile->limit[-1] = ')';
-  else if (pfile->limit[-1] == '(')
-    {
-      cpp_error (pfile, "empty token sequence in assertion");
-      return 0;
-    }
-  else
-    CPP_PUTC (pfile, ')');
-
-  CPP_NUL_TERMINATE (pfile);
-  return 2;
+  CPP_BUFFER (pfile)->seen_eof = 1;
 }
 
 static int
@@ -3045,9 +1704,9 @@ do_assert (pfile, keyword)
   if (CPP_PEDANTIC (pfile) && CPP_OPTIONS (pfile)->done_initializing)
     cpp_pedwarn (pfile, "ANSI C does not allow `#assert'");
 
-  cpp_skip_hspace (pfile);
+  _cpp_skip_hspace (pfile);
   sym = CPP_PWRITTEN (pfile);  /* remember where it starts */
-  ret = parse_assertion (pfile);
+  ret = _cpp_parse_assertion (pfile);
   if (ret == 0)
     goto error;
   else if (ret == 1)
@@ -3056,7 +1715,7 @@ do_assert (pfile, keyword)
       goto error;
     }
 
-  cpp_skip_hspace (pfile);
+  _cpp_skip_hspace (pfile);
   c = PEEKC();
   if (c != EOF && c != '\n')
     {
@@ -3094,7 +1753,7 @@ do_assert (pfile, keyword)
   return 0;
 
  error:
-  skip_rest_of_line (pfile);
+  _cpp_skip_rest_of_line (pfile);
   pfile->limit = sym;          /* Pop */
   return 0;
 }
@@ -3112,14 +1771,14 @@ do_unassert (pfile, keyword)
   if (CPP_PEDANTIC (pfile) && CPP_OPTIONS (pfile)->done_initializing)
     cpp_pedwarn (pfile, "ANSI C does not allow `#unassert'");
 
-  cpp_skip_hspace (pfile);
+  _cpp_skip_hspace (pfile);
 
   sym = CPP_PWRITTEN (pfile);  /* remember where it starts */
-  ret = parse_assertion (pfile);
+  ret = _cpp_parse_assertion (pfile);
   if (ret == 0)
     goto error;
   
-  cpp_skip_hspace (pfile);
+  _cpp_skip_hspace (pfile);
   c = PEEKC ();
   if (c != EOF && c != '\n')
       cpp_error (pfile, "junk at end of `#unassert'");
@@ -3163,54 +1822,112 @@ do_unassert (pfile, keyword)
   pfile->limit = sym;          /* Pop */
   return 0;
  error:
-  skip_rest_of_line (pfile);
+  _cpp_skip_rest_of_line (pfile);
   pfile->limit = sym;          /* Pop */
   return 0;
 }
 
-/* Process STR as if it appeared as the body of an #unassert. */
+/* 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_unassert (pfile, str)
+cpp_define (pfile, str)
      cpp_reader *pfile;
      const char *str;
 {
-  if (cpp_push_buffer (pfile, str, strlen (str)) != NULL)
+  char *buf, *p;
+  size_t count;
+
+  p = strchr (str, '=');
+  /* 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.  Then add a newline and a NUL.  */
+  
+  if (p)
     {
-      do_unassert (pfile, NULL);
-      cpp_pop_buffer (pfile);
+      count = strlen (str) + 2;
+      buf = alloca (count);
+      memcpy (buf, str, count - 2);
+      buf[p - str] = ' ';
+      buf[count - 2] = '\n';
+      buf[count - 1] = '\0';
+    }
+  else
+    {
+      count = strlen (str) + 4;
+      buf = alloca (count);
+      memcpy (buf, str, count - 4);
+      strcpy (&buf[count-4], " 1\n");
     }
-}  
-
-/* Remember the current position of PFILE so it may be returned to
-   after looking ahead a bit.
 
-   Note that when you set a mark, you _must_ return to that mark.  You
-   may not forget about it and continue parsing.  You may not pop a
-   buffer with an active mark.  You may not call CPP_BUMP_LINE while a
-   mark is active.  */
+  if (cpp_push_buffer (pfile, buf, count - 1) != NULL)
+    {
+      do_define (pfile, NULL);
+      cpp_pop_buffer (pfile);
+    }
+}
 
-static void
-parse_set_mark (pfile)
+/* Process MACRO as if it appeared as the body of an #undef.  */
+void
+cpp_undef (pfile, macro)
      cpp_reader *pfile;
+     const char *macro;
 {
-  cpp_buffer *ip = CPP_BUFFER (pfile);
-  if (ACTIVE_MARK_P())
-      cpp_ice (pfile, "mark active in parse_set_mark");
-
-  ip->mark = ip->cur - ip->buf;
+  /* Copy the string so we can append a newline.  */
+  size_t len = strlen (macro);
+  char *buf = alloca (len + 2);
+  memcpy (buf, macro, len);
+  buf[len]     = '\n';
+  buf[len + 1] = '\0';
+  if (cpp_push_buffer (pfile, buf, len + 1))
+    {
+      do_undef (pfile, NULL);
+      cpp_pop_buffer (pfile);
+    }
 }
 
-/* Backup the current position of PFILE to that saved in its mark,
-   and clear the mark.  */
+/* Process the string STR as if it appeared as the body of a #assert. */
+void
+cpp_assert (pfile, str)
+     cpp_reader *pfile;
+     const char *str;
+{
+  if (cpp_push_buffer (pfile, str, strlen (str)) != NULL)
+    {
+      do_assert (pfile, NULL);
+      cpp_pop_buffer (pfile);
+    }
+}
 
-static void
-parse_goto_mark (pfile)
+/* Process STR as if it appeared as the body of an #unassert. */
+void
+cpp_unassert (pfile, str)
      cpp_reader *pfile;
+     const char *str;
 {
-  cpp_buffer *ip = CPP_BUFFER (pfile);
-  if (!ACTIVE_MARK_P())
-      cpp_ice (pfile, "mark not active in parse_goto_mark");
+  if (cpp_push_buffer (pfile, str, strlen (str)) != NULL)
+    {
+      do_unassert (pfile, NULL);
+      cpp_pop_buffer (pfile);
+    }
+}  
 
-  ip->cur = ip->buf + ip->mark;
-  ip->mark = -1;
+/* Determine whether the identifier ID, of length LEN, is a defined macro.  */
+int
+cpp_defined (pfile, id, len)
+     cpp_reader *pfile;
+     const U_CHAR *id;
+     int len;
+{
+  HASHNODE *hp = _cpp_lookup (pfile, id, len);
+  if (hp && hp->type == T_POISON)
+    {
+      cpp_error (pfile, "attempt to use poisoned `%s'", hp->name);
+      return 0;
+    }
+  return (hp != NULL);
 }
index 7906d0c..19f958f 100644 (file)
@@ -40,6 +40,7 @@ enum cpp_token
   CPP_HSPACE,
   CPP_VSPACE, /* newlines and #line directives */
   CPP_NAME,
+  CPP_MACRO,
   CPP_NUMBER,
   CPP_CHAR,
   CPP_WCHAR,
@@ -233,11 +234,6 @@ struct cpp_reader
 #define CPP_ADJUST_WRITTEN(PFILE,DELTA) ((PFILE)->limit += (DELTA))
 #define CPP_SET_WRITTEN(PFILE,N) ((PFILE)->limit = (PFILE)->token_buffer + (N))
 
-/* Make sure PFILE->token_buffer has space for at least N more characters. */
-#define CPP_RESERVE(PFILE, N) \
-  (CPP_WRITTEN (PFILE) + (size_t)(N) > (PFILE)->token_buffer_size \
-   && (cpp_grow_buffer (PFILE, N), 0))
-
 #define CPP_OPTIONS(PFILE) ((PFILE)->opts)
 #define CPP_BUFFER(PFILE) ((PFILE)->buffer)
 
@@ -438,7 +434,6 @@ extern const char *progname;
 extern int cpp_handle_options PARAMS ((cpp_reader *, int, char **));
 extern enum cpp_token cpp_get_token PARAMS ((cpp_reader *));
 extern enum cpp_token cpp_get_non_space_token PARAMS ((cpp_reader *));
-extern enum cpp_token get_directive_token PARAMS ((cpp_reader *));
 
 extern void cpp_reader_init PARAMS ((cpp_reader *));
 extern void cpp_options_init PARAMS ((cpp_options *));
@@ -482,22 +477,15 @@ extern void cpp_pedwarn_with_file_and_line PARAMS ((cpp_reader *, const char *,
 extern void cpp_error_from_errno PARAMS ((cpp_reader *, const char *));
 extern void cpp_notice_from_errno PARAMS ((cpp_reader *, const char *));
 
-extern void cpp_grow_buffer PARAMS ((cpp_reader *, long));
 extern cpp_buffer *cpp_push_buffer PARAMS ((cpp_reader *,
                                            const unsigned char *, long));
 extern cpp_buffer *cpp_pop_buffer PARAMS ((cpp_reader *));
 extern int cpp_defined PARAMS ((cpp_reader *, const unsigned char *, int));
 
-extern void quote_string               PARAMS ((cpp_reader *, const char *));
 extern void cpp_expand_to_buffer       PARAMS ((cpp_reader *,
                                                 const unsigned char *, int));
 extern void cpp_scan_buffer            PARAMS ((cpp_reader *));
 
-/* Last arg to output_line_command.  */
-enum file_change_code {same_file, rename_file, enter_file, leave_file};
-extern void output_line_command                PARAMS ((cpp_reader *,
-                                                enum file_change_code));
-
 /* In cppfiles.c */
 extern int cpp_included                        PARAMS ((cpp_reader *, const char *));
 extern int cpp_read_file               PARAMS ((cpp_reader *, const char *));
index 8f2b47a..48e1b5d 100644 (file)
@@ -594,6 +594,7 @@ cppfiles.c
 cpphash.c
 cpphash.h
 cppinit.c
+cpplex.c
 cpplib.c
 cpplib.h
 cppmain.c