arc: Refurbish adc/sbc patterns
[gcc.git] / fixincludes / fixincl.c
index 243f9bbfd1017be9c021f9c9743d5d2292fddc2a..6dba2f6e830a9b9827a799984e68bb81e108fba6 100644 (file)
@@ -2,13 +2,14 @@
    files which are fixed to work correctly with ANSI C and placed in a
    directory that GCC will search.
 
-   Copyright (C) 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2012
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -17,13 +18,16 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "fixlib.h"
 
+#include <fnmatch.h>
 #include <sys/stat.h>
+#ifndef SEPARATE_FIX_PROC
+#include <sys/wait.h>
+#endif
 
 #if defined( HAVE_MMAP_FILE )
 #include <sys/mman.h>
@@ -49,22 +53,8 @@ static const char z_std_preamble[] =
     original, manufacturer supplied header file.  */\n\n";
 
 int find_base_len = 0;
-
-typedef enum {
-  VERB_SILENT = 0,
-  VERB_FIXES,
-  VERB_APPLIES,
-  VERB_PROGRESS,
-  VERB_TESTS,
-  VERB_EVERYTHING
-} te_verbose;
-
-te_verbose  verbose_level = VERB_PROGRESS;
 int have_tty = 0;
 
-#define VLEVEL(l)  ((unsigned int) verbose_level >= (unsigned int) l)
-#define NOT_SILENT VLEVEL(VERB_FIXES)
-
 pid_t process_chain_head = (pid_t) -1;
 
 char*  pz_curr_file;  /*  name of the current file under test/fix  */
@@ -84,9 +74,12 @@ int altered_ct = 0;
 #endif /* DO_STATS */
 
 const char incl_quote_pat[] = "^[ \t]*#[ \t]*include[ \t]*\"[^/]";
-tSCC z_fork_err[] = "Error %d (%s) starting filter process for %s\n";
 regex_t incl_quote_re;
 
+#ifndef SEPARATE_FIX_PROC
+tSCC z_fork_err[] = "Error %d (%s) starting filter process for %s\n";
+#endif
+
 static void do_version (void) ATTRIBUTE_NORETURN;
 char *load_file (const char *);
 void run_compiles (void);
@@ -198,7 +191,7 @@ do_version (void)
   puts (zBuf + 5);
   exit (strcmp (run_shell (zBuf), program_id));
 #else
-  exit (system (zBuf));
+  exit (system_with_shell (zBuf));
 #endif
 }
 
@@ -285,6 +278,11 @@ initialize ( int argc, char** argv )
   /* NULL as the first argument to `tempnam' causes it to DTRT
      wrt the temporary directory where the file will be created.  */
   pz_temp_file = tempnam( NULL, "fxinc" );
+
+#if defined(__MINGW32__)
+  fix_path_separators (pz_temp_file);
+#endif
+
 # endif
 
   signal (SIGQUIT, SIG_IGN);
@@ -356,102 +354,42 @@ load_file ( const char* fname )
 
 static int
 machine_matches( tFixDesc* p_fixd )
