#!@path_perl@
eval
'exec @path_perl@ -S $0 ${1+"$@"}'
if
$running_under_some_shell
;
require
"slice_boot.pl"
;
require
5.003;
require
"slice_set.pl"
;
require
"slice_term.pl"
;
require
"slice_util.pl"
;
require
"slice_vers.pl"
;
sub
usage {
print
STDERR
"Usage: slice [options] [file]\n"
;
print
STDERR
" where options are\n"
;
print
STDERR
" -o sliceterm:file create output file\n"
;
print
STDERR
" -x verbose/debug mode\n"
;
print
STDERR
" -v version string\n"
;
exit
(1);
}
sub
hello {
print
STDERR
"$Vers::SLICE_Hello\n"
;
exit
(0);
}
$Getopt::Long::bundling
= 1;
$opt_x
= 0;
$opt_v
= 0;
@opt_o
= ();
if
(not Getopt::Long::GetOptions(
"x|debug"
,
"v|version"
,
"o|outputfile=s@"
)) {
&usage
;
}
if
(
$opt_v
) {
&hello
;
}
if
(
$#ARGV
== -1 or (
$#ARGV
== 0 and
$ARGV
[0] eq
"-"
)) {
$infile
=
"-"
;
@IN
= <STDIN>;
}
else
{
$infile
=
$ARGV
[0];
open
(INFP,
"<$infile"
);
@IN
= <INFP>;
close
(INFP);
}
&verbose
(
"\nPass 1: Determine delimiters\n\n"
);
$INPUT
=
join
(
""
,
@IN
);
$NEW
=
""
;
@NAMES
= ();
$LEVELS
= new Set::IntegerFast(100);
%SLICE
= ();
$maxlevel
= 0;
sub
alloclevel {
my
(
$i
);
for
(
$i
= 0;
$i
< 100;
$i
++) {
last
if
(not
$LEVELS
->in(
$i
));
}
$LEVELS
->Insert(
$i
);
return
$i
+ 1;
}
sub
clearlevel {
my
(
$level
) =
@_
;
$LEVELS
->Delete(
$level
- 1);
}
$pos
= 0;
while
(1) {
$rc1
= (
$INPUT
=~ m|^(.*?)\[([_A-Z0-9]+):(.*)$|s);
(
$prev1
,
$name1
,
$next1
) = ($1, $2, $3);
$rc2
= (
$INPUT
=~ m|^(.*?):([_A-Z0-9]*)\](.*)$|s);
(
$prev2
,
$name2
,
$next2
) = ($1, $2, $3);
if
(not
$rc1
and not
$rc2
) {
$NEW
.=
$INPUT
;
last
;
}
elsif
((
$rc1
and
$rc2
) and (
length
(
$prev1
) <
length
(
$prev2
)) or (
$rc1
and not
$rc2
)) {
push
(
@NAMES
,
$name1
);
$pos
+=
length
(
$prev1
);
$H
=
&alloclevel
;
$LEVEL
{
$name1
} =
$H
;
$maxlevel
= (
$maxlevel
<
$H
?
$H
:
$maxlevel
);
&verbose
(
" $name1 begin @ $pos (level $H)\n"
);
if
(
$SLICE
{
$name1
} eq
""
) {
$SLICE
{
$name1
} =
"$H:$pos"
;
}
else
{
$SLICE
{
$name1
} .=
",$H:$pos"
;
}
$NEW
.=
$prev1
;
$INPUT
=
$next1
;
}
else
{
$namex
=
pop
(
@NAMES
);
if
(
$name2
eq
""
) {
$name2
=
$namex
;
}
$pos
+=
length
(
$prev2
);
&clearlevel
(
$LEVEL
{
$name2
});
$n
=
sprintf
(
"%d"
,
$pos
- 1);
&verbose
(
" $name2 end @ $n\n"
);
$SLICE
{
$name2
} .=
":$n"
;
$NEW
.=
$prev2
;
$INPUT
=
$next2
;
}
}
$IN
=
$NEW
;
if
(
$LEVELS
->Norm != 0) {
&error
(
"Sorry, some slices were not closed!\n"
);
}
&verbose
(
"\nPass 2: Calculation of slice sets\n\n"
);
$MAXSETLEN
=
length
(
$NEW
)+1;
%SLICESET
= ();
$set
= new Set::IntegerFast(
$MAXSETLEN
);
$setA
= new Set::IntegerFast(
$MAXSETLEN
);
sub
SetClone {
my
(
$set
) =
@_
;
my
(
$tmp
);
$tmp
= new Set::IntegerFast(
$set
->Size());
$tmp
->Copy(
$set
);
return
$tmp
;
}
foreach
$slice
(
keys
(
%SLICE
)) {
$asc
=
$SLICE
{
$slice
};
$set
->Empty();
&asc2set
(
$asc
,
$set
);
$SLICESET
{
$slice
} =
&SetClone
(
$set
);
}
$set
->Fill();
$SLICESET
{
'UNDEF0'
} =
&SetClone
(
$set
);
$set
->Empty();
$SLICESET
{
'DEF0'
} =
&SetClone
(
$set
);
$setA
->Empty();
for
(
$i
= 1;
$i
<=
$maxlevel
;
$i
++) {
$set
->Empty();
foreach
$name
(
keys
(
%SLICE
)) {
$asc
=
$SLICE
{
$name
};
&asc2set
(
$asc
,
$set
,
$i
, 1);
$setA
->Union(
$setA
,
$set
);
}
$SLICESET
{
"DEF$i"
} =
&SetClone
(
$set
);
$set
->Complement(
$set
);
$SLICESET
{
"UNDEF$i"
} =
&SetClone
(
$set
);
}
$SLICESET
{
'DEF'
} =
&SetClone
(
$setA
);
$setA
->Complement(
$setA
);
$SLICESET
{
'UNDEF'
} =
&SetClone
(
$setA
);
$SLICESET
{
'ALL'
} =
$SLICESET
{
'UNDEF0'
};
&verbose
(
"\nPass 3: Output generation\n\n"
);
sub
WriteOutput {
local
(
$infile
,
*IN
,
$slice
,
$outfile
,
*OUT
,
$chmod
) =
@_
;
(
$cmds
,
$var
) = SliceTerm::Parse(
$slice
);
&verbose
(
" calculated Perl 5 set term:\n"
);
&verbose
(
" ----\n"
);
$x
=
$cmds
;
$x
=~ s|\n|\n |g;
&verbose
(
" $x"
);
&verbose
(
"----\n"
);
eval
$cmds
;
$set
=
eval
"$var"
;
for
(
$i
= 0;
$i
<=
$set
->Max();
$i
++) {
if
(
$set
->in(
$i
)) {
print
OUT
substr
(
$IN
,
$i
, 1);
}
}
&verbose
(
"\n"
);
}
if
(
$#opt_o
== -1) {
@opt_o
= (
"ALL:-"
);
}
foreach
$entry
(
@opt_o
) {
if
(
$entry
=~ m|^([A-Z0-9~!+u
*n
\-\\^x()]+):(.+)@(.+)$|) {
(
$slice
,
$outfile
,
$chmod
) = ($1, $2, $3);
}
elsif
(
$entry
=~ m|^([_A-Z0-9~!+u
*n
\-\\^x()]+):(.+)$|) {
(
$slice
,
$outfile
,
$chmod
) = ($1, $2,
""
);
}
elsif
(
$entry
=~ m|^(.+)@(.+)$|) {
(
$slice
,
$outfile
,
$chmod
) = (
"ALL"
, $1, $2);
}
else
{
(
$slice
,
$outfile
,
$chmod
) = (
"ALL"
,
$entry
,
""
);
}
if
(
$outfile
eq
"-"
) {
*OUT
=
*STDOUT
;
}
else
{
open
(OUT,
">$outfile"
) ||
die
;
}
&verbose
(
" file $outfile: sliceterm='$slice', chmodopts='$chmod'\n"
);
&WriteOutput
(
$infile
,
*IN
,
$slice
,
$outfile
,
*OUT
,
$chmod
);
if
(
$outfile
ne
"-"
) {
close
(OUT);
}
if
(
$chmod
ne
""
) {
system
(
"chmod $chmod $outfile"
);
}
}
exit
(0);