gansidecl.h: Prepend a "G" to the macro wrapping this file (to distinguish it from...
[platform/upstream/gcc.git] / gcc / cccp.c
index d717009..e3568da 100644 (file)
@@ -19,11 +19,6 @@ Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA. */
 
 #include "config.h"
-#ifdef __STDC__
-# include <stdarg.h>
-#else
-# include <varargs.h>
-#endif
 
 #define PRINTF_PROTO(ARGS, m, n) PVPROTO (ARGS) ATTRIBUTE_PRINTF(m, n)
 
@@ -42,11 +37,15 @@ Boston, MA 02111-1307, USA. */
 
 typedef unsigned char U_CHAR;
 
-#include "gansidecl.h"
 #include "pcp.h"
 
-#ifndef GET_ENVIRONMENT
-#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ENV_VALUE = getenv (ENV_NAME)
+#ifdef MULTIBYTE_CHARS
+#include "mbchar.h"
+#include <locale.h>
+#endif /* MULTIBYTE_CHARS */
+
+#ifndef GET_ENV_PATH_LIST
+#define GET_ENV_PATH_LIST(VAR,NAME)    do { (VAR) = getenv (NAME); } while (0)
 #endif
 
 #ifndef STANDARD_INCLUDE_DIR
@@ -421,7 +420,6 @@ static struct default_include {
   = {
     /* Pick up GNU C++ specific include files.  */
     { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 },
-    { OLD_GPLUSPLUS_INCLUDE_DIR, 0, 1, 1 },
 #ifdef CROSS_COMPILE
     /* This is the dir for fixincludes.  Put it just before
        the files that we fix.  */
@@ -728,6 +726,8 @@ char * wchar_type = WCHAR_TYPE;
 #ifndef USER_LABEL_PREFIX
 #define USER_LABEL_PREFIX ""
 #endif
+char * user_label_prefix = USER_LABEL_PREFIX;
+#undef USER_LABEL_PREFIX
 
 /* The string value for __REGISTER_PREFIX__ */
 
@@ -943,7 +943,7 @@ static void record_control_macro PROTO((struct include_file *, U_CHAR *));
 
 static char *check_precompiled PROTO((int, struct stat *, char *, char **));
 static int check_preconditions PROTO((char *));
-static void pcfinclude PROTO((U_CHAR *, U_CHAR *, U_CHAR *, FILE_BUF *));
+static void pcfinclude PROTO((U_CHAR *, U_CHAR *, FILE_BUF *));
 static void pcstring_used PROTO((HASHNODE *));
 static void write_output PROTO((void));
 static void pass_thru_directive PROTO((U_CHAR *, U_CHAR *, FILE_BUF *, struct directive *));
@@ -1025,7 +1025,7 @@ static void dump_arg_n PROTO((DEFINITION *, int, FILE *));
 static void initialize_char_syntax PROTO((void));
 static void initialize_builtins PROTO((FILE_BUF *, FILE_BUF *));
 
-static void make_definition PROTO((char *, FILE_BUF *));
+static void make_definition PROTO((char *));
 static void make_undef PROTO((char *, FILE_BUF *));
 
 static void make_assertion PROTO((char *, char *));
@@ -1047,6 +1047,7 @@ GENERIC_PTR xmalloc PROTO((size_t));
 static GENERIC_PTR xrealloc PROTO((GENERIC_PTR, size_t));
 static GENERIC_PTR xcalloc PROTO((size_t, size_t));
 static char *savestring PROTO((char *));
+static void print_help PROTO((void));
 \f
 /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
    retrying if necessary.  If MAX_READ_LEN is defined, read at most
@@ -1146,6 +1147,73 @@ eprint_string (string, length)
 }
 
 \f
+static void
+print_help ()
+{
+  printf ("Usage: %s [switches] input output\n", progname);
+  printf ("Switches:\n");
+  printf ("  -include <file>           Include the contents of <file> before other files\n");
+  printf ("  -imacros <file>           Accept definition of marcos in <file>\n");
+  printf ("  -iprefix <path>           Specify <path> as a prefix for next two options\n");
+  printf ("  -iwithprefix <dir>        Add <dir> to the end of the system include paths\n");
+  printf ("  -iwithprefixbefore <dir>  Add <dir> to the end of the main include paths\n");
+  printf ("  -isystem <dir>            Add <dir> to the start of the system include paths\n");
+  printf ("  -idirafter <dir>          Add <dir> to the end of the system include paths\n");
+  printf ("  -I <dir>                  Add <dir> to the end of the main include paths\n");
+  printf ("  -nostdinc                 Do not search the system include directories\n");
+  printf ("  -nostdinc++               Do not search the system include directories for C++\n");
+  printf ("  -o <file>                 Put output into <file>\n");
+  printf ("  -pedantic                 Issue all warnings demanded by strict ANSI C\n");
+  printf ("  -traditional              Follow K&R pre-processor behaviour\n");
+  printf ("  -trigraphs                Support ANSI C trigraphs\n");
+  printf ("  -lang-c                   Assume that the input sources are in C\n");
+  printf ("  -lang-c89                 Assume that the input sources are in C89\n");
+  printf ("  -lang-c++                 Assume that the input sources are in C++\n");
+  printf ("  -lang-objc                Assume that the input sources are in ObjectiveC\n");
+  printf ("  -lang-objc++              Assume that the input sources are in ObjectiveC++\n");
+  printf ("  -lang-asm                 Assume that the input sources are in assembler\n");
+  printf ("  -lang-chill               Assume that the input sources are in Chill\n");
+  printf ("  -+                        Allow parsing of C++ style features\n");
+  printf ("  -w                        Inhibit warning messages\n");
+  printf ("  -Wtrigraphs               Warn if trigraphs are encountered\n");
+  printf ("  -Wno-trigraphs            Do not warn about trigraphs\n");
+  printf ("  -Wcomment{s}              Warn if one comment starts inside another\n");
+  printf ("  -Wno-comment{s}           Do not warn about comments\n");
+  printf ("  -Wtraditional             Warn if a macro argument is/would be turned into\n");
+  printf ("                             a string if -tradtional is specified\n");
+  printf ("  -Wno-traditional          Do not warn about stringification\n");
+  printf ("  -Wundef                   Warn if an undefined macro is used by #if\n");
+  printf ("  -Wno-undef                Do not warn about testing udefined macros\n");
+  printf ("  -Wimport                  Warn about the use of the #import directive\n");
+  printf ("  -Wno-import               Do not warn about the use of #import\n");
+  printf ("  -Werror                   Treat all warnings as errors\n");
+  printf ("  -Wno-error                Do not treat warnings as errors\n");
+  printf ("  -Wall                     Enable all preprocessor warnings\n");
+  printf ("  -M                        Generate make dependencies\n");
+  printf ("  -MM                       As -M, but ignore system header files\n");
+  printf ("  -MD                       As -M, but put output in a .d file\n");
+  printf ("  -MMD                      As -MD, but ignore system header files\n");
+  printf ("  -MG                       Treat missing header file as generated files\n");
+  printf ("  -g                        Include #define and #undef directives in the output\n");
+  printf ("  -D<macro>                 Define a <macro> with string '1' as its value\n");
+  printf ("  -D<macro>=<val>           Define a <macro> with <val> as its value\n");
+  printf ("  -A<question> (<answer>)   Assert the <answer> to <question>\n");
+  printf ("  -U<macro>                 Undefine <macro> \n");
+  printf ("  -u or -undef              Do not predefine any macros\n");
+  printf ("  -v                        Display the version number\n");
+  printf ("  -H                        Print the name of header files as they are used\n");
+  printf ("  -C                        Do not discard comments\n");
+  printf ("  -dM                       Display a list of macro definitions active at end\n");
+  printf ("  -dD                       Preserve macro definitions in output\n");
+  printf ("  -dN                       As -dD except that only the names are preserved\n");
+  printf ("  -dI                       Include #include directives in the output\n");
+  printf ("  -ifoutput                 Describe skipped code blocks in output \n");
+  printf ("  -P                        Do not generate #line directives\n");
+  printf ("  -$                        Do not include '$' in identifiers\n");
+  printf ("  -remap                    Remap file names when including files.\n");
+  printf ("  -h or --help              Display this information\n");
+}
+\f
 int
 main (argc, argv)
      int argc;
@@ -1240,12 +1308,21 @@ main (argc, argv)
   bzero ((char *) pend_assertions, argc * sizeof (char *));
   bzero ((char *) pend_includes, argc * sizeof (char *));
 
+#ifdef MULTIBYTE_CHARS
+  /* Change to the native locale for multibyte conversions.  */
+  setlocale (LC_CTYPE, "");
+  literal_codeset = getenv ("LANG");
+#endif
+
   /* Process switches and find input file name.  */
 
   for (i = 1; i < argc; i++) {
     if (argv[i][0] != '-') {
       if (out_fname != NULL)
-       fatal ("Usage: %s [switches] input output", argv[0]);
+       {
+         print_help ();
+         fatal ("Too many arguments");
+       }
       else if (in_fname != NULL)
        out_fname = argv[i];
       else
@@ -1453,6 +1530,13 @@ main (argc, argv)
          }
        break;
 
+      case 'f':
+       if (!strcmp (argv[i], "-fleading-underscore"))
+         user_label_prefix = "_";
+       else if (!strcmp (argv[i], "-fno-leading-underscore"))
+         user_label_prefix = "";
+       break;
+
       case 'M':
        /* The style of the choices here is a bit mixed.
           The chosen scheme is a hybrid of keeping all options in one string
@@ -1525,6 +1609,13 @@ main (argc, argv)
          debug_output = 1;
        break;
 
+      case '-':
+       if (strcmp (argv[i], "--help") != 0)
+         return i;
+       print_help ();
+       exit (0);
+       break;
+
       case 'v':
        fprintf (stderr, "GNU CPP version %s", version_string);
 #ifdef TARGET_VERSION
@@ -1659,7 +1750,7 @@ main (argc, argv)
   /* Some people say that CPATH should replace the standard include dirs,
      but that seems pointless: it comes before them, so it overrides them
      anyway.  */
-  GET_ENVIRONMENT (cp, "CPATH");
+  GET_ENV_PATH_LIST (cp, "CPATH");
   if (cp && ! no_standard_includes)
     path_include (cp);
 
@@ -1745,7 +1836,7 @@ main (argc, argv)
            sprintf (versbuf, "__VMS_VER=%08ld", vms_version_value);
            if (debug_output)
              output_line_directive (fp, &outbuf, 0, same_file);
-           make_definition (versbuf, &outbuf);
+           make_definition (versbuf);
          }
       }
 #endif
@@ -1764,7 +1855,7 @@ main (argc, argv)
          *p++= 0;
        if (debug_output)
          output_line_directive (fp, &outbuf, 0, same_file);
-       make_definition (q, &outbuf);
+       make_definition (q);
        while (*p == ' ' || *p == '\t')
          p++;
       } else if (p[0] == '-' && p[1] == 'A') {
@@ -1829,7 +1920,7 @@ main (argc, argv)
     if (pend_defs[i]) {
       if (debug_output)
         output_line_directive (fp, &outbuf, 0, same_file);
-      make_definition (pend_defs[i], &outbuf);
+      make_definition (pend_defs[i]);
     }
     if (pend_assertions[i])
       make_assertion (pend_assertion_options[i], pend_assertions[i]);
@@ -1843,16 +1934,16 @@ main (argc, argv)
     switch ((objc << 1) + cplusplus)
       {
       case 0:
-       GET_ENVIRONMENT (epath, "C_INCLUDE_PATH");
+       GET_ENV_PATH_LIST (epath, "C_INCLUDE_PATH");
        break;
       case 1:
-       GET_ENVIRONMENT (epath, "CPLUS_INCLUDE_PATH");
+       GET_ENV_PATH_LIST (epath, "CPLUS_INCLUDE_PATH");
        break;
       case 2:
-       GET_ENVIRONMENT (epath, "OBJC_INCLUDE_PATH");
+       GET_ENV_PATH_LIST (epath, "OBJC_INCLUDE_PATH");
        break;
       case 3:
-       GET_ENVIRONMENT (epath, "OBJCPLUS_INCLUDE_PATH");
+       GET_ENV_PATH_LIST (epath, "OBJCPLUS_INCLUDE_PATH");
        break;
       }
     /* If the environment var for this language is set,
@@ -2696,9 +2787,27 @@ do { ip = &instack[indepth];             \
              bp += 2;
            else if (*bp == '/' && bp[1] == '*') {
              bp += 2;
-             while (!(*bp == '*' && bp[1] == '/'))
-               bp++;
-             bp += 2;
+             while (1)
+               {
+                 if (*bp == '*')
+                   {
+                     if (bp[1] == '/')
+                       {
+                         bp += 2;
+                         break;
+                       }
+                   }
+                 else
+                   {
+#ifdef MULTIBYTE_CHARS
+                     int length;
+                     length = local_mblen (bp, limit - bp);
+                     if (length > 1)
+                       bp += (length - 1);
+#endif
+                   }
+                 bp++;
+               }
            }
            /* There is no point in trying to deal with C++ // comments here,
               because if there is one, then this # must be part of the
@@ -2859,6 +2968,24 @@ do { ip = &instack[indepth];             \
          if (ibp[-1] == c)
            goto while2end;
          break;
+#ifdef MULTIBYTE_CHARS
+       default:
+         {
+           int length;
+           --ibp;
+           length = local_mblen (ibp, limit - ibp);
+           if (length > 0)
+             {
+               --obp;
+               bcopy (ibp, obp, length);
+               obp += length;
+               ibp += length;
+             }
+           else
+             ++ibp;
+         }
+         break;
+#endif
        }
       }
     while2end:
@@ -2887,24 +3014,39 @@ do { ip = &instack[indepth];            \
          U_CHAR *before_bp = ibp;
 
          while (++ibp < limit) {
-           if (*ibp == '\n') {
-             if (ibp[-1] != '\\') {
+           if (*ibp == '\n')
+             {
                if (put_out_comments) {
                  bcopy ((char *) before_bp, (char *) obp, ibp - before_bp);
                  obp += ibp - before_bp;
                }
                break;
              }
-             if (warn_comments)
-               warning ("multiline `//' comment");
-             ++ip->lineno;
-             /* Copy the newline into the output buffer, in order to
-                avoid the pain of a #line every time a multiline comment
-                is seen.  */
-             if (!put_out_comments)
-               *obp++ = '\n';
-             ++op->lineno;
-           }
+           if (*ibp == '\\')
+             {
+               if (ibp + 1 < limit && ibp[1] == '\n')
+                 {
+                   if (warn_comments)
+                     warning ("multiline `//' comment");
+                   ++ip->lineno;
+                   /* Copy the newline into the output buffer, in order to
+                      avoid the pain of a #line every time a multiline comment
+                      is seen.  */
+                   if (!put_out_comments)
+                     *obp++ = '\n';
+                   ++op->lineno;
+                   ++ibp;
+                 }
+             }
+           else
+             {
+#ifdef MULTIBYTE_CHARS
+               int length;
+               length = local_mblen (ibp, limit - ibp);
+               if (length > 1)
+                 ibp += (length - 1);
+#endif
+             }
          }
          break;
        }
