Fixing copyright issues and code contributors
[alexxy/gromacs.git] / src / kernel / fflibutil.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team,
6  * check out http://www.gromacs.org for more information.
7  * Copyright (c) 2012,2013, by the GROMACS development team, led by
8  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9  * others, as listed in the AUTHORS file in the top-level source
10  * directory and at http://www.gromacs.org.
11  *
12  * GROMACS is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * as published by the Free Software Foundation; either version 2.1
15  * of the License, or (at your option) any later version.
16  *
17  * GROMACS is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with GROMACS; if not, see
24  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
26  *
27  * If you want to redistribute modifications to GROMACS, please
28  * consider that scientific software is very special. Version
29  * control is crucial - bugs must be traceable. We will be happy to
30  * consider code for inclusion in the official distribution, but
31  * derived work must not be called official GROMACS. Details are found
32  * in the README & COPYING files - if they are missing, get the
33  * official version at http://www.gromacs.org.
34  *
35  * To help us fund GROMACS development, we humbly ask that you cite
36  * the research papers on the package. Check out http://www.gromacs.org.
37  */
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <fcntl.h>
48 #include "sysstuff.h"
49 #include "string2.h"
50 #include "futil.h"
51 #include "network.h"
52 #include "gmx_fatal.h"
53 #include "smalloc.h"
54 #include "statutil.h"
55
56 #ifdef GMX_NATIVE_WINDOWS
57 #include <direct.h>
58 #include <io.h>
59 #endif
60
61 #ifdef HAVE_UNISTD_H
62 #include <unistd.h>
63 #endif
64
65 #ifdef GMX_THREAD_MPI
66 #include "thread_mpi.h"
67 #endif
68
69 #include "fflibutil.h"
70
71 const char *fflib_forcefield_dir_ext()
72 {
73     return ".ff";
74 }
75
76 const char *fflib_forcefield_itp()
77 {
78     return "forcefield.itp";
79 }
80
81 const char *fflib_forcefield_doc()
82 {
83     return "forcefield.doc";
84 }
85
86 void fflib_filename_base(const char *filename,char *filebase,int maxlen)
87 {
88     const char *cptr;
89     char *ptr;
90
91     cptr = strrchr(filename,DIR_SEPARATOR);
92     if (cptr != NULL)
93     {
94         /* Skip the separator */
95         cptr += 1;
96     }
97     else
98     {
99         cptr = filename;
100     }
101     if (strlen(filename) >= (size_t)maxlen)
102     {
103         gmx_fatal(FARGS,"filename is longer (%d) than maxlen (%d)",
104                   strlen(filename),maxlen);
105     }
106     strcpy(filebase,cptr);
107     /* Remove the extension */
108     ptr = strrchr(filebase,'.');
109     if (ptr != NULL)
110     {
111         ptr[0] = '\0';
112     }
113 }
114
115 static void sort_filenames(int n,char **name,char **name2)
116 {
117     /* Slow sort, but we usually have tens of names */
118     int  i,j,f;
119     char *tmp;
120
121     for(i=0; i<n-1; i++)
122     {
123         f = i;
124         for(j=i+1; j<n; j++)
125         {
126             if (strcmp(name[j],name[f]) < 0)
127             {
128                 f = j;
129             }
130         }
131         if (f > i)
132         {
133             tmp     = name[i];
134             name[i] = name[f];
135             name[f] = tmp;
136             if (name2 != NULL)
137             {
138                 tmp      = name2[i];
139                 name2[i] = name2[f];
140                 name2[f] = tmp;
141             }
142         }
143     }
144 }
145
146 static int low_fflib_search_file_end(const char *ffdir,
147                                      gmx_bool bAddCWD,
148                                      const char *file_end,
149                                      gmx_bool bFatalError,
150                                      char ***filenames,
151                                      char ***filenames_short)
152 {
153     char *ret=NULL;
154     char *lib,*dir;
155     char buf[1024];
156     char *libpath;
157     gmx_bool env_is_set;
158     int  len_fe,len_name;
159     char **fns,**fns_short;
160     char dir_print[GMX_PATH_MAX];
161     char *pdum;
162     char *s,fn_dir[GMX_PATH_MAX];
163     gmx_directory_t dirhandle;
164     char nextname[STRLEN];
165     int  n,n_thisdir,rc;
166
167     len_fe = strlen(file_end);
168
169     env_is_set = FALSE;
170     if (ffdir != NULL)
171     {
172         /* Search in current dir and ffdir */
173         libpath = gmxlibfn(ffdir);
174     }
175     else
176     {
177         /* GMXLIB can be a path now */
178         lib = getenv("GMXLIB");
179         snew(libpath,GMX_PATH_MAX);
180         if (bAddCWD)
181         {
182             sprintf(libpath,"%s%s",".",PATH_SEPARATOR);
183         }
184         if (lib != NULL)
185         {
186             env_is_set = TRUE;
187             strncat(libpath,lib,GMX_PATH_MAX);
188         } 
189         else if (!get_libdir(libpath+strlen(libpath)))
190         {
191             strncat(libpath,GMXLIBDIR,GMX_PATH_MAX);
192         }
193     }
194     s = libpath;
195     n = 0;
196     fns       = NULL;
197     fns_short = NULL;
198     /* Loop over all the entries in libpath */
199     while ((dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL)
200     {
201         rc = gmx_directory_open(&dirhandle,dir);
202         if (rc==0)
203         {
204             strcpy(dir_print,dir);
205
206             n_thisdir = 0;
207             while (gmx_directory_nextfile(dirhandle,nextname,STRLEN-1)==0)
208             {
209                 nextname[STRLEN-1]=0;
210                 if (debug)
211                 {
212                     fprintf(debug,"dir '%s' %d file '%s'\n",
213                             dir,n_thisdir,nextname);
214                 }
215                 len_name = strlen(nextname);
216                 /* What about case sensitivity? */
217                 if (len_name >= len_fe &&
218                     strcmp(nextname+len_name-len_fe,file_end) == 0)
219                 {
220                     /* We have a match */
221                     srenew(fns,n+1);
222                     sprintf(fn_dir,"%s%c%s",
223                             dir_print,DIR_SEPARATOR,nextname);
224
225                     /* Copy the file name, possibly including the path. */
226                     fns[n] = strdup(fn_dir);
227
228                     if (ffdir == NULL)
229                     {
230                         /* We are searching in a path.
231                          * Use the relative path when we use share/top
232                          * from the installation.
233                          * Add the full path when we use the current
234                          * working directory of GMXLIB.
235                          */
236                         srenew(fns_short,n+1);
237                         if (strcmp(dir,".") == 0 || env_is_set)
238                         {
239                             fns_short[n] = strdup(fn_dir);
240                         }
241                         else
242                         {
243                             fns_short[n] = strdup(nextname);
244                         }
245                     }
246                     n++;
247                     n_thisdir++;
248                 }
249             }
250             gmx_directory_close(dirhandle);
251
252             sort_filenames(n_thisdir,
253                            fns+n-n_thisdir,
254                            fns_short==NULL ? NULL : fns_short+n-n_thisdir);
255         }
256     }
257
258     sfree(libpath);
259
260     if (n == 0 && bFatalError)
261     {
262         if (ffdir != NULL)
263         {
264             gmx_fatal(FARGS,"Could not find any files ending on '%s' in the force field directory '%s'",file_end,ffdir);
265         }
266         else
267         {
268             gmx_fatal(FARGS,"Could not find any files ending on '%s' in the current directory or the GROMACS library search path",file_end);
269         }
270     }
271
272     *filenames = fns;
273     if (ffdir == NULL)
274     {
275         *filenames_short = fns_short;
276     }
277
278     return n;
279 }
280
281 int fflib_search_file_end(const char *ffdir,
282                           const char *file_end,
283                           gmx_bool bFatalError,
284                           char ***filenames)
285 {
286     return low_fflib_search_file_end(ffdir,FALSE,file_end,bFatalError,
287                                      filenames,NULL);
288 }
289
290 int fflib_search_file_in_dirend(const char *filename,const char *dirend,
291                                 char ***dirnames)
292 {
293     int  nf,i;
294     char **f,**f_short;
295     int  n;
296     char **dns;
297     gmx_directory_t dirhandle;
298     char nextname[STRLEN];
299     int  rc;
300     
301     /* Find all files (not only dir's) ending on dirend */
302     nf = low_fflib_search_file_end(NULL,TRUE,dirend,FALSE,&f,&f_short);
303
304     n = 0;
305     dns = NULL;
306     for(i=0; i<nf; i++)
307     {
308         rc = gmx_directory_open(&dirhandle,f[i]);
309
310         if (rc==0)
311         {
312             while (gmx_directory_nextfile(dirhandle,nextname,STRLEN-1)==0)
313             {
314                 nextname[STRLEN-1]=0;
315                 if (strcmp(nextname,filename) == 0)
316                 {
317                     /* We have a match */
318                     srenew(dns,n+1);
319                     dns[n] = strdup(f_short[i]);
320                     n++;
321                 }
322             }
323             gmx_directory_close(dirhandle);
324         }
325         sfree(f[i]);
326         sfree(f_short[i]);
327     }
328     sfree(f);
329     sfree(f_short);
330
331     *dirnames = dns;
332
333     return n;
334 }
335
336 gmx_bool fflib_fexist(const char *file)
337 {
338     char *file_fullpath;
339
340     file_fullpath = low_gmxlibfn(file,TRUE,FALSE);
341     
342     if (file_fullpath == NULL)
343     {
344         return FALSE;
345     }
346     else
347     {
348         sfree(file_fullpath);
349
350         return TRUE;
351     }
352 }
353
354
355 FILE *fflib_open(const char *file)
356 {
357     char *file_fullpath;
358     FILE *fp;
359
360     file_fullpath = gmxlibfn(file);
361     fprintf(stderr,"Opening force field file %s\n",file_fullpath);
362     fp = ffopen(file_fullpath,"r");
363     sfree(file_fullpath);
364
365     return fp;
366 }