-        {
-# ifndef SEPARATE_FIX_PROC
-          tSCC case_fmt[] = "case %s in\n";     /*  9 bytes, plus string */
-          tSCC esac_fmt[] =
-               " )\n    echo %s ;;\n* ) echo %s ;;\nesac";/*  4 bytes */
-          tSCC skip[] = "skip";                 /*  4 bytes */
-          tSCC run[] = "run";                   /*  3 bytes */
-          /* total bytes to add to machine sum:    49 - see fixincl.tpl */
-
-          const char **papz_machs = p_fixd->papz_machs;
-          char *pz;
-          const char *pz_sep = "";
-          tCC *pz_if_true;
-          tCC *pz_if_false;
-          char cmd_buf[ MACH_LIST_SIZE_LIMIT ]; /* size lim from fixincl.tpl */
-
-          /* Start the case statement */
-
-          sprintf (cmd_buf, case_fmt, pz_machine);
-          pz = cmd_buf + strlen (cmd_buf);
-
-          /*  Determine if a match means to apply the fix or not apply it */
-
-          if (p_fixd->fd_flags & FD_MACH_IFNOT)
-            {
-              pz_if_true  = skip;
-              pz_if_false = run;
-            }
-          else
-            {
-              pz_if_true  = run;
-              pz_if_false = skip;
-            }
-
-          /*  Emit all the machine names.  If there are more than one,
-              then we will insert " | \\\n" between the names  */
-
-          for (;;)
-            {
-              const char* pz_mach = *(papz_machs++);
-
-              if (pz_mach == (const char*) NULL)
-                break;
-              sprintf (pz, "%s%s", pz_sep, pz_mach);
-              pz += strlen (pz);
-              pz_sep = " | \\\n";
-            }
-
-          /* Now emit the match and not-match actions and the esac */
-
-          sprintf (pz, esac_fmt, pz_if_true, pz_if_false);
-
-          /*  Run the script.
-              The result will start either with 's' or 'r'.  */
-
-          {
-            int skip;
-            pz = run_shell (cmd_buf);
-            skip = (*pz == 's');
-            free ( (void*)pz );
-            if (skip)
-              {
-                p_fixd->fd_flags |= FD_SKIP_TEST;
-               return BOOL_FALSE;
-             }
-         }
+{
+  char const ** papz_machs = p_fixd->papz_machs;
+  int have_match = BOOL_FALSE;
 
-  return BOOL_TRUE;
-# else /* is SEPARATE_FIX_PROC */
-  const char **papz_machs = p_fixd->papz_machs;
-  int invert = (p_fixd->fd_flags & FD_MACH_IFNOT) != 0;
   for (;;)
     {
-      const char* pz_mach = *(papz_machs++);
-
-      if (pz_mach == (const char*) NULL)
+      char const * pz_mpat = *(papz_machs++);
+      if (pz_mpat == NULL)
         break;
-      if (strstr (pz_mach, "dos") != NULL && !invert)
-       return BOOL_TRUE;
+      if (fnmatch(pz_mpat, pz_machine, 0) == 0)
+        {
+          have_match = BOOL_TRUE;
+          break;
+        }
     }
 
-  p_fixd->fd_flags |= FD_SKIP_TEST;
-  return BOOL_FALSE;
-# endif
+  /* Check for sense inversion then set the "skip test" flag, if needed */
+  if (p_fixd->fd_flags & FD_MACH_IFNOT)
+    have_match = ! have_match;
+
+  if (! have_match)
+    p_fixd->fd_flags |= FD_SKIP_TEST;
+
+  return have_match;
 }
 
 /* * * * * * * * * * * * *
-
-   run_compiles   run all the regexp compiles for all the fixes once.
  */
+ *
*  run_compiles   run all the regexp compiles for all the fixes once.
+ */
 void
 run_compiles (void)
 {
   tFixDesc *p_fixd = fixDescList;
   int fix_ct = FIX_COUNT;
-  regex_t *p_re = xcalloc (REGEX_COUNT, sizeof (regex_t));
+  regex_t *p_re = XCNEWVEC (regex_t, REGEX_COUNT);
 
   /*  Make sure compile_re does not stumble across invalid data */
 
@@ -468,8 +406,17 @@ run_compiles (void)
   /* FOR every fixup, ...  */
   do
     {
-      tTestDesc *p_test = p_fixd->p_test_desc;
-      int test_ct = p_fixd->test_ct;
+      tTestDesc *p_test;
+      int test_ct;
+
+      if (fixinc_mode && (p_fixd->fd_flags & FD_REPLACEMENT))
+        {
+          p_fixd->fd_flags |= FD_SKIP_TEST;
+          continue;
+        }
+
+      p_test = p_fixd->p_test_desc;
+      test_ct = p_fixd->test_ct;
 
       /*  IF the machine type pointer is not NULL (we are not in test mode)
              AND this test is for or not done on particular machines
@@ -627,6 +574,26 @@ fi";
   free ((void *) pz_res);
   return res;
 }
+#elif defined(__MINGW32__) || defined(__DJGPP__)
+static int
+test_test (tTestDesc* p_test, char* pz_test_file)
+{
+  tSCC cmd_fmt[] =
+#if defined(__DJGPP__)
+    "file=%s; test %s >/dev/null 2>/dev/null";
+#else
+    "file=%s; test %s > /dev/null 2>&1";
+#endif
+  int res;
+
+  char *cmd_buf = XNEWVEC (char, strlen(cmd_fmt) + strlen(pz_test_file) + strlen(p_test->pz_test_text));
+
+  sprintf (cmd_buf, cmd_fmt, pz_test_file, p_test->pz_test_text);
+  res = system_with_shell (cmd_buf);
+
+  free (cmd_buf);
+  return res ? SKIP_FIX : APPLY_FIX;
+}
 #else
 /*
  *  IF we are in MS-DOS land, then whatever shell-type test is required
@@ -658,6 +625,63 @@ egrep_test (char* pz_data, tTestDesc* p_test)
   return SKIP_FIX;
 }
 
+/* * * * * * * * * * * * *
+
+  cksum_test   check the sum of the candidate file
+  Input:  the original file contents and the file name
+  Result: APPLY_FIX if the check sum matches, SKIP_FIX otherwise
+
+  The caller may choose to reverse meaning if the sense of the test
+  is inverted.  */
+
+static int
+cksum_test (char * pz_data, tTestDesc * p_test, char * fname)
+{
+  unsigned int cksum;
+
+  /*
+   * Testing is off in normal operation mode.
+   * So, in testing mode, APPLY_FIX is always returned.
+   */
+  if (fixinc_mode != TESTING_OFF)
+    return APPLY_FIX;
+
+  {
+    char * fnm = strrchr(fname, '/');
+    if (fnm != NULL)
+      fname = fnm + 1;
+    
+    errno = 0;
+    cksum = (unsigned int)strtoul(p_test->pz_test_text, &fnm, 10);
+    if (errno != 0)
+      return SKIP_FIX;
+
+    if (! ISSPACE(*fnm++))
+      return SKIP_FIX;
+    while (ISSPACE(*fnm)) fnm++;
+
+    if (! ISDIGIT(*fnm++))
+      return SKIP_FIX;
+    while (ISDIGIT(*fnm)) fnm++;
+
+    if (! ISSPACE(*fnm++))
+      return SKIP_FIX;
+    while (ISSPACE(*fnm)) fnm++;
+
+    if (strcmp(fnm, fname) != 0)
+      return SKIP_FIX;
+  }
+
+  {
+    unsigned int sum = 0;
+    while (*pz_data != NUL) {
+      sum = (sum >> 1) + ((sum & 1) << 15) + (unsigned)(*pz_data++);
+      sum &= 0xFFFF;
+    }
+
+    return (sum == cksum) ? APPLY_FIX : SKIP_FIX;
+  }
+}
 
 /* * * * * * * * * * * * *
 
@@ -851,45 +875,47 @@ fix_with_system (tFixDesc* p_fixd,
   char*  pz_cmd;
   char*  pz_scan;
   size_t argsize;
-  int i;
-  tSCC z_applyfix_prog[2] = {
-    "/../fixincludes/applyfix" EXE_EXT,
-    "/../../fixincludes/applyfix" EXE_EXT };
 
   if (p_fixd->fd_flags & FD_SUBROUTINE)
-    for (i = 0; i < 2; i++)
-      { 
-       struct stat buf;
-
-        argsize = 32
-                + strlen( pz_orig_dir )
-                + sizeof( z_applyfix_prog )
-                + strlen( pz_fix_file )
-                + strlen( pz_file_source )
-                + strlen( pz_temp_file );
-
-        pz_cmd = xmalloc (argsize);
-
-        strcpy( pz_cmd, pz_orig_dir );
-        pz_scan = pz_cmd + strlen( pz_orig_dir );
-        strcpy( pz_scan, z_applyfix_prog );
-        pz_scan += sizeof( z_applyfix_prog ) - 1;
-
-       if (stat (pz_scan, &buf) != -1)
-         {
-            *(pz_scan++) = ' ';
-            /*
-             *  Now add the fix number and file names that may be needed
-             */
-            sprintf (pz_scan, "%ld \'%s\' \'%s\' \'%s\'", p_fixd - fixDescList,
-                    pz_fix_file, pz_file_source, pz_temp_file);
-           break;
-         }
-      }
+    {
+      static const char z_applyfix_prog[] =
+        "/../fixincludes/applyfix" EXE_EXT;
+
+      struct stat buf;
+      argsize = 32
+              + strlen (pz_orig_dir)
+              + sizeof (z_applyfix_prog)
+              + strlen (pz_fix_file)
+              + strlen (pz_file_source)
+              + strlen (pz_temp_file);
+
+      /* Allocate something sure to be big enough for our purposes */
+      pz_cmd = XNEWVEC (char, argsize);
+      strcpy (pz_cmd, pz_orig_dir);
+      pz_scan = pz_cmd + strlen (pz_orig_dir);
+
+      strcpy (pz_scan, z_applyfix_prog);
+
+      /* IF we can't find the "applyfix" executable file at the first guess,
+         try one level higher up  */
+      if (stat (pz_cmd, &buf) == -1)
+        {
+          strcpy (pz_scan, "/..");
+          strcpy (pz_scan+3, z_applyfix_prog);
+        }
+
+      pz_scan += strlen (pz_scan);
+
+      /*
+       *  Now add the fix number and file names that may be needed
+       */
+      sprintf (pz_scan, " %ld '%s' '%s' '%s'", (long) (p_fixd - fixDescList),
+               pz_fix_file, pz_file_source, pz_temp_file);
+    }
   else /* NOT an "internal" fix: */
     {
       size_t parg_size;
-#ifdef __MSDOS__
+#if defined(__MSDOS__) && !defined(__DJGPP__)
       /* Don't use the "src > dstX; rm -f dst; mv -f dstX dst" trick:
          dst is a temporary file anyway, so we know there's no other
          file by that name; and DOS's system(3) doesn't mind to
@@ -902,18 +928,24 @@ fix_with_system (tFixDesc* p_fixd,
          the following bizarre use of 'cat' only works on DOS boxes.
          It causes the file to be dropped into a temporary file for
          'cat' to read (pipes do not work on DOS).  */
-      tSCC   z_cmd_fmt[] = " \'%s\' | cat > \'%s\'";
+      tSCC   z_cmd_fmt[] = " '%s' | cat > '%s'";
 #else
       /* Don't use positional formatting arguments because some lame-o
          implementations cannot cope  :-(.  */
       tSCC   z_cmd_fmt[] = " %s > %sX ; rm -f %s; mv -f %sX %s";
 #endif
+      tSCC   z_subshell_start[] = "( ";
+      tSCC   z_subshell_end[] = " ) < ";
       tCC**  ppArgs = p_fixd->patch_args;
 
       argsize = sizeof( z_cmd_fmt ) + strlen( pz_temp_file )
               + strlen( pz_file_source );
       parg_size = argsize;
       
+      if (p_fixd->fd_flags & FD_SHELL_SCRIPT)
+        {
+          argsize += strlen( z_subshell_start ) + strlen ( z_subshell_end );
+        }
 
       /*
        *  Compute the size of the command line.  Add lotsa extra space
@@ -931,13 +963,23 @@ fix_with_system (tFixDesc* p_fixd,
         }
 
       /* Estimated buffer size we will need.  */
-      pz_scan = pz_cmd = xmalloc (argsize);
+      pz_scan = pz_cmd = XNEWVEC (char, argsize);
       /* How much of it do we allot to the program name and its
          arguments.  */
       parg_size = argsize - parg_size;
 
       ppArgs = p_fixd->patch_args;
 
+      /*
+       * If it's shell script, enclose it in parentheses and skip "sh -c".
+       */
+      if (p_fixd->fd_flags & FD_SHELL_SCRIPT)
+        {
+          strcpy (pz_scan, z_subshell_start);
+          pz_scan += strlen (z_subshell_start);
+          ppArgs += 2;
+        }
+
       /*
        *  Copy the program name, unquoted
        */
@@ -958,39 +1000,48 @@ fix_with_system (tFixDesc* p_fixd,
       for (;;)
         {
           tCC*   pArg = *(ppArgs++);
-         char*  pz_scan_save;
+          char*  pz_scan_save;
           if (pArg == NULL)
             break;
           *(pz_scan++) = ' ';
           pz_scan = make_raw_shell_str( pz_scan_save = pz_scan, pArg,
-                                       parg_size - (pz_scan - pz_cmd) );
-         /*
-          *  Make sure we don't overflow the buffer due to sloppy
-          *  size estimation.
-          */
-         while (pz_scan == (char*)NULL)
-           {
-             size_t already_filled = pz_scan_save - pz_cmd;
-             pz_cmd = xrealloc (pz_cmd, argsize += 100);
-             pz_scan_save = pz_scan = pz_cmd + already_filled;
-             parg_size += 100;
-             pz_scan = make_raw_shell_str( pz_scan, pArg,
-                                           parg_size - (pz_scan - pz_cmd) );
-           }
+                                        parg_size - (pz_scan - pz_cmd) );
+          /*
+           *  Make sure we don't overflow the buffer due to sloppy
+           *  size estimation.
+           */
+          while (pz_scan == (char*)NULL)
+            {
+              size_t already_filled = pz_scan_save - pz_cmd;
+              pz_cmd = xrealloc (pz_cmd, argsize += 100);
+              pz_scan_save = pz_scan = pz_cmd + already_filled;
+              parg_size += 100;
+              pz_scan = make_raw_shell_str( pz_scan, pArg,
+                                            parg_size - (pz_scan - pz_cmd) );
+            }
+        }
+
+      /*
+       * Close parenthesis if it's shell script.
+       */
+      if (p_fixd->fd_flags & FD_SHELL_SCRIPT)
+        {
+          strcpy (pz_scan, z_subshell_end);
+          pz_scan += strlen (z_subshell_end);
         }
 
       /*
        *  add the file machinations.
        */
-#ifdef __MSDOS__
+#if defined(__MSDOS__) && !defined(__DJGPP__)
       sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file );
 #else
       sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file,
                pz_temp_file, pz_temp_file, pz_temp_file);
 #endif
     }
