Added partial universal scripting implementation with Javascript support.

git-svn-id: http://voip.null.ro/svn/yate@4892 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2012-02-10 14:53:55 +00:00
parent 7165d33d25
commit b15e963c58
11 changed files with 3282 additions and 4 deletions

View File

@ -0,0 +1 @@
[general]

View File

@ -1417,6 +1417,7 @@ AC_CONFIG_FILES([packing/rpm/yate.spec
libs/yiax/Makefile
libs/yxml/Makefile
libs/yjabber/Makefile
libs/yscript/Makefile
libs/ymgcp/Makefile
libs/ysig/Makefile
libs/ypbx/Makefile

67
libs/yscript/Makefile.in Normal file
View File

@ -0,0 +1,67 @@
# Makefile
# This file holds the make rules for the libyatescript
DEBUG :=
CXX := @CXX@ -Wall
AR := ar
DEFS :=
INCLUDES := -I@top_srcdir@ -I../.. -I@srcdir@
CFLAGS := @CFLAGS@ @MODULE_CPPFLAGS@ @INLINE_FLAGS@
LDFLAGS:= @LDFLAGS@
SONAME_OPT := @SONAME_OPT@
YATELIBS := -L../.. -lyate @LIBS@
INCFILES := @top_srcdir@/yateclass.h @srcdir@/yatescript.h
PROGS=
LIBS = libyatescript.a
OBJS = evaluator.o script.o javascript.o jsobjects.o
LIBD_DEV:= libyatescript.so
LIBD_VER:= $(LIBD_DEV).@PACKAGE_VERSION@
LIBD:= ../../$(LIBD_VER) ../../$(LIBD_DEV)
LOCALFLAGS =
LOCALLIBS =
COMPILE = $(CXX) $(DEFS) $(DEBUG) $(INCLUDES) $(CFLAGS)
LINK = $(CXX) $(LDFLAGS)
prefix = @prefix@
exec_prefix = @exec_prefix@
# include optional local make rules
-include YateLocal.mak
.PHONY: all debug ddebug xdebug
all: $(LIBS) $(LIBD) $(PROGS)
debug:
$(MAKE) all DEBUG=-g3 MODSTRIP=
ddebug:
$(MAKE) all DEBUG='-g3 -DDEBUG' MODSTRIP=
xdebug:
$(MAKE) all DEBUG='-g3 -DXDEBUG' MODSTRIP=
.PHONY: strip
strip: all
strip --strip-debug --discard-locals $(PROGS)
.PHONY: clean
clean:
@-$(RM) $(PROGS) $(LIBS) $(LIBD) $(OBJS) core 2>/dev/null
%.o: @srcdir@/%.cpp $(INCFILES)
$(COMPILE) -c $<
Makefile: @srcdir@/Makefile.in ../../config.status
cd ../.. && ./config.status
../../$(LIBD_VER): $(OBJS)
$(LINK) -o $@ $(SONAME_OPT)$(LIBD_VER) $^ $(YATELIBS)
../../$(LIBD_DEV): ../../$(LIBD_VER)
cd ../.. && ln -sf $(LIBD_VER) $(LIBD_DEV)
$(LIBS): $(OBJS)
$(AR) rcs $@ $^

1225
libs/yscript/evaluator.cpp Normal file

File diff suppressed because it is too large Load Diff

434
libs/yscript/javascript.cpp Normal file
View File

@ -0,0 +1,434 @@
/**
* javascript.cpp
* Yet Another (Java)script library
* This file is part of the YATE Project http://YATE.null.ro
*
* Yet Another Telephony Engine - a fully featured software PBX and IVR
* Copyright (C) 2011 Null Team
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "yatescript.h"
using namespace TelEngine;
namespace { // anonymous
class JsContext : public ScriptContext
{
YCLASS(JsContext,ScriptContext)
public:
virtual bool runFunction(const ExpEvaluator* eval, ObjList& stack, const ExpOperation& oper, void* context);
virtual bool runField(const ExpEvaluator* eval, ObjList& stack, const ExpOperation& oper, void* context);
virtual bool runAssign(const ExpEvaluator* eval, const ExpOperation& oper, void* context);
};
class JsCode : public ScriptCode, public ExpEvaluator
{
YCLASS(JsCode,ScriptCode)
public:
enum JsOpcode {
OpcBegin = OpcPrivate + 1,
OpcEnd,
OpcIndex,
OpcNew,
OpcFor,
OpcWhile,
OpcIf,
OpcElse,
OpcSwitch,
OpcCase,
OpcBreak,
OpcCont,
OpcIn,
OpcVar,
OpcWith,
OpcTry,
OpcCatch,
OpcFinally,
OpcThrow,
OpcReturn,
};
inline JsCode()
: ExpEvaluator(C), m_label(0)
{ debugName("JsCode"); }
virtual bool initialize(ScriptContext* context) const;
virtual bool evaluate(ScriptContext& context, ObjList& results) const;
protected:
virtual bool keywordChar(char c) const;
virtual int getKeyword(const char* str) const;
virtual bool getInstruction(const char*& expr);
virtual Opcode getOperator(const char*& expr);
virtual Opcode getUnaryOperator(const char*& expr);
virtual Opcode getPostfixOperator(const char*& expr);
virtual const char* getOperator(Opcode oper) const;
virtual int getPrecedence(ExpEvaluator::Opcode oper) const;
virtual bool getSeparator(const char*& expr, bool remove);
virtual bool runOperation(ObjList& stack, const ExpOperation& oper, void* context) const;
private:
int m_label;
};
#define MAKEOP(s,o) { s, JsCode::Opc ## o }
static const TokenDict s_operators[] =
{
{ 0, 0 }
};
static const TokenDict s_unaryOps[] =
{
MAKEOP("new", New),
{ 0, 0 }
};
static const TokenDict s_postfixOps[] =
{
MAKEOP("++", IncPost),
MAKEOP("--", DecPost),
{ 0, 0 }
};
static const TokenDict s_instr[] =
{
MAKEOP("function", Func),
MAKEOP("for", For),
MAKEOP("while", While),
MAKEOP("if", If),
MAKEOP("else", Else),
MAKEOP("switch", Switch),
MAKEOP("case", Case),
MAKEOP("break", Break),
MAKEOP("continue", Cont),
MAKEOP("in", In),
MAKEOP("var", Var),
MAKEOP("with", With),
MAKEOP("try", Try),
MAKEOP("catch", Catch),
MAKEOP("finally", Finally),
MAKEOP("throw", Throw),
MAKEOP("return", Return),
{ 0, 0 }
};
#undef MAKEOP
bool JsContext::runFunction(const ExpEvaluator* eval, ObjList& stack, const ExpOperation& oper, void* context)
{
return ScriptContext::runFunction(eval,stack,oper,context);
}
bool JsContext::runField(const ExpEvaluator* eval, ObjList& stack, const ExpOperation& oper, void* context)
{
if (!eval)
return false;
XDebug(DebugAll,"JsContext::runField '%s'",oper.name().c_str());
return ScriptContext::runField(eval,stack,oper,context);
}
bool JsContext::runAssign(const ExpEvaluator* eval, const ExpOperation& oper, void* context)
{
if (!eval)
return false;
XDebug(DebugAll,"JsContext::runAssign '%s'='%s'",oper.name().c_str(),oper.c_str());
return ScriptContext::runAssign(eval,oper,context);
}
// Initialize standard globals in the execution context
bool JsCode::initialize(ScriptContext* context) const
{
if (!context)
return false;
JsObject::initialize(*context);
return true;
}
bool JsCode::evaluate(ScriptContext& context, ObjList& results) const
{
if (null())
return false;
return ExpEvaluator::evaluate(results,&context);
}
bool JsCode::keywordChar(char c) const
{
return ExpEvaluator::keywordChar(c) || (c == '$');
}
int JsCode::getKeyword(const char* str) const
{
int len = 0;
for (;; len++) {
char c = *str++;
if (c <= ' ')
break;
if (keywordChar(c) || (len && (c == '.')))
continue;
break;
}
if (len > 1 && (str[-2] == '.'))
len--;
return len;
}
bool JsCode::getInstruction(const char*& expr)
{
XDebug(this,DebugAll,"JsCode::getInstruction '%s'",expr);
if (skipWhites(expr) == '{') {
if (!runCompile(++expr,'}'))
return false;
if (skipWhites(expr) != '}')
return gotError("Expecting '}'",expr);
expr++;
return true;
}
Opcode op = ExpEvaluator::getOperator(expr,s_instr);
switch ((JsOpcode)op) {
case (JsOpcode)OpcNone:
return false;
case OpcThrow:
if (!runCompile(expr))
return false;
addOpcode(op);
break;
case OpcReturn:
runCompile(expr);
addOpcode(op);
break;
default:
break;
}
return true;
}
ExpEvaluator::Opcode JsCode::getOperator(const char*& expr)
{
XDebug(this,DebugAll,"JsCode::getOperator '%s'",expr);
Opcode op = ExpEvaluator::getOperator(expr,s_operators);
if (OpcNone != op)
return op;
return ExpEvaluator::getOperator(expr);
}
ExpEvaluator::Opcode JsCode::getUnaryOperator(const char*& expr)
{
XDebug(this,DebugAll,"JsCode::getUnaryOperator '%s'",expr);
Opcode op = ExpEvaluator::getOperator(expr,s_unaryOps);
if (OpcNone != op)
return op;
return ExpEvaluator::getUnaryOperator(expr);
}
ExpEvaluator::Opcode JsCode::getPostfixOperator(const char*& expr)
{
XDebug(this,DebugAll,"JsCode::getPostfixOperator '%s'",expr);
if (skipWhites(expr) == '[') {
if (!runCompile(++expr,']'))
return OpcNone;
if (skipWhites(expr) != ']') {
gotError("Expecting ']'",expr);
return OpcNone;
}
expr++;
return (Opcode)OpcIndex;
}
Opcode op = ExpEvaluator::getOperator(expr,s_postfixOps);
if (OpcNone != op)
return op;
return ExpEvaluator::getPostfixOperator(expr);
}
const char* JsCode::getOperator(Opcode oper) const
{
if (oper < OpcPrivate)
return ExpEvaluator::getOperator(oper);
if ((int)oper == (int)OpcIndex)
return "[]";
const char* tmp = lookup(oper,s_operators);
if (!tmp) {
tmp = lookup(oper,s_unaryOps);
if (!tmp) {
tmp = lookup(oper,s_postfixOps);
if (!tmp)
tmp = lookup(oper,s_instr);
}
}
return tmp;
}
int JsCode::getPrecedence(ExpEvaluator::Opcode oper) const
{
switch (oper) {
case OpcNew:
case OpcIndex:
return 12;
default:
return ExpEvaluator::getPrecedence(oper);
}
}
bool JsCode::getSeparator(const char*& expr, bool remove)
{
switch (skipWhites(expr)) {
case ']':
case ';':
if (remove)
expr++;
return true;
}
return ExpEvaluator::getSeparator(expr,remove);
}
bool JsCode::runOperation(ObjList& stack, const ExpOperation& oper, void* context) const
{
switch ((JsOpcode)oper.opcode()) {
case OpcBegin:
pushOne(stack,new ExpOperation(OpcBegin));
break;
case OpcEnd:
{
ExpOperation* op = popOne(stack);
ObjList* b = 0;
for (ObjList* l = stack.skipNull(); l; l=l->skipNext()) {
ExpOperation* o = static_cast<ExpOperation*>(l->get());
if (o && (o->opcode() == (Opcode)OpcBegin))
b = l;
}
if (!b) {
TelEngine::destruct(op);
return gotError("ExpEvaluator stack underflow");
}
b->clear();
pushOne(stack,op);
}
break;
case OpcIndex:
{
ExpOperation* op2 = popValue(stack,context);
ExpOperation* op1 = popOne(stack);
if (!op1 || !op2) {
TelEngine::destruct(op1);
TelEngine::destruct(op2);
return gotError("Stack underflow");
}
if (op1->opcode() != OpcField) {
TelEngine::destruct(op1);
TelEngine::destruct(op2);
return gotError("Expecting field name");
}
pushOne(stack,new ExpOperation(OpcField,op1->name() + "." + *op2));
TelEngine::destruct(op1);
TelEngine::destruct(op2);
}
break;
case OpcNew:
{
ExpOperation* op = popOne(stack);
if (!op)
return gotError("Stack underflow");
if (op->opcode() != OpcField) {
TelEngine::destruct(op);
return gotError("Expecting class name");
}
}
break;
case OpcThrow:
{
ExpOperation* op = popOne(stack);
if (!op)
return gotError("Stack underflow");
bool ok = false;
while (ExpOperation* drop = popAny(stack)) {
JsOpcode c = (JsOpcode)drop->opcode();
TelEngine::destruct(drop);
if (c == OpcTry) {
ok = true;
break;
}
}
if (!ok)
return gotError("'try' not found");
pushOne(stack,op);
}
break;
case OpcReturn:
{
ExpOperation* op = popOne(stack);
bool ok = false;
while (ExpOperation* drop = popAny(stack)) {
ok = drop->opcode() == OpcFunc;
int n = drop->number();
TelEngine::destruct(drop);
if (ok) {
DDebug(this,DebugAll,"return popping %d off stack",n);
while (n-- > 0)
TelEngine::destruct(popAny(stack));
break;
}
}
if (!ok) {
TelEngine::destruct(op);
return gotError("Function not found on stack");
}
pushOne(stack,op);
}
break;
default:
return ExpEvaluator::runOperation(stack,oper);
}
return true;
}
}; // anonymous namespace
// Parse a piece of Javascript text
bool JsParser::parse(const char* text)
{
if (TelEngine::null(text))
return false;
// TODO
return false;
}
// Evaluate a string as expression or statement
ScriptRun::Status JsParser::eval(const String& text, ExpOperation** result, ScriptContext* context)
{
if (TelEngine::null(text))
return ScriptRun::Invalid;
JsCode* code = new JsCode;
if (!code->compile(text)) {
TelEngine::destruct(code);
return ScriptRun::Invalid;
}
DDebug(DebugAll,"Compiled: %s",code->dump().c_str());
code->simplify();
DDebug(DebugAll,"Simplified: %s",code->dump().c_str());
ScriptContext* ctxt = 0;
if (!context)
context = ctxt = new JsContext();
ScriptRun* runner = new ScriptRun(code,context);
TelEngine::destruct(ctxt);
code->extender(runner->context());
TelEngine::destruct(code);
ScriptRun::Status rval = runner->run();
if (result && (ScriptRun::Succeeded == rval))
*result = ExpEvaluator::popOne(runner->stack());
TelEngine::destruct(runner);
return rval;
}
/* vi: set ts=8 sw=4 sts=4 noet: */

125
libs/yscript/jsobjects.cpp Normal file
View File

@ -0,0 +1,125 @@
/**
* jsobject.cpp
* Yet Another (Java)script library
* This file is part of the YATE Project http://YATE.null.ro
*
* Yet Another Telephony Engine - a fully featured software PBX and IVR
* Copyright (C) 2011 Null Team
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "yatescript.h"
using namespace TelEngine;
namespace { // anonymous
// Base class for all native objects that hold a NamedList
class JsNative : public JsObject
{
YCLASS(JsNative,JsObject)
public:
inline JsNative(const char* name, NamedList* list)
: JsObject(name),
m_list(list)
{ }
virtual NamedList& list()
{ return *m_list; }
virtual const NamedList& list() const
{ return *m_list; }
private:
NamedList* m_list;
};
// Array object
class JsArray : public JsObject
{
YCLASS(JsArray,JsObject)
public:
inline JsArray()
: JsObject("Array")
{ }
};
// Function object
class JsFunction : public JsObject
{
YCLASS(JsFunction,JsObject)
public:
inline JsFunction()
: JsObject("Function")
{ }
};
// Object constructor
class JsConstructor : public JsFunction
{
YCLASS(JsConstructor,JsFunction)
public:
inline JsConstructor()
{ }
};
// Date object
class JsDate : public JsObject
{
YCLASS(JsDate,JsObject)
public:
inline JsDate()
: JsObject("Date")
{
addParam(new ExpOperation(ExpEvaluator::OpcFunc,"now"));
}
};
// Math class - not really an object, all methods are static
class JsMath : public JsObject
{
YCLASS(JsMath,JsObject)
public:
inline JsMath()
: JsObject("Math")
{
addParam(new ExpOperation(ExpEvaluator::OpcFunc,"abs"));
}
};
}; // anonymous namespace
// Helper function that adds an object to a parent
static inline void addObject(NamedList& params, const char* name, NamedList* obj)
{
params.addParam(new NamedPointer(name,obj,obj->toString()));
}
// Initialize standard globals in the execution context
void JsObject::initialize(ScriptContext& context)
{
NamedList& params = context.params();
static_cast<String&>(params) = "[Object Global]";
if (!params.getParam(YSTRING("Object")))
addObject(params,"Object",new JsObject);
if (!params.getParam(YSTRING("Function")))
addObject(params,"Function",new JsFunction);
if (!params.getParam(YSTRING("Date")))
addObject(params,"Date",new JsDate);
if (!params.getParam(YSTRING("Math")))
addObject(params,"Math",new JsMath);
}
/* vi: set ts=8 sw=4 sts=4 noet: */

159
libs/yscript/script.cpp Normal file
View File

@ -0,0 +1,159 @@
/**
* script.cpp
* Yet Another (Java)script library
* This file is part of the YATE Project http://YATE.null.ro
*
* Yet Another Telephony Engine - a fully featured software PBX and IVR
* Copyright (C) 2011 Null Team
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "yatescript.h"
using namespace TelEngine;
ScriptParser::~ScriptParser()
{
TelEngine::destruct(m_code);
}
void ScriptParser::setCode(ScriptCode* code)
{
ScriptCode* tmp = m_code;
if (tmp == code)
return;
if (code)
code->ref();
m_code = code;
TelEngine::destruct(tmp);
}
bool ScriptContext::runFunction(const ExpEvaluator* eval, ObjList& stack, const ExpOperation& oper, void* context)
{
return false;
}
bool ScriptContext::runField(const ExpEvaluator* eval, ObjList& stack, const ExpOperation& oper, void* context)
{
if (!eval)
return false;
XDebug(DebugAll,"ScriptContext::runField '%s'",oper.name().c_str());
ExpEvaluator::pushOne(stack,new ExpOperation(m_params[oper.name()],oper.name()));
return true;
}
bool ScriptContext::runAssign(const ExpEvaluator* eval, const ExpOperation& oper, void* context)
{
if (!eval)
return false;
XDebug(DebugAll,"ScriptContext::runAssign '%s'='%s'",oper.name().c_str(),oper.c_str());
m_params.setParam(oper.name(),oper);
return true;
}
#define MAKE_NAME(x) { #x, ScriptRun::x }
static const TokenDict s_states[] = {
MAKE_NAME(Invalid),
MAKE_NAME(Running),
MAKE_NAME(Incomplete),
MAKE_NAME(Succeeded),
MAKE_NAME(Failed),
{ 0, 0 }
};
#undef MAKE_NAME
ScriptRun::ScriptRun(ScriptCode* code, ScriptContext* context)
: Mutex(true,"ScriptRun"),
m_state(Invalid)
{
if (code)
code->ref();
m_code = code;
if (context)
context->ref();
else
context = new ScriptContext;
m_context = context;
reset();
}
ScriptRun::~ScriptRun()
{
lock();
m_state = Invalid;
TelEngine::destruct(m_code);
TelEngine::destruct(m_context);
unlock();
}
const char* ScriptRun::textState(Status state)
{
return lookup(state,s_states,"Unknown");
}
// Reset script (but not the context) to initial state
ScriptRun::Status ScriptRun::reset()
{
Lock mylock(this);
// TODO
m_stack.clear();
return (m_state = (m_code && m_code->initialize(m_context)) ? Incomplete : Invalid);
}
// Resume execution, run one or more instructions of code
ScriptRun::Status ScriptRun::resume()
{
Lock mylock(this);
if (Running != m_state)
return m_state;
RefPointer<ScriptCode> code = m_code;
RefPointer<ScriptContext> ctxt = m_context;
if (!(code && ctxt))
return Invalid;
mylock.drop();
return code->evaluate(*ctxt,stack()) ? Succeeded : Failed;
}
// Execute one or more instructions of code from where it was left
ScriptRun::Status ScriptRun::execute()
{
Lock mylock(this);
if (Incomplete != m_state)
return m_state;
m_state = Running;
mylock.drop();
Status st = resume();
if (Running == st)
st = Incomplete;
lock();
if (Running == m_state)
m_state = st;
unlock();
return st;
}
// Execute instructions until succeeds or fails
ScriptRun::Status ScriptRun::run()
{
reset();
ScriptRun::Status s = state();
while (Incomplete == s)
s = execute();
return s;
}
/* vi: set ts=8 sw=4 sts=4 noet: */

1154
libs/yscript/yatescript.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1196,13 +1196,14 @@ void SS7MTP3::notify(SS7Layer2* link)
}
}
countLinks();
String text;
text << "Linkset has " << m_active << " active, ";
text << m_checked << " checked of " << m_total << " links";
#ifdef DEBUG
String tmp;
if (link)
tmp << "Link '" << link->toString() << "' is " << (link->operational()?"":"not ") << "operational. ";
Debug(this,DebugInfo,"%sLinkset has %u/%u/%u active/checked links [%p]",
tmp.null()?"":tmp.c_str(),
m_active,m_checked,m_total,this);
Debug(this,DebugInfo,"%s%s [%p]",tmp.safe(),text.c_str(),this);
#endif
// if operational status of a link changed notify upper layer
if (act != m_active || chk != m_checked) {
@ -1252,7 +1253,7 @@ void SS7MTP3::notify(SS7Layer2* link)
notif.addParam("total",String(m_total));
notif.addParam("link", link ? link->toString() : "");
notif.addParam("linkup", link ? String::boolText(link->operational()) : "");
notif.addParam("text", text);
mylock.drop();
SS7Layer3::notify(sls);
engine()->notify(this,notif);

View File

@ -368,6 +368,10 @@ server/sipfeatures.yate: ../libs/yxml/libyatexml.a
server/sipfeatures.yate: LOCALFLAGS = -I@top_srcdir@/libs/yxml
server/sipfeatures.yate: LOCALLIBS = -L../libs/yxml -lyatexml
javascript.yate: ../libyatescript.so
javascript.yate: LOCALFLAGS = -I@top_srcdir@/libs/yscript
javascript.yate: LOCALLIBS = -lyatescript
zlibcompress.yate: LOCALFLAGS = $(ZLIB_INC)
zlibcompress.yate: LOCALLIBS = $(ZLIB_LIB)
@ -405,6 +409,9 @@ server/ysnmpagent.yate: LOCALLIBS = -L../libs/yasn -lyasn -L../libs/ysnmp -lysnm
../libyatejabber.so ../libs/yjabber/libyatejabber.a: @top_srcdir@/libs/yjabber/xmpputils.h @top_srcdir@/libs/yjabber/yatejabber.h @top_srcdir@/libs/yjabber/yatejingle.h
$(MAKE) -C ../libs/yjabber
../libyatescript.so ../libs/yjabber/libyatescript.a: @top_srcdir@/libs/yscript/yatescript.h
$(MAKE) -C ../libs/yscript
../libs/ypbx/libyatepbx.a: @top_srcdir@/libs/ypbx/yatepbx.h
$(MAKE) -C ../libs/ypbx

104
modules/javascript.cpp Normal file
View File

@ -0,0 +1,104 @@
/**
* javascript.cpp
* This file is part of the YATE Project http://YATE.null.ro
*
* Javascript support based on libyscript
*
* Yet Another Telephony Engine - a fully featured software PBX and IVR
* Copyright (C) 2011 Null Team
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <yatephone.h>
#include <yatescript.h>
using namespace TelEngine;
namespace { // anonymous
class JavascriptModule : public Module
{
public:
JavascriptModule();
~JavascriptModule();
virtual void initialize();
bool unload();
protected:
virtual bool commandExecute(String& retVal, const String& line);
virtual bool commandComplete(Message& msg, const String& partLine, const String& partWord);
};
INIT_PLUGIN(JavascriptModule);
UNLOAD_PLUGIN(unloadNow)
{
if (unloadNow)
return __plugin.unload();
return true;
}
JavascriptModule::JavascriptModule()
: Module("javascript","misc",true)
{
Output("Loaded module Javascript");
}
JavascriptModule::~JavascriptModule()
{
Output("Unloading module Javascript");
}
bool JavascriptModule::commandExecute(String& retVal, const String& line)
{
if (!line.startsWith("js "))
return false;
String cmd = line.substr(3).trimSpaces();
if (cmd.null())
return false;
ExpOperation* rval = 0;
ScriptRun::Status st = JsParser::eval(cmd,&rval);
if (rval)
retVal << "'" << rval->name() << "'='" << *rval << "'\r\n";
else
retVal << ScriptRun::textState(st) << "\r\n";
TelEngine::destruct(rval);
return true;
}
bool JavascriptModule::commandComplete(Message& msg, const String& partLine, const String& partWord)
{
if (partLine.null() && partWord.null())
return false;
if (partLine.null() || (partLine == "help"))
itemComplete(msg.retValue(),"js",partWord);
return Module::commandComplete(msg,partLine,partWord);
}
bool JavascriptModule::unload()
{
uninstallRelays();
return true;
}
void JavascriptModule::initialize()
{
Output("Initializing module Javascript");
setup();
}
}; // anonymous namespace
/* vi: set ts=8 sw=4 sts=4 noet: */