#!/local/bin/perl # ------------------------------------------------------------------ # rfc-what-i-mean V1.0 # # Find the most recent/dependent RFCs from a list # # J. Touch # touch@isi.edu # http://www.isi.edu/touch # # USC Information Sciences Institute (USC/ISI) # Marina del Rey, California 90292, USA # Copyright (c) 2006 # # Revision date: Nov. 2, 2006 # ------------------------------------------------------------------ # # Copyright (c) 2006 by the University of Southern California. # All rights reserved. # # Permission to use, copy, modify, and distribute this software and # its documentation in source and binary forms for non-commercial # purposes and without fee is hereby granted, provided that the # above copyright notice appear in all copies and that both the # copyright notice and this permission notice appear in supporting # documentation, and that any documentation, advertising materials, # and other materials related to such distribution and use # acknowledge that the software was developed by the University of # Southern California, Information Sciences Institute. The name of # the University may not be used to endorse or promote products # derived from this software without specific prior written # permission. # # THE UNIVERSITY OF SOUTHERN CALIFORNIA MAKES NO REPRESENTATIONS # ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. THIS # SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # ------------------------------------------------------------------ # # usage: # rfc-what-i-mean rfc-index.txt yourfile.txt [> outputfile.txt] # # rfc-index.txt = RFC index file from www.rfc-editor.org # # yourfile.txt = file with RFCs to check, in format: # (RFC|rfc)(\s|\-)*(\d+) # # output = RFCs you really mean in two sets: # first set: one line each, your RFC and its # appropriate successor(s), including updates: # a single line "RFCS TO REPLACE:" # rfc2255 -> rfc4516 # rfc2798 -> rfc3698, rfc4517 # rfc3698 -> rfc3698, rfc4517 # a single line of "RFCS YOU MEAN:" # second set: one line each, of the sorted, # unique set of RFCs you want: # rfc3698 # rfc4516 # rfc4517 # # output may include warning errors, which appear as: # ERROR-WARN: # # ------------------------------------------------------------------ ############################################################ # GLOBAL variables ############################################################ my $debug = 0; # set to 1 to print debugging statements my %rfc; # rfc-index entry of the index my %obsoletedby; # things that obsolete the index my %updatedby; # things that update the index ############################################################ # debug print ############################################################ sub dprint($$) { my $name = shift; my $s = shift; print "$name: >$s<\n" if $debug; } ############################################################ # inputs the rfc-index.txt file ############################################################ sub readrfcs($) { my $fh = shift; my $line, $whole, $inrfc=0, *INFILE; while ($line = <$fh>) { $line =~ s/\r?\n?$//; # reset if new RFC entry if ($line =~ /^\d\d\d\d/) { if ($whole =~ /^(\d\d\d\d)/) { # prevents junk $rfc{"RFC$1"} = $whole; dprint("readrfcs","$whole"); } $whole = ""; } $whole .= $line; } # grab the last one you got if ($whole =~ /^(\d\d\d\d)/) { # prevents junk $rfc{$1} = $whole; dprint("readrfcs",$whole); } return %rfc; } ############################################################ # grab a list of RFC nums off of an obsoletes/updates list # used by getstructure ############################################################ sub getlist($) { my $s = shift; my @result = (); while ($s =~ s/(IEN|STD|NIC|RTR|RFC)\s*(\d+)//) { push(@result, $1 . $2); } warn "ERROR-WARN: getlist missed $s" if ($s !~ /^(\,|\s)+$/); return @result; } ############################################################ # creates datastructure t0 relate current RFCs to right ones ############################################################ sub getstructure() { # populate %obsoleteby, %updatedby my $k, @olist; foreach $k (sort(keys(%rfc))) { if ($rfc{$k} =~ /\(Obsoleted\s+by([^\)]+)\)/) { @olist = getlist($1); dprint("getstructure-obsoletedby","$k --> " . join(' ',@olist)); # RFC k is obsoleted by entries in olist $obsoletedby{$k} = join(' ',@olist); } if ($rfc{$k} =~ /\(Updated\s+by([^\)]+)\)/) { @olist = getlist($1); dprint("getstructure-updatedby","$k --> " . join(' ',@olist)); # RFC k is updated by entries in olist $updatedby{$k} = join(' ',@olist); } } } ############################################################ # given a desired RFCs, find the list you really want ############################################################ sub findwhatimean ($) { my $in = shift; my @outlist = (); my @inlist = (); my @finallist = (); my $changed = 0; my $item; dprint("findwhatimean","starting"); push(@inlist,$in); do { dprint("findwhatimean","in repeat with inlist = " . join(" ",@inlist)); @outlist = (); foreach $item (@inlist) { dprint("findwhatimean","in foreach"); $changed = 0; dprint("findwhatimean", "looking at $item"); # check whether to replace item if (defined($obsoletedby{$item})) { push(@outlist, split(/ /,$obsoletedby{$item})); dprint("findwhatimean","$item ==> $obsoletedby{$item}"); $changed = 1; } else { # keep this one dprint("findwhatimean","$item OK"); push(@finallist, $item); # check whether to add to item if (defined($updatedby{$item})) { dprint("findwhatimean","$item ++> $updatedby{$item}"); push(@outlist, split(/ /,$updatedby{$item})); $changed = 1; } } } @inlist = @outlist; } until ($changed == 0); # print the RFCS TO REPLACE: if (($#finallist != 0) || ($finallist[0] ne $in)) { print("Replace $in -> ", join(", ",@finallist), "\n"); } return @finallist; } ############################################################ # sort -u ############################################################ sub findset(@) { my @inlist = @_; my %inset; my $item; foreach $item (@inlist) { $inset{$item} = 1; } return sort(keys(%inset)); } ############################################################ ############################################################ # main ############################################################ ############################################################ { local *INFILE, *YOURFILE; my @list; print "RFC-WHAT-I-MEAN v1.0\n\n"; die "usage: $0 rfc-index.txt yourfile.txt\n" if ($#ARGV != 1); open(INFILE,$ARGV[0]) || die "rfc-index.txt file: $ARGV[0] could not be opened"; readrfcs(*INFILE); getstructure(); # get the input file list open(YOURFILE,$ARGV[1]) || die "your file: $ARGV[1] could not be opened"; dprint("main","reading $ARGV[1]"); { my $line; while ($line = ) { while ($line =~ s/rfc(\s|\-)*(\d+)//i) { # make RFCs in 4-digit format, as per rfc-index.txt dprint("main RFC list",sprintf("RFC%04d", $2)); push(@rfclist, sprintf("RFC%04d", $2)); } } } print "\nRFCS To Replace:\n\n"; { my $elt; my @wholelist = (); my $entry; foreach $elt (sort(@rfclist)) { push(@wholelist, findwhatimean($elt)); } @list = findset(@wholelist); } print "\n\nRFCs You Mean:\n\n"; print join("\n",@list), "\n"; }