1333091c11ac401d3dfaab5955b00a0447849cf6
[alexxy/gromacs.git] / src / gromacs / fileio / filenm.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  * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 #include "gmxpre.h"
38
39 #include "filenm.h"
40
41 #include <stdio.h>
42 #include <string.h>
43
44 #include "gromacs/legacyheaders/macros.h"
45 #include "gromacs/legacyheaders/types/commrec.h"
46 #include "gromacs/utility/basedefinitions.h"
47 #include "gromacs/utility/cstringutil.h"
48 #include "gromacs/utility/fatalerror.h"
49 #include "gromacs/utility/smalloc.h"
50
51 /* Use bitflag ... */
52 #define IS_SET(fn) ((fn.flag & ffSET) != 0)
53 #define IS_OPT(fn) ((fn.flag & ffOPT) != 0)
54
55 enum
56 {
57     eftASC, eftXDR, eftTNG, eftGEN, eftNR
58 };
59
60 /* To support multiple file types with one general (eg TRX) we have
61  * these arrays.
62  */
63 static const int trxs[] =
64 {
65     efXTC, efTRR, efCPT,
66     efGRO, efG96, efPDB, efTNG
67 };
68 #define NTRXS asize(trxs)
69
70 static const int trcompressed[] =
71 {
72     efXTC,
73     efTNG
74 };
75 #define NTRCOMPRESSED asize(trcompressed)
76
77 static const int tros[] =
78 {
79     efXTC, efTRR,
80     efGRO, efG96, efPDB, efTNG
81 };
82 #define NTROS asize(tros)
83
84 static const int trns[] =
85 {
86     efTRR, efCPT,
87     efTNG
88 };
89 #define NTRNS asize(trns)
90
91 static const int stos[] =
92 { efGRO, efG96, efPDB, efBRK, efENT, efESP };
93 #define NSTOS asize(stos)
94
95 static const int stxs[] =
96 {
97     efGRO, efG96, efPDB, efBRK, efENT, efESP,
98     efTPR
99 };
100 #define NSTXS asize(stxs)
101
102 static const int tpss[] =
103 {
104     efTPR,
105     efGRO, efG96, efPDB, efBRK, efENT
106 };
107 #define NTPSS asize(tpss)
108
109 typedef struct
110 {
111     int         ftype;
112     const char *ext;
113     const char *defnm;
114     const char *defopt;
115     const char *descr;
116     int         ntps;
117     const int  *tps;
118 } t_deffile;
119
120 /* this array should correspond to the enum in filenm.h */
121 static const t_deffile
122     deffile[efNR] =
123 {
124     { eftASC, ".mdp", "grompp", "-f", "grompp input file with MD parameters" },
125     { eftGEN, ".???", "traj", "-f", "Trajectory", NTRXS, trxs },
126     { eftGEN, ".???", "trajout", "-f", "Trajectory", NTROS, tros },
127     { eftGEN, ".???", "traj", NULL,
128       "Full precision trajectory", NTRNS, trns },
129     { eftXDR, ".trr", "traj", NULL, "Trajectory in portable xdr format" },
130     { eftGEN, ".???", "traj_comp", NULL,
131       "Compressed trajectory (tng format or portable xdr format)", NTRCOMPRESSED, trcompressed},
132     { eftXDR, ".xtc", "traj", NULL,
133       "Compressed trajectory (portable xdr format): xtc" },
134     { eftTNG, ".tng", "traj", NULL,
135       "Trajectory file (tng format)" },
136     { eftXDR, ".edr", "ener",   NULL, "Energy file"},
137     { eftGEN, ".???", "conf", "-c", "Structure file", NSTXS, stxs },
138     { eftGEN, ".???", "out", "-o", "Structure file", NSTOS, stos },
139     { eftASC, ".gro", "conf", "-c", "Coordinate file in Gromos-87 format" },
140     { eftASC, ".g96", "conf", "-c", "Coordinate file in Gromos-96 format" },
141     { eftASC, ".pdb", "eiwit",  "-f", "Protein data bank file"},
142     { eftASC, ".brk", "eiwit",  "-f", "Brookhaven data bank file"},
143     { eftASC, ".ent", "eiwit", "-f", "Entry in the protein date bank" },
144     { eftASC, ".esp", "conf", "-f", "Coordinate file in Espresso format" },
145     { eftASC, ".pqr", "state",  "-o", "Coordinate file for MEAD"},
146     { eftXDR, ".cpt", "state",  "-cp", "Checkpoint file"},
147     { eftASC, ".log", "run",    "-l", "Log file"},
148     { eftASC, ".xvg", "graph",  "-o", "xvgr/xmgr file"},
149     { eftASC, ".out", "hello",  "-o", "Generic output file"},
150     { eftASC, ".ndx", "index",  "-n", "Index file", },
151     { eftASC, ".top", "topol",  "-p", "Topology file"},
152     { eftASC, ".itp", "topinc", NULL, "Include file for topology"},
153     { eftGEN, ".???", "topol", "-s", "Structure+mass(db)", NTPSS, tpss },
154     { eftXDR, ".tpr", "topol",  "-s", "Portable xdr run input file"},
155     { eftASC, ".tex", "doc",    "-o", "LaTeX file"},
156     { eftASC, ".rtp", "residue", NULL, "Residue Type file used by pdb2gmx" },
157     { eftASC, ".atp", "atomtp", NULL, "Atomtype file used by pdb2gmx" },
158     { eftASC, ".hdb", "polar",  NULL, "Hydrogen data base"},
159     { eftASC, ".dat", "nnnice", NULL, "Generic data file"},
160     { eftASC, ".dlg", "user",   NULL, "Dialog Box data for ngmx"},
161     { eftASC, ".map", "ss", NULL, "File that maps matrix data to colors" },
162     { eftASC, ".eps", "plot", NULL, "Encapsulated PostScript (tm) file" },
163     { eftASC, ".mat", "ss",     NULL, "Matrix Data file"},
164     { eftASC, ".m2p", "ps",     NULL, "Input file for mat2ps"},
165     { eftXDR, ".mtx", "hessian", "-m", "Hessian matrix"},
166     { eftASC, ".edi", "sam",    NULL, "ED sampling input"},
167     { eftASC, ".cub", "pot",  NULL, "Gaussian cube file" },
168     { eftASC, ".xpm", "root", NULL, "X PixMap compatible matrix file" },
169     { eftASC, "", "rundir", NULL, "Run directory" }
170 };
171
172 #define NZEXT 2
173 static const char *z_ext[NZEXT] =
174 { ".gz", ".Z" };
175
176 const char *ftp2ext(int ftp)
177 {
178     if ((0 <= ftp) && (ftp < efNR))
179     {
180         return deffile[ftp].ext[0] != '\0' ? deffile[ftp].ext + 1 : "";
181     }
182     else
183     {
184         return "unknown";
185     }
186 }
187
188 const char *ftp2ext_generic(int ftp)
189 {
190     if ((0 <= ftp) && (ftp < efNR))
191     {
192         switch (ftp)
193         {
194             case efTRX:
195                 return "trx";
196             case efTRN:
197                 return "trn";
198             case efSTO:
199                 return "sto";
200             case efSTX:
201                 return "stx";
202             case efTPS:
203                 return "tps";
204             default:
205                 return ftp2ext(ftp);
206         }
207     }
208     else
209     {
210         return "unknown";
211     }
212 }
213
214 const char *ftp2ext_with_dot(int ftp)
215 {
216     if ((0 <= ftp) && (ftp < efNR))
217     {
218         return deffile[ftp].ext;
219     }
220     else
221     {
222         return "unknown";
223     }
224 }
225
226 int ftp2generic_count(int ftp)
227 {
228     if ((0 <= ftp) && (ftp < efNR))
229     {
230         return deffile[ftp].ntps;
231     }
232     else
233     {
234         return 0;
235     }
236 }
237
238 const int *ftp2generic_list(int ftp)
239 {
240     if ((0 <= ftp) && (ftp < efNR))
241     {
242         return deffile[ftp].tps;
243     }
244     else
245     {
246         return 0;
247     }
248 }
249
250 const char *ftp2desc(int ftp)
251 {
252     if ((0 <= ftp) && (ftp < efNR))
253     {
254         return deffile[ftp].descr;
255     }
256     else
257     {
258         return "unknown filetype";
259     }
260 }
261
262 gmx_bool ftp_is_text(int ftp)
263 {
264     if ((ftp >= 0) && (ftp < efNR))
265     {
266         return deffile[ftp].ftype == eftASC;
267     }
268     return FALSE;
269 }
270
271 gmx_bool ftp_is_xdr(int ftp)
272 {
273     if ((ftp >= 0) && (ftp < efNR))
274     {
275         return deffile[ftp].ftype == eftXDR;
276     }
277     return FALSE;
278 }
279
280 const char *ftp2defnm(int ftp)
281 {
282     if ((0 <= ftp) && (ftp < efNR))
283     {
284         return deffile[ftp].defnm;
285     }
286     else
287     {
288         return NULL;
289     }
290 }
291
292 const char *ftp2defopt(int ftp)
293 {
294     if ((0 <= ftp) && (ftp < efNR))
295     {
296         return deffile[ftp].defopt;
297     }
298     else
299     {
300         return NULL;
301     }
302 }
303
304 int fn2ftp(const char *fn)
305 {
306     int         i, len;
307     const char *feptr;
308     const char *eptr;
309
310     if (!fn)
311     {
312         return efNR;
313     }
314
315     len = strlen(fn);
316     if ((len >= 4) && (fn[len - 4] == '.'))
317     {
318         feptr = &(fn[len - 4]);
319     }
320     else
321     {
322         return efNR;
323     }
324
325     for (i = 0; (i < efNR); i++)
326     {
327         if ((eptr = deffile[i].ext) != NULL)
328         {
329             if (gmx_strcasecmp(feptr, eptr) == 0)
330             {
331                 break;
332             }
333         }
334     }
335
336     return i;
337 }
338
339 const char *opt2fn(const char *opt, int nfile, const t_filenm fnm[])
340 {
341     int i;
342
343     for (i = 0; (i < nfile); i++)
344     {
345         if (strcmp(opt, fnm[i].opt) == 0)
346         {
347             return fnm[i].fns[0];
348         }
349     }
350
351     fprintf(stderr, "No option %s\n", opt);
352
353     return NULL;
354 }
355
356 const char *opt2fn_master(const char *opt, int nfile, const t_filenm fnm[],
357                           t_commrec *cr)
358 {
359     return SIMMASTER(cr) ? opt2fn(opt, nfile, fnm) : NULL;
360 }
361
362 int opt2fns(char **fns[], const char *opt, int nfile, const t_filenm fnm[])
363 {
364     int i;
365
366     for (i = 0; (i < nfile); i++)
367     {
368         if (strcmp(opt, fnm[i].opt) == 0)
369         {
370             *fns = fnm[i].fns;
371             return fnm[i].nfiles;
372         }
373     }
374
375     fprintf(stderr, "No option %s\n", opt);
376     return 0;
377 }
378
379 const char *ftp2fn(int ftp, int nfile, const t_filenm fnm[])
380 {
381     int i;
382
383     for (i = 0; (i < nfile); i++)
384     {
385         if (ftp == fnm[i].ftp)
386         {
387             return fnm[i].fns[0];
388         }
389     }
390
391     fprintf(stderr, "ftp2fn: No filetype %s\n", deffile[ftp].ext);
392     return NULL;
393 }
394
395 int ftp2fns(char **fns[], int ftp, int nfile, const t_filenm fnm[])
396 {
397     int i;
398
399     for (i = 0; (i < nfile); i++)
400     {
401         if (ftp == fnm[i].ftp)
402         {
403             *fns = fnm[i].fns;
404             return fnm[i].nfiles;
405         }
406     }
407
408     fprintf(stderr, "ftp2fn: No filetype %s\n", deffile[ftp].ext);
409     return 0;
410 }
411
412 gmx_bool ftp2bSet(int ftp, int nfile, const t_filenm fnm[])
413 {
414     int i;
415
416     for (i = 0; (i < nfile); i++)
417     {
418         if (ftp == fnm[i].ftp)
419         {
420             return (gmx_bool) IS_SET(fnm[i]);
421         }
422     }
423
424     fprintf(stderr, "ftp2bSet: No filetype %s\n", deffile[ftp].ext);
425
426     return FALSE;
427 }
428
429 gmx_bool opt2bSet(const char *opt, int nfile, const t_filenm fnm[])
430 {
431     int i;
432
433     for (i = 0; (i < nfile); i++)
434     {
435         if (strcmp(opt, fnm[i].opt) == 0)
436         {
437             return (gmx_bool) IS_SET(fnm[i]);
438         }
439     }
440
441     fprintf(stderr, "No option %s\n", opt);
442
443     return FALSE;
444 }
445
446 const char *opt2fn_null(const char *opt, int nfile, const t_filenm fnm[])
447 {
448     int i;
449
450     for (i = 0; (i < nfile); i++)
451     {
452         if (strcmp(opt, fnm[i].opt) == 0)
453         {
454             if (IS_OPT(fnm[i]) && !IS_SET(fnm[i]))
455             {
456                 return NULL;
457             }
458             else
459             {
460                 return fnm[i].fns[0];
461             }
462         }
463     }
464     fprintf(stderr, "No option %s\n", opt);
465     return NULL;
466 }
467
468 const char *ftp2fn_null(int ftp, int nfile, const t_filenm fnm[])
469 {
470     int i;
471
472     for (i = 0; (i < nfile); i++)
473     {
474         if (ftp == fnm[i].ftp)
475         {
476             if (IS_OPT(fnm[i]) && !IS_SET(fnm[i]))
477             {
478                 return NULL;
479             }
480             else
481             {
482                 return fnm[i].fns[0];
483             }
484         }
485     }
486     fprintf(stderr, "ftp2fn: No filetype %s\n", deffile[ftp].ext);
487     return NULL;
488 }
489
490 gmx_bool is_optional(const t_filenm *fnm)
491 {
492     return ((fnm->flag & ffOPT) == ffOPT);
493 }
494
495 gmx_bool is_output(const t_filenm *fnm)
496 {
497     return ((fnm->flag & ffWRITE) == ffWRITE);
498 }
499
500 gmx_bool is_set(const t_filenm *fnm)
501 {
502     return ((fnm->flag & ffSET) == ffSET);
503 }
504
505 int add_suffix_to_output_names(t_filenm *fnm, int nfile, const char *suffix)
506 {
507     int   i, j, pos;
508     char  buf[STRLEN], newname[STRLEN];
509     char *extpos;
510
511     for (i = 0; i < nfile; i++)
512     {
513         if (is_output(&fnm[i]) && fnm[i].ftp != efCPT)
514         {
515             /* We never use multiple _outputs_, but we might as well check
516                for it, just in case... */
517             for (j = 0; j < fnm[i].nfiles; j++)
518             {
519                 strncpy(buf, fnm[i].fns[j], STRLEN - 1);
520                 extpos  = strrchr(buf, '.');
521                 *extpos = '\0';
522                 sprintf(newname, "%s%s.%s", buf, suffix, extpos + 1);
523                 sfree(fnm[i].fns[j]);
524                 fnm[i].fns[j] = gmx_strdup(newname);
525             }
526         }
527     }
528     return 0;
529 }
530
531 t_filenm *dup_tfn(int nf, const t_filenm tfn[])
532 {
533     int       i, j;
534     t_filenm *ret;
535
536     snew(ret, nf);
537     for (i = 0; i < nf; i++)
538     {
539         ret[i] = tfn[i]; /* just directly copy all non-string fields */
540         if (tfn[i].opt)
541         {
542             ret[i].opt = gmx_strdup(tfn[i].opt);
543         }
544         else
545         {
546             ret[i].opt = NULL;
547         }
548
549         if (tfn[i].fn)
550         {
551             ret[i].fn = gmx_strdup(tfn[i].fn);
552         }
553         else
554         {
555             ret[i].fn = NULL;
556         }
557
558         if (tfn[i].nfiles > 0)
559         {
560             snew(ret[i].fns, tfn[i].nfiles);
561             for (j = 0; j < tfn[i].nfiles; j++)
562             {
563                 ret[i].fns[j] = gmx_strdup(tfn[i].fns[j]);
564             }
565         }
566     }
567     return ret;
568 }
569
570 void done_filenms(int nf, t_filenm fnm[])
571 {
572     int i, j;
573
574     for (i = 0; i < nf; ++i)
575     {
576         for (j = 0; j < fnm[i].nfiles; ++j)
577         {
578             sfree(fnm[i].fns[j]);
579         }
580         sfree(fnm[i].fns);
581         fnm[i].fns = NULL;
582     }
583 }