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