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