/************************************************************************* * * 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; } }