/************************************************************************* * * * YAP Prolog * * * * Yap Prolog was developed at NCCUP - Universidade do Porto * * * * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 * * * ************************************************************************** * * * File: yio.yap * * Last rev: * * mods: * * comments: Input output predicates * * * *************************************************************************/ :- system_module( '$_yio', [at_end_of_line/0, at_end_of_line/1, consult_depth/1, current_char_conversion/2, current_line_number/1, current_line_number/2, current_stream/3, display/1, display/2, exists/1, fileerrors/0, format/1, nofileerrors/0, open_pipe_streams/2, prolog_file_name/2, read/1, read/2, sformat/3, socket/2, socket/4, socket_connect/3, stream_position/2, stream_position/3, stream_position_data/3, ttyget/1, ttyget0/1, ttynl/0, ttyput/1, ttyskip/1, rename/2, write_depth/2], ['$default_expand'/1, '$extend_file_search_path'/1, '$set_default_expand'/1]). :- use_system_module( '$_boot', ['$system_catch'/4]). :- use_system_module( '$_errors', ['$do_error'/2]). /** @defgroup InputOutput Input/Output Predicates @ingroup builtins Some of the Input/Output predicates described below will in certain conditions provide error messages and abort only if the file_errors flag is set. If this flag is cleared the same predicates will just fail. Details on setting and clearing this flag are given under 7.7. @{ */ /* stream predicates */ /** @defgroup IO_Sockets YAP Old Style Socket and Pipe Interface @{ Autoload the socket/pipe library */ /** @pred socket(+ _DOMAIN_,- _SOCKET_) Call socket/4 with _TYPE_ bound to `SOCK_STREAM'` and _PROTOCOL_ bound to `0`. */ /** @pred socket(+ _DOMAIN_,+ _TYPE_,+ _PROTOCOL_,- _SOCKET_) Corresponds to the BSD system call `socket`. Create a socket for domain _DOMAIN_ of type _TYPE_ and protocol _PROTOCOL_. Both _DOMAIN_ and _TYPE_ should be atoms, whereas _PROTOCOL_ must be an integer. The new socket object is accessible through a descriptor bound to the variable _SOCKET_. The current implementation of YAP accepts socket domains `AF_INET` and `AF_UNIX`. Socket types depend on the underlying operating system, but at least the following types are supported: `SOCK_STREAM'` and `SOCK_DGRAM'` (untested in 6.3). */ /** @pred socket_connect(+ _SOCKET_, + _PORT_, - _STREAM_) Interface to system call `connect`, used for clients: connect socket _SOCKET_ to _PORT_. The connection results in the read/write stream _STREAM_. Port information depends on the domain: + 'AF_UNIX'(+ _FILENAME_) + 'AF_FILE'(+ _FILENAME_) connect to socket at file _FILENAME_. + 'AF_INET'(+ _HOST_,+ _PORT_) Connect to socket at host _HOST_ and port _PORT_. */ /** @pred open_pipe_streams(Read, Write) Autoload old pipe access interface */ %! @} /** @pred exists(+ _F_) Checks if file _F_ exists in the current directory. */ exists(F) :- absolute_file_name(F, _, [file_errors(fail),access(exist),expand(true)]). %! @addtogroup ReadTerm % @{ /* Term IO */ %! @} %! @addtogroup Write % @{ /* meaning of flags for '$write' is 1 quote illegal atoms 2 ignore operator declarations 4 output '$VAR'(N) terms as A, B, C, ... 8 use portray(_) flags are defined in yapio.h */ /** @pred display(+ _T_) Displays term _T_ on the current output stream. All Prolog terms are written in standard parenthesized prefix notation. */ display(T) :- current_output(Out), write_term(Out, T, [ignore_ops(true)]). /** @pred display(+ _S_, _T_) Like display/1, but using stream _S_ to display the term. */ display(Stream, T) :- write_term(Stream, T, [ignore_ops(true)]). /* interface to user portray */ '$portray'(T) :- \+ '$undefined'(portray(_),user), catch(user:portray(T),Error,'$Error'(Error)), !, set_value('$portray',true), fail. '$portray'(_) :- set_value('$portray',false), fail. %! @} %! @addtogroup Format % @{ /** @pred format(+ _T_) Print formatted output to the current output stream. */ format(T) :- format(T, []). %! @} %! @addtogroup CharsIO % @{ /* character I/O */ /** @pred ttyget(- _C_) The same as `get(C)`, but from stream user_input. */ ttyget(N) :- get(user_input,N). /** @pred ttyget0(- _C_) The same as `get0(C)`, but from stream user_input. */ ttyget0(N) :- get0(user_input,N). /** @pred ttyskip(- _C_) Like skip/1, but always using stream user_input. stream. */ ttyskip(N) :- N1 is N, '$skip'(user_input,N1). /** @pred ttyput(+ _N_) As `put(N)` but always to user_output. */ ttyput(N) :- N1 is N, put(user_output,N1). /** @pred ttynl Outputs a new line to stream user_output. */ ttynl :- nl(user_output). %! @} %! @addtogroup StreamM % @{ /** @pred current_line_number(- _LineNumber_) Unify _LineNumber_ with the line number for the current output stream. */ current_line_number(N) :- current_input(Stream), line_count(Stream, N). /** @pred current_line_number(+ _Stream_,- _LineNumber_) Unify _LineNumber_ with the line number for _Stream_. */ current_line_number(Stream,N) :- line_count(Stream, N). /** @pred stream_position(+ _Stream_,- _StreamPosition_) Unify _StreamPosition_ with the packaged information of position on current stream _Stream_. Use stream_position_data/3 to retrieve information on character or line count. */ stream_position(Stream, Position) :- stream_property(Stream, position(Position)). /** @pred stream_position(+ _Stream_,- _StreamPosition_, +_NewPosition_) Unify _StreamPosition_ with the packaged information of position on current stream _Stream_ an then moves to position _NewPosition_. */ stream_position(Stream, Position, NewPosition) :- stream_property(Stream, position(Position)), set_stream_position(Stream, NewPosition). /** @pred at_end_of_line Tests whether the next character in the current input stream is a line break character. */ at_end_of_line :- current_input(S), at_end_of_line(S). /** @pred at_end_of_line( +Stream ) Tests whether the next character in the stream is a line break character. */ at_end_of_line(S) :- stream_property(S, end_of_stream(past)), !. at_end_of_line(S) :- peek_code(S,N), ( N = 10 -> true ; N = -1). /** @pred current_char_conversion(? _IN_,? _OUT_) is iso If _IN_ is unbound give all current character translations. Otherwise, give the translation for _IN_, if one exists. */ current_char_conversion(X,Y) :- var(X), !, '$all_char_conversions'(List), '$fetch_char_conversion'(List,X,Y). current_char_conversion(X,Y) :- '$current_char_conversion'(X,Y). '$fetch_char_conversion'([X,Y|_],X,Y). '$fetch_char_conversion'([_,_|List],X,Y) :- '$fetch_char_conversion'(List,X,Y). split_path_file(File, Path, Name) :- file_directory_name(File, Path), file_base_name(File, Name). /** @pred current_stream( _F_, _M_, _S_) Defines the relation: The stream _S_ is opened on the file _F_ in mode _M_. It might be used to obtain all open streams (by backtracking) or to access the stream for a file _F_ in mode _M_, or to find properties for a stream _S_. Notice that some streams might not be associated to a file: in this case YAP tries to return the file number. If that is not available, YAP unifies _F_ with _S_. */ current_stream(File, Mode, Stream) :- stream_property(Stream, mode(Mode)), '$stream_name'(Stream, File). '$stream_name'(Stream, File) :- stream_property(Stream, file_name(File)), !. '$stream_name'(Stream, file_no(File)) :- stream_property(Stream, file_no(File)), !. '$stream_name'(Stream, Stream). '$extend_file_search_path'(P) :- atom_codes(P,S), '$env_separator'(ES), '$split_for_path'(S,0'=,ES,Paths), %' '$add_file_search_paths'(Paths). '$split_for_path'([], _, _, []). '$split_for_path'(S, S1, S2, [A1=A2|R]) :- '$fetch_first_path'(S, S1, A1, SR1), '$fetch_second_path'(SR1, S2, A2, SR), '$split_for_path'(SR, S1, S2, R) . '$fetch_first_path'([S1|SR],S1,[],SR) :- !. '$fetch_first_path'([C|S],S1,[C|F],SR) :- '$fetch_first_path'(S,S1,F,SR). '$fetch_second_path'([],_,[],[]). '$fetch_second_path'([S1|SR],S1,[],SR) :- !. '$fetch_second_path'([C|S],S1,[C|A2],SR) :- '$fetch_second_path'(S,S1,A2,SR). '$add_file_search_paths'([]). '$add_file_search_paths'([NS=DS|Paths]) :- atom_codes(N,NS), atom_codes(D,DS), assert(user:file_search_path(N,D)), '$add_file_search_paths'(Paths). '$format@'(Goal,Out) :- with_output_to(codes(Out), Goal). sformat(String, Form, Args) :- format(codes(String, []), Form, Args). /** @pred stream_position_data(+ _Field_,+ _StreamPosition_,- _Info_) Extract values from stream position objects. '$stream_position' is of the format '$stream_position'(Byte, Char, Line, LinePos). Given the packaged stream position term _StreamPosition_, unify _Info_ with _Field_ `line_count`, `byte_count`, or `char_count`. */ stream_position_data(Prop, Term, Value) :- nonvar(Prop), !, ( '$stream_position_field'(Prop, Pos) -> arg(Pos, Term, Value) ; '$do_error'(domain_error(stream_position_data), Prop) ). stream_position_data(Prop, Term, Value) :- '$stream_position_field'(Prop, Pos), arg(Pos, Term, Value). '$stream_position_field'(char_count, 1). '$stream_position_field'(line_count, 2). '$stream_position_field'(line_position, 3). '$stream_position_field'(byte_count, 4). '$set_encoding'(Enc) :- set_stream(loop_stream, encoding(Enc)). %! @} '$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). /** @pred file_exists(+ _File__) The atom _File_ corresponds to an existing file or directory. */ file_exists(IFile) :- absolute_file_name(IFile, _File, [expand(true), solutions(first), access(exist)]). /** @pred rename(+F , +G) Renames the single file _F_ to _G_. */ rename(IFile, OFile) :- absolute_file_name(IFile, IF, [access(read),expand(true)]), absolute_file_name(OFile, OF, [expand(true)]), '$rename'(IF, OF). /** @pred access_file(+F , +G) Verify whether file F respects property _G_. The file is processed with absolute_file_name. */ access_file(IFile, Access) :- absolute_file_name(IFile, _IF, [access(Access),expand(true)]). /** @} */