Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2019 The plumed team
3 : (see the PEOPLE file at the root of the distribution for a list of names)
4 :
5 : See http://www.plumed.org for more information.
6 :
7 : This file is part of plumed, version 2.
8 :
9 : plumed is free software: you can redistribute it and/or modify
10 : it under the terms of the GNU Lesser General Public License as published by
11 : the Free Software Foundation, either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : plumed is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU Lesser General Public License for more details.
18 :
19 : You should have received a copy of the GNU Lesser General Public License
20 : along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 : #include "Plumed.h"
23 :
24 : #ifdef __PLUMED_HAS_DLOPEN
25 : #include <dlfcn.h>
26 : #endif
27 : #include <stdio.h>
28 : #include <assert.h>
29 : #include <stdlib.h>
30 : #include <limits.h>
31 :
32 : /* DECLARATION USED ONLY IN THIS FILE */
33 :
34 : #ifdef __cplusplus
35 : extern "C" {
36 : #endif
37 :
38 : /**
39 : Holder for plumedmain function pointers.
40 : */
41 : typedef struct {
42 : void*(*create)(void);
43 : void(*cmd)(void*,const char*,const void*);
44 : void(*finalize)(void*);
45 : } plumed_plumedmain_function_holder;
46 :
47 : /**
48 : Register for plumedmain function pointers
49 : */
50 : plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmain_function_holder*);
51 :
52 : #ifdef __PLUMED_STATIC_KERNEL
53 : /* Real interface */
54 : void*plumedmain_create(void);
55 : void plumedmain_cmd(void*,const char*,const void*);
56 : void plumedmain_finalize(void*);
57 : #else
58 : /* dummy interface */
59 : void*plumed_dummy_create(void);
60 : void plumed_dummy_cmd(void*,const char*,const void*);
61 : void plumed_dummy_finalize(void*);
62 : #endif
63 :
64 : #ifdef __cplusplus
65 : }
66 : #endif
67 :
68 : /* END OF DECLARATION USED ONLY IN THIS FILE */
69 :
70 : /* These are the dummy routines which are used when plumed is not available */
71 :
72 : #ifdef __PLUMED_STATIC_KERNEL
73 :
74 : static int installed=1;
75 :
76 : #else
77 :
78 : static int installed=0;
79 :
80 : static int dummy;
81 :
82 : void*plumed_dummy_create(void) {
83 : return (void*)&dummy;
84 : }
85 :
86 : void plumed_dummy_cmd(void*p,const char*key,const void*val) {
87 : (void) p; /* avoid warning on unused parameter */
88 : (void) key; /* avoid warning on unused parameter */
89 : (void) val; /* avoid warning on unused parameter */
90 : fprintf(stderr,"+++ ERROR: you are trying to use plumed, but it is not available +++\n");
91 : fprintf(stderr,"+++ Check your PLUMED_KERNEL environment variable +++\n");
92 : exit(1);
93 : }
94 :
95 : void plumed_dummy_finalize(void*p) {
96 : (void) p; /* avoid warning on unused parameter */
97 : }
98 :
99 : #endif
100 :
101 262159 : plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmain_function_holder* f) {
102 : #ifdef __PLUMED_STATIC_KERNEL
103 : /*
104 : When __PLUMED_STATIC_KERNEL is defined, the function holder is initialized
105 : to statically bound plumedmain_create,plumedmain_cmd,plumedmain_finalize and
106 : cannot be changed. This saves from mis-set values for PLUMED_KERNEL
107 : */
108 : static plumed_plumedmain_function_holder g= {plumedmain_create,plumedmain_cmd,plumedmain_finalize};
109 : (void) f; /* avoid warning on unused parameter */
110 262159 : return &g;
111 : #else
112 : /*
113 : On the other hand, for runtime binding, we allow to reset the function holder on the
114 : first call to plumed_kernel_register.
115 : Notice that in principle plumed_kernel_register is entered *twice*: one for the first
116 : plumed usage, and then from the PlumedMainInitializer object of the shared library.
117 : This is why we set "first=0" only *after* loading the shared library.
118 : Also notice that we should put some guard here for safe multithread calculations.
119 : */
120 : static plumed_plumedmain_function_holder g= {plumed_dummy_create,plumed_dummy_cmd,plumed_dummy_finalize};
121 : static int first=1;
122 : #ifdef __PLUMED_HAS_DLOPEN
123 : char* path;
124 : void* p;
125 : if(first && f==NULL) {
126 : path=getenv("PLUMED_KERNEL");
127 : #ifdef __PLUMED_DEFAULT_KERNEL
128 : /*
129 : This variable allows a default path for the kernel to be hardcoded.
130 : Can be useful for hardcoding the predefined plumed location
131 : still allowing the user to override this choice setting PLUMED_KERNEL.
132 : The path should be chosen at compile time adding e.g.
133 : -D__PLUMED_DEFAULT_KERNEL=/opt/local/lib/libplumed.dylib
134 : */
135 : /* This is required to add quotes */
136 : #define PLUMED_QUOTE_DIRECT(name) #name
137 : #define PLUMED_QUOTE(macro) PLUMED_QUOTE_DIRECT(macro)
138 : if(! (path && (*path) )) path=PLUMED_QUOTE(__PLUMED_DEFAULT_KERNEL);
139 : #endif
140 : if(path && (*path)) {
141 : fprintf(stderr,"+++ Loading the PLUMED kernel runtime +++\n");
142 : fprintf(stderr,"+++ PLUMED_KERNEL=\"%s\" +++\n",path);
143 : p=dlopen(path,RTLD_NOW|RTLD_GLOBAL);
144 : if(p) {
145 : fprintf(stderr,"+++ PLUMED kernel successfully loaded +++\n");
146 : installed=1;
147 : } else {
148 : fprintf(stderr,"+++ PLUMED kernel not found ! +++\n");
149 : fprintf(stderr,"+++ error message from dlopen(): %s\n",dlerror());
150 : }
151 : }
152 : }
153 : #endif
154 : first=0;
155 : if(f) g=*f;
156 : return &g;
157 : #endif
158 : }
159 :
160 : /* C wrappers: */
161 :
162 2152 : plumed plumed_create(void) {
163 : plumed p;
164 2152 : plumed_plumedmain_function_holder*h=plumed_kernel_register(NULL);
165 : assert(h);
166 : assert(h->create);
167 2152 : p.p=(*(h->create))();
168 : assert(p.p);
169 2152 : return p;
170 : }
171 :
172 256234 : void plumed_cmd(plumed p,const char*key,const void*val) {
173 256234 : plumed_plumedmain_function_holder*h=plumed_kernel_register(NULL);
174 : assert(p.p);
175 : assert(h);
176 : assert(h->cmd);
177 256234 : (*(h->cmd))(p.p,key,val);
178 256187 : }
179 :
180 2152 : void plumed_finalize(plumed p) {
181 2152 : plumed_plumedmain_function_holder*h=plumed_kernel_register(NULL);
182 : assert(p.p);
183 : assert(h);
184 : assert(h->finalize);
185 2152 : (*(h->finalize))(p.p);
186 : p.p=NULL;
187 2152 : }
188 :
189 8 : int plumed_installed(void) {
190 8 : plumed_kernel_register(NULL);
191 8 : return installed;
192 : }
193 :
194 : /* we declare a Plumed_g_main object here, in such a way that it is always available */
195 :
196 : static plumed gmain= {NULL};
197 :
198 2 : plumed plumed_global(void) {
199 2 : return gmain;
200 : }
201 :
202 16 : void plumed_gcreate(void) {
203 : assert(gmain.p==NULL);
204 16 : gmain=plumed_create();
205 16 : }
206 :
207 80 : void plumed_gcmd(const char*key,const void*val) {
208 : assert(gmain.p);
209 80 : plumed_cmd(gmain,key,val);
210 80 : }
211 :
212 16 : void plumed_gfinalize(void) {
213 : assert(gmain.p);
214 16 : plumed_finalize(gmain);
215 16 : gmain.p=NULL;
216 16 : }
217 :
218 24 : int plumed_ginitialized(void) {
219 24 : if(gmain.p) return 1;
220 16 : else return 0;
221 : }
222 :
223 15 : void plumed_c2f(plumed p,char*c) {
224 : unsigned i;
225 : unsigned char* cc;
226 : /*
227 : Convert the address stored in p.p into a proper FORTRAN string
228 : made of only ASCII characters. For this to work, the two following
229 : assertions should be satisfied:
230 : */
231 : assert(CHAR_BIT<=12);
232 : assert(sizeof(p.p)<=16);
233 :
234 : assert(c);
235 : cc=(unsigned char*)&p.p;
236 255 : for(i=0; i<sizeof(p.p); i++) {
237 : /*
238 : characters will range between '0' (ASCII 48) and 'o' (ASCII 111=48+63)
239 : */
240 120 : c[2*i]=cc[i]/64+48;
241 120 : c[2*i+1]=cc[i]%64+48;
242 : }
243 15 : }
244 :
245 149 : plumed plumed_f2c(const char*c) {
246 : plumed p;
247 : unsigned i;
248 : unsigned char* cc;
249 :
250 : assert(CHAR_BIT<=12);
251 : assert(sizeof(p.p)<=16);
252 :
253 : assert(c);
254 : cc=(unsigned char*)&p.p;
255 2533 : for(i=0; i<sizeof(p.p); i++) {
256 : /*
257 : perform the reversed transform
258 : */
259 1192 : cc[i]=(c[2*i]-48)*64 + (c[2*i+1]-48);
260 : }
261 149 : return p;
262 : }
263 :
264 :
265 : #ifdef __cplusplus
266 : extern "C" {
267 : #endif
268 :
269 : /*
270 : Fortran wrappers
271 : These are just like the global C wrappers. They are
272 : just defined here and not declared in the .h file since they
273 : should not be used from c/c++ anyway.
274 : */
275 :
276 : /*
277 : First we assume no name mangling
278 : */
279 :
280 6 : void plumed_f_installed(int*i) {
281 : assert(i);
282 6 : *i=plumed_installed();
283 6 : }
284 :
285 18 : void plumed_f_ginitialized(int*i) {
286 : assert(i);
287 18 : *i=plumed_ginitialized();
288 18 : }
289 :
290 12 : void plumed_f_gcreate(void) {
291 12 : plumed_gcreate();
292 12 : }
293 :
294 60 : void plumed_f_gcmd(char*key,void*val) {
295 60 : plumed_gcmd(key,val);
296 60 : }
297 :
298 12 : void plumed_f_gfinalize(void) {
299 12 : plumed_gfinalize();
300 12 : }
301 :
302 7 : void plumed_f_create(char*c) {
303 : plumed p;
304 7 : p=plumed_create();
305 7 : plumed_c2f(p,c);
306 7 : }
307 :
308 140 : void plumed_f_cmd(char*c,char*key,void*val) {
309 : plumed p;
310 140 : p=plumed_f2c(c);
311 140 : plumed_cmd(p,key,val);
312 140 : }
313 :
314 7 : void plumed_f_finalize(char*c) {
315 : plumed p;
316 7 : p=plumed_f2c(c);
317 7 : plumed_finalize(p);
318 7 : }
319 :
320 6 : void plumed_f_global(char*c) {
321 6 : plumed_c2f(gmain,c);
322 6 : }
323 :
324 : /*
325 : Then we add wrappers for there functions to cover all
326 : the possible fortran mangling schemes, which should be:
327 : without underscore, with one underscore and with two underscores
328 : lower or upper case
329 : */
330 :
331 : #define IMPLEMENT(lower,upper,implem) \
332 : void lower ##_ implem \
333 : void lower ##__ implem \
334 : void upper implem \
335 : void upper ##_ implem \
336 : void upper ##__ implem
337 :
338 10 : IMPLEMENT(plumed_f_gcreate, PLUMED_F_GCREATE, (void) {plumed_f_gcreate();})
339 50 : IMPLEMENT(plumed_f_gcmd, PLUMED_F_GCMD, (char* key,void* val) {plumed_f_gcmd(key,val);})
340 10 : IMPLEMENT(plumed_f_gfinalize, PLUMED_F_GFINALIZE, (void) {plumed_f_gfinalize();})
341 15 : IMPLEMENT(plumed_f_ginitialized,PLUMED_F_GINITIALIZED,(int*i) {plumed_f_ginitialized(i);})
342 5 : IMPLEMENT(plumed_f_create, PLUMED_F_CREATE, (char*c) {plumed_f_create(c);})
343 100 : IMPLEMENT(plumed_f_cmd, PLUMED_F_CMD, (char*c,char* key,void* val) {plumed_f_cmd(c,key,val);})
344 5 : IMPLEMENT(plumed_f_finalize, PLUMED_F_FINALIZE, (char*c) {plumed_f_finalize(c);})
345 5 : IMPLEMENT(plumed_f_installed, PLUMED_F_INSTALLED, (int*i) {plumed_f_installed(i);})
346 5 : IMPLEMENT(plumed_f_global, PLUMED_F_GLOBAL, (char*c) {plumed_f_global(c);})
347 :
348 : #ifdef __cplusplus
349 : }
350 : #endif
351 :
352 :
353 :
354 :
|