Yate
|
00001 /* 00002 * yatescript.h 00003 * Yet Another (Java)script library 00004 * This file is part of the YATE Project http://YATE.null.ro 00005 * 00006 * Yet Another Telephony Engine - a fully featured software PBX and IVR 00007 * Copyright (C) 2011 Null Team 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 00022 */ 00023 00024 #ifndef __YATESCRIPT_H 00025 #define __YATESCRIPT_H 00026 00027 #include <yateclass.h> 00028 00029 #ifdef _WINDOWS 00030 00031 #ifdef LIBYSCRIPT_EXPORTS 00032 #define YSCRIPT_API __declspec(dllexport) 00033 #else 00034 #ifndef LIBYSCRIPT_STATIC 00035 #define YSCRIPT_API __declspec(dllimport) 00036 #endif 00037 #endif 00038 00039 #endif /* _WINDOWS */ 00040 00041 #ifndef YSCRIPT_API 00042 #define YSCRIPT_API 00043 #endif 00044 00048 namespace TelEngine { 00049 00050 class ExpEvaluator; 00051 class ExpOperation; 00052 00057 class YSCRIPT_API ExpExtender 00058 { 00059 public: 00063 virtual ~ExpExtender() 00064 { } 00065 00070 virtual RefObject* refObj(); 00071 00079 virtual bool hasField(ObjList& stack, const String& name, GenObject* context) const; 00080 00088 virtual NamedString* getField(ObjList& stack, const String& name, GenObject* context) const; 00089 00098 virtual bool runFunction(ObjList& stack, const ExpOperation& oper, GenObject* context); 00099 00107 virtual bool runField(ObjList& stack, const ExpOperation& oper, GenObject* context); 00108 00116 virtual bool runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context); 00117 }; 00118 00123 class YSCRIPT_API ExpEvaluator : public DebugEnabler 00124 { 00125 public: 00129 enum Parser { 00130 C, 00131 SQL, 00132 }; 00133 00137 enum Opcode { 00138 // FORTH style notation of effect on stack, C-syntax expression 00139 OpcNone = 0,// ( --- ) 00140 OpcNull, // ( --- A) 00141 OpcPush, // ( --- A) 00142 OpcDrop, // (A --- ) 00143 OpcDup, // (A --- A A) 00144 OpcSwap, // (A B --- B A) 00145 OpcRot, // (A B C --- B C A) 00146 OpcOver, // (A B --- A B A) 00147 // Arithmetic operators 00148 OpcAdd, // (A B --- A+B) 00149 OpcSub, // (A B --- A-B) 00150 OpcMul, // (A B --- A*B) 00151 OpcDiv, // (A B --- A/B) 00152 OpcMod, // (A B --- A%B) 00153 OpcNeg, // (A --- -A) 00154 OpcIncPre, // (A --- ++A) 00155 OpcDecPre, // (A --- --A) 00156 OpcIncPost, // (A --- A++) 00157 OpcDecPost, // (A --- A--) 00158 // Bitwise logic operators 00159 OpcAnd, // (A B --- A&B) 00160 OpcOr, // (A B --- A|B) 00161 OpcXor, // (A B --- A^B) 00162 OpcNot, // (A --- ~A) 00163 OpcShl, // (A B --- A<<B) 00164 OpcShr, // (A B --- A>>B) 00165 // Boolean logic operators 00166 OpcLAnd, // (A B --- A&&B) 00167 OpcLOr, // (A B --- A||B) 00168 OpcLXor, // (A B --- A^^B) 00169 OpcLNot, // (A --- !A) 00170 // String concatenation 00171 OpcCat, // (A B --- A.B) 00172 // String matching 00173 OpcReM, // (A B --- Amatch/B/) 00174 OpcReIM, // (A B --- Amatch_insensitive/B/) 00175 OpcReNm, // (A B --- A!match/B/) 00176 OpcReINm, // (A B --- A!match_insensitive/B/) 00177 OpcLike, // (A B --- AlikeB) 00178 OpcILike, // (A B --- Alike_insensitiveB) 00179 OpcNLike, // (A B --- A!likeB) 00180 OpcNIlike, // (A B --- A!like_insensitiveB) 00181 // Comparation operators 00182 OpcEq, // (A B --- A==B) 00183 OpcNe, // (A B --- A!=B) 00184 OpcGt, // (A B --- A>B) 00185 OpcLt, // (A B --- A<B) 00186 OpcGe, // (A B --- A>=B) 00187 OpcLe, // (A B --- A<=B) 00188 // Ternary conditional operator 00189 OpcCond, // (A B C --- A?B:C) 00190 // Field naming operator 00191 OpcAs, // (A B --- A[name=B]) 00192 // Field replacement 00193 OpcField, // (A --- A) 00194 // Call of function with N parameters 00195 OpcFunc, // (... funcN --- func(...)) 00196 // Label for a jump 00197 OpcLabel, // ( --- ) 00198 // Field assignment - can be ORed with other binary operators 00199 OpcAssign = 0x0100, // (A B --- B,(&A=B)) 00200 // Private extension area for derived classes 00201 OpcPrivate = 0x1000 00202 }; 00203 00209 explicit ExpEvaluator(const TokenDict* operators = 0, const TokenDict* unaryOps = 0); 00210 00215 explicit ExpEvaluator(Parser style); 00216 00221 ExpEvaluator(const ExpEvaluator& original); 00222 00226 virtual ~ExpEvaluator(); 00227 00234 int compile(const char* expr, GenObject* context = 0); 00235 00242 bool evaluate(ObjList* results, GenObject* context = 0) const; 00243 00250 inline bool evaluate(ObjList& results, GenObject* context = 0) const 00251 { return evaluate(&results,context); } 00252 00261 int evaluate(NamedList& results, unsigned int index = 0, const char* prefix = 0, GenObject* context = 0) const; 00262 00270 int evaluate(Array& results, unsigned int index, GenObject* context = 0) const; 00271 00276 inline bool simplify() 00277 { return trySimplify(); } 00278 00283 inline bool inError() const 00284 { return m_inError; } 00285 00290 inline bool null() const 00291 { return m_opcodes.count() == 0; } 00292 00298 void dump(const ObjList& codes, String& res) const; 00299 00304 inline void dump(String& res) const 00305 { return dump(m_opcodes,res); } 00306 00312 inline String dump(const ObjList& codes) const 00313 { String s; dump(codes,s); return s; } 00314 00319 inline String dump() const 00320 { String s; dump(s); return s; } 00321 00326 inline const TokenDict* operators() const 00327 { return m_operators; } 00328 00333 inline const TokenDict* unaryOps() const 00334 { return m_unaryOps; } 00335 00340 inline ExpExtender* extender() const 00341 { return m_extender; } 00342 00347 void extender(ExpExtender* ext); 00348 00354 static void pushOne(ObjList& stack, ExpOperation* oper); 00355 00361 static ExpOperation* popOne(ObjList& stack); 00362 00368 static ExpOperation* popAny(ObjList& stack); 00369 00376 virtual ExpOperation* popValue(ObjList& stack, GenObject* context = 0) const; 00377 00386 virtual bool runOperation(ObjList& stack, const ExpOperation& oper, GenObject* context = 0) const; 00387 00394 virtual bool runAllFields(ObjList& stack, GenObject* context = 0) const; 00395 00396 protected: 00402 static char skipWhites(const char*& expr); 00403 00410 inline static char condLower(char chr, bool makeLower) 00411 { return (makeLower && ('A' <= chr) && (chr <= 'Z')) ? (chr + ('a' - 'A')) : chr; } 00412 00420 Opcode getOperator(const char*& expr, const TokenDict* operators, bool caseInsensitive = false) const; 00421 00427 virtual bool keywordChar(char c) const; 00428 00434 virtual int getKeyword(const char* str) const; 00435 00442 bool gotError(const char* error = 0, const char* text = 0) const; 00443 00450 bool gotError(const char* error = 0, const char* text = 0); 00451 00459 virtual bool runCompile(const char*& expr, char stop = 0, Opcode nested = OpcNone); 00460 00467 virtual char skipComments(const char*& expr, GenObject* context = 0) const; 00468 00475 virtual int preProcess(const char*& expr, GenObject* context = 0); 00476 00482 virtual Opcode getOperator(const char*& expr); 00483 00489 virtual Opcode getUnaryOperator(const char*& expr); 00490 00496 virtual Opcode getPostfixOperator(const char*& expr); 00497 00503 virtual const char* getOperator(Opcode oper) const; 00504 00510 virtual int getPrecedence(Opcode oper) const; 00511 00517 virtual bool getRightAssoc(Opcode oper) const; 00518 00525 virtual bool getSeparator(const char*& expr, bool remove); 00526 00533 virtual bool getInstruction(const char*& expr, Opcode nested = OpcNone); 00534 00541 virtual bool getOperand(const char*& expr, bool endOk = true); 00542 00548 virtual bool getNumber(const char*& expr); 00549 00555 virtual bool getString(const char*& expr); 00556 00562 virtual bool getFunction(const char*& expr); 00563 00569 virtual bool getField(const char*& expr); 00570 00576 ExpOperation* addOpcode(Opcode oper, bool barrier = false); 00577 00584 ExpOperation* addOpcode(Opcode oper, long int value, bool barrier = false); 00585 00590 ExpOperation* addOpcode(const String& value); 00591 00596 ExpOperation* addOpcode(long int value); 00597 00602 ExpOperation* addOpcode(bool value); 00603 00611 ExpOperation* addOpcode(Opcode oper, const String& name, long int value = 0, bool barrier = false); 00612 00617 virtual bool trySimplify(); 00618 00626 virtual bool runEvaluate(const ObjList& opcodes, ObjList& stack, GenObject* context = 0) const; 00627 00636 virtual bool runEvaluate(const ObjVector& opcodes, ObjList& stack, GenObject* context = 0, unsigned int index = 0) const; 00637 00644 virtual bool runEvaluate(ObjList& stack, GenObject* context = 0) const; 00645 00654 virtual bool runFunction(ObjList& stack, const ExpOperation& oper, GenObject* context = 0) const; 00655 00663 virtual bool runField(ObjList& stack, const ExpOperation& oper, GenObject* context = 0) const; 00664 00672 virtual bool runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context = 0) const; 00673 00677 const TokenDict* m_operators; 00678 00682 const TokenDict* m_unaryOps; 00683 00687 ObjList m_opcodes; 00688 00692 bool m_inError; 00693 00694 private: 00695 ExpExtender* m_extender; 00696 }; 00697 00702 class YSCRIPT_API ExpOperation : public NamedString 00703 { 00704 friend class ExpEvaluator; 00705 YCLASS(ExpOperation,NamedString) 00706 public: 00711 inline static long int nonInteger() 00712 { return LONG_MIN; } 00713 00718 inline ExpOperation(const ExpOperation& original) 00719 : NamedString(original.name(),original), 00720 m_opcode(original.opcode()), m_number(original.number()), 00721 m_barrier(original.barrier()) 00722 { } 00723 00729 inline ExpOperation(const ExpOperation& original, const char* name) 00730 : NamedString(name,original), 00731 m_opcode(original.opcode()), m_number(original.number()), 00732 m_barrier(original.barrier()) 00733 { } 00734 00741 inline explicit ExpOperation(const String& value, const char* name = 0, bool autoNum = false) 00742 : NamedString(name,value), 00743 m_opcode(ExpEvaluator::OpcPush), 00744 m_number(autoNum ? value.toLong(nonInteger()) : nonInteger()), 00745 m_barrier(false) 00746 { if (autoNum && value.isBoolean()) m_number = value.toBoolean() ? 1 : 0; } 00747 00753 inline explicit ExpOperation(const char* value, const char* name = 0) 00754 : NamedString(name,value), 00755 m_opcode(ExpEvaluator::OpcPush), m_number(nonInteger()), m_barrier(false) 00756 { } 00757 00763 inline explicit ExpOperation(long int value, const char* name = 0) 00764 : NamedString(name,"NaN"), 00765 m_opcode(ExpEvaluator::OpcPush), m_number(value), m_barrier(false) 00766 { if (value != nonInteger()) String::operator=((int)value); } 00767 00773 inline explicit ExpOperation(bool value, const char* name = 0) 00774 : NamedString(name,String::boolText(value)), 00775 m_opcode(ExpEvaluator::OpcPush), m_number(value ? 1 : 0), m_barrier(false) 00776 { } 00777 00785 inline ExpOperation(ExpEvaluator::Opcode oper, const char* name = 0, long int value = nonInteger(), bool barrier = false) 00786 : NamedString(name,""), 00787 m_opcode(oper), m_number(value), m_barrier(barrier) 00788 { } 00789 00797 inline ExpOperation(ExpEvaluator::Opcode oper, const char* name, const char* value, bool barrier = false) 00798 : NamedString(name,value), 00799 m_opcode(oper), m_number(nonInteger()), m_barrier(barrier) 00800 { } 00801 00806 inline ExpEvaluator::Opcode opcode() const 00807 { return m_opcode; } 00808 00813 inline bool isInteger() const 00814 { return m_number != nonInteger(); } 00815 00820 inline long int number() const 00821 { return m_number; } 00822 00827 inline bool barrier() const 00828 { return m_barrier; } 00829 00835 inline long int operator=(long int num) 00836 { m_number = num; String::operator=((int)num); return num; } 00837 00843 virtual ExpOperation* clone(const char* name) const 00844 { return new ExpOperation(*this,name); } 00845 00850 inline ExpOperation* clone() const 00851 { return clone(name()); } 00852 00853 private: 00854 ExpEvaluator::Opcode m_opcode; 00855 long int m_number; 00856 bool m_barrier; 00857 }; 00858 00863 class YSCRIPT_API ExpFunction : public ExpOperation 00864 { 00865 YCLASS(ExpFunction,ExpOperation) 00866 public: 00872 inline ExpFunction(const char* name, long int argc = 0) 00873 : ExpOperation(ExpEvaluator::OpcFunc,name,argc) 00874 { if (name) (*this) << "[function " << name << "()]"; } 00875 00881 virtual ExpOperation* clone(const char* name) const; 00882 }; 00883 00888 class YSCRIPT_API ExpWrapper : public ExpOperation 00889 { 00890 public: 00896 inline ExpWrapper(GenObject* object, const char* name = 0) 00897 : ExpOperation(ExpEvaluator::OpcPush,name, 00898 object ? object->toString().c_str() : (const char*)0), 00899 m_object(object) 00900 { } 00901 00905 virtual ~ExpWrapper() 00906 { TelEngine::destruct(m_object); } 00907 00913 virtual void* getObject(const String& name) const; 00914 00920 virtual ExpOperation* clone(const char* name) const; 00921 00926 GenObject* object() const 00927 { return m_object; } 00928 00929 private: 00930 GenObject* m_object; 00931 }; 00932 00937 class YSCRIPT_API TableEvaluator 00938 { 00939 public: 00944 TableEvaluator(const TableEvaluator& original); 00945 00950 TableEvaluator(ExpEvaluator::Parser style); 00951 00957 TableEvaluator(const TokenDict* operators, const TokenDict* unaryOps); 00958 00962 virtual ~TableEvaluator(); 00963 00969 virtual bool evalWhere(GenObject* context = 0); 00970 00977 virtual bool evalSelect(ObjList& results, GenObject* context = 0); 00978 00984 virtual unsigned int evalLimit(GenObject* context = 0); 00985 00990 void extender(ExpExtender* ext); 00991 00992 protected: 00993 ExpEvaluator m_select; 00994 ExpEvaluator m_where; 00995 ExpEvaluator m_limit; 00996 unsigned int m_limitVal; 00997 }; 00998 00999 class ScriptRun; 01000 01005 class YSCRIPT_API ScriptContext : public RefObject, public ExpExtender 01006 { 01007 public: 01012 inline explicit ScriptContext(const char* name = 0) 01013 : m_params(name) 01014 { } 01015 01020 inline NamedList& params() 01021 { return m_params; } 01022 01027 inline const NamedList& params() const 01028 { return m_params; } 01029 01034 virtual const String& toString() const 01035 { return m_params; } 01036 01042 virtual void* getObject(const String& name) const; 01043 01048 virtual RefObject* refObj() 01049 { return this; } 01050 01055 virtual Mutex* mutex() = 0; 01056 01064 virtual bool hasField(ObjList& stack, const String& name, GenObject* context) const; 01065 01073 virtual NamedString* getField(ObjList& stack, const String& name, GenObject* context) const; 01074 01082 virtual bool runFunction(ObjList& stack, const ExpOperation& oper, GenObject* context); 01083 01091 virtual bool runField(ObjList& stack, const ExpOperation& oper, GenObject* context); 01092 01100 virtual bool runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context); 01101 01102 private: 01103 NamedList m_params; 01104 }; 01105 01110 class YSCRIPT_API ScriptCode : public RefObject 01111 { 01112 YCLASS(ScriptCode,RefObject) 01113 public: 01119 virtual bool initialize(ScriptContext* context) const = 0; 01120 01126 virtual bool evaluate(ScriptRun& runner, ObjList& results) const = 0; 01127 }; 01128 01133 class YSCRIPT_API ScriptStack : public ObjList 01134 { 01135 YCLASS(ScriptStack,ObjList) 01136 YNOCOPY(ScriptStack); 01137 public: 01142 ScriptStack(ScriptRun* owner) 01143 : m_runner(owner) 01144 { } 01145 01150 inline ScriptRun* runner() 01151 { return m_runner; } 01152 private: 01153 ScriptRun* m_runner; 01154 }; 01155 01160 class YSCRIPT_API ScriptRun : public GenObject, public Mutex 01161 { 01162 friend class ScriptCode; 01163 YCLASS(ScriptRun,GenObject) 01164 YNOCOPY(ScriptRun); 01165 public: 01169 enum Status { 01170 Invalid, 01171 Running, 01172 Incomplete, 01173 Succeeded, 01174 Failed, 01175 }; 01176 01182 ScriptRun(ScriptCode* code, ScriptContext* context = 0); 01183 01187 virtual ~ScriptRun(); 01188 01193 inline ScriptCode* code() const 01194 { return m_code; } 01195 01200 inline ScriptContext* context() const 01201 { return m_context; } 01202 01206 inline Status state() const 01207 { return m_state; } 01208 01214 static const char* textState(Status state); 01215 01220 inline const char* textState() const 01221 { return textState(m_state); } 01222 01227 inline ObjList& stack() 01228 { return m_stack; } 01229 01234 inline const ObjList& stack() const 01235 { return m_stack; } 01236 01241 inline ScriptRun* clone() const 01242 { return new ScriptRun(code(),context()); } 01243 01248 Status reset(); 01249 01254 Status execute(); 01255 01260 Status run(); 01261 01268 bool runAssign(const ExpOperation& oper, GenObject* context = 0); 01269 01270 protected: 01275 Status resume(); 01276 01277 private: 01278 ScriptCode* m_code; 01279 ScriptContext* m_context; 01280 Status m_state; 01281 ObjList m_stack; 01282 }; 01283 01288 class YSCRIPT_API ScriptParser : public GenObject 01289 { 01290 YCLASS(ScriptParser,GenObject) 01291 public: 01295 virtual ~ScriptParser(); 01296 01303 virtual bool parse(const char* text, bool fragment = false) = 0; 01304 01311 virtual bool parseFile(const char* name, bool fragment = false); 01312 01316 inline void clear() 01317 { setCode(0); } 01318 01323 inline ScriptCode* code() const 01324 { return m_code; } 01325 01330 virtual ScriptContext* createContext() const; 01331 01338 virtual ScriptRun* createRunner(ScriptCode* code, ScriptContext* context = 0) const; 01339 01345 inline ScriptRun* createRunner(ScriptContext* context = 0) const 01346 { return createRunner(code(),context); } 01347 01348 protected: 01352 inline ScriptParser() 01353 : m_code(0) 01354 { } 01355 01360 void setCode(ScriptCode* code); 01361 01362 private: 01363 ScriptCode* m_code; 01364 }; 01365 01370 class YSCRIPT_API JsObject : public ScriptContext 01371 { 01372 YCLASS(JsObject,ScriptContext) 01373 public: 01380 JsObject(const char* name = "Object", Mutex* mtx = 0, bool frozen = false); 01381 01385 virtual ~JsObject(); 01386 01391 virtual Mutex* mutex() 01392 { return m_mutex; } 01393 01402 virtual bool runFunction(ObjList& stack, const ExpOperation& oper, GenObject* context); 01403 01411 virtual bool runField(ObjList& stack, const ExpOperation& oper, GenObject* context); 01412 01420 virtual bool runAssign(ObjList& stack, const ExpOperation& oper, GenObject* context); 01421 01428 virtual ExpOperation* popValue(ObjList& stack, GenObject* context = 0); 01429 01434 inline bool frozen() const 01435 { return m_frozen; } 01436 01440 inline void freeze() 01441 { m_frozen = true; } 01442 01447 static void initialize(ScriptContext* context); 01448 01449 protected: 01458 virtual bool runNative(ObjList& stack, const ExpOperation& oper, GenObject* context); 01459 01460 private: 01461 bool m_frozen; 01462 Mutex* m_mutex; 01463 }; 01464 01469 class YSCRIPT_API JsFunction : public JsObject 01470 { 01471 YCLASS(JsFunction,JsObject) 01472 public: 01473 01478 inline JsFunction(Mutex* mtx = 0) 01479 : JsObject("Function",mtx,true) 01480 { } 01481 01490 virtual bool runDefined(ObjList& stack, const ExpOperation& oper, GenObject* context); 01491 01492 }; 01493 01498 class YSCRIPT_API JsParser : public ScriptParser 01499 { 01500 YCLASS(JsParser,ScriptParser) 01501 public: 01508 virtual bool parse(const char* text, bool fragment = false); 01509 01514 virtual ScriptContext* createContext() const; 01515 01522 virtual ScriptRun* createRunner(ScriptCode* code, ScriptContext* context = 0) const; 01523 01529 inline ScriptRun* createRunner(ScriptContext* context = 0) const 01530 { return createRunner(code(),context); } 01531 01536 void adjustPath(String& script); 01537 01542 inline const String& basePath() const 01543 { return m_basePath; } 01544 01549 inline void basePath(const char* path) 01550 { m_basePath = path; } 01551 01559 static ScriptRun::Status eval(const String& text, ExpOperation** result = 0, ScriptContext* context = 0); 01560 01561 private: 01562 String m_basePath; 01563 }; 01564 01565 }; // namespace TelEngine 01566 01567 #endif /* __YATESCRIPT_H */ 01568 01569 /* vi: set ts=8 sw=4 sts=4 noet: */