1#!/usr/bin/perl -w 2# 3# Gnumeric 4# 5# Copyright (C) 2003 Morten Welinder. 6# 7# This program is free software; you can redistribute it and/or 8# modify it under the terms of the GNU General Public License as 9# published by the Free Software Foundation; either version 2 of the 10# License, or (at your option) any later version. 11# 12# This library is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15# General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this library; if not, see <https://www.gnu.org/licenses/>. 19# 20# Author: Morten Welinder <terra@gnome.org> 21 22use strict; 23 24my $exitcode = 0; 25my $verbose = 0; 26my $strict = 0; 27 28warn "$0: should be run from top-level directory.\n" 29 unless -r "configure.ac" && -r 'ChangeLog'; 30 31my %base_exceptions = 32 (); 33 34my %exceptions = 35 (); 36 37{ 38 local (*FIND); 39 open (*FIND, "find . '(' -type f -name '*.c' -print ')' -o '(' -type d '(' -name .git -o -name intl -o -name macros -o -name win32 ')' -prune ')' |") 40 or die "$0: cannot execute find: $!\n"; 41 FILE: 42 foreach my $filename (<FIND>) { 43 chomp $filename; 44 $filename =~ s|^\./||; 45 46 next if $exceptions{$filename}; 47 my $basename = $filename; 48 $basename =~ s|^.*/||; 49 next if $base_exceptions{$basename}; 50 51 local (*FIL); 52 if (open (*FIL, "< $filename")) { 53 # print "Checking $filename...\n"; 54 my $lineno = 0; 55 my $state = 0; 56 my ($good,$dubious,$bad,$functype); 57 my ($seen_good,$seen_dubious,$seen_bad); 58 my %values; 59 LINE: 60 while (<FIL>) { 61 $lineno++; 62 63 if (/^(static\s+)?(inline\s+)?(unsigned\s+|signed\s+|const\s+)*(int|gu?int(|8|16|32|64)|char|gu?char)\b[^*]*$/) { 64 $state = 1; 65 $good = '[-+]?\d+'; 66 $dubious = 'FALSE|TRUE'; 67 $bad = 'NULL'; 68 $functype = 'integer'; 69 } elsif (/^(static\s+)?(inline\s+)?gboolean\b[^*]*$/) { 70 $state = 1; 71 $good = 'FALSE|TRUE'; 72 $dubious = '0|1'; 73 $bad = 'NULL|[-+]\d+|[2-9]\d*'; 74 $functype = 'boolean'; 75 } elsif (/^(static\s+)?(inline\s+)?(const\s+)?(gpointer|\S[ a-zA-Z0-9]+\*)/) { 76 $state = 1; 77 $good = 'NULL'; 78 $dubious = '0'; 79 $bad = 'FALSE'; 80 $functype = 'pointer'; 81 } 82 83 if ($state == 1) { 84 if (/;\s*$/) { 85 $state = 0; 86 next; 87 } 88 89 if (/^\{/) { 90 $state++; 91 $seen_good = $seen_dubious = $seen_bad = 0; 92 %values = (); 93 next; 94 } 95 } 96 97 if (/^\}/) { 98 if ($state == 2 && !$strict && $seen_good && $seen_dubious) { 99 print "$filename:$lineno: mixture of good and dubious return values: "; 100 print join (', ', sort keys %values), ".\n"; 101 } 102 103 $state = 0; 104 next; 105 } 106 107 if ($state == 2) { 108 my $val; 109 110 if (/\breturn(\s|\()\s*($good|$dubious|$bad)\s*\)*\s*;/) { 111 $val = $2; 112 } elsif (/\bg_return_val_if_fail.*,\s*($good|$dubious|$bad)\s*\)\s*;\s*$/) { 113 $val = $1; 114 } else { 115 next; 116 } 117 118 my $barf = 0; 119 if ($val =~ /^($bad)$/) { 120 $seen_bad = 1; 121 $barf = 1; 122 } elsif ($val =~ /^($dubious)$/) { 123 $seen_dubious = 1; 124 $barf = 1 if $strict; 125 $values{$val} = 1; 126 } else { 127 $seen_good = 1; 128 $values{$val} = 1; 129 } 130 131 print "$filename:$lineno: returning $val in a $functype function.\n" 132 if $barf; 133 134 next; 135 } 136 } 137 close (*FIL); 138 } else { 139 print STDERR "$0: Cannot read `$filename': $!\b"; 140 $exitcode = 1; 141 } 142 } 143 close (*FIND); 144} 145 146exit $exitcode; 147