/demo/generic/domxpath.c
C | 1902 lines | 1683 code | 111 blank | 108 comment | 194 complexity | 681d1290e61b202fd229fbf3f2fbe79d MD5 | raw file
Possible License(s): LGPL-2.1
Large files files are truncated, but you can click here to view the full file
- /*----------------------------------------------------------------------------
- | Copyright (c) 1999-2001 Jochen Loewer (loewerj@hotmail.com)
- |-----------------------------------------------------------------------------
- |
- | $Id: domxpath.c,v 1.94 2007/08/05 17:52:35 rolf Exp $
- |
- |
- | A XPath implementation (lexer/parser/evaluator) for tDOM,
- | the DOM implementation for Tcl.
- | Based on November 16 1999 Recommendation of the W3C
- | (http://www.w3.org/TR/1999/REC-xslt-19991116)
- |
- |
- | The contents of this file are subject to the Mozilla Public License
- | Version 1.1 (the "License"); you may not use this file except in
- | compliance with the License. You may obtain a copy of the License at
- | http://www.mozilla.org/MPL/
- |
- | Software distributed under the License is distributed on an "AS IS"
- | basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- | License for the specific language governing rights and limitations
- | under the License.
- |
- | The Original Code is tDOM.
- |
- | The Initial Developer of the Original Code is Jochen Loewer
- | Portions created by Jochen Loewer are Copyright (C) 1999 - 2001
- | Jochen Loewer. All Rights Reserved.
- |
- | Portions created by Zoran Vasiljevic are Copyright (C) 2000-2002
- | Zoran Vasiljevic. All Rights Reserved.
- |
- | Portions created by Rolf Ade are Copyright (C) 1999-2007
- | Rolf Ade. All Rights Reserved.
- |
- | Contributor(s):
- | April00 Rolf Ade Add support for following/preceding/
- | precedingSibling axis plus several
- | bug fixes
- |
- | Aug00 Rolf Ade Rewrite of comparisons plus several
- | bug fixes/reports
- |
- | Aug01 Rolf Ade id(), unparsed-entity(), lang(), fixes
- |
- | 2002 Rolf Ade Namespace aware nodetests and NS wildcard
- | expr, namespace aware variables, keys and
- | function, made lexer utf-8 aware, node sets
- | could now include nodes of different types,
- | better IEEE 754 rules support, code
- | restructured, serveral optimizations and bug
- | fixes.
- |
- | written by Jochen Loewer
- | July, 1999
- |
- \---------------------------------------------------------------------------*/
- /*----------------------------------------------------------------------------
- | Includes
- |
- \---------------------------------------------------------------------------*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <float.h>
- #include <math.h>
- #include <limits.h>
- #include <ctype.h>
- #include <dom.h>
- #include <domxpath.h>
- #include <domxslt.h>
- /*----------------------------------------------------------------------------
- | Macros
- |
- \---------------------------------------------------------------------------*/
- #define JDBG(x)
- #define DBG(x)
- #define DDBG(x)
- #define TRACE(x) DDBG(fprintf(stderr,(x)))
- #define TRACE1(x,a) DDBG(fprintf(stderr,(x),(a)))
- #define TRACE2(x,a,b) DDBG(fprintf(stderr,(x),(a),(b)))
- #define TRACE3(x,a,b,c) DDBG(fprintf(stderr,(x),(a),(b),(c)))
- #define INITIAL_SIZE 100
- #define ADD_TOKEN(t) if ((l+1)>=allocated) { \
- tokens=(XPathTokens)REALLOC((char*)tokens, 2*allocated\
- *sizeof(XPathToken)); \
- allocated = allocated * 2; \
- } \
- tokens[l].token = (t); \
- tokens[l++].pos = i; \
- tokens[l].token = EOS; \
- tokens[l].strvalue = NULL; \
- tokens[l].intvalue = 0; \
- tokens[l].realvalue = 0.0;
- #define DeclProduction(name) static ast name (int *l,XPathTokens tokens,char **errMsg)
- #define Production(name) static ast name (int *l,XPathTokens tokens,char **errMsg) \
- { char *__func = #name; \
- ast a = NULL; \
- TRACE2("\nProduction "#name": start l=%d next:%s\n", \
- *l,token2str[tokens[*l].token]);
- #define EndProduction TRACE3("EndProd %s: start l=%d next:%s\n", \
- __func, *l,token2str[tokens[*l].token]); \
- DDBG(printAst(0,a);) \
- return a; \
- }
- #define LA tokens[*l].token
- #define LA2 tokens[*l+1].token
- #define LA3 tokens[*l+2].token
- /* #define Recurse(p) rc=p(l,tokens,errMsg);if(rc==NULL)return rc;*/
- #define Recurse(p) p(l,tokens,errMsg)
- #define Consume(tk) if (tokens[*l].token == tk) { \
- TRACE2("Production %s: %s consumed\n", \
- __func, token2str[tokens[*l].token]); \
- (*l)++; \
- } else { \
- if (*errMsg==NULL) {ErrExpected(#tk);} \
- else return a; \
- }
- #define STRVAL tokens[(*l)-1].strvalue
- #define INTVAL tokens[(*l)-1].intvalue
- #define REALVAL tokens[(*l)-1].realvalue
- #define NEWCONS ((ast)MALLOC(sizeof(astElem)))
- #define IS_STR(c,s) (c==*(tokens[(*l)-1].strvalue))&&(strcmp(tokens[(*l)-1].strvalue,s)==0)
- #define IS_FUNC(c,s) ((*(step->strvalue)==(c)) && (strcmp((s),step->strvalue)==0))
- #define ErrExpected(msg) *errMsg = (char*)MALLOC(255); \
- **errMsg = '\0'; \
- strcpy(*errMsg, __func); \
- strcat(*errMsg, ": Expected " #msg); \
- return a;
- #define CHECK_RC if (rc) return rc
- #define checkRsAddNode(rs,node) if (useFastAdd) rsAddNodeFast( rs,node); \
- else rsAddNode (rs,node);
- /*----------------------------------------------------------------------------
- | Types for Lexer
- |
- \---------------------------------------------------------------------------*/
- typedef enum {
- LPAR, RPAR, LBRACKET, RBRACKET, DOT, DOTDOT, ATTRIBUTEPREFIX,
- ATTRIBUTE, COMMA, COLONCOLON, LITERAL, NSPREFIX, NSWC,
- INTNUMBER, REALNUMBER, SLASH, SLASHSLASH,
- PIPE, PLUS, MINUS, EQUAL, NOTEQ, LT, LTE, GT, GTE,
- AND, OR, MOD, DIV, MULTIPLY, FUNCTION, VARIABLE,
- FQVARIABLE, WCARDNAME, COMMENT, TEXT, PINSTR, NODE, AXISNAME,
- EOS
- } Token;
- static char *token2str[] = {
- "LPAR", "RPAR", "LBRACKET", "RBRACKET", "DOT", "DOTDOT", "ATTRIBUTEPREFIX",
- "ATTRIBUTE", "COMMA", "COLONCOLON", "LITERAL", "NSPREFIX", "NSWC",
- "INTNUMBER", "REALNUMBER", "SLASH", "SLASHSLASH",
- "PIPE", "PLUS", "MINUS", "EQUAL", "NOTEQ", "LT", "LTE", "GT", "GTE",
- "AND", "OR", "MOD", "DIV", "MULTIPLY", "FUNCTION", "VARIABLE",
- "FQVARIABLE", "WCARDNAME", "COMMENT", "TEXT", "PI", "NODE", "AXISNAME",
- "EOS"
- };
- typedef struct {
- Token token;
- char *strvalue;
- int intvalue;
- double realvalue;
- int pos;
- } XPathToken;
- typedef XPathToken *XPathTokens;
- /*----------------------------------------------------------------------------
- | Types for abstract syntax trees
- |
- \---------------------------------------------------------------------------*/
- static char *astType2str[] = {
- "Int", "Real", "Mult", "Div", "Mod", "UnaryMinus", "IsNSElement",
- "IsNode", "IsComment", "IsText", "IsPI", "IsSpecificPI", "IsElement",
- "IsFQElement", "GetVar", "GetFQVar", "Literal", "ExecFunction", "Pred",
- "EvalSteps", "SelectRoot", "CombineSets", "Add", "Substract", "Less",
- "LessOrEq", "Greater", "GreaterOrEq", "Equal", "NotEqual", "And", "Or",
- "IsNSAttr", "IsAttr", "AxisAncestor", "AxisAncestorOrSelf",
- "AxisAttribute", "AxisChild",
- "AxisDescendant", "AxisDescendantOrSelf", "AxisFollowing",
- "AxisFollowingSibling", "AxisNamespace", "AxisParent",
- "AxisPreceding", "AxisPrecedingSilbing", "AxisSelf",
- "GetContextNode", "GetParentNode", "AxisDescendantOrSelfLit",
- "AxisDescendantLit", "SlashSlash",
- "CombinePath", "IsRoot", "ToParent", "ToAncestors", "FillNodeList",
- "FillWithCurrentNode",
- "ExecIdKey"
- };
- /*----------------------------------------------------------------------------
- | functionTag
- |
- \---------------------------------------------------------------------------*/
- typedef enum {
- f_unknown = 1,
- f_boolean, f_ceiling, f_concat, f_contains, f_count, f_false, f_floor,
- f_generateId, f_id, f_lang, f_last, f_localName, f_name, f_namespaceUri,
- f_normalizeSpace, f_not, f_number, f_position, f_round, f_startsWith,
- f_string, f_stringLength, f_substring, f_substringAfter,
- f_substringBefore, f_sum, f_translate, f_true, f_unparsedEntityUri,
- f_fqfunction
- } functionTag;
- /*----------------------------------------------------------------------------
- | Prototypes / Forwards
- |
- \---------------------------------------------------------------------------*/
- DeclProduction(OrExpr);
- DeclProduction(Predicate);
- DeclProduction(RelativeLocationPath);
- DeclProduction(AbsoluteLocationPath);
- char *xpathFuncString (xpathResultSet *rs );
- static int xpathEvalStep (ast step, domNode *ctxNode, domNode *exprContext,
- int position, xpathResultSet *nodeList,
- xpathCBs *cbs, xpathResultSet *result,
- int *docOrder, char **errMsg);
- static int xpathEvalPredicate (ast steps, domNode *exprContext,
- xpathResultSet *result,
- xpathResultSet *stepResult,
- xpathCBs *cbs, int *docOrder, char **errMsg);
- /*----------------------------------------------------------------------------
- | xpath result set functions
- |
- \---------------------------------------------------------------------------*/
- void xpathRSFree ( xpathResultSet *rs ) {
- if (rs->type == xNodeSetResult) {
- if (!rs->intvalue) {
- if (rs->nodes) FREE((char*)rs->nodes);
- }
- rs->nr_nodes = 0;
- } else
- if (rs->type == StringResult) {
- if (rs->string) FREE((char*)rs->string);
- }
- rs->type = EmptyResult;
- }
- void rsPrint ( xpathResultSet *rs ) {
- int i = 0,l; char tmp[80];
- switch (rs->type) {
- case EmptyResult:
- fprintf(stderr, "empty result \n");
- break;
- case BoolResult:
- fprintf(stderr, "boolean result: %d \n", rs->intvalue);
- break;
- case IntResult:
- fprintf(stderr, "int result: %d \n", rs->intvalue);
- break;
- case RealResult:
- fprintf(stderr, "real result: %f \n", rs->realvalue);
- break;
- case StringResult:
- fprintf(stderr, "string result: -%*s-\n", rs->string_len,
- rs->string);
- break;
- case xNodeSetResult:
- if (!i) fprintf(stderr,"nodeSet result (len %d):\n",rs->nr_nodes);
- for (i=0; i<rs->nr_nodes; i++) {
- if (rs->nodes[i]->nodeType == ELEMENT_NODE) {
- fprintf(stderr, "%2d domNode%p %s ",
- i, rs->nodes[i], rs->nodes[i]->nodeName);
- if (rs->nodes[i]->firstChild &&
- rs->nodes[i]->firstChild->nodeType == TEXT_NODE)
- {
- l = ((domTextNode*)rs->nodes[i]->firstChild)->valueLength;
- if (l > 25) l = 25;
- memcpy(tmp, ((domTextNode*)rs->nodes[i]->firstChild)->nodeValue, l);
- tmp[l] = '\0';
- fprintf(stderr, "'%s'", tmp);
- }
- fprintf(stderr, "\n");
- } else
- if (rs->nodes[i]->nodeType == TEXT_NODE) {
- l = ((domTextNode*)rs->nodes[i])->valueLength;
- if (l > 60) l = 60;
- memcpy(tmp, ((domTextNode*)rs->nodes[i])->nodeValue, l);
- tmp[l] = '\0';
- fprintf(stderr, "%2d domNode%p text:'%s' \n",
- i, rs->nodes[i], tmp);
- } else
- if (rs->nodes[i]->nodeType == COMMENT_NODE) {
- l = ((domTextNode*)rs->nodes[i])->valueLength;
- memcpy (tmp, "<!--", 4);
- if (l > 60) l = 60;
- memcpy(&tmp[4], ((domTextNode*)rs->nodes[i])->nodeValue, l);
- memcpy(&tmp[4+l], "-->", 3);
- tmp[7+l] = '\0';
- fprintf(stderr, "%2d domNode%p text:'%s' \n",
- i, rs->nodes[i], tmp);
- } else
- if (rs->nodes[i]->nodeType == ATTRIBUTE_NODE) {
- fprintf(stderr, "%2d Attr %s='%*s'\n", i,
- ((domAttrNode*)rs->nodes[i])->nodeName,
- ((domAttrNode*)rs->nodes[i])->valueLength,
- ((domAttrNode*)rs->nodes[i])->nodeValue);
- }
- }
- break;
- case NaNResult: fprintf (stderr, "NaN result\n"); break;
- case InfResult: fprintf (stderr, "Inf result\n"); break;
- case NInfResult: fprintf (stderr, "-Inf result\n"); break;
-
- default:
- fprintf (stderr, "unknown result type: '%d'!!!\n", rs->type);
- break;
- }
- }
- void rsSetReal ( xpathResultSet *rs, double d) {
- rs->type = RealResult;
- rs->realvalue = d;
- }
- void rsSetNaN ( xpathResultSet *rs ) {
- rs->type = NaNResult;
- }
- void rsSetInf ( xpathResultSet *rs ) {
- rs->type = InfResult;
- }
- void rsSetNInf ( xpathResultSet *rs ) {
- rs->type = NInfResult;
- }
- void rsSetInt ( xpathResultSet *rs, int i) {
- rs->type = IntResult;
- rs->intvalue = i;
- }
- void rsSetBool ( xpathResultSet *rs, int i) {
- rs->type = BoolResult;
- rs->intvalue = (i ? 1 : 0);
- }
- void rsSetString ( xpathResultSet *rs, char *s) {
- rs->type = StringResult;
- if (s) {
- rs->string = tdomstrdup(s);
- rs->string_len = strlen(s);
- } else {
- rs->string = tdomstrdup("");
- rs->string_len = 0;
- }
- rs->nr_nodes = 0;
- }
- void rsAddNode ( xpathResultSet *rs, domNode *node) {
- if ((rs->type != EmptyResult) && (rs->type != xNodeSetResult)) {
- domPanic("Can not add node to non NodeSetResult xpathResultSet!");
- }
- if (rs->type == EmptyResult) {
- rs->type = xNodeSetResult;
- rs->nodes = (domNode**)MALLOC(INITIAL_SIZE * sizeof(domNode*));
- rs->allocated = INITIAL_SIZE;
- rs->nr_nodes = 1;
- rs->nodes[0] = node;
- } else {
- int insertIndex;
- int i;
- if (rs->intvalue) {
- /* we must do a copy-on-write */
- domNode **nodes;
- nodes = (domNode**)MALLOC(rs->allocated * sizeof(domNode*));
- memcpy (nodes, rs->nodes, sizeof(domNode*) * rs->nr_nodes);
- rs->nodes = nodes;
- rs->intvalue = 0;
- }
- insertIndex = rs->nr_nodes;
- for (i = rs->nr_nodes - 1; i >= 0; i--) {
- if (node == rs->nodes[i]) return;
- if (!domPrecedes (node, rs->nodes[i])) {
- break;
- }
- insertIndex--;
- }
- if ((rs->nr_nodes+1) >= rs->allocated) {
- rs->nodes = (domNode**)REALLOC((void*)rs->nodes,
- 2 * rs->allocated * sizeof(domNode*));
- rs->allocated = rs->allocated * 2;
- }
- if (insertIndex == rs->nr_nodes) {
- rs->nodes[rs->nr_nodes++] = node;
- } else {
- for (i = rs->nr_nodes - 1; i >= insertIndex; i--) {
- rs->nodes[i+1] = rs->nodes[i];
- }
- rs->nodes[insertIndex] = node;
- rs->nr_nodes++;
- }
- }
- }
- void rsAddNodeFast ( xpathResultSet *rs, domNode *node) {
- if ((rs->type != EmptyResult) && (rs->type != xNodeSetResult)) {
- fprintf(stderr, "could not add node to non NodeSetResult xpathResultSet!"); return;
- }
- if (rs->type == EmptyResult) {
- rs->type = xNodeSetResult;
- rs->nodes = (domNode**)MALLOC(INITIAL_SIZE * sizeof(domNode*));
- rs->allocated = INITIAL_SIZE;
- rs->nr_nodes = 1;
- rs->nodes[0] = node;
- } else {
- if ((rs->nr_nodes+1) >= rs->allocated) {
- rs->nodes = (domNode**)REALLOC((void*)rs->nodes,
- 2 * rs->allocated * sizeof(domNode*));
- rs->allocated = rs->allocated * 2;
- }
- rs->nodes[rs->nr_nodes++] = node;
- }
- }
- void rsCopy ( xpathResultSet *to, xpathResultSet *from ) {
- int i;
- to->type = from->type;
- to->intvalue = from->intvalue;
- if (from->type == RealResult) {
- to->realvalue = from->realvalue;
- } else
- if (from->type == StringResult) {
- to->string = tdomstrdup(from->string);
- to->string_len = from->string_len;
- } else
- if (from->type == xNodeSetResult) {
- to->nr_nodes = from->nr_nodes;
- to->nodes = (domNode**)MALLOC(from->nr_nodes * sizeof(domNode*));
- for (i=0; i<from->nr_nodes; i++)
- to->nodes[i] = from->nodes[i];
- to->intvalue = 0;
- }
- }
- /*----------------------------------------------------------------------------
- | AST construct functions
- |
- \---------------------------------------------------------------------------*/
- static ast New( astType type ) {
- ast t = NEWCONS;
- t->type = type;
- t->next = t->child = NULL;
- t->strvalue = NULL;
- t->intvalue = 0;
- t->realvalue = 0.0;
- return t;
- }
- static ast New1( astType type, ast a) {
- ast t = NEWCONS;
- t->type = type;
- t->next = NULL;
- t->child = a;
- t->strvalue = NULL;
- t->intvalue = 0;
- t->realvalue = 0.0;
- return t;
- }
- static ast New1WithEvalSteps( astType type, ast a) {
- ast t = NEWCONS;
- t->type = type;
- t->next = NULL;
- if (a && a->next) {
- t->child = New1(EvalSteps,a);
- } else {
- t->child = a;
- }
- t->strvalue = NULL;
- t->intvalue = 0;
- t->realvalue = 0.0;
- return t;
- }
- static ast New2( astType type, ast a, ast b ) {
- ast t = NEWCONS;
- t->type = type;
- t->next = NULL;
- t->strvalue = NULL;
- t->intvalue = 0;
- t->realvalue = 0.0;
- if (a && a->next) {
- t->child = New1(EvalSteps,a);
- } else {
- t->child = a;
- }
- if (b && b->next) {
- t->child->next = New1(EvalSteps, b);
- } else {
- t->child->next = b;
- }
- return t;
- }
- static ast NewInt( int i ) {
- ast t = NEWCONS;
- t->type = Int;
- t->strvalue = NULL;
- t->intvalue = i;
- t->realvalue = 0.0;
- t->next = t->child = NULL;
- return t;
- }
- static ast NewReal( double r ) {
- ast t = NEWCONS;
- t->type = Real;
- t->strvalue = NULL;
- t->intvalue = 0;
- t->realvalue = r;
- t->next = t->child = NULL;
- return t;
- }
- static ast NewStr( astType type, char *str ) {
- ast t = NEWCONS;
- t->type = type;
- t->strvalue = tdomstrdup(str);
- t->intvalue = 0;
- t->realvalue = 0.0;
- t->next = t->child = NULL;
- return t;
- }
- static ast Append( ast m, ast n ) {
- if (!n) return NULL;
- if (!m) return NULL;
- while (m->next != NULL) m = m->next;
- m->next = n;
- return m;
- }
- static ast AddChild( ast m, ast child ) {
- if (!child) return NULL;
- if (!m) return NULL;
- if (m->child == NULL) {
- m->child = child;
- } else {
- ast c = m->child;
- while (c->next != NULL) c = c->next;
- c->next = child;
- }
- return m;
- }
- static ast AddChildWithEvalSteps( ast m, ast child ) {
- if (!child) return NULL;
- if (!m) return NULL;
- if (child->next) {
- child = New1(EvalSteps, child);
- }
- if (m->child == NULL) {
- m->child = child;
- } else {
- ast c = m->child;
- while (c->next != NULL) c = c->next;
- c->next = child;
- }
- /*child->next = NULL;*/
- return m;
- }
- static void freeAst (ast t)
- {
- ast tmp;
- while (t) {
- tmp = t->next;
- if (t->strvalue) FREE(t->strvalue);
- if (t->child) freeAst (t->child);
- FREE((char*)t);
- t = tmp;
- }
- }
- void printAst (int depth, ast t)
- {
- int i;
- while (t) {
- for (i=0; i<depth; i++) fprintf(stderr, " ");
- fprintf(stderr, "%s ", astType2str[t->type]);
- switch (t->type) {
- case Int : fprintf(stderr, "%d", t->intvalue); break;
- case Real: fprintf(stderr, "%f", t->realvalue); break;
- case IsElement:
- case IsFQElement:
- case IsNSAttr:
- case IsAttr:
- case ExecFunction:
- case Literal:
- case GetFQVar:
- case GetVar: fprintf(stderr, "'%s'", t->strvalue); break;
- default: break;
- }
- fprintf(stderr, "\n");
- if (t->child) printAst (depth+1, t->child);
- t = t->next;
- }
- }
- /*----------------------------------------------------------------------------
- | xpathFreeAst
- |
- \---------------------------------------------------------------------------*/
- void xpathFreeAst(
- ast t
- )
- {
- freeAst(t);
- }
- /*----------------------------------------------------------------------------
- | xpathLexer
- |
- \---------------------------------------------------------------------------*/
- static XPathTokens xpathLexer (
- char *xpath,
- domNode *exprContext,
- char **prefixMappings,
- int *useNamespaceAxis,
- xpathParseVarCB *varParseCB,
- char **errMsg
- )
- {
- int l, allocated;
- int i, k, start, offset;
- char delim, *ps, save, *uri, tmpErr[80];
- XPathTokens tokens;
- int token = EOS;
- tokens = (XPathTokens)MALLOC(INITIAL_SIZE * sizeof(XPathToken));
- if (tokens == NULL) {
- *errMsg = tdomstrdup("Unable to alloc initial memory!");
- return NULL;
- }
- allocated = INITIAL_SIZE;
- l = 0;
- tokens[l].token = EOS;
- tokens[l].strvalue = NULL;
- tokens[l].intvalue = 0;
- tokens[l].realvalue = 0.0;
- i = 0;
- while (xpath[i]) {
- switch (xpath[i]) {
- case ' ' :
- case '\n':
- case '\r':
- case '\t': i++; continue;
- case '(': token = LPAR; break;
- case ')': token = RPAR; break;
- case '[': token = LBRACKET; break;
- case ']': token = RBRACKET; break;
- case '@': i++;
- while (xpath[i] && IS_XML_WHITESPACE(xpath[i])) i++;
- if ( isNCNameStart (&xpath[i]) ) {
- ps = &(xpath[i]);
- i += UTF8_CHAR_LEN (xpath[i]);
- while (xpath[i] && isNCNameChar (&xpath[i]))
- i += UTF8_CHAR_LEN (xpath[i]);
- save = xpath[i];
- xpath[i] = '\0';
- if (save == ':' && xpath[i+1] != ':') {
- uri = domLookupPrefixWithMappings (
- exprContext, ps, prefixMappings);
- if (!uri) {
- xpath[i] = save;
- *errMsg = tdomstrdup ("Prefix doesn't"
- " resolve");
- return tokens;
- }
- tokens[l].strvalue = tdomstrdup (uri);
- xpath[i] = save;
- token = ATTRIBUTEPREFIX;
- ADD_TOKEN (token);
- if (xpath[i+1] == '*') {
- token = ATTRIBUTE;
- tokens[l].strvalue = tdomstrdup("*");
- i++;
- } else {
- ps = &(xpath[++i]);
- if (!(isNCNameStart (&xpath[i]))) {
- *errMsg =
- tdomstrdup ("Illegal attribute"
- " name");
- return tokens;
- }
- i += UTF8_CHAR_LEN (xpath[i]);
- while (xpath[i] && isNCNameChar (&xpath[i]))
- i += UTF8_CHAR_LEN (xpath[i]);
- save = xpath[i];
- xpath[i] = '\0';
- token = ATTRIBUTE;
- tokens[l].strvalue = tdomstrdup(ps);
- xpath[i--] = save;
- }
- } else {
- tokens[l].strvalue = tdomstrdup(ps);
- xpath[i] = save;
- token = ATTRIBUTE;
- i--;
- }
- } else if (xpath[i]=='*') {
- tokens[l].strvalue = tdomstrdup("*");
- token = ATTRIBUTE;
- } else {
- *errMsg = tdomstrdup("Expected attribute name");
- return tokens;
- }; break;
- case ',': token = COMMA; break;
- case ':': if (xpath[i+1] == ':') {
- token = COLONCOLON;
- i++;
- } else {
- *errMsg = tdomstrdup("Unexpected token ':'");
- return tokens;
- }; break;
- case '"' :
- case '\'': delim = xpath[i]; start = ++i;
- while (xpath[i] && (xpath[i] != delim)) i++;
- if (!xpath[i]) {
- *errMsg = tdomstrdup("Undetermined string");
- return tokens;
- }
- xpath[i] = '\0'; /* terminate string */
- tokens[l].strvalue = tdomstrdup(&xpath[start]);
- token = LITERAL;
- xpath[i] = delim;
- break;
- case '/': if (xpath[i+1] == '/') {
- token = SLASHSLASH;
- i++;
- } else {
- token = SLASH;
- };
- break;
- case '|': token = PIPE; break;
- case '+': token = PLUS; break;
- case '-': token = MINUS; break;
- case '=': token = EQUAL; break;
- case '!': if (xpath[i+1] == '=') {
- token = NOTEQ;
- i++;
- } else {
- *errMsg = tdomstrdup("Unexpected token '!'");
- return tokens;
- }; break;
- case '<': if (xpath[i+1] == '=') {
- token = LTE;
- i++;
- } else {
- token = LT;
- };break;
- case '>': if (xpath[i+1] == '=') {
- token = GTE;
- i++;
- } else {
- token = GT;
- }; break;
- case '*': if ((l>0)
- && (tokens[l-1].token != COLONCOLON)
- && (tokens[l-1].token != LPAR)
- && (tokens[l-1].token != LBRACKET)
- && (tokens[l-1].token != COMMA)
- && (tokens[l-1].token != SLASH)
- && (tokens[l-1].token != SLASHSLASH)
- ) {
- token = MULTIPLY;
- } else {
- token = WCARDNAME;
- tokens[l].strvalue = tdomstrdup("*");
- }; break;
- case '$': if (varParseCB) {
- ps = (varParseCB->parseVarCB) (
- varParseCB->parseVarClientData, &xpath[i],
- &offset, errMsg
- );
- if (ps) {
- token = LITERAL;
- tokens[l].strvalue = tdomstrdup (ps);
- i += offset - 1;
- } else {
- return tokens;
- }
- } else {
- i++;
- if ( isNCNameStart (&xpath[i])) {
- ps = &(xpath[i]);
- i += UTF8_CHAR_LEN (xpath[i]);
- while (xpath[i] && isNCNameChar(&xpath[i]))
- i += UTF8_CHAR_LEN(xpath[i]);
- if (xpath[i] == ':' && xpath[i+1] != ':') {
- token = FQVARIABLE;
- save = xpath[i];
- xpath[i] = '\0';
- uri = domLookupPrefixWithMappings (
- exprContext, ps, prefixMappings);
- if (!uri) {
- xpath[i] = save;
- *errMsg = tdomstrdup ("Prefix doesn't"
- " resolve");
- return tokens;
- }
- tokens[l].strvalue = tdomstrdup (uri);
- xpath[i] = save;
- ADD_TOKEN (token);
- ps = &(xpath[++i]);
- if (!isNCNameStart (&xpath[i])) {
- *errMsg = tdomstrdup ("Illegal variable"
- " name");
- return tokens;
- }
- i += UTF8_CHAR_LEN (xpath[i]);
- while (xpath[i] && isNCNameChar (&xpath[i]))
- i += UTF8_CHAR_LEN (xpath[i]);
- }
- token = VARIABLE;
- save = xpath[i];
- xpath[i] = '\0';
- tokens[l].strvalue = tdomstrdup(ps);
- xpath[i--] = save;
- } else {
- *errMsg = tdomstrdup("Expected variable name");
- return tokens;
- }
- }
- break;
- case '.': if (xpath[i+1] == '.') {
- token = DOTDOT;
- i++;
- break;
- } else if (!isdigit((unsigned char)xpath[i+1])) {
- token = DOT;
- break;
- }
- /* DOT followed by digit, ie a REAL.
- Handled by default. Fall throu */
- default: if ( isNCNameStart (&xpath[i])) {
- ps = &(xpath[i]);
- i += UTF8_CHAR_LEN (xpath[i]);
- while (xpath[i] && isNCNameChar(&xpath[i])) {
- i += UTF8_CHAR_LEN(xpath[i]);
- }
- k = i;
- if (xpath[i] == ':') {
- if (xpath[i+1] == '*') {
- save = xpath[i];
- xpath[i] = '\0'; /* terminate */
- token = NSWC;
- uri = domLookupPrefixWithMappings (
- exprContext, ps, prefixMappings);
- if (!uri) {
- xpath[i] = save;
- *errMsg = tdomstrdup ("Prefix doesn't"
- " resolve");
- return tokens;
- }
- tokens[l].strvalue = tdomstrdup (uri);
- xpath[i] = save;
- i++;
- break;
- }
- if (xpath[i+1] != ':') {
- save = xpath[i];
- xpath[i] = '\0'; /* terminate */
- token = NSPREFIX;
- uri = domLookupPrefixWithMappings (
- exprContext, ps, prefixMappings);
- if (!uri) {
- xpath[i] = save;
- *errMsg = tdomstrdup ("Prefix doesn't"
- " resolve");
- return tokens;
- }
- tokens[l].strvalue = tdomstrdup (uri);
- xpath[i] = save;
- ADD_TOKEN (token);
- ps = &(xpath[++i]);
- if (!(isNCNameStart (&xpath[i]))) {
- *errMsg =
- tdomstrdup ("Illegal character in"
- " localname");
- return tokens;
- }
- i += UTF8_CHAR_LEN (xpath[i]);
- while (xpath[i] && isNCNameChar (&xpath[i]))
- i += UTF8_CHAR_LEN (xpath[i]);
- k = i;
- }
- }
- /* read over white space */
- while ((xpath[k] == ' ') ||
- (xpath[k] == '\n') ||
- (xpath[k] == '\r') ||
- (xpath[k] == '\t') ) k++;
- if (l>0 && tokens[l-1].token == NSPREFIX) {
- if (xpath[k]!='(') token = WCARDNAME;
- else token = FUNCTION;
- save = xpath[i];
- xpath[i] = '\0';
- tokens[l].strvalue = tdomstrdup(ps);
- xpath[i--] = save;
- break;
- }
-
- if (xpath[k]=='(') {
- save = xpath[i];
- xpath[i] = '\0'; /* terminate */
- if (strcmp(ps,"text")==0) {
- token = TEXT;
- } else if (strcmp(ps,"node")==0) {
- token = NODE;
- } else if (strcmp(ps,"comment")==0) {
- token = COMMENT;
- } else if (strcmp(ps,"processing-instruction")==0) {
- token = PINSTR;
- } else {
- if ((save!='(') && (strcmp(ps,"and")==0)) token = AND;
- else
- if ((save!='(') && (strcmp(ps,"or")==0)) token = OR;
- else
- if ((save!='(') && (strcmp(ps,"mod")==0)) token = MOD;
- else
- if ((save!='(') && (strcmp(ps,"div")==0)) token = DIV;
- else {
- token = FUNCTION;
- tokens[l].strvalue = tdomstrdup(ps);
- }
- }
- xpath[i] = save;
- } else if ((xpath[k]==':') && (xpath[k+1]==':')) {
- token = AXISNAME;
- save = xpath[i];
- xpath[i] = '\0'; /* terminate */
- tokens[l].strvalue = tdomstrdup(ps);
- if (ps[0] == 'n'&& strcmp(ps, "namespace")==0) {
- *useNamespaceAxis = 1;
- }
- xpath[i] = save;
- } else {
- save = xpath[i];
- xpath[i] = '\0';
- if ((l>0)
- && (tokens[l-1].token != COLONCOLON)
- && (tokens[l-1].token != LPAR)
- && (tokens[l-1].token != LBRACKET)
- && (tokens[l-1].token != COMMA)
- && (tokens[l-1].token != SLASH)
- && (tokens[l-1].token != SLASHSLASH)
- && (tokens[l-1].token != PIPE)
- && (tokens[l-1].token != PLUS)
- && (tokens[l-1].token != MINUS)
- && (tokens[l-1].token != EQUAL)
- && (tokens[l-1].token != NOTEQ)
- && (tokens[l-1].token != LT)
- && (tokens[l-1].token != LTE)
- && (tokens[l-1].token != GT)
- && (tokens[l-1].token != GTE)
- && (tokens[l-1].token != AND)
- && (tokens[l-1].token != OR)
- && (tokens[l-1].token != MOD)
- && (tokens[l-1].token != DIV)
- && (tokens[l-1].token != MULTIPLY)
- ) {
- if (strcmp(ps,"and")==0) {
- token = AND;
- } else if (strcmp(ps,"or")==0) {
- token = OR;
- } else if (strcmp(ps,"mod")==0) {
- token = MOD;
- } else if (strcmp(ps,"div")==0) {
- token = DIV;
- } else {
- token = WCARDNAME;
- tokens[l].strvalue = tdomstrdup(ps);
- }
- } else {
- token = WCARDNAME;
- tokens[l].strvalue = tdomstrdup(ps);
- }
- xpath[i] = save;
- }
- i--;
- } else if (isdigit((unsigned char)xpath[i])
- || (xpath[i] == '.')) {
- if (xpath[i] == '.') {
- token = REALNUMBER;
- } else {
- token = INTNUMBER;
- }
- ps = &(xpath[i++]);
- while (xpath[i] && isdigit((unsigned char)xpath[i]))
- i++;
- if (xpath[i]=='.') {
- if (token == REALNUMBER) {
- sprintf (tmpErr, "Unexpected character "
- "'%c' at position %d", xpath[i],
- i);
- *errMsg = tdomstrdup (tmpErr);
- return tokens;
- }
- token = REALNUMBER;
- i++;
- while (xpath[i]
- && isdigit((unsigned char)xpath[i])) i++;
- }
- save = xpath[i];
- xpath[i] = '\0';
- if (token == INTNUMBER) {
- tokens[l].intvalue = atoi(ps);
- }
- tokens[l].realvalue = (double)atof(ps);
- xpath[i--] = save;
- } else {
- sprintf (tmpErr, "Unexpected character '%c' at "
- "position %d", xpath[i], i);
- *errMsg = tdomstrdup (tmpErr);
- return tokens;
- }
- break;
- } /* switch */
- ADD_TOKEN(token);
- i++;
- }
- ADD_TOKEN(EOS);
- return tokens;
- } /* xpathLexer */
- /*-----------------------------------------------------------------
- | NodeTest production
- |
- \----------------------------------------------------------------*/
- Production(NodeTest)
- if (LA==NODE) {
- Consume(NODE);
- Consume(LPAR);
- Consume(RPAR);
- a = New (IsNode);
- } else
- if (LA==TEXT) {
- Consume(TEXT);
- Consume(LPAR);
- Consume(RPAR);
- a = New (IsText);
- } else
- if (LA==COMMENT) {
- Consume(COMMENT);
- Consume(LPAR);
- Consume(RPAR);
- a = New (IsComment);
- } else
- if (LA==PINSTR) {
- Consume(PINSTR);
- Consume(LPAR);
- if (LA==LITERAL) {
- Consume(LITERAL);
- a = NewStr (IsSpecificPI, STRVAL);
- } else {
- a = New (IsPI);
- }
- Consume(RPAR);
- } else
- if (LA==MULTIPLY) {
- Consume(MULTIPLY);
- a = NewStr (IsElement, "*");
- } else
- if (LA==NSPREFIX) {
- ast b;
- Consume (NSPREFIX);
- a = NewStr (IsFQElement, STRVAL);
- Consume (WCARDNAME);
- b = NewStr (IsElement, STRVAL);
- AddChild (a, b);
- } else
- if (LA==NSWC) {
- Consume (NSWC);
- a = NewStr (IsNSElement, STRVAL);
- } else {
- Consume(WCARDNAME);
- a = NewStr (IsElement, STRVAL);
- }
- EndProduction
- /*-----------------------------------------------------------------
- | AbbreviatedBasis production
- |
- \----------------------------------------------------------------*/
- Production(AbbreviatedBasis)
- if (LA==ATTRIBUTE) {
- Consume(ATTRIBUTE);
- a = New1( AxisAttribute, NewStr(IsAttr, STRVAL) );
- } else
- if (LA==ATTRIBUTEPREFIX) {
- ast b, c;
- Consume(ATTRIBUTEPREFIX);
- a = New (AxisAttribute);
- b = NewStr (IsNSAttr, STRVAL);
- AddChild (a, b);
- Consume(ATTRIBUTE);
- c = NewStr (IsAttr, STRVAL);
- AddChild (b, c);
- }
- else {
- a = New1( AxisChild, Recurse(NodeTest));
- }
- EndProduction
- /*-----------------------------------------------------------------
- | getFunctionTag
- |
- \----------------------------------------------------------------*/
- static functionTag
- getFunctionTag (char *funcName)
- {
- switch (funcName[0]) {
- case 'b':
- if (strcmp (funcName, "boolean")==0) return f_boolean;
- break;
- case 'c':
- if (strcmp (funcName, "ceiling")==0) return f_ceiling;
- else if (strcmp (funcName, "concat")==0) return f_concat;
- else if (strcmp (funcName, "contains")==0) return f_contains;
- else if (strcmp (funcName, "count")==0) return f_count;
- break;
- case 'f':
- if (strcmp (funcName, "false")==0) return f_false;
- else if (strcmp (funcName, "floor")==0) return f_floor;
- break;
- case 'g':
- if (strcmp (funcName, "generate-id")==0) return f_generateId;
- break;
- case 'i':
- if (strcmp (funcName, "id")==0) return f_id;
- case 'l':
- if (strcmp (funcName, "lang")==0) return f_lang;
- else if (strcmp (funcName, "last")==0) return f_last;
- else if (strcmp (funcName, "local-name")==0) return f_localName;
- break;
- case 'n':
- if (strcmp (funcName, "name")==0) return f_name;
- else if (strcmp (funcName, "namespace-uri")==0) return f_namespaceUri;
- else if (strcmp (funcName, "normalize-space")==0) return f_normalizeSpace;
- else if (strcmp (funcName, "not")==0) return f_not;
- else if (strcmp (funcName, "number")==0) return f_number;
- break;
- case 'p':
- if (strcmp (funcName, "position")==0) return f_position;
- break;
- case 'r':
- if (strcmp (funcName, "round")==0) return f_round;
- break;
- case 's':
- if (strcmp (funcName, "starts-with")==0) return f_startsWith;
- else if (strcmp (funcName, "string")==0) return f_string;
- else if (strcmp (funcName, "string-length")==0) return f_stringLength;
- else if (strcmp (funcName, "substring")==0) return f_substring;
- else if (strcmp (funcName, "substring-after")==0) return f_substringAfter;
- else if (strcmp (funcName, "substring-before")==0) return f_substringBefore;
- else if (strcmp (funcName, "sum")==0) return f_sum;
- break;
- case 't':
- if (strcmp (funcName, "translate")==0) return f_translate;
- else if (strcmp (funcName, "true")==0) return f_true;
- break;
- case 'u':
- if (strcmp (funcName, "unparsed-entity-uri")==0) return f_unparsedEntityUri;
- break;
- default:
- break;
- }
- return f_unknown;
- }
- /*-----------------------------------------------------------------
- | FilterExpr production
- |
- \----------------------------------------------------------------*/
- Production(FilterExpr)
- if (LA==VARIABLE) {
- Consume(VARIABLE);
- a = NewStr( GetVar, STRVAL);
- } else if (LA==FQVARIABLE) {
- Consume(FQVARIABLE);
- a = NewStr( GetFQVar, STRVAL);
- Consume(VARIABLE);
- AddChild (a, NewStr( GetVar, STRVAL));
- } else if (LA==LPAR) {
- Consume(LPAR);
- a = New1(EvalSteps, Recurse(OrExpr));
- Consume(RPAR);
- } else if (LA==LITERAL) {
- Consume(LITERAL);
- a = NewStr( Literal, STRVAL);
- } else if (LA==INTNUMBER) {
- Consume(INTNUMBER);
- a = NewInt( INTVAL );
- } else if (LA==REALNUMBER) {
- Consume(REALNUMBER);
- a = NewReal( REALVAL );
- } else if (LA==FUNCTION || LA==NSPREFIX) {
- if (LA==FUNCTION) {
- Consume(FUNCTION);
- a = NewStr( ExecFunction, STRVAL);
- a->intvalue = getFunctionTag (STRVAL);
- } else {
- Consume(NSPREFIX);
- a = NewStr( ExecFunction, STRVAL);
- a->intvalue = f_fqfunction;
- Consume(FUNCTION);
- AddChild (a, NewStr( ExecFunction, STRVAL));
- }
- Consume(LPAR);
- if (LA!=RPAR) {
- AddChildWithEvalSteps (a, Recurse(OrExpr));
- while(LA==COMMA) {
- Consume(COMMA);
- AddChildWithEvalSteps (a, Recurse(OrExpr) );
- }
- }
- Consume(RPAR);
- } else {
- ErrExpected("$var or (expr) or literal or number or func");
- }
- while (LA==LBRACKET) {
- ast b;
- b = Recurse(Predicate);
- if (!b) return NULL;
- Append( a, New1WithEvalSteps( Pred, b));
- }
- EndProduction
- /*-----------------------------------------------------------------
- | PathExpr production
- |
- \----------------------------------------------------------------*/
- Production(PathExpr)
- if ( (LA==VARIABLE)
- ||(LA==FQVARIABLE)
- ||(LA==LPAR)
- ||(LA==LITERAL)
- ||(LA==INTNUMBER)
- ||(LA==REALNUMBER)
- ||(LA==FUNCTION)
- ||(LA==NSPREFIX && LA2==FUNCTION)
- ) {
- a = Recurse(FilterExpr);
- if (LA==SLASH) {
- Consume(SLASH);
- Append(a, Recurse(RelativeLocationPath));
- } else if (LA==SLASHSLASH) {
- ast b;
- Consume(SLASHSLASH);
- b = Recurse(RelativeLocation…
Large files files are truncated, but you can click here to view the full file