📄 interp.cpp
字号:
cmd->enterMutex(); --image->refcount; if(image) if(!image->refcount && image != cmd->active) delete image; cmd->leaveMutex(); image = NULL; while(stack) pull(); purge(); leaveMutex();}bool ScriptInterp::step(void){ bool rtn = false; Line *next, *line; unsigned count = autoStepping; if(!image) return true; enterMutex(); if(!frame[stack].line) goto exit;trans: updated = false; frame[stack].index = 0; line = getLine(); next = line->next; rtn = execute(line->scr.method); release(); if(!rtn || !frame[stack].line) goto exit; if((frame[stack].tranflag && !trace)) { count = 0; goto trans; } if(count-- && frame[stack].line == next && !trace) goto trans;exit: while(!frame[stack].line && stack) { if(frame[stack - 1].local == frame[stack].local) break; pull(); if(frame[stack].line) advance(); } if(!frame[stack].line) { if(initialized) exit(); rtn = false; } else if(!rtn && thread) { release(); startThread(); } else release(); leaveMutex(); return rtn;}void ScriptInterp::ripple(void){ char namebuf[256]; char *label; Name *scr = frame[stack].script; Line *line; const char *name = getValue(NULL); snprintf(namebuf, sizeof(namebuf), "%s", name); label = strchr(namebuf, ':'); if(!label) { label = namebuf; goto find; } *(label++) = 0; scr = getScript(namebuf); if(!scr) { logmissing(name, "missing", "script"); error("label-missing"); return; } find: if(!label || !*label) { line = scr->first; goto done; } line = scr->first; while(line) { if(!stricmp(line->cmd, "label")) if(!stricmp(line->args[0], label)) break; line = line->next; } if(!line) { logmissing(name, "missing", "script"); error("label-missing"); return; }done: frame[stack].caseflag = false; frame[stack].script = scr; frame[stack].first = scr->first; frame[stack].line = line; frame[stack].index = 0; frame[stack].mask = scr->mask; updated = true;}bool ScriptInterp::redirect(bool evflag){ char namebuf[256]; const char *label = getValue(NULL); char *ext; size_t len; bool pvt = true; Name *scr = frame[stack].script; bool shortflag = true; unsigned base = frame[stack].base; bool fun = false; bool isfun = false; unsigned long mask = frame[stack].line->mask & frame[stack].mask & cmd->imask; if(!stricmp(frame[stack].line->cmd, "call")) fun = true; isfun = isFunction(scr); if(!label) { logmissing(label, "missing", "script"); error("branch-failed"); return true; } if(*label == '&') ++label; if(strstr(label, "::")) shortflag = false; len = strlen(label);retry: if(shortflag) { snprintf(namebuf, sizeof(namebuf), "%s", frame[stack].script->name); ext = strstr(namebuf, "::"); if(ext) *ext = 0; len = strlen(namebuf); snprintf(namebuf + len, sizeof(namebuf) - len, "::%s", label); scr = getScript(namebuf); if(scr) { pvt = false; goto script; } shortflag = false; goto retry; } else if(!strncmp(label, "::", 2)) { pvt = false; setString(namebuf, sizeof(namebuf), frame[stack].script->name); ext = strstr(namebuf, "::"); if(ext) setString(ext, sizeof(namebuf) + namebuf - ext, label); else addString(namebuf, sizeof(namebuf), label); label = namebuf; } else if(fun || isfun) { setString(namebuf, sizeof(namebuf), frame[stack].script->name); ext = strstr(namebuf, "::"); if(ext) setString(ext + 2, sizeof(namebuf) + namebuf - ext - 2, label); else { addString(namebuf, sizeof(namebuf), "::"); addString(namebuf, sizeof(namebuf), label); } scr = getScript(namebuf); if(scr) { pvt = false; goto script; } } scr = getScript(label);script: if(!scr) { logmissing(label, "missing", "script"); error("script-not-found"); return true; } if(pvt && isPrivate(scr)) { logmissing(label, "access", "script"); error("script-private"); return true; } if(!isfun && !fun && isFunction(scr) && scr != frame[stack].script) { logmissing(label, "access", "script"); error("script-function"); return true; } if(!isFunction(scr)) isfun = false; if(isfun && evflag) clearStack(); else while(evflag && stack > base) pull(); frame[stack].caseflag = false; frame[stack].script = scr; frame[stack].line = frame[stack].first = scr->first; frame[stack].index = 0; if(evflag && isfun && stack) { mask = frame[stack - 1].line->mask & frame[stack - 1].mask & cmd->imask; frame[stack].mask = (mask | scr->mask); } else if(evflag) frame[stack].mask = getMask(); else frame[stack].mask = (mask | scr->mask); updated = true; return true;}bool ScriptInterp::redirect(const char *scriptname){ Name *scr; char namebuf[128]; char *ext; if(!strncmp(scriptname, "::", 2)) { setString(namebuf, sizeof(namebuf), frame[stack].script->name); ext = strstr(namebuf, "::"); if(ext) *ext = 0; addString(namebuf, sizeof(namebuf), scriptname); } else setString(namebuf, sizeof(namebuf), scriptname); scr = getScript(namebuf); if(scr) { clearStack(); frame[stack].script = scr; frame[stack].line = frame[stack].first = scr->first; frame[stack].mask = getMask(); return true; } else logmissing(namebuf, "missing", "script"); return false;}unsigned long ScriptInterp::getMask(void){ unsigned sp = frame[stack].base; unsigned long mask = 0; while(sp < stack) { mask |= (frame[sp].script->mask & frame[sp].line->mask & cmd->imask); ++sp; } mask |= frame[stack].script->mask; return mask;}void ScriptInterp::enterThread(ScriptThread *thr){}bool ScriptInterp::eventThread(const char *evt, bool flag){ if(updated) return false; if(scriptEvent(evt, flag)) updated = true; return updated;}void ScriptInterp::exitThread(const char *msg){ if(updated) return; if(msg) error(msg); else advance(); updated = true;}void ScriptInterp::startThread(void){ thread->start();}void ScriptInterp::waitThread(void){ timeout_t timer = getTimeout(); if(!timer) return; Thread::sleep(timer); enterMutex(); delete thread; thread = NULL; if(!updated) error("timeout"); updated = true; leaveMutex();}bool ScriptInterp::exit(void){ if(exiting) return false; exiting = true; trap((unsigned)0); if(frame[stack].line) return true; return redirect("::exit");}bool ScriptInterp::signal(const char *trapname){ unsigned long mask, cmask; Line *line = getLine(); if(!image) return true; MutexLock lock(*this); cmask = mask = cmd->getTrapMask(trapname); mask &= line->mask; mask &= frame[stack].mask; if(frame[stack].line) mask &= frame[stack].line->mask; if(exiting) mask &= ~1; if(!mask) return false;// stop(mask); trap(trapname); branching(); image->fastBranch(this); return true;}bool ScriptInterp::signal(unsigned id){ unsigned long mask, cmask; if(!image) return true; if(!id && exiting) return false; MutexLock lock(*this); if(id >= TRAP_BITS) return false; cmask = mask = cmd->getTrapMask(id); mask &= frame[stack].mask; if(frame[stack].line) mask &= frame[stack].line->mask; if(!mask) return false;// stop(mask); trap(id); branching(); image->fastBranch(this); return true;}const char *ScriptInterp::hasOption(void){ for(;;) { if(frame[stack].index >= frame[stack].line->argc) return NULL; if(*frame[stack].line->args[frame[stack].index] != '=') break; frame[stack].index += 2; } return frame[stack].line->args[frame[stack].index];}const char *ScriptInterp::getOption(const char *def){ for(;;) { if(frame[stack].index >= frame[stack].line->argc) return (char *)def; if(*frame[stack].line->args[frame[stack].index] != '=') break; frame[stack].index += 2; } return frame[stack].line->args[frame[stack].index++];}const char *ScriptInterp::getSymbol(const char *id){ const char *val = getExternal(id); Symbol *sym; if(val) return val; sym = mapSymbol(id); if(!sym) return NULL; return extract(sym);} Script::Symbol *ScriptInterp::getSymbol(unsigned short size){ const char *id = getOption(NULL); if(!id) return NULL; if(*id != '%' && *id != '&' && *id != '@') return NULL; return mapSymbol(id, size);} const char *ScriptInterp::getMember(void){ const char *cp = strchr(frame[stack].line->cmd, '.'); if(cp) ++cp; return cp;}const char *ScriptInterp::getKeyoption(const char *kw){ unsigned idx = 0; Line *line = frame[stack].line; const char *opt; while(idx < line->argc) { opt = line->args[idx++]; if(*opt == '=') { if(!strnicmp(kw, opt + 1, strlen(kw))) return line->args[idx]; ++idx; } } return NULL;}const char *ScriptInterp::getKeyword(const char *kw){ unsigned idx = 0; Line *line = frame[stack].line; const char *opt; while(idx < line->argc) { opt = line->args[idx++]; if(*opt == '=') { if(!strnicmp(kw, opt + 1, strlen(kw))) return getContent(line->args[idx]); ++idx; } } return NULL;}Script::Symbol *ScriptInterp::getKeysymbol(const char *kw, unsigned size){ const char *opt = getKeyoption(kw); Symbol *sym; if(!opt) return NULL; if(*opt != '&') return NULL; sym = mapSymbol(opt, size); if(!sym) logmissing(opt); return deref(sym);}const char *ScriptInterp::getSymContent(const char *opt){ Symbol *sym; if(!opt) return NULL; if(*opt != '&') return getContent(opt); sym = mapSymbol(++opt); if(sym) return extract(sym); logmissing(opt); return NULL;}const char *ScriptInterp::getContent(const char *opt){ Symbol *sym; const char *val; char *tmp; Array *a; ScriptProperty *p; long v; if(!opt) return NULL; if(*opt == '%' && !opt[1]) return opt; if(*opt == '{') return ++opt; if(*opt == '#') { tmp = getTemp(); val = getExternal(++opt); if(val) { snprintf(tmp, 11, "%ld", strlen(val)); return tmp; } sym = mapSymbol(opt); if(!sym) { logmissing(opt); return NULL; } tmp = getTemp(); a = (Array *)&sym->data; switch(sym->type) { case symARRAY: snprintf(tmp, 11, "%d", a->tail); return tmp; case symCONST: case symNORMAL: snprintf(tmp, 11, "%ld", strlen(sym->data)); return tmp; case symCOUNTER: snprintf(tmp, 11, "%ld", atol(sym->data)); return tmp; case symTIMER: if(!sym->data[0]) { setString(tmp, 11, "999999999"); return tmp; } v = atol(extract(sym)); if(v < 0) snprintf(tmp, 11, "%ld", -v); else setString(tmp, 11, "0"); return tmp; case symINITIAL: return "0"; case symPROPERTY: opt = sym->data + sizeof(ScriptProperty *); memcpy(&p, &sym->data, sizeof(p)); snprintf(tmp, 11, "%ld", p->getValue(opt)); return tmp; case Script::symSTACK: case Script::symFIFO: if(a->tail >= a->head) snprintf(tmp, 11, "%d", a->tail - a->head); else snprintf(tmp, 11, "%d", a->count - (a->tail - a->head)); return tmp; default: return NULL; } } if(*opt != '%' && *opt != '@') return opt; if(*opt != '@') { ++opt; val = session->getExternal(opt); if(val) return val; } sym = mapSymbol(opt); if(sym) return extract(sym); logmissing(opt); return NULL;}const char *ScriptInterp::getValue(const char *def){ const char *opt = getOption(NULL); if(!opt) return def; opt = getContent(opt); if(!opt) return def; return opt;} void ScriptInterp::logerror(const char *msg, const char *scrname){ if(!scrname && frame[stack].script) scrname = frame[stack].script->name; if(scrname) slog.error() << logname << ": " << scrname << ": " << msg << endl; else slog.error() << logname << ": " << msg << endl;}void ScriptInterp::logmissing(const char *sym, const char *reason, const char *group){ char msg[65]; if(*sym == '@' || *sym == '%' || *sym == '&') ++sym; if(!frame[stack].line) return; slog.warn() << logname << ": " << frame[stack].script->filename << "(" << frame[stack].line->lnum << "): " << group << " " << sym << " " << reason << endl; snprintf(msg, sizeof(msg), "%s(%d): %s %s", frame[stack].script->filename, frame[stack].line->lnum, group, sym); cmd->enterMutex(); if(image->getLast(msg)) { cmd->leaveMutex(); return; } image->setValue(msg, reason); if(!stricmp(reason, "undefined")) reason = "missing"; cmd->errlog(reason, msg); cmd->leaveMutex();}bool ScriptInterp::done(void){ if(!stack && !frame[stack].line && exiting) return true; return false;}bool ScriptInterp::catSymbol(const char *id, const char *value, unsigned short size){ Symbol *sym; if(!id) return false; if(!value) return true; while(*id == '%' || *id == '&' || *id == '@') ++id; if(!*id) return false; MutexLock local(*this); if(strchr(id, '.') && session != this) MutexLock sess(*session); sym = mapSymbol(id, size); if(!sym) return false; return append(sym, value);} bool ScriptInterp::putSymbol(const char *id, const char *value, unsigned short size){ Symbol *sym; if(!id) return false; if(!value) value = ""; while(*id == '&' || *id == '%' || *id == '@') ++id; if(!*id) return false; MutexLock local(*this); if(strchr(id, '.') && session != this) MutexLock sess(*session); sym = mapSymbol(id, size); if(!sym) return false; return commit(sym, value);}bool ScriptInterp::getSymbol(const char *id, char *buffer, unsigned short size){ Symbol *sym; const char *cp; if(!id) return false; if(!buffer) return false; while(*id == '&' || *id == '%' || *id == '@') ++id; if(!*id) return false; MutexLock local(*this); if(strchr(id, '.') && session != this) MutexLock sess(*session); sym = mapSymbol(id); if(!sym) return false; *buffer = 0; cp = extract(sym); if(!cp) return false; setString(buffer, size, cp); return true;}timeout_t ScriptInterp::getTimeout(void){ if(!thread) return 0; return thread->getTimeout();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -