LCOV - code coverage report
Current view: top level - wrapper - Plumed.c (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 80 80 100.0 %
Date: 2020-11-18 11:20:57 Functions: 65 66 98.5 %

          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             : 

Generated by: LCOV version 1.13