ЗАТВЕРДЖЕНО 1116139.00218-01 12 01-ЛЗ	

Середовище програмування системи OpenSCADA

Текст програми

1116139.00218-01 12 01

Листів 109

2005

АНОТАЦІЯ

Документ 1116139.00218-01 12 01 “Середовище програмування системи OpenSCADA. Текст програми” входить до складу документації на компоненти середовища програмування системи OpenSCADA.

Цей документ містить вихідні тексти компонентів середовища програмування системи OpenSCADA. Вихідні тексти розповсюджуються за публічною ліцензією GNU GPL v 2.

У перелік компонентів середовища програмування входять наступні компоненти:

підсистема “Функції” системи OpenSCADA;

модуль “JavaLikeCalc” підсистеми “Контролери”;

модуль “BlockCalc” підсистеми “Контролери”;

модуль “StaticFuncLibs” підсистеми “Спеціальні”.

Підсистема “Функції” входить до складу ядра системи OpenSCADA. Модулі входять у дистрибутив системи OpenSCADA.

Запуск компонентів відбувається разом з системою OpenSCADA. На момент розробки компонентів підтримується ОС Linux, на якій і треба запускати систему OpenSCADA.

ЗМІСТ

1 Підсистема “Функції” системи OpenSCADA	4

1.1 Вміст файлу tfunctions.h	4

1.2 Вміст файлу tfunctions.cpp	7

2 Модуль “JavaLikeCalc” підсистеми “Контролери”;	16

2.1 Вміст файлу virtual.h	17

2.2 Вміст файлу virtual.cpp	19

2.3 Вміст файлу freelib.h	29

2.4 Вміст файлу freelib.cpp	30

2.5 Вміст файлу freefunc.h	33

2.6 Вміст файлу freefunc.cpp	38

2.7 Вміст файлу func_analise.ypp	58

3 Модуль “BlockCalc” підсистеми “Контролери”;	65

3.1 Вміст файлу virtual.h	66

3.2 Вміст файлу virtual.cpp	68

3.3 Вміст файлу block.h	76

3.4 Вміст файлу block.cpp	78

4 Модуль “StaticFuncLibs” підсистеми “Спеціальні”	89

4.1 Вміст файлу statfunc.h	90

4.2 Вміст файлу statfunc.cpp	90

4.3 Вміст файлу libcompl1.h	92

4.4 Вміст файлу stdmath.h	103

Підсистема “Функції” системи OpenSCADA

Підсистему функції реалізовано у файлах tfunctions.cpp та tfunctions.h. Ці файли інтегровано у ядро системи OpenSCADA.

Підсистема “Функції” представлена декількома об'єктами(класами). Статичну діаграму об'єктів підсистеми “Функції” та взаємозв'язки між ними наведено на рис. 1.

Рис. 1. Статична діаграма класів підсистеми "Функції"

Вміст файлу tfunctions.h

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#ifndef TFUNCTIONS_H

#define TFUNCTIONS_H

#include <string>

#include <vector>

#include "tsys.h"

using std::string;

using std::vector;

class TFunction;

class IO

{

friend class TFunction;

public:

enum Type { String, Integer, Real, Boolean, Vector };

enum Mode { Input, Output, Return };

IO( const char *iid, const char *iname, IO::Type itype, IO::Mode imode,

const char *idef = "", bool ihide = false, const char *ivect = "" );

const string &id()	{ return m_id; }

const string &name()	{ return m_name; }

const Type &type()	{ return m_type; }

const Mode &mode()	{ return m_mode; }

const string &def()	{ return m_def; }

const string &vector()	{ return m_vect; }

bool hide()	{ return m_hide; }

void id( const string &val );

void name( const string &val );

void type( Type val );

void mode( Mode val );

void def( const string &val );

void vector( const string &val );

void hide( bool val );

private:

string	m_id;

string	m_name;

Type	m_type;

Mode	m_mode;

string m_def;

string	m_vect;

bool	m_hide;

TFunction *owner;

};

//Function abstract object

class TValFunc;

class TFunction : public TCntrNode

{

public:

TFunction( const string &iid );

virtual ~TFunction();

string &id()	{ return m_id; };

virtual string name() = 0;

virtual string descr() = 0;

bool startStat() { return run_st; }

virtual void start( bool val ) { run_st = val; }

void ioList( vector<string> &list );

int ioId( const string &id );

int ioSize();

IO *io( int id );

virtual void calc( TValFunc *val ) = 0;

void valAtt( TValFunc *vfnc );

void valDet( TValFunc *vfnc );

virtual void preIOCfgChange();

virtual void postIOCfgChange();

protected:

//================== Controll functions ========================

void cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd );

void ioAdd( IO *io );

void ioIns( IO *io, int pos );

void ioDel( int pos );

void ioMove( int pos, int to );

void preDisable(int flag);

protected:

string m_id;

bool run_st;

TValFunc *m_tval;

private:

string nodeName() { return id(); }

private:

vector<IO*>	m_io;

vector<TValFunc*>	used;

};

class TValFunc

{

public:

TValFunc( const string &iname = "", TFunction *ifunc = NULL );

virtual ~TValFunc( );

const string &name()	{ return m_name; }

void name( const char &inm )	{ m_name = inm; }

void	ioList( vector<string> &list );

int	ioId( const string &id );	//IO id

int	ioSize( );

IO::Type ioType( unsigned id )

{

if( id >= m_val.size() ) throw TError("ValFunc",Mess->I18N("Id or IO %d error!"),id);

return m_func->io(id)->type();

}

IO::Mode ioMode( unsigned id )

{

if( id >= m_val.size() ) throw TError("ValFunc",Mess->I18N("Id or IO %d error!"),id);

return m_func->io(id)->mode();

}

bool ioHide( unsigned id )

{

if( id >= m_val.size() ) throw TError("ValFunc",Mess->I18N("Id or IO %d error!"),id);

return m_func->io(id)->hide();

}

//get IO value

string getS( unsigned id );

int getI( unsigned id );

double getR( unsigned id );

bool getB( unsigned id );

//set IO value

void setS( unsigned id, const string &val );

void setI( unsigned id, int val );

void setR( unsigned id, double val );

void setB( unsigned id, bool val );

//Dimension controll

bool	dimens()	{ return m_dimens; }

void	dimens( bool set )	{ m_dimens = set; }

//Calc function

virtual void calc( );

//Calc time function

double calcTm( )	{ return tm_calc; }

//Attached function

TFunction *func( )	{ return m_func; }

void func( TFunction *ifunc, bool att_det = true );

virtual void preIOCfgChange();

virtual void postIOCfgChange();

protected:

struct SVl

{

IO::Type	tp;

void	*vl;

};

vector<SVl> m_val; //pointer to: string, int, double, bool

private:

void funcDisConnect( bool det = true );

private:

string	m_name;	//Value name

bool	m_dimens;	//Make dimension of the calc time

double	tm_calc;	//Calc time in mikroseconds

TFunction	*m_func;

};

//Function library abstract object

class TLibFunc : public TCntrNode

{

public:

TLibFunc( const string &iid );

virtual ~TLibFunc( );

string &id()	{ return m_id; };

virtual string name() = 0;

virtual string descr() = 0;

bool startStat( )	{ return run_st; }

virtual void start( bool val );

void list( vector<string> &ls )	{ chldList(m_fnc,ls); }

bool present( const string &id )	{ return chldPresent(m_fnc,id); }

AutoHD<TFunction> at( const string &id )

{ return chldAt(m_fnc,id); }

protected:

void reg( TFunction *fnc )	{ chldAdd(m_fnc,fnc); }

void unreg( const string &id )	{ chldDel(m_fnc,id); }

//================== Controll functions ========================

void cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd );

AutoHD<TCntrNode> ctrAt( const string &br );

protected:

int m_fnc;

private:

string nodeName() { return id(); }

private:

bool	run_st;

string	m_id;

};

//List of function libraries

class TFunctionS : public TSubSYS

{

public:

TFunctionS( );

~TFunctionS( );

void subStart( );

void subStop( );

void list( vector<string> &ls )	{ chldList(m_lb,ls); }

bool present( const string &id ){ return chldPresent(m_lb,id); }

void reg( TLibFunc *lib )	{ chldAdd(m_lb,lib); }

void unreg( const string &id, int flg = 0 )	{ chldDel(m_lb,id,-1,flg); }

AutoHD<TLibFunc> at( const string &id )

{ return chldAt(m_lb,id); }

private:

//================== Controll functions ========================

void cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd );

AutoHD<TCntrNode> ctrAt( const string &br );

private:

bool run_st;

int	m_lb;

};

#endif //TFUNCTIONS_H

Вміст файлу tfunctions.cpp

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#include <math.h>

#include <tsys.h>

#include <tmess.h>

#include "tfunctions.h"

//List of function libraries

TFunctionS::TFunctionS( ) : TSubSYS("Functions","Functions",false), run_st(false)

{

m_lb = grpAdd();

}

TFunctionS::~TFunctionS()

{

}

void TFunctionS::subStart( )

{

vector<string> lst;

list(lst);

for( int i_f = 0; i_f < lst.size(); i_f++ )

at(lst[i_f]).at().start(true);

run_st = true;

}

void TFunctionS::subStop( )

{

vector<string> lst;

list(lst);

for( int i_f = 0; i_f < lst.size(); i_f++ )

at(lst[i_f]).at().start(false);

run_st = false;

}

void TFunctionS::cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd )

{

switch(cmd)

{

case TCntrNode::Info:

TSubSYS::cntrCmd_( a_path, opt, cmd ); //Call parent

ctrInsNode("area",0,opt,a_path.c_str(),"/lslib",Mess->I18N("Function's libraries"));

ctrMkNode("list",opt,a_path.c_str(),"/lslib/lib",Mess->I18N("Libraries"),0444,0,0,"br")->

attr_("idm","1")->attr_("mode","att")->attr_("br_pref","_");

break;

case TCntrNode::Get:

if( a_path == "/lslib/lib" )

{

vector<string> list_el;

list(list_el);

opt->childClean();

for( unsigned i_f=0; i_f < list_el.size(); i_f++ )

ctrSetS( opt, at(list_el[i_f]).at().name(), list_el[i_f].c_str() );

}

else TSubSYS::cntrCmd_( a_path, opt, cmd );

break;

case TCntrNode::Set:

TSubSYS::cntrCmd_( a_path, opt, cmd );

break;

}

}

AutoHD<TCntrNode> TFunctionS::ctrAt( const string &br )

{

if( br.substr(0,1) == "_" )	return at(TSYS::strEncode(br.substr(1),TSYS::PathEl));

else throw TError(nodePath().c_str(),Mess->I18N("Branch <%s> error!"),br.c_str());

}

//Function library abstract object

TLibFunc::TLibFunc( const string &iid ) : m_id(iid), run_st(false)

{

m_fnc = grpAdd();

}

TLibFunc::~TLibFunc()

{

}

void TLibFunc::start( bool val )

{

vector<string> lst;

list(lst);

for( int i_f = 0; i_f < lst.size(); i_f++ )

at(lst[i_f]).at().start(val);

run_st = val;

}

void TLibFunc::cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd )

{

if( cmd==TCntrNode::Info )

{

ctrMkNode("oscada_cntr",opt,a_path.c_str(),"/",Mess->I18N("Function's library: ")+id());

ctrMkNode("area",opt,a_path.c_str(),"/lib",Mess->I18N("Library"));

ctrMkNode("area",opt,a_path.c_str(),"/lib/st",Mess->I18N("State"));

ctrMkNode("fld",opt,a_path.c_str(),"/lib/st/st",Mess->I18N("Accessing"),0664,0,0,"bool");

ctrMkNode("area",opt,a_path.c_str(),"/lib/cfg",Mess->I18N("Config"));

ctrMkNode("fld",opt,a_path.c_str(),"/lib/cfg/id",Mess->I18N("Id"),0444,0,0,"str");

ctrMkNode("fld",opt,a_path.c_str(),"/lib/cfg/name",Mess->I18N("Name"),0444,0,0,"str");

ctrMkNode("fld",opt,a_path.c_str(),"/lib/cfg/descr",Mess->I18N("Description"),0444,0,0,"str")->

attr_("cols","90")->attr_("rows","4");

ctrMkNode("area",opt,a_path.c_str(),"/func",Mess->I18N("Functions"));

ctrMkNode("list",opt,a_path.c_str(),"/func/func",Mess->I18N("Functions"),0444,0,0,"br")->

attr_("idm","1")->attr_("mode","att")->attr_("br_pref","_");

}

else if( cmd==TCntrNode::Get )

{

if( a_path == "/lib/st/st" )	ctrSetB( opt, run_st );

else if( a_path == "/lib/cfg/id" )	ctrSetS( opt, id() );

else if( a_path == "/lib/cfg/name" )	ctrSetS( opt, name() );

else if( a_path == "/lib/cfg/descr" )	ctrSetS( opt, descr() );

else if( a_path == "/func/func" )

{

vector<string> list_el;

list(list_el);

opt->childClean();

for( unsigned i_f=0; i_f < list_el.size(); i_f++ )

ctrSetS( opt, at(list_el[i_f]).at().name(), list_el[i_f].c_str() );

}

else throw TError(nodePath().c_str(),Mess->I18N("Branch <%s> error!"),a_path.c_str());

}

else if( cmd==TCntrNode::Set )

{

if( a_path == "/lib/st/st" )	start(ctrGetB(opt));

else throw TError(nodePath().c_str(),Mess->I18N("Branch <%s> error!"),a_path.c_str());

}

}

AutoHD<TCntrNode> TLibFunc::ctrAt( const string &br )

{

if( br.substr(0,1) == "_" )	return at(TSYS::strEncode(br.substr(1),TSYS::PathEl));

else throw TError(nodePath().c_str(),Mess->I18N("Branch <%s> error!"),br.c_str());

}

//Function abstract object

TFunction::TFunction( const string &iid ) : m_id(iid), m_tval(NULL), run_st(false)

{

}

TFunction::~TFunction()

{

for( int i_io = 0; i_io < m_io.size(); i_io++ )

delete m_io[i_io];

}

void TFunction::preDisable(int flag)

{

if( m_tval ) { delete m_tval; m_tval = NULL; }

if( used.size() )

{

string mess = Mess->I18N("Function used by: ");

for( int i=0; i < used.size(); i++ )

mess+=used[i]->name()+", ";

throw TError(nodePath().c_str(),mess.c_str());

}

}

int TFunction::ioSize()

{

return m_io.size();

}

IO *TFunction::io( int iid )

{

if( iid >= m_io.size() ) throw TError(nodePath().c_str(),Mess->I18N("Index %d broken!"),iid);

return m_io[iid];

}

int TFunction::ioId( const string &id )

{

for( int i_io = 0; i_io < m_io.size(); i_io++ )

if( m_io[i_io]->id() == id ) return i_io;

return -1;

}

void TFunction::ioList( vector<string> &list )

{

for( int i_io = 0; i_io < m_io.size(); i_io++ )

list.push_back( m_io[i_io]->id() );

}

void TFunction::ioAdd( IO *io )

{

preIOCfgChange();

m_io.push_back(io);

io->owner = this;

postIOCfgChange();

}

void TFunction::ioIns( IO *io, int pos )

{

if( pos < 0 || pos > m_io.size() )

pos = m_io.size();

preIOCfgChange();

m_io.insert(m_io.begin()+pos,io);

io->owner = this;

postIOCfgChange();

}

void TFunction::ioDel( int pos )

{

if( pos < 0 || pos >= m_io.size() )

throw TError(nodePath().c_str(),Mess->I18N("Delete IO <%d> error."),pos);

preIOCfgChange();

m_io.erase(m_io.begin()+pos);

postIOCfgChange();

}

void TFunction::ioMove( int pos, int to )

{

if( pos < 0 || pos >= m_io.size() || to < 0 || to >= m_io.size() )

throw TError(nodePath().c_str(),Mess->I18N("Move IO from %d to %d error."),pos,to);

preIOCfgChange();

IO *io = m_io[to];

m_io[to] = m_io[pos];

m_io[pos] = io;

postIOCfgChange();

}

void TFunction::preIOCfgChange()

{

for(unsigned i=0; i < used.size(); i++)

used[i]->preIOCfgChange();

}

void TFunction::postIOCfgChange()

{

for(unsigned i=0; i < used.size(); i++)

used[i]->postIOCfgChange();

}

void TFunction::valAtt( TValFunc *vfnc )

{

for(unsigned i=0; i < used.size() ;i++)

if(used[i] == vfnc)

throw TError(nodePath().c_str(),Mess->I18N("Value <%s> already attached!"),vfnc->name().c_str());

used.push_back(vfnc);

}

void TFunction::valDet( TValFunc *vfnc )

{

for(unsigned i=0; i < used.size() ;i++)

if(used[i] == vfnc)

{

used.erase(used.begin()+i);

break;

}

}

void TFunction::cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd )

{

if( cmd==TCntrNode::Info )

{

ctrMkNode("oscada_cntr",opt,a_path.c_str(),"/",Mess->I18N("Function: ")+name());

ctrMkNode("area",opt,a_path.c_str(),"/func",Mess->I18N("Function"));

ctrMkNode("area",opt,a_path.c_str(),"/func/st",Mess->I18N("State"));

ctrMkNode("fld",opt,a_path.c_str(),"/func/st/st",Mess->I18N("Accessing"),0664,0,0,"bool");

ctrMkNode("area",opt,a_path.c_str(),"/func/cfg",Mess->I18N("Config"));

ctrMkNode("fld",opt,a_path.c_str(),"/func/cfg/id",Mess->I18N("Id"),0444,0,0,"str");

ctrMkNode("fld",opt,a_path.c_str(),"/func/cfg/name",Mess->I18N("Name"),0444,0,0,"str");

ctrMkNode("fld",opt,a_path.c_str(),"/func/cfg/descr",Mess->I18N("Description"),0444,0,0,"str")->

attr_("cols","70")->attr_("rows","4");

ctrMkNode("area",opt,a_path.c_str(),"/io",Mess->I18N("IO"));

ctrMkNode("table",opt,a_path.c_str(),"/io/io",Mess->I18N("IO"),0440,0,0);

ctrMkNode("list",opt,a_path.c_str(),"/io/io/0",Mess->I18N("Id"),0440,0,0,"str");

ctrMkNode("list",opt,a_path.c_str(),"/io/io/1",Mess->I18N("Name"),0440,0,0,"str");

ctrMkNode("list",opt,a_path.c_str(),"/io/io/2",Mess->I18N("Type"),0440,0,0,"str");

ctrMkNode("list",opt,a_path.c_str(),"/io/io/3",Mess->I18N("Mode"),0440,0,0,"str");

ctrMkNode("list",opt,a_path.c_str(),"/io/io/4",Mess->I18N("Hide"),0440,0,0,"bool");

ctrMkNode("list",opt,a_path.c_str(),"/io/io/5",Mess->I18N("Default"),0440,0,0,"str");

//ctrMkNode("list",opt,a_path.c_str(),"/io/io/6",Mess->I18N("Vector"),0440,0,0,"str");

ctrMkNode("area",opt,a_path.c_str(),"/test",Mess->I18N("Test"));

ctrMkNode("fld",opt,a_path.c_str(),"/test/en",Mess->I18N("Enable"),0660,0,0,"bool");

//Add test form

if( m_tval )

{

ctrMkNode("area",opt,a_path.c_str(),"/test/io",Mess->I18N("IO"));

//Put io

for( int i_io = 0; i_io < ioSize(); i_io++ )

{

if( m_io[i_io]->hide() ) continue;

char *tp = "";

if(io(i_io)->type() == IO::String)	tp = "str";

else if(io(i_io)->type() == IO::Integer)tp = "dec";

else if(io(i_io)->type() == IO::Real)	tp = "real";

else if(io(i_io)->type() == IO::Boolean)tp = "bool";

ctrMkNode("fld",opt,a_path.c_str(),("/test/io/"+io(i_io)->id()).c_str(),io(i_io)->name(),0664,0,0,tp);

}

//Add Calc button and Calc time

ctrMkNode("fld",opt,a_path.c_str(),"/test/tm",Mess->I18N("Calc time (mks)"),0444,0,0,"real");

ctrMkNode("comm",opt,a_path.c_str(),"/test/calc",Mess->I18N("Calc"));

}

}

else if( cmd==TCntrNode::Get )

{

if( a_path == "/func/st/st" )	ctrSetB( opt, run_st );

else if( a_path == "/func/cfg/id" )	ctrSetS( opt, id() );

else if( a_path == "/func/cfg/name" )	ctrSetS( opt, name() );

else if( a_path == "/func/cfg/descr" )	ctrSetS( opt, descr() );

else if( a_path == "/io/io" )

{

XMLNode *n_id	= ctrId(opt,"0");

XMLNode *n_nm	= ctrId(opt,"1");

XMLNode *n_type	= ctrId(opt,"2");

XMLNode *n_mode	= ctrId(opt,"3");

XMLNode *n_hide	= ctrId(opt,"4");

XMLNode *n_def	= ctrId(opt,"5");

//XMLNode *n_vect	= ctrId(opt,"6");

for( int i_io = 0; i_io < ioSize(); i_io++ )

{

ctrSetS(n_id,io(i_io)->id());

ctrSetS(n_nm,io(i_io)->name());

//Make type

if( io(i_io)->type() == IO::String )	ctrSetS(n_type,Mess->I18N("String"));

else if( io(i_io)->type() == IO::Integer )	ctrSetS(n_type,Mess->I18N("Integer"));

else if( io(i_io)->type() == IO::Real )	ctrSetS(n_type,Mess->I18N("Real"));

else if( io(i_io)->type() == IO::Boolean )	ctrSetS(n_type,Mess->I18N("Bool"));

else if( io(i_io)->type() == IO::Vector )	ctrSetS(n_type,Mess->I18N("Vector"));

//Make mode

if( io(i_io)->mode() == IO::Output )	ctrSetS(n_mode,Mess->I18N("Output"));

else if( io(i_io)->mode() == IO::Return )	ctrSetS(n_mode,Mess->I18N("Return"));

else if( io(i_io)->mode() == IO::Input )	ctrSetS(n_mode,Mess->I18N("Input"));

if( io(i_io)->hide() )	ctrSetB(n_hide,true);

else	ctrSetB(n_hide,false);

ctrSetS(n_def,io(i_io)->def());

//ctrSetS(n_vect,io(i_io)->vector());

}

}

else if( a_path == "/test/en" )	ctrSetB( opt, m_tval?true:false );

else if( m_tval && a_path == "/test/tm" )	ctrSetR( opt, m_tval->calcTm() );

else if( m_tval && a_path.substr(0,8) == "/test/io" )

{

for( int i_io = 0; i_io < m_io.size(); i_io++ )

if( TSYS::pathLev(a_path,2) == io(i_io)->id() )

{

if(io(i_io)->type() == IO::String)	ctrSetS( opt, m_tval->getS(i_io) );

else if(io(i_io)->type() == IO::Integer)	ctrSetI( opt, m_tval->getI(i_io) );

else if(io(i_io)->type() == IO::Real)	ctrSetR( opt, m_tval->getR(i_io) );

else if(io(i_io)->type() == IO::Boolean)	ctrSetB( opt, m_tval->getB(i_io) );

}

}

else throw TError(nodePath().c_str(),Mess->I18N("Branch <%s> error!"),a_path.c_str());

}

else if( cmd==TCntrNode::Set )

{

if( a_path == "/func/st/st" )	start(ctrGetB( opt ));

else if( a_path == "/test/en" )

{

if( ctrGetB( opt ) && !m_tval )

{

m_tval = new TValFunc(id()+"_test",this);

m_tval->dimens(true);

}

if( !ctrGetB( opt ) && m_tval ) { delete m_tval; m_tval = NULL; }

}

else if( m_tval && a_path.substr(0,8) == "/test/io" )

{

for( int i_io = 0; i_io < ioSize(); i_io++ )

if( TSYS::pathLev(a_path,2) == io(i_io)->id() )

{

if(io(i_io)->type() == IO::String)	m_tval->setS(i_io, ctrGetS( opt ));

else if(io(i_io)->type() == IO::Integer)	m_tval->setI(i_io, ctrGetI( opt ));

else if(io(i_io)->type() == IO::Real) m_tval->setR(i_io, ctrGetR( opt ));

else if(io(i_io)->type() == IO::Boolean)	m_tval->setB(i_io, ctrGetB( opt ));

}

}

else if( m_tval && a_path == "/test/calc" )	m_tval->calc();

else throw TError(nodePath().c_str(),Mess->I18N("Branch <%s> error!"),a_path.c_str());

}

}

IO::IO( const char *iid, const char *iname, IO::Type itype, IO::Mode imode, const char *idef, bool ihide, const char *ivect )

{

m_id = iid;

m_name = iname;

m_type = itype;

m_mode = imode;

m_hide = ihide;

m_def = idef;

m_vect = ivect;

}

void IO::id( const string &val )

{

owner->preIOCfgChange();

m_id = val;

owner->postIOCfgChange();

}

void IO::name( const string &val )

{

owner->preIOCfgChange();

m_name = val;

owner->postIOCfgChange();

}

void IO::type( Type val )

{

owner->preIOCfgChange();

m_type = val;

owner->postIOCfgChange();

}

void IO::mode( Mode val )

{

owner->preIOCfgChange();

m_mode = val;

owner->postIOCfgChange();

}

void IO::def( const string &val )

{

owner->preIOCfgChange();

m_def = val;

owner->postIOCfgChange();

}

void IO::vector( const string &val )

{

owner->preIOCfgChange();

m_vect = val;

owner->postIOCfgChange();

}

void IO::hide( bool val )

{

owner->preIOCfgChange();

m_hide = val;

owner->postIOCfgChange();

}

//===================================================

//========== TValFunc ===============================

//===================================================

TValFunc::TValFunc( const string &iname, TFunction *ifunc ) : m_name(iname), m_func(NULL), m_dimens(false), tm_calc(0.0)

{

func(ifunc);

}

TValFunc::~TValFunc( )

{

if( m_func ) funcDisConnect();

}

void TValFunc::func( TFunction *ifunc, bool att_det )

{

if( m_func ) funcDisConnect(att_det);

if( ifunc )

{

m_func = ifunc;

if(att_det) m_func->valAtt(this);

for( int i_vl = 0; i_vl < m_func->ioSize(); i_vl++ )

{

SVl val;

val.tp = m_func->io(i_vl)->type();

if( val.tp == IO::String )	val.vl = new string(m_func->io(i_vl)->def());

else if( val.tp == IO::Integer )	val.vl = new int(atoi(m_func->io(i_vl)->def().c_str()));

else if( val.tp == IO::Real )	val.vl = new double(atof(m_func->io(i_vl)->def().c_str()));

else if( val.tp == IO::Boolean )	val.vl = new bool(atoi(m_func->io(i_vl)->def().c_str()));

m_val.push_back(val);

}

}

}

void TValFunc::funcDisConnect( bool det )

{

if( m_func )

{

for( int i_vl = 0; i_vl < m_val.size(); i_vl++ )

if( m_val[i_vl].tp == IO::String )	delete (string *)m_val[i_vl].vl;

else if( m_val[i_vl].tp == IO::Integer )	delete (int *)m_val[i_vl].vl;

else if( m_val[i_vl].tp == IO::Real )	delete (double *)m_val[i_vl].vl;

else if( m_val[i_vl].tp == IO::Boolean )	delete (bool *)m_val[i_vl].vl;

m_val.clear();

if(det)

{

m_func->valDet(this);

m_func = NULL;

}

}

}

int TValFunc::ioId( const string &iid )

{

if( !m_func )	throw TError("ValFnc",Mess->I18N("IO <%s> no present!"),iid.c_str());

return m_func->ioId(iid);

}

void TValFunc::ioList( vector<string> &list )

{

if( !m_func ) throw TError("ValFnc",Mess->I18N("Function no attached!"));

return m_func->ioList(list);

}

int TValFunc::ioSize( )

{

if( !m_func ) throw TError("ValFnc",Mess->I18N("Function no attached!"));

return m_func->ioSize();

}

string TValFunc::getS( unsigned id )

{

if( id >= m_val.size() ) throw TError("ValFnc",Mess->I18N("Id or IO %d error!"),id);

switch(m_val[id].tp)

{

case IO::String:	return *(string *)m_val[id].vl;

case IO::Integer:	return TSYS::int2str(*(int *)m_val[id].vl);

case IO::Real:	return TSYS::real2str(*(double *)m_val[id].vl);

case IO::Boolean:	return TSYS::int2str(*(bool *)m_val[id].vl);

}

return "";

}

int TValFunc::getI( unsigned id )

{

if( id >= m_val.size() ) throw TError("ValFnc",Mess->I18N("Id or IO %d error!"),id);

switch(m_val[id].tp)

{

case IO::String:	return atoi(((string *)m_val[id].vl)->c_str());

case IO::Integer:	return *(int *)m_val[id].vl;

case IO::Real:	return (int)(*(double *)m_val[id].vl);

case IO::Boolean:	return *(bool *)m_val[id].vl;

}

return 0;

}

double TValFunc::getR( unsigned id )

{

if( id >= m_val.size() ) throw TError("ValFnc",Mess->I18N("Id or IO %d error!"),id);

switch(m_val[id].tp)

{

case IO::String:	return atof(((string *)m_val[id].vl)->c_str());

case IO::Integer:	return *(int *)m_val[id].vl;

case IO::Real:	return *(double *)m_val[id].vl;

case IO::Boolean:	return *(bool *)m_val[id].vl;

}

return 0.0;

}

bool TValFunc::getB( unsigned id )

{

if( id >= m_val.size() ) throw TError("ValFnc",Mess->I18N("Id or IO %d error!"),id);

switch(m_val[id].tp)

{

case IO::String:	return atoi(((string *)m_val[id].vl)->c_str());

case IO::Integer:	return *(int *)m_val[id].vl;

case IO::Real:	return *(double *)m_val[id].vl;

case IO::Boolean:	return *(bool *)m_val[id].vl;

}

return false;

}

void TValFunc::setS( unsigned id, const string &val )

{

if( id >= m_val.size() ) throw TError("ValFnc",Mess->I18N("Id or IO %d error!"),id);

switch(m_val[id].tp)

{

case IO::String:	*(string *)m_val[id].vl = val;	break;

case IO::Integer:	*(int *)m_val[id].vl = atoi(val.c_str());	break;

case IO::Real:	*(double *)m_val[id].vl = atof(val.c_str());	break;

case IO::Boolean:	*(bool *)m_val[id].vl = atoi(val.c_str());	break;

}

}

void TValFunc::setI( unsigned id, int val )

{

if( id >= m_val.size() ) throw TError("ValFnc",Mess->I18N("Id or IO %d error!"),id);

switch(m_val[id].tp)

{

case IO::String:	*(string *)m_val[id].vl = TSYS::int2str(val);	break;

case IO::Integer:	*(int *)m_val[id].vl = val;	break;

case IO::Real:	*(double *)m_val[id].vl = val;	break;

case IO::Boolean:	*(bool *)m_val[id].vl = val;	break;

}

}

void TValFunc::setR( unsigned id, double val )

{

if( id >= m_val.size() ) throw TError("ValFnc",Mess->I18N("Id or IO %d error!"),id);

if( isnan(val) ) val = 0.;	//Check for 'Not a Number'

switch(m_val[id].tp)

{

case IO::String:	*(string *)m_val[id].vl = TSYS::real2str(val);	break;

case IO::Integer:	*(int *)m_val[id].vl = (int)val;break;

case IO::Real:	*(double *)m_val[id].vl = val;	break;

case IO::Boolean:	*(bool *)m_val[id].vl = val;	break;

}

}

void TValFunc::setB( unsigned id, bool val )

{

if( id >= m_val.size() ) throw TError("ValFnc",Mess->I18N("Id or IO %d error!"),id);

switch(m_val[id].tp)

{

case IO::String:	*(string *)m_val[id].vl = TSYS::int2str(val);	break;

case IO::Integer:	*(int *)m_val[id].vl = val;	break;

case IO::Real:	*(double *)m_val[id].vl = val;	break;

case IO::Boolean:	*(bool *)m_val[id].vl = val;	break;

}

}

void TValFunc::calc( )

{

if( !m_func || !m_func->startStat() ) return;

if( !m_dimens ) m_func->calc(this);

else

{

unsigned long long t_cnt = SYS->shrtCnt();

m_func->calc(this);

tm_calc = 1.0e6*((double)(SYS->shrtCnt()-t_cnt))/((double)SYS->sysClk());

}

}

void TValFunc::preIOCfgChange()

{

func( NULL, false );

}

void TValFunc::postIOCfgChange()

{

func( m_func, false );

}

Модуль “JavaLikeCalc” підсистеми “Контролери”;

Модуль “JavaLikeCalc” призначено для надання інструменту створення бібліотек функцій та для безпосередніх обчислень на мові програмування високого рівня. Модуль реалізує граматика подібну до мови Java.

Файли у яких реалізовано модуль “JavaLikeCalc” приведені у таблиці 1.

Таблиця 1. Файли модуля "JavaLikeCalk"

Файл	Опис
virtual.h	Визначення корінних об'єктів модуля.
virtual.cpp	Корінні об'єкти модуля.
freelib.h	Визначення об'єкту бібліотеки функції.
freelib.cpp	Об'єкт бібліотеки функцій.
freefunc.h	Визначення об'єкту функції.
freefunc.cpp	Об'єкт функції.
func_analise.ypp	Граматика Java подібної мови (для генератора граматики Bison)

Модуль “JavaLikeCalc” представлено декількома об'єктами(класами). Статичну діаграму об'єктів модуля “JavaLikeCalc” та взаємозв'язки між ними наведено на рис. 2.

Рис. 2. Статична діаграма класів модуля "JavaLikeCalc"

