1
2 /* Web Polygraph http://www.web-polygraph.org/
3 * Copyright 2003-2011 The Measurement Factory
4 * Licensed under the Apache License, Version 2.0 */
5
6 #include "pgl/pgl.h"
7
8 #include "xstd/h/sstream.h"
9
10 #include "xparser/TokenSym.h"
11 #include "xparser/ParsSym.h"
12
13 #include "pgl/PglPp.h"
14 #include "pgl/PglParser.h"
15
16 #include "pgl/PglTimeSym.h"
17 #include "pgl/PglIntSym.h"
18 #include "pgl/PglListSym.h"
19 #include "pgl/PglContainerSym.h"
20 #include "pgl/PglArraySym.h"
21 #include "pgl/AgentSym.h"
22 #include "pgl/NetPipeSym.h"
23 #include "pgl/AddrMapSym.h"
24 #include "pgl/SslWrapSym.h"
25 #include "pgl/MembershipMapSym.h"
26 #include "pgl/BenchSym.h"
27 #include "pgl/PhaseSym.h"
28 #include "pgl/StatsSampleSym.h"
29 #include "pgl/PglStaticSemx.h"
30
31
32 Array<AgentSym*> PglStaticSemx::TheAgentsToUse;
33 Array<NetPipeSym*> PglStaticSemx::TheNetPipesToUse;
34 Array<AddrMapSym*> PglStaticSemx::TheAddrMapsToUse;
35 Array<SslWrapSym*> PglStaticSemx::TheSslWrapsToUse;
36 Array<ContainerSym*> PglStaticSemx::TheAddrSubstsToUse;
37 Array<MembershipMapSym*> PglStaticSemx::TheMembershipsToUse;
38 BenchSym *PglStaticSemx::TheBench = 0;
39
40 Array<PhaseSym*> PglStaticSemx::TheSchedule;
41 Array<StatsSampleSym*> PglStaticSemx::TheSmplSchedule;
42
43 Time PglStaticSemx::TheWorkSetLen;
44 int PglStaticSemx::TheWorkSetCap = -1;
45
46 static const String strAddrArr = "addr[]";
47
48
Interpret(const String & fname)49 const String PglStaticSemx::Interpret(const String &fname) {
50 PglPp pp(fname);
51 PglParser parser(&pp);
52
53 if (const SynSym *s = parser.parse()) {
54 PglStaticSemx semx;
55 semx.interpret(*s);
56 delete s;
57 } else {
58 cerr << here << "internal error: failed to interpret parsed " <<
59 fname << endl << xexit;
60 }
61 return pp.image();
62 }
63
64 // default implementation complaints and exits
callProc(const String & cname,const ListSym & args)65 void PglStaticSemx::callProc(const String &cname, const ListSym &args) {
66 if (cname == "use") {
67 use(args);
68 } else
69 if (cname == "schedule") {
70 schedule(args);
71 } else
72 if (cname == "note_substitutes") {
73 noteSubstitutes(args);
74 } else
75 if (cname == "working_set_length") {
76 checkArgs(cname, 1, args);
77 const TimeSym &length = (const TimeSym&)
78 extractArg(cname, 0, args, TimeSym::TheType);
79 TheWorkSetLen = length.val();
80 } else
81 if (cname == "working_set_cap") {
82 checkArgs(cname, 1, args);
83 const IntSym &cap = (const IntSym&)
84 extractArg(cname, 0, args, IntSym::TheType);
85 TheWorkSetCap = cap.val();
86 } else {
87 PglSemx::callProc(cname, args);
88 }
89 }
90
91 template <class Store, class Item>
92 inline
cuse(Store & used,Item * item,bool valid,const char * reason,const TokenLoc & loc)93 void cuse(Store &used, Item *item, bool valid, const char *reason, const TokenLoc &loc) {
94 if (valid) {
95 used.append(item);
96 return;
97 }
98 cerr << loc << "warning: ignoring use() of " << item->type() <<
99 " " << reason << endl;
100 delete item; // it was cloned in use()
101 }
102
103 // register things that will be actually used
use(const ListSym & objects)104 void PglStaticSemx::use(const ListSym &objects) {
105 const TokenLoc &loc = objects.loc();
106 for (int i = 0; i < objects.count(); ++i) {
107 if (objects[i]->isA(ListSym::TheType))
108 use((ListSym &)objects[i]->cast(ListSym::TheType)); // flatten
109 else
110 if (AgentSym *a = (AgentSym*)objects[i]->clone(AgentSym::TheType))
111 cuse(TheAgentsToUse, a, a->hostCount(), "without addresses", loc);
112 else
113 if (NetPipeSym *p = (NetPipeSym*)objects[i]->clone(NetPipeSym::TheType))
114 cuse(TheNetPipesToUse, p, p->hostCount(), "without addresses", loc);
115 else
116 if (AddrMapSym *m = (AddrMapSym*)objects[i]->clone(AddrMapSym::TheType))
117 cuse(TheAddrMapsToUse, m, m->usable(), "without names or addresses", loc);
118 else
119 if (SslWrapSym *m = (SslWrapSym*)objects[i]->clone(SslWrapSym::TheType))
120 TheSslWrapsToUse.append(m);
121 else
122 if (MembershipMapSym *g = (MembershipMapSym*)objects[i]->clone(MembershipMapSym::TheType))
123 TheMembershipsToUse.append(g);
124 else
125 if (BenchSym *b = (BenchSym*)objects[i]->clone(BenchSym::TheType)) {
126 if (TheBench) {
127 cerr << objects.loc() << "warning: new bench selected with use()" << endl;
128 cerr << b->loc() << "possible location of the new bench declaration" << endl;
129 cerr << TheBench->loc() << "possible location of the old bench declaration" << endl;
130 delete TheBench;
131 }
132 TheBench = b;
133 } else {
134 cerr << objects[i]->loc() << "entry of type '" <<
135 objects[i]->type() << "' in 'use()' argument list" <<
136 endl << xexit;
137 }
138 }
139 }
140
141 // register stat phases that will be actually used
schedule(const ListSym & items)142 void PglStaticSemx::schedule(const ListSym &items) {
143 for (int i = 0; i < items.count(); ++i) {
144 if (items[i]->isA(ListSym::TheType))
145 schedule((ListSym &)items[i]->cast(ListSym::TheType)); // flatten
146 else
147 if (PhaseSym *p = (PhaseSym*)items[i]->clone(PhaseSym::TheType))
148 TheSchedule.append(p);
149 else
150 if (StatsSampleSym *s = (StatsSampleSym*)items[i]->clone(StatsSampleSym::TheType))
151 TheSmplSchedule.append(s);
152 else {
153 cerr << items[i]->loc() << "entry of type '" <<
154 items[i]->type() << "' cannot be scheduled" << endl << xexit;
155 }
156 }
157 }
158
159 // register agents that will be actually used
noteSubstitutes(const ListSym & groups)160 void PglStaticSemx::noteSubstitutes(const ListSym &groups) {
161 // note: the argument list is not flattened
162 for (int i = 0; i < groups.count(); ++i) {
163 const SynSym &gs = *groups[i];
164 if (ArraySym *a = (ArraySym*)gs.clone(strAddrArr)) {
165 TheAddrSubstsToUse.append(a);
166 } else {
167 cerr << gs.loc() << "entry of type '" << gs.type() <<
168 "' in 'note_substitutes()' argument list" << endl << xexit;
169 }
170 }
171 }
172