TMLTextSpecification.java 111.31 KiB
/* Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Ludovic Apvrille
*
* ludovic.apvrille AT enst.fr
*
* This software is a computer program whose purpose is to allow the
* edition of TURTLE analysis, design and deployment diagrams, to
* allow the generation of RT-LOTOS or Java code from this diagram,
* and at last to allow the analysis of formal validation traces
* obtained from external tools, e.g. RTL from LAAS-CNRS and CADP
* from INRIA Rhone-Alpes.
*
* This software is governed by the CeCILL license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/ or redistribute the software under the terms of the CeCILL
* license as circulated by CEA, CNRS and INRIA at the following URL
* "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided only
* with a limited warranty and the software's author, the holder of the
* economic rights, and the successive licensors have only limited
* liability.
*
* In this respect, the user's attention is drawn to the risks associated
* with loading, using, modifying and/or developing or reproducing the
* software by the user in light of its specific status of free software,
* that may mean that it is complicated to manipulate, and that also
* therefore means that it is reserved for developers and experienced
* professionals having in-depth computer knowledge. Users are therefore
* encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or
* data to be ensured and, more generally, to use and operate it in the
* same conditions as regards security.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL license and that you accept its terms.
*/
package tmltranslator;
import common.SpecConfigTTool;
import myutil.Conversion;
import myutil.FileException;
import myutil.FileUtils;
import myutil.TraceManager;
import java.io.BufferedReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* Class TMLTextSpecification
* Import and export of TML textual specifications
* Creation: 12/09/2007
*
* @author Ludovic APVRILLE
* @version 1.0 12/09/2007
*/
public class TMLTextSpecification<E> {
public final static String CR = "\n";
public final static String SP = " ";
public final static String CR2 = "\n\n";
public final static String SC = ";";
public final static String C = ",";
public final static String AENCRYPT = "AE";
public final static String SENCRYPT = "SE";
public final static String MAC = "MAC";
public final static String NONCE = "NONCE";
public final static String HASH = "HASH";
public final static String ADV = "ADV";
public final static String EMPTY_KEY_NONCE = "-";
public final static int ENCRYPTION_PROCESS = 1;
public final static int DECRYPTION_PROCESS = 2;
private String spec;
private String title;
private TMLModeling<E> tmlm;
private ArrayList<TMLTXTError> errors;
private ArrayList<TMLTXTError> warnings;
// For reading TMLTXT specifications
private boolean inDec = true;
private boolean inTask = false;
private boolean inTaskDec = false;
// private boolean inTaskBehavior = false;
private TMLTask task;
private TMLActivityElement tmlae;
private ArrayList<TMLParserSaveElt> parses;
private Map<String, SecurityPattern> securityPatternMap = new HashMap<String, SecurityPattern>();
private static String keywords[] = {"BOOL", "INT", "NAT", "CHANNEL", "EVENT", "REQUEST",
"LOSSYCHANNEL", "VCCHANNEL", "CONFCHANNEL", "AUTHCHANNEL",
"LOSSYEVENT", "LOSSYREQUEST", "BRBW", "NBRNBW",
"BRNBW", "INF", "NIB", "NINB", "TASK", "ENDTASK", "DAEMON", "TASKOP", "IF", "ELSE", "ORIF", "ENDIF", "FOR", "ENDFOR",
"SELECTEVT", "CASE", "ENDSELECTEVT", "ENDCASE", "WRITE", "READ", "WAIT", "NOTIFY", "NOTIFIED", "NOTIFYREQUEST", "RAND", "CASERAND",
"ENDRAND",
"ENDCASERAND", "EXECI", "EXECC", "DELAY", "RANDOM",
"RANDOMSEQ", "ENDRANDOMSEQ", "SEQ", "ENDSEQ", "PRAGMA"};
private String channeltypes[] = {"BRBW", "NBRNBW", "BRNBW"};
private String eventtypes[] = {"INF", "NIB", "NINB"};
private String beginArray[] = {"TASK", "FOR", "IF", "ELSE", "ORIF", "SELECTEVT", "CASE", "RAND", "CASERAND", "RANDOMSEQ", "SEQ"};
private String endArray[] = {"ENDTASK", "ENDFOR", "ENDIF", "ELSE", "ORIF", "ENDSELECTEVT", "ENDCASE", "ENDRAND", "ENDCASERAND", "ENDRANDOMSEQ",
"ENDSEQ"};
// New argument to be added on EXECC for security: CC_name Type Encrypt_complexity Decrypt_Complexity Overhead Size Nonce Key
// New argument on Read/Write Channels: CC_name
public TMLTextSpecification(String _title) {
title = _title;
}
public TMLTextSpecification(String _title, boolean reset) {
title = _title;
if (reset) {
DIPLOElement.resetID();
}
}
public void saveFile(String path, String filename) throws FileException {
SpecConfigTTool.checkAndCreateTMLDir(path);
TraceManager.addUser("Saving TML spec file in " + path + filename);
FileUtils.saveFile(path + filename, spec);
}
public TMLModeling<E> getTMLModeling() {
return tmlm;
}
public ArrayList<TMLTXTError> getErrors() {
return errors;
}
public ArrayList<TMLTXTError> getWarnings() {
return warnings;
}
public void indent() {
indent(4);
}
public void indent(int _nbDec) {
int dec = 0;
int indexEnd;
String output = "";
String tmp;
int nbOpen = 0;
int nbClose = 0;
while ((indexEnd = spec.indexOf('\n')) > -1) {
tmp = spec.substring(0, indexEnd + 1);
try {
spec = spec.substring(indexEnd + 1, spec.length());
} catch (Exception e) {
spec = "";
}
nbOpen = nbOfOpen(tmp);
nbClose = nbOfClose(tmp);
dec -= nbClose * _nbDec;
tmp = Conversion.addHead(tmp.trim(), ' ', dec);
dec += nbOpen * _nbDec;
//TraceManager.addDev("dec=" + dec);
output += tmp + "\n";
}
spec = output;
}
private int nbOfOpen(String tmp) {
return nbOf(tmp, beginArray);
}
private int nbOfClose(String tmp) {
return nbOf(tmp, endArray);
}
private int nbOf(String _tmp, String[] array) {
String tmp;
// int size;
for (int i = 0; i < array.length; i++) {
if (_tmp.startsWith(array[i])) {
tmp = _tmp.substring(array[i].length(), _tmp.length());
//TraceManager.addDev("tmp=" + tmp + " _tmp" + _tmp + " array=" + array[i]);
if ((tmp.length() == 0) || (tmp.charAt(0) == ' ') || (tmp.charAt(0) == '(') || (tmp.charAt(0) == '\n')) {
//TraceManager.addDev("Returning 1!!");
return 1;
}
}
}
return 0;
}
public String toString() {
return spec;
}
public String toTextFormat(TMLModeling<E> tmlm) {
tmlm.removeForksAndJoins();
tmlm.sortByName();
// Print TMLTasks WCET
tmlm.printWCETOfTasks();
spec = makeDeclarations(tmlm);
//Set up Cryptographic Configurations
spec += makeTasks(tmlm);
indent();
return spec;
}
public String makeDeclarations(TMLModeling<E> tmlm) {
int i;
String sb = "";
sb += "// TML Application - FORMAT 0.2" + CR;
sb += "// Application: " + title + CR;
sb += "// Generated: " + new Date().toString() + CR2;
sb += "// PRAGMAS" + CR;
for(String s: tmlm.getPragmas()) {
sb += "PRAGMA " + s + CR;
}
sb += CR;
sb += "// Channels" + CR;
for (TMLChannel ch : tmlm.getChannels()) {
if (ch.isBasicChannel()) {
sb += "CHANNEL" + SP + ch.getName() + SP + TMLChannel.getStringType(ch.getType()) + SP + ch.getSize();
if (!ch.isInfinite()) {
sb += SP + ch.getMax();
}
//TraceManager.addDev("Declaration. Handling channel " + ch.getName());
if (ch.getOriginTask() == null) {
TraceManager.addDev("Missing origin Task in " + ch.getName());
}
if (ch.getDestinationTask() == null) {
TraceManager.addDev("Missing destination Task in " + ch.getName());
}
sb += SP + "OUT" + SP + ch.getOriginTask().getName() + SP + "IN" + SP + ch.getDestinationTask().getName() + CR;
} else {
sb += "CHANNEL" + SP + ch.getName() + SP + TMLChannel.getStringType(ch.getType()) + SP + ch.getSize();
if (!ch.isInfinite()) {
sb += SP + ch.getMax();
}
sb += SP + "OUT";
for (TMLTask task : ch.getOriginTasks()) {
sb += SP + task.getName();
}
sb += SP + "IN";
for (TMLTask task : ch.getDestinationTasks()) {
sb += SP + task.getName();
}
sb += CR;
}
if (ch.isLossy()) {
sb += "LOSSYCHANNEL" + SP + ch.getName() + SP + ch.getLossPercentage() + SP + ch.getMaxNbOfLoss() + CR;
}
if (ch.getVC() >= 0) {
sb += "VCCHANNEL" + SP + ch.getName() + SP + ch.getVC() + CR;
}
if (ch.isCheckConfChannel()) {
sb += "CONFCHANNEL" + SP + ch.getName() + SP + CR;
}
if (ch.isCheckAuthChannel()) {
sb += "AUTHCHANNEL" + SP + ch.getName() + SP + CR;
}
}
sb += CR;
sb += "// Events" + CR;
for (TMLEvent evt : tmlm.getEvents()) {
sb += "EVENT" + SP + evt.getName() + "(";
for (i = 0; i < evt.getNbOfParams(); i++) {
if (i != 0) {
sb += ", ";
}
sb += TMLType.getStringType(evt.getType(i).getType());
}
sb += ")";
sb += SP + evt.getTypeTextFormat();
if (!evt.isInfinite()) {
sb += SP + evt.getMaxSize();
}
//TraceManager.addDev("Handing Event:" + evt.getName());
if (evt.getOriginTask() == null) {
TraceManager.addDev("Missing origin Task in " + evt.getName());
}
if (evt.getDestinationTask() == null) {
TraceManager.addDev("Missing destination Task in " + evt.getName());
}
sb += SP + evt.getOriginTask().getName() + SP + evt.getDestinationTask().getName();
sb += CR;
if (evt.isLossy()) {
sb += "LOSSYEVENT" + SP + evt.getName() + SP + evt.getLossPercentage() + SP + evt.getMaxNbOfLoss() + CR;
}
}
sb += CR;
sb += "// Requests" + CR;
for (TMLRequest request : tmlm.getRequests()) {
sb += "REQUEST" + SP + request.getName() + "(";
for (i = 0; i < request.getNbOfParams(); i++) {
if (i != 0) {
sb += ", ";
}
sb += TMLType.getStringType(request.getType(i).getType());
}
sb += ")";
for (TMLTask t : request.getOriginTasks()) {
sb += SP + t.getName();
}
sb += SP + request.getDestinationTask().getName();
sb += CR;
if (request.isLossy()) {
sb += "LOSSYREQUEST" + SP + request.getName() + SP + request.getLossPercentage() + SP + request.getMaxNbOfLoss() + CR;
}
}
sb += CR;
return sb;
}
public String makeTasks(TMLModeling<E> tmlm) {
String sb = "";
for (TMLTask task : tmlm.getTasks()) {
sb += "TASK" + SP + task.getName() + CR;
if (task.isDaemon()) {
sb += "DAEMON" + CR;
}
if (task.isPeriodic()) {
sb += "PERIODIC " + task.getPeriodValue() + SP + task.getPeriodUnit() + CR;
}
sb += "TASKOP" + SP + task.getOperation() + CR;
sb += makeActivity(task);
sb += "ENDTASK" + CR2;
}
return sb;
}
public String makeActivity(TMLTask task) {
String sb = "";
sb += "//Local variables" + CR;
//TraceManager.addDev("Making activity of task:" + task.getTaskName());
for (TMLAttribute attr : task.getAttributes()) {
sb += TMLType.getStringType(attr.getType().getType()) + SP + attr.getName();
if ((attr.getInitialValue() != null) && (attr.getInitialValue().length() > 0)) {
sb += " = " + attr.getInitialValue();
}
sb += CR;
}
sb += CR;
sb += "//Behavior" + CR;
sb += makeBehavior(task, task.getActivityDiagram().getFirst());
return sb;
}
public String makeBehavior(TMLTask task, TMLActivityElement elt) {
String code,/* code1,*/ code2;
TMLForLoop tmlfl;
TMLActivityElementChannel tmlch;
TMLActivityElementEvent tmlevt;
TMLSendRequest tmlreq;
// TMLEvent evt;
TMLRandom random;
int i;
String tmp1, tmp2;
if (elt instanceof TMLStartState) {
return makeBehavior(task, elt.getNextElement(0));
} else if (elt instanceof TMLStopState) {
return "";
} else if (elt instanceof TMLExecI) {
code = "EXECI" + SP + modifyString(((TMLExecI) elt).getAction()) + CR;
return code + makeBehavior(task, elt.getNextElement(0));
} else if (elt instanceof TMLExecIInterval) {
code = "EXECI" + SP + modifyString(((TMLExecIInterval) elt).getMinDelay()) + SP + modifyString(((TMLExecIInterval) elt).getMaxDelay()) + CR;
return code + makeBehavior(task, elt.getNextElement(0));
} else if (elt instanceof TMLExecC) {
if (elt.getSecurityPattern() == null) {
code = "EXECC" + SP + modifyString(((TMLExecC) elt).getAction()) + CR;
} else {
String type = "";
if (elt.getSecurityPattern().getType().equals(SecurityPattern.ASYMMETRIC_ENC_PATTERN)) {
type = AENCRYPT;
} else if (elt.getSecurityPattern().getType().equals(SecurityPattern.SYMMETRIC_ENC_PATTERN)) {
type = SENCRYPT;
} else if (elt.getSecurityPattern().getType().equals(SecurityPattern.MAC_PATTERN)) {
type = MAC;
} else if (elt.getSecurityPattern().getType().equals(SecurityPattern.NONCE_PATTERN)) {
type = NONCE;
} else if (elt.getSecurityPattern().getType().equals(SecurityPattern.HASH_PATTERN)) {
type = HASH;
} else if (elt.getSecurityPattern().getType().equals(SecurityPattern.ADVANCED_PATTERN)) {
type = ADV;
}
String nonce = elt.getSecurityPattern().getNonce();
if (nonce.length() == 0) {
nonce = EMPTY_KEY_NONCE;
}
String key = elt.getSecurityPattern().getKey();
if (key.length() == 0) {
key = EMPTY_KEY_NONCE;
}
int process = (((TMLExecC) elt).isDecryptionProcess()) ? DECRYPTION_PROCESS : ENCRYPTION_PROCESS;
code = "EXECC" + SP + modifyString(((TMLExecC) elt).getAction()) + SP + elt.getSecurityPattern().getName() + SP + type + SP +
elt.getSecurityPattern().getEncTime() + SP + elt.getSecurityPattern().getDecTime() + SP + elt.getSecurityPattern().getOverhead() + SP +
elt.getSecurityPattern().getSize() + SP + nonce + SP + key + SP + process + CR;
}
return code + makeBehavior(task, elt.getNextElement(0));
} else if (elt instanceof TMLExecCInterval) {
code = "EXECC" + SP + modifyString(((TMLExecCInterval) elt).getMinDelay()) + SP + modifyString(((TMLExecCInterval) elt).getMaxDelay()) + CR;
return code + makeBehavior(task, elt.getNextElement(0));
} else if (elt instanceof TMLDelay) {
tmp1 = ((TMLDelay) elt).getMinDelay();
tmp2 = ((TMLDelay) elt).getMaxDelay();
if (tmp1.compareTo(tmp2) == 0) {
code = "DELAY" + SP + modifyString(((TMLDelay) elt).getMinDelay()) + SP + modifyString(((TMLDelay) elt).getUnit()) + SP + "isActiveDelay" + SP + ((TMLDelay) elt).getActiveDelay() + CR;
} else {
code = "DELAY" + SP + modifyString(((TMLDelay) elt).getMinDelay()) + SP + modifyString(((TMLDelay) elt).getMaxDelay()) + SP + modifyString(((TMLDelay) elt).getUnit()) + SP + "isActiveDelay" + SP + ((TMLDelay) elt).getActiveDelay() + CR;
}
return code + makeBehavior(task, elt.getNextElement(0));
} else if (elt instanceof TMLForLoop) {
tmlfl = (TMLForLoop) elt;
if (tmlfl.isInfinite()) {
code = "FOR( " + SC + " " + SC + " )" + CR;
} else {
code = "FOR(" + tmlfl.getInit() + SC + SP;
code += tmlfl.getCondition() + SC + SP;
code += tmlfl.getIncrement() + ")" + CR;
}
code += makeBehavior(task, elt.getNextElement(0));
return code + "ENDFOR" + CR + makeBehavior(task, elt.getNextElement(1));
} else if (elt instanceof TMLRandom) {
random = (TMLRandom) elt;
code = "RANDOM" + SP + modifyString("" + random.getFunctionId()) + SP;
code += modifyString(random.getVariable()) + SP;
code += modifyString(random.getMinValue()) + SP;
code += modifyString(random.getMaxValue()) + CR;
return code + makeBehavior(task, elt.getNextElement(0));
} else if (elt instanceof TMLActionState) {
code = modifyString(((TMLActivityElementWithAction) elt).getAction()) + CR;
return code + makeBehavior(task, elt.getNextElement(0));
} else if (elt instanceof TMLWriteChannel) {
tmlch = (TMLActivityElementChannel) elt;
code = "WRITE ";
for (int k = 0; k < tmlch.getNbOfChannels(); k++) {
code = code + tmlch.getChannel(k).getName() + SP;
}
//TraceManager.addDev("Nb of samples in task " + task.getName() + " = " + tmlch.getNbOfSamples());
code = code + modifyString(tmlch.getNbOfSamples());
if (elt.getSecurityPattern() != null) {
code = code + SP + elt.getSecurityPattern().getName() + CR;
} else {
code = code + CR;
}
return code + makeBehavior(task, elt.getNextElement(0));
} else if (elt instanceof TMLReadChannel) {
tmlch = (TMLActivityElementChannel) elt;
if (elt.getSecurityPattern() == null) {
code = "READ " + tmlch.getChannel(0).getName() + SP + modifyString(tmlch.getNbOfSamples()) + CR;
} else {
code = "READ " + tmlch.getChannel(0).getName() + SP + modifyString(tmlch.getNbOfSamples()) + SP + elt.getSecurityPattern().getName() + CR;
}
return code + makeBehavior(task, elt.getNextElement(0));
} else if (elt instanceof TMLSendEvent) {
tmlevt = (TMLActivityElementEvent) elt;
code = "NOTIFY " + tmlevt.getEvent().getName() + " " + tmlevt.getAllParams(" ") + CR;
return code + makeBehavior(task, elt.getNextElement(0));
} else if (elt instanceof TMLWaitEvent) {
tmlevt = (TMLActivityElementEvent) elt;
code = "WAIT " + tmlevt.getEvent().getName() + " " + tmlevt.getAllParams(" ") + CR;
return code + makeBehavior(task, elt.getNextElement(0));
} else if (elt instanceof TMLNotifiedEvent) {
tmlevt = (TMLActivityElementEvent) elt;
code = "NOTIFIED " + tmlevt.getEvent().getName() + " " + tmlevt.getVariable() + CR;
return code + makeBehavior(task, elt.getNextElement(0));
} else if (elt instanceof TMLSendRequest) {
tmlreq = (TMLSendRequest) elt;
code = "NOTIFYREQUEST " + tmlreq.getRequest().getName() + " " + tmlreq.getAllParams(" ") + CR;
return code + makeBehavior(task, elt.getNextElement(0));
} else if (elt instanceof TMLSequence) {
code = "";
for (i = 0; i < elt.getNbNext(); i++) {
code += makeBehavior(task, elt.getNextElement(i));
}
return code;
} else if (elt instanceof TMLChoice) {
TMLChoice choice = (TMLChoice) elt;
code = "";
if (choice.getNbGuard() != 0) {
// code1 = "";
int index1 = choice.getElseGuard(), index2 = choice.getAfterGuard();
int nb = Math.max(choice.nbOfNonDeterministicGuard(), choice.nbOfStochasticGuard());
if (nb > 0) {
// Assumed to be a non deterministic choice
TraceManager.addDev("Non determinitic choice in task " + task.getTaskName()+ " nb=" + nb +
" NonDeterministic:" + choice.nbOfNonDeterministicGuard()
+ " nbOfStochastic:" + choice.nbOfStochasticGuard()
+ " nbOfGuards:" + choice.getNbGuard() + " choice=" + choice.customExtraToXML());
code += "RAND" + CR;
}
nb = 0;
for (i = 0; i < choice.getNbGuard(); i++) {
if (i != index2) {
if (choice.isNonDeterministicGuard(i)) {
code2 = "" + (int) (Math.floor(100 / choice.getNbGuard()));
nb++;
} else if (choice.isStochasticGuard(i)) {
code2 = prepareString(choice.getStochasticGuard(i));
nb++;
} else {
code2 = modifyString(choice.getGuard(i));
code2 = Conversion.replaceAllChar(code2, '[', "(");
code2 = Conversion.replaceAllChar(code2, ']', ")");
}
//TraceManager.addDev("guard = " + code1 + " i=" + i);
if (nb != 0) {
/*if (choice.isNonDeterministicGuard(i)) {
code = "CASERAND 50";
} else {
code = "CASERAND " + prepareString(choice.getStochasticGuard(i));
}*/
//nb ++;
if (i != index1) {
code += "CASERAND " + code2 + CR;
code += makeBehavior(task, elt.getNextElement(i));
code += "ENDCASERAND" + CR;
}
} else {
if (i == 0) {
code += "IF " + code2;
} else {
if (i != index1) {
code += "ORIF " + code2;
} else {
code += "ELSE";
}
}
code += CR + makeBehavior(task, elt.getNextElement(i));
}
}
}
if (nb > 0) {
// Assumed to be a non deterministic choice
code += "ENDRAND" + CR;
} else {
code += "ENDIF" + CR;
}
if (index2 != -1) {
code += makeBehavior(task, elt.getNextElement(index2));
}
}
return code;
} else if (elt instanceof TMLSelectEvt) {
code = "SELECTEVT" + CR;
for (i = 0; i < elt.getNbNext(); i++) {
try {
tmlevt = (TMLActivityElementEvent) (elt.getNextElement(i));
code += "CASE ";
code += tmlevt.getEvent().getName() + " " + tmlevt.getAllParams(" ") + CR;
code += makeBehavior(task, elt.getNextElement(i).getNextElement(0));
code += "ENDCASE" + CR;
} catch (Exception e) {
TraceManager.addError("Non-event receiving following a select event operator");
}
}
code += "ENDSELECTEVT" + CR;
return code;
} else if (elt instanceof TMLRandomSequence) {
code = "RANDOMSEQ" + CR;
for (i = 0; i < elt.getNbNext(); i++) {
code += "SEQ" + CR;
code += makeBehavior(task, elt.getNextElement(i));
code += "ENDSEQ" + CR;
}
code += "ENDRANDOMSEQ" + CR;
return code;
} else {
if (elt == null) {
return "";
}
TraceManager.addDev("Unrecognized element: " + elt);
return makeBehavior(task, elt.getNextElement(0));
}
}
public boolean makeTMLModeling(String _spec) {
spec = _spec;
tmlm = new TMLModeling<>();
errors = new ArrayList<TMLTXTError>();
warnings = new ArrayList<TMLTXTError>();
spec = Conversion.removeComments(spec);
//TraceManager.addDev(spec);
browseCode();
return (errors.size() == 0);
}
public String printErrors() {
String ret = "";
for (TMLTXTError error : errors) {
ret += "ERROR at line " + error.lineNb + ": " + error.message + CR;
try {
ret += "->" + spec.split("\n")[error.lineNb] + CR2;
} catch (Exception e) {
ret += "(Code line not accessible)" + CR;
}
}
return ret;
}
public String printWarnings() {
String ret = "";
for (TMLTXTError error : warnings) {
ret += "WARNING at line " + error.lineNb + CR;
ret += error.message + CR;
}
return ret;
}
public String printSummary() {
String ret = "";
if (errors.size() == 0) {
ret += printWarnings();
ret += "Compilation successful" + CR;
ret += "No error, " + warnings.size() + " warning(s)" + CR;
} else {
ret += printErrors() + CR + printWarnings() + CR;
ret += "Compilation failed" + CR;
ret += errors.size() + " error(s), " + warnings.size() + " warning(s)" + CR;
}
return ret;
}
public void browseCode() {
// Browse lines of code one after the other
// Build accordinlgy the TMLModeling and updates errors and warnings
// In case of fatal error, immedialty quit code bowsing
StringReader sr = new StringReader(spec);
BufferedReader br = new BufferedReader(sr);
String s;
String s1;
String[] split;
int lineNb = 0;
inDec = true;
inTask = false;
inTaskDec = false;
// inTaskBehavior = false;
//String instruction;
parses = new ArrayList<TMLParserSaveElt>();
//Start by reading once and creating all Cryptographic Configuration
try {
while ((s = br.readLine()) != null) {
if (s != null) {
s = s.trim();
//TraceManager.addDev("line=" + s);
s = removeUndesiredWhiteSpaces(s, lineNb);
s1 = Conversion.replaceAllString(s, "\t", " ");
s1 = Conversion.replaceRecursiveAllString(s1, " ", " ");
//TraceManager.addDev("s1=" + s1);
if (s1 != null) {
split = s1.split("\\s");
if (split.length > 0) {
if (isInstruction(split[0], "EXECC")) {
if (!findAndCheckSec(split)) {
addError(0, lineNb, 0, "The Security Pattern " + split[2] + " already exists");
}
}
}
}
lineNb++;
}
}
} catch (Exception e) {
TraceManager.addError("Exception when reading specification: " + e.getMessage());
addError(0, lineNb, 0, "Exception when reading specification");
}
lineNb = 0;
br = new BufferedReader(new StringReader(spec));
try {
while ((s = br.readLine()) != null) {
if (s != null) {
s = s.trim();
//TraceManager.addDev("line=" + s);
s = removeUndesiredWhiteSpaces(s, lineNb);
s1 = Conversion.replaceAllString(s, "\t", " ");
s1 = Conversion.replaceRecursiveAllString(s1, " ", " ");
//TraceManager.addDev("s1=" + s1);
if (s1 != null) {
split = s1.split("\\s");
if (split.length > 0) {
//TraceManager.addDev("analyse");
analyseInstruction(s, lineNb, split);
//TraceManager.addDev("end analyse");
}
}
lineNb++;
}
}
} catch (Exception e) {
TraceManager.addError("Exception when reading specification: " + e.getMessage());
addError(0, lineNb, 0, "Exception when reading specification");
}
}
public boolean findAndCheckSec(String[] _split) {
boolean isNewSec = true;
if (_split.length > 10) {
TraceManager.addDev("Found EXECC in: " + _split.length + " name=" + _split[2] + " type=" + _split[3]);
if (_split[10].compareTo("" + ENCRYPTION_PROCESS) == 0) {
String ccName = _split[2];
if (securityPatternMap.containsKey(ccName)) {
isNewSec = false;
} else {
String type = _split[3];
String stringType = "";
if (type.equals(AENCRYPT)) {
stringType = SecurityPattern.ASYMMETRIC_ENC_PATTERN;
} else if (type.equals(SENCRYPT)) {
stringType = SecurityPattern.SYMMETRIC_ENC_PATTERN;
} else if (type.equals(HASH)) {
stringType = SecurityPattern.HASH_PATTERN;
} else if (type.equals(MAC)) {
stringType = SecurityPattern.MAC_PATTERN;
} else if (type.equals(NONCE)) {
stringType = SecurityPattern.NONCE_PATTERN;
} else if (type.equals(ADV)) {
stringType = SecurityPattern.ADVANCED_PATTERN;
}
if (!stringType.isEmpty()) {
TraceManager.addDev("Found security pattern: " + ccName + " with type: " + stringType);
String nonce = _split[8];
if (_split[8].compareTo(EMPTY_KEY_NONCE) == 0) {
nonce = "";
}
String key = _split[9];
if (_split[9].compareTo(EMPTY_KEY_NONCE) == 0) {
key = "";
}
SecurityPattern sp = new SecurityPattern(ccName, stringType, _split[6], _split[7], _split[4], _split[5], nonce, "",
key);
tmlm.addSecurityPattern(sp);
securityPatternMap.put(ccName, sp);
TraceManager.addDev("Security pattern " + ccName + " added");
}
}
}
}
return isNewSec;
}
public void addError(int _type, int _lineNb, int _charNb, String _msg) {
TMLTXTError error = new TMLTXTError(_type);
error.lineNb = _lineNb;
error.charNb = _charNb;
error.message = _msg;
errors.add(error);
}
public int analyseInstruction(String _line, int _lineNb, String[] _split) throws TMLCheckingError {
String error;
String params;
String id;
TMLChannel ch;
TMLEvent evt;
TMLRequest request;
TMLTask t1, t2;
TMLAttribute attribute;
// TMLType type;
TMLStopState stop;
TMLRandom random;
int tmp, tmp0, tmp1, i;
int dec = 0;
boolean blocking;
TMLParserSaveElt parseElt;
//TraceManager.addDev("Analyzing instruction:" + _line);
if (parses.size() > 0) {
parseElt = parses.get(0);
if ((parseElt.type == TMLParserSaveElt.SELECTEVT) && ((!isInstruction("CASE", _split[0]) && (!isInstruction("ENDSELECTEVT", _split[0]))))) {
error = "CASE or ENDSELECTEVT instruction expected";
addError(0, _lineNb, 0, error);
return -1;
}
if ((parseElt.type == TMLParserSaveElt.RAND) && ((!isInstruction("CASERAND", _split[0]) && (!isInstruction("ENDRAND", _split[0]))))) {
error = "CASERAND or ENDRAND instruction expected";
addError(0, _lineNb, 0, error);
return -1;
}
}
// PRAGMA
if (isInstruction("PRAGMA", _split[0])) {
if (!inDec) {
error = "A pragma must not be declared outside of the declaration part of a TML specification";
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length < 2) {
error = "A pragma instruction must contain a pragma";
addError(0, _lineNb, 0, error);
return -1;
}
String pragma = "";
for (int cpt=1; cpt<_split.length; cpt++) {
pragma += _split[cpt] + " ";
}
tmlm.addPragma(pragma);
}
// CHANNEL
if (isInstruction("CHANNEL", _split[0])) {
if (!inDec) {
error = "A channel may not be declared in a non-declaration part of a TML specification";
addError(0, _lineNb, 0, error);
return -1;
}
if (!((_split.length > 7))) {
error = "A channel must be declared with at least 7 parameters, and not: " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (!checkParameter("CHANNEL", _split, 1, 0, _lineNb)) {
return -1;
}
if (!checkParameter("CHANNEL", _split, 2, 2, _lineNb)) {
return -1;
}
if (!checkParameter("CHANNEL", _split, 3, 1, _lineNb)) {
return -1;
}
// Max nb of elements?
try {
tmp = Integer.decode(_split[4]).intValue();
dec = 1;
} catch (Exception e) {
dec = 0;
tmp = 8;
}
//TraceManager.addDev("Checking OUT");
// "OUT" keyword?
if (!checkParameter("CHANNEL", _split, 4 + dec, 10, _lineNb)) {
return -1;
}
//TraceManager.addDev("Checking other params of channels");
int indexOfIN = -1;
for (i = 5 + dec; i < _split.length; i++) {
if (!checkParameter("CHANNEL", _split, i, 0, _lineNb)) {
return -1;
}
if (_split[i].compareTo("IN") == 0) {
indexOfIN = i;
}
}
if (indexOfIN == -1) {
error = "\"IN\" keyword is missing";
addError(0, _lineNb, 0, error);
return -1;
}
if (tmlm.getChannelByName(_split[1]) != null) {
error = "Duplicate definition of channel " + _split[1];
addError(0, _lineNb, 0, error);
return -1;
}
if (_split[2].toUpperCase().compareTo("NIB") == 0) {
}
ch = new TMLChannel(_split[1], null);
ch.setTypeByName(_split[2]);
ch.setMax(tmp);// the capacity already calculated with _split[4]
try {
tmp = Integer.decode(_split[3]).intValue();
} catch (Exception e) {
tmp = 4;
}
ch.setSize(tmp);
for (i = 5 + dec; i < _split.length; i++) {
if (i != indexOfIN) {
t1 = tmlm.getTMLTaskByName(_split[i]);
if (t1 == null) {
t1 = new TMLTask(_split[i], null, null);
tmlm.addTask(t1);
//TraceManager.addDev("New task:" + _split[4+dec]);
}
TMLPort port = new TMLPort(ch.getName(), null);
ch.addTaskPort(t1, port, (i < indexOfIN));
}
}
TraceManager.addDev("******** ch " + ch.getName() + " toBasicIfPossible");
ch.toBasicIfPossible();
if (ch.getOriginPort() == null) {
TraceManager.addDev("******** NULL PORT");
}
if (!(ch.isBasicChannel())) {
TraceManager.addDev("******* Not a basic channel");
if (ch.isBadComplexChannel()) {
error = "A complex channel must be \"1 -> many\" of \"many -> 1\"";
addError(0, _lineNb, 0, error);
return -1;
}
}
tmlm.addChannel(ch);
} // CHANNEL
// LOSSYCHANNEL
if (isInstruction("LOSSYCHANNEL", _split[0])) {
if (!inDec) {
error = "A lossychannel may not be declared in a non-declaration part of a TML specification";
addError(0, _lineNb, 0, error);
return -1;
}
if (!((_split.length > 3) && (_split.length < 5))) {
error = "A lossychannel must be declared with exactly 3 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (!checkParameter("LOSSYCHANNEL", _split, 1, 0, _lineNb)) {
return -1;
}
if (!checkParameter("LOSSYCHANNEL", _split, 2, 1, _lineNb)) {
return -1;
}
if (!checkParameter("LOSSYCHANNEL", _split, 3, 9, _lineNb)) {
return -1;
}
ch = tmlm.getChannelByName(_split[1]);
if (ch == null) {
error = "lossy channel not previously declared as a regular channel " + _split[1];
addError(0, _lineNb, 0, error);
return -1;
}
try {
tmp0 = Integer.decode(_split[2]).intValue();
} catch (Exception e) {
tmp0 = 5;
}
try {
tmp1 = Integer.decode(_split[3]).intValue();
} catch (Exception e) {
tmp1 = -1;
}
ch.setLossy(true, tmp0, tmp1);
} // LOSSYCHANNEL
if (isInstruction("VCCHANNEL", _split[0])) {
if (!inDec) {
error = "A vcchannel may not be declared in a non-declaration part of a TML specification";
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length != 3) {
error = "A vcchannel must be declared with exactly 2 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (!checkParameter("VCCHANNEL", _split, 1, 0, _lineNb)) {
return -1;
}
if (!checkParameter("VCCHANNEL", _split, 2, 1, _lineNb)) {
return -1;
}
ch = tmlm.getChannelByName(_split[1]);
if (ch == null) {
error = "vcc channel not previously declared as a regular channel " + _split[1];
addError(0, _lineNb, 0, error);
return -1;
}
try {
tmp0 = Integer.decode(_split[2]);
} catch (Exception e) {
tmp0 = -1;
}
ch.setVC(tmp0);
} // VCCHANNEL
if (isInstruction("CONFCHANNEL", _split[0])) {
if (!inDec) {
error = "A confchannel may not be declared in a non-declaration part of a TML specification";
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length != 2) {
error = "A confchannel must be declared with exactly 1 parameter, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (!checkParameter("CONFCHANNEL", _split, 1, 0, _lineNb)) {
return -1;
}
ch = tmlm.getChannelByName(_split[1]);
if (ch == null) {
error = "conf channel not previously declared as a regular channel " + _split[1];
addError(0, _lineNb, 0, error);
return -1;
}
ch.checkConf = true;
} // CONFCHANNEL
if (isInstruction("AUTHCHANNEL", _split[0])) {
if (!inDec) {
error = "An authchannel may not be declared in a non-declaration part of a TML specification";
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length != 2) {
error = "An authchannel must be declared with exactly 1 parameter, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (!checkParameter("AUTHCHANNEL", _split, 1, 0, _lineNb)) {
return -1;
}
ch = tmlm.getChannelByName(_split[1]);
if (ch == null) {
error = "auth channel not previously declared as a regular channel " + _split[1];
addError(0, _lineNb, 0, error);
return -1;
}
ch.checkAuth = true;
} // AUTHCHANNEL
// EVENT
if (isInstruction("EVENT", _split[0])) {
if (!inDec) {
error = "An event may not be declared in a non-declaration part of a TML specification";
addError(0, _lineNb, 0, error);
return -1;
}
if (!((_split.length > 4) && (_split.length < 7))) {
error = "An event must be declared with only 4 or 5 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length == 6) {
dec = 1;
} else {
dec = 0;
}
id = getEvtId(_split[1]);
params = getParams(_split[1]);
//TraceManager.addDev("Evt id=" + id + "params=" + params);
if (!checkParameter("EVENT", _split, 1, 4, _lineNb)) {
return -1;
}
if (!checkParameter("EVENT", _split, 2, 3, _lineNb)) {
return -1;
}
if (_split.length == 6) {
if (!checkParameter("EVENT", _split, 3, 1, _lineNb)) {
return -1;
}
}
if (!checkParameter("EVENT", _split, 3 + dec, 0, _lineNb)) {
return -1;
}
if (!checkParameter("EVENT", _split, 4 + dec, 0, _lineNb)) {
return -1;
}
if (tmlm.getEventByName(id) != null) {
error = "Duplicate definition of event " + id;
addError(0, _lineNb, 0, error);
return -1;
}
blocking = _split[2].toUpperCase().compareTo("NIB") == 0;
if (_split[2].toUpperCase().compareTo("INF") == 0) {
tmp = -1;
} else {
try {
tmp = Integer.decode(_split[3]).intValue();
} catch (Exception e) {
error = "Unvalid parameter #3: should be a numeric value";
addError(0, _lineNb, 0, error);
return -1;
}
}
evt = new TMLEvent(id, null, tmp, blocking);
evt.addParam(params);
t1 = tmlm.getTMLTaskByName(_split[3 + dec]);
if (t1 == null) {
t1 = new TMLTask(_split[3 + dec], null, null);
//TraceManager.addDev("New task:" + _split[3+dec]);
tmlm.addTask(t1);
}
t2 = tmlm.getTMLTaskByName(_split[4 + dec]);
if (t2 == null) {
t2 = new TMLTask(_split[4 + dec], null, null);
//TraceManager.addDev("New task:" + _split[4+dec]);
tmlm.addTask(t2);
}
evt.setTasks(t1, t2);
tmlm.addEvent(evt);
} // EVENT
// LOSSYEVENT
if (isInstruction("LOSSYEVENT", _split[0])) {
if (!inDec) {
error = "A lossyevent may not be declared in a non-declaration part of a TML specification";
addError(0, _lineNb, 0, error);
return -1;
}
if (!((_split.length > 3) && (_split.length < 5))) {
error = "A lossyevent must be declared with exactly 3 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (!checkParameter("LOSSYEVENT", _split, 1, 0, _lineNb)) {
return -1;
}
if (!checkParameter("LOSSYEVENT", _split, 2, 1, _lineNb)) {
return -1;
}
if (!checkParameter("LOSSYEVENT", _split, 3, 9, _lineNb)) {
return -1;
}
evt = tmlm.getEventByName(_split[1]);
if (evt == null) {
error = "lossyevent not previsouly declared as a regular event " + _split[1];
addError(0, _lineNb, 0, error);
return -1;
}
try {
tmp0 = Integer.decode(_split[2]).intValue();
} catch (Exception e) {
tmp0 = 5;
}
try {
tmp1 = Integer.decode(_split[3]).intValue();
} catch (Exception e) {
tmp1 = -1;
}
evt.setLossy(true, tmp0, tmp1);
} // LOSSYEVENT
// REQUEST
if ((isInstruction("REQUEST", _split[0])) && (inDec)) {
if (!inDec) {
error = "A request may not be declared in a non-declaration part of a TML specification";
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length < 4) {
error = "A request must be declared with at least 4 paremeters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
id = getEvtId(_split[1]);
params = getParams(_split[1]);
//TraceManager.addDev("Evt id=" + id + "params=" + params);
if (!checkParameter("REQUEST", _split, 1, 4, _lineNb)) {
return -1;
}
for (i = 2; i < _split.length; i++) {
if (!checkParameter("REQUEST", _split, i, 0, _lineNb)) {
return -1;
}
}
if (tmlm.getRequestByName(id) != null) {
error = "Duplicate definition of request " + id;
addError(0, _lineNb, 0, error);
return -1;
}
request = new TMLRequest(id, null);
request.addParam(params);
for (i = 2; i < _split.length; i++) {
t1 = tmlm.getTMLTaskByName(_split[i]);
if (t1 == null) {
t1 = new TMLTask(_split[i], null, null);
//TraceManager.addDev("New task:" + _split[i]);
tmlm.addTask(t1);
}
if ((i + 1) == _split.length) {
request.setDestinationTask(t1);
t1.setRequested(true);
t1.setRequest(request);
} else {
request.addOriginTask(t1);
}
}
tmlm.addRequest(request);
} // REQUEST
// LOSSYREQUEST
if (isInstruction("LOSSYREQUEST", _split[0])) {
if (!inDec) {
error = "A lossyrequest may not be declared in a non-declaration part of a TML specification";
addError(0, _lineNb, 0, error);
return -1;
}
if (!((_split.length > 3) && (_split.length < 5))) {
error = "A lossyrequest must be declared with exactly 3 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (!checkParameter("LOSSYREQUEST", _split, 1, 0, _lineNb)) {
return -1;
}
if (!checkParameter("LOSSYREQUEST", _split, 2, 1, _lineNb)) {
return -1;
}
if (!checkParameter("LOSSYREQUEST", _split, 3, 9, _lineNb)) {
return -1;
}
request = tmlm.getRequestByName(_split[1]);
if (request == null) {
error = "lossyrequest not previsouly declared as a regular event " + _split[1];
addError(0, _lineNb, 0, error);
return -1;
}
try {
tmp0 = Integer.decode(_split[2]).intValue();
} catch (Exception e) {
tmp0 = 5;
}
try {
tmp1 = Integer.decode(_split[3]).intValue();
} catch (Exception e) {
tmp1 = -1;
}
request.setLossy(true, tmp0, tmp1);
} // LOSSYREQUEST
// TASK
if ((isInstruction("TASK", _split[0]))) {
//TraceManager.addDev("In task");
if (inTask) {
error = "A task may not be declared in the body of another task";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = true;
// inTaskBehavior = false;
if (_split.length != 2) {
error = "A task must be declared with exactly 2 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (!checkParameter("TASK", _split, 1, 0, _lineNb)) {
return -1;
}
//TraceManager.addDev("In task: 12");
task = tmlm.getTMLTaskByName(_split[1]);
if ((task != null) && (task.getActivityDiagram() != null)) {
if (task.getActivityDiagram().getFirst() != null) {
error = "Duplicate definition for task " + (_split[1]);
addError(0, _lineNb, 0, error);
return -1;
}
}
//TraceManager.addDev("In task: 13");
if (task == null) {
task = new TMLTask(_split[1], null, null);
tmlm.addTask(task);
//TraceManager.addDev("New task:" + _split[1]);
}
TMLStartState start = new TMLStartState("start", null);
task.getActivityDiagram().setFirst(start);
tmlae = start;
} // TASK
// TASKOP
if ((isInstruction("TASKOP", _split[0]))) {
//An operation is really specified?
if (!inTask) {
error = "A task operation cannot be declared outside the body of another task";
addError(0, _lineNb, 0, error);
return -1;
}
if (!inTaskDec) {
error = "A task operation cannot be declared outside the declarative part of another task";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = true;
String tmpOp = "";
for (int j = 1; j < _split.length; j++) {
tmpOp += _split[j] + " ";
}
task.addOperation(tmpOp);
}
// DAEMON
if ((isInstruction("DAEMON", _split[0]))) {
if (!inTask) {
error = "A daemon task cannot be declared outside the body of another task";
addError(0, _lineNb, 0, error);
return -1;
}
if (!inTaskDec) {
error = "A daemon operation cannot be declared outside the declarative part of another task";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = true;
task.setDaemon(true);
}
// PERIODIC
if ((isInstruction("PERIODIC", _split[0]))) {
// periodic task?
if (!inTask) {
error = "A periodic task cannot be declared outside the body of another task";
addError(0, _lineNb, 0, error);
return -1;
}
if (!inTaskDec) {
error = "A periodic operation cannot be declared outside the declarative part of another task";
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length < 3) {
error = "A periodic task must be declared with a value and a unit";
addError(0, _lineNb, 0, error);
return -1;
}
String periodValue = _split[1];
String unit = _split[2];
if (!periodValue.matches("-?\\d+")) {
error = "A periodic task must be declared with a numerical period value (and not " + periodValue + ")";
addError(0, _lineNb, 0, error);
return -1;
}
if (!unit.matches("(?i)ns|us|ms|s")) {
error = "A periodic task must be declared with a unit equal to ns or us or ms or s";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = true;
task.setPeriodic(true, periodValue, unit);
}
// ENDTASK
if ((isInstruction("ENDTASK", _split[0]))) {
if (!inTask) {
error = "A endtask may not be used outside the body of a task";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = true;
inTask = false;
inTaskDec = false;
// inTaskBehavior = false;
stop = new TMLStopState("stop", null);
task.getActivityDiagram().addElement(stop);
tmlae.addNext(stop);
task = null;
} // ENDTASK
// Attribute declaration
if ((isInstruction("INT", _split[0])) || (isInstruction("NAT", _split[0])) || (isInstruction("BOOL", _split[0]))) {
if (!inTaskDec) {
error = "An attribute declaration must be done in a task right after its declaration, and before its behavior";
addError(0, _lineNb, 0, error);
return -1;
}
String inst = _split[0].toUpperCase();
if (!((_split.length == 2) || (_split.length == 4))) {
error = "An attribute declaration must be done with either 1 or 3 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (!checkParameter(inst, _split, 1, 0, _lineNb)) {
return -1;
}
if (_split.length > 2) {
if (!checkParameter(inst, _split, 2, 5, _lineNb)) {
return -1;
}
if (!checkParameter(inst, _split, 3, 6, _lineNb)) {
return -1;
}
}
//TraceManager.addDev("Adding attribute " + _split[0] + " " + _split[1]);
TMLAttribute ta = new TMLAttribute(_split[1], new TMLType(TMLType.getType(_split[0])));
if (_split.length > 2) {
ta.initialValue = _split[3];
} else {
ta.initialValue = ta.getDefaultInitialValue();
}
task.addAttribute(ta);
} // Attribute declaration
// RANDOM
if ((isInstruction("RANDOM", _split[0]))) {
if (!inTask) {
error = "A RANDOM operation may only be performed in a task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
if (_split.length != 5) {
error = "A RANDOM operation must be declared with exactly 4 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (!checkParameter("RANDOM", _split, 1, 1, _lineNb)) {
return -1;
}
if (!checkParameter("RANDOM", _split, 2, 0, _lineNb)) {
return -1;
}
random = new TMLRandom("random", null);
try {
random.setFunctionId(Integer.decode(_split[1]).intValue());
} catch (Exception e) {
}
random.setVariable(_split[2]);
random.setMinValue(_split[3]);
random.setMaxValue(_split[4]);
TraceManager.addDev("RANDOM min=" + random.getMinValue() + " max=" + random.getMaxValue());
task.getActivityDiagram().addElement(random);
tmlae.addNext(random);
tmlae = random;
} // RANDOM
// READ
if ((isInstruction("READ", _split[0]))) {
if (!inTask) {
error = "A READ operation may only be performed in a task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
if (_split.length != 3 && _split.length != 4) {
error = "A READ operation must be declared with exactly 3 or 4 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (!checkParameter("READ", _split, 1, 0, _lineNb)) {
return -1;
}
/*if (!checkParameter("READ", _split, 2, 7, _lineNb)) {
return -1;
}*/
ch = tmlm.getChannelByName(_split[1]);
if (ch == null) {
error = "Undeclared channel: " + _split[1];
addError(0, _lineNb, 0, error);
return -1;
}
if (!(ch.hasDestinationTask(task))) {
error = "READ operations must be done only in destination task(s). Should be in task(s): " + ch.getNameOfDestinationTasks();
addError(0, _lineNb, 0, error);
return -1;
}
TMLReadChannel tmlrch = new TMLReadChannel(_split[1], null);
tmlrch.addChannel(ch);
tmlrch.setNbOfSamples(_split[2]);
task.getActivityDiagram().addElement(tmlrch);
tmlae.addNext(tmlrch);
if (_split.length == 4) {
if (securityPatternMap.containsKey(_split[3])) {
tmlrch.setSecurityPattern(securityPatternMap.get(_split[3]));
}
}
tmlae = tmlrch;
} // READ
// WRITE
if ((isInstruction("WRITE", _split[0]))) {
if (!inTask) {
error = "A WRITE operation may only be performed in a task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
if (_split.length > 5 || _split.length < 2) {
error = "A WRITE operation must be declared with at most 4 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (!checkParameter("WRITE", _split, 1, 0, _lineNb)) {
return -1;
}
//TraceManager.addDev("Handling write channel 1");
TMLWriteChannel tmlwch = new TMLWriteChannel(_split[1], null);
if (_split.length > 3) {
if (securityPatternMap.containsKey(_split[_split.length - 1])) {
tmlwch.setSecurityPattern(securityPatternMap.get(_split[_split.length - 1]));
TraceManager.addDev("Nb of samples in task " + task.getName() +
" security pattern: " + tmlwch.getSecurityPattern().getName());
//tmlwch.getSecurityPattern().setOriginTask(task.getTaskName());
}
for (int k = 0; k < _split.length - 3; k++) {
//TraceManager.addDev("Handling write channel 1.1");
ch = tmlm.getChannelByName(_split[1 + k]);
if (ch == null) {
error = "Undeclared channel: " + _split[1 + k];
addError(0, _lineNb, 0, error);
return -1;
}
//TraceManager.addDev("Handling write channel 1.2 for task: " + task.getName());
if (!(ch.hasOriginTask(task))) {
error = "WRITE operations must be done only in origin task(s). Should be in task(s): " + ch.getNameOfOriginTasks();
addError(0, _lineNb, 0, error);
return -1;
}
//TraceManager.addDev("Handling write channel 1.3");
tmlwch.addChannel(ch);
}
} else {
for (int k = 0; k < _split.length - 2; k++) {
//TraceManager.addDev("Handling write channel 1.1");
ch = tmlm.getChannelByName(_split[1 + k]);
if (ch == null) {
error = "Undeclared channel: " + _split[1 + k];
addError(0, _lineNb, 0, error);
return -1;
}
//TraceManager.addDev("Handling write channel 1.2 for task: " + task.getName());
if (!(ch.hasOriginTask(task))) {
error = "WRITE operations must be done only in origin task(s). Should be in task(s): " + ch.getNameOfOriginTasks();
addError(0, _lineNb, 0, error);
return -1;
}
//TraceManager.addDev("Handling write channel 1.3");
tmlwch.addChannel(ch);
}
}
//TraceManager.addDev("Handling write channel 2");
tmlwch.setNbOfSamples(_split[2]);
task.getActivityDiagram().addElement(tmlwch);
tmlae.addNext(tmlwch);
tmlae = tmlwch;
} // WRITE
// NOTIFY
if ((isInstruction("NOTIFY", _split[0]))) {
if (!inTask) {
error = "A NOTIFY operation may only be performed in a task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
if (_split.length < 2) {
error = "A NOTIFY operation must be declared with at least 2 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
evt = tmlm.getEventByName(_split[1]);
if (evt == null) {
error = "Unknown event: " + _split[1];
addError(0, _lineNb, 0, error);
return -1;
}
dec = evt.getNbOfParams();
if (_split.length != 2 + dec) {
error = "A NOTIFY operation on evt " + evt.getName() + " must be declared with exactly " + (1 + dec) + " parameters and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
TMLSendEvent sevt = new TMLSendEvent(evt.getName(), null);
sevt.setEvent(evt);
for (i = 2; i < 2 + dec; i++) {
sevt.addParam(_split[i]);
}
task.getActivityDiagram().addElement(sevt);
tmlae.addNext(sevt);
tmlae = sevt;
} // NOTIFY
// WAIT
if ((isInstruction("WAIT", _split[0]))) {
if (!inTask) {
error = "A WAIT operation may only be performed in a task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
if (_split.length < 2) {
error = "A WAIT operation must be declared with at least 2 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
evt = tmlm.getEventByName(_split[1]);
if (evt == null) {
error = "Unknown event: " + _split[1];
addError(0, _lineNb, 0, error);
return -1;
}
dec = evt.getNbOfParams();
if (_split.length != 2 + dec) {
error = "A WAIT operation on evt " + evt.getName() + " must be declared with exactly " + (1 + dec) + " parameters and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
// Each param must be a declared attribute of the right type
for (i = 2; i < 2 + dec; i++) {
attribute = task.getAttributeByName(_split[i]);
if (attribute == null) {
error = "Attribute: " + _split[i] + " is undeclared";
addError(0, _lineNb, 0, error);
return -1;
}
if (attribute.type.getType() != evt.getType(i - 2).getType()) {
error = "Attribute: " + _split[i] + " is not of the right type";
addError(0, _lineNb, 0, error);
return -1;
}
}
TMLWaitEvent wevt = new TMLWaitEvent(evt.getName(), null);
wevt.setEvent(evt);
for (i = 2; i < 2 + dec; i++) {
wevt.addParam(_split[i]);
}
task.getActivityDiagram().addElement(wevt);
tmlae.addNext(wevt);
tmlae = wevt;
} // WAIT
// NOTIFIED
if ((isInstruction("NOTIFIED", _split[0]))) {
if (!inTask) {
error = "A NOTIFIED operation may only be performed in a task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
if (_split.length != 3) {
error = "A NOTIFIED operation must be declared with exactly 2 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
evt = tmlm.getEventByName(_split[1]);
if (evt == null) {
error = "Unknown event: " + _split[1];
addError(0, _lineNb, 0, error);
return -1;
}
attribute = task.getAttributeByName(_split[2]);
if (attribute == null) {
error = "Attribute: " + _split[2] + " is undeclared";
addError(0, _lineNb, 0, error);
return -1;
}
if (attribute.type.getType() != TMLType.NATURAL) {
error = "Attribute: " + _split[2] + " should be of natural type";
addError(0, _lineNb, 0, error);
return -1;
}
TMLNotifiedEvent nevt = new TMLNotifiedEvent(evt.getName(), null);
nevt.setEvent(evt);
nevt.setVariable(_split[2]);
task.getActivityDiagram().addElement(nevt);
tmlae.addNext(nevt);
tmlae = nevt;
} // NOTIFIED
// Send REQUEST a.k.a. NOTIFYREQUEST
if ((isInstruction("NOTIFYREQUEST", _split[0])) && (inTask)) {
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
if (_split.length < 2) {
error = "A REQUEST operation must be declared with at least 1 parameter (request name), and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
request = tmlm.getRequestByName(_split[1]);
if (request == null) {
error = "Unknown request: " + _split[1];
addError(0, _lineNb, 0, error);
return -1;
}
dec = request.getNbOfParams();
if (_split.length != 2 + dec) {
error = "A REQUEST operation on request " + request.getName() + " must be declared with exactly " + (1 + dec) + " parameters and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
TMLSendRequest sreq = new TMLSendRequest(request.getName(), null);
sreq.setRequest(request);
for (i = 2; i < 2 + dec; i++) {
sreq.addParam(_split[i]);
}
task.getActivityDiagram().addElement(sreq);
tmlae.addNext(sreq);
tmlae = sreq;
} // Send REQUEST
// FOR
if ((isInstruction("FOR", _split[0])) && (inTask)) {
//TraceManager.addDev("FOR encountered");
if (_split.length < 2) {
error = "FOR operation: missing parameters";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
// Extract the three elements of FOR
String forp = _split[1];
// String forps[];
tmp0 = forp.indexOf('(');
tmp1 = forp.lastIndexOf(')');
if ((tmp0 == -1) || (tmp1 == -1)) {
error = "FOR operation: badly formed parameters";
addError(0, _lineNb, 0, error);
return -1;
}
forp = forp.substring(tmp0 + 1, tmp1);
int first = forp.indexOf(";");
String init = "";
if (first > -1) {
init = forp.substring(0, first);
} else {
error = "FOR operation: badly formed parameters";
addError(0, _lineNb, 0, error);
return -1;
}
String condition = "";
String increment = "";
forp = forp.substring(first + 1, forp.length()).trim();
int second = forp.indexOf(";");
if (second == -1) {
error = "FOR operation: badly formed parameters ";
addError(0, _lineNb, 0, error);
return -1;
}
condition = forp.substring(0, second);
increment = forp.substring(second + 1, forp.length());
// All is ok: constructing the FOR
parseElt = new TMLParserSaveElt();
parseElt.type = TMLParserSaveElt.FOR;
parses.add(0, parseElt);
TMLForLoop loop = new TMLForLoop("loop", null);
loop.setInit(init);
loop.setCondition(condition);
loop.setIncrement(increment);
task.getActivityDiagram().addElement(loop);
parseElt.tmlae = loop;
tmlae.addNext(loop);
tmlae = loop;
} // FOR
// ENDFOR
if (isInstruction("ENDFOR", _split[0])) {
if (!inTask) {
error = "ENDFOR: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
// Extract the first element of the stack
if (parses.size() == 0) {
error = "ENDFOR: badly placed instruction.";
addError(0, _lineNb, 0, error);
return -1;
}
parseElt = parses.get(0);
if (parseElt.type != TMLParserSaveElt.FOR) {
error = "ENDFOR: badly placed instruction. Was expecting: " + parseElt.getExpectedInstruction();
addError(0, _lineNb, 0, error);
return -1;
}
// All is ok: constructing the FOR
parses.remove(0);
stop = new TMLStopState("stop loop", null);
task.getActivityDiagram().addElement(stop);
tmlae.addNext(stop);
tmlae = parseElt.tmlae;
} // ENDFOR
// SELECTEVT
if ((isInstruction("SELECTEVT", _split[0]))) {
if (!inTask) {
error = "SELECTEVT: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length > 1) {
error = "A SELECTEVT cannot have any parameters";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
parseElt = new TMLParserSaveElt();
parseElt.type = TMLParserSaveElt.SELECTEVT;
parses.add(0, parseElt);
TMLSequence seq = new TMLSequence("sequence", null);
parseElt.top = seq;
tmlae.addNext(seq);
TMLSelectEvt sel = new TMLSelectEvt("select evt", null);
parseElt.tmlae = sel;
seq.addNext(sel);
task.getActivityDiagram().addElement(seq);
task.getActivityDiagram().addElement(sel);
tmlae = sel;
} // SELECTEVT
// ENDSELECTEVT
if ((isInstruction("ENDSELECTEVT", _split[0]))) {
if (!inTask) {
error = "ENDSELECTEVT: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
// Extract the first element of the stack
if (parses.size() == 0) {
error = "ENDSELECTEVT: badly placed instruction.";
addError(0, _lineNb, 0, error);
return -1;
}
parseElt = parses.get(0);
if (parseElt.type != TMLParserSaveElt.SELECTEVT) {
error = "ENDSELECTEVT: badly placed instruction. Was expecting: " + parseElt.getExpectedInstruction();
addError(0, _lineNb, 0, error);
return -1;
}
parses.remove(0);
tmlae = parseElt.top;
} // ENDSELECTEVT
// CASE
if ((isInstruction("CASE", _split[0]))) {
if (!inTask) {
error = "CASE: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
if (parses.size() == 0) {
error = "CASE: corresponding SELECTEVT not found";
addError(0, _lineNb, 0, error);
return -1;
} else {
parseElt = parses.get(0);
if (parseElt.type != TMLParserSaveElt.SELECTEVT) {
error = "CASE: corresponding SELECTEVT not found";
addError(0, _lineNb, 0, error);
return -1;
}
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
if (_split.length < 2) {
error = "A CASE must have at least two parameters";
addError(0, _lineNb, 0, error);
return -1;
}
evt = tmlm.getEventByName(_split[1]);
if (evt == null) {
error = "Unknown event: " + _split[1];
addError(0, _lineNb, 0, error);
return -1;
}
dec = evt.getNbOfParams();
if (_split.length != 2 + dec) {
error = "A CASE operation on evt " + evt.getName() + " must be declared with exactly " + (1 + dec) + " parameters and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
TMLWaitEvent wevt = new TMLWaitEvent(evt.getName(), null);
wevt.setEvent(evt);
for (i = 2; i < 2 + dec; i++) {
wevt.addParam(_split[i]);
}
task.getActivityDiagram().addElement(wevt);
tmlae.addNext(wevt);
parseElt = new TMLParserSaveElt();
parseElt.type = TMLParserSaveElt.CASE;
parseElt.tmlae = wevt;
parseElt.top = tmlae;
parses.add(0, parseElt);
tmlae = wevt;
} // CASE
// ENDCASE
if ((isInstruction("ENDCASE", _split[0]))) {
if (!inTask) {
error = "ENDCASE: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
// Extract the first element of the stack
if (parses.size() == 0) {
error = "ENDCASE: badly placed instruction.";
addError(0, _lineNb, 0, error);
return -1;
}
parseElt = parses.get(0);
if (parseElt.type != TMLParserSaveElt.CASE) {
error = "ENDCASE: badly placed instruction. Was expecting: " + parseElt.getExpectedInstruction();
addError(0, _lineNb, 0, error);
return -1;
}
parses.remove(0);
stop = new TMLStopState("stop case", null);
task.getActivityDiagram().addElement(stop);
tmlae.addNext(stop);
tmlae = parseElt.top;
} // ENDCASE
// RANDOMSEQ
if ((isInstruction("RANDOMSEQ", _split[0]))) {
if (!inTask) {
error = "RANDOMSEQ: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length > 1) {
error = "A RANDOMSEQ cannot have any parameters";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
parseElt = new TMLParserSaveElt();
parseElt.type = TMLParserSaveElt.RANDOMSEQ;
parses.add(0, parseElt);
TMLSequence seq = new TMLSequence("sequence", null);
parseElt.top = seq;
tmlae.addNext(seq);
TMLRandomSequence rseq = new TMLRandomSequence("random sequence", null);
parseElt.tmlae = rseq;
seq.addNext(rseq);
task.getActivityDiagram().addElement(seq);
task.getActivityDiagram().addElement(rseq);
tmlae = rseq;
} // RANDOMSEQ
// ENDRANDOMSEQ
if ((isInstruction("ENDRANDOMSEQ", _split[0]))) {
if (!inTask) {
error = "ENDRANDOMSEQ: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
// Extract the first element of the stack
if (parses.size() == 0) {
error = "ENDRANDOMSEQ: badly placed instruction.";
addError(0, _lineNb, 0, error);
return -1;
}
parseElt = parses.get(0);
if (parseElt.type != TMLParserSaveElt.RANDOMSEQ) {
error = "ENDRANDOMSEQ: badly placed instruction. Was expecting: " + parseElt.getExpectedInstruction();
addError(0, _lineNb, 0, error);
return -1;
}
parses.remove(0);
tmlae = parseElt.top;
} // ENDRANDOMSEQ
// SEQ
if ((isInstruction("SEQ", _split[0]))) {
if (!inTask) {
error = "SEQ: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
if (parses.size() == 0) {
error = "SEQ: corresponding RANDOMSEQ not found";
addError(0, _lineNb, 0, error);
return -1;
} else {
parseElt = parses.get(0);
if (parseElt.type != TMLParserSaveElt.RANDOMSEQ) {
error = "SEQ: corresponding RANDOMSEQ not found";
addError(0, _lineNb, 0, error);
return -1;
}
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
if (_split.length > 1) {
error = "A SEQ has no parameter";
addError(0, _lineNb, 0, error);
return -1;
}
if (!(parseElt.tmlae instanceof TMLRandomSequence)) {
error = "Malformed specification: unexpected SEQ";
addError(0, _lineNb, 0, error);
return -1;
}
TMLRandomSequence rseq = (TMLRandomSequence) parseElt.tmlae;
TMLSequence seq = new TMLSequence("sequence", null);
rseq.addNext(seq);
task.getActivityDiagram().addElement(seq);
parseElt = new TMLParserSaveElt();
parseElt.type = TMLParserSaveElt.SEQ;
parseElt.tmlae = seq;
parseElt.top = rseq;
parses.add(0, parseElt);
tmlae = seq;
} // SEQ
// ENDSEQ
if ((isInstruction("ENDSEQ", _split[0]))) {
if (!inTask) {
error = "ENDSEQ: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
// Extract the first element of the stack
if (parses.size() == 0) {
error = "ENDSEQ: badly placed instruction.";
addError(0, _lineNb, 0, error);
return -1;
}
parseElt = parses.get(0);
if (parseElt.type != TMLParserSaveElt.SEQ) {
error = "ENDSEQ: badly placed instruction. Was expecting: " + parseElt.getExpectedInstruction();
addError(0, _lineNb, 0, error);
return -1;
}
parses.remove(0);
stop = new TMLStopState("stop case", null);
task.getActivityDiagram().addElement(stop);
tmlae.addNext(stop);
tmlae = parseElt.top;
} // ENDSEQ
// RAND
if ((isInstruction("RAND", _split[0]))) {
if (!inTask) {
error = "RAND: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length > 1) {
error = "A RAND cannot have any parameters";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
parseElt = new TMLParserSaveElt();
parseElt.type = TMLParserSaveElt.RAND;
parses.add(0, parseElt);
TMLSequence seq = new TMLSequence("sequence", null);
parseElt.top = seq;
tmlae.addNext(seq);
TMLChoice choice = new TMLChoice("choice evt", null);
parseElt.tmlae = choice;
seq.addNext(choice);
task.getActivityDiagram().addElement(seq);
task.getActivityDiagram().addElement(choice);
tmlae = choice;
} // RAND
// ENDRAND
if ((isInstruction("ENDRAND", _split[0]))) {
if (!inTask) {
error = "ENDRAND: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
// Extract the first element of the stack
if (parses.size() == 0) {
error = "ENDRAND: badly placed instruction.";
addError(0, _lineNb, 0, error);
return -1;
}
parseElt = parses.get(0);
if (parseElt.type != TMLParserSaveElt.RAND) {
error = "ENDRAND: badly placed instruction. Was expecting: " + parseElt.getExpectedInstruction();
addError(0, _lineNb, 0, error);
return -1;
}
parses.remove(0);
tmlae = parseElt.top;
} // ENDRAND
// CASERAND
if ((isInstruction("CASERAND", _split[0]))) {
if (!inTask) {
error = "CASERAND: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
if (parses.size() == 0) {
error = "CASERAND: corresponding RAND not found";
addError(0, _lineNb, 0, error);
return -1;
} else {
parseElt = parses.get(0);
if (parseElt.type != TMLParserSaveElt.RAND) {
error = "CASERAND: corresponding RAND not found";
addError(0, _lineNb, 0, error);
return -1;
}
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
if (_split.length != 2) {
error = "A CASERAND should have one parameter";
addError(0, _lineNb, 0, error);
return -1;
}
if (!(parseElt.tmlae instanceof TMLChoice)) {
error = "Malformed specification";
addError(0, _lineNb, 0, error);
return -1;
}
TMLChoice choice = (TMLChoice) parseElt.tmlae;
TMLSequence seq = new TMLSequence("sequence", null);
choice.addGuard("[" + _split[1] + "%]");
choice.addNext(seq);
task.getActivityDiagram().addElement(seq);
parseElt = new TMLParserSaveElt();
parseElt.type = TMLParserSaveElt.CASERAND;
parseElt.tmlae = seq;
parseElt.top = choice;
parses.add(0, parseElt);
tmlae = seq;
} // CASERAND
// ENDCASERAND
if ((isInstruction("ENDCASERAND", _split[0]))) {
if (!inTask) {
error = "ENDCASERAND: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
// Extract the first element of the stack
if (parses.size() == 0) {
error = "ENDCASERAND: badly placed instruction.";
addError(0, _lineNb, 0, error);
return -1;
}
parseElt = parses.get(0);
if (parseElt.type != TMLParserSaveElt.CASERAND) {
error = "ENDCASERAND: badly placed instruction. Was expecting: " + parseElt.getExpectedInstruction();
addError(0, _lineNb, 0, error);
return -1;
}
parses.remove(0);
stop = new TMLStopState("stop case", null);
task.getActivityDiagram().addElement(stop);
tmlae.addNext(stop);
tmlae = parseElt.top;
} // ENDCASERAND
// IF
if ((isInstruction("IF", _split[0]))) {
if (!inTask) {
error = "IF: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length != 2) {
error = "IF should be followed by one condition";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
String cond = _split[1].trim();
tmp0 = cond.indexOf('(');
tmp1 = cond.lastIndexOf(')');
if ((tmp0 == -1) || (tmp1 == -1)) {
error = "IF operation: badly formed condition";
addError(0, _lineNb, 0, error);
return -1;
}
cond = cond.substring(tmp0 + 1, tmp1);
parseElt = new TMLParserSaveElt();
parseElt.type = TMLParserSaveElt.IF;
parses.add(0, parseElt);
TMLSequence seq = new TMLSequence("sequence", null);
parseElt.top = seq;
tmlae.addNext(seq);
TMLChoice choice = new TMLChoice("if", null);
parseElt.tmlae = choice;
seq.addNext(choice);
task.getActivityDiagram().addElement(seq);
task.getActivityDiagram().addElement(choice);
seq = new TMLSequence("sequence", null);
task.getActivityDiagram().addElement(seq);
choice.addNext(seq);
choice.addGuard("[" + cond + "]");
tmlae = seq;
} // IF
// ORIF
if ((isInstruction("ORIF", _split[0]))) {
if (!inTask) {
error = "ORIF: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length != 2) {
error = "ORIF should be followed by one condition";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
String cond = _split[1].trim();
//TraceManager.addDev("cond1=" + cond);
tmp0 = cond.indexOf('(');
tmp1 = cond.lastIndexOf(')');
if ((tmp0 == -1) || (tmp1 == -1)) {
error = "ORIF operation: badly formed condition";
addError(0, _lineNb, 0, error);
return -1;
}
cond = cond.substring(tmp0 + 1, tmp1);
//TraceManager.addDev("cond2=" + cond);
if (parses.size() == 0) {
error = "ORIF: badly placed instruction.";
addError(0, _lineNb, 0, error);
return -1;
}
parseElt = parses.get(0);
if (parseElt.type != TMLParserSaveElt.IF) {
error = "ORIF: badly placed instruction. Was expecting: " + parseElt.getExpectedInstruction();
addError(0, _lineNb, 0, error);
return -1;
}
if (parseElt.nbElse > 0) {
error = "ORIF: should not followed a else instruction";
addError(0, _lineNb, 0, error);
return -1;
}
stop = new TMLStopState("stop", null);
task.getActivityDiagram().addElement(stop);
tmlae.addNext(stop);
TMLSequence seq = new TMLSequence("sequence", null);
TMLChoice choice = (TMLChoice) parseElt.tmlae;
task.getActivityDiagram().addElement(seq);
choice.addNext(seq);
choice.addGuard("[" + cond + "]");
tmlae = seq;
} // ORIF
// ELSE
if ((isInstruction("ELSE", _split[0]))) {
if (!inTask) {
error = "ELSE: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length != 1) {
error = "ELSE should have no parameter";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
if (parses.size() == 0) {
error = "ELSE: badly placed instruction.";
addError(0, _lineNb, 0, error);
return -1;
}
parseElt = parses.get(0);
if (parseElt.type != TMLParserSaveElt.IF) {
error = "ELSE: badly placed instruction. Was expecting: " + parseElt.getExpectedInstruction();
addError(0, _lineNb, 0, error);
return -1;
}
stop = new TMLStopState("stop", null);
task.getActivityDiagram().addElement(stop);
tmlae.addNext(stop);
parseElt.nbElse++;
TMLSequence seq = new TMLSequence("sequence", null);
TMLChoice choice = (TMLChoice) parseElt.tmlae;
task.getActivityDiagram().addElement(seq);
choice.addNext(seq);
choice.addGuard("[else]");
tmlae = seq;
} // ELSE
// ENDIF
if ((isInstruction("ENDIF", _split[0]))) {
if (!inTask) {
error = "ENDIF: must be used in a Task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
// Extract the first element of the stack
if (parses.size() == 0) {
error = "ENDIF: badly placed instruction.";
addError(0, _lineNb, 0, error);
return -1;
}
parseElt = parses.get(0);
if (parseElt.type != TMLParserSaveElt.IF) {
error = "ENDIF: badly placed instruction. Was expecting: " + parseElt.getExpectedInstruction();
addError(0, _lineNb, 0, error);
return -1;
}
stop = new TMLStopState("stop", null);
task.getActivityDiagram().addElement(stop);
tmlae.addNext(stop);
parses.remove(0);
tmlae = parseElt.top;
} // ENDIF
// EXECI
if ((isInstruction("EXECI", _split[0]))) {
if (!inTask) {
error = "An EXECI operation may only be performed in a task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
if ((_split.length < 2) || (_split.length > 4)) {
error = "An EXECI operation must be declared with 1 or 2 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length == 2) {
TMLExecI execi = new TMLExecI("execi", null);
execi.setAction(_split[1]);
tmlae.addNext(execi);
task.getActivityDiagram().addElement(execi);
tmlae = execi;
} else {
TMLExecIInterval execi = new TMLExecIInterval("execi", null);
execi.setMinDelay(_split[1]);
execi.setMaxDelay(_split[2]);
tmlae.addNext(execi);
task.getActivityDiagram().addElement(execi);
tmlae = execi;
}
} // EXECI
// EXECC
if ((isInstruction("EXECC", _split[0]))) {
if (!inTask) {
error = "An EXECC operation may only be performed in a task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
TraceManager.addDev("Found EXECC " + _split);
if (_split.length == 11) {
if (securityPatternMap.containsKey(_split[2])) {
if ((_split[10].compareTo("" + DECRYPTION_PROCESS) == 0) || (_split[10].compareTo("" + ENCRYPTION_PROCESS) == 0)) {
//Security operation
TraceManager.addDev("Found security pattern: " + _split[2]);
TMLExecC execc = new TMLExecC("encrypt_" + _split[2], null);
execc.setAction(_split[1]);
SecurityPattern sp = securityPatternMap.get(_split[2]);
execc.setSecurityPattern(sp);
if (_split[10].compareTo("" + DECRYPTION_PROCESS) == 0) {
execc.setDecryptionProcess(true);
execc.setName("decrypt_" + _split[2]);
}
if (!tmlm.getSecurityTaskMap().containsKey(sp)) {
tmlm.getSecurityTaskMap().put(sp, new ArrayList<TMLTask>());
}
if (!tmlm.getSecurityTaskMap().get(sp).contains(task)) {
tmlm.getSecurityTaskMap().get(sp).add(task);
}
tmlae.addNext(execc);
task.getActivityDiagram().addElement(execc);
tmlae = execc;
} else {
error = "EXECC " + _split[2] + " has an unknown security process";
addError(0, _lineNb, 0, error);
return -1;
}
} else {
error = "An EXECC with a security configuration must contain a valid security configuration name " + (_split[2]);
addError(0, _lineNb, 0, error);
return -1;
}
} else {
if ((_split.length < 2) || (_split.length > 4)) {
error = "An EXECC operation must be declared with 1, 2 or 10 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length == 2) {
TMLExecC execc = new TMLExecC("execc", null);
execc.setAction(_split[1]);
tmlae.addNext(execc);
task.getActivityDiagram().addElement(execc);
tmlae = execc;
} else {
TMLExecCInterval execci = new TMLExecCInterval("execci", null);
execci.setMinDelay(_split[1]);
execci.setMaxDelay(_split[2]);
tmlae.addNext(execci);
task.getActivityDiagram().addElement(execci);
tmlae = execci;
}
}
} // EXECC
// DELAY
if ((isInstruction("DELAY", _split[0]))) {
if (!inTask) {
error = "A DELAY operation may only be performed in a task body";
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
if ((_split.length < 3) || (_split.length > 6)) {
error = "A DELAY operation must be declared with 2, 3, 4 or 5 parameters, and not " + (_split.length - 1);
addError(0, _lineNb, 0, error);
return -1;
}
if (_split.length == 3 || _split.length == 5) {
if (!checkParameter("DELAY", _split, 2, 0, _lineNb)) {
error = "A DELAY operation must be specified with a valid time unit (ns, us, ms, s))";
addError(0, _lineNb, 0, error);
return -1;
}
}
if (_split.length == 4 || _split.length == 6) {
if (!checkParameter("DELAY", _split, 3, 0, _lineNb)) {
error = "A DELAY operation must be specified with a valid time unit (ns, us, ms, s))";
addError(0, _lineNb, 0, error);
return -1;
}
}
TMLDelay delay = new TMLDelay("delay", null);
delay.setMinDelay(_split[1]);
if (_split.length == 3) {
delay.setMaxDelay(_split[1]);
delay.setUnit(_split[2]); // DELAY min unit - this is for old format
} else if (_split.length == 4) {
delay.setMaxDelay(_split[2]);
delay.setUnit(_split[3]); // DELAY min max unit - this is for old format
} else if (_split.length == 5) {
delay.setMaxDelay(_split[1]);
delay.setUnit(_split[2]);
delay.setActiveDelay(Boolean.valueOf(_split[4])); // DELAY min unit isActivedelay boolean
} else {
delay.setMaxDelay(_split[2]);
delay.setUnit(_split[3]);
delay.setActiveDelay(Boolean.valueOf(_split[5])); // DELAY min max unit isActivedelay boolean
}
tmlae.addNext(delay);
task.getActivityDiagram().addElement(delay);
tmlae = delay;
} // EXECC
// Other command
if ((_split[0].length() > 0) && (!(isInstruction(_split[0])))) {
//TraceManager.addDev("Not an instruction:" + _split[0]);
if (!inTask) {
error = "Syntax error in TML modeling: unrecognized instruction:" + _split[0];
addError(0, _lineNb, 0, error);
return -1;
}
inDec = false;
inTask = true;
inTaskDec = false;
// inTaskBehavior = true;
TMLActionState action = new TMLActionState(_split[0], null);
action.setAction(_line);
tmlae.addNext(action);
task.getActivityDiagram().addElement(action);
tmlae = action;
} // Other command
return 0;
}
// Type 0: id
// Type 1: numeral
// Type 2: channel type
// Type 3: event type
// Type 4: event name
// Type 5: '='
// Type 6: attribute value
// Type 7: id or numeral
// Type 8:unit
public boolean checkParameter(String _inst, String[] _split, int _parameter, int _type, int _lineNb) {
boolean err = false;
String error;
if (_parameter < _split.length) {
switch (_type) {
case 0:
if (!isAValidId(_split[_parameter])) {
err = true;
}
break;
case 1:
if (!isANumeral(_split[_parameter])) {
err = true;
}
break;
case 2:
if (!isIncluded(_split[_parameter], channeltypes)) {
err = true;
}
break;
case 3:
if (!isIncluded(_split[_parameter], eventtypes)) {
err = true;
}
break;
case 4:
if (!isAValidId(getEvtId(_split[_parameter]))) {
err = true;
//TraceManager.addDev("Unvalid id");
} else if (!TMLEvent.isAValidListOfParams(getParams(_split[_parameter]))) {
//TraceManager.addDev("Unvalid param");
err = true;
}
break;
case 5:
if (!(_split[_parameter].equals("="))) {
TraceManager.addDev("Error of =");
err = true;
}
break;
case 6:
if (_inst.equals("BOOL")) {
String tmp = _split[_parameter].toUpperCase();
if (!(tmp.equals("TRUE") || tmp.equals("FALSE"))) {
err = true;
}
} else {
if (!isANumeral(_split[_parameter])) {
err = true;
}
}
break;
case 7:
if (!isAValidId(_split[_parameter]) && !isANumeral(_split[_parameter])) {
err = true;
}
break;
case 8:
if (!isAValidUnit(_split[_parameter])) {
err = true;
}
break;
case 9:
if (!isANegativeOrPositiveNumeral(_split[_parameter])) {
err = true;
}
break;
case 10:
if (!(_split[_parameter].compareTo("OUT") == 0)) {
err = true;
}
break;
}
} else {
err = true;
}
if (err) {
error = "Unvalid parameter #" + _parameter + "-> $" + _split[_parameter] + "$ <- in " + _inst + " instruction";
addError(0, _lineNb, 0, error);
return false;
}
return true;
}
public boolean isInstruction(String instcode, String inst) {
return (inst.toUpperCase().compareTo(instcode) == 0);
}
public boolean isInstruction(String instcode) {
return (!checkKeywords(instcode));
}
public static boolean isAValidId(String _id) {
if ((_id == null) || (_id.length() == 0)) {
return false;
}
boolean b1 = (_id.substring(0, 1)).matches("[a-zA-Z]");
boolean b2 = _id.matches("\\w*");
boolean b3 = checkKeywords(_id);
return (b1 && b2 && b3);
}
public boolean isANumeral(String _num) {
return _num.matches("\\d*");
}
public boolean isANegativeOrPositiveNumeral(String _num) {
if (_num.startsWith("-")) {
return isANumeral(_num.substring(1, _num.length()));
}
return isANumeral(_num);
}
public boolean isAValidUnit(String s) {
if (s.compareTo("ns") == 0) {
return true;
} else if (s.compareTo("us") == 0) {
return true;
} else if (s.compareTo("ms") == 0) {
return true;
} else if (s.compareTo("s") == 0) {
return true;
}
return false;
}
public static boolean checkKeywords(String _id) {
String id = _id.toUpperCase();
for (int i = 0; i < keywords.length; i++) {
if (id.compareTo(keywords[i]) == 0) {
return false;
}
}
return true;
}
public boolean isIncluded(String _id, String[] _list) {
String id = _id.toUpperCase();
for (int i = 0; i < _list.length; i++) {
if (id.compareTo(_list[i]) == 0) {
return true;
}
}
return false;
}
public String removeUndesiredWhiteSpaces(String _input, int _lineNb) {
String error, tmp;
int index0, index1;//, index2;
if (_input.startsWith("EVENT ")) {
index0 = _input.indexOf('(');
index1 = _input.indexOf(')');
if ((index0 == -1) || (index1 == -1)) {
error = "Syntax Error: should be of the form EVENT evtname(<list of max three types>) + other parameters";
addError(0, _lineNb, 0, error);
return null;
}
return Conversion.replaceBetweenIndex(_input, index0, index1, " ", "");
}
if (_input.startsWith("REQUEST ") && (inDec)) {
index0 = _input.indexOf('(');
index1 = _input.indexOf(')');
if ((index0 == -1) || (index1 == -1)) {
error = "Syntax Error: should be of the form REQUEST requestname(<list of max three types>) + other parameters";
addError(0, _lineNb, 0, error);
return null;
}
return Conversion.replaceBetweenIndex(_input, index0, index1, " ", "");
}
if (_input.startsWith("FOR(")) {
_input = "FOR (" + _input.substring(4, _input.length());
}
if (_input.startsWith("FOR (")) {
tmp = _input.substring(5, _input.length());
tmp = Conversion.replaceAllString(tmp, " ", "");
return "FOR (" + tmp;
}
if (_input.startsWith("IF(")) {
_input = "IF (" + _input.substring(3, _input.length());
}
if (_input.startsWith("IF (")) {
tmp = _input.substring(4, _input.length());
tmp = Conversion.replaceAllString(tmp, " ", "");
return "IF (" + tmp;
}
if (_input.startsWith("ORIF(")) {
_input = "ORIF (" + _input.substring(5, _input.length());
}
if (_input.startsWith("ORIF (")) {
tmp = _input.substring(6, _input.length());
tmp = Conversion.replaceAllString(tmp, " ", "");
return "ORIF (" + tmp;
}
return _input;
}
private String getEvtId(String _input) {
int index = _input.indexOf('(');
if (index == -1) {
return _input;
}
return _input.substring(0, index);
}
private String getParams(String _input) {
//TraceManager.addDev("input=" + _input);
int index0 = _input.indexOf('(');
int index1 = _input.indexOf(')');
if ((index0 == -1) || (index1 == -1)) {
return _input;
}
return _input.substring(index0 + 1, index1);
}
private static String prepareString(String s) {
if (s == null) {
return null;
}
return s.replaceAll("\\s", "");
}
public static String modifyString(String s) {
return prepareString(s);
}
}