@@ -2993,6 +3135,16 @@ do { ip = &instack[indepth];             \
              goto limit_reached;
            }
            break;
+#ifdef MULTIBYTE_CHARS
+         default:
+           {
+             int length;
+             length = local_mblen (ibp, limit - ibp);
+             if (length > 1)
+               ibp += (length - 1);
+           }
+           break;
+#endif
          }
        }
       comment_end:
@@ -3355,11 +3507,27 @@ randomchar:
                              break;
                            }
                          }
-                         if (*ibp == '\n') {
+                         else if (*ibp == '\n') {
                            /* Newline in a file.  Count it.  */
                            ++ip->lineno;
                            ++op->lineno;
                          }
+                         else
+                           {
+#ifdef MULTIBYTE_CHARS
+                             int length;
+                             length = local_mblen (ibp, limit - ibp);
+                             if (length > 1)
+                               {
+                                 if (put_out_comments)
+                                   {
+                                     bcopy (ibp, obp, length - 1);
+                                     obp += length - 1;
+                                   }
+                                 ibp += (length - 1);
+                               }
+#endif
+                           }
                          if (put_out_comments)
                            *obp++ = *ibp;
                        }
@@ -3370,9 +3538,34 @@ randomchar:
                        } else if (! traditional) {
                          *obp++ = ' ';
                        }
