⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interp.cpp

📁 GNU ccScript is a C++ class framework for creating a virtual machine execution system for use with a
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Copyright (C) 1999-2005 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, you may use this file as part of a free software// library without restriction.  Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License.  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 GNU// ccScript.  If you copy code from other releases into a copy of GNU// ccScript, 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 GNU ccScript, it is your choice// whether to permit this exception to apply to your modifications.// If you do not wish that, delete this exception notice.//#include "engine.h"using namespace std;using namespace ost;ScriptInterp::ScriptInterp() :Mutex(), ScriptSymbols(){	stack = 0;	cmd = NULL;	image = NULL;	memset(temps, 0, sizeof(temps));	tempidx = 0;	session = this;	thread = NULL;	trace = false;	lock = NULL;	sequence = 0;	setString(logname, sizeof(logname), "ccscript");}unsigned ScriptInterp::getTempSize(void){	return symsize + 1;}char *ScriptInterp::getTemp(void){	char *tmp = temps[tempidx++];		if(tempidx >= SCRIPT_TEMP_SPACE)		tempidx = 0;	return tmp;}ScriptInterp *ScriptInterp::getInterp(const char *id){	if(!atoi(id))		return this;	return NULL;}unsigned ScriptInterp::getId(void){	return 0;}bool ScriptInterp::isLocked(const char *id){	if(!strnicmp(id, "script.", 7) && initialized)		return true; 	if(!strnicmp(id, "initial.", 8) && initialized)		return true;	return false;} void ScriptInterp::setFrame(void){	frame[stack].index = 0;	updated = false;}const char *ScriptInterp::remapLocal(void){	return "script";}const char *ScriptInterp::getExternal(const char *opt){	char *cp, *p;	Line *line;	unsigned idx;	if(!cmd)		return NULL;	if(!stricmp(opt, "script.id"))	{		cp = getTemp();		snprintf(cp, symsize, "%d", getId());		return cp;	}	else if(!stricmp(opt, "script.index"))	{		if(!stack)			return "";		line = frame[stack - 1].line;		idx = frame[stack - 1].index;		cp = getTemp();		snprintf(cp, symsize, "%u", idx - 1);		return cp;	}	else if(!stricmp(opt, "script.basename"))	{		cp = getTemp();		setString(cp, symsize, frame[stack].script->name);		p = strstr(cp, "::");		if(p)			*p = 0;		return cp;	}	else if(!stricmp(opt, "script.subname"))	{                cp = getTemp();                setString(cp, symsize, frame[stack].script->name);                p = strstr(cp, "::");		if(p)			return p + 2;		return cp;	}	else if(!stricmp(opt, "script.name"))		return frame[stack].script->name;	else if(!stricmp(opt, "script.stack"))	{		cp = getTemp();		snprintf(cp, symsize, "%d", stack);		return cp;	}	else if(!stricmp(opt, "script.base"))	{		cp = getTemp();		snprintf(cp, symsize, "%d", frame[stack].base);	}	return cmd->getExternal(opt);}void ScriptInterp::initialize(void){}bool ScriptInterp::execute(Method method){	return (this->*(method))();}void ScriptInterp::branching(void){}Script::Name *ScriptInterp::getScript(const char *name){	if(!image)		return NULL;	Name *scr = image->getScript(name);	return scr;}void ScriptInterp::release(void){	if(lock)	{		lock->leaveMutex();		lock = NULL;	}}ScriptSymbols *ScriptInterp::getSymbols(const char *id){	if(strchr(id, '.') && session != this)	{		if(lock)			lock->leaveMutex();		session->enterMutex();		lock = dynamic_cast<Mutex *>(session);	}	else		release();		if(strchr(id, '.'))		return dynamic_cast<ScriptSymbols*>(session);	if(!frame[stack].local)		return dynamic_cast<ScriptSymbols*>(this);		return frame[stack].local;}ScriptSymbols *ScriptInterp::getLocal(void){	if(frame[stack].local)		return frame[stack].local;	return dynamic_cast<ScriptSymbols*>(this);}bool ScriptInterp::setConst(const char *id, const char *value){	MutexLock lock(*this);	Symbol *sym;	unsigned short len;	if(!value)		return false;	len = (unsigned short)strlen(value);	if(!len)		++len;	sym = mapSymbol(id, len);	if(!sym)		return false;	if(sym->type != symINITIAL)		return false;	sym->type = symCONST;	setString(sym->data, sym->size + 1, value);	return true;}char ScriptInterp::getPackToken(void){        const char *sym = extract(mapSymbol("script.token"));        if(!sym)                sym = ",";        if(!*sym)                sym = ",";        return *sym;}Script::Symbol *ScriptInterp::mapSymbol(const char *id, unsigned short size){	Symbol *sym;	if(*id != '@')		return mapDirect(id, size);	sym = mapDirect(++id);	if(!sym)		return NULL;	id = extract(sym);	if(!id)		return NULL;	if(!*id)		return NULL;	return mapDirect(id, size);}Script::Symbol *ScriptInterp::mapDirect(const char *id, unsigned short size){	Symbol *sym;	ScriptSymbols *syms;	unsigned count = 1;	char partial[70];	char *cp;	const char *p;	if(!id)		return NULL;	if(*id == '%' || *id == '&')		++id;	if(*id == '.' && frame[stack].script)	{		cp = (char *)strchr(frame[stack].script->filename, '.');		if(cp && !stricmp(cp, ".mod"))			setString(partial, sizeof(partial), "mod.");		else			setString(partial, sizeof(partial), "scr.");		addString(partial, sizeof(partial), frame[stack].script->name); 		cp = (char *)strstr("::", partial);		if(cp)			*cp = 0;		addString(partial, sizeof(partial), id);		id = partial;	}retry:	if(!isalpha(*id) && *id != '_')	{		logmissing(id, "invalid");		return NULL;	}			while(count < 64)	{		if(!id[count])			break;		if(!strchr("abcdefghijklmnopqrstuvwxyz01234567890._", tolower(id[count])))		{			logmissing(id, "invalid");			return NULL;		}		++count;	}	if(count == 64)	{		logmissing(id, "invalid");		return NULL;	}	if(size && isLocked(id))		size = 0;	syms = getSymbols(id);	if(!syms)		return NULL;	sym = deref(syms->find(id, size));	if(!sym && !strchr(id, '.'))	{		p = remapLocal();		if(!p)			return NULL;		snprintf(partial, sizeof(partial), "%s.%s", p, id);		id = partial;		goto retry;	}	return sym;}bool ScriptInterp::setNumber(const char *id, const char *value, unsigned dec){	Symbol *sym;		if(!dec)		dec = 11;	else		dec += 12;	sym = mapSymbol(id, dec);	if(!sym)		return false;	if(!value)		return true;	if(sym->type == symINITIAL)		sym->type = symNUMBER;	return commit(sym, value);}bool ScriptInterp::setSymbol(const char *id, const char *value, unsigned short size){	Symbol *sym;	if(!size)		size = symsize;	sym = mapSymbol(id, size);	if(!sym)		return false;	if(!value)		return true;	return commit(sym, value);}void ScriptInterp::trap(const char *trapid){	unsigned trap = cmd->getTrapId(trapid);	if(!trap)	{		if(!image)			return;		if(!stricmp(trapid, "first") || !stricmp(trapid, "top"))		{			frame[stack].tranflag = frame[stack].caseflag = false;			frame[stack].line = frame[stack].first;			return;		}	}	ScriptInterp::trap(trap);}void ScriptInterp::trap(unsigned id){	Line *trap = NULL;	unsigned base = frame[stack].base;	if(!image)		return;	// we can inherit traps at lower levels	for(;;)	{		trap = frame[stack].script->trap[id];		if(trap == frame[stack].first)		{			advance();			return;		}		if(!trap && !cmd->isInherited(id))		{			advance();			return;		}			if(trap || stack == base)			break;		pull();	}	// when doing a trap, always unwind loop or recursive stack frames	clearStack();	frame[stack].tranflag = frame[stack].caseflag = false;	frame[stack].line = frame[stack].first = trap;	if(!id)	{		if(!trap)			redirect("::exit");		exiting = true;	}}bool ScriptInterp::pull(void)      {        if(!stack)        {                error("stack-underflow");                  return false;        }        if(frame[stack].local && frame[stack - 1].local != frame[stack].local)        	delete frame[stack].local;        --stack;        return true;}bool ScriptInterp::push(void)      {        if(stack >= (SCRIPT_STACK_SIZE - 1))        {                error("stack-overflow");                return false;        }        frame[stack + 1] = frame[stack];        frame[stack + 1].caseflag = frame[stack + 1].tranflag = false;        ++stack;        return true;}void ScriptInterp::clearStack(void){	unsigned indexes[SCRIPT_STACK_SIZE];	unsigned idx = 0, len = 0;	char values[SCRIPT_STACK_SIZE * 6];	while(stack)	{		if(frame[stack - 1].script != frame[stack].script)			break;		pull();		indexes[idx++] = frame[stack].index;	}	snprintf(values, 3, "%d", idx);	setSymbol("script.stack", values, 4);	values[1] = 0;	while(idx--)	{		snprintf(values + len, sizeof(values) - len, ",%d", indexes[idx]);		len = (unsigned)strlen(values);	}	setSymbol("script.index", values + 1, 3);}void ScriptInterp::skip(void){        frame[stack].line = frame[stack].line->next;}void ScriptInterp::advance(void){	if(updated)		return;        frame[stack].line = frame[stack].line->next;	updated = true;}void ScriptInterp::error(const char *errmsg){        char evtname[128];        setSymbol("script.error", errmsg);        snprintf(evtname, sizeof(evtname), "error:%s", errmsg);        if(scriptEvent(evtname))                return;        if((frame[stack].script->mask & 0x02) && frame[stack].script->trap[1])	{                trap(1);		return;	}        advance();}bool ScriptInterp::tryCatch(const char *id){	Name *scr;	char namebuf[160];	char *cp;	unsigned stk = frame[stack].base;	setString(namebuf, sizeof(namebuf), frame[stk].script->name);	cp = strstr(namebuf, "::");	if(cp)		*(cp + 2) = 0;	else		addString(namebuf, sizeof(namebuf), "::");	addString(namebuf, sizeof(namebuf), id);	scr = getScript(namebuf);	if(!scr || !push())		return false;	branching();	frame[stack].script = scr;	frame[stack].line = frame[stack].first = scr->first;	frame[stack].caseflag = frame[stack].tranflag = 0;	frame[stack].index = 0;	frame[stack].mask = getMask();	image->fastBranch(this);	return true;}void ScriptInterp::gotoEvent(NamedEvent *evt){        clearStack();	branching();        frame[stack].tranflag = frame[stack].caseflag = false;        frame[stack].line = frame[stack].first = evt->line;        image->fastBranch(this);}bool ScriptInterp::scriptEvent(const char *name, bool inhereted){	char evtname[128];	const char *savname = name;	NamedEvent *evt, *top = frame[stack].script->events;	unsigned base = frame[stack].base;	const char *chkname = name;	unsigned current = stack;	bool found = false;#ifdef	HAVE_REGEX_H	regex_t *regex;#endifretry:	evt = frame[current].script->events;	while(evt)	{		switch(evt->type)		{		case '@':			if(!stricmp(evt->name, chkname))				found = true;			break;#ifdef	HAVE_REGEX_H		case '~':			regex = new regex_t;                	memset(regex, 0, sizeof(regex_t));                	if(!regcomp(regex, evt->name, REG_ICASE|REG_NOSUB|REG_NEWLINE))				if(!regexec(regex, chkname, 0, NULL, 0))					found = true;                        regfree(regex);                        delete regex;			break;#endif		}		if(found)			break;		evt = evt->next;	}	if(!evt && NULL != (chkname = strchr(chkname, ':')))	{		++chkname;		goto retry;	}	if(evt)	{		while(stack > current)			pull();		gotoEvent(evt);		return true;	}	while(current > base && frame[current].script->events == top && inhereted)		--current;	if(frame[current].script->events != top)	{		top = frame[current].script->events;		chkname = name;		goto retry;	}	if(*savname == '@')		++savname; 	snprintf(evtname, sizeof(evtname), "-catch-%s", savname);	if(tryCatch(evtname))		return true;	return false;}void ScriptInterp::initRuntime(Name *scr){	MutexLock lock(*this);        while(stack)                pull();        frame[stack].script = scr;        frame[stack].line = frame[stack].first = frame[stack].script->first;        frame[stack].index = 0;        frame[stack].caseflag = frame[stack].tranflag = false;        frame[stack].decimal = 0;        frame[stack].base = 0;        frame[stack].mask = frame[stack].script->mask;}bool ScriptInterp::attach(ScriptCommand *cmdref, const char *scrname){	Name *scr;	char msg[65];	cmd = cmdref;	enterMutex();	purge();		cmd->enterMutex();	image = cmd->active;	if(!image)	{		cmd->leaveMutex();		leaveMutex();		return false;	}	scr = getScript(scrname);	if(!scr || scr->access != scrPUBLIC)	{                snprintf(msg, sizeof(msg), "%s: attach failed", scrname);		if(!image->getLast(msg))		{			image->setValue(msg, "missing");			cmd->errlog("missing", msg);		}		cmd->leaveMutex();		leaveMutex();		logerror("missing; attach failed", scrname);		snprintf(msg, sizeof(msg), "%s: attach failed", scrname);		return false;	}	++image->refcount;	cmd->leaveMutex();	attach(cmd, image, scr);	return true;}void ScriptInterp::attach(ScriptCommand *cmdref, ScriptImage *img, Name *scr){	const char *scrname = scr->name;	ScriptImage::InitialList *ilist;	ScriptBinder *mod;	Name *init;	Line *line;	stack = 0;	cmd = cmdref;	exiting = initialized = false;	session = this;	thread = NULL;	bool selected = false;	Symbol *sym;		image = img;	frame[stack].local = NULL;	for(tempidx = 0; tempidx < SCRIPT_TEMP_SPACE; ++tempidx)		temps[tempidx] = (char *)alloc(symsize + 1);	tempidx = 0;	ilist = image->ilist;	while(ilist)	{		setSymbol(ilist->name, ilist->value, ilist->size);		ilist = ilist->next;	}	sym = mapSymbol("script.authorize", 0);	if(sym)		sym->type = symTIMER;	setSymbol("script.home", scrname);	mod = ScriptBinder::first;	while(mod)	{		mod->attach(this);		mod = mod->next;	}	initialize();	init = image->index[SCRIPT_INDEX_SIZE];	leaveMutex();	while(init)	{		initRuntime(init);		while(step())			Thread::yield();		init = init->next;	}	initialized = true;	enterMutex();	initRuntime(scr);	mod = ScriptBinder::first;	while(mod && !selected)	{		selected = mod->select(this);		mod = mod->next;	}	if(selected)		goto finish;	if(fastStart)	{		image->fastBranch(this);		goto finish;	}		line = getLine();	if(!line)		goto finish;	if(!stricmp(line->cmd, "options"))		execute(line->scr.method);finish:	leaveMutex();}void ScriptInterp::detach(void){	ScriptBinder *mod = ScriptBinder::first;	char scrname[65];	char *sp;	++sequence;	snprintf(scrname, sizeof(scrname), "%s", frame[0].script->name);	sp = strchr(scrname, ':');	if(sp)		*sp = 0;		if(!image)		return;	if(thread)	{		delete thread;		thread = NULL;	}	while(mod)	{		mod->detach(this);		mod = mod->next;	}	enterMutex();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -