CodesToNumber,
CopyTermWithoutAttrVars,
CheckCutPoint,
+ Close,
CopyToLiftedHeap,
CreatePartialString,
CurrentHostname,
&SystemClauseType::REPL(REPLCodePtr::UseQualifiedModuleFromFile) => {
clause_name!("$use_qualified_module_from_file")
}
+ &SystemClauseType::Close => clause_name!("$close"),
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
&SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
("$compile_batch", 0) => Some(SystemClauseType::REPL(REPLCodePtr::CompileBatch)),
("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap),
+ ("$close", 2) => Some(SystemClauseType::Close),
("$current_hostname", 1) => Some(SystemClauseType::CurrentHostname),
("$current_input", 1) => Some(SystemClauseType::CurrentInput),
("$current_output", 1) => Some(SystemClauseType::CurrentOutput),
(:)/7, (:)/8, (:)/9, (:)/10, (:)/11, (:)/12,
abolish/1, asserta/1, assertz/1, atom_chars/2,
atom_codes/2, atom_concat/3, atom_length/2,
- bagof/3, catch/3, char_code/2, clause/2,
- current_input/1, current_output/1, current_op/3,
- current_predicate/1, current_prolog_flag/2,
- expand_goal/2, expand_term/2, fail/0, false/0,
- findall/3, findall/4, get_char/1, halt/0,
- max_arity/1, number_chars/2, number_codes/2,
- once/1, op/3, open/3, open/4, read_term/2,
- read_term/3, repeat/0, retract/1,
- set_prolog_flag/2, set_input/1, set_output/1,
- setof/3, sub_atom/5, subsumes_term/2,
- term_variables/2, throw/1, true/0,
- unify_with_occurs_check/2, write/1,
+ bagof/3, catch/3, char_code/2, clause/2, close/1,
+ close/2, current_input/1, current_output/1,
+ current_op/3, current_predicate/1,
+ current_prolog_flag/2, expand_goal/2,
+ expand_term/2, fail/0, false/0, findall/3,
+ findall/4, get_char/1, halt/0, max_arity/1,
+ number_chars/2, number_codes/2, once/1, op/3,
+ open/3, open/4, read_term/2, read_term/3,
+ repeat/0, retract/1, set_prolog_flag/2,
+ set_input/1, set_output/1, setof/3, sub_atom/5,
+ subsumes_term/2, term_variables/2, throw/1,
+ true/0, unify_with_occurs_check/2, write/1,
write_canonical/1, write_term/2, write_term/3,
writeq/1]).
'$open'(SourceSink, Mode, Stream, Alias, EOFAction, Reposition, Type)
).
+
+parse_close_options(Options, OptionValues, Stub) :-
+ DefaultOptions = [force-false],
+ parse_options_list(Options, parse_close_options_, DefaultOptions, OptionValues, Stub).
+
+parse_close_options_(force(Force), force-Force) :-
+ ( nonvar(Force), lists:member(Force, [true, false]), !
+ ;
+ throw(error(domain_error(close_option, force(Force)), _))
+ ).
+parse_close_options_(E, _) :-
+ throw(error(domain_error(close_option, E), _)).
+
+
+close(Stream, CloseOptions) :-
+ parse_close_options(CloseOptions, [Force], close/2),
+ '$close'(Stream, CloseOptions).
+
+close(Stream) :-
+ close(Stream, []).
use std::fs::File;
use std::io::{stdout, Cursor, ErrorKind, Read, Seek, SeekFrom, Write};
use std::hash::{Hash, Hasher};
-use std::net::TcpStream;
+use std::net::{Shutdown, TcpStream};
use std::rc::Rc;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
TcpStream(TcpStream),
}
+impl Drop for StreamInstance {
+ fn drop(&mut self) {
+ match self {
+ StreamInstance::TcpStream(ref mut tcp_stream) => {
+ tcp_stream.shutdown(Shutdown::Both).unwrap();
+ }
+ _ => {
+ }
+ }
+ }
+}
+
impl fmt::Debug for StreamInstance {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self {
}
}
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, Hash)]
pub struct Stream {
pub options: StreamOptions,
stream_inst: WrappedStreamInstance,
}
+impl PartialEq for Stream {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ self.stream_inst == other.stream_inst
+ }
+}
+
+impl Eq for Stream {}
+
impl From<TcpStream> for Stream {
fn from(tcp_stream: TcpStream) -> Self {
tcp_stream.set_read_timeout(None).unwrap();
}
}
+ #[inline]
+ pub(crate)
+ fn close(&mut self) {
+ *self.stream_inst.0.borrow_mut() = StreamInstance::Null;
+ }
+
#[inline]
pub(crate)
fn is_input_stream(&self) -> bool {
}
};
}
+ &SystemClauseType::Close => {
+ let mut stream =
+ self.get_stream_or_alias(self[temp_v!(1)], indices, "close", 2)?;
+
+ if stream.is_output_stream() {
+ stream.flush().unwrap(); // 8.11.6.1b)
+ }
+
+ if stream == *current_input_stream {
+ *current_input_stream = readline::input_stream();
+ } else if stream == *current_output_stream {
+ *current_output_stream = Stream::stdout();
+ }
+
+ stream.close();
+
+ if let Some(alias) = stream.options.alias {
+ indices.stream_aliases.remove(&alias);
+ }
+ }
&SystemClauseType::CopyToLiftedHeap => {
match self.store(self.deref(self[temp_v!(1)])) {
Addr::Usize(lh_offset) => {
stream.options = options;
+ if let Some(ref alias) = &stream.options.alias {
+ indices.stream_aliases.insert(alias.clone(), stream.clone());
+ }
+
let stream = self.heap.to_unifiable(HeapCellValue::Stream(stream));
let stream_var = self.store(self.deref(self[temp_v!(3)]));
match TcpStream::connect(socket_addr).map_err(|e| e.kind()) {
Ok(tcp_stream) => {
let mut stream = Stream::from(tcp_stream);
+ stream.options = options;
- if let Some(ref alias) = &options.alias {
+ if let Some(ref alias) = &stream.options.alias {
indices.stream_aliases.insert(alias.clone(), stream.clone());
}
- stream.options = options;
self.heap.to_unifiable(HeapCellValue::Stream(stream))
}
Err(ErrorKind::PermissionDenied) => {