chiark / gitweb /
undo broken deletion
[trains.git] / cebpic / merge-hex
1 #!/usr/bin/perl -w
2 # See http://www.precma.it/download/intelhex.pdf
3 #
4 # Written by Ian Jackson in November/December 2005.
5 # I hereby waive my copyright in this file.  - Ian Jackson 16.12.2005.
6 # $Id$
7
8 use strict qw(refs vars);
9
10 our ($lba,$sba,$loc,$eof,%once);
11
12 $lba=$sba=0;
13
14 sub once {
15     my ($r) = @_;
16     my ($o);
17     $o= \$once{$_[0]};
18     if (!defined $$o) { $$o= $loc; return; }
19     die sprintf("%s: %s: clash at 0x%x (1st)\n".
20                 "%s: %s: clash at 0x%x (2nd)\n",
21                 $0, $$o, $r, $0, $loc, $r);
22 }
23
24 sub bad ($) { my ($m)=@_; die "$0: $loc: $m\n"; }
25
26 my ($drlo,$dri,$orgline,$la);
27
28 while (<>) {
29     $orgline= $_;
30     $loc= "$ARGV:$.";
31     
32     chomp; # General Record Format, p5
33     s/^\:// or bad('no colon');
34     $_= lc $_;
35     m/[^0-9a-f]/ and bad("bad char ".ord($&));
36     length() & 1 and bad('odd length');
37
38     s/..$//; # chop checksum (we don't check this)
39     s/^..//; # chop reclen (we don't check this)
40
41     if (s/^000001//) { # End of File, p11
42         $eof= $orgline;
43         if ($lba)    { $orgline= ":020000040000FA\n"; $lba=0; }
44         elsif ($sba) { $orgline= ":020000020000FC\n"; $sba=0; }
45         else { next; }
46     } elsif (s/^000004(....)$//) { $lba= hex($1)<<16; } # Ext'd Linear Addr, p6
47     elsif (s/^000002(....)$//) { $sba= hex($1)<<4; } # Ext'd Seg. Addr., p7
48     elsif (s/^(....)00//) { # Data Record, p8
49         $drlo= hex $1;
50         for ($dri=0; s/^..//; $dri++) {
51             bad('both LBA and SBA') if $lba && $sba;
52             if ($lba) { $la= ($lba+$drlo+$dri) & 0x0ffffffff; }
53             elsif ($sba) { $la= $sba + (($drlo+$dri) & 0xffff); }
54             else { $la= $drlo+$dri; }
55 #print STDERR ">$lba|$sba|$drlo|$dri|$la|$_<\n";
56             once($la);
57         }
58     }
59     elsif (s/^000005//) { once('start'); } # Start Linear Address, p9
60     elsif (s/^000003//) { once('start'); } # Start Segment Address, p10
61     else {
62         bad('unknown record or bad record');
63     }
64     print $orgline or die $!;
65 }
66
67 our ($lx,$ld);
68
69 $lx= 0;
70 $ld= '';
71 sub pf {
72     my ($f) = shift @_;
73     my ($s) = sprintf $f, @_;
74     if ($s =~ m/^\s/ && length($ld.$s) > 70) {
75         print STDERR $ld,"\n" or die $!; $ld= " ";
76     }
77     $ld.= $s;
78 }
79 sub pf_end () {
80     print STDERR $ld,"\n" or die $!;
81 }
82
83 my ($ca,$a1);
84 undef $la;
85 foreach $ca (sort { $a <=> $b } keys %once) {
86     next if defined($la) && $ca == ++$la;
87     defined($la) and
88         --$la != $a1 and
89             pf("-%x", $la);
90     pf("  %x", $ca);
91     $la=$a1=$ca;
92 }
93 if (!defined($la)) {
94     pf("  empty");
95 } elsif ($la != $a1) {
96     pf("-%x", $la);
97 }
98 pf_end();
99
100 die "$0: no input files or missing EOF markers\n" unless defined $eof;
101 print $eof or die $!;