#!/usr/bin/env perl1#***************************************************************************2# _ _ ____ _3# Project ___| | | | _ \| |4# / __| | | | |_) | |5# | (__| |_| | _ <| |___6# \___|\___/|_| \_\_____|7#8# Copyright (C) Daniel Stenberg, <[email protected]>, et al.9#10# This software is licensed as described in the file COPYING, which11# you should have received as part of this distribution. The terms12# are also available at https://curl.se/docs/copyright.html.13#14# You may opt to use, copy, modify, merge, publish, distribute and/or sell15# copies of the Software, and permit persons to whom the Software is16# furnished to do so, under the terms of the COPYING file.17#18# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY19# KIND, either express or implied.20#21# SPDX-License-Identifier: curl22#23###########################################################################24#25# This script grew out of help from Przemyslaw Iskra and Balint Szilakszi26# a late evening in the #curl IRC channel.27#2829use strict;30use warnings;31use vars qw($Cpreprocessor);3233#34# configurehelp perl module is generated by configure script35#36my $rc = eval {37require configurehelp;38configurehelp->import(qw(39$Cpreprocessor40));411;42};43# Set default values if configure has not generated a configurehelp.pm file.44# This is the case with cmake.45if (!$rc) {46$Cpreprocessor = 'cpp';47}4849my $verbose=0;5051# verbose mode when -v is the first argument52if($ARGV[0] eq "-v") {53$verbose=1;54shift;55}5657# we may get the dir root pointed out58my $root=$ARGV[0] || ".";5960# need an include directory when building out-of-tree61my $i = ($ARGV[1]) ? "-I$ARGV[1] " : '';6263my $incdir = "$root/include/curl";6465my $summary=0;66my $misses=0;6768my @syms;6970sub scanenums {71my ($file)=@_;72my $skipit = 0;7374open H_IN, "-|", "$Cpreprocessor -DCURL_DISABLE_DEPRECATION $i$file" ||75die "Cannot preprocess $file";76while ( <H_IN> ) {77my ($line, $linenum) = ($_, $.);78if( /^#(line|) (\d+) \"(.*)\"/) {79# if the included file isn't in our incdir, then we skip this section80# until next #line81#82if($3 !~ /^$incdir/) {83$skipit = 1;84next;85}86# parse this!87$skipit = 0;88next;89}90if($skipit) {91next;92}93if (/^#/) {94next;95}96if ( /enum\s+(\S+\s+)?{/ .. /}/ ) {97s/^\s+//;98chomp;99s/[,\s].*//;100if(($_ !~ /\}(;|)/) &&101($_ ne "typedef") &&102($_ ne "enum") &&103($_ ne "=") &&104($_ !~ /^\d+$/) &&105($_ !~ /^[ \t]*$/)) {106if($verbose) {107print "Source: $Cpreprocessor $i$file\n";108print "Symbol: $_\n";109print "Line #$linenum: $line\n\n";110}111push @syms, $_;112}113}114}115close H_IN || die "Error preprocessing $file";116}117118sub scanheader {119my ($f)=@_;120scanenums($f);121open H, "<$f";122while(<H>) {123my ($line, $linenum) = ($_, $.);124if (/^ *# *define +([^ \n]*)/) {125if($verbose) {126print "Source: $f\n";127print "Symbol: $1\n";128print "Line #$linenum: $line\n\n";129}130push @syms, $1;131}132}133close H;134}135136137opendir(my $dh, $incdir) || die "Can't opendir $incdir: $!";138my @hfiles = grep { /\.h$/ } readdir($dh);139closedir $dh;140141for(@hfiles) {142scanheader("$incdir/$_");143}144145my $errors = 0;146for my $s (@syms) {147if($s !~ /^(lib|)curl/i) {148print "Bad symbols in public header files:\n" if(!$errors);149$errors++;150print " $s\n";151}152}153if($errors) {154exit 1;155}156printf "%d fine symbols found\n", scalar(@syms);157158159