public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* setmode (long)
@ 1999-02-24  0:31 E. Robert Tisdale
       [not found] ` < 36D39A03.89B3C703@netwood.net >
  1999-02-28 23:02 ` E. Robert Tisdale
  0 siblings, 2 replies; 42+ messages in thread
From: E. Robert Tisdale @ 1999-02-24  0:31 UTC (permalink / raw)
  To: cygwin

I have written an application in C++ which is supposed to compile
and run on any platform including UNIX, DOS and Windows 95/98/NT.
It reads and writes text as well as binary data from files and
standard input and output.  It uses the line feed (newline) character
to mark the end of a line and the carriage return line feed sequence
to mark the end of a paragraph.  It reads and writes text files
in binary mode and converts \r\n to \n on input and \n to \r\n
on output for DOS (and Windows 95/98/NT) systems so that the user
can read, edit and print them using native tools.

On DOS and Windows 95/98/NT systems, the C preprocessor includes code
which uses setmode to change the default I/O mode from text to binary.
This worked just fine with older versions of DJGPP on DOS
but I have just downloaded and installed the most recent versions
of DJGPP, Cygwin and mingw32 and I am experiencing some problems.
I wrote a short program, `test.cc', to help illustrate them.
----------------------------------------------------------------------

// test.cc

#include<fstream.h>
#include<io.h>
#include<fcntl.h>

int
main() {
  int   oldmode = 0;
  cout << "default mode:\n";
  cout << "  0 carriage returns\n";
  cout << "  1 carriage returns\r\n";
  cout << "  2 carriage returns\r\r\n";
  cout << "  3 carriage returns\r\r\r\n";
  oldmode = setmode(1, O_TEXT);
  cout << hex << oldmode <<
    " = setmode(1, " << hex << O_TEXT   << "):\n";
  cout << "  0 carriage returns\n";
  cout << "  1 carriage returns\r\n";
  cout << "  2 carriage returns\r\r\n";
  cout << "  3 carriage returns\r\r\r\n";
  oldmode = setmode(1, O_BINARY);
  cout << hex << oldmode <<
    " = setmode(1, " << hex << O_BINARY << "):\n";
  cout << "  0 carriage returns\n";
  cout << "  1 carriage returns\r\n";
  cout << "  2 carriage returns\r\r\n";
  cout << "  3 carriage returns\r\r\r\n";
  oldmode = setmode(1, O_TEXT);
  cout << hex << oldmode <<
    " = setmode(1, " << hex << O_TEXT   << "):\n";
  cout << "  0 carriage returns\n";
  cout << "  1 carriage returns\r\n";
  cout << "  2 carriage returns\r\r\n";
  cout << "  3 carriage returns\r\r\r\n";

  ofstream      test_out("test.out", ios::out);
  test_out << "default mode:\n";
  test_out << "  0 carriage returns\n";
  test_out << "  1 carriage returns\r\n";
  test_out << "  2 carriage returns\r\r\n";
  test_out << "  3 carriage returns\r\r\r\n";
  oldmode = setmode((test_out.rdbuf())->fd(), O_TEXT);
  test_out << hex << oldmode <<
    " = setmode((test_out.rdbuf())->fd(), " << hex << O_TEXT   << "):\n";
  test_out << "  0 carriage returns\n";
  test_out << "  1 carriage returns\r\n";
  test_out << "  2 carriage returns\r\r\n";
  test_out << "  3 carriage returns\r\r\r\n";
  oldmode = setmode((test_out.rdbuf())->fd(), O_BINARY);
  test_out << hex << oldmode <<
    " = setmode((test_out.rdbuf())->fd(), " << hex << O_BINARY << "):\n";
  test_out << "  0 carriage returns\n";
  test_out << "  1 carriage returns\r\n";
  test_out << "  2 carriage returns\r\r\n";
  test_out << "  3 carriage returns\r\r\r\n";
  oldmode = setmode((test_out.rdbuf())->fd(), O_TEXT);
  test_out << hex << oldmode <<
    " = setmode((test_out.rdbuf())->fd(), " << hex << O_TEXT   << "):\n";
  test_out << "  0 carriage returns\n";
  test_out << "  1 carriage returns\r\n";
  test_out << "  2 carriage returns\r\r\n";
  test_out << "  3 carriage returns\r\r\r\n";
  return 0;
  }
----------------------------------------------------------------------

I compiled under Windows 98 using DJGPP and a DOS shell (MS-DOS Prompt)

        >gxx -v -w -O2 -o test test.cc -lgpp

and I ran the test program

        >.\test > test.dos

I started a Cygwin-b20 bash shell and examined the results:

        $ vi test.dos
        default mode:^M
          0 carriage returns^M
          1 carriage returns^M^M
          2 carriage returns^M^M^M
          3 carriage returns^M^M^M^M
        8 = setmode(1, 8):^M
          0 carriage returns^M
          1 carriage returns^M^M
          2 carriage returns^M^M^M
          3 carriage returns^M^M^M^M
        8 = setmode(1, 4):
          0 carriage returns
          1 carriage returns^M
          2 carriage returns^M^M
          3 carriage returns^M^M^M
        4 = setmode(1, 8):^M
          0 carriage returns^M
          1 carriage returns^M^M
          2 carriage returns^M^M^M
          3 carriage returns^M^M^M^M

appears to be correct but

        $ vi test.out
        default mode:
          0 carriage returns
          1 carriage returns^M
          2 carriage returns^M^M
          3 carriage returns^M^M^M
        8 = setmode((test_out.rdbuf())->fd(), 8):
          0 carriage returns
          1 carriage returns^M
          2 carriage returns^M^M
          3 carriage returns^M^M^M
        8 = setmode((test_out.rdbuf())->fd(), 4):
          0 carriage returns
          1 carriage returns^M
          2 carriage returns^M^M
          3 carriage returns^M^M^M
        4 = setmode((test_out.rdbuf())->fd(), 8):
          0 carriage returns
          1 carriage returns^M
          2 carriage returns^M^M
          3 carriage returns^M^M^M

shows that test.out was opened in binary mode
and setmode didn't switch to text mode.

----------------------------------------------------------------------

I compiled under Windows 98 using EGCS Cygwin-b20 and a bash shell

        $ g++ -v -Wall -O2 -o test test.cc

ran the test program

        $ ./test > test.cyg

and examined the results:

        $ vi test.cyg
        default mode:^M
          0 carriage returns^M
          1 carriage returns^M^M
          2 carriage returns^M^M^M
          3 carriage returns^M^M^M^M
        20000 = setmode(1, 20000):^M
          0 carriage returns^M
          1 carriage returns^M^M
          2 carriage returns^M^M^M
          3 carriage returns^M^M^M^M
        20000 = setmode(1, 10000):
          0 carriage returns
          1 carriage returns^M
          2 carriage returns^M^M
          3 carriage returns^M^M^M
        10000 = setmode(1, 20000):^M
          0 carriage returns^M
          1 carriage returns^M^M
          2 carriage returns^M^M^M
          3 carriage returns^M^M^M^M

appears to be correct but

        $ vi test.out
        default mode:
          0 carriage returns
          1 carriage returns^M
          2 carriage returns^M^M
          3 carriage returns^M^M^M
        20000 = setmode((test_out.rdbuf())->fd(), 20000):
          0 carriage returns
          1 carriage returns^M
          2 carriage returns^M^M
          3 carriage returns^M^M^M
        20000 = setmode((test_out.rdbuf())->fd(), 10000):
          0 carriage returns
          1 carriage returns^M
          2 carriage returns^M^M
          3 carriage returns^M^M^M
        10000 = setmode((test_out.rdbuf())->fd(), 20000):
          0 carriage returns
          1 carriage returns^M
          2 carriage returns^M^M
          3 carriage returns^M^M^M

shows that test.out was opened in binary mode
and setmode didn't switch to text mode.

----------------------------------------------------------------------

I re-compiled under Windows 98 using EGCS Cygwin-b20 with mingw32

        $ g++ -L/mingw32/lib -L/mingw32/i386-mingw32/lib \
        -L/mingw32/lib/gcc-lib/i386-mingw32/egcs-2.91.60 \
        -v -Wall -O2 -mno-cygwin -o test test.cc -lstdc++ -liberty

and ran the test program using and a DOS shell (MS-DOS Prompt)

        >.\test > test.win

I used the Cygwin-b20 bash shell to examine the results:

        $ vi test.win
        default mode:
          0 carriage returns
          1 carriage returns
          2 carriage returns
          3 carriage returns
        4000 = setmode(1, 4000):
          0 carriage returns
          1 carriage returns
          2 carriage returns
          3 carriage returns
        4000 = setmode(1, 8000):
          0 carriage returns
          1 carriage returns
          2 carriage returns
          3 carriage returns
        8000 = setmode(1, 4000):
          0 carriage returns
          1 carriage returns
          2 carriage returns
          3 carriage returns

contains no carriage returns and

       $ vi test.out
        default mode:
          0 carriage returns
          1 carriage returns^M
          2 carriage returns^M^M
          3 carriage returns^M^M^M
        4000 = setmode((test_out.rdbuf())->fd(), 4000):
          0 carriage returns
          1 carriage returns^M
          2 carriage returns^M^M
          3 carriage returns^M^M^M
        4000 = setmode((test_out.rdbuf())->fd(), 8000):
          0 carriage returns
          1 carriage returns^M
          2 carriage returns^M^M
          3 carriage returns^M^M^M
        8000 = setmode((test_out.rdbuf())->fd(), 4000):
          0 carriage returns
          1 carriage returns^M
          2 carriage returns^M^M
          3 carriage returns^M^M^M

shows that test.out was opened in binary mode
and setmode didn't switch to text mode.

----------------------------------------------------------------------

I didn't change any of the default settings when I installed Cygwin.
I didn't mount any file systems as binary only or define binmode.
I've read the FAQs and searched the mailing list archives.

It appears to me that there are still very serious problems
with text and binary I/O in DJGPP, Cygwin-b20 and mingw32
using Cygwin-b20 bash and MS-DOS Prompt under Windows 98.

Also, all the information regarding text and binary I/O
seems to be scattered across many different documents.
I think it would help me and other portable application
programmers if someone could put it all together
in one place with expicit references to the specific
operating system, compiler and shell to which it applies.

Thanks in advance, E. Robert Tisdale <edwin@netwood.net>

NOTE:   My editor, `vi', displays a carriage return as ^M
        but the line feed at the end of the line is invisible.
        My DOS shell is C:\WINDOWS\COMMAND.COM



