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_T0,    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 
~Vertex()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 
execute(Sit S,Context * c,Bool resolvingGlobals)350 eFlag Vertex::execute(Sit S, Context *c, Bool resolvingGlobals)
351 {
352     sabassert(FALSE);
353     return NOT_OK;
354 }
355 
value(Sit S,DStr & ret,Context * c)356 eFlag Vertex::value(Sit S, DStr& ret, Context *c)
357 {
358     sabassert(0);
359     return NOT_OK;
360 }
361 
startCopy(Sit S,OutputterObj & out)362 eFlag Vertex::startCopy(Sit S, OutputterObj& out)
363 {
364     return OK;
365 };
366 
endCopy(Sit S,OutputterObj & out)367 eFlag Vertex::endCopy(Sit S, OutputterObj& out)
368 {
369     return OK;
370 };
371 
copy(Sit S,OutputterObj & out)372 eFlag Vertex::copy(Sit S, OutputterObj& out)
373 {
374   S.setCurrSAXLine(lineno); //for SAX copying - be careful
375 
376   OutputterObj *aux;
377   E( startDocument(S, aux) );
378 
379   OutputterObj &useOut = aux ? *aux : out;
380   E( startCopy(S, useOut) );
381   E( endCopy(S, useOut) );
382 
383   E( finishDocument(S) );
384 
385   return OK;
386 }
387 
speak(DStr & ret,SpeakMode mode)388 void Vertex::speak(DStr &ret, SpeakMode mode)
389 {
390 }
391 
setParent(Vertex * v)392 void Vertex::setParent(Vertex *v)
393 {
394     parent = v;
395 }
396 
getPreviousSibling()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 
getNextSibling()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 
getName() const415 const QName& Vertex::getName() const
416 {
417     return owner.getTheEmptyQName();
418 }
419 
getOwner() const420 Tree& Vertex::getOwner() const
421 {
422     return owner;
423 }
424 
report(Sit S,MsgType type,MsgCode code,const Str & arg1,const Str & arg2) const425 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 
dict() const432 HashTable& Vertex::dict() const
433 {
434     return getOwner().dict();
435 }
436 
serialize(Sit S,OutputterObj & out)437 eFlag Vertex::serialize(Sit S, OutputterObj &out)
438 {
439     return OK;
440 }
441 
makeStamps(int & stamp_)442 void Vertex::makeStamps(int& stamp_)
443 {
444     stamp = stamp_++;
445 }
446 
getMatchingList(Sit S,Expression & match,Context & result)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 
getImportPrecedence()458 int Vertex::getImportPrecedence()
459 {
460     return NZ( getSubtreeInfo() ) -> getStructure() -> getImportPrecedence();
461 }
462 
startDocument(Sit S,OutputterObj * & out)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 
finishDocument(Sit S)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 
VertexList(int logBlockSize_)490 VertexList::VertexList(int logBlockSize_ /*=LIST_SIZE_SMALL*/)
491   : SList<Vertex*>(logBlockSize_)
492 {
493 }
494 
~VertexList()495 VertexList::~VertexList()
496 {
497     deppendall();
498 }
499 
destructMembers()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 
execute(Sit S,Context * c,Bool resolvingGlobals)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 
value(Sit S,DStr & ret,Context * c)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 
speak(DStr & ret,SpeakMode mode)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 
append(Vertex * v)546 void VertexList::append(Vertex *v)
547 {
548     v -> ordinal = number();
549     List<Vertex*>::append(v);
550 }
551 
strip()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 
copy(Sit S,OutputterObj & out)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 
insertBefore(Vertex * newChild,int refIndex)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 
rm(int ndx)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 
getIndex(Vertex * v)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 
serialize(Sit S,OutputterObj & out)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 
makeStamps(int & stamp_)605 void VertexList::makeStamps(int& stamp_)
606 {
607     for (int i = 0; i < number(); i++)
608         (*this)[i] -> makeStamps(stamp_);
609 }
610 
getMatchingList(Sit S,Expression & match,Context & result)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 
Daddy(Tree & owner_,VTYPE avt)623 Daddy::Daddy(Tree& owner_, VTYPE avt /* = VT_DADDY_WF */)
624 : Vertex(owner_, avt), contents(&(owner_.getArena()))
625 {
626 };
627 
628 
~Daddy()629 Daddy::~Daddy()
630 {
631     // not doing freeall since it's all in the arena
632     // contents.freeall(FALSE);
633     contents.destructMembers();
634 };
635 
execute(Sit S,Context * c,Bool resolvingGlobals)636 eFlag Daddy::execute(Sit S, Context *c, Bool resolvingGlobals)
637 {
638     E( contents.execute(S, c, resolvingGlobals) );
639     return OK;
640 };
641 
value(Sit S,DStr & ret,Context * c)642 eFlag Daddy::value(Sit S, DStr &ret, Context *c)
643 {
644     E( contents.value(S, ret, c) );
645     return OK;
646 }
647 
checkChildren(Sit S)648 eFlag Daddy::checkChildren(Sit S)
649 {
650     sabassert(!"Daddy::checkChildren()");
651     return NOT_OK;
652 }
653 
newChild(Sit S,Vertex * v)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 
speak(DStr & ret,SpeakMode mode)662 void Daddy::speak(DStr &ret, SpeakMode mode)
663 {
664     if (mode & SM_CONTENTS)
665         contents.speak(ret, mode);
666 }
667 
strip()668 int Daddy::strip()
669 {
670     return contents.strip();
671 }
672 
getMatchingList(Sit S,Expression & match,Context & result)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 
~RootNode()687 RootNode::~RootNode()
688 {
689 }
690 
execute(Sit S,Context * c,Bool resolvingGlobals)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 
checkChildren(Sit S)699 eFlag RootNode::checkChildren(Sit S)
700 {
701     return OK;
702 }
703 
newChild(Sit S,Vertex * v)704 eFlag RootNode::newChild(Sit S, Vertex *v)
705 {
706     //! insert prolog
707     //
708     E( Daddy::newChild(S, v) );
709     return OK;
710 };
711 
speak(DStr & s,SpeakMode mode)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 
startCopy(Sit S,OutputterObj & out)720 eFlag RootNode::startCopy(Sit S, OutputterObj& out)
721 {
722     return Vertex::startCopy(S, out);
723 };
724 
endCopy(Sit S,OutputterObj & out)725 eFlag RootNode::endCopy(Sit S, OutputterObj& out)
726 {
727     return Vertex::endCopy(S, out);
728 };
729 
copy(Sit S,OutputterObj & out)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 
serialize(Sit S,OutputterObj & out)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 
Element(Tree & owner_,QName & aqname,VTYPE avt)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 
~Element()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 
strip()782 int Element::strip()
783 {
784   if (!preserveSpace)
785     return contents.strip();
786   else
787     return 0;
788 }
789 
execute(Sit S,Context * c,Bool resolvingGlobals)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 
executeFallback(Sit S,Context * c,Bool & hasSome,Bool resolvingGlobals)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 
newChild(Sit S,Vertex * v)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 
speak(DStr & ret,SpeakMode mode)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 
removeBindings(Sit S)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 
startCopy(Sit S,OutputterObj & out)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 
endCopy(Sit S,OutputterObj & out)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 
copy(Sit S,OutputterObj & out)936 eFlag Element::copy(Sit S, OutputterObj& out)
937 {
938   OutputterObj *aux;
939   E( 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   E( finishDocument(S) );
950 
951   return OK;
952 };
953 
getName() const954 const QName& Element::getName() const
955 {
956     return name;
957 }
958 
setLogical(Sit S,QName & qn,const Str & string,Bool defaultToo,Phrase defUri) const959 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 
serialize(Sit S,OutputterObj & out)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 
serializeSubtree(Sit S,OutputterObj & out)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( namespaces.serialize(S, out) );
1021     E( atts.serialize(S, out) );
1022     E( contents.serialize(S, out) );
1023     E( out.eventElementEnd(S, ename) );
1024 
1025     E( out.eventEndOutput(S) );
1026     return OK;
1027 }
1028 
removeChild(Vertex * child)1029 void Element::removeChild(Vertex *child)
1030 {
1031     sabassert(child -> parent == this);
1032     contents.rm(child -> ordinal);
1033     child -> setParent(NULL);
1034 }
1035 
makeStamps(int & stamp_)1036 void Element::makeStamps(int& stamp_)
1037 {
1038     Vertex::makeStamps(stamp_);
1039     namespaces.makeStamps(stamp_);
1040     atts.makeStamps(stamp_);
1041     contents.makeStamps(stamp_);
1042 }
1043 
getMatchingList(Sit S,Expression & match,Context & result)1044 eFlag Element::getMatchingList(Sit S, Expression& match, Context& result)
1045 {
1046     E( Vertex::getMatchingList(S, match, result) );
1047     E( namespaces.getMatchingList(S, match, result) );
1048     E( atts.getMatchingList(S, match, result) );
1049     E( contents.getMatchingList(S, match, result) );
1050 	return OK;
1051 }
1052 
attSetNames(Bool canCreate)1053 QNameList* Element::attSetNames(Bool canCreate) {
1054   if (!attsNames && canCreate) attsNames = new QNameList;
1055   return attsNames;
1056 }
1057 
executeAttributeSets(Sit S,Context * c,Bool resolvingGlobals)1058 eFlag Element::executeAttributeSets(Sit S, Context *c, Bool resolvingGlobals)
1059 {
1060   Processor *proc = NZ(S.getProcessor());
1061   proc -> vars -> pushCallLevel(0);
1062   if (attsNames)
1063     {
1064       for (int i = 0; i < attsNames -> number(); i++)
1065 	{
1066 	  QNameList history;
1067 	  E( getOwner().attSets().executeAttSet(S, *((*attsNames)[i]),
1068 						c, getOwner(), history,
1069 						resolvingGlobals) );
1070 	}
1071     }
1072   proc -> vars -> popCallLevel();
1073   return OK;
1074 }
1075 
1076 /****************************************
1077 A t t r i b u t e
1078 ****************************************/
1079 
Attribute(Tree & owner_,const QName & aqname,const Str & acont,XSL_ATT aop)1080 Attribute::Attribute(Tree &owner_, const QName &aqname,
1081     const Str &acont, XSL_ATT aop)
1082 : Vertex(owner_, (VTYPE) (VT_ATTRIBUTE_WF |
1083     (aop != XSLA_NONE ? VT_XSL : 0))),
1084     cont(&(owner_.getArena()))
1085 {
1086     expr = NULL;
1087     name = aqname;
1088     cont = acont;
1089     op = aop;
1090 };
1091 
~Attribute()1092 Attribute::~Attribute()
1093 {
1094     if (expr)
1095         delete expr;
1096 }
1097 
findAVTBrace(Sit S,char * & p,char which,DStr & copybuf)1098 eFlag findAVTBrace(Sit S, char *&p, char which, DStr &copybuf)
1099 {
1100     char *p0 = p; // ,c;
1101     int len;
1102     copybuf.empty();
1103     while (*p)
1104     {
1105         if (*p != which)
1106             p++;
1107         else
1108         {
1109             if (*(p+1) == which)
1110             {
1111                 len = p+1 - p0;
1112                 if (len)
1113                     copybuf.nadd(p0, len);
1114                 p += 2;
1115                 p0 = p;
1116             }
1117             else break;
1118         };
1119     };
1120     len = p - p0;
1121     if (len) copybuf.nadd(p0, len);
1122     return OK;
1123 }
1124 
buildExpr(Sit S,Bool asTemplate,ExType ty)1125 eFlag Attribute::buildExpr(Sit S, Bool asTemplate, ExType ty)
1126 {
1127     char *q;
1128     GP( Expression ) eadd;
1129     if (asTemplate)
1130     {
1131         DStr sadd;
1132         expr = new Expression(*toE(parent), EXF_STRINGSEQ);  // GP: OK
1133         char *p = (char*) cont;
1134         while (*p)
1135         {
1136             E( findAVTBrace(S, q = p, '{', sadd) );
1137             if (!sadd.isEmpty())
1138             {
1139                 eadd = new Expression(*toE(parent), EXF_ATOM);
1140                 (*eadd).setAtom(sadd);
1141                 expr -> args.append(eadd.keep());
1142             };
1143             if (!*q) break;
1144             //
1145             if (!*(p = q + 1)) break;
1146             E( findAVTBrace(S, q = p, '}',sadd) );
1147             if (!sadd.isEmpty())
1148             {
1149                 eadd = new Expression(*toE(parent));
1150                 E( (*eadd).parse(S, sadd));
1151                 expr -> args.append(eadd.keep());
1152             };
1153             if (!*q) break;
1154             p = q + 1;
1155         }
1156     }
1157     else
1158     {
1159         expr = new Expression(*toE(parent));    // GP: OK
1160         E( expr -> parse(S, cont, (Bool) (ty == EX_NODESET_PATTERN)) );
1161     }
1162     return OK;
1163 }
1164 
execute(Sit S,Context * c,Bool resolvingGlobals)1165 eFlag Attribute::execute(Sit S, Context *c, Bool resolvingGlobals)
1166 {
1167     sabassert(parent);
1168     EQName ename;
1169     owner.expandQ(name, ename);
1170     OutputterObj &out = *(NZ(S.getProcessor()) -> outputter());
1171 
1172     if (isXSLElement(parent) || op != XSLA_NONE ||
1173 	ename.getUri() == theXSLTNamespace )
1174       {
1175         return OK;
1176       }
1177 
1178     E( out.eventAttributeStart(S, ename) );
1179     DStr temp;
1180     E( value(S, temp,c) );
1181     E( out.eventData(S, temp) );
1182     E( out.eventAttributeEnd(S) );
1183     return OK;
1184 }
1185 
value(Sit S,DStr & ret,Context * c)1186 eFlag Attribute::value(Sit S, DStr &ret, Context *c)
1187 {
1188     if (expr)
1189     {
1190         Expression temp(*toE(parent));
1191         E( expr -> eval(S, temp, c) );
1192         E( temp.tostring(S, ret) );
1193     }
1194     else
1195         ret = cont;
1196     return OK;
1197 }
1198 
speak(DStr & ret,SpeakMode mode)1199 void Attribute::speak(DStr &ret, SpeakMode mode)
1200 {
1201     if (mode & (SM_NAME | SM_CONTENTS))
1202     {
1203 	    Str fullName;
1204 	    owner.expandQStr(name, fullName);
1205 	    ret += fullName;
1206 	    // name.speak(ret,mode);
1207 	}
1208     if (mode & SM_CONTENTS)
1209     {
1210         ret += "=\"";
1211         // escape whitespace and quotes in value
1212         DStr escapedCont;
1213         const char* escNTQLG[] =
1214             {escNewline, escTab, escQuote, escLess, escGreater, NULL};
1215         escapeChars(escapedCont, cont, "\n\t\"<>", escNTQLG);
1216         escapedCont.appendSelf(ret);
1217         ret += '\"';
1218     }
1219 }
1220 
startCopy(Sit S,OutputterObj & out)1221 eFlag Attribute::startCopy(Sit S, OutputterObj& out)
1222 {
1223     EQName ename;
1224     owner.expandQ(name, ename);
1225     E( out.eventAttributeStart(S, ename) );
1226     E( out.eventData(S, cont) );
1227     E( out.eventAttributeEnd(S) );
1228     return OK;
1229 }
1230 
getName() const1231 const QName& Attribute::getName() const
1232 {
1233     return name;
1234 }
1235 
setValue(const Str & newValue)1236 void Attribute::setValue(const Str& newValue)
1237 {
1238     cont = newValue;
1239 }
1240 
serialize(Sit S,OutputterObj & out)1241 eFlag Attribute::serialize(Sit S, OutputterObj &out)
1242 {
1243     EQName ename;
1244     getOwner().expandQ(name, ename);
1245     E( out.eventAttributeStart(S, ename) );
1246     E( out.eventData(S, cont) );
1247     E( out.eventAttributeEnd(S) );
1248     return OK;
1249 }
1250 
1251 /****************************************
1252 A t t L i s t
1253 ****************************************/
1254 
find(XSL_ATT what)1255 Attribute* AttList::find(XSL_ATT what)
1256 {
1257     int i;
1258     Attribute *a;
1259     int num = number();
1260     for (i = 0; i < num; i++)
1261     {
1262 	// need to use a temporary variable
1263 	// to get around Solaris template problem
1264         Vertex * pTemp = (*this)[i];
1265         a = cast(Attribute *, pTemp);
1266         if (a -> op == what)
1267             return a;
1268     };
1269     return NULL;
1270 }
1271 
findNdx(const QName & attName)1272 int AttList::findNdx(const QName& attName)
1273 {
1274     int i;
1275     Attribute *a;
1276     int num = number();
1277     for (i = 0; i < num; i++)
1278     {
1279 	// need to use a temporary variable
1280 	// to get around Solaris template problem
1281         Vertex * pTemp = (*this)[i];
1282         a = toA(pTemp);
1283         if (attName == a -> getName())
1284             return i;
1285     };
1286     return -1;
1287 }
1288 
find(const QName & attName)1289 Attribute* AttList::find(const QName& attName)
1290 {
1291     int ndx = findNdx(attName);
1292     // need to use a temporary variable
1293     // to get around Solaris template problem
1294     if (ndx != -1)
1295       {
1296 	Vertex * pTemp = (*this)[ndx];
1297 	return toA(pTemp);
1298       }
1299     else
1300       {
1301 	return NULL;
1302       }
1303 }
1304 
1305 /*****************************************************************
1306     N m S p a c e
1307 *****************************************************************/
1308 //NmSpace::NmSpace(Tree& owner_, Phrase _prefix, Phrase _uri, NsKind _kind)
NmSpace(Tree & owner_,Phrase _prefix,Phrase _uri,Bool _excluded,NsKind _kind)1309 NmSpace::NmSpace(Tree& owner_, Phrase _prefix, Phrase _uri,
1310 		 Bool _excluded, NsKind _kind)
1311 : Vertex(owner_, VT_NAMESPACE)
1312 {
1313     prefix = _prefix;
1314     uri = _uri;
1315     name.setLocal(prefix);
1316     kind = _kind;
1317     excluded = _excluded;
1318     usageCount = 0;
1319 }
1320 
~NmSpace()1321 NmSpace::~NmSpace()
1322 {
1323 }
1324 
execute(Sit S,Context * c,Bool resolvingGlobals)1325 eFlag NmSpace::execute(Sit S, Context *c, Bool resolvingGlobals)
1326 {
1327     sabassert(parent);
1328 
1329     E( NZ(S.getProcessor()) -> outputter() ->
1330        eventNamespace(S,
1331 		      //was: proc -> aliasXL(prefix)),
1332 		      getOwner().dict().getKey(prefix),
1333 		      getOwner().dict().getKey(uri),
1334 		      excluded
1335 		      ));
1336     return OK;
1337 }
1338 
executeSkip(Sit S,Context * c,Bool resolvingGlobals,EQName & exName,Bool aliased)1339 eFlag NmSpace::executeSkip(Sit S, Context *c, Bool resolvingGlobals,
1340 			   EQName & exName, Bool aliased)
1341 {
1342     sabassert(parent);
1343 
1344     const Str & pStr = getOwner().dict().getKey(prefix);
1345     const Str & uStr = getOwner().dict().getKey(uri);
1346 
1347     if (!aliased || !(exName.getPrefix() == pStr))
1348       E( NZ(S.getProcessor()) -> outputter() ->
1349 	 eventNamespace(S, pStr, uStr, excluded) );
1350     return OK;
1351 }
1352 
speak(DStr & s,SpeakMode mode)1353 void NmSpace::speak(DStr& s, SpeakMode mode)
1354 {
1355     s += "xmlns";
1356     if (prefix != UNDEF_PHRASE)
1357     {
1358         s += ':';
1359         s += getOwner().dict().getKey(prefix);
1360     }
1361     s += "=\"";
1362     s += getOwner().dict().getKey(uri);
1363     s += '\"';
1364 }
1365 
value(Sit S,DStr & s,Context * c)1366 eFlag NmSpace::value(Sit S, DStr &s, Context *c)
1367 {
1368     s = getOwner().dict().getKey(uri);
1369     return OK;
1370 }
1371 
startCopy(Sit S,OutputterObj & out)1372 eFlag NmSpace::startCopy(Sit S, OutputterObj& out)
1373 {
1374     E( out.eventNamespace(S,
1375 			  getOwner().dict().getKey(prefix),
1376 			  getOwner().dict().getKey(uri),
1377 			  excluded) );
1378     return OK;
1379 }
1380 
getName() const1381 const QName& NmSpace::getName() const
1382 {
1383     return name;
1384 }
1385 
serialize(Sit S,OutputterObj & out)1386 eFlag NmSpace::serialize(Sit S, OutputterObj &out)
1387 {
1388     const Str &prefixStr = getOwner().expand(prefix),
1389         &uriStr = getOwner().expand(uri);
1390 	// hide the "xml" binding
1391 	if (!(prefixStr == "xml"))
1392         E( out.eventNamespace(S, prefixStr, uriStr) );
1393     return OK;
1394 }
1395 
setKind(NsKind kind_)1396 NsKind NmSpace::setKind(NsKind kind_) {
1397     if (kind < kind_) kind = kind_;
1398     return kind;
1399 }
1400 /*****************************************************************
1401     N S L i s t
1402 *****************************************************************/
1403 
~NSList()1404 NSList::~NSList()
1405 {
1406 }
1407 
find(Phrase prefix) const1408 NmSpace* NSList::find(Phrase prefix) const
1409 {
1410     int ndx = findNdx(prefix);
1411     return (ndx == -1) ? NULL : toNS((*this)[ndx]);
1412 }
1413 
findNdx(Phrase prefix) const1414 int NSList::findNdx(Phrase prefix) const
1415 {
1416     int i;
1417     for (i = 0; i < number(); i++)
1418       if (toNS((*this)[i]) -> prefix == prefix)
1419 	return i;
1420     return -1;
1421 }
1422 
resolve(Sit S,Phrase & what,Bool defaultToo) const1423 eFlag NSList::resolve(Sit S, Phrase &what, Bool defaultToo) const
1424 {
1425     Bool emptystr = (what == UNDEF_PHRASE);
1426     if (emptystr && !defaultToo)
1427         return OK;
1428     NmSpace *p = find(what);
1429     if (!p)
1430     {
1431         if (!emptystr)
1432             what = UNDEF_PHRASE;
1433     }
1434     else
1435         what = p -> uri;
1436     return OK;
1437 }
1438 
unresolve(Phrase & what) const1439 void NSList::unresolve(Phrase &what) const
1440 {
1441     sabassert(what != UNDEF_PHRASE);
1442     NmSpace *currNS;
1443     for (int i = 0; i < number(); i++)
1444     {
1445         currNS = toNS((*this)[i]);
1446         if (what == currNS -> uri)
1447         {
1448             what = currNS -> prefix;
1449             return;
1450         }
1451     };
1452     sabassert(0);
1453 }
1454 
1455 /*
1456 appends all current namespace declarations as vertices to tree t
1457 'other' is the list where they are being appended in t
1458 */
1459 
giveCurrent(Sit S,NSList & other,Tree * t,int nscount) const1460 void NSList::giveCurrent(Sit S, NSList &other, Tree *t, int nscount) const
1461 {
1462     const NmSpace *currNS, *addedNS;
1463     const int imax = number() - 1;
1464     UriList &excludedNS = t -> getCurrentInfo() -> getExcludedNS();
1465     for (int i = imax; i >= 0; i--)
1466     {
1467         currNS = toNS((*this)[i]);
1468         if (other.findNdx(currNS -> prefix) == -1) {
1469 	    addedNS = new(&(NZ(t) -> getArena()))
1470 	      NmSpace(*t, currNS -> prefix, currNS -> uri,
1471 		      excludedNS.findNdx(currNS->uri)!=-1 || currNS->excluded,
1472 		      i > (imax - nscount) ?  NSKIND_DECLARED : NSKIND_PARENT);
1473             t -> appendVertex(S, toV(addedNS));
1474 	    // _JP_ ??? why not other.append(toV(addedNS));
1475 	};
1476     }
1477 }
1478 
swallow(Sit S,NSList & other,Tree * srcTree,Tree * t)1479 void NSList::swallow(Sit S, NSList &other, Tree* srcTree, Tree *t)
1480 {
1481   for (int i = 0; i < other.number(); i++)
1482     {
1483       NmSpace *currNS = toNS(other[i]);
1484 
1485       Phrase p, u;
1486       //translate between dictionaries
1487       if (srcTree && srcTree != t)
1488 	{
1489 	  if (currNS -> prefix == UNDEF_PHRASE)
1490 	    {
1491 	      p = UNDEF_PHRASE;
1492 	    }
1493 	  else {
1494 	    const Str &aux1 = srcTree -> expand(currNS -> prefix);
1495 	    p = t -> unexpand(aux1);
1496 	  }
1497 
1498 	  const Str &aux2 = srcTree -> expand(currNS -> uri);
1499 	  u = t -> unexpand(aux2);
1500 	}
1501       else
1502 	{
1503 	  sabassert(!srcTree);
1504 	  p = currNS -> prefix;
1505 	  u = currNS -> uri;
1506 	}
1507 
1508       NmSpace *nm = new (&(NZ(t) -> getArena())) NmSpace(*t, p, u, NSKIND_PARENT);
1509       append(nm);
1510     }
1511 }
1512 
1513 
findPrefix(QName & q)1514 void NSList::findPrefix(QName &q)
1515 {
1516     if (q.getUri() == UNDEF_PHRASE)
1517         q.setPrefix(UNDEF_PHRASE);
1518     else
1519     {
1520         Phrase thePrefix = q.getUri();
1521         unresolve(thePrefix);
1522 	    q.setPrefix(thePrefix);
1523 	}
1524 }
1525 
report(Sit S,MsgType type,MsgCode code,const Str & arg1,const Str & arg2) const1526 void NSList::report(Sit S, MsgType type, MsgCode code,
1527     const Str &arg1, const Str &arg2) const
1528 {
1529     S.message(type, code, arg1, arg2);
1530 }
1531 
setPrefixKind(Phrase prefix_,NsKind kind_) const1532 void NSList::setPrefixKind(Phrase prefix_, NsKind kind_) const
1533 {
1534     int ndx = findNdx(prefix_);
1535     if (ndx != -1) {
1536       toNS((*this)[ndx]) -> setKind(kind_);
1537     };
1538 }
1539 
incPrefixUsage(Phrase prefix_) const1540 void NSList::incPrefixUsage(Phrase prefix_) const
1541 {
1542     int ndx = findNdx(prefix_);
1543     if (ndx != -1) {
1544       toNS((*this)[ndx]) -> usageCount++;
1545     };
1546 }
1547 
decPrefixUsage(Phrase prefix_) const1548 void NSList::decPrefixUsage(Phrase prefix_) const
1549 {
1550     int ndx = findNdx(prefix_);
1551     if (ndx != -1) {
1552       toNS((*this)[ndx]) -> usageCount--;
1553     };
1554 }
1555 
executeSkip(Sit S,Context * c,Bool resolvingGlobals,EQName & exName,Bool aliased)1556 eFlag NSList::executeSkip(Sit S, Context * c, Bool resolvingGlobals,
1557 			  EQName & exName, Bool aliased)
1558 {
1559   int i;
1560 
1561   for (i=0; i<number(); i++)
1562     E( toNS((*this)[i]) -> executeSkip(S, c, resolvingGlobals,
1563 				 exName, aliased) );
1564   return OK;
1565 }
1566 
1567 /****************************************
1568 T e x t
1569 ****************************************/
1570 
Text(Tree & owner_,char * acont,int alen)1571 Text::Text(Tree& owner_, char *acont, int alen /* =0 */)
1572     : Vertex(owner_, VT_TEXT_WF), cont(&(owner_.getArena()))
1573 {
1574     if (alen)
1575         cont.nset(acont,alen);
1576     else cont = (char*) acont;
1577     isCDATAFlag = FALSE;
1578 }
1579 
~Text()1580 Text::~Text()
1581 {
1582 }
1583 
execute(Sit S,Context * c,Bool resolvingGlobals)1584 eFlag Text::execute(Sit S, Context *c, Bool resolvingGlobals)
1585 {
1586     E( NZ(S.getProcessor()) -> outputter() -> eventData(S, cont) );
1587     return OK;
1588 }
1589 
value(Sit S,DStr & ret,Context * c)1590 eFlag Text::value(Sit S, DStr& ret, Context *c)
1591 {
1592     ret = cont;
1593     return OK;
1594 }
1595 
speak(DStr & ret,SpeakMode mode)1596 void Text::speak(DStr &ret, SpeakMode mode)
1597 {
1598     if (mode & SM_ESCAPE)
1599         cont.speakTerse(ret);
1600     else
1601         ret += cont;
1602 };
1603 
startCopy(Sit S,OutputterObj & out)1604 eFlag Text::startCopy(Sit S, OutputterObj& out)
1605 {
1606     E( out.eventData(S, cont) );
1607     return OK;
1608 }
1609 
serialize(Sit S,OutputterObj & out)1610 eFlag Text::serialize(Sit S, OutputterObj &out)
1611 {
1612     if (isCDATAFlag)
1613         E( out.eventCDataSection(S, cont) )
1614 	else
1615         E( out.eventData(S, cont) );
1616     return OK;
1617 }
1618 
beCDATA()1619 void Text::beCDATA()
1620 {
1621     isCDATAFlag = TRUE;
1622 }
1623 
isCDATA()1624 Bool Text::isCDATA()
1625 {
1626     return isCDATAFlag;
1627 }
1628 
1629 /****************************************
1630 C o m m e n t
1631 ****************************************/
1632 
Comment(Tree & owner_,const Str & cont_)1633 Comment::Comment(Tree& owner_, const Str& cont_)
1634 :
1635 Vertex(owner_, VT_COMMENT), cont(&(owner_.getArena()))
1636 {
1637     cont = cont_;
1638 }
1639 
~Comment()1640 Comment::~Comment()
1641 {
1642 }
1643 
execute(Sit S,Context * c,Bool resolvingGlobals)1644 eFlag Comment::execute(Sit S, Context *c, Bool resolvingGlobals)
1645 {
1646     return OK;
1647 }
1648 
value(Sit S,DStr & ret,Context * c)1649 eFlag Comment::value(Sit S, DStr& ret, Context *c)
1650 {
1651     ret = cont;
1652     return OK;
1653 }
1654 
speak(DStr & ret,SpeakMode mode)1655 void Comment::speak(DStr &ret, SpeakMode mode)
1656 {
1657     ret += cont;
1658 };
1659 
startCopy(Sit S,OutputterObj & out)1660 eFlag Comment::startCopy(Sit S, OutputterObj& out)
1661 {
1662     E( out.eventCommentStart(S) );
1663     E( out.eventData(S, cont) );
1664     E( out.eventCommentEnd(S) );
1665     return OK;
1666 }
1667 
serialize(Sit S,OutputterObj & out)1668 eFlag Comment::serialize(Sit S, OutputterObj &out)
1669 {
1670     E( out.eventCommentStart(S) );
1671     E( out.eventData(S, cont) );
1672     E( out.eventCommentEnd(S) );
1673     return OK;
1674 }
1675 
1676 /****************************************
1677 P r o c I n s t r
1678 ****************************************/
1679 
ProcInstr(Tree & owner_,Phrase name_,const Str & cont_)1680 ProcInstr::ProcInstr(Tree& owner_, Phrase name_, const Str& cont_)
1681 :
1682 Vertex(owner_, VT_PI), cont(&(owner_.getArena()))
1683 {
1684     name.empty();
1685     name.setLocal(name_);
1686     cont = cont_;
1687 }
1688 
~ProcInstr()1689 ProcInstr::~ProcInstr()
1690 {
1691 }
1692 
execute(Sit S,Context * c,Bool resolvingGlobals)1693 eFlag ProcInstr::execute(Sit S, Context *c, Bool resolvingGlobals)
1694 {
1695     return OK;
1696 }
1697 
value(Sit S,DStr & ret,Context * c)1698 eFlag ProcInstr::value(Sit S, DStr& ret, Context *c)
1699 {
1700     ret = cont;
1701     return OK;
1702 }
1703 
speak(DStr & ret,SpeakMode mode)1704 void ProcInstr::speak(DStr &ret, SpeakMode mode)
1705 {
1706     ret += cont;
1707 };
1708 
startCopy(Sit S,OutputterObj & out)1709 eFlag ProcInstr::startCopy(Sit S, OutputterObj& out)
1710 {
1711     E( out.eventPIStart(S, owner.expand(name.getLocal())) );
1712     E( out.eventData(S, cont) );
1713     E( out.eventPIEnd(S) );
1714     return OK;
1715 }
1716 
getName() const1717 const QName& ProcInstr::getName() const
1718 {
1719     return name;
1720 }
1721 
serialize(Sit S,OutputterObj & out)1722 eFlag ProcInstr::serialize(Sit S, OutputterObj &out)
1723 {
1724     const Str& nameStr = getOwner().expand(name.getLocal());
1725     E( out.eventPIStart(S, nameStr) );
1726     E( out.eventData(S, cont) );
1727     E( out.eventPIEnd(S) );
1728     return OK;
1729 }
1730 
1731 /****************************************
1732 X S L E l e m e n t
1733 ****************************************/
1734 
XSLElement(Tree & owner_,QName & aqname,XSL_OP code)1735 XSLElement::XSLElement(Tree& owner_, QName& aqname, XSL_OP code)
1736 :
1737 Element(owner_, aqname, VT_XSL_ELEMENT_WF)
1738 {
1739     sabassert(code != XSL_NONE);
1740     op = code;
1741 };
1742 
1743 
newChild(Sit S,Vertex * v)1744 eFlag XSLElement::newChild(Sit S, Vertex *v)
1745 {
1746     // process defs
1747     //
1748     E( Element::newChild(S, v) );
1749     return OK;
1750 };
1751 
execute(Sit S,Context * c,Bool resolvingGlobals)1752 eFlag XSLElement::execute(Sit S, Context *c, Bool resolvingGlobals)
1753 {
1754     Attribute *a;
1755     Bool didNotExecute = FALSE;
1756     Processor *proc = NZ(S.getProcessor());
1757     // ???
1758     if (c -> isFinished())
1759         return OK;
1760 
1761     //c->setCurrentNode(NULL); _cn_
1762 
1763     NodeHandle v = c -> current();
1764     sabassert(v);
1765 
1766     //we store the current context to the element
1767     //e.g. the current() function needs it
1768     //setOrigContext(c);
1769 
1770 #ifdef SABLOT_DEBUGGER
1771     if (debugger) E( debugger -> breakOnElement(S, this, c) );
1772 #endif
1773 
1774     switch(op)
1775     {
1776     case XSL_APPLY_TEMPLATES:
1777     {
1778 	Attribute *aSelect = atts.find(XSLA_SELECT);
1779 	GP( Expression ) e;
1780 	if (aSelect)
1781 	    e.assign( NZ(aSelect -> expr) );
1782 	else
1783 	{
1784 	    e = new Expression(*this, EXF_LOCPATH);
1785 	    (*e).setLS(
1786 		AXIS_CHILD,
1787 		EXNODE_NODE);
1788 	};
1789 
1790 	// mode
1791 	Bool addedMode = TRUE;
1792 	a = atts.find(XSLA_MODE);
1793 	if (a)
1794 	{
1795 	    GP( QName ) m = new QName;
1796 	    E( setLogical(S, *m, a -> cont,FALSE) );
1797 	    proc -> pushMode(m.keep());
1798 	}
1799 	else if (proc -> getCurrentMode())
1800 	    proc -> pushMode(NULL);
1801 	else addedMode = FALSE;
1802 
1803 	GP( Context ) newc;
1804 	newc.assign(c);
1805 	E( (*e).createContext( S, newc ) );
1806 	newc.unkeep();
1807 	if (!(*newc).isVoid())
1808 	{
1809 	    // *** SORT HERE ***
1810 	    SortDefList sortDefs;
1811 	    makeSortDefs(S, sortDefs, c);
1812 	    if (sortDefs.number())
1813 		E( (*newc).sort(S, this, &sortDefs) );
1814 	    sortDefs.freeall(FALSE);
1815 
1816 	    // process with-params
1817 	    E( contents.execute(S, c, resolvingGlobals) );
1818 	    // proc will dispose of newc:
1819 	    E( proc -> execute(S, (Vertex*) NULL, newc, resolvingGlobals) );
1820 	    newc.keep();
1821 	    // remove the prebindings introduced by with-param
1822 	    proc -> vars -> rmPrebindings();
1823 	}
1824 	else
1825 	    newc.del();    // GP: done automatically anyway
1826 	if (addedMode)
1827 	    proc -> popMode();
1828 	if (!aSelect)
1829 	    e.del();    // GP: done automatically anyway
1830     }; break;
1831 
1832     case XSL_APPLY_IMPORTS:
1833     {
1834 	E( proc -> execApplyImports(S, c, subtree, resolvingGlobals) );
1835     }; break;
1836 
1837     case XSL_IF:
1838     {
1839 	a = NZ( atts.find(XSLA_TEST) );
1840 	Expression boolexpr(*this);
1841 	E( NZ(a -> expr) -> eval(S, boolexpr,c) );
1842 	Bool boolval = boolexpr.tobool();
1843 	if ((boolval) && (contents.number()))
1844 	    E( contents.execute(S, c, resolvingGlobals) )
1845 		else
1846 		    didNotExecute = TRUE;
1847     }; break;
1848     case XSL_CHOOSE:
1849     {
1850 	Bool done = FALSE;
1851 	for (int i = 0; i < contents.number() && !done; i++)
1852 	{
1853 	    // need to use a temporary variable
1854 	    // to get around Solaris template problem
1855             Vertex * pTemp = contents[i];
1856 	    XSLElement *x = cast(XSLElement*,pTemp);
1857 	    //needed for the current() function
1858 	    //problem was, that trueFor is called before x -> execute
1859 	    //x -> setOrigContext(c);
1860 	    if (x -> op == XSL_WHEN)
1861 	    {
1862 	      a = NZ( x -> atts.find(XSLA_TEST) );
1863 	      Expression boolexpr(*this);
1864 	      E( NZ(a -> expr) -> eval(S, boolexpr, c) );
1865 	      done = boolexpr.tobool();
1866 
1867 	      if (done)
1868 		E( x -> execute(S, c, resolvingGlobals) );
1869 	    }
1870 	    else
1871 	    {
1872 		sabassert(x -> op == XSL_OTHERWISE);
1873 		E( x -> execute(S, c, resolvingGlobals) );
1874 	    };
1875 	};
1876     }; break;
1877     case XSL_WHEN: // condition tested by CHOOSE
1878     {
1879 	E( contents.execute(S, c, resolvingGlobals) );
1880     }; break;
1881     case XSL_OTHERWISE: // condition tested by CHOOSE
1882     {
1883 	E( contents.execute(S, c, resolvingGlobals) );
1884     }; break;
1885     case XSL_ELEMENT:
1886     {
1887 	QName q;
1888 	DStr nameStr;
1889 	E( NZ( atts.find(XSLA_NAME) ) -> value(S, nameStr, c) );
1890 	if (! isValidQName((char*)nameStr) )
1891 	  Err1(S, E_INVALID_QNAME, (char*)nameStr);
1892 
1893 	Phrase nsuri = UNDEF_PHRASE;
1894 	DStr uristr;
1895 	//prepare for namespace handling
1896 	Attribute *a = atts.find(XSLA_NAMESPACE);
1897 	if (a) {
1898 	  E( a -> value(S, uristr, c) );
1899 	  nsuri = owner.unexpand(uristr);
1900 	}
1901 
1902 	E( setLogical(S, q, nameStr, TRUE, nsuri) );
1903 
1904 	Str prefix = owner.expand(q.getPrefix());
1905 	if (nsuri != UNDEF_PHRASE &&
1906 	    (q.getPrefix() == UNDEF_PHRASE || prefix == "xmlns"))
1907 	  {
1908     	    Str pfx = S.getProcessor() -> getNextNSPrefix();
1909     	    q.setPrefix(owner.unexpand(pfx));
1910 	  }
1911 
1912 	EQName ename;
1913 	owner.expandQ(q, ename);
1914 
1915 	E( proc -> outputter() -> eventElementStart(S, ename) );
1916 	//we have to inherit namespaces
1917 	E( namespaces.execute(S, c, resolvingGlobals) );
1918 	//add namespace from 'namespace' attribute
1919 	if (a)
1920 	  {
1921 	    prefix = ename.getPrefix();
1922 	    proc -> outputter() -> eventNamespace(S, prefix, uristr);
1923 	  }
1924 	//execute attribute sets
1925 	E( executeAttributeSets(S, c, resolvingGlobals) );
1926 	//and so on...
1927 	E( Daddy::execute(S, c, resolvingGlobals) );
1928 	E( proc -> outputter() -> eventElementEnd(S, ename) );
1929     }; break;
1930 
1931     case XSL_PROCESSING_INSTR:
1932     {
1933 	QName q;
1934 	DStr nameStr;
1935 	E( NZ( atts.find(XSLA_NAME) ) -> value(S, nameStr, c) );
1936 	if (! isValidNCName((char*)nameStr) )
1937 	  Err1(S, E_INVALID_NCNAME, (char*)nameStr);
1938 
1939 	E( setLogical(S, q, nameStr, FALSE) );
1940 	const Str& qloc = owner.expand(q.getLocal());
1941 	if (( q.getPrefix() != UNDEF_PHRASE ) ||
1942 	    strEqNoCase( qloc, "xml") || (qloc == "") )
1943 	    Err1(S, E1_PI_TARGET, nameStr);
1944 	E( proc -> outputter() -> eventPIStart( S, qloc ) );
1945 	E( contents.execute(S, c, resolvingGlobals) );
1946 	//for better error report
1947 	eFlag flg = proc -> outputter() -> eventPIEnd(S);
1948 	if (S.getError() == E_INVALID_DATA_IN_PI)
1949 	  Err(S, E_INVALID_DATA_IN_PI);
1950 	E( flg );
1951     }; break;
1952     case XSL_COMMENT:
1953     {
1954 	E( proc -> outputter() -> eventCommentStart(S) );
1955 	E( contents.execute(S, c, resolvingGlobals) );
1956 	E( proc -> outputter() -> eventCommentEnd(S) );
1957     }; break;
1958     case XSL_ATTRIBUTE:
1959     {
1960 	QName q;
1961 	DStr nameStr;
1962 	E( NZ( atts.find(XSLA_NAME) ) -> value(S, nameStr, c) );
1963 	if (! isValidQName((char*)nameStr) )
1964 	  Err1(S, E_INVALID_QNAME, (char*)nameStr);
1965 
1966 	Phrase nsuri = UNDEF_PHRASE;
1967 	DStr uristr;
1968 	//prepare for namespace handling
1969 	Attribute *a = atts.find(XSLA_NAMESPACE);
1970 	if (a) {
1971 	  E( a -> value(S, uristr, c) );
1972 	  nsuri = owner.unexpand(uristr);
1973 	}
1974 
1975 	E( setLogical(S, q, nameStr, FALSE, nsuri) );
1976 
1977 	Str prefix = owner.expand(q.getPrefix());
1978 	if (nsuri != UNDEF_PHRASE &&
1979 	    (q.getPrefix() == UNDEF_PHRASE || prefix == "xmlns"))
1980 	  {
1981 
1982 	    Str pfx = S.getProcessor() -> getNextNSPrefix();
1983 	    q.setPrefix(owner.unexpand(pfx));
1984 	  }
1985 
1986 	EQName ename;
1987 	owner.expandQ(q, ename);
1988 
1989 	//output new namespace if needed
1990 	if (a)
1991 	  {
1992 	    prefix = ename.getPrefix();
1993 	    proc -> outputter() -> eventNamespace(S, prefix, uristr);
1994 	  }
1995 
1996 	E( proc -> outputter() -> eventAttributeStart(S, ename) );
1997 	E( contents.execute(S, c, resolvingGlobals) );
1998 	E( proc -> outputter() -> eventAttributeEnd(S) );
1999     }; break;
2000     case XSL_TEXT:
2001     {
2002 	Attribute *disableEsc = atts.find(XSLA_DISABLE_OUTPUT_ESC);
2003 	if (disableEsc && disableEsc -> cont == (const char*)"yes")
2004 	    E( proc -> outputter() -> eventDisableEscapingForNext(S) );
2005 	E( contents.execute(S, c, resolvingGlobals) );
2006     }; break;
2007     case XSL_TEMPLATE:
2008       {
2009 	proc -> vars -> startApplyOne();
2010 	E( Daddy::execute(S, c, resolvingGlobals) );
2011 	proc -> vars -> endApplyOne();
2012       }; break;
2013     case XSL_FALLBACK: //simply does nothing
2014       break;
2015     case XSL_STYLESHEET:
2016     case XSL_TRANSFORM:
2017     {
2018 	GP( Context ) newc = c -> copy();
2019 
2020 	Processor *proc = NZ(S.getProcessor());
2021 
2022 	// process globals
2023 	//_PH_ globals
2024 	//E( getOwner().resolveGlobals(S, c, S.getProcessor()) );
2025 	// process other top level elements
2026 	for (int i = 0; i < contents.number(); i++)
2027 	{
2028 	    Vertex *son = contents[i];
2029 	    if (isXSLElement(son) && (instrTable[toX(son) -> op].flags & ELEM_TOPLEVEL))
2030 	    {
2031 		switch(toX(son) -> op)
2032 		{
2033 		case XSL_TEMPLATE:
2034 		    break;
2035 		    // global vars have been executed before
2036 		case XSL_VARIABLE:
2037 		case XSL_PARAM:
2038 		  {
2039 		    //_PH_ globals
2040 		    QName temp;
2041 		    temp.empty();
2042 		    E( proc -> resolveGlobal(S, c, temp, toX(son)) );
2043 		  }; break;
2044 		default: E( son -> execute(S, c, resolvingGlobals) );
2045 		}
2046 	    }
2047 	    //execute top-level extension elements as well
2048 	    if ( isExtension(son) ) {
2049 	      E( son -> execute(S, c, resolvingGlobals) );
2050 	    }
2051 	}
2052 
2053 	proc -> vars -> startCall();
2054 
2055 	E( proc -> execute(S, (Vertex*) NULL, newc, resolvingGlobals ));
2056 
2057 	// newc has been deleted by now
2058 	newc.keep();
2059 	proc -> vars -> endCall();
2060 
2061     }; break;
2062     case XSL_VALUE_OF:
2063     {
2064 	a = NZ( atts.find(XSLA_SELECT) );
2065 	Expression temp(*this);
2066 	E( NZ( a -> expr ) -> eval(S, temp, c, resolvingGlobals) );
2067 	// set output escaping
2068 	Attribute *disableEsc = atts.find(XSLA_DISABLE_OUTPUT_ESC);
2069 	if (disableEsc && disableEsc -> cont == (const char*)"yes")
2070 	    E( proc -> outputter() -> eventDisableEscapingForNext(S) );
2071 	// dump contents
2072 	Str cont;
2073 	E( temp.tostring(S, cont) );
2074 	E( proc -> outputter() -> eventData(S, cont) );
2075     };
2076     break;
2077     case XSL_COPY_OF:
2078     {
2079 	a = NZ( atts.find(XSLA_SELECT) );
2080 	Expression temp(*this);
2081 	E( NZ( a -> expr ) -> eval(S, temp, c, resolvingGlobals) );
2082 	if (temp.type == EX_NODESET)
2083 	{
2084 	    const Context& ctxt = temp.tonodesetRef();
2085 	    int k, kLimit = ctxt.getSize();
2086 
2087 	    for (k = 0; k < kLimit; k++)
2088 		// assuming here the context holds physical vertices
2089 	      //E( toPhysical(ctxt[k]) -> copy(S, *(proc -> outputter())) );
2090 	      E( S.dom().copyNode(S, ctxt[k], *(proc -> outputter())) );
2091 	}
2092 	else
2093 	{
2094 	    Str cont;
2095 	    E( temp.tostring(S, cont) );
2096 	    E( proc -> outputter() -> eventData(S, cont) );
2097 	}
2098     }; break;
2099     case XSL_COPY:
2100     {
2101       NodeHandle curr = c -> current();
2102       E( S.dom().startCopy(S, curr, *(proc -> outputter())) );
2103       //E( curr -> startCopy(S, *(proc -> outputter())) );
2104       //execute attribute sets
2105       E( executeAttributeSets(S, c, resolvingGlobals) );
2106 
2107       E( contents.execute(S, c, resolvingGlobals) );
2108       E( S.dom().endCopy(S, curr, *(proc -> outputter())) );
2109       //E( curr -> endCopy(S, *(proc -> outputter())) );
2110     }; break;
2111     case XSL_FOR_EACH:
2112     {
2113 	a = NZ( atts.find(XSLA_SELECT) );
2114 	GP( Context ) newc;
2115 	newc.assign(c);
2116 	E( NZ( a -> expr ) -> createContext(S, newc));
2117 	newc.unkeep();
2118 	if (!(*newc).isVoid() && contents.number())
2119 	{
2120 	    // *** SORT HERE ***
2121 	    SortDefList sortDefs;
2122 	    makeSortDefs(S, sortDefs, c);
2123 	    if (sortDefs.number())
2124 		E( (*newc).sort(S, this, &sortDefs) );
2125 	    sortDefs.freeall(FALSE);
2126 
2127 	    E( proc -> execute(S, contents, newc, resolvingGlobals) );
2128 	    // proc disposes of the new context
2129 	    newc.keep();
2130 	}
2131 /*
2132   else
2133   newc.del();    // done automatically
2134 */
2135     };
2136     break;
2137     case XSL_CALL_TEMPLATE:
2138     {
2139 	QName q;
2140 	a = NZ( atts.find(XSLA_NAME) );
2141 	XSLElement *thatrule;
2142 	E( setLogical(S, q, a -> cont, FALSE) );
2143 	if (!(thatrule = getOwner().findRuleByName(q)))
2144 	  {
2145 	    Err1(S, E1_RULE_NOT_FOUND, (char*)getOwner().expand(q.getLocal()));
2146 	  }
2147 
2148 //            proc -> vars -> rmPrebindings();
2149 	//process with-param
2150 	E( contents.execute(S, c, resolvingGlobals) );
2151 	//execute the other rule
2152 //            proc -> vars -> startLevel();
2153 	E( thatrule -> execute(S, c, resolvingGlobals) );
2154 	proc -> vars -> rmPrebindings();
2155 //            proc -> vars -> endLevel();
2156     }; break;
2157     case XSL_MESSAGE:
2158     {
2159 	DStr msg;
2160 	GP( Expression ) expr = new Expression(*this);
2161 	if (contents.isEmpty())
2162 	{
2163 	  (*expr).setAtom((const char*)"");
2164 	}
2165 	else
2166 	{
2167 	    proc -> vars -> startNested();
2168 	    TreeConstructer *newTC;
2169 	    E( proc -> pushTreeConstructer(S, newTC, (*expr).setFragment(),
2170 					   SAXOUTPUT_INT_PHYSICAL) );
2171 	    E( contents.execute(S, c, resolvingGlobals) );
2172 	    E( proc -> outputter() -> eventEndOutput(S) );
2173 	    E( proc -> popTreeConstructer(S, newTC) );
2174 	    proc -> vars -> endNested();
2175 	};
2176 	GP( Expression ) temp = new Expression(*this);
2177 	E( (*expr).eval(S, *temp,c, resolvingGlobals) );
2178 	(*temp).pTree = (*expr).pTree;
2179 	(*expr).pTree = NULL;
2180 	a =  atts.find(XSLA_TERMINATE);
2181 	Str tempStr;
2182 	(*temp).tostring(S, tempStr);
2183 	if (a && a -> cont == (const char*) "yes")
2184 	{
2185 	    Err1(S, E1_XSL_MESSAGE_TERM, tempStr);
2186 	}
2187 	else
2188 	{
2189 	    Warn1(S, W1_XSL_MESSAGE_NOTERM, tempStr);
2190 	};
2191 /*
2192   delete NZ(expr);     GP: automatic
2193   delete NZ(temp);
2194 */
2195     };
2196     break;
2197     // this is only executed for non-toplevel vars/params
2198     // (see case XSL_STYLESHEET)
2199     case XSL_VARIABLE:
2200     case XSL_WITH_PARAM:
2201     case XSL_PARAM:
2202     {
2203 	QName q;
2204 
2205 	GP( Expression ) expr = NULL;
2206 
2207 	// there must be a 'name' attribute
2208 	a = NZ(atts.find(XSLA_NAME));
2209 	// stick the name into q referring to this element's namespace decl's
2210 	E( setLogical(S, q, a -> cont, FALSE) );
2211 
2212 	// if there's a 'select', use the expression it gives
2213 	a = atts.find(XSLA_SELECT);
2214 	if (a)
2215 	  expr.assign(NZ(a -> expr));
2216 
2217 	// otherwise, construct a new expression; it may be an empty string
2218 	// if this element has void content, or a result tree fragment otherwise
2219 	else
2220 	  {
2221 	    expr = new Expression(*this);
2222 	    if (contents.isEmpty())
2223 		(*expr).setAtom((const char*)"");
2224 	    else // result tree fragment
2225 	    {
2226 		// starting a nesting will make the current prebindings
2227 		// invisible
2228 		// don't do it if we are resolving globals
2229 
2230 	      proc -> pushInBinding(TRUE);
2231 
2232 	      if (!resolvingGlobals)
2233 		proc -> vars -> startNested();
2234 	      TreeConstructer *newTC;
2235 	      E( proc -> pushTreeConstructer(S, newTC, (*expr).setFragment(),
2236 					     SAXOUTPUT_INT_PHYSICAL) );
2237 	      // execute the inside to create the fragment
2238 	      E( contents.execute(S, c, resolvingGlobals) );
2239 	      E( proc -> outputter() -> eventEndOutput(S) );
2240 	      E( proc -> popTreeConstructer(S, newTC) );
2241 
2242 	      // end the shadowing of preexisting bindings
2243 	      if (!resolvingGlobals)
2244 		proc -> vars -> endNested();
2245 
2246 	      proc -> popInBinding();
2247 	    };
2248 	}
2249 	//
2250 	// evaluate the expression
2251 	GP( Expression ) temp = new Expression(*this);
2252 	E( (*expr).eval(S, *temp, c, resolvingGlobals) );
2253 	(*temp).pTree = (*expr).pTree;
2254 	(*expr).pTree = NULL;
2255 
2256 	// expr is automatically deallocated if newly constructed
2257 
2258 	// add the new binding
2259 	switch(op)
2260 	{
2261 	case XSL_PARAM:
2262 	{
2263 	    E( proc -> vars -> addBinding(S, q, temp, FALSE) );
2264 	}; break;
2265 	case XSL_WITH_PARAM:
2266 	{
2267 	    E( proc -> vars -> addPrebinding(S, q, temp) );
2268 	}; break;
2269 	case XSL_VARIABLE:
2270 	{
2271 	    E( proc -> vars -> addBinding(S, q, temp, TRUE) );
2272 	}; break;
2273 	};
2274 	temp.keep();    // deleted when removing the binding
2275     }; break;
2276     case XSL_KEY:
2277     {
2278 	Attribute
2279 	    *name = atts.find(XSLA_NAME),
2280 	    *match = atts.find(XSLA_MATCH),
2281 	    *use = atts.find(XSLA_USE);
2282 	sabassert(name && match && use && match -> expr && use -> expr);
2283 	EQName ename;
2284 	QName q;
2285 	E( setLogical(S, q, NZ(name) -> cont, FALSE) );
2286 	getOwner().expandQ(q, ename);
2287 	E( proc -> addKey(S, ename, *(match -> expr), *(use -> expr)) );
2288     }; break;
2289     case XSL_DECIMAL_FORMAT:
2290     {
2291 	Attribute *name = atts.find(XSLA_NAME);
2292 	QName q;
2293 	if (name)
2294 	    E( setLogical(S, q, name -> cont, FALSE) );
2295 	EQName ename;
2296 	getOwner().expandQ(q, ename);
2297 	DecimalFormat *decFormat;
2298 	E( proc -> decimals().add(S, ename, decFormat) );
2299 	for (int k = 0; k < atts.number(); k++)
2300 	{
2301 	    if (toA(atts[k]) -> op != XSLA_NAME)
2302 		E( decFormat -> setItem(S, toA(atts[k]) -> op, toA(atts[k]) -> cont) );
2303 	}
2304     }; break;
2305 
2306 #define evalToStr(ATT, VAR) \
2307 { if (NULL != (e = getAttExpr(ATT)))\
2308     { E( e -> eval(S, evaluated, c, resolvingGlobals) );\
2309       E( evaluated.tostring(S, VAR) ); }}
2310 
2311     case XSL_NUMBER:
2312     {
2313 	// auxiliary functions are in numbering.h
2314 	ListInt theList;
2315 	Str theString;
2316 	// find @value
2317 	Expression *e = getAttExpr(XSLA_VALUE),
2318 	    evaluated(*this, EXF_ATOM);
2319 	if (e)
2320 	{
2321 	    E( e -> eval(S, evaluated, c, resolvingGlobals) );
2322 	    theList.append(evaluated.tonumber(S).round());
2323 	}
2324 	else
2325 	{
2326 	    NumberingLevel level = NUM_SINGLE;
2327 	    Attribute *a;
2328 	    if (NULL != (a = atts.find(XSLA_LEVEL)))
2329 	    {
2330 		if (a -> cont == "multiple")
2331 		    level = NUM_MULTIPLE;
2332 		else if (a -> cont == "any")
2333 		    level = NUM_ANY;
2334 		else if (!(a -> cont == "single"))
2335 		    Err1(S, E1_NUMBER_LEVEL, a -> cont);
2336 	    }
2337 	    E( xslNumberCount(S, level,
2338 			      getAttExpr(XSLA_COUNT),
2339 			      getAttExpr(XSLA_FROM),
2340 			      v, theList) );
2341 	}
2342 	Str format = "1",
2343 	    lang,
2344 	    letterValueStr,
2345 	    groupingSep;
2346 	int groupingSize = 0;
2347 
2348 	evalToStr(XSLA_FORMAT, format);  // defined above case XSL_NUMBER
2349 	evalToStr(XSLA_LANG, lang);
2350 
2351 	// get @letter-value
2352 	NumberingLetterValue letterValue = NUM_ALPHABETIC;
2353 	if (NULL != (e = getAttExpr(XSLA_LETTER_VALUE)))
2354 	{
2355 	    E( e -> eval(S, evaluated, c, resolvingGlobals) );
2356 	    E( evaluated.tostring(S, letterValueStr) );
2357 	    if (letterValueStr == "traditional")
2358 		letterValue = NUM_TRADITIONAL;
2359 	    else if (!(letterValueStr == "alphabetic"))
2360 		Err1(S, E1_NUMBER_LETTER_VALUE, letterValueStr);
2361 	}
2362 
2363 	// get @grouping-size
2364 	if (NULL != (e = getAttExpr(XSLA_GROUPING_SIZE)))
2365 	{
2366 	    E( e -> eval(S, evaluated, c, resolvingGlobals) );
2367 	    groupingSize = evaluated.tonumber(S).round();
2368 	}
2369 
2370 	// get @grouping-separator
2371 	Expression *eSep;
2372 	if (NULL != (eSep = getAttExpr(XSLA_GROUPING_SEPARATOR)))
2373 	{
2374 	    E( eSep -> eval(S, evaluated, c, resolvingGlobals) );
2375 	    E( evaluated.tostring(S, groupingSep) );
2376 	}
2377 
2378 	if (e || eSep)
2379 	{
2380 	    if (!e || !eSep || groupingSize <= 0 || utf8StrLength(groupingSep) != 1)
2381 	    {
2382 		Warn(S, W_NUMBER_GROUPING);
2383 		groupingSize = 0;
2384 		groupingSep.empty();
2385 	    }
2386 	}
2387 
2388 	E( xslNumberFormat(S, theList, format,
2389 			   lang, letterValue, groupingSep, groupingSize, theString) );
2390 
2391 	E( proc -> outputter() -> eventData(S, theString) );
2392     }; break;
2393     case XSL_OUTPUT:
2394     case XSL_NAMESPACE_ALIAS:
2395       // these were processed during parse
2396 	break;
2397     case XSL_SORT:
2398       // processed by parent
2399 	break;
2400     case XSL_ATTRIBUTE_SET:
2401       //processed during parse
2402       break;
2403     // unsupported instructions that are not considered harmful
2404     case XSL_STRIP_SPACE:
2405     case XSL_PRESERVE_SPACE:
2406       //processed during parse
2407       //Warn1(S, W1_UNSUPP_XSL, xslOpNames[op]);
2408 	break;
2409     default:
2410 	Err1(S, E1_UNSUPP_XSL, xslOpNames[op]);
2411     };
2412 
2413     //remove the variable bindings that occured inside this element
2414     if ((op != XSL_TEMPLATE) && (op != XSL_TRANSFORM) && (op != XSL_STYLESHEET) &&
2415         (op != XSL_FOR_EACH) && !didNotExecute)
2416         removeBindings(S);
2417     return OK;
2418 }
2419 
getAttExpr(XSL_ATT code)2420 Expression* XSLElement::getAttExpr(XSL_ATT code)
2421 {
2422     Attribute *a = atts.find(code);
2423     return a ? (a -> expr) : NULL;
2424 }
2425 
strip()2426 int XSLElement::strip()
2427 {
2428     if (op != XSL_TEXT && !preserveSpace)
2429         return /* defs.strip() + */ contents.strip();
2430     else return 0;
2431 }
2432 
2433 /*................................................................
2434 findAttNdx()
2435     returns the index of given attribute in the attribute table
2436     or -1 if not found
2437 ................................................................*/
2438 
findAttNdx(InstrTableItem & iitem,Attribute * a)2439 int findAttNdx(InstrTableItem &iitem, Attribute *a)
2440 {
2441     for (int i = 0; i < iitem.maxAtts; i++)
2442         if (iitem.att[i].attCode == a -> op) return i;
2443     return -1;
2444 }
2445 
2446 /*================================================================
2447 checkAtts
2448     called when all attributes have been parsed in. Returns FALSE
2449     iff they are OK. Return value of TRUE means that the end tag handler
2450     signals error.
2451 ================================================================*/
2452 
checkAtts(Sit S)2453 eFlag XSLElement::checkAtts(Sit S)
2454 {
2455     InstrTableItem &instrData = instrTable[op];
2456     sabassert(instrData.op == op);
2457     int
2458         attNdx,
2459         reqCount = 0;
2460     Attribute *a;
2461     for (int i = 0; i < atts.number(); i++)
2462     {
2463 	// need to use a temporary variable
2464 	// to get around Solaris template problem
2465         Vertex * pTemp = atts[i];
2466         a = cast(Attribute*, pTemp);
2467         if (((attNdx = findAttNdx(instrData,a)) == -1) &&
2468             a -> name.getUri() == UNDEF_PHRASE)
2469             // FIXME: issue a warning when ignoring an att??
2470 	    {
2471 	        Str fullName;
2472 		    owner.expandQStr(a -> name, fullName);
2473             Err1(S, ET_BAD_ATTR, fullName);
2474 	    }
2475         if (instrData.att[attNdx].required)
2476             reqCount++;
2477         if (instrData.att[attNdx].exprType != EX_NONE)
2478 	  {
2479             E( a -> buildExpr(S,
2480 			      instrData.att[attNdx].avtemplate,
2481 			      instrData.att[attNdx].exprType) );
2482 	    if (op == XSL_TEMPLATE && a->op == XSLA_MATCH)
2483 	      {
2484 		//must not contain variable ref
2485 		if (a->expr && a->expr->containsFunctor(EXF_VAR))
2486 		  Err(S, E_VAR_IN_MATCH);
2487 	      }
2488 	  }
2489     };
2490     if (reqCount < instrData.reqAtts)
2491         Err(S, ET_REQ_ATTR);
2492     return OK;
2493 };
2494 
2495 //................................................................
2496 
checkExtraChildren(int & k)2497 void XSLElement::checkExtraChildren(int& k)
2498 {
2499     Vertex *w;
2500     XSL_OP hisop;
2501     int status = 0;
2502     for (k = 0; k < contents.number(); k++)
2503     {
2504         w = contents[k];
2505         if (!isXSLElement(w)) return;
2506         hisop = toX(w) -> op;
2507         switch(op)
2508         {
2509         case XSL_APPLY_TEMPLATES:
2510             if ((hisop != XSL_SORT) && (hisop != XSL_WITH_PARAM)) return;
2511             break;
2512         case XSL_ATTRIBUTE_SET:
2513             if (hisop != XSL_ATTRIBUTE) return;
2514             break;
2515         case XSL_CALL_TEMPLATE:
2516             if (hisop != XSL_WITH_PARAM) return;
2517             break;
2518         case XSL_CHOOSE:
2519             switch(hisop)
2520             {
2521             case XSL_WHEN:
2522                 {
2523                     if (status <= 1) status = 1;
2524                     else return;
2525                 }; break;
2526             case XSL_OTHERWISE:
2527                 {
2528                     if (status == 1) status = 2;
2529                     else return;
2530                 }; break;
2531             default: return;
2532             };
2533             break;
2534         case XSL_FOR_EACH:
2535             if (hisop != XSL_SORT) return;
2536             break;
2537         case XSL_STYLESHEET:
2538         case XSL_TRANSFORM:
2539             if (hisop != XSL_WITH_PARAM) return;
2540             break;
2541         case XSL_TEMPLATE:
2542             if (hisop != XSL_PARAM) return;
2543             break;
2544         default:
2545             return;
2546         }
2547     }
2548 }
2549 
checkToplevel(Sit S)2550 eFlag XSLElement::checkToplevel(Sit S)
2551 {
2552   //if we're nested in top level foreign node, all is ok
2553   if (vt & VT_TOP_FOREIGN) return OK;
2554 
2555   if (!(instrTable[op].flags & ELEM_INSTR) &&
2556       !(instrTable[op].flags & ELEM_EXTRA) &&
2557       (!isXSL(parent) ||
2558        !(instrTable[toX(parent) -> op].flags & ELEM_CONT_TOPLEVEL)))
2559     Err1(S, E1_ELEM_TOPLEVEL, xslOpNames[op]);
2560   return OK;
2561 }
2562 
checkChildren(Sit S)2563 eFlag XSLElement::checkChildren(Sit S)
2564 {
2565     InstrTableItem &iData = instrTable[op];
2566     sabassert(iData.op == op);
2567 
2568     if (!(iData.flags & ELEM_CONT) && contents.number())
2569         Err1(S, E_ELEM_MUST_EMPTY, xslOpNames[op]);
2570 
2571     int firstAfter = 0;
2572     if (iData.flags & ELEM_CONT_EXTRA)
2573         checkExtraChildren(firstAfter);
2574 
2575     for (int k = firstAfter; k < contents.number(); k++)
2576     {
2577         Vertex *w = contents[k];
2578 
2579 	if (isElement(w) && (toE(w)->getName().getPrefix() != UNDEF_PHRASE) &&
2580 	    (iData.flags & ELEM_CONT_EXTENSION))
2581 	  {
2582 	    continue;
2583 	  }
2584 
2585 	if (isElement(w) && (iData.flags & ELEM_CONT_PCDATA)) {
2586 	  Err1(S, E_ELEM_MUST_BE_PCDATA, xslOpNames[op]);
2587 	}
2588 
2589         if (isText(w) || (isElement(w) && !isXSLElement(w)))
2590         {
2591             if (!(iData.flags & (ELEM_CONT_INSTR | ELEM_CONT_PCDATA)))
2592                 Err1(S, E_ELEM_CONT_TEXT_OR_LRE, xslOpNames[op]);
2593         }
2594         else
2595         {
2596             if (isXSLElement(w))
2597             {
2598                 int hisflags = instrTable[toX(w) -> op].flags;
2599                 if (!(((hisflags & ELEM_TOPLEVEL) && (iData.flags & ELEM_CONT_TOPLEVEL)) ||
2600                     ((hisflags & ELEM_INSTR) && (iData.flags & ELEM_CONT_INSTR))))
2601                     Err2(S, E_ELEM_CONTAINS_ELEM, xslOpNames[op], xslOpNames[toX(w) -> op]);
2602             }
2603             else
2604                 Err1(S, E_BAD_ELEM_CONTENT, xslOpNames[op]);
2605         }
2606     };
2607 
2608     return OK;
2609 }
2610 
make1SortDef(Sit S,SortDef * & def,Context * c)2611 eFlag XSLElement::make1SortDef(Sit S, SortDef *&def, Context *c)
2612 {
2613     DStr temp;
2614 
2615     sabassert(op == XSL_SORT);
2616     def = NULL;
2617     GP( SortDef ) newDef = new SortDef;
2618 
2619     Attribute *a = atts.find(XSLA_SELECT);
2620     if (a)
2621         (*newDef).sortExpr = a -> expr;
2622 
2623     a = atts.find(XSLA_LANG);
2624     if (a)
2625     {
2626         E( a -> value(S, temp, c));
2627         (*newDef).lang = temp;
2628     }
2629     else
2630     {
2631         // lang is system-dependent!!! How about setting ""?
2632         (*newDef).lang = "en";
2633     };
2634 
2635     a = atts.find(XSLA_DATA_TYPE);
2636     if (a)
2637     {
2638         E( a -> value(S, temp, c) );
2639         if (temp == (const char*) "number")
2640             (*newDef).asText = FALSE;
2641         else
2642             if (!(temp == (const char*) "text"))
2643                 Warn1(S, W1_SORT_DATA_TYPE, temp);
2644     }
2645 
2646     a = atts.find(XSLA_ORDER);
2647     if (a)
2648     {
2649         E( a -> value(S, temp, c) );
2650         if (temp == (const char*) "descending")
2651             (*newDef).ascend = FALSE;
2652         else if (!(temp == (const char*) "ascending"))
2653             Warn1(S, W1_SORT_ORDER, temp);
2654     }
2655 
2656     a = atts.find(XSLA_CASE_ORDER);
2657     if (a)
2658     {
2659         E( a -> value(S, temp, c) );
2660         if (temp == (const char*) "lower-first")
2661             (*newDef).upper1st = FALSE;
2662         else
2663         {
2664             if (!(temp == (const char*) "upper-first"))
2665                 Warn1(S, W1_SORT_CASE_ORDER, temp);
2666             // get upper1st as system default!!
2667             (*newDef).upper1st = TRUE;
2668         }
2669     }
2670     def = newDef.keep();
2671     return OK;
2672 }
2673 
makeSortDefs(Sit S,SortDefList & sortDefs,Context * c)2674 eFlag XSLElement::makeSortDefs(Sit S, SortDefList &sortDefs, Context *c)
2675 {
2676     sabassert(op == XSL_APPLY_TEMPLATES || op == XSL_FOR_EACH);
2677 
2678     Vertex *child;
2679     for (int i = 0; i < contents.number(); i++)
2680     {
2681         child = contents[i];
2682         if (!isXSLElement(child)) break;
2683         if (toX(child) -> op == XSL_SORT)
2684         {
2685             // *** make the single sort def
2686             SortDef *newDef;
2687             E( toX(child) -> make1SortDef(S, newDef, c) );
2688             sortDefs.append(newDef);
2689 #           if !defined(SAB_WCS_COLLATE)
2690             // warn that string sorting may be incorrect -
2691             // sorting as ascii
2692             if (newDef -> asText)
2693                 Warn(S, W_NO_WCSXFRM);
2694 #           endif
2695 
2696         }
2697         else if (toX(child) -> op != XSL_WITH_PARAM) break;
2698     };
2699     return OK;
2700 }
2701 
2702 /****************************************
2703 ExtensionElement
2704 ****************************************/
2705 const char* extNSUri[] = {
2706   "http://exslt.org/functions",
2707   "http://www.exslt.org/functions",
2708   "http://exslt.org/common",
2709   NULL
2710 };
2711 
2712 const char* exsltElementsFunctions[] = {
2713   "script",
2714   NULL
2715 };
2716 
2717 const char* exsltElementsCommon[] = {
2718   "document",
2719   NULL
2720 };
2721 
ExtensionElement(Tree & owner_,QName & aqname)2722 ExtensionElement::ExtensionElement(Tree& owner_, QName& aqname)
2723 :
2724 Element(owner_, aqname, VT_EXT_ELEMENT_WF)
2725 {
2726   extns = EXTNS_UNKNOWN;
2727   op = EXTE_UNKNOWN;
2728   lookupExt(owner, aqname, extns, op);
2729 };
2730 
2731 #ifdef ENABLE_JS
executeEXSLTScript(Sit S,Context * c,Bool resolvingGlobals)2732 eFlag ExtensionElement::executeEXSLTScript(Sit S, Context *c,
2733 					   Bool resolvingGlobals)
2734 {
2735 #ifdef SABLOT_DEBUGGER
2736   if (debugger) E( debugger -> breakOnElement(S, this, c) );
2737 #endif
2738 
2739   QName attName;
2740   //why no uri?????
2741   //attName.setUri(getName().getUri());
2742   attName.setLocal(owner.unexpand("language"));
2743   Attribute *a = NZ( atts.find(attName) );
2744 
2745   QName lang;
2746   E( setLogical(S, lang, a -> cont, false) );
2747   //debug
2748   EQName elang;
2749   getOwner().expandQ(lang, elang);
2750   //debug - end
2751   if (lang.getUri() == UNDEF_PHRASE || elang.getUri() == extNSUri[0])
2752     {
2753       if (! (elang.getLocal() == (const char*)"javascript") &&
2754 	  ! (elang.getLocal() == (const char*)"ecmascript"))
2755 	return OK;
2756     }
2757   else
2758     return OK;
2759 
2760 
2761   //if (!(a -> cont == (const char*) "javascript") &&
2762   //    !(a -> cont == (const char*) "ecmascript"))
2763   //  return OK;
2764 
2765   //implements-prefix
2766   attName.setLocal(owner.unexpand("implements-prefix"));
2767   a = NZ( atts.find(attName) );
2768 
2769   Phrase uri = owner.unexpand(a -> cont);
2770   E( namespaces.resolve(S, uri, TRUE) );
2771   Str suri = owner.expand(uri);
2772   //check uri validity!!!
2773 
2774   //script
2775   DStr script;
2776 
2777   attName.setLocal(owner.unexpand("src"));
2778   a = atts.find(attName);
2779   if (a)
2780     {
2781       DataLine src;
2782       StrStrList &args = S.getProcessor() -> getArgList();
2783 
2784       const Str &base = S.findBaseURI(getSubtreeInfo() -> getBaseURI());
2785       Str absolute;
2786       makeAbsoluteURI(S, a -> cont, base, absolute);
2787 
2788       eFlag status = src.open(S, absolute, DLMODE_READ,  &args);
2789 
2790       if (status == OK)
2791 	{
2792 	  char buff[1024];
2793 	  int read;
2794 	  while ((read = src.get(S, buff, 1024)))
2795 	    {
2796 	      script.nadd(buff, read);
2797 	    }
2798 	}
2799       else
2800 	{
2801 	  E( status );
2802 	}
2803       E( src.close(S) );
2804     }
2805   else
2806     {
2807       for (int i = 0; i < contents.number(); i++)
2808 	{
2809 	  Vertex *v = contents[i];
2810 	  if ( isText(v) )
2811 	    {
2812 	      script = script + toText(v) -> cont;
2813 	    }
2814 	}
2815     }
2816   E( NZ( S.getProcessor() ) -> evaluateJavaScript(S, suri, script) );
2817   return OK;
2818 }
2819 #endif
2820 
2821 const char* _exsltDocAtts[] = {
2822   "version",
2823   "encoding",
2824   "omit-xml-declaration",
2825   "standalone",
2826   "doctype-public",
2827   "doctype-system",
2828   "indent",
2829   "media-type",
2830   NULL
2831 };
2832 
2833 XSL_ATT _exsltDocMapping[] = {
2834   XSLA_VERSION,
2835   XSLA_ENCODING,
2836   XSLA_OMIT_XML_DECL,
2837   XSLA_STANDALONE,
2838   XSLA_DOCTYPE_PUBLIC,
2839   XSLA_DOCTYPE_SYSTEM,
2840   XSLA_INDENT,
2841   XSLA_MEDIA_TYPE,
2842   XSLA_NONE
2843 };
2844 
_lookupEXSLTDocumentAttr(const char * name)2845 XSL_ATT _lookupEXSLTDocumentAttr(const char* name)
2846 {
2847   int idx = lookup(name, _exsltDocAtts);
2848   return _exsltDocMapping[idx];
2849 }
2850 
exsltDocGetOutputterDef(Sit S,Context * c,OutputDefinition & def)2851 eFlag ExtensionElement::exsltDocGetOutputterDef(Sit S, Context *c,
2852 						OutputDefinition &def)
2853 {
2854   int i, attsNumber = atts.number();
2855   Attribute *theAtt;
2856   for (i = 0; i < attsNumber; i++)
2857     {
2858       theAtt = toA(atts[i]);
2859       Str attName = getOwner().expand(theAtt -> getName().getLocal());
2860       Str attUri = getOwner().expand(theAtt -> getName().getUri());
2861 
2862       //skip xslt attributes
2863       if ( attUri == theXSLTNamespace )
2864 	continue;
2865 
2866       if (attName == (const char*) "method")
2867 	{
2868 	  QName q;
2869 	  EQName eq;
2870 	  DStr val;
2871 	  theAtt -> value(S, val, c);
2872 	  E( setLogical(S, q, val, FALSE) );
2873 	  getOwner().expandQ(q, eq);
2874 	  E( def.setItemEQName(S, XSLA_METHOD, eq, theAtt, 0) );
2875 	}
2876       else if (attName == (const char*) "cdata-section-elements")
2877 	{
2878 	  QName q;
2879 	  Bool someRemains;
2880 	  Str listPart;
2881 	  DStr val;
2882 	  theAtt -> value(S, val, c);
2883 	  char *p = (char*)val;
2884 	  do
2885 	    {
2886 	      someRemains = getWhDelimString(p, listPart);
2887 	      if (someRemains)
2888 		{
2889 		  E( setLogical(S, q, listPart, TRUE) );
2890 		  EQName expanded;
2891 		  getOwner().expandQ(q, expanded);
2892 		  E( def.setItemEQName(S, XSLA_CDATA_SECT_ELEMS,
2893 				       expanded, theAtt, 0) );
2894 		};
2895 	    }
2896 	  while (someRemains);
2897 	}
2898       else if ( !(attName == (const char*) "href") )
2899 	{
2900 	  DStr val;
2901 	  theAtt -> value(S, val, c);
2902 	  XSL_ATT attType = _lookupEXSLTDocumentAttr(attName);
2903 	  if (attType == XSLA_NONE)
2904 	    Err1(S, ET_BAD_ATTR, (char*)attName);
2905 	  E( def.setItemStr(S, attType, val, theAtt, 0) );
2906 
2907 	};
2908     };
2909   return OK;
2910 }
2911 
executeEXSLTDocument(Sit S,Context * c,Bool resolvingGlobals)2912 eFlag ExtensionElement::executeEXSLTDocument(Sit S, Context *c,
2913 					     Bool resolvingGlobals)
2914 {
2915   Processor *proc = NZ( S.getProcessor() );
2916 
2917   //get output uri
2918   QName attName;
2919   attName.setLocal(owner.unexpand("href"));
2920   Attribute *a = NZ( atts.find(attName) );
2921 
2922   DStr href;
2923   E( a -> value(S, href, c) );
2924 
2925   GP(OutputDefinition) def = new OutputDefinition();
2926   E( exsltDocGetOutputterDef(S, c, *def) );
2927 
2928   OutputDocument *doc;
2929   E( proc -> getOutputDocument(S, href, doc, def.keep()) );
2930   //we do not need to keep the definition, since document
2931   //initialized the outputter with it (I hope)
2932 
2933   Bool handleOutputter = !proc -> isInBinding();
2934 
2935   if (handleOutputter)
2936     {
2937       S.message(MT_LOG, L2_SUBDOC_STARTED, href, "output");
2938       E( proc -> startDocument(S, doc) );
2939     }
2940   else
2941     {
2942       S.message(MT_LOG, L2_SUBDOC_STARTED, href, "variable");
2943       E( proc -> outputter() -> setDocumentForLevel(S, doc) );
2944     }
2945 
2946   E( contents.execute(S, c, resolvingGlobals) );
2947 
2948   if (handleOutputter)
2949     {
2950       E( proc -> finishDocument(S, doc, TRUE) );
2951     }
2952 
2953   return OK;
2954 }
2955 
execute(Sit S,Context * c,Bool resolvingGlobals)2956 eFlag ExtensionElement::execute(Sit S, Context *c, Bool resolvingGlobals)
2957 {
2958   switch (op) {
2959   case EXTE_EXSLT_SCRIPT:
2960 #ifdef ENABLE_JS
2961     E( executeEXSLTScript(S, c, resolvingGlobals) );
2962 #else
2963     sabassert(!"JSExtension not built");
2964 #endif
2965     break;
2966   case EXTE_EXSLT_DOCUMENT:
2967     E( executeEXSLTDocument(S, c, resolvingGlobals) );
2968     break;
2969   case EXTE_UNKNOWN:
2970     {
2971       //do fallback
2972       Bool hasSome = FALSE;
2973       executeFallback(S, c, hasSome, resolvingGlobals);
2974       if (! hasSome)
2975 	{
2976 	  Str name = owner.expand(getName().getPrefix());
2977 	  name = name + ":";
2978 	  name = name + owner.expand(getName().getLocal());
2979 	  Err1(S, E_UNSUPPORTED_EXELEMENT, (char*)name);
2980 	}
2981     }; break;
2982   default:
2983     {};
2984   }
2985   return OK;
2986 }
2987 
checkChildren(Sit S)2988 eFlag ExtensionElement::checkChildren(Sit S)
2989 {
2990   switch (op) {
2991   case EXTNS_EXSLT_FUNCTIONS:
2992   case EXTNS_EXSLT_FUNCTIONS_2:
2993     {
2994       int num = contents.number();
2995       for (int i = 0; i < num; i++)
2996 	{
2997 	  Vertex *v = contents[i];
2998 	  if (!isText(v) &&
2999 	      (! isXSLElement(v) || !(toX(v) -> op == XSL_FALLBACK)) )
3000 	  {
3001 	    Err(S, E_BAD_ELEM_CONTENT);
3002 	  }
3003 	}
3004     }; break;
3005   }
3006 
3007   return OK;
3008 }
3009 
checkHasAttr(Sit S,const char * name)3010 eFlag ExtensionElement::checkHasAttr(Sit S, const char *name)
3011 {
3012   QName attName;
3013   attName.setLocal(owner.unexpand(name));
3014   Attribute *a = atts.find(attName);
3015   if (!a) Err1(S, E_ATTR_MISSING, name);
3016   return OK;
3017 }
3018 
checkAtts(Sit S)3019 eFlag ExtensionElement::checkAtts(Sit S)
3020 {
3021   switch (op) {
3022   case EXTE_EXSLT_SCRIPT:
3023     {
3024       E( checkHasAttr(S, "implements-prefix") );
3025       E( checkHasAttr(S, "language") );
3026     }; break;
3027   case EXTE_EXSLT_DOCUMENT:
3028     {
3029       E( checkHasAttr(S, "href") );
3030       //all attributes are value templates
3031       int num = atts.number();
3032       for (int i = 0; i < num; i++)
3033 	E( toA(atts[i]) -> buildExpr(S, TRUE, EX_NONE) );
3034     }; break;
3035   }
3036   return OK;
3037 }
3038 
lookupExt(Tree & tree,QName & name,ExtNamespace & extns_,ExtElement & op_)3039 void ExtensionElement::lookupExt(Tree &tree, QName &name,
3040 				 ExtNamespace &extns_, ExtElement &op_)
3041 {
3042   Str myns = tree.expand(name.getUri());
3043   Str mylocal = tree.expand(name.getLocal());
3044   extns_ = (ExtNamespace) lookup(myns, extNSUri);
3045   switch (extns_) {
3046   case EXTNS_EXSLT_FUNCTIONS:
3047   case EXTNS_EXSLT_FUNCTIONS_2:
3048     {
3049       int i = lookup(mylocal, exsltElementsFunctions);
3050       if ( exsltElementsFunctions[i] ) {
3051 	op_ = (ExtElement) (i + (int)EXTE_EXSLT_FUNCTIONS);
3052       } else {
3053 	op_ = EXTE_UNKNOWN;
3054       }
3055     }; break;
3056   case EXTNS_EXSLT_COMMON:
3057     {
3058       int i = lookup(mylocal, exsltElementsCommon);
3059       if ( exsltElementsCommon[i] ) {
3060 	op_ = (ExtElement) (i + (int)EXTE_EXSLT_COMMON);
3061       } else {
3062 	op_ = EXTE_UNKNOWN;
3063       }
3064     }; break;
3065   default:
3066     {
3067       op_ = EXTE_UNKNOWN;
3068     }
3069   }
3070   //now we have to check, whether the element is really supported
3071 #ifndef ENABLE_JS
3072   if (op_ == EXTE_EXSLT_SCRIPT) op_ = EXTE_UNKNOWN;
3073 #endif
3074 }
3075 
elementAvailable(Tree & t,QName & name)3076 Bool ExtensionElement::elementAvailable(Tree &t, QName &name)
3077 {
3078   ExtNamespace ns;
3079   ExtElement op;
3080   lookupExt(t, name, ns, op);
3081 #ifndef ENABLE_JS
3082   if (op == EXTE_EXSLT_SCRIPT) op = EXTE_UNKNOWN;
3083 #endif
3084   return op != EXTE_UNKNOWN;
3085 }
3086