default: all
+#---------- general definitions etc. ----------
+
+TARGETS += $(foreach i, $(PICNOS), idlocs$i.hex noncode$i.hex)
+MORSE_INCLUDE ?= common.inc
+INCLUDES += ../iwjpictest/insn-aliases.inc morse+auto.inc
+
+include ../common.make
+include ../pic.make
+
#---------- bizarre macro arrangements for $(PROGRAMS) ----------
define define_prog
$(1)_CODEHEX= $$(foreach panel, $$(XCODEN_$(1)), $(1)+$$(panel).hex) \
$$(foreach panel, $$(XCODE1_$(1)), $$(panel).hex)
-$(1)+code.hex: $(1)+program.hex $$($(1)_CODEHEX)
+$(1)+code.hex: $$(HEXMERGER) $(1)+program.hex $$($(1)_CODEHEX)
$$(MERGEHEX)
-$(1)+entire%.hex: $(1)+program.hex $$($(1)_CODEHEX) idlocs%.hex config.hex
+$(1)+entire%.hex: $$(HEXMERGER) $(1)+program.hex $$($(1)_CODEHEX) idlocs%.hex config.hex
$$(MERGEHEX)
$(1)+program.hex: $(1).o $$(OBJS_$(prog)) $$(LIBS)
define define_directasm
-$(1).hex: $(1).asm
+$(1).hex: $(1).asm $$(INCLUDES)
$$(ASSEMBLE) $$<
endef
echo >>$@.new " end"
mv -f $@.new $@
-#---------- general definitions etc. ----------
-
-TARGETS += $(foreach i, $(PICNOS), idlocs$i.hex noncode$i.hex)
-MORSE_INCLUDE ?= common.inc
-INCLUDES += ../iwjpictest/insn-aliases.inc morse+auto.inc
-
-include ../common.make
-include ../pic.make
-
#---------- targets ----------
all: $(TARGETS)
-noncode%.hex: idlocs%.hex config.hex
+noncode%.hex: $(HEXMERGER) idlocs%.hex config.hex
$(MERGEHEX)
morse+auto.inc: $(CEBPIC)morse-generator morse.messages
-#!/usr/bin/perl
-$end= ':00000001FF';
+#!/usr/bin/perl -w
+# See http://www.precma.it/download/intelhex.pdf
+
+use strict qw(refs vars);
+
+our ($lba,$sba,$loc,$eof,%once);
+
+$lba=$sba=0;
+
+sub once {
+ my ($r) = @_;
+ my ($o);
+ $o= \$once{$_[0]};
+ if (!defined $$o) { $$o= $loc; return; }
+ die sprintf("%s: %s: clash at 0x%x (1st)\n".
+ "%s: %s: clash at 0x%x (2nd)\n",
+ $0, $$o, $r, $0, $loc, $r);
+}
+
+sub bad ($) { my ($m)=@_; die "$0: $loc: $m\n"; }
+
+my ($drlo,$dri,$orgline,$la);
+
while (<>) {
- chomp;
- next if uc $_ eq $end;
- print or die $!;
- print "\n" or die $!;
+ $orgline= $_;
+ $loc= "$ARGV:$.";
+
+ chomp; # General Record Format, p5
+ s/^\:// or bad('no colon');
+ $_= lc $_;
+ m/[^0-9a-f]/ and bad("bad char ".ord($&));
+ length() & 1 and bad('odd length');
+
+ s/..$//; # chop checksum (we don't check this)
+ s/^..//; # chop reclen (we don't check this)
+
+ if (s/^000001//) { # End of File, p11
+ $eof= $orgline;
+ if ($lba) { $orgline= ":020000040000f8"; $lba=0; }
+ elsif ($sba) { $orgline= ":020000020000fc"; $sba=0; }
+ else { next; }
+ } elsif (s/^000004(....)$//) { $lba= hex($1)<<16; } # Ext'd Linear Addr, p6
+ elsif (s/^000002(....)$//) { $sba= hex($1)<<4; } # Ext'd Seg. Addr., p7
+ elsif (s/^(....)00//) { # Data Record, p8
+ $drlo= hex $1;
+ for ($dri=0; s/^..//; $dri++) {
+ bad('both LBA and SBA') if $lba && $sba;
+ if ($lba) { $la= ($lba+$drlo+$dri) & 0x0ffffffff; }
+ elsif ($sba) { $la= $sba + (($drlo+$dri) & 0xffff); }
+ else { $la= $drlo+$dri; }
+#print STDERR ">$lba|$sba|$drlo|$dri|$la|$_<\n";
+ once($la);
+ }
+ }
+ elsif (s/^000005//) { once('start'); } # Start Linear Address, p9
+ elsif (s/^000003//) { once('start'); } # Start Segment Address, p10
+ else {
+ bad('unknown record or bad record');
+ }
+ print $orgline or die $!;
+}
+
+our ($lx,$ld);
+
+$lx= 0;
+$ld= '';
+sub pf {
+ my ($f) = shift @_;
+ my ($s) = sprintf $f, @_;
+ if ($s =~ m/^\s/ && length($ld.$s) > 70) {
+ print STDERR $ld,"\n" or die $!; $ld= " ";
+ }
+ $ld.= $s;
+}
+sub pf_end () {
+ print STDERR $ld,"\n" or die $!;
+}
+
+my ($ca,$a1);
+undef $la;
+foreach $ca (sort { $a <=> $b } keys %once) {
+ next if defined($la) && $ca == ++$la;
+ defined($la) and
+ --$la != $a1 and
+ pf("-%x", $la);
+ pf(" %x", $ca);
+ $la=$a1=$ca;
+}
+if (!defined($la)) {
+ pf(" empty");
+} elsif ($la != $a1) {
+ pf("-%x", $la);
}
-print $end or die $!;
-print "\n" or die $!;
+pf_end();
+
+die "$0: no input files or missing EOF markers\n" unless defined $eof;
+print $eof or die $!;