Create fileio module
[alexxy/gromacs.git] / src / gromacs / onlinehelp / wman.cpp
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.
14
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.
19  *
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.
26  *
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.
29  *
30  * For more info, check our website at http://www.gromacs.org
31  *
32  * And Hey:
33  * GROningen Mixture of Alchemy and Childrens' Stories
34  */
35 #include <string>
36
37 #include "gromacs/commandline/cmdlinehelpcontext.h"
38 #include "gromacs/onlinehelp/wman.h"
39 #include "gromacs/utility/exceptions.h"
40 #include "gromacs/utility/file.h"
41 #include "gromacs/utility/stringutil.h"
42
43 #include "gmx_fatal.h"
44 #include "string2.h"
45 #include "smalloc.h"
46 #include "sysstuff.h"
47 #include "gromacs/fileio/filenm.h"
48 #include "gromacs/fileio/gmxfio.h"
49 #include "macros.h"
50 #include "statutil.h"
51 #include "copyrite.h"
52 #include "strdb.h"
53 #include "readinp.h"
54
55 /* The source code in this file should be thread-safe.
56          Please keep it that way. */
57
58
59 typedef struct {
60     const char *search, *replace;
61 } t_sandr_const;
62
63 typedef struct {
64     char *search, *replace;
65 } t_sandr;
66
67 /* The order of these arrays is significant. Text search and replace
68  * for each element occurs in order, so earlier changes can induce
69  * subsequent changes even though the original text might not appear
70  * to invoke the latter changes. */
71
72 const t_sandr_const sandrTty[] = {
73     { "[TT]", "" },
74     { "[tt]", "" },
75     { "[BB]", "" },
76     { "[bb]", "" },
77     { "[IT]", "" },
78     { "[it]", "" },
79     { "[MATH]", "" },
80     { "[math]", "" },
81     { "[CHEVRON]", "<" },
82     { "[chevron]", ">" },
83     { "[MAG]", "|" },
84     { "[mag]", "|" },
85     { "[INT]", "integral" },
86     { "[FROM]", " from " },
87     { "[from]", "" },
88     { "[TO]", " to " },
89     { "[to]", " of" },
90     { "[int]", "" },
91     { "[SUM]", "sum" },
92     { "[sum]", "" },
93     { "[SUB]", "_" },
94     { "[sub]", "" },
95     { "[SQRT]", "sqrt(" },
96     { "[sqrt]", ")" },
97     { "[EXP]", "exp(" },
98     { "[exp]", ")" },
99     { "[LN]", "ln(" },
100     { "[ln]", ")" },
101     { "[LOG]", "log(" },
102     { "[log]", ")" },
103     { "[COS]", "cos(" },
104     { "[cos]", ")" },
105     { "[SIN]", "sin(" },
106     { "[sin]", ")" },
107     { "[TAN]", "tan(" },
108     { "[tan]", ")" },
109     { "[COSH]", "cosh(" },
110     { "[cosh]", ")" },
111     { "[SINH]", "sinh(" },
112     { "[sinh]", ")" },
113     { "[TANH]", "tanh(" },
114     { "[tanh]", ")" },
115     { "[PAR]", "\n\n" },
116     { "[BR]", "\n"},
117     { "[GRK]", "" },
118     { "[grk]", "" }
119 };
120 #define NSRTTY asize(sandrTty)
121
122 const t_sandr_const sandrNROFF[] = {
123     { "[TT]", "\\fB " },
124     { "[tt]", "\\fR" },
125     { "[BB]", "\\fB " },
126     { "[bb]", "\\fR" },
127     { "[IT]", "\\fI " },
128     { "[it]", "\\fR" },
129     { "[MATH]", "" },
130     { "[math]", "" },
131     { "[CHEVRON]", "<" },
132     { "[chevron]", ">" },
133     { "[MAG]", "|" },
134     { "[mag]", "|" },
135     { "[INT]", "integral" },
136     { "[FROM]", " from " },
137     { "[from]", "" },
138     { "[TO]", " to " },
139     { "[to]", " of" },
140     { "[int]", "" },
141     { "[SUM]", "sum" },
142     { "[sum]", "" },
143     { "[SUB]", "_" },
144     { "[sub]", "" },
145     { "[SQRT]", "sqrt(" },
146     { "[sqrt]", ")", },
147     { "[EXP]", "exp(" },
148     { "[exp]", ")" },
149     { "[LN]", "ln(" },
150     { "[ln]", ")" },
151     { "[LOG]", "log(" },
152     { "[log]", ")" },
153     { "[COS]", "cos(" },
154     { "[cos]", ")" },
155     { "[SIN]", "sin(" },
156     { "[sin]", ")" },
157     { "[TAN]", "tan(" },
158     { "[tan]", ")" },
159     { "[COSH]", "cosh(" },
160     { "[cosh]", ")" },
161     { "[SINH]", "sinh(" },
162     { "[sinh]", ")" },
163     { "[TANH]", "tanh(" },
164     { "[tanh]", ")" },
165     { "[PAR]", "\n\n" },
166     { "\n ",    "\n" },
167     { "<",    "" },
168     { ">",    "" },
169     { "^",    "" },
170     { "#",    "" },
171     { "[BR]", "\n"},
172     { "-",    "\\-"},
173     { "[GRK]", "" },
174     { "[grk]", "" }
175 };
176 #define NSRNROFF asize(sandrNROFF)
177
178 const t_sandr_const sandrHTML[] = {
179     { "<",    "&lt;" },
180     { ">",    "&gt;" },
181     { "[TT]", "<tt>" },
182     { "[tt]", "</tt>" },
183     { "[BB]", "<b>" },
184     { "[bb]", "</b>" },
185     { "[IT]", "<it>" },
186     { "[it]", "</it>" },
187     { "[MATH]", "" },
188     { "[math]", "" },
189     { "[CHEVRON]", "<" },
190     { "[chevron]", ">" },
191     { "[MAG]", "|" },
192     { "[mag]", "|" },
193     { "[INT]", "integral" },
194     { "[FROM]", " from " },
195     { "[from]", "" },
196     { "[TO]", " to " },
197     { "[to]", " of" },
198     { "[int]", "" },
199     { "[SUM]", "sum" },
200     { "[sum]", "" },
201     { "[SUB]", "_" },
202     { "[sub]", "" },
203     { "[SQRT]", "sqrt(" },
204     { "[sqrt]", ")", },
205     { "[EXP]", "exp(" },
206     { "[exp]", ")" },
207     { "[LN]", "ln(" },
208     { "[ln]", ")" },
209     { "[LOG]", "log(" },
210     { "[log]", ")" },
211     { "[COS]", "cos(" },
212     { "[cos]", ")" },
213     { "[SIN]", "sin(" },
214     { "[sin]", ")" },
215     { "[TAN]", "tan(" },
216     { "[tan]", ")" },
217     { "[COSH]", "cosh(" },
218     { "[cosh]", ")" },
219     { "[SINH]", "sinh(" },
220     { "[sinh]", ")" },
221     { "[TANH]", "tanh(" },
222     { "[tanh]", ")" },
223     { "[PAR]", "<p>" },
224     { "[BR]", "<br>" },
225     { "[GRK]", "&"  },
226     { "[grk]", ";"  }
227 };
228 #define NSRHTML asize(sandrHTML)
229
230
231 /* Data structure for saved HTML links */
232 typedef struct t_linkdata {
233     int      nsr;
234     t_sandr *sr;
235 } t_linkdata;
236
237 static t_linkdata *init_linkdata()
238 {
239     t_linkdata *p;
240     snew(p, 1);
241     p->sr  = NULL;
242     p->nsr = 0;
243
244     return p;
245 }
246
247 static void finish_linkdata(t_linkdata *p)
248 {
249     int i;
250
251     for (i = 0; i < p->nsr; i++)
252     {
253         sfree(p->sr[i].search);
254         sfree(p->sr[i].replace);
255     }
256     sfree(p->sr);
257     sfree(p);
258 }
259
260 static char *repall(const char *s, int nsr, const t_sandr_const sa[])
261 {
262     try
263     {
264         std::string result(s);
265         for (int i = 0; i < nsr; ++i)
266         {
267             result = gmx::replaceAll(result, sa[i].search, sa[i].replace);
268         }
269         return gmx_strdup(result.c_str());
270     }
271     GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
272 }
273
274 static char *repallww(const char *s, int nsr, const t_sandr sa[])
275 {
276     try
277     {
278         std::string result(s);
279         for (int i = 0; i < nsr; ++i)
280         {
281             result = gmx::replaceAllWords(result, sa[i].search, sa[i].replace);
282         }
283         return gmx_strdup(result.c_str());
284     }
285     GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
286 }
287
288 static char *html_xref(char *s, const char *program, t_linkdata *links)
289 {
290     char   buf[256], **filestr;
291     int    i, j, n;
292
293     if (links->sr == NULL)
294     {
295         n          = get_file("links.dat", &(filestr));
296         links->nsr = n;
297         snew(links->sr, n);
298         for (i = 0, j = 0; (i < n); i++)
299         {
300             if (!program || (gmx_strcasecmp(program, filestr[i])  != 0))
301             {
302                 links->sr[j].search = gmx_strdup(filestr[i]);
303                 sprintf(buf, "<a href=\"%s.html\">%s</a>", filestr[i], filestr[i]);
304                 links->sr[j].replace = gmx_strdup(buf);
305                 j++;
306             }
307         }
308         links->nsr = j;
309         for (i = 0; i < n; i++)
310         {
311             sfree(filestr[i]);
312         }
313         sfree(filestr);
314     }
315     return repallww(s, links->nsr, links->sr);
316 }
317
318 static char *check_nroff(const char *s)
319 {
320     return repall(s, NSRNROFF, sandrNROFF);
321 }
322
323 static char *check_html(const char *s, const char *program, t_linkdata *links)
324 {
325     char *buf;
326
327     buf = repall(s, NSRHTML, sandrHTML);
328     buf = html_xref(buf, program, links);
329
330     return buf;
331 }
332
333 #define NSR(s) check_html(s, program, links)
334
335 #define FLAG_SET(flag, mask) ((flag &mask) == mask)
336 char *fileopt(unsigned long flag, char buf[], int maxsize)
337 {
338     char tmp[256];
339
340     if (FLAG_SET(flag, ffRW))
341     {
342         sprintf(tmp, "In/Out");
343     }
344     else if (FLAG_SET(flag, ffREAD))
345     {
346         sprintf(tmp, "Input");
347     }
348     else if (FLAG_SET(flag, ffWRITE))
349     {
350         sprintf(tmp, "Output");
351     }
352     else
353     {
354         sprintf(tmp, "Dunno");
355     }
356
357     if (FLAG_SET(flag, ffOPT))
358     {
359         strcat(tmp, ", Opt");
360         if (FLAG_SET(flag, ffSET))
361         {
362             strcat(tmp, "!");
363         }
364         else
365         {
366             strcat(tmp, ".");
367         }
368     }
369     if (FLAG_SET(flag, ffLIB))
370     {
371         strcat(tmp, ", Lib.");
372     }
373     if (FLAG_SET(flag, ffMULT))
374     {
375         strcat(tmp, ", Mult.");
376     }
377
378     sprintf(buf, "%s", tmp);
379
380     return buf;
381 }
382
383 static void write_nroffman(FILE *out,
384                            const char *program,
385                            int nldesc, const char **desc,
386                            int nfile, t_filenm *fnm,
387                            int npargs, t_pargs *pa,
388                            int nbug, const char **bugs,
389                            t_linkdata *links)
390
391 {
392     int  i;
393     char tmp[256];
394
395     fprintf(out, ".SH SYNOPSIS\n");
396     fprintf(out, "\\f3%s\\fP\n", program);
397
398     /* command line arguments */
399     if (nfile > 0)
400     {
401         for (i = 0; (i < nfile); i++)
402         {
403             fprintf(out, ".BI \"%s\" \" %s \"\n", check_nroff(fnm[i].opt),
404                     check_nroff(fnm[i].fns[0]));
405         }
406     }
407     if (npargs > 0)
408     {
409         for (i = 0; (i < npargs); i++)
410         {
411             if (pa[i].type == etBOOL)
412             {
413                 fprintf(out, ".BI \"\\-[no]%s\" \"\"\n", check_nroff(pa[i].option+1));
414             }
415             else
416             {
417                 fprintf(out, ".BI \"%s\" \" %s \"\n", check_nroff(pa[i].option),
418                         check_nroff(get_arg_desc(pa[i].type)));
419             }
420         }
421     }
422
423     /* description */
424     if (nldesc > 0)
425     {
426         fprintf(out, ".SH DESCRIPTION\n");
427         for (i = 0; (i < nldesc); i++)
428         {
429             fprintf(out, "\\&%s\n", check_nroff(desc[i]));
430         }
431     }
432
433     /* FILES */
434     if (nfile > 0)
435     {
436         fprintf(out, ".SH FILES\n");
437         for (i = 0; (i < nfile); i++)
438         {
439             fprintf(out, ".BI \"%s\" \" %s\" \n.B %s\n %s \n\n",
440                     check_nroff(fnm[i].opt),
441                     check_nroff(fnm[i].fns[0]),
442                     check_nroff(fileopt(fnm[i].flag, tmp, 255)),
443                     check_nroff(ftp2desc(fnm[i].ftp)));
444         }
445     }
446
447     /* other options */
448     fprintf(out, ".SH OTHER OPTIONS\n");
449     if (npargs > 0)
450     {
451         for (i = 0; (i < npargs); i++)
452         {
453             if (pa[i].type == etBOOL)
454             {
455                 fprintf(out, ".BI \"\\-[no]%s\"  \"%s\"\n %s\n\n",
456                         check_nroff(pa[i].option+1),
457                         check_nroff(pa_val(&(pa[i]), tmp, 255)),
458                         check_nroff(pa[i].desc));
459             }
460             else
461             {
462                 fprintf(out, ".BI \"%s\"  \" %s\" \" %s\" \n %s\n\n",
463                         check_nroff(pa[i].option),
464                         check_nroff(get_arg_desc(pa[i].type)),
465                         check_nroff(pa_val(&(pa[i]), tmp, 255)),
466                         check_nroff(pa[i].desc));
467             }
468         }
469     }
470
471     if (nbug > 0)
472     {
473         fprintf(out, ".SH KNOWN PROBLEMS\n");
474         for (i = 0; (i < nbug); i++)
475         {
476             fprintf(out, "\\- %s\n\n", check_nroff(bugs[i]));
477         }
478     }
479 }
480
481 char *check_tty(const char *s)
482 {
483     return repall(s, NSRTTY, sandrTty);
484 }
485
486 static void
487 print_tty_formatted(FILE *out, int nldesc, const char **desc, int indent,
488                     t_linkdata *links, const char *program)
489 {
490     char *buf;
491     char *temp;
492     int   buflen, i;
493
494     buflen = 80*nldesc;
495     snew(buf, buflen);
496     for (i = 0; (i < nldesc); i++)
497     {
498         if ((strlen(buf) > 0) &&
499             (buf[strlen(buf)-1] != ' ') && (buf[strlen(buf)-1] != '\n'))
500         {
501             strcat(buf, " ");
502         }
503         temp = check_tty(desc[i]);
504         if (strlen(buf) + strlen(temp) >= (size_t)(buflen-2))
505         {
506             buflen += strlen(temp);
507             srenew(buf, buflen);
508         }
509         strcat(buf, temp);
510         sfree(temp);
511     }
512     /* Make lines of at most 79 characters */
513     temp = wrap_lines(buf, 78, indent, FALSE);
514     fprintf(out, "%s\n", temp);
515     sfree(temp);
516     sfree(buf);
517 }
518
519 static void write_ttyman(FILE *out,
520                          const char *program,
521                          int nldesc, const char **desc,
522                          int nfile, t_filenm *fnm,
523                          int npargs, t_pargs *pa,
524                          int nbug, const char **bugs,
525                          t_linkdata *links)
526 {
527     int   i;
528     char *tmp;
529
530     if (nldesc > 0)
531     {
532         fprintf(out, "DESCRIPTION\n-----------\n");
533         print_tty_formatted(out, nldesc, desc, 0, links, program);
534     }
535     if (nbug > 0)
536     {
537         fprintf(out, "\n");
538         fprintf(out, "KNOWN PROBLEMS\n----------\n");
539         for (i = 0; i < nbug; i++)
540         {
541             snew(tmp, strlen(bugs[i])+3);
542             strcpy(tmp, "* ");
543             strcpy(tmp+2, check_tty(bugs[i]));
544             fprintf(out, "%s\n", wrap_lines(tmp, 78, 2, FALSE));
545             sfree(tmp);
546         }
547     }
548     if (nfile > 0)
549     {
550         fprintf(out, "\n");
551         pr_fns(out, nfile, fnm);
552     }
553     if (npargs > 0)
554     {
555         print_pargs(out, npargs, pa);
556     }
557 }
558
559 static void pr_html_files(FILE *out, int nfile, t_filenm fnm[],
560                           const char *program, t_linkdata *links)
561 {
562     int  i;
563     char link[10], tmp[255];
564
565     fprintf(out,
566             "<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=2>\n"
567             "<TR>"
568             "<TH>option</TH>"
569             "<TH>filename</TH>"
570             "<TH>type</TH>"
571             "<TH>description</TH>"
572             "</TR>\n");
573
574     for (i = 0; (i < nfile); i++)
575     {
576         strcpy(link, ftp2ext(fnm[i].ftp));
577         if (strcmp(link, "???") == 0)
578         {
579             strcpy(link, "files");
580         }
581         fprintf(out,
582                 "<TR>"
583                 "<TD ALIGN=RIGHT> <b><tt>%s</tt></b> </TD>"
584                 "<TD ALIGN=RIGHT> <tt><a href=\"%s.html\">%12s</a></tt> </TD>"
585                 "<TD> %s </TD>"
586                 "<TD> %s </TD>"
587                 "</TR>\n",
588                 fnm[i].opt, link, fnm[i].fns[0], fileopt(fnm[i].flag, tmp, 255),
589                 NSR(ftp2desc(fnm[i].ftp)));
590     }
591
592     fprintf(out, "</TABLE>\n");
593 }
594
595 static void write_htmlman(FILE *out,
596                           const char *program,
597                           int nldesc, const char **desc,
598                           int nfile, t_filenm *fnm,
599                           int npargs, t_pargs *pa,
600                           int nbug, const char **bugs,
601                           t_linkdata *links)
602 {
603     int  i;
604     char tmp[255];
605
606     if (nldesc > 0)
607     {
608         fprintf(out, "<H3>Description</H3>\n<p>\n");
609         for (i = 0; (i < nldesc); i++)
610         {
611             fprintf(out, "%s\n", NSR(desc[i]));
612         }
613     }
614     if (nfile > 0)
615     {
616         fprintf(out, "<P>\n");
617         fprintf(out, "<H3>Files</H3>\n");
618         pr_html_files(out, nfile, fnm, program, links);
619     }
620     if (npargs > 0)
621     {
622         fprintf(out, "<P>\n");
623         fprintf(out, "<H3>Other options</H3>\n");
624         fprintf(out,
625                 "<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=2>\n"
626                 "<TR>"
627                 "<TH>option</TH>"
628                 "<TH>type</TH>"
629                 "<TH>default</TH>"
630                 "<TH>description</TH>"
631                 "</TR>\n");
632         for (i = 0; (i < npargs); i++)
633         {
634             fprintf(out,
635                     "<TR>"
636                     "<TD ALIGN=RIGHT> <b><tt>%s%s</tt></b> </TD>"
637                     "<TD ALIGN=RIGHT> %s </TD>"
638                     "<TD ALIGN=RIGHT> <tt>%s</tt> </TD>"
639                     "<TD> %s </TD>"
640                     "</TD>\n",
641                     (pa[i].type == etBOOL) ? "-[no]" : "-", pa[i].option+1,
642                     get_arg_desc(pa[i].type), pa_val(&(pa[i]), tmp, 255), NSR(pa[i].desc));
643         }
644         fprintf(out, "</TABLE>\n");
645     }
646     if (nbug > 0)
647     {
648         fprintf(out, "<P>\n");
649         fprintf(out, "<H3>Known problems</H3>\n");
650         fprintf(out, "<UL>\n");
651         for (i = 0; (i < nbug); i++)
652         {
653             fprintf(out, "<LI>%s\n", NSR(bugs[i]));
654         }
655         fprintf(out, "</UL>\n");
656     }
657 }
658
659 static void pr_opts(FILE *fp,
660                     int nfile,  t_filenm *fnm,
661                     int npargs, t_pargs pa[], int shell)
662 {
663     int i;
664
665     switch (shell)
666     {
667         case eshellCSH:
668             fprintf(fp, " \"c/-/(");
669             for (i = 0; i < nfile; i++)
670             {
671                 fprintf(fp, " %s", fnm[i].opt+1);
672             }
673             for (i = 0; i < npargs; i++)
674             {
675                 if ( (pa[i].type == etBOOL) && *(pa[i].u.b) )
676                 {
677                     fprintf(fp, " no%s", pa[i].option+1);
678                 }
679                 else
680                 {
681                     fprintf(fp, " %s", pa[i].option+1);
682                 }
683             }
684             fprintf(fp, ")/\"");
685             break;
686         case eshellBASH:
687             fprintf(fp, "if (( $COMP_CWORD <= 1 )) || [[ $c == -* ]]; then COMPREPLY=( $(compgen  -W '");
688             for (i = 0; i < nfile; i++)
689             {
690                 fprintf(fp, " -%s", fnm[i].opt+1);
691             }
692             for (i = 0; i < npargs; i++)
693             {
694                 if ( (pa[i].type == etBOOL) && *(pa[i].u.b) )
695                 {
696                     fprintf(fp, " -no%s", pa[i].option+1);
697                 }
698                 else
699                 {
700                     fprintf(fp, " -%s", pa[i].option+1);
701                 }
702             }
703             fprintf(fp, "' -- $c)); return 0; fi\n");
704             break;
705         case eshellZSH:
706             fprintf(fp, " -x 's[-]' -s \"");
707             for (i = 0; i < nfile; i++)
708             {
709                 fprintf(fp, " %s", fnm[i].opt+1);
710             }
711             for (i = 0; i < npargs; i++)
712             {
713                 if ( (pa[i].type == etBOOL) && *(pa[i].u.b) )
714                 {
715                     fprintf(fp, " no%s", pa[i].option+1);
716                 }
717                 else
718                 {
719                     fprintf(fp, " %s", pa[i].option+1);
720                 }
721             }
722             fprintf(fp, "\" ");
723             break;
724     }
725 }
726
727 static void write_cshcompl(FILE *out,
728                            int nfile,  t_filenm *fnm,
729                            int npargs, t_pargs *pa)
730 {
731     fprintf(out, "complete %s", ShortProgram());
732     pr_enums(out, npargs, pa, eshellCSH);
733     pr_fopts(out, nfile, fnm, eshellCSH);
734     pr_opts(out, nfile, fnm, npargs, pa, eshellCSH);
735     fprintf(out, "\n");
736 }
737
738 static void write_zshcompl(FILE *out,
739                            int nfile,  t_filenm *fnm,
740                            int npargs, t_pargs *pa)
741 {
742     fprintf(out, "compctl ");
743
744     /* start with options, since they are always present */
745     pr_opts(out, nfile, fnm, npargs, pa, eshellZSH);
746     pr_enums(out, npargs, pa, eshellZSH);
747     pr_fopts(out, nfile, fnm, eshellZSH);
748     fprintf(out, "-- %s\n", ShortProgram());
749 }
750
751 static void write_bashcompl(FILE *out,
752                             int nfile,  t_filenm *fnm,
753                             int npargs, t_pargs *pa)
754 {
755     /* Advanced bash completions are handled by shell functions.
756      * p and c hold the previous and current word on the command line.
757      * We need to use extended globbing, so write it in each completion file */
758     fprintf(out, "shopt -s extglob\n");
759     fprintf(out, "_%s_compl() {\nlocal p c\n", ShortProgram());
760     fprintf(out, "COMPREPLY=() c=${COMP_WORDS[COMP_CWORD]} p=${COMP_WORDS[COMP_CWORD-1]}\n");
761     pr_opts(out, nfile, fnm, npargs, pa, eshellBASH);
762     fprintf(out, "case \"$p\" in\n");
763
764     pr_enums(out, npargs, pa, eshellBASH);
765     pr_fopts(out, nfile, fnm, eshellBASH);
766     fprintf(out, "esac }\ncomplete -F _%s_compl %s\n", ShortProgram(), ShortProgram());
767 }
768
769 void write_man(const char *mantp,
770                const char *program,
771                int nldesc, const char **desc,
772                int nfile, t_filenm *fnm,
773                int npargs, t_pargs *pa,
774                int nbug, const char **bugs)
775 {
776     bool        bHidden = false;
777     int         npar;
778     t_pargs    *par;
779
780     t_linkdata *links;
781
782     links = init_linkdata();
783
784     const gmx::CommandLineHelpContext *context
785         = gmx::GlobalCommandLineHelpContext::get();
786     bool  bFileOpened = false;
787     FILE *out;
788     if (context != NULL)
789     {
790         out     = context->writerContext().outputFile().handle();
791         bHidden = context->showHidden();
792     }
793     else
794     {
795         char buf[256];
796         sprintf(buf, "%s.%s", program, mantp);
797         out         = gmx_fio_fopen(buf, "w");
798         bFileOpened = true;
799     }
800
801     if (bHidden)
802     {
803         npar = npargs;
804         par  = pa;
805     }
806     else
807     {
808         snew(par, npargs);
809         npar = 0;
810         for (int i = 0; i < npargs; i++)
811         {
812             if (!is_hidden(&pa[i]))
813             {
814                 par[npar] = pa[i];
815                 npar++;
816             }
817         }
818     }
819
820     if (strcmp(mantp, "nroff") == 0)
821     {
822         write_nroffman(out, context->moduleDisplayName(), nldesc, desc,
823                        nfile, fnm, npar, par, nbug, bugs, links);
824     }
825     if (strcmp(mantp, "help") == 0)
826     {
827         write_ttyman(out, program, nldesc, desc, nfile, fnm, npar, par, nbug, bugs, links);
828     }
829     if (strcmp(mantp, "html") == 0)
830     {
831         write_htmlman(out, program, nldesc, desc, nfile, fnm, npar, par, nbug, bugs, links);
832     }
833     if (strcmp(mantp, "completion-zsh") == 0)
834     {
835         write_zshcompl(out, nfile, fnm, npar, par);
836     }
837     if (strcmp(mantp, "completion-bash") == 0)
838     {
839         write_bashcompl(out, nfile, fnm, npar, par);
840     }
841     if (strcmp(mantp, "completion-csh") == 0)
842     {
843         write_cshcompl(out, nfile, fnm, npar, par);
844     }
845
846     if (bFileOpened)
847     {
848         gmx_fio_fclose(out);
849     }
850
851     if (!bHidden)
852     {
853         sfree(par);
854     }
855
856     finish_linkdata(links);
857 }
858
859 const char *get_arg_desc(int type)
860 {
861     static const char *argtp[etNR] = {
862         "int", "step", "real", "time", "string", "bool", "vector", "enum"
863     };
864     return argtp[type];
865 }