tDOM

Check-in [bfa5b4bab7]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

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

Overview
Comment:wip
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | wip
Files: files | file ages | folders
SHA3-256: bfa5b4bab734b4e6f6774fa4dd75f8f51bf22cd6676b3401fff4bbcf70989797
User & Date: rolf 2019-03-09 15:09:46
Context
2019-03-11
00:47
wip check-in: e2187f0363 user: rolf tags: wip
2019-03-09
15:09
wip check-in: bfa5b4bab7 user: rolf tags: wip
2019-03-07
23:12
Removed an ancient CONST, that somehow sliped in. check-in: afef231e60 user: rolf tags: schema
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/schema.c.

77
78
79
80
81
82
83

84
85
86
87
88
89
90
...
693
694
695
696
697
698
699




























700
701
702
703
704
705
706
...
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
...
766
767
768
769
770
771
772

773
774
775


776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
...
878
879
880
881
882
883
884
885








886
887
888
889
890
891
892
....
1719
1720
1721
1722
1723
1724
1725

1726
1727
1728

1729
1730
1731
1732
1733
1734
1735
....
1777
1778
1779
1780
1781
1782
1783

1784
1785
1786

1787
1788
1789
1790
1791
1792
1793
....
1796
1797
1798
1799
1800
1801
1802

1803
















1804
1805
1806
1807
1808
1809
1810
....
1822
1823
1824
1825
1826
1827
1828

1829
1830
1831
1832
1833
1834
1835
typedef struct
{
    SchemaData *sdata;
    Tcl_Interp    *interp;
    XML_Parser     parser;
    Tcl_DString   *cdata;

    char          *uri;
    int            maxUriLen;
} ValidateMethodData;

/*----------------------------------------------------------------------------
|   Macros
|
................................................................................
        sdata->stack->interleaveState = NULL;
    }
    se = sdata->stack->down;
    sdata->stack->down = sdata->stackPool;
    sdata->stackPool = sdata->stack;
    sdata->stack = se;
}





























/* The cp argument must be type SCHEMA_CTYPE_TEXT */
static int
checkText (
    Tcl_Interp *interp,
    void *clientData,
    char *text
................................................................................
    char *namespace
    )
{
    SchemaCP *cp, *candidate, *icp;
    int hm, ac, i, mayskip, rc;
    int isName = 0;
    SchemaValidationStack *se;
    Tcl_Obj *cmdPtr;

    if (!sdata->stack) return 0;
    se = sdata->stack;
    getContext (cp, ac, hm);

    switch (cp->type) {
    case SCHEMA_CTYPE_NAME:
................................................................................
            candidate = cp->content[ac];
            mayskip = 0;
            switch (candidate->type) {
            case SCHEMA_CTYPE_TEXT:
                if (candidate->nc) {
                    if (!checkText (interp, candidate, "")) {
                        if (sdata->reportCmd) {

                            cmdPtr = Tcl_DuplicateObj (sdata->reportCmd);
                            Tcl_ListObjAppendElement (interp, cmdPtr,
                                                      sdata->self);


                            Tcl_ListObjAppendElement (
                                interp, cmdPtr,
                                Tcl_NewStringObj ("MISSING_TEXT", 22)
                                );
                            sdata->currentEvals++;
                            rc = Tcl_EvalObjEx (interp, cmdPtr,
                                                TCL_EVAL_GLOBAL
                                                | TCL_EVAL_DIRECT);
                            sdata->currentEvals--;
                            Tcl_DecrRefCount (cmdPtr);
                            if (rc != TCL_OK) {
                                return 0;
                            }
                            break;
                        }
                        
                        return 0;
                    }
                }
                break;

            case SCHEMA_CTYPE_ANY:
                updateStack (se, cp, ac);
................................................................................
            }
            if (!mayskip && mustMatch (cp->quants[ac], hm)) {
                return 0;
            }
            ac++;
            hm = 0;
        }
        if (isName) return 0;








        return -1;

    case SCHEMA_CTYPE_VIRTUAL:
    case SCHEMA_CTYPE_CHOICE:
    case SCHEMA_CTYPE_TEXT:
    case SCHEMA_CTYPE_ANY:
        /* Never pushed onto stack */
................................................................................
        || (vdata->sdata->stack
            && (vdata->sdata->stack->pattern->flags & CONSTRAINT_TEXT_CHILD))) {
        if (probeText (vdata->interp, vdata->sdata,
                       Tcl_DStringValue (vdata->cdata)) != TCL_OK) {
            vdata->sdata->validationState = VALIDATION_ERROR;
            XML_StopParser (vdata->parser, 0);
            Tcl_DStringSetLength (vdata->cdata, 0);

            return;
        }
        Tcl_DStringSetLength (vdata->cdata, 0);

    }
    s = name;
    while (*s && *s != '\xFF') {
        i++; s++;
    }
    namespace = NULL;
    if (*s == '\xFF') {
................................................................................
    if (Tcl_DStringLength (vdata->cdata)
        || vdata->sdata->stack->pattern->flags & CONSTRAINT_TEXT_CHILD) {
        if (probeText (vdata->interp, vdata->sdata,
                       Tcl_DStringValue (vdata->cdata)) != TCL_OK) {
            vdata->sdata->validationState = VALIDATION_ERROR;
            XML_StopParser (vdata->parser, 0);
            Tcl_DStringSetLength (vdata->cdata, 0);

            return;
        }
        Tcl_DStringSetLength (vdata->cdata, 0);

    }
    if (probeElementEnd (vdata->interp, vdata->sdata)
        != TCL_OK) {
        vdata->sdata->validationState = VALIDATION_ERROR;
        XML_StopParser (vdata->parser, 0);
    }
}
................................................................................
characterDataHandler (
    void        *userData,
    const char  *s,
    int          len
)
{
    ValidateMethodData *vdata = (ValidateMethodData *) userData;


















    Tcl_DStringAppend (vdata->cdata, s, len);
}

