added Info.plist
[TestXSLT.git] / libsablot / src / engine / verts.cpp
1 /* 
2  * The contents of this file are subject to the Mozilla Public
3  * License Version 1.1 (the "License"); you may not use this file
4  * except in compliance with the License. You may obtain a copy of
5  * the License at http://www.mozilla.org/MPL/
6  * 
7  * Software distributed under the License is distributed on an "AS
8  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9  * implied. See the License for the specific language governing
10  * rights and limitations under the License.
11  * 
12  * The Original Code is the Sablotron XSLT Processor.
13  * 
14  * The Initial Developer of the Original Code is Ginger Alliance Ltd.
15  * Portions created by Ginger Alliance are Copyright (C) 2000-2002
16  * Ginger Alliance Ltd. All Rights Reserved.
17  * 
18  * Contributor(s):
19  * 
20  * Alternatively, the contents of this file may be used under the
21  * terms of the GNU General Public License Version 2 or later (the
22  * "GPL"), in which case the provisions of the GPL are applicable 
23  * instead of those above.  If you wish to allow use of your 
24  * version of this file only under the terms of the GPL and not to
25  * allow others to use your version of this file under the MPL,
26  * indicate your decision by deleting the provisions above and
27  * replace them with the notice and other provisions required by
28  * the GPL.  If you do not delete the provisions above, a recipient
29  * may use your version of this file under either the MPL or the
30  * GPL.
31  */
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 #define SablotAsExport
38 #include "verts.h"
39 #include "tree.h"
40 #include "expr.h"
41 #include "proc.h"
42 #include "context.h"
43 #include "vars.h"
44 #include "parser.h"
45
46 #include "guard.h"      // GP: clean
47 #include "numbering.h"
48 #include "utf8.h"
49 #include "domprovider.h"
50 #include "uri.h"
51
52 #ifdef SABLOT_DEBUGGER
53 #include "debugger.h"
54 #endif
55
56 #ifdef ENABLE_DOM
57 #include "sdom.h"
58 #endif
59
60 /*****************************************************************
61     Instruction tables
62 *****************************************************************/
63
64 struct AttTableItem
65 {
66     XSL_ATT
67         attCode;
68     Bool 
69         required,
70         avtemplate;
71     ExType
72         exprType;
73 };
74
75 typedef AttTableItem AttTable[];
76 //declarations using AttTable doesn't work with Sun CC.
77
78 AttTableItem at_empty[] = 
79 {
80   {XSLA_NONE, FALSE, FALSE, EX_NONE}
81 };
82 AttTableItem at_apply_templates[]  = 
83 {
84     {XSLA_SELECT, FALSE, FALSE, EX_NODESET},
85     {XSLA_MODE, FALSE, FALSE, EX_NONE}
86 };
87 AttTableItem at_attribute[] = 
88 {
89     {XSLA_NAME, TRUE, TRUE, EX_STRING},
90     {XSLA_NAMESPACE, FALSE, TRUE, EX_STRING}
91 };
92 AttTableItem at_attribute_set[] =
93 {
94     {XSLA_NAME, TRUE, FALSE, EX_NONE},
95     {XSLA_USE_ATTR_SETS, FALSE, FALSE, EX_NONE},
96 };
97 AttTableItem at_call_template[] = 
98 {
99   {XSLA_NAME, TRUE, FALSE, EX_NONE}
100 };
101 AttTableItem  at_copy[] =
102 {
103   {XSLA_USE_ATTR_SETS, FALSE,  FALSE, EX_NONE}
104 };
105 AttTableItem at_copy_of[] =
106 {
107   {XSLA_SELECT, TRUE, FALSE, EX_UNKNOWN}
108 };
109 AttTableItem at_decimal_format[] =
110 {
111   {XSLA_NAME, FALSE, FALSE, EX_NONE},
112   {XSLA_DECIMAL_SEPARATOR, FALSE, FALSE, EX_NONE},
113   {XSLA_GROUPING_SEPARATOR, FALSE, FALSE, EX_NONE},
114   {XSLA_INFINITY, FALSE, FALSE, EX_NONE},
115   {XSLA_MINUS_SIGN, FALSE, FALSE, EX_NONE},
116   {XSLA_NAN, FALSE, FALSE, EX_NONE},
117   {XSLA_PERCENT, FALSE, FALSE, EX_NONE},
118   {XSLA_PER_MILLE, FALSE, FALSE, EX_NONE},
119   {XSLA_ZERO_DIGIT, FALSE, FALSE, EX_NONE},
120   {XSLA_DIGIT, FALSE, FALSE, EX_NONE},
121   {XSLA_PATTERN_SEPARATOR, FALSE, FALSE, EX_NONE}
122 };
123 AttTableItem at_element[] =
124 {
125   {XSLA_NAME, TRUE, TRUE, EX_STRING},
126   {XSLA_NAMESPACE, FALSE, TRUE, EX_STRING},
127   {XSLA_USE_ATTR_SETS, FALSE, FALSE, EX_NONE}
128 };
129 AttTableItem at_for_each[] =
130 {
131   {XSLA_SELECT, TRUE, FALSE, EX_NODESET}
132 };
133 AttTableItem at_if[] =
134 {
135   {XSLA_TEST, TRUE, FALSE, EX_BOOLEAN}
136 };
137 AttTableItem at_import[] =
138 {
139   {XSLA_HREF, TRUE, FALSE, EX_NONE}
140 };
141 AttTableItem at_include[] =
142 {
143   {XSLA_HREF, TRUE, FALSE, EX_NONE}
144 };
145 AttTableItem at_key[] =
146 {
147   {XSLA_NAME, TRUE, FALSE, EX_NONE},
148   {XSLA_MATCH, TRUE, FALSE, EX_NODESET_PATTERN},
149   {XSLA_USE, TRUE, FALSE, EX_UNKNOWN}
150 };
151 AttTableItem at_message[] =
152 {
153   {XSLA_TERMINATE, FALSE, FALSE, EX_NONE}
154 };
155 AttTableItem at_ns_alias[] =
156 {
157   {XSLA_STYLESHEET_PREFIX, TRUE, FALSE, EX_NONE},
158   {XSLA_RESULT_PREFIX, TRUE, FALSE, EX_NONE}
159 };
160 AttTableItem at_number[] =
161 {
162   {XSLA_LEVEL, FALSE, FALSE, EX_NONE},
163   {XSLA_COUNT, FALSE, FALSE, EX_NODESET_PATTERN},
164   {XSLA_FROM, FALSE, FALSE, EX_NODESET_PATTERN},
165   {XSLA_VALUE, FALSE, FALSE, EX_NUMBER},
166   {XSLA_FORMAT, FALSE, TRUE, EX_STRING},
167   {XSLA_LANG, FALSE, TRUE, EX_STRING},
168   {XSLA_LETTER_VALUE, FALSE, TRUE, EX_STRING},
169   {XSLA_GROUPING_SEPARATOR, FALSE, TRUE, EX_STRING},
170   {XSLA_GROUPING_SIZE, FALSE, TRUE, EX_STRING}
171 };
172 AttTableItem at_output[] =
173   {
174     {XSLA_METHOD, FALSE, FALSE, EX_NONE},
175     {XSLA_VERSION, FALSE, FALSE, EX_NONE},
176     {XSLA_ENCODING, FALSE, FALSE, EX_NONE},
177     {XSLA_OMIT_XML_DECL, FALSE, FALSE, EX_NONE},
178     {XSLA_STANDALONE, FALSE, FALSE, EX_NONE},
179     {XSLA_DOCTYPE_PUBLIC, FALSE, FALSE, EX_NONE},
180     {XSLA_DOCTYPE_SYSTEM, FALSE, FALSE, EX_NONE},
181     {XSLA_CDATA_SECT_ELEMS, FALSE, FALSE, EX_NONE},
182     {XSLA_INDENT, FALSE, FALSE, EX_NONE},
183     {XSLA_MEDIA_TYPE, FALSE, FALSE, EX_NONE}
184   };
185 AttTableItem at_param[] =
186 {
187   {XSLA_NAME, TRUE, FALSE, EX_NONE},
188   {XSLA_SELECT, FALSE, FALSE, EX_UNKNOWN}
189 };
190 AttTableItem at_preserve_space[] =
191 {
192   {XSLA_ELEMENTS, TRUE, FALSE, EX_NONE}
193 };
194 AttTableItem at_pi[] =
195 {
196   {XSLA_NAME, TRUE, TRUE, EX_STRING}
197 };
198 AttTableItem at_sort[] =
199 {
200   {XSLA_SELECT, FALSE, FALSE, EX_STRING},
201   {XSLA_LANG, FALSE, TRUE, EX_STRING},
202   {XSLA_DATA_TYPE, FALSE, TRUE, EX_STRING},
203   {XSLA_ORDER, FALSE, TRUE, EX_STRING},
204   {XSLA_CASE_ORDER, FALSE, TRUE, EX_STRING}
205 };
206 AttTableItem at_strip_space[] =
207 {
208   {XSLA_ELEMENTS, TRUE, FALSE, EX_NONE}
209 };
210 AttTableItem at_template[] =
211 {
212   {XSLA_MATCH, FALSE, FALSE, EX_NODESET_PATTERN},
213   {XSLA_NAME, FALSE, FALSE, EX_NONE},
214   {XSLA_PRIORITY, FALSE, FALSE, EX_NONE},
215   {XSLA_MODE, FALSE, FALSE, EX_NONE}
216 };
217 AttTableItem at_text[] =
218 {
219   {XSLA_DISABLE_OUTPUT_ESC, FALSE, FALSE, EX_NONE}
220 };
221 AttTableItem at_transform[] =
222 {
223   {XSLA_ID, FALSE, FALSE, EX_NONE},
224   {XSLA_EXT_ELEM_PREFIXES, FALSE, FALSE, EX_NONE},
225   {XSLA_EXCL_RES_PREFIXES, FALSE, FALSE, EX_NONE},
226   {XSLA_VERSION, TRUE, FALSE, EX_NONE}
227 };
228 AttTableItem at_value_of[] =
229 {
230   {XSLA_SELECT, TRUE, FALSE, EX_STRING},
231   {XSLA_DISABLE_OUTPUT_ESC, FALSE, FALSE, EX_NONE}
232 };
233 AttTableItem at_variable[] =
234 {
235   {XSLA_NAME, TRUE, FALSE, EX_NONE},
236   {XSLA_SELECT, FALSE, FALSE, EX_UNKNOWN}
237 };
238 AttTableItem at_when[] =
239 {
240   {XSLA_TEST, TRUE, FALSE, EX_BOOLEAN}
241 };
242 AttTableItem at_with_param[] =
243 {
244   {XSLA_NAME, TRUE, FALSE, EX_NONE},
245   {XSLA_SELECT, FALSE, FALSE, EX_UNKNOWN}
246 };
247
248 #define instr(code, elemflg, req, max, table) \
249 {code, elemflg, req, max, (AttTableItem*) table}
250
251 enum ElemFlags
252 {
253 //    ELEM_EMPTY = 1,
254     ELEM_TOPLEVEL = 2,
255     ELEM_INSTR = 4,
256     ELEM_EXTRA = 8,
257     //
258     ELEM_CONT_PCDATA = 0x10,
259     ELEM_CONT_TOPLEVEL = 0x20,
260     ELEM_CONT_INSTR = 0x40,
261     ELEM_CONT_EXTRA = 0x80,
262     ELEM_CONT_EXTENSION = 0x100,
263     //
264     ELEM_SELF = ELEM_TOPLEVEL | ELEM_INSTR | ELEM_EXTRA,
265     ELEM_CONT = ELEM_CONT_PCDATA | ELEM_CONT_TOPLEVEL | ELEM_CONT_INSTR | ELEM_CONT_EXTRA,
266     //
267     ELEM_I0 = ELEM_INSTR,
268     ELEM_IX = ELEM_INSTR | ELEM_CONT_EXTRA,
269     ELEM_II = ELEM_INSTR | ELEM_CONT_INSTR,
270     ELEM_IT_I = ELEM_INSTR | ELEM_TOPLEVEL | ELEM_CONT_INSTR,
271     ELEM_I_XI = ELEM_INSTR | ELEM_CONT_EXTRA | ELEM_CONT_INSTR,
272     ELEM_I__ = ELEM_INSTR | ELEM_CONT_PCDATA,
273     //
274     ELEM_T0 = ELEM_TOPLEVEL,
275     ELEM_TX = ELEM_TOPLEVEL | ELEM_CONT_EXTRA,
276     ELEM_TX_I = ELEM_TOPLEVEL | ELEM_EXTRA | ELEM_CONT_INSTR,
277     ELEM_T_XI = ELEM_TOPLEVEL | ELEM_CONT_EXTRA | ELEM_CONT_INSTR,
278     //
279     ELEM_X0 = ELEM_EXTRA,
280     ELEM_XI = ELEM_EXTRA | ELEM_CONT_INSTR,
281     ELEM_X_XT = ELEM_EXTRA | ELEM_CONT_EXTRA | ELEM_CONT_TOPLEVEL |
282                 ELEM_CONT_EXTENSION,
283     ELEM_NONE
284 };
285
286 struct InstrTableItem
287 {
288     XSL_OP op;
289     ElemFlags flags;
290     int 
291         reqAtts,
292         maxAtts;
293     AttTableItem *att;
294 } instrTable[]
295 =
296 {
297     instr(XSL_APPLY_IMPORTS,    ELEM_I0,    0, 0, at_empty),
298     instr(XSL_APPLY_TEMPLATES,  ELEM_IX,    0, 2, at_apply_templates),
299     instr(XSL_ATTRIBUTE,        ELEM_II,    1, 2, at_attribute),
300     instr(XSL_ATTRIBUTE_SET,    ELEM_TX,    1, 2, at_attribute_set),
301     instr(XSL_CALL_TEMPLATE,    ELEM_IX,    1, 1, at_call_template),
302     instr(XSL_CHOOSE,           ELEM_IX,    0, 0, at_empty),
303     instr(XSL_COMMENT,          ELEM_II,    0, 0, at_empty),
304     instr(XSL_COPY,             ELEM_II,    0, 1, at_copy),
305     instr(XSL_COPY_OF,          ELEM_I0,    1, 1, at_copy_of),
306     instr(XSL_DECIMAL_FORMAT,   ELEM_T0,    0, 11, at_decimal_format),
307     instr(XSL_ELEMENT,          ELEM_II,    1, 3, at_element),
308     instr(XSL_FALLBACK,         ELEM_II,    0, 0, at_empty),
309     instr(XSL_FOR_EACH,         ELEM_I_XI,  1, 1, at_for_each),
310     instr(XSL_IF,               ELEM_II,    1, 1, at_if),
311     instr(XSL_IMPORT,           ELEM_X0,    1, 1, at_import),
312     instr(XSL_INCLUDE,          ELEM_T0,    1, 1, at_include),
313     instr(XSL_KEY,              ELEM_T0,    3, 3, at_key),
314     instr(XSL_MESSAGE,          ELEM_II,    0, 1, at_message),
315     instr(XSL_NAMESPACE_ALIAS,  ELEM_T0,    2, 2, at_ns_alias),
316     instr(XSL_NUMBER,           ELEM_I0,    0, 9, at_number),
317     instr(XSL_OTHERWISE,        ELEM_XI,    0, 0, at_empty),
318     instr(XSL_OUTPUT,           ELEM_T0,    0, 10, at_output),
319     instr(XSL_PARAM,            ELEM_TX_I,  1, 2, at_param),
320     instr(XSL_PRESERVE_SPACE,   ELEM_T0,    1, 1, at_preserve_space),
321     instr(XSL_PROCESSING_INSTR, ELEM_II,    1, 1, at_pi),
322     instr(XSL_SORT,             ELEM_X0,    0, 5, at_sort),
323     instr(XSL_STRIP_SPACE,      ELEM_T0,    1, 1, at_strip_space),
324     instr(XSL_STYLESHEET,       ELEM_X_XT,  1, 4, at_transform),
325     instr(XSL_TEMPLATE,         ELEM_T_XI,  0, 4, at_template),
326     instr(XSL_TEXT,             ELEM_I__,   0, 1, at_text),
327     instr(XSL_TRANSFORM,        ELEM_X_XT,  1, 4, at_transform),
328     instr(XSL_VALUE_OF,         ELEM_I0,    1, 2, at_value_of),
329     instr(XSL_VARIABLE,         ELEM_IT_I,  1, 2, at_variable),
330     instr(XSL_WHEN,             ELEM_XI,    1, 1, at_when),
331     instr(XSL_WITH_PARAM,       ELEM_XI,    1, 2, at_with_param)
332 };
333
334 /****************************************
335 V e r t e x
336 ****************************************/
337
338 Vertex::~Vertex()
339 {
340 #ifdef _TH_DEBUG
341   printf("Vertex destructor >%x<\n",this);
342 #endif
343     // call DOM dispose callback if set
344 #ifdef ENABLE_DOM
345   if (SDOM_getDisposeCallback())
346     (*(SDOM_getDisposeCallback()))(this);
347 #endif
348 };
349
350 eFlag Vertex::execute(Sit S, Context *c, Bool resolvingGlobals)
351 {
352     assert(FALSE);
353     return NOT_OK;
354 }
355
356 eFlag Vertex::value(Sit S, DStr& ret, Context *c)
357 {
358     assert(0);
359     return NOT_OK;
360 }
361
362 eFlag Vertex::startCopy(Sit S, OutputterObj& out)
363 {
364     return OK;
365 };
366
367 eFlag Vertex::endCopy(Sit S, OutputterObj& out)
368 {
369     return OK;
370 };
371
372 eFlag Vertex::copy(Sit S, OutputterObj& out)
373 {
374   S.setCurrSAXLine(lineno); //for SAX copying - be careful
375
376   OutputterObj *aux;
377   startDocument(S, aux);
378
379   OutputterObj &useOut = aux ? *aux : out;
380   E( startCopy(S, useOut) );
381   E( endCopy(S, useOut) );
382
383   finishDocument(S);
384
385   return OK;
386 }
387
388 void Vertex::speak(DStr &ret, SpeakMode mode)
389 {
390 }
391
392 void Vertex::setParent(Vertex *v)
393 {
394     parent = v;
395 }
396
397 Vertex* Vertex::getPreviousSibling()
398 {
399     if (!parent || !isElement(parent))
400         return NULL;
401         if (!ordinal)
402             return NULL;
403         return toE(parent) -> contents[ordinal - 1];
404 }
405
406 Vertex* Vertex::getNextSibling()
407 {
408     if (!parent || !isElement(parent))
409         return NULL;
410         if (ordinal >= toE(parent) -> contents.number() - 1)
411             return NULL;
412         return toE(parent) -> contents[ordinal + 1];
413 }
414
415 const QName& Vertex::getName() const
416 {
417     return owner.getTheEmptyQName();
418 }
419
420 Tree& Vertex::getOwner() const
421 {    
422     return owner;
423 }
424
425 void Vertex::report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2) const
426 {
427     S.setCurrV((Vertex*)this);
428     S.setCurrFile(getSubtreeInfo() -> getBaseURI());
429     S.message(type, code, arg1, arg2);
430 }
431
432 HashTable& Vertex::dict() const
433 {
434     return getOwner().dict();
435 }
436
437 eFlag Vertex::serialize(Sit S, OutputterObj &out)
438 {
439     return OK;
440 }
441
442 void Vertex::makeStamps(int& stamp_)
443 {
444     stamp = stamp_++;
445 }
446
447 eFlag Vertex::getMatchingList(Sit S, Expression& match, Context& result)
448 {
449   Context aux(NULL);
450   aux.set(this);
451   Bool yes;
452   E( match.matchesPattern(S, &aux, yes) );
453   if (yes)
454     result.append(this);
455   return OK;
456 }
457
458 int Vertex::getImportPrecedence()
459
460     return NZ( getSubtreeInfo() ) -> getStructure() -> getImportPrecedence(); 
461 }
462
463 eFlag Vertex::startDocument(Sit S, OutputterObj*& out)
464 {
465   Processor *proc;
466   if (outputDocument && (proc = S.getProcessor()))
467     {
468       E( proc -> startDocument(S, outputDocument) );
469       out = NZ( outputDocument -> getOutputter() );
470     }
471   else
472     out = NULL;
473   return OK;
474 }
475
476 eFlag Vertex::finishDocument(Sit S)
477 {
478   Processor *proc;
479   if (outputDocument && (proc = S.getProcessor()))
480     {
481       E( proc -> finishDocument(S, outputDocument, FALSE) );
482     }
483   return OK;
484 }
485
486 /****************************************
487 V e r t e x L i s t
488 ****************************************/
489
490 VertexList::VertexList(int logBlockSize_ /*=LIST_SIZE_SMALL*/)
491   : SList<Vertex*>(logBlockSize_)
492 {
493 }
494
495 VertexList::~VertexList()
496 {
497     deppendall();
498 }
499
500 void VertexList::destructMembers()
501 {
502     for (int i = 0; i < nItems; i++)
503     {
504         Vertex *v = (*this)[i];
505             if (isDaddy(v))
506                 toD(v) -> ~Daddy();
507                 else
508                     v -> ~Vertex();
509         }
510 }
511
512
513 eFlag VertexList::execute(Sit S, Context *c, Bool resolvingGlobals)
514 {
515     int i;
516     for (i=0; i<number(); i++)
517         E( (*this)[i] -> execute(S, c, resolvingGlobals) );
518     return OK;
519 }
520
521 eFlag VertexList::value(Sit S, DStr &ret, Context *c)
522 {
523     int i;
524     DStr temp;
525
526     ret.empty();
527     for (i=0; i<number(); i++)
528     {
529         E( (*this)[i] -> value(S, temp, c) );
530         temp.appendSelf(ret);
531     };
532     return OK;
533 }
534
535 void VertexList::speak(DStr &ret, SpeakMode mode)
536 {
537     int i;
538     for (i = 0; i < number(); i++)
539     {
540         (*this)[i] -> speak(ret, mode);
541         if ((mode & SM_INS_SPACES) && (i < number() - 1))
542              ret += ' ';
543     };
544 }
545
546 void VertexList::append(Vertex *v)
547 {
548     v -> ordinal = number();
549     List<Vertex*>::append(v);
550 }
551
552 int VertexList::strip()
553 {
554     int cnt = 0;
555     for (int i = 0; i < number(); i++)
556     {
557         Vertex *node = (*this)[i];
558         if ((node -> vt == VT_TEXT) && isAllWhite((char*)(toText(node) -> cont)))
559         {
560             cnt++;
561             // not doing a freerm() since the node is allocated in the arena
562             // freerm(i--,FALSE);
563             rm(i--);
564         }
565     };
566     return cnt;
567 }
568
569 eFlag VertexList::copy(Sit S, OutputterObj& out)
570 {
571     for (int i = 0; i < number(); i++)
572         E( (*this)[i] -> copy(S, out) );
573     return OK;
574 }
575
576 void VertexList::insertBefore(Vertex *newChild, int refIndex)
577 {
578     PList<Vertex*>::insertBefore(newChild, refIndex);
579     for (int i = refIndex; i < number(); i++)
580         (*this)[i] -> ordinal = i;
581 }
582
583 void VertexList::rm(int ndx)
584 {
585     SList<Vertex*>::rm(ndx);
586     for (int i = ndx; i < number(); i++)
587         (*this)[i] -> ordinal = i;    
588 }
589
590 int VertexList::getIndex(Vertex *v)
591 {
592     for (int i = 0; i < number(); i++)
593         if ((*this)[i] == v) return i;
594         return -1;
595 }
596
597 eFlag VertexList::serialize(Sit S, OutputterObj &out)
598 {
599     int i;
600     for (i = 0; i < number(); i++)
601         E( (*this)[i] -> serialize(S, out) );
602     return OK;
603 }
604
605 void VertexList::makeStamps(int& stamp_)
606 {
607     for (int i = 0; i < number(); i++)
608         (*this)[i] -> makeStamps(stamp_);
609 }
610
611 eFlag VertexList::getMatchingList(Sit S, Expression& match, Context& result)
612 {
613   for (int i = 0; i < number(); i++)
614     E( (*this)[i] -> getMatchingList(S, match, result) );
615   return OK;
616 }
617
618 /****************************************
619 D a d d y
620 a vertex with contents
621 ****************************************/
622
623 Daddy::Daddy(Tree& owner_, VTYPE avt /* = VT_DADDY_WF */)
624 : Vertex(owner_, avt), contents(&(owner_.getArena()))
625 {
626 };
627
628
629 Daddy::~Daddy()
630 {
631     // not doing freeall since it's all in the arena
632     // contents.freeall(FALSE);
633     contents.destructMembers();
634 };
635
636 eFlag Daddy::execute(Sit S, Context *c, Bool resolvingGlobals)
637 {
638     E( contents.execute(S, c, resolvingGlobals) );
639     return OK;
640 };
641
642 eFlag Daddy::value(Sit S, DStr &ret, Context *c)
643 {
644     E( contents.value(S, ret, c) );
645     return OK;
646 }
647
648 eFlag Daddy::checkChildren(Sit S)
649 {
650     assert(!"Daddy::checkChildren()");
651     return NOT_OK;
652 }
653
654 eFlag Daddy::newChild(Sit S, Vertex *v)
655 {
656     // contents.appendAndSetOrdinal(v);
657     contents.append(v);
658     v -> setParent(this);
659     return OK;
660 };
661
662 void Daddy::speak(DStr &ret, SpeakMode mode)
663 {
664     if (mode & SM_CONTENTS)
665         contents.speak(ret, mode);
666 }
667
668 int Daddy::strip()
669 {
670     return contents.strip();
671 }
672
673 eFlag Daddy::getMatchingList(Sit S, Expression& match, Context& result)
674 {
675     E( Vertex::getMatchingList(S, match, result) );
676     E( contents.getMatchingList(S, match, result) );
677         return OK;
678 }
679
680
681
682 /****************************************
683 R o o t N o d e
684 a vertex with prolog and contents 
685 ****************************************/
686
687 RootNode::~RootNode()
688 {
689 }
690
691 eFlag RootNode::execute(Sit S, Context *c, Bool resolvingGlobals)
692 {
693   //! process prolog
694   //
695   E( Daddy::execute(S, c, resolvingGlobals) );
696   return OK;
697 };
698
699 eFlag RootNode::checkChildren(Sit S)
700 {
701     return OK;
702 }
703
704 eFlag RootNode::newChild(Sit S, Vertex *v)
705 {
706     //! insert prolog
707     //
708     E( Daddy::newChild(S, v) );
709     return OK;
710 };
711
712 void RootNode::speak(DStr &s, SpeakMode mode)
713 {
714     if (mode & SM_DESCRIBE)
715         s += "[ROOT]";
716     if (mode & SM_CONTENTS)
717         Daddy::speak(s,mode);
718 }
719
720 eFlag RootNode::startCopy(Sit S, OutputterObj& out)
721 {
722     return Vertex::startCopy(S, out);
723 };
724
725 eFlag RootNode::endCopy(Sit S, OutputterObj& out)
726 {
727     return Vertex::endCopy(S, out);
728 };
729
730 eFlag RootNode::copy(Sit S, OutputterObj& out)
731 {
732   //RootNode shouldn't need to case for outputDocument
733
734   E( startCopy(S, out) );
735   E( contents.copy(S, out) );
736   E( endCopy(S, out) );
737   return OK;
738 }
739
740 eFlag RootNode::serialize(Sit S, OutputterObj &out)
741 {
742     E( out.eventBeginOutput(S) );
743     E( contents.serialize(S, out) );
744     E( out.eventEndOutput(S) );
745     return OK;
746 }
747
748 /****************************************
749 E l e m e n t
750 a vertex with attributes, defs and contents
751 ****************************************/
752
753 Element::Element(Tree& owner_, QName& aqname, VTYPE avt /*= VT_ELEMENT_WF*/)
754 : Daddy(owner_, avt), 
755   namespaces(&(owner_.getArena())), 
756   atts(&(owner_.getArena()))
757 {
758     name = aqname;
759     //origContext = NULL;
760     //exNS = NULL;
761     //extNS = NULL;
762     attsNames = NULL;
763     preserveSpace = FALSE;
764 #ifdef SABLOT_DEBUGGER
765     breakpoint = NULL;
766 #endif
767 };
768
769 Element::~Element()
770 {
771     // not doing freeall since it's all in the arena
772     // namespaces.freeall(FALSE);
773     // atts.freeall(FALSE);
774     if (attsNames) {
775       attsNames -> freeall(FALSE);
776       delete attsNames;
777     }
778     namespaces.destructMembers();
779     atts.destructMembers();
780 };
781
782 int Element::strip() 
783 {
784   if (!preserveSpace)
785     return contents.strip();
786   else
787     return 0;
788 }
789
790 eFlag Element::execute(Sit S, Context *c, Bool resolvingGlobals)
791 {
792 #ifdef SABLOT_DEBUGGER
793   if (debugger) E( debugger -> breakOnElement(S, this, c) );
794 #endif
795
796     EQName expandedName;
797     owner.expandQ(name, expandedName);
798     OutputterObj * out = NZ(S.getProcessor()) -> outputter();
799
800     //name aliasing
801     Bool aliased = false;
802     NZ(S.getProcessor()) -> getAliasedName(expandedName, aliased);
803
804     //set subtree for exclusions
805     E( out -> eventElementStart(S, expandedName) );
806     //output namespaces (and extra aliased namespace if needed)
807     E( namespaces.executeSkip(S, c, resolvingGlobals, expandedName, aliased) );
808     if (aliased)
809       E( out -> eventNamespace(S, expandedName.getPrefix(), 
810                                expandedName.getUri() ) )
811     //attribute sets
812     if (attSetNames(FALSE))
813       E( executeAttributeSets(S, c, resolvingGlobals) );
814     //plain attributes
815     E( atts.execute(S, c, resolvingGlobals) );
816     //content
817     E( Daddy::execute(S, c, resolvingGlobals) );
818     removeBindings(S);
819     //end tag
820     E( out -> eventElementEnd(S, expandedName));
821
822     return OK;
823 }
824
825 eFlag Element::executeFallback(Sit S, Context *c, Bool &hasSome, 
826                                Bool resolvingGlobals)
827 {
828   Processor *proc = NZ(S.getProcessor());
829   for (int i = 0; i < contents.number(); i++) 
830     {
831       Vertex *v = contents[i];
832       if (isXSLElement(v) && (toX(v) -> op == XSL_FALLBACK) )
833         {
834           proc -> vars -> startApplyOne();
835           E( toE(v) -> contents.execute(S, c, resolvingGlobals) );
836           proc -> vars -> endApplyOne();
837           hasSome = TRUE;
838         }
839     }
840   return OK;
841 }
842
843 eFlag Element::newChild(Sit S, Vertex *v)
844 {
845     v -> setParent(this);
846     if isAttr(v)
847         atts.append(v);
848         // atts.appendAndSetOrdinal(v);
849     else
850     {
851         if (isNS(v))
852             namespaces.append(v);
853             // namespaces.appendAndSetOrdinal(v);
854         else
855             E( Daddy::newChild(S, v) );
856     }
857     return OK;
858 };
859
860 void Element::speak(DStr &ret, SpeakMode mode)
861 {
862     if (mode & (SM_NAME | SM_CONTENTS))
863     {
864         ret += '<';
865             Str fullName;
866             owner.expandQStr(name, fullName);
867             ret += fullName;
868 //        name.speak(ret,mode);
869         if (mode & SM_CONTENTS)
870         {
871             if (namespaces.number())
872             {
873                 ret += ' ';
874                 namespaces.speak(ret, (SpeakMode)(mode | SM_INS_SPACES));
875             }
876             if (atts.number())
877             {
878                 ret += ' ';
879                 atts.speak(ret, (SpeakMode)(mode | SM_INS_SPACES));
880             };
881             {
882                 ret += '>';
883                 contents.speak(ret,(SpeakMode)(mode & ~SM_INS_SPACES));
884                 ret += "</";
885                     ret += fullName;
886 //                name.speak(ret,mode);
887                 ret += '>';
888             };
889         }
890         else ret += '>';
891     };
892 };
893
894 /*================================================================
895 removeBindings
896     This removes all VARIABLE bindings for the variables
897     that are children of this element. The param and with-param
898     bindings are removed by the 'vars' list itself.
899 ================================================================*/
900
901 void Element::removeBindings(Sit S)
902 {
903     Attribute *a;
904     Vertex *v;
905     for (int i = contents.number() - 1; i >= 0; i--)
906     {
907         v = contents[i];
908         if (isXSLElement(v) && (cast(XSLElement*, v) -> op == XSL_VARIABLE))
909         {
910             QName q;
911             a = NZ(cast(XSLElement*, v) -> atts.find(XSLA_NAME));
912                 // FIXME: check for error in setLogical
913             setLogical(S, q, a -> cont, FALSE);
914             NZ(S.getProcessor()) -> vars -> rmBinding(q);
915         }
916     }
917 }
918
919 eFlag Element::startCopy(Sit S, OutputterObj& out)
920 {
921   EQName expandedName;
922   owner.expandQ(name, expandedName);
923   E( out.eventElementStart(S, expandedName ));
924   E( namespaces.copy(S, out) );
925   return OK;
926 }
927
928 eFlag Element::endCopy(Sit S, OutputterObj& out)
929 {
930   EQName expandedName;
931   owner.expandQ(name, expandedName);
932   E( out.eventElementEnd(S, expandedName ));
933   return OK;
934 }
935
936 eFlag Element::copy(Sit S, OutputterObj& out)
937 {
938   OutputterObj *aux;
939   startDocument(S, aux);
940
941   OutputterObj &useOut = aux ? *aux : out;
942
943   S.setCurrSAXLine(lineno); //for SAX copying - be careful
944   E( startCopy(S, useOut) );
945   E( atts.copy(S, useOut) );
946   E( contents.copy(S, useOut) );
947   E( endCopy(S, useOut) );
948
949   finishDocument(S);
950
951   return OK;
952 };
953
954 const QName& Element::getName() const
955 {
956     return name;
957 }
958
959 eFlag Element::setLogical(Sit S, QName &qn, const Str &string, 
960                           Bool defaultToo, Phrase defUri /*= UNDEF_PHRASE*/) const
961 // GP: OK
962 {
963     Phrase thePrefix, resolved;
964     char *p = (char *)(Str &) string,
965         *q = strchr(p,':'),
966         *localPart;
967     if (q)
968     {
969         *q = 0;
970         qn.setPrefix(resolved = thePrefix = dict().insert(p));
971         *q = ':';
972         localPart = q + 1;
973     }
974     else
975     {
976         qn.setPrefix(resolved = thePrefix = UNDEF_PHRASE);
977         localPart = p;
978     };
979     
980     if (defUri != UNDEF_PHRASE) {
981       resolved = defUri;
982     }
983     else{
984       if (thePrefix != getOwner().stdPhrase(PHRASE_XMLNS))
985         {
986           E( namespaces.resolve(S, resolved, defaultToo) );
987           // check if a non-undef was resolved to an undef
988           if (resolved == UNDEF_PHRASE && thePrefix != UNDEF_PHRASE)
989             Err1(S, ET_BAD_PREFIX, (char *)(Str &)string);
990         }
991       else
992         resolved = UNDEF_PHRASE;
993     }
994     if (strchr(localPart,':'))
995       Err1(S, E1_EXTRA_COLON, (char *)(Str &)string);
996     qn.setUri(resolved);
997     qn.setLocal(dict().insert(localPart));
998     return OK;
999 }
1000
1001 eFlag Element::serialize(Sit S, OutputterObj &out)
1002 {
1003     EQName ename;
1004     getOwner().expandQ(name, ename);
1005     E( out.eventElementStart(S, ename) );
1006     E( namespaces.serialize(S, out) );
1007     E( atts.serialize(S, out) );
1008     E( contents.serialize(S, out) );
1009     E( out.eventElementEnd(S, ename) );
1010     return OK;
1011 }
1012
1013 eFlag Element::serializeSubtree(Sit S, OutputterObj &out)
1014 {
1015     E( out.eventBeginSubtree(S) );
1016
1017     EQName ename;
1018     getOwner().expandQ(name, ename);
1019     E( out.eventElementStart(S, ename) );
1020     E( atts.serialize(S, out) );
1021     E( contents.serialize(S, out) );
1022     E( out.eventElementEnd(S, ename) );
1023
1024     E( out.eventEndOutput(S) );
1025     return OK;
1026 }
1027
1028 void Element::removeChild(Vertex *child)
1029 {
1030     assert(child -> parent == this);
1031     contents.rm(child -> ordinal);
1032     child -> setParent(NULL);    
1033 }
1034
1035 void Element::makeStamps(int& stamp_)
1036 {
1037     Vertex::makeStamps(stamp_);
1038     namespaces.makeStamps(stamp_);
1039     atts.makeStamps(stamp_);
1040     contents.makeStamps(stamp_);
1041 }
1042
1043 eFlag Element::getMatchingList(Sit S, Expression& match, Context& result)
1044 {
1045     E( Vertex::getMatchingList(S, match, result) );
1046     E( namespaces.getMatchingList(S, match, result) );
1047     E( atts.getMatchingList(S, match, result) );    
1048     E( contents.getMatchingList(S, match, result) );
1049         return OK;
1050 }
1051
1052 QNameList* Element::attSetNames(Bool canCreate) {
1053   if (!attsNames && canCreate) attsNames = new QNameList;
1054   return attsNames;
1055 }
1056
1057 eFlag Element::executeAttributeSets(Sit S, Context *c, Bool resolvingGlobals)
1058 {
1059   Processor *proc = NZ(S.getProcessor());
1060   proc -> vars -> pushCallLevel(0);
1061   if (attsNames)
1062     {
1063       for (int i = 0; i < attsNames -> number(); i++)
1064         {
1065           QNameList history;
1066           E( getOwner().attSets().executeAttSet(S, *((*attsNames)[i]), 
1067                                                 c, getOwner(), history, 
1068                                                 resolvingGlobals) );
1069         }
1070     }
1071   proc -> vars -> popCallLevel();
1072   return OK;
1073 }
1074
1075 /****************************************
1076 A t t r i b u t e
1077 ****************************************/
1078
1079 Attribute::Attribute(Tree &owner_, const QName &aqname, 
1080     const Str &acont, XSL_ATT aop)
1081 : Vertex(owner_, (VTYPE) (VT_ATTRIBUTE_WF | 
1082     (aop != XSLA_NONE ? VT_XSL : 0))),
1083     cont(&(owner_.getArena()))
1084 {
1085     expr = NULL;
1086     name = aqname;
1087     cont = acont;
1088     op = aop;
1089 };
1090
1091 Attribute::~Attribute()
1092 {
1093     if (expr)
1094         delete expr;
1095 }
1096
1097 eFlag findAVTBrace(Sit S, char *&p, char which, DStr &copybuf)
1098 {
1099     char *p0 = p; // ,c;
1100     int len;
1101     copybuf.empty();
1102     while (*p)
1103     {
1104         if (*p != which) 
1105             p++;
1106         else
1107         {
1108             if (*(p+1) == which)
1109             {
1110                 len = p+1 - p0;
1111                 if (len)
1112                     copybuf.nadd(p0, len);
1113                 p += 2;
1114                 p0 = p;
1115             }
1116             else break;
1117         };
1118     };
1119     len = p - p0;
1120     if (len) copybuf.nadd(p0, len);
1121     return OK;
1122 }
1123
1124 eFlag Attribute::buildExpr(Sit S, Bool asTemplate, ExType ty)
1125 {
1126     char *q;
1127     GP( Expression ) eadd;
1128     if (asTemplate)
1129     {
1130         DStr sadd;
1131         expr = new Expression(*toE(parent), EXF_STRINGSEQ);  // GP: OK
1132         char *p = (char*) cont;
1133         while (*p)
1134         {
1135             E( findAVTBrace(S, q = p, '{', sadd) );
1136             if (!sadd.isEmpty())
1137             {
1138                 eadd = new Expression(*toE(parent), EXF_ATOM);
1139                 (*eadd).setAtom(sadd);
1140                 expr -> args.append(eadd.keep());
1141             };
1142             if (!*q) break;
1143             //
1144             if (!*(p = q + 1)) break;
1145             E( findAVTBrace(S, q = p, '}',sadd) );
1146             if (!sadd.isEmpty())
1147             {
1148                 eadd = new Expression(*toE(parent));
1149                 E( (*eadd).parse(S, sadd));
1150                 expr -> args.append(eadd.keep());
1151             };
1152             if (!*q) break;
1153             p = q + 1;
1154         }
1155     }
1156     else
1157     {
1158         expr = new Expression(*toE(parent));    // GP: OK
1159         E( expr -> parse(S, cont, (Bool) (ty == EX_NODESET_PATTERN)) );
1160     }
1161     return OK;
1162 }
1163
1164 eFlag Attribute::execute(Sit S, Context *c, Bool resolvingGlobals)
1165 {
1166     assert(parent);
1167     EQName ename;
1168     owner.expandQ(name, ename);
1169     OutputterObj &out = *(NZ(S.getProcessor()) -> outputter());
1170
1171     if (isXSLElement(parent) || op != XSLA_NONE || 
1172         ename.getUri() == theXSLTNamespace )
1173       {
1174         return OK;
1175       }
1176
1177     E( out.eventAttributeStart(S, ename) );
1178     DStr temp;
1179     E( value(S, temp,c) );
1180     E( out.eventData(S, temp) );
1181     E( out.eventAttributeEnd(S) );
1182     return OK;
1183 }
1184
1185 eFlag Attribute::value(Sit S, DStr &ret, Context *c)
1186 {
1187     if (expr)
1188     {
1189         Expression temp(*toE(parent));
1190         E( expr -> eval(S, temp, c) );
1191         E( temp.tostring(S, ret) );
1192     }
1193     else
1194         ret = cont;
1195     return OK;
1196 }
1197
1198 void Attribute::speak(DStr &ret, SpeakMode mode)
1199 {
1200     if (mode & (SM_NAME | SM_CONTENTS))
1201     {
1202             Str fullName;
1203             owner.expandQStr(name, fullName);
1204             ret += fullName;
1205             // name.speak(ret,mode);
1206         }
1207     if (mode & SM_CONTENTS)
1208     {
1209         ret += "=\"";
1210         // escape whitespace and quotes in value
1211         DStr escapedCont;
1212         const char* escNTQLG[] = 
1213             {escNewline, escTab, escQuote, escLess, escGreater, NULL};
1214         escapeChars(escapedCont, cont, "\n\t\"<>", escNTQLG);
1215         escapedCont.appendSelf(ret);
1216         ret += '\"';
1217     }
1218 }
1219
1220 eFlag Attribute::startCopy(Sit S, OutputterObj& out)
1221 {
1222     EQName ename;
1223     owner.expandQ(name, ename);    
1224     E( out.eventAttributeStart(S, ename) );
1225     E( out.eventData(S, cont) );
1226     E( out.eventAttributeEnd(S) );
1227     return OK;
1228 }
1229
1230 const QName& Attribute::getName() const
1231 {
1232     return name;
1233 }
1234
1235 void Attribute::setValue(const Str& newValue)
1236 {
1237     cont = newValue;
1238 }
1239
1240 eFlag Attribute::serialize(Sit S, OutputterObj &out)
1241 {
1242     EQName ename;
1243     getOwner().expandQ(name, ename);
1244     E( out.eventAttributeStart(S, ename) );
1245     E( out.eventData(S, cont) );
1246     E( out.eventAttributeEnd(S) );
1247     return OK;
1248 }
1249
1250 /****************************************
1251 A t t L i s t
1252 ****************************************/
1253
1254 Attribute* AttList::find(XSL_ATT what)
1255 {
1256     int i;
1257     Attribute *a;
1258     int num = number();
1259     for (i = 0; i < num; i++)
1260     {
1261         // need to use a temporary variable
1262         // to get around Solaris template problem
1263         Vertex * pTemp = (*this)[i];
1264         a = cast(Attribute *, pTemp);
1265         if (a -> op == what)
1266             return a;
1267     };
1268     return NULL;
1269 }
1270
1271 int AttList::findNdx(const QName& attName)
1272 {
1273     int i;
1274     Attribute *a;
1275     int num = number();
1276     for (i = 0; i < num; i++)
1277     {
1278         // need to use a temporary variable
1279         // to get around Solaris template problem
1280         Vertex * pTemp = (*this)[i];
1281         a = toA(pTemp);
1282         if (attName == a -> getName())
1283             return i;
1284     };
1285     return -1;
1286 }
1287
1288 Attribute* AttList::find(const QName& attName)
1289 {
1290     int ndx = findNdx(attName);
1291     // need to use a temporary variable
1292     // to get around Solaris template problem
1293     if (ndx != -1)
1294       {
1295         Vertex * pTemp = (*this)[ndx];
1296         return toA(pTemp);
1297       } 
1298     else
1299       {
1300         return NULL;
1301       }
1302 }
1303
1304 /*****************************************************************
1305     N m S p a c e
1306 *****************************************************************/
1307 //NmSpace::NmSpace(Tree& owner_, Phrase _prefix, Phrase _uri, NsKind _kind)
1308 NmSpace::NmSpace(Tree& owner_, Phrase _prefix, Phrase _uri, 
1309                  Bool _excluded, NsKind _kind)
1310 : Vertex(owner_, VT_NAMESPACE)
1311 {
1312     prefix = _prefix;
1313     uri = _uri;
1314     name.setLocal(prefix);
1315     kind = _kind;
1316     excluded = _excluded;
1317     usageCount = 0;
1318 }
1319
1320 NmSpace::~NmSpace()
1321 {
1322 }
1323
1324 eFlag NmSpace::execute(Sit S, Context *c, Bool resolvingGlobals)
1325 {
1326     assert(parent);
1327
1328     E( NZ(S.getProcessor()) -> outputter() -> 
1329        eventNamespace(S,
1330                       //was: proc -> aliasXL(prefix)),
1331                       getOwner().dict().getKey(prefix), 
1332                       getOwner().dict().getKey(uri),
1333                       excluded
1334                       ));
1335     return OK;
1336 }
1337
1338 eFlag NmSpace::executeSkip(Sit S, Context *c, Bool resolvingGlobals,
1339                            EQName & exName, Bool aliased)
1340 {
1341     assert(parent);
1342
1343     const Str & pStr = getOwner().dict().getKey(prefix);
1344     const Str & uStr = getOwner().dict().getKey(uri);
1345
1346     if (!aliased || !(exName.getPrefix() == pStr))
1347       E( NZ(S.getProcessor()) -> outputter() -> 
1348          eventNamespace(S, pStr, uStr, excluded) );
1349     return OK;
1350 }
1351
1352 void NmSpace::speak(DStr& s, SpeakMode mode)
1353 {
1354     s += "xmlns";
1355     if (prefix != UNDEF_PHRASE)
1356     {
1357         s += ':';
1358         s += getOwner().dict().getKey(prefix);
1359     }
1360     s += "=\"";
1361     s += getOwner().dict().getKey(uri);
1362     s += '\"';
1363 }
1364
1365 eFlag NmSpace::value(Sit S, DStr &s, Context *c)
1366 {
1367     s = getOwner().dict().getKey(uri);
1368     return OK;
1369 }
1370
1371 eFlag NmSpace::startCopy(Sit S, OutputterObj& out)
1372 {
1373     E( out.eventNamespace(S,
1374                           getOwner().dict().getKey(prefix), 
1375                           getOwner().dict().getKey(uri),
1376                           excluded) );
1377     return OK;
1378 }
1379
1380 const QName& NmSpace::getName() const
1381 {
1382     return name;
1383 }
1384
1385 eFlag NmSpace::serialize(Sit S, OutputterObj &out)
1386 {
1387     const Str &prefixStr = getOwner().expand(prefix),
1388         &uriStr = getOwner().expand(uri);
1389         // hide the "xml" binding
1390         if (!(prefixStr == "xml"))
1391         E( out.eventNamespace(S, prefixStr, uriStr) );
1392     return OK;
1393 }
1394
1395 NsKind NmSpace::setKind(NsKind kind_) {
1396     if (kind < kind_) kind = kind_;
1397     return kind;
1398 }
1399 /*****************************************************************
1400     N S L i s t
1401 *****************************************************************/
1402
1403 NSList::~NSList()
1404 {
1405 }
1406
1407 NmSpace* NSList::find(Phrase prefix) const
1408 {
1409     int ndx = findNdx(prefix);
1410     return (ndx == -1) ? NULL : toNS((*this)[ndx]);
1411 }
1412
1413 int NSList::findNdx(Phrase prefix) const
1414 {
1415     int i;
1416     for (i = 0; i < number(); i++) 
1417       if (toNS((*this)[i]) -> prefix == prefix)
1418         return i;
1419     return -1;
1420 }
1421
1422 eFlag NSList::resolve(Sit S, Phrase &what, Bool defaultToo) const
1423 {
1424     Bool emptystr = (what == UNDEF_PHRASE);
1425     if (emptystr && !defaultToo)
1426         return OK;
1427     NmSpace *p = find(what);
1428     if (!p)
1429     {
1430         if (!emptystr)
1431             what = UNDEF_PHRASE;
1432     }
1433     else
1434         what = p -> uri;
1435     return OK;
1436 }
1437
1438 void NSList::unresolve(Phrase &what) const
1439 {
1440     assert(what != UNDEF_PHRASE);
1441     NmSpace *currNS;
1442     for (int i = 0; i < number(); i++)
1443     {
1444         currNS = toNS((*this)[i]);
1445         if (what == currNS -> uri)
1446         {
1447             what = currNS -> prefix;
1448             return;
1449         }
1450     };
1451     assert(0);
1452 }
1453
1454 /*
1455 appends all current namespace declarations as vertices to tree t
1456 'other' is the list where they are being appended in t
1457 */
1458
1459 void NSList::giveCurrent(Sit S, NSList &other, Tree *t, int nscount) const
1460 {
1461     const NmSpace *currNS, *addedNS;
1462     const int imax = number() - 1;
1463     UriList &excludedNS = t -> getCurrentInfo() -> getExcludedNS();
1464     for (int i = imax; i >= 0; i--)
1465     {
1466         currNS = toNS((*this)[i]);
1467         if (other.findNdx(currNS -> prefix) == -1) {
1468             addedNS = new(&(NZ(t) -> getArena())) 
1469               NmSpace(*t, currNS -> prefix, currNS -> uri, 
1470                       excludedNS.findNdx(currNS->uri)!=-1 || currNS->excluded,
1471                       i > (imax - nscount) ?  NSKIND_DECLARED : NSKIND_PARENT);
1472             t -> appendVertex(S, toV(addedNS));
1473             // _JP_ ??? why not other.append(toV(addedNS));
1474         };
1475     }
1476 }
1477
1478 void NSList::swallow(Sit S, NSList &other, Tree* srcTree, Tree *t)
1479 {
1480   for (int i = 0; i < other.number(); i++)
1481     {
1482       NmSpace *currNS = toNS(other[i]);
1483
1484       Phrase p, u;
1485       //translate between dictionaries
1486       if (srcTree && srcTree != t)
1487         {
1488           if (currNS -> prefix == UNDEF_PHRASE)
1489             {
1490               p = UNDEF_PHRASE;
1491             }
1492           else {
1493             const Str &aux1 = srcTree -> expand(currNS -> prefix);
1494             p = t -> unexpand(aux1);
1495           }
1496
1497           const Str &aux2 = srcTree -> expand(currNS -> uri);
1498           u = t -> unexpand(aux2);
1499         }
1500       else
1501         {
1502           assert(!srcTree);
1503           p = currNS -> prefix;
1504           u = currNS -> uri;
1505         }
1506
1507       NmSpace *nm = new (&(NZ(t) -> getArena())) NmSpace(*t, p, u, NSKIND_PARENT);
1508       append(nm);
1509     }
1510 }
1511
1512
1513 void NSList::findPrefix(QName &q)
1514 {
1515     if (q.getUri() == UNDEF_PHRASE)
1516         q.setPrefix(UNDEF_PHRASE);
1517     else
1518     {
1519         Phrase thePrefix = q.getUri();
1520         unresolve(thePrefix);
1521             q.setPrefix(thePrefix);
1522         }
1523 }
1524
1525 void NSList::report(Sit S, MsgType type, MsgCode code, 
1526     const Str &arg1, const Str &arg2) const
1527 {
1528     S.message(type, code, arg1, arg2);
1529 }
1530
1531 void NSList::setPrefixKind(Phrase prefix_, NsKind kind_) const
1532 {
1533     int ndx = findNdx(prefix_);
1534     if (ndx != -1) {
1535       toNS((*this)[ndx]) -> setKind(kind_);
1536     };
1537 }
1538
1539 void NSList::incPrefixUsage(Phrase prefix_) const
1540 {
1541     int ndx = findNdx(prefix_);
1542     if (ndx != -1) {
1543       toNS((*this)[ndx]) -> usageCount++;
1544     };
1545 }
1546
1547 void NSList::decPrefixUsage(Phrase prefix_) const
1548 {
1549     int ndx = findNdx(prefix_);
1550     if (ndx != -1) {
1551       toNS((*this)[ndx]) -> usageCount--;
1552     };
1553 }
1554
1555 eFlag NSList::executeSkip(Sit S, Context * c, Bool resolvingGlobals,
1556                           EQName & exName, Bool aliased)
1557 {
1558   int i;
1559   for (i=0; i<number(); i++)
1560     E( toNS((*this)[i]) -> executeSkip(S, c, resolvingGlobals,
1561                                  exName, aliased) );
1562   return OK;
1563 }
1564
1565 /****************************************
1566 T e x t
1567 ****************************************/
1568
1569 Text::Text(Tree& owner_, char *acont, int alen /* =0 */)
1570     : Vertex(owner_, VT_TEXT_WF), cont(&(owner_.getArena()))
1571 {
1572     if (alen)
1573         cont.nset(acont,alen);
1574     else cont = (char*) acont;
1575     isCDATAFlag = FALSE;
1576 }
1577
1578 Text::~Text()
1579 {
1580 }
1581
1582 eFlag Text::execute(Sit S, Context *c, Bool resolvingGlobals)
1583 {
1584     E( NZ(S.getProcessor()) -> outputter() -> eventData(S, cont) );
1585     return OK;
1586 }
1587
1588 eFlag Text::value(Sit S, DStr& ret, Context *c)
1589 {
1590     ret = cont;
1591     return OK;
1592 }
1593
1594 void Text::speak(DStr &ret, SpeakMode mode)
1595 {
1596     if (mode & SM_ESCAPE)
1597         cont.speakTerse(ret);
1598     else
1599         ret += cont;
1600 };
1601
1602 eFlag Text::startCopy(Sit S, OutputterObj& out)
1603 {
1604     E( out.eventData(S, cont) );
1605     return OK;
1606 }
1607
1608 eFlag Text::serialize(Sit S, OutputterObj &out)
1609 {
1610     if (isCDATAFlag)
1611         E( out.eventCDataSection(S, cont) )
1612         else
1613         E( out.eventData(S, cont) );
1614     return OK;
1615 }
1616
1617 void Text::beCDATA()
1618 {
1619     isCDATAFlag = TRUE;
1620 }
1621
1622 Bool Text::isCDATA()
1623 {
1624     return isCDATAFlag;
1625 }
1626
1627 /****************************************
1628 C o m m e n t
1629 ****************************************/
1630
1631 Comment::Comment(Tree& owner_, const Str& cont_)
1632
1633 Vertex(owner_, VT_COMMENT), cont(&(owner_.getArena()))
1634 {
1635     cont = cont_;
1636 }
1637
1638 Comment::~Comment()
1639 {
1640 }
1641
1642 eFlag Comment::execute(Sit S, Context *c, Bool resolvingGlobals)
1643 {
1644     return OK;
1645 }
1646
1647 eFlag Comment::value(Sit S, DStr& ret, Context *c)
1648 {
1649     ret = cont;
1650     return OK;
1651 }
1652
1653 void Comment::speak(DStr &ret, SpeakMode mode)
1654 {
1655     ret += cont;
1656 };
1657
1658 eFlag Comment::startCopy(Sit S, OutputterObj& out)
1659 {
1660     E( out.eventCommentStart(S) );
1661     E( out.eventData(S, cont) );
1662     E( out.eventCommentEnd(S) );
1663     return OK;
1664 }
1665
1666 eFlag Comment::serialize(Sit S, OutputterObj &out)
1667 {
1668     E( out.eventCommentStart(S) );
1669     E( out.eventData(S, cont) );
1670     E( out.eventCommentEnd(S) );
1671     return OK;
1672 }
1673
1674 /****************************************
1675 P r o c I n s t r
1676 ****************************************/
1677
1678 ProcInstr::ProcInstr(Tree& owner_, Phrase name_, const Str& cont_)
1679
1680 Vertex(owner_, VT_PI), cont(&(owner_.getArena()))
1681 {
1682     name.empty();
1683     name.setLocal(name_);
1684     cont = cont_;
1685 }
1686
1687 ProcInstr::~ProcInstr()
1688 {
1689 }
1690
1691 eFlag ProcInstr::execute(Sit S, Context *c, Bool resolvingGlobals)
1692 {
1693     return OK;
1694 }
1695
1696 eFlag ProcInstr::value(Sit S, DStr& ret, Context *c)
1697 {
1698     ret = cont;
1699     return OK;
1700 }
1701
1702 void ProcInstr::speak(DStr &ret, SpeakMode mode)
1703 {
1704     ret += cont;
1705 };
1706
1707 eFlag ProcInstr::startCopy(Sit S, OutputterObj& out)
1708 {
1709     E( out.eventPIStart(S, owner.expand(name.getLocal())) );
1710     E( out.eventData(S, cont) );
1711     E( out.eventPIEnd(S) );
1712     return OK;
1713 }
1714
1715 const QName& ProcInstr::getName() const
1716 {
1717     return name;
1718 }
1719
1720 eFlag ProcInstr::serialize(Sit S, OutputterObj &out)
1721 {
1722     const Str& nameStr = getOwner().expand(name.getLocal());
1723     E( out.eventPIStart(S, nameStr) );
1724     E( out.eventData(S, cont) );
1725     E( out.eventPIEnd(S) );
1726     return OK;
1727 }
1728
1729 /****************************************
1730 X S L E l e m e n t
1731 ****************************************/
1732
1733 XSLElement::XSLElement(Tree& owner_, QName& aqname, XSL_OP code)
1734 :
1735 Element(owner_, aqname, VT_XSL_ELEMENT_WF)
1736 {
1737     assert(code != XSL_NONE);
1738     op = code;
1739 };
1740
1741
1742 eFlag XSLElement::newChild(Sit S, Vertex *v)
1743 {
1744     // process defs
1745     //
1746     E( Element::newChild(S, v) );
1747     return OK;
1748 };
1749
1750 eFlag XSLElement::execute(Sit S, Context *c, Bool resolvingGlobals)
1751 {
1752     Attribute *a;
1753     Bool didNotExecute = FALSE;
1754     Processor *proc = NZ(S.getProcessor());
1755     // ???
1756     if (c -> isFinished())
1757         return OK;
1758
1759     //c->setCurrentNode(NULL); _cn_
1760
1761     NodeHandle v = c -> current();
1762     assert(v);
1763
1764     //we store the current context to the element
1765     //e.g. the current() function needs it
1766     //setOrigContext(c);
1767
1768 #ifdef SABLOT_DEBUGGER
1769     if (debugger) E( debugger -> breakOnElement(S, this, c) );
1770 #endif
1771
1772     switch(op)
1773     {
1774     case XSL_APPLY_TEMPLATES:
1775     {
1776         Attribute *aSelect = atts.find(XSLA_SELECT);
1777         GP( Expression ) e;
1778         if (aSelect)
1779             e.assign( NZ(aSelect -> expr) );
1780         else
1781         {
1782             e = new Expression(*this, EXF_LOCPATH);
1783             (*e).setLS(
1784                 AXIS_CHILD, 
1785                 EXNODE_NODE);
1786         };
1787
1788         // mode
1789         Bool addedMode = TRUE;
1790         a = atts.find(XSLA_MODE);
1791         if (a)
1792         {
1793             GP( QName ) m = new QName;
1794             E( setLogical(S, *m, a -> cont,FALSE) );
1795             proc -> pushMode(m.keep());
1796         }
1797         else if (proc -> getCurrentMode())
1798             proc -> pushMode(NULL);
1799         else addedMode = FALSE;
1800             
1801         GP( Context ) newc;
1802         newc.assign(c);
1803         E( (*e).createContext( S, newc ) );
1804         newc.unkeep();
1805         if (!(*newc).isVoid())
1806         {
1807             // *** SORT HERE ***
1808             SortDefList sortDefs;
1809             makeSortDefs(S, sortDefs, c);
1810             if (sortDefs.number())
1811                 E( (*newc).sort(S, this, &sortDefs) );
1812             sortDefs.freeall(FALSE);
1813
1814             // process with-params
1815             E( contents.execute(S, c, resolvingGlobals) );
1816             // proc will dispose of newc:
1817             E( proc -> execute(S, (Vertex*) NULL, newc, resolvingGlobals) );
1818             newc.keep();
1819             // remove the prebindings introduced by with-param
1820             proc -> vars -> rmPrebindings();
1821         }
1822         else
1823             newc.del();    // GP: done automatically anyway
1824         if (addedMode)
1825             proc -> popMode();
1826         if (!aSelect)
1827             e.del();    // GP: done automatically anyway
1828     }; break;
1829
1830     case XSL_APPLY_IMPORTS:
1831     {
1832         E( proc -> execApplyImports(S, c, subtree, resolvingGlobals) );
1833     }; break;
1834     
1835     case XSL_IF:
1836     {
1837         a = NZ( atts.find(XSLA_TEST) );
1838         Expression boolexpr(*this);
1839         E( NZ(a -> expr) -> eval(S, boolexpr,c) );
1840         Bool boolval = boolexpr.tobool();
1841         if ((boolval) && (contents.number()))
1842             E( contents.execute(S, c, resolvingGlobals) )
1843                 else
1844                     didNotExecute = TRUE;
1845     }; break;
1846     case XSL_CHOOSE:
1847     {
1848         Bool done = FALSE;
1849         for (int i = 0; i < contents.number() && !done; i++)
1850         {
1851             // need to use a temporary variable
1852             // to get around Solaris template problem
1853             Vertex * pTemp = contents[i];
1854             XSLElement *x = cast(XSLElement*,pTemp);
1855             //needed for the current() function
1856             //problem was, that trueFor is called before x -> execute
1857             //x -> setOrigContext(c); 
1858             if (x -> op == XSL_WHEN)
1859             {
1860               a = NZ( x -> atts.find(XSLA_TEST) );
1861               Expression boolexpr(*this);
1862               E( NZ(a -> expr) -> eval(S, boolexpr, c) );
1863               done = boolexpr.tobool();
1864
1865               if (done) 
1866                 E( x -> execute(S, c, resolvingGlobals) );
1867             }
1868             else
1869             {
1870                 assert(x -> op == XSL_OTHERWISE);
1871                 E( x -> execute(S, c, resolvingGlobals) );
1872             };
1873         };
1874     }; break;
1875     case XSL_WHEN: // condition tested by CHOOSE
1876     {
1877         E( contents.execute(S, c, resolvingGlobals) );
1878     }; break;
1879     case XSL_OTHERWISE: // condition tested by CHOOSE
1880     {
1881         E( contents.execute(S, c, resolvingGlobals) );
1882     }; break;
1883     case XSL_ELEMENT:
1884     {
1885         QName q;
1886         DStr nameStr;
1887         E( NZ( atts.find(XSLA_NAME) ) -> value(S, nameStr, c) );
1888         if (! isValidQName((char*)nameStr) ) 
1889           Err1(S, E_INVALID_QNAME, (char*)nameStr);
1890
1891         Phrase nsuri = UNDEF_PHRASE;
1892         DStr uristr;
1893         //prepare for namespace handling
1894         Attribute *a = atts.find(XSLA_NAMESPACE);
1895         if (a) {
1896           E( a -> value(S, uristr, c) );
1897           nsuri = owner.unexpand(uristr);
1898         }
1899
1900         E( setLogical(S, q, nameStr, TRUE, nsuri) );
1901
1902         Str prefix = owner.expand(q.getPrefix());
1903         if (nsuri != UNDEF_PHRASE &&
1904             (q.getPrefix() == UNDEF_PHRASE || prefix == "xmlns"))
1905           {
1906             Str pfx = S.getProcessor() -> getNextNSPrefix();
1907             q.setPrefix(owner.unexpand(pfx));
1908           }
1909
1910         EQName ename;
1911         owner.expandQ(q, ename);
1912
1913         E( proc -> outputter() -> eventElementStart(S, ename) );
1914         //we have to inherit namespaces
1915         E( namespaces.execute(S, c, resolvingGlobals) );
1916         //add namespace from 'namespace' attribute
1917         if (a) 
1918           {
1919             prefix = ename.getPrefix();
1920             proc -> outputter() -> eventNamespace(S, prefix, uristr);
1921           }
1922         //execute attribute sets
1923         E( executeAttributeSets(S, c, resolvingGlobals) );
1924         //and so on...
1925         E( Daddy::execute(S, c, resolvingGlobals) );
1926         E( proc -> outputter() -> eventElementEnd(S, ename) );
1927     }; break;
1928
1929     case XSL_PROCESSING_INSTR:
1930     {
1931         QName q;
1932         DStr nameStr;
1933         E( NZ( atts.find(XSLA_NAME) ) -> value(S, nameStr, c) );
1934         if (! isValidNCName((char*)nameStr) ) 
1935           Err1(S, E_INVALID_NCNAME, (char*)nameStr);
1936
1937         E( setLogical(S, q, nameStr, FALSE) );
1938         const Str& qloc = owner.expand(q.getLocal());
1939         if (( q.getPrefix() != UNDEF_PHRASE ) || 
1940             strEqNoCase( qloc, "xml") || (qloc == "") )
1941             Err1(S, E1_PI_TARGET, nameStr);
1942         E( proc -> outputter() -> eventPIStart( S, qloc ) );
1943         E( contents.execute(S, c, resolvingGlobals) );
1944         //for better error report
1945         eFlag flg = proc -> outputter() -> eventPIEnd(S); 
1946         if (S.getError() == E_INVALID_DATA_IN_PI)
1947           Err(S, E_INVALID_DATA_IN_PI);
1948         E( flg );
1949     }; break;
1950     case XSL_COMMENT:
1951     {
1952         E( proc -> outputter() -> eventCommentStart(S) );
1953         E( contents.execute(S, c, resolvingGlobals) );
1954         E( proc -> outputter() -> eventCommentEnd(S) ); 
1955     }; break;
1956     case XSL_ATTRIBUTE:
1957     {
1958         QName q;
1959         DStr nameStr;
1960         E( NZ( atts.find(XSLA_NAME) ) -> value(S, nameStr, c) );
1961         if (! isValidQName((char*)nameStr) ) 
1962           Err1(S, E_INVALID_QNAME, (char*)nameStr);
1963
1964         Phrase nsuri = UNDEF_PHRASE;
1965         DStr uristr;
1966         //prepare for namespace handling
1967         Attribute *a = atts.find(XSLA_NAMESPACE);
1968         if (a) {
1969           E( a -> value(S, uristr, c) );
1970           nsuri = owner.unexpand(uristr);
1971         }
1972
1973         E( setLogical(S, q, nameStr, FALSE, nsuri) );
1974         
1975         Str prefix = owner.expand(q.getPrefix());
1976         if (nsuri != UNDEF_PHRASE && 
1977             (q.getPrefix() == UNDEF_PHRASE || prefix == "xmlns"))
1978           {
1979
1980             Str pfx = S.getProcessor() -> getNextNSPrefix();
1981             q.setPrefix(owner.unexpand(pfx));
1982           }
1983
1984         EQName ename;
1985         owner.expandQ(q, ename);
1986
1987         //output new namespace if needed
1988         if (a)
1989           {
1990             prefix = ename.getPrefix();
1991             proc -> outputter() -> eventNamespace(S, prefix, uristr);
1992           }
1993         
1994         E( proc -> outputter() -> eventAttributeStart(S, ename) );
1995         E( contents.execute(S, c, resolvingGlobals) );
1996         E( proc -> outputter() -> eventAttributeEnd(S) );
1997     }; break;
1998     case XSL_TEXT:
1999     {
2000         Attribute *disableEsc = atts.find(XSLA_DISABLE_OUTPUT_ESC);
2001         if (disableEsc && disableEsc -> cont == (const char*)"yes")
2002             E( proc -> outputter() -> eventDisableEscapingForNext(S) );
2003         E( contents.execute(S, c, resolvingGlobals) );
2004     }; break;
2005     case XSL_TEMPLATE:
2006       {
2007         proc -> vars -> startApplyOne();
2008         E( Daddy::execute(S, c, resolvingGlobals) );
2009         proc -> vars -> endApplyOne();
2010       }; break;
2011     case XSL_FALLBACK: //simply does nothing
2012       break;
2013     case XSL_STYLESHEET:
2014     case XSL_TRANSFORM:
2015     {
2016         GP( Context ) newc = c -> copy();
2017         
2018         Processor *proc = NZ(S.getProcessor());
2019         
2020         // process globals
2021         //_PH_ globals
2022         //E( getOwner().resolveGlobals(S, c, S.getProcessor()) );
2023         // process other top level elements
2024         for (int i = 0; i < contents.number(); i++)
2025         {
2026             Vertex *son = contents[i];
2027             if (isXSLElement(son) && (instrTable[toX(son) -> op].flags & ELEM_TOPLEVEL))
2028             {
2029                 switch(toX(son) -> op)
2030                 {
2031                 case XSL_TEMPLATE: 
2032                     break;
2033                     // global vars have been executed before
2034                 case XSL_VARIABLE:
2035                 case XSL_PARAM:
2036                   {
2037                     //_PH_ globals
2038                     QName temp;
2039                     temp.empty();
2040                     E( proc -> resolveGlobal(S, c, temp, toX(son)) );
2041                   }; break;
2042                 default: E( son -> execute(S, c, resolvingGlobals) );
2043                 }
2044             }
2045             //execute top-level extension elements as well
2046             if ( isExtension(son) ) {
2047               E( son -> execute(S, c, resolvingGlobals) );
2048             }
2049         }
2050
2051         proc -> vars -> startCall();
2052
2053         E( proc -> execute(S, (Vertex*) NULL, newc, resolvingGlobals ));
2054
2055         // newc has been deleted by now
2056         newc.keep();
2057         proc -> vars -> endCall();
2058
2059     }; break;
2060     case XSL_VALUE_OF:
2061     {
2062         a = NZ( atts.find(XSLA_SELECT) );
2063         Expression temp(*this);
2064         E( NZ( a -> expr ) -> eval(S, temp, c, resolvingGlobals) );
2065         // set output escaping
2066         Attribute *disableEsc = atts.find(XSLA_DISABLE_OUTPUT_ESC);
2067         if (disableEsc && disableEsc -> cont == (const char*)"yes")
2068             E( proc -> outputter() -> eventDisableEscapingForNext(S) );
2069         // dump contents
2070         Str cont;
2071         E( temp.tostring(S, cont) );
2072         E( proc -> outputter() -> eventData(S, cont) );
2073     };
2074     break;
2075     case XSL_COPY_OF:
2076     {
2077         a = NZ( atts.find(XSLA_SELECT) );
2078         Expression temp(*this);
2079         E( NZ( a -> expr ) -> eval(S, temp, c, resolvingGlobals) );
2080         if (temp.type == EX_NODESET)
2081         {
2082             const Context& ctxt = temp.tonodesetRef();
2083             int k, kLimit = ctxt.getSize();
2084
2085             for (k = 0; k < kLimit; k++)
2086                 // assuming here the context holds physical vertices
2087               //E( toPhysical(ctxt[k]) -> copy(S, *(proc -> outputter())) );
2088               E( S.dom().copyNode(S, ctxt[k], *(proc -> outputter())) );
2089         }
2090         else
2091         {
2092             Str cont;
2093             E( temp.tostring(S, cont) );
2094             E( proc -> outputter() -> eventData(S, cont) );
2095         }
2096     }; break;
2097     case XSL_COPY:
2098     {
2099       NodeHandle curr = c -> current();
2100       E( S.dom().startCopy(S, curr, *(proc -> outputter())) );
2101       //E( curr -> startCopy(S, *(proc -> outputter())) );
2102       //execute attribute sets
2103       E( executeAttributeSets(S, c, resolvingGlobals) );
2104       
2105       E( contents.execute(S, c, resolvingGlobals) );
2106       E( S.dom().endCopy(S, curr, *(proc -> outputter())) );
2107       //E( curr -> endCopy(S, *(proc -> outputter())) );
2108     }; break;
2109     case XSL_FOR_EACH:
2110     {
2111         a = NZ( atts.find(XSLA_SELECT) );
2112         GP( Context ) newc;
2113         newc.assign(c);
2114         E( NZ( a -> expr ) -> createContext(S, newc));
2115         newc.unkeep();
2116         if (!(*newc).isVoid() && contents.number())
2117         {
2118             // *** SORT HERE ***
2119             SortDefList sortDefs;
2120             makeSortDefs(S, sortDefs, c);
2121             if (sortDefs.number())
2122                 E( (*newc).sort(S, this, &sortDefs) );
2123             sortDefs.freeall(FALSE);
2124
2125             E( proc -> execute(S, contents, newc, resolvingGlobals) );
2126             // proc disposes of the new context
2127             newc.keep();
2128         }
2129 /*
2130   else
2131   newc.del();    // done automatically
2132 */
2133     };
2134     break;
2135     case XSL_CALL_TEMPLATE:
2136     {
2137         QName q;
2138         a = NZ( atts.find(XSLA_NAME) );
2139         XSLElement *thatrule;
2140         E( setLogical(S, q, a -> cont, FALSE) );
2141         if (!(thatrule = getOwner().findRuleByName(q))) 
2142           {
2143             Err1(S, E1_RULE_NOT_FOUND, (char*)getOwner().expand(q.getLocal()));
2144           }
2145
2146 //            proc -> vars -> rmPrebindings();
2147         //process with-param
2148         E( contents.execute(S, c, resolvingGlobals) );
2149         //execute the other rule
2150 //            proc -> vars -> startLevel();
2151         E( thatrule -> execute(S, c, resolvingGlobals) );
2152         proc -> vars -> rmPrebindings();
2153 //            proc -> vars -> endLevel();
2154     }; break;
2155     case XSL_MESSAGE:
2156     {
2157         DStr msg;
2158         GP( Expression ) expr = new Expression(*this);
2159         if (contents.isEmpty())
2160         {
2161           (*expr).setAtom((const char*)"");
2162         } 
2163         else 
2164         {
2165             proc -> vars -> startNested();
2166             TreeConstructer *newTC;
2167             E( proc -> pushTreeConstructer(S, newTC, (*expr).setFragment(), 
2168                                            SAXOUTPUT_INT_PHYSICAL) );
2169             E( contents.execute(S, c, resolvingGlobals) );
2170             E( proc -> outputter() -> eventEndOutput(S) );
2171             E( proc -> popTreeConstructer(S, newTC) );
2172             proc -> vars -> endNested();
2173         };
2174         GP( Expression ) temp = new Expression(*this);
2175         E( (*expr).eval(S, *temp,c, resolvingGlobals) );
2176         (*temp).pTree = (*expr).pTree;
2177         (*expr).pTree = NULL;
2178         a =  atts.find(XSLA_TERMINATE);
2179         Str tempStr;
2180         (*temp).tostring(S, tempStr); 
2181         if (a && a -> cont == (const char*) "yes")
2182         {
2183             Err1(S, E1_XSL_MESSAGE_TERM, tempStr);
2184         } 
2185         else 
2186         {
2187             Warn1(S, W1_XSL_MESSAGE_NOTERM, tempStr);
2188         };
2189 /*
2190   delete NZ(expr);     GP: automatic
2191   delete NZ(temp);
2192 */
2193     };
2194     break;
2195     // this is only executed for non-toplevel vars/params
2196     // (see case XSL_STYLESHEET)
2197     case XSL_VARIABLE:
2198     case XSL_WITH_PARAM:
2199     case XSL_PARAM:
2200     {
2201         QName q;
2202
2203         GP( Expression ) expr = NULL;
2204
2205         // there must be a 'name' attribute
2206         a = NZ(atts.find(XSLA_NAME));
2207         // stick the name into q referring to this element's namespace decl's
2208         E( setLogical(S, q, a -> cont, FALSE) );
2209
2210         // if there's a 'select', use the expression it gives
2211         a = atts.find(XSLA_SELECT);
2212         if (a)
2213           expr.assign(NZ(a -> expr));
2214
2215         // otherwise, construct a new expression; it may be an empty string
2216         // if this element has void content, or a result tree fragment otherwise 
2217         else
2218           {
2219             expr = new Expression(*this);
2220             if (contents.isEmpty())
2221                 (*expr).setAtom((const char*)"");
2222             else // result tree fragment
2223             {
2224                 // starting a nesting will make the current prebindings
2225                 // invisible
2226                 // don't do it if we are resolving globals
2227               
2228               proc -> pushInBinding(TRUE);
2229
2230               if (!resolvingGlobals)
2231                 proc -> vars -> startNested();
2232               TreeConstructer *newTC;
2233               E( proc -> pushTreeConstructer(S, newTC, (*expr).setFragment(),
2234                                              SAXOUTPUT_INT_PHYSICAL) );
2235               // execute the inside to create the fragment
2236               E( contents.execute(S, c, resolvingGlobals) );
2237               E( proc -> outputter() -> eventEndOutput(S) );
2238               E( proc -> popTreeConstructer(S, newTC) );
2239               
2240               // end the shadowing of preexisting bindings
2241               if (!resolvingGlobals)
2242                 proc -> vars -> endNested();
2243               
2244               proc -> popInBinding();
2245             };
2246         }
2247         //
2248         // evaluate the expression
2249         GP( Expression ) temp = new Expression(*this);  
2250         E( (*expr).eval(S, *temp, c, resolvingGlobals) );
2251         (*temp).pTree = (*expr).pTree;
2252         (*expr).pTree = NULL;
2253
2254         // expr is automatically deallocated if newly constructed
2255
2256         // add the new binding
2257         switch(op)
2258         {
2259         case XSL_PARAM:
2260         {
2261             E( proc -> vars -> addBinding(S, q, temp, FALSE) );
2262         }; break;
2263         case XSL_WITH_PARAM:
2264         {
2265             E( proc -> vars -> addPrebinding(S, q, temp) );
2266         }; break;
2267         case XSL_VARIABLE:
2268         {
2269             E( proc -> vars -> addBinding(S, q, temp, TRUE) );
2270         }; break;
2271         };
2272         temp.keep();    // deleted when removing the binding
2273     }; break;
2274     case XSL_KEY:
2275     {
2276         Attribute 
2277             *name = atts.find(XSLA_NAME),
2278             *match = atts.find(XSLA_MATCH),
2279             *use = atts.find(XSLA_USE);
2280         assert(name && match && use && match -> expr && use -> expr);
2281         EQName ename;
2282         QName q;
2283         E( setLogical(S, q, NZ(name) -> cont, FALSE) );
2284         getOwner().expandQ(q, ename);
2285         E( proc -> addKey(S, ename, *(match -> expr), *(use -> expr)) );
2286     }; break;
2287     case XSL_DECIMAL_FORMAT:
2288     {
2289         Attribute *name = atts.find(XSLA_NAME);
2290         QName q;
2291         if (name)
2292             E( setLogical(S, q, name -> cont, FALSE) );
2293         EQName ename;
2294         getOwner().expandQ(q, ename);
2295         DecimalFormat *decFormat;
2296         E( proc -> decimals().add(S, ename, decFormat) );
2297         for (int k = 0; k < atts.number(); k++)
2298         {
2299             if (toA(atts[k]) -> op != XSLA_NAME)
2300                 E( decFormat -> setItem(S, toA(atts[k]) -> op, toA(atts[k]) -> cont) );
2301         }
2302     }; break;
2303
2304 #define evalToStr(ATT, VAR) \
2305 { if (NULL != (e = getAttExpr(ATT)))\
2306     { E( e -> eval(S, evaluated, c, resolvingGlobals) );\
2307       E( evaluated.tostring(S, VAR) ); }}
2308
2309     case XSL_NUMBER:
2310     {
2311         // auxiliary functions are in numbering.h
2312         ListInt theList;
2313         Str theString;
2314         // find @value
2315         Expression *e = getAttExpr(XSLA_VALUE),
2316             evaluated(*this, EXF_ATOM);
2317         if (e)
2318         {
2319             E( e -> eval(S, evaluated, c, resolvingGlobals) );
2320             theList.append(evaluated.tonumber(S).round());
2321         }
2322         else
2323         {
2324             NumberingLevel level = NUM_SINGLE;
2325             Attribute *a;
2326             if (NULL != (a = atts.find(XSLA_LEVEL)))
2327             {
2328                 if (a -> cont == "multiple")
2329                     level = NUM_MULTIPLE;
2330                 else if (a -> cont == "any")
2331                     level = NUM_ANY;
2332                 else if (!(a -> cont == "single"))
2333                     Err1(S, E1_NUMBER_LEVEL, a -> cont);
2334             }
2335             E( xslNumberCount(S, level, 
2336                               getAttExpr(XSLA_COUNT),
2337                               getAttExpr(XSLA_FROM),
2338                               v, theList) );
2339         }
2340         Str format = "1",
2341             lang,
2342             letterValueStr,
2343             groupingSep;
2344         int groupingSize = 0;
2345
2346         evalToStr(XSLA_FORMAT, format);  // defined above case XSL_NUMBER
2347         evalToStr(XSLA_LANG, lang);
2348
2349         // get @letter-value
2350         NumberingLetterValue letterValue = NUM_ALPHABETIC;
2351         if (NULL != (e = getAttExpr(XSLA_LETTER_VALUE)))
2352         {
2353             E( e -> eval(S, evaluated, c, resolvingGlobals) );
2354             E( evaluated.tostring(S, letterValueStr) );
2355             if (letterValueStr == "traditional")
2356                 letterValue = NUM_TRADITIONAL;
2357             else if (!(letterValueStr == "alphabetic"))
2358                 Err1(S, E1_NUMBER_LETTER_VALUE, letterValueStr);
2359         }
2360
2361         // get @grouping-size
2362         if (NULL != (e = getAttExpr(XSLA_GROUPING_SIZE)))
2363         {
2364             E( e -> eval(S, evaluated, c, resolvingGlobals) );
2365             groupingSize = evaluated.tonumber(S).round();
2366         }
2367
2368         // get @grouping-separator
2369         Expression *eSep;
2370         if (NULL != (eSep = getAttExpr(XSLA_GROUPING_SEPARATOR)))
2371         {
2372             E( eSep -> eval(S, evaluated, c, resolvingGlobals) );
2373             E( evaluated.tostring(S, groupingSep) );
2374         }
2375
2376         if (e || eSep)
2377         {
2378             if (!e || !eSep || groupingSize <= 0 || utf8StrLength(groupingSep) != 1)
2379             {
2380                 Warn(S, W_NUMBER_GROUPING);
2381                 groupingSize = 0;
2382                 groupingSep.empty();
2383             }
2384         }
2385
2386         E( xslNumberFormat(S, theList, format, 
2387                            lang, letterValue, groupingSep, groupingSize, theString) );
2388         
2389         E( proc -> outputter() -> eventData(S, theString) );
2390     }; break;
2391     case XSL_OUTPUT:
2392     case XSL_NAMESPACE_ALIAS:
2393       // these were processed during parse
2394         break;
2395     case XSL_SORT:
2396       // processed by parent
2397         break;
2398     case XSL_ATTRIBUTE_SET:
2399       //processed during parse
2400       break;
2401     // unsupported instructions that are not considered harmful
2402     case XSL_STRIP_SPACE:
2403     case XSL_PRESERVE_SPACE:
2404       //processed during parse
2405       //Warn1(S, W1_UNSUPP_XSL, xslOpNames[op]);
2406         break;
2407     default: 
2408         Err1(S, E1_UNSUPP_XSL, xslOpNames[op]);
2409     };
2410
2411     //remove the variable bindings that occured inside this element
2412     if ((op != XSL_TEMPLATE) && (op != XSL_TRANSFORM) && (op != XSL_STYLESHEET) && 
2413         (op != XSL_FOR_EACH) && !didNotExecute)
2414         removeBindings(S);
2415     return OK;
2416 }
2417
2418 Expression* XSLElement::getAttExpr(XSL_ATT code)
2419 {
2420     Attribute *a = atts.find(code);
2421     return a ? (a -> expr) : NULL;
2422 }
2423
2424 int XSLElement::strip()
2425 {
2426     if (op != XSL_TEXT && !preserveSpace)
2427         return /* defs.strip() + */ contents.strip();
2428     else return 0;
2429 }
2430
2431 /*................................................................
2432 findAttNdx()
2433     returns the index of given attribute in the attribute table
2434     or -1 if not found
2435 ................................................................*/
2436
2437 int findAttNdx(InstrTableItem &iitem, Attribute *a)
2438 {
2439     for (int i = 0; i < iitem.maxAtts; i++)
2440         if (iitem.att[i].attCode == a -> op) return i;
2441     return -1;
2442 }
2443
2444 /*================================================================
2445 checkAtts
2446     called when all attributes have been parsed in. Returns FALSE
2447     iff they are OK. Return value of TRUE means that the end tag handler
2448     signals error.
2449 ================================================================*/
2450
2451 eFlag XSLElement::checkAtts(Sit S)
2452 {
2453     InstrTableItem &instrData = instrTable[op];
2454     assert(instrData.op == op);
2455     int
2456         attNdx,
2457         reqCount = 0;
2458     Attribute *a;
2459     for (int i = 0; i < atts.number(); i++)
2460     {
2461         // need to use a temporary variable
2462         // to get around Solaris template problem
2463         Vertex * pTemp = atts[i];
2464         a = cast(Attribute*, pTemp);
2465         if (((attNdx = findAttNdx(instrData,a)) == -1) && 
2466             a -> name.getUri() == UNDEF_PHRASE)
2467             // FIXME: issue a warning when ignoring an att??
2468             {
2469                 Str fullName;
2470                     owner.expandQStr(a -> name, fullName);
2471             Err1(S, ET_BAD_ATTR, fullName);
2472             }
2473         if (instrData.att[attNdx].required)
2474             reqCount++;
2475         if (instrData.att[attNdx].exprType != EX_NONE)
2476           {
2477             E( a -> buildExpr(S,
2478                               instrData.att[attNdx].avtemplate,
2479                               instrData.att[attNdx].exprType) );
2480             if (op == XSL_TEMPLATE && a->op == XSLA_MATCH)
2481               {
2482                 //must not contain variable ref
2483                 if (a->expr && a->expr->containsFunctor(EXF_VAR))
2484                   Err(S, E_VAR_IN_MATCH);
2485               }
2486           }
2487     };
2488     if (reqCount < instrData.reqAtts)
2489         Err(S, ET_REQ_ATTR);
2490     return OK;
2491 };
2492
2493 //................................................................
2494
2495 void XSLElement::checkExtraChildren(int& k)
2496 {
2497     Vertex *w;
2498     XSL_OP hisop;
2499     int status = 0;
2500     for (k = 0; k < contents.number(); k++)
2501     {
2502         w = contents[k];
2503         if (!isXSLElement(w)) return;
2504         hisop = toX(w) -> op;
2505         switch(op)
2506         {
2507         case XSL_APPLY_TEMPLATES:
2508             if ((hisop != XSL_SORT) && (hisop != XSL_WITH_PARAM)) return;
2509             break;
2510         case XSL_ATTRIBUTE_SET:
2511             if (hisop != XSL_ATTRIBUTE) return;
2512             break;
2513         case XSL_CALL_TEMPLATE:
2514             if (hisop != XSL_WITH_PARAM) return;
2515             break;
2516         case XSL_CHOOSE:
2517             switch(hisop)
2518             {
2519             case XSL_WHEN:
2520                 {
2521                     if (status <= 1) status = 1;
2522                     else return;
2523                 }; break;
2524             case XSL_OTHERWISE:
2525                 {
2526                     if (status == 1) status = 2;
2527                     else return;
2528                 }; break;
2529             default: return;
2530             }; 
2531             break;
2532         case XSL_FOR_EACH:
2533             if (hisop != XSL_SORT) return;
2534             break;
2535         case XSL_STYLESHEET:
2536         case XSL_TRANSFORM:
2537             if (hisop != XSL_WITH_PARAM) return;
2538             break;
2539         case XSL_TEMPLATE:
2540             if (hisop != XSL_PARAM) return;
2541             break;
2542         default: 
2543             return;
2544         }
2545     }
2546 }
2547
2548 eFlag XSLElement::checkToplevel(Sit S)
2549 {
2550   //if we're nested in top level foreign node, all is ok
2551   if (vt & VT_TOP_FOREIGN) return OK;
2552
2553   if (!(instrTable[op].flags & ELEM_INSTR) && 
2554       !(instrTable[op].flags & ELEM_EXTRA) &&
2555       (!isXSL(parent) || 
2556        !(instrTable[toX(parent) -> op].flags & ELEM_CONT_TOPLEVEL)))
2557     Err1(S, E1_ELEM_TOPLEVEL, xslOpNames[op]);
2558   return OK;
2559 }
2560
2561 eFlag XSLElement::checkChildren(Sit S)
2562 {
2563     InstrTableItem &iData = instrTable[op];
2564     assert(iData.op == op);
2565
2566     if (!(iData.flags & ELEM_CONT) && contents.number())
2567         Err1(S, E_ELEM_MUST_EMPTY, xslOpNames[op]);
2568
2569     int firstAfter = 0;
2570     if (iData.flags & ELEM_CONT_EXTRA)
2571         checkExtraChildren(firstAfter);
2572
2573     for (int k = firstAfter; k < contents.number(); k++)
2574     {
2575         Vertex *w = contents[k];
2576
2577         if (isElement(w) && (toE(w)->getName().getPrefix() != UNDEF_PHRASE) &&
2578             (iData.flags & ELEM_CONT_EXTENSION))
2579           {
2580             continue;
2581           }
2582
2583         if (isElement(w) && (iData.flags & ELEM_CONT_PCDATA)) {
2584           Err1(S, E_ELEM_MUST_BE_PCDATA, xslOpNames[op]);
2585         }
2586
2587         if (isText(w) || (isElement(w) && !isXSLElement(w)))
2588         {
2589             if (!(iData.flags & (ELEM_CONT_INSTR | ELEM_CONT_PCDATA)))
2590                 Err1(S, E_ELEM_CONT_TEXT_OR_LRE, xslOpNames[op]);
2591         }
2592         else
2593         {
2594             if (isXSLElement(w))
2595             {
2596                 int hisflags = instrTable[toX(w) -> op].flags;
2597                 if (!(((hisflags & ELEM_TOPLEVEL) && (iData.flags & ELEM_CONT_TOPLEVEL)) ||
2598                     ((hisflags & ELEM_INSTR) && (iData.flags & ELEM_CONT_INSTR))))
2599                     Err2(S, E_ELEM_CONTAINS_ELEM, xslOpNames[op], xslOpNames[toX(w) -> op]);
2600             }
2601             else
2602                 Err1(S, E_BAD_ELEM_CONTENT, xslOpNames[op]);
2603         }
2604     };
2605
2606     return OK;
2607 }
2608
2609 eFlag XSLElement::make1SortDef(Sit S, SortDef *&def, Context *c)
2610 {
2611     DStr temp;
2612
2613     assert(op == XSL_SORT);
2614     def = NULL;
2615     GP( SortDef ) newDef = new SortDef;
2616     
2617     Attribute *a = atts.find(XSLA_SELECT);
2618     if (a)
2619         (*newDef).sortExpr = a -> expr;
2620
2621     a = atts.find(XSLA_LANG);
2622     if (a)
2623     {
2624         E( a -> value(S, temp, c));
2625         (*newDef).lang = temp;
2626     }
2627     else
2628     {
2629         // lang is system-dependent!!! How about setting ""?
2630         (*newDef).lang = "en";
2631     };
2632
2633     a = atts.find(XSLA_DATA_TYPE);
2634     if (a)
2635     {
2636         E( a -> value(S, temp, c) );
2637         if (temp == (const char*) "number")
2638             (*newDef).asText = FALSE;
2639         else
2640             if (!(temp == (const char*) "text"))
2641                 Warn1(S, W1_SORT_DATA_TYPE, temp);
2642     }
2643
2644     a = atts.find(XSLA_ORDER);
2645     if (a)
2646     {
2647         E( a -> value(S, temp, c) );
2648         if (temp == (const char*) "descending")
2649             (*newDef).ascend = FALSE;
2650         else if (!(temp == (const char*) "ascending"))
2651             Warn1(S, W1_SORT_ORDER, temp);
2652     }
2653     
2654     a = atts.find(XSLA_CASE_ORDER);
2655     if (a)
2656     {
2657         E( a -> value(S, temp, c) );
2658         if (temp == (const char*) "lower-first")
2659             (*newDef).upper1st = FALSE;
2660         else 
2661         {
2662             if (!(temp == (const char*) "upper-first"))
2663                 Warn1(S, W1_SORT_CASE_ORDER, temp);
2664             // get upper1st as system default!!
2665             (*newDef).upper1st = TRUE;
2666         }
2667     }
2668     def = newDef.keep();
2669     return OK;
2670 }
2671
2672 eFlag XSLElement::makeSortDefs(Sit S, SortDefList &sortDefs, Context *c)
2673 {
2674     assert(op == XSL_APPLY_TEMPLATES || op == XSL_FOR_EACH);
2675
2676     Vertex *child;
2677     for (int i = 0; i < contents.number(); i++)
2678     {
2679         child = contents[i];
2680         if (!isXSLElement(child)) break;
2681         if (toX(child) -> op == XSL_SORT)
2682         {
2683             // *** make the single sort def
2684             SortDef *newDef;
2685             E( toX(child) -> make1SortDef(S, newDef, c) );
2686             sortDefs.append(newDef);
2687 #           if !defined(SAB_WCS_COLLATE)
2688             // warn that string sorting may be incorrect - 
2689             // sorting as ascii
2690             if (newDef -> asText)
2691                 Warn(S, W_NO_WCSXFRM);
2692 #           endif
2693
2694         }
2695         else if (toX(child) -> op != XSL_WITH_PARAM) break;
2696     };
2697     return OK;
2698 }
2699
2700 /****************************************
2701 ExtensionElement
2702 ****************************************/
2703 const char* extNSUri[] = {
2704   "http://exslt.org/functions",
2705   "http://www.exslt.org/functions",
2706   "http://exslt.org/common",
2707   NULL
2708 };
2709
2710 const char* exsltElementsFunctions[] = {
2711   "script", 
2712   NULL
2713 };
2714
2715 const char* exsltElementsCommon[] = {
2716   "document", 
2717   NULL
2718 };
2719
2720 ExtensionElement::ExtensionElement(Tree& owner_, QName& aqname)
2721 :
2722 Element(owner_, aqname, VT_EXT_ELEMENT_WF)
2723 {
2724   extns = EXTNS_UNKNOWN;
2725   op = EXTE_UNKNOWN;
2726   lookupExt(owner, aqname, extns, op);
2727 };
2728
2729 #ifdef ENABLE_JS
2730 eFlag ExtensionElement::executeEXSLTScript(Sit S, Context *c, 
2731                                            Bool resolvingGlobals)
2732 {
2733 #ifdef SABLOT_DEBUGGER
2734   if (debugger) E( debugger -> breakOnElement(S, this, c) );
2735 #endif
2736
2737   QName attName;
2738   //why no uri?????
2739   //attName.setUri(getName().getUri());
2740   attName.setLocal(owner.unexpand("language"));
2741   Attribute *a = NZ( atts.find(attName) );
2742   
2743   QName lang;
2744   E( setLogical(S, lang, a -> cont, false) );
2745   //debug
2746   EQName elang;
2747   getOwner().expandQ(lang, elang);
2748   //debug - end
2749   if (lang.getUri() == UNDEF_PHRASE || elang.getUri() == extNSUri[0])
2750     {
2751       if (! (elang.getLocal() == (const char*)"javascript") &&
2752           ! (elang.getLocal() == (const char*)"ecmascript"))
2753         return OK;
2754     }
2755   else
2756     return OK;
2757   
2758
2759   //if (!(a -> cont == (const char*) "javascript") && 
2760   //    !(a -> cont == (const char*) "ecmascript"))
2761   //  return OK;
2762   
2763   //implements-prefix
2764   attName.setLocal(owner.unexpand("implements-prefix"));
2765   a = NZ( atts.find(attName) );
2766   
2767   Phrase uri = owner.unexpand(a -> cont);
2768   E( namespaces.resolve(S, uri, TRUE) );
2769   Str suri = owner.expand(uri);
2770   //check uri validity!!!
2771   
2772   //script
2773   DStr script;
2774   
2775   attName.setLocal(owner.unexpand("src"));
2776   a = atts.find(attName);
2777   if (a)
2778     {
2779       DataLine src;
2780       StrStrList &args = S.getProcessor() -> getArgList();
2781       
2782       const Str &base = S.findBaseURI(getSubtreeInfo() -> getBaseURI());
2783       Str absolute;
2784       makeAbsoluteURI(S, a -> cont, base, absolute);
2785       
2786       eFlag status = src.open(S, absolute, DLMODE_READ,  &args);
2787       
2788       if (status == OK)
2789         {
2790           char buff[1024];
2791           int read;
2792           while ((read = src.get(S, buff, 1024)))
2793             {
2794               script.nadd(buff, read);
2795             }
2796         }
2797       else
2798         {
2799           E( status );
2800         }
2801       E( src.close(S) );
2802     }
2803   else
2804     {
2805       for (int i = 0; i < contents.number(); i++) 
2806         {
2807           Vertex *v = contents[i];
2808           if ( isText(v) ) 
2809             {
2810               script = script + toText(v) -> cont;
2811             }
2812         }
2813     }
2814   E( NZ( S.getProcessor() ) -> evaluateJavaScript(S, suri, script) );
2815   return OK;
2816 }
2817 #endif
2818
2819 const char* _exsltDocAtts[] = {
2820   "version", 
2821   "encoding",
2822   "omit-xml-declaration",
2823   "standalone",
2824   "doctype-public",
2825   "doctype-system",
2826   "indent",
2827   "media-type",
2828   NULL
2829 };
2830
2831 XSL_ATT _exsltDocMapping[] = {
2832   XSLA_VERSION,
2833   XSLA_ENCODING,
2834   XSLA_OMIT_XML_DECL,
2835   XSLA_STANDALONE,
2836   XSLA_DOCTYPE_PUBLIC,
2837   XSLA_DOCTYPE_SYSTEM,
2838   XSLA_INDENT,
2839   XSLA_MEDIA_TYPE,
2840   XSLA_NONE
2841 };
2842
2843 XSL_ATT _lookupEXSLTDocumentAttr(const char* name)
2844 {
2845   int idx = lookup(name, _exsltDocAtts);
2846   return _exsltDocMapping[idx];
2847 }
2848
2849 eFlag ExtensionElement::exsltDocGetOutputterDef(Sit S, Context *c,
2850                                                 OutputDefinition &def)
2851 {
2852   int i, attsNumber = atts.number();
2853   Attribute *theAtt;
2854   for (i = 0; i < attsNumber; i++)
2855     {
2856       theAtt = toA(atts[i]);
2857       Str attName = getOwner().expand(theAtt -> getName().getLocal());
2858       Str attUri = getOwner().expand(theAtt -> getName().getUri());
2859
2860       //skip xslt attributes
2861       if ( attUri == theXSLTNamespace )
2862         continue;
2863
2864       if (attName == (const char*) "method")
2865         {
2866           QName q;
2867           EQName eq;
2868           DStr val;
2869           theAtt -> value(S, val, c);
2870           E( setLogical(S, q, val, FALSE) );
2871           getOwner().expandQ(q, eq);
2872           E( def.setItemEQName(S, XSLA_METHOD, eq, theAtt, 0) );
2873         }
2874       else if (attName == (const char*) "cdata-section-elements")
2875         {
2876           QName q;
2877           Bool someRemains;
2878           Str listPart;
2879           DStr val;
2880           theAtt -> value(S, val, c);
2881           char *p = (char*)val;
2882           do
2883             {
2884               someRemains = getWhDelimString(p, listPart);
2885               if (someRemains)
2886                 {
2887                   E( setLogical(S, q, listPart, TRUE) );
2888                   EQName expanded;
2889                   getOwner().expandQ(q, expanded);
2890                   E( def.setItemEQName(S, XSLA_CDATA_SECT_ELEMS,
2891                                        expanded, theAtt, 0) );
2892                 };
2893             }
2894           while (someRemains);
2895         }
2896       else if ( !(attName == (const char*) "href") )
2897         {
2898           DStr val;
2899           theAtt -> value(S, val, c);
2900           XSL_ATT attType = _lookupEXSLTDocumentAttr(attName);
2901           if (attType == XSLA_NONE)
2902             Err1(S, ET_BAD_ATTR, (char*)attName);
2903           E( def.setItemStr(S, attType, val, theAtt, 0) );
2904           
2905         };
2906     };
2907   return OK;
2908 }
2909
2910 eFlag ExtensionElement::executeEXSLTDocument(Sit S, Context *c, 
2911                                              Bool resolvingGlobals)
2912 {
2913   Processor *proc = NZ( S.getProcessor() );
2914
2915   //get output uri
2916   QName attName;
2917   attName.setLocal(owner.unexpand("href"));
2918   Attribute *a = NZ( atts.find(attName) );
2919   
2920   DStr href;
2921   E( a -> value(S, href, c) );
2922
2923   GP(OutputDefinition) def = new OutputDefinition();
2924   E( exsltDocGetOutputterDef(S, c, *def) );
2925
2926   OutputDocument *doc;
2927   E( proc -> createOutputDocument(S, href, doc, def.keep()) );
2928   //we do not need to keep the definition, since document
2929   //initialized the outputter with it (I hope)
2930   
2931   Bool handleOutputter = !proc -> isInBinding();
2932   
2933   if (handleOutputter)
2934     {
2935       S.message(MT_LOG, L2_SUBDOC_STARTED, href, "output");
2936       E( proc -> startDocument(S, doc) );
2937     }
2938   else
2939     {
2940       S.message(MT_LOG, L2_SUBDOC_STARTED, href, "variable");
2941       E( proc -> outputter() -> setDocumentForLevel(S, doc) );
2942     }
2943
2944   E( contents.execute(S, c, resolvingGlobals) );
2945
2946   if (handleOutputter)
2947     {
2948       E( proc -> finishDocument(S, doc, TRUE) );
2949     }
2950
2951   return OK;
2952 }
2953
2954 eFlag ExtensionElement::execute(Sit S, Context *c, Bool resolvingGlobals) 
2955 {
2956   switch (op) {
2957   case EXTE_EXSLT_SCRIPT:
2958 #ifdef ENABLE_JS
2959     E( executeEXSLTScript(S, c, resolvingGlobals) );
2960 #else
2961     assert(!"JSExtension not build");
2962 #endif
2963     break;
2964   case EXTE_EXSLT_DOCUMENT:
2965     E( executeEXSLTDocument(S, c, resolvingGlobals) );
2966     break;
2967   case EXTE_UNKNOWN:
2968     {
2969       //do fallback
2970       Bool hasSome = FALSE;
2971       executeFallback(S, c, hasSome, resolvingGlobals);
2972       if (! hasSome) 
2973         {
2974           Str name = owner.expand(getName().getPrefix());
2975           name = name + ":";
2976           name = name + owner.expand(getName().getLocal());
2977           Err1(S, E_UNSUPPORTED_EXELEMENT, (char*)name);
2978         }
2979     }; break;
2980   default:
2981     {};
2982   }
2983   return OK;
2984 }
2985
2986 eFlag ExtensionElement::checkChildren(Sit S) 
2987 {
2988   switch (op) {
2989   case EXTNS_EXSLT_FUNCTIONS:
2990   case EXTNS_EXSLT_FUNCTIONS_2:
2991     {
2992       int num = contents.number();
2993       for (int i = 0; i < num; i++) 
2994         {
2995           Vertex *v = contents[i];
2996           if (!isText(v) && 
2997               (! isXSLElement(v) || !(toX(v) -> op == XSL_FALLBACK)) )
2998           {
2999             Err(S, E_BAD_ELEM_CONTENT);
3000           }
3001         }
3002     }; break;
3003   }
3004
3005   return OK;
3006 }
3007
3008 eFlag ExtensionElement::checkHasAttr(Sit S, const char *name)
3009 {
3010   QName attName;
3011   attName.setLocal(owner.unexpand(name));
3012   Attribute *a = atts.find(attName);    
3013   if (!a) Err1(S, E_ATTR_MISSING, name);
3014   return OK;
3015 }
3016
3017 eFlag ExtensionElement::checkAtts(Sit S) 
3018 {
3019   switch (op) {
3020   case EXTE_EXSLT_SCRIPT:
3021     {
3022       E( checkHasAttr(S, "implements-prefix") );
3023       E( checkHasAttr(S, "language") );
3024     }; break;
3025   case EXTE_EXSLT_DOCUMENT:
3026     {
3027       E( checkHasAttr(S, "href") );
3028       //all attributes are value templates
3029       int num = atts.number();
3030       for (int i = 0; i < num; i++)
3031         E( toA(atts[i]) -> buildExpr(S, TRUE, EX_NONE) );
3032     }; break;
3033   }
3034   return OK;
3035 }
3036
3037 void ExtensionElement::lookupExt(Tree &tree, QName &name,
3038                                  ExtNamespace &extns_, ExtElement &op_) 
3039 {
3040   Str myns = tree.expand(name.getUri());
3041   Str mylocal = tree.expand(name.getLocal());
3042   extns_ = (ExtNamespace) lookup(myns, extNSUri);
3043   switch (extns_) {
3044   case EXTNS_EXSLT_FUNCTIONS:
3045   case EXTNS_EXSLT_FUNCTIONS_2:
3046     {
3047       int i = lookup(mylocal, exsltElementsFunctions);
3048       if ( exsltElementsFunctions[i] ) {
3049         op_ = (ExtElement) (i + (int)EXTE_EXSLT_FUNCTIONS);
3050       } else {
3051         op_ = EXTE_UNKNOWN;
3052       }
3053     }; break;
3054   case EXTNS_EXSLT_COMMON:
3055     {
3056       int i = lookup(mylocal, exsltElementsCommon);
3057       if ( exsltElementsCommon[i] ) {
3058         op_ = (ExtElement) (i + (int)EXTE_EXSLT_COMMON);
3059       } else {
3060         op_ = EXTE_UNKNOWN;
3061       }
3062     }; break;
3063   default:
3064     {
3065       op_ = EXTE_UNKNOWN;
3066     }
3067   }
3068   //now we have to check, whether the element is really supported
3069 #ifndef ENABLE_JS
3070   if (op_ == EXTE_EXSLT_SCRIPT) op_ = EXTE_UNKNOWN;
3071 #endif
3072 }
3073
3074 Bool ExtensionElement::elementAvailable(Tree &t, QName &name) 
3075 {
3076   ExtNamespace ns;
3077   ExtElement op;
3078   lookupExt(t, name, ns, op);
3079 #ifndef ENABLE_JS
3080   if (op == EXTE_EXSLT_SCRIPT) op = EXTE_UNKNOWN;
3081 #endif
3082   return op != EXTE_UNKNOWN;
3083 }