2 #***************************************************************************
4 # Project ___| | | | _ \| |
6 # | (__| |_| | _ <| |___
7 # \___|\___/|_| \_\_____|
9 # Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
11 # This software is licensed as described in the file COPYING, which
12 # you should have received as part of this distribution. The terms
13 # are also available at https://curl.se/docs/copyright.html.
15 # You may opt to use, copy, modify, merge, publish, distribute and/or sell
16 # copies of the Software, and permit persons to whom the Software is
17 # furnished to do so, under the terms of the COPYING file.
19 # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 # KIND, either express or implied.
22 # SPDX-License-Identifier: curl
25 ###########################################################################
27 # Check that the deprecated statuses of functions and enum values in header
28 # files, man pages and symbols-in-versions are in sync.
35 my $root=$ARGV[0] || ".";
36 my $incdir = "$root/include/curl";
37 my $docdir = "$root/docs";
38 my $libdocdir = "$docdir/libcurl";
41 # Symbol-indexed hashes.
44 # ? Deprecated in unknown version
45 # x.yy.z Deprecated in version x.yy.z
46 my %syminver; # Symbols-in-versions deprecations.
47 my %hdr; # Public header files deprecations.
48 my %funcman; # Function man pages deprecations.
49 my %optman; # Option man pages deprecations.
52 # Scan header file for public function and enum values. Flag them with
53 # the version they are deprecated in, if some.
60 open(my $h, "<", "$f");
62 s/^\s*(.*?)\s*$/$1/; # Trim.
63 # Remove multi-line comment trail.
65 if($_ !~ /.*?\*\/\s*(.*)$/) {
77 while($_ =~ /^(.*?)\/\*.*?\*\/(.*)$/) {
80 if($_ =~ /^(.*)\/\*/) {
84 s/^\s*(.*?)\s*$/$1/; # Trim again.
85 # Ignore preprocessor directives and blank lines.
86 if($_ =~ /^(?:#|$)/) {
89 # Handle lines that may be continued as if they were folded.
95 if($_ =~ /CURLOPTDEPRECATED\(/) {
96 # Handle deprecated CURLOPT_* option.
97 if($_ !~ /CURLOPTDEPRECATED\(\s*(\S+)\s*,(?:.*?,){2}\s*(.*?)\s*,.*"\)/) {
104 elsif($_ =~ /CURLOPT\(/) {
105 # Handle non-deprecated CURLOPT_* option.
106 if($_ !~ /CURLOPT\(\s*(\S+)\s*(?:,.*?){2}\)/) {
116 # Get other kind of deprecation from this line.
117 if($_ =~ /CURL_DEPRECATED\(/) {
118 if($_ !~ /^(.*)CURL_DEPRECATED\(\s*(\S+?)\s*,.*?"\)(.*)$/) {
126 if($_ =~ /^CURL_EXTERN\s+.*\s+(\S+?)\s*\(/) {
127 # Flag public function.
130 elsif($inenum && $_ =~ /(\w+)\s*[,=}]/) {
135 # Remember if we are in an enum definition.
136 $inenum |= ($_ =~ /\benum\b/);
144 # Scan function man page for options.
145 # Each option has to be declared as ".IP <option>" where <option> starts with
146 # the prefix. Flag each option with its deprecation version, if some.
147 sub scan_man_for_opts {
152 open(my $m, "<", "$f");
155 # roff directive found: end current option paragraph.
158 if($_ =~ /^\.IP\s+((?:$prefix)_\w+)/) {
159 # A new option has been found.
162 $_ = $line; # Get full paragraph.
164 s/\\f.//g; # Remove font formatting.
165 s/\s+/ /g; # One line with single space only.
168 # Check if paragraph is mentioning deprecation.
169 while($_ =~ /(?:deprecated|obsoleted?)\b\s*(?:in\b|since\b)?\s*(?:version\b|curl\b|libcurl\b)?\s*(\d[0-9.]*\d)?\b\s*(.*)$/i) {
170 $funcman{$o} = $1 || "?";
176 # Text line: accumulate.
183 # Scan man page for deprecation in DESCRIPTION and/or AVAILABILITY sections.
185 my ($path, $sym, $table)=@_;
188 if(open(my $fh, "<", "$path")) {
193 if($_ =~ /\.so\s+man3\/(.*\.3\b)/) {
194 # Handle man page inclusion.
195 scan_man_page(dirname($path) . "/$1", $sym, $table);
196 $version = exists($$table{$sym})? $$table{$sym}: $version;
199 # Line is a roff directive.
200 if($_ =~ /^\.SH\b\s*(\w*)/) {
201 # Section starts. End previous one.
205 $_ = $line; # Previous section text.
209 s/\\f.//g; # Remove font formatting.
210 s/\s+/ /g; # One line with single space only.
211 if($sh =~ /DESCRIPTION|AVAILABILITY/) {
212 while($_ =~ /(?:deprecated|obsoleted?)\b\s*(?:in\b|since\b)?\s*(?:version\b|curl\b|libcurl\b)?\s*(\d[0-9.]*\d)?\b\s*(.*)$/i) {
213 # Flag deprecation status.
214 if($version ne "X" && $version ne "?") {
215 if($1 && $1 ne $version) {
216 print "error: $sym man page lists unmatching deprecation versions $version and $1\n";
221 $version = $1 || "?";
229 # Text line: accumulate.
234 $$table{$sym} = $version;
239 # Read symbols-in-versions.
240 open(my $fh, "<", "$libdocdir/symbols-in-versions") ||
241 die "$libdocdir/symbols-in-versions";
243 if($_ =~ /^((?:CURL|LIBCURL)\S+)\s+\S+\s*(\S*)\s*(\S*)$/) {
246 if($2 ne "" && $2 ne ".") {
254 # Get header file names,
255 opendir(my $dh, $incdir) || die "Can't opendir $incdir";
256 my @hfiles = grep { /\.h$/ } readdir($dh);
259 # Get functions and enum symbols from header files.
261 scan_header("$incdir/$_");
264 # Get function statuses from man pages.
265 foreach my $sym (keys %hdr) {
266 if($sym =~/^(?:curl|curlx)_\w/) {
267 scan_man_page("$libdocdir/$sym.3", $sym, \%funcman);
271 # Get options from function man pages.
272 scan_man_for_opts("$libdocdir/curl_easy_setopt.3", "CURLOPT");
273 scan_man_for_opts("$libdocdir/curl_easy_getinfo.3", "CURLINFO");
275 # Get deprecation status from option man pages.
276 foreach my $sym (keys %syminver) {
277 if($sym =~ /^(?:CURLOPT|CURLINFO)_\w+$/) {
278 scan_man_page("$libdocdir/opts/$sym.3", $sym, \%optman);
283 my %keys = (%syminver, %funcman, %optman, %hdr);
284 my $leader = <<HEADER
288 ? Deprecated in unknown version
289 x.yy.z Deprecated in version x.yy.z
291 Symbol symbols-in func man opt man .h
295 foreach my $sym (sort {$a cmp $b} keys %keys) {
296 if($sym =~ /^(?:CURLOPT|CURLINFO|curl|curlx)_\w/) {
297 my $s = exists($syminver{$sym})? $syminver{$sym}: " ";
298 my $f = exists($funcman{$sym})? $funcman{$sym}: " ";
299 my $o = exists($optman{$sym})? $optman{$sym}: " ";
300 my $h = exists($hdr{$sym})? $hdr{$sym}: " ";
303 # There are deprecated symbols in symbols-in-versions that are aliases
304 # and thus not listed anywhere else. Ignore them.
305 "$f$o$h" =~ /[X ]{3}/ && next;
307 # Check for inconsistencies between deprecations from the different sources.
308 foreach my $k ($s, $f, $o, $h) {
309 $r = $r eq " "? $k: $r;
310 if($k ne " " && $r ne $k) {
312 $r = $k ne "X"? $k: "!";
314 elsif($r eq "X" || $k ne "?") {
323 printf("%-38s %-11s %-9s %-9s %s\n", $sym, $s, $f, $o, $h);