123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- #! /usr/bin/env perl
- #
- # C source compressor. This:
- #
- # - merges continuation lines
- # - removes comments (not in strings)
- # - removes empty lines (not in strings)
- use strict;
- use warnings;
- my $debug = defined $ENV{DEBUG};
- my $lang = shift @ARGV;
- # Slurp the file
- $/ = undef;
- $_ = <>;
- if ($lang eq 'C') {
- # Merge continuation lines
- s{\\\n}{}g;
- # Regexp for things that should be preserved
- my $preserved =
- qr{
- (?:
- " # String start
- (?: \\. | [^\"])* # Any character, including escaped ones
- " # String end
- )
- | # OR
- (?:
- ' # Character start (multi-chars supported)
- (?: \\. | [^\'])+ # Any character, including escaped ones
- ' # String end
- )
- }x;
- # Remove comments while preserving strings
- s{
- (?| # All things preserved end up in $1
- /\* # C comment start
- .*? # Contents up until
- \*/ # C comment end
- | # OR
- ( # Grouping for the replacement
- $preserved
- )
- )
- }{
- if ($debug) {
- print STDERR "DEBUG: '$&' => '$1'\n" if defined $1;
- print STDERR "DEBUG: '$&' removed\n" unless defined $1;
- }
- defined $1 ? $1 : ""
- }gsxe;
- # Remove empty lines
- s{
- (?| # All things preserved end up in $1
- (^|\n)(?:\s*(?:\n|$))+ # Empty lines, preserve one newline
- | # OR
- ( # Grouping for the replacement
- $preserved
- )
- )
- }{$1}gsx;
- # Remove extra spaces
- s{
- (?| # All things preserved end up in $1
- \h+ # Horizontal spaces replaced with one
- | # OR
- ( # Grouping for the replacement
- $preserved
- )
- )
- }{
- if ($debug) {
- print STDERR "DEBUG: '$&' => '$1'\n" if defined $1;
- print STDERR "DEBUG: '$&' => ' '\n" unless defined $1;
- }
- defined $1 ? $1 : " "
- }gsxe;
- # Clean up spaces at start and end of lines
- s/^ //mg;
- s/ $//mg;
- } elsif ($lang eq 'S') {
- # Because we use C++ style comments in our .S files, all we can do
- # is to drop them
- s{
- ^([^\n]*?)//[^\n]*?$ # Any line with a // comment
- }{
- if ($debug) {
- print STDERR "DEBUG: '$&' => '$1'\n" if defined $1;
- print STDERR "DEBUG: '$&' removed\n" unless defined $1;
- }
- defined $1 ? $1 : ""
- }mgsxe;
- # Drop all empty lines
- s{
- (^|\n)(?:\s*(?:\n|$))+ # Empty lines, preserve one newline
- }{$1}gsx;
- } elsif ($lang eq 'perl') {
- # Merge continuation lines
- s{\\\n}{}g;
- # Regexp for things that should be preserved
- my $preserved =
- qr{
- (?:
- <<["']?(\w+)["']? # HERE document start
- .*? # Its contents
- ^\g{-1}$
- )
- |
- (?:
- " # Double quoted string start
- (?: \\. | [^\"])* # Any character, including escaped ones
- " # Double quoted string end
- )
- | # OR
- (?:
- ' # Single quoted string start
- [^\']* # Any character
- ' # Single quoted string end
- )
- }msx;
- # Remove comments while preserving strings
- s{
- (?| # All things preserved end up in $1
- \#.*?(\n|$) # Perl comments
- | # OR
- ( # Grouping for the replacement
- $preserved
- )
- )
- }{
- if ($debug) {
- print STDERR "DEBUG: '$&' => '$1'\n" if defined $1;
- print STDERR "DEBUG: '$&' removed\n" unless defined $1;
- }
- defined $1 ? $1 : ""
- }gsxe;
- # Remove empty lines
- s{
- (?| # All things preserved end up in $1
- (^|\n)(?:\s*(?:\n|$))+ # Empty lines, preserve one newline
- | # OR
- ( # Grouping for the replacement
- $preserved
- )
- )
- }{$1}gsx;
- }
- print;
|