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.
45 int findEndOfRegPrinter(string config
, int startPos
)
47 int pos
= config
.find(")", startPos
);
48 if(pos
== string::npos
)
50 cerr
<< "Couldn't find the closing parenthesis for a reg printer" << endl
;
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
)
60 int length
= config
.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
)
67 cerr
<< "Couldn't find the closing parenthesis for a nesting printer on the first try" << endl
;
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
)
76 while(type
!= PRINTER_NONE
&& endPos
>= parenPos
)
78 //Find the next closest ending parenthesis since we passed
80 parenPos
= config
.find(")", endPos
+ 1);
81 //If we didn't find one, we're in trouble
82 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
106 PrinterType
findSub(string config
, int & startPos
, int & endPos
)
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
)
116 if(nestingPos
== string::npos
)
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
)
125 //If we didn't find anything close enough, say so.
126 if(regPos
>= endPos
&& nestingPos
>= endPos
)
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
)
132 int regEnd
= findEndOfRegPrinter(config
, regPos
+ 2);
133 //If we couldn't find the end...
136 cerr
<< "Couldn't find the end of the reg printer" << endl
;
137 return PRINTER_ERROR
;
139 //Report the sub printer's vitals.
146 int nestingEnd
= findEndOfNestingPrinter(config
, nestingPos
+ 2);
147 //If we couldn't find the end...
150 cerr
<< "Couldn't find the end of the nesting printer" << endl
;
151 return PRINTER_ERROR
;
153 //Report the sub printer's vitals.
154 startPos
= nestingPos
;
156 return PRINTER_NESTING
;
161 //Set up a nesting printer. This printer can contain sub printers
162 bool NestingPrinter::configure(string config
)
164 //Clear out any old stuff
165 constStrings
.clear();
168 int length
= config
.length();
169 int startPos
= 0, endPos
= length
;
171 //Try to find a sub printer
172 PrinterType type
= findSub(config
, startPos
, endPos
);
173 if(type
== PRINTER_ERROR
)
175 cerr
<< "Problem finding first sub printer" << endl
;
178 while(type
!= PRINTER_NONE
)
180 string prefix
= config
.substr(lastEndPos
+ 1, startPos
- lastEndPos
- 1);
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
);
190 //If we found a plain register printer
193 //Get the register name
194 subConfig
= config
.substr(startPos
+ 2, endPos
- startPos
- 2);
195 if(!regPrinter
->configure(subConfig
))
198 cerr
<< "Error configuring reg printer" << endl
;
201 printers
.push_back(regPrinter
);
203 //If we found an embedded nesting printer
204 case PRINTER_NESTING
:
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
)
212 childSwitchVar
= child
->getRegNum(subConfig
.substr(0, commaPos
));
213 if(childSwitchVar
== -1)
215 cerr
<< "Couldn't configure switching variable!" << endl
;
218 //Eat up remaining arguments
219 while(commaPos
!= string::npos
)
221 lastCommaPos
= commaPos
;
222 commaPos
= subConfig
.find(",", commaPos
+ 1);
224 if(lastCommaPos
!= string::npos
)
226 subConfig
= subConfig
.substr(lastCommaPos
+ 1, subConfig
.length() - lastCommaPos
- 1);
228 if(!nestingPrinter
->configure(subConfig
))
230 delete nestingPrinter
;
231 cerr
<< "Error configuring nesting printer" << endl
;
234 nestingPrinter
->switchVar
= childSwitchVar
;
235 printers
.push_back(nestingPrinter
);
238 cerr
<< "Unrecognized printer type" << endl
;
241 //Move down past what we just parsed
242 startPos
= endPos
+ 1;
244 type
= findSub(config
, startPos
, endPos
);
245 if(type
== PRINTER_ERROR
)
247 cerr
<< "Unable to find subprinters on later tries" << endl
;
251 //Put in the trailing stuff
252 string trailer
= config
.substr(startPos
, length
- startPos
);
253 constStrings
.push_back(trailer
);
257 bool RegPrinter::configure(string config
)
259 //Figure out what our register number is based on the name we're given
260 int num
= child
->getRegNum(config
);
263 cerr
<< "Couldn't find register " << config
<< endl
;
270 ostream
& NestingPrinter::writeOut(ostream
& os
)
272 if(switchVar
== -1 || child
->diffSinceUpdate(switchVar
))
275 for(x
= 0; x
< numPrinters
; x
++)
277 os
<< constStrings
[x
];
280 os
<< constStrings
[x
];
285 ostream
& RegPrinter::writeOut(ostream
& os
)
287 os
<< child
->printReg(intRegNum
);