Don't use POSIX fnmatch() for pattern matching.
[gromacs/qmmm-gamess-us.git] / src / gmxlib / pargs.c
blob586e75ac63a527d840b44689a379d554e14ec6d0
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 /* This file is completely threadsafe - keep it that way! */
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
40 #include <stdio.h>
41 #include <string.h>
42 #include <ctype.h>
43 #include "typedefs.h"
44 #include "gmx_fatal.h"
45 #include "statutil.h"
46 #include "readinp.h"
47 #include "smalloc.h"
48 #include "names.h"
49 #include "string2.h"
50 #include "vec.h"
52 /* The source code in this file should be thread-safe.
53 Please keep it that way. */
55 bool is_hidden(t_pargs *pa)
57 return ((strstr(pa->desc,"HIDDEN") != NULL) ||
58 (strstr(pa->desc,"[hidden]") != NULL));
61 void get_pargs(int *argc,char *argv[],int nparg,t_pargs pa[],bool bKeepArgs)
63 int i,j,k,match;
64 bool *bKeep;
65 char buf[32];
66 char *ptr;
68 snew(bKeep,*argc+1);
69 bKeep[0] = TRUE;
70 bKeep[*argc] = TRUE;
72 for(i=1; (i<*argc); i++) {
73 bKeep[i] = TRUE;
74 for(j=0; (j<nparg); j++) {
75 if (pa[j].type == etBOOL) {
76 sprintf(buf,"-no%s",pa[j].option+1);
77 if (strcmp(pa[j].option,argv[i])== 0) {
78 *pa[j].u.b = TRUE;
79 pa[j].bSet = TRUE;
80 bKeep[i] = FALSE;
82 else if (strcmp(buf,argv[i])== 0) {
83 *pa[j].u.b = FALSE;
84 pa[j].bSet = TRUE;
85 bKeep[i] = FALSE;
88 else if (strcmp(pa[j].option,argv[i])== 0) {
89 if (pa[j].bSet)
90 fprintf(stderr,"Setting option %s more than once!\n",
91 pa[j].option);
92 pa[j].bSet = TRUE;
93 bKeep[i] = FALSE;
94 switch(pa[j].type) {
95 case etINT:
96 *pa[j].u.i = iscan(*argc,argv,&i);
97 break;
98 case etGMX_LARGE_INT:
99 *pa[j].u.is = istepscan(*argc,argv,&i);
100 break;
101 case etTIME:
102 case etREAL:
103 *pa[j].u.r = dscan(*argc,argv,&i);
104 break;
105 case etSTR:
106 *(pa[j].u.c) = sscan(*argc,argv,&i);
107 break;
108 case etENUM:
109 match=NOTSET;
110 ptr = sscan(*argc,argv,&i);
111 for(k=1; (pa[j].u.c[k] != NULL); k++)
112 /* only check ptr against beginning of
113 pa[j].u.c[k] */
114 if (strncasecmp(ptr,pa[j].u.c[k],strlen(ptr)) == 0)
115 if ( ( match == NOTSET ) ||
116 ( strlen(pa[j].u.c[k]) <
117 strlen(pa[j].u.c[match]) ) )
118 match = k;
119 if (match!=NOTSET)
120 pa[j].u.c[0] = pa[j].u.c[match];
121 else
122 gmx_fatal(FARGS,"Invalid argument %s for option %s",
123 ptr,pa[j].option);
124 break;
125 case etRVEC:
126 (*pa[j].u.rv)[0] = dscan(*argc,argv,&i);
127 if ( (i+1 == *argc) ||
128 ( (argv[i+1][0]=='-') &&
129 !isdigit(argv[i+1][1]) ) )
130 (*pa[j].u.rv)[1] =
131 (*pa[j].u.rv)[2] =
132 (*pa[j].u.rv)[0];
133 else {
134 bKeep[i] = FALSE;
135 (*pa[j].u.rv)[1] = dscan(*argc,argv,&i);
136 if ( (i+1 == *argc) ||
137 ( (argv[i+1][0]=='-') &&
138 !isdigit(argv[i+1][1]) ) )
139 gmx_fatal(FARGS,
140 "%s: vector must have 1 or 3 real parameters",
141 pa[j].option);
142 bKeep[i] = FALSE;
143 (*pa[j].u.rv)[2] = dscan(*argc,argv,&i);
145 break;
146 default:
147 gmx_fatal(FARGS,"Invalid type %d in pargs",pa[j].type);
149 /* i may be incremented, so set it to not keep */
150 bKeep[i] = FALSE;
154 if (!bKeepArgs) {
155 /* Remove used entries */
156 for(i=j=0; (i<=*argc); i++) {
157 if (bKeep[i])
158 argv[j++]=argv[i];
160 (*argc)=j-1;
162 sfree(bKeep);
165 int opt2parg_int(const char *option,int nparg,t_pargs pa[])
167 int i;
169 for(i=0; (i<nparg); i++)
170 if (strcmp(pa[i].option,option) == 0)
171 return *pa[i].u.i;
173 gmx_fatal(FARGS,"No integer option %s in pargs",option);
175 return 0;
178 bool opt2parg_bool(const char *option,int nparg,t_pargs pa[])
180 int i;
182 for(i=0; (i<nparg); i++)
183 if (strcmp(pa[i].option,option) == 0)
184 return *pa[i].u.b;
186 gmx_fatal(FARGS,"No boolean option %s in pargs",option);
188 return FALSE;
191 real opt2parg_real(const char *option,int nparg,t_pargs pa[])
193 int i;
195 for(i=0; (i<nparg); i++)
196 if (strcmp(pa[i].option,option) == 0)
197 return *pa[i].u.r;
199 gmx_fatal(FARGS,"No real option %s in pargs",option);
201 return 0.0;
204 const char *opt2parg_str(const char *option,int nparg,t_pargs pa[])
206 int i;
208 for(i=0; (i<nparg); i++)
209 if (strcmp(pa[i].option,option) == 0)
210 return *(pa[i].u.c);
212 gmx_fatal(FARGS,"No string option %s in pargs",option);
214 return NULL;
217 bool opt2parg_bSet(const char *option,int nparg,t_pargs pa[])
219 int i;
221 for(i=0; (i<nparg); i++)
222 if (strcmp(pa[i].option,option) == 0)
223 return pa[i].bSet;
225 gmx_fatal(FARGS,"No such option %s in pargs",option);
227 return FALSE; /* Too make some compilers happy */
230 const char *opt2parg_enum(const char *option,int nparg,t_pargs pa[])
232 int i;
234 for(i=0; (i<nparg); i++)
235 if (strcmp(pa[i].option,option) == 0)
236 return pa[i].u.c[0];
238 gmx_fatal(FARGS,"No such option %s in pargs",option);
240 return NULL;
243 char *pa_val(t_pargs *pa, char buf[], int sz)
245 real r;
246 char buf_str[1256]; buf_str[0]='\0';
248 buf[0]='\0';
250 if(sz<255)
251 gmx_fatal(FARGS,"Buffer must be at least 255 chars\n");
253 switch(pa->type) {
254 case etINT:
255 sprintf(buf,"%-d",*(pa->u.i));
256 break;
257 case etGMX_LARGE_INT:
258 sprintf(buf,gmx_large_int_pfmt,*(pa->u.is));
259 break;
260 case etTIME:
261 case etREAL:
262 r=*(pa->u.r);
263 sprintf(buf_str,"%-6g",r);
264 strcpy(buf, buf_str);
265 break;
266 case etBOOL:
267 sprintf(buf,"%-6s",*(pa->u.b) ? "yes" : "no");
268 break;
269 case etSTR:
270 if (*(pa->u.c)) {
271 if (strlen(*(pa->u.c)) >= (size_t)sz)
272 gmx_fatal(FARGS,"Argument too long: \"%d\"\n",*(pa->u.c));
273 else
274 strcpy(buf,*(pa->u.c));
276 break;
277 case etENUM:
278 strcpy(buf,*(pa->u.c));
279 break;
280 case etRVEC:
281 sprintf(buf,"%g %g %g",(*pa->u.rv)[0],
282 (*pa->u.rv)[1],
283 (*pa->u.rv)[2]);
284 break;
286 return buf;
289 #define OPTLEN 12
290 #define TYPELEN 6
291 #define LONGSTR 1024
292 char *pargs_print_line(t_pargs *pa,bool bLeadingSpace)
294 char buf[LONGSTR],*buf2,*tmp;
296 snew(buf2,LONGSTR+strlen(pa->desc));
297 snew(tmp,LONGSTR+strlen(pa->desc));
299 if (pa->type == etBOOL)
300 sprintf(buf,"-[no]%s",pa->option+1);
301 else
302 strcpy(buf,pa->option);
303 if (strlen(buf)>((OPTLEN+TYPELEN)-max(strlen(argtp[pa->type]),4))) {
304 sprintf(buf2,"%s%s %-6s %-6s %-s\n",
305 bLeadingSpace ? " " : "",buf,
306 argtp[pa->type],pa_val(pa,tmp,LONGSTR-1),check_tty(pa->desc));
307 } else if (strlen(buf)>OPTLEN) {
308 /* so type can be 3 or 4 char's, this fits in the %4s */
309 sprintf(buf2,"%s%-14s %-4s %-6s %-s\n",
310 bLeadingSpace ? " " : "",buf,argtp[pa->type],
311 pa_val(pa,tmp,LONGSTR-1),check_tty(pa->desc));
312 } else
313 sprintf(buf2,"%s%-12s %-6s %-6s %-s\n",
314 bLeadingSpace ? " " : "",buf,argtp[pa->type],
315 pa_val(pa,tmp,LONGSTR-1),check_tty(pa->desc));
317 sfree(tmp);
319 tmp = wrap_lines(buf2,78,28,FALSE);
321 sfree(buf2);
323 return tmp;
326 void print_pargs(FILE *fp, int npargs,t_pargs pa[],bool bLeadingSpace)
328 bool bShowHidden;
329 char buf[32],buf2[256],tmp[256];
330 char *wdesc;
331 int i;
333 /* Cannot call opt2parg_bSet here, because it crashes when the option
334 * is not in the list (mdrun)
336 bShowHidden = FALSE;
337 for(i=0; (i<npargs); i++)
338 if ((strcmp(pa[i].option,"-hidden")==0) && (pa[i].bSet))
339 bShowHidden = TRUE;
341 if (npargs > 0) {
342 fprintf(fp,"%s%-12s %-6s %-6s %-s\n",
343 bLeadingSpace ? " " : "","Option","Type","Value","Description");
344 fprintf(fp,"%s------------------------------------------------------\n",
345 bLeadingSpace ? " " : "");
346 for(i=0; (i<npargs); i++) {
347 if (bShowHidden || !is_hidden(&pa[i])) {
348 wdesc = pargs_print_line(&pa[i],bLeadingSpace);
349 fprintf(fp,"%s",wdesc);
350 sfree(wdesc);
353 fprintf(fp,"\n");
357 void pr_enums(FILE *fp, int npargs,t_pargs pa[], int shell)
359 int i,j;
361 switch (shell) {
362 case eshellCSH:
363 for (i=0; i<npargs; i++)
364 if (pa[i].type==etENUM) {
365 fprintf(fp," \"n/%s/(",pa[i].option);
366 for(j=1; pa[i].u.c[j]; j++)
367 fprintf(fp," %s",pa[i].u.c[j]);
368 fprintf(fp,")/\"");
370 break;
371 case eshellBASH:
372 for (i=0; i<npargs; i++)
373 if (pa[i].type==etENUM) {
374 fprintf(fp,"%s) COMPREPLY=( $(compgen -W '",pa[i].option);
375 for(j=1; pa[i].u.c[j]; j++)
376 fprintf(fp," %s",pa[i].u.c[j]);
377 fprintf(fp," ' -- $c ));;\n");
379 break;
380 case eshellZSH:
381 for (i=0; i<npargs; i++)
382 if (pa[i].type==etENUM) {
383 fprintf(fp,"- 'c[-1,%s]' -s \"", pa[i].option);
384 for(j=1; pa[i].u.c[j]; j++)
385 fprintf(fp," %s",pa[i].u.c[j]);
386 fprintf(fp,"\" ");
388 break;