popen support

This commit is contained in:
Vitor Santos Costa 2018-04-24 17:51:00 +01:00
parent 2c1d6910de
commit af848f28aa
10 changed files with 788 additions and 750 deletions

View File

@ -2119,7 +2119,7 @@ X_API int YAP_InitConsult(int mode, const char *fname, char **full, int *osnop)
}
}
bool consulted = (mode == YAP_CONSULT_MODE);
sno = Yap_OpenStream(fl, "r", MkAtomTerm(Yap_LookupAtom(fl)), LOCAL_encoding);
sno = Yap_OpenStream(MkStringTerm(fl), "r", MkAtomTerm(Yap_LookupAtom(fl)), LOCAL_encoding);
if (sno < 0 ||
!Yap_ChDir(dirname((char *)fl))) {
pop_text_stack(lvl);

View File

@ -290,7 +290,6 @@ A OutOfStackError N "out_of_stack_error"
A OutOfTrailError N "out_of_trail_error"
A Output N "output"
A Parameter N "parameter"
A PrologCommonsDir N "prolog_commons_directory"
A Past N "past"
A PastEndOfStream N "past_end_of_stream"
A PermissionError N "permission_error"
@ -299,6 +298,7 @@ A Pipe N "pipe"
A Priority N "priority"
A Plus N "+"
A Pointer N "pointer"
A Popen N "popen"
A Portray F "portray"
A PredicateIndicator N "predicate_indicator"
A Primitive N "primitive"
@ -307,6 +307,7 @@ A PrivateProcedure N "private_procedure"
A Procedure N "procedure"
A Profile F "$profile"
A Prolog N "prolog"
A PrologCommonsDir N "prolog_commons_directory"
A ProtectStack F "$protect_stack"
A Qly N "qly"
A Query N "?-"
@ -558,6 +559,7 @@ F Or Semic 2
F Output Output 1
F PermissionError PermissionError 3
F Plus Plus 2
F Popen Popen 1
F Portray Portray 1
F PrintMessage PrintMessage 2
F Procedure Procedure 5

View File

@ -285,7 +285,6 @@
AtomOutOfTrailError = Yap_LookupAtom("out_of_trail_error"); TermOutOfTrailError = MkAtomTerm(AtomOutOfTrailError);
AtomOutput = Yap_LookupAtom("output"); TermOutput = MkAtomTerm(AtomOutput);
AtomParameter = Yap_LookupAtom("parameter"); TermParameter = MkAtomTerm(AtomParameter);
AtomPrologCommonsDir = Yap_LookupAtom("prolog_commons_directory"); TermPrologCommonsDir = MkAtomTerm(AtomPrologCommonsDir);
AtomPast = Yap_LookupAtom("past"); TermPast = MkAtomTerm(AtomPast);
AtomPastEndOfStream = Yap_LookupAtom("past_end_of_stream"); TermPastEndOfStream = MkAtomTerm(AtomPastEndOfStream);
AtomPermissionError = Yap_LookupAtom("permission_error"); TermPermissionError = MkAtomTerm(AtomPermissionError);
@ -294,6 +293,7 @@
AtomPriority = Yap_LookupAtom("priority"); TermPriority = MkAtomTerm(AtomPriority);
AtomPlus = Yap_LookupAtom("+"); TermPlus = MkAtomTerm(AtomPlus);
AtomPointer = Yap_LookupAtom("pointer"); TermPointer = MkAtomTerm(AtomPointer);
AtomPopen = Yap_LookupAtom("popen"); TermPopen = MkAtomTerm(AtomPopen);
AtomPortray = Yap_FullLookupAtom("portray"); TermPortray = MkAtomTerm(AtomPortray);
AtomPredicateIndicator = Yap_LookupAtom("predicate_indicator"); TermPredicateIndicator = MkAtomTerm(AtomPredicateIndicator);
AtomPrimitive = Yap_LookupAtom("primitive"); TermPrimitive = MkAtomTerm(AtomPrimitive);
@ -302,6 +302,7 @@
AtomProcedure = Yap_LookupAtom("procedure"); TermProcedure = MkAtomTerm(AtomProcedure);
AtomProfile = Yap_FullLookupAtom("$profile"); TermProfile = MkAtomTerm(AtomProfile);
AtomProlog = Yap_LookupAtom("prolog"); TermProlog = MkAtomTerm(AtomProlog);
AtomPrologCommonsDir = Yap_LookupAtom("prolog_commons_directory"); TermPrologCommonsDir = MkAtomTerm(AtomPrologCommonsDir);
AtomProtectStack = Yap_FullLookupAtom("$protect_stack"); TermProtectStack = MkAtomTerm(AtomProtectStack);
AtomQly = Yap_LookupAtom("qly"); TermQly = MkAtomTerm(AtomQly);
AtomQuery = Yap_LookupAtom("?-"); TermQuery = MkAtomTerm(AtomQuery);
@ -553,6 +554,7 @@
FunctorOutput = Yap_MkFunctor(AtomOutput,1);
FunctorPermissionError = Yap_MkFunctor(AtomPermissionError,3);
FunctorPlus = Yap_MkFunctor(AtomPlus,2);
FunctorPopen = Yap_MkFunctor(AtomPopen,1);
FunctorPortray = Yap_MkFunctor(AtomPortray,1);
FunctorPrintMessage = Yap_MkFunctor(AtomPrintMessage,2);
FunctorProcedure = Yap_MkFunctor(AtomProcedure,5);

View File

@ -285,7 +285,6 @@
AtomOutOfTrailError = AtomAdjust(AtomOutOfTrailError); TermOutOfTrailError = MkAtomTerm(AtomOutOfTrailError);
AtomOutput = AtomAdjust(AtomOutput); TermOutput = MkAtomTerm(AtomOutput);
AtomParameter = AtomAdjust(AtomParameter); TermParameter = MkAtomTerm(AtomParameter);
AtomPrologCommonsDir = AtomAdjust(AtomPrologCommonsDir); TermPrologCommonsDir = MkAtomTerm(AtomPrologCommonsDir);
AtomPast = AtomAdjust(AtomPast); TermPast = MkAtomTerm(AtomPast);
AtomPastEndOfStream = AtomAdjust(AtomPastEndOfStream); TermPastEndOfStream = MkAtomTerm(AtomPastEndOfStream);
AtomPermissionError = AtomAdjust(AtomPermissionError); TermPermissionError = MkAtomTerm(AtomPermissionError);
@ -294,6 +293,7 @@
AtomPriority = AtomAdjust(AtomPriority); TermPriority = MkAtomTerm(AtomPriority);
AtomPlus = AtomAdjust(AtomPlus); TermPlus = MkAtomTerm(AtomPlus);
AtomPointer = AtomAdjust(AtomPointer); TermPointer = MkAtomTerm(AtomPointer);
AtomPopen = AtomAdjust(AtomPopen); TermPopen = MkAtomTerm(AtomPopen);
AtomPortray = AtomAdjust(AtomPortray); TermPortray = MkAtomTerm(AtomPortray);
AtomPredicateIndicator = AtomAdjust(AtomPredicateIndicator); TermPredicateIndicator = MkAtomTerm(AtomPredicateIndicator);
AtomPrimitive = AtomAdjust(AtomPrimitive); TermPrimitive = MkAtomTerm(AtomPrimitive);
@ -302,6 +302,7 @@
AtomProcedure = AtomAdjust(AtomProcedure); TermProcedure = MkAtomTerm(AtomProcedure);
AtomProfile = AtomAdjust(AtomProfile); TermProfile = MkAtomTerm(AtomProfile);
AtomProlog = AtomAdjust(AtomProlog); TermProlog = MkAtomTerm(AtomProlog);
AtomPrologCommonsDir = AtomAdjust(AtomPrologCommonsDir); TermPrologCommonsDir = MkAtomTerm(AtomPrologCommonsDir);
AtomProtectStack = AtomAdjust(AtomProtectStack); TermProtectStack = MkAtomTerm(AtomProtectStack);
AtomQly = AtomAdjust(AtomQly); TermQly = MkAtomTerm(AtomQly);
AtomQuery = AtomAdjust(AtomQuery); TermQuery = MkAtomTerm(AtomQuery);
@ -553,6 +554,7 @@
FunctorOutput = FuncAdjust(FunctorOutput);
FunctorPermissionError = FuncAdjust(FunctorPermissionError);
FunctorPlus = FuncAdjust(FunctorPlus);
FunctorPopen = FuncAdjust(FunctorPopen);
FunctorPortray = FuncAdjust(FunctorPortray);
FunctorPrintMessage = FuncAdjust(FunctorPrintMessage);
FunctorProcedure = FuncAdjust(FunctorProcedure);

View File

@ -285,7 +285,6 @@ X_API EXTERNAL Atom AtomOutOfStackError; X_API EXTERNAL Term TermOutOfStackError
X_API EXTERNAL Atom AtomOutOfTrailError; X_API EXTERNAL Term TermOutOfTrailError;
X_API EXTERNAL Atom AtomOutput; X_API EXTERNAL Term TermOutput;
X_API EXTERNAL Atom AtomParameter; X_API EXTERNAL Term TermParameter;
X_API EXTERNAL Atom AtomPrologCommonsDir; X_API EXTERNAL Term TermPrologCommonsDir;
X_API EXTERNAL Atom AtomPast; X_API EXTERNAL Term TermPast;
X_API EXTERNAL Atom AtomPastEndOfStream; X_API EXTERNAL Term TermPastEndOfStream;
X_API EXTERNAL Atom AtomPermissionError; X_API EXTERNAL Term TermPermissionError;
@ -294,6 +293,7 @@ X_API EXTERNAL Atom AtomPipe; X_API EXTERNAL Term TermPipe;
X_API EXTERNAL Atom AtomPriority; X_API EXTERNAL Term TermPriority;
X_API EXTERNAL Atom AtomPlus; X_API EXTERNAL Term TermPlus;
X_API EXTERNAL Atom AtomPointer; X_API EXTERNAL Term TermPointer;
X_API EXTERNAL Atom AtomPopen; X_API EXTERNAL Term TermPopen;
X_API EXTERNAL Atom AtomPortray; X_API EXTERNAL Term TermPortray;
X_API EXTERNAL Atom AtomPredicateIndicator; X_API EXTERNAL Term TermPredicateIndicator;
X_API EXTERNAL Atom AtomPrimitive; X_API EXTERNAL Term TermPrimitive;
@ -302,6 +302,7 @@ X_API EXTERNAL Atom AtomPrivateProcedure; X_API EXTERNAL Term TermPrivateProcedu
X_API EXTERNAL Atom AtomProcedure; X_API EXTERNAL Term TermProcedure;
X_API EXTERNAL Atom AtomProfile; X_API EXTERNAL Term TermProfile;
X_API EXTERNAL Atom AtomProlog; X_API EXTERNAL Term TermProlog;
X_API EXTERNAL Atom AtomPrologCommonsDir; X_API EXTERNAL Term TermPrologCommonsDir;
X_API EXTERNAL Atom AtomProtectStack; X_API EXTERNAL Term TermProtectStack;
X_API EXTERNAL Atom AtomQly; X_API EXTERNAL Term TermQly;
X_API EXTERNAL Atom AtomQuery; X_API EXTERNAL Term TermQuery;
@ -662,6 +663,8 @@ X_API EXTERNAL Functor FunctorPermissionError;
X_API EXTERNAL Functor FunctorPlus;
X_API EXTERNAL Functor FunctorPopen;
X_API EXTERNAL Functor FunctorPortray;
X_API EXTERNAL Functor FunctorPrintMessage;

View File

@ -64,21 +64,6 @@ available by loading the
:- use_module(library(readutil),
[read_line_to_codes/2]).
re_open(S, Mode, S) :-
is_stream(S),
!,
current_stream(_, Mode, S).
re_open(F, Mode, S) :-
open(F, Mode, S).
re_open(S, Mode, S, Props) :-
is_stream(S),
!,
current_stream(_, Mode, S),
maplist( set_stream(S), Props).
re_open(F, Mode, S, Props) :-
open(F, Mode, S, Props).
/**
@pred search_for(+ _Char_,+ _Line_)
Search for a character _Char_ in the list of codes _Line_.
@ -469,8 +454,8 @@ process(StreamInp, Command) :-
the output stream is accessible through `filter_output`.
*/
file_filter(Inp, Out, Command) :-
re_open(Inp, read, StreamInp, [alias(filter_input)]),
re_open(Out, write, StreamOut),
open(Inp, read, StreamInp, [alias(filter_input)]),
open(Out, write, StreamOut),
filter(StreamInp, StreamOut, Command),
close(StreamInp),
close(StreamOut).
@ -482,8 +467,8 @@ Same as file_filter/3, but before starting the filter execute
_Arguments_.
*/
file_filter_with_initialization(Inp, Out, Command, FormatString, Parameters) :-
re_open(Inp, read, StreamInp, [alias(filter_input)]),
re_open(Out, write, StreamOut, [alias(filter_output)]),
open(Inp, read, StreamInp, [alias(filter_input)]),
open(Out, write, StreamOut, [alias(filter_output)]),
format(StreamOut, FormatString, Parameters),
filter(StreamInp, StreamOut, Command),
close(StreamInp),
@ -498,8 +483,8 @@ _StartGoal_, and call _ENdGoal_ as an epilog.
The input stream are always accessible through `filter_output` and `filter_input`.
*/
file_filter_with_start_end(Inp, Out, Command, StartGoal, EndGoal) :-
re_open(Inp, read, StreamInp, [alias(filter_input)]),
re_open(Out, write, StreamOut, [alias(filter_output)]),
open(Inp, read, StreamInp, [alias(filter_input)]),
open(Out, write, StreamOut, [alias(filter_output)]),
call( StartGoal, StreamInp, StreamOut ),
filter(StreamInp, StreamOut, Command),
call( EndGoal, StreamInp, StreamOut ),
@ -525,7 +510,7 @@ file_filter_with_start_end(Inp, Out, Command, StartGoal, EndGoal) :-
file_select(Inp, Command) :-
( retract(alias(F)) -> true ; F = '' ),
atom_concat(filter_input, F, Alias),
re_open(Inp, read, StreamInp, [Alias]),
open(Inp, read, StreamInp, [Alias]),
atom_concat('_', F, NF),
assert( alias(NF) ),
repeat,

View File

@ -74,44 +74,7 @@ are available through the `use_module(library(system))` command.
*/
/**
@pred datime(datime(- _Year_, - _Month_, - _DayOfTheMonth_, - _Hour_, - _Minute_, - _Second_)
The datime/1 procedure returns the current date and time, with
information on _Year_, _Month_, _DayOfTheMonth_,
_Hour_, _Minute_, and _Second_. The _Hour_ is returned
on local time. This function uses the WIN32
`GetLocalTime` function or the Unix `localtime` function.
~~~~~
?- datime(X).
X = datime(2001,5,28,15,29,46) ?
~~~~~
*/
/** @pred environ(+ _E_,- _S_)
Given an environment variable _E_ this predicate unifies the second argument _S_ with its value.
*/
/** @pred system(+ _S_)
Passes command _S_ to the Bourne shell (on UNIX environments) or the
current command interpreter in WIN32 environments.
*/
/** @pred working_directory(- _CurDir_,? _NextDir_)
@ -176,27 +139,6 @@ X = 'C:\\cygwin\\home\\administrator' ?
~~~~~
*/
/** @pred exec(+ _Command_, _StandardStreams_,- _PID_)
Execute command _Command_ with its standard streams connected to
the list [_InputStream_, _OutputStream_, _ErrorStream_]. The
process that executes the command is returned as _PID_. The
command is executed by the default shell `bin/sh -c` in Unix.
The following example demonstrates the use of exec/3 to send a
command and process its output:
~~~~~
exec(ls,[std,pipe(S),null],P),repeat, get0(S,C), (C = -1, close(S) ! ; put(C)).
~~~~~
The streams may be one of standard stream, `std`, null stream,
`null`, or `pipe(S)`, where _S_ is a pipe stream. Note
that it is up to the user to close the pipe.
*/
/** @pred file_exists(+ _File_)
@ -289,37 +231,7 @@ process. An interface to the <tt>getpid</tt> function.
*/
/** @pred popen(+ _Command_, + _TYPE_, - _Stream_)
Interface to the <tt>popen</tt> function. It opens a process by creating a
pipe, forking and invoking _Command_ on the current shell. Since a
pipe is by definition unidirectional the _Type_ argument may be
`read` or `write`, not both. The stream should be closed
using close/1, there is no need for a special `pclose`
command.
The following example demonstrates the use of popen/3 to process
the output of a command, as exec/3 would do:
~~~~~{.prolog}
?- popen(ls,read,X),repeat, get0(X,C), (C = -1, ! ; put(C)).
X = 'C:\\cygwin\\home\\administrator' ?
~~~~~
The WIN32 implementation of popen/3 relies on exec/3.
*/
/** @pred rename_file(+ _OldFile_,+ _NewFile_)
Create file _OldFile_ to _NewFile_. This predicate uses the
`C` built-in function `rename`.
*/
/** @pred read_link(+ SymbolicLink, -Link, -NewPath)
@ -423,6 +335,24 @@ also `absolute_file_name/2` and chdir/1.
% time builtins
/**
@pred datime(datime(- _Year_, - _Month_, - _DayOfTheMonth_, - _Hour_, - _Minute_, - _Second_)
The datime/1 procedure returns the current date and time, with
information on _Year_, _Month_, _DayOfTheMonth_,
_Hour_, _Minute_, and _Second_. The _Hour_ is returned
on local time. This function uses the WIN32
`GetLocalTime` function or the Unix `localtime` function.
~~~~~
?- datime(X).
X = datime(2001,5,28,15,29,46) ?
~~~~~
*/
datime(X) :-
datime(X, Error),
handle_system_internal(Error, off, datime(X)).
@ -567,10 +497,14 @@ file_property(File, Type, Size, Date, Permissions, LinkName) :-
handle_system_internal(Error, off, file_property(File)).
%
% environment manipulation.
%
/** @pred environ(+E, -S)
Given an environment variable _E_ this predicate unifies the second
argument _S_ with its value. _E_ may be bound to an atom, or just be
unbound. In the latter case environ/2 will enumerate over all
environment variables.
*/
environ(Na,Val) :- var(Na), !,
environ_enum(0,I),
( p_environ(I,S) -> environ_split(S,SNa,SVal) ; !, fail ),
@ -597,9 +531,33 @@ environ_split([61|SVal], [], SVal) :- !.
environ_split([C|S],[C|SNa],SVal) :-
environ_split(S,SNa,SVal).
%
% process execution
%
/** @pred exec(+ _Command_, _StandardStreams_,- _PID_)
*
*
*
* Execute command _Command_ with its standard streams connected to the
* list [_InputStream_, _OutputStream_, _ErrorStream_]. A numeric
* identifier to the process that executes the command is returned as
* _PID_. The command is executed by the default shell `bin/sh -c` in
* Unix.
*
* The following example demonstrates the use of exec/3 to send a
* command and process its output:
*
* ~~~~~
go :-
exec(ls,[std,pipe(S),null],P),
repeat,
get0(S,C),
(C = -1, close(S) ! ; put(C)).
~~~~~
*
* The streams may be one of standard stream, `std`, null stream,
* `null`, or `pipe(S)`, where _S_ is a pipe stream. Note
* that it is up to the user to close the pipe.
*
*
*/
exec(Command, [StdIn, StdOut, StdErr], PID) :-
G = exec(Command, [StdIn, StdOut, StdErr], PID),
check_command_with_default_shell(Command, TrueCommand, G),
@ -652,8 +610,32 @@ close_temp_streams([S|Ss]) :-
close(S),
close_temp_streams(Ss).
popen(Command, Mode, Stream) :-
open(pipe(Command), Mode, Stream).
/** @pred popen(+ _Command_, + _TYPE_, - _Stream_)
* Provides the functionaluty of the Unix <tt>popen</tt> function. It
* opens a process by creating a pipe, forking and invoking _Command_ on
* the child process. Since a pipe is by definition unidirectional the
* _Type_ argument may be `read` or `write`, not both. The stream should
* be closed using close/1, there is no need for a special `pclose`
* command.
*
* The following example demonstrates the use of popen/3 to process the
* output of a command, note that popen/3 works as a simplified interface
* to the exec/3 command:
*
~~~~~{.prolog}
?- popen(ls,read,X),repeat, get0(X,C), (C = -1, ! ; put(C)).
X = 'C:\\cygwin\\home\\administrator' ?
~~~~~
*
* The implementation of popen/3 relies on exec/3.
*
*/
popen(Command, read, Stream) :-
exec(Command, [std,pipe(Stream),std], Stream).
popen(Command, write, Stream) :-
exec(Command, [pipe(Stream),std,std], Stream).
check_command_with_default_shell(Com, ComF, G) :-
check_command(Com, G),
@ -811,5 +793,23 @@ read_link(P,D,F) :-
read_link(P, D),
absolute_file_name(D, [], F).
/** @pred rename_file(+ _OldFile_,+ _NewFile_)
Create file _OldFile_ to _NewFile_. This predicate uses the
`C` built-in function `rename`.
*/
rename_file(F0, F) :-
rename_file(F0, F, Error),
handle_system_internal(Error, off, rename_file(F0, F))).
/** @pred system(+ _S_)
Passes command _S_ to the Bourne shell (on UNIX environments) or the
current command interpreter in WIN32 environments.
*/
/** @} */

