1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is TransforMiiX XSLT processor code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Jonas Sicking.
19 : * Portions created by the Initial Developer are Copyright (C) 2002
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Jonas Sicking <jonas@sicking.cc>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "txStylesheet.h"
40 : #include "txExpr.h"
41 : #include "txXSLTPatterns.h"
42 : #include "txToplevelItems.h"
43 : #include "txInstructions.h"
44 : #include "txXSLTFunctions.h"
45 : #include "txLog.h"
46 : #include "txKey.h"
47 : #include "txXPathTreeWalker.h"
48 :
49 0 : txStylesheet::txStylesheet()
50 0 : : mRootFrame(nsnull)
51 : {
52 0 : }
53 :
54 : nsresult
55 0 : txStylesheet::init()
56 : {
57 0 : mRootFrame = new ImportFrame;
58 0 : NS_ENSURE_TRUE(mRootFrame, NS_ERROR_OUT_OF_MEMORY);
59 :
60 : // Create default templates
61 : // element/root template
62 0 : mContainerTemplate = new txPushParams;
63 0 : NS_ENSURE_TRUE(mContainerTemplate, NS_ERROR_OUT_OF_MEMORY);
64 :
65 0 : nsAutoPtr<txNodeTest> nt(new txNodeTypeTest(txNodeTypeTest::NODE_TYPE));
66 0 : NS_ENSURE_TRUE(nt, NS_ERROR_OUT_OF_MEMORY);
67 :
68 0 : nsAutoPtr<Expr> nodeExpr(new LocationStep(nt, LocationStep::CHILD_AXIS));
69 0 : NS_ENSURE_TRUE(nodeExpr, NS_ERROR_OUT_OF_MEMORY);
70 :
71 0 : nt.forget();
72 :
73 0 : txPushNewContext* pushContext = new txPushNewContext(nodeExpr);
74 0 : mContainerTemplate->mNext = pushContext;
75 0 : NS_ENSURE_TRUE(pushContext, NS_ERROR_OUT_OF_MEMORY);
76 :
77 : txApplyDefaultElementTemplate* applyTemplates =
78 0 : new txApplyDefaultElementTemplate;
79 0 : pushContext->mNext = applyTemplates;
80 0 : NS_ENSURE_TRUE(applyTemplates, NS_ERROR_OUT_OF_MEMORY);
81 :
82 0 : txLoopNodeSet* loopNodeSet = new txLoopNodeSet(applyTemplates);
83 0 : applyTemplates->mNext = loopNodeSet;
84 0 : NS_ENSURE_TRUE(loopNodeSet, NS_ERROR_OUT_OF_MEMORY);
85 :
86 0 : txPopParams* popParams = new txPopParams;
87 0 : pushContext->mBailTarget = loopNodeSet->mNext = popParams;
88 0 : NS_ENSURE_TRUE(popParams, NS_ERROR_OUT_OF_MEMORY);
89 :
90 0 : popParams->mNext = new txReturn();
91 0 : NS_ENSURE_TRUE(popParams->mNext, NS_ERROR_OUT_OF_MEMORY);
92 :
93 : // attribute/textnode template
94 0 : nt = new txNodeTypeTest(txNodeTypeTest::NODE_TYPE);
95 0 : NS_ENSURE_TRUE(nt, NS_ERROR_OUT_OF_MEMORY);
96 :
97 0 : nodeExpr = new LocationStep(nt, LocationStep::SELF_AXIS);
98 0 : NS_ENSURE_TRUE(nodeExpr, NS_ERROR_OUT_OF_MEMORY);
99 :
100 0 : nt.forget();
101 :
102 0 : mCharactersTemplate = new txValueOf(nodeExpr, false);
103 0 : NS_ENSURE_TRUE(mCharactersTemplate, NS_ERROR_OUT_OF_MEMORY);
104 :
105 0 : mCharactersTemplate->mNext = new txReturn();
106 0 : NS_ENSURE_TRUE(mCharactersTemplate->mNext, NS_ERROR_OUT_OF_MEMORY);
107 :
108 : // pi/comment/namespace template
109 0 : mEmptyTemplate = new txReturn();
110 0 : NS_ENSURE_TRUE(mEmptyTemplate, NS_ERROR_OUT_OF_MEMORY);
111 :
112 0 : return NS_OK;
113 : }
114 :
115 0 : txStylesheet::~txStylesheet()
116 : {
117 : // Delete all ImportFrames
118 0 : delete mRootFrame;
119 0 : txListIterator frameIter(&mImportFrames);
120 0 : while (frameIter.hasNext()) {
121 0 : delete static_cast<ImportFrame*>(frameIter.next());
122 : }
123 :
124 0 : txListIterator instrIter(&mTemplateInstructions);
125 0 : while (instrIter.hasNext()) {
126 0 : delete static_cast<txInstruction*>(instrIter.next());
127 : }
128 :
129 : // We can't make the map own its values because then we wouldn't be able
130 : // to merge attributesets of the same name
131 0 : txExpandedNameMap<txInstruction>::iterator attrSetIter(mAttributeSets);
132 0 : while (attrSetIter.next()) {
133 0 : delete attrSetIter.value();
134 : }
135 0 : }
136 :
137 : txInstruction*
138 0 : txStylesheet::findTemplate(const txXPathNode& aNode,
139 : const txExpandedName& aMode,
140 : txIMatchContext* aContext,
141 : ImportFrame* aImportedBy,
142 : ImportFrame** aImportFrame)
143 : {
144 0 : NS_ASSERTION(aImportFrame, "missing ImportFrame pointer");
145 :
146 0 : *aImportFrame = nsnull;
147 0 : txInstruction* matchTemplate = nsnull;
148 0 : ImportFrame* endFrame = nsnull;
149 0 : txListIterator frameIter(&mImportFrames);
150 :
151 0 : if (aImportedBy) {
152 0 : ImportFrame* curr = static_cast<ImportFrame*>(frameIter.next());
153 0 : while (curr != aImportedBy) {
154 0 : curr = static_cast<ImportFrame*>(frameIter.next());
155 : }
156 0 : endFrame = aImportedBy->mFirstNotImported;
157 : }
158 :
159 : #ifdef PR_LOGGING
160 0 : txPattern* match = 0;
161 : #endif
162 :
163 : ImportFrame* frame;
164 0 : while (!matchTemplate &&
165 0 : (frame = static_cast<ImportFrame*>(frameIter.next())) &&
166 : frame != endFrame) {
167 :
168 : // get templatelist for this mode
169 : nsTArray<MatchableTemplate>* templates =
170 0 : frame->mMatchableTemplates.get(aMode);
171 :
172 0 : if (templates) {
173 : // Find template with highest priority
174 0 : PRUint32 i, len = templates->Length();
175 0 : for (i = 0; i < len && !matchTemplate; ++i) {
176 0 : MatchableTemplate& templ = (*templates)[i];
177 0 : if (templ.mMatch->matches(aNode, aContext)) {
178 0 : matchTemplate = templ.mFirstInstruction;
179 0 : *aImportFrame = frame;
180 : #ifdef PR_LOGGING
181 0 : match = templ.mMatch;
182 : #endif
183 : }
184 : }
185 : }
186 : }
187 :
188 : #ifdef PR_LOGGING
189 0 : nsAutoString mode, nodeName;
190 0 : if (aMode.mLocalName) {
191 0 : aMode.mLocalName->ToString(mode);
192 : }
193 0 : txXPathNodeUtils::getNodeName(aNode, nodeName);
194 0 : if (matchTemplate) {
195 0 : nsAutoString matchAttr;
196 : #ifdef TX_TO_STRING
197 0 : match->toString(matchAttr);
198 : #endif
199 0 : PR_LOG(txLog::xslt, PR_LOG_DEBUG,
200 : ("MatchTemplate, Pattern %s, Mode %s, Node %s\n",
201 : NS_LossyConvertUTF16toASCII(matchAttr).get(),
202 : NS_LossyConvertUTF16toASCII(mode).get(),
203 : NS_LossyConvertUTF16toASCII(nodeName).get()));
204 : }
205 : else {
206 0 : PR_LOG(txLog::xslt, PR_LOG_DEBUG,
207 : ("No match, Node %s, Mode %s\n",
208 : NS_LossyConvertUTF16toASCII(nodeName).get(),
209 : NS_LossyConvertUTF16toASCII(mode).get()));
210 : }
211 : #endif
212 :
213 0 : if (!matchTemplate) {
214 : // Test for these first since a node can be both a text node
215 : // and a root (if it is orphaned)
216 0 : if (txXPathNodeUtils::isAttribute(aNode) ||
217 0 : txXPathNodeUtils::isText(aNode)) {
218 0 : matchTemplate = mCharactersTemplate;
219 : }
220 0 : else if (txXPathNodeUtils::isElement(aNode) ||
221 0 : txXPathNodeUtils::isRoot(aNode)) {
222 0 : matchTemplate = mContainerTemplate;
223 : }
224 : else {
225 0 : matchTemplate = mEmptyTemplate;
226 : }
227 : }
228 :
229 0 : return matchTemplate;
230 : }
231 :
232 : txDecimalFormat*
233 0 : txStylesheet::getDecimalFormat(const txExpandedName& aName)
234 : {
235 0 : return mDecimalFormats.get(aName);
236 : }
237 :
238 : txInstruction*
239 0 : txStylesheet::getAttributeSet(const txExpandedName& aName)
240 : {
241 0 : return mAttributeSets.get(aName);
242 : }
243 :
244 : txInstruction*
245 0 : txStylesheet::getNamedTemplate(const txExpandedName& aName)
246 : {
247 0 : return mNamedTemplates.get(aName);
248 : }
249 :
250 : txOutputFormat*
251 0 : txStylesheet::getOutputFormat()
252 : {
253 0 : return &mOutputFormat;
254 : }
255 :
256 : txStylesheet::GlobalVariable*
257 0 : txStylesheet::getGlobalVariable(const txExpandedName& aName)
258 : {
259 0 : return mGlobalVariables.get(aName);
260 : }
261 :
262 : const txOwningExpandedNameMap<txXSLKey>&
263 0 : txStylesheet::getKeyMap()
264 : {
265 0 : return mKeys;
266 : }
267 :
268 : bool
269 0 : txStylesheet::isStripSpaceAllowed(const txXPathNode& aNode, txIMatchContext* aContext)
270 : {
271 0 : PRInt32 frameCount = mStripSpaceTests.Length();
272 0 : if (frameCount == 0) {
273 0 : return false;
274 : }
275 :
276 0 : txXPathTreeWalker walker(aNode);
277 :
278 0 : if (txXPathNodeUtils::isText(walker.getCurrentPosition()) &&
279 0 : (!txXPathNodeUtils::isWhitespace(aNode) || !walker.moveToParent())) {
280 0 : return false;
281 : }
282 :
283 0 : const txXPathNode& node = walker.getCurrentPosition();
284 :
285 0 : if (!txXPathNodeUtils::isElement(node)) {
286 0 : return false;
287 : }
288 :
289 : // check Whitespace stipping handling list against given Node
290 : PRInt32 i;
291 0 : for (i = 0; i < frameCount; ++i) {
292 0 : txStripSpaceTest* sst = mStripSpaceTests[i];
293 0 : if (sst->matches(node, aContext)) {
294 0 : return sst->stripsSpace() && !XMLUtils::getXMLSpacePreserve(node);
295 : }
296 : }
297 :
298 0 : return false;
299 : }
300 :
301 : nsresult
302 0 : txStylesheet::doneCompiling()
303 : {
304 0 : nsresult rv = NS_OK;
305 : // Collect all importframes into a single ordered list
306 0 : txListIterator frameIter(&mImportFrames);
307 0 : rv = frameIter.addAfter(mRootFrame);
308 0 : NS_ENSURE_SUCCESS(rv, rv);
309 :
310 0 : mRootFrame = nsnull;
311 0 : frameIter.next();
312 0 : rv = addFrames(frameIter);
313 0 : NS_ENSURE_SUCCESS(rv, rv);
314 :
315 : // Loop through importframes in decreasing-precedence-order and process
316 : // all items
317 0 : frameIter.reset();
318 : ImportFrame* frame;
319 0 : while ((frame = static_cast<ImportFrame*>(frameIter.next()))) {
320 0 : nsTArray<txStripSpaceTest*> frameStripSpaceTests;
321 :
322 0 : txListIterator itemIter(&frame->mToplevelItems);
323 0 : itemIter.resetToEnd();
324 : txToplevelItem* item;
325 0 : while ((item = static_cast<txToplevelItem*>(itemIter.previous()))) {
326 0 : switch (item->getType()) {
327 : case txToplevelItem::attributeSet:
328 : {
329 : rv = addAttributeSet(static_cast<txAttributeSetItem*>
330 0 : (item));
331 0 : NS_ENSURE_SUCCESS(rv, rv);
332 0 : break;
333 : }
334 : case txToplevelItem::dummy:
335 : case txToplevelItem::import:
336 : {
337 0 : break;
338 : }
339 : case txToplevelItem::output:
340 : {
341 0 : mOutputFormat.merge(static_cast<txOutputItem*>(item)->mFormat);
342 0 : break;
343 : }
344 : case txToplevelItem::stripSpace:
345 : {
346 : rv = addStripSpace(static_cast<txStripSpaceItem*>(item),
347 0 : frameStripSpaceTests);
348 0 : NS_ENSURE_SUCCESS(rv, rv);
349 0 : break;
350 : }
351 : case txToplevelItem::templ:
352 : {
353 : rv = addTemplate(static_cast<txTemplateItem*>(item),
354 0 : frame);
355 0 : NS_ENSURE_SUCCESS(rv, rv);
356 :
357 0 : break;
358 : }
359 : case txToplevelItem::variable:
360 : {
361 : rv = addGlobalVariable(static_cast<txVariableItem*>
362 0 : (item));
363 0 : NS_ENSURE_SUCCESS(rv, rv);
364 :
365 0 : break;
366 : }
367 : }
368 0 : delete item;
369 0 : itemIter.remove(); //remove() moves to the previous
370 0 : itemIter.next();
371 : }
372 0 : if (!mStripSpaceTests.AppendElements(frameStripSpaceTests)) {
373 0 : return NS_ERROR_OUT_OF_MEMORY;
374 : }
375 :
376 0 : frameStripSpaceTests.Clear();
377 : }
378 :
379 0 : if (!mDecimalFormats.get(txExpandedName())) {
380 0 : nsAutoPtr<txDecimalFormat> format(new txDecimalFormat);
381 0 : NS_ENSURE_TRUE(format, NS_ERROR_OUT_OF_MEMORY);
382 :
383 0 : rv = mDecimalFormats.add(txExpandedName(), format);
384 0 : NS_ENSURE_SUCCESS(rv, rv);
385 :
386 0 : format.forget();
387 : }
388 :
389 0 : return NS_OK;
390 : }
391 :
392 : nsresult
393 0 : txStylesheet::addTemplate(txTemplateItem* aTemplate,
394 : ImportFrame* aImportFrame)
395 : {
396 0 : NS_ASSERTION(aTemplate, "missing template");
397 :
398 0 : txInstruction* instr = aTemplate->mFirstInstruction;
399 0 : nsresult rv = mTemplateInstructions.add(instr);
400 0 : NS_ENSURE_SUCCESS(rv, rv);
401 :
402 : // mTemplateInstructions now owns the instructions
403 0 : aTemplate->mFirstInstruction.forget();
404 :
405 0 : if (!aTemplate->mName.isNull()) {
406 0 : rv = mNamedTemplates.add(aTemplate->mName, instr);
407 0 : NS_ENSURE_TRUE(NS_SUCCEEDED(rv) || rv == NS_ERROR_XSLT_ALREADY_SET,
408 : rv);
409 : }
410 :
411 0 : if (!aTemplate->mMatch) {
412 : // This is no error, see section 6 Named Templates
413 :
414 0 : return NS_OK;
415 : }
416 :
417 : // get the txList for the right mode
418 : nsTArray<MatchableTemplate>* templates =
419 0 : aImportFrame->mMatchableTemplates.get(aTemplate->mMode);
420 :
421 0 : if (!templates) {
422 : nsAutoPtr< nsTArray<MatchableTemplate> > newList(
423 0 : new nsTArray<MatchableTemplate>);
424 0 : NS_ENSURE_TRUE(newList, NS_ERROR_OUT_OF_MEMORY);
425 :
426 0 : rv = aImportFrame->mMatchableTemplates.set(aTemplate->mMode, newList);
427 0 : NS_ENSURE_SUCCESS(rv, rv);
428 :
429 0 : templates = newList.forget();
430 : }
431 :
432 : // Add the simple patterns to the list of matchable templates, according
433 : // to default priority
434 0 : nsAutoPtr<txPattern> simple = aTemplate->mMatch;
435 0 : nsAutoPtr<txPattern> unionPattern;
436 0 : if (simple->getType() == txPattern::UNION_PATTERN) {
437 0 : unionPattern = simple;
438 0 : simple = unionPattern->getSubPatternAt(0);
439 0 : unionPattern->setSubPatternAt(0, nsnull);
440 : }
441 :
442 0 : PRUint32 unionPos = 1; // only used when unionPattern is set
443 0 : while (simple) {
444 0 : double priority = aTemplate->mPrio;
445 0 : if (txDouble::isNaN(priority)) {
446 0 : priority = simple->getDefaultPriority();
447 0 : NS_ASSERTION(!txDouble::isNaN(priority),
448 : "simple pattern without default priority");
449 : }
450 :
451 0 : PRUint32 i, len = templates->Length();
452 0 : for (i = 0; i < len; ++i) {
453 0 : if (priority > (*templates)[i].mPriority) {
454 0 : break;
455 : }
456 : }
457 :
458 0 : MatchableTemplate* nt = templates->InsertElementAt(i);
459 0 : NS_ENSURE_TRUE(nt, NS_ERROR_OUT_OF_MEMORY);
460 :
461 0 : nt->mFirstInstruction = instr;
462 0 : nt->mMatch = simple;
463 0 : nt->mPriority = priority;
464 :
465 0 : if (unionPattern) {
466 0 : simple = unionPattern->getSubPatternAt(unionPos);
467 0 : if (simple) {
468 0 : unionPattern->setSubPatternAt(unionPos, nsnull);
469 : }
470 0 : ++unionPos;
471 : }
472 : }
473 :
474 0 : return NS_OK;
475 : }
476 :
477 : nsresult
478 0 : txStylesheet::addFrames(txListIterator& aInsertIter)
479 : {
480 0 : ImportFrame* frame = static_cast<ImportFrame*>(aInsertIter.current());
481 0 : nsresult rv = NS_OK;
482 0 : txListIterator iter(&frame->mToplevelItems);
483 : txToplevelItem* item;
484 0 : while ((item = static_cast<txToplevelItem*>(iter.next()))) {
485 0 : if (item->getType() == txToplevelItem::import) {
486 0 : txImportItem* import = static_cast<txImportItem*>(item);
487 0 : import->mFrame->mFirstNotImported =
488 0 : static_cast<ImportFrame*>(aInsertIter.next());
489 0 : rv = aInsertIter.addBefore(import->mFrame);
490 0 : NS_ENSURE_SUCCESS(rv, rv);
491 :
492 0 : import->mFrame.forget();
493 0 : aInsertIter.previous();
494 0 : rv = addFrames(aInsertIter);
495 0 : NS_ENSURE_SUCCESS(rv, rv);
496 0 : aInsertIter.previous();
497 : }
498 : }
499 :
500 0 : return NS_OK;
501 : }
502 :
503 : nsresult
504 0 : txStylesheet::addStripSpace(txStripSpaceItem* aStripSpaceItem,
505 : nsTArray<txStripSpaceTest*>& aFrameStripSpaceTests)
506 : {
507 0 : PRInt32 testCount = aStripSpaceItem->mStripSpaceTests.Length();
508 0 : for (; testCount > 0; --testCount) {
509 0 : txStripSpaceTest* sst = aStripSpaceItem->mStripSpaceTests[testCount-1];
510 0 : double priority = sst->getDefaultPriority();
511 0 : PRInt32 i, frameCount = aFrameStripSpaceTests.Length();
512 0 : for (i = 0; i < frameCount; ++i) {
513 0 : if (aFrameStripSpaceTests[i]->getDefaultPriority() < priority) {
514 0 : break;
515 : }
516 : }
517 0 : if (!aFrameStripSpaceTests.InsertElementAt(i, sst)) {
518 0 : return NS_ERROR_OUT_OF_MEMORY;
519 : }
520 :
521 0 : aStripSpaceItem->mStripSpaceTests.RemoveElementAt(testCount-1);
522 : }
523 :
524 0 : return NS_OK;
525 : }
526 :
527 : nsresult
528 0 : txStylesheet::addAttributeSet(txAttributeSetItem* aAttributeSetItem)
529 : {
530 0 : nsresult rv = NS_OK;
531 0 : txInstruction* oldInstr = mAttributeSets.get(aAttributeSetItem->mName);
532 0 : if (!oldInstr) {
533 : rv = mAttributeSets.add(aAttributeSetItem->mName,
534 0 : aAttributeSetItem->mFirstInstruction);
535 0 : NS_ENSURE_SUCCESS(rv, rv);
536 :
537 0 : aAttributeSetItem->mFirstInstruction.forget();
538 :
539 0 : return NS_OK;
540 : }
541 :
542 : // We need to prepend the new instructions before the existing ones.
543 0 : txInstruction* instr = aAttributeSetItem->mFirstInstruction;
544 0 : txInstruction* lastNonReturn = nsnull;
545 0 : while (instr->mNext) {
546 0 : lastNonReturn = instr;
547 0 : instr = instr->mNext;
548 : }
549 :
550 0 : if (!lastNonReturn) {
551 : // The new attributeset is empty, so lets just ignore it.
552 0 : return NS_OK;
553 : }
554 :
555 : rv = mAttributeSets.set(aAttributeSetItem->mName,
556 0 : aAttributeSetItem->mFirstInstruction);
557 0 : NS_ENSURE_SUCCESS(rv, rv);
558 :
559 0 : aAttributeSetItem->mFirstInstruction.forget();
560 :
561 0 : lastNonReturn->mNext = oldInstr; // ...and link up the old instructions.
562 :
563 0 : return NS_OK;
564 : }
565 :
566 : nsresult
567 0 : txStylesheet::addGlobalVariable(txVariableItem* aVariable)
568 : {
569 0 : if (mGlobalVariables.get(aVariable->mName)) {
570 0 : return NS_OK;
571 : }
572 : nsAutoPtr<GlobalVariable> var(
573 : new GlobalVariable(aVariable->mValue, aVariable->mFirstInstruction,
574 0 : aVariable->mIsParam));
575 0 : NS_ENSURE_TRUE(var, NS_ERROR_OUT_OF_MEMORY);
576 :
577 0 : nsresult rv = mGlobalVariables.add(aVariable->mName, var);
578 0 : NS_ENSURE_SUCCESS(rv, rv);
579 :
580 0 : var.forget();
581 :
582 0 : return NS_OK;
583 :
584 : }
585 :
586 : nsresult
587 0 : txStylesheet::addKey(const txExpandedName& aName,
588 : nsAutoPtr<txPattern> aMatch, nsAutoPtr<Expr> aUse)
589 : {
590 0 : nsresult rv = NS_OK;
591 :
592 0 : txXSLKey* xslKey = mKeys.get(aName);
593 0 : if (!xslKey) {
594 0 : xslKey = new txXSLKey(aName);
595 0 : NS_ENSURE_TRUE(xslKey, NS_ERROR_OUT_OF_MEMORY);
596 :
597 0 : rv = mKeys.add(aName, xslKey);
598 0 : if (NS_FAILED(rv)) {
599 0 : delete xslKey;
600 0 : return rv;
601 : }
602 : }
603 0 : if (!xslKey->addKey(aMatch, aUse)) {
604 0 : return NS_ERROR_OUT_OF_MEMORY;
605 : }
606 0 : return NS_OK;
607 : }
608 :
609 : nsresult
610 0 : txStylesheet::addDecimalFormat(const txExpandedName& aName,
611 : nsAutoPtr<txDecimalFormat> aFormat)
612 : {
613 0 : txDecimalFormat* existing = mDecimalFormats.get(aName);
614 0 : if (existing) {
615 0 : NS_ENSURE_TRUE(existing->isEqual(aFormat),
616 : NS_ERROR_XSLT_PARSE_FAILURE);
617 :
618 0 : return NS_OK;
619 : }
620 :
621 0 : nsresult rv = mDecimalFormats.add(aName, aFormat);
622 0 : NS_ENSURE_SUCCESS(rv, rv);
623 :
624 0 : aFormat.forget();
625 :
626 0 : return NS_OK;
627 : }
628 :
629 0 : txStylesheet::ImportFrame::~ImportFrame()
630 : {
631 0 : txListIterator tlIter(&mToplevelItems);
632 0 : while (tlIter.hasNext()) {
633 0 : delete static_cast<txToplevelItem*>(tlIter.next());
634 : }
635 0 : }
636 :
637 0 : txStylesheet::GlobalVariable::GlobalVariable(nsAutoPtr<Expr> aExpr,
638 : nsAutoPtr<txInstruction> aFirstInstruction,
639 : bool aIsParam)
640 0 : : mExpr(aExpr), mFirstInstruction(aFirstInstruction), mIsParam(aIsParam)
641 : {
642 0 : }
|