View source with formatted comments or as raw
    1/*  Part of SWI-Prolog
    2
    3    Author:        Jan Wielemaker, Johan Romme
    4    E-mail:        J.Wielemaker@cs.vu.nl
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (c)  2012-2016, VU University Amsterdam
    7    All rights reserved.
    8
    9    Redistribution and use in source and binary forms, with or without
   10    modification, are permitted provided that the following conditions
   11    are met:
   12
   13    1. Redistributions of source code must retain the above copyright
   14       notice, this list of conditions and the following disclaimer.
   15
   16    2. Redistributions in binary form must reproduce the above copyright
   17       notice, this list of conditions and the following disclaimer in
   18       the documentation and/or other materials provided with the
   19       distribution.
   20
   21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   24    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   25    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   26    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   27    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   28    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   29    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   31    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   32    POSSIBILITY OF SUCH DAMAGE.
   33*/
   34
   35:- module(ifprolog,
   36	  [ calling_context/1,			% -Module
   37	    context/2,				% :Goal, +Mapping
   38	    block/3,				% :Goal, +Tag, :Recovery
   39	    exit_block/1,			% +Tag
   40	    cut_block/1,			% +Tag
   41
   42	    modify_mode/3,			% +PI, -Old, +New
   43	    debug_mode/3,			% +PI, -Old, +New
   44	    ifprolog_debug/1,			% :Goal,
   45	    debug_config/3,			% +Key, +Current, +Value
   46	    float_format/2,			% -Old, +New
   47	    program_parameters/1,		% -Argv
   48	    user_parameters/1,			% -Argv
   49	    match/2,				% +Mask, +Atom
   50	    match/3,				% +Mask, +Atom, ?Replacements
   51	    lower_upper/2,			% ?Lower, ?Upper
   52	    current_error/1,			% -Stream
   53	    writeq_atom/2,			% +Term, -Atom
   54	    write_atom/2,			% +Term, -Atom
   55	    write_formatted_atom/3,		% -Atom, +Format, +ArgList
   56	    write_formatted/2,			% +Format, +ArgList
   57	    write_formatted/3,			% +Stream, +Format, +ArgList
   58	    atom_part/4,			% +Atom, +Pos, +Len, -Sub
   59	    atom_prefix/3,			% +Atom, +Len, -Sub
   60	    atom_suffix/3,			% +Atom, +Len, -Sub
   61	    atom_split/3,			% +Atom, +Delimiter, ?Subatoms
   62	    if_concat_atom/2,			% +List, ?Atom
   63	    if_concat_atom/3,			% +List, +Delimiter, ?Atom
   64	    getchar/3,				% +Atom, +Pos, -Char
   65	    parse_atom/6,			% +Atom, +StartPos, ?EndPos,
   66						% ?Term, ?VarList, ?Error
   67	    index/3,				% +Atom, +String, -Position
   68	    list_length/2,			% +List, ?Length
   69	    load/1,				% :FileName
   70%	    unload/1,				% +Module
   71	    file_test/2,			% +File, +Mode
   72	    filepos/2,				% @Stream, -Line
   73	    filepos/3,				% @Stream, -Line, -Column
   74	    getcwd/1,				% -Dir
   75	    assign_alias/2,			% +Alias, @Stream
   76	    get_until/3,			% +SearchChar, ?Text, ?EndChar
   77	    get_until/4,			% @In, +SearchChar, ?Text, ?EndChar
   78	    for/3,				% +Start, ?Counter, +End
   79	    prolog_version/1,                   % -Atom
   80	    proroot/1,				% -Atom
   81	    system_name/1,			% -Atom
   82	    localtime/9,			% +Time, ?Year, ?Month,
   83						% ?Day, ?DoW, ?DoY,
   84						% ?Hour, ?Min, ?Sec
   85
   86	    asserta_with_names/2,		% @Term, +VarNames
   87	    assertz_with_names/2,		% @Term, +VarNames
   88	    clause_with_names/3,		% ?Head, ?Body, ?VarNames
   89	    retract_with_names/2,		% ?Clause, ?VarNames
   90	    predicate_type/2,			% @Predicate, ?Type
   91	    current_visible/2,			% @Module, @Predicate
   92	    current_signal/2,			% ?Signal, ?Mode
   93	    digit/1,				% +Character
   94	    letter/1,				% +Character
   95
   96	    current_global/1,			% +Name
   97	    get_global/2,			% +Name, ?Value
   98	    set_global/2,			% +Name, ?Value
   99	    unset_global/1,			% +Name
  100
  101	    current_default_module/1,		% -Module
  102	    set_default_module/1,		% +Module
  103
  104	    op(1150, fx, (meta)),
  105	    op(1150, fx, (export)),
  106	    op(100, xfx, @),
  107	    op(900, xfx, =>),
  108	    op(900,  fy, not)
  109	  ]).  110:- use_module(library(debug)).  111:- use_module(library(arithmetic)).  112:- use_module(library(memfile)).  113:- use_module(library(apply)).  114:- set_prolog_flag(double_quotes, codes).  115
  116/** <module> IF/Prolog compatibility package
  117
  118This library realises emulation of IF/Prolog.  As with all the emulation
  119layers in the dialect directory, the   emulation has been established on
  120`as needed' basis from porting programs. This implies that the emulation
  121is incomplete. Emumated directives, predicates   and libraries are often
  122not 100% compatible with the IF/Prolog version.
  123
  124Note that this emulation layer targets primarily IF/Prolog version 5.
  125
  126Please   help   extending   this   library   and   submit   patches   to
  127bugs@swi-prolog.org.
  128*/
  129
  130:- module_transparent
  131	calling_context/1.  132
  133:- meta_predicate
  134	context(0, +),
  135	block(0, +, 0),
  136	modify_mode(:, -, +),
  137	debug_mode(:, -, +),
  138	ifprolog_debug(0),
  139	load(:),
  140	asserta_with_names(:, +),
  141	assertz_with_names(:, +),
  142	clause_with_names(:, -, -),
  143	retract_with_names(:, -),
  144	predicate_type(:, -),
  145	current_global(:),
  146	get_global(:, -),
  147	set_global(:, +),
  148	unset_global(:).  149
  150
  151		 /*******************************
  152		 *	     EXPANSION		*
  153		 *******************************/
  154
  155:- multifile
  156	user:goal_expansion/2,
  157	user:term_expansion/2,
  158	user:file_search_path/2,
  159	user:prolog_file_type/2,
  160	ifprolog_goal_expansion/2,
  161	ifprolog_term_expansion/2.  162:- dynamic
  163	user:goal_expansion/2,
  164	user:term_expansion/2,
  165	user:file_search_path/2,
  166	user:prolog_file_type/2.  167
  168:- dynamic
  169	in_module_interface/1.  170
  171user:goal_expansion(In, Out) :-
  172	prolog_load_context(dialect, ifprolog),
  173	ifprolog_goal_expansion(In, Out).
  174
  175user:term_expansion(In, Out) :-
  176	prolog_load_context(dialect, ifprolog),
  177	ifprolog_term_expansion(In, Out).
  178
  179%%	ifprolog_goal_expansion(+In, +Out)
  180%
  181%	goal_expansion  rules  to   emulate    IF/Prolog   behaviour  in
  182%	SWI-Prolog. The expansions  below   maintain  optimization  from
  183%	compilation.   Defining   them   as   predicates   would   loose
  184%	compilation.
  185
  186%%	context(:Goal, Handler)
  187%
  188%	Is  mapped  to  catch(Goal,  Error,    Recover)  is  Handler  is
  189%	=|error(_,_) => Recover|=. Other cases are   not  covered by the
  190%	emulation.
  191
  192%%	asserta(Head,Body) is det.
  193%%	assertz(Head,Body) is det.
  194%%	retract(Head,Body) is det.
  195%
  196%	Mapped to asserta((Head:-Body)),  etc.  Note   that  this  masks
  197%	SWI-Prolog's asserta/2, etc.
  198
  199ifprolog_goal_expansion(Module:Goal, Expanded) :-
  200	Module == system, nonvar(Goal), !,
  201	expand_goal(Goal, ExpandedGoal),
  202	head_pi(ExpandedGoal, PI),
  203	(   current_predicate(ifprolog:PI),
  204	    \+ predicate_property(ExpandedGoal, imported_from(_))
  205	->  Expanded = ifprolog:ExpandedGoal
  206	;   Expanded = ExpandedGoal
  207	).
  208ifprolog_goal_expansion(Goal, Expanded) :-
  209	if_goal_expansion(Goal, Expanded).
  210
  211if_goal_expansion(context(Goal, [Error => Recover]),
  212		  catch(Goal, Error, Recover)) :-
  213	assertion(Error = error(_,_)).
  214if_goal_expansion(assertz(Head,Body),
  215		  assertz((Head:-Body))).
  216if_goal_expansion(asserta(Head,Body),
  217		  asserta((Head:-Body))).
  218if_goal_expansion(retract(Head,Body),
  219		  retract((Head:-Body))).
  220if_goal_expansion(Call@Module, call((Module:Goal)@Module)) :-
  221	nonvar(Call),
  222	Call = call(Goal).
  223if_goal_expansion(concat_atom(L,A), if_concat_atom(L,A)).
  224if_goal_expansion(concat_atom(L,D,A), if_concat_atom(L,D,A)).
  225
  226
  227head_pi(M:Head, M:PI) :- !,
  228	head_pi(Head, PI).
  229head_pi(Head, Name/Arity) :-
  230	functor(Head, Name, Arity).
  231
  232
  233%%	ifprolog_term_expansion(+In, +Out)
  234%
  235%	term_expansion  rules  to   emulate    IF/Prolog   behaviour  in
  236%	SWI-Prolog.
  237
  238%%	meta(+ListOfPI)
  239%
  240%	Mapped  to  module_transparent/1.  Not  sure   whether  this  is
  241%	correct. It surely is not very elegant   to  map to a deprecated
  242%	feature.  Luckily,  although  the  module_transparent/1  API  is
  243%	deprecated, the underlying functionality is   still  core of the
  244%	module system.
  245%
  246%	Note that if :- meta  appears   inside  a  module interface, the
  247%	predicate is also exported.
  248
  249%%	export(+ListOfPI) is det.
  250%%	discontiguous(+ListOfPI) is det.
  251%
  252%	Mapped to comma-lists
  253
  254%%	module(+Name).
  255%%	begin_module(+Name).
  256%%	end_module(+Name).
  257%
  258%	These are emulated correctly,  provided   module/1  is the first
  259%	term of the file and the  implementation   is  part  of the same
  260%	file. Begin/end are ignored.
  261
  262ifprolog_term_expansion((:- meta([])), []).
  263ifprolog_term_expansion((:- meta(List)),
  264			[ (:- module_transparent(Spec))
  265			| Export
  266			]) :-
  267	pi_list_to_pi_term(List, Spec),
  268	(   in_module_interface(_)
  269	->  Export = [(:- export(Spec))]
  270	;   Export = []
  271	).
  272
  273ifprolog_term_expansion((:- export([])), []).
  274ifprolog_term_expansion((:- export(List)),
  275			(:- export(Spec))) :-
  276	is_list(List),
  277	pi_list_to_pi_term(List, Spec).
  278
  279ifprolog_term_expansion((:- private(_)), []).
  280
  281ifprolog_term_expansion((:- discontiguous([])), []).
  282ifprolog_term_expansion((:- discontiguous(List)),
  283			(:- discontiguous(Spec))) :-
  284	is_list(List),
  285	pi_list_to_pi_term(List, Spec).
  286
  287ifprolog_term_expansion((:- multifile([])), []).
  288ifprolog_term_expansion((:- multifile(List)),
  289			(:- multifile(Spec))) :-
  290	is_list(List),
  291	pi_list_to_pi_term(List, Spec).
  292
  293ifprolog_term_expansion((:- module(Name)),
  294			(:- module(Name, []))) :-
  295	asserta(in_module_interface(Name)).
  296ifprolog_term_expansion((:- begin_module(Name)), []) :-
  297	prolog_load_context(module, Loading),
  298	assertion(Name == Loading),
  299	retract(in_module_interface(Name)).
  300ifprolog_term_expansion((:- end_module(_)), []).
  301ifprolog_term_expansion((:- end_module), []).
  302ifprolog_term_expansion((:- nonotify), []).	% TBD: set verbosity
  303
  304
  305ifprolog_term_expansion((:- import(Module)),
  306			(:- use_module(File))) :-
  307	(   module_property(Module, file(File))
  308	->  true
  309	;   existence_error(module, Module)
  310	).
  311ifprolog_term_expansion((:- import(Module, ImportList)),
  312			(:- use_module(File, ImportList))) :-
  313	(   module_property(Module, file(File))
  314	->  true
  315	;   existence_error(module, Module)
  316	).
  317
  318%%	pi_list_to_pi_term(+List, -CommaList) is det.
  319
  320pi_list_to_pi_term([PI], PI) :- !.
  321pi_list_to_pi_term([H|T], (H,CommaList)) :-
  322	pi_list_to_pi_term(T, CommaList).
  323
  324                 /*******************************
  325                 *          LIBRARY SETUP       *
  326                 *******************************/
  327
  328%%      push_ifprolog_library
  329%
  330%       Pushes searching for dialect/ifprolog in   front of every library
  331%       directory that contains such as sub-directory.
  332
  333push_ifprolog_library :-
  334        (   absolute_file_name(library(dialect/ifprolog), Dir,
  335                               [ file_type(directory),
  336                                 access(read),
  337                                 solutions(all),
  338                                 file_errors(fail)
  339                               ]),
  340            asserta((user:file_search_path(library, Dir) :-
  341                    prolog_load_context(dialect, ifprolog))),
  342            fail
  343        ;   true
  344        ).
  345
  346%%	push_ifprolog_file_extension
  347%
  348%	Looks for .pro files before looking for .pl files if the current
  349%	dialect is =pro=. If the dialect is   not active, the .pro files
  350%	are found as last resort.
  351
  352push_ifprolog_file_extension :-
  353	asserta((user:prolog_file_type(pro, prolog) :-
  354		prolog_load_context(dialect, ifprolog))).
  355
  356user:prolog_file_type(pro, prolog) :-
  357	\+ prolog_load_context(dialect, ifprolog).
  358
  359:- push_ifprolog_library,
  360   push_ifprolog_file_extension.  361
  362
  363		 /*******************************
  364		 *	    PREDICATES		*
  365		 *******************************/
  366
  367%%	calling_context(-Context)
  368%
  369%	Mapped to context_module/1.
  370
  371calling_context(Context) :-
  372	context_module(Context).
  373
  374%%	context(:Goal, +Mapping)
  375%
  376%	IF/Prolog context/2 construct. This is  the true predicate. This
  377%	is normally mapped by goal-expansion.
  378%
  379%	@bug	Does not deal with IF/Prolog signal mapping
  380
  381context(M:Goal, Mapping) :-
  382	member(Error => Action, Mapping),
  383	nonvar(Error),
  384	Error = error(_,_), !,
  385	catch(M:Goal, Error, Action).
  386context(M:Goal, _Mapping) :-
  387	M:Goal.
  388
  389%%	block(:Goal, +Tag, :Recovery).
  390%%	exit_block(+Tag).
  391%%	cut_block(+Tag) is semidet.
  392%
  393%	The control construct block/3 runs Goal in a block labelled Tag.
  394%	If Goal calls exit_block/1 using a   matching Tag, the execution
  395%	of Goal is abandoned  using   exception  handling  and execution
  396%	continues by running Recovery.  Goal   can  call cut_block/1. If
  397%	there is a block with matching   Tag,  all choice points created
  398%	since the block was started are destroyed.
  399%
  400%	@bug	The block control structure is implemented on top of
  401%		catch/3 and throw/1.  If catch/3 is used inside Goal,
  402%		the user must ensure that either (1) the protected
  403%		goal does not call exit_block/1 or cut_block/1 or (2)
  404%		the _Catcher_ of the catch/3 call does *not* unify with
  405%		a term block(_,_).
  406
  407block(Goal, Tag, Recovery) :-
  408	prolog_current_choice(Choice),
  409	catch(Goal, block(Tag, Choice), Recovery).
  410
  411exit_block(Tag) :-
  412	throw(block(Tag, _)).
  413
  414cut_block(Tag) :-
  415	prolog_current_frame(Frame),
  416	findall(Choice,			% use findall/3 to avoid binding
  417		prolog_frame_attribute(
  418		    Frame, parent_goal,
  419		    system:catch(_, block(Tag, Choice), _)),
  420		[Choice]),
  421	nonvar(Choice),
  422	prolog_cut_to(Choice).
  423
  424%%	modify_mode(+PI, -OldMode, +NewMode) is det.
  425%
  426%	Switch between static and  dynamic   code.  Fully supported, but
  427%	notably changing static to dynamic code   is  not allowed if the
  428%	predicate has clauses.
  429
  430modify_mode(PI, OldMode, NewMode) :-
  431	pi_head(PI, Head),
  432	old_mode(Head, OldMode),
  433	set_mode(PI, OldMode, NewMode).
  434
  435old_mode(Head, Mode) :-
  436	(   predicate_property(Head, dynamic)
  437	->  Mode = on
  438	;   Mode = off
  439	).
  440
  441set_mode(_, Old, Old) :- !.
  442set_mode(PI, _, on) :- !,
  443	dynamic(PI).
  444set_mode(PI, _, off) :-
  445	compile_predicates([PI]).
  446
  447pi_head(M:PI, M:Head) :- !,
  448	pi_head(PI, Head).
  449pi_head(Name/Arity, Term) :-
  450	functor(Term, Name, Arity).
  451
  452%%	debug_mode(:PI, -Old, +New)
  453%
  454%	Old is not unified.  Only  New  ==   off  is  mapped  to disable
  455%	debugging of a predicate.
  456
  457debug_mode(PI, _, off) :- !,
  458	'$hide'(PI).
  459debug_mode(_, _, on).
  460
  461%%	ifprolog_debug(:Goal)
  462%
  463%	Map IF/Prolog debug(Goal)@Module. This should  run Goal in debug
  464%	mode. We rarely needs this type of measures in SWI-Prolog.
  465
  466ifprolog_debug(Goal) :-
  467	Goal.
  468
  469%%	debug_config(+Key, -Current, +Value)
  470%
  471%	Ignored.  Prints a message.
  472
  473debug_config(Key,Current,Value) :-
  474	print_message(informational, ignored(debug_config(Key,Current,Value))).
  475
  476%%	float_format(-Old, +New)
  477%
  478%	Ignored. Prints a message. Cannot   be emulated. Printing floats
  479%	with a specified precision can only be done using format/2.
  480
  481float_format(Old, New) :-
  482	print_message(informational, ignored(float_format(Old, New))).
  483
  484%%	program_parameters(-List:atom)
  485%
  486%	All command-line argument, including the executable,
  487
  488program_parameters(Argv) :-
  489	current_prolog_flag(os_argv, Argv).
  490
  491%%	user_parameters(-List:atom)
  492%
  493%	Parameters after =|--|=.
  494
  495user_parameters(Argv) :-
  496	current_prolog_flag(argv, Argv).
  497
  498%%	match(+Mask, +Atom) is semidet.
  499%
  500%	Same as once(match(Mask, Atom, _Replacements)).
  501
  502match(Mask, Atom) :-
  503	match(Mask, Atom, _), !.
  504
  505%%	match(+Mask, +Atom, ?Replacements) is nondet.
  506%
  507%	Pattern matching. This emulation  should   be  complete.  Can be
  508%	optimized using caching of  the   pattern-analysis  or doing the
  509%	analysis at compile-time.
  510
  511match(Mask, Atom, Replacements) :-
  512	atom_codes(Mask, MaskCodes),
  513	atom_codes(Atom, Codes),
  514	phrase(match_pattern(Pattern), MaskCodes), !,
  515	pattern_goal(Pattern, Codes, Replacements, Goal),
  516	Goal.
  517
  518pattern_goal([], [], [], true).
  519pattern_goal([string(String)|T], Codes, Replacements, Goal) :- !,
  520	append(String, Rest, Codes),
  521	pattern_goal(T, Rest, Replacements, Goal).
  522pattern_goal([star|T], Codes, [Atom|Replacements], Goal) :-
  523	append(Replacement, Rest, Codes),
  524	Goal = (atom_codes(Atom, Replacement),Goal2),
  525	pattern_goal(T, Rest, Replacements, Goal2).
  526pattern_goal([set(S)|T], [C|Rest], [Atom|Replacements], Goal) :-
  527	memberchk(C, S), !,
  528	Goal = (char_code(Atom, C),Goal2),
  529	pattern_goal(T, Rest, Replacements, Goal2).
  530pattern_goal([any|T], [C|Rest], [Atom|Replacements], Goal) :-
  531	Goal = (char_code(Atom, C),Goal2),
  532	pattern_goal(T, Rest, Replacements, Goal2).
  533
  534match_pattern([set(S)|T]) -->
  535	"[",
  536	match_set(S), !,
  537	match_pattern(T).
  538match_pattern([string(List)|T]) -->
  539	non_special(List),
  540	{ List \== [] }, !,
  541	match_pattern(T).
  542match_pattern([star|T]) -->
  543	"*", !,
  544	match_pattern(T).
  545match_pattern([any|T]) -->
  546	"?", !,
  547	match_pattern(T).
  548match_pattern([]) --> [].
  549
  550match_set([]) --> "]", !.
  551match_set(L) -->
  552	[C0], "-", [C1],
  553	{ C1 \= 0'],
  554	  C0 =< C1,
  555	  numlist(C0, C1, Range),
  556	  append(Range, T, L)
  557	},
  558	match_set(T).
  559match_set([C|L]) -->
  560	[C],
  561	match_set(L).
  562
  563non_special([H|T]) -->
  564	[H],
  565	{ \+ special(H) }, !,
  566	non_special(T).
  567non_special([]) --> [].
  568
  569special(0'*).
  570special(0'?).
  571special(0'[).
  572
  573%%	lower_upper(+Lower, -Upper) is det.
  574%%	lower_upper(-Lower, +Upper) is det.
  575%
  576%	Multi-moded combination of upcase_atom/2 and downcase_atom/2.
  577
  578
  579lower_upper(Lower, Upper) :-
  580	nonvar(Lower), !,
  581	upcase_atom(Lower, Upper).
  582lower_upper(Lower, Upper) :-
  583	downcase_atom(Upper, Lower).
  584
  585%%	load(File)
  586%
  587%	Mapped to consult.  I think that the compatible version should
  588%	only load .qlf (compiled) code.
  589
  590load(File) :-
  591	consult(File).
  592
  593%%	unload(+Module) is det.
  594%
  595%	Unload the named module.
  596%
  597%	@bug: What to do with modules that are not associated to a
  598%	file?
  599
  600unload(Module) :-
  601	module_property(Module, file(File)), !,
  602	unload_file(File).
  603unload(_Module) :-
  604	assertion(fail).
  605
  606%%	file_test(+File, +Mode)
  607%
  608%	Mapped to access_file/2 (which understand more modes). Note that
  609%	this predicate is defined in the   module  =system= to allow for
  610%	direct calling.
  611
  612file_test(File, Mode) :-
  613	access_file(File, Mode).
  614
  615%%	filepos(@Stream, -Line)
  616%
  617%	from  the  IF/Prolog  documentation    The  predicate  filepos/2
  618%	determines the current line  position   of  the  specified input
  619%	stream and unifies the  result  with   Line.  The  current  line
  620%	position is the number of line processed + 1
  621
  622filepos(Stream, Line) :-
  623	line_count(Stream, L),
  624	Line is L + 1.
  625
  626
  627%%	getcwd(-Dir)
  628%
  629%	The predicate getcwd/1 unifies Dir with the full pathname of the
  630%	current working directory.
  631
  632getcwd(Dir) :-
  633	working_directory(Dir, Dir).
  634
  635%%	filepos(@Stream, -Line, -Column)
  636%
  637%	from  the  IF/Prolog  documentation    The  predicate  filepos/2
  638%	determines the current line  position   of  the  specified input
  639%	stream and unifies the  result  with   Line.  The  current  line
  640%	position is the number of line processed + 1
  641
  642filepos(Stream, Line, Column) :-
  643	line_count(Stream, L),
  644	line_position(Stream, C),
  645	Line is L + 1,
  646	Column is C + 1.
  647
  648%%	assign_alias(+Alias, @Stream) is det.
  649%
  650
  651assign_alias(Alias, Stream) :-
  652	set_stream(Stream, alias(Alias)).
  653
  654%%	writeq_atom(+Term, -Atom)
  655%
  656%	Use writeq/1 to write Term to Atom.
  657
  658writeq_atom(Term, Atom) :-
  659	with_output_to(atom(Atom), writeq(Term)).
  660
  661%%	write_atom(+Term, -Atom)
  662%
  663%	Use write/1 to write Term to Atom.
  664
  665write_atom(Term, Atom) :-
  666	with_output_to(atom(Atom), write(Term)).
  667
  668%%	current_error(-Stream)
  669%
  670%	Doesn't exist in SWI-Prolog, but =user_error= is always an alias
  671%	to the current error stream.
  672
  673current_error(user_error).
  674
  675
  676		 /*******************************
  677		 *	  FORMATTED WRITE	*
  678		 *******************************/
  679
  680%%	write_formatted_atom(-Atom, +Format, +ArgList) is det.
  681%%	write_formatted(+Format, +ArgList) is det.
  682%%	write_formatted(@Stream, +Format, +ArgList) is det.
  683%
  684%	Emulation of IF/Prolog formatted write.   The  emulation is very
  685%	incomplete. Notable asks for dealing with aligned fields, etc.
  686%
  687%	@bug	Not all format characters are processed
  688%	@bug    Incomplete processing of modifiers, fieldwidth and precision
  689%	@tbd	This should become goal-expansion based to process
  690%		format specifiers at compile-time.
  691
  692write_formatted_atom(Atom, Format, ArgList) :-
  693	with_output_to(atom(Atom), write_formatted(Format, ArgList)).
  694
  695write_formatted(Format, ArgList) :-
  696	write_formatted(current_output, Format, ArgList).
  697
  698write_formatted(Out, Format, ArgList) :-
  699	atom_codes(Format, Codes),
  700	phrase(format_string(FormatCodes), Codes), !,
  701	string_codes(FormatString, FormatCodes),
  702	format(Out, FormatString, ArgList).
  703
  704format_string([]) --> [].
  705format_string(Fmt) -->
  706	"%", format_modifiers(Flags, FieldLen, Precision), [IFC], !,
  707	{   map_format([IFC], Flags, FieldLen, Precision, Repl)
  708	->  append(Repl, T, Fmt)
  709	;   print_message(warning, ifprolog_format(IFC)),
  710	    %backtrace(20),
  711	    T = Fmt
  712	},
  713	format_string(T).
  714format_string([H|T]) -->
  715	[H],
  716	format_string(T).
  717
  718map_format(Format, [], default, default, Mapped) :- !,
  719	map_format(Format, Mapped).
  720map_format(Format, Flags, Width, Precision, Mapped) :-
  721	integer(Width), !,			% left/right aligned in Width
  722	map_format(Format, Field),
  723	format_precision(Precision, Field, PrecField),
  724	fill_code(Flags, [Fill]),
  725	(   memberchk(-, Flags)			% left aligned
  726	->  format(codes(Mapped), '~~|~s~~`~ct~~~d+', [PrecField, Fill, Width])
  727	;   format(codes(Mapped), '~~|~~`~ct~s~~~d+', [Fill, PrecField, Width])
  728	).
  729map_format(Format, Flags, _, _, Mapped) :-
  730	memberchk(#, Flags),
  731	can_format(Format, Mapped), !.
  732map_format(Format, _, _, Precision, Mapped) :-
  733	map_format(Format, Field),
  734	format_precision(Precision, Field, Mapped).
  735
  736can_format("o", "0~8r").
  737can_format("x", "0x~16r").
  738can_format("X", "0x~16R").
  739can_format("w", "~k").
  740
  741map_format("t", "~w").
  742map_format("q", "~q").
  743map_format("s", "~a").
  744map_format("f", "~f").
  745map_format("e", "~e").
  746map_format("E", "~E").
  747map_format("g", "~G").
  748map_format("d", "~d").
  749map_format("x", "~16r").
  750map_format("o", "~8r").
  751map_format("X", "~16R").
  752map_format("O", "~8R").
  753map_format("c", "~c").
  754map_format("%", "%").
  755
  756have_precision("d").
  757have_precision("D").
  758have_precision("e").
  759have_precision("E").
  760have_precision("f").
  761have_precision("g").
  762have_precision("G").
  763
  764format_precision(N, [0'~|C], [0'~|Field]) :-
  765    integer(N),
  766    have_precision(C),
  767    !,
  768    format(codes(Field), '~d~s', [N, C]).
  769format_precision(_, Field, Field).
  770
  771fill_code(Flags, "0") :- memberchk(0, Flags), !.
  772fill_code(_,     " ").
  773
  774%%	format_modifiers(-Flags, -FieldLength, -Precision) is det.
  775%
  776%	Read the IF/Prolog format modifiers. We currently do not process
  777%	any of the modifiers! Some code seems to be using e.g. %07lx. We
  778%	assume this is the same as -07x (assuming l=left).
  779
  780format_modifiers(Flags, FieldLength, Precision) -->
  781	format_flags(Flags0),
  782	digits(FieldLengthDigits),
  783	{   FieldLengthDigits == []
  784	->  FieldLength = default
  785	;   number_codes(FieldLength, FieldLengthDigits)
  786	},
  787	(   "."
  788	->  digits(PrecisionDigits),
  789	    { number_codes(Precision, PrecisionDigits) }
  790	;   { Precision = default }
  791	),
  792	opt_alignment(Flags0, Flags).
  793
  794format_flags([H|T]) -->
  795	format_flag(H), !,
  796	format_flags(T).
  797format_flags([]) --> [].
  798
  799format_flag(+) --> "+".		% Always prefix number with a sign
  800format_flag(-) --> "-".		% Left-justify
  801format_flag(space) --> " ".	% Space before positive numbers
  802format_flag(#) --> "#".		% Canonical output
  803format_flag(0) --> "0".		% Use leading 0 for integers
  804
  805digits([D0|T]) -->
  806	digit(D0), !,
  807	digits(T).
  808digits([]) --> [].
  809
  810digit(D) --> [D], {between(0'0, 0'9, D)}.
  811
  812opt_alignment(L, [-|L]) --> "l", !.
  813opt_alignment(L, L) --> [].
  814
  815
  816%%	get_until(+SearchChar, -Text, -EndChar) is det.
  817%%	get_until(@Stream, +SearchChar, -Text, -EndChar) is det.
  818%
  819%	Read input from Stream  until   SearchChar.  Unify  EndChar with
  820%	either SearchChar or the atom =end_of_file=.
  821
  822get_until(SearchChar, Text, EndChar) :-
  823	get_until(current_input, SearchChar, Text, EndChar).
  824
  825get_until(In, SearchChar, Text, EndChar) :-
  826	get_char(In, C0),
  827	get_until(C0, In, SearchChar, Codes, EndChar),
  828	atom_chars(Text, Codes).
  829
  830get_until(C0, _, C0, [], C0) :- !.
  831get_until(end_of_file, _, _,  [], end_of_file) :- !.
  832get_until(C0, In, Search, [C0|T], End) :-
  833	get_char(In, C1),
  834	get_until(C1, In, Search, T, End).
  835
  836
  837		 /*******************************
  838		 *	      PARSE		*
  839		 *******************************/
  840
  841%%	atom_part(+Atom, +Pos, +Len, -Sub) is det.
  842%
  843%	True when Sub is part  of   the  atom [Pos,Pos+Len). Unifies Sub
  844%	with '' if Pos or Len is out of range!?
  845
  846atom_part(_, Pos, _, Sub) :-
  847	Pos < 1, !,
  848	Sub = ''.
  849atom_part(_, _, Len, Sub) :-
  850	Len < 1, !,
  851	Sub = ''.
  852atom_part(Atom, Pos, _, Sub) :-
  853	atom_length(Atom, Len),
  854	Pos > Len, !,
  855	Sub = ''.
  856atom_part(Atom, Pos, Len, Sub) :-
  857	Pos >= 1,
  858	Pos0 is Pos - 1,
  859	atom_length(Atom, ALen),
  860	Len0 is min(Len, ALen-Pos0),
  861	sub_atom(Atom, Pos0, Len0, _, Sub).
  862
  863%%	atom_prefix(+Atom, +Len, -Sub) is det.
  864%
  865%	Unifies Sub with the atom formed by  the first Len characters in
  866%	atom.
  867%
  868%	 - If Len < 1, Sub is unified with the null atom ''.
  869%	 - If Len > length of Atom, Sub is unified with Atom.
  870
  871atom_prefix(_, Len, Sub) :-
  872	Len < 1, !,
  873	Sub = ''.
  874atom_prefix(Atom, Len, Sub) :-
  875	atom_length(Atom, AtomLen),
  876	Len > AtomLen, !,
  877	Sub = Atom.
  878atom_prefix(Atom, Len, Sub) :-
  879	sub_atom(Atom, 0, Len, _, Sub).
  880
  881%%	atom_suffix(+Atom, +Len, -Sub) is det.
  882%
  883%	Unifies Sub with the atom formed by   the last Len characters in
  884%	atom.
  885%
  886%	  - If Len < 1, Sub is unified with the null atom ''.
  887%	  - If Len > length of Atom, Sub is unified with Atom.
  888
  889atom_suffix(_, Len, Sub) :-
  890	Len < 1, !,
  891	Sub = ''.
  892atom_suffix(Atom, Len, Sub) :-
  893	atom_length(Atom, AtomLen),
  894	Len > AtomLen, !,
  895	Sub = Atom.
  896atom_suffix(Atom, Len, Sub) :-
  897	atom_length(Atom, AtomLen),
  898	Pos is AtomLen - Len,
  899	sub_atom(Atom, Pos, Len, _, Sub).
  900
  901%%	atom_split( +Atom, +Delimiter, ?Subatoms )
  902%
  903%	Split Atom over Delimiter and unify the parts with Subatoms.
  904
  905atom_split(Atom, Delimiter, Subatoms)  :-
  906	atomic_list_concat(Subatoms, Delimiter, Atom).
  907
  908%%	if_concat_atom(+List, +Delimiter, -Atom) is det.
  909%
  910%	True when Atom is the concatenation of   the lexical form of all
  911%	elements from List, using Delimiter to delimit the elements.
  912%
  913%	The behavior of this  ifprolog   predicate  is  different w.r.t.
  914%	SWI-Prolog in two respect: it supports   arbitrary terms in List
  915%	rather than only atomic and it does _not_ work in mode -,+,+.
  916
  917if_concat_atom(List, Delimiter, Atom) :-
  918	maplist(write_term_to_atom, List, AtomList),
  919	atomic_list_concat(AtomList, Delimiter, Atom).
  920
  921write_term_to_atom(Term, Atom) :-
  922	(   atomic(Term)
  923	->  Atom = Term
  924	;   with_output_to(string(Atom), write(Term))
  925	).
  926
  927%%	if_concat_atom(+List, -Atom) is det.
  928%
  929%	True when Atom is the concatenation of   the lexical form of all
  930%	elements  from  List.  Same  as  if_concat_atom/3  using  ''  as
  931%	delimiter.
  932
  933if_concat_atom(List, Atom) :-
  934	maplist(write_term_to_atom, List, AtomList),
  935	atomic_list_concat(AtomList, Atom).
  936
  937%%	getchar(+Atom, +Pos, -Char)
  938%
  939%	Unifies Char with the Position-th character in Atom
  940%	If Pos < 1 or Pos > length of Atom, then fail.
  941
  942getchar(_, Pos, _) :-
  943	Pos < 1, !,
  944	fail.
  945getchar(Atom, Pos, _) :-
  946	atom_length(Atom, Len),
  947	Pos > Len, !,
  948	fail.
  949getchar(Atom, Pos, Char) :-
  950	P is Pos - 1,
  951	sub_atom(Atom, P, 1, _, Char).
  952
  953
  954%%	parse_atom(+Atom, +StartPos, ?EndPos, ?Term, ?VarList, ?Error)
  955%
  956%	Read from an atom.
  957%
  958%	@param StartPos is 1-based position to start reading
  959%	@param Error is the 1-based position of a syntax error or 0 if
  960%	       there is no error.
  961
  962parse_atom(Atom, StartPos, EndPos, Term, VarList, Error) :-
  963	setup_call_cleanup(
  964	    ( atom_to_memory_file(Atom, MemF),
  965	      open_memory_file(MemF, read, In)
  966	    ),
  967	    ( StartPos0 is StartPos-1,
  968	      seek(In, StartPos0, bof, _),
  969	      catch(read_term(In, Term, [variable_names(VarList)]), E, true),
  970	      parse_atom_error(E, Error),
  971	      character_count(In, EndPos0),
  972	      EndPos is EndPos0+1
  973	    ),
  974	    ( close(In),
  975	      free_memory_file(MemF)
  976	    )).
  977
  978parse_atom_error(Var, Pos) :-
  979	var(Var), !, Pos = 0.
  980parse_atom_error(error(_, stream(_Stream, _, _, Pos)), Pos1) :-
  981	Pos1 is Pos+1.
  982
  983
  984%%	index(+Atom, +String, -Position) is semidet.
  985%
  986%	True when Position is the first   occurrence  of String in Atom.
  987%	Position is 1-based.
  988
  989index(Atom, String, Position) :-
  990	sub_string(Atom, Pos0, _, _, String), !,
  991        Position is Pos0 + 1.
  992
  993%%	list_length(+List, ?Length) is det.
  994%
  995%	Deterministic version of length/2. Current implementation simply
  996%	calls length/2.
  997
  998list_length(List, Length) :-
  999	length(List, Length).
 1000
 1001
 1002		 /*******************************
 1003		 *	      MISC		*
 1004		 *******************************/
 1005
 1006%%	for(+Start, ?Count, +End) is nondet.
 1007%
 1008%	Similar to between/3, but can count down if Start > End.
 1009
 1010for(Start, Count, End) :-
 1011	Start =< End, !,
 1012	between(Start, End, Count).
 1013for(Start, Count, End) :-
 1014	nonvar(Count), !,
 1015	between(End, Start, Count).
 1016for(Start, Count, End) :-
 1017	Range is Start-End,
 1018	between(0, Range, X),
 1019	Count is Start-X.
 1020
 1021%%	prolog_version(-Version)
 1022%
 1023%	Return IF/Prolog simulated version string
 1024
 1025prolog_version(Version) :-
 1026	current_prolog_flag(version_data, swi(Major, Minor, Patch, _)),
 1027	atomic_list_concat([Major, Minor, Patch], '.', Version).
 1028
 1029%%	proroot(-Path)
 1030%
 1031%	True when Path is  the  installation   location  of  the  Prolog
 1032%	system.
 1033
 1034proroot(Path) :-
 1035	current_prolog_flag(home, Path).
 1036
 1037%%	system_name(-SystemName)
 1038%
 1039%	True when SystemName identifies the  operating system. Note that
 1040%	this returns the SWI-Prolog =arch= flag,   and not the IF/Prolog
 1041%	identifiers.
 1042
 1043system_name(SystemName) :-
 1044	current_prolog_flag(arch, SystemName).
 1045
 1046%%	localtime(+Time, ?Year, ?Month, ?Day, ?DoW, ?DoY, ?Hour, ?Min, ?Sec)
 1047%
 1048%	Break system time into its components.  Deefines components:
 1049%
 1050%	  | Year    | Year number    | 4 digits        |
 1051%	  | Month   | Month number   | 1..12           |
 1052%	  | Day	    | Day of month   | 1..31           |
 1053%	  | DoW	    | Day of week    | 1..7 (Mon-Sun)  |
 1054%	  | DoY	    | Day in year    | 1..366          |
 1055%	  | Hour    | Hours	     | 0..23           |
 1056%	  | Min	    | Minutes	     | 0..59           |
 1057%	  | Sec	    | Seconds	     | 0..59           |
 1058%
 1059%	Note that in IF/Prolog  V4,  Year  is   0..99,  while  it  is  a
 1060%	four-digit number in IF/Prolog V5.  We emulate IF/Prolog V5.
 1061
 1062localtime(TimeExpr, Year, Month, Day, DoW, DoY, Hour, Min, Sec) :-
 1063	arithmetic_expression_value(TimeExpr, Time),
 1064        stamp_date_time(Time, date(Year, Month, Day,
 1065				   Hour, Min, SecFloat,
 1066				   _Off, _TZ, _DST), local),
 1067        Sec is floor(SecFloat),
 1068	Date = date(Year,Month,Day),
 1069	day_of_the_year(Date, DoY),
 1070        day_of_the_week(Date, DoW).
 1071
 1072
 1073%%	current_global(+Name) is semidet.
 1074%%	get_global(+Name, ?Value) is det.
 1075%%	set_global(+Name, ?Value) is det.
 1076%%	unset_global(+Name) is det.
 1077%
 1078%	IF/Prolog  global  variables,  mapped    to   SWI-Prolog's  nb_*
 1079%	predicates.
 1080
 1081current_global(Name) :-
 1082	gvar_name(Name, GName),
 1083	nb_current(GName, _).
 1084
 1085get_global(Name, Value) :-
 1086	gvar_name(Name, GName),
 1087	nb_getval(GName, Value).
 1088
 1089set_global(Name, Value) :-
 1090	gvar_name(Name, GName),
 1091	nb_setval(GName, Value).
 1092
 1093unset_global(Name) :-
 1094	gvar_name(Name, GName),
 1095	nb_delete(GName).
 1096
 1097gvar_name(Module:Name, GName) :-
 1098	atomic_list_concat([Module, :, Name], GName).
 1099
 1100
 1101%%	current_default_module(-Module) is det.
 1102%
 1103%	Name of the toplevel typein module.
 1104
 1105current_default_module(Module) :-
 1106	'$current_typein_module'(Module).
 1107
 1108%%	set_default_module(+Module) is det.
 1109%
 1110%	Set the default toplevel module.
 1111
 1112set_default_module(Module) :-
 1113	module(Module).
 1114
 1115
 1116		 /*******************************
 1117		 *	      DATABASE		*
 1118		 *******************************/
 1119
 1120:- dynamic
 1121	names/2. 1122
 1123%%	asserta_with_names(@Clause, +VarNames) is det.
 1124%%	assertz_with_names(@Clause, +VarNames) is det.
 1125%%	clause_with_names(?Head, ?Body, -VarNames) is det.
 1126%%	retract_with_names(?Clause, -VarNames) is det.
 1127%
 1128%	Predicates that manage  the  database   while  keeping  track of
 1129%	variable names.
 1130
 1131asserta_with_names(M:Clause, VarNames) :-
 1132	term_varnames(Clause, VarNames, VarTerm),
 1133	system:asserta(M:Clause, Ref),
 1134	asserta(names(Ref, VarTerm)).
 1135assertz_with_names(M:Clause, VarNames) :-
 1136	term_varnames(Clause, VarNames, VarTerm),
 1137	system:assertz(M:Clause, Ref),
 1138	asserta(names(Ref, VarTerm)).
 1139
 1140term_varnames(Term, VarNames, VarTerm) :-
 1141	findall(Vars,
 1142		( term_variables(Term, Vars),
 1143		  bind_names(VarNames)
 1144		),
 1145		[ VarList ]),
 1146	VarTerm =.. [ v | VarList ].
 1147
 1148bind_names([]).
 1149bind_names([Name=Var|T]) :-
 1150	Name=Var,
 1151	bind_names(T).
 1152
 1153
 1154clause_with_names(M:Head, Body, VarNames) :-
 1155	clause(M:Head, Body, Ref),
 1156	(   names(Ref, VarTerm)
 1157	->  term_variables((Head:-Body), Vars),
 1158	    VarTerm =.. [v|NameList],
 1159	    make_bindings(NameList, Vars, VarNames)
 1160	;   VarNames = []
 1161	).
 1162
 1163retract_with_names(M:Term, VarNames) :-
 1164	clause(M:Term, Ref),
 1165	erase(Ref),
 1166	(   retract(names(Ref, VarTerm))
 1167	->  term_variables((Term), Vars),
 1168	    VarTerm =.. [v|NameList],
 1169	    make_bindings(NameList, Vars, VarNames)
 1170	;   VarNames = []
 1171	).
 1172
 1173make_bindings([], [], []).
 1174make_bindings([Name|NT], [Var|VT], [Name=Var|BT]) :-
 1175	make_bindings(NT, VT, BT).
 1176
 1177
 1178%%	predicate_type(:PI, -Type) is det.
 1179%
 1180%	True when Type describes the type  of   PI.  Note that the value
 1181%	=linear= seems to mean you can use clause/2 on it, which is true
 1182%	for any SWI-Prolog predicate that is  defined. Therefore, we use
 1183%	it for any predicate that is defined.
 1184
 1185predicate_type(M:Name/Arity, Type) :-
 1186	functor(Head, Name, Arity),
 1187	Pred = M:Head,
 1188	(   (   predicate_property(Pred, built_in)
 1189	    ;	predicate_property(Pred, foreign)
 1190	    )
 1191	->  Type = builtin
 1192	;   predicate_property(Pred, imported_from(_))
 1193	->  Type = imported
 1194	;   predicate_property(Pred, dynamic)
 1195	->  Type = linear
 1196	;   control(Head)
 1197	->  Type = control
 1198	;   Name == call
 1199	->  Type = control
 1200	;   current_predicate(M:Name/Arity)
 1201	->  Type = linear
 1202	;   Type = undefined
 1203	).
 1204
 1205control((_,_)).
 1206control((_;_)).
 1207control((_->_)).
 1208control((_*->_)).
 1209control((!)).
 1210
 1211%%	current_visible(@Module, @PredicateIndicator).
 1212%
 1213%	FIXME check with documentation
 1214
 1215current_visible(Module, Name/Arity) :-
 1216	atom(Name), integer(Arity), !,
 1217	functor(Head, Name, Arity),
 1218	predicate_property(Module:Head, visible).
 1219current_visible(Module, Name/Arity) :-
 1220	predicate_property(Module:Head, visible),
 1221	functor(Head, Name, Arity).
 1222
 1223%%	current_signal(?Signal, ?Mode) is nondet.
 1224%
 1225%	True when Mode is the current   mode  for handling Signal. Modes
 1226%	are =on=, =off=,  =default=,  =ignore=.   Signals  are  =abort=,
 1227%	=alarm=, =interrupt=, =pipe=, =quit=,   =termination=,  =user_1=
 1228%	and =user_2=.
 1229%
 1230%	@tbd	Implement
 1231
 1232current_signal(_,_) :- fail.
 1233
 1234
 1235%%	digit(+A).
 1236%
 1237%	Is the character A a digit [0-9]
 1238digit(A) :-
 1239	char_type(A, digit).
 1240
 1241%%	letter(+A).
 1242%
 1243%	Is the character A a letter [A-Za-z]
 1244letter(A) :-
 1245	char_type(A, alpha).
 1246
 1247		 /*******************************
 1248		 *	    ARITHMETIC		*
 1249		 *******************************/
 1250
 1251:- arithmetic_function(system:time/0). 1252:- arithmetic_function(system:trunc/1). 1253:- arithmetic_function(system:ln/1). 1254:- arithmetic_function(system:minint/0). 1255:- arithmetic_function(system:maxint/0). 1256:- arithmetic_function(system:dbsize/0). 1257:- arithmetic_function(system:dbused/0). 1258:- arithmetic_function(system:ssize/0). 1259:- arithmetic_function(system:gused/0). 1260:- arithmetic_function(system:lused/0). 1261:- arithmetic_function(system:tused/0). 1262
 1263system:time(Time) :-
 1264	get_time(GetTime),
 1265	Time is round(GetTime).  % Time in seconds since 1970-01-01 00:00:00 UTC
 1266system:trunc(Val, Trunc) :-
 1267	Trunc is truncate(Val).
 1268system:ln(Val, Log) :-
 1269	Log is log(Val).
 1270system:minint(MinInt) :-
 1271	MinInt is -1<<31.
 1272system:maxint(MaxInt) :-
 1273	MaxInt is 1<<31 - 1.
 1274system:dbsize(0).
 1275system:dbused(0).
 1276system:ssize(Size) :-
 1277	statistics(globallimit, Size).
 1278system:gused(Size) :-
 1279	statistics(globalused, Size).
 1280system:lused(Size) :-
 1281	statistics(localused, Size).
 1282system:tused(Size) :-
 1283	statistics(trailused, Size).
 1284
 1285
 1286		 /*******************************
 1287		 *	       MESSAGES		*
 1288		 *******************************/
 1289
 1290prolog:message(ifprolog_format(IFC)) -->
 1291	[ 'Unknown specifier for write_formatted/3: ~c'-[IFC] ].
 1292
 1293
 1294		 /*******************************
 1295		 *	  COLOUR SUPPORT	*
 1296		 *******************************/
 1297
 1298:- multifile
 1299	prolog_colour:style/2,
 1300	prolog_colour:goal_colours/2. 1301
 1302prolog_colour:goal_colours(meta(_),
 1303			   ifprolog-[predicates]).
 1304prolog_colour:goal_colours(private(_),
 1305			   ifprolog-[predicates]).
 1306prolog_colour:goal_colours(import(Module,_),
 1307			   ifprolog-[module(Module),predicates]).
 1308prolog_colour:goal_colours(begin_module(Module),
 1309			   ifprolog-[module(Module)]).
 1310prolog_colour:goal_colours(end_module(Module),
 1311			   ifprolog-[module(Module)]).
 1312prolog_colour:goal_colours(end_module,
 1313			   ifprolog-[]).
 1314prolog_colour:goal_colours(nonotify,
 1315			   ifprolog-[]).
 1316
 1317prolog_colour:style(goal(ifprolog,_), [ colour(blue), background(lightcyan) ])