--
Want to unsubscribe from this list?
Send a message to cygwin-unsubscribe@sourceware.cygnus.com

^ permalink raw reply	[flat|nested] 42+ messages in thread
[parent not found: <3.0.5.32.19990225144311.0084fc50@pop.ne.mediaone.net>]
* RE: setmode (long)
@ 1999-02-26  2:47 Bernard Dautrevaux
  1999-02-28 23:02 ` Bernard Dautrevaux
  1999-03-03 19:19 ` E. Robert Tisdale
  0 siblings, 2 replies; 42+ messages in thread
From: Bernard Dautrevaux @ 1999-02-26  2:47 UTC (permalink / raw)
  To: 'E. Robert Tisdale', cygwin

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 3063 bytes --]

> -----Original Message-----
> From: E. Robert Tisdale [ mailto:edwin@netwood.net ]
> Sent: Friday, February 26, 1999 7:27 AM
> To: cygwin@sourceware.cygnus.com
> Subject: Re: setmode (long)
> 
> 
> Mumit Khan wrote:
> 
> > I believe Pierre has something here.
> > I took another look at your code,
> > and you're changing the mode of a buffered stream!
> > Could you flush the stream (stream << flush)
> > before changing the mode and see what happens?
> 
> No, I can't just now.
> I sent the computer with Windows 98
> and the DJPP and Cygnus compilers to my brother-in-law.
> You'll have to wait until I can fire up my old Windows 95.
> 
> > I don't believe that your code is well-defined,
> > since changing anything for an underlying descriptor
> > of a buffered stream without flushing
> > is not guaranteed to produce the desired effect.
> 
> Can you tell me where I can get documentation
> for this behavior in setmode?
> I got the file descriptors for standard I/O from
> 
> 0 == (cin.rdbuf())->_fileno
> 1 == (cout.rdbuf())->_fileno
> 2 == (cerr.rdbuf())->_fileno
> 
> because a
> ostdiostream has a
> stdiobuf which is a
> filebuf which is a
> streambuf which is a
> _IO_FILE which has an
> int _fileno.
> 
> Is there a portable way to get file descriptors
> for cin, cout, cerr and clog?
> 
> I suspect that Pierre may indeed have part of the answer
> for his Windows 95 OS and his Emacs shell
> but it doesn't explain why my `test.out' files
> appear to be written in binary mode
> even when the last mode set is text mode.
> 

