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 ©buf)
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