Newsgroups: perl.perl6.internals
From: ni...@glencros.demon.co.uk (Nick Glencross)
Date: Tue, 27 Apr 2004 15:58:32 +0100
Local: Tues, Apr 27 2004 10:58 am
Subject: md5sum, in parrot
for fun I've written md5sum using IMCC, and have attached my first cut. It will need some further testing, but in the most part it works well. * 200K file limit imposed when reading in the file It would be nice to make sure that it works on all architectures as it The only problems have been: * Using macros which call one another seemed to hang if argument names Cheers, Nick
[
=head1 NAME md5sum.imc - calculate MD5 checksums =head1 SYNOPSIS =head1 DESCRIPTION This is a pure Parrot MD5 hash routine. =head1 SUBROUTINES =head2 _md5sum Pass in a string, returns a PMC Array with the result =head1 BUGS Only tested so far on i386. =over 4 =item * Might work on 64 bit platforms =item * Might not work on big endian systems =back =cut ########################################################################### # Main Harness to show that it works .sub _main .local Array args args = P5 # Argument count if $I0 > 0 goto has_args $S0 = args[0] end has_args: maxsize = 200000 $I1 = 1 next_iter: if $I1 > $I0 goto iter_done $S0 = args[$I1] open $P0, $S0, "<" $I2 = length $S1 printerr "Too large\n" size_ok: $P0 = _md5sum ($S1) _md5_print ($P0) iter_cont: $I1 = $I1 + 1 iter_done: end .end ########################################################################### # A parrot rol instruction might be good (as it can often be JIT'd) .macro FF (b,c,d) .macro FH (b,c,d) .macro FI (b,c,d) ########################################################################### .macro common (a, b, k, s, T) .macro OP1 (aa,bb,cc,dd, kk, ss, TT) .macro OP2 (aa,bb,cc,dd, kk, ss, TT) .macro OP3 (aa,bb,cc,dd, kk, ss, TT) .macro OP4 (aa,bb,cc,dd, kk, ss, TT) ########################################################################### .macro swap (w) $I10 = .w & 0x000000ff $I10 = $I10 << 24 $I10 = $I10 | $I11 # For 64-bit architectures .endm ########################################################################### .include "library/config.imc" .sub _md5sum $P0 = _config() $I0 = $P0["intsize"] printerr "This doesn't seem to be a 32 bit processor: " is_4byte_word: $I0 = $P0["bigendian"] unless $I0 goto is_little_endian printerr "This appears to be a big endian processor: " is_little_endian: .local Array buffer $P0 = new Array _md5_create_buffer (str, buffer, $I0) # _print_buffer (buffer, 8) _md5_init ($P0) .pcc_begin_return ########################################################################### .sub _md5_init # Initial MD5 constants .end ########################################################################### .sub _md5_create_buffer .local int counter .local int word $I0 = length str $I1 = $I0 - 1 .local int words buffer = words word = 0 counter = 0 md5_create_buffer_loop: $I5 = counter + subcounter if $I5 > $I0 goto md5_create_buffer_break # MD5 pad character if $I5 > $I1 goto string_char string_char: word = word << 8 subcounter = subcounter + 1 if subcounter != 4 goto md5_create_buffer_loop if endian goto endian_ok .swap (word) endian_ok: buffer[slow_counter] = word word = 0 goto md5_create_buffer_loop md5_create_buffer_break: # Check for a partial word if subcounter == 0 goto complete subcounter = 4 - subcounter .local int shift word = word << shift if endian goto endian_ok2 .swap (word) endian_ok2: buffer[slow_counter] = word complete: $I1 = $I0 >>> 29 $I0 = $I0 << 3 .end ########################################################################### .sub _md5_process_buffer .local int A .local int A_save .local int tmp $P0 = new Array A = context[0] md5_loop: A_save = A # Round 1. # Round 2. # Round 3. # Round 4. A += A_save splice buffer, $P0, 0, 16 if $I0 > 0 goto md5_loop context[0] = A # _print_vals (A,B,C,D) .end ########################################################################### .sub _number_as_hex $P0 = new Array $S1 = "%0" sprintf $S0, $S1, $P0 .pcc_begin_return ########################################################################### .sub _print_vals $P0 = new Array sprintf $S0, "%08lx %08lx %08lx %08lx", $P0 ########################################################################### .sub _md5_print .local int A A = context[0] $P0 = _config() $I0 = $P0["bigendian"] if $I0 goto dont_swap .swap (A) dont_swap: _print_vals (A,B,C,D) ########################################################################### # For debugging .sub _print_buffer .local int size size = buffer .local int counter counter = 0 print_buffer_done: print "\n" You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
| ||||||||||||||