#! /usr/bin/perl -w
use bytes;

$includeroot = "/usr/src/linux-headers-2.6.27-15/include";
$outputroot = "fixedincludes";
mkdir($outputroot) || die;

@dirs = ();
opendir(D, $includeroot) || die;
while (($d = readdir(D))) {
    push @dirs, $d if $d !~ /^\./ && -d "$includeroot/$d";
}
closedir(D);
undef $/;

sub sprotect ($) {
    my($t) = $_[0];
    $t =~ tr/\000-\177/\200-\377/;
    $t;
}

sub sunprotect ($) {
    my($t) = $_[0];
    $t =~ tr/\200-\377/\000-\177/;
    $t;
}

while (@dirs) {
    $dd = shift @dirs;

    opendir(D, "$includeroot/$dd") || die "$includeroot/$dd: $!";
    mkdir("$outputroot/$dd") || die;
    while (($d = readdir(D))) {
	next if $d =~ /^\./;
	$f = "$includeroot/$dd/$d";
	if (-d $f) {
	    push @dirs, "$dd/$d";
	    next;
	}
	print STDERR "$dd/$d\n";

	# Now we definitely have a file.
	open(F, $f);
	$_ = <F>;
	close(F);

	# Fix include files for C++ compatibility.

	# First obscure comments and things that would confuse parsing.

	# DO NOT do preprocessor directives; we need to fix their definitions
	# s{(?<=\n)(#.*?[^\\])(?=\n)}{sprotect($1)}gse;
	# C comments (assume no string includes '/*')
	s{(/\*.*?\*/)}{sprotect($1)}gse;
	# C++ comments (assume no string includes '//')
	s{(//.*?)}{sprotect($1)}ge;
	# strings
	s{("")}{sprotect($1)}ge;
	s{"(.*?[^\\])"}{"\"" . sprotect($1) . "\""}sge;
	# characters
	s{'(.*?[^\\])'}{"\'" . sprotect($1) . "\'"}sge;

	# Now fix problems.

	# empty structures
	s{(\bstruct[\s\w\200-\377]+\{)([\s\200-\377]+\})}{$1 . "\n  int __padding_convince_cplusplus_zero_size__[0];\n" . $2}sge;

	# colon-colon
	s{:(?=:)}{: }g;

	# "extern asmlinkage"
	s{\bextern\s+asmlinkage\b}{asmlinkage}g;

	# advanced C initializers
	s{([\{,]\s*)\.\s*([a-zA-Z_]\w*)\s*=}{$1$2: }g;

	# Write the fixed file.
	open(F, ">$outputroot/$dd/$d") || die;
	print F sunprotect($_);
	close(F);
    }
}