Вміст файлу virtual.h

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#ifndef FREEFUNCLIBS_H

#define FREEFUNCLIBS_H

#include <string>

#include <vector>

#include <tfunctions.h>

#include <tcontrollers.h>

#include "freefunc.h"

using std::string;

using std::vector;

namespace JavaLikeCalc

{

//===================================================================

//================ Constant structure ===============================

//===================================================================

class NConst

{

public:

NConst( const char *inm, double ival ) : name(inm), val(ival) { }

string name;

double val;

};

//===================================================================

//================ Buildin functions structure ======================

//===================================================================

class BFunc

{

public:

BFunc( const char *inm, Reg::Code icd, int iprm ) :

name(inm), code(icd), prm(iprm) { }

string	name;

Reg::Code code;

int prm;

};

//===================================================================

//================ Parameter object =================================

//===================================================================

class Prm : public TParamContr

{

public:

Prm( string name, TTipParam *tp_prm );

void enable();

void disable();

private:

void preDisable(int flag);

//================== Controll functions ========================

void cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd );

void vlSet( TVal &val );

void vlGet( TVal &val );

private:

string &m_dfld;	//Assign data field

TElem v_el; //Values elem

};

//===================================================================

//================ Controller object ================================

//===================================================================

class Contr: public TController, public TValFunc

{

public:

Contr( string name_c, const TBDS::SName &bd, ::TElem *cfgelem );

~Contr();

int period() { return m_per; }

int iterate() { return m_iter; }

private:

void postDisable(int flag);

void load( );

void save( );

void start( );

void stop( );

void enable_( );

void disable_( );

TParamContr *ParamAttach( const string &name, int type );

//================== Controll functions ========================

void cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd );

static void *Task(void *);

private:

bool endrun; // Command for stop task

int &m_per; // calc period ms

int &m_iter;	// iteration number

string	&m_fnc;	// Work function

pthread_t pthr_tsk;	// task pthread header

};

//===================================================================

//================ Type controller object ===========================

//===================================================================

class TipContr : public TTipController

{

public:

TipContr( string src );

~TipContr();

void modLoad( );

void modSave( );

void modStart( );

void modStop( );

TBDS::SName	BD();

TElem &elVal() { return val_el; }

TElem &elLib()	{ return lb_el; }

TElem &elFnc()	{ return fnc_el; }

TElem &elFncIO(){ return fncio_el; }

int &parseRes( ){ return parse_res; }

vector<string> &freeLibList() { return free_libs; }

bool present( const string &lib );

AutoHD<Lib> at( const string &id )

{ return SYS->func().at().at(id); }

//Named constant

NConst *constGet( const char *nm );

//BuildIn functions

BFunc *bFuncGet( const char *nm );

protected:

void cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd );

AutoHD<TCntrNode> ctrAt( const string &a_path );

private:

void postEnable( );

void preDisable(int flag);

TController *ContrAttach( const string &name, const TBDS::SName &bd);

private:

vector<string>	free_libs;

TElem	val_el, lb_el, fnc_el, fncio_el;

TBDS::SName m_bd;

//General parse data

int	parse_res;	//Syntax analisator

vector<NConst> m_const; //Name constant table

vector<BFunc>	m_bfunc;	//Buildin functions

};

extern TipContr *mod;

} //End namespace StatFunc

#endif //FREEFUNCLIBS_H

Вміст файлу virtual.cpp

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#include <signal.h>

#include <sys/time.h>

#include <sys/times.h>

#include <tsys.h>

#include <resalloc.h>

#include <tmess.h>

#include <ttiparam.h>

#include "freelib.h"

#include "freefunc.h"

#include "virtual.h"

//============ Modul info! =====================================================

#define MOD_ID "JavaLikeCalc"

#define MOD_NAME "Java-like based calculator"

#define MOD_TYPE "Controller"

#define VER_TYPE VER_SPC

#define SUB_TYPE "LIB"

#define VERSION "0.8.0"

#define AUTORS "Roman Savochenko"

#define DESCRIPTION "Allow java-like based calculator and function's libraries engine. User can create and modify function and libraries."

#define LICENSE "GPL"

//==============================================================================

JavaLikeCalc::TipContr *JavaLikeCalc::mod;

extern "C"

{

TModule::SAt module( int n_mod )

{

TModule::SAt AtMod;

if(n_mod==0)

{

AtMod.id	= MOD_ID;

AtMod.type = MOD_TYPE;

AtMod.t_ver = VER_TYPE;

}

else

AtMod.id	= "";

return( AtMod );

}

TModule *attach( const TModule::SAt &AtMod, const string &source )

{

JavaLikeCalc::TipContr *self_addr = NULL;

if( AtMod.id == MOD_ID && AtMod.type == MOD_TYPE && AtMod.t_ver == VER_TYPE )

self_addr = JavaLikeCalc::mod = new JavaLikeCalc::TipContr( source );

return ( self_addr );

}

}

using namespace JavaLikeCalc;

//===================== Complex1 functions library =========================

TipContr::TipContr( string src ) : m_bd("","","vLibFunc")

{

mId	= MOD_ID;

mName = MOD_NAME;

mType	= MOD_TYPE;

mVers	= VERSION;

mAutor	= AUTORS;

mDescr	= DESCRIPTION;

mLicense	= LICENSE;

mSource	= src;

parse_res = ResAlloc::resCreate();

}

TipContr::~TipContr()

{

nodeDelAll();

ResAlloc::resDelete(parse_res);

}

void TipContr::preDisable(int flag)

{

//stop();

while( free_libs.size() )

{

owner().owner().func().at().unreg(free_libs[0]);

free_libs.erase(free_libs.begin());

}

}

void TipContr::postEnable( )

{

TModule::postEnable( );

//Controller db structure

fldAdd( new TFld("PRM_BD",I18N("Parameters table"),TFld::String,0,"30","system") );

fldAdd( new TFld("FUNC",I18N("Controller's function (<lib>.<func>)"),TFld::String,0,"20") );

fldAdd( new TFld("PERIOD",I18N("Calc period (ms)"),TFld::Dec,0,"5","1000","0;10000") );

fldAdd( new TFld("ITER",I18N("Iteration number into calc period"),TFld::Dec,0,"2","1","0;99") );

//Controller value db structure

val_el.fldAdd( new TFld("ID",Mess->I18N("IO ID"),TFld::String,FLD_KEY,"10") );

val_el.fldAdd( new TFld("VAL",Mess->I18N("IO value"),TFld::String,0,"20") );

//Add parameter types

int t_prm = tpParmAdd("All","PRM_BD",I18N("Parameters"));

tpPrmAt(t_prm).fldAdd( new TFld("FLD",I18N("Data field"),TFld::String,FLD_NOVAL,"10") );

//Lib's db structure

lb_el.fldAdd( new TFld("ID",I18N("ID"),TFld::String,FLD_KEY,"10") );

lb_el.fldAdd( new TFld("NAME",I18N("Name"),TFld::String,0,"50") );

lb_el.fldAdd( new TFld("DESCR",I18N("Description"),TFld::String,0,"300") );

lb_el.fldAdd( new TFld("BD_TP",I18N("Data base type"),TFld::String,0,"20") );

lb_el.fldAdd( new TFld("BD_NM",I18N("Data base name"),TFld::String,0,"50") );

lb_el.fldAdd( new TFld("BD_TBL",I18N("Data base table"),TFld::String,0,"20") );

//Function's structure

fnc_el.fldAdd( new TFld("ID",I18N("ID"),TFld::String,FLD_KEY,"10") );

fnc_el.fldAdd( new TFld("NAME",I18N("Name"),TFld::String,0,"50") );

fnc_el.fldAdd( new TFld("DESCR",I18N("Description"),TFld::String,0,"300") );

fnc_el.fldAdd( new TFld("FORMULA",I18N("Formula"),TFld::String,0,"1000") );

//Function's IO structure

fncio_el.fldAdd( new TFld("F_ID",I18N("Function ID"),TFld::String,FLD_KEY,"10") );

fncio_el.fldAdd( new TFld("ID",I18N("ID"),TFld::String,FLD_KEY,"10") );

fncio_el.fldAdd( new TFld("NAME",I18N("Name"),TFld::String,0,"50") );

fncio_el.fldAdd( new TFld("TYPE",I18N("Type"),TFld::Dec,0,"1") );

fncio_el.fldAdd( new TFld("MODE",I18N("Mode"),TFld::Dec,0,"1") );

fncio_el.fldAdd( new TFld("DEF",I18N("Default value"),TFld::String,0,"20") );

fncio_el.fldAdd( new TFld("VECT",I18N("Vector"),TFld::String,0,"10") );

fncio_el.fldAdd( new TFld("HIDE",I18N("Hide"),TFld::Bool,0,"1") );

fncio_el.fldAdd( new TFld("POS",I18N("Position"),TFld::Dec,0,"3") );

//Init named constant table

m_const.push_back(NConst("pi",3.14159265358l));

m_const.push_back(NConst("e",2.71828182845l));

//Init buildin functions list

m_bfunc.push_back(BFunc("sin",Reg::FSin,1));

m_bfunc.push_back(BFunc("cos",Reg::FCos,1));

m_bfunc.push_back(BFunc("tan",Reg::FTan,1));

m_bfunc.push_back(BFunc("sinh",Reg::FSinh,1));

m_bfunc.push_back(BFunc("cosh",Reg::FCosh,1));

m_bfunc.push_back(BFunc("tanh",Reg::FTanh,1));

m_bfunc.push_back(BFunc("asin",Reg::FAsin,1));

m_bfunc.push_back(BFunc("acos",Reg::FAcos,1));

m_bfunc.push_back(BFunc("atan",Reg::FAtan,1));

m_bfunc.push_back(BFunc("rand",Reg::FRand,1));

m_bfunc.push_back(BFunc("lg",Reg::FLg,1));

m_bfunc.push_back(BFunc("ln",Reg::FLn,1));

m_bfunc.push_back(BFunc("exp",Reg::FExp,1));

m_bfunc.push_back(BFunc("pow",Reg::FPow,2));

m_bfunc.push_back(BFunc("sqrt",Reg::FSqrt,1));

m_bfunc.push_back(BFunc("abs",Reg::FAbs,1));

m_bfunc.push_back(BFunc("sign",Reg::FSign,1));

m_bfunc.push_back(BFunc("ceil",Reg::FCeil,1));

m_bfunc.push_back(BFunc("floor",Reg::FFloor,1));

}

TController *TipContr::ContrAttach( const string &name, const TBDS::SName &bd )

{

return( new Contr(name,bd,this));

}

bool TipContr::present( const string &lib )

{

for(int i_lb=0; i_lb < free_libs.size(); i_lb++ )

if( free_libs[i_lb] == lib ) return true;

return false;

}

TBDS::SName TipContr::BD()

{

return owner().owner().nameDBPrep(m_bd);

}

void TipContr::modLoad( )

{

try

{

TConfig c_el(&elLib());

AutoHD<TTable> tbl = SYS->db().at().open(BD());

int fld_cnt = 0;

while( SYS->db().at().dataSeek(tbl,nodePath()+"lib/",fld_cnt++,c_el) )

{

string l_id = c_el.cfg("ID").getS();

int f_lb;

for( f_lb = 0; f_lb < free_libs.size(); f_lb++ )

if( free_libs[f_lb] == l_id )	break;

if( f_lb >= free_libs.size() )

{

Lib *lb = new Lib(l_id.c_str(),this);

//*(TConfig *)lb = c_el;

SYS->func().at().reg(lb);

free_libs.push_back(l_id);

}

((Lib &)SYS->func().at().at(l_id).at()).load();

}

if(!tbl.freeStat())

{

tbl.free();

SYS->db().at().close(BD());

}

}catch( TError err ){ Mess->put(err.cat.c_str(),TMess::Error,err.mess.c_str()); }

}

void TipContr::modSave()

{

for( int l_id = 0; l_id < free_libs.size(); l_id++ )

((Lib &)owner().owner().func().at().at(free_libs[l_id]).at()).save();

}

void TipContr::modStart( )

{

//Start functions

for(int i_lb=0; i_lb < free_libs.size(); i_lb++ )

owner().owner().func().at().at(free_libs[i_lb]).at().start(true);

//Enable and start all JavaLike-controllers

vector<string> lst;

list(lst);

for(int i_l=0; i_l<lst.size(); i_l++)

TTipController::at(lst[i_l]).at().start( );

}

void TipContr::modStop( )

{

//Stop and disable all JavaLike-controllers

vector<string> lst;

list(lst);

for(int i_l=0; i_l<lst.size(); i_l++)

TTipController::at(lst[i_l]).at().disable( );

//Stop functions

for(int i_lb=0; i_lb < free_libs.size(); i_lb++ )

owner().owner().func().at().at(free_libs[i_lb]).at().start(false);

}

void TipContr::cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd )

{

if( cmd==TCntrNode::Info )

{

TTipController::cntrCmd_( a_path, opt, cmd ); //Call parent

ctrInsNode("area",1,opt,a_path.c_str(),"/libs",I18N("Functions' Libraries"));

ctrMkNode("list",opt,a_path.c_str(),"/libs/lb",I18N("Libraries"),0664,0,0,"br")->

attr_("idm","1")->attr_("s_com","add,del")->attr_("mode","att")->attr_("br_pref","_lb_");

ctrMkNode("comm",opt,a_path.c_str(),"/libs/load",Mess->I18N("Load"),0550);

ctrMkNode("comm",opt,a_path.c_str(),"/libs/save",Mess->I18N("Save"),0550);

}

else if( cmd==TCntrNode::Get )

{

if( a_path == "/libs/lb" )

{

opt->childClean();

for( unsigned i_a=0; i_a < free_libs.size(); i_a++ )

ctrSetS( opt, owner().owner().func().at().at(free_libs[i_a]).at().name(), free_libs[i_a].c_str() );

}

else TTipController::cntrCmd_( a_path, opt, cmd );

}

else if( cmd==TCntrNode::Set )

{

if( a_path == "/libs/lb" )

{

if( opt->name() == "add" )

{

SYS->func().at().reg(new Lib(opt->attr("id").c_str(),this,opt->text().c_str()));

free_libs.push_back(opt->attr("id"));

}

else if( opt->name() == "del" )

{

SYS->func().at().unreg(opt->attr("id"),1);

for(int i_el = 0; i_el < free_libs.size(); i_el++)

if( free_libs[i_el] == opt->attr("id") )

{

free_libs.erase(free_libs.begin()+i_el);

break;

}

}

}

else if( a_path == "/libs/load" )	modLoad();

else if( a_path == "/libs/save" )	modSave();

else TTipController::cntrCmd_( a_path, opt, cmd );

}

}

AutoHD<TCntrNode> TipContr::ctrAt( const string &a_path )

{

if( a_path.substr(0,4) == "_lb_" )	return owner().owner().func().at().at(TSYS::strEncode(a_path.substr(4),TSYS::PathEl));

else return TTipController::ctrAt(a_path);

}

NConst *TipContr::constGet( const char *nm )

{

for( int i_cst = 0; i_cst < m_const.size(); i_cst++)

if( m_const[i_cst].name == nm ) return &m_const[i_cst];

return NULL;

}

BFunc *TipContr::bFuncGet( const char *nm )

{

for( int i_bf = 0; i_bf < m_bfunc.size(); i_bf++)

if( m_bfunc[i_bf].name == nm ) return &m_bfunc[i_bf];

return NULL;

}

//===================================================================

//================ Controller object ================================

//===================================================================

Contr::Contr( string name_c, const TBDS::SName &bd, ::TElem *cfgelem) :

::TController(name_c, bd, cfgelem), TValFunc(name_c.c_str()), endrun(false),

m_per(cfg("PERIOD").getId()), m_iter(cfg("ITER").getId()), m_fnc(cfg("FUNC").getSd())

{

cfg("PRM_BD").setS(name_c+"_prm");

dimens(true);

}

Contr::~Contr()

{

}

void Contr::postDisable(int flag)

{

if( run_st ) stop();

try

{

if( flag )

{

//Delete IO value's table

bool to_open = false;

if( !((TTipBD &)SYS->db().at().modAt(BD().tp).at()).openStat(BD().bd) )

{

to_open = true;

((TTipBD &)SYS->db().at().modAt(BD().tp).at()).open(BD().bd,false);

}

((TTipBD &)SYS->db().at().modAt(BD().tp).at()).at(BD().bd).at().del(TController::id()+"_val");

if( to_open ) ((TTipBD &)SYS->db().at().modAt(BD().tp).at()).close(BD().bd);

}

}catch(TError err)

{ Mess->put(nodePath().c_str(),TMess::Error,err.mess.c_str()); }

TController::postDisable(flag);

}

void Contr::enable_( )

{

if( !mod->present(TSYS::strSepParse(m_fnc,0,'.')) )

throw TError(nodePath().c_str(),mod->I18N("Functions library <%s> no present. Please, create functions library!"),TSYS::strSepParse(m_fnc,0,'.').c_str());

if( !mod->at(TSYS::strSepParse(m_fnc,0,'.')).at().present(TSYS::strSepParse(m_fnc,1,'.')) )

{

Mess->put(nodePath().c_str(),TMess::Info,mod->I18N("Create new function <%s>."),m_fnc.c_str());

mod->at(TSYS::strSepParse(m_fnc,0,'.')).at().add(TSYS::strSepParse(m_fnc,1,'.').c_str());

}

func( &SYS->func().at().at(TSYS::strSepParse(m_fnc,0,'.')).at().at(TSYS::strSepParse(m_fnc,1,'.')).at() );

try{ load( ); }

catch(TError err){ Mess->put(err.cat.c_str(),TMess::Warning,err.mess.c_str()); }

}

void Contr::disable_( )

{

func(NULL);

}

void Contr::load( )

{

TController::load();

if( func() != NULL )

{

((Func *)func())->load();

//Load values

TConfig cfg(&mod->elVal());

TBDS::SName bd = BD();

bd.tbl = TController::id()+"_val";

AutoHD<TTable> tbl = SYS->db().at().open(bd);

int fld_cnt=0;

while( SYS->db().at().dataSeek(tbl,mod->nodePath()+bd.tbl,fld_cnt++,cfg) )

if( func()->ioId(cfg.cfg("ID").getS()) >= 0 )

setS(func()->ioId(cfg.cfg("ID").getS()),cfg.cfg("VAL").getS());

if( !tbl.freeStat() )

{

tbl.free();

SYS->db().at().close(bd);

}

}

}

void Contr::save( )

{

TController::save();

if( func() != NULL )

{

((Func *)func())->save();

//Save values

TConfig cfg(&mod->elVal());

TBDS::SName val_bd = BD();

val_bd.tbl = TController::id()+"_val";

AutoHD<TTable> tbl = SYS->db().at().open(val_bd,true);

if( !tbl.freeStat() )

{

for( int iio = 0; iio < ioSize(); iio++ )

{

cfg.cfg("ID").setS(func()->io(iio)->id());

cfg.cfg("VAL").setS(getS(iio));

tbl.at().fieldSet(cfg);

}

//Clear VAL

int fld_cnt=0;

while( tbl.at().fieldSeek(fld_cnt++,cfg) )

if( ioId(cfg.cfg("ID").getS()) < 0 )

{ tbl.at().fieldDel(cfg); fld_cnt--; }

tbl.free();

SYS->db().at().close(val_bd);

}

}

}

void Contr::start( )

{

pthread_attr_t pthr_attr;

struct sched_param prior;

TController::start();

if( !run_st )

{

((Func *)func())->start( true );

//Make process task

pthread_attr_init(&pthr_attr);

if(SYS->user() == "root")

{

prior.__sched_priority=10;

pthread_attr_setschedpolicy(&pthr_attr,SCHED_FIFO);

pthread_attr_setschedparam(&pthr_attr,&prior);

Mess->put(nodePath().c_str(),TMess::Info,mod->I18N("Start into realtime mode!"));

}

else pthread_attr_setschedpolicy(&pthr_attr,SCHED_OTHER);

pthread_create(&pthr_tsk,&pthr_attr,Task,this);

pthread_attr_destroy(&pthr_attr);

if( TSYS::eventWait( run_st, true, nodePath()+"start",5) )

throw TError(nodePath().c_str(),mod->I18N("Controller no started!"));

}

}

void Contr::stop( )

{

TController::stop();

if( run_st )

{

endrun = true;

pthread_kill(pthr_tsk, SIGALRM);

if( TSYS::eventWait( run_st, false, nodePath()+"stop",5) )

throw TError(nodePath().c_str(),mod->I18N("Controller no stoped!"));

pthread_join(pthr_tsk, NULL);

}

}

void *Contr::Task(void *contr)

{

int i_sync=0;

struct itimerval mytim; //Interval timer

long time_t1,time_t2,cnt_lost=0;

int frq = sysconf(_SC_CLK_TCK); //Count of system timer n/sek

Contr *cntr = (Contr *)contr;

#if OSC_DEBUG

Mess->put(cntr->nodePath().c_str(),TMess::Debug,mod->I18N("Thread <%d> started!"),getpid() );

#endif

try

{

if(cntr->m_per == 0) return(NULL);

if(cntr->m_iter <= 0) cntr->m_iter = 1;

//Start interval timer

mytim.it_interval.tv_sec = 0; mytim.it_interval.tv_usec = cntr->m_per*1000;

mytim.it_value.tv_sec = 0; mytim.it_value.tv_usec = cntr->m_per*1000;

setitimer(ITIMER_REAL,&mytim,NULL);

cntr->run_st = true; cntr->endrun = false;

time_t1=times(NULL);

while( !cntr->endrun )

{

cntr->calc();

pause();

}

} catch(TError err)

{ Mess->put(err.cat.c_str(),TMess::Error,err.mess.c_str() ); }

//Stop interval timer

mytim.it_interval.tv_sec = mytim.it_interval.tv_usec = 0;

mytim.it_value.tv_sec = mytim.it_value.tv_usec = 0;

setitimer(ITIMER_REAL,&mytim,NULL);

cntr->run_st = false;

return(NULL);

}

TParamContr *Contr::ParamAttach( const string &name, int type )

{

return new Prm(name,&owner().tpPrmAt(type));

}

//======================================================================

//==== Contr

//======================================================================

void Contr::cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd )

{

if( cmd==TCntrNode::Info )

{

TController::cntrCmd_( a_path, opt, cmd );

ctrMkNode("area",opt,a_path.c_str(),"/fnc",mod->I18N("Calcing"));

ctrMkNode("fld",opt,a_path.c_str(),"/fnc/flib",mod->I18N("Use function"),0664,0,0,"str")->

attr_("dest","select")->attr_("select","/fnc/libs");

ctrMkNode("fld",opt,a_path.c_str(),"/fnc/func","",0664,0,0,"str");

ctrMkNode("comm",opt,a_path.c_str(),"/fnc/lnk",mod->I18N("Go to function"),0550,0,0,"lnk");

if( enableStat() )

{

ctrMkNode("fld",opt,a_path.c_str(),"/fnc/clc_tm",mod->I18N("Calc time (mks)"),0444,0,0,"real");

ctrMkNode("table",opt,a_path.c_str(),"/fnc/io",mod->I18N("Data"),0664,0,0)->attr_("s_com","add,del,ins,move")->

attr_("rows","15");

ctrMkNode("list",opt,a_path.c_str(),"/fnc/io/0",Mess->I18N("Id"),0664,0,0,"str");

ctrMkNode("list",opt,a_path.c_str(),"/fnc/io/1",Mess->I18N("Name"),0664,0,0,"str");

ctrMkNode("list",opt,a_path.c_str(),"/fnc/io/2",Mess->I18N("Type"),0664,0,0,"str")->

attr_("idm","1")->attr_("dest","select")->attr_("select","/fnc/tp");

ctrMkNode("list",opt,a_path.c_str(),"/fnc/io/3",Mess->I18N("Mode"),0664,0,0,"str")->

attr_("idm","1")->attr_("dest","select")->attr_("select","/fnc/md");

ctrMkNode("list",opt,a_path.c_str(),"/fnc/io/4",mod->I18N("Value"),0664,0,0,"str");

ctrMkNode("fld",opt,a_path.c_str(),"/fnc/prog",mod->I18N("Programm"),0664,0,0,"str")->

attr_("cols","90")->attr_("rows","10");

}

}

else if( cmd==TCntrNode::Get )

{

if( a_path == "/fnc/flib" )	ctrSetS( opt, TSYS::strSepParse(m_fnc,0,'.') );

else if( a_path == "/fnc/func" )ctrSetS( opt, TSYS::strSepParse(m_fnc,1,'.') );

else if( a_path == "/fnc/libs" )

{

opt->childClean();

for( unsigned i_a=0; i_a < mod->freeLibList().size(); i_a++ )

ctrSetS( opt, SYS->func().at().at(mod->freeLibList()[i_a]).at().name(), mod->freeLibList()[i_a].c_str());

}

else if( a_path == "/fnc/lnk" )	opt->text("d_Functions/d_"+TSYS::strSepParse(m_fnc,0,'.')+"/d_"+TSYS::strSepParse(m_fnc,1,'.') );

else if( enableStat() )

{

if( a_path == "/fnc/clc_tm" )	ctrSetR(opt,calcTm( ));

else if( a_path == "/fnc/io" )

{

XMLNode *n_id	= ctrId(opt,"0");

XMLNode *n_nm	= ctrId(opt,"1");

XMLNode *n_type	= ctrId(opt,"2");

XMLNode *n_mode	= ctrId(opt,"3");

XMLNode *n_val	= ctrId(opt,"4");

for( int id = 0; id < func()->ioSize(); id++ )

{

ctrSetS(n_id,func()->io(id)->id());

ctrSetS(n_nm,func()->io(id)->name());

//Make type

if( func()->io(id)->type() == IO::Integer )	ctrSetS(n_type,"int");

else if( func()->io(id)->type() == IO::Real ) ctrSetS(n_type,"real");

else if( func()->io(id)->type() == IO::Boolean )ctrSetS(n_type,"bool");

else if( func()->io(id)->type() == IO::String ) ctrSetS(n_type,"str");

//Make mode

if( func()->io(id)->mode() == IO::Output ) ctrSetS(n_mode,"out");

else if( func()->io(id)->mode() == IO::Return ) ctrSetS(n_mode,"ret");

else if( func()->io(id)->mode() == IO::Input ) ctrSetS(n_mode,"in");

//Value

ctrSetS(n_val,getS(id));

}

}

else if( a_path == "/fnc/tp" )

{

ctrSetS( opt, Mess->I18N("Real"), "real" );

ctrSetS( opt, Mess->I18N("Integer"), "int" );

ctrSetS( opt, Mess->I18N("Boolean"), "bool" );

ctrSetS( opt, Mess->I18N("String"), "str" );

}

else if( a_path == "/fnc/md" )

{

ctrSetS( opt, Mess->I18N("Input"), "in" );

ctrSetS( opt, Mess->I18N("Output"), "out" );

ctrSetS( opt, Mess->I18N("Return"), "ret" );

}

else if( a_path == "/fnc/prog" ) ctrSetS( opt, ((Func *)func())->prog() );

else TController::cntrCmd_( a_path, opt, cmd );

}

else TController::cntrCmd_( a_path, opt, cmd );

}

else if( cmd==TCntrNode::Set )

{

if( a_path == "/fnc/flib" )	m_fnc = ctrGetS( opt )+"."+TSYS::strSepParse(m_fnc,1,'.');

else if( a_path == "/fnc/func" )m_fnc = TSYS::strSepParse(m_fnc,0,'.')+"."+ctrGetS( opt );

else if( enableStat() )

{

if( a_path == "/fnc/io" )

{

if( opt->name() == "add" ) ((Func *)func())->ioAdd( new IO("new","New IO",IO::Real,IO::Input) );

else if( opt->name() == "ins" ) ((Func *)func())->ioIns( new IO("new","New IO",IO::Real,IO::Input), atoi(opt->attr("row").c_str()) );

else if( opt->name() == "del" ) ((Func *)func())->ioDel( atoi(opt->attr("row").c_str()) );

else if( opt->name() == "move" ) ((Func *)func())->ioMove( atoi(opt->attr("row").c_str()), atoi(opt->attr("to").c_str()) );

else if( opt->name() == "set" )

{

int row = atoi(opt->attr("row").c_str());

int col = atoi(opt->attr("col").c_str());

if( (col == 0 || col == 1) && !opt->text().size() )

throw TError(nodePath().c_str(),"Empty value no valid.");

if( col == 0 )	func()->io(row)->id(ctrGetS(opt));

else if( col == 1 )	func()->io(row)->name(ctrGetS(opt));

else if( col == 2 )

{

if( ctrGetS(opt) == "real" )	func()->io(row)->type(IO::Real);

else if( ctrGetS(opt) == "int" )	func()->io(row)->type(IO::Integer);

else if( ctrGetS(opt) == "bool" )	func()->io(row)->type(IO::Boolean);

else if( ctrGetS(opt) == "str" )	func()->io(row)->type(IO::String);

}

else if( col == 3 )

{

if( ctrGetS(opt) == "in" )	func()->io(row)->mode(IO::Input);

else if( ctrGetS(opt) == "out" )	func()->io(row)->mode(IO::Output);

else if( ctrGetS(opt) == "ret" )	func()->io(row)->mode(IO::Return);

}

else if( col == 4 )	setS(row,ctrGetS(opt));

}

}

else if( a_path == "/fnc/prog" )

{

((Func *)func())->prog(ctrGetS(opt).c_str());

((Func *)func())->progCompile();

}

else TController::cntrCmd_( a_path, opt, cmd );

}

else TController::cntrCmd_( a_path, opt, cmd );

}

}

//======================================================================

//==== Prm

//======================================================================

Prm::Prm( string name, TTipParam *tp_prm ) :

TParamContr(name,tp_prm), v_el(name), m_dfld(cfg("FLD").getSd())

{

vlAttElem(&v_el);

}

void Prm::preDisable(int flag)

{

vlDetElem(&v_el);

TParamContr::preDisable(flag);

}

void Prm::enable()

{

if( enableStat() ) return;

//Init elements

unsigned char flg = FLD_DWR|FLD_DRD;

TFld::Type tp = TFld::String;

int io_id = ((Contr &)owner()).ioId(m_dfld);

if( io_id < 0 ) throw TError(nodePath().c_str(),mod->I18N("Data field not connected."));

if( ((Contr &)owner()).ioMode(io_id) != IO::Input )

flg |= FLD_NWR;

switch( ((Contr &)owner()).ioType(io_id) )

{

case IO::String: tp = TFld::String; break;

case IO::Integer: tp = TFld::Dec; break;

case IO::Real: tp = TFld::Real; break;

case IO::Boolean: tp = TFld::Bool; break;

}

if( !v_el.fldPresent("val") ||

v_el.fldAt(v_el.fldId("val")).type() != tp ||

v_el.fldAt(v_el.fldId("val")).flg() != flg )

{

if(v_el.fldPresent("val")) v_el.fldDel(v_el.fldId("val"));

v_el.fldAdd( new TFld("val",mod->I18N("Value"),tp,flg) );

}

TParamContr::enable();

}

void Prm::disable()

{

if( !enableStat() ) return;

TParamContr::disable();

}

void Prm::vlSet( TVal &val )

{

if( !enableStat() ) return;

try

{

int io_id = ((Contr &)owner()).ioId(m_dfld);

if( io_id < 0 ) disable();

else

{

switch(val.fld().type())

{

case TFld::String:

((Contr &)owner()).setS(io_id,val.getS(NULL,true));

break;

case TFld::Dec:

((Contr &)owner()).setI(io_id,val.getI(NULL,true));

break;

case TFld::Real:

((Contr &)owner()).setR(io_id,val.getR(NULL,true));

break;

case TFld::Bool:

((Contr &)owner()).setB(io_id,val.getB(NULL,true));

break;

}

}

}catch(TError err) { disable(); }

}

void Prm::vlGet( TVal &val )

{

if( !enableStat() ) return;

try

{

int io_id = ((Contr &)owner()).ioId(m_dfld);

if( io_id < 0 ) disable();

else

{

switch(val.fld().type())

{

case TFld::String:

val.setS(((Contr &)owner()).getS(io_id),NULL,true);

break;

case TFld::Dec:

val.setI(((Contr &)owner()).getI(io_id),NULL,true);

break;

case TFld::Real:

val.setR(((Contr &)owner()).getR(io_id),NULL,true);

break;

case TFld::Bool:

val.setB(((Contr &)owner()).getB(io_id),NULL,true);

break;

}

}

}catch(TError err) { disable(); }

}

void Prm::cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd )

{

if( cmd==TCntrNode::Info )

{

TParamContr::cntrCmd_( a_path, opt, cmd );

ctrId(opt,"/prm/cfg/FLD")->attr_("dest","select")->attr_("select","/prm/cfg/FLD_list");

}

else if( cmd==TCntrNode::Get )

{

if( a_path == "/prm/cfg/FLD_list" )

{

vector<string> list;

opt->childClean();

if( ((Contr &)owner()).func( ) )	((Contr &)owner()).ioList(list);

for( unsigned i_a=0; i_a < list.size(); i_a++ )

ctrSetS( opt, ((Contr &)owner()).func()->io(i_a)->name(), list[i_a].c_str() );

}

else TParamContr::cntrCmd_( a_path, opt, cmd );

}

else if( cmd==TCntrNode::Set )

TParamContr::cntrCmd_( a_path, opt, cmd );

}

Вміст файлу freelib.h

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#ifndef FREELIB_H

#define FREELIB_H

#include <string>

#include <vector>

#include <tfunctions.h>

using std::string;

using std::vector;

namespace JavaLikeCalc