-  system( pz_cmd );
-  free( (void*)pz_cmd );
+  system_with_shell (pz_cmd);
+  free (pz_cmd);
 }
 
 /* * * * * * * * * * * * *
@@ -1018,8 +1069,8 @@ start_fixer (int read_fd, tFixDesc* p_fixd, char* pz_fix_file)
   else
     {
       tSCC z_cmd_fmt[] = "file='%s'\n%s";
-      pz_cmd = xmalloc (strlen (p_fixd->patch_args[2])
-                       + sizeof (z_cmd_fmt) + strlen (pz_fix_file));
+      pz_cmd = XNEWVEC (char, strlen (p_fixd->patch_args[2])
+                        + sizeof (z_cmd_fmt) + strlen (pz_fix_file));
       sprintf (pz_cmd, z_cmd_fmt, pz_fix_file, p_fixd->patch_args[2]);
       pz_cmd_save = p_fixd->patch_args[2];
       p_fixd->patch_args[2] = pz_cmd;
@@ -1066,14 +1117,22 @@ start_fixer (int read_fd, tFixDesc* p_fixd, char* pz_fix_file)
   return read_fd;
 }
 #endif
-
+#ifdef DEBUG
+# define NOTE_SKIP(_ttyp)  do {                                         \
+            if (VLEVEL( VERB_EVERYTHING ))                              \
+              fprintf (stderr, z_failed, _ttyp, p_fixd->fix_name,       \
+                       pz_fname, p_fixd->test_ct - test_ct);            \
+          } while (0)
+#else
+# define NOTE_SKIP(_ttyp)
+#endif
 
 /* * * * * * * * * * * * *
-
-   Process the potential fixes for a particular include file.
-   Input:  the original text of the file and the file's name
-   Result: none.  A new file may or may not be created.  */
-
+ *
*  Process the potential fixes for a particular include file.
*  Input:  the original text of the file and the file's name
+ *  Result: none.  A new file may or may not be created.
+ */
 static t_bool
 fix_applies (tFixDesc* p_fixd)
 {
@@ -1081,8 +1140,10 @@ fix_applies (tFixDesc* p_fixd)
   const char *pz_scan = p_fixd->file_list;
   int test_ct;
   tTestDesc *p_test;
+  t_bool saw_sum_test   = BOOL_FALSE;
+  t_bool one_sum_passed = BOOL_FALSE;
 
-# ifdef SEPARATE_FIX_PROC
+#if defined(__MSDOS__) && !defined(__DJGPP__)
   /*
    *  There is only one fix that uses a shell script as of this writing.
    *  I hope to nuke it anyway, it does not apply to DOS and it would
@@ -1090,39 +1151,31 @@ fix_applies (tFixDesc* p_fixd)
    */
   if (p_fixd->fd_flags & (FD_SHELL_SCRIPT | FD_SKIP_TEST))
     return BOOL_FALSE;
-# else
+#else
   if (p_fixd->fd_flags & FD_SKIP_TEST)
     return BOOL_FALSE;
-# endif
+#endif
 
   /*  IF there is a file name restriction,
       THEN ensure the current file name matches one in the pattern  */
 
   if (pz_scan != (char *) NULL)
     {
-      size_t name_len;
-
       while ((pz_fname[0] == '.') && (pz_fname[1] == '/'))
         pz_fname += 2;
-      name_len = strlen (pz_fname);
 
       for (;;)
         {
-          pz_scan = strstr (pz_scan + 1, pz_fname);
-          /*  IF we can't match the string at all,
-              THEN bail  */
-          if (pz_scan == (char *) NULL)
-            return BOOL_FALSE;
-
-          /*  IF the match is surrounded by the '|' markers,
-              THEN we found a full match -- time to run the tests  */
-
-          if ((pz_scan[-1] == '|') && (pz_scan[name_len] == '|'))
+          if (fnmatch (pz_scan, pz_fname, 0) == 0)
             break;
+          pz_scan += strlen (pz_scan) + 1;
+          if (*pz_scan == NUL)
+            return BOOL_FALSE;
         }
     }
 
   /*  FOR each test, see if it fails.
+      "sum" fails only if all "sum" tests fail.
       IF it does fail, then we go on to the next test */
 
   for (p_test = p_fixd->p_test_desc, test_ct = p_fixd->test_ct;
@@ -1133,52 +1186,51 @@ fix_applies (tFixDesc* p_fixd)
         {
         case TT_TEST:
           if (test_test (p_test, pz_curr_file) != APPLY_FIX) {
-#ifdef DEBUG
-            if (VLEVEL( VERB_EVERYTHING ))
-              fprintf (stderr, z_failed, "TEST", p_fixd->fix_name,
-                       pz_fname, p_fixd->test_ct - test_ct);
-#endif
+            NOTE_SKIP("TEST");
             return BOOL_FALSE;
           }
           break;
 
         case TT_EGREP:
           if (egrep_test (pz_curr_data, p_test) != APPLY_FIX) {
-#ifdef DEBUG
-            if (VLEVEL( VERB_EVERYTHING ))
-              fprintf (stderr, z_failed, "EGREP", p_fixd->fix_name,
-                       pz_fname, p_fixd->test_ct - test_ct);
-#endif
+            NOTE_SKIP("EGREP");
             return BOOL_FALSE;
           }
           break;
 
         case TT_NEGREP:
           if (egrep_test (pz_curr_data, p_test) == APPLY_FIX) {
-#ifdef DEBUG
-            if (VLEVEL( VERB_EVERYTHING ))
-              fprintf (stderr, z_failed, "NEGREP", p_fixd->fix_name,
-                       pz_fname, p_fixd->test_ct - test_ct);
-#endif
+            NOTE_SKIP("NEGREP");
             /*  Negated sense  */
             return BOOL_FALSE;
           }
           break;
 
+        case TT_CKSUM:
+         if (one_sum_passed)
+           break; /*  No need to check any more  */
+
+          saw_sum_test = BOOL_TRUE;
+          if (cksum_test (pz_curr_data, p_test, pz_curr_file) != APPLY_FIX) {
+            NOTE_SKIP("CKSUM");
+          } else {
+            one_sum_passed = BOOL_TRUE;
+          }
+          break;
+
         case TT_FUNCTION:
           if (run_test (p_test->pz_test_text, pz_curr_file, pz_curr_data)
               != APPLY_FIX) {
-#ifdef DEBUG
-            if (VLEVEL( VERB_EVERYTHING ))
-              fprintf (stderr, z_failed, "FTEST", p_fixd->fix_name,
-                       pz_fname, p_fixd->test_ct - test_ct);
-#endif
+            NOTE_SKIP("FTEST");
             return BOOL_FALSE;
           }
           break;
         }
     }
 
+  if (saw_sum_test)
+    return one_sum_passed;
+
   return BOOL_TRUE;
 }
 
@@ -1197,7 +1249,10 @@ write_replacement (tFixDesc* p_fixd)
 
    {
      FILE* out_fp = create_file ();
-     fputs (pz_text, out_fp);
+     size_t sz = strlen (pz_text);
+     fwrite (pz_text, sz, 1, out_fp);
+     if (pz_text[ sz-1 ] != '\n')
+       fputc ('\n', out_fp);
      fclose (out_fp);
    }
 }
@@ -1250,7 +1305,7 @@ test_for_changes (int read_fd)
           /*  IF there are matched data, write the matched part now. */
           if ((char*)pz_cmp != pz_curr_data)
             fwrite (pz_curr_data, (size_t)((char*)pz_cmp - pz_curr_data),
-                                       1, out_fp);
+                    1, out_fp);
 
           /*  Emit the current unmatching character */
           putc (ch, out_fp);
@@ -1313,7 +1368,7 @@ process (void)
 #endif
   if (VLEVEL( VERB_PROGRESS ) && have_tty)
     fprintf (stderr, "%6lu %-50s   \r",
-            (unsigned long) data_map_size, pz_curr_file);
+             (unsigned long) data_map_size, pz_curr_file);
 
 # ifndef SEPARATE_FIX_PROC
   process_chain_head = NOPROCESS;