#!/usr/bin/perl -w
#
# $Id$
#
# Copyright 1989-2016 MINES ParisTech
#
# This file is part of PIPS.
#
# PIPS 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
# any later version.
#
# PIPS 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 PIPS. If not, see .
#
# This takes a PIPS output file in the GRAPH format as a file name
# and generates a new one in the daVinci format on stdout.
#
# Ronan.Keryell@cri.ensmp.fr, 5/09/1995.
$statement_number = 0;
$indent_level = 0;
$output_statement_buffer = "";
$this_is_the_unstructured_entry_p = 0;
%node_attribute_to_add = ();
%edge_attribute_to_add = ();
sub indent_string {
local($i) = $indent_level;
return " " x $indent_level;
}
sub output_indent {
print &indent_string;
}
sub indent_plus {
$indent_level += 2;
}
sub indent_minus {
$indent_level -= 2;
}
sub output_a_statement_begin {
local($label, $comment) = @_;
&output_indent;
print "l(\"$label\",\n";
$indent_level += 2;
&output_indent;
print "n(\"$comment\",\n";
$indent_level += 2;
&output_indent;
# Remove the \ and n at the end:
chop $output_statement_buffer;
chop $output_statement_buffer;
print "[\n";
&indent_plus;
if ($this_is_the_unstructured_entry_p == 1) {
&add_a_node_attribute("_GO", "ellipse");
}
&add_a_node_attribute("OBJECT", $output_statement_buffer);
&add_a_node_attribute("FONTFAMILY", "courier");
$output_statement_buffer = "";
&output_some_other_node_attributes;
&indent_minus ;
&output_indent;
print "],\n";
&output_indent;
print "[\n";
&indent_plus ;
}
sub output_a_successor {
local($successor, $comment) = @_;
&output_indent;
print "e(\"$comment\", [";
&output_some_other_edge_attributes;
print "], r(\"$successor\")),\n";
}
sub output_a_statement_end {
&indent_minus;
&output_indent;
print "]\n";
&indent_minus;
&output_indent;
print " )\n";
&indent_minus;
&output_indent;
print " ),\n";
$this_is_the_unstructured_entry_p = 0;
}
sub output_some_other_node_attributes {
while (($attribute, $value) = each %node_attribute_to_add) {
&output_indent;
print "a(\"$attribute\", \"$value\"),\n";
}
%node_attribute_to_add = ();
}
sub add_a_node_attribute {
local($attribute, $value) = @_;
# Keep only the last value for this attribute:
$node_attribute_to_add{$attribute} = $value;
}
sub output_some_other_edge_attributes {
while (($attribute, $value) = each %edge_attribute_to_add) {
&output_indent;
print "a(\"$attribute\", \"$value\"),\n";
}
%edge_attribute_to_add = ();
}
sub add_an_edge_attribute {
local($attribute, $value) = @_;
# Keep only the last value for this attribute:
$edge_attribute_to_add{$attribute} = $value;
}
sub output_a_node {
local($label, $name, $successors, $comment) = @_;
&output_indent;
print "l(\"$label\",\n";
$indent_level += 2;
&output_indent;
print "n(\"$comment\",\n";
$indent_level += 2;
&output_indent;
# Remove the \ and n at the end:
chop $output_statement_buffer;
chop $output_statement_buffer;
print "[\n";
&indent_plus ;
&add_a_node_attribute("OBJECT", $name);
&output_some_other_node_attributes;
&indent_minus ;
&output_indent;
print "],\n";
&output_indent;
print "[\n";
&indent_plus ;
foreach $successor (split(/ /, $successors)) {
&output_a_successor($successor, $comment);
}
&indent_minus;
&output_indent;
print "]\n";
&indent_minus;
&output_indent;
print " )\n";
&indent_minus;
&output_indent;
print " ),\n";
}
# If the node given to this procedure is an entry node of an
# unstructured that has an unreachable exit node, display a dashed arrow
# from the entry node to the exit:
sub output_an_eventual_unreachable_arrow {
my($control) = @_;
if ($unreachable_exit{$control}) {
$exit_node = $unreachable_exit{$control};
&add_an_edge_attribute("EDGEPATTERN", "dashed");
&add_an_edge_attribute("EDGECOLOR", "violet");
&output_a_successor($exit_node, "Unreachable from $control to $exit_node");
}
}
sub keep_for_output {
my($string) = @_;
$output_statement_buffer .= $string . "\\n";
}
$input_file_name = $ARGV[0];
shift;
# First build a map of unstructured with unreachable exit:
open(INPUT, "<$input_file_name") || die "Cannot open \"$input_file_name\".";
while () {
/^\204Unstructured Unreachable (.*) -> (.*)$/ && do {
# \204Unstructured Unreachable 0xf4a3e8 -> 0xf4a8a8
$entry_control = $1;
$exit_control = $2;
$unreachable_exit{$entry_control} = $exit_control;
}
}
close INPUT || die "Cannot close \"$input_file_name\".";
print "[\n";
$indent_level += 2;
# The label of the statement:
$control = $statement_number;
# Entry node of the module:
&add_a_node_attribute("COLOR", "yellow");
# Open again the imput file:
open(INPUT, "<$input_file_name") || die "Cannot open \"$input_file_name\".";
while () {
#print;
chop;
# daVinci do not like at all TABs:
s/\t/ /g;
# Protect the "" :
s/"/\\"/g;
($a_command_line = $_) =~ s/.(.*)/$1/;
/^\200Unstructured (.*) end: (.*)$/ && do {
# Unstructured 0x3c79f0 end: 0x3c8f30
$unstructured_begin = $1;
$unstructured_end = $2;
&output_a_statement_begin($control,
"Statement not from an unstructured");
&output_a_successor($unstructured_begin,
"Go to the entry of the unstructured");
&output_a_statement_end();
$statement_number ++;
# Keep track of the number of the statement that should follow
# this unstructured at its exit:
push(@statement_number_stack, $statement_number);
# Since the first node could be an IF, delay the _GO
$this_is_the_unstructured_entry_p = 1;
#&add_a_node_attribute("_GO", "ellipse");
&add_a_node_attribute("COLOR", "lightgreen");
next;
};
/^\201Unstructured End (.*) end: (.*)$/ && do {
# Unstructured End 0x3cfa40 end: 0x3cfa40
$unstructured_begin = $1;
$unstructured_end = $2;
$control = pop(@statement_number_stack);
next;
};
/^\202Unstructured Item (.*)$/ && do {
# \202Unstructured Item 0x3c79f0
# Should use a stack here ?
$control = $1;
next;
};
/^\203Unstructured Successor ->(.*)$/ && do {
# \203Unstructured Successor 0x3c8280
@successors = split(/ /, $1);
# Be careful, if there is something in the the successors, the first
# blank generated a void element...
# print "\n**** @successors, $#successors\n";
if ($#successors == -1) {
&add_a_node_attribute("_GO", "ellipse");
&add_a_node_attribute("COLOR", "lightgray");
&output_a_statement_begin($control, $a_command_line);
&output_a_successor($statement_number_stack[$#statement_number_stack],
"The unstructured end point to the statement following the unstructured");
}
elsif ($#successors == 2) {
# 2 successors, that is an "if then else":
&add_a_node_attribute("_GO", "rhombus");
if ($this_is_the_unstructured_entry_p == 0) {
&add_a_node_attribute("COLOR", "cyan");
}
else {
# Display a lightgreen rhombus to mark the IF at the unstructured entry:
$this_is_the_unstructured_entry_p = 0;
}
&output_a_statement_begin($control, $a_command_line);
&output_an_eventual_unreachable_arrow($control);
&add_an_edge_attribute("EDGECOLOR", "red");
&output_a_successor("then_$statement_number", $a_command_line);
&add_an_edge_attribute("EDGECOLOR", "blue");
&output_a_successor("else_$statement_number", $a_command_line);
&output_a_statement_end();
&add_a_node_attribute("COLOR", "lightred");
&add_a_node_attribute("_GO", "text");
&add_a_node_attribute("FONTFAMILY", "helvetica");
&add_a_node_attribute("FONTSTYLE", "bold_italic");
&add_an_edge_attribute("EDGECOLOR", "red");
&output_a_node("then_$statement_number", "THEN",
$successors[1], $a_command_line);
&add_a_node_attribute("COLOR", "lightblue");
&add_a_node_attribute("_GO", "text");
&add_a_node_attribute("FONTFAMILY", "helvetica");
&add_a_node_attribute("FONTSTYLE", "bold_italic");
&add_an_edge_attribute("EDGECOLOR", "blue");
&output_a_node("else_$statement_number", "ELSE",
$successors[2], $a_command_line);
$statement_number ++;
next;
}
else {
# Just a sequence I guess: */
&output_a_statement_begin($control, $a_command_line);
&output_a_successor($successors[1], $a_command_line);
&output_an_eventual_unreachable_arrow($control);
}
&output_a_statement_end();
next;
};
# By default, put the statement with a an explicit \ n for daVinci:
&keep_for_output($_);
}
close INPUT || die "Cannot close \"$input_file_name\".";
&output_a_statement_begin($control,
"Statement not from an unstructured");
&output_a_statement_end();
print "]\n";