{

//Free library

class TipContr;

class Lib : public TConfig, public ::TLibFunc

{

public:

Lib( const char *id, TipContr *own, const char *name = "" );

~Lib();

string name()	{ return m_name; }

string descr()	{ return m_descr; }

void load( );

void save( );

void add( const char *id, const char *name = "" );

void del( const char *id );

void copyFunc( const string &f_id, const string &l_id, const string &to_id, const string &to_name );

TBDS::SName BD();

TipContr &owner();

protected:

void cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd );

void preDisable(int flag);

void postDisable(int flag);

private:

string	&m_name;

string	&m_descr;

string	&m_bd_tp;

string	&m_bd_nm;

string	&m_bd_tbl;

TipContr *m_owner;

};

} //End namespace FreeLib

#endif //FREELIB_H

Вміст файлу freelib.cpp

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#include <tsys.h>

#include <tmess.h>

#include "freefunc.h"

#include "virtual.h"

#include "freelib.h"

using namespace JavaLikeCalc;

//================ Functions library ==================

Lib::Lib( const char *id, TipContr *own, const char *name ) :

TConfig(&own->elLib()), TLibFunc(id), m_owner(own),

m_name(cfg("NAME").getSd()), m_descr(cfg("DESCR").getSd()),

m_bd_tp(cfg("BD_TP").getSd()), m_bd_nm(cfg("BD_NM").getSd()), m_bd_tbl(cfg("BD_TBL").getSd())

{

cfg("ID").setS(id);

m_bd_tbl = string("lib_")+id;

m_name = name;

}

Lib::~Lib()

{

}

void Lib::preDisable(int flag)

{

start(false);

}

void Lib::postDisable(int flag)

{

if( flag )

{

//Delete libraries record

AutoHD<TBDS> bd = owner().owner().owner().db();

bd.at().open(owner().BD()).at().fieldDel(*this);

bd.at().close(owner().BD());

//Delete function's files

bool to_open = false;

if( !((TTipBD &)bd.at().modAt(BD().tp).at()).openStat(BD().bd) )

{

to_open = true;

((TTipBD &)bd.at().modAt(BD().tp).at()).open(BD().bd,false);

}

((TTipBD &)bd.at().modAt(BD().tp).at()).at(BD().bd).at().del(BD().tbl);

((TTipBD &)bd.at().modAt(BD().tp).at()).at(BD().bd).at().del(BD().tbl+"_io");

if( to_open ) ((TTipBD &)bd.at().modAt(BD().tp).at()).close(BD().bd);

}

}

void Lib::load( )

{

AutoHD<TTable> tbl = SYS->db().at().open(owner().BD());

SYS->db().at().dataGet(tbl,mod->nodePath()+"lib/",*this);

if( !tbl.freeStat() )

{

tbl.free();

SYS->db().at().close(owner().BD());

}

//Load functions

TConfig c_el(&owner().elFnc());

tbl = SYS->db().at().open(BD());

int fld_cnt = 0;

while( SYS->db().at().dataSeek(tbl,nodePath()+"fnc/", fld_cnt++,c_el) )

{

string f_id = c_el.cfg("ID").getS();

if( !present(f_id) )

{

Func *n_fnc = new Func(f_id.c_str(),this);

//*(TConfig *)n_fnc = c_el;

reg(n_fnc);

}

((Func &)at(f_id).at()).load();

}

if(!tbl.freeStat())

{

tbl.free();

SYS->db().at().close(BD());

}

}

void Lib::save( )

{

AutoHD<TTable> tbl = SYS->db().at().open(owner().BD(),true);

SYS->db().at().dataSet(tbl,mod->nodePath()+"lib/",*this);

if( !tbl.freeStat() )

{

tbl.free();

SYS->db().at().close(owner().BD());

}

//Save functions

vector<string> f_lst;

list(f_lst);

for( int i_ls = 0; i_ls < f_lst.size(); i_ls++ )

((Func &)at(f_lst[i_ls]).at()).save();

}

void Lib::copyFunc( const string &f_id, const string &l_id, const string &to_id, const string &to_name )

{

string lib = l_id;

string toid = to_id;

string toname = to_name;

if( !present(f_id) )

throw TError(nodePath().c_str(),mod->I18N("Function <%s> no present."),f_id.c_str());

if( !lib.size() )	lib = id();

if( !toid.size() )	toid = at(f_id).at().id();

if( !toname.size() )toname = at(f_id).at().name();

if( !owner().present(lib) )

throw TError(nodePath().c_str(),mod->I18N("Library <%s> no present."),lib.c_str());

if( owner().owner().owner().func().at().at(lib).at().present(toid) )

throw TError(nodePath().c_str(),mod->I18N("Function <%s:%s> already present."),lib.c_str(),toid.c_str());

//Make new function

Func *n_fnc = new Func(toid.c_str(),this);

(*n_fnc) = ((Func&)at(f_id).at());

n_fnc->name(to_name.c_str());

((Lib&)owner().owner().owner().func().at().at(lib).at()).reg(n_fnc);

}

void Lib::add( const char *id, const char *name )

{

reg(new Func(id,this,name));

}

void Lib::del( const char *id )

{

unreg(id);

}

TBDS::SName Lib::BD()

{

return SYS->nameDBPrep(TBDS::SName(m_bd_tp.c_str(),m_bd_nm.c_str(),m_bd_tbl.c_str()));

}

TipContr &Lib::owner()

{

return *m_owner;

}

void Lib::cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd )

{

vector<string> list;

if( cmd==TCntrNode::Info )

{

TLibFunc::cntrCmd_( a_path, opt, cmd ); //Call parent

ctrMkNode("fld",opt,a_path.c_str(),"/lib/cfg/name",Mess->I18N("Name"),0664,0,0,"str");

ctrMkNode("fld",opt,a_path.c_str(),"/lib/cfg/descr",Mess->I18N("Description"),0664,0,0,"str");

if( !SYS->shrtDBNm( ) || m_bd_tp.size() || m_bd_nm.size() )

{

ctrMkNode("fld",opt,a_path.c_str(),"/lib/cfg/bd_tp",mod->I18N("Library BD (module:bd:table)"),0660,0,0,"str")->

attr_("idm","1")->attr_("dest","select")->attr_("select","/lib/cfg/b_mod");

ctrMkNode("fld",opt,a_path.c_str(),"/lib/cfg/bd_nm","",0660,0,0,"str");

ctrMkNode("fld",opt,a_path.c_str(),"/lib/cfg/bd_tbl","",0660,0,0,"str");

}

else ctrMkNode("fld",opt,a_path.c_str(),"/lib/cfg/bd_tbl",mod->I18N("Library table"),0660,0,0,"str");

ctrMkNode("comm",opt,a_path.c_str(),"/lib/cfg/load",Mess->I18N("Load"),0550);

ctrMkNode("comm",opt,a_path.c_str(),"/lib/cfg/save",Mess->I18N("Save"),0550);

ctrMkNode("list",opt,a_path.c_str(),"/func/func",Mess->I18N("Functions"),0664,0,0,"br")->

attr_("idm","1")->attr_("s_com","add,del,edit")->attr_("mode","att")->attr_("br_pref","_");

ctrMkNode("comm",opt,a_path.c_str(),"/func/copy",mod->I18N("Copy function"),0440);

ctrMkNode("fld",opt,a_path.c_str(),"/func/copy/fnc",mod->I18N("Function"),0660,0,0,"str")->

attr_("idm","1")->attr_("dest","select")->attr_("select","/func/func");

ctrMkNode("fld",opt,a_path.c_str(),"/func/copy/lib",mod->I18N("To library"),0660,0,0,"str")->

attr_("idm","1")->attr_("dest","select")->attr_("select","/func/ls_lib");

ctrMkNode("fld",opt,a_path.c_str(),"/func/copy/id",mod->I18N("Name as"),0660,0,0,"str")->attr_("len","10");

ctrMkNode("fld",opt,a_path.c_str(),"/func/copy/nm","",0660,0,0,"str");

}

else if( cmd==TCntrNode::Get )

{

if( a_path == "/lib/cfg/bd_tp" )	ctrSetS(opt,m_bd_tp);

else if( a_path == "/lib/cfg/bd_nm" )	ctrSetS(opt,m_bd_nm);

else if( a_path == "/lib/cfg/bd_tbl" )	ctrSetS(opt,m_bd_tbl);

else if( a_path == "/lib/cfg/b_mod" )

{

opt->childClean();

owner().owner().owner().db().at().modList(list);

ctrSetS( opt, "", "" );

for( unsigned i_a=0; i_a < list.size(); i_a++ )

ctrSetS( opt, owner().owner().owner().db().at().modAt(list[i_a]).at().modName(), list[i_a].c_str() );

}

else if( a_path == "/func/ls_lib" )

{

opt->childClean();

ctrSetS( opt, "", "" );

for( unsigned i_a=0; i_a < owner().freeLibList().size(); i_a++ )

ctrSetS( opt, owner().owner().owner().func().at().at(owner().freeLibList()[i_a]).at().name(),

owner().freeLibList()[i_a].c_str() );

}

else TLibFunc::cntrCmd_( a_path, opt, cmd ); //Call parent

}

else if( cmd==TCntrNode::Set )

{

if( a_path == "/lib/cfg/name" )	m_name	= ctrGetS(opt);

else if( a_path == "/lib/cfg/descr" )	m_descr = ctrGetS(opt);

else if( a_path == "/lib/cfg/bd_tp" )	m_bd_tp	= ctrGetS(opt);

else if( a_path == "/lib/cfg/bd_nm" )	m_bd_nm	= ctrGetS(opt);

else if( a_path == "/lib/cfg/bd_tbl" )	m_bd_tbl= ctrGetS(opt);

else if( a_path == "/func/func" )

{

if( opt->name() == "add" )	reg( new Func(opt->attr("id").c_str(),this,opt->text().c_str()) );

else if( opt->name() == "del" )	chldDel(m_fnc,opt->attr("id"),-1,1);

else if( opt->name() == "edit" )

{

((Func&)at(opt->attr("p_id")).at()).chID(opt->attr("id").c_str());

((Func&)at(opt->attr("id")).at()).name(opt->text().c_str());

((Func&)at(opt->attr("id")).at()).save();

}

}

else if( a_path == "/func/copy" )

copyFunc(ctrGetS(ctrId(opt,"fnc")),ctrGetS(ctrId(opt,"lib")), ctrGetS(ctrId(opt,"id")), ctrGetS(ctrId(opt,"nm")));

else if( a_path == "/lib/cfg/load" )	load();

else if( a_path == "/lib/cfg/save" )	save();

else TLibFunc::cntrCmd_( a_path, opt, cmd ); //Call parent

}

}

Вміст файлу freefunc.h

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#ifndef FREEFUNC_H

#define FREEFUNC_H

#define DEBUG_VM 0

typedef unsigned short int WORD;

typedef unsigned char BYTE;

#include <string>

#include <vector>

#include <deque>

#include <tfunctions.h>

#include <tconfig.h>

using std::string;

using std::vector;

using std::deque;

namespace JavaLikeCalc

{

//Bison parse function

int yyparse( );

//=======================================================

//=========== Using func list element ===================

//=======================================================

class UFunc

{

public:

UFunc( const string &lib, const string &nm, TFunctionS &fsubs ) :

m_lib(lib), m_name(nm)

{

m_fval.func(&fsubs.at(lib).at().at(nm).at());

}

~UFunc( )

{

m_fval.func(NULL);

}

const string &name()	{ return m_name; }

const string &lib()	{ return m_lib; }

TValFunc &valFunc()	{ return m_fval; }

private:

string	m_lib, m_name;

TValFunc	m_fval;

};

//=======================================================

//============ Register =================================

//=======================================================

class Func;

class Reg

{

public:

enum Type

{

Free,	//Free

Bool,	//Boolean

Int,	//Integer

Real,	//Real

String,	//String

Var	//IO variable

};

enum Code //Byte codes

{

End, //[E]: End programm.

MviB,	//[CRB]: Load boolean <B> to register <R>.

MviI,	//[CR____]: Load integer <____> to register <R>.

MviR,	//[CR______]: Load real <______> to register <R>.

MviS,	//[CRn_____]: Load string len <n> to to register <R>.

AssB, //[CRR]: Assign bool from register to register.

AssI,	//[CRR]: Assign integer from register to register.

AssR,	//[CRR]: Assign real from register to register.

AssS,	//[CRR]: Assign string from register to register.

MovB, //[CRR]: Move bool from register to register.

MovI, //[CRR]: Move integer from register to register.

MovR, //[CRR]: Move real from register to register.

MovS, //[CRR]: Move string from register to register.

AddI,	//[CRRR]: Integer add.

AddR, //[CRRR]: Real add.

AddS,	//[CRRR]: String add.

SubI, //[CRRR]: Integer subtract.

SubR, //[CRRR]: Real subtract.

MulI,	//[CRRR]: Integer multiply.

MulR,	//[CRRR]: Real multiply.

DivI,	//[CRRR]: Integer divide.

DivR, //[CRRR]: Real divide.

RstI,	//[CRRR]: Integer divide rest.

BitOr,	//[CRRR]: Integer bit or.

BitAnd,	//[CRRR]: Integer bit and.

BitXor,	//[CRRR]: Integer bit xor.

LOr,	//[CRRR]: Boolean OR.

LAnd,	//[CRRR]: Boolean AND.

LTI,	//[CRRR]: Integer least.

LTR,	//[CRRR]: Real least.

GTI,	//[CRRR]: Integer great.

GTR,	//[CRRR]: Real great.

LEI,	//[CRRR]: Integer least equal.

LER,	//[CRRR]: Real least equal.

GEI,	//[CRRR]: Integer great equal.

GER,	//[CRRR]: Real great equal.

EQI,	//[CRRR]: Integer equal.

EQR,	//[CRRR]: Real equal.

EQS,	//[CRRR]: String equal.

NEI,	//[CRRR]: Integer no equal.

NER,	//[CRRR]: Real no equal.

NES,	//[CRRR]: String no equal.

Not,	//[CRR]: Boolean not.

BitNot,	//[CRR]: Integer bit not.

NegI,	//[CRR]: Negate integer.

NegR, //[CRR]: Negate real.

If,	//[CR00nn]: Construction [if(R) else <00>; <nn>]

FSin,	//[CRR]: Function sine.

FCos,	//[CRR]: Function cosine.

FTan,	//[CRR]: Function tangent.

FSinh,	//[CRR]: Function sine hyperbolic.

FCosh,	//[CRR]: Function cosine hyperbolic.

FTanh,	//[CRR]: Function tangent hyperbolic.

FAsin,	//[CRR]: Function arcsine.

FAcos, //[CRR]: Function arccosine.

FAtan, //[CRR]: Function arctangent.

FRand, //[CRR]: Function randomize.

FLg, //[CRR]: Function decimal logarithm.

FLn,	//[CRR]: Function natural logarithm.

FExp,	//[CRR]: Function exponent.

FPow,	//[CRRR]: Function power.

FSqrt,	//[CRR]: Function sqrt.

FAbs,	//[CRR]: Function absolute.

FSign,	//[CRR]: Function sign.

FCeil,	//[CRR]: Function ceil.

FFloor,	//[CRR]: Function floor.

CProc,	//[CFnR____]: Procedure (R - don't used).

CFunc	//[CFnR____]: Function.

};

union El

{

bool	b_el;	//Boolean for constant and local variable

int i_el; //Integer for constant and local variable

double r_el; //Real for constant and local variable

string	*s_el; //String for constant and local variable

int io;	//IO id for IO variable

};

public:

Reg( ) : m_tp(Free), m_flg(0), m_nm(NULL), m_pos(-1) { }

Reg( int ipos ) : m_tp(Free), m_flg(0), m_nm(NULL), m_pos(ipos) { }

~Reg( )

{

type(Free);

if(m_nm) delete m_nm;

}

Reg &operator=( Reg &irg );

void operator=( bool ivar )	{ type(Bool);	el.b_el = ivar; }

void operator=( int ivar )	{ type(Int);	el.i_el = ivar; }

void operator=( double ivar )	{ type(Real);	el.r_el = ivar; }

void operator=( const string &ivar )	{ type(String);	*el.s_el = ivar;}

void setVar( int ivar )	{ type(Var);	el.io = ivar; }

int pos()	{ return m_pos; }

string name() const;

void name( const char *nm );

Type type( ) const	{ return m_tp; }

Type vType( Func *fnc );

void type( Type tp )

{

if( m_tp == tp ) return;

//Free old type

if( m_tp == String ) delete el.s_el;

//Set new type

if( tp == String ) el.s_el = new string;

m_tp = tp;

}

void free();

bool lock()	{ return m_flg&0x01; }

void lock( bool vl )	{ m_flg = (vl)?m_flg|0x01:m_flg&(~0x01); }

El &val()	{ return el; }

private:

int	m_pos;

string	*m_nm;

char	m_flg;	//Locked register

Type	m_tp;

El	el;

};

class RegW

{

public:

RegW( ) : m_tp(Reg::Free) { }

RegW( const Reg &irg );

~RegW( ) { type(Reg::Free); }

void operator=( bool ivar )	{ type(Reg::Bool);	el.b_el = ivar; }

void operator=( int ivar )	{ type(Reg::Int);	el.i_el = ivar; }

void operator=( double ivar )	{ type(Reg::Real);	el.r_el = ivar; }

void operator=( const string &ivar )	{ type(Reg::String);	*el.s_el = ivar;}

void setVar( int ivar )	{ type(Reg::Var);	el.io = ivar; }

Reg::Type type( ) const	{ return m_tp; }

void type( Reg::Type tp )

{

if( m_tp == tp ) return;

//Free old type

if( m_tp == Reg::String ) delete el.s_el;

//Set new type

if( tp == Reg::String ) el.s_el = new string;

m_tp = tp;

}

Reg::El &val()	{ return el; }

private:

Reg::Type	m_tp;

Reg::El	el;

};

//Function

class Lib;

class Func : public TConfig, public TFunction

{

friend int yylex( );

friend int yyparse( );

friend void yyerror(const char*);

public:

Func( const char *, Lib *own, const char *name = "" );

~Func();

void postDisable(int flag);

Func &operator=(Func &func);

string name()	{ return m_name; }

string descr()	{ return m_descr; }

const string &prog() { return prg_src; }

void name( const char *nm )	{ m_name = nm; }

void descr( const char *dscr )	{ m_descr = dscr; }

void prog( const char *prg )	{ prg_src = prg; }

void start( bool val );

void load( );

void save( );

void del( );

void calc( TValFunc *val );

void chID( const char *id );

Lib &owner();

void preIOCfgChange();

void postIOCfgChange();

//Functins` list functions

int funcGet( const string &lib, const string &name );

UFunc *funcAt( int id )	{ return m_fncs.at(id); }

void funcClear();

//Registers` list functions

int regNew( bool var = false );

int regGet( const char *nm );

Reg *regAt( int id )	{ return m_regs.at(id); }

void regClear();

//Temporary registers` list functions

Reg *regTmpNew( );

void regTmpClean( );

//Parse function

void progCompile();

//Code functions

Reg *cdTypeConv( Reg *opi, Reg::Type tp, bool no_code = false );

Reg *cdMvi( Reg *op, bool no_code = false );

void cdAssign( Reg *rez, Reg *op );

Reg *cdMove( Reg *rez, Reg *op );

Reg *cdBinaryOp( Reg::Code cod, Reg *op1, Reg *op2 );

Reg *cdUnaryOp( Reg::Code cod, Reg *op );

Reg *cdCond( Reg *cond, int p_cmd, int p_else, int p_end, Reg *thn = NULL, Reg *els = NULL);

Reg *cdBldFnc( int f_id, Reg *prm1 = NULL, Reg *prm2 = NULL);

Reg *cdExtFnc( int f_id, int p_cnt, bool proc = false );

//Variable access

bool getValB( TValFunc *io, RegW &rg );

int getValI( TValFunc *io, RegW &rg );

double getValR( TValFunc *io, RegW &rg );

string getValS( TValFunc *io, RegW &rg );

void setValB( TValFunc *io, RegW &rg, bool val );

void setValI( TValFunc *io, RegW &rg, int val );

void setValR( TValFunc *io, RegW &rg, double val );

void setValS( TValFunc *io, RegW &rg, const string &val );

//IO operations

void ioAdd( IO *io )	{ TFunction::ioAdd(io); }

void ioIns( IO *io, int pos )	{ TFunction::ioIns(io,pos); }

void ioDel( int pos )	{ TFunction::ioDel(pos); }

void ioMove( int pos, int to )	{ TFunction::ioMove(pos,to); }

protected:

void cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd );

void loadIO( );

void saveIO( );

void delIO( );

void exec( TValFunc *val, RegW *reg, const BYTE *cprg );

private:

string	&m_name;

string	&m_descr;

string	&prg_src;

Lib	*m_owner;

bool	be_start;	//Change structure check

int	calc_res;

//Parser's data

string prg; //Build prog

int la_pos; //LA position

string p_err; //Parse error

vector<UFunc*> m_fncs; //Work functions list

vector<Reg*> m_regs; //Work registers list

vector<Reg*> m_tmpregs;	//Constant temporary list

deque<Reg*>	f_prmst;	//Function's parameters stack

int &parse_res;

};

extern Func *p_fnc;

} //End namespace StatFunc

#endif //FREEFUNC_H

Вміст файлу freefunc.cpp

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#include <math.h>

#include <tsys.h>

#include <resalloc.h>

#include <tmess.h>

#include "virtual.h"

#include "freelib.h"

#include "freefunc.h"

using namespace JavaLikeCalc;

Func *JavaLikeCalc::p_fnc;

//================== Function ========================

Func::Func( const char *id, Lib *own, const char *name ) :

TConfig(&mod->elFnc()), TFunction(id), m_owner(own), parse_res(mod->parseRes( )),

m_name(cfg("NAME").getSd()), m_descr(cfg("DESCR").getSd()), prg_src(cfg("FORMULA").getSd())

{

cfg("ID").setS(id);

m_name = name;

if( !m_name.size() ) m_name = id;

calc_res = ResAlloc::resCreate();

}

Func::~Func( )

{

start(false);

ResAlloc::resDelete(calc_res);

}

void Func::postDisable(int flag)

{

if( flag )

try{ del( ); }

catch(TError err)

{ Mess->put(err.cat.c_str(),TMess::Error,err.mess.c_str()); }

}

Func &Func::operator=(Func &func)

{

//======== Set name ============

*(TConfig *)this = (TConfig&)func;

if( m_id.empty() )	m_id = cfg("ID").getS();

else	cfg("ID").setS(m_id);

//======== Copy IO =============

//Clear current IO

while( ioSize() ) ioDel(0);

//Make new IO

for( int i_io = 0; i_io < func.ioSize(); i_io++ )

ioAdd( new IO( func.io(i_io)->id().c_str(), func.io(i_io)->name().c_str(),

func.io(i_io)->type(), func.io(i_io)->mode(),

func.io(i_io)->def().c_str(), func.io(i_io)->hide(),

func.io(i_io)->vector().c_str() ) );

}

Lib &Func::owner()

{

return *m_owner;

}

void Func::chID( const char *iid )

{

if( owner().present(iid) )

throw TError(nodePath().c_str(),mod->I18N("Rename error. Function <%s> already present."),iid);

del();

//Set new ID

m_id = iid;

cfg("ID").setS(m_id);

//Save new function

save();

}

void Func::load( )

{

AutoHD<TTable> tbl = SYS->db().at().open(owner().BD());

SYS->db().at().dataGet(tbl,owner().nodePath()+"fnc/",*this);

if( !tbl.freeStat() )

{

tbl.free();

SYS->db().at().close(owner().BD());

}

loadIO( );

}

void Func::loadIO( )

{

TConfig cfg(&mod->elFncIO());

TBDS::SName io_bd = owner().BD();

io_bd.tbl += "_io";

AutoHD<TTable> tbl = SYS->db().at().open(io_bd);

int fld_cnt=0;

vector<int>	u_pos;

while( SYS->db().at().dataSeek(tbl,owner().nodePath()+"fnc_io/",fld_cnt++,cfg) )

if( cfg.cfg("F_ID").getS() == id() )

{

string sid = cfg.cfg("ID").getS();

//Calc insert position

int pos = cfg.cfg("POS").getI();

int i_ps;

for( i_ps = 0; i_ps < u_pos.size(); i_ps++ )

if( u_pos[i_ps] > pos )	break;

u_pos.insert(u_pos.begin()+i_ps,pos);

if( ioId(sid) < 0 )

ioIns( new IO(sid.c_str(),"",IO::Real,IO::Input), i_ps );

int id = ioId(sid);

//Set values

io(id)->name(cfg.cfg("NAME").getS());

io(id)->type((IO::Type)cfg.cfg("TYPE").getI());

io(id)->mode((IO::Mode)cfg.cfg("MODE").getI());

io(id)->def(cfg.cfg("DEF").getS());

io(id)->vector(cfg.cfg("VECT").getS());

io(id)->hide(cfg.cfg("HIDE").getB());

}

if( !tbl.freeStat() )

{

tbl.free();

SYS->db().at().close(io_bd);

}

}

void Func::save( )

{

AutoHD<TTable> tbl = SYS->db().at().open(owner().BD(),true);

SYS->db().at().dataSet(tbl,owner().nodePath()+"fnc/",*this);

if( !tbl.freeStat() )

{

tbl.free();

SYS->db().at().close(owner().BD());

}

//Save io config

saveIO();

}

void Func::saveIO( )

{

TConfig cfg(&mod->elFncIO());

TBDS::SName io_bd = owner().BD();

io_bd.tbl += "_io";

AutoHD<TTable> tbl = SYS->db().at().open(io_bd,true);

if( tbl.freeStat() ) return;

//Save allow IO

cfg.cfg("F_ID").setS(id());

for( int i_io = 0; i_io < ioSize(); i_io++ )

{

cfg.cfg("ID").setS(io(i_io)->id());

cfg.cfg("NAME").setS(io(i_io)->name());

cfg.cfg("TYPE").setI(io(i_io)->type());

cfg.cfg("MODE").setI(io(i_io)->mode());

cfg.cfg("DEF").setS(io(i_io)->def());

cfg.cfg("VECT").setS(io(i_io)->vector());

cfg.cfg("HIDE").setB(io(i_io)->hide());

cfg.cfg("POS").setI(i_io);

tbl.at().fieldSet(cfg);

}

//Clear IO

int fld_cnt=0;

while( tbl.at().fieldSeek(fld_cnt++,cfg) )

if( cfg.cfg("F_ID").getS() == id() && ioId(cfg.cfg("ID").getS()) < 0 )

{ tbl.at().fieldDel(cfg); fld_cnt--; }

tbl.free();

SYS->db().at().close(io_bd);

}

void Func::del( )

{

SYS->db().at().open(owner().BD()).at().fieldDel(*this);

SYS->db().at().close(owner().BD());

//Delete io from DB

delIO();

}

void Func::delIO( )

{

TConfig cfg(&mod->elFncIO());

int fld_cnt=0;

TBDS::SName io_bd = owner().BD();

io_bd.tbl += "_io";

AutoHD<TTable> tbl = SYS->db().at().open(io_bd);

while( tbl.at().fieldSeek(fld_cnt++,cfg) )

if( cfg.cfg("F_ID").getS() == id() )

{ tbl.at().fieldDel(cfg); fld_cnt--; }

tbl.free();

SYS->db().at().close(io_bd);

}

void Func::preIOCfgChange()

{

be_start = startStat();

if( be_start )

{

start(false);

if( m_tval ) { delete m_tval; m_tval = NULL; }

}

TFunction::preIOCfgChange();

}

void Func::postIOCfgChange()

{

if( be_start ) start(true);

TFunction::postIOCfgChange();

}

void Func::start( bool val )

{

//if( run_st == val )	return;

if( val )

{

//Start calc

progCompile( );

run_st = true;

}

else

{

if( m_tval ) { delete m_tval; m_tval = NULL; }

//Stop calc

ResAlloc res(calc_res,true);

prg = "";

regClear();

regTmpClean( );

funcClear();

run_st = false;

}

}

void Func::progCompile()

{

ResAlloc res(parse_res,true);

ResAlloc res1(calc_res,true);

p_fnc = this;	//Parse func

p_err = "";	//Clear error messages

la_pos = 0;	//LA position

prg = "";	//Clear programm

regClear();	//Clear registers list

regTmpClean( );	//Clear temporary registers list

funcClear();	//Clear functions list

if( yyparse( ) )

{

prg = "";

regClear();

regTmpClean( );

funcClear();

run_st = false;

throw TError(nodePath().c_str(),p_err.c_str());

}

regTmpClean( );

}

int Func::funcGet( const string &lib, const string &name )

{

for( int i_fnc = 0; i_fnc < m_fncs.size(); i_fnc++ )

if( m_fncs[i_fnc]->lib() == lib && m_fncs[i_fnc]->name() == name )

return i_fnc;

if( !SYS->func().at().present(lib) ||

!SYS->func().at().at(lib).at().present(name) )

return -1;

m_fncs.push_back(new UFunc(lib,name,SYS->func().at()));

return m_fncs.size()-1;

}

void Func::funcClear()

{

for( int i_fnc = 0; i_fnc < m_fncs.size(); i_fnc++ )

delete m_fncs[i_fnc];

m_fncs.clear();

}

int Func::regNew( bool var )

{

//Get new register

int i_rg = m_regs.size();

if( !var )

for( i_rg = 0; i_rg < m_regs.size(); i_rg++ )

if( !m_regs[i_rg]->lock() && m_regs[i_rg]->type() == Reg::Free )

break;

if( i_rg >= m_regs.size() ) m_regs.push_back(new Reg(i_rg));

return i_rg;

}

int Func::regGet( const char *nm )

{

//Check allow registers

for( int i_rg = 0; i_rg < m_regs.size(); i_rg++ )

if( m_regs[i_rg]->name() == nm )

return i_rg;

return -1;

}

void Func::regClear()

{

for( int i_rg = 0; i_rg < m_regs.size(); i_rg++ )

delete m_regs[i_rg];

m_regs.clear();

}

Reg *Func::regTmpNew( )

{

int i_rg;

for( i_rg = 0; i_rg < m_tmpregs.size(); i_rg++ )

if( m_tmpregs[i_rg]->type() == Reg::Free )

break;

if( i_rg >= m_tmpregs.size() ) m_tmpregs.push_back(new Reg());

return m_tmpregs[i_rg];

}

void Func::regTmpClean( )

{

for( int i_rg = 0; i_rg < m_tmpregs.size(); i_rg++ )

delete m_tmpregs[i_rg];

m_tmpregs.clear();

}

Reg *Func::cdMvi( Reg *op, bool no_code )

{

if( op->pos() >= 0 ) return op;	//Already load

int r_id = p_fnc->regNew( );

Reg *rez = regAt(r_id);

*rez = *op;

op->free();

if( no_code ) return rez;

switch(rez->type())

{

case Reg::Free:

throw TError(nodePath().c_str(),mod->I18N("Variable <%s> is used but undefined"),rez->name().c_str());

case Reg::Bool:

prg+=(BYTE)Reg::MviB;

prg+=(BYTE)rez->pos();

prg+=(BYTE)rez->val().b_el;

break;

case Reg::Int:

prg+=(BYTE)Reg::MviI;

prg+=(BYTE)rez->pos();

prg.append(((char *)&rez->val().i_el),sizeof(int));

break;

case Reg::Real:

prg+=(BYTE)Reg::MviR;

prg+=(BYTE)rez->pos();

prg.append(((char *)&rez->val().r_el),sizeof(double));

break;

case Reg::String:

prg+=(BYTE)Reg::MviS;

prg+=(BYTE)rez->pos();

prg+=(BYTE)rez->val().s_el->size();

prg+= *rez->val().s_el;

break;

}

return rez;

}

Reg *Func::cdTypeConv( Reg *op, Reg::Type tp, bool no_code )

{

Reg *rez = op;

if( rez->pos() < 0 )

{

if( tp != rez->vType(this) )

switch(tp)

{

case Reg::Bool:

switch(rez->vType(this))

{

case Reg::Int:

*rez = (bool)rez->val().i_el;

break;

case Reg::Real:

*rez = (bool)rez->val().r_el;

break;

case Reg::String:

*rez = (bool)atoi(rez->val().s_el->c_str());

break;

}	break;

case Reg::Int:

switch(rez->vType(this))

{

case Reg::Bool:

*rez = (int)rez->val().b_el;

break;

case Reg::Real:

*rez = (int)rez->val().r_el;

break;

case Reg::String:

*rez = atoi(rez->val().s_el->c_str());

break;

}

break;

case Reg::Real:

switch(rez->vType(this))

{

case Reg::Bool:

*rez = (double)rez->val().b_el;

break;

case Reg::Int:

*rez = (double)rez->val().i_el;

break;

case Reg::String:

*rez = atof(rez->val().s_el->c_str());

break;

}

break;

case Reg::String:

switch(rez->vType(this))

{

case Reg::Bool:

*rez = TSYS::int2str(rez->val().b_el);

break;

case Reg::Int:

*rez = TSYS::int2str(rez->val().i_el);

break;

case Reg::Real:

*rez = TSYS::real2str(rez->val().r_el);

break;

}

break;

}

if(!no_code) rez = cdMvi(rez);

}

return rez;

}

void Func::cdAssign( Reg *rez, Reg *op )

{

op = cdTypeConv(op,rez->vType(this));

switch(rez->vType(this))

{

case Reg::Bool: prg+=(BYTE)Reg::AssB; break;

case Reg::Int:	prg+=(BYTE)Reg::AssI;	break;

case Reg::Real:	prg+=(BYTE)Reg::AssR;	break;

case Reg::String:	prg+=(BYTE)Reg::AssS;	break;

}

prg+=(BYTE)rez->pos();

prg+=(BYTE)op->pos();

//Free temp operands

op->free();

}

