#! /bin/perl
#
# Extends include-header-files with __attribute__((packed))
# to make ixemul and os-includes ppc-compatible
#
# 07.06.98 Samuel Devulder: __attribute((aligned(2)) for all >2 byte elements
# 18.06.98 Holger Jakob:    It is not enough to use a modified
#                           exec/types.h only :(
#
require 5.002;


undef $/;

die "no include" if not $include=@ARGV[0];
print STDERR "Copying $include ... ";

open(INP,"<$include");
$source=<INP>;

# Check for additional patches here...
# user.h, (screens.h), setjmp.h...

if( $include=~ /include\/user.h$/i ) { $source=~ s/(\W)jmp_buf(\W)/$1jmp_buf_m68k$2/g; }
if( $include=~ /include\/setjmp.h$/i ) {
  $source=~ s/(#define\s+_JBLEN)(\s+\d+)/$1_M68K $2\n$1\t\t26+17*2/;
  $source=~ s/(typedef\s+int\s+sigjmp_buf)(.*)(_JBLEN)(.*)/$1_m68k$2$3_M68K$4\n$1$2$3$4/;
  $source=~ s/(typedef\s+int\s+jmp_buf)(.*)(_JBLEN)(.*)/$1_m68k$2$3_M68K$4\n$1$2$3$4/;
}
if( $include=~ /include\/sys\/syscall.h$/i ) { $source=~ s/#ifndef\s+?_KERNEL(.*?)#endif//s; }

#
#

$source=~ s/\/\*.*?\*\///sg;  # Sorry, no comments
$source=~ s/^struct((.|\n)*?)({(.|\n)*?});/&ins_packed_struct($1,$3)/meg;
# ToDo: same for typdef
#$source=~ s/^typedef((.|\n)*?)((\w|\n)*?);/&ins_packed_typedef($1,$3)/meg;
print $source;

close(INP);
print STDERR "Applied ";
print STDERR ($source=~ s/__attribute/__attribute/g) || "no";
print STDERR " patches.\n";

sub ins_packed_struct
{
	local ($name,$text)=@_;
	local ($return);


#	$text=~ s/(LONG|struct)([^;])/$1$2 __attribute__((aligned(2))) /g;

	$return="struct".$name.$text." __attribute__((packed));";

#FIXME: /* ; */ is not recogniced and 2-word types(eg. unsigned int) as well
#FIXED!?
	$return=~ s/^(\s*)(\w*)(\s*)([a-zA-Z_]*)(.*?);/&ins_align($1,$2,$3,$4,$5)/ge;

	return $return;
}
sub ins_packed_typedef
{
	local ($text,$name)=@_;
	local ($return);


#	$text=~ s/(LONG|struct)([^;])/$1$2 __attribute__((aligned(2))) /g;

#	$return="struct".$name.$text." __attribute__((packed));";

#FIXME: /* ; */ is not recogniced and 2-word types(eg. unsigned int) as well
#FIXED!?
#	$return=~ s/^(\s*)(\w*)(\s*)([a-zA-Z_]*)(.*?);/&ins_align($1,$2,$3,$4,$5)/ge;

	return "typedef $name;";
}

sub ins_align
{
	local ($space,$type,$space2,$type2,$part1)=@_;

	if( $type=~ /^([AC]PTR|STRPTR|LONG|LONGBITS|ULONG|FLOAT|DOUBLE)$/ ) {
		$type=$type." __attribute__((aligned(2)))";
	} elsif( $type=~ /^struct$/ ) {
		if( $part1=~ /^\s*\*/ ) {
			$type2=$type2." __attribute__((aligned(2)))";
		}
	} elsif( $type=~ /^unsigned$/ ) {
		$type2=$type2." __attribute__((aligned(2)))";
	} elsif( $type=~ /^(int|long)$/ ) {
		$type=$type." __attribute__((aligned(2)))";
	} elsif( $part1=~ /^(\*|\(\*)/ ) {
		$type=$type." __attribute__((aligned(2)))";
	}
	return $space.$type.$space2.$type2.$part1.";";
}
