summaryrefslogtreecommitdiff
path: root/perl
diff options
context:
space:
mode:
Diffstat (limited to 'perl')
-rw-r--r--perl/Makefile.am7
-rwxr-xr-xperl/jsmin.pl.in389
2 files changed, 396 insertions, 0 deletions
diff --git a/perl/Makefile.am b/perl/Makefile.am
new file mode 100644
index 0000000..7cd8778
--- /dev/null
+++ b/perl/Makefile.am
@@ -0,0 +1,7 @@
+
+############################################################
+# Don't strip jsmin.pl script when `make install-strip' #
+############################################################
+INSTALL_SCRIPT = ${INSTALL}
+
+bin_SCRIPTS = jsmin.pl
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;