#!/usr/local/bin/perl -w # ======================================================================== # extract_code - extract sample MD5 implementation from RFC 1321 text # Andrew Ho (andrew@tellme.com) # # usage: extract_code filename < rfc1321.txt # # This script extracts the sample code from Appendix A of RFC 1321. # Give it the filename that you want to extract (for example, md5.h). # The text RFC is downloadable from http://www.ietf.org/rfc/rfc1321.txt. # # There is special functionality to add largefile support to mddriver.c, # and to un-munge the test suite from appendix A.5. # # $Id: extract_code,v 1.2 2004/07/02 00:26:16 andrew Exp $ # ======================================================================== require 5.005; use strict; $| = 1; use File::Basename qw(basename); use vars qw($ME); $ME = basename $0; my $filename = shift; die "$ME: required argument missing\nusage: $ME filename\n" unless defined $filename; # ---------------------------------------------------------------------- # Main loop that finds the source code and accumulates it into $text my $text = undef; my $file = undef; while(<>) { if(/^A\.\d+.*\b(\Q$filename\E)\b/i) { # Found appendix header that has the source listing we want $file = lc $1; <> unless eof; # skip blank line following appendix header $text = ''; } elsif(defined $file) { if(/^Rivest\s+\[Page\s+\d+\]$/) { # Found middle of page break chomp $text for 1..3; # chomp last three blanks for(1..4) { <>; last if eof } # skip next four page lines } elsif(/^A\.\d+\s+/) { # Found some other appendix that is not what we want undef $file; last; } else { # Found regular text, accumulate it $text .= $_; } } } # ---------------------------------------------------------------------- # Source code postprocessing # Postprocess mddriver.c to enable largefile support if($filename =~ /mddriver\.c/i) { my $header = << " EndHeader"; /* enable large files early on (added by $ME) */ #undef _FILE_OFFSET_BITS /* to clear compilation warning */ #define _FILE_OFFSET_BITS 64 /* enable large files */ #include /* for large file types */ EndHeader $text = join "\n", $header, $text; # Postprocess test suite output to sanitize text file weirdness } elsif($filename =~ /test suite/i) { $text =~ s/^.+?(MD5 test suite:)/$1/si; # cut out beginning before "MD5 test suite" $text =~ s/\n\s*\n.*$//s; # remove anything after blanks begin $text =~ s/\n(?!MD5)//gs; # remove spurious linebreaks $text =~ s/\s*=\s*/ = /g; # clean up equal signs $text .= "\n"; # restore final linebreak } # Silence gcc warnings by adding extra parens to predicate assignments $text =~ s/\b(while|if)(\s*)(\((?!\s*\()[^=\)]+\=[^=\)]+?\))/$1$2($3)/gsx; # ---------------------------------------------------------------------- # Output text print $text; exit 0; # ======================================================================== __END__