/* Web Polygraph http://www.web-polygraph.org/ * (C) 2003-2006 The Measurement Factory * Licensed under the Apache License, Version 2.0 */ #include "pgl/pgl.h" #include "xstd/h/sstream.h" #include "xparser/TokenSym.h" #include "xparser/ParsSym.h" #include "pgl/PglPp.h" #include "pgl/PglParser.h" #include "pgl/PglTimeSym.h" #include "pgl/PglIntSym.h" #include "pgl/PglListSym.h" #include "pgl/PglContainerSym.h" #include "pgl/PglArraySym.h" #include "pgl/AgentSym.h" #include "pgl/NetPipeSym.h" #include "pgl/AddrMapSym.h" #include "pgl/SslWrapSym.h" #include "pgl/MembershipMapSym.h" #include "pgl/BenchSym.h" #include "pgl/PhaseSym.h" #include "pgl/StatsSampleSym.h" #include "pgl/PglStaticSemx.h" Array<AgentSym*> PglStaticSemx::TheAgentsToUse; Array<NetPipeSym*> PglStaticSemx::TheNetPipesToUse; Array<AddrMapSym*> PglStaticSemx::TheAddrMapsToUse; Array<SslWrapSym*> PglStaticSemx::TheSslWrapsToUse; Array<ContainerSym*> PglStaticSemx::TheAddrSubstsToUse; Array<MembershipMapSym*> PglStaticSemx::TheMembershipsToUse; BenchSym *PglStaticSemx::TheBench = 0; Array<PhaseSym*> PglStaticSemx::TheSchedule; Array<StatsSampleSym*> PglStaticSemx::TheSmplSchedule; Time PglStaticSemx::TheWorkSetLen; int PglStaticSemx::TheWorkSetCap = -1; static const String strAddrArr = "addr[]"; template <class Item> static void PglStaticSemxDestroyArray(Array<Item> &arr) { while (arr.count()) delete arr.pop(); } void PglStaticSemx::Destroy() { PglStaticSemxDestroyArray(TheAgentsToUse); PglStaticSemxDestroyArray(TheNetPipesToUse); PglStaticSemxDestroyArray(TheAddrMapsToUse); PglStaticSemxDestroyArray(TheSslWrapsToUse); PglStaticSemxDestroyArray(TheMembershipsToUse); PglStaticSemxDestroyArray(TheSchedule); PglStaticSemxDestroyArray(TheSmplSchedule); delete TheBench; } void PglStaticSemx::Interpret(const String &fname) { PglPp pp(fname); PglParser parser(&pp); if (const SynSym *s = parser.parse()) { PglStaticSemx semx; semx.interpret(*s); } else { cerr << here << "internal error: failed to interpret parsed " << fname << endl << xexit; } } // default implementation complaints and exits void PglStaticSemx::callProc(const String &cname, const ListSym &args) { if (cname == "use") { use(args); } else if (cname == "schedule") { schedule(args); } else if (cname == "note_substitutes") { noteSubstitutes(args); } else if (cname == "working_set_length") { checkArgs(cname, 1, args); const TimeSym &length = (const TimeSym&) extractArg(cname, 0, args, TimeSym::TheType); TheWorkSetLen = length.val(); } else if (cname == "working_set_cap") { checkArgs(cname, 1, args); const IntSym &cap = (const IntSym&) extractArg(cname, 0, args, IntSym::TheType); TheWorkSetCap = cap.val(); } else { PglSemx::callProc(cname, args); } } // register things that will be actually used void PglStaticSemx::use(const ListSym &objects) { for (int i = 0; i < objects.count(); ++i) { if (objects[i]->isA(ListSym::TheType)) use((ListSym &)objects[i]->cast(ListSym::TheType)); // flatten else if (AgentSym *a = (AgentSym*)objects[i]->clone(AgentSym::TheType)) TheAgentsToUse.append(a); else if (NetPipeSym *p = (NetPipeSym*)objects[i]->clone(NetPipeSym::TheType)) TheNetPipesToUse.append(p); else if (AddrMapSym *m = (AddrMapSym*)objects[i]->clone(AddrMapSym::TheType)) TheAddrMapsToUse.append(m); else if (SslWrapSym *m = (SslWrapSym*)objects[i]->clone(SslWrapSym::TheType)) TheSslWrapsToUse.append(m); else if (MembershipMapSym *g = (MembershipMapSym*)objects[i]->clone(MembershipMapSym::TheType)) TheMembershipsToUse.append(g); else if (BenchSym *b = (BenchSym*)objects[i]->clone(BenchSym::TheType)) { if (TheBench) { cerr << objects.loc() << "warning: new bench selected with use()" << endl; cerr << b->loc() << "possible location of the new bench declaration" << endl; cerr << TheBench->loc() << "possible location of the old bench declaration" << endl; delete TheBench; } TheBench = b; } else { cerr << objects[i]->loc() << "entry of type '" << objects[i]->type() << "' in 'use()' argument list" << endl << xexit; } } } // register stat phases that will be actually used void PglStaticSemx::schedule(const ListSym &items) { for (int i = 0; i < items.count(); ++i) { if (items[i]->isA(ListSym::TheType)) schedule((ListSym &)items[i]->cast(ListSym::TheType)); // flatten else if (PhaseSym *p = (PhaseSym*)items[i]->clone(PhaseSym::TheType)) TheSchedule.append(p); else if (StatsSampleSym *s = (StatsSampleSym*)items[i]->clone(StatsSampleSym::TheType)) TheSmplSchedule.append(s); else { cerr << items[i]->loc() << "entry of type '" << items[i]->type() << "' cannot be scheduled" << endl << xexit; } } } // register agents that will be actually used void PglStaticSemx::noteSubstitutes(const ListSym &groups) { // note: the argument list is not flattened for (int i = 0; i < groups.count(); ++i) { const SynSym &gs = *groups[i]; if (ArraySym *a = (ArraySym*)gs.clone(strAddrArr)) { TheAddrSubstsToUse.append(a); } else { cerr << gs.loc() << "entry of type '" << gs.type() << "' in 'note_substitutes()' argument list" << endl << xexit; } } }