Statetrace: Fix indendation. Set the default hostname to "localhost" instead of my...
[gem5.git] / util / statetrace / printer.cc
1 /*
2 * Copyright (c) 2006-2007 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Gabe Black
29 */
30
31 #include "tracechild.hh"
32 #include "printer.hh"
33
34 using namespace std;
35
36 //Types of printers. If none is found, or there is an error in the input,
37 //there are psuedo types to return.
38 enum PrinterType {PRINTER_NONE, PRINTER_ERROR, PRINTER_NESTING, PRINTER_REG};
39
40 int findEndOfRegPrinter(string, int);
41 int findEndOfNestingPrinter(string, int);
42 PrinterType findSub(string, int &, int &);
43
44 //This is pretty easy. Just find the closing parenthesis.
45 int findEndOfRegPrinter(string config, int startPos)
46 {
47 int pos = config.find(")", startPos);
48 if(pos == string::npos)
49 {
50 cerr << "Couldn't find the closing parenthesis for a reg printer" << endl;
51 return 0;
52 }
53 return pos;
54 }
55
56 //This is a little harder. We need to make sure we don't
57 //grab an ending parenthesis that belongs to the nesting printer.
58 int findEndOfNestingPrinter(string config, int startPos)
59 {
60 int length = config.length();
61 int pos = startPos;
62 int endPos = length;
63 int parenPos = config.find(")", pos);
64 //If we didn't find an ending parenthesis at all, we're in trouble
65 if(parenPos == string::npos)
66 {
67 cerr << "Couldn't find the closing parenthesis for a nesting printer on the first try" << endl;
68 return 0;
69 }
70 //Keep pulling out embedded stuff until we can't any more
71 //we need to make sure we aren't skipping over the parenthesis
72 //that ends -this- printer.
73 PrinterType type = findSub(config, pos, endPos);
74 if(type == PRINTER_ERROR)
75 return 0;
76 while(type != PRINTER_NONE && endPos >= parenPos)
77 {
78 //Find the next closest ending parenthesis since we passed
79 //up the last one
80 parenPos = config.find(")", endPos + 1);
81 //If we didn't find one, we're in trouble
82 if(parenPos == string::npos)
83 {
84 cerr << "Couldn't find the closing parenthesis for a nested printer on later tries" << endl;
85 return 0;
86 }
87 //Start looking for the end of this printer and embedded
88 //stuff past the one we just found
89 pos = endPos + 1;
90 //Reset endPos so we search to the end of config
91 endPos = length;
92 type = findSub(config, pos, endPos);
93 if(type == PRINTER_ERROR)
94 return 0;
95 }
96 //We ran out of embedded items, and we didn't pass up our last
97 //closing paren. This must be the end of this printer.
98 return parenPos;
99 }
100
101 //Find a sub printer. This looks for things which have a type defining
102 //character and then an opening parenthesis. The type is returned, and
103 //startPos and endPos are set to the beginning and end of the sub printer
104 //On entry, the search starts at index startPos and ends at either index
105 //endPos or a closing parenthesis, whichever comes first
106 PrinterType findSub(string config, int & startPos, int & endPos)
107 {
108 int length = config.length();
109 //Figure out where the different types of sub printers may start
110 int regPos = config.find("%(", startPos);
111 int nestingPos = config.find("~(", startPos);
112 //If a type of printer wasn't found, say it was found too far away.
113 //This simplifies things later
114 if(regPos == string::npos)
115 regPos = endPos;
116 if(nestingPos == string::npos)
117 nestingPos = endPos;
118 //If we find a closing paren, that marks the
119 //end of the region we're searching.
120 int closingPos = config.find(")", startPos);
121 if(closingPos != string::npos &&
122 closingPos < regPos &&
123 closingPos < nestingPos)
124 return PRINTER_NONE;
125 //If we didn't find anything close enough, say so.
126 if(regPos >= endPos && nestingPos >= endPos)
127 return PRINTER_NONE;
128 //At this point, we know that one of the options starts legally
129 //We need to find which one is first and return that
130 if(regPos < nestingPos)
131 {
132 int regEnd = findEndOfRegPrinter(config, regPos + 2);
133 //If we couldn't find the end...
134 if(!regEnd)
135 {
136 cerr << "Couldn't find the end of the reg printer" << endl;
137 return PRINTER_ERROR;
138 }
139 //Report the sub printer's vitals.
140 startPos = regPos;
141 endPos = regEnd;
142 return PRINTER_REG;
143 }
144 else
145 {
146 int nestingEnd = findEndOfNestingPrinter(config, nestingPos + 2);
147 //If we couldn't find the end...
148 if(!nestingEnd)
149 {
150 cerr << "Couldn't find the end of the nesting printer" << endl;
151 return PRINTER_ERROR;
152 }
153 //Report the sub printer's vitals.
154 startPos = nestingPos;
155 endPos = nestingEnd;
156 return PRINTER_NESTING;
157 }
158 return PRINTER_NONE;
159 }
160
161 //Set up a nesting printer. This printer can contain sub printers
162 bool NestingPrinter::configure(string config)
163 {
164 //Clear out any old stuff
165 constStrings.clear();
166 numPrinters = 0;
167 printers.clear();
168 int length = config.length();
169 int startPos = 0, endPos = length;
170 int lastEndPos = -1;
171 //Try to find a sub printer
172 PrinterType type = findSub(config, startPos, endPos);
173 if(type == PRINTER_ERROR)
174 {
175 cerr << "Problem finding first sub printer" << endl;
176 return false;
177 }
178 while(type != PRINTER_NONE)
179 {
180 string prefix = config.substr(lastEndPos + 1, startPos - lastEndPos - 1);
181 lastEndPos = endPos;
182 constStrings.push_back(prefix);
183 string subConfig, subString;
184 long int commaPos, lastCommaPos, childSwitchVar;
185 //Set up the register printer
186 RegPrinter * regPrinter = new RegPrinter(child);
187 NestingPrinter * nestingPrinter = new NestingPrinter(child);
188 switch(type)
189 {
190 //If we found a plain register printer
191 case PRINTER_REG:
192 numPrinters++;
193 //Get the register name
194 subConfig = config.substr(startPos + 2, endPos - startPos - 2);
195 if(!regPrinter->configure(subConfig))
196 {
197 delete regPrinter;
198 cerr << "Error configuring reg printer" << endl;
199 return false;
200 }
201 printers.push_back(regPrinter);
202 break;
203 //If we found an embedded nesting printer
204 case PRINTER_NESTING:
205 numPrinters++;
206 //Punt on reading in all the parameters of the nesting printer
207 subConfig = config.substr(startPos + 2, endPos - startPos - 2);
208 lastCommaPos = string::npos;
209 commaPos = subConfig.find(",");
210 if(commaPos == string::npos)
211 return false;
212 childSwitchVar = child->getRegNum(subConfig.substr(0, commaPos));
213 if(childSwitchVar == -1)
214 {
215 cerr << "Couldn't configure switching variable!" << endl;
216 return false;
217 }
218 //Eat up remaining arguments
219 while(commaPos != string::npos)
220 {
221 lastCommaPos = commaPos;
222 commaPos = subConfig.find(",", commaPos + 1);
223 }
224 if(lastCommaPos != string::npos)
225 {
226 subConfig = subConfig.substr(lastCommaPos + 1, subConfig.length() - lastCommaPos - 1);
227 }
228 if(!nestingPrinter->configure(subConfig))
229 {
230 delete nestingPrinter;
231 cerr << "Error configuring nesting printer" << endl;
232 return false;
233 }
234 nestingPrinter->switchVar = childSwitchVar;
235 printers.push_back(nestingPrinter);
236 break;
237 default:
238 cerr << "Unrecognized printer type" << endl;
239 return false;
240 }
241 //Move down past what we just parsed
242 startPos = endPos + 1;
243 endPos = length;
244 type = findSub(config, startPos, endPos);
245 if(type == PRINTER_ERROR)
246 {
247 cerr << "Unable to find subprinters on later tries" << endl;
248 return false;
249 }
250 }
251 //Put in the trailing stuff
252 string trailer = config.substr(startPos, length - startPos);
253 constStrings.push_back(trailer);
254 return true;
255 }
256
257 bool RegPrinter::configure(string config)
258 {
259 //Figure out what our register number is based on the name we're given
260 int num = child->getRegNum(config);
261 if(num == -1)
262 {
263 cerr << "Couldn't find register " << config << endl;
264 return false;
265 }
266 regNum(num);
267 return true;
268 }
269
270 ostream & NestingPrinter::writeOut(ostream & os)
271 {
272 if(switchVar == -1 || child->diffSinceUpdate(switchVar))
273 {
274 int x;
275 for(x = 0; x < numPrinters; x++)
276 {
277 os << constStrings[x];
278 os << printers[x];
279 }
280 os << constStrings[x];
281 }
282 return os;
283 }
284
285 ostream & RegPrinter::writeOut(ostream & os)
286 {
287 os << child->printReg(intRegNum);
288 return os;
289 }
290