Fixup fromcvs/togit conversion
[minix-pkgsrc.git] / mk / help / help.awk
blob0deff3ff942cfd086aeabe4d59fad70ebdf44a08
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...
9 BEGIN {
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?
17 last_fname = "";
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) {
39 cleanup();
40 return;
43 for (k in keywords)
44 all_keywords[k]++;
46 relevant = (topic in keywords || lctopic in keywords || uctopic in keywords || topic == ":all");
47 if (relevant && !print_index) {
49 if (found_anything)
50 print "";
51 found_anything = yes;
53 kw = "";
54 for (i in keywords)
55 kw = kw " " i;
56 print "===> "last_fname " (keywords:" kw "):";
58 for (i = 0; i < nlines; i++) {
59 if (print_noncomment_lines || (lines[i] ~ /^#/))
60 print lines[i];
63 cleanup();
66 function cleanup() {
67 ignore_next_empty_line = yes;
68 delete lines;
69 nlines = 0;
70 delete keywords;
71 comment_lines = 0;
72 print_noncomment_lines = yes;
73 ignore_this_section = no;
76 always {
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.
83 /^#.*\$.*\$$/ {
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
91 # can be reached.
92 ($1 == "#" && $2 == "Keywords:") {
93 for (i = 3; i <= NF; i++) {
94 w = ($i == toupper($i)) ? tolower($i) : $i;
95 sub(/,$/, "", w);
96 keywords[w] = yes;
98 ignore_this_line = yes;
99 ignore_next_empty_line = yes;
102 ($0 == "#") {
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" {
115 end_of_topic();
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);
132 if (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.
152 } else {
153 sub(/^#[ \t]*/, "", w);
154 sub(/(:|\?=|=)$/, "", w);
155 sub(/:$/, "", w);
156 if (w != "") {
157 keywords[w] = yes;
162 # Don't print the implementation of make targets.
163 $1 ~ /:$/ {
164 print_noncomment_lines = no;
167 $1 == "#" {
168 comment_lines++;
171 /^$/ || last_fname != FILENAME {
172 end_of_topic();
175 always {
176 last_fname = FILENAME;
179 END {
180 end_of_topic();
181 if (print_index) {
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".";