-                       for (ibp += 2; *ibp != '\n' || ibp[-1] == '\\'; ibp++)
-                         if (put_out_comments)
-                           *obp++ = *ibp;
+                       for (ibp += 2; ; ibp++)
+                         {
+                           if (*ibp == '\n')
+                             break;
+                           if (*ibp == '\\' && ibp[1] == '\n')
+                             {
+                               if (put_out_comments)
+                                 *obp++ = *ibp++;
+                             }
+                           else
+                             {
+#ifdef MULTIBYTE_CHARS
+                               int length;
+                               length = local_mblen (ibp, limit - ibp);
+                               if (length > 1)
+                                 {
+                                   if (put_out_comments)
+                                     {
+                                       bcopy (ibp, obp, length - 1);
+                                       obp += length - 1;
+                                     }
+                                   ibp += (length - 1);
+                                 }
+#endif
+                             }
+                           if (put_out_comments)
+                             *obp++ = *ibp;
+                         }
                      } else
                        break;
                    }
@@ -4097,7 +4290,7 @@ special_symbol (hp, op)
     break;
 
   case T_USER_LABEL_PREFIX_TYPE:
-    buf = USER_LABEL_PREFIX;
+    buf = user_label_prefix;
     break;
 
   case T_REGISTER_PREFIX_TYPE:
