From 5df79c53745fde5d6c3340a2979b1429cd5892c1 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sat, 8 Oct 2011 20:30:28 +0200 Subject: Initial import of htcd system 1.0 Signed-off-by: Henrik Rydberg --- src/lang/env.cc | 308 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 src/lang/env.cc (limited to 'src/lang/env.cc') diff --git a/src/lang/env.cc b/src/lang/env.cc new file mode 100644 index 0000000..83f1a7e --- /dev/null +++ b/src/lang/env.cc @@ -0,0 +1,308 @@ +/************************************************************************* + * + * HTCd - Copyright (C) 1998-2006 Henrik Rydberg + * + * 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 +#include + +static unsigned long seed=RandomInit(time(0)); + +mstring Random(int n) +{ + mstring s; + for(int i=0;i9) THROW("env: assertion on lib failed"); + s+=char(48+digit); + } + return s; +} + +/////////////////////////////////////////////////// + +void Env::clear_args() +{ + for(int i=0;i=0&&nresult; + else eval(out,rarg[n-xsize()],0); + } + } + else if(up) up->parg(out,n); +} + +void Env::parg(mstring& tmp,int n) throw(merror_t) +{ + swrite sw(tmp); + parg(sw,n); +} + +mstring Env::parg(int n) throw(merror_t) +{ + mswrite tmp; parg(tmp,n); return tmp.str(); +} + +////////////////////////////////////////////////////// + +int Env::onarg(int n) const +{ + if(args) { + if(n<0) n+=args; + if(n>=0&&nresult.nempty(); + else return rarg[n-xsize()]->expr.nempty(); + } + } + else if(up) return up->onarg(n); + return 0; +} + +expr_t* Env::arg(int n) throw(merror_t) { + if(args) { + if(n<0) n+=args; + if(n>=0&&narg(n); + THROW("env: bad arg number "<=0&&nresult; + else THROW("env: post-eval expression not readable here"); + } + } + else if(up) return up->operator[](n); + THROW("env: bad arg number "<get(t); + if(is_clear(p)&&!p->is_runnable()) return p->body; + THROW("env: could not find global variable "<get(t); + return is_clear(p)&&!p->is_runnable(); +} + +int Env::onglob(const sref& t) const +{ + const tok_t* p=toks->get(t); + return is_clear(p)&&!p->is_runnable()&&p->body.nempty(); +} + +void Env::glob_list(rpile& list,const sref& t) const +{ + list.clear(); + if(t.empty()) { + for(const_iterator p=toks->begin();p!=toks->end();++p) { + if(is_clear(*p)&&!(*p)->is_runnable()) list.push_back((*p)->name); + } + } + else { + int cont=1; + for(const tokmap* tok=toks;tok&&cont;tok=tok->up) { + for(const_iterator p=tok->begin();p!=tok->end();++p) { + if((*p)->name.left(t.size())==t&&is_clear(*p)&&!(*p)->is_runnable()) { + list.push_back((*p)->name); + cont=0; + } + } + } + } +} + +void Env::glob_adb(const sref& fx,const sref& t) throw(merror_t) +{ + if(!db) THROW("htc: no active database"); + rpile list; glob_list(list,t); + mrvec col(list.size()); + int index=-1; + for(int i=0;iIndex(fx+list[i].right(t.size())); + if(col[i]==db->Index()) index=i; + } + if(index<0) THROW("env: index required when adding a db record"); + int row=db->Find(glob(list[index])); + if(row>=0) { + for(int i=0;iSet(row,col[i],glob(list[i])); + } + else { + spile nlist(db->Tables()); + for(int i=0;iInsert(nlist,1); + } + if(row<0) THROW("htc: could not add record - denied"); + dbat=row; +} + +////////////////////////////////////////////////////// + +const sref Env::aloc(const sref& t,const sref& v) throw(merror_t) +{ + if(!is_tokname(t)) THROW("env: bad token name "<body; +} + +const sref Env::sloc(const sref& t,const sref& v) throw(merror_t) +{ + if(db) { + int p=db->FindIndex(*t=='@'?t.popf():t); + if(p>=0) { + if(p==db->Index()) THROW("env: cannot assign to db index"); + if(dbat<0||dbat>=db->size()) THROW("env: not a valid db record"); + db->Set(dbat,p,v); + return db->at(dbat,p); + } + } + return loc.set(new tok_t(t,v,tight()),1,1)->body; +} + +const sref Env::gloc(const sref& t) const throw(merror_t) +{ + if(db) { + int p=db->FindIndex(*t=='@'?t.popf():t); + if(p>=0) { + if(dbat>=0&&dbatsize()) return db->at(dbat,p); + else THROW("env: not a valid database record"); + } + } + const tok_t* p=loc.get(t); + if(is_clear(p)&&!p->is_runnable()) return p->body; + THROW("env: could not find local variable "<FindIndex(*t=='@'?t.popf():t); + if(p>=0) return dbat>=0&&dbatsize(); + } + const tok_t* p=loc.get(t); + return is_clear(p)&&!p->is_runnable(); +} + +int Env::onloc(const sref& t) const +{ + if(db) { + int p=db->FindIndex(*t=='@'?t.popf():t); + if(p>=0) return dbat>=0&&dbatsize()&&db->at(dbat,p).nempty(); + } + const tok_t* p=loc.get(t); + return is_clear(p)&&!p->is_runnable()&&p->body.nempty(); +} + +void Env::gloc_list(rpile& list,const sref& t) const +{ + list.clear(); + if(t.empty()) { + for(const_iterator p=loc.begin();p!=loc.end();++p) { + if(is_clear(*p)&&!(*p)->is_runnable()) list.push_back((*p)->name); + } + } + else if(*t=='@') { + if(db) { + sref tt=t.popf(); + for(int i=0;iTables();i++) { + if(tt.empty()||db->Table(i).left(tt.size())==tt) list.push_back(db->Table(i)); + } + } + else THROW("env: cannot use '@' - no active database"); + } + else { + int cont=1; + for(const tokmap* tok=&loc;tok&&cont;tok=tok->up) { + for(const_iterator p=tok->begin();p!=tok->end();++p) { + if((*p)->name.left(t.size())==t&&is_clear(*p)&&!(*p)->is_runnable()) { + list.push_back((*p)->name); + cont=0; + } + } + } + } +} + +void Env::gloc_adb(const sref& fx,const sref& t) throw(merror_t) +{ + if(!db) THROW("htc: no active database"); + rpile list; gloc_list(list,t); + mrvec col(list.size()); + int index=-1; + for(int i=0;iIndex(fx+list[i].right(t.size())); + if(col[i]==db->Index()) index=i; + } + if(index<0) THROW("env: index required when adding a db record"); + int row=db->Find(gloc(list[index])); + if(row>=0) { + for(int i=0;iSet(row,col[i],gloc(list[i])); + } + else { + spile nlist(db->Tables()); + for(int i=0;iInsert(nlist,1); + } + if(row<0) THROW("htc: could not add record - denied"); + dbat=row; +} + +////////////////////////////////////////////////////// + +const mstring sback="../",sident="./",sdots="..",sslash="//"; + +mstring Env::URI(const sref& raw) +{ + int s; mstring cwd=pwd.left_last('/'),uri=raw; + while(uri.left(sback.size())==sback) { + uri.erase(0,sback.size()); + cwd=cwd.left_last('/'); + } + while((s=uri.find(sback))>=0) { + mstring tmp=uri.left(s).left_last('/').leftand_last('/'); + tmp+=uri.right(s+sback.size()); + uri=tmp; + } + while((s=uri.find(sdots))>=0) uri.erase(s,sdots.size()); + while((s=uri.find(sident))>=0) uri.erase(s,sident.size()); + while((s=uri.find(sslash))>=0) uri.erase(s,sslash.size()); + if(*uri=='/') return uri; + else { cwd+='/'; cwd+=uri; return cwd; } +} -- cgit v1.2.3