1*6236dae4SAndroid Build Coastguard Worker#!/usr/bin/env perl 2*6236dae4SAndroid Build Coastguard Worker#*************************************************************************** 3*6236dae4SAndroid Build Coastguard Worker# _ _ ____ _ 4*6236dae4SAndroid Build Coastguard Worker# Project ___| | | | _ \| | 5*6236dae4SAndroid Build Coastguard Worker# / __| | | | |_) | | 6*6236dae4SAndroid Build Coastguard Worker# | (__| |_| | _ <| |___ 7*6236dae4SAndroid Build Coastguard Worker# \___|\___/|_| \_\_____| 8*6236dae4SAndroid Build Coastguard Worker# 9*6236dae4SAndroid Build Coastguard Worker# Copyright (C) Daniel Stenberg, <[email protected]>, et al. 10*6236dae4SAndroid Build Coastguard Worker# 11*6236dae4SAndroid Build Coastguard Worker# This software is licensed as described in the file COPYING, which 12*6236dae4SAndroid Build Coastguard Worker# you should have received as part of this distribution. The terms 13*6236dae4SAndroid Build Coastguard Worker# are also available at https://curl.se/docs/copyright.html. 14*6236dae4SAndroid Build Coastguard Worker# 15*6236dae4SAndroid Build Coastguard Worker# You may opt to use, copy, modify, merge, publish, distribute and/or sell 16*6236dae4SAndroid Build Coastguard Worker# copies of the Software, and permit persons to whom the Software is 17*6236dae4SAndroid Build Coastguard Worker# furnished to do so, under the terms of the COPYING file. 18*6236dae4SAndroid Build Coastguard Worker# 19*6236dae4SAndroid Build Coastguard Worker# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20*6236dae4SAndroid Build Coastguard Worker# KIND, either express or implied. 21*6236dae4SAndroid Build Coastguard Worker# 22*6236dae4SAndroid Build Coastguard Worker# SPDX-License-Identifier: curl 23*6236dae4SAndroid Build Coastguard Worker# 24*6236dae4SAndroid Build Coastguard Worker########################################################################### 25*6236dae4SAndroid Build Coastguard Worker# 26*6236dae4SAndroid Build Coastguard Worker# This script grew out of help from Przemyslaw Iskra and Balint Szilakszi 27*6236dae4SAndroid Build Coastguard Worker# a late evening in the #curl IRC channel. 28*6236dae4SAndroid Build Coastguard Worker# 29*6236dae4SAndroid Build Coastguard Worker 30*6236dae4SAndroid Build Coastguard Workeruse strict; 31*6236dae4SAndroid Build Coastguard Workeruse warnings; 32*6236dae4SAndroid Build Coastguard Workeruse vars qw($Cpreprocessor); 33*6236dae4SAndroid Build Coastguard Worker 34*6236dae4SAndroid Build Coastguard Worker# 35*6236dae4SAndroid Build Coastguard Worker# configurehelp perl module is generated by configure script 36*6236dae4SAndroid Build Coastguard Worker# 37*6236dae4SAndroid Build Coastguard Workermy $rc = eval { 38*6236dae4SAndroid Build Coastguard Worker require configurehelp; 39*6236dae4SAndroid Build Coastguard Worker configurehelp->import(qw( 40*6236dae4SAndroid Build Coastguard Worker $Cpreprocessor 41*6236dae4SAndroid Build Coastguard Worker )); 42*6236dae4SAndroid Build Coastguard Worker 1; 43*6236dae4SAndroid Build Coastguard Worker}; 44*6236dae4SAndroid Build Coastguard Worker# Set default values if configure has not generated a configurehelp.pm file. 45*6236dae4SAndroid Build Coastguard Worker# This is the case with cmake. 46*6236dae4SAndroid Build Coastguard Workerif (!$rc) { 47*6236dae4SAndroid Build Coastguard Worker $Cpreprocessor = 'cpp'; 48*6236dae4SAndroid Build Coastguard Worker} 49*6236dae4SAndroid Build Coastguard Worker 50*6236dae4SAndroid Build Coastguard Worker# we may get the dir root pointed out 51*6236dae4SAndroid Build Coastguard Workermy $root=$ARGV[0] || "."; 52*6236dae4SAndroid Build Coastguard Worker 53*6236dae4SAndroid Build Coastguard Worker# need an include directory when building out-of-tree 54*6236dae4SAndroid Build Coastguard Workermy $i = ($ARGV[1]) ? "-I$ARGV[1] " : ''; 55*6236dae4SAndroid Build Coastguard Worker 56*6236dae4SAndroid Build Coastguard Workermy $verbose=0; 57*6236dae4SAndroid Build Coastguard Workermy $summary=0; 58*6236dae4SAndroid Build Coastguard Workermy $misses=0; 59*6236dae4SAndroid Build Coastguard Worker 60*6236dae4SAndroid Build Coastguard Workermy @manrefs; 61*6236dae4SAndroid Build Coastguard Workermy @syms; 62*6236dae4SAndroid Build Coastguard Workermy %doc; 63*6236dae4SAndroid Build Coastguard Workermy %rem; 64*6236dae4SAndroid Build Coastguard Worker 65*6236dae4SAndroid Build Coastguard Worker# scanenum runs the preprocessor on curl.h so it will process all enums 66*6236dae4SAndroid Build Coastguard Worker# included by it, which *should* be all headers 67*6236dae4SAndroid Build Coastguard Workersub scanenum { 68*6236dae4SAndroid Build Coastguard Worker my ($file) = @_; 69*6236dae4SAndroid Build Coastguard Worker open my $h_in, "-|", "$Cpreprocessor $i$file" || die "Cannot preprocess $file"; 70*6236dae4SAndroid Build Coastguard Worker while ( <$h_in> ) { 71*6236dae4SAndroid Build Coastguard Worker if ( /enum\s+(\S+\s+)?{/ .. /}/ ) { 72*6236dae4SAndroid Build Coastguard Worker s/^\s+//; 73*6236dae4SAndroid Build Coastguard Worker next unless /^CURL/; 74*6236dae4SAndroid Build Coastguard Worker chomp; 75*6236dae4SAndroid Build Coastguard Worker s/[,\s].*//; 76*6236dae4SAndroid Build Coastguard Worker push @syms, $_; 77*6236dae4SAndroid Build Coastguard Worker } 78*6236dae4SAndroid Build Coastguard Worker } 79*6236dae4SAndroid Build Coastguard Worker close $h_in || die "Error preprocessing $file"; 80*6236dae4SAndroid Build Coastguard Worker} 81*6236dae4SAndroid Build Coastguard Worker 82*6236dae4SAndroid Build Coastguard Workersub scanheader { 83*6236dae4SAndroid Build Coastguard Worker my ($f)=@_; 84*6236dae4SAndroid Build Coastguard Worker open my $h, "<", "$f"; 85*6236dae4SAndroid Build Coastguard Worker while(<$h>) { 86*6236dae4SAndroid Build Coastguard Worker if (/^#define ((LIB|)CURL[A-Za-z0-9_]*)/) { 87*6236dae4SAndroid Build Coastguard Worker push @syms, $1; 88*6236dae4SAndroid Build Coastguard Worker } 89*6236dae4SAndroid Build Coastguard Worker } 90*6236dae4SAndroid Build Coastguard Worker close $h; 91*6236dae4SAndroid Build Coastguard Worker} 92*6236dae4SAndroid Build Coastguard Worker 93*6236dae4SAndroid Build Coastguard Workersub scanallheaders { 94*6236dae4SAndroid Build Coastguard Worker my $d = "$root/include/curl"; 95*6236dae4SAndroid Build Coastguard Worker opendir(my $dh, $d) || 96*6236dae4SAndroid Build Coastguard Worker die "Can't opendir: $!"; 97*6236dae4SAndroid Build Coastguard Worker my @headers = grep { /.h\z/ } readdir($dh); 98*6236dae4SAndroid Build Coastguard Worker closedir $dh; 99*6236dae4SAndroid Build Coastguard Worker foreach my $h (@headers) { 100*6236dae4SAndroid Build Coastguard Worker scanenum("$d/$h"); 101*6236dae4SAndroid Build Coastguard Worker scanheader("$d/$h"); 102*6236dae4SAndroid Build Coastguard Worker } 103*6236dae4SAndroid Build Coastguard Worker} 104*6236dae4SAndroid Build Coastguard Worker 105*6236dae4SAndroid Build Coastguard Workersub checkmanpage { 106*6236dae4SAndroid Build Coastguard Worker my ($m) = @_; 107*6236dae4SAndroid Build Coastguard Worker 108*6236dae4SAndroid Build Coastguard Worker open(my $mh, "<", "$m"); 109*6236dae4SAndroid Build Coastguard Worker my $line = 1; 110*6236dae4SAndroid Build Coastguard Worker while(<$mh>) { 111*6236dae4SAndroid Build Coastguard Worker # strip off formatting 112*6236dae4SAndroid Build Coastguard Worker $_ =~ s/(^|[^A-Z0-9])[*_]+/ /; 113*6236dae4SAndroid Build Coastguard Worker # detect global-looking 'CURL[BLABLA]_*' symbols 114*6236dae4SAndroid Build Coastguard Worker while(s/\W(CURL(AUTH|E|H|MOPT|OPT|SHOPT|UE|M|SSH|SSLBACKEND|HEADER|FORM|FTP|PIPE|MIMEOPT|GSSAPI|ALTSVC|PROTO|PROXY|UPART|USESSL|_READFUNC|_WRITEFUNC|_CSELECT|_FORMADD|_IPRESOLVE|_REDIR|_RTSPREQ|_TIMECOND|_VERSION)_[a-zA-Z0-9_]+)//) { 115*6236dae4SAndroid Build Coastguard Worker my $s = $1; 116*6236dae4SAndroid Build Coastguard Worker # skip two "special" ones 117*6236dae4SAndroid Build Coastguard Worker if($s !~ /^(CURLE_OBSOLETE|CURLOPT_TEMPLATE)/) { 118*6236dae4SAndroid Build Coastguard Worker push @manrefs, "$1:$m:$line"; 119*6236dae4SAndroid Build Coastguard Worker } 120*6236dae4SAndroid Build Coastguard Worker } 121*6236dae4SAndroid Build Coastguard Worker $line++; 122*6236dae4SAndroid Build Coastguard Worker } 123*6236dae4SAndroid Build Coastguard Worker close($mh); 124*6236dae4SAndroid Build Coastguard Worker} 125*6236dae4SAndroid Build Coastguard Worker 126*6236dae4SAndroid Build Coastguard Workersub scanman_md_dir { 127*6236dae4SAndroid Build Coastguard Worker my ($d) = @_; 128*6236dae4SAndroid Build Coastguard Worker opendir(my $dh, $d) || 129*6236dae4SAndroid Build Coastguard Worker die "Can't opendir: $!"; 130*6236dae4SAndroid Build Coastguard Worker my @mans = grep { /.md\z/ } readdir($dh); 131*6236dae4SAndroid Build Coastguard Worker closedir $dh; 132*6236dae4SAndroid Build Coastguard Worker for my $m (@mans) { 133*6236dae4SAndroid Build Coastguard Worker checkmanpage("$d/$m"); 134*6236dae4SAndroid Build Coastguard Worker } 135*6236dae4SAndroid Build Coastguard Worker} 136*6236dae4SAndroid Build Coastguard Worker 137*6236dae4SAndroid Build Coastguard Worker 138*6236dae4SAndroid Build Coastguard Workerscanallheaders(); 139*6236dae4SAndroid Build Coastguard Workerscanman_md_dir("$root/docs/libcurl"); 140*6236dae4SAndroid Build Coastguard Workerscanman_md_dir("$root/docs/libcurl/opts"); 141*6236dae4SAndroid Build Coastguard Worker 142*6236dae4SAndroid Build Coastguard Workeropen my $s, "<", "$root/docs/libcurl/symbols-in-versions"; 143*6236dae4SAndroid Build Coastguard Workerwhile(<$s>) { 144*6236dae4SAndroid Build Coastguard Worker if(/(^[^ \n]+) +(.*)/) { 145*6236dae4SAndroid Build Coastguard Worker my ($sym, $rest)=($1, $2); 146*6236dae4SAndroid Build Coastguard Worker if($doc{$sym}) { 147*6236dae4SAndroid Build Coastguard Worker print "Detected duplicate symbol: $sym\n"; 148*6236dae4SAndroid Build Coastguard Worker $misses++; 149*6236dae4SAndroid Build Coastguard Worker next; 150*6236dae4SAndroid Build Coastguard Worker } 151*6236dae4SAndroid Build Coastguard Worker $doc{$sym}=$sym; 152*6236dae4SAndroid Build Coastguard Worker my @a=split(/ +/, $rest); 153*6236dae4SAndroid Build Coastguard Worker if($a[2]) { 154*6236dae4SAndroid Build Coastguard Worker # this symbol is documented to have been present the last time 155*6236dae4SAndroid Build Coastguard Worker # in this release 156*6236dae4SAndroid Build Coastguard Worker $rem{$sym}=$a[2]; 157*6236dae4SAndroid Build Coastguard Worker } 158*6236dae4SAndroid Build Coastguard Worker } 159*6236dae4SAndroid Build Coastguard Worker} 160*6236dae4SAndroid Build Coastguard Workerclose $s; 161*6236dae4SAndroid Build Coastguard Worker 162*6236dae4SAndroid Build Coastguard Workermy $ignored=0; 163*6236dae4SAndroid Build Coastguard Workerfor my $e (sort @syms) { 164*6236dae4SAndroid Build Coastguard Worker # OBSOLETE - names that are just placeholders for a position where we 165*6236dae4SAndroid Build Coastguard Worker # previously had a name, that is now removed. The OBSOLETE names should 166*6236dae4SAndroid Build Coastguard Worker # never be used for anything. 167*6236dae4SAndroid Build Coastguard Worker # 168*6236dae4SAndroid Build Coastguard Worker # CURL_EXTERN - is a define used for libcurl functions that are external, 169*6236dae4SAndroid Build Coastguard Worker # public. No app or other code should ever use it. 170*6236dae4SAndroid Build Coastguard Worker # 171*6236dae4SAndroid Build Coastguard Worker # CURLINC_ - defines for header dual-include prevention, ignore those. 172*6236dae4SAndroid Build Coastguard Worker # 173*6236dae4SAndroid Build Coastguard Worker # CURL_TEMP_ - are defined and *undefined* again within the file 174*6236dae4SAndroid Build Coastguard Worker # 175*6236dae4SAndroid Build Coastguard Worker # *_LAST and *_LASTENTRY are just prefix for the placeholders used for the 176*6236dae4SAndroid Build Coastguard Worker # last entry in many enum series. 177*6236dae4SAndroid Build Coastguard Worker # 178*6236dae4SAndroid Build Coastguard Worker 179*6236dae4SAndroid Build Coastguard Worker if($e =~ /(OBSOLETE|^CURL_EXTERN|^CURLINC_|_LAST\z|_LASTENTRY\z|^CURL_TEMP_)/) { 180*6236dae4SAndroid Build Coastguard Worker $ignored++; 181*6236dae4SAndroid Build Coastguard Worker next; 182*6236dae4SAndroid Build Coastguard Worker } 183*6236dae4SAndroid Build Coastguard Worker if($doc{$e}) { 184*6236dae4SAndroid Build Coastguard Worker if($verbose) { 185*6236dae4SAndroid Build Coastguard Worker print $e."\n"; 186*6236dae4SAndroid Build Coastguard Worker } 187*6236dae4SAndroid Build Coastguard Worker $doc{$e}="used"; 188*6236dae4SAndroid Build Coastguard Worker next; 189*6236dae4SAndroid Build Coastguard Worker } 190*6236dae4SAndroid Build Coastguard Worker else { 191*6236dae4SAndroid Build Coastguard Worker print $e."\n"; 192*6236dae4SAndroid Build Coastguard Worker $misses++; 193*6236dae4SAndroid Build Coastguard Worker } 194*6236dae4SAndroid Build Coastguard Worker} 195*6236dae4SAndroid Build Coastguard Worker 196*6236dae4SAndroid Build Coastguard Worker# 197*6236dae4SAndroid Build Coastguard Worker# now scan through all symbols that were present in the symbols-in-versions 198*6236dae4SAndroid Build Coastguard Worker# but not in the headers 199*6236dae4SAndroid Build Coastguard Worker# 200*6236dae4SAndroid Build Coastguard Worker# If the symbols were marked 'removed' in symbols-in-versions we don't output 201*6236dae4SAndroid Build Coastguard Worker# anything about it since that is perfectly fine. 202*6236dae4SAndroid Build Coastguard Worker# 203*6236dae4SAndroid Build Coastguard Worker 204*6236dae4SAndroid Build Coastguard Workermy $anyremoved; 205*6236dae4SAndroid Build Coastguard Worker 206*6236dae4SAndroid Build Coastguard Workerfor my $e (sort keys %doc) { 207*6236dae4SAndroid Build Coastguard Worker if(($doc{$e} ne "used") && !$rem{$e}) { 208*6236dae4SAndroid Build Coastguard Worker 209*6236dae4SAndroid Build Coastguard Worker if(!$anyremoved++) { 210*6236dae4SAndroid Build Coastguard Worker print "Missing symbols mentioned in symbols-in-versions\n"; 211*6236dae4SAndroid Build Coastguard Worker print "Add them to a header, or mark them as removed.\n"; 212*6236dae4SAndroid Build Coastguard Worker } 213*6236dae4SAndroid Build Coastguard Worker 214*6236dae4SAndroid Build Coastguard Worker print "$e\n"; 215*6236dae4SAndroid Build Coastguard Worker $misses++; 216*6236dae4SAndroid Build Coastguard Worker } 217*6236dae4SAndroid Build Coastguard Worker} 218*6236dae4SAndroid Build Coastguard Worker 219*6236dae4SAndroid Build Coastguard Workermy %warned; 220*6236dae4SAndroid Build Coastguard Workerfor my $r (@manrefs) { 221*6236dae4SAndroid Build Coastguard Worker if($r =~ /^([^:]+):(.*)/) { 222*6236dae4SAndroid Build Coastguard Worker my ($sym, $file)=($1, $2); 223*6236dae4SAndroid Build Coastguard Worker if(!$doc{$sym} && !$warned{$sym, $file}) { 224*6236dae4SAndroid Build Coastguard Worker print "$file: $sym is not a public symbol\n"; 225*6236dae4SAndroid Build Coastguard Worker $warned{$sym, $file} = 1; 226*6236dae4SAndroid Build Coastguard Worker } 227*6236dae4SAndroid Build Coastguard Worker } 228*6236dae4SAndroid Build Coastguard Worker} 229*6236dae4SAndroid Build Coastguard Worker 230*6236dae4SAndroid Build Coastguard Workerif($summary) { 231*6236dae4SAndroid Build Coastguard Worker print "Summary:\n"; 232*6236dae4SAndroid Build Coastguard Worker printf "%d symbols in headers (out of which %d are ignored)\n", scalar(@syms), 233*6236dae4SAndroid Build Coastguard Worker $ignored; 234*6236dae4SAndroid Build Coastguard Worker printf "%d symbols in headers are interesting\n", 235*6236dae4SAndroid Build Coastguard Worker scalar(@syms)- $ignored; 236*6236dae4SAndroid Build Coastguard Worker printf "%d symbols are listed in symbols-in-versions\n (out of which %d are listed as removed)\n", scalar(keys %doc), scalar(keys %rem); 237*6236dae4SAndroid Build Coastguard Worker printf "%d symbols in symbols-in-versions should match the ones in headers\n", scalar(keys %doc) - scalar(keys %rem); 238*6236dae4SAndroid Build Coastguard Worker} 239*6236dae4SAndroid Build Coastguard Worker 240*6236dae4SAndroid Build Coastguard Workerif($misses) { 241*6236dae4SAndroid Build Coastguard Worker exit 0; # there are stuff to attend to! 242*6236dae4SAndroid Build Coastguard Worker} 243*6236dae4SAndroid Build Coastguard Workerelse { 244*6236dae4SAndroid Build Coastguard Worker print "OK\n"; 245*6236dae4SAndroid Build Coastguard Worker} 246