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