msxml3: Escape '<','&','"' and '>' in attribute value.
[wine] / dlls / msxml3 / xslpattern.y
1 /*
2  *    XSLPattern parser (XSLPattern => XPath)
3  *
4  * Copyright 2010 Adam Martinson for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 %{
22 #include "config.h"
23 #include "wine/port.h"
24
25 #ifdef HAVE_LIBXML2
26 #include "xslpattern.h"
27 #include <libxml/xpathInternals.h>
28 #include "wine/debug.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
31
32
33 static const xmlChar NameTest_mod_pre[] = "*[name()='";
34 static const xmlChar NameTest_mod_post[] = "']";
35
36 #define U(str) BAD_CAST str
37
38 static inline BOOL is_literal(xmlChar const* tok)
39 {
40     return (tok && tok[0] && tok[1] &&
41             tok[0]== tok[xmlStrlen(tok)-1] &&
42             (tok[0] == '\'' || tok[0] == '"'));
43 }
44
45 static void xslpattern_error(parser_param* param, void const* scanner, char const* msg)
46 {
47     FIXME("%s:\n"
48           "  param {\n"
49           "    yyscanner=%p\n"
50           "    ctx=%p\n"
51           "    in=\"%s\"\n"
52           "    pos=%i\n"
53           "    len=%i\n"
54           "    out=\"%s\"\n"
55           "    err=%i\n"
56           "  }\n"
57           "  scanner=%p\n",
58           msg, param->yyscanner, param->ctx, param->in, param->pos,
59           param->len, param->out, ++param->err, scanner);
60 }
61
62 %}
63
64 %token TOK_Parent TOK_Self TOK_DblFSlash TOK_FSlash TOK_Axis TOK_Colon
65 %token TOK_OpAnd TOK_OpOr TOK_OpNot
66 %token TOK_OpEq TOK_OpIEq TOK_OpNEq TOK_OpINEq
67 %token TOK_OpLt TOK_OpILt TOK_OpGt TOK_OpIGt TOK_OpLEq TOK_OpILEq TOK_OpGEq TOK_OpIGEq
68 %token TOK_OpAll TOK_OpAny
69 %token TOK_NCName TOK_Literal TOK_Number
70
71 %start XSLPattern
72
73 %pure_parser
74 %parse-param {parser_param* p}
75 %parse-param {void* scanner}
76 %lex-param {yyscan_t* scanner}
77
78 %left TOK_OpAnd TOK_OpOr
79 %left TOK_OpEq TOK_OpIEq TOK_OpNEq TOK_OpINEq
80 %left TOK_OpLt TOK_OpILt TOK_OpGt TOK_OpIGt TOK_OpLEq TOK_OpILEq TOK_OpGEq TOK_OpIGEq
81
82 %expect 14
83
84 %%
85
86     XSLPattern              : Expr
87                             {
88                                 p->out = $1;
89                             }
90     ;
91
92 /* Mostly verbatim from the w3c XML Namespaces standard.
93  * <http://www.w3.org/TR/REC-xml-names/> */
94
95     /* [4] Qualified Names */
96     QName                   : PrefixedName
97                             | UnprefixedName
98     ;
99     PrefixedName            : TOK_NCName TOK_Colon TOK_NCName
100                             {
101                                 TRACE("Got PrefixedName: \"%s:%s\"\n", $1, $3);
102                                 $$=$1;
103                                 $$=xmlStrcat($$,U(":"));
104                                 $$=xmlStrcat($$,$3);
105                                 xmlFree($3);
106                             }
107     ;
108     UnprefixedName          : TOK_NCName
109                             {
110                                 TRACE("Got UnprefixedName: \"%s\"\n", $1);
111                                 $$=$1;
112                             }
113     ;
114
115 /* Based on the w3c XPath standard, adapted where needed.
116  * <http://www.w3.org/TR/xpath/> */
117
118     /* [2] Location Paths */
119     LocationPath            : RelativeLocationPath
120                             | AbsoluteLocationPath
121     ;
122     AbsoluteLocationPath    : TOK_FSlash RelativeLocationPath
123                             {
124                                 TRACE("Got AbsoluteLocationPath: \"/%s\"\n", $2);
125                                 $$=xmlStrdup(U("/"));
126                                 $$=xmlStrcat($$,$2);
127                                 xmlFree($2);
128                             }
129                             | TOK_FSlash
130                             {
131                                 TRACE("Got AbsoluteLocationPath: \"/\"\n");
132                                 $$=xmlStrdup(U("/"));
133                             }
134                             | AbbreviatedAbsoluteLocationPath
135     ;
136     RelativeLocationPath    : Step
137                             | RelativeLocationPath TOK_FSlash Step
138                             {
139                                 TRACE("Got RelativeLocationPath: \"%s/%s\"\n", $1, $3);
140                                 $$=$1;
141                                 $$=xmlStrcat($$,U("/"));
142                                 $$=xmlStrcat($$,$3);
143                                 xmlFree($3);
144                             }
145                             | AbbreviatedRelativeLocationPath
146     ;
147     /* [2.1] Location Steps */
148     Step                    : AxisSpecifier NodeTest Predicates
149                             {
150                                 TRACE("Got Step: \"%s%s%s\"\n", $1, $2, $3);
151                                 $$=$1;
152                                 $$=xmlStrcat($$,$2);
153                                 xmlFree($2);
154                                 $$=xmlStrcat($$,$3);
155                                 xmlFree($3);
156                             }
157                             | NodeTest Predicates
158                             {
159                                 TRACE("Got Step: \"%s%s\"\n", $1, $2);
160                                 $$=$1;
161                                 $$=xmlStrcat($$,$2);
162                                 xmlFree($2);
163                             }
164                             | AxisSpecifier NodeTest
165                             {
166                                 TRACE("Got Step: \"%s%s\"\n", $1, $2);
167                                 $$=$1;
168                                 $$=xmlStrcat($$,$2);
169                                 xmlFree($2);
170                             }
171                             | NodeTest
172                             | Attribute
173                             | AbbreviatedStep
174     ;
175     AxisSpecifier           : TOK_NCName TOK_Axis
176                             {
177                                 TRACE("Got AxisSpecifier: \"%s::\"\n", $1);
178                                 $$=$1;
179                                 $$=xmlStrcat($$,U("::"));
180                             }
181     ;
182     Attribute               : '@' QName
183                             {
184                                 TRACE("Got Attribute: \"@%s\"\n", $2);
185                                 $$=xmlStrdup(U("@"));
186                                 $$=xmlStrcat($$,$2);
187                                 xmlFree($2);
188                             }
189     ;
190
191     /* [2.3] Node Tests */
192     NodeTest                : NameTest
193                             | FunctionCall
194     ;
195     NameTest                : '*'
196                             {
197                                 TRACE("Got NameTest: \"*\"\n");
198                                 $$=xmlStrdup(U("*"));
199                             }
200                             | TOK_NCName TOK_Colon '*'
201                             {
202                                 TRACE("Got NameTest: \"%s:*\"\n", $1);
203                                 $$=$1;
204                                 $$=xmlStrcat($$,U(":*"));
205                             }
206                             | TOK_NCName TOK_Colon TOK_NCName
207                             { /* PrefixedName */
208                                 xmlChar const* registeredNsURI = xmlXPathNsLookup(p->ctx, $1);
209                                 TRACE("Got PrefixedName: \"%s:%s\"\n", $1, $3);
210
211                                 if (registeredNsURI)
212                                     $$=xmlStrdup(U(""));
213                                 else
214                                     $$=xmlStrdup(NameTest_mod_pre);
215
216                                 $$=xmlStrcat($$,$1);
217                                 xmlFree($1);
218                                 $$=xmlStrcat($$,U(":"));
219                                 $$=xmlStrcat($$,$3);
220                                 xmlFree($3);
221
222                                 if (!registeredNsURI)
223                                     $$=xmlStrcat($$,NameTest_mod_post);
224                             }
225                             | UnprefixedName
226                             {
227                                 $$=xmlStrdup(NameTest_mod_pre);
228                                 $$=xmlStrcat($$,$1);
229                                 xmlFree($1);
230                                 $$=xmlStrcat($$,NameTest_mod_post);
231                             }
232     /* [2.4] Predicates */
233     Predicates              : Predicates Predicate
234                             {
235                                 $$=$1;
236                                 $$=xmlStrcat($$,$2);
237                                 xmlFree($2);
238                             }
239                             | Predicate
240     ;
241     Predicate               : '[' PredicateExpr ']'
242                             {
243                                 TRACE("Got Predicate: \"[%s]\"\n", $2);
244                                 $$=xmlStrdup(U("["));
245                                 $$=xmlStrcat($$,$2);
246                                 xmlFree($2);
247                                 $$=xmlStrcat($$,U("]"));
248                             }
249     ;
250     PredicateExpr           : TOK_Number
251                             {
252                                 $$=xmlStrdup(U("index()="));
253                                 $$=xmlStrcat($$,$1);
254                                 xmlFree($1);
255                             }
256                             | BoolExpr
257                             | Attribute
258     ;
259     /* [2.5] Abbreviated Syntax */
260     AbbreviatedAbsoluteLocationPath : TOK_DblFSlash RelativeLocationPath
261                             {
262                                 TRACE("Got AbbreviatedAbsoluteLocationPath: \"//%s\"\n", $2);
263                                 $$=xmlStrdup(U("//"));
264                                 $$=xmlStrcat($$,$2);
265                                 xmlFree($2);
266                             }
267     ;
268     AbbreviatedRelativeLocationPath : RelativeLocationPath TOK_DblFSlash Step
269                             {
270                                 TRACE("Got AbbreviatedRelativeLocationPath: \"%s//%s\"\n", $1, $3);
271                                 $$=$1;
272                                 $$=xmlStrcat($$,U("//"));
273                                 $$=xmlStrcat($$,$3);
274                                 xmlFree($3);
275                             }
276     ;
277     AbbreviatedStep         : TOK_Parent
278                             {
279                                 TRACE("Got AbbreviatedStep: \"..\"\n");
280                                 $$=xmlStrdup(U(".."));
281                             }
282                             | TOK_Self
283                             {
284                                 TRACE("Got AbbreviatedStep: \".\"\n");
285                                 $$=xmlStrdup(U("."));
286                             }
287     ;
288
289     /* [3] Expressions */
290     /* [3.1] Basics */
291     Expr                    : OrExpr
292     ;
293     BoolExpr                : FunctionCall
294                             | BoolUnaryExpr
295                             | BoolRelationalExpr
296                             | BoolEqualityExpr
297                             | BoolAndExpr
298                             | BoolOrExpr
299     ;
300     PrimaryExpr             : '(' Expr ')'
301                             {
302                                 TRACE("Got PrimaryExpr: \"(%s)\"\n", $1);
303                                 $$=xmlStrdup(U("("));
304                                 $$=xmlStrcat($$,$2);
305                                 xmlFree($2);
306                                 $$=xmlStrcat($$,U(")"));
307                             }
308                             | PathExpr '!' FunctionCall
309                             {
310                                 TRACE("Got PrimaryExpr: \"%s!%s\"\n", $1, $3);
311                                 $$=$1;
312                                 $$=xmlStrcat($$,U("/"));
313                                 $$=xmlStrcat($$,$3);
314                                 xmlFree($3);
315                             }
316                             | TOK_Literal
317                             | TOK_Number
318     ;
319     /* [3.2] Function Calls */
320     FunctionCall            : QName '(' Arguments ')'
321                             {
322                                 TRACE("Got FunctionCall: \"%s(%s)\"\n", $1, $3);
323                                 if (xmlStrEqual($1,U("ancestor")))
324                                 {
325                                     $$=$1;
326                                     $$=xmlStrcat($$,U("::"));
327                                     $$=xmlStrcat($$,$3);
328                                     xmlFree($3);
329                                 }
330                                 else if (xmlStrEqual($1,U("attribute")))
331                                 {
332                                     if (is_literal($3))
333                                     {
334                                         $$=xmlStrdup(U("@*[name()="));
335                                         xmlFree($1);
336                                         $$=xmlStrcat($$,$3);
337                                         xmlFree($3);
338                                         $$=xmlStrcat($$,U("]"));
339                                     }
340                                     else
341                                     {
342                                         /* XML_XPATH_INVALID_TYPE */
343                                         $$=xmlStrdup(U("error(1211, 'Error: attribute("));
344                                         xmlFree($1);
345                                         $$=xmlStrcat($$,$3);
346                                         xmlFree($3);
347                                         $$=xmlStrcat($$,U("): invalid argument')"));
348                                     }
349                                 }
350                                 else if (xmlStrEqual($1,U("element")))
351                                 {
352                                     if (is_literal($3))
353                                     {
354                                         $$=xmlStrdup(U("node()[nodeType()=1][name()="));
355                                         xmlFree($1);
356                                         $$=xmlStrcat($$,$3);
357                                         xmlFree($3);
358                                         $$=xmlStrcat($$,U("]"));
359                                     }
360                                     else
361                                     {
362                                         /* XML_XPATH_INVALID_TYPE */
363                                         $$=xmlStrdup(U("error(1211, 'Error: element("));
364                                         xmlFree($1);
365                                         $$=xmlStrcat($$,$3);
366                                         xmlFree($3);
367                                         $$=xmlStrcat($$,U("): invalid argument')"));
368                                     }
369                                 }
370                                 else
371                                 {
372                                     $$=$1;
373                                     $$=xmlStrcat($$,U("("));
374                                     $$=xmlStrcat($$,$3);
375                                     xmlFree($3);
376                                     $$=xmlStrcat($$,U(")"));
377                                 }
378                             }
379                             | QName '(' ')'
380                             {
381                                 TRACE("Got FunctionCall: \"%s()\"\n", $1);
382                                 /* comment() & node() work the same in XPath */
383                                 if (xmlStrEqual($1,U("attribute")))
384                                 {
385                                     $$=xmlStrdup(U("@*"));
386                                     xmlFree($1);
387                                 }
388                                 else if (xmlStrEqual($1,U("element")))
389                                 {
390                                     $$=xmlStrdup(U("node()[nodeType()=1]"));
391                                     xmlFree($1);
392                                 }
393                                 else if (xmlStrEqual($1,U("pi")))
394                                 {
395                                     $$=xmlStrdup(U("processing-instruction()"));
396                                     xmlFree($1);
397                                 }
398                                 else if (xmlStrEqual($1,U("textnode")))
399                                 {
400                                     $$=xmlStrdup(U("text()"));
401                                     xmlFree($1);
402                                 }
403                                 else
404                                 {
405                                     $$=$1;
406                                     $$=xmlStrcat($$,U("()"));
407                                 }
408                             }
409     ;
410     Arguments               : Argument ',' Arguments
411                             {
412                                 $$=$1;
413                                 $$=xmlStrcat($$,U(","));
414                                 $$=xmlStrcat($$,$3);
415                                 xmlFree($3);
416                             }
417                             | Argument
418     ;
419     Argument                : Expr
420     ;
421     /* [3.3] Node-sets */
422     UnionExpr               : PathExpr
423                             | UnionExpr '|' PathExpr
424                             {
425                                 TRACE("Got UnionExpr: \"%s|%s\"\n", $1, $3);
426                                 $$=$1;
427                                 $$=xmlStrcat($$,U("|"));
428                                 $$=xmlStrcat($$,$3);
429                                 xmlFree($3);
430                             }
431     ;
432     PathExpr                : LocationPath
433                             | FilterExpr TOK_FSlash RelativeLocationPath
434                             {
435                                 TRACE("Got PathExpr: \"%s/%s\"\n", $1, $3);
436                                 $$=$1;
437                                 $$=xmlStrcat($$,U("/"));
438                                 $$=xmlStrcat($$,$3);
439                                 xmlFree($3);
440                             }
441                             | FilterExpr TOK_DblFSlash RelativeLocationPath
442                             {
443                                 TRACE("Got PathExpr: \"%s//%s\"\n", $1, $3);
444                                 $$=$1;
445                                 $$=xmlStrcat($$,U("//"));
446                                 $$=xmlStrcat($$,$3);
447                                 xmlFree($3);
448                             }
449                             | FilterExpr
450     ;
451     FilterExpr              : PrimaryExpr
452                             | FilterExpr Predicate
453                             {
454                                 TRACE("Got FilterExpr: \"%s%s\"\n", $1, $2);
455                                 $$=$1;
456                                 $$=xmlStrcat($$,$2);
457                                 xmlFree($2);
458                             }
459     ;
460     /* [3.4] Booleans */
461     OrExpr                  : AndExpr
462                             | BoolOrExpr
463     ;
464     BoolOrExpr              : OrExpr TOK_OpOr AndExpr
465                             {
466                                 TRACE("Got OrExpr: \"%s $or$ %s\"\n", $1, $3);
467                                 $$=$1;
468                                 $$=xmlStrcat($$,U(" or "));
469                                 $$=xmlStrcat($$,$3);
470                                 xmlFree($3);
471                             }
472     ;
473     AndExpr                 : EqualityExpr
474                             | BoolAndExpr
475     ;
476     BoolAndExpr             : AndExpr TOK_OpAnd EqualityExpr
477                             {
478                                 TRACE("Got AndExpr: \"%s $and$ %s\"\n", $1, $3);
479                                 $$=$1;
480                                 $$=xmlStrcat($$,U(" and "));
481                                 $$=xmlStrcat($$,$3);
482                                 xmlFree($3);
483                             }
484     ;
485     EqualityExpr            : RelationalExpr
486                             | BoolEqualityExpr
487     ;
488     BoolEqualityExpr        : EqualityExpr TOK_OpEq RelationalExpr
489                             {
490                                 TRACE("Got EqualityExpr: \"%s $eq$ %s\"\n", $1, $3);
491                                 $$=$1;
492                                 $$=xmlStrcat($$,U("="));
493                                 $$=xmlStrcat($$,$3);
494                                 xmlFree($3);
495                             }
496                             | EqualityExpr TOK_OpIEq RelationalExpr
497                             {
498                                 TRACE("Got EqualityExpr: \"%s $ieq$ %s\"\n", $1, $3);
499                                 $$=xmlStrdup(U("OP_IEq("));
500                                 $$=xmlStrcat($$,$1);
501                                 xmlFree($1);
502                                 $$=xmlStrcat($$,U(","));
503                                 $$=xmlStrcat($$,$3);
504                                 xmlFree($3);
505                                 $$=xmlStrcat($$,U(")"));
506                             }
507                             | EqualityExpr TOK_OpNEq RelationalExpr
508                             {
509                                 TRACE("Got EqualityExpr: \"%s $ne$ %s\"\n", $1, $3);
510                                 $$=$1;
511                                 $$=xmlStrcat($$,U("!="));
512                                 $$=xmlStrcat($$,$3);
513                                 xmlFree($3);
514                             }
515                             | EqualityExpr TOK_OpINEq RelationalExpr
516                             {
517                                 TRACE("Got EqualityExpr: \"%s $ine$ %s\"\n", $1, $3);
518                                 $$=xmlStrdup(U("OP_INEq("));
519                                 $$=xmlStrcat($$,$1);
520                                 xmlFree($1);
521                                 $$=xmlStrcat($$,U(","));
522                                 $$=xmlStrcat($$,$3);
523                                 xmlFree($3);
524                                 $$=xmlStrcat($$,U(")"));
525                             }
526     ;
527     RelationalExpr          : UnaryExpr
528                             | BoolRelationalExpr
529     ;
530     BoolRelationalExpr      : RelationalExpr TOK_OpLt UnaryExpr
531                             {
532                                 TRACE("Got RelationalExpr: \"%s $lt$ %s\"\n", $1, $3);
533                                 $$=$1;
534                                 $$=xmlStrcat($$,U("<"));
535                                 $$=xmlStrcat($$,$3);
536                                 xmlFree($3);
537                             }
538                             | RelationalExpr TOK_OpILt UnaryExpr
539                             {
540                                 TRACE("Got RelationalExpr: \"%s $ilt$ %s\"\n", $1, $3);
541                                 $$=xmlStrdup(U("OP_ILt("));
542                                 $$=xmlStrcat($$,$1);
543                                 xmlFree($1);
544                                 $$=xmlStrcat($$,U(","));
545                                 $$=xmlStrcat($$,$3);
546                                 xmlFree($3);
547                                 $$=xmlStrcat($$,U(")"));
548                             }
549                             | RelationalExpr TOK_OpGt UnaryExpr
550                             {
551                                 TRACE("Got RelationalExpr: \"%s $gt$ %s\"\n", $1, $3);
552                                 $$=$1;
553                                 $$=xmlStrcat($$,U(">"));
554                                 $$=xmlStrcat($$,$3);
555                                 xmlFree($3);
556                             }
557                             | RelationalExpr TOK_OpIGt UnaryExpr
558                             {
559                                 TRACE("Got RelationalExpr: \"%s $igt$ %s\"\n", $1, $3);
560                                 $$=xmlStrdup(U("OP_IGt("));
561                                 $$=xmlStrcat($$,$1);
562                                 xmlFree($1);
563                                 $$=xmlStrcat($$,U(","));
564                                 $$=xmlStrcat($$,$3);
565                                 xmlFree($3);
566                                 $$=xmlStrcat($$,U(")"));
567                             }
568                             | RelationalExpr TOK_OpLEq UnaryExpr
569                             {
570                                 TRACE("Got RelationalExpr: \"%s $le$ %s\"\n", $1, $3);
571                                 $$=$1;
572                                 $$=xmlStrcat($$,U("<="));
573                                 $$=xmlStrcat($$,$3);
574                                 xmlFree($3);
575                             }
576                             | RelationalExpr TOK_OpILEq UnaryExpr
577                             {
578                                 TRACE("Got RelationalExpr: \"%s $ile$ %s\"\n", $1, $3);
579                                 $$=xmlStrdup(U("OP_ILEq("));
580                                 $$=xmlStrcat($$,$1);
581                                 xmlFree($1);
582                                 $$=xmlStrcat($$,U(","));
583                                 $$=xmlStrcat($$,$3);
584                                 xmlFree($3);
585                                 $$=xmlStrcat($$,U(")"));
586                             }
587                             | RelationalExpr TOK_OpGEq UnaryExpr
588                             {
589                                 TRACE("Got RelationalExpr: \"%s $ge$ %s\"\n", $1, $3);
590                                 $$=$1;
591                                 $$=xmlStrcat($$,U(">="));
592                                 $$=xmlStrcat($$,$3);
593                                 xmlFree($3);
594                             }
595                             | RelationalExpr TOK_OpIGEq UnaryExpr
596                             {
597                                 TRACE("Got RelationalExpr: \"%s $ige$ %s\"\n", $1, $3);
598                                 $$=xmlStrdup(U("OP_IGEq("));
599                                 $$=xmlStrcat($$,$1);
600                                 xmlFree($1);
601                                 $$=xmlStrcat($$,U(","));
602                                 $$=xmlStrcat($$,$3);
603                                 xmlFree($3);
604                                 $$=xmlStrcat($$,U(")"));
605                             }
606     ;
607
608     /* [3.5] Numbers */
609     UnaryExpr               : UnionExpr
610                             | BoolUnaryExpr
611     ;
612     BoolUnaryExpr           : TOK_OpNot UnaryExpr
613                             {
614                                 TRACE("Got UnaryExpr: \"$not$ %s\"\n", $2);
615                                 $$=xmlStrdup(U(" not("));
616                                 $$=xmlStrcat($$,$2);
617                                 xmlFree($2);
618                                 $$=xmlStrcat($$,U(")"));
619                             }
620                             | TOK_OpAny Expr
621                             {
622                                 TRACE("Got UnaryExpr: \"$any$ %s\"\n", $2);
623                                 $$=xmlStrdup(U("boolean("));
624                                 $$=xmlStrcat($$,$2);
625                                 xmlFree($2);
626                                 $$=xmlStrcat($$,U(")"));
627                             }
628                             | TOK_OpAll AllExpr
629                             {
630                                 TRACE("Got UnaryExpr: \"$all$ %s\"\n", $2);
631                                 $$=xmlStrdup(U("not("));
632                                 $$=xmlStrcat($$,$2);
633                                 xmlFree($2);
634                                 $$=xmlStrcat($$,U(")"));
635                             }
636                             | TOK_OpAll
637                             {
638                                 FIXME("Unrecognized $all$ expression - ignoring\n");
639                                 $$=xmlStrdup(U(""));
640                             }
641     ;
642     AllExpr                 : PathExpr TOK_OpEq PathExpr
643                             {
644                                 $$=$1;
645                                 $$=xmlStrcat($$,U("!="));
646                                 $$=xmlStrcat($$,$3);
647                                 xmlFree($3);
648                             }
649                             | PathExpr TOK_OpNEq PathExpr
650                             {
651                                 $$=$1;
652                                 $$=xmlStrcat($$,U("="));
653                                 $$=xmlStrcat($$,$3);
654                                 xmlFree($3);
655                             }
656                             | PathExpr TOK_OpLt PathExpr
657                             {
658                                 $$=$1;
659                                 $$=xmlStrcat($$,U(">="));
660                                 $$=xmlStrcat($$,$3);
661                                 xmlFree($3);
662                             }
663                             | PathExpr TOK_OpLEq PathExpr
664                             {
665                                 $$=$1;
666                                 $$=xmlStrcat($$,U(">"));
667                                 $$=xmlStrcat($$,$3);
668                                 xmlFree($3);
669                             }
670                             | PathExpr TOK_OpGt PathExpr
671                             {
672                                 $$=$1;
673                                 $$=xmlStrcat($$,U("<="));
674                                 $$=xmlStrcat($$,$3);
675                                 xmlFree($3);
676                             }
677                             | PathExpr TOK_OpGEq PathExpr
678                             {
679                                 $$=$1;
680                                 $$=xmlStrcat($$,U("<"));
681                                 $$=xmlStrcat($$,$3);
682                                 xmlFree($3);
683                             }
684                             | PathExpr TOK_OpIEq PathExpr
685                             {
686                                 $$=xmlStrdup(U("OP_INEq("));
687                                 $$=xmlStrcat($$,$1);
688                                 xmlFree($1);
689                                 $$=xmlStrcat($$,U(","));
690                                 $$=xmlStrcat($$,$3);
691                                 xmlFree($3);
692                                 $$=xmlStrcat($$,U(")"));
693                             }
694                             | PathExpr TOK_OpINEq PathExpr
695                             {
696                                 $$=xmlStrdup(U("OP_IEq("));
697                                 $$=xmlStrcat($$,$1);
698                                 xmlFree($1);
699                                 $$=xmlStrcat($$,U(","));
700                                 $$=xmlStrcat($$,$3);
701                                 xmlFree($3);
702                                 $$=xmlStrcat($$,U(")"));
703                             }
704                             | PathExpr TOK_OpILt PathExpr
705                             {
706                                 $$=xmlStrdup(U("OP_IGEq("));
707                                 $$=xmlStrcat($$,$1);
708                                 xmlFree($1);
709                                 $$=xmlStrcat($$,U(","));
710                                 $$=xmlStrcat($$,$3);
711                                 xmlFree($3);
712                                 $$=xmlStrcat($$,U(")"));
713                             }
714                             | PathExpr TOK_OpILEq PathExpr
715                             {
716                                 $$=xmlStrdup(U("OP_IGt("));
717                                 $$=xmlStrcat($$,$1);
718                                 xmlFree($1);
719                                 $$=xmlStrcat($$,U(","));
720                                 $$=xmlStrcat($$,$3);
721                                 xmlFree($3);
722                                 $$=xmlStrcat($$,U(")"));
723                             }
724                             | PathExpr TOK_OpIGt PathExpr
725                             {
726                                 $$=xmlStrdup(U("OP_ILEq("));
727                                 $$=xmlStrcat($$,$1);
728                                 xmlFree($1);
729                                 $$=xmlStrcat($$,U(","));
730                                 $$=xmlStrcat($$,$3);
731                                 xmlFree($3);
732                                 $$=xmlStrcat($$,U(")"));
733                             }
734                             | PathExpr TOK_OpIGEq PathExpr
735                             {
736                                 $$=xmlStrdup(U("OP_ILt("));
737                                 $$=xmlStrcat($$,$1);
738                                 xmlFree($1);
739                                 $$=xmlStrcat($$,U(","));
740                                 $$=xmlStrcat($$,$3);
741                                 xmlFree($3);
742                                 $$=xmlStrcat($$,U(")"));
743                             }
744     ;
745
746 %%
747
748 #endif  /* HAVE_LIBXML2 */