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