* fixed GCC 4.4.0 mingw compilation:
[fw/sdcc] / support / scripts / inc2h.pl
index 02dce1caefc137c9c82213c16b894c8e61158d23..7fa4151cec9422067e9d39873dc8adb05f706eda 100755 (executable)
@@ -1,4 +1,6 @@
-#!/usr/bin/perl
+#!/usr/bin/perl -w
+
+use strict;
 
 # Copyright (c) 2002 Kevin L. Pauba
 
 # 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)
+#####################################################################
+# >>> How to add a new device to SDCC PIC14 port?
+#
+# This description assumes that you have a copy of SDCC's sources
+# in /path/to/sdcc and a (source or installed) version of gputils
+# in /path/to/gputils (the only important point here is that
+# /path/to/gputils/headers must exist and contain "p<DEVICE>.inc").
+# Furthermore, I assume you want to add support for the 16f887 device
+# (note: no 'pic' or 'p' prefix!), change this as desired.
+# inc2h.pl can only deal with one single device at a time; repeat the
+# ../inc2h.pl-step as often as required.
+#
+# The proposed sequence of commands is then:
+#
+# $ cd /path/to/sdcc/support/scripts
+# $ mkdir build && cd build
+# $ ../inc2h.pl 16f887 /path/to/gputils
+# $ mv pic16f887.c /path/to/sdcc/device/lib/pic/libdev
+# $ mv pic16f887.h /path/to/sdcc/device/include/pic
+# $ vim /path/to/sdcc/device/include/pic/pic14devices.inc
+# 
+# # Use any pure text editor you like (`[Esc]:q![Enter]' quits Vim ;-)).
+# # Add a record for the new device to the file; usually you can copy
+# # the record of a similar device and adjust the values using the
+# # datasheet. The format of pic14devices.txt is explained in the file
+# # itself. Please keep the file sorted.
+# # When you are done:
+#
+# $ cd /path/to/sdcc/device/lib
+# $ make model-pic14
+# $ make install 
+#
+# Congratulations, you have just added support for a new device to
+# the port. You may consider posting your (changes to)
+# pic14devices.txt and the generated files (picDEVICE.[ch]) to
+# have them included into the official source tree.
+# Some testing beforehand would be appreciated, though.
+#####################################################################
+
+my $rcsid = q~$Id$~;
+my ($junk, $file, $version, $date, $time, $programmer, $status)
     = split(/\s+/, $rcsid);
-($programName) = ($file =~ /(\S+)/);
+my ($programName) = ($file =~ /(\S+)/);
 
 if ($#ARGV < 0 || $#ARGV > 1 ) {
     Usage();
 }
