/************************************************************************* * * 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 #include #include using namespace std; static fp_stream mout(stdout),merr(stderr); struct tt_env : public op_env { sspile var; tt_env(opmap& map) : op_env(map) {} int split(sref& first,sref& rest) throw(merror_t) { static const charset spec("+-*%/<=>^_!~&|,?:;"); static const charset delim("()\"\\"); static const charset specws=spec|delim|cset_ws; int s; rest=rest.right_first_not_of(cset_ws); if((s=rest.skip(cset_quotes))>0) { first=rest.left(s); rest=rest.right(s); } else if((s=rest.skip(cset_para))>0) { first=Trim(rest.left(s),cset_para); rest=rest.right(s); } else if((s=rest.skip(cset_braces))>0) { first=rest.left(s); rest=rest.right(s); } else if(spec.test(*rest)) { first=rest.left_first_not_of(spec); rest=rest.adv(first); } else { first=rest.left_first_of(specws); rest=rest.adv(first); } return first.nempty(); } void term(mstream& out,expr_t* x) throw(merror_t) { if(x->expr.empty()) { x->status=0; } else if(x->expr.skip(cset_quotes)==x->expr.size()) { out<expr(1,-3); x->status=0; } else if(x->expr.find_not_of(cset_real)<0) { out<expr; x->status=0; } else { for(sspile::iterator s=var.begin();s!=var.end();s++) if(s->first==x->expr) { out<second; x->status=OP_LOCAL; break; } } } }; #define TT_IMPL(n) \ static void impl_##n(mstream& out,tt_env& env,const sref& L,const sref& R) #define TT_ADDN(p,f,n,d) \ M.add(new op_t(#n,0,p,1,2,0,(op_t::op2_t)impl_##f,d)) TT_IMPL(assign) { sspile& var=env.var; for(sspile::iterator p=var.begin();p!=var.end();p++) if(p->first==L) { p->second=R; return; } var.push_back(sstring(L,R)); } TT_IMPL(incr) { sspile& var=env.var; for(sspile::iterator p=var.begin();p!=var.end();p++) if(p->first==L) { p->second=itoa(atoi(p->second)+atoi(R)); break; } } TT_IMPL(decr) { sspile& var=env.var; for(sspile::iterator p=var.begin();p!=var.end();p++) if(p->first==L) { p->second=itoa(atoi(p->second)-atoi(R)); break; } } inline void opAddTT(opmap& M) { TT_ADDN(4,assign,=,"C style"); TT_ADDN(4,assign,:=,"new var"); TT_ADDN(4,incr,+=,"C style"); TT_ADDN(4,decr,-=,"C style"); } main(int argc,char* argv[]) try { opmap ops; opAddHEXP(ops); opAddTT(ops); tt_env env(ops); mstring buf; sref_t line; expr_t expr; if(argc>1) { buf.load(sref(argv[1])); sref first,rest=buf; Splitln(first,rest); if(first.left(2)!=sref("#!")) rest=buf; (expr=buf).expand(env); expr.eval(mout,env,OP_ALL); mout<<"\n"; } else { while(1) { merr<<"ops>"; cin.getline(line,sizeof(sref_t)); sref first,rest(line); Split(first,rest); if(first==sref("exit")) { break; } else if(first==sref("tree")) { expr.trav(mout,12); } else if(first==sref("eval")) { expr.eval(mout,env,OP_ALL); mout<<"\n"; } else { buf=line; try { (expr=buf).expand(env); expr.eval(mout,env,OP_ALL); mout<<"\n"; } catch(const merror_t& e) { merr<