c56958363e2848cff26158f5a4ebc13284ecafd9
[alexxy/gromacs.git] / src / gmxlib / wman.c
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 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #include "string2.h"
40 #include "smalloc.h"
41 #include "sysstuff.h"
42 #include "filenm.h"
43 #include "macros.h"
44 #include "replace.h"
45 #include "wman.h"
46 #include "statutil.h"
47 #include "copyrite.h"
48 #include "strdb.h"
49 #include "time.h"
50 #include "readinp.h"
51
52 /* The source code in this file should be thread-safe. 
53          Please keep it that way. */
54
55
56 typedef struct {
57   const char *search,*replace;
58 } t_sandr_const;
59
60 typedef struct {
61   char *search,*replace;
62 } t_sandr;
63
64 const t_sandr_const sandrTeX[] = {
65   { "[TT]", "{\\tt " },
66   { "[tt]", "}"      },
67   { "[BB]", "{\\bf " },
68   { "[bb]", "}"      },
69   { "[IT]", "{\\em " },
70   { "[it]", "}"      },
71   { "[PAR]","\n\n"   },
72   /* Escaping underscore for LaTeX is no longer necessary, and it breaks
73    * text searching and the index if you do. */
74   /*
75   { "_",    "\\_"    },
76   */
77   { "$",    "\\$"    },
78   { "<=",   "\\ensuremath{\\leq{}}"},
79   { ">=",   "\\ensuremath{\\geq{}}"},
80   { "<",    "\\textless{}" },
81   { ">",    "\\textgreater{}" },
82   { "^",    "\\^{}"    },
83   { "\\^{}t", "\\ensuremath{^t}" },
84   { "\\^{}a", "\\ensuremath{^a}" },
85   { "\\^{}b", "\\ensuremath{^b}" },
86   { "\\^{}2", "\\ensuremath{^2}" },
87   { "\\^{}3", "\\ensuremath{^3}" },
88   { "\\^{}6", "\\ensuremath{^6}" },
89   { "#",    "\\#"    },
90   { "[BR]", "\\\\"   },
91   { "%",    "\\%"    },
92   { "&",    "\\&"    },
93   /* The next two lines used to substitute "|" and "||" to "or", but only
94    * g_angle used that functionality, so that was changed to a textual
95    * "or" there, so that other places could use those symbols to indicate
96    * magnitudes. */
97   { "||",    "\\textbar{}\\textbar"    },
98   { "|",     "\\textbar{}"    }
99 };
100 #define NSRTEX asize(sandrTeX)
101
102 const t_sandr_const sandrTty[] = {
103   { "[TT]", "" },
104   { "[tt]", "" },
105   { "[BB]", "" },
106   { "[bb]", "" },
107   { "[IT]", "" },
108   { "[it]", "" },
109   { "[PAR]","\n\n" },
110   { "[BR]", "\n"}
111 };
112 #define NSRTTY asize(sandrTty)
113
114 const t_sandr_const sandrWiki[] = {
115   { "&",    "&amp;" },
116   { "<",    "&lt;" },
117   { ">",    "&gt;" },
118   { "[TT]", "&lt;code&gt;" },
119   { "[tt]", "&lt;/code&gt;" },
120   { "[BB]", "'''" },
121   { "[bb]", "'''" },
122   { "[IT]", "''" },
123   { "[it]", "''" },
124   { "[PAR]","\n\n" },
125   { "[BR]", "\n"}
126 };
127 #define NSRWIKI asize(sandrWiki)
128
129 const t_sandr_const sandrNROFF[] = {
130   { "[TT]", "\\fB " },
131   { "[tt]", "\\fR" },
132   { "[BB]", "\\fB " },
133   { "[bb]", "\\fR" },
134   { "[IT]", "\\fI " },
135   { "[it]", "\\fR" },
136   { "[PAR]","\n\n" },
137   { "\n ",    "\n" },
138   { "<",    "" },
139   { ">",    "" },
140   { "^",    "" },
141   { "#",    "" },
142   { "[BR]", "\n"},
143   { "-",    "\\-"}
144 };
145 #define NSRNROFF asize(sandrNROFF)
146
147 const t_sandr_const sandrHTML[] = {
148   { "<",    "&lt;" },
149   { ">",    "&gt;" },
150   { "[TT]", "<tt>" },
151   { "[tt]", "</tt>" },
152   { "[BB]", "<b>" },
153   { "[bb]", "</b>" },
154   { "[IT]", "<it>" },
155   { "[it]", "</it>" },
156   { "[PAR]","<p>" },
157   { "[BR]", "<br>" }
158 };
159 #define NSRHTML asize(sandrHTML)
160
161 const t_sandr_const sandrXML[] = {
162   { "<",    "&lt;" },
163   { ">",    "&gt;" },
164   { "[TT]", "<arg>" },
165   { "[tt]", "</arg>" },
166   { "[BB]", "<emp>" },
167   { "[bb]", "</emp>" },
168   { "[IT]", "<it>" },
169   { "[it]", "</it>" },
170   { "[PAR]","</par>\n<par>" },
171   { "[BR]", "<br />" }
172 };
173 #define NSRXML asize(sandrXML)
174
175 static void mynum(char *buf,int n)
176 {
177   if (n >= 10)
178     sprintf(buf,"%2d",n);
179   else
180     sprintf(buf,"0%1d",n);
181 }
182
183 static char *mydate(char buf[], int maxsize,gmx_bool bWiki)
184 {
185   const char *mon[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", 
186                          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
187   const char *day[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
188   const char *num[] = { "01", "02", "03", "04", "05", "06","07", "08", "09" }; 
189   time_t now;
190   struct tm tm;
191   
192   time(&now);
193 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
194   /* Native windows */
195   localtime_s(&tm,&now);
196 #else
197   localtime_r(&now,&tm);
198 #endif
199
200   /* subtract one from maxsize, so we have room for \0. */
201   if (bWiki) {
202     char dd[8],mm[8],ss[8],hh[8],mn[8];
203     
204     mynum(dd,tm.tm_mday);
205     mynum(mm,tm.tm_mon);
206     mynum(ss,tm.tm_sec);
207     mynum(hh,tm.tm_hour);
208     mynum(mn,tm.tm_min);
209     sprintf(buf,"%4d-%2s-%2sT%2s:%2s:%2sZ",
210              tm.tm_year+1900,mm,dd,hh,mn,ss);
211   }
212   else
213     sprintf(buf,"%s %d %s %d",day[tm.tm_wday],tm.tm_mday,
214              mon[tm.tm_mon],tm.tm_year+1900);
215   
216   return buf;
217 }
218
219 /* Data structure for saved HTML links */
220 typedef struct t_linkdata {
221   int     nsr;
222   t_sandr *sr;
223 } t_linkdata;
224
225 static t_linkdata *init_linkdata()
226 {
227   t_linkdata *p;
228   snew(p,1);
229   p->sr=NULL;
230   p->nsr=0;
231
232   return p;
233 }
234
235 static void finish_linkdata(t_linkdata *p)
236 {
237   int i;
238   
239   for(i=0;i<p->nsr;i++) {
240     sfree(p->sr[i].search);    
241     sfree(p->sr[i].replace);
242   }
243   sfree(p->sr);
244   sfree(p);
245 }
246
247 static char *repall(const char *s,int nsr,const t_sandr_const sa[])
248 {
249   int  i;
250   char *buf1,*buf2;
251   
252   /* Copy input to a non-constant char buffer.
253    * buf1 is allocated here 
254    */
255   buf1=gmx_strdup(s); 
256   
257   for(i=0; (i<nsr); i++) {
258     /* Replace in buffer1, put result in buffer2.
259      * buf2 is allocated here.
260      */
261     buf2=replace(buf1,sa[i].search,sa[i].replace);
262     sfree(buf1);
263     buf1=buf2;
264   }
265   
266   return buf1;
267
268
269 static char *repallww(const char *s,int nsr,const t_sandr sa[])
270 {
271   int  i;
272   char *buf1,*buf2;
273
274   /* Copy input to a non-constant char buffer.
275    * buf1 is allocated here 
276    */
277   buf1=gmx_strdup(s); 
278   
279   for(i=0; (i<nsr); i++) {
280     /* Replace in buffer1, put result in buffer2.
281      * buf2 is allocated here.
282      */
283     buf2=replaceww(buf1,sa[i].search,sa[i].replace);
284     sfree(buf1);
285     buf1=buf2;
286   }
287   return buf1;
288 }
289
290 static char *html_xref(char *s,const char *program, t_linkdata *links,gmx_bool bWiki)
291 {
292   char   buf[256],**filestr;
293   int    i,j,n;
294   
295   if (links->sr == NULL) {
296     n=get_file("links.dat",&(filestr));
297     links->nsr=n;
298     snew(links->sr,n);
299     for(i=0,j=0; (i<n); i++) {
300       if (!program || (gmx_strcasecmp(program,filestr[i])  != 0)) {
301         links->sr[j].search=gmx_strdup(filestr[i]);
302         if (bWiki)
303           sprintf(buf,"[[%s]]",filestr[i]);
304         else
305           sprintf(buf,"<a href=\"%s.html\">%s</a>",filestr[i],filestr[i]);
306         links->sr[j].replace=gmx_strdup(buf);
307         j++;
308       }
309     }
310     links->nsr=j;
311     for(i=0;i<n;i++)
312       sfree(filestr[i]);
313     sfree(filestr);
314   }
315   return repallww(s,links->nsr,links->sr);
316 }
317
318 char *check_tex(const char *s)
319 {
320   return repall(s,NSRTEX,sandrTeX);
321 }
322
323 static char *check_nroff(const char *s)
324 {
325   return repall(s,NSRNROFF,sandrNROFF);
326 }
327
328 static char *check_wiki(const char *s,const char *program, t_linkdata *links)
329 {
330   char *buf;
331   
332   buf = repall(s,NSRWIKI,sandrWiki);
333   buf = html_xref(buf,program,links,TRUE);
334   
335   return buf;
336 }
337
338 static char *check_html(const char *s,const char *program, t_linkdata *links)
339 {
340   char *buf;
341   
342   buf = repall(s,NSRHTML,sandrHTML);
343   buf = html_xref(buf,program,links,FALSE);
344   
345   return buf;
346 }
347
348 #define NWR(s) check_wiki(s,program,links)
349 #define NSR(s) check_html(s,program,links)
350   
351 #define FLAG_SET(flag, mask) ((flag & mask) == mask)
352 char *fileopt(unsigned long flag,char buf[],int maxsize)
353 {
354   char tmp[256];
355   
356   if (FLAG_SET(flag, ffRW))
357     sprintf(tmp,"In/Out");
358   else if (FLAG_SET(flag, ffREAD))
359     sprintf(tmp,"Input");
360   else if (FLAG_SET(flag, ffWRITE))
361     sprintf(tmp,"Output");
362   else
363     sprintf(tmp,"Dunno");
364
365   if (FLAG_SET(flag, ffOPT)) {
366     strcat(tmp,", Opt");
367     if (FLAG_SET(flag, ffSET)) 
368       strcat(tmp,"!");
369     else
370       strcat(tmp,".");
371   }
372   if (FLAG_SET(flag, ffLIB))
373     strcat(tmp,", Lib.");
374   if (FLAG_SET(flag, ffMULT))
375     strcat(tmp,", Mult.");
376
377   sprintf(buf,"%s",tmp);
378   
379   return buf;
380 }
381
382 static void write_texman(FILE *out,const char *program,
383                          int nldesc,const char **desc,
384                          int nfile,t_filenm *fnm,
385                          int npargs,t_pargs *pa,
386                          int nbug,const char **bugs,
387                          t_linkdata *links)
388 {
389   int i;
390   char tmp[256];
391   
392   fprintf(out,"\\section{\\normindex{%s}}\\label{%s}\n\n",check_tex(program),check_tex(program));
393   
394   if (nldesc > 0)
395     for(i=0; (i<nldesc); i++) 
396       fprintf(out,"%s\n",check_tex(desc[i]));
397
398   if (nfile > 0) {
399     fprintf(out,"\\vspace{-2ex}\\begin{tabbing}\n");
400     fprintf(out,"\n{\\normalsize \\bf Files}\\nopagebreak\\\\\n");
401     fprintf(out,"{\\tt ~~~~~~~} \\= {\\tt ~~~~~~~~~~~~~~} \\= "
402             "~~~~~~~~~~~~~~~~~~~~~~ \\= \\nopagebreak\\kill\n");
403     for(i=0; (i<nfile); i++)
404       fprintf(out,"\\>{\\tt %s} \\'\\> {\\tt %s} \\' %s \\> "
405               "\\parbox[t]{0.55\\linewidth}{%s} \\\\\n",
406               check_tex(fnm[i].opt),check_tex(fnm[i].fns[0]),
407               check_tex(fileopt(fnm[i].flag,tmp,255)),
408               check_tex(ftp2desc(fnm[i].ftp)));
409     fprintf(out,"\\end{tabbing}\\vspace{-4ex}\n");
410   }
411   if (npargs > 0) {
412     fprintf(out,"\\vspace{-2ex}\\begin{tabbing}\n");
413     fprintf(out,"\n{\\normalsize \\bf Other options}\\nopagebreak\\\\\n");
414     fprintf(out,"{\\tt ~~~~~~~~~~} \\= vector \\= "
415             "{\\tt ~~~~~~~} \\= \\nopagebreak\\kill\n");
416     for(i=0; (i<npargs); i++) {
417       if (strlen(check_tex(pa_val(&(pa[i]),tmp,255))) <= 8)
418         fprintf(out,"\\> {\\tt %s} \\'\\> %s \\'\\> {\\tt %s} \\' "
419                 "\\parbox[t]{0.68\\linewidth}{%s}\\\\\n",
420                 check_tex(pa[i].option),argtp[pa[i].type],
421                 check_tex(pa_val(&(pa[i]),tmp,255)),
422                 check_tex(pa[i].desc));
423       else
424         fprintf(out,"\\> {\\tt %s} \\'\\> %s \\'\\>\\\\\n"
425                 "\\> \\'\\> \\'\\> {\\tt %s} \\' "
426                 "\\parbox[t]{0.7\\linewidth}{%s}\\\\\n",
427                 check_tex(pa[i].option),argtp[pa[i].type],
428                 check_tex(pa_val(&(pa[i]),tmp,255)),
429                 check_tex(pa[i].desc));
430     }
431     fprintf(out,"\\end{tabbing}\\vspace{-4ex}\n");
432   }
433   if (nbug > 0) {
434     fprintf(out,"\n");
435     fprintf(out,"\\begin{itemize}\n");
436     for(i=0; (i<nbug); i++)
437       fprintf(out,"\\item %s\n",check_tex(bugs[i]));
438     fprintf(out,"\\end{itemize}\n");
439   }
440 /*   fprintf(out,"\n\\newpage\n"); */
441 }
442
443 static void write_nroffman(FILE *out,
444                            const char *program,
445                            int nldesc,const char **desc,
446                            int nfile,t_filenm *fnm,
447                            int npargs,t_pargs *pa,
448                            int nbug,const char **bugs,
449                            t_linkdata *links)
450
451 {
452   int i;
453   char tmp[256];
454   
455   
456   fprintf(out,".TH %s 1 \"%s\" \"\" \"GROMACS suite, %s\"\n",program,mydate(tmp,255,FALSE),GromacsVersion());
457   fprintf(out,".SH NAME\n");
458   fprintf(out,"%s\n",program);
459   fprintf(out,".B %s\n",GromacsVersion());
460   
461   fprintf(out,".SH SYNOPSIS\n");
462   fprintf(out,"\\f3%s\\fP\n",program);
463
464   /* command line arguments */
465   if (nfile > 0) {
466     for(i=0; (i<nfile); i++)
467       fprintf(out,".BI \"%s\" \" %s \"\n",check_nroff(fnm[i].opt),
468               check_nroff(fnm[i].fns[0]));
469   }
470   if (npargs > 0) {
471     for(i=0; (i<npargs); i++)
472       if (pa[i].type == etBOOL)
473         fprintf(out,".BI \"\\-[no]%s\" \"\"\n",check_nroff(pa[i].option+1));
474       else
475         fprintf(out,".BI \"%s\" \" %s \"\n",check_nroff(pa[i].option),
476                 check_nroff(argtp[pa[i].type]));
477   }
478   
479   /* description */
480   if (nldesc > 0) {
481     fprintf(out,".SH DESCRIPTION\n");
482     for(i=0; (i<nldesc); i++) 
483       fprintf(out,"\\&%s\n",check_nroff(desc[i]));
484   }
485
486   /* FILES */
487   if (nfile > 0) {
488     fprintf(out,".SH FILES\n");
489     for(i=0; (i<nfile); i++)
490       fprintf(out,".BI \"%s\" \" %s\" \n.B %s\n %s \n\n",
491               check_nroff(fnm[i].opt),
492               check_nroff(fnm[i].fns[0]),
493               check_nroff(fileopt(fnm[i].flag,tmp,255)),
494               check_nroff(ftp2desc(fnm[i].ftp)));
495   }
496   
497   /* other options */
498   fprintf(out,".SH OTHER OPTIONS\n");
499   if ( npargs > 0 ) {
500     for(i=0; (i<npargs); i++) {
501       if (pa[i].type == etBOOL)
502         fprintf(out,".BI \"\\-[no]%s\"  \"%s\"\n %s\n\n",
503                 check_nroff(pa[i].option+1),
504                 check_nroff(pa_val(&(pa[i]),tmp,255)),
505                 check_nroff(pa[i].desc));
506       else
507         fprintf(out,".BI \"%s\"  \" %s\" \" %s\" \n %s\n\n",
508                 check_nroff(pa[i].option),
509                 check_nroff(argtp[pa[i].type]),
510                 check_nroff(pa_val(&(pa[i]),tmp,255)),
511                 check_nroff(pa[i].desc));
512     }
513   }
514
515   if (nbug > 0) {
516     fprintf(out,".SH KNOWN PROBLEMS\n");
517     for(i=0; (i<nbug); i++)
518       fprintf(out,"\\- %s\n\n",check_nroff(bugs[i]));
519   }
520
521   fprintf(out,".SH SEE ALSO\n.BR gromacs(7)\n\n");
522   fprintf(out,"More information about \\fBGROMACS\\fR is available at <\\fIhttp://www.gromacs.org/\\fR>.\n");
523
524 }
525
526 char *check_tty(const char *s)
527 {
528   return repall(s,NSRTTY,sandrTty);
529 }
530
531 void
532 print_tty_formatted(FILE *out, int nldesc, const char **desc,int indent,
533                     t_linkdata *links,const char *program,gmx_bool bWiki)
534 {
535   char *buf;
536   char *temp;
537   int buflen,i,j;
538
539   buflen = 80*nldesc;
540   snew(buf,buflen);
541   for(i=0; (i<nldesc); i++) {
542     if ((strlen(buf)>0) && 
543         (buf[strlen(buf)-1] !=' ') && (buf[strlen(buf)-1] !='\n'))
544       strcat(buf," ");
545     if (bWiki)
546       temp=NWR(desc[i]);
547     else
548       temp=check_tty(desc[i]);
549     if (strlen(buf) + strlen(temp) >= (size_t)(buflen-2)) {
550       buflen += strlen(temp);
551       srenew(buf,buflen);
552     }
553     strcat(buf,temp);
554     sfree(temp);
555   }
556   /* Make lines of at most 79 characters */
557   temp = wrap_lines(buf,78,indent,FALSE);
558   fprintf(out,"%s\n",temp);
559   sfree(temp);
560   sfree(buf);
561 }
562
563 static void write_ttyman(FILE *out,
564                          const char *program,
565                          int nldesc,const char **desc,
566                          int nfile,t_filenm *fnm,
567                          int npargs,t_pargs *pa,
568                          int nbug,const char **bugs,gmx_bool bHeader,
569                          t_linkdata *links)
570 {
571   int i;
572   char buf[256];
573   char *tmp;
574   
575   if (bHeader) {
576     fprintf(out,"%s\n\n",check_tty(program));
577     fprintf(out,"%s\n%s\n",GromacsVersion(),mydate(buf,255,FALSE));
578   }
579   if (nldesc > 0) {
580     fprintf(out,"DESCRIPTION\n-----------\n");
581     print_tty_formatted(out,nldesc,desc,0,links,program,FALSE);
582   }
583   if (nbug > 0) {
584     fprintf(out,"\n");
585     fprintf(out,"KNOWN PROBLEMS\n----------\n");
586     for(i=0; i<nbug; i++) {
587       snew(tmp,strlen(bugs[i])+3);
588       strcpy(tmp,"* ");
589       strcpy(tmp+2,check_tty(bugs[i]));
590       fprintf(out,"%s\n",wrap_lines(tmp,78,2,FALSE));
591       sfree(tmp);
592     }
593   }
594   if (nfile > 0) {
595     fprintf(out,"\n");
596     pr_fns(out,nfile,fnm);
597   }
598   if (npargs > 0) {
599     print_pargs(out,npargs,pa,FALSE);
600   }
601 }
602
603 static void pr_html_files(FILE *out,int nfile,t_filenm fnm[],
604                           const char *program,t_linkdata *links,gmx_bool bWiki)
605
606   int  i;
607   char link[10],tmp[255];
608   
609   if (bWiki)
610     fprintf(out," %-10s %-12s %-12s %-s\n"
611             " -----------------------------------------------------\n",
612             "Option","Filename","Type","Description");
613   else
614     fprintf(out,
615             "<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=2>\n"
616             "<TR>"
617             "<TH>option</TH>"
618             "<TH>filename</TH>"
619             "<TH>type</TH>"
620             "<TH>description</TH>"
621             "</TR>\n");
622   
623   for(i=0; (i<nfile); i++) {
624     strcpy(link,ftp2ext(fnm[i].ftp));
625     if (strcmp(link,"???")==0)
626       strcpy(link,"files");
627     if (bWiki)
628       fprintf(out," %-10s %-16s %-12s %-s\n",
629               fnm[i].opt,
630               NWR(fnm[i].fns[0]),
631               fileopt(fnm[i].flag,tmp,255),
632               NWR(ftp2desc(fnm[i].ftp)));
633     else
634       fprintf(out,
635               "<TR>"
636               "<TD ALIGN=RIGHT> <b><tt>%s</tt></b> </TD>"
637               "<TD ALIGN=RIGHT> <tt><a href=\"%s.html\">%12s</a></tt> </TD>"
638               "<TD> %s </TD>"
639               "<TD> %s </TD>"
640               "</TR>\n",
641               fnm[i].opt,link,fnm[i].fns[0],fileopt(fnm[i].flag,tmp,255),
642               NSR(ftp2desc(fnm[i].ftp)));
643   }
644   if (!bWiki)
645     fprintf(out,"</TABLE>\n");
646 }
647
648 static void write_wikiman(FILE *out,
649                           const char *program,
650                           int nldesc,const char **desc,
651                           int nfile,t_filenm *fnm,
652                           int npargs,t_pargs *pa,
653                           int nbug,const char **bugs,gmx_bool bHeader,
654                           t_linkdata *links)
655 {
656   int i;
657   char buf[256],link[10];
658   char *tmp,*tmp2;
659   fprintf(out,"<page>\n<title>Manual:%s_%s</title>\n",program,
660           VERSION);
661   fprintf(out,"<revision>\n");
662   fprintf(out,"<timestamp>%s</timestamp>\n",mydate(buf,255,TRUE));
663   fprintf(out,"<text xml:space=\"preserve\">\n");
664   if (nldesc > 0) {
665     fprintf(out,"== Description ==\n");
666     print_tty_formatted(out,nldesc,desc,0,links,program,TRUE);
667     fprintf(out,"\n");
668   }
669   if (nbug > 0) {
670     fprintf(out,"== Known Problems ==\n");
671     for(i=0; i<nbug; i++) {
672       snew(tmp,strlen(bugs[i])+3);
673       strcpy(tmp,"* ");
674       strcpy(tmp+2,bugs[i]);
675       fprintf(out,"%s\n",NWR(tmp));
676       sfree(tmp);
677     }
678   }
679   if (nfile > 0) {
680     fprintf(out,"\n== Files ==\n");
681     pr_html_files(out,nfile,fnm,program,links,TRUE);
682   }
683   if (npargs > 0) {
684     fprintf(out,"\n== Options ==\n");
685     fprintf(out," %-12s %-6s %-6s  %-s\n",
686             "Option","Type","Value","Description");
687     fprintf(out," ------------------------------------------------------\n");
688     for(i=0; (i<npargs); i++) {
689       tmp = NWR(pargs_print_line(&pa[i],TRUE));
690       fprintf(out,"%s",tmp);
691       sfree(tmp);
692     }
693   }
694   fprintf(out,"[[category:Manual_Pages_%s|%s]]\n",VERSION,program);
695   fprintf(out,"</text>\n");
696   fprintf(out,"</revision>\n");
697   fprintf(out,"</page>\n\n");
698 }
699
700 static void write_htmlman(FILE *out,
701                           const char *program,
702                           int nldesc,const char **desc,
703                           int nfile,t_filenm *fnm,
704                           int npargs,t_pargs *pa,
705                           int nbug,const char **bugs,
706                           t_linkdata *links)
707 {
708   int i;
709   char link[10],tmp[255];
710   
711   fprintf(out,"<HTML>\n<HEAD>\n<TITLE>%s</TITLE>\n",program);
712   fprintf(out,"<LINK rel=stylesheet href=\"style.css\" type=\"text/css\">\n");
713   fprintf(out,"<BODY text=\"#000000\" bgcolor=\"#FFFFFF\" link=\"#0000FF\" vlink=\"#990000\" alink=\"#FF0000\">\n");
714   fprintf(out,"<TABLE WIDTH=\"98%%\" NOBORDER >\n<TR><TD WIDTH=400>\n");
715   fprintf(out,"<TABLE WIDTH=400 NOBORDER>\n<TD WIDTH=116>\n");
716   fprintf(out,"<a href=\"http://www.gromacs.org/\">"
717           "<img SRC=\"../images/gmxlogo_small.png\""
718           "BORDER=0 </a></td>\n");
719   fprintf(out,"<td ALIGN=LEFT VALIGN=TOP WIDTH=280>"
720           "<br><h2>%s</h2>",program);
721   fprintf(out,"<font size=-1><A HREF=\"../online.html\">Main Table of Contents</A></font><br>");
722   fprintf(out,"<br></td>\n</TABLE></TD><TD WIDTH=\"*\" ALIGN=RIGHT VALIGN=BOTTOM><p><B>%s<br>\n",GromacsVersion());
723   fprintf(out,"%s</B></td></tr></TABLE>\n<HR>\n",mydate(tmp,255,FALSE));
724   
725   if (nldesc > 0) {
726     fprintf(out,"<H3>Description</H3>\n<p>\n");
727     for(i=0; (i<nldesc); i++) 
728       fprintf(out,"%s\n",NSR(desc[i]));
729   }
730   if (nfile > 0) {
731     fprintf(out,"<P>\n");
732     fprintf(out,"<H3>Files</H3>\n");
733     pr_html_files(out,nfile,fnm,program,links,FALSE);
734   }
735   if (npargs > 0) {
736     fprintf(out,"<P>\n");
737     fprintf(out,"<H3>Other options</H3>\n");
738     fprintf(out,
739             "<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=2>\n"
740             "<TR>"
741             "<TH>option</TH>"
742             "<TH>type</TH>"
743             "<TH>default</TH>"
744             "<TH>description</TH>"
745             "</TR>\n");
746     for(i=0; (i<npargs); i++)
747       fprintf(out,
748               "<TR>"
749               "<TD ALIGN=RIGHT> <b><tt>%s%s</tt></b> </TD>"
750               "<TD ALIGN=RIGHT> %s </TD>"
751               "<TD ALIGN=RIGHT> <tt>%s</tt> </TD>"
752               "<TD> %s </TD>"
753               "</TD>\n",
754               (pa[i].type == etBOOL)?"-[no]":"-",pa[i].option+1,
755               argtp[pa[i].type],pa_val(&(pa[i]),tmp,255),NSR(pa[i].desc));
756     fprintf(out,"</TABLE>\n");
757   }
758   if (nbug > 0) {
759     fprintf(out,"<P>\n");
760     fprintf(out,"<H3>Known problems</H3>\n");
761     fprintf(out,"<UL>\n");
762     for(i=0; (i<nbug); i++)
763       fprintf(out,"<LI>%s\n",NSR(bugs[i]));
764     fprintf(out,"</UL>\n");
765   }
766   fprintf(out,"<P>\n");
767   fprintf(out,"<hr>\n<div ALIGN=RIGHT>\n");
768   fprintf(out,"<font size=\"-1\"><a href=\"http://www.gromacs.org\">"
769           "http://www.gromacs.org</a></font><br>\n");
770   fprintf(out,"<font size=\"-1\"><a href=\"mailto:gromacs@gromacs.org\">"
771           "gromacs@gromacs.org</a></font><br>\n");
772   fprintf(out,"</div>\n");
773   fprintf(out,"</BODY>\n");
774 }
775
776 char *check_xml(const char *s,const char *program,t_linkdata *links)
777 {
778   char *buf;
779   
780   buf=repall(s,NSRXML,sandrXML);
781   buf=html_xref(buf,program,links,FALSE);       /* the same in html and xml */
782   
783   return buf;
784 }
785
786 static void write_xmlman(FILE *out,
787                          const char *program,
788                          int nldesc,const char **desc,
789                          int nfile,t_filenm *fnm,
790                          int npargs,t_pargs *pa,
791                          int nbug,const char **bugs,
792                          t_linkdata *links)
793 {
794   int i;
795   char link[10],buf[256],opt[10];
796
797 #define NSR2(s) check_xml(s,program,links)
798 #define FLAG(w,f) (((w) & (f))==(f)) 
799
800   fprintf(out,"<gromacs-manual version=\"%s\" date=\"%s\" www=\"http://www.gromacs.org\">\n",GromacsVersion(),mydate(buf,255,FALSE));
801   /* fprintf(out,"<LINK rel=stylesheet href=\"style.css\" type=\"text/css\">\n"); */
802
803   fprintf(out,"<program name=\"%s\">",program);  
804   if (nldesc > 0) {
805     fprintf(out,"\n<description>\n<par>\n");
806     for(i=0; (i<nldesc); i++) 
807       fprintf(out,"%s\n",NSR2(desc[i]));
808   }
809   fprintf(out,"</par>\n</description>\n");
810
811   if (nfile > 0) {
812     fprintf(out,"\n<files>\n");
813     for(i=0; (i<nfile); i++) {
814       strcpy(link,ftp2ext(fnm[i].ftp));
815       if (strcmp(link,"???")==0)
816         strcpy(link,"files");
817         if (fnm[i].opt[0]=='-') strcpy(opt,fnm[i].opt+1);
818         else strcpy(opt,fnm[i].opt);
819       fprintf(out,
820               "<file type=\"%s\" typeid=\"%d\">\n"
821               "\t<flags read=\"%d\" write=\"%d\" optional=\"%d\"/>\n"
822               "\t<option>%s</option>\n"
823               "\t<default-name link=\"%s.html\">%s</default-name>\n"
824               "\t<description>%s</description>\n"
825               "</file>\n",
826               ftp2defnm(fnm[i].ftp),    /* from gmxlib/filenm.c */
827               fnm[i].ftp,
828               FLAG(fnm[i].flag,ffREAD), FLAG(fnm[i].flag,ffWRITE), FLAG(fnm[i].flag,ffOPT), 
829               opt,link,fnm[i].fn,/*fileopt(fnm[i].flag),*/
830               NSR(ftp2desc(fnm[i].ftp)));
831     }
832     fprintf(out,"</files>\n");
833   }
834
835   if (npargs > 0) {
836     fprintf(out,"\n<options>\n");
837     for(i=0; (i<npargs); i++)
838       fprintf(out,
839               "<option type=\"%s\" hidden=\"%d\">\n"
840               "\t<name >%s</name>\n"
841               "\t<default-value>%s</default-value>\n"
842               "\t<description>%s</description>\n"
843               "</option>\n",
844               argtp[pa[i].type], is_hidden(&pa[i]),
845               pa[i].option+1,                  /* +1 - with no trailing '-' */
846               pa_val(&(pa[i]),buf,255),pa[i].desc); /*argtp[pa[i].type],*/
847     fprintf(out,"</options>\n");
848   }
849
850   if (nbug > 0) {
851     fprintf(out,"\n<bugs>\n");
852     for(i=0; (i<nbug); i++)
853       fprintf(out,"\t<bug>%s</bug>\n",NSR(bugs[i]));
854     fprintf(out,"</bugs>\n");
855   }
856   fprintf(out,"\n</program>\n</gromacs-manual>\n");
857 #undef FLAG  
858 }
859
860 static void pr_opts(FILE *fp, 
861                     int nfile,  t_filenm *fnm, 
862                     int npargs, t_pargs pa[], int shell)
863 {
864   int i;
865   
866   switch (shell) {
867   case eshellCSH:
868     fprintf(fp," \"c/-/(");
869     for (i=0; i<nfile; i++)
870       fprintf(fp," %s",fnm[i].opt+1);
871     for (i=0; i<npargs; i++)
872       if ( (pa[i].type==etBOOL) && *(pa[i].u.b) )
873         fprintf(fp," no%s",pa[i].option+1);
874       else
875         fprintf(fp," %s",pa[i].option+1);
876     fprintf(fp,")/\"");
877     break;
878   case eshellBASH:
879     fprintf(fp,"if (( $COMP_CWORD <= 1 )) || [[ $c == -* ]]; then COMPREPLY=( $(compgen  -W '");
880     for (i=0; i<nfile; i++)
881       fprintf(fp," -%s",fnm[i].opt+1);
882     for (i=0; i<npargs; i++)
883       if ( (pa[i].type==etBOOL) && *(pa[i].u.b) )
884         fprintf(fp," -no%s",pa[i].option+1);
885       else
886         fprintf(fp," -%s",pa[i].option+1);
887     fprintf(fp,"' -- $c)); return 0; fi\n");
888     break;
889   case eshellZSH:
890     fprintf(fp," -x 's[-]' -s \"");
891     for (i=0; i<nfile; i++)
892       fprintf(fp," %s",fnm[i].opt+1);
893     for (i=0; i<npargs; i++)
894       if ( (pa[i].type==etBOOL) && *(pa[i].u.b) )
895         fprintf(fp," no%s",pa[i].option+1);
896       else
897         fprintf(fp," %s",pa[i].option+1);
898     fprintf(fp,"\" ");
899     break;
900   }
901 }
902
903 static void write_cshcompl(FILE *out,
904                            int nfile,  t_filenm *fnm,
905                            int npargs, t_pargs *pa)
906 {
907   fprintf(out,"complete %s",ShortProgram());
908   pr_enums(out,npargs,pa,eshellCSH);
909   pr_fopts(out,nfile,fnm,eshellCSH);
910   pr_opts(out,nfile,fnm,npargs,pa,eshellCSH);
911   fprintf(out,"\n");
912 }
913
914 static void write_zshcompl(FILE *out,
915                            int nfile,  t_filenm *fnm,
916                            int npargs, t_pargs *pa)
917 {
918   fprintf(out,"compctl ");
919
920   /* start with options, since they are always present */
921   pr_opts(out,nfile,fnm,npargs,pa,eshellZSH);
922   pr_enums(out,npargs,pa,eshellZSH);
923   pr_fopts(out,nfile,fnm,eshellZSH);
924   fprintf(out,"-- %s\n",ShortProgram());
925 }
926
927 static void write_bashcompl(FILE *out,
928                             int nfile,  t_filenm *fnm,
929                             int npargs, t_pargs *pa)
930 {
931   /* Advanced bash completions are handled by shell functions.
932    * p and c hold the previous and current word on the command line.
933    * We need to use extended globbing, so write it in each completion file */
934   fprintf(out,"shopt -s extglob\n");
935   fprintf(out,"_%s_compl() {\nlocal p c\n",ShortProgram());
936   fprintf(out,"COMPREPLY=() c=${COMP_WORDS[COMP_CWORD]} p=${COMP_WORDS[COMP_CWORD-1]}\n");
937   pr_opts(out,nfile,fnm,npargs,pa,eshellBASH);
938   fprintf(out,"case \"$p\" in\n");
939   
940   pr_enums(out,npargs,pa,eshellBASH);
941   pr_fopts(out,nfile,fnm,eshellBASH);
942   fprintf(out,"esac }\ncomplete -F _%s_compl %s\n",ShortProgram(),ShortProgram());
943 }
944
945 static void write_py(FILE *out,const char *program,
946                      int nldesc,const char **desc,
947                      int nfile,t_filenm *fnm,
948                      int npargs,t_pargs *pa,
949                      int nbug,const char **bugs,
950                      t_linkdata *links)
951 {
952   gmx_bool bHidden;
953   const char *cls = program;
954   char *tmp;
955   int  i,j;
956
957   /* Header stuff */  
958   fprintf(out,"#!/usr/bin/python\n\nfrom GmxDialog import *\n\n");
959   
960   /* Class definition */
961   fprintf(out,"class %s:\n",cls);
962   fprintf(out,"    def __init__(self,tk):\n");
963   
964   /* Help text */
965   fprintf(out,"        %s_help = \"\"\"\n",cls);
966   fprintf(out,"        DESCRIPTION\n");
967   print_tty_formatted(out,nldesc,desc,8,links,program,FALSE);
968   if (nbug > 0) {
969     fprintf(out,"\n        BUGS and PROBLEMS\n");
970     for(i=0; i<nbug; i++) {
971       snew(tmp,strlen(bugs[i])+3);
972       strcpy(tmp,"* ");
973       strcpy(tmp+2,check_tty(bugs[i]));
974       fprintf(out,"%s\n",wrap_lines(tmp,78,10,TRUE));
975       sfree(tmp);
976     }
977   }
978   fprintf(out,"        \"\"\"\n\n        # Command line options\n");
979   /* File options */
980   fprintf(out,"        flags = []\n");
981   for(i=0; (i<nfile); i++) 
982     fprintf(out,"        flags.append(pca_file('%s',\"%s\",0,%d))\n",
983             ftp2ext_generic(fnm[i].ftp),fnm[i].opt ? fnm[i].opt : "k",
984             is_optional(&(fnm[i])));
985             
986             
987   /* Other options */
988   for(i=0; (i<npargs); i++) {
989     switch(pa[i].type) {
990     case etINT:
991       fprintf(out,"        flags.append(pca_int(\"%s\",\"%s\",%d,%d))\n",
992               pa[i].option,pa[i].desc,*pa[i].u.i,is_hidden(&(pa[i])));
993       break;
994     case etREAL:
995     case etTIME:
996       fprintf(out,"        flags.append(pca_float(\"%s\",\"%s\",%f,%d))\n",
997               pa[i].option,pa[i].desc,*pa[i].u.r,is_hidden(&(pa[i])));
998       break;
999     case etSTR:
1000     case etBOOL:
1001       fprintf(out,"        flags.append(pca_gmx_bool(\"%s\",\"%s\",%d,%d))\n",
1002               pa[i].option,pa[i].desc,*pa[i].u.b,is_hidden(&(pa[i])));
1003       break;
1004     case etRVEC:
1005       fprintf(stderr,"Sorry, no rvecs yet...\n");
1006       break;
1007     case etENUM:
1008       fprintf(out,"        flags.append(pca_enum(\"%s\",\"%s\",\n",
1009               pa[i].option,pa[i].desc);
1010       fprintf(out,"        ['%s'",pa[i].u.c[1]);
1011       for(j=2; (pa[i].u.c[j] != NULL); j++)
1012         fprintf(out,",'%s'",pa[i].u.c[j]);
1013       fprintf(out,"],%d))\n",is_hidden(&(pa[i])));
1014     default:
1015       break;
1016     }
1017   }
1018     
1019   /* Make the dialog box */
1020   fprintf(out,"        gmxd = gmx_dialog(tk,\"%s\",flags,%s_help)\n\n",
1021           cls,cls);
1022           
1023   /* Main loop */
1024   fprintf(out,"#####################################################\n");
1025   fprintf(out,"tk     = Tk()\n");
1026   fprintf(out,"my%s = %s(tk)\n",cls,cls);
1027   fprintf(out,"tk.mainloop()\n");
1028 }
1029
1030 void write_man(FILE *out,const char *mantp,
1031                const char *program,
1032                int nldesc,const char **desc,
1033                int nfile,t_filenm *fnm,
1034                int npargs,t_pargs *pa,
1035                int nbug,const char **bugs,
1036                gmx_bool bHidden)
1037 {
1038   const char *pr;
1039   int     i,npar;
1040   t_pargs *par;
1041  
1042   t_linkdata *links;
1043   
1044   links=init_linkdata();
1045   
1046   /* Don't write hidden options to completions, it just
1047    * makes the options more complicated for normal users
1048    */
1049
1050   if (bHidden) {
1051     npar=npargs;
1052     par=pa;
1053   }
1054   else {
1055     snew(par,npargs);
1056     npar=0;
1057     for(i=0;i<npargs;i++)
1058       if (!is_hidden(&pa[i])) {
1059         par[npar]=pa[i];
1060         npar++;
1061       }
1062   }
1063   
1064   if ((pr=strrchr(program,DIR_SEPARATOR)) == NULL)
1065     pr=program;
1066   else
1067     pr+=1;
1068   if (strcmp(mantp,"tex")==0)
1069     write_texman(out,pr,nldesc,desc,nfile,fnm,npar,par,nbug,bugs,links);
1070   if (strcmp(mantp,"nroff")==0)
1071     write_nroffman(out,pr,nldesc,desc,nfile,fnm,npar,par,nbug,bugs,links);
1072   if (strcmp(mantp,"ascii")==0)
1073     write_ttyman(out,pr,nldesc,desc,nfile,fnm,npar,par,nbug,bugs,TRUE,links);
1074   if (strcmp(mantp,"wiki")==0)
1075     write_wikiman(out,pr,nldesc,desc,nfile,fnm,npar,par,nbug,bugs,TRUE,links);
1076   if (strcmp(mantp,"help")==0)
1077     write_ttyman(out,pr,nldesc,desc,nfile,fnm,npar,par,nbug,bugs,FALSE,links);
1078   if (strcmp(mantp,"html")==0)
1079     write_htmlman(out,pr,nldesc,desc,nfile,fnm,npar,par,nbug,bugs,links);
1080   if (strcmp(mantp,"py")==0)
1081     write_py(out,pr,nldesc,desc,nfile,fnm,npar,par,nbug,bugs,links);
1082   if (strcmp(mantp,"xml")==0)
1083     write_xmlman(out,pr,nldesc,desc,nfile,fnm,npargs,pa,nbug,bugs,links);       
1084   if (strcmp(mantp,"completion-zsh")==0)
1085     write_zshcompl(out,nfile,fnm,npar,par);
1086   if (strcmp(mantp,"completion-bash")==0)
1087     write_bashcompl(out,nfile,fnm,npar,par);
1088   if (strcmp(mantp,"completion-csh")==0)
1089     write_cshcompl(out,nfile,fnm,npar,par);
1090
1091   if (!bHidden)
1092     sfree(par);
1093
1094   finish_linkdata(links);
1095 }
1096