Source: ../../extras/script/script.h
|
|
|
|
// Copyright (C) 1999-2000 Open Source Telecom Corporation.
//
// 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.
//
// As a special exception to the GNU General Public License, permission is
// granted for additional uses of the text contained in its release
// of Common C++.
//
// The exception is that, if you link the Common C++ library with other
// files to produce an executable, this does not by itself cause the
// resulting executable to be covered by the GNU General Public License.
// Your use of that executable is in no way restricted on account of
// linking the Common C++ library code into it.
//
// This exception does not however invalidate any other reasons why
// the executable file might be covered by the GNU General Public License.
//
// This exception applies only to the code released under the
// name Common C++. If you copy code from other releases into a copy of
// Common C++, as the General Public License permits, the exception does
// not apply to the code that you add in this way. To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own for Common C++, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.
#ifndef __CCXX_SCRIPT_H__
#define __CCXX_SCRIPT_H__
#ifndef __CCXX_MISC_H__
#include <cc++/misc.h>
#else
#ifdef __CCXX_NAMESPACE_H__
#include <cc++/macros.h>
#endif
#endif
class ScriptCommand;
class ScriptImage;
class ScriptInterp;
struct _line;
#define TRAP_BITS (sizeof(unsigned long) * 8)
#define SCRIPT_STACK_SIZE 10
#define KEYWORD_INDEX_SIZE 37
#define SYMBOL_INDEX_SIZE 187
#define SCRIPT_INDEX_SIZE KEYWORD_INDEX_SIZE
typedef bool (ScriptInterp::*scriptmethod_t)(void);
typedef char *(ScriptCommand::*scriptcheck_t)(struct _line *line);
#pragma pack(1)
typedef struct _symbol
{
struct _symbol *next;
char *id;
struct
{
unsigned size : 16;
bool initial : 1;
bool system : 1;
bool readonly : 1;
bool commit : 1;
} flags;
char data[1];
} scriptsymbol_t;
typedef struct _line
{
struct _line *next;
unsigned long mask;
unsigned short loop;
unsigned short line;
unsigned short argc;
scriptmethod_t method;
char *cmd;
char **args;
} scriptline_t;
typedef struct _script
{
struct _script *next;
struct _line *first;
struct _line *trap[TRAP_BITS];
struct _line *skip[10];
unsigned long mask;
char *name;
} scriptname_t;
typedef struct
{
const char *keyword;
scriptmethod_t method;
scriptcheck_t check;
} SCRKEYWORDS;
#pragma pack()
/**
* This class holds the bound keyword set for a given Bayonne style
* script interpreter. Application specific dialects are created
* by deriving a application specific version of ScriptCommand which
* then binds application specific keywords and associated methods
* in an application derived ScriptInterp which are typecast to
* (scriptmethod_t).
*
* @author David Sugar <dyfet@ostel.com>
* @short Bayonne script keyword binding tables and compiler constants.
*/
class ScriptCommand : public Keydata, public Mutex
{
private:
friend class ScriptImage;
friend class ScriptInterp;
#pragma pack(1)
typedef struct _keyword
{
struct _keyword *next;
scriptmethod_t method;
scriptcheck_t check;
char keyword[1];
} keyword_t;
#pragma pack()
keyword_t *keywords[KEYWORD_INDEX_SIZE];
char *traps[TRAP_BITS];
ScriptImage *active;
int keyword_count;
int trap_count;
/**
* Get the method handler associated with a given keyword. This
* is used by ScriptImage when compiling.
*
* @param keyword to search for.
* @return method handler to execute for this keyword.
*/
scriptmethod_t getHandler(const char *keyword);
/**
* Check keyword syntax.
*
* @return syntax error string or NULL.
* @param name of keyword to check.
*/
char *Check(char *command, scriptline_t *line);
protected:
/**
* Get the trap id number associated with a trap name.
*
* @return trap id number, 0 (exit) if invalid.
* @param name of trap identifier.
*/
virtual unsigned getTrapId(const char *trap);
/**
* Get a trap mask for a given identifer. This is a virtual
* since some derived handlers may manipulate mask bits.
*
* @return signal mask.
* @param identifier.
*/
virtual unsigned long getTrapMask(unsigned id);
/**
* A helper method for the compiler. Converts a named
* trap into it's bit shifted mask. By making it a virtual,
* derived dialects can add "aliases" to default trap names.
*
* @param name of trap identifier.
* @return bit shifted mask or 0 if invalid.
*/
virtual unsigned long getTrapModifier(const char *trapname)
{return getTrapMask(trapname);};
/**
* A helper method for the compiler used specifically for
* "^" trap subsection requests. These will occasionally
* carry different attribute settings.
*
* @param name of trap identifier.
* @return bit shifted mask or 0 if invalid.
*/
virtual unsigned long getTrapMask(const char *trapname);
/**
* Default compiler syntax to accept any syntax.
*/
char *chkIgnore(scriptline_t *line);
/**
* A check used by "inc" and "dec".
*
* @return synxtax error message string or NULL.
* @param line statement.
*/
char *chkHasModify(scriptline_t *line);
/**
* Script compiler syntax check for certain variable using
* statements such as "clear". Assumes list of valid variable
* arguments.
*/
char *chkHasVars(scriptline_t *line);
/**
* Script compiler syntax check for assignment statements
* such as "set", "for", etc.
*
* @return syntax error message string or NULL.
* @param line statement.
*/
char *chkHasList(scriptline_t *line);
/**
* Script compiler syntax check for commands that require
* no arguments to be present.
*
* @return syntax error message string or NULL.
* @param line statement.
*/
char *chkNoArgs(scriptline_t *line);
/**
* Script compiler syntax check for commands that require
* one or more arguments to be present.
*
* @return syntax error message string or NULL.
* @param line statement.
*/
char *chkHasArgs(scriptline_t *line);
/**
* Load a set of keywords into the system keyword table. This
* provides a convenient method of initializing and adding to
* the keyword indexes.
*
* @param keyword entries to load.
*/
void Load(SCRKEYWORDS *keywords);
/**
* Add a trap handler symbolic identity to the keyword table.
* These are used to handle signal mask coercion and event
* branch points in the compiler.
*
* @param requested trap name.
* @return assigned id number for the trap.
*/
int Trap(const char *name);
/**
* Get count of active traps.
*
* @return count of active trap identifiers.
*/
inline int getCount(void)
{return trap_count;};
/**
* Perform compile time check of a specified symbol.
*
* @return syntax error message string.
* @param line pointer.
*/
virtual char *Check(scriptcheck_t check, scriptline_t *line)
{return (this->*(check))(line);};
/**
* Load a keydata entry for compile-time constants and
* bind the default ScriptInterp base class methods. This
* class is never used alone, so no public constructor is
* provided.
*
* @param keydata entry for constants.
*/
ScriptCommand(const char *cfgfile);
};
/**
* This class manages symbol tables for the scripting engine. A symbol
* is a variable with a reserved memory space. Some derived systems, like
* Bayonne IVR, may make use of a channel specific and global symbol
* tables.
*
* @author David Sugar <dyfet@ostel.com>
* @short Symbol table management for scripting engine.
*/
class ScriptSymbol : public SharedMemPager
{
private:
int symsize;
scriptsymbol_t *index[SYMBOL_INDEX_SIZE];
unsigned getIndex(const char *symbol);
protected:
/**
* Fetch a symbol entry. Normally this is presumed to be from
* the native symbol table. However, the use of a virtual allows
* one to derive special "system" symbols as needed for Bayonne
* dialects, as well as specify special attributes and properties
* for system symbols. For example, in the Bayonne IVR, symbols
* might be used to retrieve the current DTMF digit buffer and
* count, but these are stored as and manipulated in a channel
* structure rather than in "symbol space".
*
* @return symbol entry or NULL if not found.
* @param symbol name to find or create.
* @param size of symbol space to create if not found.
*/
virtual scriptsymbol_t *getEntry(const char *symbol, int size = 0);
/**
* A virtual method used when "committing" symbol changes.
* Normally this is a non-operation, but when system specific
* dialects are created, special symbols that must be converted
* from strings into other kinds of internal data types, or that
* might perform operations can be represented with the commit.
*
* @param symbol to commit.
*/
virtual void Commit(scriptsymbol_t *sym)
{return;};
/**
* Fetch default symbol size.
*
* @return default symbol size.
*/
inline int getSymbolSize(void)
{return symsize;};
public:
ScriptSymbol(int size, int pgsize = 1024);
/**
* Fetch the address of the value of a given symbol identifier.
*
* @param symbol name.
* @return symbol buffer address, or NULL if not found.
*/
char *getSymbol(const char *symbol);
/**
* Set a given symbol to a new value.
*
* @param symbol name to find.
* @param value string to set.
* @return NULL if not found, else value.
*/
char *setSymbol(const char *symbol, const char *value = "");
/**
* Create a new symbol entry of a specified size.
*
* @param symbol name to create.
* @param size of symbol, otherwise default size used.
* @param buffer or NULL if exists.
*/
char *setSymbol(const char *symbol, int size = 0);
/**
* Clear a symbol definition. This does not remove the
* entry if it already exists. It mearly clears the initial
* flag so it still can appear undefined.
*
* @param symbol name to clear.
*/
void clrSymbol(const char *id);
/**
* Purge user defined symbols and memory space.
*/
void Purge(void);
};
/**
* A derivable class to hold compiled script images for active processes.
* This includes the script image compiler itself. Typically, a script is
* compiled one file at a time from a directory, and the committed, during
* the constructor in a derived class.
*
* @author David Sugar <dyfet@ostel.com>.
* @short Script compiler image set.
*/
class ScriptImage : public MemPager
{
private:
ifstream scrFile;
ScriptCommand *cmds;
int refcount;
scriptname_t *index[SCRIPT_INDEX_SIZE];
char buffer[512];
char *bp;
bool quote;
friend class ScriptInterp;
char *getToken(void);
protected:
/**
* Construct a new working image. This must be derived to an
* application specific compiler that can scan directories and
* invoke the compiler as needed.
*
* @param cmdset of keyword table object used.
*/
ScriptImage(ScriptCommand *cmdset);
/**
* The script compiler itself. This linearly compiles a Bayonne
* script file that is specified. Normally used along with a dir
* scanner in the constructor.
*
* @return lines of script compiled.
* @param name of script file to compile.
*/
int Compile(const char *scrfile);
/**
* Used in the derived constructor to "commit" the current image
* for new processes. This is usually the last statement in the
* derived constructor.
*/
void Commit(void);
/**
* Fetch named script.
*
* @param script name to find.
* @return script or NULL.
*/
scriptname_t *getScript(const char *name);
};
/**
* System script interpreter core engine class. This class is further
* derived to impliment application specific language dialects.
*
* @author David Sugar <dyfet@ostel.com>
* @short Extensible Bayonne Scripting Engine.
*/
class ScriptInterp : public ScriptSymbol
{
private:
typedef struct
{
scriptname_t *script;
scriptline_t *line;
unsigned index, argc;
char **argv;
} scriptcontext_t;
ScriptCommand *cmd;
ScriptImage *image;
scriptcontext_t script[SCRIPT_STACK_SIZE + 1];
int stack;
bool scrSlog(void);
bool scrElog(void);
bool scrInc(void);
bool scrDec(void);
bool scrSet(void);
bool scrSize(void);
bool scrInit(void);
bool scrClear(void);
bool scrCall(void);
bool scrIf(void);
bool scrFor(void);
bool scrDo(void);
bool scrLoop(void);
bool scrBreak(void);
bool scrContinue(void);
bool scrReturn(void);
bool scrPop(void);
bool scrSelect(void);
friend class ScriptCommand;
protected:
/**
* Derive a new instance of the system script interpreter.
*
* @param symsize for default symbol sizing.
* @param pgsize for memory fragmentation.
*/
ScriptInterp(ScriptCommand *cmd, int symsize, int pgsize = 1024);
/**
* Fetch the active command interpreter subsystem.
*
* @return script interpreter.
*/
inline ScriptCommand *getCommand(void)
{return cmd;};
/**
* Used to process "conditional" arguments such as for IF/DO/LOOP
* statements. The index is kept at the next logical argument
* so a goto can be performed if needed.
*
* @return true if conditional test is true.
*/
bool Conditional(void);
/**
* Some systems can derive alternative "exit" commands
* which can call this routine after performing other
* operations.
*/
bool scrExit(void);
/**
* This is often called to process branching requests.
*/
bool scrGoto(void);
/**
* Attempt to attach script engine to active session and
* specify a starting script.
*
* @return false if failed to attach.
* @param name of script entry.
*/
bool Attach(const char *scrname);
/**
* Detach the current script image. If it is the last
* ref count and the exit flag is set, then delete it.
*/
void Detach(void);
/**
* Used to return channel identifiers in some systems.
*
* @return channel id or 0 for none.
*/
virtual unsigned getId(void)
{return 0;};
/**
* Fetch next logical option but do not evaluate. The index
* is advanced.
*
* @return option or NULL if end of list.
* @param optional default.
*/
char *getOption(const char *def = NULL);
/**
* Fetch and evaluate next logical option. If a symbol ref.
* then the symbol is also expressed. The index is advanced.
*
* @return option value or NULL if end of list.
* @param optional default value.
*/
char *getValue(const char *def = NULL);
/**
* Fetch a variable (symbol) that will be used to store data.
* This advances the index.
*
* @return symbol found if any.
* @param optional size to allocate if new symbol.
*/
scriptsymbol_t *getVariable(int size = 0);
/**
* Evaluate the content of an option retrieved with getOption.
*
* @return value of evaluation.
* @param option string.
*/
char *getContent(char *sym);
/**
* May be used to override processing of indirect content
* requests. This is used in the Bayonne IVR to fetch
* content constants based on language and country settings.
*
* @return symbol for indirect content.
* @param indirect fetch request.
*/
virtual scriptsymbol_t *getIndirect(char *sym)
{return NULL;};
/**
* Advance program to the next script statement.
*/
void Advance(void);
/**
* Set error variable and advance to either the error handler
* or next script statement.
*
* @param error message.
*/
void Error(const char *error);
/**
* Set the execution interpreter to a trap identifier. If no
* trap id exists, then advance to next script statement (unless
* exit trap).
*
* @param id of trap to select numerically.
*/
void Trap(unsigned id);
/**
* Select trap by symbolic name and execute if found, else advance
* to next script step (unless exit trap).
*
* @param name of trap to select.
*/
void Trap(const char *trapname);
/**
* Attempt to push a value onto the stack.
*
* @return false if stack overflow.
*/
bool Push(void);
/**
* Attempt to recall a previous stack level.
*
* @return false if stack underflow.
*/
bool Pull(void);
/**
* Execute the next pending script statement. If no statement
* is selected, then we execute the exit handler instead. We
* can also force feed a trap identifier.
*
* @return true if advanced to next script statement already.
* @param optional trap branch point (also checks mask).
*/
bool Step(const char *trapname = NULL);
/**
* Signals are used during "delayed" execution steps when a
* signal event has occured aynchronously with the execution
* of a script controlled state event handler. This mechanism
* can be used in place of calling implicit "Step" traps.
*
* @return true if signal handler is not blocked.
* @param name of signal identifier.
*/
bool Signal(const char *trapname);
/**
* Signals can be referenced by numeric id as well as by symbolic
* name.
*
* @return true if signal handler is not blocked.
* @param trap number of handler.
*/
bool Signal(unsigned trapid);
/**
* Runtime execution of script handler. This can be called in
* the current or derived class to invoke extensible methods.
*
* @return true if immediately ready for next step.
* @param derived method to call.
*/
virtual bool Execute(scriptmethod_t method)
{return (this->*(method))();};
/**
* Stop request handler. Used for handling external trap
* requests during a "Signal". This is needed in some state
* engines when the current state is being abandoned because
* of a signaled trap.
*
* @param signal mask forcing stop.
*/
virtual void Stop(unsigned long mask)
{return;};
/**
* Exit request handler. This is called when no script line
* exists. No default behavior is known.
*/
virtual void Exit(void) = 0;
};
#ifdef __CCXX_NAMESPACE_H__
#undef __CCXX_NAMESPACE_H__
#include <cc++/namespace.h>
#endif
#endif
Generated by: dyfet@home.sys on Fri May 12 08:41:04 200. |