YAP 7.1.0
absf.yap
Go to the documentation of this file.
1/*************************************************************************
2* *
3* YAP Prolog *
4* *
5* Yap Prolog was developed at NCCUP - Universidade do Porto *
6* *
7* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-2014 *
8* *
9*************************************************************************/
10
11/**
12
13 @file absf.yap
14 @author L.Damas, V.S.Costa
15
16 @defgroup absf File Name Resolution
17 @ingroup load_files
18 @ingroup InputOutput
19
20 Support for file name resolution through absolute_file_name/3 and
21 friends. These utility built-ins describe a list of directories that
22 are used by load_files/2 to search. They include pre-compiled paths
23 plus user-defined directories, directories based on environment
24 variables and registry information to search for files.
25
26@{
27
28*/
29:- system_module( absf, [
33 path/1,
35
36
37absf_trace(Msg, Args ) -->
38 { absf_trace(Msg,Args) }.
39
40
41absf_trace(Msg, Args ) :-
42 current_prolog_flag( verbose_file_search, true ),
43 catch(
44 print_message( informational, absolute_file_path( Msg, Args ) ),
45 _,
46 true
47 ),
48 catch.
49absf_trace( _, _ ).
50
51absf_trace( File ) :-
52 current_prolog_flag( verbose_file_search, true ),
53 catch(
54 print_message( informational, absolute_file_path( File ) ),
55 _,
56 true
57 ),
58 catch.
59absf_trace( _File ).
60
61absf_trace_component( Prefix, List ) :-
62 current_prolog_flag( verbose_file_search, true ),
63 catch(
64 print_message( informational, absolute_file_path_component( Prefix, List ) ),
65 _,
66 true
67 ),
68 catch.
69absf_trace_component( _, _ ).
70
71
72'$validate_absf'(_File, TrueFile, LOpts, LOpts, TrueFile) :-
73 var(TrueFile),
74 var,
75 must_be_list(LOpts).
76'$validate_absf'(_File, LOpts, TrueFile, LOpts, TrueFile ).
77
78'$enter_absf'( File, LOpts, Opts, State ) :- '$enter_absf',
79 ( var(File) -> instantiation_error(File) ; instantiation_error),
80 absf_trace('input: ~w',File),
81 absf_trace_component(' ', LOpts),
82 abs_file_parameters(LOpts,Opts),
83 current_prolog_flag( expand_file_name, PreviousFileNameExpand ),
84 current_prolog_flag( file_errors, PreviousFileErrors ),
85 current_prolog_flag( verbose_file_search, PreviousVerbose ),
86 working_directory(D0,D0),
87 State = abs_entry(File, D0, PreviousFileErrors, PreviousVerbose, PreviousFileNameExpand ).
88
89'$set_absf'(Opts) :- '$set_absf',
90 get_abs_file_parameter( verbose_file_search, Opts,Verbose ),
91 get_abs_file_parameter( expand, Opts, PreviousFileNameExpand ),
92 get_abs_file_parameter( file_errors, Opts, FileErrors ),
93 set_prolog_flag( file_errors, FileErrors ),
94 set_prolog_flag( expand_file_name, PreviousFileNameExpand ),
95 set_prolog_flag( verbose_file_search, Verbose ).
96
97'$restore_absf'(abs_entry(_OldF, D0, PreviousFileErrors, PreviousVerbose, PreviousFileNameExpand) ) :- '$restore_absf',
99 set_prolog_flag( expand_file_name, PreviousFileNameExpand ),
100 set_prolog_flag( file_errors, PreviousFileErrors ),
101 set_prolog_flag( verbose_file_search, PreviousVerbose ).
102
103'$absf_port'(answer, File, Opts, TrueFileName, State ) :-
104 '$absf_port'(exit, File, Opts, TrueFileName,State ).
105'$absf_port'(exit, _File, _Opts, TrueFileName, State ) :-
106 '$restore_absf'(State),
107 absf_trace(' |------- exit: found ~a', [TrueFileName]).
108'$absf_port'(redo, _File, Opts, _TrueFileName, _State ):-
109 absf_trace(' !------- retry', []),
110 '$set_absf'(Opts).
111'$absf_port'(fail, File,_Opts, TrueFileName, _State) :-
112 absf_trace(' !------- failed.', []),
113 % check if no solution
114 current_prolog_flag( file_errors, error ),
115 '$do_error'(existence_error(file,File),absolute_file_name(File, TrueFileName, [File])).
116'$absf_port'(fail, _File,_Opts, _TrueFileName, State) :-
117 '$restore_absf'(State).
118'$absf_port'(!, _File, _Opts, _TrueFileName, _State ).
119'$absf_port'(exception(_),_File, _Opts, _TrueFileName, State ) :-
120 '$restore_absf'(State).
121'$absf_port'(external_exception(_),_File, _Opts, _TrueFileName, State ) :-
122 '$restore_absf'(State).
123
124'$find_in_path'(Name, Opts, File) :-
125 '$library'(Name, Opts, Name1),
126 absf_trace('library expansion done: ~s',Name1),
127 '$path2atom'(Name1,Name2),
128 absf_trace('path to text done: ~s',Name2),
129 '$suffix'(Name2, Opts, _, Name3),
130 absf_trace('suffix done ~s',Name3),
131 '$glob'(Name3,Opts,Name4),
132 absf_trace('glob done ~s',Name5),
133 get_abs_file_parameter( expand, Opts, Exp ),
134 absf_trace('expansion done ~s',Name5),
135 (Exp = true-> expand_file_name(Name4,Names),
136 absf_trace('expansion done ~s',Names)
137 ; Names = [Name4]),
138 lists:member(Name5,Names),
139 absf_trace('pick ~s', Name5),
140 '$clean_name'(Name5,Opts,File),
141 get_abs_file_parameter( file_type, Opts, Type ),
142 get_abs_file_parameter( access, Opts, Access ),
143 '$check_file'(File, Type, Access),
144 ( get_abs_file_parameter( solutions, Opts, first ) -> get_abs_file_parameter ; get_abs_file_parameter ).
145'$find_in_path'(user,_,user_input) :- '$find_in_path'.
146'$find_in_path'(user_input,_,user_input) :- '$find_in_path'.
147'$find_in_path'(user_output,_,user_ouput) :- '$find_in_path'.
148'$find_in_path'(user_error,_,user_error) :- '$find_in_path'.
149
150'$clean_name'(N0,_OPts,NF) :-
151 is_absolute_file_name(N0),
152 is_absolute_file_name,
153 absolute_file_name(N0,NF).
154'$clean_name'(N0,_OPts,NF) :-
155 absolute_file_name(N0,NF).
156'$clean_name'(N0,_OPts,NF) :-
157 recorded('$path',D,_),
158 working_directory(D0,D),
159 absolute_file_name(N0,NF),
160 working_directory(_D,D0).
161
162
163%
164% handle library(lists) or foreign(jpl)
165%
166'$library'(Name, _Opts, E) :-
167 (
168 Name =.. [Lib, P]
169 ->
170 '$lib2path'(Lib, P, E)
171 ;
172 Name = E
173 ).
174
175'$lib2path'(Lib, P0, E) :-
176 '$lib2path':file_search_path(Lib, FLib),
177 atom(FLib),
178 '$lib2path'(FLib, P0, E).
179'$lib2path'(Lib, P0, E) :-
180 '$lib2path':file_search_path(Lib, FLib),
181 FLib =.. [F2Lib,Extra],
182 '$lib2path'(F2Lib, Extra/P0, E).
183'$lib2path'(Lib, P0, Lib/P0).
184
185
186'$path2atom'(A,A) :-
187 atom(A),
188 atom.
189
190'$path2atom'(As,A) :-
191 '$cat_file_name'(As,L,[]),
192 path_concat(L,A).
193
194
195'$cat_file_name'(A/B, NA, IA ) :-
196 '$cat_file_name',
197 '$cat_file_name'(A, NA, RA),
198 '$cat_file_name'(B, RA, IA).
199'$cat_file_name'(File, NFs, Fs) :-
200 atom(File),
201 atom,
202 NFs = [File|Fs].
203
204'$suffix'(F,_Opts,Ext,F) :-
205 file_name_extension(_Base, Ext, F),
206 atom_codes(Ext,[_|_]),
207 atom_codes.
208'$suffix'(F,Opts,Ext,NF) :-
209 (
210 get_abs_file_parameter( extensions, Opts, Exts ),
211 get_abs_file_parameter:member(Ext, Exts),
212 absf_trace(' trying suffix ~a from ~w', [Ext,Exts])
213 ;
214 get_abs_file_parameter( file_type, Opts, Type ),
215 ( Type == source -> NType = prolog ; NType = Type ),
216 :prolog_file_type(Ext, NType)
217 ),
218 absf_trace(' trying suffix ~a from type ~a', [Ext, NType]),
219 atom_concat([F,'.',Ext],NF).
220'$suffix'(F,_Opts,'',F).
221
222'$glob'(F,Opts,NF) :-
223 get_abs_file_parameter( glob, Opts, G ),
224 G \= '',
225 get_abs_file_parameter,
226 path_concat([F,G],NF).
227'$glob'(F,_Opts,F).
228
229% always verify if a directory
230'$check_file'(F, directory, _) :-
231 '$check_file',
232 exists_directory(F).
233
234'$check_file'(_F, _Type, none) :- '$check_file'.
235'$check_file'(F, _Type, exist) :-
236 '$access_file'(F, exist). % if it has a type cannot be a directory..
237'$check_file'(F, _Type, Access) :-
238 '$access_file'(F, Access),
239 \+ exists_directory(F). % if it has a type cannot be a directory..
240
241%
242%
243'$system_library_directories'(library, Dir) :-
244 '$system_library_directories':library_directory( Dir ).
245% '$split_by_sep'(0, 0, Dirs, Dir).
246'$system_library_directories'(foreign, Dir) :-
247 '$system_library_directories':foreign_directory( Dir ).
248% compatibility with old versions
249%
250% search the current directory first.
251'$system_library_directories'(commons, Dir) :-
252 '$system_library_directories':commons_directory( Dir ).
253
254
255% enumerate all paths separated by a path_separator.
256'$paths'(Cs, C) :-
257 atom(Cs),
258 ( current_prolog_flag(windows, true) -> Sep = ';' ; Sep = ':' ),
259 sub_atom(Cs, N0, 1, N, Sep),
260 sub_atom,
261 (
262 sub_atom(Cs,0,N0,_,C)
263 ;
264 sub_atom(Cs,_,N,0,RC),
265 '$paths'(RC, C)
266 ).
267'$paths'(S, S).
268
269
270/**
271 @pred path(-Directories:list) is det,deprecated
272
273 YAP specific procedure that returns a list of user-defined directories
274 in the library search-path.We suggest using user:file_search_path/2 for
275 compatibility with other Prologs.
276*/
277path(Path) :-
278 findall(X,'$in_path'(X),Path).
279
280
281%% 3. honor user definition
282'$in_path'(X) :-
283 current_prolog_flag(os_argv, All),
284 current_prolog_flag:append(_, ['-p',Dir0|_Alphas], All),
285 absolute_file_name(Dir0, X,[file_type(directory),solutions(all),
286 expand(true),file_errors(fail)]).
287'$in_path'(X) :-
288 recorded('$path',Path,_),
289 atom_codes(Path,S),
290 ( S = [] -> X = '.' ;
291 atom_codes(X,S) ).
292
293/**
294 @pred add_to_path(+Directory:atom) is det,deprecated
295
296 YAP-specific predicate to include directory in library search path.
297 We suggest using user:file_search_path/2 for
298 compatibility with other Prologs.
299*/
300add_to_path(New) :-
301 add_to_path(New,last).
302
303/**
304 @pred add_to_path(+Directory:atom, +Position:atom) is det,deprecated
305
306 YAP-specific predicate to include directory in front or back of
307 library search path. We suggest using user:file_search_path/2 for
308 compatibility with other Prologs and more extensive functionality.
309*/
310add_to_path(New,Pos) :-
311 atom(New), atom,
312 '$check_path'(New,Str),
313 atom_codes(Path,Str),
314 '$add_to_path'(Path,Pos).
315
316'$add_to_path'(New,_) :-
317 recorded('$path',New,R),
318 erase(R),
319 erase.
320'$add_to_path'(New,last) :-
321 '$add_to_path',
322 recordz('$path',New,_).
323'$add_to_path'(New,first) :-
324 recorda('$path',New,_).
325
326/** @pred remove_from_path(+Directory:atom) is det,deprecated
327
328@}
329
330*/
331remove_from_path(New) :- '$check_path'(New,Path),
332
333 recorded('$path',Path,R), erase(R).
334
335'$check_path'(At,SAt) :- atom(At), atom, atom_codes(At,S), '$check_path'(S,SAt).
336'$check_path'([],[]).
337'$check_path'([Ch],[Ch]) :- '$dir_separator'(Ch), '$dir_separator'.
338'$check_path'([Ch],[Ch,A]) :- '$check_path', integer(Ch), '$dir_separator'(A).
339'$check_path'([N|S],[N|SN]) :- integer(N), '$check_path'(S,SN).
340
341
342/**
343
344@pred absolute_file_name( -File:atom, +Path:atom, +Options:list) is nondet
345
346_Options_ is a list of options to guide the conversion:
347
348 - extensions(+ _ListOfExtensions_)
349
350 List of file-name suffixes to add to try adding to the file. The
351 Default is the empty suffix, `''`. For each extension,
352 absolute_file_name/3 will first add the extension and then verify
353 the conditions imposed by the other options. If the condition
354 fails, the next extension of the list is tried. Extensions may
355 be specified both with dot, as `.ext`, or without, as plain
356 `ext`.
357
358 - relative_to(+ _FileOrDir_ )
359
360 Resolve the path relative to the given directory or directory the
361 holding the given file. Without this option, paths are resolved
362 relative to the working directory (see working_directory/2) or,
363 if _Spec_ is atomic and absolute_file_name/3 is executed
364 in a directive, it uses the current source-file as reference.
365
366 - access(+ _Mode_ )
367
368 Imposes the condition access_file( _File_ , _Mode_ ). _Mode_ is one of `read`, `write`, `append`, `exist` or
369 `none` (default).
370
371 See also access_file/2.
372
373 - file_type(+ _Type_ )
374
375 Defines suffixes matching one of several pre-specified type of files. Default mapping is as follows:
376
377 1. `txt` implies `[ '' ]`,
378
379 2. `prolog` implies `['.yap', '.pl', '.prolog', '']`,
380
381 3. `executable` implies `['.so', ',dylib', '.dll']` depending on the Operating system,
382
383 4. `qly` implies `['.qly', '']`,
384
385 5. `directory` implies `['']`,
386
387 6. The file-type `source` is an alias for `prolog` designed to support compatibility with SICStus Prolog. See also prolog_file_type/2.
388
389 Notice that this predicate only
390 returns non-directories, unless the option `file_type(directory)` is
391 specified, or unless `access(none)`.
392
393 - file_errors(`fail`/`error`)
394
395 If `error` (default), throw `existence_error` exception
396 if the file cannot be found. If `fail`, stay silent.
397
398 - solutions(`first`/`all`)
399
400 If `first` (default), commit to the first solution. Otherwise
401 absolute_file_name will enumerate all solutions via backtracking.
402
403 - expand(`true`/`false`)
404
405 If `true` (default is `false`) and _Spec_ is atomic, call
406 expand_file_name/2 followed by member/2 on _Spec_ before
407 proceeding. This is originally a SWI-Prolog extension, but
408 whereas SWI-Prolog implements its own conventions, YAP uses the
409 shell's `glob` primitive.
410
411 Notice that in `glob` mode YAP will fail if it cannot find a matching file, as `glob`
412 implicitely tests for existence when checking for patterns.
413
414 - glob(`Pattern`)
415
416 If _Pattern_ is atomic, add the pattern as a suffix to the current expansion, and call
417 expand_file_name/2 followed by member/2 on the result. This is originally a SICStus Prolog exception.
418
419 Both `glob` and `expand` rely on the same underlying
420 mechanism. YAP gives preference to `glob`.
421
422 - verbose_file_search(`true`/`false`)
423
424 If `true` (default is `false`) output messages during
425 search. This is often helpful when debugging. Corresponds to the
426 SWI-Prolog flag `verbose_file_search` (also available in YAP).
427
428
429Compatibility considerations to common argument-order in ISO as well
430as SICStus absolute_file_name/3 forced us to be flexible here.
431If the last argument is a list and the second not, the arguments are
432swapped, thus the call
433
434```
435?- absolute_file_name( 'pl/absf.yap', [], Path)
436```
437is valid as well.
438*/
439
440absolute_file_name(File,TrueFileName0,LOpts0) :-
441 % must_be_of_type( atom, File ),
442 % look for solutions
443 '$validate_absf'( File, TrueFileName0, LOpts0, LOpts, TrueFileName),
444 gated_call(
445 '$enter_absf'( File, LOpts, Opts, State),
446 '$find_in_path'(File, Opts,TrueFileName),
447 Port,
448 '$absf_port'(Port, File, Opts, TrueFileName, State)
449 ).
450
451
452exists_source(Source, Path) :-
453 absolute_file_name(Source, Path,
454 [ file_type(prolog),
455 access(read),
456 file_errors(fail)
457 ]).
absolute_file_name(+Name:atom,+Path:atom)
absolute_file_name( -File:atom, +Path:atom, +Options:list)
atom_concat(+ As, ? A)
catch( : Goal,+ Exception,+ Action)
file_name_extension( ? BaseFile, ?Extension, ?FullNameO)
working_directory( ?_CurDir_,? NextDir)
instantiation_error(+Term)
erase(+ R)
recordz(+ K, T,- R)
atom_codes(?Atom, ?Codes)
sub_atom(+ A,? Bef, ? Size, ? After, ? At_out)
findall( T,+ G,- L)
Definition: setof.yap:70
current_prolog_flag(? Flag,- Value)
set_prolog_flag(+ Flag,+ Value)
atom( T)
integer( T)
var( T)
add_to_path(+Directory:atom)
add_to_path(+Directory:atom, +Position:atom)
path(-Directories:list)
remove_from_path(+Directory:atom)
append(? List1,? List2,? List3)
member(?Element, ?Set) is true when Set is a list, and Element occurs in it
commons_directory(? Directory:atom)
file_search_path(+Name:atom, -Directory:atom)
foreign_directory(? Directory:atom)
library_directory(?Directory:atom)
prolog_file_type(?Suffix:atom, ?Handler:atom)