delete the AliSurvey objs after use
[u/mrichter/AliRoot.git] / share / mangen
1 #!/bin/sh
2 #
3 # mangen - generate manual entries for library
4 #
5 # modification history
6 # 02g,16jul93,abh   Added compatibility for FORTRAN "C" style comments. See 
7 #                   STAR programming guidelines for template.
8 # 02f,08may90,jdi   nroff lines: took out colrm, added tbl and -Tlp.
9 # 02e,12mar90,jdi   made NOMANUAL work for module entries;
10 #                   added CS/CE macros to routine declarations in lib synopsis.
11 # 02d,25jan90,rbr   works with "#!/bin/awk -f" and the like
12 # 02c,10apr89,dnw   changed to always put individual routine manual entries in
13 #                     chapter 2 instead of in (summary chapter + 1), so driver
14 #                     routines end up in 2 rather than 4.
15 # 02b,05apr89,dnw   removed NOT_GENERIC filter
16 #                   added removing of mg.out and mgr.out before starting
17 # 02a,05nov87,jlf   changed to allow mangen'ing of scripts
18 #                   changed so routine definitions that don't fit on one
19 #                      one line, have a '...' appended in synopses.
20 #                   changed documentation format so mangen can be mangen'ed.
21 #
22 #
23 # SYNOPSIS
24 # mangen [-d] [-n] [-l] chapter file
25 #
26 # DESCRIPTION
27 # generates:    <name>.<chapter#>  (manual entry for module)
28 # and if "-l":  <name>.<chapter#+1> (manual entries for each routine)
29 #
30 # where <name> is the "root" of the "tail" of the specified file
31 # (i.e. if file="/usr/dave/gronk.c", then name="gronk");
32 # and <chapter#> is the single digit chapter number
33 # (i.e. just the specified chapter number if one was given,
34 # or the number from the table below if a chapter name was given).
35 #
36 # <chapter> can be any digit or any of the following chapter abbreviations:
37 #
38 #  #  abbr   name        what
39 #  =  ====   =========== ====================================
40 #  0  con*  
41 #     over*  conventions - conventions and overview material
42 #  1  lib*   libraries   - subroutine library summaries
43 #  2         routines    - individual library routines
44 #  3  task*
45 #     tsk*
46 #     dr*    drivers     - tasks and drivers
47 #  4  tool*  tools       - Unix development/maintenence tools
48 #
49 # NOTE: Specifying the chapter as "lib" automatically selects the -l option.
50 #
51 # "-l" flag causes a special library module style manual entry to be created.
52 # The manual entry for a library has a specially constructed synopsis section
53 # that contains the titles and calling sequence of each routine in the library.
54 # Also a seperate manual entry is generated for each of the routines in the
55 # library.  These routine manual entries will be put in a file named libxxx.2.
56 #
57 # "-d" flag causes the intermediate nroff source files to NOT be deleted.
58 # These are called "mg.out" and "mgr.out" for the module manual entry
59 # and individual routine entries (only if -l option specified), respectively.
60 # This option is useful for debugging manual entries that don't look the
61 # way you expected.
62 #
63 # "-n" flag causes nroff sources not to be deleted, and not to be nroffed
64 # either.  In this case, "mg.out" (and "mgr.out") will be the ONLY output
65 # from mangen.
66 #
67 # EXAMPLE:
68 #       % mangen lib /usr/vw/lib/lstlib.c
69 # will create "lstlib.1" and "liblst.2" in the current directory.
70 #C<
71
72 trap "rm -f mg.out mgr.out /tmp/mangen$$; exit" 1 2 3 15
73
74 rm -f mg.out mgr.out            # start with a clean slate
75
76 # set home to directory that contains this script
77
78 home=`expr $0 : '\(.*/\)[^/]' '|' ./`
79
80 dontdelete=0
81 dontnroff=0
82 lib=0
83 chapter=0
84
85 while (test $# -gt 1)
86 do
87     case "$1" in
88         -d)             dontdelete=1 ;;
89         -l)             lib=1 ;;
90         -n)             dontdelete=1; dontnroff=1 ;;
91         [0-9])          chapter=$1 ;;
92         con* | over*)   chapter=0 ;;
93         lib*)           chapter=1; lib=1 ;;
94         task* | tsk* | dr*) chapter=3 ;;
95         tool*)          chapter=4 ;;
96         *)              echo "flag not recognized:" $1; exit 1 ;;
97         esac
98     shift
99 done
100
101 # remove path
102
103 name=`basename $1`
104
105 # remove trailing component, eg. ".xx"
106
107 section=`expr $name : '\(.*\)\..*' '|' $name`
108
109 # create awk program found at end of this script, and
110 # make substitutions in the awk program source
111
112 awk '/^#START_AWK$/,/^#STOP_AWK$/' <$0 | \
113 sed -e "s^\%filename^$name^g" \
114     -e "s/\%chapter/$chapter/g" \
115     -e "s/\%lib/$lib/" \
116     >/tmp/mangen$$
117
118 # generate the nroff source of the manual entries
119
120 awk -f /tmp/mangen$$ <$1
121
122 rm /tmp/mangen$$
123
124 # nroff them unless -n option
125
126 if (test $dontnroff -eq 0) then
127         #tbl mg.out | nroff -man -Tman  >$section.$chapter
128         #tbl mg.out | nroff -man -Tlp >$section.$chapter
129         #tbl mg.out | nroff -mangen -Tlp  >$section.$chapter
130         tbl mg.out | nroff >$section.$chapter
131 else
132         mv mg.out $section.$chapter
133 fi
134
135 if (test $lib -eq 1) then
136     if (test $dontnroff -eq 0) then
137         #tbl mgr.out | nroff -man -Tman  >$section.2
138         #tbl mgr.out | nroff -mangen -Tlp  >$section.2
139         tbl mgr.out | nroff >$section.2
140     else
141         mv mgr.out $section.2
142     fi
143 fi
144 # delete the nroff source, unless -d or -n option
145
146 if (test $dontdelete -eq 0) then
147     rm -f mg.out mgr.out
148 fi
149
150 exit 0
151
152 #START_AWK
153
154 # mangen.awk - awk program to generate manual entries
155
156 # the variable "s" holds the current state of the scan:
157 #
158 #   title  - get title line (initial state
159 #   mh0    - skip to start of modification history
160 #   mh     - skip to end of modification history
161 #   desc0  - skip to start of module description
162 #   desc   - process module description
163 #   
164 # the following additional states are used if the "lib" flag is specified:
165 #
166 #   rtn    - skip to start of next routine
167 #   rtitle - skip to, and process, routine title line
168 #   rdesc  - skip to, and process, routine description
169 #   rsy0   - skip to start of routine synopsis
170 #   rsy    - process routine synopsis
171
172
173 BEGIN           {
174                 blanks = "                                            "
175
176                 # the following values preceded by a "%" are substituted
177                 # for by a "sed" program
178
179                 filename = "%filename"  # source filename
180                 chapter = %chapter      # chapter number
181                 lib = %lib              # 1 = make routine entries, 0 = don't
182
183                 # initialize
184
185                 dbg = 0                 # 1 = output debug stuff
186                 s = "title"             # initial state
187
188                 # get module name w/o the extension and the output file names
189
190                 dot = index (filename, ".")
191
192                 if (dot == 0)
193                     modname = filename
194                 else
195                     modname = substr (filename, 1, dot - 1)
196
197                 outfile = "mg.out"
198                 rtnfile = "mgr.out"
199                 }
200
201 dbg == 1        {
202                 print s "\n" $0 >outfile
203                 }
204
205 # ignore lint directive lines
206
207 /LINTLIBRARY/   {next}
208 /ARGSUSED/      {next}
209 /VARARGS/       {next}
210
211 # get ss = line without  leading '/* ' or '* ' or '# ' and trailing '*/'
212 #     subhead  = subheading (all caps at beginning of line w/ optional ':')
213 #     subheadl = remainder of subheading line following ':'
214
215                 {
216                 # detab line
217
218                 nf = split ($0, words, "\t")
219
220                 if (nf == 0)
221                     l = ""
222                 else
223                     {
224                     l = words[1]
225
226                     for (i = 2; i <= nf; i++)
227                         l = l substr("        ", 1, 8-(length(l) % 8)) words[i]
228                     }
229
230                 # strip off leading and trailing comment indicators
231
232                 if ((l ~ /^C>/) || (l ~ /^\/\*/))
233                     {
234                     if ((l ~ /^C> /) || (l ~ /^\/\* /))
235                         start = 4
236                     else
237                         start = 3
238                     }
239                 else if ((l ~ /^C/) || (l ~ /^\*/))
240                     {
241                     if ((l ~ /^C /) || (l ~ /^\* /))
242                         start = 3
243                     else
244                         start = 2
245                     }
246                 else if (l ~ /^\#/)
247                     {
248                     if (l ~ /^\# /)
249                         start = 3
250                     else
251                         start = 2
252                     }
253                 else
254                     start = 1
255
256                 end = length (l)
257
258                 if ((l ~ /C<$/) || (l ~ /\*\/$/))
259                     end = end - 2
260
261                 ss = substr (l, start, end - start + 1)
262
263
264                 # check for sub heading line
265
266                 if ((ss !~ /^[A-Z][^a-z]*:/) && \
267                     (ss !~ /^[A-Z][^a-z]*$/))
268                     subhead = ""
269                 else
270                     {
271                     colon = index (ss, ":")
272
273                     if (colon == 0)
274                         {
275                         subhead = ss
276                         subheadl = ""
277                         }
278                     else
279                         {
280                         subhead = substr (ss, 1, colon - 1)
281
282                         subheadl = substr (ss, colon + 2)
283                         if (subheadl ~ /^ *$/)
284                             subheadl = ""
285                         }
286                     }
287                 }
288
289 # get module name and title: 1st line in file
290
291 s == "title"    {
292                 # This gets rid of .yacc first lines ("%{"), and the first
293                 # line or two of a script ("#!/bin/sh", etc.).
294
295                 if (NF == 1 || index($1, "#!"))
296                     next
297
298                 # check that title matches module name
299
300                 dot = index ($2, ".")
301                 if (dot == 0)
302                     titlename = $2
303                 else
304                     titlename = substr (ss, 1, dot - 1)
305
306                 if (titlename != modname)
307                     {
308                     print "ERROR: on line " NR \
309                           ": module name inconsistent w/ file name."
310                     exit
311                     }
312
313                 title = ss
314
315                 s = "mh0"
316                 next
317                 }
318
319 # skip modification history: skip, looking for 'modification history' then blank
320
321 s == "mh0"      {
322                 if (l ~ /modification history/)
323                     s = "mh"
324                 next
325                 }
326
327 s == "mh"       {
328                 if (ss ~ /^ *$/)
329                     {
330                     s = "desc0"
331                     xdesc = 0
332                     }
333                 next
334                 }
335
336 # get module description: ignore leading blank lines; turn capital lines
337 #       into subheadings; accumulate rest looking for '*/'
338
339 s == "desc0"    {
340                 if (l !~ /^ *$/)
341                     {
342                     ignore = 0
343                     s = "desc"
344                     }
345                 }
346
347 s == "desc"     {
348                 # suppress manual entry if NOMANUAL specified
349
350                 if (l ~ /NO[ _-]?MANUAL/)
351                     {
352                     ignorelib = 1
353                     }
354
355                 # check for end of description section
356
357                 if ((l ~ /^\#*C</) || (l ~ /^\#*\*\//))
358                     {
359                     if (lib == 0)
360                         exit
361                     else
362                         {
363                         s = "rtn"
364                         next
365                         }
366                     }
367
368
369                 # check for description section missing entirely
370
371                 if ((l ~ /-----------------------------/) || (l ~ /\*\*\*\*\*\*\*\*\*\*/))
372                     {
373                     print "ERROR: on line " NR ": module description missing."
374                     exit
375                     }
376
377
378                 # skip leading blank lines
379
380                 if ((xdesc == 0) && (ss ~ /^ *$/))
381                     next
382
383
384                 # check for subheading line and accumulate description
385
386                 if (subhead == "")
387                     {
388                     if (!ignore)
389                         desc[++xdesc] = ss
390                     }
391                 else
392                     {
393                     if (subhead ~ /^INTERNAL/)
394                         ignore = 1
395                     else
396                         {
397                         desc[++xdesc] = ".SH " subhead
398                         if (subheadl != "")
399                             desc[++xdesc] = subheadl
400                         ignore = 0
401                         }
402                     }
403
404                 next
405                 }
406
407 # skip to routine start: skip looking for '**********'
408
409 s == "rtn"      {
410                 if ((l ~ /--------------------------/) || (l ~ /\*\*\*\*\*\*\*\*\*\*/))
411                     { rtitle = ""; rnm = ""; xrdesc = 0; xrsy = 0; s = "rtitle" }
412                 next
413                 }
414
415 # get routine title: skip looking for 1st non-blank line
416
417 s == "rtitle"   {
418                 if (ss !~ /^ *$/)
419                     { rtitle = ss; rnm = $2; ignore = 0; s = "rdesc" }
420                 next
421                 }
422
423 # get routine description: skip leading blank lines; make capital lines
424 #       be subheadings; accumulate rest looking for '*/' or blank line
425
426 s == "rdesc"    {
427                 # check for end of routine description
428
429                 if ((l ~ /^C</) || (l ~ /^\*\//) || (l ~ /^ *$/))
430                     {
431                     s = "rsy0"
432                     next
433                     }
434
435                 # skip leading blank lines
436
437                 if (xrdesc == 0 && ss ~ /^ *$/)
438                     next
439
440                 # suppress manual entry if NOMANUAL specified
441
442                 if (l ~ /NO[ _-]?MANUAL/)
443                     {
444                     s = "rtn"
445                     next
446                     }
447
448                 # check for sub heading and accumulate routine description
449                 # ignore INTERNAL sections
450
451                 if (subhead == "")
452                     {
453                     if (!ignore)
454                         rdesc[++xrdesc] = ss
455                     }
456                 else
457                     {
458                     if (subhead ~ /^INTERNAL/)
459                         ignore = 1
460                     else
461                         {
462                         rdesc[++xrdesc] = ".SH " subhead
463                         if (subheadl != "")
464                             rdesc[++xrdesc] = subheadl
465                         ignore = 0
466                         }
467                     }
468                 next
469                 }
470
471 # get routine synopsis: throw away local routines; check declared name matches
472 #       title; accumulate rest looking for "{"; then output routine manual
473
474 s == "rsy0"     {
475                 # skip to next non-blank line
476
477                 if (l ~ /^ *$/)
478                     next
479
480                 # found the function declaration line
481                 # quit processing of local functions: don't make manual
482
483                 l = substr (ss, 1, index (ss, "(") - 1)
484                 n = split (l, words)
485
486                 if ((words[1] == "LOCAL") || (words[1] == "static"))
487                     {
488                     s = "rtn"
489                     next
490                     }
491
492                 # check that declared name matches name in title
493
494                 if ((words[n] != rnm) && (words[n] != ("*" rnm)))
495                     {
496                     print "ERROR on line " NR           \
497                     ": title inconsistent with declaration:\n" rtitle "\n" l
498                     }
499
500                 # save routine declaration line
501
502                 rsy [1] = ss
503                 xrsy = 1
504                 maxlen = 0
505                 mingap = 100
506                 s = "rsy"
507                 next
508                 }
509
510 s == "rsy"      {
511                 # accumulate synopsis til '{' or blank line, then output manual
512
513 #               if ((l !~ /^ *{/) && (l !~ /^ *$/))
514                 if ((l !~ /^ *\{/) && (l !~ /^ *$/))
515                     {
516                     xrsy++
517
518                     # get real part up to ';' and note longest declaration
519
520                     is = index (l, ";")
521
522                     if (is == 0)
523                         {
524                         rsy[xrsy] = ""
525
526                         ic = index (l, $1)
527                         }
528                     else
529                         {
530                         if (($1 == "FAST") || ($1 == "register") || ($1 == "*"))
531                             i = index (l, $2)
532                         else
533                             i = index (l, $1)
534
535                         rsy [xrsy] = substr (l, i, is - i + 1)
536
537                         ic = index (l, "/*")
538                         }
539
540                     # get comment if any
541
542                     if (ic == 0)
543                         rsyc [xrsy] = ""
544                     else
545                         {
546                         rsyc [xrsy] = substr (l, ic)
547                         rsyci [xrsy] = ic
548                         }
549
550                     # note maximum length of line
551
552                     len = length (l)
553                     if (len > maxlen)
554                         maxlen = len
555
556                     # note minimum gap between code and comment
557
558                     if ((ic != 0) && (is != 0))
559                         {
560                         gap = ic - is - 1 + i - 5
561                         if (gap < mingap)
562                             mingap = gap
563                         }
564                     }
565                 else
566                     {
567                     # end of synopsis reached; output routine name, then
568                     # manual for this routine, then form-feed
569
570                     s = "rtn"
571
572                     print rnm >rtnfile
573                     stitle [++xrtn] = rtitle
574                     ssy [xrtn] = rsy[1]
575
576                     # print name and title
577
578                     print ".TH " rnm " 2" \
579                           " \"\" \"ALICE Reference Manual\"" >rtnfile
580                     print ".ad b" >rtnfile
581                     print ".SH NAME\n" rtitle >rtnfile
582
583                     # print routine synopsis
584
585                     # figure out if we should squeeze decls and comments
586
587                     squeeze = 0
588                     if (maxlen > 60) 
589                         {
590                         squeeze = maxlen - 60
591                         if (squeeze > (mingap - 1))
592                             squeeze = mingap - 1
593                         }
594
595                     print ".SH SYNOPSIS" >rtnfile
596                     print ".CS" >rtnfile
597                     print ".nf" >rtnfile
598                     print rsy[1] >rtnfile
599                     for (i = 2; i <= xrsy; i++)
600                         {
601                         if (rsyc[i] == "")
602                             n = 0
603                         else
604                             n = rsyci[i] - length(rsy[i]) - 5 - squeeze
605                         print "    " rsy[i] substr(blanks,0,n) rsyc[i] >rtnfile
606                         }
607                     print ".fi" >rtnfile
608                     print ".CE" >rtnfile
609
610                     # print description
611
612                     if ((xrdesc != 0) && (rdesc[1] !~ /^\.SH/))
613                         print ".SH DESCRIPTION" >rtnfile
614
615                     seealso = 0
616
617                     for (i = 1; i <= xrdesc; i++)
618                         {
619                         print rdesc[i] >rtnfile
620
621                         if (rdesc[i] ~ /^.SH SEE ALSO/)
622                             {
623                             print modname "(" chapter ")," >rtnfile
624                             seealso = 1
625                             }
626                         }
627
628                     # print see also if not already done above
629
630                     if (seealso == 0)
631                         {
632                         print ".SH SEE ALSO" >rtnfile
633                         print modname "(" chapter ")" >rtnfile
634                         }
635                     # form-feed
636
637                     print "\f" >rtnfile
638                     }
639
640                 next
641                 }
642
643 # end of file: output module manual
644
645 END             {
646                 if (!ignorelib)
647                     {
648                     # print name and title
649
650                     print ".TH " modname " " chapter \
651                           " \"\" \"ALICE Reference Manual\"" >outfile
652                     print ".ad b" >outfile
653                     print ".SH NAME\n" title >outfile
654
655
656                     # print specially constructed synopsis, if library
657                     # If no routines, say so.
658
659                     if (lib == 1)
660                         {
661                         print ".SH SYNOPSIS" >outfile
662                         print ".nf" >outfile
663                         for (i = 1; i <= xrtn; i++)
664                             print stitle[i] >outfile
665                         print "" >outfile
666                         if (xrtn == 0)
667                             print "NO CALLABLE ROUTINES" >outfile
668                         print ".CS" >outfile
669                         for (i = 1; i <= xrtn; i++)
670                             {
671                             if (substr(ssy[i], length (ssy[i])) == ")")
672                                 print ssy[i] >outfile
673                             else
674                                 print ssy[i], "..." >outfile
675                             }
676                         print ".CE" >outfile
677                         print ".fi" >outfile
678                         }
679
680
681                     # print module description
682
683                     if ((xdesc != 0) && (desc[1] !~ /^\.SH/))
684                         print ".SH DESCRIPTION" >outfile
685                     for (i = 1; i <= xdesc; i++)
686                         print desc[i] >outfile
687                     }
688                 }
689 #STOP_AWK