34
35:- module(swish_include,
36 [
37 ]). 38:- use_module(storage). 39:- use_module(config). 40:- use_module(library(sandbox), []). 41:- use_module(library(debug)). 42:- use_module(library(settings)). 43:- use_module(library(filesex)). 44:- use_module(library(error)). 45:- use_module(library(readutil)).
62swish:term_expansion(:- include(FileIn), Expansion) :-
63 include_file_id(FileIn, File),
64 ( prolog_load_context(module, Module),
65 clause(Module:'swish included'(File), true)
66 -> Expansion = []
67 ; Expansion = [ (:- discontiguous('swish included'/1)),
68 'swish included'(File),
69 (:- include(stream(URI, Stream, [close(true)])))
70 ],
71 '$push_input_context'(swish_include),
72 include_data(File, URI, Data),
73 open_string(Data, Stream),
74 '$pop_input_context'
75 ).
81include_data(Name, URI, Data) :- 82 atom(Name),
83 !,
84 add_extension(Name, FileExt),
85 catch(storage_file(FileExt, Data, _Meta),
86 error(existence_error(_,_),_),
87 fail),
88 atom_concat('swish://', FileExt, URI).
89include_data(Spec, URI, Data) :-
90 absolute_file_name(Spec, Path, [ file_type(prolog), access(read) ]),
91 read_file_to_string(Path, Data, []),
92 Spec =.. [Alias,_],
93 file_base_name(Path, NameExt),
94 format(atom(URI), 'swish://~w/~w', [Alias, NameExt]).
101include_file_id(FileIn, File) :-
102 atomic(FileIn),
103 !,
104 atom_string(File, FileIn).
105include_file_id(FileIn, File) :-
106 compound(FileIn),
107 FileIn =.. [Alias,NameIn],
108 atom_string(Name, NameIn),
109 ( safe_name(Name),
110 swish_config(include_alias, Alias)
111 -> true
112 ; permission_error(include, file, Name)
113 ),
114 File =.. [Alias,Name].
115
116safe_name(Name) :-
117 \+ ( sub_atom(Name, 0, _, _, '../')
118 ; sub_atom(Name, _, _, _, '/../')
119 ; sub_atom(Name, _, _, 0, '/..')
120 ; Name == '..'
121 ).
128file_alias(File, Spec) :-
129 atomic_list_concat([Alias,Name], /, File),
130 swish_config(include_alias, Alias),
131 safe_name(Name),
132 !,
133 Spec =.. [Alias,Name].
139add_extension(File, FileExt) :-
140 file_name_extension(_, Ext, File),
141 Ext \== '',
142 !,
143 FileExt = File.
144add_extension(Hash, Hash) :-
145 is_hash(Hash),
146 !.
147add_extension(File, FileExt) :-
148 file_name_extension(File, pl, FileExt).
149
150is_hash(Name) :-
151 atom_length(Name, 40),
152 split_string(Name, ":", "0123456789abcdef", [""]).
153
154
155 158
159:- multifile
160 sandbox:safe_directive/1. 161
162sandbox:safe_directive(M:include(stream(Id, Stream, [close(true)]))) :-
163 is_stream(Stream),
164 sub_atom(Id, 0, _, _, 'swish://'),
165 prolog_load_context(module, M).
166
167
168 171
172:- multifile
173 prolog_colour:term_colours/2. 174
175prolog_colour:term_colours((:- include(FileIn)),
176 neck(directive) -
177 [ goal(built_in,include(FileIn)) -
178 [ FileClass
179 ]
180 ]) :-
181 debug(include, 'Classifying ~p', [FileIn]),
182 ( catch(include_file_id(FileIn, File), _, fail)
183 -> classify_include(File, FileClass)
184 ; FileClass = nofile
185 ),
186 debug(include, 'Class ~p', [FileClass]).
187
188classify_include(File, FileClass) :-
189 atom(File),
190 !,
191 add_extension(File, FileExt),
192 catch(storage_meta_data(FileExt, _Meta), _, fail),
193 atom_concat('swish://', FileExt, Id),
194 FileClass = file(Id).
195classify_include(Spec, FileClass) :-
196 absolute_file_name(Spec, Path, [ file_type(prolog), access(read) ]),
197 Spec =.. [Alias,_],
198 file_base_name(Path, NameExt),
199 format(atom(URI), 'swish://~w/~w', [Alias, NameExt]),
200 FileClass = file(URI).
201
202
203 206
207:- multifile
208 prolog:xref_open_source/2,
209 prolog:xref_source_file/3,
210 prolog:xref_source_identifier/2,
211 prolog:xref_source_time/2.
219prolog:xref_source_identifier(Src, Id) :-
220 atom(Src),
221 sub_atom(Src, 0, _, _, 'swish://'),
222 !,
223 Id = Src.
224
225prolog:xref_open_source(File, Stream) :-
226 atom(File),
227 atom_concat('swish://', Name, File),
228 ( file_alias(File, Spec)
229 -> absolute_file_name(Spec, Path, [ file_type(prolog), access(read) ]),
230 open(Path, read, Stream)
231 ; catch(storage_file(Name, Data, _Meta), _, fail),
232 open_string(Data, Stream)
233 ).
234
235prolog:xref_source_time(File, Modified) :-
236 atom(File),
237 atom_concat('swish://', Name, File),
238 ( file_alias(File, Spec)
239 -> absolute_file_name(Spec, Path, [ file_type(prolog), access(read) ]),
240 time_file(Path, Modified)
241 ; catch(storage_meta_data(Name, Meta), _, fail),
242 Modified = Meta.get(time)
243 ).
250prolog:xref_source_file(stream(Id, _Stream, [close(true)]), Id, _).
251prolog:xref_source_file(File, Id, Options) :-
252 atom(File),
253 option(relative_to(Src), Options),
254 atom(Src),
255 atom_concat('swish://', SrcFile, Src),
256 add_extension(File, FileExt),
257 file_directory_name(SrcFile, SrcDir),
258 directory_file_path(SrcDir, FileExt, TargetFile),
259 atom_concat('swish://', TargetFile, Id)
Support :-
include(File)
from SWISHThis module allows SWISH programs to include other programs from the shared gitty store. It realises this using the following steps:
We allow for hierarchical and circular includes. */