=pod =head1 Nova Software, Inc. http://www.nova-sw.com =head2 Perl Code Obscurer (Obscure.pl) Strips comments, blank lines, and indentation from a perl source code file, and then substitutes non-mnemonic names for variable and subroutine names. Passes through pod anywhere in the file verbatim, as well as anything following an '__END__' or '__DATA__' literal. The output file is useable perl code and will run on the perl 5.6 interpreter, but is more difficult for others to understand, follow and modify than the input source. Call with the pathnames of the input and output files in that order as arguments. Writes the substitution totals and lists to a file named .sub and leaves an intermediate (pre-substitution file) .tmp in the same directory as the output file. Provides a progressing line count on STDOUT during execution and dies with a message if the list of substitute names is exhausted before the input file is completely processed. Limitations: -Comments must begin with '##' or '# '. This condition is for simplicity, and could be relaxed. -Sub names should not be dictionary words, to avoid substitution into text strings. -Labels and constants are not renamed. -Variables to be renamed must declared in 'my' statements. -Does not rename any variable beginning with 'tmp' due to the author's custom of liberal use of such names as local scratchpad variables in his code. Copyright by Nova Software, Inc. 2001 All rights reserved. Written and maintained by James Eshelman, Oct, 2001 This program is free software; you can use, redistribute, and/or modify it under the same terms as Perl itself. =cut use strict; use v5.6.1; my ($t,$i,$a,$b,$c); my (@t1,%subs,%strs,%arys,%hshs); my ($pod,$numnames); my @names = qw(aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at au av aw ax ay az ba bb bc bd b1 bf bg bh bi bj bk bl bm bn bo bp bq br bs bt bu bv bw bx b2 bz ca cb cc cd ce cf cg ch ci cj ck cl cm cn co cp cq cr cs ct cu cv cw cx cy cz da db dc dd de df dg dh di dj dk dl dm dn d1 dp dq dr ds dt du dv dw dx dy dz ea eb ec ed ee ef eg eh ei ej ek el em en eo ep e1 er es et eu ev ew ex ey ez fa fb fc fd fe ff fg fh fi fj fk fl fm fn fo fp fq fr fs ft fu fv fw fx fy fz ga gb gc gd g1 gf gg gh gi gj gk gl gm gn g2 gp gq gr gs g3 gu gv gw gx gy gz ha hb hc hd h1 hf hg hh h2 hj hk hl hm hn h3 hp hq hr hs ht hu hv hw hx hy hz ia ib ic i1 i2 i3 ig ih ii ij ik il im i4 i5 i6 iq ir i7 i8 iu iv iw ix iy iz ja jb jc jd je jf jg jh ji jj jk jl jm jn jo jp jq jr js jt ju jv jw jx jy jz ka kb kc kd ke kf kg kh ki kj kk kl km kn ko kp kq kr ks kt ku kv kw kx ky kz la lb l1 ld l2 lf lg lh li lj lk ll lm ln l3 lp lq lr ls l4 lu lv lw lx ly lz ma mb mc md m1 mf mg mh mi mj mk m2 mm mn mo mp mq mr ms mt mu mv mw mx m3 mz); $numnames=$#names; open FH1, "<$ARGV[0]" or die "Can't open $ARGV[0] due to: $! \n"; open FH2, ">$ARGV[1].tmp" or die "Can't open $ARGV[1].tmp due to: $! \n"; open FH3, ">$ARGV[1].sub" or die "Can't open $ARGV[1].sub due to: $! \n"; print "\nNumber of names available = $numnames\n\nProgram lines processed:\n"; print FH3 "\nNumber of names available = $numnames\n\nProgram lines processed = "; while () { $i++; print "$i\r"; /^__END__|^__DATA__/ and print(FH2 $_) and last; # Disk writes are not checked for errors due to laziness! /^=pod/ and $pod=1 and print(FH2 $_) and next; /^=cut/ and $pod=0 and print(FH2 $_) and next; $pod and print(FH2 $_) and next; s/#\s.*|##.*//g; s/^\s*//; s/^\n//; print FH2 $_; if (/^sub\s+\w+\s+/) { @t1=split; $t1[1]=~/BEGIN/ or $subs{$t1[1]}=shift@names; } if (/\s*my\s+/) { @t1=(); @t1=split /,/,$'; foreach $a (@t1) { next if $a=~/\$tmp\w*/; next if $a=~'@tmp\w*'; next if $a=~/%tmp\w*/; next if $a=~'@_'; if ($a=~/\$\w+/) { $b=$&; $c=substr $b,1; $strs{$c} or $strs{$c}=shift@names; } if ($a=~/@\w+/) { $b=$&; $c=substr $b,1; $arys{$c} or $arys{$c}=shift@names; } if ($a=~/%\w+/) { $b=$&; $c=substr $b,1; $hshs{$c} or $hshs{$c}=shift@names; } } } @names or die "\n\n >>>>>>> OUT OF NAMES! <<<<<<<<\n\n"; } while () { $i++; print "$i\r"; print FH2 $_} print FH3 "$i\n"; close FH1; close FH2; open FH1, "<$ARGV[1].tmp" or die "Can't open $ARGV[1].tmp due to: $! \n"; open FH2, ">$ARGV[1]" or die "Can't open $ARGV[1] due to: $! \n"; print "\n\nIntermediate file lines:\n"; print FH3 "\n\nIntermediate file lines = "; $i=0; while () { $i++; print "$i\r"; /^__END__|^__DATA__/ and print(FH2 $_) and last; /^=pod/ and $pod=1 and print(FH2 $_) and next; /^=cut/ and $pod=0 and print(FH2 $_) and next; $pod and print(FH2 $_) and next; my $ln=$_; # Note: order of matching is chosen to minimize accidental matches in sub-strings. foreach $a (keys %hshs) { $b='%'.$a; $c='%'.$hshs{$a}; $ln=~s/$b/$c/g; $b='\$'.$a.'\{'; $c='$'.$hshs{$a}.'{'; $ln=~s/$b/$c/g; } foreach $a (keys %arys) { $b='@'.$a; $c='@'.$arys{$a}; $ln=~s/$b/$c/g; $b='\$'.$a.'\['; $c='$'.$arys{$a}.'['; $ln=~s/$b/$c/g; } foreach $a (keys %strs) { $b='\$'.$a; $c='$'.$strs{$a}; $ln=~s/$b(\W)/$c$1/g; } foreach $a (keys %subs) { $c=$subs{$a}; $ln=~s/$a/$c/g; } print FH2 $ln; } while () { $i++; print "$i\r"; print FH2 $_} print FH3 "$i\n"; close FH1; close FH2; $t=$numnames-$#names; print "\n\nNumber of names used = $t\n"; print FH3 "\n\nNumber of names used = $t\n"; print "\nWriting the symbol substitution lists in $ARGV[1].sub...\n"; print FH3 "\n\nsubs\n\n"; foreach (keys(%subs)) { print FH3 $_,"\t",$subs{$_},"\n";} print FH3 "\nstrings\n\n"; foreach (keys(%strs)) { print FH3 '$',$_,"\t",'$',$strs{$_},"\n";} print FH3 "\narrays\n\n"; foreach (keys(%arys)) { print FH3 '@',$_,"\t",'@',$arys{$_},"\n";} print FH3 "\nhashes\n\n"; foreach (keys(%hshs)) { print FH3 '%',$_,"\t",'%',$hshs{$_},"\n";} close FH3; __END__