1#!/usr/bin/env perl 2#*************************************************************************** 3# _ _ ____ _ 4# Project ___| | | | _ \| | 5# / __| | | | |_) | | 6# | (__| |_| | _ <| |___ 7# \___|\___/|_| \_\_____| 8# 9# Copyright (C) 2010-2021, Daniel Stenberg, <daniel@haxx.se>, et al. 10# 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. 14# 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. 18# 19# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20# KIND, either express or implied. 21# 22########################################################################### 23# 24# This script grew out of help from Przemyslaw Iskra and Balint Szilakszi 25# a late evening in the #curl IRC channel. 26# 27 28use strict; 29use warnings; 30use vars qw($Cpreprocessor); 31 32# 33# configurehelp perl module is generated by configure script 34# 35my $rc = eval { 36 require configurehelp; 37 configurehelp->import(qw( 38 $Cpreprocessor 39 )); 40 1; 41}; 42# Set default values if configure has not generated a configurehelp.pm file. 43# This is the case with cmake. 44if (!$rc) { 45 $Cpreprocessor = 'cpp'; 46} 47 48my $verbose=0; 49 50# verbose mode when -v is the first argument 51if($ARGV[0] eq "-v") { 52 $verbose=1; 53 shift; 54} 55 56# we may get the dir root pointed out 57my $root=$ARGV[0] || "."; 58 59# need an include directory when building out-of-tree 60my $i = ($ARGV[1]) ? "-I$ARGV[1] " : ''; 61 62my $incdir = "$root/include/curl"; 63 64my $summary=0; 65my $misses=0; 66 67my @syms; 68my %doc; 69my %rem; 70 71sub scanenums { 72 my ($file)=@_; 73 my $skipit = 0; 74 75 open H_IN, "-|", "$Cpreprocessor $i$file" || die "Cannot preprocess $file"; 76 while ( <H_IN> ) { 77 my ($line, $linenum) = ($_, $.); 78 if( /^#(line|) (\d+) \"(.*)\"/) { 79 # if the included file isn't in our incdir, then we skip this section 80 # until next #line 81 # 82 if($3 !~ /^$incdir/) { 83 $skipit = 1; 84 next; 85 } 86 # parse this! 87 $skipit = 0; 88 next; 89 } 90 if($skipit) { 91 next; 92 } 93 if (/^#/) { 94 next; 95 } 96 if ( /enum\s+(\S+\s+)?{/ .. /}/ ) { 97 s/^\s+//; 98 chomp; 99 s/[,\s].*//; 100 if(($_ !~ /\}(;|)/) && 101 ($_ ne "typedef") && 102 ($_ ne "enum") && 103 ($_ !~ /^[ \t]*$/)) { 104 if($verbose) { 105 print "Source: $Cpreprocessor $i$file\n"; 106 print "Symbol: $_\n"; 107 print "Line #$linenum: $line\n\n"; 108 } 109 push @syms, $_; 110 } 111 } 112 } 113 close H_IN || die "Error preprocessing $file"; 114} 115 116sub scanheader { 117 my ($f)=@_; 118 scanenums($f); 119 open H, "<$f"; 120 while(<H>) { 121 my ($line, $linenum) = ($_, $.); 122 if (/^#define +([^ \n]*)/) { 123 if($verbose) { 124 print "Source: $f\n"; 125 print "Symbol: $1\n"; 126 print "Line #$linenum: $line\n\n"; 127 } 128 push @syms, $1; 129 } 130 } 131 close H; 132} 133 134 135opendir(my $dh, $incdir) || die "Can't opendir $incdir: $!"; 136my @hfiles = grep { /\.h$/ } readdir($dh); 137closedir $dh; 138 139for(@hfiles) { 140 scanheader("$incdir/$_"); 141} 142 143my $errors = 0; 144for my $s (@syms) { 145 if($s !~ /^(lib|)curl/i) { 146 print "Bad symbols in public header files:\n" if(!$errors); 147 $errors++; 148 print " $s\n"; 149 } 150} 151if($errors) { 152 exit 1; 153} 154printf "%d fine symbols found\n", scalar(@syms); 155