On Sat, 05 May 2007 07:58:45 -0700
"Bernhard Schmalhofer via RT" <[EMAIL PROTECTED]> wrote:
> > * Fix up the indentation problems caused by the above bullet point.
> > (TODO: why does t/codingstd/c_indent.t require indentation for #if
> > and #ifdef, but not for #ifndef?)
> As far as I understand c_indent.t, #ifndef is also covered
Except that it isn't. If you apply the attached patch, you will see
that t/codingstd/c_indent.t starts failing. C_indent.t will not be
happy until you reindent everything else, inside of it. (This patch
should not be checked in, it only exhibits the problem, it does not
solve anything.)
> > I'd like to write some tests for this stuff, and then fix up the
> > rest of the cases (I know I've missed a bunch). How would the list
> > feel about a patch to PDD07 specifying the above for header files,
> > and a codingstd test to enforce it?
> My feeling is that we need to differentiate two cases:
> i. header files that define an interfaces for e.g. a subsystem
> ii. Convenience headers, that contain declaration of internal
> functions
>
> Case i. might need stricter checks than ii.
Thanks for your input. I have written a test case for this,
t/codingstd/c_header_guards.t (attached), which checks the following:
* The existence of an #ifndef PARROT_*_GUARD
* That each header file only contains one #ifndef PARROT_*_GUARD
* The existence of a matching #define (this caught a few misspells)
* The existence of an #endif /* PARROT_*_GUARD */
* That the PARROT_*_GUARD macro is unique (doesn't stomp on any other
files)
I patched up another large set of headers, to pass this test. But
before I send in another big patch with some changes to type ii
("convenience") headers, can you please tell me if there's a clean,
programmatic way to determine which headers it should perform strict
checks on? That way I can fix the test to only run on the
non-"convenience" subset of headers.
Also, should any of the above tests be applied to type ii headers, or
should they only apply to type i headers? (Should type ii headers be
ignored completely, or only subjected to a subset of the tests?)
Mark
Index: src/stm/stm_internal.h
===================================================================
--- src/stm/stm_internal.h (revision 18445)
+++ src/stm/stm_internal.h (working copy)
@@ -1,4 +1,4 @@
-#ifndef PARROT_STM_INTERNAL_H_GUARD
+#if !defined(PARROT_STM_INTERNAL_H_GUARD)
#define PARROT_STM_INTERNAL_H_GUARD
#include <parrot/parrot.h>
#! perl
# Copyright (C) 2006-2007, The Perl Foundation.
# $Id$
use strict;
use warnings;
use lib qw( . lib ../lib ../../lib );
use Test::More tests => 5;
use Parrot::Distribution;
=head1 NAME
t/codingstd/c_header_guards.t - checks for rules related to guards in C header files
=head1 SYNOPSIS
# test all files
% prove t/codingstd/c_header_guards.t
# test specific files
% perl t/codingstd/c_header_guards.t include/parrot/bar.h
=head1 DESCRIPTION
Checks that all C language header files have an #ifndef PARROT_WHATEVER_H_GUARD definition,
and an #endif /* PARROT_WHATEVER_H_GUARD */ at the end, as specified in PDD07.
=head1 SEE ALSO
L<docs/pdds/pdd07_codingstd.pod>
=cut
my $DIST = Parrot::Distribution->new();
my @files = @ARGV ? @ARGV : map { $_->path() } $DIST->c_header_files();
#foreach my $file ( @files ) {
# print $file, "\n";
#}
#exit;
check_header_guards(@files);
exit;
sub check_header_guards {
my (%guardnames, %redundants, %collisions,
%missing_guard, %missing_define, %missing_comment);
F: foreach my $file (@_) {
open my $fh, '<', $file
or die "Can not open '$file' for reading!\n";
my @source = <$fh>;
close $fh;
chomp @source;
my ($ifndef, $define, $endif);
L: foreach my $line (@source) {
$line =~ s/\s+/ /;
$line =~ s/^ //;
# skip Bison parser files
next F if $line =~ /A Bison parser/;
# skip the non-preprocessor lines
next L unless substr($line,0,1) eq '#';
# skip the "#", and any leading whitespace
$line = substr($line, 1);
$line =~ s/^ //;
if($line =~ m[ifndef (PARROT_.+_GUARD)$]) {
# check for multiple guards in the same file
$redundants{$file} = $1 if defined $ifndef;
# check for the same guard-name in multiple files
$collisions{$file} = $guardnames{$1}
if exists $guardnames{1};
$ifndef = $1;
$guardnames{$1} = $file;
}
if($line =~ m[define (PARROT_.+_GUARD)$]) {
$define = $1
if(defined($ifndef) && $ifndef eq $1);
}
if($line =~ m[endif /\* (PARROT_.+_GUARD) \*/$]) {
$endif = $1
if(defined($ifndef) && $ifndef eq $1);
}
}
$missing_guard{$file} = 1 unless defined $ifndef;
$missing_define{$file} = 1 unless defined $define;
$missing_comment{$file} = 1 unless defined $endif;
}
ok(!(scalar %collisions),
"identical PARROT_*_GUARD macro names used in headers "
. join(", ", %collisions));
ok(!(scalar %redundants),
"multiple PARROT_*_GUARD macros found in headers "
. join(", ", keys %redundants));
ok(!(scalar %missing_guard),
"missing or misspelled PARROT_*_GUARD ifndef in headers "
. join(", ", sort keys %missing_guard));
ok(!(scalar %missing_define),
"missing or misspelled PARROT_*_GUARD define in headers "
. join(", ", sort keys %missing_define));
ok(!(scalar %missing_comment),
"missing or misspelled PARROT_*_GUARD comment after the #endif in headers "
. join(", ", sort keys %missing_comment));
}
return 0;
# Local Variables:
# mode: cperl
# cperl-indent-level: 4
# fill-column: 100
# End:
# vim: expandtab shiftwidth=4: