Stuff from aldaqdqm09
[u/mrichter/AliRoot.git] / share / mangen
CommitLineData
e0381e22 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
72trap "rm -f mg.out mgr.out /tmp/mangen$$; exit" 1 2 3 15
73
74rm -f mg.out mgr.out # start with a clean slate
75
76# set home to directory that contains this script
77
78home=`expr $0 : '\(.*/\)[^/]' '|' ./`
79
80dontdelete=0
81dontnroff=0
82lib=0
83chapter=0
84
85while (test $# -gt 1)
86do
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
99done
100
101# remove path
102
103name=`basename $1`
104
105# remove trailing component, eg. ".xx"
106
107section=`expr $name : '\(.*\)\..*' '|' $name`
108
109# create awk program found at end of this script, and
110# make substitutions in the awk program source
111
112awk '/^#START_AWK$/,/^#STOP_AWK$/' <$0 | \
113sed -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
120awk -f /tmp/mangen$$ <$1
121
122rm /tmp/mangen$$
123
124# nroff them unless -n option
125
126if (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
131else
132 mv mg.out $section.$chapter
133fi
134
135if (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
143fi
144# delete the nroff source, unless -d or -n option
145
146if (test $dontdelete -eq 0) then
147 rm -f mg.out mgr.out
148fi
149
150exit 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
173BEGIN {
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
201dbg == 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
291s == "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
321s == "mh0" {
322 if (l ~ /modification history/)
323 s = "mh"
324 next
325 }
326
327s == "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
339s == "desc0" {
340 if (l !~ /^ *$/)
341 {
342 ignore = 0
343 s = "desc"
344 }
345 }
346
347s == "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
409s == "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
417s == "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
426s == "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
474s == "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
510s == "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
645END {
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