This has in fact nothing to do with win95/98/...; it's a conceptual
problem. You should *never* twiddle the underlying file descriptor when
using *any* kind of buffered stream! The problem is that the buffered
stream is optimizing out a lot of the calls to the underlying file
descriptor. It may even happen that the buffered stream cache some of
the characteristics of the underlying file descriptor to optimize
performance in its own handling of data :-)

You *may* try to use fflush() before, but you have the same problem with
the iostream, so you may have to flush them. But note that flush only
guarantee that you flush the output buffer of the stream, not that you
flush any internal cache.

Well behaved buffered streams (I don't know for those you use) should
have an fsetmode() (for stdio) or stream::setmode() (for iosteams) call
that do the setmode in the proper way so that you get the expected
result. *Any* other attempt to hack on th efile descriptor of an opened
buffered stream is *guaranteed* to be opened to subtle misbehaviours,
and (for once :-) Micro$oft is not responsible here...

HTH

		Bernard

--------------------------------------------
Bernard Dautrevaux
Microprocess Ingéniérie
97 bis, rue de Colombes
92400 COURBEVOIE
FRANCE
Tel:	+33 (0) 1 47 68 80 80
Fax:	+33 (0) 1 47 88 97 85
e-mail:	dautrevaux@microprocess.com
		b.dautrevaux@usa.net
-------------------------------------------- 

--
Want to unsubscribe from this list?
Send a message to cygwin-unsubscribe@sourceware.cygnus.com

^ permalink raw reply	[flat|nested] 42+ messages in thread

end of thread, other threads:[~1999-03-31 19:45 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-02-24  0:31 setmode (long) E. Robert Tisdale
     [not found] ` < 36D39A03.89B3C703@netwood.net >
1999-02-24 11:42   ` Christopher Faylor
1999-02-25  1:26     ` E. Robert Tisdale
     [not found]       ` < 36D51691.6E1579DF@netwood.net >
1999-02-25  3:51         ` ... is not writable by you Sebastien Barre
     [not found]           ` < 4.1.19990225124802.02724850@mail.club-internet.fr >
1999-02-25  7:21             ` Dennis Newbold
     [not found]               ` < Pine.LNX.3.96.990225083630.12938A-100000@blackberry.ivs.com >
1999-02-25  9:41                 ` Sebastien Barre
1999-02-25 11:14                   ` John Fortin
     [not found]                     ` < 36D59F7D.81FA327@ibm.net >
1999-02-25 16:33                       ` Sebastien Barre
1999-02-28 23:02                         ` Sebastien Barre
1999-02-28 23:02                     ` John Fortin
1999-02-28 23:02                   ` Sebastien Barre
1999-02-28 23:02               ` Dennis Newbold
1999-02-28 23:02           ` Sebastien Barre
1999-02-25  8:02         ` setmode (long) DJ Delorie
1999-02-25 22:44           ` E. Robert Tisdale
1999-02-28 23:02             ` E. Robert Tisdale
1999-02-28 23:02           ` DJ Delorie
1999-02-25  9:25         ` Mumit Khan
1999-02-28 23:02           ` Mumit Khan
1999-02-28 23:02       ` E. Robert Tisdale
1999-03-02 18:59       ` Christopher Faylor
1999-03-03 19:29         ` E. Robert Tisdale
     [not found]           ` < 36DDFD4C.B4B6F7C4@netwood.net >
1999-03-04  8:17             ` Chris Faylor
1999-03-31 19:45               ` Chris Faylor
1999-03-31 19:45           ` E. Robert Tisdale
1999-03-31 19:45         ` Christopher Faylor
1999-02-28 23:02     ` Christopher Faylor
1999-02-28 23:02 ` E. Robert Tisdale
     [not found] <3.0.5.32.19990225144311.0084fc50@pop.ne.mediaone.net>
1999-02-25 12:12 ` E. Robert Tisdale
     [not found]   ` < 36D5ADF0.C5FC769@netwood.net >
1999-02-25 18:48     ` Pierre A. Humblet
     [not found]       ` < 3.0.5.32.19990225215015.00857270@pop.ne.mediaone.net >
1999-02-25 18:57         ` Mumit Khan
1999-02-25 22:29           ` E. Robert Tisdale
1999-02-28 23:02             ` E. Robert Tisdale
1999-02-28 23:02           ` Mumit Khan
1999-02-28 23:02       ` Pierre A. Humblet
1999-02-28 23:02   ` E. Robert Tisdale
     [not found] ` <3.0.5.32.19990225152844.008374c0@pop.ne.mediaone.net>
1999-02-25 21:56   ` E. Robert Tisdale
1999-02-28 23:02     ` E. Robert Tisdale
1999-02-26  2:47 Bernard Dautrevaux
1999-02-28 23:02 ` Bernard Dautrevaux
1999-03-03 19:19 ` E. Robert Tisdale
1999-03-31 19:45   ` E. Robert Tisdale

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).