1 % (c) 2009-2019 Lehrstuhl fuer Softwaretechnik und Programmiersprachen,
2 % Heinrich Heine Universitaet Duesseldorf
3 % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html)
4
5 :- module(pathes,[
6 set_search_pathes/0, % install run-time search pathes
7 runtime_application_path/1
8 ]).
9
10 :- use_module(module_information).
11
12 :- module_info(group,infrastructure).
13 :- module_info(description,'This module contains code to compute compile-time and runtime-pathes.').
14
15 :- use_module(library(system),[environ/2]).
16 :- use_module(library(file_systems),[file_exists/1,
17 current_directory/1]).
18 :- use_module(library(lists),[reverse/2]).
19
20 :- multifile user:file_search_path/2.
21 :- dynamic user:file_search_path/2.
22
23 % some pathes may be set by environment variables during compilation,
24 :- dynamic compile_time_env_path/2.
25 lookup_env_path(Pathname, Varname) :-
26 ( environ(Varname,Value) ->
27 print('Hard-wired path for alias '),print(Pathname),print(': '),print(Value),nl,
28 assert(compile_time_env_path(Pathname,Value))
29 ; otherwise ->
30 true).
31 % compile-time pathes
32 :- lookup_env_path(prob_comp_home,'PROB_COMP_HOME'). % hard-wired version of the runtime_application_path
33 % This is used on systems where it absolutely clear where the
34 % ProB's application directory will be, namely Debian/Ubuntu packages
35 % run-time pathes
36 :- lookup_env_path(prob_home,'PROB_HOME').
37 :- lookup_env_path(examples,'PROB_EXAMPLES'). % hard-wired pathes, see above (about Debian/Ubuntu packages)
38 :- lookup_env_path(prob_lib,'PROB_LIB'). % hard-wired pathes, see above (about Debian/Ubuntu packages)
39 :- lookup_env_path(prob_tcl,'PROB_TCL'). % hard-wired pathes, see above (about Debian/Ubuntu packages)
40
41 % removes an (optional) trailing /src directory from the path,
42 % the result will not end with a slash
43 remove_src_dir(Orig,Dir) :-
44 atom_codes(Orig,COrig),
45 ? ( append(CDir,"/src/",COrig) -> true
46 ; append(CDir,"/src",COrig) -> true
47 ; append(CDir,"/src/proz",COrig) -> true
48 ; append(CDir,"/src/proz/",COrig) -> true
49 ; append(CDir,"/",COrig) -> true
50 ; otherwise -> COrig=CDir),
51 atom_codes(Dir,CDir).
52
53 % returns the path to the application directory (at run-time)
54 runtime_application_path(Dir) :-
55 ( environ('PROB_HOME',Dir) -> % the user has set the environment variable PROB_HOME and thus overrides any other setting
56 true % the Rodin plugin used this mechanism
57 ? ; application_path2(Dir),is_correct_prob_home_path(Dir) ->
58 true
59 ; application_path2(D),absolute_file_name(D,D1),parent_dir(D1,Dir,_),
60 is_correct_prob_home_path(Dir) ->
61 true
62 ; compile_time_env_path(prob_comp_home,Dir) -> % e.g. Debian/Ubuntu systems: the path was hard-wired at compile-time
63 true
64 ; otherwise -> % usually a run from source code, where we the current directory is prob/src
65 current_directory(Current), remove_src_dir(Current,Dir)).
66 application_path2(Dir) :-
67 prolog_flag(system_type,development),
68 % try and find location of src/module_information.pl
69 current_module(module_information,MFile),parent_dir(MFile,SrcDir,_),
70 remove_src_dir(SrcDir,Dir).
71 application_path2(Dir) :-
72 \+(prolog_flag(system_type,development)),
73 environ('SP_APP_DIR',Dir). /* /usr/local/bin/sicstus on development systems */
74 application_path2(Dir) :-
75 \+(prolog_flag(system_type,development)),
76 environ('SP_STARTUP_DIR',Dir).
77
78 % check if the path points to a directory with a lib subdirectory and the probcliparser.jar file
79 is_correct_prob_home_path(D) :- % print(trying_as_prob_home_path(D)),nl,nl,
80 atom_concat(D,'/lib/probcliparser.jar',ConParser),
81 file_exists(ConParser).
82
83 parent_dir(FullFile,Dir,Basename) :-
84 atom_chars(FullFile,CFullFile), % "path/to/file"
85 reverse(CFullFile,RCFullFile), % "elif/ot/htap"
86 ? append(RCFile,['/'|RCDir],RCFullFile),!, % "elif" "/ot/htap"
87 reverse(RCFile,CFile),reverse(['/'|RCDir],CDir), % "file" "path/to/"
88 atom_chars(Basename,CFile),atom_chars(Dir,CDir).
89
90 % we do not use our standard test case schema here because we do not
91 % want to introduce a dependency to the test framework at this level
92 parent_dir_test1 :-
93 parent_dir('/aaaa/bbb/cc/d.app',D,B),D=='/aaaa/bbb/cc/',B=='d.app'.
94 parent_dir_test2 :-
95 parent_dir('/aaaa/bbb/cc/',D,B),D=='/aaaa/bbb/cc/',B==''.
96 parent_dir_test :-
97 parent_dir_test1, parent_dir_test2.
98 :- ( parent_dir_test -> true
99 ; otherwise -> write(user_error,'testcase for pathes:parent_dir/2 failed, aborted.\n'),
100 halt(1)).
101
102 % returns the path to the application directory (compile-time)
103 compiletime_application_path(Dir) :-
104 compile_time_env_path(prob_comp_home,Dir),!.
105 compiletime_application_path(Dir) :-
106 runtime_application_path(Dir).
107
108 check_if_hard_wired(Alias, _Prefix, _Dir, Full) :-
109 compile_time_env_path(Alias,Full),!.
110 check_if_hard_wired(_Alias, Prefix, Dir, Full) :-
111 atom_concat(Prefix,Dir,Full).
112
113 set_search_path(Alias, Prefix, Dir) :-
114 check_if_hard_wired(Alias, Prefix, Dir, Full),
115 %% print(setting_path(Alias,Full)),nl, %%
116 ( catch( user:file_search_path(Alias,Full), _, fail) -> true
117 ; otherwise ->
118 catch( retractall(user:file_search_path(Alias,_)), _, true), % remove any old defintion
119 assertz(user:file_search_path(Alias,Full)) % , print(setting_search_path(Alias,Full)),nl
120 ).
121
122 % pathes that can be used by use_module(...), but
123 % must not be used in run-time code
124 set_compile_time_search_pathes :-
125 compiletime_application_path(App),
126 %format('~n ProB compile time application path: ~w~n~n',[App]),
127 set_search_path(extension, App, '/extensions'),
128 set_search_path(probsrc, App, '/src'),
129 set_search_path(chrsrc, App, '/src/chr'),
130 set_search_path(probcspsrc, App, '/src/cia'),
131 set_search_path(probltlsrc, App, '/src/ltl'),
132 set_search_path(probporsrc, App, '/src/por'),
133 set_search_path(probpgesrc, App, '/src/pge'),
134 set_search_path(prozsrc, App, '/src/proz'),
135 set_search_path(kodkodsrc, App, '/src/kodkod'),
136 set_search_path(symbolic_model_checker, App, '/src/symbolic_model_checker'),
137 set_search_path(partial_evaluator, App, '/src/partial_evaluator'),
138 %set_search_path(plugins, App, '/plugins'),
139 %set_search_path(abstract_domains, App, '/plugins/absint/domains'),
140 set_search_path(tclsrc, App, '/tcl'),
141 %set_search_path(probpromela,App,'/src/promela'),
142 set_search_path(prob_rewrite_rules, App, '/src/rewrite_rules'),
143 set_search_path(smtlib_solver, App, '/src/smtlib_solver'),
144 set_search_path(smt_solvers_interface, App, '/src/smt_solvers_interface'),
145 set_search_path(synthesis, App, '/src/synthesis'),
146 set_search_path(library_plspec, App, '/src/library_plspec'). % patched libraries for plspec
147 :- set_compile_time_search_pathes.
148
149 % pathes that can be used in run-time code; should not be called at compile time
150 set_search_pathes :-
151 runtime_application_path(App),
152 %print(runtime_application_path(App)),nl,
153 set_search_path(prob_home, App, ''),
154 set_search_path(examples, App, '/../probprivate/public_examples'),
155 set_search_path(prob_lib, App, '/lib'),
156 set_search_path(prob_tcl, App, '/tcl'),
157
158 check_if_hard_wired(prob_lib, App, '/lib', LibDir),
159 ( catch(user:library_directory(LibDir), _, fail) -> true % ,print(already_set(LibDir)),nl
160 ; otherwise ->
161 catch( retractall(user:library_directory(_)), _, true), % remove any old defintion
162 assertz(user:library_directory(LibDir))).