# Get rid of all line endings, regardless of which flavor they are
(my $line = shift) =~ s/[\r\n]//g;
####
# does this look like a S1, S2, or S3 record? These are the only ones that
# carry an actual data payload. Other record types do not, so just ignore
# them.
return unless $line =~ m/^s([1-3])(\p{IsXDigit}{2})(\p{IsXDigit}{4,6,8})(\p{IsXDigit}+)(\p{IsXDigit}{2})$/;
my ($type, $count, $address, $data, $cs) = ($1, $2, $3, $4, $5);
# does the address length match the record type?
return unless length $address == 2 * ($type + 1);
# Make sure the COUNT field makes sense. It should represent the sum of
# address, data, and checksum fields, in bytes
return unless hex($count) == (length($address) + length($data) + length($cs)) / 2;
####
my $compCs = hex($count);
foreach my $nibble ($address =~ m/../g, $data =~ m/../g) {
$compCs += hex($nibble);
}
####
my $compCs = hex($count);
$compCs += hex($_) foreach($address =~ m/../g, $data =~ m/../g);
####
my $compCs = reduce { $a + $b }
map { hex $_ }
($count, $address =~ m/../g, $data =~ m/../g);
####
my $status = $compCs == hex($cs);
####
use List::Util;
# ...
# Parse a single line of S-record, validate the line, and extract the address
# and data fields. Return a list of three scalars:
# 1. TRUE if extraction was successful, FALSE otherwise (i.e. not a valid data
# carrying S-record, bad s-record length, bad s-record checksum).
# 2. The address of the line's payload, as a string.
# 3. The data of the line's payload, as a string.
sub ProcessSrecLine
{
# Get rid of all line endings, regardless of which flavor they are
(my $line = shift) =~ s/[\r\n]//g;
# does this look like a S1, S2, or S3 record? These are the only ones that
# carry an actual data payload. Other record types do not, so just ignore
# them.
return unless $line =~ m/^s([1-3])(\p{IsXDigit}{2})(\p{IsXDigit}{4,6,8})(\p{IsXDigit}+)(\p{IsXDigit}{2})$/;
my ($type, $count, $address, $data, $cs) = ($1, $2, $3, $4, $5);
# does the address length match the record type?
return unless length $address == 2 * ($type + 1);
# Make sure the COUNT field makes sense. It should represent the sum of
# address, data, and checksum fields, in bytes
return unless hex($count) == (length($address) + length($data) + length($cs)) / 2;
# Make sure the checksum makes sense. It is the two's complement of
# the sum of count, address, and data fields
my $compCs = reduce { $a + $b }
map { hex $_ }
($count, $address =~ m/../g, $data =~ m/../g);
$compCs %= 256;
$compCs = 255 - $compCs;
# if the checksum actually matches, then call it a good S-record
my $status = $compCs == hex($cs);
return ($status, $address, $data);
}
####
# ...
# if the checksum actually matches, then call it a good S-record
return ($compCs == hex($cs), $address, $data);