Merge branch 'master' of git://git.gromacs.org/gromacs
[gromacs/adressmacs.git] / src / kernel / fflibutil.c
blob0254f12bea09de3cc45c7805a4102ab63942ace8
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
3 *
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 3.2.0
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
33 * And Hey:
34 * GROningen Mixture of Alchemy and Childrens' Stories
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <fcntl.h>
46 #include "sysstuff.h"
47 #include "string2.h"
48 #include "futil.h"
49 #include "network.h"
50 #include "gmx_fatal.h"
51 #include "smalloc.h"
52 #include "statutil.h"
54 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
55 #include <direct.h>
56 #include <io.h>
57 #endif
59 #ifdef HAVE_UNISTD_H
60 #include <unistd.h>
61 #endif
63 #ifdef GMX_THREADS
64 #include "thread_mpi.h"
65 #endif
67 #include "fflibutil.h"
69 const char *fflib_forcefield_dir_ext()
71 return ".ff";
74 const char *fflib_forcefield_itp()
76 return "forcefield.itp";
79 const char *fflib_forcefield_doc()
81 return "forcefield.doc";
84 void fflib_filename_base(const char *filename,char *filebase,int maxlen)
86 const char *cptr;
87 char *ptr;
89 cptr = strrchr(filename,DIR_SEPARATOR);
90 if (cptr != NULL)
92 /* Skip the separator */
93 cptr += 1;
95 else
97 cptr = filename;
99 if (strlen(filename) >= (size_t)maxlen)
101 gmx_fatal(FARGS,"filename is longer (%d) than maxlen (%d)",
102 strlen(filename),maxlen);
104 strcpy(filebase,cptr);
105 /* Remove the extension */
106 ptr = strrchr(filebase,'.');
107 if (ptr != NULL)
109 ptr[0] = '\0';
113 static void sort_filenames(int n,char **name,char **name2)
115 /* Slow sort, but we usually have tens of names */
116 int i,j,f;
117 char *tmp;
119 for(i=0; i<n-1; i++)
121 f = i;
122 for(j=i+1; j<n; j++)
124 if (strcmp(name[j],name[f]) < 0)
126 f = j;
129 if (f > i)
131 tmp = name[i];
132 name[i] = name[f];
133 name[f] = tmp;
134 if (name2 != NULL)
136 tmp = name2[i];
137 name2[i] = name2[f];
138 name2[f] = tmp;
144 static int low_fflib_search_file_end(const char *ffdir,
145 gmx_bool bAddCWD,
146 const char *file_end,
147 gmx_bool bFatalError,
148 char ***filenames,
149 char ***filenames_short)
151 char *ret=NULL;
152 char *lib,*dir;
153 char buf[1024];
154 char *libpath;
155 gmx_bool env_is_set;
156 int len_fe,len_name;
157 char **fns,**fns_short;
158 char dir_print[GMX_PATH_MAX];
159 char *pdum;
160 char *s,fn_dir[GMX_PATH_MAX];
161 gmx_directory_t dirhandle;
162 char nextname[STRLEN];
163 int n,n_thisdir,rc;
165 len_fe = strlen(file_end);
167 env_is_set = FALSE;
168 if (ffdir != NULL)
170 /* Search in current dir and ffdir */
171 libpath = gmxlibfn(ffdir);
173 else
175 /* GMXLIB can be a path now */
176 lib = getenv("GMXLIB");
177 snew(libpath,GMX_PATH_MAX);
178 if (bAddCWD)
180 sprintf(libpath,"%s%s",".",PATH_SEPARATOR);
182 if (lib != NULL)
184 env_is_set = TRUE;
185 strncat(libpath,lib,GMX_PATH_MAX);
187 else if (!get_libdir(libpath+strlen(libpath)))
189 strncat(libpath,GMXLIBDIR,GMX_PATH_MAX);
192 s = libpath;
193 n = 0;
194 fns = NULL;
195 fns_short = NULL;
196 /* Loop over all the entries in libpath */
197 while ((dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL)
199 rc = gmx_directory_open(&dirhandle,dir);
200 if (rc==0)
202 strcpy(dir_print,dir);
204 n_thisdir = 0;
205 while (gmx_directory_nextfile(dirhandle,nextname,STRLEN-1)==0)
207 nextname[STRLEN-1]=0;
208 if (debug)
210 fprintf(debug,"dir '%s' %d file '%s'\n",
211 dir,n_thisdir,nextname);
213 len_name = strlen(nextname);
214 /* What about case sensitivity? */
215 if (len_name >= len_fe &&
216 strcmp(nextname+len_name-len_fe,file_end) == 0)
218 /* We have a match */
219 srenew(fns,n+1);
220 sprintf(fn_dir,"%s%c%s",
221 dir_print,DIR_SEPARATOR,nextname);
223 /* Copy the file name, possibly including the path. */
224 fns[n] = strdup(fn_dir);
226 if (ffdir == NULL)
228 /* We are searching in a path.
229 * Use the relative path when we use share/top
230 * from the installation.
231 * Add the full path when we use the current
232 * working directory of GMXLIB.
234 srenew(fns_short,n+1);
235 if (strcmp(dir,".") == 0 || env_is_set)
237 fns_short[n] = strdup(fn_dir);
239 else
241 fns_short[n] = strdup(nextname);
244 n++;
245 n_thisdir++;
248 gmx_directory_close(dirhandle);
250 sort_filenames(n_thisdir,
251 fns+n-n_thisdir,
252 fns_short==NULL ? NULL : fns_short+n-n_thisdir);
256 sfree(libpath);
258 if (n == 0 && bFatalError)
260 if (ffdir != NULL)
262 gmx_fatal(FARGS,"Could not find any files ending on '%s' in the force field directory '%s'",file_end,ffdir);
264 else
266 gmx_fatal(FARGS,"Could not find any files ending on '%s' in the current directory or the GROMACS library search path",file_end);
270 *filenames = fns;
271 if (ffdir == NULL)
273 *filenames_short = fns_short;
276 return n;
279 int fflib_search_file_end(const char *ffdir,
280 const char *file_end,
281 gmx_bool bFatalError,
282 char ***filenames)
284 return low_fflib_search_file_end(ffdir,FALSE,file_end,bFatalError,
285 filenames,NULL);
288 int fflib_search_file_in_dirend(const char *filename,const char *dirend,
289 char ***dirnames)
291 int nf,i;
292 char **f,**f_short;
293 int n;
294 char **dns;
295 gmx_directory_t dirhandle;
296 char nextname[STRLEN];
297 int rc;
299 /* Find all files (not only dir's) ending on dirend */
300 nf = low_fflib_search_file_end(NULL,TRUE,dirend,FALSE,&f,&f_short);
302 n = 0;
303 dns = NULL;
304 for(i=0; i<nf; i++)
306 rc = gmx_directory_open(&dirhandle,f[i]);
308 if (rc==0)
310 while (gmx_directory_nextfile(dirhandle,nextname,STRLEN-1)==0)
312 nextname[STRLEN-1]=0;
313 if (strcmp(nextname,filename) == 0)
315 /* We have a match */
316 srenew(dns,n+1);
317 dns[n] = strdup(f_short[i]);
318 n++;
321 gmx_directory_close(dirhandle);
323 sfree(f[i]);
324 sfree(f_short[i]);
326 sfree(f);
327 sfree(f_short);
329 *dirnames = dns;
331 return n;
334 gmx_bool fflib_fexist(const char *file)
336 char *file_fullpath;
338 file_fullpath = low_gmxlibfn(file,TRUE,FALSE);
340 if (file_fullpath == NULL)
342 return FALSE;
344 else
346 sfree(file_fullpath);
348 return TRUE;
353 FILE *fflib_open(const char *file)
355 char *file_fullpath;
356 FILE *fp;
358 file_fullpath = gmxlibfn(file);
359 fprintf(stderr,"Opening force field file %s\n",file_fullpath);
360 fp = ffopen(file_fullpath,"r");
361 sfree(file_fullpath);
363 return fp;