#!/usr/bin/perl -w # # ao.pl # # 'Auto-obfuscator', or simple text compressor, for C programs. # # Replaces commonly-used long words with an abbreviation (which is # the first 1 or more characters from the beginning), and adds # '#define ABBR WORD' at the top of the file. Running the output # through the C preprocessor will give back the same file, although # whitespace will be different. # # Bugs: has absolutely no idea about strings. # # -- Ed Avis, epa98@doc.ic.ac.uk, 1999-09-12 # while (<>) { while (length) { s/^(\w+)// or s/^(\W+)// or die; push @{$l[$.]}, $1; } } foreach $l (1 .. $#l) { foreach (grep /^[a-zA-Z_]/, @{$l[$l]}) { $c{$_}++; $used{$_}++; } } while (($word, $freq) = each %c) { next if $freq == 1; # print "word $word appears $freq times, "; if (defined($abbrev = getabbrev($word))) { $al = (length "#define $word $abbrev\n") + (length $abbrev) * $freq; $l = (length $word) * $freq; if ($al < $l) { $used{$abbrev}++; $abbrev{$word} = $abbrev; print "#define $abbrev $word\n"; # print "abbrev is $abbrev\n"; } # else { print "abbrev is $abbrev, but not used\n"; } } # else { print "no abbrev\n" } } foreach $l (1 .. $#l) { foreach (@{$l[$l]}) { print defined $abbrev{$_} ? $abbrev{$_} : $_; } } sub getabbrev($) { my ($w) = @_; foreach my $l (1 .. (length $w) - 1) { my $a = substr($w, 0, $l); return $a unless $used{$a}; } return undef; }