#!/usr/bin/perl

# Copyright (c) 2002 Kevin L. Pauba


# License:
#
# SDCC is licensed under the GNU Public license (GPL) v2.  Note that
# this license covers the code to the compiler and other executables,
# but explicitly does not cover any code or objects generated by sdcc.
# We have not yet decided on a license for the run time libraries, but
# it will not put any requirements on code linked against it. See:
# 
# http://www.gnu.org/copyleft/gpl.html
#
# See http://sdcc.sourceforge.net/ for the latest information on sdcc.


$rcsid = q~$Id$~;
($junk, $file, $version, $date, $time, $programmer, $status)
  = split(/\s+/, $rcsid);
($programName) = ($file =~ /(\S+),v/);

if ($#ARGV != 0) {
	Usage();
}

#
# Read the symbols at the end of this file.
#
while (<DATA>) {
	next if /^\s*#/;

	if (/^alias\s+(\S+)\s+(\S+)/) {
		#
		# Set an alias for a special function register.
		# Some MPASM include files are not entirely consistent
		# with sfr names.
		#
		$alias{$2} = $1;
	} elsif (/^address\s+(\S+)\s+(\S+)/) {
		#
		# Set a default address for a special function register.
		# Some MPASM include files don't specify the address
		# of all registers.
		# 
		$addr{"$1"} = $2;
	} elsif (/^(\S+)/) {
		$type = $1;
	} else {
		foreach $key (split) {
			eval "\$type{'$key'} = $type;";
		}
	}
}

#
# Print the header.
#
print <<EOT;
//
// This header file was automatically generated by:
//
//\t$programName V$version
//
// 

#ifndef BIT_AT
#define BIT_AT(base,bitno) bit at ((base<<3)+bitno)
#endif


EOT

#
# Convert the file.
#
$defaultType = 'other';
while (<>) {
	if (/^;-* (\S+) Bits/i) {
		if (defined($alias{$1})) {
			$defaultType = "bits $alias{$1}";
		} else {
			$defaultType = "bits $1";
		}
		s/;/\/\//;
		print "$_";
	} elsif (/^;-* Register Files/i) {
		$defaultType = 'sfr';
		s/;/\/\//;
		print "$_";
	} elsif (/^;=*/i) {
		$defaultType = '';
		s/;/\/\//;
		print "$_";
	} elsif (/^\s*;/) {
		#
		# Convert ASM comments to C style.
		#
		print "//$'";
	} elsif (/^\s*IFNDEF __(\S+)/) {
		#
		# Processor type.
		#
		$processor = $1;
		print "//$_";
	} elsif (/^\s*(\S+)\s+EQU\s+H'(.+)'/) {
		#
		# Useful bit of information.
		#
		$name = $1;
		$value = $2;
		$rest = $';
		$rest =~ s/;/\/\//;
		chomp($rest);

		if (defined($type{"$name"})) {
			$type = $type{"$name"};
		} else {
			$type = $defaultType;
		}

		if ($type eq 'sfr') {
			#
			# A special function register.
			#
			printf("sfr at 0x%s %s;$rest\n", $value, $name);
			$addr{"$name"} = "0x$value";
		} elsif ($type eq 'volatile') {
			#
			# A location that can change without 
			# direct program manipulation.
			#
			printf("data at 0x%s volatile char %s;$rest\n", $value, $name);
		} elsif ($type =~ /^bits/) {
			($junk, $register) = split(/\s/, $type);
			$bit = hex($value);
			$addr = $addr{"$register"};
			printf("BIT_AT($addr,$bit) $name;$rest\n");
		} else {
			#
			# Other registers, bits and/or configurations.
			#
			if ($type eq 'other') {
				#
				# A known symbol.
				#
				printf("#define %-20s 0x%s$rest\n", $name, $value);
			} else {
				#
				# A symbol that isn't defined in the data
				# section at the end of the file.  Let's 
				# add a comment so that we can add it later.
				#
				printf("#define %-20s 0x%s$rest\n",
				       $name, $value);
			}
		}
	} elsif (/^\s*$/) {
		#
		# Blank line.
		#
		print;
	} else {
		#
		# Anything else we'll just comment out.
		#
		print "// $_";
	}
}

sub Usage {
	print STDERR <<EOT;

inc2h.pl - A utility to convert MPASM include files to header files
           suitable for the SDCC compiler.

License: Copyright (c) 2002 Kevin L. Pauba

	 SDCC is licensed under the GNU Public license (GPL) v2; see
	 http://www.gnu.org/copyleft/gpl.html See http://sdcc.sourceforge.net/
	 for the latest information on sdcc.

Usage:   $programName [file]

	 where:

	 file	A MPASM include file name.  If none is supplied, the
		standard input will be used.

	 The header file will be written to the standard output.


EOT
	exit;
}

__END__

alias OPTION_REG OPTION
address OPTION_REG 0x0081

sfr

volatile
	INDF PCL

bit

