Subject: Re: Protecting the rest of the kerner headers against multiple inclusion
To: Christos Zoulas <christos@zoulas.com>
From: Simon J. Gerraty <sjg@quick.com.au>
List: tech-kern
Date: 09/13/1999 17:57:29
> | does not already protect itself), it would look nicer, though perhaps
> | be less efficient to put the #ifndef _SYS_TYPES_H_ before the first
> | non-comment line?
> 
> Dunno, I like them where they are now I guess, where it is after the
> copyright.

Ok, here's the perl version which does the right thing wrt comments.

#!/usr/bin/env perl

# NAME:
#	chprot - protect C headers from themselves
#
# SYNOPSIS:
#	chprot.pl [options] *.h
#	find . -name '*.h' -print | chprot.pl [options]
#
# DESCRIPTION:
#	Ensure C headers protect themselves against multiple
#	inclusion.
#
#	We first attempt to check if the header is already
#	protected.  If not we generate a tag to protect it that
#	will hopefully be unique such as:
#.nf
#
#	stdio.h		_STDIO_H_
#	sys/types.h	_SYS_TYPES_H_
#.fi
#
#	The the first non-empty, non-comment line of the header to the
#	end of file is then enclosed by:
#.nf
#
#	#ifndef $tag
#	# define $tag
#	<original header>
#	#endif /* $tag */
#.fi
#
#	Options:
#
#	-l	Use lower case tags.
#
#	-v	Be verbose, tell us what is going on.
#	
# AUTHOR:
#	Simon J. Gerraty <sjg@quick.com.au>
#	

$RCSid = '$Id: chprot.pl,v 1.2 1999/09/13 07:55:13 sjg Exp $'; # emacs'

#
#	@(#)Copyright (c) 1991 Simon J. Gerraty
#
#	This file is provided in the hope that it will
#	be of use.  There is absolutely NO WARRANTY.
#	Permission to copy, redistribute or otherwise
#	use this file is hereby granted provided that 
#	the above copyright notice and this notice are
#	left intact. 
#      
#	Please send copies of changes and bug-fixes to:
#	sjg@quick.com.au
#

require 'getopts.pl';

&Getopts('vd');

sub show {
  local($flag,@args) = @_;

  if ($flag ne '') {
    printf STDERR @args;
  }
}

sub protect {
  local($hdr) = @_;

  if ($hdr =~ m,/assert.h,) {
    &show(1, "skipping $hdr\n");
    return;
  }
  $tag = $hdr;
  $tag =~ s,.*include,,;
  $tag =~ y,a-z\./,A-Z__,;
  $tag = "_${tag}_";
  $tag =~ s,__+,_,g;

  $tag =~ y/A-Z/a-z/ if ($opt_l ne '');
  
  # first see if there is some attempt at protecting it already.
  $check = $tag;
  $check =~ s/.*(_[^_]+_H)_*$/$1/;
  chop($ok = `grep -i "#[ \t]*if.*def.*$check" $hdr`);
  if ($ok ne '') {
    &show("$opt_d$opt_v", "$hdr protected by $ok\n");
    return;
  }
  
  if (open(H, "< $hdr")) {
    if (open(N, "> $hdr.new")) {
      $protected = 0;
      $comment = 0;
      &show("$opt_d$opt_v", "$hdr protecting with $tag\n");
      
      while (<H>) {
	if (m,^\s*/\*.*\*/,) {
	  print N;
	  next;
	} elsif (m,^\s*/\*,) {
	  $comment = 1;
	  print N;
	  next;
	} elsif (m,\*/,) {
	  $comment = 0;
	  print N;
	  next;
	} elsif (m/^\s*$/) {
	  print N;
	  next;
	} else {
	  if (!$protected && !$comment) {
	    print N "#ifndef $tag\n# define $tag\n\n";
	    $protected = 1;
	  }
	  print N;
	}
      }
      if ($protected) {
	print N "\n#endif /* $tag */\n";
      }
      close N;
      close H;
      rename($hdr, "$hdr.bak");
      rename("$hdr.new", $hdr);
    } else {
      close H;
    }
  }
}

sub main {
  if (scalar(@ARGV) > 0) {
    foreach $hdr (@ARGV) {
      &protect($hdr);
    }
  } else {
    while (<STDIN>) {
      chop;
      &protect($_);
    }
  }
}

&main;
exit 0;