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 ($_ !~ /^\d+$/) && 108 ($_ !~ /^[ \t]*$/)) { 109 if($verbose) { 110 print "Source: $Cpreprocessor $i$file\n"; 111 print "Symbol: $_\n"; 112 print "Line #$linenum: $line\n\n"; 113 } 114 push @syms, $_; 115 } 116 } 117 } 118 close H_IN || die "Error preprocessing $file"; 119} 120 121sub scanheader { 122 my ($f)=@_; 123 scanenums($f); 124 open H, "<$f"; 125 while(<H>) { 126 my ($line, $linenum) = ($_, $.); 127 if (/^#define +([^ \n]*)/) { 128 if($verbose) { 129 print "Source: $f\n"; 130 print "Symbol: $1\n"; 131 print "Line #$linenum: $line\n\n"; 132 } 133 push @syms, $1; 134 } 135 } 136 close H; 137} 138 139 140opendir(my $dh, $incdir) || die "Can't opendir $incdir: $!"; 141my @hfiles = grep { /\.h$/ } readdir($dh); 142closedir $dh; 143 144for(@hfiles) { 145 scanheader("$incdir/$_"); 146} 147 148my $errors = 0; 149for my $s (@syms) { 150 if($s !~ /^(lib|)curl/i) { 151 print "Bad symbols in public header files:\n" if(!$errors); 152 $errors++; 153 print " $s\n"; 154 } 155} 156if($errors) { 157 exit 1; 158} 159printf "%d fine symbols found\n", scalar(@syms); 160