[m-rev.] For review: Java implementation of IO library

James Goddard goddardjames at yahoo.com
Thu Jan 8 15:04:41 AEDT 2004


Apologies in advance for the huge post (and doubtless quantity of mistakes) =)

Estimated hours taken: 60
Branches: main

Implement some library procedures for the Java back end.

library/io.m:
	Implement the following procedures:
		io__clear_err/3
		ferror/5
		io__get_system_error/3
		make_err_message/5
		io__stream_file_size/4
		io__file_modification_time_2/6
		file_type_implemented/0
		io__file_type_2/5
		io__check_file_accessibility_2/5
		compare_file_id_2/6
		io__get_stream_db/3
		io__set_stream_db/3
		io__get_globals/3
		io__set_globals/3
		io__get_stream_id/1
		io__read_char_code/4
		io__read_byte_val/4
		io__putback_char/4
		io__putback_byte/4
		io__write_byte/3
		io__write_bytes/3
		io__flush_output/2
		io__flush_binary_output/2
		io__seek_binary_2/5
		io__binary_stream_offset/4
		io__write_string/4
		io__write_char/4
		io__write_int/4
		io__write_float/4
		io__write_byte/4
		io__write_bytes/4
		io__flush_output/3
		io__flush_binary_output/3
		io__stdin_stream/3
		io__stdout_stream/3
		io__stderr_stream/3
		io__stdin_binary_stream/3
		io__stdout_binary_stream/3
		io__input_stream/3
		io__output_stream/3
		io__binary_input_stream/3
		io__binary_output_stream/3
		io__get_line_number/3
		io__get_line_number/4
		io__set_line_number/3
		io__set_line_number/4
		io__get_output_line_number/3
		io__get_output_line_number/4
		io__set_output_line_number/3
		io__set_output_line_number/4
		io__set_input_stream/4
		io__set_output_stream/4
		io__set_binary_input_stream/4
		io__set_binary_output_stream/4
		io__do_open_text/7
		io__do_open_binary/7
		io__close_stream/3
		io__progname/4
		io__get_exit_status/3
		io__set_exit_status/3
		build_command_line_args/2
		command_line_argument/2
		io__call_system_code/5
		io__getenv/2
		io__setenv/2
		io__putenv/2
		io__do_make_temp/8
		io__make_temp/3
		io__make_temp/5
		io__remove_file_2/5
		io__rename_file_2/6
		io__make_symlink_2/5
		io__read_symlink_2/6

Index: io.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/io.m,v
retrieving revision 1.315
diff -u -d -r1.315 io.m
--- io.m	2 Dec 2003 10:02:05 -0000	1.315
+++ io.m	8 Jan 2004 03:13:36 -0000
@@ -1654,6 +1654,12 @@
 		ML_file_encoding_kind.ML_OS_text_encoding;
 ").
 
+:- pragma foreign_code("Java",
+"
+	static java.lang.Object			ML_io_stream_db;
+	static java.lang.Object			ML_io_user_globals;
+").
+
 
 :- type io__stream_putback ==	map(io__stream_id, list(char)).
 
@@ -1666,6 +1672,7 @@
 :- pragma foreign_type("C", io__stream, "MercuryFilePtr").
 :- pragma foreign_type("il", io__stream,
 	"class [mercury]mercury.io__csharp_code.MR_MercuryFileStruct").
+:- pragma foreign_type("Java", io__stream, "mercury.io.MR_MercuryFileStruct").
 
 	% a unique identifier for an IO stream
 :- type io__stream_id == int.
@@ -2164,6 +2171,12 @@
 	// in MF_Mercury_file for compatibility)
 }").
 
