Code beautification with uncrustify
[alexxy/gromacs.git] / src / gromacs / gmxpreprocess / fflibutil.c
1 /*  -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
2  *
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.
15
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.
20  *
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.
27  *
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.
30  *
31  * For more info, check our website at http://www.gromacs.org
32  *
33  * And Hey:
34  * GROningen Mixture of Alchemy and Childrens' Stories
35  */
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
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"
53
54 #ifdef HAVE_UNISTD_H
55 #include <unistd.h>
56 #endif
57
58 #ifdef GMX_THREAD_MPI
59 #include "thread_mpi.h"
60 #endif
61
62 #include "fflibutil.h"
63
64 const char *fflib_forcefield_dir_ext()
65 {
66     return ".ff";
67 }
68
69 const char *fflib_forcefield_itp()
70 {
71     return "forcefield.itp";
72 }
73
74 const char *fflib_forcefield_doc()
75 {
76     return "forcefield.doc";
77 }
78
79 void fflib_filename_base(const char *filename, char *filebase, int maxlen)
80 {
81     const char *cptr;
82     char       *ptr;
83
84     cptr = strrchr(filename, DIR_SEPARATOR);
85     if (cptr != NULL)
86     {
87         /* Skip the separator */
88         cptr += 1;
89     }
90     else
91     {
92         cptr = filename;
93     }
94     if (strlen(filename) >= (size_t)maxlen)
95     {
96         gmx_fatal(FARGS, "filename is longer (%d) than maxlen (%d)",
97                   strlen(filename), maxlen);
98     }
99     strcpy(filebase, cptr);
100     /* Remove the extension */
101     ptr = strrchr(filebase, '.');
102     if (ptr != NULL)
103     {
104         ptr[0] = '\0';
105     }
106 }
107
108 static void sort_filenames(int n, char **name, char **name2)
109 {
110     /* Slow sort, but we usually have tens of names */
111     int   i, j, f;
112     char *tmp;
113
114     for (i = 0; i < n-1; i++)
115     {
116         f = i;
117         for (j = i+1; j < n; j++)
118         {
119             if (strcmp(name[j], name[f]) < 0)
120             {
121                 f = j;
122             }
123         }
124         if (f > i)
125         {
126             tmp     = name[i];
127             name[i] = name[f];
128             name[f] = tmp;
129             if (name2 != NULL)
130             {
131                 tmp      = name2[i];
132                 name2[i] = name2[f];
133                 name2[f] = tmp;
134             }
135         }
136     }
137 }
138
139 static int low_fflib_search_file_end(const char *ffdir,
140                                      gmx_bool    bAddCWD,
141                                      const char *file_end,
142                                      gmx_bool    bFatalError,
143                                      char     ***filenames,
144                                      char     ***filenames_short)
145 {
146     char           *ret = NULL;
147     char           *lib, *dir;
148     char            buf[1024];
149     char           *libpath;
150     gmx_bool        env_is_set;
151     int             len_fe, len_name;
152     char          **fns, **fns_short;
153     char            dir_print[GMX_PATH_MAX];
154     char           *pdum;
155     char           *s, fn_dir[GMX_PATH_MAX];
156     gmx_directory_t dirhandle;
157     char            nextname[STRLEN];
158     int             n, n_thisdir, rc;
159
160     len_fe = strlen(file_end);
161
162     env_is_set = FALSE;
163     if (ffdir != NULL)
164     {
165         /* Search in current dir and ffdir */
166         libpath = gmxlibfn(ffdir);
167     }
168     else
169     {
170         /* GMXLIB can be a path now */
171         lib = getenv("GMXLIB");
172         snew(libpath, GMX_PATH_MAX);
173         if (bAddCWD)
174         {
175             sprintf(libpath, "%s%s", ".", PATH_SEPARATOR);
176         }
177         if (lib != NULL)
178         {
179             env_is_set = TRUE;
180             strncat(libpath, lib, GMX_PATH_MAX);
181         }
182         else if (!get_libdir(libpath+strlen(libpath)))
183         {
184             strncat(libpath, GMXLIBDIR, GMX_PATH_MAX);
185         }
186     }
187     s         = libpath;
188     n         = 0;
189     fns       = NULL;
190     fns_short = NULL;
191     /* Loop over all the entries in libpath */
192     while ((dir = gmx_strsep(&s, PATH_SEPARATOR)) != NULL)
193     {
194         rc = gmx_directory_open(&dirhandle, dir);
195         if (rc == 0)
196         {
197             strcpy(dir_print, dir);
198
199             n_thisdir = 0;
200             while (gmx_directory_nextfile(dirhandle, nextname, STRLEN-1) == 0)
201             {
202                 nextname[STRLEN-1] = 0;
203                 if (debug)
204                 {
205                     fprintf(debug, "dir '%s' %d file '%s'\n",
206                             dir, n_thisdir, nextname);
207                 }
208                 len_name = strlen(nextname);
209                 /* What about case sensitivity? */
210                 if (len_name >= len_fe &&
211                     strcmp(nextname+len_name-len_fe, file_end) == 0)
212                 {
213                     /* We have a match */
214                     srenew(fns, n+1);
215                     sprintf(fn_dir, "%s%c%s",
216                             dir_print, DIR_SEPARATOR, nextname);
217
218                     /* Copy the file name, possibly including the path. */
219                     fns[n] = strdup(fn_dir);
220
221                     if (ffdir == NULL)
222                     {
223                         /* We are searching in a path.
224                          * Use the relative path when we use share/top
225                          * from the installation.
226                          * Add the full path when we use the current
227                          * working directory of GMXLIB.
228                          */
229                         srenew(fns_short, n+1);
230                         if (strcmp(dir, ".") == 0 || env_is_set)
231                         {
232                             fns_short[n] = strdup(fn_dir);
233                         }
234                         else
235                         {
236                             fns_short[n] = strdup(nextname);
237                         }
238                     }
239                     n++;
240                     n_thisdir++;
241                 }
242             }
243             gmx_directory_close(dirhandle);
244
245             sort_filenames(n_thisdir,
246                            fns+n-n_thisdir,
247                            fns_short == NULL ? NULL : fns_short+n-n_thisdir);
248         }
249     }
250
251     sfree(libpath);
252
253     if (n == 0 && bFatalError)
254     {
255         if (ffdir != NULL)
256         {
257             gmx_fatal(FARGS, "Could not find any files ending on '%s' in the force field directory '%s'", file_end, ffdir);
258         }
259         else
260         {
261             gmx_fatal(FARGS, "Could not find any files ending on '%s' in the current directory or the GROMACS library search path", file_end);
262         }
263     }
264
265     *filenames = fns;
266     if (ffdir == NULL)
267     {
268         *filenames_short = fns_short;
269     }
270
271     return n;
272 }
273
274 int fflib_search_file_end(const char *ffdir,
275                           const char *file_end,
276                           gmx_bool    bFatalError,
277                           char     ***filenames)
278 {
279     return low_fflib_search_file_end(ffdir, FALSE, file_end, bFatalError,
280                                      filenames, NULL);
281 }
282
283 int fflib_search_file_in_dirend(const char *filename, const char *dirend,
284                                 char ***dirnames)
285 {
286     int             nf, i;
287     char          **f, **f_short;
288     int             n;
289     char          **dns;
290     gmx_directory_t dirhandle;
291     char            nextname[STRLEN];
292     int             rc;
293
294     /* Find all files (not only dir's) ending on dirend */
295     nf = low_fflib_search_file_end(NULL, TRUE, dirend, FALSE, &f, &f_short);
296
297     n   = 0;
298     dns = NULL;
299     for (i = 0; i < nf; i++)
300     {
301         rc = gmx_directory_open(&dirhandle, f[i]);
302
303         if (rc == 0)
304         {
305             while (gmx_directory_nextfile(dirhandle, nextname, STRLEN-1) == 0)
306             {
307                 nextname[STRLEN-1] = 0;
308                 if (strcmp(nextname, filename) == 0)
309                 {
310                     /* We have a match */
311                     srenew(dns, n+1);
312                     dns[n] = strdup(f_short[i]);
313                     n++;
314                 }
315             }
316             gmx_directory_close(dirhandle);
317         }
318         sfree(f[i]);
319         sfree(f_short[i]);
320     }
321     sfree(f);
322     sfree(f_short);
323
324     *dirnames = dns;
325
326     return n;
327 }
328
329 gmx_bool fflib_fexist(const char *file)
330 {
331     char *file_fullpath;
332
333     file_fullpath = low_gmxlibfn(file, TRUE, FALSE);
334
335     if (file_fullpath == NULL)
336     {
337         return FALSE;
338     }
339     else
340     {
341         sfree(file_fullpath);
342
343         return TRUE;
344     }
345 }
346
347
348 FILE *fflib_open(const char *file)
349 {
350     char *file_fullpath;
351     FILE *fp;
352
353     file_fullpath = gmxlibfn(file);
354     fprintf(stderr, "Opening force field file %s\n", file_fullpath);
355     fp = ffopen(file_fullpath, "r");
356     sfree(file_fullpath);
357
358     return fp;
359 }