Don't use POSIX fnmatch() for pattern matching.
[gromacs/qmmm-gamess-us.git] / src / gmxlib / filenm.c
blob45c45e9e4424c8a81a94a4f81d7699ad526e7a8a
1 /*
2 *
3 * This source code is part of
4 *
5 * G R O M A C S
6 *
7 * GROningen MAchine for Chemical Simulations
8 *
9 * VERSION 3.2.0
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
32 * And Hey:
33 * GROningen Mixture of Alchemy and Childrens' Stories
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
39 #include <string.h>
40 #include "sysstuff.h"
41 #include "typedefs.h"
42 #include "smalloc.h"
43 #include "string2.h"
44 #include "gmx_fatal.h"
45 #include "filenm.h"
46 #include "futil.h"
47 #include "wman.h"
48 #include "xdrf.h"
49 #include "macros.h"
51 #ifdef GMX_THREADS
52 #include "thread_mpi.h"
53 #endif
55 /* NOTE: this was a cesspool of thread-unsafe code, has now been
56 properly proteced by mutexes (hopefully). */
59 /* XDR should be available on all platforms now,
60 * but we keep the possibility of turning it off...
62 #define USE_XDR
64 /* Use bitflag ... */
65 #define IS_SET(fn) ((fn.flag & ffSET) != 0)
66 #define IS_OPT(fn) ((fn.flag & ffOPT) != 0)
67 #define IS_MULT(fn) ((fn.flag & ffMULT) != 0)
68 #define UN_SET(fn) (fn.flag = (fn.flag & ~ffSET))
69 #define DO_SET(fn) (fn.flag = (fn.flag | ffSET))
71 enum { eftASC, eftBIN, eftXDR, eftGEN, eftNR };
73 /* To support multiple file types with one general (eg TRX) we have
74 * these arrays.
76 static const int trxs[]={
77 #ifdef USE_XDR
78 efXTC, efTRR, efCPT,
79 #endif
80 efTRJ, efGRO, efG96, efPDB, efG87 };
81 #define NTRXS asize(trxs)
83 static const int tros[]={
84 #ifdef USE_XDR
85 efXTC, efTRR,
86 #endif
87 efTRJ, efGRO, efG96, efPDB, efG87 };
88 #define NTROS asize(tros)
90 static const int trns[]={
91 #ifdef USE_XDR
92 efTRR, efCPT,
93 #endif
94 efTRJ };
95 #define NTRNS asize(trns)
97 static const int stos[]={ efGRO, efG96, efPDB, efBRK,
98 efENT, efESP, efXYZ};
99 #define NSTOS asize(stos)
101 static const int stxs[]={ efGRO, efG96, efPDB, efBRK, efENT, efESP, efXYZ,
102 #ifdef USE_XDR
103 efTPR,
104 #endif
105 efTPB, efTPA };
106 #define NSTXS asize(stxs)
108 static const int tpxs[]={
109 #ifdef USE_XDR
110 efTPR,
111 #endif
112 efTPB, efTPA };
113 #define NTPXS asize(tpxs)
115 static const int tpss[]={
116 #ifdef USE_XDR
117 efTPR,
118 #endif
119 efTPB, efTPA, efGRO, efG96, efPDB, efBRK, efENT };
120 #define NTPSS asize(tpss)
122 typedef struct {
123 int ftype;
124 const char *ext;
125 const char *defnm;
126 const char *defopt;
127 const char *descr;
128 int ntps;
129 const int *tps;
130 } t_deffile;
133 /* this array should correspond to the enum in include/types/filenm.h */
134 static const t_deffile deffile[efNR] = {
135 { eftASC, ".mdp", "grompp", "-f", "grompp input file with MD parameters" },
136 { eftASC, ".gct", "gct", "-f", "General coupling stuff" },
137 { eftGEN, ".???", "traj", "-f", "Trajectory: xtc trr trj gro g96 pdb cpt", NTRXS, trxs },
138 { eftGEN, ".???", "trajout","-f", "Trajectory: xtc trr trj gro g96 pdb", NTROS, tros },
139 { eftGEN, ".???", "traj", NULL, "Full precision trajectory: trr trj cpt", NTRNS, trns },
140 { eftXDR, ".trr", "traj", NULL, "Trajectory in portable xdr format" },
141 { eftBIN, ".trj", "traj", NULL, "Trajectory file (architecture specific)" },
142 { eftXDR, ".xtc", "traj", NULL, "Compressed trajectory (portable xdr format)"},
143 { eftASC, ".g87", "gtraj", NULL, "Gromos-87 ASCII trajectory format" },
144 { eftXDR, ".edr", "ener", NULL, "Energy file" },
145 { eftGEN, ".???", "conf", "-c", "Structure file: gro g96 pdb tpr etc.", NSTXS, stxs },
146 { eftGEN, ".???", "out", "-o", "Structure file: gro g96 pdb etc.", NSTOS, stos },
147 { eftASC, ".gro", "conf", "-c", "Coordinate file in Gromos-87 format" },
148 { eftASC, ".g96", "conf", "-c", "Coordinate file in Gromos-96 format" },
149 { eftASC, ".pdb", "eiwit", "-f", "Protein data bank file" },
150 { eftASC, ".brk", "eiwit", "-f", "Brookhaven data bank file" },
151 { eftASC, ".ent", "eiwit", "-f", "Entry in the protein date bank" },
152 { eftASC, ".esp", "conf", "-f", "Coordinate file in Espresso format" },
153 { eftASC, ".pqr", "state", "-o", "Coordinate file for MEAD" },
154 { eftASC, ".xyz", "conf", "-o", "Coordinate file for some other programs"},
155 { eftXDR, ".cpt", "state", "-cp","Checkpoint file" },
156 { eftASC, ".log", "run", "-l", "Log file" },
157 { eftASC, ".xvg", "graph", "-o", "xvgr/xmgr file" },
158 { eftASC, ".out", "hello", "-o", "Generic output file" },
159 { eftASC, ".ndx", "index", "-n", "Index file", },
160 { eftASC, ".top", "topol", "-p", "Topology file" },
161 { eftASC, ".itp", "topinc", NULL, "Include file for topology" },
162 { eftGEN, ".???", "topol", "-s", "Run input file: tpr tpb tpa", NTPXS, tpxs },
163 { eftGEN, ".???", "topol", "-s", "Structure+mass(db): tpr tpb tpa gro g96 pdb", NTPSS, tpss },
164 { eftXDR, ".tpr", "topol", "-s", "Portable xdr run input file" },
165 { eftASC, ".tpa", "topol", "-s", "Ascii run input file" },
166 { eftBIN, ".tpb", "topol", "-s", "Binary run input file" },
167 { eftASC, ".tex", "doc", "-o", "LaTeX file" },
168 { eftASC, ".rtp", "residue",NULL, "Residue Type file used by pdb2gmx" },
169 { eftASC, ".atp", "atomtp", NULL, "Atomtype file used by pdb2gmx" },
170 { eftASC, ".hdb", "polar", NULL, "Hydrogen data base" },
171 { eftASC, ".dat", "nnnice", NULL, "Generic data file" },
172 { eftASC, ".dlg", "user", NULL, "Dialog Box data for ngmx" },
173 { eftASC, ".map", "ss", NULL, "File that maps matrix data to colors" },
174 { eftASC, ".eps", "plot", NULL, "Encapsulated PostScript (tm) file" },
175 { eftASC, ".mat", "ss", NULL, "Matrix Data file" },
176 { eftASC, ".m2p", "ps", NULL, "Input file for mat2ps" },
177 { eftXDR, ".mtx", "hessian","-m", "Hessian matrix" },
178 { eftASC, ".edi", "sam", NULL, "ED sampling input" },
179 { eftASC, ".edo", "sam", NULL, "ED sampling output" },
180 { eftASC, ".hat", "gk", NULL, "Fourier transform of spread function" },
181 { eftASC, ".xpm", "root", NULL, "X PixMap compatible matrix file" }
185 static char *default_file_name=NULL;
187 #ifdef GMX_THREADS
188 static tMPI_Thread_mutex_t filenm_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
189 #endif
191 #define NZEXT 2
192 const char *z_ext[NZEXT] = { ".gz", ".Z" };
194 void set_default_file_name(const char *name)
196 int i;
197 #ifdef GMX_THREADS
198 tMPI_Thread_mutex_lock(&filenm_mutex);
199 #endif
200 default_file_name = strdup(name);
201 #ifdef GMX_THREADS
202 tMPI_Thread_mutex_unlock(&filenm_mutex);
203 #endif
205 #if 0
206 for(i=0; i<efNR; i++)
207 deffile[i].defnm = default_file_name;
208 #endif
211 const char *ftp2ext(int ftp)
213 if ((0 <= ftp) && (ftp < efNR))
214 return deffile[ftp].ext+1;
215 else
216 return "unknown";
219 const char *ftp2ext_generic(int ftp)
221 if ((0 <= ftp) && (ftp < efNR)) {
222 switch (ftp) {
223 case efTRX:
224 return "trx";
225 case efTRN:
226 return "trn";
227 case efSTO:
228 return "sto";
229 case efSTX:
230 return "stx";
231 case efTPX:
232 return "tpx";
233 case efTPS:
234 return "tps";
235 default:
236 return ftp2ext(ftp);
239 else
240 return "unknown";
243 const char *ftp2desc(int ftp)
245 if ((0 <= ftp) && (ftp < efNR))
246 return deffile[ftp].descr;
247 else
248 return "unknown filetype";
251 const char *ftp2ftype(int ftp)
253 if ((ftp >= 0) && (ftp < efNR)) {
254 switch (deffile[ftp].ftype) {
255 case eftASC:
256 return "ASCII";
257 case eftBIN:
258 return "Binary";
259 case eftXDR:
260 return "XDR portable";
261 case eftGEN:
262 return "";
263 default:
264 gmx_fatal(FARGS,"Unknown filetype %d in ftp2ftype",deffile[ftp].ftype);
265 break;
268 return "unknown";
271 const char *ftp2defnm(int ftp)
273 const char *buf=NULL;
275 #ifdef GMX_THREADS
276 tMPI_Thread_mutex_lock(&filenm_mutex);
277 #endif
279 if (default_file_name)
281 buf=default_file_name;
283 else
285 if ((0 <= ftp) && (ftp < efNR))
287 buf=deffile[ftp].defnm;
290 #ifdef GMX_THREADS
291 tMPI_Thread_mutex_unlock(&filenm_mutex);
292 #endif
294 return buf;
297 void pr_def(FILE *fp,int ftp)
299 const t_deffile *df;
300 const char *s=NULL;
301 char *flst, *tmp;
302 const char *ext,*desc;
303 const char *defnm;
305 df=&(deffile[ftp]);
306 defnm=ftp2defnm(ftp);
307 /* find default file extension and \tt-ify description */
308 /* FIXME: The constness should not be cast away */
309 flst=(char *)"";
310 if (df->ntps) {
311 ext = deffile[df->tps[0]].ext;
312 desc= strdup(df->descr);
313 tmp = strstr(desc,": ")+1;
314 if (tmp) {
315 tmp[0] = '\0';
316 tmp++;
317 snew(flst,strlen(tmp)+6);
318 strcpy(flst, " \\tt ");
319 strcat(flst, tmp);
321 } else {
322 ext = df->ext;
323 desc= df->descr;
325 /* now skip dot */
326 if (ext[0])
327 ext++;
328 else
329 ext="";
330 /* set file contents type */
331 switch (df->ftype) {
332 case eftASC: s="Asc";
333 break;
334 case eftBIN: s="Bin";
335 break;
336 case eftXDR: s="xdr";
337 break;
338 case eftGEN: s="";
339 break;
340 default:
341 gmx_fatal(FARGS,"Unimplemented filetype %d %d",ftp,
342 df->ftype);
344 fprintf(fp,"\\tt %8s & \\tt %3s & %3s & \\tt %2s & %s%s \\\\[-0.1ex]\n",
345 defnm, ext, s, df->defopt ? df->defopt : "",
346 check_tex(desc),check_tex(flst));
349 void pr_fns(FILE *fp,int nf,const t_filenm tfn[])
351 int i,f;
352 size_t j;
353 char buf[256],*wbuf,opt_buf[32];
354 #define OPTLEN 4
355 #define NAMELEN 14
356 fprintf(fp,"%6s %12s %-12s %s\n",
357 "Option","Filename","Type","Description");
358 fprintf(fp,"------------------------------------------------------------\n");
359 for(i=0; (i<nf); i++) {
360 for(f=0; (f<tfn[i].nfiles); f++) {
361 sprintf(buf, "%4s %14s %-12s ",
362 (f==0) ? tfn[i].opt : "",tfn[i].fns[f],
363 (f==0) ? fileopt(tfn[i].flag,opt_buf,32) : "");
364 if ( f < tfn[i].nfiles-1 )
365 fprintf(fp, "%s\n", buf);
367 if (tfn[i].nfiles > 0) {
368 strcat(buf, deffile[tfn[i].ftp].descr);
369 if ( (strlen(tfn[i].opt)>OPTLEN) &&
370 (strlen(tfn[i].opt)<=
371 ((OPTLEN+NAMELEN)-strlen(tfn[i].fns[tfn[i].nfiles-1]))) )
373 for(j=strlen(tfn[i].opt);
374 j<strlen(buf)-(strlen(tfn[i].opt)-OPTLEN)+1; j++)
375 buf[j]=buf[j+strlen(tfn[i].opt)-OPTLEN];
377 wbuf=wrap_lines(buf,78,35,FALSE);
378 fprintf(fp,"%s\n",wbuf);
379 sfree(wbuf);
382 fprintf(fp,"\n");
383 fflush(fp);
386 void pr_fopts(FILE *fp,int nf,const t_filenm tfn[], int shell)
388 int i,j;
390 switch (shell) {
391 case eshellCSH:
392 for(i=0; (i<nf); i++) {
393 fprintf(fp," \"n/%s/f:*.",tfn[i].opt);
394 if (deffile[tfn[i].ftp].ntps) {
395 fprintf(fp,"{");
396 for(j=0; j<deffile[tfn[i].ftp].ntps; j++) {
397 if (j>0)
398 fprintf(fp,",");
399 fprintf(fp,"%s",deffile[deffile[tfn[i].ftp].tps[j]].ext+1);
401 fprintf(fp,"}");
402 } else
403 fprintf(fp,"%s",deffile[tfn[i].ftp].ext+1);
404 fprintf(fp,"{");
405 for(j=0; j<NZEXT; j++)
406 fprintf(fp,",%s",z_ext[j]);
407 fprintf(fp,"}/\"");
409 break;
410 case eshellBASH:
411 for(i=0; (i<nf); i++) {
412 fprintf(fp,"%s) COMPREPLY=( $(compgen -X '!*.",tfn[i].opt);
413 if (deffile[tfn[i].ftp].ntps) {
414 fprintf(fp,"+(");
415 for(j=0; j<deffile[tfn[i].ftp].ntps; j++) {
416 if (j>0)
417 fprintf(fp,"|");
418 fprintf(fp,"%s",deffile[deffile[tfn[i].ftp].tps[j]].ext+1);
420 fprintf(fp,")");
421 } else
422 fprintf(fp,"%s",deffile[tfn[i].ftp].ext+1);
423 fprintf(fp,"*(");
424 for(j=0; j<NZEXT; j++) {
425 if (j>0)
426 fprintf(fp,"|");
427 fprintf(fp,"%s",z_ext[j]);
429 fprintf(fp,")' -f $c ; compgen -S '/' -X '.*' -d $c ));;\n");
431 break;
432 case eshellZSH:
433 for(i=0; (i<nf); i++) {
434 fprintf(fp,"- 'c[-1,%s]' -g '*.",tfn[i].opt);
435 if (deffile[tfn[i].ftp].ntps) {
436 fprintf(fp,"(");
437 for(j=0; j<deffile[tfn[i].ftp].ntps; j++) {
438 if (j>0)
439 fprintf(fp,"|");
440 fprintf(fp,"%s",deffile[deffile[tfn[i].ftp].tps[j]].ext+1);
442 fprintf(fp,")");
443 } else
444 fprintf(fp,"%s",deffile[tfn[i].ftp].ext+1);
445 fprintf(fp,"(");
446 for(j=0; j<NZEXT; j++)
447 fprintf(fp,"|%s",z_ext[j]);
448 fprintf(fp,") *(/)' ");
450 break;
454 static void check_opts(int nf,t_filenm fnm[])
456 int i;
457 const t_deffile *df;
459 for(i=0; (i<nf); i++) {
460 df=&(deffile[fnm[i].ftp]);
461 if (fnm[i].opt == NULL) {
462 if (df->defopt == NULL)
463 gmx_fatal(FARGS,"No default cmd-line option for %s (type %d)\n",
464 deffile[fnm[i].ftp].ext,fnm[i].ftp);
465 else
466 fnm[i].opt=df->defopt;
471 int fn2ftp(const char *fn)
473 int i,len;
474 const char *feptr;
475 const char *eptr;
477 if (!fn)
478 return efNR;
480 len=strlen(fn);
481 if ((len >= 4) && (fn[len-4] == '.'))
482 feptr=&(fn[len-4]);
483 else
484 return efNR;
486 for(i=0; (i<efNR); i++)
487 if ((eptr=deffile[i].ext) != NULL)
488 if (strcasecmp(feptr,eptr)==0)
489 break;
491 return i;
494 static void set_extension(char *buf,int ftp)
496 int len,extlen;
497 const t_deffile *df;
499 /* check if extension is already at end of filename */
500 df=&(deffile[ftp]);
501 len=strlen(buf);
502 extlen = strlen(df->ext);
503 if ((len <= extlen) || (strcasecmp(&(buf[len-extlen]),df->ext) != 0))
504 strcat(buf,df->ext);
507 static void add_filenm(t_filenm *fnm, const char *filenm)
509 srenew(fnm->fns, fnm->nfiles+1);
510 fnm->fns[fnm->nfiles] = strdup(filenm);
511 fnm->nfiles++;
514 static void set_grpfnm(t_filenm *fnm,const char *name,bool bCanNotOverride)
516 char buf[256],buf2[256];
517 int i,type;
518 bool bValidExt;
519 int nopts;
520 const int *ftps;
522 nopts = deffile[fnm->ftp].ntps;
523 ftps = deffile[fnm->ftp].tps;
524 if ((nopts == 0) || (ftps == NULL))
525 gmx_fatal(FARGS,"nopts == 0 || ftps == NULL");
527 bValidExt = FALSE;
528 if (name && (bCanNotOverride || (default_file_name == NULL))) {
529 strcpy(buf,name);
530 /* First check whether we have a valid filename already */
531 type = fn2ftp(name);
532 for(i=0; (i<nopts) && !bValidExt; i++)
533 if (type == ftps[i])
534 bValidExt = TRUE;
535 } else
536 /* No name given, set the default name */
537 strcpy(buf,ftp2defnm(fnm->ftp));
539 if (!bValidExt && (fnm->flag & ffREAD)) {
540 /* for input-files only: search for filenames in the directory */
541 for(i=0; (i<nopts) && !bValidExt; i++) {
542 type = ftps[i];
543 strcpy(buf2,buf);
544 set_extension(buf2,type);
545 if (gmx_fexist(buf2)) {
546 bValidExt = TRUE;
547 strcpy(buf,buf2);
552 if (!bValidExt)
553 /* Use the first extension type */
554 set_extension(buf,ftps[0]);
556 add_filenm(fnm, buf);
559 static void set_filenm(t_filenm *fnm,const char *name,bool bCanNotOverride,
560 bool bReadNode)
562 /* Set the default filename, extension and option for those fields that
563 * are not already set. An extension is added if not present, if fn = NULL
564 * or empty, the default filename is given.
566 char buf[256];
567 int i,len,extlen;
569 if ((fnm->flag & ffREAD) && !bReadNode)
571 return;
574 if ((fnm->ftp < 0) || (fnm->ftp >= efNR))
575 gmx_fatal(FARGS,"file type out of range (%d)",fnm->ftp);
577 if (name)
578 strcpy(buf, name);
579 if ((fnm->flag & ffREAD) && name && gmx_fexist(name)) {
580 /* check if filename ends in .gz or .Z, if so remove that: */
581 len = strlen(name);
582 for (i=0; i<NZEXT; i++) {
583 extlen = strlen(z_ext[i]);
584 if (len > extlen)
585 if (strcasecmp(name+len-extlen,z_ext[i]) == 0) {
586 buf[len-extlen]='\0';
587 break;
592 if (deffile[fnm->ftp].ntps)
593 set_grpfnm(fnm,name ? buf : NULL,bCanNotOverride);
594 else {
595 if ((name == NULL) || !(bCanNotOverride || (default_file_name == NULL)))
597 const char *defnm=ftp2defnm(fnm->ftp);
598 strcpy(buf,defnm);
600 set_extension(buf,fnm->ftp);
602 add_filenm(fnm, buf);
606 static void set_filenms(int nf,t_filenm fnm[],bool bReadNode)
608 int i;
610 for(i=0; (i<nf); i++)
611 if (!IS_SET(fnm[i]))
612 set_filenm(&(fnm[i]),fnm[i].fn,FALSE,bReadNode);
615 void parse_file_args(int *argc,char *argv[],int nf,t_filenm fnm[],
616 bool bKeep,bool bReadNode)
618 int i,j;
619 bool *bRemove;
621 check_opts(nf,fnm);
623 for(i=0; (i<nf); i++)
624 UN_SET(fnm[i]);
626 if (*argc > 1) {
627 snew(bRemove,(*argc)+1);
628 i=1;
629 do {
630 for(j=0; (j<nf); j++) {
631 if (strcmp(argv[i],fnm[j].opt) == 0) {
632 DO_SET(fnm[j]);
633 bRemove[i]=TRUE;
634 i++;
635 /* check if we are out of arguments for this option */
636 if ( (i >= *argc) || (argv[i][0] == '-') )
637 set_filenm(&fnm[j],fnm[j].fn,FALSE,bReadNode);
638 /* sweep up all file arguments for this option */
639 while ((i < *argc) && (argv[i][0] != '-')) {
640 set_filenm(&fnm[j],argv[i],TRUE,bReadNode);
641 bRemove[i]=TRUE;
642 i++;
643 /* only repeat for 'multiple' file options: */
644 if ( ! IS_MULT(fnm[j]) )
645 break;
648 break; /* jump out of 'j' loop */
651 /* No file found corresponding to option argv[i] */
652 if (j == nf)
653 i++;
654 } while (i < *argc);
656 if (!bKeep) {
657 /* Remove used entries */
658 for(i=j=0; (i<=*argc); i++) {
659 if (!bRemove[i])
660 argv[j++]=argv[i];
662 (*argc)=j-1;
664 sfree(bRemove);
667 set_filenms(nf,fnm,bReadNode);
671 const char *opt2fn(const char *opt,int nfile, const t_filenm fnm[])
673 int i;
675 for(i=0; (i<nfile); i++)
676 if (strcmp(opt,fnm[i].opt)==0) {
677 return fnm[i].fns[0];
680 fprintf(stderr,"No option %s\n",opt);
682 return NULL;
685 const char *opt2fn_master(const char *opt, int nfile, const t_filenm fnm[],
686 t_commrec *cr )
688 return SIMMASTER(cr)?opt2fn(opt,nfile,fnm):NULL;
691 int opt2fns(char **fns[], const char *opt,int nfile, const t_filenm fnm[])
693 int i;
695 for(i=0; (i<nfile); i++)
696 if (strcmp(opt,fnm[i].opt)==0) {
697 *fns = fnm[i].fns;
698 return fnm[i].nfiles;
701 fprintf(stderr,"No option %s\n",opt);
702 return 0;
705 const char *ftp2fn(int ftp,int nfile,const t_filenm fnm[])
707 int i;
709 for(i=0; (i<nfile); i++)
710 if (ftp == fnm[i].ftp)
711 return fnm[i].fns[0];
713 fprintf(stderr,"ftp2fn: No filetype %s\n",deffile[ftp].ext);
714 return NULL;
717 int ftp2fns(char **fns[], int ftp,int nfile, const t_filenm fnm[])
719 int i;
721 for(i=0; (i<nfile); i++)
722 if (ftp == fnm[i].ftp) {
723 *fns = fnm[i].fns;
724 return fnm[i].nfiles;
727 fprintf(stderr,"ftp2fn: No filetype %s\n",deffile[ftp].ext);
728 return 0;
731 bool ftp2bSet(int ftp,int nfile,const t_filenm fnm[])
733 int i;
735 for(i=0; (i<nfile); i++)
736 if (ftp == fnm[i].ftp)
737 return (bool) IS_SET(fnm[i]);
739 fprintf(stderr,"ftp2bSet: No filetype %s\n",deffile[ftp].ext);
741 return FALSE;
744 bool opt2bSet(const char *opt,int nfile,const t_filenm fnm[])
746 int i;
748 for(i=0; (i<nfile); i++)
749 if (strcmp(opt,fnm[i].opt)==0)
750 return (bool) IS_SET(fnm[i]);
752 fprintf(stderr,"No option %s\n",opt);
754 return FALSE;
757 const char *opt2fn_null(const char *opt,int nfile, const t_filenm fnm[])
759 int i;
761 for(i=0; (i<nfile); i++)
762 if (strcmp(opt,fnm[i].opt)==0) {
763 if (IS_OPT(fnm[i]) && !IS_SET(fnm[i]))
764 return NULL;
765 else
766 return fnm[i].fns[0];
768 fprintf(stderr,"No option %s\n",opt);
769 return NULL;
772 const char *ftp2fn_null(int ftp,int nfile, const t_filenm fnm[])
774 int i;
776 for(i=0; (i<nfile); i++)
777 if (ftp == fnm[i].ftp) {
778 if (IS_OPT(fnm[i]) && !IS_SET(fnm[i]))
779 return NULL;
780 else
781 return fnm[i].fns[0];
783 fprintf(stderr,"ftp2fn: No filetype %s\n",deffile[ftp].ext);
784 return NULL;
787 #if 0
788 static void add_filters(char *filter,int *n,int nf,const int ftp[])
790 char buf[8];
791 int i;
793 sprintf(filter,"*.{");
794 for(i=0; (i<nf); i++) {
795 sprintf(buf,"%s",ftp2ext(ftp[i]));
796 if (*n > 0)
797 strcat(filter,",");
798 strcat(filter,buf);
799 (*n) ++;
801 strcat(filter,"}");
804 char *ftp2filter(int ftp)
806 int n;
807 static char filter[128];
809 filter[0] = '\0';
810 n = 0;
811 switch (ftp) {
812 case efTRX:
813 add_filters(filter,&n,NTRXS,trxs);
814 break;
815 case efTRN:
816 add_filters(filter,&n,NTRNS,trns);
817 break;
818 case efSTO:
819 add_filters(filter,&n,NSTOS,stos);
820 break;
821 case efSTX:
822 add_filters(filter,&n,NSTXS,stxs);
823 break;
824 case efTPX:
825 add_filters(filter,&n,NTPXS,tpxs);
826 break;
827 default:
828 sprintf(filter,"*%s",ftp2ext(ftp));
829 break;
831 return filter;
833 #endif
836 bool is_optional(const t_filenm *fnm)
838 return ((fnm->flag & ffOPT) == ffOPT);
841 bool is_output(const t_filenm *fnm)
843 return ((fnm->flag & ffWRITE) == ffWRITE);
846 bool is_set(const t_filenm *fnm)
848 return ((fnm->flag & ffSET) == ffSET);
853 int add_suffix_to_output_names(t_filenm *fnm, int nfile, const char *suffix)
855 int i,j,pos;
856 char buf[STRLEN],newname[STRLEN];
857 char *extpos;
859 for( i=0 ; i<nfile ; i++)
861 if( is_output(&fnm[i]) && fnm[i].ftp != efCPT )
863 /* We never use multiple _outputs_, but we might as well check
864 for it, just in case... */
865 for( j=0 ; j<fnm[i].nfiles ; j++)
867 strncpy(buf,fnm[i].fns[j],STRLEN-1);
868 extpos = strrchr(buf,'.');
869 *extpos = '\0';
870 sprintf(newname,"%s.%s.%s",buf,suffix,extpos+1);
871 free(fnm[i].fns[j]);
872 fnm[i].fns[j]=strdup(newname);
876 return 0;
879 t_filenm *dup_tfn(int nf, const t_filenm tfn[])
881 int i,j;
882 t_filenm *ret;
884 snew(ret, nf);
885 for(i=0;i<nf;i++)
887 ret[i] = tfn[i]; /* just directly copy all non-string fields */
888 if (tfn[i].opt)
889 ret[i].opt = strdup(tfn[i].opt);
890 else
891 ret[i].opt = NULL;
893 if (tfn[i].fn)
894 ret[i].fn = strdup(tfn[i].fn);
895 else
896 ret[i].fn = NULL;
898 if (tfn[i].nfiles > 0)
900 snew(ret[i].fns,tfn[i].nfiles);
901 for(j=0;j<tfn[i].nfiles;j++)
903 ret[i].fns[j] = strdup(tfn[i].fns[j]);
907 return ret;