[m-rev.] .NET I/O rewrite
Fergus Henderson
fjh at cs.mu.OZ.AU
Sat Oct 19 23:55:34 AEST 2002
Estimated hours taken: 6
Branches: main
library/io.m:
Rewrite most of the .NET I/O routines.
The previous version didn't work.
This required splitting some of the higher-level routines such as
io__do_open and io__read_char_code into two versions, one for text
and one for binary.
Workspace: /c/fjh/ws/2/mercury
Index: library/io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/io.m,v
retrieving revision 1.268
diff -u -d -r1.268 io.m
--- library/io.m 18 Oct 2002 13:32:43 -0000 1.268
+++ library/io.m 19 Oct 2002 13:49:11 -0000
@@ -1307,14 +1307,31 @@
").
:- pragma foreign_code("MC++", "
+ // The ML_ prefixes here are not really needed,
+ // since the MC++ code all gets generated inside a class,
+ // but we keep them for consistency with the C code.
+
#ifdef MR_HIGHLEVEL_DATA
- static mercury::tree234::tree234_2 __gc *ML_io_stream_names;
+ typedef mercury::tree234::tree234_2 __gc *ML_Map;
#else
- static MR_Word ML_io_stream_names;
+ typedef MR_Word ML_Map;
#endif
+
+ static ML_Map ML_io_stream_names;
static MR_Univ ML_io_user_globals;
- static int next_id;
- static System::Text::ASCIIEncoding *ascii_encoder;
+
+ // a counter used to generate unique stream ids
+ static int ML_next_stream_id;
+
+ // This specifies the default encoding used for text files.
+ // It must be either ML_OS_text_encoding or ML_Unix_text_encoding.
+ //
+ // XXX The initial setting for this should be controlled
+ // by an environment variable. (This might require moving
+ // the code which initializes mercury_stdin, etc.)
+ //
+ static ML_file_encoding_kind ML_default_text_encoding =
+ ML_OS_text_encoding;
").
@@ -1351,7 +1368,18 @@
:- pred io__read_char_code(io__input_stream, int, io__state, io__state).
:- mode io__read_char_code(in, out, di, uo) is det.
-% Reads a character code from specified stream.
+% Reads a character from specified stream,
+% and returns the numerical value for that character
+% (as from char__to_int).
+% This may involve converting external character encodings
+% into Mercury's internal character repesentation
+% and (for text streams) converting OS line indicators,
+% e.g. CR-LF for Windows, to '\n' characters.
+% Returns -1 if at EOF, -2 if an error occurs.
+
+:- pred io__read_byte_val(io__input_stream, int, io__state, io__state).
+:- mode io__read_byte_val(in, out, di, uo) is det.
+% Reads a byte from specified stream.
% Returns -1 if at EOF, -2 if an error occurs.
:- pred io__call_system_code(string, int, string, io__state, io__state).
@@ -1362,11 +1390,16 @@
% Otherwise returns the raw exit status from the system()
% call.
-:- pred io__do_open(string, string, int, io__input_stream,
+:- pred io__do_open_binary(string, string, int, io__input_stream,
io__state, io__state).
-:- mode io__do_open(in, in, out, out, di, uo) is det.
-% io__do_open(File, Mode, ResultCode, Stream, IO0, IO1).
+:- mode io__do_open_binary(in, in, out, out, di, uo) is det.
+:- pred io__do_open_text(string, string, int, io__input_stream,
+ io__state, io__state).
+:- mode io__do_open_text(in, in, out, out, di, uo) is det.
+% io__do_open_binary(File, Mode, ResultCode, Stream, IO0, IO1):
+% io__do_open_text(File, Mode, ResultCode, Stream, IO0, IO1):
% Attempts to open a file in the specified mode.
+% The Mode is a string suitable for passing to fopen().
% Result is 0 for success, -1 for failure.
:- semipure pred io__getenv(string, string).
@@ -1418,7 +1451,7 @@
io__read_byte(Stream, Result).
io__read_byte(Stream, Result) -->
- io__read_char_code(Stream, Code),
+ io__read_byte_val(Stream, Code),
(
{ Code >= 0 }
->
@@ -1921,10 +1954,10 @@
"{
MR_MercuryFile mf = ML_DownCast(MR_MercuryFile,
MR_word_to_c_pointer(Stream));
- if (mf->stream->get_CanSeek()) {
- Size = mf->stream->get_Length();
+ if (mf->stream->CanSeek) {
+ Size = mf->stream->Length;
} else {
- Size = -1;
+ Size = -1;
}
MR_update_io(IO0, IO);
}").
@@ -2787,7 +2820,7 @@
% stream predicates
io__open_input(FileName, Result) -->
- io__do_open(FileName, "r", Result0, NewStream),
+ io__do_open_text(FileName, "r", Result0, NewStream),
( { Result0 \= -1 } ->
{ Result = ok(NewStream) },
io__insert_stream_name(NewStream, FileName)
@@ -2797,7 +2830,7 @@
).
io__open_output(FileName, Result) -->
- io__do_open(FileName, "w", Result0, NewStream),
+ io__do_open_text(FileName, "w", Result0, NewStream),
( { Result0 \= -1 } ->
{ Result = ok(NewStream) },
io__insert_stream_name(NewStream, FileName)
@@ -2807,7 +2840,7 @@
).
io__open_append(FileName, Result) -->
- io__do_open(FileName, "a", Result0, NewStream),
+ io__do_open_text(FileName, "a", Result0, NewStream),
( { Result0 \= -1 } ->
{ Result = ok(NewStream) },
io__insert_stream_name(NewStream, FileName)
@@ -2817,7 +2850,7 @@
).
io__open_binary_input(FileName, Result) -->
- io__do_open(FileName, "rb", Result0, NewStream),
+ io__do_open_binary(FileName, "rb", Result0, NewStream),
( { Result0 \= -1 } ->
{ Result = ok(NewStream) },
io__insert_stream_name(NewStream, FileName)
@@ -2827,7 +2860,7 @@
).
io__open_binary_output(FileName, Result) -->
- io__do_open(FileName, "wb", Result0, NewStream),
+ io__do_open_binary(FileName, "wb", Result0, NewStream),
( { Result0 \= -1 } ->
{ Result = ok(NewStream) },
io__insert_stream_name(NewStream, FileName)
@@ -2837,7 +2870,7 @@
).
io__open_binary_append(FileName, Result) -->
- io__do_open(FileName, "ab", Result0, NewStream),
+ io__do_open_binary(FileName, "ab", Result0, NewStream),
( { Result0 \= -1 } ->
{ Result = ok(NewStream) },
io__insert_stream_name(NewStream, FileName)
@@ -3240,7 +3273,6 @@
io__gc_init(_StreamNamesType::in, _UserGlobalsType::in,
IO0::di, IO::uo), [will_not_call_mercury, promise_pure], "
MR_update_io(IO0, IO);
- ascii_encoder = new System::Text::ASCIIEncoding();
").
io__gc_init(_, _) --> [].
@@ -3381,39 +3413,54 @@
:- pragma foreign_decl("MC++", "
- // XXX currently we only handle text streams.
-
namespace mercury {
-namespace io__cpp_code {
-__gc struct MR_MercuryFileStruct {
-public:
- // Note that stream reader and writer might be null, if they are
- // currently unused.
+ namespace io__cpp_code {
+ __value enum ML_file_encoding_kind {
+ ML_OS_text_encoding, // file stores characters,
+ // using the operating system's
+ // default encoding, and OS's
+ // usual line-ending convention
+ // (e.g. CR-LF for DOS/Windows).
+
+ ML_Unix_text_encoding, // file stores characters,
+ // using the operating system's
+ // default encoding, but with the
+ // Unix line-ending convention.
+
+ ML_raw_binary // file stores bytes
+ };
+
+ __gc struct MR_MercuryFileStruct {
+ public:
+ // Note that stream reader and writer are initialized lazily;
+ // that is, if the stream has not yet been used for reading,
+ // the `reader' field may be null. Any code which accesses that
+ // field must check for null and initialize it if needed.
+ // Likewise for the `writer' field.
System::IO::Stream *stream; // The stream itself
System::IO::TextReader *reader; // A stream reader for reading it
System::IO::TextWriter *writer; // A stream writer for writing it
- int line_number;
- int id;
-
-};
+ ML_file_encoding_kind file_encoding; // DOS, Unix, or raw binary
+ int line_number;
+ int id;
-typedef __gc struct MR_MercuryFileStruct *MR_MercuryFile;
+ };
-}
+ typedef __gc struct MR_MercuryFileStruct *MR_MercuryFile;
+ }
}
// These macros aren't very safe -- they don't enforce
- // safe casts in anyway. Make sure you use them for good
- // and not evil.
+ // safe casts in any way. The point of using them is
+ // just to express the programmer's intent.
+ // Make sure you use them for good and not evil.
#define ML_DownCast(Cast, Expr) dynamic_cast<Cast>(Expr)
#define ML_UpCast(Cast, Expr) ((Cast) (Expr))
#define MR_initial_io_state() 0 /* some random number */
#define MR_update_io(r_src, r_dest) (0)
#define MR_final_io_state(r)
-
-
").
:- pragma foreign_code("C", "
@@ -3467,46 +3514,43 @@
:- pragma foreign_code("MC++", "
-static MR_MercuryFile new_mercury_file(System::IO::Stream *stream,
- int line_number) {
- MR_MercuryFile mf = new MR_MercuryFileStruct();
- mf->stream = stream;
- mf->reader = NULL;
- mf->writer = NULL;
- mf->line_number = line_number;
- mf->id = next_id++;
- return mf;
-}
-
-static MR_MercuryFile new_open_mercury_file(System::IO::Stream *stream,
+static MR_MercuryFile
+mercury_file_init(System::IO::Stream *stream,
System::IO::TextReader *reader, System::IO::TextWriter *writer,
- int line_number) {
+ ML_file_encoding_kind file_encoding)
+{
MR_MercuryFile mf = new MR_MercuryFileStruct();
mf->stream = stream;
mf->reader = reader;
mf->writer = writer;
- mf->line_number = line_number;
- mf->id = next_id++;
+ mf->file_encoding = file_encoding;
+ mf->line_number = 1;
+ mf->id = ML_next_stream_id++;
return mf;
}
- // XXX this will cause problems with GUI programs that have no
- // consoles.
+ // Note: for Windows GUI programs, the Console is set to the
+ // equivalent of /dev/null. This could perhaps be considered a
+ // problem. But if so, it is a problem in Windows, not in Mercury --
+ // I don't think it is one that the Mercury implementation should
+ // try to solve.
static MR_MercuryFile mercury_stdin =
- new_open_mercury_file(System::Console::OpenStandardInput(),
- System::Console::In, NULL, 1);
+ mercury_file_init(System::Console::OpenStandardInput(),
+ System::Console::In, NULL, ML_default_text_encoding);
static MR_MercuryFile mercury_stdout =
- new_open_mercury_file(System::Console::OpenStandardOutput(),
- NULL, System::Console::Out, 1);
+ mercury_file_init(System::Console::OpenStandardOutput(),
+ NULL, System::Console::Out, ML_default_text_encoding);
static MR_MercuryFile mercury_stderr =
- new_open_mercury_file(System::Console::OpenStandardError(),
- NULL, System::Console::Error, 1);
+ mercury_file_init(System::Console::OpenStandardError(),
+ NULL, System::Console::Error, ML_default_text_encoding);
static MR_MercuryFile mercury_stdin_binary =
- new_mercury_file(0, 1);
+ mercury_file_init(System::Console::OpenStandardInput(),
+ System::Console::In, NULL, ML_raw_binary);
static MR_MercuryFile mercury_stdout_binary =
- new_mercury_file(0, 1);
+ mercury_file_init(System::Console::OpenStandardOutput(),
+ NULL, System::Console::Out, ML_raw_binary);
static MR_MercuryFile mercury_current_text_input = mercury_stdin;
static MR_MercuryFile mercury_current_text_output = mercury_stdout;
@@ -3538,7 +3582,8 @@
:- pragma foreign_code("MC++", "
MR_MercuryFile
-static mercury_open(MR_String filename, MR_String openmode)
+static mercury_open(MR_String filename, MR_String openmode,
+ ML_file_encoding_kind file_encoding)
{
MR_MercuryFile mf = new MR_MercuryFileStruct();
System::IO::FileMode fa;
@@ -3576,7 +3621,9 @@
if (!stream) {
return 0;
} else {
- mf = new_mercury_file(stream, 1);
+ // we initialize the `reader' and `writer' fields to null;
+ // they will be filled in later if they are needed.
+ mf = mercury_file_init(stream, NULL, NULL, file_encoding);
return mf;
}
}
@@ -3645,18 +3692,66 @@
:- pragma foreign_code("MC++", "
+// Any changes here should also be reflected in the code for
+// io__write_char, which (for efficiency) uses its own inline
+// code, rather than calling this function.
static void
mercury_print_string(MR_MercuryFile mf, MR_String s)
{
- unsigned char ByteArray __gc[] = ascii_encoder->GetBytes(s);
- mf->stream->Write(ByteArray, 0, ByteArray->get_Length());
- mf->stream->Flush();
+ //
+ // For the .NET back-end, strings are represented as Unicode.
+ // Text output streams (which may be connected to text files,
+ // or to the console) require a byte stream.
+ // This raises the question: how should we
+ // convert from Unicode to the byte sequence?
+ //
+ // We leave this up to the system, by just using the TextWriter
+ // associated with the file. For the console, this will be
+ // System.Console.Out, which will use whatever encoding
+ // is appropriate for the console. For a file, the TextWriter
+ // will use the System.Encoding.Default encoding, which
+ // will normally be an 8-bit national character set.
+ // If the Unicode string contains characters which can't be
+ // represented in this set, then the encoder will throw an exception.
+ //
+ // For files, we construct the TextWriter here, rather than at file
+ // open time, so that we don't try to construct TextWriters for
+ // input streams.
- for (int i = 0; i < s->Length; i++) {
- if (s->Chars[i] == '\\n') {
- mf->line_number++;
- }
- }
+ if (mf->writer == NULL) {
+ mf->writer = new System::IO::StreamWriter(mf->stream,
+ System::Text::Encoding::Default);
+
+ }
+
+ switch (mf->file_encoding) {
+ case ML_raw_binary:
+ case ML_Unix_text_encoding:
+ mf->writer->Write(s);
+ for (int i = 0; i < s->Length; i++) {
+ if (s->Chars[i] == '\\n') {
+ mf->line_number++;
+ }
+ }
+ break;
+ case ML_OS_text_encoding:
+ //
+ // We can't just use the System.TextWriter.Write(String)
+ // method, since that method doesn't convert newline
+ // characters to the system's newline convention
+ // (e.g. CR-LF on Windows).
+ // Only the WriteLine(...) method handles those properly.
+ // So we have to output each character separately.
+ //
+ for (int i = 0; i < s->Length; i++) {
+ if (s->Chars[i] == '\\n') {
+ mf->line_number++;
+ mf->writer->WriteLine("""");
+ } else {
+ mf->writer->Write(s->Chars[i]);
+ }
+ }
+ }
}
").
@@ -3693,23 +3788,114 @@
static void
mercury_print_binary_string(MR_MercuryFile mf, MR_String s)
{
- // XXX we should re-use the same stream writer...
- System::IO::StreamWriter *w = new System::IO::StreamWriter(mf->stream);
- w->Write(s);
- w->Flush();
+ // sanity check
+ if (mf->file_encoding != ML_raw_binary) {
+ mercury::runtime::Errors::fatal_error(
+ ""mercury_print_binary_string: ""
+ ""file encoding is not raw binary"");
+ }
+
+ //
+ // For the .NET back-end, strings are represented as Unicode.
+ // Binary files are stored as byte sequences. This raises the
+ // question: how should we convert from Unicode to the byte sequence?
+ //
+ // If the string that we are writing is a genuine character string,
+ // then probably the best thing to do is the same thing that we do
+ // for mercury_print_string(): do the conversion using
+ // the System.Encoding.Default encoding, which is the encoding
+ // corresponding to the system's code page (character set), which
+ // will normally be an 8-bit national character set. If the Unicode
+ // string contains characters which can't be represented in this set,
+ // then the encoder will throw an exception.
+ //
+ // On the other hand, if the string contains binary values which
+ // are supposed to be used only for their binary value -- which may
+ // be the case if it was constructed using characters which have
+ // been obtained using `enum__from_int' (i.e. the reverse mode of
+ // `char__to_int'), then probably it would be better to just
+ // take the lower 8 bits of the Unicode values, and throw an
+ // exception if any of the other bits are set.
+ //
+ // The documentation for io__write_bytes doesn't make it clear
+ // which of these is the case. It says ``the bytes are taken
+ // from a string'', but it doesn't say how. I will assume
+ // that it means the bottom 8 bits of the Unicode value,
+ // just like io__write_byte takes the byte from the bottom 8 bits
+ // of the int value.
+
+#if 0
+ unsigned char byte_array __gc[] =
+ System::Text::Encoding::Default()->GetBytes(s);
+#else
+ int len = s->Length;
+ unsigned char byte_array __gc[] = new unsigned char __gc[len];
+ for (int i = 0; i < len; i++) {
+ byte_array[i] = s->get_Chars(i);
+ if (byte_array[i] != s->get_Chars(i)) {
+ mercury::runtime::Errors::SORRY(
+ ""write_bytes: Unicode char does not fit in a byte"");
+ }
+ }
+#endif
+ mf->stream->Write(byte_array, 0, byte_array->Length);
}
").
:- pragma foreign_code("MC++", "
+// Read in a character.
+// This means reading in one or more bytes,
+// converting the bytes from the system's default encoding to Unicode,
+// and possibly converting CR-LF to newline.
+// Returns -1 on error or EOF.
static int
mercury_getc(MR_MercuryFile mf)
{
- int c = mf->stream->ReadByte();
- if (c == '\\n') {
- mf->line_number++;
- }
+ int c;
+
+ if (mf->reader == NULL) {
+ mf->reader = new System::IO::StreamReader(mf->stream,
+ System::Text::Encoding::Default);
+ }
+
+ c = mf->reader->Read();
+ switch (mf->file_encoding) {
+ case ML_raw_binary:
+ case ML_Unix_text_encoding:
+ if (c == '\\n') {
+ mf->line_number++;
+ }
+ break;
+ case ML_OS_text_encoding:
+ // First, check if the character we've read matches
+ // System::Environment::NewLine.
+ // We assume that System::Environment::NewLine is non-null
+ // and that System::Environment::NewLine->Length > 0.
+ if (c == System::Environment::NewLine->get_Chars(0)) {
+ switch (System::Environment::NewLine->Length) {
+ case 1:
+ mf->line_number++;
+ c = '\\n';
+ case 2:
+ if (mf->reader->Peek() == System::
+ Environment::NewLine->get_Chars(1))
+ {
+ (void) mf->reader->Read();
+ mf->line_number++;
+ c = '\\n';
+ }
+ break;
+ default:
+ mercury::runtime::Errors::SORRY(
+ ""mercury_getc: ""
+ ""Environment::NewLine::Length ""
+ ""is neither 1 nor 2"");
+ }
+ }
+ break;
+ }
return c;
}
@@ -3935,6 +4121,14 @@
").
:- pragma foreign_proc("C",
+ io__read_byte_val(File::in, ByteVal::out, IO0::di, IO::uo),
+ [will_not_call_mercury, promise_pure, tabled_for_io],
+"
+ ByteVal = mercury_getc((MercuryFile *) File);
+ MR_update_io(IO0, IO);
+").
+
+:- pragma foreign_proc("C",
io__putback_char(File::in, Character::in, IO0::di, IO::uo),
[may_call_mercury, promise_pure, tabled_for_io],
"{
@@ -3971,8 +4165,18 @@
").
:- pragma foreign_proc("MC++",
+ io__read_byte_val(File::in, ByteVal::out, IO0::di, IO::uo),
+ [will_not_call_mercury, promise_pure], "
+ MR_MercuryFile mf = ML_DownCast(MR_MercuryFile,
+ MR_word_to_c_pointer(File));
+ ByteVal = mf->stream->ReadByte();
+ MR_update_io(IO0, IO);
+").
+
+:- pragma foreign_proc("MC++",
io__putback_char(File::in, Character::in, IO0::di, IO::uo),
[may_call_mercury, promise_pure], "{
+ // XXX This is wrong; it doesn't handle CR-LF properly.
MR_MercuryFile mf = ML_DownCast(MR_MercuryFile,
MR_word_to_c_pointer(File));
@@ -3986,7 +4190,6 @@
:- pragma foreign_proc("MC++",
io__putback_byte(File::in, _Character::in, IO0::di, IO::uo),
[may_call_mercury, promise_pure], "{
-
MR_MercuryFile mf = ML_DownCast(MR_MercuryFile,
MR_word_to_c_pointer(File));
mf->stream->Seek(-1, System::IO::SeekOrigin::Current);
@@ -3998,6 +4201,11 @@
% matching foreign_proc version.
{ private_builtin__sorry("io__read_char_code") }.
+io__read_byte_val(_, _) -->
+ % This version is only used for back-ends for which there is no
+ % matching foreign_proc version.
+ { private_builtin__sorry("io__read_byte_val") }.
+
io__putback_char(_, _) -->
% This version is only used for back-ends for which there is no
% matching foreign_proc version.
@@ -4104,12 +4312,27 @@
io__write_char(Character::in, IO0::di, IO::uo),
[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
"
- System::IO::StreamWriter *w = new System::IO::StreamWriter(
- mercury_current_text_output->stream);
- w->Write(Character);
- w->Flush();
+ /* See mercury_output_string() for comments */
+ if (mercury_current_text_output->writer == NULL) {
+ mercury_current_text_output->writer =
+ new System::IO::StreamWriter(
+ mercury_current_text_output->stream,
+ System::Text::Encoding::Default);
+ }
+ System::IO::TextWriter *w = mercury_current_text_output->writer;
if (Character == '\\n') {
+ switch (mercury_current_text_output->file_encoding) {
+ case ML_raw_binary:
+ case ML_Unix_text_encoding:
+ w->Write(Character);
+ break;
+ case ML_OS_text_encoding:
+ w->WriteLine("""");
+ break;
+ }
mercury_current_text_output->line_number++;
+ } else {
+ w->Write(Character);
}
MR_update_io(IO0, IO);
").
@@ -4131,15 +4354,11 @@
").
:- pragma foreign_proc("MC++",
- io__write_byte(Byte::in, _IO0::di, _IO::uo),
+ io__write_byte(Byte::in, IO0::di, IO::uo),
[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
"
- mercury::runtime::Errors::SORRY(""foreign code for this function"");
- // XXX something like this...
- System::IO::StreamWriter *w = new System::IO::StreamWriter(
- mercury_current_text_output->stream);
- w->Write(Byte.ToString());
- w->Flush();
+ mercury_current_binary_output->stream->WriteByte(Byte);
+ MR_update_io(IO0, IO);
").
:- pragma foreign_proc("MC++",
@@ -4374,10 +4593,26 @@
"{
MR_MercuryFile stream = ML_DownCast(MR_MercuryFile,
MR_word_to_c_pointer(Stream));
- System::IO::StreamWriter *w = new System::IO::StreamWriter(
- mercury_current_binary_output->stream);
- w->Write(Character);
- w->Flush();
+ /* See mercury_output_string() for comments */
+ if (stream->writer == NULL) {
+ stream->writer = new System::IO::StreamWriter(stream->stream,
+ System::Text::Encoding::Default);
+ }
+ System::IO::TextWriter *w = stream->writer;
+ if (Character == '\\n') {
+ switch (stream->file_encoding) {
+ case ML_raw_binary:
+ case ML_Unix_text_encoding:
+ w->Write(Character);
+ break;
+ case ML_OS_text_encoding:
+ w->WriteLine("""");
+ break;
+ }
+ stream->line_number++;
+ } else {
+ w->Write(Character);
+ }
MR_update_io(IO0, IO);
}").
@@ -4387,10 +4622,7 @@
"{
MR_MercuryFile stream = ML_DownCast(MR_MercuryFile,
MR_word_to_c_pointer(Stream));
- System::IO::StreamWriter *w = new System::IO::StreamWriter(
- mercury_current_binary_output->stream);
- w->Write(Val.ToString());
- w->Flush();
+ mercury_print_string(stream, Val.ToString());
MR_update_io(IO0, IO);
}").
@@ -4400,10 +4632,7 @@
"{
MR_MercuryFile stream = ML_DownCast(MR_MercuryFile,
MR_word_to_c_pointer(Stream));
- System::IO::StreamWriter *w = new System::IO::StreamWriter(
- mercury_current_binary_output->stream);
- w->Write(Val.ToString());
- w->Flush();
+ mercury_print_string(stream, Val.ToString());
MR_update_io(IO0, IO);
}").
@@ -4411,14 +4640,9 @@
io__write_byte(Stream::in, Byte::in, IO0::di, IO::uo),
[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
"{
- mercury::runtime::Errors::SORRY(""foreign code for this function"");
- // something like this...
MR_MercuryFile stream = ML_DownCast(MR_MercuryFile,
MR_word_to_c_pointer(Stream));
- System::IO::StreamWriter *w = new System::IO::StreamWriter(
- mercury_current_binary_output->stream);
- w->Write(Byte.ToString());
- w->Flush();
+ stream->stream->WriteByte(Byte);
MR_update_io(IO0, IO);
}").
@@ -5036,7 +5260,18 @@
% Attempts to open a file in the specified mode.
% ResultCode is 0 for success, -1 for failure.
:- pragma foreign_proc("C",
- io__do_open(FileName::in, Mode::in, ResultCode::out,
+ io__do_open_text(FileName::in, Mode::in, ResultCode::out,
+ Stream::out, IO0::di, IO::uo),
+ [will_not_call_mercury, promise_pure, tabled_for_io,
+ thread_safe],
+"
+ Stream = (MR_Word) mercury_open(FileName, Mode);
+ ResultCode = (Stream ? 0 : -1);
+ MR_update_io(IO0, IO);
+").
+
+:- pragma foreign_proc("C",
+ io__do_open_binary(FileName::in, Mode::in, ResultCode::out,
Stream::out, IO0::di, IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io,
thread_safe],
@@ -5047,21 +5282,39 @@
").
:- pragma foreign_proc("MC++",
- io__do_open(FileName::in, Mode::in, ResultCode::out,
+ io__do_open_text(FileName::in, Mode::in, ResultCode::out,
Stream::out, IO0::di, IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io,
thread_safe],
"
- MR_MercuryFile mf = mercury_open(FileName, Mode);
+ MR_MercuryFile mf = mercury_open(FileName, Mode,
+ ML_default_text_encoding);
MR_c_pointer_to_word(Stream, mf);
ResultCode = (mf ? 0 : -1);
MR_update_io(IO0, IO);
").
-io__do_open(_, _, _, _) -->
+:- pragma foreign_proc("MC++",
+ io__do_open_binary(FileName::in, Mode::in, ResultCode::out,
+ Stream::out, IO0::di, IO::uo),
+ [will_not_call_mercury, promise_pure, tabled_for_io,
+ thread_safe],
+"
+ MR_MercuryFile mf = mercury_open(FileName, Mode, ML_raw_binary);
+ MR_c_pointer_to_word(Stream, mf);
+ ResultCode = (mf ? 0 : -1);
+ MR_update_io(IO0, IO);
+").
+
+io__do_open_text(_, _, _, _) -->
% This version is only used for back-ends for which there is no
% matching foreign_proc version.
- { private_builtin__sorry("io__do_open") }.
+ { private_builtin__sorry("io__do_open_text") }.
+
+io__do_open_binary(_, _, _, _) -->
+ % This version is only used for back-ends for which there is no
+ % matching foreign_proc version.
+ { private_builtin__sorry("io__do_open_binary") }.
io__close_input(Stream) -->
io__delete_stream_name(Stream),
@@ -5258,7 +5511,7 @@
io__get_exit_status(ExitStatus::out, IO0::di, IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io],
"
- ExitStatus = System::Environment::get_ExitCode();
+ ExitStatus = System::Environment::ExitCode;
MR_update_io(IO0, IO);
").
@@ -5266,7 +5519,7 @@
io__set_exit_status(ExitStatus::in, IO0::di, IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io],
"
- System::Environment::set_ExitCode(ExitStatus);
+ System::Environment::ExitCode = ExitStatus;
MR_update_io(IO0, IO);
").
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list