Reg *Func::cdMove( Reg *rez, Reg *op )

{

Reg *rez_n=rez;

op = cdMvi( op );

if( rez_n == NULL ) rez_n = regAt(regNew());

rez_n = cdMvi( rez_n, true );

rez_n->type(op->vType(this));

switch(rez_n->vType(this))

{

case Reg::Bool: prg+=(BYTE)Reg::MovB; break;

case Reg::Int: prg+=(BYTE)Reg::MovI; break;

case Reg::Real: prg+=(BYTE)Reg::MovR; break;

case Reg::String: prg+=(BYTE)Reg::MovS; break;

}

prg+=(BYTE)rez_n->pos();

prg+=(BYTE)op->pos();

//Free temp operands

op->free();

return rez_n;

}

Reg *Func::cdBinaryOp( Reg::Code cod, Reg *op1, Reg *op2 )

{

//Check allowing type operations

switch(op1->vType(this))

{

case Reg::String:

switch(cod)

{

case Reg::SubI:

case Reg::MulI:

case Reg::DivI:

case Reg::RstI:

case Reg::BitOr:

case Reg::BitAnd:

case Reg::BitXor:

case Reg::LOr:

case Reg::LAnd:

case Reg::LTI:

case Reg::GTI:

case Reg::LEI:

case Reg::GEI:

throw TError(nodePath().c_str(),mod->I18N("Operation %d no support string type"),cod);

}

}

//Check allow the buildin calc and calc

if( op1->pos() < 0 && op2->pos() < 0 )

{

op2 = cdTypeConv( op2, op1->vType(this), true);

switch(op1->vType(this))

{

case Reg::Int:

switch(cod)

{

case Reg::AddI: *op1 = op1->val().i_el + op2->val().i_el;	break;

case Reg::SubI: *op1 = op1->val().i_el - op2->val().i_el;	break;

case Reg::MulI: *op1 = op1->val().i_el * op2->val().i_el;	break;

case Reg::DivI: *op1 = op1->val().i_el / op2->val().i_el;	break;

case Reg::RstI: *op1 = op1->val().i_el % op2->val().i_el;	break;

case Reg::BitOr: *op1 = op1->val().i_el | op2->val().i_el;	break;

case Reg::BitAnd: *op1 = op1->val().i_el & op2->val().i_el;	break;

case Reg::BitXor: *op1 = op1->val().i_el ^ op2->val().i_el; break;

case Reg::LOr: *op1 = op1->val().i_el || op2->val().i_el;	break;

case Reg::LAnd: *op1 = op1->val().i_el && op2->val().i_el;	break;

case Reg::LTI: *op1 = op1->val().i_el < op2->val().i_el;	break;

case Reg::GTI: *op1 = op1->val().i_el > op2->val().i_el;	break;

case Reg::LEI: *op1 = op1->val().i_el <= op2->val().i_el;	break;

case Reg::GEI: *op1 = op1->val().i_el >= op2->val().i_el;	break;

case Reg::EQI: *op1 = op1->val().i_el == op2->val().i_el;	break;

case Reg::NEI: *op1 = op1->val().i_el != op2->val().i_el;	break;

}

break;

case Reg::Real:

switch(cod)

{

case Reg::AddI: *op1 = op1->val().r_el + op2->val().r_el;	break;

case Reg::SubI: *op1 = op1->val().r_el - op2->val().r_el;	break;

case Reg::MulI: *op1 = op1->val().r_el * op2->val().r_el;	break;

case Reg::DivI: *op1 = op1->val().r_el / op2->val().r_el;	break;

case Reg::BitOr: *op1 = (int)op1->val().r_el | (int)op2->val().r_el; break;

case Reg::BitAnd: *op1 = (int)op1->val().r_el & (int)op2->val().r_el; break;

case Reg::BitXor: *op1 = (int)op1->val().i_el ^ (int)op2->val().i_el; break;

case Reg::LOr: *op1 = op1->val().r_el || op2->val().r_el; break;

case Reg::LAnd: *op1 = op1->val().r_el && op2->val().r_el; break;

case Reg::LTI: *op1 = op1->val().r_el < op2->val().r_el;	break;

case Reg::GTI: *op1 = op1->val().r_el > op2->val().r_el;	break;

case Reg::LEI: *op1 = op1->val().r_el <= op2->val().r_el;	break;

case Reg::GEI: *op1 = op1->val().r_el >= op2->val().r_el;	break;

case Reg::EQI: *op1 = op1->val().r_el == op2->val().r_el;	break;

case Reg::NEI: *op1 = op1->val().r_el != op2->val().r_el;	break;

}

break;

case Reg::Bool:

switch(cod)

{

case Reg::AddI: *op1 = op1->val().b_el + op2->val().b_el; break;

case Reg::SubI: *op1 = op1->val().b_el - op2->val().b_el; break;

case Reg::MulI: *op1 = op1->val().b_el * op2->val().b_el; break;

case Reg::DivI: *op1 = op1->val().b_el / op2->val().b_el; break;

case Reg::RstI: *op1 = op1->val().b_el % op2->val().b_el; break;

case Reg::BitOr: *op1 = op1->val().b_el | op2->val().b_el; break;

case Reg::BitAnd: *op1 = op1->val().b_el & op2->val().b_el; break;

case Reg::BitXor: *op1 = op1->val().b_el ^ op2->val().b_el; break;

case Reg::LOr: *op1 = op1->val().b_el || op2->val().b_el; break;

case Reg::LAnd: *op1 = op1->val().b_el && op2->val().b_el; break;

case Reg::LTI: *op1 = op1->val().b_el < op2->val().b_el;	break;

case Reg::GTI: *op1 = op1->val().b_el > op2->val().b_el;	break;

case Reg::LEI: *op1 = op1->val().b_el <= op2->val().b_el;	break;

case Reg::GEI: *op1 = op1->val().b_el >= op2->val().b_el;	break;

case Reg::EQI: *op1 = op1->val().b_el == op2->val().b_el;	break;

case Reg::NEI: *op1 = op1->val().b_el != op2->val().b_el;	break;

}

case Reg::String:

switch(cod)

{

case Reg::AddI: *op1->val().s_el += *op2->val().s_el;	break;

case Reg::EQI: *op1 = *op1->val().s_el == *op2->val().s_el;	break;

case Reg::NEI: *op1 = *op1->val().s_el != *op2->val().s_el;	break;

}

break;

}

return op1;

}

//Make operation cod

//Prepare operands

op1 = cdMvi( op1 );

Reg::Type op1_tp = op1->vType(this);

int op1_pos = op1->pos();

op2 = cdTypeConv(op2,op1_tp);

int op2_pos = op2->pos();

op1->free();

op2->free();

//Prepare rezult

Reg *rez = regAt(regNew());

rez->type(op1_tp);

//Add code

switch(op1_tp)

{

case Reg::Bool:

case Reg::Int:

switch(cod)

{

case Reg::AddI:	prg+=(BYTE)Reg::AddI; break;

case Reg::SubI: prg+=(BYTE)Reg::SubI; break;

case Reg::MulI: prg+=(BYTE)Reg::MulI;	break;

case Reg::DivI: prg+=(BYTE)Reg::DivI;	break;

case Reg::RstI: prg+=(BYTE)Reg::RstI;	break;

case Reg::BitOr: prg+=(BYTE)Reg::BitOr;	break;

case Reg::BitAnd: prg+=(BYTE)Reg::BitAnd; break;

case Reg::BitXor: prg+=(BYTE)Reg::BitXor; break;

case Reg::LOr: prg+=(BYTE)Reg::LOr; break;

case Reg::LAnd: prg+=(BYTE)Reg::LAnd; break;

case Reg::LTI:	prg+=(BYTE)Reg::LTI;	break;

case Reg::GTI:	prg+=(BYTE)Reg::GTI;	break;

case Reg::LEI:	prg+=(BYTE)Reg::LEI;	break;

case Reg::GEI:	prg+=(BYTE)Reg::GEI;	break;

case Reg::EQI:	prg+=(BYTE)Reg::EQI;	break;

case Reg::NEI:	prg+=(BYTE)Reg::NEI;	break;

}

break;

case Reg::Real:

switch(cod)

{

case Reg::AddI:	prg+=(BYTE)Reg::AddR; break;

case Reg::SubI: prg+=(BYTE)Reg::SubR; break;

case Reg::MulI: prg+=(BYTE)Reg::MulR;	break;

case Reg::DivI: prg+=(BYTE)Reg::DivR;	break;

case Reg::BitOr: prg+=(BYTE)Reg::BitOr; break;

case Reg::BitAnd: prg+=(BYTE)Reg::BitAnd; break;

case Reg::BitXor: prg+=(BYTE)Reg::BitXor; break;

case Reg::LOr: prg+=(BYTE)Reg::LOr; break;

case Reg::LAnd: prg+=(BYTE)Reg::LAnd; break;

case Reg::LTI:	prg+=(BYTE)Reg::LTR;	break;

case Reg::GTI:	prg+=(BYTE)Reg::GTR;	break;

case Reg::LEI:	prg+=(BYTE)Reg::LER;	break;

case Reg::GEI:	prg+=(BYTE)Reg::GER;	break;

case Reg::EQI:	prg+=(BYTE)Reg::EQR;	break;

case Reg::NEI:	prg+=(BYTE)Reg::NER;	break;

}

break;

case Reg::String:

switch(cod)

{

case Reg::AddI:	prg+=(BYTE)Reg::AddS; break;

case Reg::EQI:	prg+=(BYTE)Reg::EQS;	break;

case Reg::NEI:	prg+=(BYTE)Reg::NES;	break;

}

break;

}

prg+=(BYTE)rez->pos();

prg+=(BYTE)op1_pos;

prg+=(BYTE)op2_pos;

return rez;

}

Reg *Func::cdUnaryOp( Reg::Code cod, Reg *op )

{

//Check allowing type operations

switch(op->type())

{

case Reg::String:

switch(cod)

{

case Reg::Not:

case Reg::BitNot:

case Reg::NegI:

throw TError(nodePath().c_str(),mod->I18N("Operation %d no support string type"),cod);

}

}

//Check allow the buildin calc and calc

if( op->pos() < 0 )

{

switch(op->vType(this))

{

case Reg::Int:

switch(cod)

{

case Reg::Not:	*op = !op->val().i_el;	break;

case Reg::BitNot:	*op = ~op->val().i_el;	break;

case Reg::NegI:	*op = -op->val().i_el;	break;

}

break;

case Reg::Real:

switch(cod)

{

case Reg::Not:	*op = !op->val().r_el;	break;

case Reg::BitNot:	*op = ~(int)op->val().r_el;	break;

case Reg::NegI:	*op = -op->val().r_el;	break;

}

break;

case Reg::Bool:

switch(cod)

{

case Reg::Not:	*op = !op->val().b_el;	break;

case Reg::BitNot:	*op = ~op->val().b_el;	break;

case Reg::NegI:	*op = -op->val().b_el;	break;

}

}

return op;

}

//=========== Make operation cod =================

//Prepare operand

op = cdMvi( op );

Reg::Type op_tp = op->vType(this);

int op_pos = op->pos();

op->free();

//Prepare rezult

Reg *rez = regAt(regNew());

rez->type(op->vType(this));

//Add code

switch(op_tp)

{

case Reg::Bool:

case Reg::Int:

switch(cod)

{

case Reg::Not:	prg+=(BYTE)Reg::Not; break;

case Reg::BitNot:	prg+=(BYTE)Reg::BitNot; break;

case Reg::NegI:	prg+=(BYTE)Reg::NegI; break;

}

break;

case Reg::Real:

switch(cod)

{

case Reg::Not:	prg+=(BYTE)Reg::Not; break;

case Reg::BitNot:	prg+=(BYTE)Reg::BitNot; break;

case Reg::NegI:	prg+=(BYTE)Reg::NegR; break;

}

break;

}

prg+=(BYTE)rez->pos();

prg+=(BYTE)op_pos;

return rez;

}

Reg *Func::cdCond( Reg *cond, int p_cmd, int p_else, int p_end, Reg *thn, Reg *els )

{

Reg *rez = NULL;

int a_sz = sizeof(WORD);

string cd_tmp;

//Mvi cond register (insert to programm)

cd_tmp = prg.substr(p_cmd);

prg.erase(p_cmd);

cond = cdMvi(cond);

p_else+=prg.size()-p_cmd;

p_end+=prg.size()-p_cmd;

p_cmd=prg.size();

prg+=cd_tmp;

int p_cond = cond->pos(); cond->free();

if( thn != NULL && els != NULL )

{

//Add Move command to "then" end (insert to programm)

cd_tmp = prg.substr(p_else-1);	//-1 pass end command

prg.erase(p_else-1);

thn = cdMvi( thn );

rez = cdMove(NULL,thn);

p_end+=prg.size()-p_else+1;

p_else = prg.size()+1;

prg+=cd_tmp;

//Add Move command to "else" end (insert to programm)

cd_tmp = prg.substr(p_end-1); //-1 pass end command

prg.erase(p_end-1);

els = cdMvi( els );

cdMove(rez,els);

p_end = prg.size()+1;

prg+=cd_tmp;

}

//Make apropos adress

p_else -= p_cmd;

p_end -= p_cmd;

prg[p_cmd+1] = (BYTE)p_cond;

prg.replace(p_cmd+2,a_sz,((char *)&p_else),a_sz);

prg.replace(p_cmd+2+a_sz,a_sz,((char *)&p_end),a_sz);

return rez;

}

Reg *Func::cdBldFnc( int f_cod, Reg *prm1, Reg *prm2 )

{

Reg *rez;

int p1_pos=-1, p2_pos=-1;

if( (prm1 && prm1->vType(this) == Reg::String) ||

(prm2 && prm2->vType(this) == Reg::String) )

throw TError(nodePath().c_str(),mod->I18N("Buildin functions no support string type"));

//Free parameter's registers

if( prm1 )	{ prm1 = cdMvi( prm1 ); p1_pos = prm1->pos(); }

if( prm2 )	{ prm2 = cdMvi( prm2 ); p2_pos = prm2->pos(); }

if( prm1 )	prm1->free();

if( prm2 )	prm2->free();

//Get rezult register

rez = regAt(regNew());

rez->type(Reg::Real);

//Make code

prg+=(BYTE)f_cod;

prg+=(BYTE)rez->pos();

if( p1_pos >= 0 ) prg+=(BYTE)p1_pos;

if( p2_pos >= 0 ) prg+=(BYTE)p2_pos;

return rez;

}

Reg *Func::cdExtFnc( int f_id, int p_cnt, bool proc )

{

int r_pos;	//Return function's position

Reg *rez = NULL;

deque<int> p_pos;

//Check return IO position

bool ret_ok = false;

for( r_pos = 0; r_pos < funcAt(f_id)->valFunc().func()->ioSize(); r_pos++ )

if( funcAt(f_id)->valFunc().func()->io(r_pos)->mode() == IO::Return )

{ ret_ok=true; break; }

//Check IO and parameters count

if( p_cnt > funcAt(f_id)->valFunc().func()->ioSize()-ret_ok )

throw TError(nodePath().c_str(),mod->I18N("Request more %d parameters for function <%s>"),

funcAt(f_id)->valFunc().func()->ioSize(),funcAt(f_id)->valFunc().func()->id().c_str());

//Check the present return for fuction

if( !proc && !ret_ok )

throw TError(nodePath().c_str(),mod->I18N("Request function <%s>, but it not have return IO"),funcAt(f_id)->valFunc().func()->id().c_str());

//Mvi all parameters

for( int i_prm = 0; i_prm < p_cnt; i_prm++ )

f_prmst[i_prm] = cdMvi( f_prmst[i_prm] );

//Get parameters. Add check parameters type !!!!

for( int i_prm = 0; i_prm < p_cnt; i_prm++ )

{

p_pos.push_front( f_prmst.front()->pos() );

f_prmst.front()->free();

f_prmst.pop_front();

}

//Make result

if( !proc )

{

rez = regAt(regNew());

switch(funcAt(f_id)->valFunc().func()->io(r_pos)->type())

{

case IO::String:	rez->type(Reg::String); break;

case IO::Integer:	rez->type(Reg::Int);	break;

case IO::Real:	rez->type(Reg::Real);	break;

case IO::Boolean:	rez->type(Reg::Bool); break;

}

}

//Make code

if( proc )	prg+=(BYTE)Reg::CProc;

else	prg+=(BYTE)Reg::CFunc;

prg+=(BYTE)f_id;

prg+=(BYTE)p_cnt;

prg+=(BYTE)((proc)?0:rez->pos());

for( int i_prm = 0; i_prm < p_pos.size(); i_prm++ )

prg+=(BYTE)p_pos[i_prm];

return rez;

}

bool Func::getValB( TValFunc *io, RegW &rg )

{

switch(rg.type())

{

case Reg::Bool: return rg.val().b_el;

case Reg::Int: return (bool)rg.val().i_el;

case Reg::Real: return (bool)rg.val().r_el;

case Reg::String: return (bool)atoi(rg.val().s_el->c_str());

case Reg::Var: return io->getB(rg.val().io);

}

}

int Func::getValI( TValFunc *io, RegW &rg )

{

switch(rg.type())

{

case Reg::Bool: return rg.val().b_el;

case Reg::Int: return rg.val().i_el;

case Reg::Real: return (int)rg.val().r_el;

case Reg::String: return atoi(rg.val().s_el->c_str());

case Reg::Var: return io->getI(rg.val().io);

}

}

double Func::getValR( TValFunc *io, RegW &rg )

{

switch(rg.type())

{

case Reg::Bool: return (double)rg.val().b_el;

case Reg::Int: return (double)rg.val().i_el;

case Reg::Real: return rg.val().r_el;

case Reg::String: return atof(rg.val().s_el->c_str());

case Reg::Var: return io->getR(rg.val().io);

}

}

string Func::getValS( TValFunc *io, RegW &rg )

{

switch(rg.type())

{

case Reg::Bool: return TSYS::int2str(rg.val().b_el);

case Reg::Int: return TSYS::int2str(rg.val().i_el);

case Reg::Real: return TSYS::real2str(rg.val().r_el);

case Reg::String: return *rg.val().s_el;

case Reg::Var: return io->getS(rg.val().io);

}

}

void Func::setValB( TValFunc *io, RegW &rg, bool val )

{

switch(rg.type())

{

case Reg::Bool: rg.val().b_el = val; break;

case Reg::Int: rg.val().i_el = val; break;

case Reg::Real: rg.val().r_el = val; break;

case Reg::String: *rg.val().s_el = TSYS::int2str(val); break;

case Reg::Var: io->setB(rg.val().io,val); break;

}

}

void Func::setValI( TValFunc *io, RegW &rg, int val )

{

switch(rg.type())

{

case Reg::Bool: rg.val().b_el = val; break;

case Reg::Int: rg.val().i_el = val; break;

case Reg::Real: rg.val().r_el = val; break;

case Reg::String: *rg.val().s_el = TSYS::int2str(val); break;

case Reg::Var: io->setI(rg.val().io,val); break;

}

}

void Func::setValR( TValFunc *io, RegW &rg, double val )

{

switch(rg.type())

{

case Reg::Bool: rg.val().b_el = val; break;

case Reg::Int: rg.val().i_el = (int)val; break;

case Reg::Real: rg.val().r_el = val; break;

case Reg::String: *rg.val().s_el = TSYS::real2str(val); break;

case Reg::Var: io->setR(rg.val().io,val); break;

}

}

void Func::setValS( TValFunc *io, RegW &rg, const string &val )

{

switch(rg.type())

{

case Reg::Bool: rg.val().b_el = atoi(val.c_str()); break;

case Reg::Int: rg.val().i_el = atoi(val.c_str()); break;

case Reg::Real: rg.val().r_el = atof(val.c_str()); break;

case Reg::String: *rg.val().s_el = val; break;

case Reg::Var: io->setS(rg.val().io,val); break;

}

}

void Func::calc( TValFunc *val )

{

ResAlloc::resRequestR(calc_res);

//Init list of registers

RegW reg[m_regs.size()];

for( int i_rg = 0; i_rg < m_regs.size(); i_rg++ )

{

reg[i_rg].type(m_regs[i_rg]->type());

if(reg[i_rg].type() == Reg::Var) reg[i_rg].val().io = m_regs[i_rg]->val().io;

}

//Exec calc

const BYTE *cprg = (const BYTE *)prg.c_str();

exec(val,reg,cprg);

ResAlloc::resReleaseR(calc_res);

}

void Func::exec( TValFunc *val, RegW *reg, const BYTE *cprg )