static int
validateString (
    Tcl_Interp *interp,
    SchemaData *sdata,
................................................................................

    parser = XML_ParserCreate_MM (NULL, MEM_SUITE, &sep);
    vdata.interp = interp;
    vdata.sdata = sdata;
    vdata.parser = parser;
    Tcl_DStringInit (&cdata);
    vdata.cdata = &cdata;

    vdata.uri = (char *) MALLOC (URI_BUFFER_LEN_INIT);
    vdata.maxUriLen = URI_BUFFER_LEN_INIT;
    XML_SetUserData (parser, &vdata);
    XML_SetElementHandler (parser, startElement, endElement);
    XML_SetCharacterDataHandler (parser, characterDataHandler);

    if (XML_Parse (parser, xmlstr, len, 1) != XML_STATUS_OK






>







 







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







 







<







 







>



>
>


|











|
<







 







|
>
>
>
>
>
>
>
>







 







>



>







 







>



>







 







>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
...
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
...
776
777
778
779
780
781
782

783
784
785
786
787
788
789
...
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821

822
823
824
825
826
827
828
...
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
....
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
....
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
....
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
....
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
typedef struct
{
    SchemaData *sdata;
    Tcl_Interp    *interp;
    XML_Parser     parser;
    Tcl_DString   *cdata;
    int            onlyWhiteSpace;
    char          *uri;
    int            maxUriLen;
} ValidateMethodData;

/*----------------------------------------------------------------------------
|   Macros
|
................................................................................
        sdata->stack->interleaveState = NULL;
    }
    se = sdata->stack->down;
    sdata->stack->down = sdata->stackPool;
    sdata->stackPool = sdata->stack;
    sdata->stack = se;
}

static int 
recover (
    SchemaData *sdata,
    const char *errType
    )
{
    Tcl_Obj *cmdPtr;
    int rc;
    
    cmdPtr = Tcl_DuplicateObj (sdata->reportCmd);
    Tcl_ListObjAppendElement (interp, cmdPtr,
                              sdata->self);
    Tcl_ListObjAppendElement (
        interp, cmdPtr,
        Tcl_NewStringObj (errType, len)
        );
    sdata->currentEvals++;
    rc = Tcl_EvalObjEx (interp, cmdPtr,
                        TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);
    sdata->currentEvals--;
    Tcl_DecrRefCount (cmdPtr);
    if (rc != TCL_OK) {
        sdata->evalError = 1;
        return 0;
    }
    return 1;
}

/* The cp argument must be type SCHEMA_CTYPE_TEXT */
static int
checkText (
    Tcl_Interp *interp,
    void *clientData,
    char *text
................................................................................
    char *namespace
    )
{
    SchemaCP *cp, *candidate, *icp;
    int hm, ac, i, mayskip, rc;
    int isName = 0;
    SchemaValidationStack *se;


    if (!sdata->stack) return 0;
    se = sdata->stack;
    getContext (cp, ac, hm);

    switch (cp->type) {
    case SCHEMA_CTYPE_NAME:
................................................................................
            candidate = cp->content[ac];
            mayskip = 0;
            switch (candidate->type) {
            case SCHEMA_CTYPE_TEXT:
                if (candidate->nc) {
                    if (!checkText (interp, candidate, "")) {
                        if (sdata->reportCmd) {
                            Tcl_Obj *cmdPtr;
                            cmdPtr = Tcl_DuplicateObj (sdata->reportCmd);
                            Tcl_ListObjAppendElement (interp, cmdPtr,
                                                      sdata->self);
                            fprintf (stderr, "HIER: %s\n",
                                     Tcl_GetString (sdata->self));
                            Tcl_ListObjAppendElement (
                                interp, cmdPtr,
                                Tcl_NewStringObj ("MISSING_TEXT", 12)
                                );
                            sdata->currentEvals++;
                            rc = Tcl_EvalObjEx (interp, cmdPtr,
                                                TCL_EVAL_GLOBAL
                                                | TCL_EVAL_DIRECT);
                            sdata->currentEvals--;
                            Tcl_DecrRefCount (cmdPtr);
                            if (rc != TCL_OK) {
                                return 0;
                            }
                            break;
                        }                        

                        return 0;
                    }
                }
                break;

            case SCHEMA_CTYPE_ANY:
                updateStack (se, cp, ac);
................................................................................
            }
            if (!mayskip && mustMatch (cp->quants[ac], hm)) {
                return 0;
            }
            ac++;
            hm = 0;
        }
        if (isName) {
            if (recover (sdata, "MISSING_ELEMENT")) {
                /* Skip the just opened element tag and the following
                 * content of it. */
                sdata->skipDeep = 2;
                return 1;
            }
            return 0;
        }
        return -1;

    case SCHEMA_CTYPE_VIRTUAL:
    case SCHEMA_CTYPE_CHOICE:
    case SCHEMA_CTYPE_TEXT:
    case SCHEMA_CTYPE_ANY:
        /* Never pushed onto stack */
................................................................................
        || (vdata->sdata->stack
            && (vdata->sdata->stack->pattern->flags & CONSTRAINT_TEXT_CHILD))) {
        if (probeText (vdata->interp, vdata->sdata,
                       Tcl_DStringValue (vdata->cdata)) != TCL_OK) {
            vdata->sdata->validationState = VALIDATION_ERROR;
            XML_StopParser (vdata->parser, 0);
            Tcl_DStringSetLength (vdata->cdata, 0);
            vdata->onlyWhiteSpace = 1;
            return;
        }
        Tcl_DStringSetLength (vdata->cdata, 0);
        vdata->onlyWhiteSpace = 1;
    }
    s = name;
    while (*s && *s != '\xFF') {
        i++; s++;
    }
    namespace = NULL;
    if (*s == '\xFF') {
................................................................................
    if (Tcl_DStringLength (vdata->cdata)
        || vdata->sdata->stack->pattern->flags & CONSTRAINT_TEXT_CHILD) {
        if (probeText (vdata->interp, vdata->sdata,
                       Tcl_DStringValue (vdata->cdata)) != TCL_OK) {
            vdata->sdata->validationState = VALIDATION_ERROR;
            XML_StopParser (vdata->parser, 0);
            Tcl_DStringSetLength (vdata->cdata, 0);
            vdata->onlyWhiteSpace = 1;
            return;
        }
        Tcl_DStringSetLength (vdata->cdata, 0);
        vdata->onlyWhiteSpace = 1;
    }
    if (probeElementEnd (vdata->interp, vdata->sdata)
        != TCL_OK) {
        vdata->sdata->validationState = VALIDATION_ERROR;
        XML_StopParser (vdata->parser, 0);
    }
}
................................................................................
characterDataHandler (
    void        *userData,
    const char  *s,
    int          len
)
{
    ValidateMethodData *vdata = (ValidateMethodData *) userData;
    const char *pc;
    
    if (vdata->onlyWhiteSpace) {
        int i = 0;
        pc = s;
        while (i < len) {
            if ( (*pc == ' ')  ||
                 (*pc == '\n') ||
                 (*pc == '\r') ||
                 (*pc == '\t') ) {
                pc++;
                i++;
                continue;
            }
            vdata->onlyWhiteSpace = 0;
            break;
        }
    }
    Tcl_DStringAppend (vdata->cdata, s, len);
}

static int
validateString (
    Tcl_Interp *interp,
    SchemaData *sdata,
................................................................................

    parser = XML_ParserCreate_MM (NULL, MEM_SUITE, &sep);
    vdata.interp = interp;
    vdata.sdata = sdata;
    vdata.parser = parser;
    Tcl_DStringInit (&cdata);
    vdata.cdata = &cdata;
    vdata.onlyWhiteSpace = 1;
    vdata.uri = (char *) MALLOC (URI_BUFFER_LEN_INIT);
    vdata.maxUriLen = URI_BUFFER_LEN_INIT;
    XML_SetUserData (parser, &vdata);
    XML_SetElementHandler (parser, startElement, endElement);
    XML_SetCharacterDataHandler (parser, characterDataHandler);

    if (XML_Parse (parser, xmlstr, len, 1) != XML_STATUS_OK

Changes to tests/schema.test.

3762
3763
3764
3765
3766
3767
3768
3769


3770


















            element a2
        }
    }
    set result [lsort [s info defelements]]
    s delete
    set result
} {a b}



}

























>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
            element a2
        }
    }
    set result [lsort [s info defelements]]
    s delete
    set result
} {a b}

proc schema-18 {args} {
    lappend ::result {*}$args
}
test schema-18.1 {reportcmd} {
    tdom::schema s
    s define {
        defelement doc {
            element e
            text {minLength 1}
            element e
        }
    }
    s reportcmd schema-18
    set rc [s validate {<doc><e/></doc>} errMsg]
    puts $errMsg
    lappend result $rc
    s delete
    set result
} {MISSING_TEXT s 1}

}