2 * Copyright (c) 2006-2007 The Regents of The University of Michigan
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.
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.
31 #include "tracechild.hh"
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
};
40 int findEndOfRegPrinter(string
, int);
41 int findEndOfNestingPrinter(string
, int);
42 PrinterType
findSub(string
, int &, int &);
44 //This is pretty easy. Just find the closing parenthesis.
46 findEndOfRegPrinter(string config
, int startPos
)
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
;
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.
60 findEndOfNestingPrinter(string config
, int startPos
)
62 int length
= config
.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
;
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
)
78 while (type
!= PRINTER_NONE
&& endPos
>= parenPos
) {
79 //Find the next closest ending parenthesis since we passed
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
;
87 //Start looking for the end of this printer and embedded
88 //stuff past the one we just found
90 //Reset endPos so we search to the end of config
92 type
= findSub(config
, pos
, endPos
);
93 if (type
== PRINTER_ERROR
)
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.
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
107 findSub(string config
, int & startPos
, int & endPos
)
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
)
117 if (nestingPos
== string::npos
)
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
)
126 //If we didn't find anything close enough, say so.
127 if (regPos
>= endPos
&& nestingPos
>= endPos
)
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...
135 cerr
<< "Couldn't find the end of the reg printer" << endl
;
136 return PRINTER_ERROR
;
138 //Report the sub printer's vitals.
143 int nestingEnd
= findEndOfNestingPrinter(config
, nestingPos
+ 2);
144 //If we couldn't find the end...
146 cerr
<< "Couldn't find the end of the nesting printer" << endl
;
147 return PRINTER_ERROR
;
149 //Report the sub printer's vitals.
150 startPos
= nestingPos
;
152 return PRINTER_NESTING
;
157 //Set up a nesting printer. This printer can contain sub printers
159 NestingPrinter::configure(string config
)
161 //Clear out any old stuff
162 constStrings
.clear();
165 int length
= config
.length();
166 int startPos
= 0, endPos
= length
;
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
;
174 while (type
!= PRINTER_NONE
) {
175 string prefix
= config
.substr(lastEndPos
+ 1,
176 startPos
- lastEndPos
- 1);
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
);
185 //If we found a plain register printer
188 //Get the register name
189 subConfig
= config
.substr(startPos
+ 2, endPos
- startPos
- 2);
190 if (!regPrinter
->configure(subConfig
)) {
192 cerr
<< "Error configuring reg printer" << endl
;
195 printers
.push_back(regPrinter
);
197 //If we found an embedded nesting printer
198 case PRINTER_NESTING
:
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
)
206 childSwitchVar
= child
->getRegNum(subConfig
.substr(0, commaPos
));
207 if (childSwitchVar
== -1) {
208 cerr
<< "Couldn't configure switching variable!" << endl
;
211 //Eat up remaining arguments
212 while (commaPos
!= string::npos
) {
213 lastCommaPos
= commaPos
;
214 commaPos
= subConfig
.find(",", commaPos
+ 1);
216 if (lastCommaPos
!= string::npos
) {
217 subConfig
= subConfig
.substr(lastCommaPos
+ 1,
218 subConfig
.length() - lastCommaPos
- 1);
220 if (!nestingPrinter
->configure(subConfig
)) {
221 delete nestingPrinter
;
222 cerr
<< "Error configuring nesting printer" << endl
;
225 nestingPrinter
->switchVar
= childSwitchVar
;
226 printers
.push_back(nestingPrinter
);
229 cerr
<< "Unrecognized printer type" << endl
;
232 //Move down past what we just parsed
233 startPos
= endPos
+ 1;
235 type
= findSub(config
, startPos
, endPos
);
236 if (type
== PRINTER_ERROR
) {
237 cerr
<< "Unable to find subprinters on later tries" << endl
;
241 //Put in the trailing stuff
242 string trailer
= config
.substr(startPos
, length
- startPos
);
243 constStrings
.push_back(trailer
);
248 RegPrinter::configure(string config
)
250 //Figure out what our register number is based on the name we're given
251 int num
= child
->getRegNum(config
);
253 cerr
<< "Couldn't find register " << config
<< endl
;
261 NestingPrinter::writeOut(ostream
& os
)
263 if (switchVar
== -1 || child
->diffSinceUpdate(switchVar
)) {
265 for (x
= 0; x
< numPrinters
; x
++) {
266 os
<< constStrings
[x
];
269 os
<< constStrings
[x
];
275 RegPrinter::writeOut(ostream
& os
)
277 os
<< child
->printReg(intRegNum
);