pngfix: ensure fclose happens last on file close

This reverts the code to a variant of my old style of doing an 'fclose'
correctly and adds comments explaining why it is so difficult.  Thanks
to @ihsinme for pointing out the error on github.com

Signed-off-by: John Bowler <jbowler@acm.org>
diff --git a/contrib/tools/pngfix.c b/contrib/tools/pngfix.c
index cdf3f1c..0dd0dbb 100644
--- a/contrib/tools/pngfix.c
+++ b/contrib/tools/pngfix.c
@@ -1005,10 +1005,18 @@
 
    if (file->out != NULL)
    {
-      /* NOTE: this is bitwise |, all the following functions must execute and
-       * must succeed.
+      /* On some systems 'fclose' deletes the FILE struct (making it
+       * inaccessbile).  There is no guarantee that fclose returns an error
+       * code from fflush or, indeed, from the FILE error indicator.  There is
+       * also no explicit (or clear) guarantee in the standard that anything
+       * other than a read or write operation sets the error indicator; fflush
+       * is not a read or write operation, so both conditions must be checked
+       * to ensure the close succeeded and in ANSI-C conformant code they must
+       * be checked before the fclose call.
        */
-      if (ferror(file->out) | fflush(file->out) | fclose(file->out))
+      const int err = fflush(file->out) || ferror(file->out);
+
+      if (fclose(file->out) || err)
       {
          perror(file->out_name);
          emit_error(file, READ_ERROR_CODE, "output write error");
@@ -4054,3 +4062,4 @@
    return 77;
 }
 #endif /* PNG_SETJMP_SUPPORTED */
+/* vi: set textwidth=80 shiftwidth=3 softtabstop=-1 expandtab: */