+:- pragma foreign_proc("Java",
+	io__clear_err(_Stream::in, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
+	// XXX as for .NET above
+").
 
 :- pred io__check_err(stream, io__res, io__state, io__state).
 :- mode io__check_err(in, out, di, uo) is det.
@@ -2203,6 +2216,14 @@
 	RetVal = 0;
 }").
 
+:- pragma foreign_proc("Java",
+	ferror(_Stream::in, RetVal::out, _RetStr::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"{
+	// XXX see clearerr
+	RetVal = 0;
+}").
+
 :- pred io__make_err_msg(string, string, io__state, io__state).
 :- mode io__make_err_msg(in, out, di, uo) is det.
 
@@ -2228,6 +2249,13 @@
 	Error = MR_io_exception;
 }").
 
+:- pragma foreign_proc("Java",
+	io__get_system_error(Error::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"{
+	Error = MR_io_exception;
+}").
+
 :- pragma export(make_err_msg(in, in, out, di, uo), "ML_make_err_msg").
 :- pragma foreign_proc("C",
 	make_err_msg(Error::in, Msg0::in, Msg::out, IO0::di, IO::uo),
@@ -2244,6 +2272,17 @@
 	Msg = System.String.Concat(Msg0, Error.Message);
 }").
 
+:- pragma foreign_proc("Java",
+	make_err_msg(Error::in, Msg0::in, Msg::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure],
+"{
+	if (Error.getMessage() != null) {
+		Msg = Msg0 + Error.getMessage();
+	} else {
+		Msg = Msg0;
+	}
+}").
+
 have_win32 :- semidet_fail.
 
 :- pragma foreign_proc("C",
@@ -2353,6 +2392,13 @@
 	}
 }").
 
+:- pragma foreign_proc("Java",
+	io__stream_file_size(Stream::in, Size::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
+	Size = Stream.size();
+").
+
 io__file_modification_time(File, Result) -->
 	io__file_modification_time_2(File, Status, Msg, Time),
 	{ Status = 1 ->
@@ -2407,6 +2453,24 @@
 	}
 }").
 
+:- pragma foreign_proc("Java",
+	io__file_modification_time_2(FileName::in, Status::out, Msg::out,
+		Time::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	Time = new java.util.Date();
+
+	try {
+		((java.util.Date) Time).setTime(
+				(new java.io.File(FileName)).lastModified());
+		Msg = """";
+		Status = 1;
+	} catch (java.lang.Exception e) {
+		((java.util.Date) Time).setTime(0);
+		Msg = ""lastModified() failed: "" + e.getMessage();
+		Status = 0;
+	}
+").
 
 
 %-----------------------------------------------------------------------------%
@@ -2436,6 +2500,11 @@
 	[will_not_call_mercury, promise_pure, thread_safe],
 	"SUCCESS_INDICATOR = true;"
 ).
+:- pragma foreign_proc("Java", file_type_implemented,
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
+	succeeded = true;
+").
 
 :- pred io__file_type_2(int, string, io__res(io__file_type),
 		io__state, io__state).
@@ -2605,6 +2674,28 @@
     }
 ").
 
+:- pragma foreign_proc("Java",
+	io__file_type_2(_FollowSymLinks::in, FileName::in,
+		Result::out, _IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	java.io.File file = new java.io.File(FileName);
+
+	// The Java implementation can distinguish between regular files and
+	// directorys, and for everything else it just returns unknown.
+
+	if (file.isFile()) {
+		Result = new mercury.io.res_1.ok_1(new mercury.io.file_type_0(
+				mercury.io.file_type_0.regular_file));
+	} else if (file.isDirectory()) {
+		Result = new mercury.io.res_1.ok_1(new mercury.io.file_type_0(
+				mercury.io.file_type_0.directory));
+	} else {
+		Result = new mercury.io.res_1.ok_1(new mercury.io.file_type_0(
+				mercury.io.file_type_0.unknown));
+	}
+").
+
 :- func file_type_character_device = file_type.
 :- func file_type_block_device = file_type.
 :- func file_type_fifo = file_type.
@@ -2707,6 +2798,52 @@
 	IO = IO0;
 }").
 
+:- pragma foreign_proc("Java",
+	io__check_file_accessibility_2(FileName::in, AccessTypes::in,
+		Result::out, _IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	java.lang.String permissions = null;
+
+	if (access_types_includes_read_1_p_0(
+			(mercury.list.list_1) AccessTypes))
+	{
+		permissions = ""read"";
+	}
+
+	if (access_types_includes_write_1_p_0(
+			(mercury.list.list_1) AccessTypes))
+	{
+		if (permissions == null) {
+			permissions = ""write"";
+		} else {
+			permissions = ""read,write"";
+		}
+	}
+
+	if (access_types_includes_execute_1_p_0(
+			(mercury.list.list_1) AccessTypes))
+	{
+		if (permissions == null) {
+			permissions = ""execute"";
+		} else {
+			permissions = permissions + "",execute"";
+		}
+	}
+
+	try {
+		if (permissions != null) {
+			java.lang.System.getSecurityManager().checkPermission(
+					new java.io.FilePermission(
+					FileName, permissions));
+		}
+		Result = make_io_res_0_ok_0_f_0();
+	}
+	catch (java.lang.Exception e) {
+		Result = make_io_res_0_error_msg_1_f_0(e.getMessage());
+	}
+").
+
 	% The .NET CLI doesn't provide an equivalent of access(), so
 	% we have to try to open the file to see if it is accessible.
 :- pred io__check_file_accessibility_dotnet(string::in, list(access_type)::in,
@@ -2962,6 +3099,14 @@
 	}
 ").
 
+:- pragma foreign_proc("Java",
+	compare_file_id_2(_Res::out, _FileId1::in, _FileId2::in),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
+	throw new java.lang.RuntimeException(
+			""File IDs are not supported by Java."");
+").
+
 io__file_id(FileName, Result) -->
 	( { have_file_ids } ->
 		io__file_id_2(FileName, Status, Msg, FileId),
@@ -3001,6 +3146,19 @@
 #endif
 }").
 
+:- pragma foreign_proc("Java",
+	io__file_id_2(_FileName::in, _Status::out, _Msg::out,
+		_FileId::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	// This function should never be called, since have_file_ids will
+	// fail for Java.
+	if (true) {	// otherwise Java complains about unreachable stmts.
+		throw new RuntimeException(
+				""io.file_id_2 called but not supported"");
+	}
+").
+
 % Can we retrieve inode numbers on this system.
 have_file_ids :- semidet_fail.
 :- pragma foreign_proc("C", have_file_ids,
@@ -4199,6 +4357,20 @@
 	ML_io_stream_db = StreamDb;
 ").
 
+:- pragma foreign_proc("Java", 
+	io__get_stream_db(StreamDb::out, _IO0::di, _IO::uo), 
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	StreamDb = ML_io_stream_db;
+").
+
+:- pragma foreign_proc("Java", 
+	io__set_stream_db(StreamDb::in, _IO0::di, _IO::uo), 
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	ML_io_stream_db = StreamDb;
+").
+
 %-----------------------------------------------------------------------------%
 
 :- pred io__insert_stream_info(io__stream::in, stream_info::in,
@@ -4282,6 +4454,20 @@
 	ML_io_user_globals = Globals;
 ").
 
+:- pragma foreign_proc("Java", 
+	io__get_globals(Globals::uo, _IOState0::di, _IOState::uo), 
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	Globals = ML_io_user_globals;
+").
+
+:- pragma foreign_proc("Java", 
+	io__set_globals(Globals::di, _IOState0::di, _IOState::uo), 
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	ML_io_user_globals = Globals;
+").
+
 io__progname_base(DefaultName, PrognameBase) -->
 	io__progname(DefaultName, Progname),
 	{ PrognameBase = dir__basename_det(Progname) }.
@@ -4314,6 +4500,13 @@
 	Id = Stream.id;
 ").
 
+:- pragma foreign_proc("Java",
+	io__get_stream_id(Stream::in) = (Id::out), 
+	[will_not_call_mercury, promise_pure],
+"
+	Id = Stream.id;
+").
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -4603,6 +4796,257 @@
 }
 ").
 
+:- pragma foreign_code("Java",
+"
+	/* stdin, stdout, stderr treated as input/output streams,
+	** all files to use random access r+w
+	*/
+	public static class MR_MercuryFileStruct {
+		public	static int			ML_next_stream_id = 0;
+		public	int				id;
+
+		public	int				line_number;
+
+		private static final int		INPUT		= 1;
+		private static final int		OUTPUT		= 2;
+		private static final int		BOTH		= 3;
+		private int				mode;
+
+		private static final int		SEEK_SET	= 0;
+		private static final int		SEEK_CUR	= 1;
+		private static final int		SEEK_END	= 2;
+
+		private	java.util.Stack			pushback;
+		private java.io.InputStream		input		= null;
+		private java.io.OutputStream		output		= null;
+		private java.io.RandomAccessFile	randomaccess	= null;
+
+		private java.lang.String		filename	= null;
+
+		public MR_MercuryFileStruct(java.io.InputStream stream) {
+			line_number	= 1;
+			id		= ML_next_stream_id++;
+			mode		= INPUT;
+			pushback	= new java.util.Stack();
+			input		= stream;
+		}
+
+		public MR_MercuryFileStruct(java.io.OutputStream stream) {
+			line_number	= 1;
+			id		= ML_next_stream_id++;
+			mode		= OUTPUT;
+			pushback	= null;
+			output		= stream;
+		}
+
+		public MR_MercuryFileStruct(java.lang.String file) {
+			try {
+				randomaccess	= new java.io.RandomAccessFile(
+						file, ""rws"");
+			} catch (java.lang.Exception e) {
+				throw new RuntimeException(e.getMessage());
+			}
+			line_number	= 1;
+			id		= ML_next_stream_id++;
+			mode		= BOTH;
+			pushback	= new java.util.Stack();
+			filename	= file;
+		}
+
+		public MR_MercuryFileStruct(java.lang.String file,
+				boolean append)
+		{
+			try {
+				randomaccess	= new java.io.RandomAccessFile(
+						file, ""rws"");
+				id		= ML_next_stream_id++;
+				mode		= BOTH;
+				pushback	= new java.util.Stack();
+				filename	= file;
+				line_number	= 1;
+
+				if (append) {
+					while (true) {
+						int c = randomaccess.read();
+						if (c == '\\n') {
+							line_number++;
+						} else if (c == -1) {
+							break;
+						}
+					}
+				// XXX hopefully at this point we're at the
+				// end of the file, ready to append.
+				}
+			} catch (java.lang.Exception e) {
+				throw new RuntimeException(e.getMessage());
+			}
+		}
+
+		public int size() {
+			try {
+				return (int) randomaccess.length();
+			} catch (java.lang.Exception e) {
+				return -1;
+			}
+		}
+
+		public void seek(int flag, int offset) {
+			try {
+				switch (flag) {
+					case SEEK_SET:
+						randomaccess.seek(offset);
+						break;
+					case SEEK_CUR:
+						randomaccess.seek(
+							randomaccess.
+							getFilePointer() +
+							offset);
+						break;
+					case SEEK_END:
+						randomaccess.seek(
+							randomaccess.length() +
+							offset);
+						break;
+					default:
+						throw new java.lang.
+							RuntimeException(
+							""Invalid seek flag"");
+				}
+			} catch (java.lang.Exception e) {
+				throw new java.lang.RuntimeException(
+						e.getMessage());
+			}
+		}
+
+		public int getOffset() {
+			try {
+				return (int) randomaccess.getFilePointer();
+			} catch (java.lang.Exception e) {
+				return -1;
+			}
+		}
+
+		public int getc() {
+			int c;
+			if (mode == OUTPUT) {
+				throw new java.lang.RuntimeException(
+					""Attempted to read output stream"");
+			}
+			if (pushback.empty()) {
+				try {
+					if (input != null) {
+						c = input.read();
+					} else {
+						c = randomaccess.read();
+					}
+				} catch (java.io.IOException e) {
+					throw new java.lang.RuntimeException(
+							e.getMessage());
+				}
+			} else {
+				c = ((java.lang.Integer)pushback.pop()).
+						intValue();
+			}
+			if (c == '\\n') {
+				line_number++;
+			}
+
+			return c;
+		}
+
+		public void ungetc(int c) {
+			if (mode == OUTPUT) {
+				throw new java.lang.RuntimeException(
+				""Attempted to unget char to output stream"");
+			}
+			if (c == '\\n') {
+				line_number--;
+			}
+
+			pushback.push(new Integer(c));
+		}
+
+		public void putc(int c) {
+			if (mode == INPUT) {
+				throw new java.lang.RuntimeException(
+					""Attempted to write to input stream"");
+			}
+			if (c == '\\n') {
+				line_number++;
+			}
+	
+			try {
+				if (output != null) {
+					output.write(c);
+				} else {
+					randomaccess.write(c);
+				}
+			} catch (java.io.IOException e) {
+				throw new java.lang.RuntimeException(
+						e.getMessage());
+			}
+			pushback = new java.util.Stack();
+		}
+
+		public void write(java.lang.String s) {
+			if (mode == INPUT) {
+				throw new java.lang.RuntimeException(
+					""Attempted to write to input stream"");
+			}
+			for (int i = 0; i < s.length(); i++) {
+				if (s.charAt(i) == '\\n') {
+					line_number++;
+				}
+			}
+			
+			try {
+				if (output != null) {
+					output.write(s.getBytes());
+				} else {
+					randomaccess.write(s.getBytes());
+				}
+			} catch (java.io.IOException e) {
+				throw new java.lang.RuntimeException(
+						e.getMessage());
+			}
+			pushback = new java.util.Stack();
+		}
+
+		public void flush() {
+			if (mode == INPUT) {
+				throw new java.lang.RuntimeException(
+					""Attempted to flush input stream"");
+			}
+
+			try {
+				if (output != null) {
+					output.flush();
+				}
+				// else randomaccess already writes all data
+				// synchronously to the underlying device.
+			} catch (java.io.IOException e) {
+				throw new java.lang.RuntimeException(
+						e.getMessage());
+			}
+		}
+
+		public void close() {
+			try {
+				if (mode == INPUT) {
+					input.close();
+				} else if (mode == OUTPUT) {
+					output.close();
+				} else {
+					randomaccess.close();
+				}
+			} catch (java.io.IOException e) {
+				throw new java.lang.RuntimeException(
+						""Error closing stream"");
+			}
+		}
+	}
+").
+
 :- pragma foreign_code("C", "
 
 MercuryFile mercury_stdin;
@@ -4704,6 +5148,28 @@
 
 ").
 
+:- pragma foreign_code("Java",
+"
+static MR_MercuryFileStruct mercury_stdin =
+		new MR_MercuryFileStruct(java.lang.System.in);
+static MR_MercuryFileStruct mercury_stdout =
+		new MR_MercuryFileStruct(java.lang.System.out);
+static MR_MercuryFileStruct mercury_stderr =
+		new MR_MercuryFileStruct(java.lang.System.err);
+static MR_MercuryFileStruct mercury_stdin_binary =
+		new MR_MercuryFileStruct(java.lang.System.in);
+static MR_MercuryFileStruct mercury_stdout_binary =
+		new MR_MercuryFileStruct(java.lang.System.out);
+
+static MR_MercuryFileStruct mercury_current_text_input = mercury_stdin;
+static MR_MercuryFileStruct mercury_current_text_output = mercury_stdout;
+static MR_MercuryFileStruct mercury_current_binary_input = mercury_stdin_binary;
+static MR_MercuryFileStruct mercury_current_binary_output =
+		mercury_stdout_binary;
+		
+static java.lang.Exception MR_io_exception;
+").
+
 
 :- pragma foreign_code("C", "
 
@@ -4783,6 +5249,29 @@
 
 ").
 
+:- pragma foreign_code("Java",
+"
+static MR_MercuryFileStruct mercury_open(String filename, String openmode) {
+	try {
+		if (openmode.charAt(0) == 'r') {
+			return new MR_MercuryFileStruct(filename);
+		}
+		if (openmode.charAt(0) == 'w') {
+			return new MR_MercuryFileStruct(filename);
+		}
+		if (openmode.charAt(0) == 'a') {
+			return new MR_MercuryFileStruct(filename, true);
+		}
+
+		throw new java.lang.RuntimeException(
+				""Invalid file open mode: "" + openmode);
+	} catch (java.lang.Exception e) {
+		MR_io_exception = e;
+	}
+
+	return null;
+}
+").
 
 :- pred throw_io_error(string::in) is erroneous.
 :- pragma export(throw_io_error(in), "ML_throw_io_error").
@@ -4910,6 +5399,7 @@
 
 ").
 
+
 :- pragma foreign_code("C", "
 
 void
@@ -5387,6 +5877,35 @@
 	mf.putback = Byte;
 }").
 
+:- pragma foreign_proc("Java", 
+	io__read_char_code(File::in, CharCode::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure],
+"
+	CharCode = File.getc();
+").
+
+:- pragma foreign_proc("Java", 
+	io__read_byte_val(File::in, ByteVal::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure],
+"
+	ByteVal = File.getc();
+").
+
+:- pragma foreign_proc("Java",
+	io__putback_char(File::in, Character::in, _IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure],
+"
+	File.ungetc(Character);
+").
+
+:- pragma foreign_proc("Java",
+	io__putback_byte(File::in, Byte::in, _IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure],
+"
+	File.ungetc(Byte);
+").
+
+
 /* output predicates - with output to mercury_current_text_output */
 
 :- pragma foreign_proc("C", 
@@ -5569,6 +6088,34 @@
 	System.out.print(Val);
 ").
 
+:- pragma foreign_proc("Java",
+	io__write_byte(Byte::in, _IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+	mercury_current_binary_output.putc(Byte);
+").
+
+:- pragma foreign_proc("Java",
+	io__write_bytes(Message::in, _IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"{
+	mercury_current_binary_output.write(Message);
+}").
+
+:- pragma foreign_proc("Java",
+	io__flush_output(_IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+	mercury_current_text_output.flush();
+").
+
+:- pragma foreign_proc("Java",
+	io__flush_binary_output(_IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+	mercury_current_binary_output.flush();
+").
+
 io__write_float(Float) -->
 	io__write_string(string__float_to_string(Float)).
 
@@ -5772,6 +6319,76 @@
 	Stream.stream.Flush();
 }").
 
+:- pragma foreign_proc("Java",
+	io__seek_binary_2(Stream::in, Flag::in, Off::in, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	Stream.seek(Flag, Off);
+").
+
+:- pragma foreign_proc("Java",
+	io__binary_stream_offset(Stream::in, Offset::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	Offset = Stream.getOffset();
+").
+
+:- pragma foreign_proc("Java",
+	io__write_string(Stream::in, Message::in, _IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure, thread_safe, tabled_for_io], 
+"
+	Stream.write(Message);
+").
+
+:- pragma foreign_proc("Java",
+	io__write_char(Stream::in, Character::in, _IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+	Stream.putc(Character);
+").
+
+:- pragma foreign_proc("Java",
+	io__write_int(Stream::in, Val::in, _IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	Stream.write(java.lang.String.valueOf(Val));
+").
+
+:- pragma foreign_proc("Java",
+	io__write_float(Stream::in, Val::in, _IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	Stream.write(java.lang.String.valueOf(Val));
+").
+
+:- pragma foreign_proc("Java",
+	io__write_byte(Stream::in, Byte::in, _IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+	Stream.putc(Byte);
+").
+
+:- pragma foreign_proc("Java",
+	io__write_bytes(Stream::in, Message::in, _IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+	Stream.write(Message);
+").
+
+:- pragma foreign_proc("Java",
+	io__flush_output(Stream::in, _IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+	Stream.flush();
+").
+
+:- pragma foreign_proc("Java",
+	io__flush_binary_output(Stream::in, _IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+	Stream.flush();
+").
+
 io__write_float(Stream, Float) -->
 	io__write_string(Stream, string__float_to_string(Float)).
 
@@ -6119,6 +6736,162 @@
 	mercury_current_binary_output = NewStream;
 ").
 
+:- pragma foreign_proc("Java",
+	io__stdin_stream(Stream::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+	Stream = mercury_stdin;
+").
+
+:- pragma foreign_proc("Java",
+	io__stdout_stream(Stream::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+	Stream = mercury_stdout;
+").
+
+:- pragma foreign_proc("Java",
+	io__stderr_stream(Stream::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+	Stream = mercury_stderr;
+").
+
+:- pragma foreign_proc("Java",
+	io__stdin_binary_stream(Stream::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+	Stream = mercury_stdin_binary;
+").
+
+:- pragma foreign_proc("Java",
+	io__stdout_binary_stream(Stream::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
+"
+	Stream = mercury_stdout_binary;
+").
+
+:- pragma foreign_proc("Java",
+	io__input_stream(Stream::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	Stream = mercury_current_text_input;
+").
+
+:- pragma foreign_proc("Java",
+	io__output_stream(Stream::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	Stream = mercury_current_text_output;
+").
+
+:- pragma foreign_proc("Java",
+	io__binary_input_stream(Stream::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	Stream = mercury_current_binary_input;
+").
+
+:- pragma foreign_proc("Java",
+	io__binary_output_stream(Stream::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	Stream = mercury_current_binary_output;
+").
+
+:- pragma foreign_proc("Java",
+	io__get_line_number(LineNum::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	LineNum = mercury_current_text_input.line_number;
+").
+
+:- pragma foreign_proc("Java",
+	io__get_line_number(Stream::in, LineNum::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"{
+	LineNum = Stream.line_number;
+}").
+
+:- pragma foreign_proc("Java",
+	io__set_line_number(LineNum::in, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	mercury_current_text_input.line_number = LineNum;
+").
+
+:- pragma foreign_proc("Java",
+	io__set_line_number(Stream::in, LineNum::in, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"{
+	Stream.line_number = LineNum;
+}").
+
+:- pragma foreign_proc("Java",
+	io__get_output_line_number(LineNum::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	LineNum = mercury_current_text_output.line_number;
+").
+
+:- pragma foreign_proc("Java",
+	io__get_output_line_number(Stream::in, LineNum::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"{
+	LineNum = Stream.line_number;
+}").
+
+:- pragma foreign_proc("Java",
+	io__set_output_line_number(LineNum::in, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	mercury_current_text_output.line_number = LineNum;
+").
+
+:- pragma foreign_proc("Java",
+	io__set_output_line_number(Stream::in, LineNum::in, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"{
+	Stream.line_number = LineNum;
+}").
+
+% io__set_input_stream(NewStream, OldStream, IO0, IO1)
+%	Changes the current input stream to the stream specified.
+%	Returns the previous stream.
+:- pragma foreign_proc("Java",
+	io__set_input_stream(NewStream::in, OutStream::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	OutStream = mercury_current_text_input;
+	mercury_current_text_input = NewStream;
+").
+
+:- pragma foreign_proc("Java",
+	io__set_output_stream(NewStream::in, OutStream::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	OutStream = mercury_current_text_output;
+	mercury_current_text_output = NewStream;
+").
+
+:- pragma foreign_proc("Java",
+	io__set_binary_input_stream(NewStream::in, OutStream::out,
+		_IO0::di, _IO::uo), 
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	OutStream = mercury_current_binary_input;
+	mercury_current_binary_input = NewStream;
+").
+
+:- pragma foreign_proc("Java",
+	io__set_binary_output_stream(NewStream::in, OutStream::out,
+		_IO0::di, _IO::uo), 
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	OutStream = mercury_current_binary_output;
+	mercury_current_binary_output = NewStream;
+").
+
 /* stream open/close predicates */
 
 %	io__do_open_binary(File, Mode, ResultCode, StreamId, Stream, IO0, IO):
@@ -6191,6 +6964,38 @@
 	}
 ").
 
+:- pragma foreign_proc("Java",
+	io__do_open_text(FileName::in, Mode::in, ResultCode::out,
+		StreamId::out, Stream::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	try {
+		Stream = mercury_open(FileName, Mode);
+		StreamId = Stream.id;
+		ResultCode = 0;
+	} catch (java.lang.Exception e) {
+		Stream = null;
+		StreamId = -1;
+		ResultCode = -1;
+	}
+").
+
+:- pragma foreign_proc("Java",
+	io__do_open_binary(FileName::in, Mode::in, ResultCode::out,
+		StreamId::out, Stream::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	try {
+		Stream = mercury_open(FileName, Mode);
+		StreamId = Stream.id;
+		ResultCode = 0;
+	} catch (java.lang.Exception e) {
+		Stream = null;
+		StreamId = -1;
+		ResultCode = -1;
+	}
+").
+
 io__close_input(Stream) -->
 	io__maybe_delete_stream_info(Stream),
 	io__close_stream(Stream).
@@ -6224,6 +7029,13 @@
 	mercury_close(Stream);
 ").
 
+:- pragma foreign_proc("Java",
+	io__close_stream(Stream::in, _IO0::di, _IO::uo),
+	[may_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	Stream.close();
+").
+
 /* miscellaneous predicates */
 
 :- pragma foreign_proc("C",
@@ -6426,6 +7238,76 @@
 	}
 ").
 
+:- pragma foreign_proc("Java",
+	io__progname(_Default::in, PrognameOut::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	PrognameOut = ""java "" + mercury.runtime.JavaInternal.progname;
+").
+
+:- pragma foreign_proc("Java",
+	io__get_exit_status(ExitStatus::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io], 
+"
+	ExitStatus = mercury.runtime.JavaInternal.exit_status;
+").
+
+:- pragma foreign_proc("Java",
+	io__set_exit_status(ExitStatus::in, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io], 
+"
+	mercury.runtime.JavaInternal.exit_status = ExitStatus;
+").
+
+io__command_line_arguments(Args, IO, IO) :-
+	build_command_line_args(0, Args).
+
+:- pred build_command_line_args(int, list(string)).
+:- mode build_command_line_args(in, out) is det.
+
+build_command_line_args(ArgNumber, Args) :-
+	( command_line_argument(ArgNumber, Arg) ->
+		Args = [Arg|MoreArgs],
+		build_command_line_args(ArgNumber + 1, MoreArgs)
+	;
+		Args = []
+	).
+
+:- pred command_line_argument(int, string).
+:- mode command_line_argument(in, out) is semidet.
+
+:- pragma foreign_proc("Java",
+	command_line_argument(ArgNum::in, Arg::out),
+	[will_not_call_mercury, promise_pure, thread_safe],
+"
+	String[] arg_vector = mercury.runtime.JavaInternal.args;
+
+	if (ArgNum < arg_vector.length && ArgNum >= 0) {
+		Arg = arg_vector[ArgNum];
+		succeeded = true;
+	} else {
+		Arg = null;
+		succeeded = false;
+	}
+").
+
+:- pragma foreign_proc("Java",
+	io__call_system_code(Command::in, Status::out, Msg::out,
+			_IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io],
+"
+	try {
+		java.lang.Process command = java.lang.Runtime.getRuntime().
+				exec(Command);
+		command.waitFor();
+		Status	= command.exitValue();
+		Msg	= null;
+	} catch (java.lang.Exception e) {
+		Status	= 127;
+		Msg	= e.getMessage();
+	}
+").
+
 /*---------------------------------------------------------------------------*/
 
 /* io__getenv and io__setenv */
@@ -6452,6 +7334,29 @@
 	SUCCESS_INDICATOR = (Value != null);
 }").
 
+:- pragma foreign_proc("Java",
+	io__getenv(Var::in, Value::out),
+	[will_not_call_mercury, tabled_for_io],
+"
+	// Note that this approach only works for environmental variables that
+	// are recognized by Java and hava a special format.
+	// (eg os.name, user.timezone etc)
+	// To add custom environmental variables, they must be set at the
+	// command line with java's -D option
+	// (ie java -DENV_VARIABLE_NAME=$ENV_VARIABLE_NAME ClassName)
+	// XXX Perhaps a better approach would be to determine the OS at
+	// runtime and then Runtime.exec() the equivalent of 'env'?
+
+	try {
+		Value = java.lang.System.getProperty(Var);
+		succeeded = (Value != null);
+	} catch (java.lang.Exception e) {
+		Value = null;
+		succeeded = false;
+	}
+").
+
+
 io__setenv(Var, Value) :-
 	impure io__putenv(Var ++ "=" ++ Value).
 
@@ -6485,6 +7390,33 @@
 	SUCCESS_INDICATOR = (mercury.runtime.PInvoke._putenv(VarAndValue) == 0);
 ").
 
+:- pragma foreign_proc("Java",
+	io__setenv(Var::in, Value::in),
+	[will_not_call_mercury, tabled_for_io],
+"
+	// XXX see io__getenv/2
+
+	try {
+		Value = java.lang.System.setProperty(Var, Value);
+		succeeded = true;
+	} catch (java.lang.Exception e) {
+		succeeded = false;
+	}
+").
+
+:- pragma foreign_proc("Java",
+	io__putenv(VarAndValue::in),
+	[will_not_call_mercury, tabled_for_io],
+"
+	// This procedure should never be called, as io__setenv/2 has been
+	// implemented directly for Java.
+	// This implementation is included only to suppress warnings.
+
+	throw new RuntimeException(
+			""io__putenv/1 not implemented for Java: "" +
+			VarAndValue);
+").
+
 /*---------------------------------------------------------------------------*/
 
 io__tmpnam(Name) -->
@@ -6663,6 +7595,48 @@
 	}
 }").
 
+% For the Java implementation, io__make_temp/3 is overwritten directly, since
+% Java is capable of locating the default temp directory itself.
+
+:- pragma foreign_proc("Java",
+	io__do_make_temp(_Dir::in, _Prefix::in, _Sep::in, _FileName::out,
+		_Error::out, _ErrorMessage::out, _IO0::di, _IO::uo),
+        [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	// this function should never be called.
+
+	throw new RuntimeException(""io__do_make_temp not implemented"");
+").
+
+:- pragma foreign_proc("Java",
+        io__make_temp(FileName::out, _IO0::di, _IO::uo),
+        [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	try {
+		FileName = java.io.File.createTempFile(""mercury"", null).
+				getName();
+	} catch (java.lang.Exception e) {
+		throw new RuntimeException(e.getMessage());
+	}
+").
+
+:- pragma foreign_proc("Java",
+        io__make_temp(Dir::in, Prefix::in, FileName::out, _IO0::di, _IO::uo),
+        [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	try {
+		if (Prefix.length() < 3) {
+			Prefix = Prefix + ""xxx"";
+		} else if (Prefix.length() > 5) {
+			Prefix = Prefix.substring(0, 5);
+		}
+		FileName = java.io.File.createTempFile(Prefix, null,
+				new java.io.File(Dir)).getName();
+	} catch (java.lang.Exception e) {
+		throw new RuntimeException(e.getMessage());
+	}
+").
+
 /*---------------------------------------------------------------------------*/
 
 :- pragma foreign_decl("C", "
@@ -6819,6 +7793,32 @@
 	}
 }").
 
+:- pragma foreign_proc("Java",
+	io__remove_file_2(FileName::in, RetVal::out, RetStr::out,
+		_IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	try {
+		java.io.File file = new java.io.File(FileName);
+
+		if (file.exists()) {
+			if (file.delete()) {
+				RetVal = 0;
+				RetStr = """";
+			} else {
+				RetVal = -1;
+				RetStr = ""remove_file failed"";
+			}
+		} else {
+			RetVal = -1;
+			RetStr = ""remove failed: No such file or directory"";
+		}
+	} catch (java.lang.Exception e) {
+		RetVal = -1;
+		RetStr = e.getMessage();
+	}
+").
+
 io__rename_file(OldFileName, NewFileName, Result, IO0, IO) :-
 	io__rename_file_2(OldFileName, NewFileName, Res, ResString, IO0, IO),
 	( Res \= 0 ->
@@ -6862,6 +7862,32 @@
 	}
 }").
 
+:- pragma foreign_proc("Java",
+	io__rename_file_2(OldFileName::in, NewFileName::in, RetVal::out,
+		RetStr::out, _IO0::di, _IO::uo),
+	[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	try {
+		java.io.File file = new java.io.File(OldFileName);
+
+		if (file.exists()) {
+			if (file.renameTo(new java.io.File(NewFileName))) {
+				RetVal = 0;
+				RetStr = """";
+			} else {
+				RetVal = -1;
+				RetStr = ""rename_file failed"";
+			}
+		} else {
+			RetVal = -1;
+			RetStr = ""rename failed: No such file or directory"";
+		}
+	} catch (java.lang.Exception e) {
+		RetVal = -1;
+		RetStr = e.getMessage();
+	}
+").
+
 io__have_symlinks :- semidet_fail.
 
 :- pragma foreign_proc("C", io__have_symlinks,
@@ -6972,6 +7998,30 @@
 	MR_update_io(IO0, IO);
 }").
 
+% Since io__have_symlinks will fail for Java, these procedures should never be
+% called:
+
+:- pragma foreign_proc("Java",
+	io__make_symlink_2(_FileName::in, _LinkFileName::in,
+		_Status::out, _IO0::di, _IO::uo), 
+	[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	if (true) {
+		throw new java.lang.RuntimeException(
+				""io__make_symlink_2 not implemented"");
+	}
+").
+
+:- pragma foreign_proc("Java",
+	io__read_symlink_2(_FileName::in, _TargetFileName::out,
+		_Status::out, _Error::out, _IO0::di, _IO::uo), 
+	[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
+"
+	if (true) {
+		throw new java.lang.RuntimeException(
+				""io__read_symlink_2 not implemented"");
+	}
+").
 
 /*---------------------------------------------------------------------------*/
 
--------------------------------------------------------------------------
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