In the latest patch, those three gotos confused me. Part of the confusion is due to uses like 'if (fflush (fp))' which are of course valid but which I find a bit hard to read at first. Also, the comment's "contents is" is not quite grammatical, and the comment is a bit overconfident about getting the "same errno".
How about this (untested) patch to make the code a bit more readable? 2006-04-24 Paul Eggert <[EMAIL PROTECTED]> * fwriteerror.c (fwriteerror): Rewrite to avoid gotos. *** fwriteerror.c Mon Apr 24 10:32:45 2006 --- /tmp/fwriteerror.c Mon Apr 24 11:15:01 2006 *************** fwriteerror (FILE *fp) *** 46,72 **** if (ferror (fp)) { - if (fflush (fp)) - goto close_preserving_errno; /* errno is set here */ /* The stream had an error earlier, but its errno was lost. If the ! error was not temporary, we can get the same errno by writing and flushing one more byte. We can do so because at this point the ! stream's contents is garbage anyway. */ ! if (fputc ('\0', fp) == EOF) ! goto close_preserving_errno; /* errno is set here */ ! if (fflush (fp)) ! goto close_preserving_errno; /* errno is set here */ ! /* Give up on errno. */ ! errno = 0; ! close_preserving_errno: ! /* There's an error. Nevertheless call fclose(fp), for consistency ! with the other cases. */ ! { ! int saved_errno = errno; ! fclose (fp); ! errno = saved_errno; ! return -1; ! } } /* If we are closing stdout, don't attempt to do it later again. */ --- 46,65 ---- if (ferror (fp)) { /* The stream had an error earlier, but its errno was lost. If the ! error was not temporary, we can usually get a useful errno by ! flushing the file, or, if that doesn't work, by writing and flushing one more byte. We can do so because at this point the ! stream contains garbage anyway. */ ! int saved_errno = ! (fflush (fp) != 0 || fputc ('\0', fp) == EOF || fflush (fp) != 0 ! ? errno ! : 0); ! ! /* Close the file, for consistency with the other cases. */ ! fclose (fp); ! errno = saved_errno; ! return -1; } /* If we are closing stdout, don't attempt to do it later again. */