@@ -4364,7 +4557,7 @@ get_filename:
      */
     /* Note: The argument of ISALPHA() can be evaluated twice, so do
        the pre-decrement outside of the macro. */
-    if (retried && (--fbeg, ISALPHA(*(U_CHAR *) (fbeg)))) {
+    if (retried && (--fin, ISALPHA(*(U_CHAR *) (fin)))) {
       while (fin != limit && (!ISSPACE(*fin)))
        *fend++ = *fin++;
       warning ("VAX-C-style include specification found, use '#include <filename.h>' !");
@@ -4629,8 +4822,7 @@ get_filename:
     if (pcfbuf) {
       pcfname = xmalloc (strlen (pcftry) + 1);
       strcpy (pcfname, pcftry);
-      pcfinclude ((U_CHAR *) pcfbuf, (U_CHAR *) pcfbuflimit,
-                 (U_CHAR *) fname, op);
+      pcfinclude ((U_CHAR *) pcfbuf, (U_CHAR *) fname, op);
     }
     else
       finclude (f, inc, op, is_system_include (fname), searchptr);
@@ -5337,8 +5529,8 @@ check_preconditions (prec)
    in.  OP is the main output buffer.  */
 
 static void
-pcfinclude (buf, limit, name, op)
-     U_CHAR *buf, *limit, *name;
+pcfinclude (buf, name, op)
+     U_CHAR *buf, *name;
      FILE_BUF *op;
 {
   FILE_BUF tmpbuf;
@@ -5625,7 +5817,7 @@ create_definition (buf, limit, op)
       while (is_idchar[*bp]) {
        bp++;
        /* do we have a "special" rest-args extension here? */
-       if (limit - bp > REST_EXTENSION_LENGTH
+       if (limit - bp > (long) REST_EXTENSION_LENGTH
            && bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {
          if (pedantic && !instack[indepth].system_header_p)
            pedwarn ("ANSI C does not allow macro with variable arguments");
@@ -6108,6 +6300,25 @@ collect_expansion (buf, end, nargs, arglist)
       }
     }
 
+#ifdef MULTIBYTE_CHARS
+    /* Handle multibyte characters inside string and character literals.  */
+    if (expected_delimiter != '\0')
+      {
+       int length;
+       --p;
+       length = local_mblen (p, limit - p);
+       if (length > 1)
+         {
+           --exp_p;
+           bcopy (p, exp_p, length);
+           p += length;
+           exp_p += length;
+           continue;
+         }
+       ++p;
+      }
+#endif
+
     /* Handle the start of a symbol.  */
     if (is_idchar[c] && nargs > 0) {
       U_CHAR *id_beg = p - 1;
@@ -7334,9 +7545,27 @@ skip_if_group (ip, any, op)
            bp += 2;
          else if (*bp == '/' && bp[1] == '*') {
            bp += 2;
-           while (!(*bp == '*' && bp[1] == '/'))
-             bp++;
-           bp += 2;
+           while (1)
+             {
+               if (*bp == '*')
+                 {
+                   if (bp[1] == '/')
+                     {
+                       bp += 2;
+                       break;
+                     }
+                 }
+               else
+                 {
+#ifdef MULTIBYTE_CHARS
+                   int length;
+                   length = local_mblen (bp, endb - bp);
+                   if (length > 1)
+                     bp += (length - 1);
+#endif
+                 }
+               bp++;
+             }
          }
          /* There is no point in trying to deal with C++ // comments here,
             because if there is one, then this # must be part of the
@@ -7380,17 +7609,37 @@ skip_if_group (ip, any, op)
                if (bp[1] == '/')
                  break;
              }
+             else
+               {
+#ifdef MULTIBYTE_CHARS
+                 int length;
+                 length = local_mblen (bp, endb - bp);
+                 if (length > 1)
+                   bp += (length - 1);
+#endif
+               }
            }
            bp += 2;
          } else if (bp[1] == '/' && cplusplus_comments) {
            for (bp += 2; ; bp++) {
-             if (*bp == '\n') {
-               if (bp[-1] != '\\')
-                 break;
-               if (warn_comments)
-                 warning ("multiline `//' comment");
-               ip->lineno++;
-             }
+             if (*bp == '\n')
+               break;
+             if (*bp == '\\' && bp[1] == '\n')
+               {
+                 if (warn_comments)
+                   warning ("multiline `//' comment");
+                 ip->lineno++;
+                 bp++;
+               }
+             else
+               {
+#ifdef MULTIBYTE_CHARS
+                 int length;
+                 length = local_mblen (bp, endb - bp);
+                 if (length > 1)
+                   bp += (length - 1);
+#endif
+               }
            }
          } else
            break;
@@ -7686,6 +7935,15 @@ validate_else (p, limit)
              break;
            }
          }
+         else
+           {
+#ifdef MULTIBYTE_CHARS
+             int length;
+             length = local_mblen (p, limit - p);
+             if (length > 1)
+               p += (length - 1);
+#endif
+           }
        }
       }
       else if (cplusplus_comments && p[1] == '/')
@@ -7729,16 +7987,37 @@ skip_to_end_of_comment (ip, line_counter, nowarn)
   }
   if (cplusplus_comments && bp[-1] == '/') {
     for (; bp < limit; bp++) {
-      if (*bp == '\n') {
-       if (bp[-1] != '\\')
-         break;
-       if (!nowarn && warn_comments)
-         warning ("multiline `//' comment");
-       if (line_counter)
-         ++*line_counter;
-       if (op)
-         ++op->lineno;
-      }
+      if (*bp == '\n')
+       break;
+      if (*bp == '\\' && bp + 1 < limit && bp[1] == '\n')
+       {
+         if (!nowarn && warn_comments)
+           warning ("multiline `//' comment");
+         if (line_counter)
+           ++*line_counter;
+         if (op)
+           {
+             ++op->lineno;
+             *op->bufp++ = *bp;
+           }
+         ++bp;
+       }
+      else
+       {
+#ifdef MULTIBYTE_CHARS
+         int length;
+         length = local_mblen (bp, limit - bp);
+         if (length > 1)
+           {
+             if (op)
+               {
+                 bcopy (bp, op->bufp, length - 1);
+                 op->bufp += (length - 1);
+               }
+             bp += (length - 1);
+           }
+#endif
+       }
       if (op)
        *op->bufp++ = *bp;
     }
@@ -7776,6 +8055,23 @@ skip_to_end_of_comment (ip, line_counter, nowarn)
        return bp;
       }
       break;
+#ifdef MULTIBYTE_CHARS
+    default:
+      {
+       int length;
+       bp--;
+       length = local_mblen (bp, limit - bp);
+       if (length <= 0)
+         length = 1;
+       if (op)
+         {
+           op->bufp--;
+           bcopy (bp, op->bufp, length);
+           op->bufp += length;
+         }
+       bp += length;
+      }
+#endif
     }
   }
 
@@ -7866,6 +8162,16 @@ skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p,
       }
     } else if (c == match)
       break;
+#ifdef MULTIBYTE_CHARS
+    {
+      int length;
+      --bp;
+      length = local_mblen (bp, limit - bp);
+      if (length <= 0)
+       length = 1;
+      bp += length;
+    }
+#endif
   }
   return bp;
 }
@@ -8303,9 +8609,23 @@ macroexpand (hp, op)
            else {
              if (c == '\\')
                escaped = 1;
-             if (in_string) {
+             else if (in_string) {
                if (c == in_string)
                  in_string = 0;
+               else
+                 {
+#ifdef MULTIBYTE_CHARS
+                   int length;
+                   length = local_mblen (arg->raw + i, arglen - i);
+                   if (length > 1)
+                     {
+                       bcopy (arg->raw + i, xbuf + totlen, length);
+                       i += length - 1;
+                       totlen += length;
+                       continue;
+                     }
+#endif
+                 }
              } else if (c == '\"' || c == '\'')
                in_string = c;
            }
@@ -8639,17 +8959,39 @@ macarg1 (start, limit, macro, depthptr, newlines, comments, rest_args)
              break;
            }
          }
+         else
+           {
+#ifdef MULTIBYTE_CHARS
+             int length;
+             length = local_mblen (bp, limit - bp);
+             if (length > 1)
+               bp += (length - 1);
+#endif
+           }
        }
       } else if (bp[1] == '/' && cplusplus_comments) {
        *comments = 1;
        for (bp += 2; bp < limit; bp++) {
          if (*bp == '\n') {
            ++*newlines;
-           if (bp[-1] != '\\')
-             break;
-           if (warn_comments)
-             warning ("multiline `//' comment");
+           break;
          }
+         if (*bp == '\\' && bp + 1 < limit && bp[1] == '\n')
+           {
+             ++*newlines;
+             if (warn_comments)
+               warning ("multiline `//' comment");
+             ++bp;
+           }
+         else
+           {
+#ifdef MULTIBYTE_CHARS
+             int length;
+             length = local_mblen (bp, limit - bp);
+             if (length > 1)
+               bp += (length - 1);
+#endif
+           }
        }
       }
       break;
@@ -8673,6 +9015,15 @@ macarg1 (start, limit, macro, depthptr, newlines, comments, rest_args)
            if (quotec == '\'')
              break;
          }
+         else
+           {
+#ifdef MULTIBYTE_CHARS
+             int length;
+             length = local_mblen (bp, limit - bp);
+             if (length > 1)
+               bp += (length - 1);
+#endif
+           }
        }
       }
       break;
@@ -8750,8 +9101,22 @@ discard_comments (start, length, newlines)
        /* Comments are equivalent to spaces.  */
        obp[-1] = ' ';
        ibp++;
-       while (ibp < limit && (*ibp != '\n' || ibp[-1] == '\\'))
-         ibp++;
+       while (ibp < limit)
+         {
+           if (*ibp == '\n')
+             break;
+           if (*ibp == '\\' && ibp + 1 < limit && ibp[1] == '\n')
+             ibp++;
+           else
+             {
+#ifdef MULTIBYTE_CHARS
+               int length = local_mblen (ibp, limit - ibp);
+               if (length > 1)
+                 ibp += (length - 1);
+#endif
+             }
+           ibp++;
+         }
        break;
       }
       if (ibp[0] != '*' || ibp + 1 >= limit)
@@ -8771,6 +9136,14 @@ discard_comments (start, length, newlines)
            break;
          }
        }
+       else
+         {
+#ifdef MULTIBYTE_CHARS
+           int length = local_mblen (ibp, limit - ibp);
+           if (length > 1)
+             ibp += (length - 1);
+#endif
+         }
       }
       break;
 
@@ -8785,9 +9158,12 @@ discard_comments (start, length, newlines)
          *obp++ = c = *ibp++;
          if (c == quotec)
            break;
-         if (c == '\n' && quotec == '\'')
-           break;
-         if (c == '\\') {
+         if (c == '\n')
+           {
+             if (quotec == '\'')
+               break;
+           }
+         else if (c == '\\') {
            if (ibp < limit && *ibp == '\n') {
              ibp++;
              obp--;
@@ -8798,6 +9174,23 @@ discard_comments (start, length, newlines)
                *obp++ = *ibp++;
            }
          }
+         else
+           {
+#ifdef MULTIBYTE_CHARS
+             int length;
+             ibp--;
+             length = local_mblen (ibp, limit - ibp);
+             if (length > 1)
+               {
+                 obp--;
+                 bcopy (ibp, obp, length);
+                 ibp += length;
+                 obp += length;
+               }
+             else
+               ibp++;
+#endif
+           }
        }
       }
       break;
@@ -8847,10 +9240,32 @@ change_newlines (start, length)
        int quotec = c;
        while (ibp < limit) {
          *obp++ = c = *ibp++;
-         if (c == quotec && ibp[-2] != '\\')
-           break;
-         if (c == '\n' && quotec == '\'')
+         if (c == quotec)
            break;
+         else if (c == '\\' && ibp < limit && *ibp == '\n')
+           *obp++ = *ibp++;
+         else if (c == '\n')
+           {
+             if (quotec == '\'')
+               break;
+           }
+         else
+           {
+#ifdef MULTIBYTE_CHARS
+             int length;
+             ibp--;
+             length = local_mblen (ibp, limit - ibp);
+             if (length > 1)
+               {
+                 obp--;
+                 bcopy (ibp, obp, length);
+                 ibp += length;
+                 obp += length;
+               }
+             else
+               ibp++;
+#endif
+           }
        }
       }
       break;
