View source with formatted comments or as raw
    1/*  Part of SWI-Prolog
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        J.Wielemaker@vu.nl
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (c)  2019, VU University Amsterdam
    7			 CWI, Amsterdam
    8    All rights reserved.
    9
   10    Redistribution and use in source and binary forms, with or without
   11    modification, are permitted provided that the following conditions
   12    are met:
   13
   14    1. Redistributions of source code must retain the above copyright
   15       notice, this list of conditions and the following disclaimer.
   16
   17    2. Redistributions in binary form must reproduce the above copyright
   18       notice, this list of conditions and the following disclaimer in
   19       the documentation and/or other materials provided with the
   20       distribution.
   21
   22    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   23    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   24    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   25    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   26    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   27    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   28    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   29    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   30    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   32    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   33    POSSIBILITY OF SUCH DAMAGE.
   34*/
   35
   36:- module(xsb,
   37          [ add_lib_dir/1,			% +Directories
   38	    add_lib_dir/2,			% +Root, +Directories
   39
   40            compile/2,                          % +File, +Options
   41            load_dyn/1,                         % +File
   42            load_dyn/2,                         % +File, +Direction
   43            load_dync/1,                        % +File
   44            load_dync/2,                        % +File, +Direction
   45
   46            set_global_compiler_options/1,	% +Options
   47            compiler_options/1,			% +Options
   48
   49            xsb_import/2,                       % +Preds, From
   50            xsb_set_prolog_flag/2,              % +Flag, +Value
   51
   52            fail_if/1,				% :Goal
   53
   54            sk_not/1,				% :Goal
   55            gc_tables/1,                        % -Remaining
   56
   57            cputime/1,				% -Seconds
   58            walltime/1,				% -Seconds
   59            timed_call/2,                       % :Goal, :Options
   60
   61            (thread_shared)/1,                  % :Spec
   62
   63            debug_ctl/2,                        % +Option, +Value
   64
   65            fmt_write/2,                        % +Fmt, +Term
   66            fmt_write/3,                        % +Stream, +Fmt, +Term
   67
   68            path_sysop/2,                       % +Op, ?Value
   69            path_sysop/3,                       % +Op, ?Value1, ?Value2
   70
   71            abort/1,				% +Message
   72
   73            op(1050,  fy, import),
   74            op(1050,  fx, export),
   75            op(1040, xfx, from),
   76            op(1100,  fy, index),               % ignored
   77            op(1100,  fy, ti),                  % transformational indexing?
   78            op(1100,  fx, mode),                % ignored
   79            op(1045, xfx, as),
   80            op(900,   fy, tnot),
   81            op(900,   fy, not),                 % defined as op in XSB
   82            op(1100,  fx, thread_shared)
   83          ]).   84:- use_module(library(error)).   85:- use_module(library(debug)).   86:- use_module(library(dialect/xsb/source)).   87:- use_module(library(tables)).   88:- use_module(library(dialect/xsb/timed_call)).   89:- use_module(library(aggregate)).   90:- use_module(library(option)).   91:- use_module(library(apply)).   92
   93/** <module> XSB Prolog compatibility layer
   94
   95This  module  provides  partial  compatibility   with  the  [XSB  Prolog
   96system](http://xsb.sourceforge.net/)
   97*/
   98
   99:- meta_predicate
  100    xsb_import(:, +),                   % Module interaction
  101
  102    compile(:, +),                      % Loading files
  103    load_dyn(:),
  104    load_dyn(:, +),
  105    load_dync(:),
  106    load_dync(:, +),
  107
  108    thread_shared(:),
  109
  110    fail_if(0),                         % Meta predicates
  111    sk_not(0).  112
  113
  114
  115		 /*******************************
  116		 *	    LIBRARY SETUP	*
  117		 *******************************/
  118
  119%%	push_xsb_library
  120%
  121%	Pushes searching for  dialect/xsb  in   front  of  every library
  122%	directory that contains such as sub-directory.
  123
  124push_xsb_library :-
  125    (   absolute_file_name(library(dialect/xsb), Dir,
  126			   [ file_type(directory),
  127			     access(read),
  128			     solutions(all),
  129			     file_errors(fail)
  130			   ]),
  131	asserta((user:file_search_path(library, Dir) :-
  132		prolog_load_context(dialect, xsb))),
  133	fail
  134    ;   true
  135    ).
  136
  137:- push_xsb_library.  138
  139%!  setup_dialect
  140%
  141%   Further dialect initialization.  Called from expects_dialect/1.
  142
  143:- public setup_dialect/0.  144
  145setup_dialect :-
  146    style_check(-discontiguous).
  147
  148:- multifile
  149    user:term_expansion/2,
  150    user:goal_expansion/2.  151
  152:- dynamic
  153    moved_directive/2.  154
  155% Register XSB specific term-expansion to rename conflicting directives.
  156
  157user:term_expansion(In, Out) :-
  158    prolog_load_context(dialect, xsb),
  159    xsb_term_expansion(In, Out).
  160
  161xsb_term_expansion((:- Directive), []) :-
  162    prolog_load_context(file, File),
  163    retract(moved_directive(File, Directive)),
  164    debug(xsb(header), 'Moved to head: ~p', [Directive]),
  165    !.
  166xsb_term_expansion((:- import Preds from From),
  167                   (:- xsb_import(Preds, From))).
  168xsb_term_expansion((:- index(_PI, _, _)), []).  % what is tbis?
  169xsb_term_expansion((:- index(_PI, _How)), []).
  170xsb_term_expansion((:- index(_PI)), []).
  171xsb_term_expansion((:- ti(_PI)), []).
  172xsb_term_expansion((:- mode(_Modes)), []).
  173
  174user:goal_expansion(In, Out) :-
  175    prolog_load_context(dialect, xsb),
  176    (   xsb_mapped_predicate(In, Out)
  177    ->  true
  178    ;   xsb_inlined_goal(In, Out)
  179    ).
  180
  181xsb_mapped_predicate(expand_file_name(File, Expanded),
  182                     xsb_expand_file_name(File, Expanded)).
  183xsb_mapped_predicate(set_prolog_flag(Flag, Value),
  184                     xsb_set_prolog_flag(Flag, Value)).
  185xsb_mapped_predicate(abolish_module_tables(UserMod),
  186                     abolish_module_tables(user)) :-
  187    UserMod == usermod.
  188
  189xsb_inlined_goal(fail_if(P), \+(P)).
  190
  191%!  xsb_import(:Predicates, +From)
  192%
  193%   Make Predicates visible in From. As the XSB library structructure is
  194%   rather different from SWI-Prolog's, this is a heuristic process.
  195
  196:- dynamic
  197    mapped__module/2.                           % XSB name -> Our name
  198
  199xsb_import(Into:Preds, From) :-
  200    mapped__module(From, Mapped),
  201    !,
  202    xsb_import(Preds, Into, Mapped).
  203xsb_import(Into:Preds, From) :-
  204    xsb_import(Preds, Into, From).
  205
  206xsb_import(Var, _Into, _From) :-
  207    var(Var),
  208    !,
  209    instantiation_error(Var).
  210xsb_import((A,B), Into, From) :-
  211    !,
  212    xsb_import(A, Into, From),
  213    xsb_import(B, Into, From).
  214xsb_import(Name/Arity, Into, From) :-
  215    functor(Head, Name, Arity),
  216    xsb_mapped_predicate(Head, NewHead),
  217    functor(NewHead, NewName, Arity),
  218    !,
  219    xsb_import(NewName/Arity, Into, From).
  220xsb_import(PI, Into, usermod) :-
  221    !,
  222    export(user:PI),
  223    @(import(user:PI), Into).
  224xsb_import(Name/Arity, Into, _From) :-
  225    functor(Head, Name, Arity),
  226    predicate_property(Into:Head, iso),
  227    !,
  228    debug(xsb(import), '~p: already visible (ISO)', [Into:Name/Arity]).
  229xsb_import(PI, Into, From) :-
  230    import_from_module(clean, PI, Into, From),
  231    !.
  232xsb_import(PI, Into, From) :-
  233    prolog_load_context(file, Here),
  234    absolute_file_name(From, Path,
  235                       [ extensions(['P', pl, prolog]),
  236                         access(read),
  237                         relative_to(Here),
  238                         file_errors(fail)
  239                       ]),
  240    !,
  241    debug(xsb(import), '~p: importing from ~p', [Into:PI, Path]),
  242    load_module(Into:Path, PI).
  243xsb_import(PI, Into, From) :-
  244    absolute_file_name(library(From), Path,
  245                       [ extensions(['P', pl, prolog]),
  246                         access(read),
  247                         file_errors(fail)
  248                       ]),
  249    !,
  250    debug(xsb(import), '~p: importing from ~p', [Into:PI, Path]),
  251    load_module(Into:Path, PI).
  252xsb_import(Name/Arity, Into, _From) :-
  253    functor(Head, Name, Arity),
  254    predicate_property(Into:Head, visible),
  255    !,
  256    debug(xsb(import), '~p: already visible', [Into:Name/Arity]).
  257xsb_import(PI, Into, From) :-
  258    import_from_module(dirty, PI, Into, From),
  259    !.
  260xsb_import(_Name/_Arity, _Into, From) :-
  261    existence_error(xsb_module, From).
  262
  263%!  import_from_module(?Clean, +PI, +Into, +From) is semidet.
  264%
  265%   Try to import PI into  module  Into   from  Module  From.  The clean
  266%   version only deals  with  cleanly   exported  predicates.  The dirty
  267%   version is more aggressive.
  268
  269import_from_module(clean, PI, Into, From) :-
  270    module_property(From, exports(List)),
  271    memberchk(PI, List),
  272    !,
  273    debug(xsb(import), '~p: importing from module ~p', [Into:PI, From]),
  274    @(import(From:PI), Into).
  275import_from_module(dirty, PI, Into, From) :-
  276    current_predicate(From:PI),
  277    !,
  278    debug(xsb(import), '~p: importing from module ~p', [Into:PI, From]),
  279    (   check_exported(From, PI)
  280    ->  @(import(From:PI), Into)
  281    ;   true
  282    ).
  283import_from_module(dirty, PI, _Into, From) :-
  284    module_property(From, file(File)),
  285    !,
  286    print_message(error, xsb(not_in_module(File, From, PI))).
  287
  288check_exported(Module, PI) :-
  289    module_property(Module, exports(List)),
  290    memberchk(PI, List),
  291    !.
  292check_exported(Module, PI) :-
  293    module_property(Module, file(File)),
  294    print_message(error, xsb(not_in_module(File, Module, PI))).
  295
  296load_module(Into:Path, PI) :-
  297    use_module(Into:Path, []),
  298    (   module_property(Module, file(Path))
  299    ->  file_base_name(Path, File),
  300        file_name_extension(Base, _, File),
  301        (   Base == Module
  302        ->  true
  303        ;   atom_concat(xsb_, Base, Module)
  304        ->  map_module(Base, Module)
  305        ;   print_message(warning,
  306                          xsb(file_loaded_into_mismatched_module(Path, Module))),
  307            map_module(Base, Module)
  308        )
  309    ;   print_message(warning, xsb(loaded_unknown_module(Path)))
  310    ),
  311    import_from_module(_, PI, Into, Module).
  312
  313map_module(XSB, Module) :-
  314    mapped__module(XSB, Module),
  315    !.
  316map_module(XSB, Module) :-
  317    assertz(mapped__module(XSB, Module)).
  318
  319
  320%!  xsb_set_prolog_flag(+Flag, +Value)
  321%
  322%   Map some XSB Prolog flags to their SWI-Prolog's equivalents.
  323
  324xsb_set_prolog_flag(unify_with_occurs_check, XSBVal) :-
  325    !,
  326    map_bool(XSBVal, Val),
  327    set_prolog_flag(occurs_check, Val).
  328xsb_set_prolog_flag(Flag, Value) :-
  329    set_prolog_flag(Flag, Value).
  330
  331map_bool(on, true).
  332map_bool(off, false).
  333
  334
  335		 /*******************************
  336		 *      BUILT-IN PREDICATES	*
  337		 *******************************/
  338
  339%!  add_lib_dir(+Directories) is det.
  340%!  add_lib_dir(+Root, +Directories) is det.
  341%
  342%   Add    members    of    the    comma      list     Directories    to
  343%   user:library_directory/1.  If  Root  is  given,    all   members  of
  344%   Directories are interpreted relative to Root.
  345
  346add_lib_dir(Directories) :-
  347    add_lib_dir('.', Directories).
  348
  349add_lib_dir(_, Var) :-
  350    var(Var),
  351    !,
  352    instantiation_error(Var).
  353add_lib_dir(Root, (A,B)) :-
  354    !,
  355    add_lib_dir(Root, A),
  356    add_lib_dir(Root, B).
  357add_lib_dir(Root, a(Dir)) :-
  358    !,
  359    add_to_library_directory(Root, Dir, asserta).
  360add_lib_dir(Root, Dir) :-
  361    add_to_library_directory(Root, Dir, assertz).
  362
  363add_to_library_directory(Root, Dir, How) :-
  364    (   expand_file_name(Dir, [Dir1])
  365    ->  true
  366    ;   Dir1 = Dir
  367    ),
  368    relative_file_name(TheDir, Root, Dir1),
  369    exists_directory(TheDir),
  370    !,
  371    (   user:library_directory(TheDir)
  372    ->  true
  373    ;   call(How, user:library_directory(TheDir))
  374    ).
  375add_to_library_directory(_, _, _).
  376
  377%!  compile(File, Options)
  378%
  379%   The XSB version compiles a file into .xwam without loading it. We do
  380%   not have that. Calling qcompile/1 seems the best start.
  381
  382compile(File, _Options) :-
  383    qcompile(File).
  384
  385%!  load_dyn(+FileName) is det.
  386%!  load_dyn(+FileName, +Direction) is det.
  387%!  load_dync(+FileName) is det.
  388%!  load_dync(+FileName, +Direction) is det.
  389%
  390%   Proper implementation requires  the   Quintus  `all_dynamic` option.
  391%   SWI-Prolog never had that as  clause/2   is  allowed on static code,
  392%   which is the main reason to want this.
  393%
  394%   The _dync_ versions demand source in canonical format. In SWI-Prolog
  395%   there is little reason to demand this.
  396
  397load_dyn(File)       :-
  398    '$style_check'(Style, Style),
  399    setup_call_cleanup(
  400        style_check(-singleton),
  401        load_files(File),
  402        '$style_check'(_, Style)).
  403
  404load_dyn(File, Dir)  :- must_be(oneof([z]), Dir), load_dyn(File).
  405load_dync(File)      :- load_dyn(File).
  406load_dync(File, Dir) :- load_dyn(File, Dir).
  407
  408%!  set_global_compiler_options(+List) is det.
  409%
  410%   Set the XSB global compiler options.
  411
  412:- multifile xsb_compiler_option/1.  413:- dynamic   xsb_compiler_option/1.  414
  415set_global_compiler_options(List) :-
  416    must_be(list, List),
  417    maplist(set_global_compiler_option, List).
  418
  419set_global_compiler_option(+Option) :-
  420    !,
  421    valid_compiler_option(Option),
  422    (   xsb_compiler_option(Option)
  423    ->  true
  424    ;   assertz(xsb_compiler_option(Option))
  425    ).
  426set_global_compiler_option(-Option) :-
  427    !,
  428    valid_compiler_option(Option),
  429    retractall(xsb_compiler_option(Option)).
  430set_global_compiler_option(-Option) :-
  431    valid_compiler_option(Option),
  432    (   xsb_compiler_option(Option)
  433    ->  true
  434    ;   assertz(xsb_compiler_option(Option))
  435    ).
  436
  437valid_compiler_option(Option) :-
  438    must_be(oneof([ singleton_warnings_off,
  439                    optimize,
  440                    allow_redefinition,
  441                    xpp_on,
  442                    spec_off
  443                  ]), Option).
  444
  445%!  compiler_options(+Options) is det.
  446%
  447%   Locally switch the compiler options
  448
  449compiler_options(Options) :-
  450    must_be(list, Options),
  451    maplist(compiler_option, Options).
  452
  453compiler_option(+Option) :-
  454    !,
  455    valid_compiler_option(Option),
  456    set_compiler_option(Option).
  457compiler_option(-Option) :-
  458    !,
  459    valid_compiler_option(Option),
  460    clear_compiler_option(Option).
  461compiler_option(Option) :-
  462    valid_compiler_option(Option),
  463    set_compiler_option(Option).
  464
  465set_compiler_option(singleton_warnings_off) :-
  466    style_check(-singleton).
  467set_compiler_option(optimize) :-
  468    set_prolog_flag(optimise, true).
  469set_compiler_option(allow_redefinition).
  470set_compiler_option(xpp_on).
  471set_compiler_option(spec_off).
  472
  473clear_compiler_option(singleton_warnings_off) :-
  474    style_check(+singleton).
  475clear_compiler_option(optimize) :-
  476    set_prolog_flag(optimise, false).
  477clear_compiler_option(allow_redefinition).
  478clear_compiler_option(xpp_on).
  479
  480		 /*******************************
  481		 *            BUILT-INS		*
  482		 *******************************/
  483
  484%!  fail_if(:P)
  485%
  486%   Same as \+ (support XSB legacy code).  As the XSB manual claims this
  487%   is optimized we normally do goal expansion to \+/1.
  488
  489fail_if(P) :-
  490    \+ P.
  491
  492		 /*******************************
  493		 *      TABLING BUILT-INS	*
  494		 *******************************/
  495
  496%!  sk_not(:P) is semidet.
  497%
  498%   Sound negation with non-ground P.  Equivalent to not_exists/1.
  499%
  500%   @deprecated New code should use not_exists/1.
  501
  502sk_not(P) :-
  503    not_exists(P).
  504
  505%!  gc_tables(-Remaining) is det.
  506%
  507%   The table abolish predicates leave  the   actual  destruction of the
  508%   tables to the atom  garbage  collector   to  avoid  deleting  active
  509%   tables. This predicate runs garbage_collect_atoms/0   and counts the
  510%   remaining erased tables.
  511%
  512%   @compat Due to the heuristic nature of garbage_collect_atoms/0, not
  513%   all tables may be reclaimed immediately.
  514
  515gc_tables(Remaining) :-
  516    garbage_collect_atoms,
  517    aggregate_all(count, remaining_table(_), Remaining).
  518
  519remaining_table(Trie) :-
  520    current_blob(Trie, trie),
  521    '$is_answer_trie'(Trie),
  522    '$atom_references'(Trie, 0).
  523
  524%!  cputime(-Seconds) is det.
  525%
  526%   True when Seconds is the used CPU time.
  527
  528cputime(Seconds) :-
  529    statistics(cputime, Seconds).
  530
  531%!  walltime(-Seconds) is det.
  532%
  533%   True when Seconds is the wall time sice Prolog was started
  534
  535walltime(Seconds) :-
  536    get_time(Now),
  537    statistics(epoch, Epoch),
  538    Seconds is Now - Epoch.
  539
  540%!  debug_ctl(+Option, +Value) is det.
  541%
  542%   Control the XSB debugger. The  current implementation merely defines
  543%   the predicate. Much more can be mapped to SWI-Prolog primitives.
  544
  545debug_ctl(prompt, off) :-
  546    !,
  547    leash(-all).
  548debug_ctl(prompt, on) :-
  549    !,
  550    leash(+full).
  551debug_ctl(hide, Preds) :-
  552    !,
  553    '$hide'(Preds).
  554debug_ctl(Option, Value) :-
  555    debug(xsb(compat), 'XSB: not implemented: ~p',
  556          [ debug_ctl(Option, Value) ]).
  557
  558%!  thread_shared(+Spec)
  559%
  560%   Declare a dynamic predicate  as  shared.   This  is  the default for
  561%   SWI-Prolog.
  562
  563thread_shared(Spec) :-
  564    dynamic(Spec).
  565
  566
  567%!  fmt_write(+Fmt, +Term) is det.
  568%!  fmt_write(+Stream, +Fmt, +Term) is det.
  569%
  570%   C-style formatted write, where  the  arguments   are  formed  by the
  571%   arguments of Term.  We map this to format/2,3.
  572%
  573%   @bug We need to complete the  translation of the fmt_write sequences
  574%   to format/2,3 sequences.
  575
  576fmt_write(Fmt, Term) :-
  577    fmt_write(current_output, Fmt, Term).
  578
  579fmt_write(Stream, Fmt, Term) :-
  580    (   compound(Term)
  581    ->  Term =.. [_|Args]
  582    ;   Args = [Term]
  583    ),
  584    fmt_write_format(Fmt, Format),
  585    format(Stream, Format, Args).
  586
  587:- dynamic
  588    fmt_write_cache/2.  589
  590fmt_write_format(Fmt, Format) :-
  591    fmt_write_cache(Fmt, Format),
  592    !.
  593fmt_write_format(Fmt, Format) :-
  594    string_codes(Fmt, FmtCodes),
  595    phrase(format_fmt(Codes, []), FmtCodes),
  596    atom_codes(Format, Codes),
  597    asserta(fmt_write_cache(Fmt, Format)).
  598
  599format_fmt(Format, Tail) -->
  600    "%",
  601    (   format_esc(Format, Tail0)
  602    ->  !
  603    ;   here(Rest),
  604        { print_message(warning, xsb(fmt_write(ignored(Rest)))),
  605          fail
  606        }
  607    ),
  608    format_fmt(Tail0, Tail).
  609format_fmt([0'~,0'~|T0], T) -->
  610    "~",
  611    !,
  612    format_fmt(T0, T).
  613format_fmt([H|T0], T) -->
  614    [H],
  615    !,
  616    format_fmt(T0, T).
  617format_fmt(T, T) --> [].
  618
  619format_esc(Fmt, Tail) -->
  620    format_esc(Fmt0),
  621    !,
  622    { append(Fmt0, Tail, Fmt)
  623    }.
  624
  625format_esc(`~16r`) --> "x".
  626format_esc(`~d`) --> "d".
  627format_esc(`~f`) --> "f".
  628format_esc(`~s`) --> "s".
  629format_esc(`%`) --> "%".
  630
  631here(Rest, Rest, Rest).
  632
  633%!  path_sysop(+Op, ?Value) is semidet.
  634%!  path_sysop(+Op, ?Arg1, ?Arg2) is semidet.
  635%
  636%   Unified interface to the  operations  on   files.  All  these  calls
  637%   succeed iff the corresponding system call succeeds.
  638%
  639%   @compat The below implementation covers all operations from XSB 3.8.
  640%   SWI file name operations are always on   POSIX style file names. The
  641%   implementation may have semantic differences.
  642
  643path_sysop(isplain, File) :-
  644    exists_file(File).
  645path_sysop(isdir, Dir) :-
  646    exists_directory(Dir).
  647path_sysop(rm, File) :-
  648    delete_file(File).
  649path_sysop(rmdir, Dir) :-
  650    delete_directory(Dir).
  651path_sysop(rmdir_rec, Dir) :-
  652    delete_directory_and_contents(Dir).
  653path_sysop(cwd, CWD) :-
  654    working_directory(CWD, CWD).
  655path_sysop(chdir, CWD) :-
  656    working_directory(_, CWD).
  657path_sysop(mkdir, Dir) :-
  658    make_directory(Dir).
  659path_sysop(exists, Entry) :-
  660    access_file(Entry, exist).
  661path_sysop(readable, Entry) :-
  662    access_file(Entry, read).
  663path_sysop(writable, Entry) :-
  664    access_file(Entry, write).
  665path_sysop(executable, Entry) :-
  666    access_file(Entry, execute).
  667path_sysop(tmpfilename, Name) :-
  668    tmp_file(swi, Name).
  669path_sysop(isabsolute, Name) :-
  670    is_absolute_file_name(Name).
  671
  672
  673path_sysop(rename, Old, New) :-
  674    rename_file(Old, New).
  675path_sysop(copy, From, To) :-
  676    copy_file(From, To).
  677path_sysop(link, From, To) :-
  678    link_file(From, To, symbolic).
  679path_sysop(modtime, Path, Time) :-
  680    time_file(Path, Time).
  681path_sysop(newerthan, Path1, Path2) :-
  682    time_file(Path1, Time1),
  683    (   catch(time_file(Path2, Time2), error(existence_error(_,_),_), fail)
  684    ->  Time1 > Time2
  685    ;   true
  686    ).
  687path_sysop(size, Path, Size) :-
  688    size_file(Path, Size).
  689path_sysop(extension, Path, Ext) :-
  690    file_name_extension(_, Ext, Path).
  691path_sysop(basename, Path, Base) :-
  692    file_base_name(Path, File),
  693    file_name_extension(Base, _, File).
  694path_sysop(dirname, Path, Dir) :-
  695    file_directory_name(Path, Dir0),
  696    (   sub_atom(Dir0, _, _, 0, /)
  697    ->  Dir = Dir0
  698    ;   atom_concat(Dir0, /, Dir)
  699    ).
  700path_sysop(expand, Name, Path) :-
  701    absolute_file_name(Name, Path).
  702
  703%!  abort(+Message:atomic)
  704%
  705%   Abort with a message
  706
  707abort(Message) :-
  708    print_message(error, aborted(Message)),
  709    abort.
  710
  711		 /*******************************
  712		 *           MESSAGES		*
  713		 *******************************/
  714
  715:- multifile
  716    prolog:message//1.  717
  718prolog:message(xsb(not_in_module(File, Module, PI))) -->
  719    [ 'XSB: ~p, implementing ~p does not export ~p'-[File, Module, PI] ].
  720prolog:message(xsb(file_loaded_into_mismatched_module(File, Module))) -->
  721    [ 'XSB: File ~p defines module ~p'-[File, Module] ].
  722prolog:message(xsb(ignored(debug_ctl(Option, Value)))) -->
  723    [ 'XSB: debug_ctl(~p,~p) is not implemented'-[Option,Value] ]