-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 According to Joerg Sonnenberger on 7/25/2007 7:59 AM: > OK, I'm still not fully sure I understand all parts of the problem. The > flushing happens in debug_flush_files, right? When the called programs > reads from stdin itself, is m4 supposed to see such changes?
Yes, according to the rules of POSIX. > This would > mandate an explicit after the program is executed as well. Not on a compliant system, since m4 follows the rules spelled out by POSIX: http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_05.html Section 2.5.1 deals with the interaction of file descriptors and stdio streams. The fact that m4 is creating a child that inherits m4's stdin is an example of two handles to a given fd, with two changes to the active handle. For the first change, m4 wants to hand control of the active handle to the child; it follows the last bullet of the list of requirements for the owner of the first handle: "If the stream is open with a mode that allows reading and the underlying open file description refers to a device that is capable of seeking, the application shall either perform an fflush(), or the stream shall be closed. Then the child process need do nothing special to start reading at the correct offset." [and this paragraph is yet more proof that POSIX 2001 requires fflush(stdin) to work] The second transfer of active handle occurs when the child exits and returns control to m4. Here, the child falls under the same bullet, and the act of exiting the child (or if the child does an explicit fflush) will set the offset of the fd to the next byte unread by the child. At which point m4 needs do nothing to become the active handle, and should pick up where the child left off, with no extra stdio calls required on m4's part (that is, if stdio is POSIX compliant). > What happens > if the program modifies the regular file opened for stdin? m4 has no control over a child process, and whether it will correctly position the offset of the fd if it did a partial read of a seekable stdin. But having m4 comply with POSIX when it invokes a non-POSIX child process is not a requirement (in other words, if the child fails to restore the offset of fd 0 back to the next unread byte, m4 will not see those bytes, but it is not m4's fault). However, in the case where the child process also follows rules about correctly positioning seekable stdin to the next unread byte, then the approach I took in m4 is the only way I know for m4 to also follow POSIX rules about its treatment of stdin; ie. m4 will pick up reading where the child process left off (yes, this is one of the places in Unix where the actions of a child process are observable in the environment of the parent). On a system where m4 and sed both follow POSIX rules, this is an example of the above rules (and I use this example in the testsuite for CVS head of m4 http://cvs.savannah.gnu.org/viewvc/m4/tests/others.at?revision=1.35&root=m4&view=markup; it is conditionally run after first checking whether sed also obeys POSIX rules for seekable stdin): $ cat <<\EOF >in.m4 define(`foo', `FOO')m4 foo syscmd(`sed -e "s/foo/bar/;q"')sed foo m4 foo EOF $ m4 in.m4 m4 FOO sed bar m4 FOO $ > If I > understand the implications correctly, the only correct approach would > be to disable buffering before calling the program and reenable that > afterwards. That should be portable as well. Nope. It may work on some systems, but the POSIX specification of setvbuf states that it may only safely be used prior to any I/O on the stream. It is not portable to go switching m4's copy of the stream between buffered and unbuffered, once m4 has started reading from it, and I am not about to make m4 use stdin unbuffered from the getgo. So that rules out your idea of setvbuf. - -- Don't work too hard, make some time for fun as well! Eric Blake [EMAIL PROTECTED] -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGqKDD84KuGfSFAYARAuJiAJ9NVdqK9Fblr6NfiT3AXE2ppE5rsQCgkIbl NjdMI1BMj7Hgxl7Z+MFAbG8= =mI40 -----END PGP SIGNATURE-----