tDOM

Check-in [df3a907a20]
Login

Check-in [df3a907a20]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merged from trunk.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | schema
Files: files | file ages | folders
SHA3-256: df3a907a200f4a600a6b32a008d259ec693943482d139ea25b29d34ef313b4a5
User & Date: rolf 2019-07-12 22:26:12.688
Context
2019-07-23
23:54
Gardening around. Moved generation of all schmea related Tcl commands to tDOM_SchemaInit(). Moved the method 'status' as 'validationstatus' (alias 'vstatus') under the 'info' method and used the opportunity to start to define the schema command method info. check-in: e5493b6b50 user: rolf tags: schema
2019-07-12
22:26
Merged from trunk. check-in: df3a907a20 user: rolf tags: schema
2019-07-11
14:07
Fixed possible floating point exception with arithmetic operator 'mod'. check-in: 7cf8bdeb6c user: rolf tags: trunk
2019-06-18
22:18
An example of different 'styles' of a certain type: The 'interger' text constraint now has two interpretation of an integer - what Tcl_GetInt() accept and what a valid xsd:integer is, which is quite different. check-in: 9a589897fb user: rolf tags: schema
Changes
Unified Diff Ignore Whitespace Patch
Changes to expat/VERSION.
1
expat-2.2.5
|
1
expat-2.2.6
Changes to generic/domxpath.c.
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
    int      *useNamespaceAxis,
    xpathParseVarCB *varParseCB,
    char    **errMsg
)
{
    int  l, allocated;
    int  i, k, start, offset;
    char delim, *ps, save, tmpErr[80];
    const char *uri;
    XPathTokens tokens;
    int token = EOS;


    tokens = (XPathTokens)MALLOC(INITIAL_SIZE * sizeof(XPathToken));
    if (tokens == NULL) {







|







695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
    int      *useNamespaceAxis,
    xpathParseVarCB *varParseCB,
    char    **errMsg
)
{
    int  l, allocated;
    int  i, k, start, offset;
    char delim, *ps, save, tmpErr[80], *tailptr;
    const char *uri;
    XPathTokens tokens;
    int token = EOS;


    tokens = (XPathTokens)MALLOC(INITIAL_SIZE * sizeof(XPathToken));
    if (tokens == NULL) {
1129
1130
1131
1132
1133
1134
1135
1136
1137






1138
1139
1140
1141
1142
1143
1144
                               tokens[l].intvalue = strtol(ps, NULL, 10);
                               if (errno == ERANGE 
                                   && ( tokens[l].intvalue == LONG_MAX 
                                        || tokens[l].intvalue == LONG_MIN)) {
                                   token = REALNUMBER;
                               }
                           }
                           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;







|

>
>
>
>
>
>







1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
                               tokens[l].intvalue = strtol(ps, NULL, 10);
                               if (errno == ERANGE 
                                   && ( tokens[l].intvalue == LONG_MAX 
                                        || tokens[l].intvalue == LONG_MIN)) {
                                   token = REALNUMBER;
                               }
                           }
                           tokens[l].realvalue = strtod(ps, &tailptr);
                           xpath[i--] = save;
                           if (tokens[l].realvalue == 0.0 && tailptr == ps) {
                               sprintf (tmpErr, "Number value too large "
                                        "at position %d", i);
                               *errMsg = tdomstrdup (tmpErr);
                               return tokens;
                           }
                       } else {
                           sprintf (tmpErr, "Unexpected character '%c' at "
                                    "position %d", xpath[i], i);
                           *errMsg = tdomstrdup (tmpErr);
                           return tokens;
                       }
                       break;
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
                        varParseCB, errMsg);
    if (*errMsg != NULL) {
        if (tokens != NULL) xpathFreeTokens (tokens);
        return XPATH_LEX_ERR;
    }
    DDBG(
        for (i=0; tokens[i].token != EOS; i++) {
            fprintf(stderr, "%3d %-12s %5ld %8.3f %5d  %s\n",
                            i,
                            token2str[tokens[i].token-LPAR],
                            tokens[i].intvalue,
                            tokens[i].realvalue,
                            tokens[i].pos,
                            tokens[i].strvalue
            );







|







2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
                        varParseCB, errMsg);
    if (*errMsg != NULL) {
        if (tokens != NULL) xpathFreeTokens (tokens);
        return XPATH_LEX_ERR;
    }
    DDBG(
        for (i=0; tokens[i].token != EOS; i++) {
            fprintf(stderr, "%3d %-12s %5ld %8.3g %5d  %s\n",
                            i,
                            token2str[tokens[i].token-LPAR],
                            tokens[i].intvalue,
                            tokens[i].realvalue,
                            tokens[i].pos,
                            tokens[i].strvalue
            );
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
        newlen = strlen(xpath);
        *errMsg = (char*)REALLOC(*errMsg, len+newlen+10);
        memmove(*errMsg + len, " for '", 6);
        memmove(*errMsg + len+6, xpath, newlen);
        memmove(*errMsg + len+6+newlen, "' ", 3);

        for (i=0; tokens[i].token != EOS; i++) {
            sprintf(tmp, "%s\n%3s%3d %-12s %5ld %09.3f %5d  ",
                         (i==0) ? "\n\nParsed symbols:" : "",
                         (i==l) ? "-->" : "   ",
                          i,
                         token2str[tokens[i].token-LPAR],
                         tokens[i].intvalue,
                         tokens[i].realvalue,
                         tokens[i].pos







|







2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
        newlen = strlen(xpath);
        *errMsg = (char*)REALLOC(*errMsg, len+newlen+10);
        memmove(*errMsg + len, " for '", 6);
        memmove(*errMsg + len+6, xpath, newlen);
        memmove(*errMsg + len+6+newlen, "' ", 3);

        for (i=0; tokens[i].token != EOS; i++) {
            sprintf(tmp, "%s\n%3s%3d %-12s %5ld %09.3g %5d  ",
                         (i==0) ? "\n\nParsed symbols:" : "",
                         (i==l) ? "-->" : "   ",
                          i,
                         token2str[tokens[i].token-LPAR],
                         tokens[i].intvalue,
                         tokens[i].realvalue,
                         tokens[i].pos
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750

        case RealResult:
            if (IS_NAN (rs->realvalue)) return tdomstrdup ("NaN");
            else if (IS_INF (rs->realvalue)) {
                if (IS_INF (rs->realvalue) == 1) return tdomstrdup ("Infinity");
                else                             return tdomstrdup ("-Infinity");
            }
            sprintf(tmp, "%f", rs->realvalue);
            /* strip trailing 0 and . */
            len = strlen(tmp);
            for (; (len > 0) && (tmp[len-1] == '0'); len--) tmp[len-1] = '\0';
            if ((len > 0) && (tmp[len-1] == '.'))   tmp[len-1] = '\0';
            return (tdomstrdup(tmp));
            
        case NaNResult:







|







2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756

        case RealResult:
            if (IS_NAN (rs->realvalue)) return tdomstrdup ("NaN");
            else if (IS_INF (rs->realvalue)) {
                if (IS_INF (rs->realvalue) == 1) return tdomstrdup ("Infinity");
                else                             return tdomstrdup ("-Infinity");
            }
            sprintf(tmp, "%g", rs->realvalue);
            /* strip trailing 0 and . */
            len = strlen(tmp);
            for (; (len > 0) && (tmp[len-1] == '0'); len--) tmp[len-1] = '\0';
            if ((len > 0) && (tmp[len-1] == '.'))   tmp[len-1] = '\0';
            return (tdomstrdup(tmp));
            
        case NaNResult:
4475
4476
4477
4478
4479
4480
4481






4482

4483
4484
4485
4486
4487
4488
4489
                rsSetReal (result, dLeft / dRight);
            }
            break;
        case Mod:
            if ((int)dRight == 0) {
                rsSetNaN (result);
            } else {






                rsSetInt  (result, ((int)dLeft) % ((int)dRight));

            }
            break;
        default:        break;
        }
        xpathRSFree (&rightResult);
        xpathRSFree (&leftResult);
        return XPATH_OK;







>
>
>
>
>
>
|
>







4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
                rsSetReal (result, dLeft / dRight);
            }
            break;
        case Mod:
            if ((int)dRight == 0) {
                rsSetNaN (result);
            } else {
                if (dRight < LONG_MIN - 0.1
                    || dRight > LONG_MAX + 0.1
                    || dLeft < LONG_MIN - 0.1
                    || dLeft > LONG_MAX + 0.1) {
                    rsSetNaN (result);
                } else {
                    rsSetInt  (result, ((long)dLeft) % ((long)dRight));
                }
            }
            break;
        default:        break;
        }
        xpathRSFree (&rightResult);
        xpathRSFree (&leftResult);
        return XPATH_OK;
Changes to generic/domxslt.c.
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
    xsltState *xs,
    domNode   *node,
    double     precedence,
    char     **errMsg
)
{
    xsltTemplate  *tpl, *t;
    char          *prioStr, *str, prefix[MAX_PREFIX_LEN];
    const char    *localName;
    int            rc, hnew;
    domNS         *ns;
    Tcl_HashEntry *h;
    Tcl_DString    dStr;
    xsltSubDoc    *sDoc;








|







2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
    xsltState *xs,
    domNode   *node,
    double     precedence,
    char     **errMsg
)
{
    xsltTemplate  *tpl, *t;
    char          *prioStr, *str, prefix[MAX_PREFIX_LEN], *tailptr;
    const char    *localName;
    int            rc, hnew;
    domNS         *ns;
    Tcl_HashEntry *h;
    Tcl_DString    dStr;
    xsltSubDoc    *sDoc;

2966
2967
2968
2969
2970
2971
2972
2973





2974



2975
2976
2977
2978
2979
2980
2981
    tpl->prio       = 0.5;
    tpl->content    = node;
    tpl->precedence = precedence;
    tpl->next       = NULL;

    prioStr = getAttr(node,"priority", a_prio);
    if (prioStr) {
        tpl->prio = (double)atof(prioStr);





    } 



    
    sDoc = xs->subDocs;
    while (sDoc) {
        if (sDoc->doc == node->ownerDocument) break;
        sDoc = sDoc->next;
    }
    tpl->sDoc = sDoc;







|
>
>
>
>
>
|
>
>
>







2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
    tpl->prio       = 0.5;
    tpl->content    = node;
    tpl->precedence = precedence;
    tpl->next       = NULL;

    prioStr = getAttr(node,"priority", a_prio);
    if (prioStr) {
        tpl->prio = strtod (prioStr, &tailptr);
        if (tpl->prio == 0.0 && prioStr == tailptr) {
            /* If the template has a name attribute, it is already stored in
               in the namedTemplates hash table and will be freed. */
            if (!tpl->name) {
                FREE ((char*)tpl);
            }
            return -1;
        }
    }
    
    sDoc = xs->subDocs;
    while (sDoc) {
        if (sDoc->doc == node->ownerDocument) break;
        sDoc = sDoc->next;
    }
    tpl->sDoc = sDoc;
Changes to tests/xpath.test.
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573

test xpath-5.1 {erroneous XPath expr: missing right brace in predicate} {
    set result [catch {$root selectNodes {*[1}} errMsg]
    list $result $errMsg
} {1 {Predicate: Expected "RBRACKET" for '*[1' 

Parsed symbols:
     0 WCARDNAME        0 00000.000     0  *
     1 LBRACKET         0 00000.000     1  
     2 INTNUMBER        1 00001.000     2  }}

test xpath-5.2 {erroneous XPath expr: missing right brace in predicate} {
    set result [catch {$root selectNodes {*[1][@attr}} errMsg]
    list $result $errMsg
} {1 {Predicate: Expected "RBRACKET" for '*[1][@attr' 

Parsed symbols:
     0 WCARDNAME        0 00000.000     0  *
     1 LBRACKET         0 00000.000     1  
     2 INTNUMBER        1 00001.000     2  
     3 RBRACKET         0 00000.000     3  
     4 LBRACKET         0 00000.000     4  
     5 ATTRIBUTE        0 00000.000     9  attr}}

test xpath-5.3 {erroneous XPath expr: missing left brace in predicate} {
    catch {$root selectNodes {*1]}}
} {1}

test xpath-5.4 {erroneous XPath expr} {
    catch {$root selectNodes {myNS: bar}} errMsg







|
|
|







|
|
|
|
|
|







544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573

test xpath-5.1 {erroneous XPath expr: missing right brace in predicate} {
    set result [catch {$root selectNodes {*[1}} errMsg]
    list $result $errMsg
} {1 {Predicate: Expected "RBRACKET" for '*[1' 

Parsed symbols:
     0 WCARDNAME        0 000000000     0  *
     1 LBRACKET         0 000000000     1  
     2 INTNUMBER        1 000000001     2  }}

test xpath-5.2 {erroneous XPath expr: missing right brace in predicate} {
    set result [catch {$root selectNodes {*[1][@attr}} errMsg]
    list $result $errMsg
} {1 {Predicate: Expected "RBRACKET" for '*[1][@attr' 

Parsed symbols:
     0 WCARDNAME        0 000000000     0  *
     1 LBRACKET         0 000000000     1  
     2 INTNUMBER        1 000000001     2  
     3 RBRACKET         0 000000000     3  
     4 LBRACKET         0 000000000     4  
     5 ATTRIBUTE        0 000000000     9  attr}}

test xpath-5.3 {erroneous XPath expr: missing left brace in predicate} {
    catch {$root selectNodes {*1]}}
} {1}

test xpath-5.4 {erroneous XPath expr} {
    catch {$root selectNodes {myNS: bar}} errMsg
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
    set result [catch {$doc selectNodes {a[b %nodeName='another value']}} errMsg]
    lappend result $errMsg
    $doc delete
    set result
} {1 {Predicate: Expected "RBRACKET" for 'a[b %nodeName='another value']' 

Parsed symbols:
     0 WCARDNAME        0 00000.000     0  a
     1 LBRACKET         0 00000.000     1  
     2 WCARDNAME        0 00000.000     2  b
-->  3 WCARDNAME        1 00000.000    12  with spaces
     4 EQUAL            0 00000.000    13  
     5 LITERAL          0 00000.000    28  another value
     6 RBRACKET         0 00000.000    29  }}

test xpath-5.47 {Element name injected with tcl variable} {
    set doc [dom parse -json {{"a":{"":"the value"},"a":{"":"another value"}}}]
    set nodeName ""
    set node [$doc selectNodes {a[%nodeName='another value']}]
    set result [list]
    lappend result [$node nodeName]







|
|
|
|
|
|
|







1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
    set result [catch {$doc selectNodes {a[b %nodeName='another value']}} errMsg]
    lappend result $errMsg
    $doc delete
    set result
} {1 {Predicate: Expected "RBRACKET" for 'a[b %nodeName='another value']' 

Parsed symbols:
     0 WCARDNAME        0 000000000     0  a
     1 LBRACKET         0 000000000     1  
     2 WCARDNAME        0 000000000     2  b
-->  3 WCARDNAME        1 000000000    12  with spaces
     4 EQUAL            0 000000000    13  
     5 LITERAL          0 000000000    28  another value
     6 RBRACKET         0 000000000    29  }}

test xpath-5.47 {Element name injected with tcl variable} {
    set doc [dom parse -json {{"a":{"":"the value"},"a":{"":"another value"}}}]
    set nodeName ""
    set node [$doc selectNodes {a[%nodeName='another value']}]
    set result [list]
    lappend result [$node nodeName]
1175
1176
1177
1178
1179
1180
1181





































1182
1183
1184
1185
1186
1187
1188
    set nodeName1 "a/b"
    set result [list]
    lappend result [$doc selectNodes string(%nodeName0/%nodeName1)]
    lappend result [$doc selectNodes string(a/a/b)]
    $doc delete
    set result
} {a/b b}






































set doc [dom parse {
<root>
  <asub>asub2</asub>
  <asub>asub3</asub>
  <asub>asub4</asub>
  <bsub>bsub1</bsub>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
    set nodeName1 "a/b"
    set result [list]
    lappend result [$doc selectNodes string(%nodeName0/%nodeName1)]
    lappend result [$doc selectNodes string(a/a/b)]
    $doc delete
    set result
} {a/b b}

test xpath-5.57 {afl-fuzz found seg fault in reporting error in invalid expr} {
    set doc [dom createDocument doc]
    catch {$doc selectNodes /[string repeat 1 2500]}
    catch {$doc selectNodes /[string repeat 1 250]}
    $doc delete
} {}

test xpath-5.58 {afl-fuzz found seg fault in reporting error in invalid expr} {
    set doc [dom createDocument doc]
    catch {$doc selectNodes concat([string repeat 1 250],1,1)}
    $doc delete
} {}

test xpath-5.59 {afl-fuzz found floating point exception in mod calulation} {
    set doc [dom createDocument doc]
    set result [list]
    lappend result [$doc selectNodes "1111111111111 mod -1"]
    lappend result [$doc selectNodes "111111111111111111111111111111111111111 mod -1"]
    $doc delete
    set result
} {0 NaN}

test xpath-5.60 {afl-fuzz found floating point exception in mod calulation} {
    set doc [dom createDocument doc]
    set result [list]
    for {set i 1} {$i < 20} {incr i} {
        for {set j 1} {$j < 20} {incr j} {
            set this [$doc selectNodes "$i mod $j"]
            if {$this != ($i % $j)} {
                lappend result [list $i $j $this [expr "$i % $j"]]
            }
        }
    }
    $doc delete
    set result
} {}

set doc [dom parse {
<root>
  <asub>asub2</asub>
  <asub>asub3</asub>
  <asub>asub4</asub>
  <bsub>bsub1</bsub>
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
    set result ""
    foreach node [$root selectNodes {bsub|asub}] {
        append result "[$node text] "
    }
    set result
} {asub1 asub2 asub3 asub4 bsub1 bsub2 }

$doc delete


set doc [dom parse {
<!-- comment 1 -->
<!-- comment 2 -->
<?api pi data?>
<!-- still not the document element -->







|







1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
    set result ""
    foreach node [$root selectNodes {bsub|asub}] {
        append result "[$node text] "
    }
    set result
} {asub1 asub2 asub3 asub4 bsub1 bsub2 }

catch {$doc delete}


set doc [dom parse {
<!-- comment 1 -->
<!-- comment 2 -->
<?api pi data?>
<!-- still not the document element -->
Changes to tests/xslt.test.
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
    catch {$xmldoc xslt $xsltdoc resultDoc} errMsg
    $xmldoc delete
    $xsltdoc delete
    set errMsg
} {The 'current' function is not allowed in Pattern. for '*[current() != 'notthis']' 

Parsed symbols:
     0 WCARDNAME        0 00000.000     0  *
     1 LBRACKET         0 00000.000     1  
     2 FUNCTION         0 00000.000     8  current
     3 LPAR             0 00000.000     9  
     4 RPAR             0 00000.000    10  
     5 NOTEQ            0 00000.000    13  
     6 LITERAL          0 00000.000    23  notthis
     7 RBRACKET         0 00000.000    24  }

set xslt-8.2.xml {<?xml version="1.0"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">
	<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
	</DocumentProperties>
	<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
	</OfficeDocumentSettings>







|
|
|
|
|
|
|
|







1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
    catch {$xmldoc xslt $xsltdoc resultDoc} errMsg
    $xmldoc delete
    $xsltdoc delete
    set errMsg
} {The 'current' function is not allowed in Pattern. for '*[current() != 'notthis']' 

Parsed symbols:
     0 WCARDNAME        0 000000000     0  *
     1 LBRACKET         0 000000000     1  
     2 FUNCTION         0 000000000     8  current
     3 LPAR             0 000000000     9  
     4 RPAR             0 000000000    10  
     5 NOTEQ            0 000000000    13  
     6 LITERAL          0 000000000    23  notthis
     7 RBRACKET         0 000000000    24  }

set xslt-8.2.xml {<?xml version="1.0"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">
	<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
	</DocumentProperties>
	<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
	</OfficeDocumentSettings>