1 # $NetBSD: help.awk,v 1.25 2008/02/20 10:42:21 rillig Exp $
4 # This program extracts the inline documentation from *.mk files.
6 # usage: env TOPIC="topic" awk help.awk file...
10 no =
0; yes =
1; always =
1;
12 topic =
ENVIRON["TOPIC"];
13 uctopic =
toupper(topic
);
14 lctopic =
tolower(topic
);
16 found_anything = no
; # has some help text been found at all?
18 ignore_this_line = no
;
19 ignore_next_empty_line = no
;
20 ignore_this_section = no
;
22 delete lines
; # the collected lines
23 nlines =
0; # the number of lines collected so far
24 delete keywords
; # the keywords for this paragraph
25 delete all_keywords
; # all keywords that appear anywhere
26 comment_lines =
0; # the number of comment lines so far
27 print_noncomment_lines = yes
; # for make targets, this isn't useful
28 print_index =
(topic ==
":index");
29 # whether to print only the list of keywords
32 # Help topics are separated by either completely empty lines or by the
33 # end of a file or by the end of all files. When there have been enough
34 # comment lines, the topic is considered worth printing.
36 function end_of_topic
() {
38 if (comment_lines
<=
2 || ignore_this_section
) {
46 relevant =
(topic in keywords
|| lctopic in keywords
|| uctopic in keywords
|| topic ==
":all");
47 if (relevant
&& !print_index
) {
56 print "===> "last_fname
" (keywords:" kw
"):";
58 for (i =
0; i
< nlines
; i
++) {
59 if (print_noncomment_lines
|| (lines
[i
] ~
/^
#/))
67 ignore_next_empty_line = yes
;
72 print_noncomment_lines = yes
;
73 ignore_this_section = no
;
77 ignore_this_line =
(ignore_next_empty_line
&& $
0 ==
"#") || $
0 ==
"";
78 ignore_next_empty_line = no
;
81 # There is no need to print the RCS Id, since the full pathname
82 # is prefixed to the file contents.
84 ignore_this_line = yes
;
85 ignore_next_empty_line = yes
;
88 # The lines containing the keywords should also not appear in
89 # the output for now. This decision is not final since it may
90 # be helpful for the user to know by which keywords a topic
92 ($
1 ==
"#" && $
2 ==
"Keywords:") {
93 for (i =
3; i
<=
NF; i
++) {
94 w =
($i ==
toupper($i
)) ?
tolower($i
) : $i
;
98 ignore_this_line = yes
;
99 ignore_next_empty_line = yes
;
103 ignore_next_empty_line = no
;
106 $
1 ==
"#" && $
2 ==
"Copyright" {
107 ignore_this_section = yes
;
110 # Don't show the user the definition of make targets, since they are
111 # usually not interesting enough. This allows the comments to reach
112 # until the line directly above the target definition.
114 $
1 ~
/:$
/ && $
2 ==
".PHONY" {
118 (!ignore_this_line
) {
119 lines
[nlines
++] = $
0;
122 # Check whether the current line contains a keyword. Such a keyword must
123 # be all-lowercase (make targets) or all-uppercase (variable names).
124 # Everything else is assumed to belong to the explaining text.
126 NF >=
1 && !
/^
[\t.
]/ && !
/^
#*$/ {
127 w =
($
1 ~
/^\
#[A-Z]/) ? substr($1, 2) : ($1 == "#") ? $2 : $1;
129 # Reduce FOO.<param> and FOO.${param} to FOO.
130 sub(/\.
[<$
].
*[>}]$
/, "", w
);
133 # Appending to a variable is usually not a definition.
135 } else if (w
!= toupper(w
) && w
!= tolower(w
)) {
136 # Words in mixed case are not taken as keywords. If you
137 # want them anyway, list them in a "Keywords:" line.
139 } else if (w !~
/^
[A
-Za
-z
][-0-9A
-Z_a
-z
]*[0-9A
-Za
-z
](:|\?=
|=
)?$
/) {
140 # Keywords must consist only of letters, digits, hyphens
141 # and underscores; except for some trailing type specifier.
143 } else if (w ==
tolower(w
) && !
(w ~
/:$
/)) {
144 # Lower-case words (often make targets) must be followed
145 # by a colon to be recognized as keywords.
147 } else if (w ==
toupper(w
) && w ~
/:$
/) {
148 # Upper-case words ending with a colon are probably not
149 # make targets, so ignore them. Common cases are tags
150 # like FIXME and TODO.
153 sub(/^
#[ \t]*/, "", w);
154 sub(/(:|\?=
|=
)$
/, "", w
);
162 # Don't print the implementation of make targets.
164 print_noncomment_lines = no
;
171 /^$
/ || last_fname
!= FILENAME {
176 last_fname =
FILENAME;
182 for (k in all_keywords
) {
183 print all_keywords
[k
] "\t" k
;
185 } else if (!found_anything
) {
186 print "No help found for "topic
".";