{

while( true )

switch(*cprg)

{

case Reg::End: return;

//MVI codes

case Reg::MviB:

#if DEBUG_VM

printf("CODE: Load bool %d to reg %d.\n",*(BYTE *)(cprg+2),*(BYTE *)(cprg+1));

#endif

reg[*(BYTE *)(cprg+1)] = (bool)*(BYTE*)(cprg+2);

cprg+=3; break;

case Reg::MviI:

#if DEBUG_VM

printf("CODE: Load integer %d to reg %d.\n",*(int *)(cprg+2),*(BYTE *)(cprg+1));

#endif

reg[*(BYTE *)(cprg+1)] = *(int *)(cprg+2);

cprg+=2+sizeof(int); break;

case Reg::MviR:

#if DEBUG_VM

printf("CODE: Load real %f to reg %d.\n",*(double *)(cprg+2),*(BYTE *)(cprg+1));

#endif

reg[*(BYTE *)(cprg+1)] = *(double *)(cprg+2);

cprg+=2+sizeof(double); break;

case Reg::MviS:

#if DEBUG_VM

printf("CODE: Load string %s(%d) to reg %d.\n",string((char *)cprg+3,*(BYTE *)(cprg+2)).c_str(),*(BYTE *)(cprg+2),*(BYTE *)(cprg+1));

#endif

reg[*(BYTE *)(cprg+1)] = string((char *)cprg+3,*(BYTE *)(cprg+2));

cprg+=3+ *(BYTE *)(cprg+2); break;

//Assign codes

case Reg::AssB:

#if DEBUG_VM

printf("CODE: Assign boolean from %d to %d.\n",*(BYTE *)(cprg+2),*(BYTE *)(cprg+1));

#endif

setValB(val,reg[*(BYTE *)(cprg+1)],getValB(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::AssI:

#if DEBUG_VM

printf("CODE: Assign integer from %d to %d.\n",*(BYTE *)(cprg+2),*(BYTE *)(cprg+1));

#endif

setValI(val,reg[*(BYTE *)(cprg+1)],getValI(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::AssR:

#if DEBUG_VM

printf("CODE: Assign real from %d to %d.\n",*(BYTE *)(cprg+2),*(BYTE *)(cprg+1));

#endif

setValR(val,reg[*(BYTE *)(cprg+1)],getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::AssS:

#if DEBUG_VM

printf("CODE: Assign string from %d to %d.\n",*(BYTE *)(cprg+2),*(BYTE *)(cprg+1));

#endif

setValS(val,reg[*(BYTE *)(cprg+1)],getValS(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

//Mov codes

case Reg::MovB:

#if DEBUG_VM

printf("CODE: Move boolean from %d to %d.\n",*(BYTE *)(cprg+2),*(BYTE *)(cprg+1));

#endif

reg[*(BYTE *)(cprg+1)] = getValB(val,reg[*(BYTE *)(cprg+2)]);

cprg+=3; break;

case Reg::MovI:

#if DEBUG_VM

printf("CODE: Move integer from %d to %d.\n",*(BYTE *)(cprg+2),*(BYTE *)(cprg+1));

#endif

reg[*(BYTE *)(cprg+1)] = getValI(val,reg[*(BYTE *)(cprg+2)]);

cprg+=3; break;

case Reg::MovR:

#if DEBUG_VM

printf("CODE: Move real from %d to %d.\n",*(BYTE *)(cprg+2),*(BYTE *)(cprg+1));

#endif

reg[*(BYTE *)(cprg+1)] = getValR(val,reg[*(BYTE *)(cprg+2)]);

cprg+=3; break;

case Reg::MovS:

#if DEBUG_VM

printf("CODE: Move string from %d to %d.\n",*(BYTE *)(cprg+2),*(BYTE *)(cprg+1));

#endif

reg[*(BYTE *)(cprg+1)] = getValS(val,reg[*(BYTE *)(cprg+2)]);

cprg+=3; break;

//Binary operations

case Reg::AddI:

#if DEBUG_VM

printf("CODE: Integer %d = %d + %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValI(val,reg[*(BYTE *)(cprg+2)]) + getValI(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::AddR:

#if DEBUG_VM

printf("CODE: Real %d = %d + %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValR(val,reg[*(BYTE *)(cprg+2)]) + getValR(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::AddS:

#if DEBUG_VM

printf("CODE: String %d = %d + %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValS(val,reg[*(BYTE *)(cprg+2)]) + getValS(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::SubI:

#if DEBUG_VM

printf("CODE: Integer %d = %d - %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValI(val,reg[*(BYTE *)(cprg+2)]) - getValI(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::SubR:

#if DEBUG_VM

printf("CODE: Real %d = %d - %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValR(val,reg[*(BYTE *)(cprg+2)]) - getValR(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::MulI:

#if DEBUG_VM

printf("CODE: Integer %d = %d * %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValI(val,reg[*(BYTE *)(cprg+2)]) * getValI(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::MulR:

#if DEBUG_VM

printf("CODE: Real %d = %d * %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValR(val,reg[*(BYTE *)(cprg+2)]) * getValR(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::DivI:

#if DEBUG_VM

printf("CODE: Integer %d = %d / %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValI(val,reg[*(BYTE *)(cprg+2)]) / getValI(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::DivR:

#if DEBUG_VM

printf("CODE: Real %d = %d / %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValR(val,reg[*(BYTE *)(cprg+2)]) / getValR(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::RstI:

#if DEBUG_VM

printf("CODE: %d = %d % %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValI(val,reg[*(BYTE *)(cprg+2)]) % getValI(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::BitOr:

#if DEBUG_VM

printf("CODE: %d = %d | %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValI(val,reg[*(BYTE *)(cprg+2)]) | getValI(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::BitAnd:

#if DEBUG_VM

printf("CODE: %d = %d & %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValI(val,reg[*(BYTE *)(cprg+2)]) & getValI(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::BitXor:

#if DEBUG_VM

printf("CODE: %d = %d ^ %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValI(val,reg[*(BYTE *)(cprg+2)]) ^ getValI(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::LOr:

#if DEBUG_VM

printf("CODE: %d = %d || %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValB(val,reg[*(BYTE *)(cprg+2)]) || getValB(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::LAnd:

#if DEBUG_VM

printf("CODE: %d = %d && %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValB(val,reg[*(BYTE *)(cprg+2)]) && getValB(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::LTI:

#if DEBUG_VM

printf("CODE: Integer %d = %d < %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValI(val,reg[*(BYTE *)(cprg+2)]) < getValI(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::LTR:

#if DEBUG_VM

printf("CODE: Real %d = %d < %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValR(val,reg[*(BYTE *)(cprg+2)]) < getValR(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::GTI:

#if DEBUG_VM

printf("CODE: Integer %d = %d > %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValI(val,reg[*(BYTE *)(cprg+2)]) > getValI(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::GTR:

#if DEBUG_VM

printf("CODE: Real %d = %d > %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValR(val,reg[*(BYTE *)(cprg+2)]) > getValR(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::LEI:

#if DEBUG_VM

printf("CODE: Integer %d = %d <= %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValI(val,reg[*(BYTE *)(cprg+2)]) <= getValI(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::LER:

#if DEBUG_VM

printf("CODE: Real %d = %d <= %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValR(val,reg[*(BYTE *)(cprg+2)]) <= getValR(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::GEI:

#if DEBUG_VM

printf("CODE: Integer %d = %d >= %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValI(val,reg[*(BYTE *)(cprg+2)]) >= getValI(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::GER:

#if DEBUG_VM

printf("CODE: Real %d = %d >= %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValR(val,reg[*(BYTE *)(cprg+2)]) >= getValR(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::EQI:

#if DEBUG_VM

printf("CODE: Integer %d = %d == %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValI(val,reg[*(BYTE *)(cprg+2)]) == getValI(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::EQR:

#if DEBUG_VM

printf("CODE: Real %d = %d == %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValR(val,reg[*(BYTE *)(cprg+2)]) == getValR(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::EQS:

#if DEBUG_VM

printf("CODE: String %d = %d == %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValS(val,reg[*(BYTE *)(cprg+2)]) == getValS(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::NEI:

#if DEBUG_VM

printf("CODE: Integer %d = %d != %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValI(val,reg[*(BYTE *)(cprg+2)]) != getValI(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::NER:

#if DEBUG_VM

printf("CODE: Real %d = %d != %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValR(val,reg[*(BYTE *)(cprg+2)]) != getValR(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

case Reg::NES:

#if DEBUG_VM

printf("CODE: String %d = %d != %d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = getValS(val,reg[*(BYTE *)(cprg+2)]) != getValS(val,reg[*(BYTE *)(cprg+3)]);

cprg+=4; break;

//Unary operations

case Reg::Not:

#if DEBUG_VM

printf("CODE: %d = !%d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = !getValB(val,reg[*(BYTE *)(cprg+2)]);

cprg+=3; break;

case Reg::BitNot:

#if DEBUG_VM

printf("CODE: %d = ~%d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = ~getValI(val,reg[*(BYTE *)(cprg+2)]);

cprg+=3; break;

case Reg::NegI:

#if DEBUG_VM

printf("CODE: Integer %d = -%d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = -getValI(val,reg[*(BYTE *)(cprg+2)]);

cprg+=3; break;

case Reg::NegR:

#if DEBUG_VM

printf("CODE: Real %d = -%d.\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = -getValR(val,reg[*(BYTE *)(cprg+2)]);

cprg+=3; break;

//Condition

case Reg::If:

#if DEBUG_VM

printf("CODE: Condition %d: %d|%d|%d.\n",*(BYTE *)(cprg+1),6,*(WORD *)(cprg+2),*(WORD *)(cprg+4));

#endif

if(getValB(val,reg[*(BYTE *)(cprg+1)]))

exec(val,reg,cprg+6);

else if( *(WORD *)(cprg+2) != *(WORD *)(cprg+4) )

exec(val,reg,cprg + *(WORD *)(cprg+2));

cprg = cprg + *(WORD *)(cprg+4);

continue;

//Buildin functions

case Reg::FSin:

#if DEBUG_VM

printf("CODE: Function %d=sin(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = sin(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::FCos:

#if DEBUG_VM

printf("CODE: Function %d=cos(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = cos(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::FTan:

#if DEBUG_VM

printf("CODE: Function %d=tan(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = tan(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::FSinh:

#if DEBUG_VM

printf("CODE: Function %d=sinh(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = sinh(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::FCosh:

#if DEBUG_VM

printf("CODE: Function %d=cosh(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = cosh(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::FTanh:

#if DEBUG_VM

printf("CODE: Function %d=tanh(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = tanh(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::FAsin:

#if DEBUG_VM

printf("CODE: Function %d=asin(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = asin(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::FAcos:

#if DEBUG_VM

printf("CODE: Function %d=acos(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = acos(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::FAtan:

#if DEBUG_VM

printf("CODE: Function %d=atan(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = atan(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::FRand:

#if DEBUG_VM

printf("CODE: Function %d=rand(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = getValR(val,reg[*(BYTE *)(cprg+2)])*(double)rand()/(double)RAND_MAX;

cprg+=3; break;

case Reg::FLg:

#if DEBUG_VM

printf("CODE: Function %d=lg(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = log10(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::FLn:

#if DEBUG_VM

printf("CODE: Function %d=ln(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = log(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::FExp:

#if DEBUG_VM

printf("CODE: Function %d=exp(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = exp(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::FPow:

#if DEBUG_VM

printf("CODE: Function %d=pow(%d,%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2),*(BYTE *)(cprg+3));

#endif

reg[*(BYTE *)(cprg+1)] = pow(getValR(val,reg[*(BYTE *)(cprg+2)]),getValR(val,reg[*(BYTE *)(cprg+3)]));

cprg+=4; break;

case Reg::FSqrt:

#if DEBUG_VM

printf("CODE: Function %d=sqrt(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = sqrt(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::FAbs:

#if DEBUG_VM

printf("CODE: Function %d=abs(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = fabs(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::FSign:

#if DEBUG_VM

printf("CODE: Function %d=sign(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = (getValR(val,reg[*(BYTE *)(cprg+2)])>=0)?1:-1;

cprg+=3; break;

case Reg::FCeil:

#if DEBUG_VM

printf("CODE: Function %d=ceil(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = ceil(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::FFloor:

#if DEBUG_VM

printf("CODE: Function %d=floor(%d).\n",*(BYTE *)(cprg+1),*(BYTE *)(cprg+2));

#endif

reg[*(BYTE *)(cprg+1)] = floor(getValR(val,reg[*(BYTE *)(cprg+2)]));

cprg+=3; break;

case Reg::CProc:

case Reg::CFunc:

{

TValFunc &vfnc = funcAt(*(BYTE *)(cprg+1))->valFunc();

#if DEBUG_VM

printf("CODE: Call function/procedure %d = %s(%d).\n",*(BYTE *)(cprg+3),vfnc.func()->id().c_str(),*(BYTE *)(cprg+2));

#endif

//Get return position

int r_pos, i_p, p_p;

for( r_pos = 0; r_pos < vfnc.func()->ioSize(); r_pos++ )

if( vfnc.ioMode(r_pos) == IO::Return ) break;

//Process parameters

for( i_p = 0; i_p < *(BYTE *)(cprg+2); i_p++ )

{

p_p = (i_p>=r_pos)?i_p+1:i_p;

switch(vfnc.ioType(p_p))

{

case IO::String:	vfnc.setS(p_p,getValS(val,reg[*(BYTE *)(cprg+4+i_p)])); break;

case IO::Integer:	vfnc.setI(p_p,getValI(val,reg[*(BYTE *)(cprg+4+i_p)])); break;

case IO::Real:	vfnc.setR(p_p,getValR(val,reg[*(BYTE *)(cprg+4+i_p)])); break;

case IO::Boolean:	vfnc.setB(p_p,getValB(val,reg[*(BYTE *)(cprg+4+i_p)])); break;

}

}

//Make calc

vfnc.calc();

//Process outputs

for( i_p = 0; i_p < *(BYTE *)(cprg+2); i_p++ )

{

p_p = (i_p>=r_pos)?i_p+1:i_p;

if( vfnc.ioMode(p_p) == IO::Output )

switch(vfnc.ioType(p_p))

{

case IO::String: setValS(val,reg[*(BYTE *)(cprg+4+i_p)],vfnc.getS(p_p)); break;

case IO::Integer: setValI(val,reg[*(BYTE *)(cprg+4+i_p)],vfnc.getI(p_p)); break;

case IO::Real: setValR(val,reg[*(BYTE *)(cprg+4+i_p)],vfnc.getR(p_p)); break;

case IO::Boolean: setValB(val,reg[*(BYTE *)(cprg+4+i_p)],vfnc.getB(p_p)); break;

}

}

//Set return

if( *cprg == Reg::CFunc )

{

switch(vfnc.ioType(r_pos))

{

case IO::String: reg[*(BYTE *)(cprg+3)] = vfnc.getS(r_pos); break;

case IO::Integer: reg[*(BYTE *)(cprg+3)] = vfnc.getI(r_pos); break;

case IO::Real: reg[*(BYTE *)(cprg+3)] = vfnc.getR(r_pos); break;

case IO::Boolean: reg[*(BYTE *)(cprg+3)] = vfnc.getB(r_pos); break;

}

}

cprg+=4+ *(BYTE *)(cprg+2); break;

}

default:

start(false);

throw TError(nodePath().c_str(),mod->I18N("Operation %c(%xh) error. Function <%s> stoped."),*cprg,*cprg,id().c_str());

}

}

void Func::cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd )

{

if( cmd==TCntrNode::Info )

{

TFunction::cntrCmd_( a_path, opt, cmd ); //Call parent

ctrMkNode("fld",opt,a_path.c_str(),"/func/cfg/name",Mess->I18N("Name"),0664,0,0,"str");

ctrMkNode("fld",opt,a_path.c_str(),"/func/cfg/descr",Mess->I18N("Description"),0664,0,0,"str")->

attr_("cols","90")->attr_("rows","3");

ctrMkNode("comm",opt,a_path.c_str(),"/func/cfg/load",Mess->I18N("Load"),0550);

ctrMkNode("comm",opt,a_path.c_str(),"/func/cfg/save",Mess->I18N("Save"),0550);

ctrMkNode("area",opt,a_path.c_str(),"/io",Mess->I18N("Programm"));

ctrMkNode("table",opt,a_path.c_str(),"/io/io",Mess->I18N("IO"),0664,0,0)->attr_("s_com","add,del,ins,move");

ctrMkNode("list",opt,a_path.c_str(),"/io/io/0",Mess->I18N("Id"),0664,0,0,"str");

ctrMkNode("list",opt,a_path.c_str(),"/io/io/1",Mess->I18N("Name"),0664,0,0,"str");

ctrMkNode("list",opt,a_path.c_str(),"/io/io/2",Mess->I18N("Type"),0664,0,0,"str")->

attr_("idm","1")->attr_("dest","select")->attr_("select","/io/tp");

ctrMkNode("list",opt,a_path.c_str(),"/io/io/3",Mess->I18N("Mode"),0664,0,0,"str")->

attr_("idm","1")->attr_("dest","select")->attr_("select","/io/md");

ctrMkNode("list",opt,a_path.c_str(),"/io/io/4",Mess->I18N("Hide"),0664,0,0,"bool");

ctrMkNode("list",opt,a_path.c_str(),"/io/io/5",Mess->I18N("Default"),0664,0,0,"str");

//ctrMkNode("list",opt,a_path.c_str(),"/io/io/6",Mess->I18N("Vector"),0664,0,0,"str");

ctrMkNode("fld",opt,a_path.c_str(),"/io/prog",Mess->I18N("Programm"),0664,0,0,"str")->

attr_("cols","90")->attr_("rows","10");

}

else if( cmd==TCntrNode::Get )

{

if( a_path == "/io/io" )

{

XMLNode *n_id = ctrId(opt,"0");

XMLNode *n_nm = ctrId(opt,"1");

XMLNode *n_type = ctrId(opt,"2");

XMLNode *n_mode = ctrId(opt,"3");

XMLNode *n_hide = ctrId(opt,"4");

XMLNode *n_def = ctrId(opt,"5");

//XMLNode *n_vect = ctrId(opt,"6");

for( int id = 0; id < ioSize(); id++ )

{

ctrSetS(n_id,io(id)->id());

ctrSetS(n_nm,io(id)->name());

//Make type

if( io(id)->type() == IO::Integer )	ctrSetS(n_type,"int");

else if( io(id)->type() == IO::Real )	ctrSetS(n_type,"real");

else if( io(id)->type() == IO::Boolean )ctrSetS(n_type,"bool");

else if( io(id)->type() == IO::String )	ctrSetS(n_type,"str");

//Make mode

if( io(id)->mode() == IO::Output )	ctrSetS(n_mode,"out");

else if( io(id)->mode() == IO::Return )	ctrSetS(n_mode,"ret");

else if( io(id)->mode() == IO::Input )	ctrSetS(n_mode,"in");

(io(id)->hide()) ? ctrSetB(n_hide,true) : ctrSetB(n_hide,false);

ctrSetS(n_def,io(id)->def());

//ctrSetS(n_vect,io(id)->vector());

}

}

else if( a_path == "/io/tp" )

{

ctrSetS( opt, Mess->I18N("Real"), "real" );

ctrSetS( opt, Mess->I18N("Integer"), "int" );

ctrSetS( opt, Mess->I18N("Boolean"), "bool" );

ctrSetS( opt, Mess->I18N("String"), "str" );

}

else if( a_path == "/io/md" )

{

ctrSetS( opt, Mess->I18N("Input"), "in" );

ctrSetS( opt, Mess->I18N("Output"), "out" );

ctrSetS( opt, Mess->I18N("Return"), "ret" );

}

else if( a_path == "/io/prog" )	ctrSetS( opt, prg_src );

else TFunction::cntrCmd_( a_path, opt, cmd ); //Call parent

}

else if( cmd==TCntrNode::Set )

{

if( a_path == "/func/cfg/name" )	m_name	= ctrGetS(opt);

else if( a_path == "/func/cfg/descr" )	m_descr = ctrGetS(opt);

else if( a_path == "/io/io" )

{

if( opt->name() == "add" )	ioAdd( new IO("new","New IO",IO::Real,IO::Input) );

else if( opt->name() == "ins" )	ioIns( new IO("new","New IO",IO::Real,IO::Input), atoi(opt->attr("row").c_str()) );

else if( opt->name() == "del" )	ioDel( atoi(opt->attr("row").c_str()) );

else if( opt->name() == "move" )	ioMove( atoi(opt->attr("row").c_str()), atoi(opt->attr("to").c_str()) );

else if( opt->name() == "set" )

{

int row = atoi(opt->attr("row").c_str());

int col = atoi(opt->attr("col").c_str());

if( (col == 0 || col == 1) && !opt->text().size() )

throw TError(nodePath().c_str(),mod->I18N("Empty value no valid."));

if( col == 0 )	io(row)->id(ctrGetS(opt));

else if( col == 1 )	io(row)->name(ctrGetS(opt));

else if( col == 2 )

{

if( ctrGetS(opt) == "real" )	io(row)->type(IO::Real);

else if( ctrGetS(opt) == "int" )	io(row)->type(IO::Integer);

else if( ctrGetS(opt) == "bool" )	io(row)->type(IO::Boolean);

else if( ctrGetS(opt) == "str" )	io(row)->type(IO::String);

}

else if( col == 3 )

{

if( ctrGetS(opt) == "in" )	io(row)->mode(IO::Input);

else if( ctrGetS(opt) == "out" )	io(row)->mode(IO::Output);

else if( ctrGetS(opt) == "ret" )	io(row)->mode(IO::Return);

}

else if( col == 4 )	io(row)->hide(ctrGetB(opt));

else if( col == 5 )	io(row)->def(ctrGetS(opt));

//else if( col == 6 )	io(row)->vector(ctrGetS(opt));

}

}

else if( a_path == "/io/prog" )

{

prg_src = ctrGetS( opt );

progCompile();

}

else if( a_path == "/func/cfg/load" )	load();

else if( a_path == "/func/cfg/save" )	save();

else TFunction::cntrCmd_( a_path, opt, cmd ); //Call parent

}

}

//================== Reg ========================

Reg &Reg::operator=( Reg &irg )

{

type(irg.type());

switch(type())

{

case Bool:	el.b_el = irg.el.b_el; break;

case Int:	el.i_el = irg.el.i_el;	break;

case Real:	el.r_el = irg.el.r_el;	break;

case String:	*el.s_el = *irg.el.s_el;break;

case Var:	el.io = irg.el.io;	break;

}

name(irg.name().c_str());	//name

m_flg = irg.m_flg;	//flags

//m_pos = irg.m_pos;	//pos

return *this;

}

string Reg::name() const

{

return (m_nm)? *m_nm:"";

}

void Reg::name( const char *nm )

{

if(!m_nm) m_nm = new string;

*m_nm = nm;

}

Reg::Type Reg::vType( Func *fnc )

{

switch(type())

{

case Free: return Int;

case Var:

switch(fnc->io(val().io)->type())

{

case IO::String:	return String;

case IO::Boolean:	return Bool;

case IO::Integer:	return Int;

case IO::Real:	return Real;

}

default: return type();

}

}

void Reg::free()

{

if(!lock())

{

type(Free);

m_flg = 0;

if(m_nm)

{

delete m_nm;

m_nm = NULL;

}

}

}

Вміст файлу func_analise.ypp

%{

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#include <tsys.h>

#include <tmess.h>

#include "freefunc.h"

#include "freelib.h"

#include "virtual.h"

#define YYERROR_VERBOSE true

namespace JavaLikeCalc

{

char m_buf[STR_BUF_LEN];

struct YYLTYPE;

int yylex( );

void yyerror( const char *s );

void sfErr( const string &mess, YYLTYPE *ps);

%}

/************************* GRAMMAR ****************************/

%union

{

int id;	//Function id

Reg	*reg;	//Variable and Constant registers list index and function list index

int fp_cnt;	//Function parameters counter

int prg_cd;	//Programm code

}

%token ERR IF ELSE ADDEQ SUBEQ MULEQ DIVEQ

%token <id>	FUNC B_FUNC B_FUNC1 B_FUNC2

%token <reg>	VAR CONST

%type <reg> expr

%type <prg_cd>	if if_expr end

%type <fp_cnt>	prmlst

%right '=' ADDEQ SUBEQ MULEQ DIVEQ

%right '?' ':'

%left OR

%left AND

%left '|' '&' '^'

%left '>' '<' GE LE EQ NE

%left '+' '-'

%left '*' '/' '%'

%right UN_MINUS '!' '~'

%%

root:	solver end

| error	{ sfErr("",&yylloc); YYABORT; }

solver:	/*empty*/

| solver solve

solve: assign ';'

| IF '(' expr ')' if solve end

{ try{ p_fnc->cdCond($3,$5,$7,$7); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| IF '(' expr ')' if solve end ELSE solve end

{ try{ p_fnc->cdCond($3,$5,$7,$10); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| FUNC '(' prmlst ')' ';'

{ try{ p_fnc->cdExtFnc($1,$3,true); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| '{' solver '}'

assign: VAR '=' expr

{

try

{

if( $1->type() == Reg::Free ) $1->type($3->vType(p_fnc));

p_fnc->cdAssign($1,$3);

} catch(TError err){ sfErr(err.mess,&@1); YYABORT; }

}

| VAR ADDEQ expr

{

try

{

if( $1->type() == Reg::Free ) throw TError(p_fnc->nodePath().c_str(),mod->I18N("Variable <%s> is used but undefined"),$1->name().c_str());

p_fnc->cdAssign($1,p_fnc->cdBinaryOp(Reg::AddI,$1,$3));

} catch(TError err){ sfErr(err.mess,&@1); YYABORT; }

}

| VAR SUBEQ expr

{

try

{

if( $1->type() == Reg::Free ) throw TError(p_fnc->nodePath().c_str(),mod->I18N("Variable <%s> is used but undefined"),$1->name().c_str());

p_fnc->cdAssign($1,p_fnc->cdBinaryOp(Reg::SubI,$1,$3));

} catch(TError err){ sfErr(err.mess,&@1); YYABORT; }

}

| VAR MULEQ expr

{

try

{

if( $1->type() == Reg::Free ) throw TError(p_fnc->nodePath().c_str(),mod->I18N("Variable <%s> is used but undefined"),$1->name().c_str());

p_fnc->cdAssign($1,p_fnc->cdBinaryOp(Reg::MulI,$1,$3));

} catch(TError err){ sfErr(err.mess,&@1); YYABORT; }

}

| VAR DIVEQ expr

{

try

{

if( $1->type() == Reg::Free ) throw TError(p_fnc->nodePath().c_str(),mod->I18N("Variable <%s> is used but undefined"),$1->name().c_str());

p_fnc->cdAssign($1,p_fnc->cdBinaryOp(Reg::DivI,$1,$3));

} catch(TError err){ sfErr(err.mess,&@1); YYABORT; }

}

expr:	CONST	{ $$ = $1; }

| VAR

{

try

{

if( $1->type() == Reg::Free ) throw TError(p_fnc->nodePath().c_str(),mod->I18N("Variable <%s> is used but undefined"),$1->name().c_str());

$$ = $1;

} catch(TError err){ sfErr(err.mess,&@1); YYABORT; }

}

| VAR '=' expr

{

try

{

if( $1->type() == Reg::Free ) $1->type($3->vType(p_fnc));

p_fnc->cdAssign($1,$3);

$$ = $1;

} catch(TError err){ sfErr(err.mess,&@1); YYABORT; }

}

| B_FUNC '(' ')'	{ try{ $$ = p_fnc->cdBldFnc($1); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| B_FUNC1 '(' expr ')'	{ try{ $$ = p_fnc->cdBldFnc($1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| B_FUNC2 '(' expr ',' expr ')'	{ try{ $$ = p_fnc->cdBldFnc($1,$3,$5); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| FUNC '(' prmlst ')'	{ try{ $$ = p_fnc->cdExtFnc($1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr '+' expr	{ try{ $$ = p_fnc->cdBinaryOp(Reg::AddI,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr '-' expr	{ try{ $$ = p_fnc->cdBinaryOp(Reg::SubI,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr '*' expr	{ try{ $$ = p_fnc->cdBinaryOp(Reg::MulI,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr '/' expr { try{ $$ = p_fnc->cdBinaryOp(Reg::DivI,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr '%' expr { try{ $$ = p_fnc->cdBinaryOp(Reg::RstI,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr '|' expr { try{ $$ = p_fnc->cdBinaryOp(Reg::BitOr,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr '&' expr { try{ $$ = p_fnc->cdBinaryOp(Reg::BitAnd,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr '^' expr { try{ $$ = p_fnc->cdBinaryOp(Reg::BitXor,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| '(' expr ')'	{ $$ = $2; }

| expr OR expr	{ try{ $$ = p_fnc->cdBinaryOp(Reg::LOr,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr AND expr	{ try{ $$ = p_fnc->cdBinaryOp(Reg::LAnd,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr '<' expr { try{ $$ = p_fnc->cdBinaryOp(Reg::LTI,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr '>' expr { try{ $$ = p_fnc->cdBinaryOp(Reg::GTI,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr GE expr	{ try{ $$ = p_fnc->cdBinaryOp(Reg::GEI,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr LE expr	{ try{ $$ = p_fnc->cdBinaryOp(Reg::LEI,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr EQ expr	{ try{ $$ = p_fnc->cdBinaryOp(Reg::EQI,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr NE expr	{ try{ $$ = p_fnc->cdBinaryOp(Reg::NEI,$1,$3); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| '!' expr	{ try{ $$ = p_fnc->cdUnaryOp(Reg::Not,$2); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| '~' expr	{ try{ $$ = p_fnc->cdUnaryOp(Reg::BitNot,$2); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| '-' expr %prec UN_MINUS { try{ $$ = p_fnc->cdUnaryOp(Reg::NegI,$2); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

| expr if_expr expr end ':' expr end

{ try{ $$ = p_fnc->cdCond($1,$2,$4,$7,$3,$6); } catch(TError err){ sfErr(err.mess,&@1); YYABORT; } }

prmlst: /*empty*/	{ $$ = 0; }

| expr	{ $$ = 1; p_fnc->f_prmst.push_front($1); }

| prmlst ',' prmlst	{ $$ = $1 + $3; }

if:	/*empty*/	{ $$ = p_fnc->prg.size(); p_fnc->prg=p_fnc->prg+(char)Reg::If+"R00nn"; }

if_expr: '?'	{ $$ = p_fnc->prg.size(); p_fnc->prg=p_fnc->prg+(char)Reg::If+"R00nn"; }

end:	/*empty*/	{ p_fnc->prg+=(char)Reg::End; $$ = p_fnc->prg.size(); }

/************************* END OF GRAMMAR ****************************/

%%

void sfErr(const string &mess, YYLTYPE *ps)

{

snprintf(m_buf,sizeof(m_buf),mod->I18N("%s, pos: (%d,%d)-(%d,%d).\n"),

mess.c_str(),ps->first_line,ps->first_column,ps->last_line,ps->last_column );

yyerror(m_buf);

}

void yyerror( const char *s )

{

p_fnc->p_err+=s;

}

int yylex( )

{

int c, st_pos;

int &pos = p_fnc->la_pos;

string &prog = p_fnc->prg_src;

if( pos == 0 ) { yylloc.last_line = yylloc.last_column = 1; }

while( pos < prog.size() &&

((c = prog[pos]) == ' ' || c == '\n' || c == '\t' ||

c == '\f' || c == '\r' || c == '\v') )

{

if( c == '\n' )

{

yylloc.last_column = 1;

yylloc.last_line++;

}

else yylloc.last_column++;

pos++;

}

//Comentars

while( prog.substr(pos,2) == "//" )

{

while( pos < prog.size() && prog[pos] != '\n' ) pos++;

while( pos < prog.size() &&

((c = prog[pos]) == ' ' || c == '\n' || c == '\t' ||

c == '\f' || c == '\r' || c == '\v') )

{

if( c == '\n' )

{

yylloc.last_column = 1;

yylloc.last_line++;

}

else yylloc.last_column++;

pos++;

}

}

yylloc.first_line = yylloc.last_line;

yylloc.first_column = yylloc.last_column;

//End string

if( pos >= prog.size() ) return 0;

//Number

if( isdigit(c) || (c == '.' && (pos+1) < prog.size() && isdigit(prog[pos+1])) )

{

st_pos = pos;

int tp = 0;	//Type constant (0-detect;1-dec;2-oct;3-hex;4-real)

if( c == '.' )	tp = 4;

else

{

while( pos < prog.size() && isdigit(c=prog[pos]) )

{ pos++; yylloc.last_column++; }

if( pos >= prog.size() )	tp = (prog[st_pos]=='0')?2:1;

else if( c == 'x' || c == 'X' )	tp = 3;

else if( c == '.' || c == 'e' || c == 'E' )	tp = 4;

else tp = (prog[st_pos]=='0')?2:1;

}

if( tp == 1 )

{

yylval.reg = p_fnc->regTmpNew();

*yylval.reg = (int)strtol(prog.substr(st_pos,pos-st_pos).c_str(),NULL,10);

return CONST;

}

else if( tp == 2 )

{

yylloc.last_column-=pos-st_pos;

pos = st_pos;

while( pos < prog.size() && (c=prog[pos]) >= '0' && c <= '7' )

{ pos++; yylloc.last_column++; }

yylval.reg = p_fnc->regTmpNew();

*yylval.reg = (int)strtol(prog.substr(st_pos,pos-st_pos).c_str(),NULL,8);

return CONST;

}

else if( tp == 3 )

{

pos++; yylloc.last_column++;

while( pos < prog.size() && (isdigit(c=prog[pos]) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) )

{ pos++; yylloc.last_column++; }

yylval.reg = p_fnc->regTmpNew();

*yylval.reg = (int)strtol(prog.substr(st_pos,pos-st_pos).c_str(),NULL,16);

return CONST;

}

else if( tp == 4 )

{

bool e_ok = (c=='e'||c=='E')?true:false;

pos++; yylloc.last_column++;

while( pos < prog.size() && (isdigit(c=prog[pos]) || c == 'E' || c == 'e' ||

((c == '+' || c == '-') && ((prog[pos-1]) == 'e' || (prog[pos-1]) == 'E'))) )

{

if( c=='E' || c=='e' )

{

if( e_ok )	break;

else e_ok = true;

}

pos++; yylloc.last_column++;

}

yylval.reg = p_fnc->regTmpNew();

*yylval.reg = atof(prog.substr(st_pos,pos-st_pos).c_str());

return CONST;

}

else return 0;

}

//String

if( c == '"' && (pos+1) < prog.size() )

{

st_pos = ++pos;

while( pos < prog.size() && prog[pos] != '"' && prog[pos] != '\n' )

{ pos++; yylloc.last_column++; }

if( pos >= prog.size() )

{

yyerror(mod->I18N("Unexpected end programm, expect end string symbol '\"', "));

return ERR;

}

else if( prog[pos] == '\n' )

{

yyerror(mod->I18N("The next line symbol failed into string, "));

return ERR;

}

yylval.reg = p_fnc->regTmpNew();

*yylval.reg = prog.substr(st_pos,pos-st_pos);

pos++;

return CONST;

}

//Symbols

if( c == '_' || isalpha(c) )

{

st_pos = pos;

while( pos < prog.size() && ((c = prog[pos]) == '_' || c == '.' || isalnum(c)) )

{ pos++; yylloc.last_column++; }

string smb_nm = prog.substr(st_pos,pos-st_pos);

//Keywords

if( smb_nm == "if" )	return IF;

if( smb_nm == "else" )	return ELSE;

//Boolean

if( smb_nm == "true" || smb_nm == "false" )

{

yylval.reg = p_fnc->regTmpNew();

*yylval.reg = (smb_nm == "true")?true:false;

return CONST;

}

//Constants

if( p_fnc->owner().owner().constGet(smb_nm.c_str()) != NULL )

{

yylval.reg = p_fnc->regTmpNew();

*yylval.reg = p_fnc->owner().owner().constGet(smb_nm.c_str())->val;

return CONST;

}

//Find function

//Find buildin function

if( p_fnc->owner().owner().bFuncGet( smb_nm.c_str() ) != NULL )

{

yylval.id = p_fnc->owner().owner().bFuncGet(smb_nm.c_str())->code;

switch( p_fnc->owner().owner().bFuncGet(smb_nm.c_str())->prm )

{

case 0: return B_FUNC;

case 1: return B_FUNC1;

case 2: return B_FUNC2;

default:

yyerror(mod->I18N("Build in function have to mach parameters, "));

return ERR;

}

}

//Find external functions

string lib_n = p_fnc->owner().id();

string fnc_n = smb_nm;

if( TSYS::strSepParse(smb_nm,1,'.').size() )

{

lib_n = TSYS::strSepParse(smb_nm,0,'.');

fnc_n = TSYS::strSepParse(smb_nm,1,'.');

}

if( p_fnc->funcGet( lib_n, fnc_n ) >= 0 )

{

yylval.id = p_fnc->funcGet( lib_n, fnc_n );

return FUNC;

}

//Check allow registers

if( p_fnc->regGet(smb_nm.c_str()) >= 0 )

{

yylval.reg = p_fnc->regAt(p_fnc->regGet(smb_nm.c_str()));

return VAR;

}

//Check IO

int i_io;

for( i_io = 0; i_io < p_fnc->ioSize(); i_io++ )

if( p_fnc->io(i_io)->id() == smb_nm )

{

yylval.reg = p_fnc->regAt(p_fnc->regNew(true));

yylval.reg->name(smb_nm.c_str());

yylval.reg->setVar(i_io);

yylval.reg->lock(true);

return VAR;

}

//Get new register

if( i_io >= p_fnc->ioSize() )

{

yylval.reg = p_fnc->regAt(p_fnc->regNew(true));

yylval.reg->name(smb_nm.c_str());

yylval.reg->lock(true);

return VAR;

}

}

//Multi symbol operations

else if( prog.substr(pos,2) == "||" ) { pos+=2; yylloc.last_column+=2; return OR; }

else if( prog.substr(pos,2) == "&&" ) { pos+=2; yylloc.last_column+=2; return AND; }

else if( prog.substr(pos,2) == ">=" ) { pos+=2; yylloc.last_column+=2; return GE; }

else if( prog.substr(pos,2) == "<=" ) { pos+=2; yylloc.last_column+=2; return LE; }

else if( prog.substr(pos,2) == "==" ) { pos+=2; yylloc.last_column+=2; return EQ; }

else if( prog.substr(pos,2) == "!=" ) { pos+=2; yylloc.last_column+=2; return NE; }

else if( prog.substr(pos,2) == "+=" ) { pos+=2; yylloc.last_column+=2; return ADDEQ; }

else if( prog.substr(pos,2) == "-=" ) { pos+=2; yylloc.last_column+=2; return SUBEQ; }

else if( prog.substr(pos,2) == "*=" ) { pos+=2; yylloc.last_column+=2; return MULEQ; }

else if( prog.substr(pos,2) == "/=" ) { pos+=2; yylloc.last_column+=2; return DIVEQ; }

else { pos++; yylloc.last_column++; }

return c;

}

}

Модуль “BlockCalc” підсистеми “Контролери”;

Модуль “BlockCalc” призначено для створення обчислень на мові блокових схем. Файли у яких реалізовано модуль “BlockCalc” приведені у таблиці 2.

Таблиця 2. Файли модуля "BlockCalc"

Файл	Опис
virtual.h	Визначення корінних об'єктів модуля.
virtual.cpp	Корінні об'єкти модуля.
block.h	Визначення об'єкту блоку.
block.cpp	Об'єкт блоку.

Рис. 3. Статична діаграма класів модуля "BlockCalc" Модуль “BlockCalc” представлено декількома об'єктами(класами). Статичну діаграму об'єктів модуля “BlockCalc” та взаємозв'язки між ними наведено на рис. 3.

Вміст файлу virtual.h

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#ifndef VIRTUAL_H

#define VIRTUAL_H

#include <string>

#include <vector>

#include <ttipcontroller.h>

#include <tparamcontr.h>

#include "block.h"

using std::string;

using std::vector;

namespace Virtual

{

//class TConfig;

class TipContr;

class Contr: public TController

{

friend class Block;

public:

Contr( string name_c, const TBDS::SName &bd, ::TElem *cfgelem );

~Contr();

void load( );

void save( );

void start( );

void stop( );

void enable_( );

void disable_( );

TParamContr *ParamAttach( const string &name, int type );

int period() { return m_per; }

int iterate() { return m_iter; }

//Scheme's functions

void blkList( vector<string> &ls )	{ chldList(m_bl,ls); }

bool blkPresent( const string &id )	{ return chldPresent(m_bl,id); }

void blkAdd( const string &id );

void blkDel( const string &id )	{ chldDel(m_bl,id); }

AutoHD<Block> blkAt( const string &id )	{ return chldAt(m_bl,id); }

int res()	{ return hd_res; }

protected:

//================== Controll functions ========================

void cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd );

AutoHD<TCntrNode> ctrAt( const string &br );

void loadV( );

void saveV( );

void freeV( );

//Process stat

void blkProc( const string & id, bool val );

void postDisable(int flag);

private:

static void *Task(void *);

private:

bool	endrun;	// Command for stop task

int	&m_per;	// ms

int	&m_iter;

pthread_t pthr_tsk;

int	m_bl;

vector< AutoHD<Block> >	clc_blks;	// Calc blocks HD

double	tm_calc;	// Scheme's calc time

int	hd_res;	//Resource for process block

};

class Prm : public TParamContr

{

public:

Prm( string name, TTipParam *tp_prm );

void enable();

void disable();

private:

void preDisable(int flag);

//================== Controll functions ========================

void cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd );

void vlSet( TVal &val );

void vlGet( TVal &val );

private:

string &m_blck;	//Assign block

string &m_io;	//Assign block io

TElem v_el;	//Values elem

};

class TipContr: public TTipController

{

public:

TipContr( string name );

~TipContr();

void modLoad( );

TController *ContrAttach( const string &name, const TBDS::SName &bd);

TElem &blockE()	{ return(blk_el); }

TElem &blockIOE()	{ return(blkio_el); }

protected:

//================== Controll functions ========================

void cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd );

AutoHD<TCntrNode> ctrAt( const string &br );

private:

void postEnable( );

void preDisable(int flag);

string optDescr( );

void loadBD();

void saveBD();

private:

TElem	blk_el;

TElem blkio_el;

};

extern TipContr *mod;

} //End namespace virtual

#endif //VIRTUAL_H

Вміст файлу virtual.cpp

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#include <getopt.h>

#include <unistd.h>

#include <sys/time.h>

#include <sys/times.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <signal.h>

#include <math.h>

#include <terror.h>

#include <tsys.h>

#include <resalloc.h>

#include <tmess.h>

#include <tconfig.h>

#include <tvalue.h>

#include <tparam.h>

#include <tparams.h>

#include <ttiparam.h>

#include "virtual.h"

//============ Modul info! =====================================================

#define MOD_ID "BlockCalc"

#define MOD_NAME "Block based calculator"

#define MOD_TYPE "Controller"

#define VER_TYPE VER_CNTR

#define VERSION "0.7.1"

#define AUTORS "Roman Savochenko"

#define DESCRIPTION "Allow block based calculator."

#define LICENSE "GPL"

//==============================================================================

Virtual::TipContr *Virtual::mod;

extern "C"

{

TModule::SAt module( int n_mod )

{

TModule::SAt AtMod;

if(n_mod==0)

{

AtMod.id	= MOD_ID;

AtMod.type = MOD_TYPE;

AtMod.t_ver = VER_TYPE;

}

else

AtMod.id	= "";

return( AtMod );

}

TModule *attach( const TModule::SAt &AtMod, const string &source )

{

Virtual::TipContr *self_addr = NULL;

if( AtMod.id == MOD_ID && AtMod.type == MOD_TYPE && AtMod.t_ver == VER_TYPE )

self_addr = Virtual::mod = new Virtual::TipContr( source );

return ( self_addr );

}

}

using namespace Virtual;

//======================================================================

//==== TipContr ========================================================

//======================================================================

TipContr::TipContr( string name )

{

mId	= MOD_ID;

mName = MOD_NAME;

mType	= MOD_TYPE;

mVers	= VERSION;

mAutor	= AUTORS;

mDescr	= DESCRIPTION;

mLicense	= LICENSE;

mSource	= name;

}

TipContr::~TipContr()

{

nodeDelAll();

}

string TipContr::optDescr( )

{

char buf[STR_BUF_LEN];

snprintf(buf,sizeof(buf),I18N(

"======================= The module <%s:%s> options =======================\n"

"---------- Parameters of the module section <%s> in config file ----------\n"),

MOD_TYPE,MOD_ID,nodePath().c_str());

return(buf);

}

void TipContr::modLoad()

{

//========== Load parameters from command line ============

int next_opt;

char *short_opt="h";

struct option long_opt[] =

{

{"help" ,0,NULL,'h'},

{NULL ,0,NULL,0 }

};

optind=opterr=0;

do

{

next_opt=getopt_long(SYS->argc,(char * const *)SYS->argv,short_opt,long_opt,NULL);

switch(next_opt)

{

case 'h': fprintf(stdout,optDescr().c_str()); break;

case -1 : break;

}

} while(next_opt != -1);

//========== Load parameters from config file =============

}

void TipContr::postEnable()

{

TModule::postEnable();

//Controllers BD structure

fldAdd( new TFld("PRM_BD",I18N("Parameters table"),TFld::String,0,"30","system") );

fldAdd( new TFld("BLOCK_SH",I18N("Block's table"),TFld::String,0,"30","block") );

fldAdd( new TFld("PERIOD",I18N("Calc period (ms)"),TFld::Dec,0,"5","1000","0;10000") );

fldAdd( new TFld("ITER",I18N("Iteration number into calc period"),TFld::Dec,0,"2","1","0;99") );

//Add parameter types

int t_prm = tpParmAdd("All","PRM_BD",I18N("Parameters"));

tpPrmAt(t_prm).fldAdd( new TFld("BLK",I18N("Block IO"),TFld::String,FLD_NOVAL,"10") );

tpPrmAt(t_prm).fldAdd( new TFld("IO","",TFld::String,FLD_NOVAL,"10") );

//Blok's db structure

blk_el.fldAdd( new TFld("ID",Mess->I18N("ID"),TFld::String,FLD_KEY,"10") );

blk_el.fldAdd( new TFld("NAME",Mess->I18N("Name"),TFld::String,0,"20") );

blk_el.fldAdd( new TFld("DESCR",Mess->I18N("Description"),TFld::String,0,"100") );

blk_el.fldAdd( new TFld("FUNC_LIB",Mess->I18N("Function's library"),TFld::String,0,"10") );

blk_el.fldAdd( new TFld("FUNC_ID",Mess->I18N("Function's id"),TFld::String,0,"10") );

blk_el.fldAdd( new TFld("EN",Mess->I18N("To enable"),TFld::Bool,0,"1","false") );

blk_el.fldAdd( new TFld("PROC",Mess->I18N("To process"),TFld::Bool,0,"1","false") );

//IO blok's db structure

blkio_el.fldAdd( new TFld("BLK_ID",Mess->I18N("Blok's ID"),TFld::String,FLD_KEY,"10") );

blkio_el.fldAdd( new TFld("ID",Mess->I18N("IO ID"),TFld::String,FLD_KEY,"10") );

blkio_el.fldAdd( new TFld("TLNK",Mess->I18N("Link's type"),TFld::Dec,0,"2") );

blkio_el.fldAdd( new TFld("O1",Mess->I18N("Object level 1"),TFld::String,0,"20") );

blkio_el.fldAdd( new TFld("O2",Mess->I18N("Object level 2"),TFld::String,0,"20") );

blkio_el.fldAdd( new TFld("O3",Mess->I18N("Object level 3"),TFld::String,0,"20") );

blkio_el.fldAdd( new TFld("VAL",Mess->I18N("Link's value"),TFld::String,0,"20") );

}

void TipContr::preDisable(int flag)

{

vector<string> lst;

list(lst);

for(int i_cnt = 0; i_cnt < lst.size(); i_cnt++)

if( at(lst[i_cnt]).at().startStat() )

at(lst[i_cnt]).at().stop( );

for(int i_cnt = 0; i_cnt < lst.size(); i_cnt++)

if( at(lst[i_cnt]).at().enableStat() )

at(lst[i_cnt]).at().disable( );

}

TController *TipContr::ContrAttach( const string &name, const TBDS::SName &bd)

{

return( new Contr(name,bd,this));

}

void TipContr::loadBD()

{

}

void TipContr::saveBD()

{

}

//================== Controll functions ========================

void TipContr::cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd )

{

if( cmd==TCntrNode::Info )

{

TTipController::cntrCmd_( a_path, opt, cmd );

ctrMkNode("fld",opt,a_path.c_str(),"/help/g_help",Mess->I18N("Options help"),0440,0,0,"str")->

attr_("cols","90")->attr("rows","5");

}

else if( cmd==TCntrNode::Get )

{

if( a_path == "/help/g_help" )	ctrSetS( opt, optDescr() );

else TTipController::cntrCmd_( a_path, opt, cmd );

}

else if( cmd==TCntrNode::Set )

TTipController::cntrCmd_( a_path, opt, cmd );

}

AutoHD<TCntrNode> TipContr::ctrAt( const string &br )

{

return TTipController::ctrAt( br );

}

//======================================================================

//==== Contr

//======================================================================

Contr::Contr( string name_c, const TBDS::SName &bd, ::TElem *cfgelem) :

::TController(name_c, bd, cfgelem), endrun(false), tm_calc(0.0),

m_per(cfg("PERIOD").getId()), m_iter(cfg("ITER").getId())

{

cfg("PRM_BD").setS(name_c+"_prm");

cfg("BLOCK_SH").setS(name_c+"_blocks");

hd_res = ResAlloc::resCreate();

m_bl = grpAdd();

}

Contr::~Contr()

{

ResAlloc::resDelete(hd_res);

}

void Contr::postDisable(int flag)

{

if( run_st ) stop();

try

{

if( flag )

{

AutoHD<TBDS> bds = owner().owner().owner().db();

//Delete parameter's tables

bool to_open = false;

if( !((TTipBD &)bds.at().modAt(BD().tp).at()).openStat(BD().bd) )

{

to_open = true;

((TTipBD &)bds.at().modAt(BD().tp).at()).open(BD().bd,false);

}

((TTipBD &)bds.at().modAt(BD().tp).at()).at(BD().bd).at().del(cfg("BLOCK_SH").getS());

((TTipBD &)bds.at().modAt(BD().tp).at()).at(BD().bd).at().del(cfg("BLOCK_SH").getS()+"_io");

if( to_open ) ((TTipBD &)bds.at().modAt(BD().tp).at()).close(BD().bd);

}

}catch(TError err)

{ Mess->put(nodePath().c_str(),TMess::Error,err.mess.c_str()); }

TController::postDisable(flag);

}

void Contr::load( )

{

TController::load();

if( en_st )	loadV();

}

void Contr::save( )

{

TController::save();

if( en_st ) saveV();

}

void Contr::start( )

{

pthread_attr_t pthr_attr;

struct sched_param prior;

TController::start();

if( !run_st )

{

//Make process all bloks

vector<string> lst;

blkList(lst);

for( int i_l = 0; i_l < lst.size(); i_l++ )

if( blkAt(lst[i_l]).at().toEnable() )	blkAt(lst[i_l]).at().enable(true);

for( int i_l = 0; i_l < lst.size(); i_l++ )

if( blkAt(lst[i_l]).at().toProcess() )	blkAt(lst[i_l]).at().process(true);

//Make process task

pthread_attr_init(&pthr_attr);

if(SYS->user() == "root")

{

prior.__sched_priority=10;

pthread_attr_setschedpolicy(&pthr_attr,SCHED_FIFO);

pthread_attr_setschedparam(&pthr_attr,&prior);

Mess->put(nodePath().c_str(),TMess::Info,mod->I18N("Start into realtime mode!"));

}

else pthread_attr_setschedpolicy(&pthr_attr,SCHED_OTHER);

pthread_create(&pthr_tsk,&pthr_attr,Task,this);

pthread_attr_destroy(&pthr_attr);

if( TSYS::eventWait( run_st, true, nodePath()+"start",5) )

throw TError(nodePath().c_str(),mod->I18N("Controller no started!"));

}

}

void Contr::stop( )

{

TController::stop();

//Make process all bloks

vector<string> lst;

blkList(lst);

for( int i_l = 0; i_l < lst.size(); i_l++ )

if( blkAt(lst[i_l]).at().process() )

blkAt(lst[i_l]).at().process(false);

if( run_st )

{

endrun = true;

pthread_kill(pthr_tsk, SIGALRM);

if( TSYS::eventWait( run_st, false, nodePath()+"stop",5) )

throw TError(nodePath().c_str(),mod->I18N("Controller no stoped!"));

pthread_join(pthr_tsk, NULL);

}

}

void Contr::enable_( )

{

try

{

loadV( );

vector<string> lst;

blkList(lst);

for( int i_l = 0; i_l < lst.size(); i_l++ )

if( blkAt(lst[i_l]).at().toEnable() )

blkAt(lst[i_l]).at().enable(true);

}

catch(TError err)

{

Mess->put(err.cat.c_str(),TMess::Warning,err.mess.c_str());

Mess->put(nodePath().c_str(),TMess::Warning,mod->I18N("Error load blocks."));

}

}

void Contr::disable_( )

{

try{ freeV( ); }

catch(TError err) { enable_( ); throw; }

}

void Contr::loadV( )

{

TConfig c_el(&mod->blockE());

TBDS::SName bd = BD();

bd.tbl = cfg("BLOCK_SH").getS();

AutoHD<TTable> tbl = SYS->db().at().open(bd);

int fld_cnt = 0;

while( SYS->db().at().dataSeek(tbl,mod->nodePath()+bd.tbl,fld_cnt++,c_el) )

{

string id = c_el.cfg("ID").getS();

if( !chldPresent(m_bl,id) )

{

blkAdd(id);

((TConfig &)blkAt(id).at()) = c_el;

//if( blkAt(id).at().toEnable() ) blkAt(id).at().enable(true);

}

blkAt(id).at().load();

}

if(!tbl.freeStat())

{

tbl.free();

SYS->db().at().close(bd);

}

}

void Contr::saveV( )

{

vector<string> lst;

// Save messages bd

blkList(lst);

for( int i_l = 0; i_l < lst.size(); i_l++ )

blkAt(lst[i_l]).at().save();

}

void Contr::freeV( )

{

vector<string> lst;

// Save messages bd

blkList(lst);

for( int i_l = 0; i_l < lst.size(); i_l++ )

{

try{ blkDel(lst[i_l]); }

catch(TError){ throw TError(nodePath().c_str(),mod->I18N("Can't delete block <%s>."),lst[i_l].c_str()); }

}

}

void *Contr::Task(void *contr)

{

int i_sync=0;

struct itimerval mytim; //Interval timer

long time_t1,time_t2,cnt_lost=0;

int frq = sysconf(_SC_CLK_TCK); //Count of system timer n/sek

Contr *cntr = (Contr *)contr;

#if OSC_DEBUG

Mess->put(cntr->nodePath().c_str(),TMess::Debug,Mess->I18N("Thread <%d> started!"),getpid() );

#endif

try

{

if(cntr->m_per == 0) return(NULL);

if(cntr->m_iter <= 0) cntr->m_iter = 1;

//Start interval timer

mytim.it_interval.tv_sec = 0; mytim.it_interval.tv_usec = cntr->m_per*1000;

mytim.it_value.tv_sec = 0; mytim.it_value.tv_usec = cntr->m_per*1000;

setitimer(ITIMER_REAL,&mytim,NULL);

cntr->run_st = true; cntr->endrun = false;

time_t1=times(NULL);

while( !cntr->endrun )

{

//Check calk time

unsigned long long t_cnt = SYS->shrtCnt();

ResAlloc::resRequestR(cntr->hd_res);

for(unsigned i_it = 0; i_it < cntr->m_iter; i_it++)

for(unsigned i_blk = 0; i_blk < cntr->clc_blks.size(); i_blk++)

{

try{ cntr->clc_blks[i_blk].at().calc(); }

catch(TError err)

{

Mess->put(err.cat.c_str(),TMess::Error,err.mess.c_str());

if( cntr->clc_blks[i_blk].at().errCnt() < 10 ) continue;

string blck = cntr->clc_blks[i_blk].at().id();

ResAlloc::resReleaseR(cntr->hd_res);

Mess->put(cntr->nodePath().c_str(),TMess::Error,mod->I18N("Block <%s> stoped."),blck.c_str());

cntr->blkAt(blck).at().process(false);

ResAlloc::resRequestR(cntr->hd_res);

}

}

ResAlloc::resReleaseR(cntr->hd_res);

cntr->tm_calc = 1.0e6*((double)(SYS->shrtCnt()-t_cnt))/((double)SYS->sysClk());

pause();

}

} catch(TError err)

{ Mess->put(err.cat.c_str(),TMess::Error,err.mess.c_str() ); }

cntr->clc_blks.clear();	//Clear calk blocks

//Stop interval timer

mytim.it_interval.tv_sec = mytim.it_interval.tv_usec = 0;

mytim.it_value.tv_sec = mytim.it_value.tv_usec = 0;

setitimer(ITIMER_REAL,&mytim,NULL);

cntr->run_st = false;

return(NULL);

}

TParamContr *Contr::ParamAttach( const string &name, int type )

{

return new Prm(name,&owner().tpPrmAt(type));

}

void Contr::blkAdd( const string &iid )

{

if( chldPresent(m_bl,iid) ) return;

chldAdd(m_bl,new Block( iid, this ));

}

void Contr::blkProc( const string & id, bool val )

{

unsigned i_blk;

ResAlloc res(hd_res,true);

for( i_blk = 0; i_blk < clc_blks.size(); i_blk++)

if( clc_blks[i_blk].at().id() == id ) break;

if( val && i_blk >= clc_blks.size() )

clc_blks.push_back(blkAt(id));

if( !val && i_blk < clc_blks.size()	)

clc_blks.erase(clc_blks.begin()+i_blk);

}

//======================================================================

//==== Contr

//======================================================================

void Contr::cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd )

{

if( cmd==TCntrNode::Info )

{

TController::cntrCmd_( a_path, opt, cmd );

ctrMkNode("area",opt,a_path.c_str(),"/scheme",owner().I18N("Blocks scheme"));

ctrMkNode("fld",opt,a_path.c_str(),"/scheme/ctm",owner().I18N("Calk time (usek)"),0444,0,0,"real");

ctrMkNode("list",opt,a_path.c_str(),"/scheme/sch",owner().I18N("Blocks"),0664,0,0,"br")->

attr_("idm","1")->attr_("s_com","add,del")->attr_("mode","att")->attr_("br_pref","_blk_");

}

else if( cmd==TCntrNode::Get )

{

if( a_path == "/scheme/ctm" ) ctrSetR( opt, tm_calc );

else if( a_path == "/scheme/sch" )

{

vector<string> list_el;

blkList(list_el);

opt->childClean();

for( unsigned i_f=0; i_f < list_el.size(); i_f++ )

ctrSetS( opt, blkAt(list_el[i_f]).at().name(), list_el[i_f].c_str() );

}

else TController::cntrCmd_( a_path, opt, cmd );

}

else if( cmd==TCntrNode::Set )

{

if( a_path == "/scheme/sch" )

{

if( opt->name() == "add" )

{

blkAdd(opt->attr("id"));

blkAt(opt->attr("id")).at().name(opt->text());

}

else if( opt->name() == "del" )	chldDel(m_bl,opt->attr("id"),-1,1);

}

else TController::cntrCmd_( a_path, opt, cmd );

}

}

AutoHD<TCntrNode> Contr::ctrAt( const string &br )

{

if( br.substr(0,5) == "_blk_" )	return blkAt(TSYS::strEncode(br.substr(5),TSYS::PathEl));

else return TController::ctrAt( br );

}

//======================================================================

//==== Prm

//======================================================================

Prm::Prm( string name, TTipParam *tp_prm ) :

TParamContr(name,tp_prm), v_el(name), m_blck(cfg("BLK").getSd()), m_io(cfg("IO").getSd())

{

vlAttElem(&v_el);

}

void Prm::preDisable(int flag)

{

vlDetElem(&v_el);

TParamContr::preDisable(flag);

}

void Prm::enable()

{

if( enableStat() ) return;

if( !((Contr &)owner()).blkPresent(m_blck) || ((Contr &)owner()).blkAt(m_blck).at().ioId(m_io) < 0 )

throw TError(nodePath().c_str(),mod->I18N("Block's IO not connected."));

//Init elements

unsigned char flg = FLD_DWR|FLD_DRD;

TFld::Type	tp = TFld::String;

int	io_id = ((Contr &)owner()).blkAt(m_blck).at().ioId(m_io);

if( ((Contr &)owner()).blkAt(m_blck).at().ioMode(io_id) != IO::Input )

flg |= FLD_NWR;

switch( ((Contr &)owner()).blkAt(m_blck).at().ioType(io_id) )

{

case IO::String:	tp = TFld::String;	break;

case IO::Integer:	tp = TFld::Dec;	break;

case IO::Real:	tp = TFld::Real;	break;

case IO::Boolean:	tp = TFld::Bool;	break;

}

if( !v_el.fldPresent("val") ||

v_el.fldAt(v_el.fldId("val")).type() != tp ||

v_el.fldAt(v_el.fldId("val")).flg() != flg )

{

if(v_el.fldPresent("val")) v_el.fldDel(v_el.fldId("val"));

v_el.fldAdd( new TFld("val",mod->I18N("Value"),tp,flg) );

}

TParamContr::enable();

}

void Prm::disable()

{

if( !enableStat() ) return;

TParamContr::disable();

}

void Prm::vlSet( TVal &val )

{

if( !enableStat() )	return;

try

{

int io_id = ((Contr &)owner()).blkAt(m_blck).at().ioId(m_io);

if( io_id < 0 ) disable();

else

{

switch(val.fld().type())

{

case TFld::String:

((Contr &)owner()).blkAt(m_blck).at().setS(io_id,val.getS(NULL,true));

break;

case TFld::Dec:

((Contr &)owner()).blkAt(m_blck).at().setI(io_id,val.getI(NULL,true));

break;

case TFld::Real:

((Contr &)owner()).blkAt(m_blck).at().setR(io_id,val.getR(NULL,true));

break;

case TFld::Bool:

((Contr &)owner()).blkAt(m_blck).at().setB(io_id,val.getB(NULL,true));

break;

}

}

}catch(TError err) { disable(); }

}

void Prm::vlGet( TVal &val )

{

if( !enableStat() )	return;

try

{

int io_id = ((Contr &)owner()).blkAt(m_blck).at().ioId(m_io);

if( io_id < 0 )	disable();

else

{

switch(val.fld().type())

{

case TFld::String:

val.setS(((Contr &)owner()).blkAt(m_blck).at().getS(io_id),NULL,true);

break;

case TFld::Dec:

val.setI(((Contr &)owner()).blkAt(m_blck).at().getI(io_id),NULL,true);

break;

case TFld::Real:

val.setR(((Contr &)owner()).blkAt(m_blck).at().getR(io_id),NULL,true);

break;

case TFld::Bool:

val.setB(((Contr &)owner()).blkAt(m_blck).at().getB(io_id),NULL,true);

break;

}

}

}catch(TError err) { disable(); }

}

void Prm::cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd )

{

if( cmd==TCntrNode::Info )

{

TParamContr::cntrCmd_( a_path, opt, cmd );

ctrId(opt,"/prm/cfg/BLK")->attr_("dest","select")->attr_("select","/prm/cfg/BLK_list");

ctrId(opt,"/prm/cfg/IO")->attr_("dest","select")->attr_("select","/prm/cfg/IO_list");

}

else if( cmd==TCntrNode::Get )

{

if( a_path == "/prm/cfg/BLK_list" )

{

vector<string> list;

((Contr &)owner()).blkList(list);

opt->childClean();

for( unsigned i_f=0; i_f < list.size(); i_f++ )

ctrSetS( opt, ((Contr &)owner()).blkAt(list[i_f]).at().name(), list[i_f].c_str() );

}

else if( a_path == "/prm/cfg/IO_list" )

{

if( ((Contr &)owner()).blkPresent(m_blck) )

{

vector<string> list;

opt->childClean();

AutoHD<Block> blk = ((Contr &)owner()).blkAt(m_blck);

if( blk.at().func( ) )	blk.at().ioList(list);

for( unsigned i_a=0; i_a < list.size(); i_a++ )

ctrSetS( opt, blk.at().func()->io(i_a)->name(), list[i_a].c_str() );

}

}

else TParamContr::cntrCmd_( a_path, opt, cmd );

}

else if( cmd==TCntrNode::Set )

TParamContr::cntrCmd_( a_path, opt, cmd );

}

Вміст файлу block.h

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#ifndef BLOCK_H

#define BLOCK_H

#include <string>

#include <vector>

#include <tparam.h>

#include <tfunctions.h>

using std::string;

using std::vector;

namespace Virtual

{

//Function block

class Contr;

class Block : public TCntrNode, public TValFunc, public TConfig

{

public:

//Link types:

// DIS	- Disable IO

// FREE - Free link or constant

// I_LOC - Input interblocks local link

// I_GLB - Input interblocks global link

// I_PRM - Input parameter link

// O_PRM - Output parameter link

enum LnkT {DIS, FREE, I_LOC, I_GLB, I_PRM, O_PRM};

//Link comands

enum LnkCmd {INIT, DEINIT, SET};

Block( const string &iid, Contr *iown );

~Block();

//Block's parameters

string &id() { return m_id; }

string &name() { return m_name; }

string &descr() { return m_descr; }

int	errCnt(){ return err_cnt; }

void name( const string &name ){ m_name = name; }

void descr( const string &dscr ){ m_descr = dscr; }

//What make for init.

bool toEnable()	{ return m_to_en; }

bool toProcess(){ return m_to_prc; }

//Enable stat

bool enable()	{ return m_enable; }

void enable( bool val, bool dis_fnc = true );

//Process stat

bool process()	{ return m_process; }

void process( bool val );

//Link IO

LnkT link( unsigned id );

void link( unsigned id, LnkCmd cmd, LnkT lnk = FREE, const string &o1 = "", const string &o2 = "", const string &o3 = "" );

//Calc block

void calc( );

//DB commands

void load( );

void save( );

void preIOCfgChange();

void postIOCfgChange();

string getS( unsigned id );

int getI( unsigned id );

double getR( unsigned id );

bool getB( unsigned id );

Contr &owner()	{ return *(Contr *)nodePrev(); }

protected:

void loadIO( unsigned i_ln );

void saveIO( unsigned i_ln );

string nodeName(){ return m_id; }

//================== Controll functions ========================

void cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd );

void postDisable(int flag); //Delete all DB if flag 1

private:

//Define input interblock link structure

struct SLIBlk

{

string	cnt;	//External virtual controller

string	blk;	//Block

string	id;	//IO identificator

AutoHD<Block>	w_bl;	//Block AutoHD

unsigned	w_id;	//IO index

};

//Define parameter link structure

struct SLPrm

{

string prm; //Parameter

string atr; //Atribut

AutoHD<TParam>	w_prm; //Param AutoHD

};

//Define link structures

struct SLnk

{

LnkT tp;	//Link type

union

{

SLIBlk	*iblk;	//Input interblock link structure

SLPrm	*prm;	//Parameter link structure

};

};

vector<SLnk>	m_lnk;

bool	m_enable, m_process;	//Processing block

int	m_sw_mode;	//Show mode (0-values; 1-links; 2-borders)

bool	m_sw_hide;	//Show hiden

//AutoHD<TFunction> u_func;

string	&m_id, &m_name, &m_descr;

string	&m_lib, &m_func;

bool	&m_to_en, &m_to_prc;

int	lnk_res;	//Link resource

int	en_res;

int	err_cnt;

};

} //End namespace virtual

#endif //BLOCK_H

Вміст файлу block.cpp

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#include <tsys.h>

#include <resalloc.h>

#include <tmess.h>

#include <tparams.h>

#include <math.h>

#include "virtual.h"

#include "block.h"

using namespace Virtual;

//Function block

Block::Block( const string &iid, Contr *iown ) :

TCntrNode(iown), TConfig( &((TipContr &)iown->owner()).blockE() ), TValFunc(iid+"_block",NULL),

m_enable(false), m_process(false), m_sw_mode(0), m_sw_hide(false),

m_id(cfg("ID").getSd()), m_name(cfg("NAME").getSd()), m_descr(cfg("DESCR").getSd()),

m_lib(cfg("FUNC_LIB").getSd()), m_func(cfg("FUNC_ID").getSd()),

m_to_en(cfg("EN").getBd()), m_to_prc(cfg("PROC").getBd())

{

m_id = iid;

lnk_res = ResAlloc::resCreate();

en_res = ResAlloc::resCreate();

ResAlloc::resRequestW(en_res);

}

Block::~Block( )

{

if( enable() ) enable(false);

ResAlloc::resReleaseW(en_res);

ResAlloc::resDelete(lnk_res);

ResAlloc::resDelete(en_res);

}

void Block::postDisable(int flag)

{

try

{

if( flag )

{

AutoHD<TBDS> bds = owner().owner().owner().owner().db();

//Delete block from BD

TBDS::SName tbl = owner().BD();

tbl.tbl = owner().cfg("BLOCK_SH").getS();

AutoHD<TTable> dbt = bds.at().open(tbl);

if( !dbt.freeStat() )

{

dbt.at().fieldDel(*this);

dbt.free();

bds.at().close(tbl);

}

//Delete block's IO from BD

TConfig cfg(&((TipContr &)owner().owner()).blockIOE());

tbl.tbl = owner().cfg("BLOCK_SH").getS()+"_io";

dbt = bds.at().open(tbl);

if( !dbt.freeStat() )

{

int fld_cnt = 0;

while( dbt.at().fieldSeek(fld_cnt++,cfg) )

if( id() == cfg.cfg("BLK_ID").getS() )

{

dbt.at().fieldDel(cfg);

fld_cnt--;

}

dbt.free();

bds.at().close(tbl);

}

}

}catch(TError err)

{ Mess->put(err.cat.c_str(),TMess::Error,err.mess.c_str()); }

}

void Block::load( )

{

TBDS::SName bd = owner().BD();

bd.tbl = owner().cfg("BLOCK_SH").getS();

AutoHD<TTable> tbl = SYS->db().at().open(bd);

SYS->db().at().dataGet(tbl,mod->nodePath()+bd.tbl,*this);

if( !tbl.freeStat() )

{

tbl.free();

SYS->db().at().close(bd);

}

//Load io config

if( enable() )

{

for( int i_ln = 0; i_ln < m_lnk.size(); i_ln++ )

if( m_lnk[i_ln].tp != 0 )

try{ loadIO(i_ln); }

catch(TError err){ Mess->put(err.cat.c_str(),TMess::Error,err.mess.c_str()); }

}

}

void Block::save( )

{

TBDS::SName bd = owner().BD();

bd.tbl = owner().cfg("BLOCK_SH").getS();

AutoHD<TTable> tbl = SYS->db().at().open(bd,true);

SYS->db().at().dataSet(tbl,mod->nodePath()+bd.tbl,*this);

if( !tbl.freeStat() )

{

tbl.free();

SYS->db().at().close(bd);

}

//Save io config

if( enable() )

{

for( int i_ln = 0; i_ln < m_lnk.size(); i_ln++ )

if( m_lnk[i_ln].tp != 0 )

try{ saveIO(i_ln); }

catch(TError err){ Mess->put(err.cat.c_str(),TMess::Error,err.mess.c_str()); }

}

}

void Block::loadIO( unsigned i_ln )

{

if( !func() || m_lnk[i_ln].tp == 0 )	return;

TConfig cfg(&mod->blockIOE());

cfg.cfg("BLK_ID").setS(id());

cfg.cfg("ID").setS(func()->io(i_ln)->id());

TBDS::SName bd = owner().BD();

bd.tbl = owner().cfg("BLOCK_SH").getS()+"_io";

AutoHD<TTable> tbl = SYS->db().at().open(bd);

SYS->db().at().dataGet(tbl,mod->nodePath()+bd.tbl,cfg);

if( !tbl.freeStat() )

{

tbl.free();

SYS->db().at().close(bd);

}

//Link type

LnkT tp = (LnkT)cfg.cfg("TLNK").getI();

//link( i_ln, (LnkT)cfg.cfg("TLNK").getI() );

//Value

string val = cfg.cfg("VAL").getS();

if(ioType(i_ln) == IO::String ) setS(i_ln,val);

else if(ioType(i_ln) == IO::Integer )	setI(i_ln,atoi(val.c_str()));

else if(ioType(i_ln) == IO::Real )	setR(i_ln,atof(val.c_str()));

else if(ioType(i_ln) == IO::Boolean ) setB(i_ln,atoi(val.c_str()));

//Config of link

link(i_ln,SET,tp,cfg.cfg("O1").getS(),cfg.cfg("O2").getS(),cfg.cfg("O3").getS());

}

void Block::saveIO( unsigned i_ln )

{

if( !enable() || m_lnk[i_ln].tp == 0 ) return;

TConfig cfg(&mod->blockIOE());

cfg.cfg("BLK_ID").setS(id());

cfg.cfg("ID").setS(func()->io(i_ln)->id());

TBDS::SName bd = owner().BD();

bd.tbl = owner().cfg("BLOCK_SH").getS()+"_io";

//Link type

cfg.cfg("TLNK").setI(m_lnk[i_ln].tp);

//Value

string val;

if(ioType(i_ln) == IO::String )	val = getS(i_ln);

else if(ioType(i_ln) == IO::Integer )	val = TSYS::int2str(getI(i_ln));

else if(ioType(i_ln) == IO::Real )	val = TSYS::real2str(getR(i_ln));

else if(ioType(i_ln) == IO::Boolean )	val = TSYS::int2str(getB(i_ln));

cfg.cfg("VAL").setS(val);

//Config of link

switch(m_lnk[i_ln].tp)

{

case I_LOC:

cfg.cfg("O1").setS(m_lnk[i_ln].iblk->blk);

cfg.cfg("O2").setS(m_lnk[i_ln].iblk->id);

break;

case I_GLB:

cfg.cfg("O1").setS(m_lnk[i_ln].iblk->cnt);

cfg.cfg("O2").setS(m_lnk[i_ln].iblk->blk);

cfg.cfg("O3").setS(m_lnk[i_ln].iblk->id);

break;

case I_PRM:

case O_PRM:

cfg.cfg("O1").setS(m_lnk[i_ln].prm->prm);

cfg.cfg("O2").setS(m_lnk[i_ln].prm->atr);

break;

}

AutoHD<TTable> tbl = SYS->db().at().open(bd,true);

SYS->db().at().dataSet(tbl,mod->nodePath()+bd.tbl,cfg);

if( !tbl.freeStat() )

{

tbl.free();

SYS->db().at().close(bd);

}

}

void Block::enable( bool val, bool dis_fnc )

{

//Enable

if( val && !m_enable )

{

if( !func() )

func( &owner().owner().owner().owner().func().at().at(m_lib).at().at(m_func).at() );

//else enable(false,false);

//Init links

for( int i_ln = 0; i_ln < m_val.size(); i_ln++ )

{

m_lnk.push_back( SLnk() );

if( m_val[i_ln].tp )

{

m_lnk[i_ln].tp = FREE;

//Load IO

try{ loadIO(i_ln); }

catch(TError err){ Mess->put(err.cat.c_str(),TMess::Error,err.mess.c_str()); }

}

else m_lnk[i_ln].tp = DIS;

}

ResAlloc::resReleaseW(en_res);

}

//Disable

else if( !val && m_enable )

{

if( process() ) process(false);

ResAlloc::resRequestW(en_res);

for( unsigned i_ln = 0; i_ln < m_lnk.size(); i_ln++ )

link(i_ln,SET,FREE);

m_lnk.clear();

//Free func

if( dis_fnc ) func(NULL);

}

m_enable = val;

}

void Block::process( bool val )

{

if( val && !enable() ) enable(true);

//Connect links

if( val && !process() )

{

for( int i_ln = 0; i_ln < m_lnk.size(); i_ln++ )

link( i_ln, INIT );

owner().blkProc( id(), val );

}

//Disconnect links

if( !val && process() )

{

for( int i_ln = 0; i_ln < m_lnk.size(); i_ln++ )

link( i_ln, DEINIT );

owner().blkProc( id(), val );

}

m_process = val;

}

Block::LnkT Block::link( unsigned iid )

{

if( iid >= m_lnk.size() || m_lnk[iid].tp == DIS )

throw TError(nodePath().c_str(),mod->I18N("Link %d error!"),iid);

return m_lnk[iid].tp;

}

void Block::link( unsigned iid, LnkCmd cmd, LnkT lnk, const string &o1, const string &o2, const string &o3 )

{

string lo1, lo2, lo3;

ResAlloc res(lnk_res,true);

if( iid >= m_lnk.size() || m_lnk[iid].tp == DIS )

throw TError(nodePath().c_str(),mod->I18N("Link %d error!"),iid);

//Change type link

if( cmd == SET && lnk != m_lnk[iid].tp )

{

//Free old structures

switch(m_lnk[iid].tp)

{

case I_LOC: case I_GLB:	delete m_lnk[iid].iblk;	break;

case I_PRM: case O_PRM:	delete m_lnk[iid].prm;	break;

}

//Make new structures

switch(lnk)

{

case I_LOC: case I_GLB:	m_lnk[iid].iblk = new SLIBlk;	break;

case I_PRM: case O_PRM:	m_lnk[iid].prm = new SLPrm;	break;

}

m_lnk[iid].tp = lnk;

}

//Connect new link and init

if( cmd == INIT || cmd == SET )

switch(m_lnk[iid].tp)

{

case I_LOC:

if( cmd == SET )

{

m_lnk[iid].iblk->blk = o1;

m_lnk[iid].iblk->id = o2;

}

if( cmd == INIT || process() )

{

lo1 = m_lnk[iid].iblk->blk;

lo2 = m_lnk[iid].iblk->id;

if( owner().blkPresent(lo1) && owner().blkAt(lo1).at().ioId(lo2) >= 0 )

{

m_lnk[iid].iblk->w_bl = owner().blkAt(lo1);

m_lnk[iid].iblk->w_id = m_lnk[iid].iblk->w_bl.at().ioId(lo2);

}

}

break;

case I_GLB:

if( cmd == SET )

{

m_lnk[iid].iblk->cnt = o1;

m_lnk[iid].iblk->blk = o2;

m_lnk[iid].iblk->id = o3;

}

if( cmd == INIT || process() )

{

lo1 = m_lnk[iid].iblk->cnt;

lo2 = m_lnk[iid].iblk->blk;

lo3 = m_lnk[iid].iblk->id;

if( owner().owner().present(lo1) &&

((Contr &)owner().owner().at(lo1).at()).blkPresent(lo2) &&

((Contr &)owner().owner().at(lo1).at()).blkAt(lo2).at().ioId(lo3) >= 0 )

{

m_lnk[iid].iblk->w_bl = ((Contr &)owner().owner().at(lo1).at()).blkAt(lo2);

m_lnk[iid].iblk->w_id = m_lnk[iid].iblk->w_bl.at().ioId(lo3);

}

}

break;

case I_PRM: case O_PRM:

if( cmd == SET )

{

m_lnk[iid].prm->prm = o1;

m_lnk[iid].prm->atr = o2;

}

if( cmd == INIT || process() )

{

AutoHD<TParamS> prms = owner().owner().owner().owner().param();

lo1 = m_lnk[iid].prm->prm;

lo2 = m_lnk[iid].prm->atr;

if( prms.at().present(lo1) && prms.at().at(lo1).at().at().vlPresent(lo2) )

m_lnk[iid].prm->w_prm = prms.at().at(lo1);

}

break;

}

//Disconnect

if( cmd == DEINIT )

switch(m_lnk[iid].tp)

{

case I_LOC: case I_GLB:	m_lnk[iid].iblk->w_bl.free();	break;

case I_PRM: case O_PRM:	m_lnk[iid].prm->w_prm.free();	break;

}

}

void Block::calc( )

{

//Get values from input links

ResAlloc::resRequestR(lnk_res);

try

{

for( unsigned i_ln=0; i_ln < m_lnk.size(); i_ln++ )

switch( m_lnk[i_ln].tp )

{

case I_LOC: case I_GLB:

{

SLIBlk *lc = m_lnk[i_ln].iblk;

if( lc->w_bl.freeStat() || !lc->w_bl.at().enable() )	continue;

switch(ioType(i_ln))

{

case IO::String:	setS(i_ln,lc->w_bl.at().getS(lc->w_id));	break;

case IO::Integer:	setI(i_ln,lc->w_bl.at().getI(lc->w_id));	break;

case IO::Real:	setR(i_ln,lc->w_bl.at().getR(lc->w_id));	break;

case IO::Boolean:	setB(i_ln,lc->w_bl.at().getB(lc->w_id));	break;

}

break;

}

case I_PRM:

{

if( m_lnk[i_ln].prm->w_prm.freeStat() )	continue;

AutoHD<TVal> pvl = m_lnk[i_ln].prm->w_prm.at().at().vlAt(m_lnk[i_ln].prm->atr);

switch(ioType(i_ln))

{

case IO::String:	setS(i_ln,pvl.at().getS());	break;

case IO::Integer:	setI(i_ln,pvl.at().getI());	break;

case IO::Real:	setR(i_ln,pvl.at().getR());	break;

case IO::Boolean:	setB(i_ln,pvl.at().getB());	break;

}

break;

}

}

}catch(TError err)

{

err_cnt++;

ResAlloc::resReleaseR(lnk_res);

throw TError(nodePath().c_str(),mod->I18N("Error read block's <%s> links."),id().c_str());

}

ResAlloc::resReleaseR(lnk_res);

//Calc function

try{ TValFunc::calc( ); }

catch(TError err)

{

err_cnt++;

throw TError(nodePath().c_str(),mod->I18N("Error calc block <%s>."),id().c_str());

}

//Put values to output links

ResAlloc::resRequestR(lnk_res);

try

{

for( unsigned i_ln=0; i_ln < m_lnk.size(); i_ln++ )

if( m_lnk[i_ln].tp == O_PRM && !m_lnk[i_ln].prm->w_prm.freeStat() )

{

AutoHD<TVal> pvl = m_lnk[i_ln].prm->w_prm.at().at().vlAt(m_lnk[i_ln].prm->atr);

switch(ioType(i_ln))

{

case IO::String:	pvl.at().setS(getS(i_ln));	break;

case IO::Integer:	pvl.at().setI(getI(i_ln));	break;

case IO::Real:	pvl.at().setR(getR(i_ln));	break;

case IO::Boolean:	pvl.at().setB(getB(i_ln));	break;

}

}

}catch(TError err)

{

err_cnt++;

ResAlloc::resReleaseR(lnk_res);

throw TError(nodePath().c_str(),mod->I18N("Error write block's <%s> links."),id().c_str());

}

ResAlloc::resReleaseR(lnk_res);

err_cnt=0;

}

void Block::preIOCfgChange()

{

if( enable() ) enable(false,false);

TValFunc::preIOCfgChange();

}

void Block::postIOCfgChange()

{

TValFunc::postIOCfgChange();

if(toEnable())	enable(true);

if(toProcess())	process(true);

}

void Block::cntrCmd_( const string &a_path, XMLNode *opt, TCntrNode::Command cmd )

{

vector<string> list;

switch(cmd)

{

case TCntrNode::Info:

ctrMkNode("oscada_cntr",opt,a_path.c_str(),"/",mod->I18N("Block: ")+id());

ctrMkNode("area",opt,a_path.c_str(),"/blck",mod->I18N("Block"));

ctrMkNode("area",opt,a_path.c_str(),"/blck/st",mod->I18N("State"));

ctrMkNode("fld",opt,a_path.c_str(),"/blck/st/en",mod->I18N("Enable"),0664,0,0,"bool");

if( owner().startStat() )

ctrMkNode("fld",opt,a_path.c_str(),"/blck/st/prc",mod->I18N("Process"),0664,0,0,"bool");

ctrMkNode("area",opt,a_path.c_str(),"/blck/cfg",mod->I18N("Config"));

ctrMkNode("fld",opt,a_path.c_str(),"/blck/cfg/id",mod->I18N("Id"),0444,0,0,"str");

ctrMkNode("fld",opt,a_path.c_str(),"/blck/cfg/name",mod->I18N("Name"),0664,0,0,"str");

ctrMkNode("fld",opt,a_path.c_str(),"/blck/cfg/descr",mod->I18N("Description"),0664,0,0,"str")->

attr_("cols","90")->attr_("rows","4");

ctrMkNode("fld",opt,a_path.c_str(),"/blck/cfg/toen",mod->I18N("To enable"),0664,0,0,"bool");

ctrMkNode("fld",opt,a_path.c_str(),"/blck/cfg/toprc",mod->I18N("To process"),0664,0,0,"bool");

ctrMkNode("area",opt,a_path.c_str(),"/blck/cfg/func",mod->I18N("Function"));

ctrMkNode("fld",opt,a_path.c_str(),"/blck/cfg/func/lib",mod->I18N("Library"),(!func())?0664:0444,0,0,"str")->

attr_("dest","select")->attr("select","/blck/libs");

ctrMkNode("fld",opt,a_path.c_str(),"/blck/cfg/func/id",mod->I18N("Function"),(!func())?0664:0444,0,0,"str")->

attr_("dest","select")->attr("select","/blck/fncs");

ctrMkNode("comm",opt,a_path.c_str(),"/blck/cfg/func/lnk",mod->I18N("Go to function"),0550,0,0,"lnk");

ctrMkNode("comm",opt,a_path.c_str(),"/blck/cfg/load",mod->I18N("Load"),0550);

ctrMkNode("comm",opt,a_path.c_str(),"/blck/cfg/save",mod->I18N("Save"),0550);

if( enable() )

{

ctrMkNode("area",opt,a_path.c_str(),"/lio",mod->I18N("IO"));

ctrMkNode("area",opt,a_path.c_str(),"/lio/show",mod->I18N("Show"));

ctrMkNode("fld",opt,a_path.c_str(),"/lio/show/mode",mod->I18N("Show"),0664,0,0,"dec")->

attr_("dest","select")->attr("select","/lio/show/mode_lst");

ctrMkNode("fld",opt,a_path.c_str(),"/lio/show/hide",mod->I18N("Hiden"),0664,0,0,"bool");

ctrMkNode("area",opt,a_path.c_str(),"/lio/io",mod->I18N("IO"));

//Put IO links

vector<string> list;

ioList(list);

for( int i_io = 0; i_io < list.size(); i_io++ )

{

int id = ioId(list[i_io]);

if( ioHide(id) && !m_sw_hide ) continue;

//Add values

if( m_sw_mode == 0 )

{

char *tip;

switch(ioType(id))

{

case IO::String:	tip = "str";	break;

case IO::Integer:	tip = "dec";	break;

case IO::Real:	tip = "real";	break;

case IO::Boolean:	tip = "bool";	break;

}

ctrMkNode("fld",opt,a_path.c_str(),(string("/lio/io/0|")+list[i_io]).c_str(),

func()->io(id)->name().c_str(),(m_lnk[id].tp != FREE)?0444:0664,0,0,tip);

continue;

}

else if( m_sw_mode == 1 )

{

//Add link's type

ctrMkNode("fld",opt,a_path.c_str(),(string("/lio/io/1|")+list[i_io]).c_str(),

func()->io(id)->name().c_str(),0664,0,0,"str")->attr_("dest","select")->

attr_("select",(ioMode(id) != IO::Input)?"/lio/otp":"/lio/itp");

switch(m_lnk[id].tp)

{

case I_LOC:

//Local block

ctrMkNode("fld",opt,a_path.c_str(),(string("/lio/io/2|")+list[i_io]).c_str(),"",0664,0,0,"str")->

attr_("dest","select")->attr_("select","/lio/blk");

//Local block io

ctrMkNode("fld",opt,a_path.c_str(),(string("/lio/io/3|")+list[i_io]).c_str(),"",0664,0,0,"str")->

attr_("dest","select")->attr_("select",(string("/lio/io/4|")+list[i_io]).c_str());

break;

case I_GLB:

//Virtual controller

ctrMkNode("fld",opt,a_path.c_str(),(string("/lio/io/2|")+list[i_io]).c_str(),"",0664,0,0,"str")->

attr_("dest","select")->attr_("select","/lio/vcntr");

//Virtual controller block

ctrMkNode("fld",opt,a_path.c_str(),(string("/lio/io/3|")+list[i_io]).c_str(),"",0664,0,0,"str")->

attr_("dest","select")->attr_("select",(string("/lio/io/5|")+list[i_io]).c_str());

//Block's io

ctrMkNode("fld",opt,a_path.c_str(),(string("/lio/io/4|")+list[i_io]).c_str(),"",0664,0,0,"str")->

attr_("dest","select")->attr_("select",(string("/lio/io/6|")+list[i_io]).c_str());

break;

case I_PRM: case O_PRM:

//Parameter

ctrMkNode("fld",opt,a_path.c_str(),(string("/lio/io/2|")+list[i_io]).c_str(),"",0664,0,0,"str")->

attr_("dest","select")->attr_("select","/lio/prms");

// Parameter's atribut

ctrMkNode("fld",opt,a_path.c_str(),(string("/lio/io/3|")+list[i_io]).c_str(),"",0664,0,0,"str")->

attr_("dest","select")->attr_("select",(string("/lio/io/4|")+list[i_io]).c_str());

break;

}

}

}

}

break;

case TCntrNode::Get:

if( a_path == "/blck/st/en" )	ctrSetB( opt, enable() );

else if( a_path == "/blck/st/prc" )	ctrSetB( opt, process() );

else if( a_path == "/blck/cfg/id" )	ctrSetS( opt, id() );

else if( a_path == "/blck/cfg/name" )	ctrSetS( opt, name() );

else if( a_path == "/blck/cfg/descr" )	ctrSetS( opt, descr() );

else if( a_path == "/blck/cfg/toen" )	ctrSetB( opt, m_to_en );

else if( a_path == "/blck/cfg/toprc" )	ctrSetB( opt, m_to_prc );

else if( a_path == "/blck/cfg/func/lib" )	ctrSetS( opt, m_lib );

else if( a_path == "/blck/cfg/func/id" )	ctrSetS( opt, m_func );

else if( a_path == "/blck/cfg/func/lnk" )	opt->text("d_Functions/d_"+m_lib+"/d_"+m_func );

else if( a_path == "/blck/libs" )

{

owner().owner().owner().owner().func().at().list(list);

opt->childClean();

for( unsigned i_a=0; i_a < list.size(); i_a++ )

ctrSetS( opt, owner().owner().owner().owner().func().at().at(list[i_a]).at().name(),list[i_a].c_str() );

}

else if( a_path == "/blck/fncs" )

{

if( owner().owner().owner().owner().func().at().present(m_lib) )

{

owner().owner().owner().owner().func().at().at(m_lib).at().list(list);

opt->childClean();

for( unsigned i_a=0; i_a < list.size(); i_a++ )

ctrSetS( opt, owner().owner().owner().owner().func().at().at(m_lib).at().at(list[i_a]).at().name(), list[i_a].c_str() );

}

}

else if( enable() )

{

if( a_path == "/lio/show/mode" )	ctrSetI( opt, m_sw_mode );

else if( a_path == "/lio/show/mode_lst" )

{

ctrSetS( opt, mod->I18N("Values"), "0" );

ctrSetS( opt, mod->I18N("Links") , "1" );

}

else if( a_path == "/lio/show/hide" )	ctrSetB( opt, m_sw_hide );

else if( a_path.substr(0,7) == "/lio/io" )

{

char lev = TSYS::pathLev(a_path,2)[0];

int id = ioId(TSYS::pathLev(a_path,2).substr(2));

if( lev == '0' )

switch(ioType(id))

{

case IO::String:	ctrSetS( opt, getS(id) );	break;

case IO::Integer:	ctrSetI( opt, getI(id) );	break;

case IO::Real:	ctrSetR( opt, getR(id) );	break;

case IO::Boolean:	ctrSetB( opt, getB(id) );	break;

}

else if( lev == '1' )

switch(m_lnk[id].tp)

{

case FREE:	ctrSetS(opt,"free");	break;

case I_LOC:	ctrSetS(opt,"loc");	break;

case I_GLB:	ctrSetS(opt,"glob");	break;

case I_PRM:

case O_PRM:	ctrSetS(opt,"prm");	break;

}

else if( m_lnk[id].tp == I_LOC )

{

if( lev == '2' )	ctrSetS(opt,m_lnk[id].iblk->blk);

else if( lev == '3' )	ctrSetS(opt,m_lnk[id].iblk->id);

else if( lev == '4' )

{

if( owner().blkPresent(m_lnk[id].iblk->blk) )

{

AutoHD<Block> blk = owner().blkAt(m_lnk[id].iblk->blk);

if( blk.at().func( ) )	blk.at().ioList(list);

for( unsigned i_a=0; i_a < list.size(); i_a++ )

ctrSetS( opt, blk.at().func()->io(i_a)->name(), list[i_a].c_str() );

}

}

}

else if( m_lnk[id].tp == I_GLB )

{

if( lev == '2' )	ctrSetS(opt,m_lnk[id].iblk->cnt);

else if( lev == '3' )	ctrSetS(opt,m_lnk[id].iblk->blk);

else if( lev == '4' )	ctrSetS(opt,m_lnk[id].iblk->id);

else if( lev == '5' )

{

if( owner().owner().present(m_lnk[id].iblk->cnt) )

{

((Contr &)owner().owner().at(m_lnk[id].iblk->cnt).at()).blkList(list);

for( unsigned i_a=0; i_a < list.size(); i_a++ )

ctrSetS( opt, ((Contr &)owner().owner().at(m_lnk[id].iblk->cnt).at()).blkAt(list[i_a]).at().name(), list[i_a].c_str() );

}

}

else if( lev == '6' )

{

if( owner().owner().present(m_lnk[id].iblk->cnt) &&

((Contr &)owner().owner().at(m_lnk[id].iblk->cnt).at()).blkPresent(m_lnk[id].iblk->blk) )

{

AutoHD<Block> blk = ((Contr &)owner().owner().at(m_lnk[id].iblk->cnt).at()).blkAt(m_lnk[id].iblk->blk);

if( blk.at().func( ) )

blk.at().ioList(list);

for( unsigned i_a=0; i_a < list.size(); i_a++ )

ctrSetS( opt, blk.at().func()->io(i_a)->name(), list[i_a].c_str() );

}

}

}

else if( m_lnk[id].tp == I_PRM || m_lnk[id].tp == O_PRM )

{

if( lev == '2' )	ctrSetS(opt,m_lnk[id].prm->prm);

else if( lev == '3' )	ctrSetS(opt,m_lnk[id].prm->atr);

else if( lev == '4' )

{

AutoHD<TParamS> prms = owner().owner().owner().owner().param();

if( prms.at().present(m_lnk[id].prm->prm) )

{

prms.at().at(m_lnk[id].prm->prm).at().at().vlList(list);

for( unsigned i_a=0; i_a < list.size(); i_a++ )

if( m_lnk[id].tp == I_PRM ||

!(prms.at().at(m_lnk[id].prm->prm).at().at().vlAt(list[i_a]).at().fld().flg()&FLD_NWR) )

ctrSetS( opt, list[i_a] );

}

}

}

}

else if( a_path == "/lio/itp" )

{

opt->childClean();

ctrSetS( opt, mod->I18N("Free"), "free" );

ctrSetS( opt, mod->I18N("Local"), "loc" );

ctrSetS( opt, mod->I18N("Global"), "glob" );

ctrSetS( opt, mod->I18N("Parameter"), "prm" );

}

else if( a_path == "/lio/otp" )

{

opt->childClean();

ctrSetS( opt, mod->I18N("Free")	,"free" );

ctrSetS( opt, mod->I18N("Parameter")	,"prm" );

}

//Local blocks

else if( a_path == "/lio/blk" )

{

owner().blkList(list);

opt->childClean();

for( unsigned i_a=0; i_a < list.size(); i_a++ )

ctrSetS( opt, owner().blkAt(list[i_a]).at().name(), list[i_a].c_str() );

}

//Virtual controllers

else if( a_path == "/lio/vcntr" )

{

owner().owner().list(list);

opt->childClean();

for( unsigned i_a=0; i_a < list.size(); i_a++ )

ctrSetS( opt, owner().owner().at(list[i_a]).at().name(), list[i_a].c_str() );

}

//Parameters

else if( a_path == "/lio/prms" )

{

owner().owner().owner().owner().param().at().list(list);

opt->childClean();

for( unsigned i_a=0; i_a < list.size(); i_a++ )

ctrSetS( opt, list[i_a] );

}

else throw TError(nodePath().c_str(),mod->I18N("Branch <%s> error!"),a_path.c_str());

}

else throw TError(nodePath().c_str(),mod->I18N("Branch <%s> error!"),a_path.c_str());

break;

case TCntrNode::Set:

if( a_path == "/blck/st/en" )	enable(ctrGetB(opt));

else if( a_path == "/blck/st/prc" )	process(ctrGetB(opt));

else if( a_path == "/blck/cfg/name" )	name(ctrGetS(opt));

else if( a_path == "/blck/cfg/descr" )	descr(ctrGetS(opt));

else if( a_path == "/blck/cfg/toen" ) m_to_en = ctrGetB(opt);

else if( a_path == "/blck/cfg/toprc" ) m_to_prc = ctrGetB(opt);

else if( a_path == "/blck/cfg/func/lib" )	m_lib = ctrGetS( opt );

else if( a_path == "/blck/cfg/func/id" )	m_func = ctrGetS( opt );

else if( a_path == "/blck/cfg/load" ) load();

else if( a_path == "/blck/cfg/save" ) save();

else if( enable() )

{

if( a_path == "/lio/show/mode" ) m_sw_mode = ctrGetI( opt );

else if( a_path == "/lio/show/hide" )	m_sw_hide = ctrGetB( opt );

else if( a_path.substr(0,7) == "/lio/io" )

{

char lev = TSYS::pathLev(a_path,2)[0];

int id = ioId(TSYS::pathLev(a_path,2).substr(2));

if( lev == '0' )

{

if(ioType(id) == IO::String)	setS(id, ctrGetS( opt ));

else if(ioType(id) == IO::Integer)	setI(id, ctrGetI( opt ));

else if(ioType(id) == IO::Real)	setR(id, ctrGetR( opt ));

else if(ioType(id) == IO::Boolean)	setB(id, ctrGetB( opt ));

}

else if( lev == '1' )

{

if( ctrGetS(opt) == "free" )	link(id,SET,FREE);

else if( ctrGetS(opt) == "loc" )	link(id,SET,I_LOC);

else if( ctrGetS(opt) == "glob" )	link(id,SET,I_GLB);

else if( ctrGetS(opt) == "prm" )

{

if( ioMode(id) != IO::Input )	link(id,SET,O_PRM);

else	link(id,SET,I_PRM);

}

}

else if( m_lnk[id].tp == I_LOC )

{

if( lev == '2' )	link(id,SET,m_lnk[id].tp,ctrGetS(opt),m_lnk[id].iblk->id);

else if( lev == '3' )	link(id,SET,m_lnk[id].tp,m_lnk[id].iblk->blk,ctrGetS(opt));

}

else if( m_lnk[id].tp == I_GLB )

{

if( lev == '2' )	link(id,SET,m_lnk[id].tp,ctrGetS(opt),m_lnk[id].iblk->blk,m_lnk[id].iblk->id);

else if( lev == '3' )	link(id,SET,m_lnk[id].tp,m_lnk[id].iblk->cnt,ctrGetS(opt),m_lnk[id].iblk->id);

else if( lev == '4' )	link(id,SET,m_lnk[id].tp,m_lnk[id].iblk->cnt,m_lnk[id].iblk->blk,ctrGetS(opt));

}

else if( m_lnk[id].tp == I_PRM || m_lnk[id].tp == O_PRM )

{

if( lev == '2' )	link(id,SET,m_lnk[id].tp,ctrGetS(opt),m_lnk[id].prm->atr);

else if( lev == '3' )	link(id,SET,m_lnk[id].tp,m_lnk[id].prm->prm,ctrGetS(opt));

}

}

else throw TError(nodePath().c_str(),mod->I18N("Branch <%s> error!"),a_path.c_str());

}

else throw TError(nodePath().c_str(),mod->I18N("Branch <%s> error!"),a_path.c_str());

break;

}

}

string Block::getS( unsigned id )

{

ResAlloc res(en_res,false);

return TValFunc::getS(id);

}

int Block::getI( unsigned id )

{

ResAlloc res(en_res,false);

return TValFunc::getI(id);

}

double Block::getR( unsigned id )

{

ResAlloc res(en_res,false);

return TValFunc::getR(id);

}

bool Block::getB( unsigned id )

{

ResAlloc res(en_res,false);

return TValFunc::getB(id);

}

Модуль “StaticFuncLibs” підсистеми “Спеціальні”

Модуль “StaticFuncLibs” надає декілька бібліотек статичних функцій. Файли у яких реалізовано модуль “StaticFuncLibs ” приведені у таблиці 3.

Таблиця 3. Файли модуля "StaticFuncLibs"

Файл	Опис
statfunc.h	Визначення корінних об'єктів модуля.
statfunc.cpp	Корінні об'єкти модуля.
libcompl1.h	Містить бібліотеку функцій SCADA Complex1.
stdmath.h	Містить бібліотеку стандартних математичних функцій.

Рис. 4. Статична діаграма класів модуля "StaticFuncLibs" Модуль “StaticFuncLibs” представлено декількома об'єктами(класами). Статичну діаграму об'єктів модуля “StaticFuncLibs” та взаємозв'язки між ними наведено на рис.4.

Вміст файлу statfunc.h

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#ifndef STATFUNC_H

#define STATFUNC_H

#include <string>

#include <vector>

#include <tspecials.h>

using std::string;

using std::vector;

namespace StatFunc

{

//Complex1 functions library

class Libs : public TSpecial

{

public:

Libs( string src );

~Libs();

void modStart( );

void modStop( );

private:

void postEnable( );

void preDisable(int flag);

};

extern Libs *st_lib;

} //End namespace StatFunc

#endif //STATFUNC_H

Вміст файлу statfunc.cpp

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#include <tsys.h>

#include "libcompl1.h"

#include "stdmath.h"

#include "statfunc.h"

//============ Modul info! =====================================================

#define MOD_ID "StaticFuncLibs"

#define MOD_NAME "Static function's libs"

#define MOD_TYPE "Special"

#define VER_TYPE VER_SPC

#define SUB_TYPE "LIB"

#define VERSION "0.9.0"

//==============================================================================

StatFunc::Libs *StatFunc::st_lib;

extern "C"

{

TModule::SAt module( int n_mod )

{

TModule::SAt AtMod;

if(n_mod==0)

{

AtMod.id	= MOD_ID;

AtMod.type = MOD_TYPE;

AtMod.t_ver = VER_TYPE;

}

else

AtMod.id	= "";

return( AtMod );

}

TModule *attach( const TModule::SAt &AtMod, const string &source )

{

StatFunc::Libs *self_addr = NULL;

if( AtMod.id == MOD_ID && AtMod.type == MOD_TYPE && AtMod.t_ver == VER_TYPE )

StatFunc::st_lib = self_addr = new StatFunc::Libs( source );

return ( self_addr );

}

}

using namespace StatFunc;

//Complex1 functions library

Libs::Libs( string src )

{

//== Set modul info! ============

mId	= MOD_ID;

mName = MOD_NAME;

mType	= MOD_TYPE;

mVers	= VERSION;

mAutor	= "Roman Savochenko";

mDescr	= "Allow static function libraries. Include libraries: \n"

" - SCADA Complex1 functions;\n"

" - standart mathematic functions.";

mLicense	= "GPL";

mSource	= src;

}

Libs::~Libs()

{

if( owner().owner().func().at().present("complex1") )

owner().owner().func().at().unreg("complex1");

if( owner().owner().func().at().present("math") )

owner().owner().func().at().unreg("math");

}

void Libs::postEnable( )

{

TModule::postEnable( );

//Reg libraries

if(!SYS->func().at().present("complex1"))	SYS->func().at().reg(new Complex1());

if(!SYS->func().at().present("math"))	SYS->func().at().reg(new StdMath());

}

void Libs::preDisable(int flag)

{

if( SYS->func().at().present("complex1") )	SYS->func().at().unreg("complex1");

if( SYS->func().at().present("math") )	SYS->func().at().unreg("math");

TModule::preDisable(flag);

}

void Libs::modStart( )

{

owner().owner().func().at().at("complex1").at().start(true);

owner().owner().func().at().at("math").at().start(true);

}

void Libs::modStop( )

{

owner().owner().func().at().at("complex1").at().start(false);

owner().owner().func().at().at("math").at().start(false);

}

Вміст файлу libcompl1.h

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#ifndef LIBCOMPL1_H

#define LIBCOMPL1_H

#include <math.h>

#include <string>

#include <vector>

#include <tfunctions.h>

#include "statfunc.h"

using std::string;

using std::vector;

namespace StatFunc

{

//Complex1 functions:

//------------------------------------------------------------------------------------

//DigitBlock

//Support digital blocks: 0-Open;1-Start;2-Enable;3-Norm;4-Block

//------------------------------------------------------------------------------------

class DigitBlock : public TFunction

{

public:

DigitBlock() : TFunction("digitBlock")

{

//Inputs

ioAdd( new IO("cmdOpen",st_lib->I18N("Command \"Open\""),IO::Boolean,IO::Input,"0") );

ioAdd( new IO("cmdClose",st_lib->I18N("Command \"Close\""),IO::Boolean,IO::Input,"0") );

ioAdd( new IO("cmdStop",st_lib->I18N("Command \"Stop\""),IO::Boolean,IO::Input,"0") );

//Outputs

ioAdd( new IO("stOpen",st_lib->I18N("Stat \"Opened\""),IO::Boolean,IO::Output,"0") );

ioAdd( new IO("stClose",st_lib->I18N("Stat \"Closed\""),IO::Boolean,IO::Output,"0") );

}

string name()	{ return st_lib->I18N("Digital block"); }

string descr()	{ return st_lib->I18N("Digital assemble block."); }	//!!!! make full description

void calc( TValFunc *val ){ }

};

//------------------------------------------------------------------------------------

//Simple summator

//Formula: out=in1_1*in1_2+in2_1*in2_2+in3_1*in3_2+in4_1*in4_2+

// in5_1*in5_2+in6_1*in6_2+in7_1*in7_2+in8_1*in8_2;

//------------------------------------------------------------------------------------

class Sum : public TFunction

{

public:

Sum() : TFunction("sum")

{

char id_buf[10], nm_buf[20];

ioAdd( new IO("out",st_lib->I18N("Output"),IO::Real,IO::Return,"1") );

for( int i_in=1; i_in <= 8; i_in++ )

{

snprintf(id_buf,sizeof(id_buf),"in%d_1",i_in);

snprintf(nm_buf,sizeof(nm_buf),st_lib->I18N("Input %d.1"),i_in);

ioAdd( new IO(id_buf,nm_buf,IO::Real,IO::Input,"0") );

snprintf(id_buf,sizeof(id_buf),"in%d_2",i_in);

snprintf(nm_buf,sizeof(nm_buf),st_lib->I18N("Input %d.2"),i_in);

ioAdd( new IO(id_buf,nm_buf,IO::Real,IO::Input,"0") );

}

}

string name()	{ return st_lib->I18N("Simple summator"); }

string descr()

{

return st_lib->I18N("Simple summator per formula:\n"

"out=in1_1*in1_2+in2_1*in2_2+in3_1*in3_2+in4_1*in4_2+\n"

" in5_1*in5_2+in6_1*in6_2+in7_1*in7_2+in8_1*in8_2;");

}

void calc( TValFunc *val )

{

val->setR(0,

val->getR(1)*val->getR(2)+

val->getR(3)*val->getR(4)+

val->getR(5)*val->getR(6)+

val->getR(7)*val->getR(8)+

val->getR(9)*val->getR(10)+

val->getR(11)*val->getR(12)+

val->getR(13)*val->getR(14)+

val->getR(15)*val->getR(16));

}

};

//------------------------------------------------------------------------------------

//Simple moltiplicator

//Formula: out=(in1_1*in1_2*in1_3*in1_4*in1_5*in1_6)/(in2_1*in2_2*in2_3*in2_4);

//------------------------------------------------------------------------------------

class Mult : public TFunction

{

public:

Mult() : TFunction("mult")

{

ioAdd( new IO("out",st_lib->I18N("Output"),IO::Real,IO::Return,"1") );

for( int i_c = 1; i_c <= 6; i_c++ )

ioAdd( new IO(("in1_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 1.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in2_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 2.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

}

string name()	{ return st_lib->I18N("Simple multiplicator"); }

string descr()

{

return st_lib->I18N("Simple moltiplicator per formula:\n"

"out=(in1_1*in1_2*in1_3*in1_4*in1_5*in1_6)/(in2_1*in2_2*in2_3*in2_4);");

}

void calc( TValFunc *val )

{

val->setR(0,

(val->getR(1)*val->getR(2)*val->getR(3)*val->getR(4)*val->getR(5)*val->getR(6))/

(val->getR(7)*val->getR(8)*val->getR(9)*val->getR(10)));

}

};

//------------------------------------------------------------------------------------

//Multiplicator+divider

//Formula: out=(in1_1*in1_2*in1_3*in1_4*in1_5*(in2_1*in2_2*in2_3*in2_4*in2_5+"

// (in3_1*in3_2*in3_3*in3_4*in3_5)/(in4_1*in4_2*in4_3*in4_4*in4_5)))

//------------------------------------------------------------------------------------

class MultDiv : public TFunction

{

public:

MultDiv() : TFunction("multDiv")

{

ioAdd( new IO("out",st_lib->I18N("Output"),IO::Real,IO::Return,"0") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in1_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 1.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in2_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 2.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in3_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 3.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in4_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 4.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

}

string name()	{ return st_lib->I18N("Multiplicator+divider"); }

string descr()

{

return st_lib->I18N("Multiplicator+divider per formula:\n"

"out=in1_1*in1_2*in1_3*in1_4*in1_5*(in2_1*in2_2*in2_3*in2_4*in2_5+\n"

" (in3_1*in3_2*in3_3*in3_4*in3_5)/(in4_1*in4_2*in4_3*in4_4*in4_5));");

}

void calc( TValFunc *val )

{

double tmp1 = val->getR(16)*val->getR(17)*val->getR(18)*val->getR(19)*val->getR(20);

double tmp2 = val->getR(1)*val->getR(2)*val->getR(3)*val->getR(4)*val->getR(5);

double tmp3 = val->getR(6)*val->getR(7)*val->getR(8)*val->getR(9)*val->getR(10);

double tmp4 = val->getR(11)*val->getR(12)*val->getR(13)*val->getR(14)*val->getR(15);

val->setR(0,tmp2*(tmp3+tmp4/tmp1));

}

};

//------------------------------------------------------------------------------------

//Exponent

//Formula: out=exp (in1_1*in1_2*in1_3*in1_4*in1_5 +

// (in2_1*in2_2*in2_3*in2_4*in2_5+in3) / (in4_1*in4_2*in4_3*in4_4*in4_5+in5) )

//------------------------------------------------------------------------------------

class Exp : public TFunction

{

public:

Exp() : TFunction("exp")

{

ioAdd( new IO("out",st_lib->I18N("Output"),IO::Real,IO::Return,"0") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in1_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 1.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in2_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 2.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

ioAdd( new IO("in3",st_lib->I18N("Input 3"),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in4_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 4.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

ioAdd( new IO("in5",st_lib->I18N("Input 5"),IO::Real,IO::Input,"1") );

}

string name()	{ return st_lib->I18N("Exponent"); }

string descr()

{

return st_lib->I18N("Exponent per formula:\n"

"out=exp (in1_1*in1_2*in1_3*in1_4*in1_5 +\n"

" (in2_1*in2_2*in2_3*in2_4*in2_5+in3) / (in4_1*in4_2*in4_3*in4_4*in4_5+in5) );");

}

void calc( TValFunc *v )

{

double tmp1=v->getR(12)*v->getR(13)*v->getR(14)*v->getR(15)*v->getR(16)+v->getR(17);

double tmp2=v->getR(1)*v->getR(2)*v->getR(3)*v->getR(4)*v->getR(5);

double tmp3=v->getR(6)*v->getR(7)*v->getR(8)*v->getR(9)*v->getR(10)+v->getR(11);

v->setR(0,exp(tmp2+tmp3/tmp1));

}

};

//------------------------------------------------------------------------------------

//Power

//Formula: out=(in1_1*in1_2*in1_3*in1_4*in1_5)^(in2_1*in2_2*in2_3*in2_4*in2_5 +

// (in3_1*in3_2*in3_3*in3_4*in3_5)/(in4_1*in4_2*in4_3*in4_4*in4_5))

//------------------------------------------------------------------------------------

class Pow : public TFunction

{

public:

Pow() : TFunction("pow")

{

ioAdd( new IO("out",st_lib->I18N("Output"),IO::Real,IO::Return,"0") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in1_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 1.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in2_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 2.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in3_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 3.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in4_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 4.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

}

string name()	{ return st_lib->I18N("Power"); }

string descr()

{

return st_lib->I18N("Power per formula:\n"

"out=(in1_1*in1_2*in1_3*in1_4*in1_5)^(in2_1*in2_2*in2_3*in2_4*in2_5 +\n"

"	(in3_1*in3_2*in3_3*in3_4*in3_5)/(in4_1*in4_2*in4_3*in4_4*in4_5));");

}

void calc( TValFunc *v )

{

double tmp1=v->getR(16)*v->getR(17)*v->getR(18)*v->getR(19)*v->getR(20);

double tmp2=v->getR(6)*v->getR(7)*v->getR(8)*v->getR(9)*v->getR(10);

double tmp3=v->getR(11)*v->getR(12)*v->getR(13)*v->getR(14)*v->getR(15);

tmp2=tmp2+tmp3/tmp1;

tmp3=v->getR(1)*v->getR(2)*v->getR(3)*v->getR(4)*v->getR(5);

v->setR(0,pow(tmp3,tmp2));

}

};

//------------------------------------------------------------------------------------

//Condition <

//Formula: out=if( in1<(in2_1*in2_2*in2_3*in2_4) ) then in3_1*in3_2*in3_3*in3_4;

// else in4_1*in4_2*in4_3*in4_4;

//------------------------------------------------------------------------------------

class Cond1 : public TFunction

{

public:

Cond1() : TFunction("cond <")

{

ioAdd( new IO("out",st_lib->I18N("Output"),IO::Real,IO::Return,"0") );

ioAdd( new IO("in1",st_lib->I18N("Input 1"),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in2_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 2.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in3_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 3.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in4_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 4.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

}

string name()	{ return st_lib->I18N("Condition '<'"); }

string descr()

{

return st_lib->I18N("Condition '<' per formula:\n"

"out=if( in1<(in2_1*in2_2*in2_3*in2_4) ) then in3_1*in3_2*in3_3*in3_4;\n"

" else in4_1*in4_2*in4_3*in4_4;");

}

void calc( TValFunc *v )

{

double tmp1=v->getR(2)*v->getR(3)*v->getR(4)*v->getR(5);

if( v->getR(1)<tmp1 )	v->setR(0,v->getR(6)*v->getR(7)*v->getR(8)*v->getR(9));

else	v->setR(0,v->getR(10)*v->getR(11)*v->getR(12)*v->getR(13));

}

};

//------------------------------------------------------------------------------------

//Condition >

//Formula: out=if( in1>(in2_1*in2_2*in2_3*in2_4) ) then in3_1*in3_2*in3_3*in3_4;

// else in4_1*in4_2*in4_3*in4_4;

//------------------------------------------------------------------------------------

class Cond2 : public TFunction

{

public:

Cond2() : TFunction("cond >")

{

ioAdd( new IO("out",st_lib->I18N("Output"),IO::Real,IO::Return,"0") );

ioAdd( new IO("in1",st_lib->I18N("Input 1"),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in2_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 2.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in3_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 3.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in4_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 4.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

}

string name()	{ return st_lib->I18N("Condition '>'"); }

string descr()

{

return st_lib->I18N("Condition '>' per formula:\n"

"out=if( in1>(in2_1*in2_2*in2_3*in2_4) ) then in3_1*in3_2*in3_3*in3_4;\n"

" else in4_1*in4_2*in4_3*in4_4;");

}

void calc( TValFunc *v )

{

double tmp1=v->getR(2)*v->getR(3)*v->getR(4)*v->getR(5);

if( v->getR(1)>tmp1 )	v->setR(0,v->getR(6)*v->getR(7)*v->getR(8)*v->getR(9));

else	v->setR(0,v->getR(10)*v->getR(11)*v->getR(12)*v->getR(13));

}

};

//------------------------------------------------------------------------------------

//Condition x>, x<, >x>

//Formula: out = if( in1<(in2_1*in2_2*in2_3*in2_4) ) then in3_1*in3_2*in3_3*in3_4;

// else if( in1>(in4_1*in4_2*in4_3*in4_4) then in5_1*in5_2*in5_3*in5_4;

// else in6_1*in6_2*in6_3*in6_4;

//------------------------------------------------------------------------------------

class Cond3 : public TFunction

{

public:

Cond3() : TFunction("cond_full")

{

ioAdd( new IO("out",st_lib->I18N("Output"),IO::Real,IO::Return,"0") );

ioAdd( new IO("in1",st_lib->I18N("Input 1"),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in2_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 2.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in3_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 3.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in4_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 4.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in5_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 5.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in6_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 6.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

}

string name()	{ return st_lib->I18N("Full condition"); }

string descr()

{

return st_lib->I18N("Full condition per formula:\n"

"out = if( in1<(in2_1*in2_2*in2_3*in2_4) ) then in3_1*in3_2*in3_3*in3_4;\n"

" else if( in1>(in4_1*in4_2*in4_3*in4_4) then in5_1*in5_2*in5_3*in5_4;\n"

" else in6_1*in6_2*in6_3*in6_4;");

}

void calc( TValFunc *v )

{

double tmp1=v->getR(2)*v->getR(3)*v->getR(4)*v->getR(5);

double tmp2=v->getR(10)*v->getR(11)*v->getR(12)*v->getR(13);

double tmp3=v->getR(6)*v->getR(7)*v->getR(8)*v->getR(9);

double tmp4=v->getR(18)*v->getR(19)*v->getR(20)*v->getR(21);

double tmp5=v->getR(14)*v->getR(15)*v->getR(16)*v->getR(17);

if(v->getR(1)<tmp1)	v->setR(0,tmp3);

else if( v->getR(1)>tmp2)	v->setR(0,tmp5);

else	v->setR(0,tmp4);

}

};

//------------------------------------------------------------------------------------

//Selector

//Formula: out = if( sel = 1 ) then in1_1*in1_2*in1_3*in1_4;

// if( sel = 2 ) then in2_1*in2_2*in2_3*in2_4;

// if( sel = 3 ) then in3_1*in3_2*in3_3*in3_4;

// if( sel = 4 ) then in4_1*in4_2*in4_3*in4_4;

//------------------------------------------------------------------------------------

class Select : public TFunction

{

public:

Select() : TFunction("select")

{

ioAdd( new IO("out",st_lib->I18N("Output"),IO::Real,IO::Return,"0") );

ioAdd( new IO("sel",st_lib->I18N("Select"),IO::Integer,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in1_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 1.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in2_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 2.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in3_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 3.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 4; i_c++ )

ioAdd( new IO(("in4_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 4.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

}

string name()	{ return st_lib->I18N("Selector"); }

string descr()

{

return st_lib->I18N("Selector per formula:\n"

"out = if( sel = 1 ) then in1_1*in1_2*in1_3*in1_4;\n"

" if( sel = 2 ) then in2_1*in2_2*in2_3*in2_4;\n"

" if( sel = 3 ) then in3_1*in3_2*in3_3*in3_4;\n"

" if( sel = 4 ) then in4_1*in4_2*in4_3*in4_4;");

}

void calc( TValFunc *v )

{

switch(v->getI(1))

{

case 1: v->setR(0,v->getR(2)*v->getR(3)*v->getR(4)*v->getR(5)); break;

case 2: v->setR(0,v->getR(6)*v->getR(7)*v->getR(8)*v->getR(9)); break;

case 3: v->setR(0,v->getR(10)*v->getR(11)*v->getR(12)*v->getR(13)); break;

case 4: v->setR(0,v->getR(14)*v->getR(15)*v->getR(16)*v->getR(17)); break;

default: v->setR(0,0.0);

}

}

};

//------------------------------------------------------------------------------------

//Incrementator

//Formula: out = if( in > prev )then prev + k_pos*(in-prev); else prev - k_neg*(prev-in);

//------------------------------------------------------------------------------------

class Increm : public TFunction

{

public:

Increm() : TFunction("increment")

{

ioAdd( new IO("out",st_lib->I18N("Output"),IO::Real,IO::Return,"0") );

ioAdd( new IO("in",st_lib->I18N("Input"),IO::Real,IO::Input,"1") );

ioAdd( new IO("prev",st_lib->I18N("Previous"),IO::Real,IO::Input,"1") );

ioAdd( new IO("k+",st_lib->I18N("Positive koef"),IO::Real,IO::Input,"0.1") );

ioAdd( new IO("k-",st_lib->I18N("Negative koef"),IO::Real,IO::Input,"0.1") );

}

string name()	{ return st_lib->I18N("Incrementator"); }

string descr()

{

return st_lib->I18N("Incrementator per formula:\n"

"out = if( in1 > in2 )then in2 + in3*(in1-in2); else in2 - in4*(in2-in1);");

}

void calc( TValFunc *v )

{

if( v->getR(1) > v->getR(2) )

v->setR(0,v->getR(2) + v->getR(3)*(v->getR(1) - v->getR(2)));

else v->setR(0,v->getR(2) - v->getR(4)*(v->getR(2) - v->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Divider

//Formula: out = (in1_1*in1_2*in1_3*in1_4*in1_5 + in2_1*in2_2*in2_3*in2_4*in2_5 + in3) /

//	(in4_1*in4_2*in4_3*in4_4*in4_5 + in5_1*in5_2*in5_3*in5_4*in5_5 + in6);

//------------------------------------------------------------------------------------

class Divider : public TFunction

{

public:

Divider() : TFunction("div")

{

ioAdd( new IO("out",st_lib->I18N("Output"),IO::Real,IO::Return,"0") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in1_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 1.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in2_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 2.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

ioAdd( new IO("in3",st_lib->I18N("Input 3"),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in4_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 4.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in5_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 5.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

ioAdd( new IO("in6",st_lib->I18N("Input 6"),IO::Real,IO::Input,"1") );

}

string name()	{ return st_lib->I18N("Divider"); }

string descr()

{

return st_lib->I18N("Divider per formula:\n"

"out = (in1_1*in1_2*in1_3*in1_4*in1_5 + in2_1*in2_2*in2_3*in2_4*in2_5 + in3) /\n"

" (in4_1*in4_2*in4_3*in4_4*in4_5 + in5_1*in5_2*in5_3*in5_4*in5_5 + in6);");

}

void calc( TValFunc *v )

{

double t1 =	v->getR(1)*v->getR(2)*v->getR(3)*v->getR(4)*v->getR(5) +

v->getR(6)*v->getR(7)*v->getR(8)*v->getR(9)*v->getR(10) + v->getR(11);

double t2 = v->getR(12)*v->getR(13)*v->getR(14)*v->getR(15)*v->getR(16) +

v->getR(17)*v->getR(18)*v->getR(19)*v->getR(20)*v->getR(21) + v->getR(22);

v->setR(0,t1/t2);

}

};

//------------------------------------------------------------------------------------

//PID

//Inputs:

// 0:val - Value

// 1:sp - Setpoint

// 2:max - Maximum scale

// 3:min - Minimum scale

// 4:out - Output

// 5:auto - Automatic mode

// 6:casc - Cascade mode

// 7:Kp - Gain

// 8:Ti - Integral time (ms)

// 9:Td - Differencial time (ms)

// 10:Tf - Filter (lag) time (ms)

// 11:Hup - Up output limit (%)

// 12:Hdwn - Down output limit (%)

// 13:Zi - Insensibility zone (%)

// 14:K1 - Scale input 1

// 15:in1 - Add input 1

// 16:K2 - Scale input 2

// 17:in2 - Add input 2

// 18:K3 - Scale input 3

// 19:in3 - Add input 3

// 20:K4 - Scale input 4

// 21:in4 - Add input 4

// 22:cycle- Calc cycle (ms)

//Internal data:

// 23:#int - Curent integral value

// 24:#dif - Curent differencial value

// 25:#lag - Curent lag value

//------------------------------------------------------------------------------------

class PID : public TFunction

{

public:

PID() : TFunction("pid")

{

//Inputs

ioAdd( new IO("var",st_lib->I18N("Variable"),IO::Real,IO::Input,"0") );

ioAdd( new IO("sp",st_lib->I18N("Setpoint"),IO::Real,IO::Input,"0") );

ioAdd( new IO("max",st_lib->I18N("Max scale"),IO::Real,IO::Input,"100") );

ioAdd( new IO("min",st_lib->I18N("Min scale"),IO::Real,IO::Input,"0") );

ioAdd( new IO("out",st_lib->I18N("Output (%)"),IO::Real,IO::Return,"0") );

ioAdd( new IO("auto",st_lib->I18N("Auto mode"),IO::Boolean,IO::Input,"0") );

ioAdd( new IO("casc",st_lib->I18N("Cascade mode"),IO::Boolean,IO::Input,"0") );

ioAdd( new IO("Kp",st_lib->I18N("Kp"),IO::Real,IO::Input,"1") );

ioAdd( new IO("Ti",st_lib->I18N("Ti (ms)"),IO::Integer,IO::Input,"1000") );

ioAdd( new IO("Td",st_lib->I18N("Td (ms)"),IO::Integer,IO::Input,"0") );

ioAdd( new IO("Tf",st_lib->I18N("Tf-lag (ms)"),IO::Integer,IO::Input,"0") );

ioAdd( new IO("Hup",st_lib->I18N("Out up limit (%)"),IO::Real,IO::Input,"100") );

ioAdd( new IO("Hdwn",st_lib->I18N("Out down limit (%)"),IO::Real,IO::Input,"0") );

ioAdd( new IO("Zi",st_lib->I18N("Insensibility (%)"),IO::Real,IO::Input,"1") );

ioAdd( new IO("K1",st_lib->I18N("K input 1"),IO::Real,IO::Input,"0") );

ioAdd( new IO("in1",st_lib->I18N("Input 1"),IO::Real,IO::Input,"0") );

ioAdd( new IO("K2",st_lib->I18N("K input 2"),IO::Real,IO::Input,"0") );

ioAdd( new IO("in2",st_lib->I18N("Input 2"),IO::Real,IO::Input,"0") );

ioAdd( new IO("K3",st_lib->I18N("K input 3"),IO::Real,IO::Input,"0") );

ioAdd( new IO("in3",st_lib->I18N("Input 3"),IO::Real,IO::Input,"0") );

ioAdd( new IO("K4",st_lib->I18N("K input 4"),IO::Real,IO::Input,"0") );

ioAdd( new IO("in4",st_lib->I18N("Input 4"),IO::Real,IO::Input,"0") );

ioAdd( new IO("cycle",st_lib->I18N("Calc cycle (ms)"),IO::Integer,IO::Input,"1000") );

//Internal data:

ioAdd( new IO("int",st_lib->I18N("Integral value"),IO::Real,IO::Output,"0",true) );

ioAdd( new IO("dif",st_lib->I18N("Differencial value"),IO::Real,IO::Output,"0",true) );

ioAdd( new IO("lag",st_lib->I18N("Lag value"),IO::Real,IO::Output,"0",true) );

}

string name()	{ return st_lib->I18N("PID regulator"); }

string descr()	{ return st_lib->I18N("PID regulator"); }

void calc( TValFunc *v )

{

double	val	= v->getR(0),

sp	= v->getR(1),

max	= v->getR(2),

min	= v->getR(3),

out	= v->getR(4),

kp = v->getR(7),

h_up	= v->getR(11),

h_dwn	= v->getR(12),

zi	= v->getR(13),

k1 = v->getR(14),

in1 = v->getR(15),

k2 = v->getR(16),

in2 = v->getR(17),

k3 = v->getR(18),

in3 = v->getR(19),

k4 = v->getR(20),

in4 = v->getR(21),

cycle = v->getI(22),

integ = v->getR(23),

difer	= v->getR(24),

lag = v->getR(25);

double	Kf	= (v->getI(10)>cycle)?cycle/v->getI(10):1.;

double	Kint	= (v->getI(8)>cycle)?cycle/v->getI(8):1.;

double	Kdif	= (v->getI(9)>cycle)?cycle/v->getI(9):1.;

//Scale error

if( max <= min )	return;

//Prepare values

sp = 100.*(sp+min)/(max-min);

val = 100.*(val+min)/(max-min);

val += k1*in1 + k2*in2;

if(val > 100.) val = 100.;

if(val < -100.) val = -100.;

//Error

double err = sp - val;

//Insensibility

if( fabs(err) < zi )	err = 0.;

else

{

if( err>0. )	err-=zi;

else	err+=zi;

}

//Gain

err*=kp;

if(err > 100.) err = 100.;

if(err < -100.) err = -100.;

//Input filter lag

lag+=Kf*(err-lag);

//Automatic mode enabled

if(v->getB(5))

{

integ+=Kint*lag;	//Integral

difer-=Kdif*(difer-lag);	//Differecial lag

out = (2.*lag + integ - difer) + k3*in3 + k4*in4;

if(out > h_up || out < h_dwn )

{

if( out > h_up )	out = h_up;

if( out < h_dwn )	out = h_dwn;

//Fix integral

integ = out - 2.*lag + difer - k3*in3 + k4*in4;

}

}

//Write outputs

v->setR(4,out);

v->setR(23,integ);

v->setR(24,difer);

v->setR(25,lag);

}

};

//------------------------------------------------------------------------------------

//Alarm

//Formula: out = if (val>max || val<min) then true; else false;

//------------------------------------------------------------------------------------

class Alarm : public TFunction

{

public:

Alarm() : TFunction("alarm")

{

ioAdd( new IO("out",st_lib->I18N("Output"),IO::Boolean,IO::Return,"0") );

ioAdd( new IO("val",st_lib->I18N("Value"),IO::Real,IO::Input,"0") );

ioAdd( new IO("max",st_lib->I18N("Maximum"),IO::Real,IO::Input,"100") );

ioAdd( new IO("min",st_lib->I18N("Minimum"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("Alarm"); }

string descr()

{

return st_lib->I18N("Scale parameter alarm:\n"

"out = if (val>max || val<min) then true; else false;");

}

void calc( TValFunc *v )

{

double max = v->getR(2),

min = v->getR(3),

val = v->getR(1);

if( max != min && ( val < min || val > max ) )

v->setB(0,true);

else v->setB(0,false);

}

};

//------------------------------------------------------------------------------------

//Flow

//Formula: f = k1*((k3+k4*x)^k2)+Krnd*RAND

//------------------------------------------------------------------------------------

class Flow : public TFunction

{

public:

Flow() : TFunction("flow")

{

ioAdd( new IO("f",st_lib->I18N("Flow"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X positon"),IO::Real,IO::Input,"0") );

ioAdd( new IO("K1",st_lib->I18N("K1"),IO::Real,IO::Input,"1") );

ioAdd( new IO("K2",st_lib->I18N("K2"),IO::Real,IO::Input,"1") );

ioAdd( new IO("K3",st_lib->I18N("K3"),IO::Real,IO::Input,"0") );

ioAdd( new IO("K4",st_lib->I18N("K4"),IO::Real,IO::Input,"1") );

}

string name()	{ return st_lib->I18N("Flow"); }

string descr()

{

return st_lib->I18N("Flow calc per formule:\n"

"f = K1*((K3+K4*x)^K2);");

}

void calc( TValFunc *v )

{

v->setR(0,v->getR(2)*pow(v->getR(4)+v->getR(5)*v->getR(1),v->getR(3)));

}

};

//------------------------------------------------------------------------------------

//Sum+mult

//Formula: out = in1_1*in1_2*(in1_3*in1_4+in1_5) + in2_1*in2_2*(in2_3*in2_4+in2_5) +

// in4_1*in4_2*(in4_3*in4_4+in4_5) + in5_1*in5_2*(in5_3*in5_4+in5_5);

//------------------------------------------------------------------------------------

class SumMult : public TFunction

{

public:

SumMult() : TFunction("sum_mult")

{

ioAdd( new IO("out",st_lib->I18N("Output"),IO::Real,IO::Return,"0") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in1_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 1.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in2_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 2.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in3_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 3.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in4_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 4.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

}

string name()	{ return st_lib->I18N("Sum and mult"); }

string descr()

{

return st_lib->I18N("Sum and mult per formule:\n"

"out = in1_1*in1_2*(in1_3*in1_4+in1_5) + in2_1*in2_2*(in2_3*in2_4+in2_5) +\n"

" in4_1*in4_2*(in4_3*in4_4+in4_5) + in5_1*in5_2*(in5_3*in5_4+in5_5);");

}

void calc( TValFunc *v )

{

double t1 =	v->getR(1)*v->getR(2)*(v->getR(3)*v->getR(4)+v->getR(5));

double t2 =	v->getR(6)*v->getR(7)*(v->getR(8)*v->getR(9)+v->getR(10));

double t3 =	v->getR(11)*v->getR(12)*(v->getR(13)*v->getR(14)+v->getR(15));

double t4 =	v->getR(16)*v->getR(17)*(v->getR(18)*v->getR(19)+v->getR(20));

v->setR(0,t1+t2+t3+t4);

}

};

//------------------------------------------------------------------------------------

//Sum+div

//Formula: out = in1_1*in1_2*(in1_3+in1_4/in1_5) + in2_1*in2_2*(in2_3+in2_4/in2_5) +

// in4_1*in4_2*(in4_3+in4_4/in4_5) + in5_1*in5_2*(in5_3+in5_4/in5_5);

//------------------------------------------------------------------------------------

class SumDiv : public TFunction

{

public:

SumDiv() : TFunction("sum_div")

{

ioAdd( new IO("out",st_lib->I18N("Output"),IO::Real,IO::Return,"0") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in1_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 1.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in2_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 2.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in3_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 3.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

for( int i_c = 1; i_c <= 5; i_c++ )

ioAdd( new IO(("in4_"+TSYS::int2str(i_c)).c_str(),(st_lib->I18N("Input 4.")+TSYS::int2str(i_c)).c_str(),IO::Real,IO::Input,"1") );

}

string name()	{ return st_lib->I18N("Sum and divide"); }

string descr()

{

return st_lib->I18N("Sum and divide per formule:\n"

"out = in1_1*in1_2*(in1_3+in1_4/in1_5) + in2_1*in2_2*(in2_3+in2_4/in2_5) +\n"

" in4_1*in4_2*(in4_3+in4_4/in4_5) + in5_1*in5_2*(in5_3+in5_4/in5_5);");

}

void calc( TValFunc *v )

{

double t1 =	v->getR(1)*v->getR(2)*(v->getR(3)+v->getR(4)/v->getR(5));

double t2 =	v->getR(6)*v->getR(7)*(v->getR(8)+v->getR(9)/v->getR(10));

double t3 =	v->getR(11)*v->getR(12)*(v->getR(13)+v->getR(14)/v->getR(15));

double t4 =	v->getR(16)*v->getR(17)*(v->getR(18)+v->getR(19)/v->getR(20));

v->setR(0,t1+t2+t3+t4);

}

};

//------------------------------------------------------------------------------------

//Lag

//Formula: y = y - Klag*( y - x );

//------------------------------------------------------------------------------------

class Lag : public TFunction

{

public:

Lag() : TFunction("lag")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X"),IO::Real,IO::Input,"0") );

ioAdd( new IO("Klag",st_lib->I18N("Klag"),IO::Real,IO::Input,"0.1") );

}

string name()	{ return st_lib->I18N("Lag"); }

string descr()

{

return st_lib->I18N("Lag per formule:\n"

"y = y - Klag*( y - x );");

}

void calc( TValFunc *v )

{

double y = v->getR(0);

v->setR(0,y - v->getR(2)*(y - v->getR(1)));

}

};

//=====================================================

//================ Complex1 functions library =========

//=====================================================

class Complex1 : public TLibFunc

{

public:

Complex1( ) : TLibFunc("complex1") { }

void postEnable()

{

if( !present("digitBlock") )reg( new DigitBlock() );

if( !present("sum") )	reg( new Sum() );

if( !present("mult") )	reg( new Mult() );

if( !present("multDiv") )	reg( new MultDiv() );

if( !present("exp") )	reg( new Exp() );

if( !present("pow") )	reg( new Pow() );

if( !present("cond <") )	reg( new Cond1() );

if( !present("cond >") )	reg( new Cond2() );

if( !present("cond_full") )	reg( new Cond3() );

if( !present("select") )	reg( new Select() );

if( !present("increment") )	reg( new Increm() );

if( !present("div") )	reg( new Divider() );

if( !present("pid") )	reg( new PID() );

if( !present("alarm") )	reg( new Alarm() );

if( !present("flow") )	reg( new Flow() );

if( !present("sum_mult") )	reg( new SumMult() );

if( !present("sum_div") )	reg( new SumDiv() );

if( !present("lag") )	reg( new Lag() );

}

string name()	{ return st_lib->I18N("Complex1 functions"); }

string descr()	{ return st_lib->I18N("Allow functions of SCADA system 'Complex1' for compatibility."); }

};

} //End namespace virtual

#endif //LIBCOMPL1_H

Вміст файлу stdmath.h

/***************************************************************************

* Copyright (C) 2005 by Roman Savochenko *

* rom_as@fromru.com *

* *

* This program is free software; you can redistribute it and/or modify *

* it under the terms of the GNU General Public License as published by *

* the Free Software Foundation; either version 2 of the License, or *

* (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, *

* but WITHOUT ANY WARRANTY; without even the implied warranty of *

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *

* GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License *

* along with this program; if not, write to the *

* Free Software Foundation, Inc., *

* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *

***************************************************************************/

#ifndef STDMATH_H

#define STDMATH_H

#include <math.h>

#include <string>

#include <vector>

#include <tfunctions.h>

#include "statfunc.h"

using std::string;

using std::vector;

namespace StatFunc

{

//Standart mathematic functions:

//------------------------------------------------------------------------------------

//Arc cosine

//Formula: y=acos(x)

//------------------------------------------------------------------------------------

class MathAcos : public TFunction

{

public:

MathAcos() : TFunction("acos")

{

ioAdd( new IO("y",st_lib->I18N("Y(rad.)"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("ArcCos"); }

string descr()	{ return st_lib->I18N("Arc cosine math function."); }

void calc( TValFunc *val )

{

val->setR(0,acos(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Arc sine

//Formula: y=asin(x)

//------------------------------------------------------------------------------------

class MathAsin : public TFunction

{

public:

MathAsin() : TFunction("asin")

{

ioAdd( new IO("y",st_lib->I18N("Y(rad.)"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("ArcSin"); }

string descr()	{ return st_lib->I18N("Arc sine math function."); }

void calc( TValFunc *val )

{

val->setR(0,asin(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Arc tangent

//Formula: y=atan(x)

//------------------------------------------------------------------------------------

class MathAtan : public TFunction

{

public:

MathAtan() : TFunction("atan")

{

ioAdd( new IO("y",st_lib->I18N("Y(rad.)"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("ArcTan"); }

string descr()	{ return st_lib->I18N("Arc tangent math function."); }

void calc( TValFunc *val )

{

val->setR(0,atan(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Cosine

//Formula: y=cos(x)

//------------------------------------------------------------------------------------

class MathCos : public TFunction

{

public:

MathCos() : TFunction("cos")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X(rad.)"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("Cosine"); }

string descr()	{ return st_lib->I18N("Cosine math function."); }

void calc( TValFunc *val )

{

val->setR(0,cos(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Cosine hyperbolical

//Formula: y=cosh(x)

//------------------------------------------------------------------------------------

class MathCosh : public TFunction

{

public:

MathCosh() : TFunction("cosh")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("Cosine hyperbolical"); }

string descr()	{ return st_lib->I18N("Cosine hyperbolical math function."); }

void calc( TValFunc *val )

{

val->setR(0,cosh(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Exponent

//Formula: y=exp(x)

//------------------------------------------------------------------------------------

class MathExp : public TFunction

{

public:

MathExp() : TFunction("exp")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("Exponent"); }

string descr()	{ return st_lib->I18N("Exponent math function."); }

void calc( TValFunc *val )

{

val->setR(0,exp(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Natural logarithm

//Formula: y=ln(x)

//------------------------------------------------------------------------------------

class MathLn : public TFunction

{

public:

MathLn() : TFunction("ln")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("Natural logarithm"); }

string descr()	{ return st_lib->I18N("Natural logarithm math function."); }

void calc( TValFunc *val )

{

val->setR(0,log(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Decimal logarithm

//Formula: y=lg(x)

//------------------------------------------------------------------------------------

class MathLg : public TFunction

{

public:

MathLg() : TFunction("lg")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("Decimal logarithm"); }

string descr()	{ return st_lib->I18N("Decimal logarithm math function."); }

void calc( TValFunc *val )

{

val->setR(0,log10(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Power

//Formula: y=pow(x,p)

//------------------------------------------------------------------------------------

class MathPow : public TFunction

{

public:

MathPow() : TFunction("pow")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X"),IO::Real,IO::Input,"0") );

ioAdd( new IO("p",st_lib->I18N("Power"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("Power"); }

string descr()	{ return st_lib->I18N("Power math function."); }

void calc( TValFunc *val )

{

val->setR(0,pow(val->getR(1),val->getR(2)));

}

};

//------------------------------------------------------------------------------------

//Sine

//Formula: y=sin(x)

//------------------------------------------------------------------------------------

class MathSin : public TFunction

{

public:

MathSin() : TFunction("sin")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X(rad.)"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("Sine"); }

string descr()	{ return st_lib->I18N("Sine math function."); }

void calc( TValFunc *val )

{

val->setR(0,sin(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Sine hyperbolical

//Formula: y=sinh(x)

//------------------------------------------------------------------------------------

class MathSinh : public TFunction

{

public:

MathSinh() : TFunction("sinh")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("Sine hyperbolical"); }

string descr()	{ return st_lib->I18N("Sine hyperbolical math function."); }

void calc( TValFunc *val )

{

val->setR(0,sinh(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Square root

//Formula: y=sqrt(x)

//------------------------------------------------------------------------------------

class MathSqrt : public TFunction

{

public:

MathSqrt() : TFunction("sqrt")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("Square root"); }

string descr()	{ return st_lib->I18N("Square root math function."); }

void calc( TValFunc *val )

{

val->setR(0,sqrt(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Tangent

//Formula: y=tan(x)

//------------------------------------------------------------------------------------

class MathTan : public TFunction

{

public:

MathTan() : TFunction("tan")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X(rad.)"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("Tangent"); }

string descr()	{ return st_lib->I18N("Tangent math function."); }

void calc( TValFunc *val )

{

val->setR(0,tan(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Tangent hyperbolical

//Formula: y=tanh(x)

//------------------------------------------------------------------------------------

class MathTanh : public TFunction

{

public:

MathTanh() : TFunction("tanh")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("Tangent hyperbolical"); }

string descr()	{ return st_lib->I18N("Tangent hyperbolical math function."); }

void calc( TValFunc *val )

{

val->setR(0,tanh(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Ceil

//Formula: y=ceil(x)

//------------------------------------------------------------------------------------

class MathCeil : public TFunction

{

public:

MathCeil() : TFunction("ceil")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("Ceil"); }

string descr()	{ return st_lib->I18N("Ceil math function."); }

void calc( TValFunc *val )

{

val->setR(0,ceil(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Absolute

//Formula: y=abs(x)

//------------------------------------------------------------------------------------

class MathAbs : public TFunction

{

public:

MathAbs() : TFunction("abs")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("Absolute"); }

string descr()	{ return st_lib->I18N("Absolute math function."); }

void calc( TValFunc *val )

{

val->setR(0,fabs(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Floor

//Formula: y=floor(x)

//------------------------------------------------------------------------------------

class MathFloor : public TFunction

{

public:

MathFloor() : TFunction("floor")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("x",st_lib->I18N("X"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("Floor"); }

string descr()	{ return st_lib->I18N("Floor math function."); }

void calc( TValFunc *val )

{

val->setR(0,floor(val->getR(1)));

}

};

//------------------------------------------------------------------------------------

//Randomize (0..100)

//Formula: y=rand(x)

//------------------------------------------------------------------------------------

class MathRand : public TFunction

{

public:

MathRand() : TFunction("rand")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

}

string name()	{ return st_lib->I18N("Rand"); }

string descr()	{ return st_lib->I18N("Rand math function."); }

void calc( TValFunc *val )

{

val->setR(0,100.*rand()/RAND_MAX);

}

};

//------------------------------------------------------------------------------------

//Condition check

//Formula: y=if(cond,true,false)

//------------------------------------------------------------------------------------

class MathIf : public TFunction

{

public:

MathIf() : TFunction("if")

{

ioAdd( new IO("y",st_lib->I18N("Y"),IO::Real,IO::Return,"0") );

ioAdd( new IO("cond",st_lib->I18N("Condition"),IO::Real,IO::Input,"1") );

ioAdd( new IO("true",st_lib->I18N("True value"),IO::Real,IO::Input,"0") );

ioAdd( new IO("false",st_lib->I18N("False value"),IO::Real,IO::Input,"0") );

}

string name()	{ return st_lib->I18N("IF condition"); }

string descr()	{ return st_lib->I18N("Function's type 'if'-condition."); }

void calc( TValFunc *val )

{

val->setR(0,val->getR(1)?val->getR(2):val->getR(3));

}

};

//=============================================================

//========== Standart mathematic functions library ============

//=============================================================

class StdMath : public TLibFunc

{

public:

StdMath( ) : TLibFunc("math") { }

void postEnable()

{

if( !present("acos") )	reg( new MathAcos() );

if( !present("asin") )	reg( new MathAsin() );

if( !present("atan") )	reg( new MathAtan() );

if( !present("cos") )	reg( new MathCos() );

if( !present("cosh") )	reg( new MathCosh() );

if( !present("exp") )	reg( new MathExp() );

if( !present("ln") )	reg( new MathLn() );

if( !present("lg") )	reg( new MathLg() );

if( !present("pow") )	reg( new MathPow() );

if( !present("sin") )	reg( new MathSin() );

if( !present("sinh") )	reg( new MathSinh() );

if( !present("sqrt") )	reg( new MathSqrt() );

if( !present("tan") )	reg( new MathTan() );

if( !present("tanh") )	reg( new MathTanh() );

if( !present("ceil") )	reg( new MathCeil() );

if( !present("abs") )	reg( new MathAbs() );

if( !present("floor") )	reg( new MathFloor() );

if( !present("rand") )	reg( new MathRand() );

if( !present("if") )	reg( new MathIf() );

}

string name()	{ return st_lib->I18N("Mathematic functions"); }

string descr()	{ return st_lib->I18N("Allow standart mathematic functions."); }

};

}

#endif //STDMATH_H

1116139.00218-01 12 01

109

2005-05-21T12:09:12