add support for with_output_to/2.
This commit is contained in:
parent
660ea12537
commit
5b1a2067f9
14
C/iopreds.c
14
C/iopreds.c
@ -1406,8 +1406,8 @@ ConsoleSocketGetc(int sno)
|
|||||||
static int
|
static int
|
||||||
PipeGetc(int sno)
|
PipeGetc(int sno)
|
||||||
{
|
{
|
||||||
register StreamDesc *s = &Stream[sno];
|
StreamDesc *s = &Stream[sno];
|
||||||
register Int ch;
|
Int ch;
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
/* should be able to use a buffer */
|
/* should be able to use a buffer */
|
||||||
@ -1426,7 +1426,11 @@ PipeGetc(int sno)
|
|||||||
} else if (count > 0) {
|
} else if (count > 0) {
|
||||||
ch = c;
|
ch = c;
|
||||||
} else {
|
} else {
|
||||||
Yap_Error(SYSTEM_ERROR, TermNil, "read");
|
#if HAVE_STRERROR
|
||||||
|
Yap_Error(SYSTEM_ERROR, TermNil, "at pipe getc: %s", strerror(errno));
|
||||||
|
#else
|
||||||
|
Yap_Error(SYSTEM_ERROR, TermNil, "at pipe getc");
|
||||||
|
#endif
|
||||||
return post_process_eof(s);
|
return post_process_eof(s);
|
||||||
}
|
}
|
||||||
return post_process_read_char(ch, s);
|
return post_process_read_char(ch, s);
|
||||||
@ -4010,15 +4014,17 @@ static Int
|
|||||||
Stream[inp_stream].stream_getc = PlUnGetc;
|
Stream[inp_stream].stream_getc = PlUnGetc;
|
||||||
Stream[inp_stream].och = ungetc_oldc;
|
Stream[inp_stream].och = ungetc_oldc;
|
||||||
}
|
}
|
||||||
|
if (seekable) {
|
||||||
if (Stream[inp_stream].status & InMemory_Stream_f) {
|
if (Stream[inp_stream].status & InMemory_Stream_f) {
|
||||||
Stream[inp_stream].u.mem_string.pos = cpos;
|
Stream[inp_stream].u.mem_string.pos = cpos;
|
||||||
} else {
|
} else if (Stream[inp_stream].status) {
|
||||||
#if HAVE_FGETPOS
|
#if HAVE_FGETPOS
|
||||||
fsetpos(Stream[inp_stream].u.file.file, &rpos);
|
fsetpos(Stream[inp_stream].u.file.file, &rpos);
|
||||||
#else
|
#else
|
||||||
fseek(Stream[inp_stream].u.file.file, cpos, 0L);
|
fseek(Stream[inp_stream].u.file.file, cpos, 0L);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (Yap_Error_TYPE == OUT_OF_TRAIL_ERROR) {
|
if (Yap_Error_TYPE == OUT_OF_TRAIL_ERROR) {
|
||||||
Yap_Error_TYPE = YAP_NO_ERROR;
|
Yap_Error_TYPE = YAP_NO_ERROR;
|
||||||
if (!Yap_growtrail (sizeof(CELL) * 16 * 1024L, FALSE)) {
|
if (!Yap_growtrail (sizeof(CELL) * 16 * 1024L, FALSE)) {
|
||||||
|
42
docs/yap.tex
42
docs/yap.tex
@ -1,4 +1,4 @@
|
|||||||
a\input texinfo @c -*- mode: texinfo; coding: latin-1; -*-
|
´a\input texinfo @c -*- mode: texinfo; coding: latin-1; -*-
|
||||||
|
|
||||||
@c %**start of header
|
@c %**start of header
|
||||||
@setfilename yap.info
|
@setfilename yap.info
|
||||||
@ -4995,6 +4995,46 @@ Print formatted output to the current output stream.
|
|||||||
@cnindex format/3
|
@cnindex format/3
|
||||||
Print formatted output to stream @var{S}.
|
Print formatted output to stream @var{S}.
|
||||||
|
|
||||||
|
@item with_output_to(+@var{Ouput},:@var{Goal})
|
||||||
|
@findex with_output_to/2
|
||||||
|
@saindex with_output_to/2
|
||||||
|
@cnindex with_output_to/2
|
||||||
|
Run @var{Goal} as @code{once/1}, while characters written to the current
|
||||||
|
output are sent to @var{Output}. The predicate is SWI-Prolog
|
||||||
|
specific.
|
||||||
|
|
||||||
|
Applications should generally avoid creating atoms by breaking and
|
||||||
|
concatenating other atoms as the creation of large numbers of
|
||||||
|
intermediate atoms generally leads to poor performance, even more so in
|
||||||
|
multi-threaded applications. This predicate supports creating
|
||||||
|
difference-lists from character data efficiently. The example below
|
||||||
|
defines the DCG rule @code{term/3} to insert a term in the output:
|
||||||
|
|
||||||
|
@example
|
||||||
|
term(Term, In, Tail) :-
|
||||||
|
with_output_to(codes(In, Tail), write(Term)).
|
||||||
|
|
||||||
|
?- phrase(term(hello), X).
|
||||||
|
|
||||||
|
X = [104, 101, 108, 108, 111]
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item A Stream handle or alias
|
||||||
|
Temporary switch current output to the given stream. Redirection using with_output_to/2 guarantees the original output is restored, also if Goal fails or raises an exception. See also call_cleanup/2.
|
||||||
|
@item atom(-@var{Atom})
|
||||||
|
Create an atom from the emitted characters. Please note the remark above.
|
||||||
|
@item string(-@var{String})
|
||||||
|
Create a string-object (not supported in YAP).
|
||||||
|
@item codes(-@var{Codes})
|
||||||
|
Create a list of character codes from the emitted characters, similar to atom_codes/2.
|
||||||
|
@item codes(-@var{Codes}, -@var{Tail})
|
||||||
|
Create a list of character codes as a difference-list.
|
||||||
|
@item chars(-@var{Chars})
|
||||||
|
Create a list of one-character-atoms codes from the emitted characters, similar to atom_chars/2.
|
||||||
|
@item chars(-@var{Chars}, -@var{Tail})
|
||||||
|
Create a list of one-character-atoms as a difference-list.
|
||||||
|
@end table
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
@ -597,6 +597,7 @@ source_module(Mod) :-
|
|||||||
use_module(?,:,?),
|
use_module(?,:,?),
|
||||||
when(?,:),
|
when(?,:),
|
||||||
with_mutex(+,:),
|
with_mutex(+,:),
|
||||||
|
with_output_to(?,:),
|
||||||
(: -> :),
|
(: -> :),
|
||||||
(: *-> :),
|
(: *-> :),
|
||||||
(: ; :),
|
(: ; :),
|
||||||
|
60
pl/yio.yap
60
pl/yio.yap
@ -1061,7 +1061,7 @@ current_stream(File, Opts, Stream) :-
|
|||||||
'$extend_file_search_path'(P) :-
|
'$extend_file_search_path'(P) :-
|
||||||
atom_codes(P,S),
|
atom_codes(P,S),
|
||||||
'$env_separator'(ES),
|
'$env_separator'(ES),
|
||||||
'$split_for_path'(S,0'=,ES,Paths),
|
'$split_for_path'(S,0'=,ES,Paths), %'
|
||||||
'$add_file_search_paths'(Paths).
|
'$add_file_search_paths'(Paths).
|
||||||
|
|
||||||
'$split_for_path'([], _, _, []).
|
'$split_for_path'([], _, _, []).
|
||||||
@ -1152,4 +1152,60 @@ prolog_file_name(File, PrologFileName) :-
|
|||||||
prolog_file_name(File, PrologFileName) :-
|
prolog_file_name(File, PrologFileName) :-
|
||||||
'$do_error'(type_error(atom,T), prolog_file_name(File, PrologFileName)).
|
'$do_error'(type_error(atom,T), prolog_file_name(File, PrologFileName)).
|
||||||
|
|
||||||
s
|
|
||||||
|
with_output_to(Output, Command) :-
|
||||||
|
setup_call_cleanup( '$setup_wot'(Output, Stream, OldStream, with_output_to(Output, Command)),
|
||||||
|
once(Command),
|
||||||
|
'$cleanup_wot'(Output, Stream, OldStream) ).
|
||||||
|
|
||||||
|
'$setup_wot'(Output, Stream, OldStream, Goal) :-
|
||||||
|
'$setup_wot'(Output, Stream, Goal),
|
||||||
|
current_output(OldStream),
|
||||||
|
set_output(Stream).
|
||||||
|
|
||||||
|
'$setup_wot'(Output, Stream, Goal) :-
|
||||||
|
var(Output), !,
|
||||||
|
'$do_error'(instantiation_error,Goal).
|
||||||
|
'$setup_wot'(atom(_Atom), Stream, _) :- !,
|
||||||
|
charsio:open_mem_write_stream(Stream).
|
||||||
|
'$setup_wot'(codes(_Codes), Stream, _) :- !,
|
||||||
|
charsio:open_mem_write_stream(Stream).
|
||||||
|
'$setup_wot'(codes(_Codes, _Tail), Stream, _) :- !,
|
||||||
|
charsio:open_mem_write_stream(Stream).
|
||||||
|
'$setup_wot'(chars(_Chars), Stream, _) :- !,
|
||||||
|
charsio:open_mem_write_stream(Stream).
|
||||||
|
'$setup_wot'(chars(_Chars, _Tail), Stream, _) :- !,
|
||||||
|
charsio:open_mem_write_stream(Stream).
|
||||||
|
'$setup_wot'(Stream, Stream, _) :-
|
||||||
|
'$stream'(Stream), !.
|
||||||
|
'$setup_wot'(Output, _, Goal) :-
|
||||||
|
'$do_error'(type_error(output,Output),Goal).
|
||||||
|
|
||||||
|
'$cleanup_wot'(Output, Stream, OldStream) :- !,
|
||||||
|
'$cleanup_wot'(Output, Stream),
|
||||||
|
set_output(OldStream).
|
||||||
|
|
||||||
|
'$cleanup_wot'(atom(Atom), Stream) :- !,
|
||||||
|
charsio:peek_mem_write_stream(Stream, [], String),
|
||||||
|
atom_codes(Atom, String),
|
||||||
|
close(Stream).
|
||||||
|
'$cleanup_wot'(codes(Codes), Stream) :- !,
|
||||||
|
charsio:peek_mem_write_stream(Stream, [], Codes),
|
||||||
|
close(Stream).
|
||||||
|
'$cleanup_wot'(codes(Codes, Tail), Stream) :- !,
|
||||||
|
charsio:peek_mem_write_stream(Stream, Tail, Codes),
|
||||||
|
close(Stream).
|
||||||
|
'$cleanup_wot'(chars(Chars), Stream) :- !,
|
||||||
|
charsio:peek_mem_write_stream(Stream, [], String),
|
||||||
|
'$codes_to_chars'([], String, Chars),
|
||||||
|
close(Stream).
|
||||||
|
'$cleanup_wot'(chars(Chars, Tail), Stream) :- !,
|
||||||
|
charsio:peek_mem_write_stream(Stream, Tail, String),
|
||||||
|
'$codes_to_chars'(Tail, String, Chars),
|
||||||
|
close(Stream).
|
||||||
|
'$cleanup_wot'(_, _).
|
||||||
|
|
||||||
|
'$codes_to_chars'(String0, String, String0) :- String0 == String, !.
|
||||||
|
'$codes_to_chars'(String0, [Code|String], [Char|Chars]) :-
|
||||||
|
atom_codes(Char, [Code]),
|
||||||
|
'$codes_to_chars'(String0, String, Chars).
|
Reference in New Issue
Block a user