blob: 0b3e7a89c2fb7d0590650bf5e63391bc5d7a5227 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 CEA LIST.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Created on: 4 févr. 2015
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "BasicTraceParser.h"
#include <fstream>
#include <fml/expression/ExpressionConstructor.h>
#include <fml/executable/ExecutableQuery.h>
#include <fml/executable/ExecutableSystem.h>
#include <fml/executable/InstanceOfPort.h>
#include <fml/symbol/Symbol.h>
#include <fml/trace/TracePoint.h>
#include <fml/trace/TraceSequence.h>
#include <sew/Configuration.h>
namespace sep
{
////////////////////////////////////////////////////////////////////////////////
// OTHER API
////////////////////////////////////////////////////////////////////////////////
/*
* Exemple de trace basique
1
TSI_target?1
120
RSD_ENABLED_source!1
0
PSD_ENABLED_source!1
423385
RSD_CMD_source!1
0
PSD_STATE1_target?0
3025646
DEP_AUTH1_source!1
1059822
TSI1_target?0
BASIC#XLIA:
INPUT env_connection_signal( )
OUTPUT env_enter_pin_message( )
INPUT env_user_pin( 3782 )
OUTPUT env_asked_withdrawal_message( )
INPUT env_asked_withdrawal( 5001 )
OUTPUT env_operation_not_possible( 2 , 5000 )
*/
bool BasicTraceParser::parseBasicXliaTrace(TraceSequence & aTraceElement,
std::ifstream & inFile, const BF & aVarTime)
{
bool isOK = true;
//for debug purposes
bool isOKLine = true;
int cptLine = 0;
bfVarTime = aVarTime;
std::string inLine;
while( inFile.good() )
{
cptLine ++;
std::getline(inFile, inLine);
StringTools::ltrim( inLine );
if( (inLine == "\\n") || inLine.empty() )
{
// !!NOTHING: SKIP NEWLINE
isOKLine = true;
}
else if((inLine[0]) == '#')
{
// COMMENT
isOKLine = true;
}
else if( StringTools::startsWith(inLine, "delta") )
{
isOKLine = parseBasicXliaTraceDuration(aTraceElement, inLine, aVarTime);
}
else if( REGEX_STARTS(inLine, "(input|output|INPUT|OUTPUT)") )
{
isOKLine = parseBasicXliaTraceSignal(aTraceElement, inLine);
}
else if((inLine[0]) == '{')
{
isOKLine = parseBasicTraceStructure(aTraceElement, inLine);
}
isOK = isOKLine && isOK;
if(not isOKLine)
{
AVM_OS_WARN << "Error: Error while reading trace file on line "
<< cptLine << ": " << inLine << std::endl;
}
}
return( isOK );
}
bool BasicTraceParser::parseBasicXliaTraceDuration(TraceSequence & aTraceElement,
const std::string & inLine, const BF & aVarTime)
{
std::string::size_type pos = inLine.find('=');
std::string delta = inLine.substr(pos+1);
StringTools::ltrim( delta );
avm_integer_t duration;
if( from_string(delta, duration, std::dec) )
{
bfTP = new TracePoint(
ENUM_TRACE_POINT::TRACE_TIME_NATURE,
AVM_OPCODE_TIMED_GUARD, NULL,
aVarTime.to_ptr< InstanceOfData >(),
ExpressionConstructor::newInteger(duration) );
aTraceElement.points.append( bfTP );
return( true );
}
return( false );
}
bool BasicTraceParser::parseBasicXliaTraceSignal(
TraceSequence & aTraceElement, const std::string & inLine)
{
bfTP = aTracePoint = new TracePoint(ENUM_TRACE_POINT::TRACE_COM_NATURE);
Modifier::DIRECTION_KIND ioDirection;
//std::string::size_type pos = inLine.find('?');
std::string message;
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_LOG << "PARSER : the message trace is >>" << inLine << "<<"
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
if( REGEX_STARTS(inLine, "(input|INPUT)") )
{
ioDirection = Modifier::DIRECTION_INPUT_KIND;
message = inLine.substr(6);
}
else if( REGEX_STARTS(inLine, "(output|OUTPUT)") )
{
ioDirection = Modifier::DIRECTION_OUTPUT_KIND;
message = inLine.substr(7);
}
message = StringTools::trim(message);
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_LOG << "PARSER : the message is >>" << message << "<<" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
std::string::size_type pos = message.find('(');
if( pos != std::string::npos )
{
ExecutableQuery XQuery( mConfiguration );
const Symbol & foundSignal =
XQuery.getPortByQualifiedNameID(
message.substr(0, pos), ioDirection, false );
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_LOG << "PARSER : the port is >>" << message.substr(0, pos) << "<<"
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
if( foundSignal.valid() )
{
InstanceOfPort* port = foundSignal.rawPort();
aTracePoint->object = port;
if( ioDirection == Modifier::DIRECTION_INPUT_KIND )
{
if( port->hasInputRoutingData() &&
port->getInputRoutingData().isProtocolENV() )
{
aTracePoint->op = AVM_OPCODE_INPUT_ENV;
}
else
{
aTracePoint->op = AVM_OPCODE_INPUT;
}
}
else if( ioDirection == Modifier::DIRECTION_OUTPUT_KIND )
{
if( port->hasOutputRoutingData() &&
port->getOutputRoutingData().isProtocolENV() )
{
aTracePoint->op = AVM_OPCODE_OUTPUT_ENV;
}
else
{
aTracePoint->op = AVM_OPCODE_OUTPUT;
}
}
//TODO : check what happens if there is no parameter given ()
if( parseBasicTraceSignalParameters(aTracePoint, port,
message.substr(pos + 1, message.size()-pos-2)) )
{
aTraceElement.points.append( bfTP );
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_LOG << "PARSER : and its parameters are >>"
<< message.substr(pos + 1, message.size()-pos-2) << "<<"
<< std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
return( true );
}
}
}
else
{
aTracePoint->value = ExpressionConstructor::newString(inLine);
aTraceElement.points.append( bfTP );
}
return( false );
}
bool BasicTraceParser::parseBasicTrace(TraceSequence & aTraceElement,
std::ifstream & inFile, const BF & aVarTime)
{
bool isOK = true;
//for debug purposes
bool isOKLine = true;
int cptLine = 0;
bfVarTime = aVarTime;
std::string inLine;
while( inFile.good() )
{
cptLine ++;
std::getline(inFile, inLine);
StringTools::ltrim( inLine );
if( (inLine == "\\n") || inLine.empty() )
{
// !!NOTHING: SKIP NEWLINE
isOKLine = true;
}
else if((inLine[0]) == '#')
{
// COMMENT
isOKLine = true;
}
else if( std::isdigit(inLine[0]) )
{
isOKLine = parseBasicTraceDuration(aTraceElement, inLine, aVarTime);
}
else if( std::isalpha(inLine[0]) )
{
isOKLine = parseBasicTraceSignal(aTraceElement, inLine);
}
else if((inLine[0]) == '{')
{
isOKLine = parseBasicTraceStructure(aTraceElement, inLine);
}
isOK = isOKLine && isOK;
if(not isOKLine)
{
AVM_OS_WARN << "Error: Error while reading trace file on line "
<< cptLine << std::endl;
}
}
return( isOK );
}
bool BasicTraceParser::parseBasicTraceDuration(TraceSequence & aTraceElement,
const std::string & inLine, const BF & aVarTime)
{
avm_integer_t duration;
if( from_string(inLine, duration, std::dec) )
{
bfTP = new TracePoint(
ENUM_TRACE_POINT::TRACE_TIME_NATURE,
AVM_OPCODE_TIMED_GUARD, NULL,
aVarTime.to_ptr< InstanceOfData >(),
ExpressionConstructor::newInteger(duration) );
aTraceElement.points.append( bfTP );
return( true );
}
return( false );
}
bool BasicTraceParser::parseBasicTraceSignal(
TraceSequence & aTraceElement, const std::string & inLine)
{
bfTP = aTracePoint = new TracePoint(ENUM_TRACE_POINT::TRACE_COM_NATURE);
Modifier::DIRECTION_KIND io_dir;
std::string::size_type pos = inLine.find('?');
if( pos != std::string::npos )
{
io_dir = Modifier::DIRECTION_INPUT_KIND;
aTracePoint->op = AVM_OPCODE_INPUT;
}
else if( (pos = inLine.find('!')) != std::string::npos )
{
io_dir = Modifier::DIRECTION_OUTPUT_KIND;
aTracePoint->op = AVM_OPCODE_OUTPUT;
}
if( pos != std::string::npos )
{
ExecutableQuery XQuery( mConfiguration );
const Symbol & foundSignal =
XQuery.getPortByQualifiedNameID(
inLine.substr(0, pos), io_dir, false );
if( foundSignal.valid() )
{
InstanceOfPort* port = foundSignal.rawPort();
aTracePoint->object = port;
if( parseBasicTraceSignalParameters(
aTracePoint, port, inLine.substr(pos + 1)))
{
aTraceElement.points.append( bfTP );
return( true );
}
}
}
else
{
aTracePoint->value = ExpressionConstructor::newString(inLine);
aTraceElement.points.append( bfTP );
}
return( false );
}
/*
* This method takes an inputs:
* a trace point, a port and a string expression
*
*/
bool BasicTraceParser::parseBasicTraceSignalParameters(
TracePoint * aTracePoint, InstanceOfPort* port,
const std::string & anExpr)
{
std::string::size_type pos;
avm_size_t nbParams = port->getParameterCount();
avm_size_t count = 0;
//this variables is used to count the number of parameters given in the trace
std::string currentExpr = anExpr;
//TODO: do the verification on the number of parameters while parsing
// e.g. create an array with the parameter values
while ((pos = currentExpr.find(',') )!= std::string::npos)
{
currentExpr = currentExpr.substr(pos+1);
count++;
}
StringTools::trim(currentExpr);
if( currentExpr.compare("") != 0 )
{
count++;
}
if( count != port->getParameterCount() )
{
// if the number of parameters given in the trace does
// not match the declaration in the file specification
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
AVM_OS_LOG << "PARSER WARNING : the number of parameters expected "
"is " << nbParams << " while the actual number of parameters "
"given in the trace is " << count << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PROCESSOR )
return false;
}
if (nbParams != 0)
{
aTracePoint->newArrayValue(nbParams);
std::string param;
currentExpr = anExpr;
int i = 0;
bool correct = true;
//the correct number of parameters has already been ascertained
while (((pos = currentExpr.find(',')) != std::string::npos) && correct)
{
// retrieving parameter from the string
param = currentExpr.substr(0, pos);
BF paramBF = parseBasicTraceSignalParameter(
(* (port->getParameterType(i))), param);
if(paramBF == NULL)
{
return false;
}
else
{
aTracePoint->val(i, paramBF);
i++;
currentExpr = currentExpr.substr(pos+1);
}
}
param = StringTools::trim(currentExpr);
BF paramBF = parseBasicTraceSignalParameter(* port->getParameterType(i), param);
//BF paramBF = ExpressionConstructor::newExpr(* port->getParameterType(i), param);
if(paramBF == NULL)
{
return false;
}
else
{
aTracePoint->val(i, paramBF);
}
return true;
}
else
{
return true;
}
return true;
}
/*
* anExpr is the string representing the parameter to be parsed
* aTypeSpecifier is the type of the parameter
* returns a BF representing the parameter
*/
BF BasicTraceParser::parseBasicTraceSignalParameter(
const ITypeSpecifier & aTypeSpecifier, const std::string & anExpr)
{
std::string param = anExpr;
StringTools::trim(param);
BF paramBF;
//AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
// AVM_OS_LOG << "PARSER: parameter type: ";
// aTypeSpecifier.toStream(AVM_OS_LOG);
// AVM_OS_LOG << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
// Removing encompassing quotes in strings before building
if( aTypeSpecifier.isTypedString()
&& (not param.empty()) && (param[0] == '"') )
{
param = param.substr(1, param.size() - 2);
paramBF = ExpressionConstructor::newString(param);
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_LOG << "PARSER: reading a string: " << param << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
}
else if( aTypeSpecifier.isTypedCharacter() && (not param.empty()) )
{
if( param.size() == 1 )
{
paramBF = ExpressionConstructor::newChar(param[0]);
}
else if( param[0] == '\'' )
{
paramBF = ExpressionConstructor::newChar(param[1]);
}
else // ERROR !!!
{
paramBF = ExpressionConstructor::newChar(param[0]);
}
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_LOG << "PARSER: reading a string: " << param << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
}
// machines as parameters contain run and pid information,
// we must remove them (no configuration yet)
else if( aTypeSpecifier.isTypedMachine() )
{
if( StringTools::startsWith(param, "run::") )
{
std::string::size_type parampos = param.find(':', 5);
if( parampos != std::string::npos )
{
param = param.substr(parampos+1);
}
paramBF = ExpressionConstructor::newExprRuntine(mConfiguration, param);
}
else
{
paramBF = ExpressionConstructor::newExprMachine(mConfiguration, param);
}
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_LOG << "PARSER: reading a machine: " << param << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
}
else
{
paramBF = ExpressionConstructor::newExpr(
mConfiguration, aTypeSpecifier, param);
}
if( paramBF.invalid() )
{
AVM_OS_WARN << "PARSER: failed to build BF from parameter: "
<< param << std::endl;
}
else
{
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
AVM_OS_LOG << "PARSER: parameter value read: " << paramBF << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , PROCESSOR )
}
return paramBF;
}
bool BasicTraceParser::parseBasicTraceStructure(
TraceSequence & aTraceElement, const std::string & inLine)
{
return( false );
}
} /* namespace sep */