#!/usr/bin/perl
# Copyright (c) 2009, Uta Priss.
# http://www.upriss.org.uk
# For licence information run "fcastone -l"
# Version 0.3
my $dotlocation = `which dot`;
chomp($dotlocation);
### If you want to set the behaviour of the fcaStoneDotErrors.log file
### or edit the location of Graphviz's dot program, edit the following lines.
### my $errorslocation = "/dev/null"; means no error file will be created
my $errorslocation = "fcaStoneDotErrors.log";
# $dotlocation = "/usr/local/graphviz-2.14/bin/dot";
sub printlicence { print "
FcaStone - a program for FCA format conversion
Copyright (C) 2009 Uta Priss.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
";}
use strict;
#%%%%%%%%%%%%%% read arguments, open files %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
my $var1; ## temp variable
my $filename1 = $ARGV[-2]; ## input filename
my $filename2 = $ARGV[-1]; ## output filename
my $script = $filename2; ## GLOBAL VARIABLE
my %opt; ## GLOBAL VARIABLE
my $fiopt = substr($filename1,index($filename1,".")+1); ## GLOBAL VARIABLE
my $secopt = substr($filename2,index($filename2,".")+1); ## GLOBAL VARIABLE
my $typxml = 0; ## is it xml file?
my @lines; ## input for input()
my ($filecont); ## output from main_output()
my @ctxt; ## contexts: from main_input() into main_output()
## this is an array of hashs o,a,m: obj,attr,matr
if ($ARGV[-1] eq "-l") { printlicence(); exit;}
if ($filename1 =~ /^\-/ or $filename2 =~ /^\-/) {
print "usage: $0 [-bBcgijmnNOprstuUw] filename1 filename2\n";
print "Filenames must not start with '-'.\n"; exit;
}
$opt{box} = 0; $opt{cla} = 0; $opt{grp} = 0; $opt{ms} = 0; $opt{pip} = 0;
$opt{rot} = 0; $opt{sil} = 0; $opt{top} = 0; $opt{web} = 0; $opt{ima} = 0;
$opt{noI} = 0; $opt{noO} = 0; $opt{uni} = 0; $opt{uxml} = 0; $opt{one} = 0;
foreach $var1 (@ARGV) { ## reading the options
if ($var1 =~ /^\-.*b/) { $opt{box} = 1; }
if ($var1 =~ /^\-.*B/) { $opt{Box} = 1; }
if ($var1 =~ /^\-.*c/) { $opt{cla} = 1; }
if ($var1 =~ /^\-.*g/) { $opt{grp} = 1; }
if ($var1 =~ /^\-.*i/) { $opt{ima} = 1; $opt{box} = 1;} ### or Box if -B is chosen
if ($var1 =~ /^\-.*j/) { $opt{jpg} = 1; $opt{Box} = 1;}
if ($var1 =~ /^\-.*m/) { $opt{ms} = 1; }
if ($var1 =~ /^\-.*p/) { $opt{pip} = 1; }
if ($var1 =~ /^\-.*r/) { $opt{rot} = 1; }
if ($var1 =~ /^\-.*s/) { $opt{sil} = 1; }
if ($var1 =~ /^\-.*t/) { $opt{top} = 1; } ##all 4 needed
if ($var1 =~ /^\-.*w/) { $opt{web} = 1;$opt{noI} = 1;$opt{noO} = 1;$opt{sil} = 1;}
if ($var1 =~ /^\-.*n/) { $opt{noI} = 1; $opt{sil} = 1;}
if ($var1 =~ /^\-.*O/) { $opt{one} = 1; $opt{sil} = 1;}
if ($var1 =~ /^\-.*N/) { $opt{noO} = 1; $opt{sil} = 1;}
if ($var1 =~ /^\-.*u/ and $opt{uxml} == 0) { $opt{uni} = 1; }
if ($var1 =~ /^\-.*U/) { $opt{uxml} = 1; $opt{uni} = 0; }
if ($var1 =~ /^\-/ and $var1 !~ /^[\-bBcgijmnNOprstuUw]+$/) {
showerror("That option is not yet implemented.",1);
}
}
if ($opt{noO}) { $errorslocation = "/dev/null" }
if ($opt{Box}) { $opt{box} = 0 }
if ($fiopt !~ /^(cxt|csc|csv|con|slf|bin.xml|csx|cex|tuples)$/ or $secopt !~
/^(cxt|csc|csv|con|slf|bin.xml|tex|csx|cex|fig|dot|svg|jpg|gif|png|ps|pdf|gxl|tuples|gml|html)$/) {
showerror("These file extensions are not yet supported.",1);
}
if ($opt{noI} == 0) { ## open input file
if ($opt{uni} == 1 or $opt{uxml} == 1) {
open (FILE, '<:utf8', $filename1) || showerror("File does not exist.",1);
} else {
open (FILE, '<', $filename1) || showerror("File does not exist.",1);
}
@lines = ; close FILE;
} else { ## or read STDIN
if ($opt{one} == 0) {
@lines = ;
} else { ## one line input
$var1 = ;
@lines = split (/\|%\|%/,$var1);
}
}
if (-e $filename2 and $opt{sil} == 0) { ## if not silent: warn if out exists
print "$filename2 exists and will be overwritten, OK?";
$var1 = ;
if ($var1 !~ /y/i) {exit;}
}
if ($secopt =~ /svg|gxl|cex|csx|bin.xml/) { $typxml = 1; }
if ($secopt =~ /svg|jpg|gif|png|ps|pdf|gxl/) { $opt{grp} = 1; } ## deal with graphviz
if ($opt{grp} == 1) {
$var1 = `$dotlocation -V 2>&1`; ## direct stderr to stdout
if ($var1 !~ /dot.*version/i) {
showerror("Graphviz's dot program cannot be found.",1);
}
}
#%%%%%%%%%%%%%% in/out %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
chomp @lines;
$var1 = join("%&%x",@lines); ## windows return char
$var1 =~ s/\r//g;
$var1 =~ s/\s+$//; ## blank lines at end
if ($var1 =~ /^\s*$/) { showerror("File is empty.",1); }
@lines = split(/%&%x/,$var1);
($ctxt[0]{o},$ctxt[0]{a},$ctxt[0]{m}) = main_input(@lines); ## call input()
$filecont = main_output($ctxt[0]); ## call output()
#%%%%%%%%%%%%%% print %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if ($opt{uni} == 1) {
eval('use Encode;');
eval('$filecont = encode_utf8( $filecont )'); ## turns utf8 flag off
} elsif ($opt{uxml} == 1) {
eval('use Encode;');
eval('$filecont = encode("ascii", $filecont,Encode::FB_XMLCREF)');
}
if ($opt{grp} == 1) {
if ($secopt eq "gxl") {
if ($opt{noO} == 1) {open(PIPE, "| $dotlocation"."2gxl 2>$errorslocation");}
else { open(PIPE, "| $dotlocation"."2gxl -o$filename2 2>$errorslocation");}
} else {
if($opt{noO}==1){open(PIPE, "| $dotlocation -T$secopt 2>$errorslocation");}
else { open(PIPE,"| $dotlocation -T$secopt -o$filename2 2>$errorslocation");}
}
print PIPE $filecont;
close PIPE;
} else {
if ($opt{ms} == 1) {$filecont =~ s/\n/\r\n/g;}
if ($opt{noO} == 1) {
if ($typxml == 0 and $opt{web} == 1) {$filecont =~ s/\n/ /g}
elsif ($secopt ne "svg" and $opt{web} == 1) {
$filecont =~ s/</g; $filecont =~ s/>/>/g; }
if ($opt{one} == 1) { ## one line output
$filecont =~ s/\n/\|%\|%/g;
$filecont .= "\n";
}
print $filecont;
} else {
open (OUT, '>',$filename2);
print OUT $filecont;
close OUT;
}
}
#%%%%%%%%%%%%%% input %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
sub main_input{
my (@lnes) = @_;
my ($temp1, $temp2, @outcome);
my ($adlimit, $odlimit, $aslct, $oslct, $rdlimit, $islct);
my ($ndlimit, $edlimit, $nslct, $eslct);
my (@objects,@attributes,@matrix);
if ($fiopt eq "csc") {
$adlimit = 'ATTRIBUTES(.*?)RELATION';
$odlimit = 'OBJECTS(.*?)ATTRIBUTES';
$aslct ='\s*\d+\s+\w\d+\s+"(.*?)"\s*'; ## with \d must be single quotes
$oslct ='\s*\d+\s+\w\d+\s+"(.*?)"\s*';
$rdlimit = 'RELATION\s+\d+,\s+\d+\s*(.*?)\s*;';
@outcome = readcrs($adlimit,$odlimit, $aslct, $oslct, $rdlimit, @lnes);
@objects = @{$outcome[0]}; @attributes = @{$outcome[1]}; @matrix = @{$outcome[2]};
} elsif ($fiopt eq "slf") {
foreach $temp1 (@lnes) {
$temp1 =~ s/(.*)/<$1>/;
}
$adlimit = '\[Attributes\]\>\s*(.*)\s*\<\[relation\]';
$odlimit = '\[Objects\]\>\s*(.*)\s*\<\[Attributes\]';
$aslct ='\s*<\s*(.*?)\s*>\s*';
$oslct ='\s*<\s*(.*?)\s*>\s*';
$rdlimit = '\[relation\]\>\s*(.*)';
@outcome = readcrs($adlimit,$odlimit, $aslct, $oslct, $rdlimit, @lnes);
@objects = @{$outcome[0]}; @attributes = @{$outcome[1]}; @matrix = @{$outcome[2]};
} elsif ($fiopt eq "cex") {
$adlimit = '(.*)<\/Attributes>';
$odlimit = '(.*)<\/Objects>';
$aslct ='\s*\s*\s*"?(.*?)"?\s*<\/Name>\s*<\/Attribute>\s*';
$oslct ='\s*