/*
* e-Knife, a program slicing tool for Erlang based on the EDG
* Copyright (c) 2021. David Insa, Sergio PĂ©rez, Josep Silva, Salvador Tamarit.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package eknife;
import edg.DotFactory;
import edg.EDGFactory;
import edg.graph.EDG;
import edg.graph.Edge;
import edg.graph.LAST;
import edg.graph.Node;
import edg.slicing.ConstrainedAlgorithm;
import edg.slicing.SlicingAlgorithm;
import edg.slicing.SlicingCriterion;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class EKnife
{
public enum Language { Java, Erlang, Php }
public static void main(String[] args)
{
final Args arguments = EKnife.processArguments(args);
if (!arguments.isValid()) {
EKnife.printHelp();
System.exit(3);
}
EKnife.run(arguments);
}
private static Args processArguments(String[] args)
{
Args kArgs = new Args();
for (int argIndex = 0; argIndex < args.length; argIndex++)
{
final String arg = args[argIndex];
switch (arg)
{
case "-i": case "--input":
case "-o": case "--output":
case "-f": case "--file":
case "-l": case "--line":
case "-v": case "--var":
case "-n": case "--occurrence":
if (argIndex == args.length - 1) {
System.out.printf("Parameter %s requires an argument\n", arg);
printHelp();
System.exit(1);
}
default:
break;
}
switch (arg)
{
case "--help":
printHelp();
System.exit(0);
case "-i": case "--input":
kArgs.inputPath = args[argIndex + 1];
break;
case "-o": case "--output":
kArgs.outputFile = new File(args[argIndex + 1]);
break;
case "-f": case "--file":
kArgs.file = args[argIndex + 1];
break;
case "-l": case "--line":
kArgs.line = Integer.parseInt(args[argIndex + 1]);
break;
case "-v": case "--var":
kArgs.name = args[argIndex + 1];
break;
case "-n": case "--occurrence":
kArgs.occurrence = Integer.parseInt(args[argIndex + 1]);
break;
}
}
kArgs.completeData();
return kArgs;
}
private static void printHelp()
{
String help = "";
help += "Use the following options:\n";
help += " -i,--input The file/folder where the source code is\n";
help += " -o,--output The file/folder where the slice will be stored\n";
help += " -f,--file The file (relative to -i) where the slicing criterion is\n";
help += " -l,--line The line of the slicing criterion\n";
help += " -v,--var The name of the slicing criterion (must be a variable)\n";
help += " -n,--occurrence The occurrence of the slicing criterion in that line\n";
help += " --help Show this message.\n";
System.out.print(help);
}
private static void run(Args a)
{
boolean showIP = false;
Map edgeFlags = new HashMap<>();
edgeFlags.put(Edge.Type.Value, true);
edgeFlags.put(Edge.Type.ValueStructure, true);
edgeFlags.put(Edge.Type.ControlFlow, false);
edgeFlags.put(Edge.Type.Control, true);
edgeFlags.put(Edge.Type.Flow, true);
edgeFlags.put(Edge.Type.Input, showIP);
edgeFlags.put(Edge.Type.Call, showIP);
edgeFlags.put(Edge.Type.Output, showIP);
edgeFlags.put(Edge.Type.Summary, false);
final LAST last = LASTFactory.createLAST(Language.Erlang, a.inputPath, true);
// DotFactory.createDot(new File("/Users/serperu/Desktop/SlicerOutput/graph.dot"), new EDG(last), edgeFlags);
final EDG edg = new EDGFactory(last).createEDG();
// DotFactory.createDot(new File("/Users/serperu/Desktop/SlicerOutput/graph.dot"), edg, edgeFlags);
final SlicingCriterion slicingCriterion = new SlicingCriterion(a.file, a.line, a.name, a.occurrence);
final Node SC = edg.getNode(slicingCriterion);
if (SC == null) {
System.out.println("Error: the slicing criterion could not be found! " + slicingCriterion);
System.exit(1);
}
final SlicingAlgorithm slicingAlgorithm = new ConstrainedAlgorithm(edg);
final Set slice = slicingAlgorithm.slice(SC);
if (slice.isEmpty()) {
System.out.println("Warning: no files will be written, as the slice is empty.");
System.exit(2);
}
DotFactory.createDot(new File("/Users/serperu/Desktop/SlicerOutput/graphSliced.dot"), edg, SC, slice, edgeFlags);
CodeFactory.createCode(Language.Erlang, a.outputFile, edg, slice);
}
static class Args {
String inputPath;
File outputFile;
String file;
int line;
String name;
int occurrence = 1;
void completeData() {
if (file == null && inputPath != null && new File(inputPath).isFile())
file = new File(inputPath).getName();
}
boolean isValid() {
return inputPath != null && new File(inputPath).exists() &&
outputFile != null && (outputFile.exists() || outputFile.getAbsoluteFile().getParentFile().isDirectory()) &&
file != null &&
line > 0 &&
name != null && !name.isEmpty() &&
occurrence > 0;
}
}
}