]> git.ipfire.org Git - thirdparty/glibc.git/blame - manual/summary.pl
sysvipc: Implement semop based on semtimedop
[thirdparty/glibc.git] / manual / summary.pl
CommitLineData
d08a7e4c
RJ
1#!/usr/bin/perl
2# Generate the Summary of Library Facilities (summary.texi).
3
04277e02 4# Copyright (C) 2017-2019 Free Software Foundation, Inc.
d08a7e4c
RJ
5# This file is part of the GNU C Library.
6# Contributed by Rical Jasan <ricaljasan@pacific.net>, 2017.
7
8# The GNU C Library is free software; you can redistribute it and/or
9# modify it under the terms of the GNU Lesser General Public License
10# as published by the Free Software Foundation; either version 2.1 of
11# the License, or (at your option) any later version.
12
13# The GNU C Library is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16# Lesser General Public License for more details.
17
18# You should have received a copy of the GNU Lesser General Public
19# License along with the GNU C Library; if not, see
5a82c748 20# <https://www.gnu.org/licenses/>.
d08a7e4c
RJ
21
22# Anything declared in a header or defined in a standard should have
23# its origins annotated using the @standards macro (see macro.texi).
24# This script checks all such elements in the manual (generally,
25# @def|item*-commands), ensuring annotations are present and correct.
26# If any errors are detected, they are all reported at the end and
27# failure is indicated.
28
29use strict;
30use warnings;
31use locale;
32use File::Basename;
33
34$| = 1;
35my $script = basename $0;
36
37&help if $ARGV[0] eq "--help"; # Will exit(0).
38
39my @texis = @ARGV;
40
41# Various regexes.
42my $nde = qr/^\@node /;
43my $def = qr/^\@def/;
44my $itm = qr/^\@item /;
45my $itms = qr/^\@itemx? /; # Don't match @itemize.
46my $ann = qr/^\@(def\w+|item)x? /; # Annotatable.
47my $std = qr/^\@standards\{/;
48my $stx = qr/^\@standardsx\{/;
49my $stds = qr/^\@standardsx?\{/;
50my $strict_std = qr/^\@standards\{([^,]+, )[^,\}]+\}$/;
51my $strict_stx = qr/^\@standardsx\{([^,]+, ){2}[^,\}]+\}$/;
52my $lcon = qr/([vf]?table|itemize|enumerate)/;
53my $list = qr/^\@${lcon}/;
54my $endl = qr/^\@end ${lcon}/;
55my $ign = qr/^\@ignore/;
56my $eig = qr/^\@end ignore/;
57
58# Global scope.
59my $node;
60our $texi;
61my $input;
62my %entries;
63my %errors;
64
65for $texi (@texis) {
66 open $input, '<', $texi or die "open $texi: $!";
67 while (my $line = <$input>) {
68 if ($line =~ $nde) {
69 $node = &get_node($line);
70 } elsif ($line =~ $def) {
71 &process_annotation($line);
72 } elsif ($line =~ $list) {
73 &process_list($1); # @items occur in list or table context.
74 } elsif ($line =~ $stds) {
75 &record_error("Misplaced annotation", ["[$.] ".$line]);
76 } elsif ($line =~ $ign) {
77 while (<$input> !~ $eig) {}
78 }
79 }
80 close $input or die "close $texi: $!";
81}
82
83# Disabled until annotations are complete.
84&print_errors() if %errors && 0; # Will exit(1).
85
86print("\@c DO NOT EDIT THIS FILE!\n".
87 "\@c This file is generated by $script from the Texinfo sources.\n".
88 "\@c The \@items are \@include'd from a \@table in header.texi.\n\n");
89
90&print_entry($_) for sort keys %entries;
91
92# Processes an annotatable element, including any subsequent elements
93# in an @*x chain, ensuring @standards are present, with valid syntax,
94# either recording any errors detected or creating Summary entries.
95# This function is the heart of the script.
96#
97# Prototypes and standards are gathered into separate lists and used
98# to evaluate the completeness and correctness of annotations before
99# generating the Summary entries. "Prototype" is used to refer to an
100# element's entire definition while avoiding conflation with
101# @def*-commands. "Element" is strictly used here to refer to the
102# name extracted from the prototype, as used in @standardsx, for
103# sorting the Summary.
104sub process_annotation
105{
106 my $line = shift;
107 my (@prototypes, @standards, $i, @tmp);
108
109 # Gather prototypes and standards.
110 push @prototypes, $line;
111 while ($line = <$input>) {
112 last if $line !~ $ann;
113 push @prototypes, $line;
114 }
115 if ($line !~ $stds) { # The fundamental error.
116 return &record_error('Missing annotation', \@prototypes);
117 }
118 push @standards, $line;
119 push @standards, $line while ($line = <$input>) =~ $stds;
120
121 # If next line is an @item, seek back to catch it on the next
122 # iteration. This avoids imposing a non-Texinfo syntax
123 # requirement of blank lines between consecutive annotated @items.
124 if ($line =~ $itm) {
125 seek $input, -length($line), 1 or die "seek: $!";
126 }
127
128 # Strict check for syntax errors. Other matches are loose, which
129 # aids error detection and reporting by ensuring things that look
130 # like standards aren't simply passed over, but caught here.
131 for ($i=0; $i<@standards; ++$i) {
132 my $standard = $standards[$i];
133 if ($standard !~ $strict_std && $standard !~ $strict_stx) {
134 push @tmp, $standard;
135 }
136 }
137 return &record_error('Invalid syntax', \@tmp) if @tmp;
138
139 # @standardsx should not be in non-@*x chains.
140 if (@prototypes == 1) {
141 for ($i=0; $i<@standards; ++$i) {
142 return &record_error('Misplaced @standardsx', \@prototypes)
143 if $standards[$i] =~ $stx;
144 }
145 }
146 # @standards may only occur once in @*x chains, at the beginning.
147 if (@prototypes > 1) {
148 for ($i=1; $i<@standards; ++$i) {
149 return &record_error('Misplaced @standards', \@prototypes)
150 if $standards[$i] =~ $std;
151 }
152 }
153
154 # The @standards are aligned.
155 &add_entries(\@prototypes, \@standards);
156}
157
158# Goes through the prototypes, cleaning them up and extracting the
159# elements, pairing them with the appropriate annotations to create
160# Summary entries.
161sub add_entries
162{
163 my ($prototypes, $standards) = @_;
164 my $isx = @{$prototypes} > 1 ? 1 : 0;
165 my $allx = $standards->[0] =~ $stx ? 1 : 0;
166 my ($defstd, $defhdr, %standardsx, $i, $j);
167
168 # Grab the default annotation and index any @standardsx. Take
169 # care in case there is no default.
170 if ($isx) {
171 if (!$allx) {
172 ($defstd, $defhdr)
173 = $standards->[0] =~ /${std}([^,]+), (.*)\}$/;
174 }
175 for ($i = $allx ? 0 : 1; $i<@{$standards}; ++$i) {
176 my ($e, $s, $h)
177 = $standards->[$i] =~ /${stx}([^,]+), ([^,]+), (.*)\}$/;
178 push @{$standardsx{$e}{hs}}, [$h, $s];
179 }
180 }
181
182 for ($i=0; $i<@{$prototypes}; ++$i) {
183 my $e = &get_element($prototypes->[$i]);
184 my $p = &get_prototype($prototypes->[$i]);
185 my ($s, $h);
186 if ($isx && exists $standardsx{$e}) {
187 for ($j=0; $j<@{$standardsx{$e}{hs}}; ++$j) {
188 $h = $standardsx{$e}{hs}[$j]->[0];
189 $s = $standardsx{$e}{hs}[$j]->[1];
190 &record_entry($e, $p, $h, $s, $node);
191 ++$standardsx{$e}{seen};
192 }
193 } elsif ($isx && $allx) {
194 &record_error('Missing annotation', [$prototypes->[$i]]);
195 } elsif ($isx) {
196 &record_entry($e, $p, $defhdr, $defstd, $node);
197 } else {
198 for ($j=0; $j<@{$standards}; ++$j) {
199 ($s, $h) = $standards->[$j] =~ /${std}([^,]+), ([^,\}]+)\}$/;
200 &record_entry($e, $p, $h, $s, $node);
201 }
202 }
203 }
204
205 # Check if there were any unmatched @standardsx.
206 for my $e (keys %standardsx) {
207 if (!exists $standardsx{$e}{seen}) {
208 &record_error('Spurious @standardsx', [$e."\n"])
209 }
210 }
211}
212
213# Stores a Summary entry in %entries. May be called multiple times
214# per element if multiple header and standard annotations exist. Also
215# keys on prototypes, as some elements have multiple prototypes. See
216# isnan in arith.texi for one example.
217sub record_entry
218{
219 my ($ele, $proto, $hdr, $std, $node) = @_;
220 push @{$entries{$ele}{$proto}}, [$hdr, $std, $node];
221}
222
223# Processes list or table contexts, with nesting.
224sub process_list
225{
226 my $type = shift;
227 my $in_vtbl = $type eq "vtable" ? 1 : 0;
228
229 while (my $line = <$input>) {
230 if ($line =~ $itms) {
231 next if ! $in_vtbl; # Not an annotatable context.
232 &process_annotation($line);
233 } elsif ($line =~ $def) {
234 &process_annotation($line);
235 } elsif ($line =~ $stds) {
236 &record_error('Misplaced annotation', ["[$.] ".$line]);
237 } elsif ($line =~ $endl) {
238 return; # All done.
239 } elsif ($line =~ $list) {
240 &process_list($1); # Nested list.
241 }
242 }
243}
244
245# Returns the current node from an @node line. Used for referencing
246# from the Summary.
247sub get_node
248{
249 my $line = shift;
250 chomp $line;
251 $line =~ s/$nde//;
252 my ($n) = split ',', $line;
253 return $n
254}
255
256# Returns the cleaned up prototype from @def|item* lines.
257sub get_prototype
258{
259 my $dfn = shift;
260 chomp $dfn;
261 $dfn =~ s/\s+/ /g; # Collapse whitespace.
262 $dfn =~ s/ \{([^\}]*)\} / $1 /g; # Remove grouping braces.
263 $dfn =~ s/^\@\S+ //; # Remove @-command.
264 $dfn =~ s/^Macro //i; # Scrape off cruft...
265 $dfn =~ s/^Data Type //i;
266 $dfn =~ s/^Variable //i;
267 $dfn =~ s/^Deprecated Function //i;
268 $dfn =~ s/^SVID Macro //i;
269 $dfn =~ s/^Obsolete function //i;
270 $dfn =~ s/^Constant //i;
271 $dfn =~ s/^Type //i;
272 $dfn =~ s/^Function //i;
273 $dfn =~ s/^\{(.*)\}$/$1/; # Debrace yourself.
274 $dfn =~ s/^\{([^\}]*)\} /$1 /; # These ones too.
275 return $dfn;
276}
277
278# Returns an annotated element's name.
279#
280# Takes a line defining an annotatable element (e.g., @def|item*),
281# splitting it on whitespace. The element is generally detected as
282# the member immediately preceding the first parenthesized expression
283# (e.g., a function), or the last token in the list. Some additional
284# cleanup is applied to the element before returning it.
285sub get_element
286{
287 my $i = 0;
288 my @toks = split /\s+/, shift;
289 # tzname array uses '['; don't match function pointers.
290 ++$i while $toks[$i] && $toks[$i] !~ /^[\(\[](?!\*)/;
291 $toks[$i-1] =~ s/^\*//; # Strip pointer type syntax.
292 $toks[$i-1] =~ s/^\{?([^\}]+)\}?$/$1/; # Strip braces.
293 $toks[$i-1] =~ s/^\(\*([^\)]+)\)$/$1/; # Function pointers.
294 return $toks[$i-1];
295}
296
297# Records syntax errors detected in the manual related to @standards.
298# The @def|item*s are grouped by file, then errors, to make it easier
299# to track down exactly where and what the problems are.
300sub record_error
301{
302 my ($err, $list) = @_;
303 push @{$errors{$texi}{$err}}, $_ for (@{$list});
304 return 0;
305}
306
307# Reports all detected errors and exits with failure. Indentation is
308# used for readability, and "ERROR" is used for visibility.
309sub print_errors
310{
311 for $texi (sort keys %errors) {
312 print STDERR "ERRORS in $texi:\n";
313 for my $err (sort keys %{$errors{$texi}}) {
314 print STDERR " $err:\n";
315 print STDERR " $_" for (@{$errors{$texi}{$err}});
316 }
317 }
318 print(STDERR "\nFor a description of expected syntax, see ".
319 "\`$script --help'\n\n");
320 exit 1;
321}
322
323# Prints an entry in the Summary.
324#
325# All the blank lines in summary.texi may seem strange at first, but
326# they have significant impact on how Texinfo renders the output.
327# Essentially, each line is its own paragraph. There is a @comment
328# with the element name, arguably unnecessary, but useful for seeing
329# the sorting order and extracted element names, and maintains the
330# format established by summary.awk. Each @item in the @table is the
331# prototype, which may be anything from just a variable name to a
332# function declaration. The body of each @item contains lines
333# annotating the headers and standards each element is declared
334# in/comes from, with a reference to the @node documenting the element
335# wrt. each header and standard combination.
336sub print_entry
337{
338 my $element = shift;
339 for my $prototype (sort keys %{$entries{$element}}) {
340 print "\@comment $element\n\@item $prototype\n\n";
341 for (@{$entries{$element}{$prototype}}) {
342 my ($header, $standard, $node)
343 = ($_->[0], $_->[1], $_->[2]);
344 if ($header =~ /^\(none\)$/i) {
345 $header = "\@emph{no header}";
346 } elsif ($header =~ /\(optional\)$/) {
347 $header =~ s/^(\S+) \((.*)\)$/\@file{$1} \@emph{$2}/;
348 } elsif ($header ne '???') {
349 $header = "\@file{$header}";
350 }
351 print "$header ($standard): \@ref{$node}.\n\n";
352 }
353 }
354}
355
356# Document the syntax of @standards.
357sub help
358{
359 print "$script ";
360 print <<'EOH';
361generates the Summary of Library Facilities (summary.texi)
362from @standards and @standardsx macros in the Texinfo sources (see
363macros.texi). While generating the Summary, it also checks that
364@standards are used, correctly.
365
366In general, any @def*-command or @item in a @vtable is considered
367annotatable. "Misplaced annotation" refers to @standards macros
368detected outside an annotatable context. "Missing annotation" refers
369to annotatable elements without @standards. @standards are expected
370to immediately follow the elements being annotated. In @*x lists,
371@standards sets the default annotation and may only occur as the first
372annotation ("Misplaced @standards"). @standardsx may not be used
373outside @*x lists ("Misplaced @standardsx"). "Spurious @standardsx"
374refers to otherwise valid @standardsx macros that were not matched to
375an element in an @*x list. "Invalid syntax" means just that.
376
377The syntax of @standards annotations is designed to accomodate
378multiple header and standards annotations, as necessary.
379
380Examples:
381
382 @deftp FOO
383 @standards{STD, HDR}
384
385 @defvar BAR
386 @standards{STD, HDR1}
387 @standards{STD, HDR2}
388
389 @deftypefun foo
390 @deftypefunx fool
391 @standards{STD, HDR}
392
393 @item bar
394 @itemx baz
395 @standardsx{bar, STD1, HDR1}
396 @standardsx{baz, STD1, HDR1}
397 @standardsx{baz, STD2, HDR2}
398
399Note that @standardsx deviates from the usual Texinfo syntax in that
400it is optional and may be used without @standards.
401EOH
402 ; exit 0;
403}