Statetrace: Clean up style.
[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
46 findEndOfRegPrinter(string config, int startPos)
47 {
48 int pos = config.find(")", startPos);
49 if (pos == string::npos) {
50 cerr << "Couldn't find the closing " <<
51 "parenthesis for a reg printer" << endl;
52 return 0;
53 }
54 return pos;
55 }
56
57 //This is a little harder. We need to make sure we don't
58 //grab an ending parenthesis that belongs to the nesting printer.
59 int
60 findEndOfNestingPrinter(string config, int startPos)
61 {
62 int length = config.length();
63 int pos = startPos;
64 int endPos = length;
65 int parenPos = config.find(")", pos);
66 //If we didn't find an ending parenthesis at all, we're in trouble
67 if (parenPos == string::npos) {
68 cerr << "Couldn't find the closing " <<
69 "parenthesis for a nesting printer on the first try" << endl;
70 return 0;
71 }
72 //Keep pulling out embedded stuff until we can't any more
73 //we need to make sure we aren't skipping over the parenthesis
74 //that ends -this- printer.
75 PrinterType type = findSub(config, pos, endPos);
76 if (type == PRINTER_ERROR)
77 return 0;
78 while (type != PRINTER_NONE && endPos >= parenPos) {
79 //Find the next closest ending parenthesis since we passed
80 //up the last one
81 parenPos = config.find(")", endPos + 1);
82 //If we didn't find one, we're in trouble
83 if (parenPos == string::npos) {
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
107 findSub(string config, int & startPos, int & endPos)
108 {
109 int length = config.length();
110 //Figure out where the different types of sub printers may start
111 int regPos = config.find("%(", startPos);
112 int nestingPos = config.find("~(", startPos);
113 //If a type of printer wasn't found, say it was found too far away.
114 //This simplifies things later
115 if (regPos == string::npos)
116 regPos = endPos;
117 if (nestingPos == string::npos)
118 nestingPos = endPos;
119 //If we find a closing paren, that marks the
120 //end of the region we're searching.
121 int closingPos = config.find(")", startPos);
122 if (closingPos != string::npos &&
123 closingPos < regPos &&
124 closingPos < nestingPos)
125 return PRINTER_NONE;
126 //If we didn't find anything close enough, say so.
127 if (regPos >= endPos && nestingPos >= endPos)
128 return PRINTER_NONE;
129 //At this point, we know that one of the options starts legally
130 //We need to find which one is first and return that
131 if (regPos < nestingPos) {
132 int regEnd = findEndOfRegPrinter(config, regPos + 2);
133 //If we couldn't find the end...
134 if (!regEnd) {
135 cerr << "Couldn't find the end of the reg printer" << endl;
136 return PRINTER_ERROR;
137 }
138 //Report the sub printer's vitals.
139 startPos = regPos;
140 endPos = regEnd;
141 return PRINTER_REG;
142 } else {
143 int nestingEnd = findEndOfNestingPrinter(config, nestingPos + 2);
144 //If we couldn't find the end...
145 if (!nestingEnd) {
146 cerr << "Couldn't find the end of the nesting printer" << endl;
147 return PRINTER_ERROR;
148 }
149 //Report the sub printer's vitals.
150 startPos = nestingPos;
151 endPos = nestingEnd;
152 return PRINTER_NESTING;
153 }
154 return PRINTER_NONE;
155 }
156
157 //Set up a nesting printer. This printer can contain sub printers
158 bool
159 NestingPrinter::configure(string config)
160 {
161 //Clear out any old stuff
162 constStrings.clear();
163 numPrinters = 0;
164 printers.clear();
165 int length = config.length();
166 int startPos = 0, endPos = length;
167 int lastEndPos = -1;
168 //Try to find a sub printer
169 PrinterType type = findSub(config, startPos, endPos);
170 if (type == PRINTER_ERROR) {
171 cerr << "Problem finding first sub printer" << endl;
172 return false;
173 }
174 while (type != PRINTER_NONE) {
175 string prefix = config.substr(lastEndPos + 1,
176 startPos - lastEndPos - 1);
177 lastEndPos = endPos;
178 constStrings.push_back(prefix);
179 string subConfig, subString;
180 long int commaPos, lastCommaPos, childSwitchVar;
181 //Set up the register printer
182 RegPrinter * regPrinter = new RegPrinter(child);
183 NestingPrinter * nestingPrinter = new NestingPrinter(child);
184 switch (type) {
185 //If we found a plain register printer
186 case PRINTER_REG:
187 numPrinters++;
188 //Get the register name
189 subConfig = config.substr(startPos + 2, endPos - startPos - 2);
190 if (!regPrinter->configure(subConfig)) {
191 delete regPrinter;
192 cerr << "Error configuring reg printer" << endl;
193 return false;
194 }
195 printers.push_back(regPrinter);
196 break;
197 //If we found an embedded nesting printer
198 case PRINTER_NESTING:
199 numPrinters++;
200 //Punt on reading in all the parameters of the nesting printer
201 subConfig = config.substr(startPos + 2, endPos - startPos - 2);
202 lastCommaPos = string::npos;
203 commaPos = subConfig.find(",");
204 if (commaPos == string::npos)
205 return false;
206 childSwitchVar = child->getRegNum(subConfig.substr(0, commaPos));
207 if (childSwitchVar == -1) {
208 cerr << "Couldn't configure switching variable!" << endl;
209 return false;
210 }
211 //Eat up remaining arguments
212 while (commaPos != string::npos) {
213 lastCommaPos = commaPos;
214 commaPos = subConfig.find(",", commaPos + 1);
215 }
216 if (lastCommaPos != string::npos) {
217 subConfig = subConfig.substr(lastCommaPos + 1,
218 subConfig.length() - lastCommaPos - 1);
219 }
220 if (!nestingPrinter->configure(subConfig)) {
221 delete nestingPrinter;
222 cerr << "Error configuring nesting printer" << endl;
223 return false;
224 }
225 nestingPrinter->switchVar = childSwitchVar;
226 printers.push_back(nestingPrinter);
227 break;
228 default:
229 cerr << "Unrecognized printer type" << endl;
230 return false;
231 }
232 //Move down past what we just parsed
233 startPos = endPos + 1;
234 endPos = length;
235 type = findSub(config, startPos, endPos);
236 if (type == PRINTER_ERROR) {
237 cerr << "Unable to find subprinters on later tries" << endl;
238 return false;
239 }
240 }
241 //Put in the trailing stuff
242 string trailer = config.substr(startPos, length - startPos);
243 constStrings.push_back(trailer);
244 return true;
245 }
246
247 bool
248 RegPrinter::configure(string config)
249 {
250 //Figure out what our register number is based on the name we're given
251 int num = child->getRegNum(config);
252 if (num == -1) {
253 cerr << "Couldn't find register " << config << endl;
254 return false;
255 }
256 regNum(num);
257 return true;
258 }
259
260 ostream &
261 NestingPrinter::writeOut(ostream & os)
262 {
263 if (switchVar == -1 || child->diffSinceUpdate(switchVar)) {
264 int x;
265 for (x = 0; x < numPrinters; x++) {
266 os << constStrings[x];
267 os << printers[x];
268 }
269 os << constStrings[x];
270 }
271 return os;
272 }
273
274 ostream &
275 RegPrinter::writeOut(ostream & os)
276 {
277 os << child->printReg(intRegNum);
278 return os;
279 }
280