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