1*e0c4386eSCy Schubert#! /usr/bin/env perl 2*e0c4386eSCy Schubert# 3*e0c4386eSCy Schubert# C source compressor. This: 4*e0c4386eSCy Schubert# 5*e0c4386eSCy Schubert# - merges continuation lines 6*e0c4386eSCy Schubert# - removes comments (not in strings) 7*e0c4386eSCy Schubert# - removes empty lines (not in strings) 8*e0c4386eSCy Schubert 9*e0c4386eSCy Schubertuse strict; 10*e0c4386eSCy Schubertuse warnings; 11*e0c4386eSCy Schubert 12*e0c4386eSCy Schubertmy $debug = defined $ENV{DEBUG}; 13*e0c4386eSCy Schubertmy $lang = shift @ARGV; 14*e0c4386eSCy Schubert 15*e0c4386eSCy Schubert# Slurp the file 16*e0c4386eSCy Schubert$/ = undef; 17*e0c4386eSCy Schubert$_ = <>; 18*e0c4386eSCy Schubert 19*e0c4386eSCy Schubertif ($lang eq 'C') { 20*e0c4386eSCy Schubert # Merge continuation lines 21*e0c4386eSCy Schubert s{\\\n}{}g; 22*e0c4386eSCy Schubert 23*e0c4386eSCy Schubert # Regexp for things that should be preserved 24*e0c4386eSCy Schubert my $preserved = 25*e0c4386eSCy Schubert qr{ 26*e0c4386eSCy Schubert (?: 27*e0c4386eSCy Schubert " # String start 28*e0c4386eSCy Schubert (?: \\. | [^\"])* # Any character, including escaped ones 29*e0c4386eSCy Schubert " # String end 30*e0c4386eSCy Schubert ) 31*e0c4386eSCy Schubert 32*e0c4386eSCy Schubert | # OR 33*e0c4386eSCy Schubert 34*e0c4386eSCy Schubert (?: 35*e0c4386eSCy Schubert ' # Character start (multi-chars supported) 36*e0c4386eSCy Schubert (?: \\. | [^\'])+ # Any character, including escaped ones 37*e0c4386eSCy Schubert ' # String end 38*e0c4386eSCy Schubert ) 39*e0c4386eSCy Schubert }x; 40*e0c4386eSCy Schubert 41*e0c4386eSCy Schubert # Remove comments while preserving strings 42*e0c4386eSCy Schubert s{ 43*e0c4386eSCy Schubert (?| # All things preserved end up in $1 44*e0c4386eSCy Schubert 45*e0c4386eSCy Schubert /\* # C comment start 46*e0c4386eSCy Schubert .*? # Contents up until 47*e0c4386eSCy Schubert \*/ # C comment end 48*e0c4386eSCy Schubert 49*e0c4386eSCy Schubert | # OR 50*e0c4386eSCy Schubert 51*e0c4386eSCy Schubert ( # Grouping for the replacement 52*e0c4386eSCy Schubert $preserved 53*e0c4386eSCy Schubert ) 54*e0c4386eSCy Schubert 55*e0c4386eSCy Schubert ) 56*e0c4386eSCy Schubert }{ 57*e0c4386eSCy Schubert if ($debug) { 58*e0c4386eSCy Schubert print STDERR "DEBUG: '$&' => '$1'\n" if defined $1; 59*e0c4386eSCy Schubert print STDERR "DEBUG: '$&' removed\n" unless defined $1; 60*e0c4386eSCy Schubert } 61*e0c4386eSCy Schubert defined $1 ? $1 : "" 62*e0c4386eSCy Schubert }gsxe; 63*e0c4386eSCy Schubert 64*e0c4386eSCy Schubert # Remove empty lines 65*e0c4386eSCy Schubert s{ 66*e0c4386eSCy Schubert (?| # All things preserved end up in $1 67*e0c4386eSCy Schubert 68*e0c4386eSCy Schubert (^|\n)(?:\s*(?:\n|$))+ # Empty lines, preserve one newline 69*e0c4386eSCy Schubert 70*e0c4386eSCy Schubert | # OR 71*e0c4386eSCy Schubert 72*e0c4386eSCy Schubert ( # Grouping for the replacement 73*e0c4386eSCy Schubert $preserved 74*e0c4386eSCy Schubert ) 75*e0c4386eSCy Schubert 76*e0c4386eSCy Schubert ) 77*e0c4386eSCy Schubert }{$1}gsx; 78*e0c4386eSCy Schubert 79*e0c4386eSCy Schubert # Remove extra spaces 80*e0c4386eSCy Schubert s{ 81*e0c4386eSCy Schubert (?| # All things preserved end up in $1 82*e0c4386eSCy Schubert 83*e0c4386eSCy Schubert \h+ # Horizontal spaces replaced with one 84*e0c4386eSCy Schubert 85*e0c4386eSCy Schubert | # OR 86*e0c4386eSCy Schubert 87*e0c4386eSCy Schubert ( # Grouping for the replacement 88*e0c4386eSCy Schubert $preserved 89*e0c4386eSCy Schubert ) 90*e0c4386eSCy Schubert 91*e0c4386eSCy Schubert ) 92*e0c4386eSCy Schubert }{ 93*e0c4386eSCy Schubert if ($debug) { 94*e0c4386eSCy Schubert print STDERR "DEBUG: '$&' => '$1'\n" if defined $1; 95*e0c4386eSCy Schubert print STDERR "DEBUG: '$&' => ' '\n" unless defined $1; 96*e0c4386eSCy Schubert } 97*e0c4386eSCy Schubert defined $1 ? $1 : " " 98*e0c4386eSCy Schubert }gsxe; 99*e0c4386eSCy Schubert 100*e0c4386eSCy Schubert # Clean up spaces at start and end of lines 101*e0c4386eSCy Schubert s/^ //mg; 102*e0c4386eSCy Schubert s/ $//mg; 103*e0c4386eSCy Schubert} elsif ($lang eq 'S') { 104*e0c4386eSCy Schubert # Because we use C++ style comments in our .S files, all we can do 105*e0c4386eSCy Schubert # is to drop them 106*e0c4386eSCy Schubert s{ 107*e0c4386eSCy Schubert ^([^\n]*?)//[^\n]*?$ # Any line with a // comment 108*e0c4386eSCy Schubert }{ 109*e0c4386eSCy Schubert if ($debug) { 110*e0c4386eSCy Schubert print STDERR "DEBUG: '$&' => '$1'\n" if defined $1; 111*e0c4386eSCy Schubert print STDERR "DEBUG: '$&' removed\n" unless defined $1; 112*e0c4386eSCy Schubert } 113*e0c4386eSCy Schubert defined $1 ? $1 : "" 114*e0c4386eSCy Schubert }mgsxe; 115*e0c4386eSCy Schubert 116*e0c4386eSCy Schubert # Drop all empty lines 117*e0c4386eSCy Schubert s{ 118*e0c4386eSCy Schubert (^|\n)(?:\s*(?:\n|$))+ # Empty lines, preserve one newline 119*e0c4386eSCy Schubert }{$1}gsx; 120*e0c4386eSCy Schubert} elsif ($lang eq 'perl') { 121*e0c4386eSCy Schubert # Merge continuation lines 122*e0c4386eSCy Schubert s{\\\n}{}g; 123*e0c4386eSCy Schubert 124*e0c4386eSCy Schubert # Regexp for things that should be preserved 125*e0c4386eSCy Schubert my $preserved = 126*e0c4386eSCy Schubert qr{ 127*e0c4386eSCy Schubert (?: 128*e0c4386eSCy Schubert <<["']?(\w+)["']? # HERE document start 129*e0c4386eSCy Schubert .*? # Its contents 130*e0c4386eSCy Schubert ^\g{-1}$ 131*e0c4386eSCy Schubert ) 132*e0c4386eSCy Schubert | 133*e0c4386eSCy Schubert (?: 134*e0c4386eSCy Schubert " # Double quoted string start 135*e0c4386eSCy Schubert (?: \\. | [^\"])* # Any character, including escaped ones 136*e0c4386eSCy Schubert " # Double quoted string end 137*e0c4386eSCy Schubert ) 138*e0c4386eSCy Schubert 139*e0c4386eSCy Schubert | # OR 140*e0c4386eSCy Schubert 141*e0c4386eSCy Schubert (?: 142*e0c4386eSCy Schubert ' # Single quoted string start 143*e0c4386eSCy Schubert [^\']* # Any character 144*e0c4386eSCy Schubert ' # Single quoted string end 145*e0c4386eSCy Schubert ) 146*e0c4386eSCy Schubert }msx; 147*e0c4386eSCy Schubert 148*e0c4386eSCy Schubert # Remove comments while preserving strings 149*e0c4386eSCy Schubert s{ 150*e0c4386eSCy Schubert (?| # All things preserved end up in $1 151*e0c4386eSCy Schubert 152*e0c4386eSCy Schubert \#.*?(\n|$) # Perl comments 153*e0c4386eSCy Schubert 154*e0c4386eSCy Schubert | # OR 155*e0c4386eSCy Schubert 156*e0c4386eSCy Schubert ( # Grouping for the replacement 157*e0c4386eSCy Schubert $preserved 158*e0c4386eSCy Schubert ) 159*e0c4386eSCy Schubert 160*e0c4386eSCy Schubert ) 161*e0c4386eSCy Schubert }{ 162*e0c4386eSCy Schubert if ($debug) { 163*e0c4386eSCy Schubert print STDERR "DEBUG: '$&' => '$1'\n" if defined $1; 164*e0c4386eSCy Schubert print STDERR "DEBUG: '$&' removed\n" unless defined $1; 165*e0c4386eSCy Schubert } 166*e0c4386eSCy Schubert defined $1 ? $1 : "" 167*e0c4386eSCy Schubert }gsxe; 168*e0c4386eSCy Schubert 169*e0c4386eSCy Schubert # Remove empty lines 170*e0c4386eSCy Schubert s{ 171*e0c4386eSCy Schubert (?| # All things preserved end up in $1 172*e0c4386eSCy Schubert 173*e0c4386eSCy Schubert (^|\n)(?:\s*(?:\n|$))+ # Empty lines, preserve one newline 174*e0c4386eSCy Schubert 175*e0c4386eSCy Schubert | # OR 176*e0c4386eSCy Schubert 177*e0c4386eSCy Schubert ( # Grouping for the replacement 178*e0c4386eSCy Schubert $preserved 179*e0c4386eSCy Schubert ) 180*e0c4386eSCy Schubert 181*e0c4386eSCy Schubert ) 182*e0c4386eSCy Schubert }{$1}gsx; 183*e0c4386eSCy Schubert} 184*e0c4386eSCy Schubert 185*e0c4386eSCy Schubertprint; 186