-$processor = uc(shift);
-$path = shift;
-
+my $processor = uc(shift);
+my $path = shift;
+my %sfrs = ();
+my %alias = ();
+my %bits = ();
+my %bitmasks = ();
+my %addr = ();
+my %ram = ();
+my $path_delim = "/";
+my $devices = "";
+my %types = ();
+my $type = "";
 
 # just in time fixes for some register names
 sub fixname {
@@ -55,7 +104,7 @@ sub checkname {
            print "  but ".$name."0 exists---using that instead.\n";
            return $name."0";
        }
-       $try = $name;
+       my $try = $name;
        $try =~ s/[0-9]$//;
        if (exists $sfrs{$try}) {
            print "  but $try exists---using that instead.\n";
@@ -78,6 +127,7 @@ sub contained {
 }
 
 
+$path = "" if (!defined $path);
 if ($^O eq 'MSWin32') {
     if ($path eq '') {
        if (defined($path = $ENV{'GPUTILS_HEADER_PATH'}) || defined($path = $ENV{'GPUTILS_LKR_PATH'})) {
@@ -125,22 +175,22 @@ while (<DATA>) {
        # of all registers.
        # 
        # $addr{"$1"} = $2;
-       foreach $device (split(/[,\s]+/, $devices)) {
+       foreach my $device (split(/[,\s]+/, $devices)) {
            $addr{"p$device", "$1"} = $2;
        }
     } elsif (/^\s*bitmask\s+(\S+)\s+/) {
        #
        # Set the bitmask that will be used in the 'memmap' pragma.
        #
-       $bitmask = "$1";
-       foreach $register (split(/\s+/, $')) {
-           $bitmask{"$register"} = $bitmask;
+       my $bitmask = "$1";
+       foreach my $register (split(/\s+/, $')) {
+           $bitmasks{"$register"} = $bitmask;
        }
     } elsif (/^\s*ram\s+(\S+)\s+(\S+)\s+(\S+)/) {
        # This info is now provided in "include/pic/pic14devices.txt".
        #$lo = $1;
        #$hi = $2;
-       #$bitmask = $3;
+       #my $bitmask = $3;
        #foreach $device (split(/[,\s]+/, $devices)) {
        #    $ram{"p$device"} .= "#pragma memmap $lo $hi RAM $bitmask$'";
        #}
@@ -150,12 +200,12 @@ while (<DATA>) {
     } elsif (/^\s*(\S+)/) {
        $type = $1;
        $_ = $';
-       foreach $key (split) {
-           eval "\$type{'$key'} = $type;";
+       foreach my $key (split) {
+           eval "\$types{'$key'} = $type;";
        }
     } else {
-       foreach $key (split) {
-           eval "\$type{'$key'} = $type;";
+       foreach my $key (split) {
+           eval "\$types{'$key'} = $type;";
        }
     }
 }
@@ -184,8 +234,8 @@ while (<DATA>) {
 #  }
 
 # Create header for pic${processor}.c file
-$lcproc = "pic" . lc($processor);
-$c_head = <<EOT;
+my $lcproc = "pic" . lc($processor);
+my $c_head = <<EOT;
 /* Register definitions for $lcproc.
  * This file was automatically generated by:
  *   $programName V$version
@@ -198,11 +248,16 @@ EOT
 #
 # Convert the file.
 #
-%sfrs = ();
-$defaultType = 'other';
-$includeFile = $path.$path_delim.'header'.$path_delim.'p'.lc($processor).'.inc';
-$headFile = "pic" . lc($processor) . ".h";
-$defsFile = "pic" . lc($processor) . ".c";
+my $defaultType = 'other';
+my $includeFile = $path.$path_delim.'header'.$path_delim.'p'.lc($processor).'.inc';
+my $headFile = "pic" . lc($processor) . ".h";
+my $defsFile = "pic" . lc($processor) . ".c";
+
+my $body = "";
+my $header = "";
+my $addresses = "";
+my $pragmas = "";
+
 open(HEADER, "<$includeFile")
     || die "$programName: Error: Cannot open include file $includeFile ($!)\n";
 
@@ -215,7 +270,7 @@ while (<HEADER>) {
     } elsif (/^;-+\s*(\S+)\s+Bits/i || /^;-+\s*(\S+)\s+-+/i) {
        # The second case is usually bits, but the word Bits is missing
         # also accept "UIE/UIR Bits"
-       foreach $name (split(/\//, $1)) {
+       foreach my $name (split(/\//, $1)) {
            $name = fixname($name);
            $name = checkname($name);
 
@@ -246,26 +301,27 @@ while (<HEADER>) {
        #
        # Useful bit of information.
        #
-       $name = $1;
-       $value = $2;
-       $rest = $';
+       my $name = $1;
+       my $value = $2;
+       my $rest = $';
+       my $bitmask = "0x0000";
+
        $rest =~ s/;/\/\//;
        chomp($rest);
 
-       if (defined($type{"p$processor", "$name"})) {
-           $type = $type{"p$processor", "$name"};
-       } elsif (defined($type{"$name"})) {
-           $type = $type{"$name"};
+       if (defined($types{"p$processor", "$name"})) {
+           $type = $types{"p$processor", "$name"};
+       } elsif (defined($types{"$name"})) {
+           $type = $types{"$name"};
        } else {
            $type = $defaultType;
        }
+       #print "$name --> $type\n"; ## DEBUG
 
-       if (defined($bitmask{"p$processor", "$name"})) {
-           $bitmask = $bitmask{"p$processor", "$name"};
-#      } elsif (defined($bitmask{"$name"})) {
-#          $bitmask = $bitmask{"$name"};
-       } else {
-           $bitmask = "0x000";
+       if (defined($bitmasks{"p$processor", "$name"})) {
+           $bitmask = $bitmasks{"p$processor", "$name"};
+#      } elsif (defined($bitmasks{"$name"})) {
+#          $bitmask = $bitmasks{"$name"};
        }
 
        if ($type eq 'sfr') {
@@ -302,11 +358,24 @@ while (<HEADER>) {
                $addresses .= sprintf("#define %s_ADDR\t0x%s\n", $name, $value);
            }
        } elsif ($type =~ /^bits/) {
-           ($junk, $register) = split(/\s/, $type);
-           $bit = hex($value);
-           $addr = $addr{"$register"};
+           my ($junk, $register) = split(/\s/, $type);
+           my $bit = hex($value);
+           my $addr = $addr{"$register"};
+
            # prepare struct declaration
-           for ($k=0; $k < scalar @{$bits{"$register"}->{oct($bit)}}; $k++) {
+           if (0) { # DEBUG
+               foreach my $key (keys %bits) {
+                   print "   $key\n";
+               }
+               print "$register // $bit // ".$bits{"$register"}."\n";
+           }
+           if (!defined $bits{"$register"}) {
+               $bits{"$register"} = {}; # reference to empty hash
+           }
+           if (!defined $bits{"$register"}->{oct($bit)}) {
+               $bits{"$register"}->{oct($bit)} = []; # reference to empty array
+           }
+           for (my $k=0; $k < scalar @{$bits{"$register"}->{oct($bit)}}; $k++) {
              $name = "" if ($bits{"$register"}->{oct($bit)} eq $name)
            }
            if (($name ne "")
@@ -340,7 +409,10 @@ while (<HEADER>) {
        #
        $body .= "\n";
     } elsif (/__MAXRAM\s+H'([0-9a-fA-F]+)'/) {
-       $maxram .= "//\n// Memory organization.\n//\n";
+       my $maxram .= "//\n// Memory organization.\n//\n";
+       if (!defined $ram{"p$processor"}) {
+           $ram{"p$processor"} = "";
+       }
        $pragmas = $maxram
            . $ram{"p$processor"} . "\n"
                . $pragmas;
@@ -436,18 +508,26 @@ EOT
   }
 }
 
-$structs = "";
+my $structs = "";
 ## create struct declarations
-foreach $reg (sort keys %bits)
+foreach my $reg (sort keys %bits)
 {
   $structs .= "// ----- $reg bits --------------------\n";
   $structs .= "typedef union {\n";
-  $idx = 0; $max = 1;
+  my $idx = 0;
+  my $max = 1;
   do {
     $structs .= "  struct {\n";
-    for ($i=0; $i < 8; $i++)
+    for (my $i=0; $i < 8; $i++)
     {
-      @names = @{$bits{$reg}->{oct($i)}};
+      if (!defined $bits{$reg}) {
+         #print "bits{$reg} undefined\n";
+      }
+      if (!defined $bits{$reg}->{oct($i)}) {
+         #print "bits{$reg}->{".oct($i)."} undefined\n";
+         $bits{$reg}->{oct($i)} = []; # empty array reference
+      }
+      my @names = @{$bits{$reg}->{oct($i)}};
       if ($max < scalar @names) { $max = scalar @names; }
       if ($idx >= scalar @names) {
        $structs .= "    unsigned char :1;\n";
@@ -471,13 +551,15 @@ foreach $reg (sort keys %bits)
   #}
   
   # emit defines for individual bits
-  for ($i=0; $i < 8; $i++)
+  $structs .= "#ifndef NO_BIT_DEFINES\n";
+  for (my $i=0; $i < 8; $i++)
   {
-    @names = @{$bits{$reg}->{oct($i)}};
-    foreach $field (@names) {
+    my @names = @{$bits{$reg}->{oct($i)}};
+    foreach my $field (@names) {
       $structs .= sprintf("#define %-20s ${reg}_bits.$field\n", $field);
     } # foreach
   }
+  $structs .= "#endif /* NO_BIT_DEFINES */\n";
   $structs .= "\n";
 } # foreach