diff options
Diffstat (limited to 'perl/jsmin.pl.in')
-rwxr-xr-x | perl/jsmin.pl.in | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/perl/jsmin.pl.in b/perl/jsmin.pl.in new file mode 100755 index 0000000..ff648b2 --- /dev/null +++ b/perl/jsmin.pl.in @@ -0,0 +1,389 @@ +#!/usr/bin/perl -w + +use strict; +use Getopt::Long qw(:config no_ignore_case bundling); +use File::Basename; +use utf8; + +my $ifname = ''; +my $ofname = ''; +my $stdio = ''; +my $last = ''; + +my $version = "@VERSION@"; + +my ( $if, $of ); + +sub usage +{ + my $p = basename( $0 ); + + print <<EOF; + +Usage: $p [options] [input_file_name] +Options: + --output | -o - output file name; + --version | -v - print version numver; + --help | -h | -? - print this message; + -- - an option terminator; + - - use std{io|out} instead of files. + +Examples: + + Input file is 'full.json', output file is 'min.json': + + \$ $p -o min.json full.json + + Input file is 'STDIN', output file is 'min.json': + + \$ $p -o min.json - + + Please note that to terminate your input by keyboard you have to use + <Ctrl>+d combination; + + Input file is 'full.json', output file is 'STDOUT': + + \$ $p -- full.json + + Use stdin, stdout: + + \$ $p - < full.json > min.json + +Enjoj. + +EOF + exit; +} + +sub version +{ + print <<EOF; +$version +EOF + exit; +} + + +my $a = ''; +my $b = ''; +my $x = ''; +my $y = ''; + +my $lookahead = 0; + + +sub get +{ + my $c = 0; + + $c = $lookahead; + $lookahead = 0; + + if( $c == 0 ) + { + if( ! eof( $if ) ) + { + my $ch = getc( $if ); + $c = ord( $ch ); + } + else + { + $c = 0; + } + } + if( $c >= ord(" ") || $c == ord("\n") || $c == 0 ) + { + return $c; + } + if( $c == ord("\r") ) + { + return ord("\n"); + } + return ord(" "); +} + +sub peek +{ + $lookahead = get(); + return $lookahead; +} + +sub next_cn +{ + my $c = get(); + + if( $c == ord("/") ) + { + my $char = chr( peek() ); + if( $char eq "/" ) + { + for(;;) { $c = get(); if( $c <= ord("\n") ) { last; } } + } + elsif( $char eq "*" ) + { + get(); + while( $c != ord(" ") ) + { + my $cn = get(); + if( chr( $cn ) eq "*" ) + { + if( chr( peek() ) eq "/" ) { get(); $c = ord(" "); } + } + elsif( $cn == 0 ) + { + print STDERR "Unterminated comment.\n"; exit 1; + } + } + } + } + $y = $x; + $x = chr( $c ); + + return $c; +} + +sub action +{ + my $d = $_[0]; + + if( $d == 1 ) + { + print $of $a; + if( + ( $y eq "\n" || $y eq " " ) && + ( $a eq "+" || $a eq "-" || $a eq "*" || $a eq "/" ) && + ( $b eq "+" || $b eq "-" || $b eq "*" || $b eq "/" ) + ) + { + print $of $y; + } + $d = 2; + } + + if( $d == 2 ) + { + $a = $b; + if( $a eq "\'" || $a eq "\"" || $a eq "`" ) + { + for(;;) + { + my $c; + + print $of $a; + $c = get(); $a = chr( $c ); + if( $a eq $b ) { last; } + if( $a eq "\\" ) + { + print $of $a; + $c = get(); $a = chr( $c ); + } + if( $c == 0 ) + { + print STDERR "Unterminated string literal.\n"; exit 1; + } + } + } + $d = 3; + } + + if( $d == 3 ) + { + $b = chr( next_cn() ); + if( $b eq "/" && + ( $a eq "(" || $a eq "," || $a eq "=" || $a eq ":" || + $a eq "[" || $a eq "!" || $a eq "&" || $a eq "|" || + $a eq "?" || $a eq "+" || $a eq "-" || $a eq "~" || + $a eq "*" || $a eq "/" || $a eq "{" || $a eq "\n" + ) + ) + { + print $of $a; + if( $a eq "/" || $a eq "*" ) { print $of " "; } + print $of $b; + for(;;) + { + my $c; + + $c = get(); $a = chr( $c ); + if( $a eq "[" ) + { + for(;;) + { + print $of $a; + $c = get(); $a = chr( $c ); + if( $a eq "]" ) + { + last; + } + if( $a eq "\\" ) + { + print $of $a; + $c = get(); $a = chr( $c ); + } + if( $c == 0 ) + { + print STDERR "Unterminated regular expression literal.\n"; exit 1; + } + } + } + elsif( $a eq "/" ) + { + my $ch = chr( peek() ); + if( $ch eq "/" || $ch eq "*" ) + { + print STDERR "Unterminated regular expression literal.\n"; exit 1; + } + last; + } + elsif( $a eq "\\" ) + { + print $of $a; + $c = get(); $a = chr( $c ); + } + elsif( $c == 0 ) + { + print STDERR "Unterminated regular expression literal.\n"; exit 1; + } + print $of $a; + } + $b = chr( next_cn() ); + } + } +} + + +sub isalnum +{ + my $ch = $_[0]; + + if( ($ch ge "a" && $ch le "z") || ($ch ge "0" && $ch le "9") || + ($ch ge "A" && $ch le "Z") || $ch eq "_" || $ch eq "\$" || + $ch eq "\\" || $ch gt "~" + ) { return 1; } else { return 0; } +} + + +sub jsmin +{ + if( peek() == 0xEF ) { get(); get(); get(); } + $a = "\n"; + action( 3 ); + while( $a ne "" && $a ne "\0" ) + { + if( $a eq " " ) + { + action( isalnum( $b ) ? 1 : 2 ); + } + elsif( $a eq "\n" ) + { + if( $b eq "{" || $b eq "[" || $b eq "(" || $b eq "+" || + $b eq "-" || $b eq "!" || $b eq "~" + ) + { + action( 1 ); + } + elsif( $b eq " " ) + { + action( 3 ); + } + else + { + action( isalnum( $b ) ? 1 : 2 ); + } + } + else + { + if( $b eq " " ) + { + action( isalnum( $a ) ? 1 : 3 ); + } + elsif( $b eq "\n" ) + { + if( $a eq "}" || $a eq "]" || $a eq ")" || $a eq "+" || + $a eq "-" || $a eq "\"" || $a eq "\'" || $a eq "`" + ) + { + action( 1 ); + } + else + { + action( isalnum( $a ) ? 1 : 3 ); + } + } + else + { + action( 1 ); + } + } + } + #lats carriage return + print $of "\n"; +} + + +local $SIG{__WARN__} = sub { + my $message = shift; + print STDERR "ERROR: " . $message; + usage(); +}; + +if( ! GetOptions( 'o=s' => \$ofname, + 'output=s' => \$ofname, + '' => \$stdio, + 'help|h|?' => sub { usage() }, + 'version|v' => sub { version() } + ) + ) +{ + usage(); +} + +foreach( @ARGV ) +{ + $last = $_; + + if( $#ARGV ) + { + usage(); + } + +# NOTE: The '--' is an option terminator! +# So ./script -- - returns last equal to '-'. +# +# The $last argument is a ifname by default; +# +} + + +if( $ifname eq '' && $ofname eq '' && ! $stdio ) +{ + usage(); +} + +if( $ofname ne '' && $stdio && $last ne '' ) +{ + # like that: + # ./script -o min.json full.json - + # ./script -o min.json - full.json + # + print "ERROR: Input file defined twice: as 'stdin' and as a orfinary file '$last'\n"; + usage(); +} +else +{ + $ifname = $last; $last = ''; +} + +if( $ofname eq '' ) { $ofname = '-'; } +if( $ifname eq '' ) { $ifname = '-'; } +if( $ifname eq '-' ) { $if = *STDIN; } else { open( $if, "< $ifname" ); } +if( $ofname eq '-' ) { $of = *STDOUT; } else { open( $of, "> $ofname" ); } + + +jsmin(); + + +close $if; +close $of; + +exit 0; |