#! /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;