@@ -8897,14 +9312,14 @@ my_strerror (errnum)
 void
 error VPROTO ((char * msg, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   char * msg;
 #endif
   va_list args;
 
   VA_START (args, msg);
 
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   msg = va_arg (args, char *);
 #endif
 
@@ -8970,14 +9385,14 @@ error_from_errno (name)
 void
 warning VPROTO ((char * msg, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   char * msg;
 #endif
   va_list args;
 
   VA_START (args, msg);
 
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   msg = va_arg (args, char *);
 #endif
 
@@ -9019,7 +9434,7 @@ vwarning (msg, args)
 static void
 error_with_line VPROTO ((int line, char * msg, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   int line;
   char * msg;
 #endif
@@ -9027,7 +9442,7 @@ error_with_line VPROTO ((int line, char * msg, ...))
 
   VA_START (args, msg);
 
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   line = va_arg (args, int);
   msg = va_arg (args, char *);
 #endif
@@ -9065,7 +9480,7 @@ verror_with_line (line, msg, args)
 static void
 warning_with_line VPROTO ((int line, char * msg, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   int line;
   char * msg;
 #endif
@@ -9073,7 +9488,7 @@ warning_with_line VPROTO ((int line, char * msg, ...))
 
   VA_START (args, msg);
 
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   line = va_arg (args, int);
   msg = va_arg (args, char *);
 #endif
@@ -9119,14 +9534,14 @@ vwarning_with_line (line, msg, args)
 void
 pedwarn VPROTO ((char * msg, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   char * msg;
 #endif
   va_list args;
 
   VA_START (args, msg);
  
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   msg = va_arg (args, char *);
 #endif
  
@@ -9140,7 +9555,7 @@ pedwarn VPROTO ((char * msg, ...))
 void
 pedwarn_with_line VPROTO ((int line, char * msg, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   int line;
   char * msg;
 #endif
@@ -9148,7 +9563,7 @@ pedwarn_with_line VPROTO ((int line, char * msg, ...))
 
   VA_START (args, msg);
  
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   line = va_arg (args, int);
   msg = va_arg (args, char *);
 #endif
@@ -9167,7 +9582,7 @@ static void
 pedwarn_with_file_and_line VPROTO ((char *file, size_t file_len, int line,
                                    char * msg, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   char *file;
   size_t file_len;
   int line;
@@ -9177,23 +9592,25 @@ pedwarn_with_file_and_line VPROTO ((char *file, size_t file_len, int line,
 
   if (!pedantic_errors && inhibit_warnings)
     return;
-  if (file) {
-    eprint_string (file, file_len);
-    fprintf (stderr, ":%d: ", line);
-  }
-  if (pedantic_errors)
-    errors++;
-  if (!pedantic_errors)
-    fprintf (stderr, "warning: ");
+
   VA_START (args, msg);
  
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   file = va_arg (args, char *);
   file_len = va_arg (args, size_t);
   line = va_arg (args, int);
   msg = va_arg (args, char *);
 #endif
  
+  if (file) {
+    eprint_string (file, file_len);
+    fprintf (stderr, ":%d: ", line);
+  }
+  if (pedantic_errors)
+    errors++;
+  if (!pedantic_errors)
+    fprintf (stderr, "warning: ");
+
   vfprintf (stderr, msg, args);
   va_end (args);
   fprintf (stderr, "\n");
@@ -9792,9 +10209,8 @@ initialize_builtins (inp, outp)
  */
 
 static void
-make_definition (str, op)
+make_definition (str)
      char *str;
-     FILE_BUF *op;
 {
   FILE_BUF *ip;
   struct directive *kt;
@@ -10207,7 +10623,7 @@ deps_output (string, spacer)
 static void
 fatal VPROTO ((char * msg, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   char * msg;
 #endif
   va_list args;
@@ -10215,7 +10631,7 @@ fatal VPROTO ((char * msg, ...))
   fprintf (stderr, "%s: ", progname);
   VA_START (args, msg);
  
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   msg = va_arg (args, char *);
 #endif