# 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);