View File

@ -729,7 +729,15 @@ static YAP_Bool execute_command(void) {
#endif /* UNIX code */
}
/* execute a command as a detached process */
/** @pred system(+ _S_)
Passes command _S_ to the Bourne shell (on UNIX environments) or the
current command interpreter in WIN32 environments.
Note that it executes them command as a detached process. It requires
`system` to be implemented by the system library.
*/
static YAP_Bool do_system(void) {
char *command = (char *)YAP_AtomName(YAP_AtomOfTerm(YAP_ARG1));
#if HAVE_SYSTEM

View File

@ -1339,7 +1339,7 @@ do_open(Term file_name, Term t2,
"type is ~a, must be one of binary or text", t);
}
}
if ((sno = Yap_OpenStream(fname, io_mode, file_name, encoding)) < 0)
if ((sno = Yap_OpenStream(file_name, io_mode, file_name, encoding)) < 0)
{
pop_text_stack(lvl);
return false;
@ -1413,20 +1413,20 @@ do_open(Term file_name, Term t2,
/** @pred open(+ _F_,+ _M_,- _S_) is iso
Opens the file with name _F_ in mode _M_ (`read`, `write` or
`append`), returning _S_ unified with the stream name.
Opens the file with name _F_ in mode _M_ (`read`, `write` or
`append`), returning _S_ unified with the stream name.
Yap allows 64 streams opened at the same time. If you need more,
Yap allows 64 streams opened at the same time. If you need more,
redefine the MaxStreams constant. Each stream is either an input or
an output stream but not both. There are always 3 open streams:
user_input for reading, user_output for writing and user_error for
writing. If there is no ambiguity, the atoms user_input and
user_output may be referred to as `user`.
The `file_errors` flag controls whether errors are reported when in
mode `read` or `append` the file _F_ does not exist or is not
readable, and whether in mode `write` or `append` the file is not
writable.
The `file_errors` flag controls whether errors are reported when in
mode `read` or `append` the file _F_ does not exist or is not
readable, and whether in mode `write` or `append` the file is not
writable.
*/
@ -1437,73 +1437,73 @@ static Int open3(USES_REGS1) {
/** @pred open(+ _F_,+ _M_,- _S_,+ _Opts_) is iso
Opens the file with name _F_ in mode _M_ (`read`, `write` or
`append`), returning _S_ unified with the stream name, and following
these options:
Opens the file with name _F_ in mode _M_ (`read`, `write` or
`append`), returning _S_ unified with the stream name, and following
these options:
+ `type(+ _T_)` is iso
+ `type(+ _T_)` is iso
Specify whether the stream is a `text` stream (default), or a
`binary` stream.
`binary` stream.
+ `reposition(+ _Bool_)` is iso
+ `reposition(+ _Bool_)` is iso
Specify whether it is possible to reposition the stream (`true`), or
not (`false`). By default, YAP enables repositioning for all
files, except terminal files and sockets.
not (`false`). By default, YAP enables repositioning for all
files, except terminal files and sockets.
+ `eof(+ _Action_)` is iso
+ `eof(+ _Action_)` is iso
Specify the action to take if attempting to input characters from a
stream where we have previously found an `end_of_file`. The possible
actions are `error`, that raises an error, `reset`, that tries to
reset the stream and is used for `tty` type files, and `eof_code`,
which generates a new `end_of_file` (default for non-tty files).
stream where we have previously found an `end_of_file`. The possible
actions are `error`, that raises an error, `reset`, that tries to
reset the stream and is used for `tty` type files, and `eof_code`,
which generates a new `end_of_file` (default for non-tty files).
+ `alias(+ _Name_)` is iso
+ `alias(+ _Name_)` is iso
Specify an alias to the stream. The alias <tt>Name</tt> must be an atom.
The
alias can be used instead of the stream descriptor for every operation
concerning the stream.
The
alias can be used instead of the stream descriptor for every operation
concerning the stream.
The operation will fail and give an error if the alias name is already
in use. YAP allows several aliases for the same file, but only
one is returned by stream_property/2
in use. YAP allows several aliases for the same file, but only
one is returned by stream_property/2
+ `bom(+ _Bool_)`
+ `bom(+ _Bool_)`
If present and `true`, a BOM (<em>Byte Order Mark</em>) was
detected while opening the file for reading or a BOM was written while
opening the stream. See BOM for details.
detected while opening the file for reading or a BOM was written while
opening the stream. See BOM for details.
+ `encoding(+ _Encoding_)`
+ `encoding(+ _Encoding_)`
Set the encoding used for text. See Encoding for an overview of
wide character and encoding issues.
Set the encoding used for text. See Encoding for an overview of
wide character and encoding issues.
+ `representation_errors(+ _Mode_)`
+ `representation_errors(+ _Mode_)`
Change the behaviour when writing characters to the stream that cannot
be represented by the encoding. The behaviour is one of `error`
(throw and Input/Output error exception), `prolog` (write `\u...\`
escape code or `xml` (write `\&#...;` XML character entity).
The initial mode is `prolog` for the user streams and
`error` for all other streams. See also Encoding.
be represented by the encoding. The behaviour is one of `error`
(throw and Input/Output error exception), `prolog` (write `\u...\`
escape code or `xml` (write `\&#...;` XML character entity).
The initial mode is `prolog` for the user streams and
`error` for all other streams. See also Encoding.
+ `expand_filename(+ _Mode_)`
+ `expand_filename(+ _Mode_)`
If _Mode_ is `true` then do filename expansion, then ask Prolog
to do file name expansion before actually trying to opening the file:
this includes processing `~` characters and processing `$`
environment variables at the beginning of the file. Otherwise, just try
to open the file using the given name.
to do file name expansion before actually trying to opening the file:
this includes processing `~` characters and processing `$`
environment variables at the beginning of the file. Otherwise, just try
to open the file using the given name.
The default behavior is given by the Prolog flag
open_expands_filename.
open_expands_filename.
+ `script( + _Boolean_ )` YAP extension.
+ `script( + _Boolean_ )` YAP extension.
The file may be a Prolog script. In `read` mode just check for
initial lines if they start with the hash symbol, and skip them. In
@ -1571,23 +1571,27 @@ static Int p_open_null_stream(USES_REGS1) {
return (Yap_unify(ARG1, t));
}
int Yap_OpenStream(const char *fname, const char* io_mode, Term user_name, encoding_t enc) {
int Yap_OpenStream(Term tin, const char* io_mode, Term user_name, encoding_t enc) {
CACHE_REGS
int sno;
StreamDesc *st;
struct vfs *vfsp;
int flags;
const char *fname;
sno = GetFreeStreamD();
if (sno < 0) {
PlIOError(RESOURCE_ERROR_MAX_STREAMS, MkAtomTerm(Yap_LookupAtom(fname)),
"new stream not available for opening");
PlIOError(RESOURCE_ERROR_MAX_STREAMS,tin, "new stream not available for opening");
return -1;
}
st = GLOBAL_Stream + sno;
// fname = Yap_VF(fname);
flags = 0;
if ((vfsp = vfs_owner(fname)) != NULL) {
if ((((IsAtomTerm(tin) &&
(fname = RepAtom(AtomOfTerm(tin))->StrOfAE))) ||
(IsStringTerm(tin) &&
(fname =StringOfTerm(tin)))) &&
((vfsp = vfs_owner(fname)) != NULL)) {
if (!vfsp->open(vfsp, fname, io_mode, sno)) {
UNLOCK(st->streamlock);
PlIOError(EXISTENCE_ERROR_SOURCE_SINK, MkAtomTerm(Yap_LookupAtom(fname)),
@ -1597,8 +1601,41 @@ int Yap_OpenStream(const char *fname, const char* io_mode, Term user_name, encod
}
// read, write, append
user_name = st->user_name;
} else if (IsApplTerm(tin)) {
Functor f = FunctorOfTerm(tin);
if (f == FunctorAtom || f == FunctorString || f == FunctorCodes1 ||
f == FunctorCodes || f == FunctorChars1 || f == FunctorChars) {
if (strchr(io_mode, 'r')) {
return Yap_OpenBufWriteStream(PASS_REGS1);
} else {
int i = push_text_stack();
const char *buf;
buf = Yap_TextTermToText(tin PASS_REGS);
if (!buf) {
return false;
}
buf = pop_output_text_stack(i, buf);
sno = Yap_open_buf_read_stream(buf, strlen(buf) + 1, &LOCAL_encoding,
MEM_BUF_MALLOC);
return Yap_OpenBufWriteStream(PASS_REGS1);
}
} else if (f == FunctorPopen) {
const char *buf;
int i = push_text_stack();
buf = Yap_TextTermToText(tin PASS_REGS);
if (!buf) {
return false;
}
pop_text_stack(i);
#if _WIN32
st->file = _popen(buf, io_mode);
#else
st->file = popen(buf, io_mode);
#endif
} else {
st->file = fopen(fname, io_mode);
}
if (st->file == NULL) {
if (!strchr(io_mode, 'b') && binary_file(fname)) {
UNLOCK(st->streamlock);
@ -1611,17 +1648,16 @@ int Yap_OpenStream(const char *fname, const char* io_mode, Term user_name, encod
MkAtomTerm(Yap_LookupAtom(fname)), "%s: %s", fname,
strerror(errno));
}
}
return -1;
}
}
}}
Yap_initStream(sno, st->file, fname, io_mode, user_name, LOCAL_encoding, flags, vfsp);
__android_log_print(ANDROID_LOG_INFO, "YAPDroid", "exists %s <%d>", fname,
sno);
return sno;
}
}
int Yap_FileStream(FILE *fd, char *name, Term file_name, int flags,
int Yap_FileStream(FILE *fd, char *name, Term file_name, int flags,
VFS_t *vfsp) {
CACHE_REGS
int sno;
@ -1641,12 +1677,12 @@ int Yap_FileStream(FILE *fd, char *name, Term file_name, int flags,
}
Yap_initStream(sno, fd, name, mode, file_name, LOCAL_encoding, flags, vfsp);
return sno;
}
}
#define CheckStream(arg, kind, msg) \
CheckStream__(__FILE__, __FUNCTION__, __LINE__, arg, kind, msg)
static int CheckStream__(const char *file, const char *f, int line, Term arg,
static int CheckStream__(const char *file, const char *f, int line, Term arg,
int kind, const char *msg) {
int sno = -1;
arg = Deref(arg);
@ -1703,14 +1739,14 @@ static int CheckStream__(const char *file, const char *f, int line, Term arg,
return -1;
}
return sno;
}
}
int Yap_CheckStream__(const char *file, const char *f, int line, Term arg,
int Yap_CheckStream__(const char *file, const char *f, int line, Term arg,
int kind, const char *msg) {
return CheckStream__(file, f, line, arg, kind, msg);
}
}
int Yap_CheckTextStream__(const char *file, const char *f, int line, Term arg,
int Yap_CheckTextStream__(const char *file, const char *f, int line, Term arg,
int kind, const char *msg) {
int sno;
if ((sno = CheckStream__(file, f, line, arg, kind, msg)) < 0)
@ -1726,9 +1762,9 @@ int Yap_CheckTextStream__(const char *file, const char *f, int line, Term arg,
return -1;
}
return sno;
}
}
int Yap_CheckBinaryStream__(const char *file, const char *f, int line, Term arg,
int Yap_CheckBinaryStream__(const char *file, const char *f, int line, Term arg,
int kind, const char *msg) {
int sno;
if ((sno = CheckStream__(file, f, line, arg, kind, msg)) < 0)
@ -1742,10 +1778,10 @@ int Yap_CheckBinaryStream__(const char *file, const char *f, int line, Term arg,
return -1;
}
return sno;
}
}
/* used from C-interface */
int Yap_GetFreeStreamDForReading(void) {
/* used from C-interface */
int Yap_GetFreeStreamDForReading(void) {
int sno = GetFreeStreamD();
StreamDesc *s;
@ -1759,29 +1795,29 @@ int Yap_GetFreeStreamDForReading(void) {
Yap_DefaultStreamOps(s);
UNLOCK(s->streamlock);
return sno;
}
}
/**
/**
* @pred always_prompt_user
*
* Ensure that the stream always prompts before asking the standard input
stream for data.
*/
static Int always_prompt_user(USES_REGS1) {
static Int always_prompt_user(USES_REGS1) {
StreamDesc *s = GLOBAL_Stream + StdInStream;
s->status |= Promptable_Stream_f;
Yap_DefaultStreamOps(s);
return (TRUE);
}
}
static Int close1 /** @pred close(+ _S_) is iso
static Int close1 /** @pred close(+ _S_) is iso
Closes the stream _S_. If _S_ does not stand for a stream
currently opened an error is reported. The streams user_input,
user_output, and user_error can never be closed.
Closes the stream _S_. If _S_ does not stand for a stream
currently opened an error is reported. The streams user_input,
user_output, and user_error can never be closed.
*/
@ -1798,33 +1834,33 @@ static Int close1 /** @pred close(+ _S_) is iso
Yap_CloseStream(sno);
UNLOCK(GLOBAL_Stream[sno].streamlock);
return (TRUE);
}
}
#define CLOSE_DEFS() \
PAR("force", booleanFlag, CLOSE_FORCE), PAR(NULL, ok, CLOSE_END)
#define PAR(x, y, z) z
typedef enum close_enum_choices { CLOSE_DEFS() } close_choices_t;
typedef enum close_enum_choices { CLOSE_DEFS() } close_choices_t;
#undef PAR
#define PAR(x, y, z) \
{ x, y, z }
static const param_t close_defs[] = {CLOSE_DEFS()};
static const param_t close_defs[] = {CLOSE_DEFS()};
#undef PAR
/** @pred close(+ _S_,+ _O_) is iso
/** @pred close(+ _S_,+ _O_) is iso
Closes the stream _S_, following options _O_.
Closes the stream _S_, following options _O_.
The only valid options are `force(true)` and `force(false)`.
YAP currently ignores these options.
The only valid options are `force(true)` and `force(false)`.
YAP currently ignores these options.
*/
static Int close2(USES_REGS1) { /* '$close'(+GLOBAL_Stream) */
*/
static Int close2(USES_REGS1) { /* '$close'(+GLOBAL_Stream) */
Int sno = CheckStream(
ARG1, (Input_Stream_f | Output_Stream_f | Socket_Stream_f), "close/2");
Term tlist;
@ -1849,9 +1885,9 @@ static Int close2(USES_REGS1) { /* '$close'(+GLOBAL_Stream) */
Yap_CloseStream(sno);
UNLOCK(GLOBAL_Stream[sno].streamlock);
return (TRUE);
}
}
Term read_line(int sno) {
Term read_line(int sno) {
CACHE_REGS
Term tail;
Int ch;
@ -1861,7 +1897,7 @@ Term read_line(int sno) {
}
tail = read_line(sno);
return (MkPairTerm(MkIntTerm(ch), tail));
}
}
#define ABSOLUTE_FILE_NAME_DEFS() \
PAR("access", isatom, ABSOLUTE_FILE_NAME_ACCESS) \
@ -1878,20 +1914,20 @@ Term read_line(int sno) {
#define PAR(x, y, z) z
typedef enum ABSOLUTE_FILE_NAME_enum_ {
typedef enum ABSOLUTE_FILE_NAME_enum_ {
ABSOLUTE_FILE_NAME_DEFS()
} absolute_file_name_choices_t;
} absolute_file_name_choices_t;
#undef PAR
#define PAR(x, y, z) \
{ x, y, z }
static const param_t absolute_file_name_search_defs[] = {
static const param_t absolute_file_name_search_defs[] = {
ABSOLUTE_FILE_NAME_DEFS()};
#undef PAR
static Int abs_file_parameters(USES_REGS1) {
static Int abs_file_parameters(USES_REGS1) {
Term t[ABSOLUTE_FILE_NAME_END];
Term tlist = Deref(ARG1), tf;
/* get options */
@ -1953,9 +1989,9 @@ static Int abs_file_parameters(USES_REGS1) {
tf = Yap_MkApplTerm(Yap_MkFunctor(AtomOpt, ABSOLUTE_FILE_NAME_END),
ABSOLUTE_FILE_NAME_END, t);
return (Yap_unify(ARG2, tf));
}
}
static Int get_abs_file_parameter(USES_REGS1) {
static Int get_abs_file_parameter(USES_REGS1) {
Term t = Deref(ARG1), topts = Deref(ARG2);
/* get options */
/* done */
@ -1965,9 +2001,9 @@ static Int get_abs_file_parameter(USES_REGS1) {
return Yap_unify(ARG3, ArgOfTerm(i + 1, topts));
Yap_Error(DOMAIN_ERROR_ABSOLUTE_FILE_NAME_OPTION, ARG1, NULL);
return false;
}
}
void Yap_InitPlIO(struct yap_boot_params *argi) {
void Yap_InitPlIO(struct yap_boot_params *argi) {
Int i;
if (argi->inp > 0)
Yap_stdin = fdopen(argi->inp - 1, "r");
@ -1994,9 +2030,9 @@ void Yap_InitPlIO(struct yap_boot_params *argi) {
GLOBAL_Stream[i].status = Free_Stream_f;
}
InitStdStreams();
}
}
void Yap_InitIOPreds(void) {
void Yap_InitIOPreds(void) {
/* here the Input/Output predicates */
Yap_InitCPred("always_prompt_user", 0, always_prompt_user,
SafePredFlag | SyncPredFlag);
@ -2032,4 +2068,4 @@ void Yap_InitIOPreds(void) {
Yap_InitSignalPreds();
Yap_InitSysPreds();
Yap_InitTimePreds();
}
}

View File

@ -86,7 +86,7 @@ extern int Yap_PlGetWchar(void);
extern int Yap_PlFGetchar(void);
extern int Yap_GetCharForSIGINT(void);
extern Int Yap_StreamToFileNo(Term);
extern int Yap_OpenStream(const char *fname, const char* io_mode, Term user_name, encoding_t enc);
extern int Yap_OpenStream(Term tin, const char* io_mode, Term user_name, encoding_t enc);
extern int Yap_FileStream(FILE*, char *, Term, int, VFS_t *);
extern char *Yap_TermToBuffer(Term t, encoding_t encoding, int flags);
extern char *Yap_HandleToString(yhandle_t l, size_t sz, size_t *length,