tdom-0.9.5-src/0000755000175000017500000000000014703531020011736 5ustar rolfrolftdom-0.9.5-src/CHANGES0000644000175000017500000004537614703531020012750 0ustar rolfrolf --- Release 0.9.5, 13. Oct 2024 --- 2024-09-27 Rolf Ade Added the asTypedList method to the domDoc and domNode commands. Added the createFromTypedList method to the dom command. 2024-09-23 Rolf Ade Updated to expat 2.6.3. 2024-09-08 Rolf Ade Added the flag -keepTextStart to the expat command. 2024-08-31 Rolf Ade Text node commands created by createNodeCmd of the json type NULL, TRUE or FALSE may be called without argument. 2024-08-26 Rolf Ade Changed the error messages of the dom, domDoc and domNode commands to mostly confirm to ususal Tcl behaviour. 2024-08-14 Rolf Ade Added the asTclValue method to the domDoc and domNode commands. --- Release 0.9.4, 26. Jul 2024 --- 2024-07-02 Rolf Ade Added the isHTML5CustomName method to the dom command. The simple HTML reader now accept HTML5 custom element names. 2024-06-26 Rolf Ade Enhanced the set of recognised entities to HTML 5. 2024-06-01 Rolf Ade Added an optional replacement string argument to the -replace option of the dom command method clearString. 2024-06-01 Rolf Ade Added the -fastcall option to the expat SAX parser. 2024-05-17 Rolf Ade Updated to expat 2.6.2. 2024-05-09 Rolf Ade Added the -list option to the selectNodes method (cascading XPath expressions). 2023-12-29 Rolf Ade Updated to expat 2.5.0. 2023-11-14 Rolf Ade Made tDOM work with Tcl 9. 2023-09-28 Rolf Ade Updated to expat 2.4.9. 2023-05-09 Rolf Ade The XPath functions floor, ceiling and round now return an integer (up to size long). Up to now they appended a .0. It's the right thing but it is a user visible change. 2023-03-25 Rolf Ade Added the option -replace to the dom command method clearString. 2022-09-11 Rolf Ade Added the node command method getByteIndex. Added the submethod byteIndex to the info method of the schema commands. 2022-08-27 Rolf Ade Added the method asCanonicalXML to the domDoc and domNode commands. Added the options -escapeCR and -escapeTab to the method asXML of the domDoc and domNode commands. --- Release 0.9.3, 8. Aug. 2022 --- 2022-06-03 Rolf Ade Added commands tdom::fsnewNode and tdom::fsinsertNode. 2022-05-14 Rolf Ade Updated to expat 2.4.8. 2022-04-17 Rolf Ade Added option -forest to dom parse. 2022-03-19 Rolf Ade Schema command methods validate, validatefile and validatechannel enhanced with options to control external entity resolving. 2022-02-19 Rolf Ade Added the options -billionLaughsAttackProtectionMaximumAmplification and -billionLaughsAttackProtectionActivationThreshold to dom parse and the by the xml::parser/expat command created parser commands. 2022-02-14 Rolf Ade Updated to expat 2.4.4. 2021-06-02 Rolf Ade Updated to expat 2.3.0. 2021-01-22 Rolf Ade Pull-parser command find-element enhanced - skip forward not only to a specific element but to the first out of a list of elements. 2020-12-28 Rolf Ade Updated to expat 2.2.10. --- Release 0.9.2, 27. Aug. 2020 --- 2020-08-21 Rolf Ade Added tdom::schema command. 2020-08-21 Rolf Ade Added -onlyContents and -breakLines to asHTML. 2020-08-17 Rolf Ade Updated TEA. 2020-07-23 Rolf Ade Added -indent value "tab" to asXML and asJSON. 2020-07-03 Rolf Ade User configurable separator character between namespace URI and local name for XML namespace-aware SAX parser: Added the option -namespaceseparator to the expat command. 2020-05-14 Rolf Ade Added method clearString to the dom command. 2019-12-31 Rolf Ade Updated to expat 2.2.9. 2018-10-12 Rolf Ade Updated to expat 2.2.6. 2018-08-08 Rolf Ade Changed the license to MPL 2.0. --- Release 0.9.1, 24. Jul. 2018 --- 2018-07-16 Rolf Ade The package name is tDOM, but it always has been requested by [package require tdom] and now the scripted helper commands in tdom.tcl are also in the namespace tdom (not anymore in tDOM). The new pullparser command is now also in this namespace. There are aliases from the old command names to the new one, so there must be nothing done; old scripts will run as they did. It's just, that you in new code don't have to write serveral upcase letters in a row because of tDOM. 2018-07-14 Rolf Ade Updated to expat 2.2.5. Expat now want to use a "good" entropy source to salt internal hash table (to reduce the possibility of DoS attacts with malicious XML input). Configure tries to figure out automatically the most appropriate entropy source on your platform. The new configure switch --with-entropy gives control over that. The configure switch --without-entropy disables all this; expat (and in turn tDOM) will use what was used in earlier expat versions. 2018-07-12 Rolf Ade Updated TEA. 2018-05-17 Rolf Ade Added new method attributeNames to domNode (cmds). 2018-05-10 Rolf Ade Added new methods line and column to most pull parser states. 2018-05-04 Rolf Ade More fine grain control about serialization details: new asXML options -nogtescape and -noEmptyElementTag. 2018-04-24 Rolf Ade Fixed a potentially dramatic speed problem in case of certain classes of XPath expressions if a threads enabled tDOM is used, the result set is large and the DOM tree to query was altered somewhere before the query by an operation, which appended, inserted or replaced a node. 2018-03-09 Rolf Ade Added command tDOM::pullparser, with creates simple XML "pull" parser commands. This commands parse XML input and stop at certain points ("events"). You continue parsing at your will. 2018-03-06 Rolf Ade Fixed a potentially dramatic speed problem, if the expat parser is used w/ "Welch dispatch" with any 8.6 version. The core changed behaviour, we had to adapt. Added method "delete" to the [expat] push parser (as an alias to the still there "free"). 2018-02-14 Rolf Ade Added [dom featureinfo versionhash], which returns the fossil repository version hash of the sources build from. 2018-02-03 Rolf Ade In a bunch of spell fixes a few changes (partly even marginal, e.g. during configuration) in error messages for uniformly usage of names. 2017-11-07 Rolf Ade New flag -keepCDATA for [dom parse ...]. --- Release 0.9.0, 24. Aug. 2017 --- 2017-08-21 Ashok Nadkarni Windows build system (VC and mingw) modernised. 2017-08-17 Rolf Ade New feature "creating real FQ nodes with *fromScript methods", by adding option -namespace to [dom createNodeCmd]. 2017-08-14 Rolf Ade Updated TEA. 2017-07-29 Rolf Ade Removed hacky check on [load] time if the tclsh and tDOM are build with incompatible TCL_UTF_MAX (because it did not work anymore with recent tcl because of changes in core). 2017-07-28 Rolf Ade Added JSON support. New -json option to [dom parse]. New doc method asJSON. New node method jsonType. New option -jsonType of [dom createNodeCmd]. New option -tagName of [dom createNodeCmd]. New option -jsonType to dom method createDocumentNode. 2017-04-06 Rolf Ade Added HTM5 parser (new -html5 option to [dom parse]). Requires gumbo lib and must be enabled at configure time. 2016-10-01 Rolf Ade Updated to expat 2.2.0. 2015-09-11 Rolf Ade Added options -xmlDeclaration and -encString to the asXML method of the domDoc and domNode commands. 2015-04-11 Rolf Ade Changed behavior wrt to result code of a called -xsltmessagecmd script. Up to now, the result code of that script evaluation was ignored. Now, any other return code of that script then TCL_OK terminates the xslt transformation and returns error. Purposeful termination may be signaled with return -code break, for which the error message will be empty. 2015-04-01 Rolf Ade Added new expat parser cmd method currentmarkup. 2015-03-26 Rolf Ade Added option -indentAttrs to the domDoc/domNode method asXML. Thanks goes to evilotto. 2014-10-16 Rolf Ade Added configure option --with-expat, to build and link against the system or a custom expat lib. Default is, to use the included sources. 2014-01-01 Rolf Ade Rework so some basic internals, for (even) more efficiency of token mode. 2013-12-24 Rolf Ade Improved handling of characters beyond BMP. 2013-12-20 Rolf Ade Added option -feedbackcmd to the dom parse method. This option allows to specify a script, which will be called as feedback command. For backward compatibility, if no -feedbackcmd is given, but there is a tcl proc named ::dom::domParseFeedback then this proc is used as -feedbackcmd. If there isn't such a proc and -feedbackAfter is used, it is an error to not also use -feedbackcmd. A return -code break from the -feedbackcmd causes the parser to almost immediately abort parsing and let the [dom parse] call return the empty string (instead of a document) without raising error. For expat parser objects: If a handler script returns -code return, then parsing is aborted, but no error is raised. 2013-12-04 Rolf Ade tDOM now cross-compiles on linux for windows (w32/w64) with mingw-w64. 2013-09-26 Rolf Ade Added dom method featureinfo. 2013-08-31 Rolf Ade Raised the limit of maximum number of different XML namespaceses within one DOM tree to 2^31. New configure switch --enable-lessns restores old code. 2013-07-21 Rolf Ade Updated TEA build system of tdom itself and the extensions. 2013-05-16 Rolf Ade Update to expat 2.1.0. --- Release 0.8.2, 15. Aug. 2007 --- See ChangeLog for details --- 2007-08-11 Rolf Ade Now tcldomsh will source ~/.tcldomshrc at start up. 2007-08-05 Rolf Ade In case of asXML with indentation: indent XML comments as well. Added method deleteXPathCache: basic control over the xpath expression cache. Variable references in XPath queries (at the places allowed by the XPath syntax) will now be resoved as Tcl variables, relative to the scope of the expression. Ignoring the XPath syntax rules at this point, any valid Tcl variable name will work. 2007-07-31 Rolf Ade Update to expat 2.0.1. 2007-07-27 Rolf Ade Updated to TEA 3.6. 2007-07-25 Rolf Ade Fix for the -externalentitycommand problems on (some) 64-bit plattforms. 2006-11-22 Rolf Ade Normalize case of attribute also (not only elements). 2006-08-26 Rolf Ade Updated the TEA build system to 3.5, to fix build problems with newer bash shells. 2005-03-18 Rolf Ade Added the 'selectNodesNamespace' to documents, to provide a global XPath prefix / namespace mapping. See the user documentation for details. 2005-01-07 Rolf Ade Improved VC++ compiler makefile. Thanks to Pat Thoyts for contribution. 2005-01-06 Rolf Ade Added the methods 'transform' and 'delete' to xsltCmds. 2004-09-21 Rolf Ade Added the '-namespaces' option to the selectNodes method. Not resolved namespace prefixes within the xpath expression now raises an error. *** POTENTIAL INCOMPATIBILITY *** 2004-08-20 Rolf Ade Update to expat 1.95.8. 2004-08-19 Rolf Ade Made tDOM work out of the box on 64-bit systems like Itanium 2 (again) (though --disable-tdomalloc configure option at build time is still needed). --- Release 0.8.0, 11. Aug. 2004 --- See ChangeLog for details --- 2004-07-27 Rolf Ade New method createDocumentNode. Added methods nodeType, getElementById, firstChild, lastChild, appendChild, removeChild, hasChildNodes, childNodes, ownerDocument, insertBefore, replaceChild, appendFromList, appendXML, selectNodes, baseURI, appendFromScript and insertBeforeFromScript to dom docs. Beside other things, this allows much easier handling of top level nodes. The result tree may not be an XML document, but a general parsed entity. New (experimental) method setObjectCommands. 2004-05-26 Rolf Ade Added isPIName, isComment, isCDATA and isPIValue method to the dom command. Created new global (thread wide) flags for name and value checks (Names and FQ Names (element, attribute and processing instruction names), text nodes, comments, CDATA sections and processing instruction values). New methods setNameCheck and setTextCheck to control this flags. 2003-12-17 Rolf Ade Added baseURI method, which returns the current base URI and has an optional argument to set the base URI. (The getBaseURI is deprecated.) 2003-12-11 Rolf Ade Bug fix: Don't quash white space of non white space only content in trim mode. 2003-11-24 Rolf Ade Added domDoc methods omit-xml-declaration, indent, standalone, encoding and mediaType. 2003-10-23 Rolf Ade Update to expat 1.95.7. 2003-10-10 Rolf Ade Added method normalize to domNode and domDoc commands. 2003-10-07 Rolf Ade Added method insertBeforeFromScript to domNode commands. 2003-10-04 Rolf Ade Added method asText to domDoc and domNode commands. 2003-09-22 Rolf Ade Enhanced insertBefore method: If the refNode argument of that method is the empty string, the newNode argument will be inserted at the end of the list of children of the node. 2003-09-17 Rolf Ade Added the up to now missing implementation of expatObj method cget. Thanks goes to Harry Moreau for his contribution. 2003-04-09 Rolf Ade Added domDoc method toXSLTcmd, which converts the domDoc to an XSLTcmd. This has no advantage over the current method in one-shot cases (transformation of one XML document) but improves the speed of batch processing of several XML documents or server applications. The implementation was already included in the 0.7.7 release, only the documentation was not included in that release. Added option -paramentityparsing to the dom parse method. --- Release 0.7.7, 25. Mar. 2003 --- See ChangeLog for details --- --- Release 0.7.6, 24. Mar. 2003 --- See ChangeLog for details --- 2003-03-19 Rolf Ade Added option -useForeignDTD to dom parse and expat. Added domNode method 'precedes', to compare the relative order of two nodes out of the same document. 2003-02-22 Rolf Ade Added posteriori (DOM) validation capabilities. See the tnc man page for details. 2003-02-09 Rolf Ade Update to expat 1.95.6. 2003-02-09 Rolf Ade Added 'systemId' and 'publicId' methods to the domDoc commands. Added flag -doctypeDeclaration to the asXML and asHTML methods of the domDoc commands. 2003-01-29 Rolf Ade Changed the escaping while serializing XML data: in the past """ and "'" was escaped, now it isn't anymore. There isn't a clear rule (to the best of my knowledge) in any of the related specs about this, but now we do things almost along the lines, as saxon (which I regard as the currently most 'rule-setting' xslt processor) does it. In theory (from an XML viewpoint) this should not make a difference, but if somebody postprocess some tDOM output with other tools, there is a small risk, that things (slightly) breaks, therefor: *** POTENTIAL INCOMPATIBILITY *** 2002-12-28 Rolf Ade The xslt method now understands also the options -ignoreUndeclaredParameters and -xsltmessagecmd. --- Release 0.7.5, 27. Nov. 2002 --- See ChangeLog for details --- 2002-10-01 Zoran Vasiljevic The library file lib/tdomhtml.tcl is now moved to a separate package in "extensions" directory. This is a simple, yet very "clever" HTML generator, using advanced tdom HTML capabilities. To use, please change to "extensions/tdomhtml" directory and invoke "configure" followed by "make", followed by "make install". Be sure, however, to build and install the tdom package first. -EOF- tdom-0.9.5-src/aclocal.m40000644000175000017500000000025414703531020013577 0ustar rolfrolf# # Include the TEA standard macro set # builtin(include,tclconfig/tcl.m4) # # Add here whatever m4 macros you want to define for your package # builtin(include,tdom.m4) tdom-0.9.5-src/tests/0000755000175000017500000000000014703531020013100 5ustar rolfrolftdom-0.9.5-src/tests/entity.test0000644000175000017500000001014214703531020015313 0ustar rolfrolf# Features covered: Entities # # This file contains a collection of tests for the different kinds of # entities. # # entity-1.*: parameter entities, character entities # entity-2.*: predefined entities # entity-3.*: -useForeignDTD # entity-4.*: external parsed entities # # Copyright (c) 1999-2000 Zveno Pty Ltd. # Copyright (c) 2000-2004 Rolf Ade # # $Id$ source [file join [file dir [info script]] loadtdom.tcl] proc Start {name attrList args} { incr ::elements } proc pcdata text { append ::result $text } proc EntityRef name { lappend ::references $name append ::result ##entityreference## return {} } test entity-1.1 {parameter entity in document entity} { set ::result {} catch {rename xml::entity-1.1 {}} set parser [xml::parser entity-1.1 \ -characterdatacommand pcdata] $parser parse { ]> %wrong;} set ::result } {%wrong;} test entity-1.2 {character entities in hex} { set ::result {} catch {rename xml::entity-1.2 {}} set parser [xml::parser entity-1.2 \ -characterdatacommand pcdata] $parser parse {A<>$[]} set ::result } {A<>$[]} test entity-1.3 {character entities in decimal} { set ::result {} catch {rename xml::entity-1.3 {}} set parser [xml::parser entity-1.3 \ -characterdatacommand pcdata] $parser parse {A<>$[]} set ::result } {A<>$[]} test entity-1.4 {illegal character entity} { set ::result {} catch {rename xml::entity-1.4 {}} set parser [xml::parser entity-1.4 \ -characterdatacommand pcdata] set err [catch {$parser parse {&#blah;}}] list $err $::result } {1 {}} test entity-2.1 {predefined general entities} { set ::result {} catch {rename xml::entity-2.1 {}} set parser [xml::parser entity-2.1 \ -characterdatacommand pcdata] $parser parse {<>&"'} set ::result } {<>&"'} # emacs: " proc extrefhandler-3 {base args} { global extrefhandlerCalled set extrefhandlerCalled 1 return [list string $base ""] } test entity-3.1 {-useForeignDTD} { set ::extrefhandlerCalled 0 set parser [expat -useForeignDTD 0 \ -externalentitycommand extrefhandler-3 \ -paramentityparsing notstandalone] $parser parse $parser free set ::extrefhandlerCalled } {0} test entity-3.2 {-useForeignDTD} { set ::extrefhandlerCalled 0 set parser [expat -useForeignDTD 1 \ -externalentitycommand extrefhandler-3 \ -paramentityparsing notstandalone] $parser parse $parser free set ::extrefhandlerCalled } {1} test entity-3.3 {-useForeignDTD} { set ::extrefhandlerCalled 0 set parser [expat -useForeignDTD 1 \ -externalentitycommand extrefhandler-3 \ -paramentityparsing notstandalone] $parser parse { ]> } $parser free set ::extrefhandlerCalled } {1} test entity-3.4 {cget -useForeignDTD} { set parser [expat entity-4.4 -useForeignDTD 1] $parser cget -useForeignDTD } 1 proc extrefhandler-4 {args} { global notexistendpath # Search for a not existing file path set base /ae124 set filename 0 set path [file join $base $filename] while {[file exists $path]} { incr filename set path [file join $base $filename] } set notexistendpath $path return [list filename $path $path] } test entity-4.1 {external entity: returned filename dose not exist} -body { set parser [expat -useForeignDTD 1 \ -externalentitycommand extrefhandler-4 \ -paramentityparsing always] set result [catch {$parser parse } errMsg] append result " $errMsg" $parser free set result } -match glob -result {1 error opening file "/ae124/*"} foreach parser [info commands entity-*] { $parser free } # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/schema.test0000644000175000017500000104661314703531020015254 0ustar rolfrolf# Features covered: Schema validation # # Tested functionalities: # schema-1.*: Basics, interface # schema-2.*: Grammar definition ref # schema-3.*: Grammar definition choice # schema-4.*: Script level validation with event # schema-5.*: dom parse -validateCmd # schema-6.*: expat parser -validateCmd # schema-7.*: Validation checks. # schema-8.*: tdom::schema validate method # schema-9.*: Choice # schema-10.*: Any # schema-11.*: attribute, nsattribute # schema-12.*: schemaCmd domvalidate # schema-13.*: XML namespaces # schema-14.*: text # schema-15.*: Constraint cmd tcl # schema-16.*: interleave # schema-17.*: info # schema-18.*: reportcmd, validation error recover # schema-19.*: keyspace # schema-20.*: domunique # schema-21.*: internal: buffers # schema-22.*: defelementtype, elementtype # schema-23.*: validatefile # schema-24.*: validatechannel # schema-25.*: domxpathboolean # schema-26.*: info domNode # schema-27.*: Text constraint commands available outsite schema context # schema-28,*: tdom and interp # schema-29.*: text constrain jsontype # # Copyright (c) 2018-2022 Rolf Ade. source [file join [file dir [info script]] loadtdom.tcl] if {[dom featureinfo schema]} { if {[join [lrange [split [package present Tcl] .] 0 1] .] <= 8.4} { testConstraint 8.5 false testConstraint listformat false } else { testConstraint 8.5 true testConstraint listformat true } proc dummycallback {args} {} proc sortcps {a b} { switch -- [string compare [lindex $a 0] [lindex $b 0]] { -1 {return -1} 1 {return 1} default { return [string compare [lindex $a 1] [lindex $b 1]] } } } test schema-1.1 {create} { tdom::schema create grammar grammar start doc grammar delete } {} test schema-1.2 {grammar cmd outside context} { catch {tdom::schema::element} } {1} test schema-1.3 {grammar cmd} { tdom::schema create grammar grammar defpattern somePattern { element foo ! } grammar delete } {} test schema-1.4 {grammar cmd} { tdom::schema create grammar grammar defpattern somePattern { for {set i 0} {$i < 100} {incr i} { element foo$i ! } } grammar delete } {} test schema-1.5 {grammar cmd} { tdom::schema create grammar grammar defelement doc { element elm1 element elm2 * } grammar defelement elm1 {} grammar defelement elm2 {} grammar delete } {} test schema-1.6 {quants} { tdom::schema create grammar grammar defelement doc { element elm1 element elm2 * element elm3 ! element elm4 + element elm5 ? element elm6 1 element elm7 5 element elm8 12 element elm9 {0 3} element elm9 {1 12} element elm10 "8 " } grammar delete } {} test schema-1.7 {quants} { tdom::schema create grammar grammar defelement doc { for {set i 0} {$i < 100} {incr i} { element elm$i [list $i [expr {$i + 1}]] } } grammar delete } {} test schema-1.8 {Same element name in different Namespaces} { tdom::schema create grammar grammar defelement doc { element elm1 element elm2 } grammar defelement doc ns1 { # Forward defined element inherits child namespace element elm1 element elm2 } grammar defelement doc ns2 { # Forward defined element inherits child namespace element elm1 element elm2 } grammar defelement elm1 ns2 {} grammar defelement elm2 ns2 any set result [catch { grammar defelement elm1 ns1 { choice { element fooElem element barElem + } error } }] grammar defelement elm1 ns1 any grammar defelement elm2 ns1 {} grammar delete set result } 1 test schema-1.9 {Same element name in different Namespaces} { tdom::schema create grammar set result [catch { grammar defelement doc { element elm1 element elm2 } grammar defelement doc ns1 { # Forward defined element inherits child namespace element elm1 element elm2 } grammar defelement doc ns2 { # Forward defined element inherits child namespace element elm1 element elm2 } grammar defelement elm1 ns2 {} grammar defelement elm2 ns2 any grammar defelement elm1 ns1 { choice { element fooElem element barElem + } error } }] grammar delete set result } 1 test schema-1.10 {Local element definition} { tdom::schema create grammar grammar defelement doc { element elm1 element elm1 1 { element a element b } } grammar defelement c text grammar defelement d text grammar defelement elm1 { element c element d } grammar delete } {} test schema-1.11 {define} { tdom::schema create grammar set result [catch {grammar define { element elm1 }} errMsg] grammar delete lappend result $errMsg } {1 {Command not allowed at top level in schema define evaluation}} test schema-1.12 {define} { tdom::schema create grammar set result [catch {grammar define { defelement elm1 { element a element b } element elm1 }} errMsg] grammar delete lappend result $errMsg } {1 {Command not allowed at top level in schema define evaluation}} test schema-1.13 {define lots of elements} { tdom::schema create s s define { defelement elm1 { for {set i 1} {$i <= 1000} {incr i} { element a$i ? } } for {set i 1} {$i <= 1000} {incr i} { defelement a$i {} } } s delete } {} test schema-1.14 {refer local element definition with element} { tdom::schema create s s define { defelement elm1 { element elm ! { element a ! { text } } } defelement elm2 { element elm } } set result [list] foreach xml { foo foo } { lappend result [s validate $xml] } s delete set result } {1 0 0 1} test schema-1.14a1 {define start w/ namespace} { tdom::schema create s s start doc http://foo.bar s defelement doc http://foo.bar { element a element b } foreach elm {a b} { s defelement $elm http://foo.bar {} } set result [list] foreach xml { {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {1 1 1 0} test schema-1.14a {define start w/ namespace} { tdom::schema create s s prefixns {ns1 http://foo.bar} s start doc ns1 s defelement doc ns1 { element a element b } foreach elm {a b} { s defelement $elm ns1 {} } set result [list] foreach xml { {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {1 1 1 0} test schema-1.15 {call structure constraint outside define/defelement} { set result [catch {tdom::schema::element foo} errMsg] lappend result $errMsg tdom::schema create grammar lappend result [catch {tdom::schema::element foo} errMsg] lappend result $errMsg lappend result [catch {grammar define {::tdom::schema::element foo}} errMsg] lappend result $errMsg lappend result [catch {grammar defelement bar {::tdom::schema::element foo}} errMsg] lappend result $errMsg grammar delete set result } {1 {Command called outside of schema context} 1 {Command called outside of schema context} 1 {Command not allowed at top level in schema define evaluation} 0 {}} test schema-1.16 {call another schema cmd in a schema definition script} { tdom::schema create s1 s1 define { defelement s1a { element s1b * element s1c } ::tdom::schema ::s2 s2 define { defelement s1a { element s1b * element s1c } } defelement s1b { element s1b1 } } set result [list] foreach xml { } { lappend result [s1 validate $xml] lappend result [s2 validate $xml] } s1 delete s2 delete set result } {0 0 0 1 1 1 1 0} test schema-1.17 {call schema cmd evaluation in his own schema definition script} { tdom::schema create s1 set result [catch {s1 define { defelement s1a { s1 defelement s1b { element s1b1 } element s1b * element s1c } }} errMsg] s1 delete set result } 1 test schema-1.18 {delete schema cmd in definition script} { tdom::schema create s s define { defelement e { s delete element e1 1 { set ::result [catch {s delete}] } } } lappend result [info commands s] } {1 {}} test schema-1.19 {call top level schema cmd in definition script} { tdom::schema create s set result [catch {s define { defelement e { element e1 1 { deftexttype foo {minLength 1} defelement bar {} } element bar } }}] lappend result [info commands s] s delete set result } {1 s} test schema-1.20 {call top level schema cmd in definition script} { tdom::schema create s set result [catch {s defelement e { element e1 1 { deftexttype foo {minLength 1} defelement bar {} } element bar } }] lappend result [info commands s] s delete set result } {1 s} test schema-1.21 {Create other schema cmd in definition script} { tdom::schema create s1 s1 defelement e { element e1 1 {} element e1 1 { ::tdom::schema create ::s2 ::s2 define { defelement s2 { element s2e element s2ee } foreach e {s2e s2ee} { defelement $e {text} } } } } set result [info commands s1] lappend result [info commands s2] foreach xml { foo } { lappend result [s1 validate $xml] lappend result [s2 validate $xml] } s2 delete s1 delete set result } {s1 s2 1 0 0 1} test schema-1.22 {nrForwardDefinitions} { tdom::schema create s set result [list] s define { defelement e { lappend ::result [s info nrForwardDefinitions] element e1 lappend ::result [s info nrForwardDefinitions] element e1 lappend ::result [s info nrForwardDefinitions] element e2 lappend ::result [s info nrForwardDefinitions] } foreach e {e1 e2} { defelement $e {text} lappend ::result [s info nrForwardDefinitions] } } s delete set result } {0 1 1 2 1 0} test schema-1.23 {prefixns} { tdom::schema create s set result [list] lappend result [s prefixns] lappend result [s prefixns {a b}] lappend result [s prefixns] lappend result [s prefixns {a b a b c d}] lappend result [s prefixns {}] lappend result [s prefixns ""] lappend result [catch {s prefixns a b c} errMsg] lappend result $errMsg lappend result [catch {s prefixns {a b c}} errMsg] lappend result $errMsg lappend result [catch {s prefixns "a \{"} errMsg] lappend result $errMsg s delete set result } {{} {a b} {a b} {a b a b c d} {} {} 1 {wrong # args: should be "s prefixns ?prefixUriList?"} 1 {The optional argument to prefixns must be a 'prefix namespace' pairs list} 1 {The optional argument to prefixns must be a 'prefix namespace' pairs list}} test schema-1.24 {prefixns} { tdom::schema create s set result [list] lappend result [s define prefixns] lappend result [s define {prefixns {a b}}] lappend result [s define {prefixns}] lappend result [s define {prefixns {a b a b c d}}] lappend result [s define {prefixns {}}] lappend result [s define {prefixns ""}] lappend result [catch {s define {prefixns a b c}} errMsg] lappend result $errMsg lappend result [catch {s define {prefixns {a b c}}} errMsg] lappend result $errMsg lappend result [catch {s define {prefixns "a \{"}} errMsg] lappend result $errMsg s delete set result } {{} {a b} {a b} {a b a b c d} {} {} 1 {wrong # args: should be "prefixns ?prefixUriList?"} 1 {The optional argument to prefixns must be a 'prefix namespace' pairs list} 1 {The optional argument to prefixns must be a 'prefix namespace' pairs list}} test schema-1.25 {prefixns} { set result [list] set schema { defelement doc ns1 { element e } } set xml {} # 1 tdom::schema create s s define $schema lappend result [s validate $xml] s delete # 2 tdom::schema create s s prefixns {ns1 http://tdom.org/test} s define $schema lappend result [s validate $xml] s delete # 3 tdom::schema create s s prefixns {ns1 http://foo.bar} s define $schema lappend result [s validate $xml] s delete # 4 tdom::schema create s s prefixns {ns1 http://tdom.org/test ns1 http://foo.bar} s define $schema lappend result [s validate $xml] s delete # 5 tdom::schema create s s prefixns {ns1 http://foo.bar ns1 http://tdom.org/test} s define $schema lappend result [s validate $xml] s delete # 6 tdom::schema create s s prefixns {ns1 http://foo.bar} s prefixns {ns1 http://tdom.org/test ns1 http://foo.bar} s define $schema lappend result [s validate $xml] s delete # 7 tdom::schema create s s define { prefixns {ns1 http://tdom.org/test} defelement doc ns1 { element e } prefixns {ns2 http://foo.bar} defelement e ns2 {text {minLength 1}} } lappend result [s validate $xml] s delete # 8 tdom::schema create s s define { prefixns {ns1 http://tdom.org/test} defelement doc ns1 { namespace http://foo.bar { element e } } prefixns {ns2 http://foo.bar} defelement e ns2 {text {minLength 1}} } lappend result [s validate $xml] # 9 lappend result [s validate {}] # 10 lappend result [s validate {foo}] s delete # 11 tdom::schema create s s define { prefixns {ns1 http://tdom.org/test ns2 http://foo.bar} defelement doc ns1 { namespace ns2 { element e } } prefixns {ns2 http://foo.bar} defelement e ns2 {text {minLength 1}} } lappend result [s validate $xml] # 12 lappend result [s validate {}] # 13 lappend result [s validate {foo}] s delete set result } {0 1 0 1 0 1 1 0 0 1 0 0 1} test schema-1.26 {prefixns} { tdom::schema create s set result [list] lappend result [catch { s defelement doc { prefixns {a http://foo.bar} namespace a { element e } } } errMsg] lappend result $errMsg lappend result [catch { s defelement doc { namespace a { element e } prefixns {a http://foo.bar} } } errMsg] lappend result $errMsg lappend result [catch { s define { defelement doc { prefixns {a http://foo.bar} namespace a { element e } } } } errMsg] lappend result $errMsg lappend result [catch { s define { defelement doc { s prefixns {a http://foo.bar} namespace a { element e } } } } errMsg] lappend result $errMsg s delete set result } {1 {Command only allowed at lop level} 1 {Command only allowed at lop level} 1 {Command not allowed in nested schema define script} 1 {This recursive call is not allowed}} test schema-1.27 {prefixns} { tdom::schema create s s define { prefixns {a http:://some.uri} defelement doc a {} } set result [s validate {} errMsg] lappend result $errMsg s delete set result } {0 {error "Unknown element" at line 1 character 20}} test schema-1.28 {defelement} { tdom::schema s set result [catch { s defelement e { defelement a { element b } } }] s delete set result } 1 test schema-1.29 {defelement} { tdom::schema s catch { s defelement e { element a element b error "some" } } s defelement e { element a element b } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 0 1 0} test schema-1.30 {recurive allowed element} { tdom::schema s s define { defelement doc { element n } defelement n { element n ? } } set xml "" # That's 200000 (and one) nesting level append xml [string repeat "" 20000] append xml "" append xml [string repeat "" 20000] append xml "" set result [s validate $xml] s delete set result } 1 test schema-1.31 {recurive allowed element} { tdom::schema s s define { defelement doc { element n } defelement n { element n ? } } set xml "" # That's 200000 (and one) nesting level append xml [string repeat "" 20000] append xml "" append xml [string repeat "" 20000] append xml "" set result [s validate $xml errMsg] s delete list $result $errMsg } {0 {error "Element "a" doesn't match" at line 1 character 600009}} test schema-1.32 {Unknown root element} { tdom::schema s s define { defelement e { element doc ? { element e } } } set result [s validate ] s delete set result } 0 test schema-1.33 {Error after local defined element} { tdom::schema s set result [catch { s define { defelement a { element b ! { element c ! {} error "triggered" } element a ! { element c ! {} } error } } }] s delete set result } 1 test schema-1.34 {defelement nested in defelement nested in define} { tdom::schema s set result [catch { s define { defelement a { defelement b { element c ! {} } } } } errMsg] s delete lappend result $errMsg } {1 {Command not allowed in nested schema define script}} test schema-1.35 {deftexttype nested in deftexttype nested in define} { tdom::schema s set result [catch { s define { deftexttype foo { minLength 2 ::tdom::schema::deftexttype bar { maxLength 2 } } } } errMsg] s define { deftexttype foo { minLength 2 } deftexttype bar { maxLength 2 } } s delete lappend result $errMsg } {1 {Command called in invalid schema context}} test schema-1.36 {list quant with *} { tdom::schema s s define { defelement doc { element child {2 *} } } set xmls { } lappend xmls "[string repeat 100]" set result "" foreach xml $xmls { lappend result [s validate $xml] } s delete set result } {0 0 1 1 1} test schema-1.37 {invalid quant} { tdom::schema s set result [catch {s define { defelement doc {element foo {a b c} {text}} }}] lappend result [catch {s define { defelement doc {element foo {* *} {text}} }}] s delete set result } {1 1} test schema-1.38 {list quant with *} { tdom::schema s s define { defelement doc { element child {0 *} } } set xmls { } lappend xmls "[string repeat 100]" set result "" foreach xml $xmls { lappend result [s validate $xml] } s delete set result } {1 1 1 1 1} test schema-1.39 {defelement - wrong # of args} { tdom::schema s set result "" catch { s define { defelement e } } errMsg lappend result $errMsg catch { s defelement e } errMsg lappend result $errMsg catch { s define { defelement e 1 2 3 } } errMsg lappend result $errMsg catch { s defelement e 1 2 3 } errMsg lappend result $errMsg s delete set result } {{wrong # args: should be "defelement ?? pattern"} {wrong # args: should be "s defelement ?? pattern"} {wrong # args: should be "defelement ?? pattern"} {wrong # args: should be "s defelement ?? pattern"}} test schema-2.1 {grammar definition: ref} { tdom::schema create grammar grammar defpattern thisPattern { element a element b } grammar defpattern thatPattern { element c element d } grammar defelement doc { ref thisPattern ref thatPattern ? } grammar delete } {} test schema-2.2 {grammar definition: ref} { tdom::schema create grammar set result [grammar info nrForwardDefinitions] grammar defelement doc { ref thisPattern ref thatPattern ? } lappend result [grammar info nrForwardDefinitions] grammar delete set result } {0 2} test schema-2.3 {forward defined ref} { set defs { { ref thisPattern ? } { ref thatPattern } { ref thisPattern ? ref thatPattern } { ref thisPattern ? element a } { ref thatPattern element a } } set xmlinput { } set result [list] foreach def $defs { tdom::schema create s s defelement doc $def foreach xml $xmlinput { lappend result [s validate $xml errMsg] } s delete } set result } {1 0 0 1 0 0 1 0 0 0 1 0 0 1 0} test schema-2.3a {forward defined ref} { tdom::schema s s defelement doc { ref some element a } set result [s validate ] lappend result [s info nrForwardDefinitions] s delete set result } {1 2} test schema-2.4 {forward definded element} { set defs { { element thisElement ? } { element thatElement } { element thisElement ? element thatElement } { element thisElement ? element a } { element thatElement element a } } set xmlinput { } set result [list] foreach def $defs { tdom::schema create s s defelement doc $def foreach xml $xmlinput { lappend result [s validate $xml errMsg] } s delete } set result } {1 0 0 0 0 0 0 0 0 0 1 0 0 0 0} test schema-3.1 {grammar definition: choice} { tdom::schema create grammar grammar defelement doc { element elm choice { element fooElem element barElem + } choice ? { element one {2 3} element two } element three } grammar delete } {} test schema-3.2 {grammar definition: choice} { tdom::schema create grammar grammar defpattern thisPattern { element elm choice { element fooElem element barElem + } choice ? { element one {2 3} element two } element three } grammar delete } {} proc pullValidate {g xml} { tdom::pullparser pp pp input $xml while {[pp next] ne "END_DOCUMENT"} { switch [pp state] { "START_TAG" { $g event start [pp tag] } "END_TAG" { $g event end } "TEXT" { $g event text [pp text] } } } } test schema-4.1 {validation} { tdom::schema create grammar grammar defelement doc { element e1 element e2 * } foreach e {e1 e2} { grammar defelement $e {} } pullValidate grammar { } if {[grammar info vstate] ne "FINISHED"} { error "Wrong state." } grammar reset pullValidate grammar { } if {[grammar info validationstate] ne "FINISHED"} { error "Wrong state." } grammar reset pullValidate grammar { } if {[grammar info vstate] ne "FINISHED"} { error "Wrong state." } grammar delete } {} test schema-4.1a {validation} { tdom::schema create s s defelement doc { element e1 element e2 * } foreach e {e1 e2} { s defelement $e {} } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {1 1 1} test schema-4.2 {validation} { tdom::schema create s s defelement doc { element e1 * } s defelement e1 { element ee1 element ee2 } foreach e {ee1 ee2} { s defelement $e {} } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {1 0 1 1 0} test schema-4.3 {validation} { tdom::schema s s define { defelement addressBook { element card * } defelement card { element name element email } foreach e {name email} { defelement $e {text} } } set result [s validate { John Smith js@example.com Fred Bloggs fb@example.net }] s delete set result } 1 proc schema-4.4 {scmd} { global result catch {$scmd event start foo} errMsg lappend result $errMsg } test schema-4.4 {event on itself in called script} { tdom::schema s s defelement doc { element a ? tcl schema-4.4 [self] element b ? } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {{This method is not allowed in nested evaluation} 1 {This method is not allowed in nested evaluation} 1 {This method is not allowed in nested evaluation} 1} proc schema-4.5 {scmd} { global result $scmd event start foo } test schema-4.5 {event on itself in called script} { tdom::schema s s defelement doc { element a ? tcl schema-4.5 [self] element b ? } set result [list] foreach xml { } { lappend result [catch {s validate $xml errMsg} errMsg] lappend result $errMsg } s delete set result } {1 {error "This method is not allowed in nested evaluation" at line 1 character 6} 1 {error "This method is not allowed in nested evaluation" at line 1 character 15} 1 {error "This method is not allowed in nested evaluation" at line 1 character 13}} test schema-4.6 {event start with namespace} { tdom::schema s s defelement doc http://tdom.org/test { element a ! text } s event start doc http://tdom.org/test s event start a http://tdom.org/test s event text "some text" s event end s event end s delete } {} test schema-4.7 {event start with namespace} { tdom::schema s s defelement doc http://tdom.org/test { element a 1 { attribute att1 } } s event start doc http://tdom.org/test set result [catch {s event start a http://tdom.org/test} errMsg] lappend result $errMsg s delete set result } {1 {Missing mandatory attribute(s)}} test schema-4.8 {event start with namespace} { tdom::schema s s defelement doc http://tdom.org/test { element a 1 { attribute att1 } } s event start doc http://tdom.org/test s event start a {att1 "some data"} http://tdom.org/test s event end s event end s delete } {} test schema-4.9 {event start with namespace w/ namespaced attribute} { tdom::schema s s defelement doc http://tdom.org/test { element a 1 { nsattribute att1 http://tdom.org/test } } s event start doc http://tdom.org/test s event start a {{att1 http://tdom.org/test} "some data"} http://tdom.org/test s event end s event end } {} proc schema-4.10 {scmd} { error "Error raised in schema-4.10" } test schema-4.10 {event - tcl error in called script} { tdom::schema s s defelement doc { tcl schema-4.10 [self] element a } s event start doc set result [catch {s event start a} errMsg] lappend result $errMsg s delete set result } {1 {Error raised in schema-4.10}} test schema-4.11 {event - invalid root} { tdom::schema s s defelement doc {} s reportcmd dummycallback s event start doo s delete } {} test schema-4.12 {event - text without root} { tdom::schema s s defelement doc {} s reportcmd dummycallback set result [catch {s event text foo} errMsg] lappend result $errMsg s delete set result } {1 {No validation started}} test schema-4.13 {event - successive text nodes} { tdom::schema s s define { defelement doc { text integer text { oneOf { integer fixed "foo" } } text number } } set result "" foreach input { {1 2 3} {1 foo 3.2} {1 2 3 4} {foo 2 3} {1 foo} } { lappend result [catch { s event start doc foreach value $input { s event text $value } s event end }] s reset } s delete set result } {0 0 1 1 1} test schema-5.1 {dom parse -validateCmd} { set result [catch { [dom parse -validateCmd tdom::schema ] }] } 1 test schema-5.2 {dom parse -validateCmd} { tdom::schema create grammar grammar defelement doc { element e1 element e2 * } foreach e {e1 e2} { grammar defelement $e {} } dom parse -validateCmd grammar { } doc $doc delete dom parse -validateCmd grammar { } doc $doc delete dom parse -validateCmd grammar { } doc $doc delete } {} proc schema-5.3 {base systemId publicId} { return [list "string" "" ""] } test schema-5.3 {dom parse -validateCmd} { tdom::schema create grammar grammar defelement doc { element e1 element e2 * } foreach e {e1 e2} { grammar defelement $e {} } set result [catch {dom parse -validateCmd grammar \ -externalentitycommand schema-5.3 { ]> &e1;} doc} errMsg] grammar delete set result } 1 test schema-5.4 {define} { tdom::schema create grammar grammar define { defelement elm1 { element a element b } defelement a { element c } defelement b {} defelement c {} } set doc [dom parse -validateCmd grammar { }] $doc delete grammar delete } {} test schema-5.5 {validate tmml doc files} { tdom::schema s set docdir [file join [file dir [info script]] ../doc] set file [file join $docdir tmml.schema] set fd [open $file] set tmmlschema [read $fd] close $fd s define $tmmlschema set result {} foreach tmmlfile { domDoc.xml domNode.xml dom.xml expatapi.xml expat.xml pullparser.xml schema.xml tdomcmd.xml } { set file [file join $docdir $tmmlfile] set fd [open $file] set tmmldoc [read $fd] close $fd lappend result [s validate $tmmldoc] } s delete set result } {1 1 1 1 1 1 1 1} test schema-5.6 {validate tmml doc files} { tdom::schema s s defelement doc { element e1 element e2 * } s event start doc set result [catch {dom parse -validateCmd s {}}] set result } {1} test schema-6.1 {expat parser with -validateCmd} { tdom::schema create grammar grammar defelement doc { element e1 element e2 * } foreach e {e1 e2} { grammar defelement $e {} } ::xml::parser p -validateCmd grammar set result [catch {p parse {}} errMsg] p delete grammar delete set result } 1 test schema-6.2 {expat parser with -validateCmd} { tdom::schema create grammar grammar defelement doc { element e1 element e2 * } foreach e {e1 e2} { grammar defelement $e {} } ::xml::parser p -validateCmd grammar -final 0 set result [list] p parse {} errMsg] lappend result $errMsg lappend result [grammar info vstate] p parse {1/>} p configure -final 1 p reset lappend result [grammar validate ] grammar delete p delete set result } {1 {The schema command is busy} VALIDATING 1} test schema-6.3 {expat parser with -validateCmd} { tdom::schema create grammar grammar defelement doc { element e1 element e2 * } foreach e {e1 e2} { grammar defelement $e {} } ::xml::parser p -validateCmd grammar -final 0 set result [list] p parse {} errMsg] lappend result $errMsg lappend result [grammar info vstate] p parse {c>} p configure -final 1 p reset lappend result [grammar validate ] grammar delete p delete set result } {0 1 READY 1} test schema-6.4 {expat parser with -validateCmd} { tdom::schema create grammar grammar defelement doc { element e1 element e2 * } foreach e {e1 e2} { grammar defelement $e {} } ::xml::parser p -validateCmd grammar -final 0 set result [list] p parse {} errMsg] lappend result $errMsg lappend result [grammar info vstate] p parse {c} p parse {>} p configure -final 1 p reset lappend result [grammar validate ] grammar delete p delete set result } {0 1 READY 1} proc elementstart-6.5 {name attList} { lappend ::result $name } test schema-6.5 {expat parser with -validateCmd} { tdom::schema create grammar grammar defelement doc { element e1 element e2 * } foreach e {e1 e2} { grammar defelement $e {} } ::xml::parser p -validateCmd grammar -final 0\ -elementstartcommand elementstart-6.5 set result [list] p parse {} p configure -final 1 p reset lappend result [grammar validate ] grammar delete p delete set result } {doc e1 1} proc elementstart-6.6 {name attList} { lappend ::result $name if {$name eq "doc"} { grammar delete } } test schema-6.6 {expat parser with -validateCmd} { tdom::schema create grammar grammar defelement doc { element e1 element e2 * } foreach e {e1 e2} { grammar defelement $e {} } ::xml::parser p -validateCmd grammar -final 0\ -elementstartcommand elementstart-6.6 set result [list] p parse {} p configure -final 1 p reset lappend result [info command grammar] p delete set result } {doc e1 {}} test schema-6.7 {expat parser with deleted -validateCmd} { tdom::schema create grammar grammar defelement doc { element e1 element e2 * } foreach e {e1 e2} { grammar defelement $e {} } ::xml::parser p -validateCmd grammar p parse "" p reset grammar delete p parse "" p reset set result [catch {p parse ""}] p delete set result } {1} test schema-7.1 {group} { tdom::schema create grammar grammar defelement doc { element e1 group ! { element e1 element e2 } element e2 * } foreach e {e1 e2} { grammar defelement $e {} } dom parse -validateCmd grammar { } doc $doc delete grammar delete } {} test schema-7.1.1 {group} { tdom::schema create grammar grammar define { defelement doc { element e1 group ! { element e1 element e2 } group ! { element e1 element e2 } element e2 * } foreach e {e1 e2} { defelement $e {} } } dom parse -validateCmd grammar { } doc $doc delete grammar delete } {} test schema-7.2 {group} { tdom::schema create grammar grammar defelement doc { element e1 group 2 { element e1 element e2 } element e2 * } foreach e {e1 e2} { grammar defelement $e {} } dom parse -validateCmd grammar { } doc $doc delete grammar delete } {} test schema-7.2.1 {group} { tdom::schema create grammar grammar define { defelement doc { element e1 group 2 { element e1 element e2 } element e2 * } foreach e {e1 e2} { defelement $e {} } } dom parse -validateCmd grammar { } doc $doc delete grammar delete } {} test schema-7.3 {group with inline defined element} { tdom::schema create grammar grammar define { defelement doc { element e1 group 2 { element e1 1 { element e2 } element e2 } element e2 * } foreach e {e1 e2} { defelement $e {} } } dom parse -validateCmd grammar { } doc $doc delete grammar delete } {} test schema-7.4 {group with inline defined element} { tdom::schema create grammar grammar define { defelement doc { group { element e1 element e1 1 { element e2 } element e2 } } foreach e {e1 e2} { defelement $e {} } } dom parse -validateCmd grammar { } doc $doc delete grammar delete } {} test schema-7.5 {group with inline defined element} { tdom::schema create grammar grammar define { defelement doc { group { element e1 element e1 1 { element e2 } element e2 } } foreach e {e1 e2} { defelement $e {} } } ::xml::parser p -validateCmd grammar p parse { } p delete grammar delete } {} test schema-7.6 {nested groups via refs} { tdom::schema create grammar grammar define { defpattern a foouri { group { element e1 element e1 1 { element e2 } element e2 } element e3 ? } defpattern b foouri { element b1 3 group 3 { element b2 ref a } } foreach e {e1 e2 e3 b1 b2} { defelement $e foouri {} } defelement doc foouri { group { ref a ref b } } } set result [grammar validate { }] grammar delete set result } 1 test schema-7.7 {nested groups via refs} { tdom::schema create grammar grammar define { defpattern a { group { element e1 element e1 1 { element e2 } element e2 } element e3 ? } defpattern b { element b1 * group 1 { element b2 ref a } } foreach e {e1 e2 e3 b1 b2} { defelement $e {} } defelement doc { group 2 { ref b } } } set doc [dom parse -validateCmd grammar { }] $doc delete set result [grammar validate { } msg] grammar delete set result } 1 test schema-7.8 {nested groups via refs} { tdom::schema create grammar grammar define { defpattern a foouri { group { element e1 element e1 1 { element e2 } element e2 } element e3 ? } foreach e {e1 e2 e3 b1 b2} { defelement $e foouri {} } defelement doc foouri { group { ref a } } } set doc [dom parse -validateCmd grammar { }] $doc delete grammar delete } {} test schema-7.9 {loop over seq} { tdom::schema create grammar grammar define { defelement doc { group * { element a element b } element c } foreach e {a b c} { defelement $e {} } } set result [grammar validate ] grammar delete set result } 1 test schema-7.10 {loop over seq} { tdom::schema create grammar grammar define { defelement doc { group { element a element b } element c } foreach e {a b c} { defelement $e {} } } set result [grammar validate ] grammar delete set result } 0 test schema-7.10a {loop over seq} { tdom::schema create grammar set result [catch {grammar define { defelement doc { group 2 { element a element b } element c foreach e {a b c} { defelement $e {} } } }}] grammar delete set result } 1 test schema-7.10b {loop over seq} { tdom::schema create grammar grammar define { defelement doc { group { element a element b } element c } foreach e {a b c} { defelement $e {} } } set result [grammar validate errMsg] grammar delete set result } 0 test schema-7.10c {loop over seq} { tdom::schema create grammar grammar define { defelement doc { group { element a element b } element c } foreach e {a b c} { defelement $e {} } } set result [catch { set doc [dom parse -validateCmd grammar ] }] grammar delete set result } 1 test schema-7.11 {loop over seq} { tdom::schema create grammar grammar define { defelement doc { group * { element a element b } element c } foreach e {a b c} { defelement $e {} } } set result [list] foreach xml { } { lappend result [grammar validate $xml] } grammar delete set result } {1 1 1 0} test schema-7.11b {loop over seq} { tdom::schema create grammar grammar define { defelement doc { group 2 { element a ? element b ? } element c } foreach e {a b c} { defelement $e {} } } set result [list] foreach xml { } { lappend result [grammar validate $xml] } grammar delete set result } {1 1 1 0} test schema-7.12 {loop over seq} { tdom::schema create grammar grammar define { defelement doc { group { element a element b } element c } foreach e {a b c} { defelement $e {} } } set result [grammar validate errMsg] lappend result [grammar validate ] lappend result [grammar validate ] lappend result [grammar validate ] lappend result [grammar validate ] grammar delete set result } {0 0 1 0 0} test schema-7.13 {long sequence} { tdom::schema create s s define { defelement doc { for {set i 1} {$i < 200} {incr i} { element e$i } } for {set i 1} {$i < 200} {incr i} { defelement e$i {element a} } defelement a {} } set xml "" for {set i 1} {$i < 200} {incr i} { append xml "" } append xml "" set result [s validate $xml] s delete set result } 1 test schema-7.14 {mixed} { tdom::schema create s s define { defelement doc { mixed { element a element b } } foreach e {a b} { defelement $e {} } } set result [list] foreach xml { text text some some } { lappend result [s validate $xml] } s delete set result } {1 1 1 1 1 0} test schema-7.14a {mixed} { tdom::schema create s s define { defelement doc { mixed ! { element a element b } } foreach e {a b} { defelement $e {} } } set result [list] foreach xml { text text {to much} some } { lappend result [s validate $xml] } s delete set result } {1 0 1 0 0 0} test schema-7.14b {mixed} { tdom::schema create s s define { defelement doc { mixed ! { element a * element b } } foreach e {a b} { defelement $e {} } } set result [list] foreach xml { text text {to much} some } { lappend result [s validate $xml] } s delete set result } {1 0 1 1 1 0 0 0 0} test schema-7.15 {choice with optional choices} { tdom::schema create s s define { defelement doc { choice { element a * element b * } element c } foreach e {a b c} { defelement $e {} } } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 0 1 0 1 1 1} test schema-7.15a {choice with optional choices} { tdom::schema create s s define { defelement doc { choice { element a * element b * } } foreach e {a b} { defelement $e {} } } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {1 1 0 1 0 0 1} test schema-7.15b {choice with optional choices} { tdom::schema create s s define { defelement doc { choice { element a * element b } } foreach e {a b} { defelement $e {} } } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {1 1 0 1 0 0 1} test schema-7.16 {choice with optional choices} { tdom::schema create s s define { defelement doc { choice { element a * group * { element aa element ab ? } } element c } foreach e {a aa ab c} { defelement $e {} } } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 0 1 0 1 1 1 1 1} test schema-7.17 {choice with optional choices} { tdom::schema create s s define { defelement doc { choice { element a * group { element aa element ab ? } } element c } foreach e {a aa ab c} { defelement $e {} } } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 0 1 0 1 1 0 0 1} test schema-7.18 {choice} { tdom::schema create s s define { defelement doc { choice { element a group { element aa element ab ? } } element c } foreach e {a aa ab c} { defelement $e {} } } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 0 1 0 0 1 0 0 0} test schema-7.19 {choice with quantified choice} { tdom::schema create s s define { defelement doc { choice { element a {0 2} group { element aa element ab ? } } element c } foreach e {a aa ab c} { defelement $e {} } } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 0 1 1 0 0 0 1 0 0 1} test schema-7.20 {group with only optional content} { tdom::schema create s s define { defelement doc { element a group { element b ? element c ? } } foreach e {a b c} { defelement $e {} } } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 1 1 0 1 1 0} test schema-7.21 {group with only optional content} { set def { group + { element c ? element a ? element b ? } element d } set result [list] tdom::schema s s defelement doc $def foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 0 1 1 1 1 1 1 1 0} test schema-7.22 {Constraint text content in seq} { tdom::schema s s defelement doc { element a text { minLength 4 } element b } set result [list] foreach xml { 1234 123 12345 { } { } } { lappend result [s validate $xml] } s delete set result } {0 1 0 1 0 0} test schema-7.23 {Whitespace in implicit defined element} { tdom::schema s s defelement doc { element a } set result [list] foreach xml { { } { } { } {12} { } { } } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 1 0 0 0 0} test schema-7.23a {Whitespace in implicit defined element} { tdom::schema s s defelement doc { element a } set result [list] foreach xml { { } } { lappend result [s validate $xml] } s delete set result } {0} test schema-8.1 {validate method} { tdom::schema create grammar grammar defelement doc { element e1 element e2 * } foreach e {e1 e2} { grammar defelement $e {} } set result [grammar validate ] lappend result [grammar validate errMsg] lappend result [grammar validate errMsg] lappend result [grammar validate errMsg] lappend result [grammar validate errMsg] grammar delete set result } {1 0 1 1 0} test schema-8.2 {validate method} { tdom::schema create grammar grammar defelement doc foouri { element e1 element e2 * } foreach e {e1 e2} { grammar defelement $e foouri {} } set result [grammar validate {}] lappend result [grammar validate {} errMsg] grammar delete set result } {1 0} test schema-8.3 {validate method: white space between elements} { tdom::schema create grammar grammar define { defpattern a { group { element e1 element e1 1 { element e2 } element e2 } element e3 ? } defpattern b { element b1 * group 2 { element b2 ref a } } foreach e {e1 e2 e3 b1 b2} { defelement $e {} } defelement doc { group { ref b } } } set result [grammar validate { } msg] grammar delete set result } 1 test schema-8.4 {illegal text} { tdom::schema create grammar grammar define { defelement doc { group * { element a element b } element c } foreach e {a b c} { defelement $e {} } } set result [grammar validate wrong errMsg] grammar delete set result } 0 test schema-8.5 {illegal text - expat not signaling XML_STATUS_SUSPENDED although XML_StopParser() was called in handler, again.} { tdom::schema create grammar grammar define { defelement doc { group * { element a element b } element c } foreach e {a b c} { defelement $e {} } } set result [grammar validate wrong errMsg] grammar delete set result } 0 test schema-8.6 {} { tdom::schema create s s define { defelement doc {} } set result [s validate ] lappend result [s validate ] s start mydoc lappend result [s validate ] s delete set result } {1 0 0} proc schema-8.7 {scmd} { global result lappend result "in schema-8.7" $scmd delete error "this is deliberate" } test schema-8.7 {Delete schema cmd in script called by validation} { set result "" lappend result [info commands s] tdom::schema s lappend result [info commands s] s defelement doc { tcl schema-8.7 [self] } lappend result [catch {s validate } errMsg] lappend result $errMsg lappend result [info commands s] lappend result [catch {s delete}] } {{} s {in schema-8.7} 1 {error "this is deliberate" at line 1 character 6} {} 1} proc extRefHandler-8.8 {base systemId publicId} { switch $systemId { "e1" {return [list string $base "o"]} "e2" {return [list string $base "abc"]} default {error "extRefHandler: Unexpeted SYSTEM id"} } } test schema-8.8 {External entities} { set result "" tdom::schema s s define { defelement doc { text {enumeration {boo bar baz}} element e { element ee {text} } } } foreach xml { { ]> b&e1;o&e2; } } { lappend result [s validate -externalentitycommand extRefHandler-8.8 $xml] } s delete set result } {1} test schema-9.1 {choice} { tdom::schema create grammar grammar define { defelement doc foouri { choice * { element e1 element e2 } } foreach e {e1 e2} { defelement $e foouri {} } } set result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] grammar delete set result } {1 1 1 1 1 1} test schema-9.2 {group} { tdom::schema create grammar grammar define { defelement doc foouri { group { element e1 element e2 * } } foreach e {e1 e2} { defelement $e foouri {} } } set result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] grammar delete set result } {0 1 0 0 0 0 1} test schema-9.3 {choice} { tdom::schema create grammar grammar define { defelement doc foouri { choice * { element e1 group { element e2 element e3 } } } foreach e {e1 e2} { defelement $e foouri {} } } set result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] grammar delete set result } {1 1 1 1 1 1 0} test schema-9.4 {choice} { tdom::schema create grammar grammar define { defelement doc foouri { choice 2 { element e1 group { element e2 element e3 } } } foreach e {e1 e2 e3} { defelement $e foouri {} } } set result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] lappend result [grammar validate {}] grammar delete set result } {0 0 0 1 1 1 1 0} test schema-9.5 {choice as choice child} { tdom::schema create grammar grammar define { defelement doc { choice { element e1 element e2 choice { element e2 element e3 } } } foreach e {e1 e2 e3} { defelement $e foouri {} } } set result [list] foreach xml { } { lappend result [grammar validate $xml] } grammar delete set result } {0 1 0 1 1 0} test schema-9.6 {mixed as choice child} { tdom::schema create grammar grammar define { defelement doc { choice { element e1 element e2 mixed { element e2 element e3 } } } foreach e {e1 e2 e3} { defelement $e foouri {} } } set result [list] foreach xml { {} {} {} {} {} } { lappend result [grammar validate $xml] } grammar delete set result } {1 1 0 1 1 0} test schema-9.7 {choice as mixed child} { tdom::schema create grammar grammar define { defelement doc { mixed { element e1 element e2 choice { element e2 element e3 } } } foreach e {e1 e2 e3} { defelement $e foouri {} } } set result [list] foreach xml { {} {} {} {} {} } { lappend result [grammar validate $xml] } grammar delete set result } {1 1 1 1 1 0} test schema-9.8 {choice as choice child} { tdom::schema create grammar grammar define { defelement doc { choice { element e1 element e2 choice 2 { element e3 element e4 } } } } set result [list] foreach xml { {} {} {} {} {} {} } { lappend result [grammar validate $xml] } grammar delete set result } {0 1 0 1 1 1 0} test schema-9.9 {choice with optional cp belong the choices} { tdom::schema create grammar grammar define { defelement doc { element e1 choice { element e2 element e3 ? } element e4 ? } } set result [list] foreach xml { {} {} {} {} {} {} } { lappend result [grammar validate $xml] } grammar delete set result } {0 1 1 1 1 1 1} test schema-9.10 {choice with may choices} { tdom::schema create grammar grammar define { defelement doc { element e1 choice * { for {set i 1} {$i <= 20} {incr i} { element ee$i } } element e2 ? } } set result [list] foreach xml { {} {} {} {} {} {} } { lappend result [grammar validate $xml] } grammar delete set result } {0 1 1 1 1 0 1} test schema-9.11 {choice with may choices} { tdom::schema create grammar grammar define { defelement doc { element e1 choice * { for {set i 1} {$i <= 20} {incr i} { namespace foo { element ee$i } element ee$i } } element e2 ? } } set result [list] foreach xml { {} {} {} {} {} {} {} } { lappend result [grammar validate $xml] } grammar delete set result } {0 1 1 1 1 0 1} test schema-10.1 {any} { tdom::schema create s s define { defelement doc { element a any element b } defelement a {} defelement b {} } set result [list] foreach xml { text } { lappend result [s validate $xml] } s delete set result } {1 1} test schema-10.2 {any} { tdom::schema create s s define { defelement doc { element a any 1 element b } defelement a {} defelement b {} } set result [s validate {}] lappend result [s validate {}] lappend result [s validate {}] lappend result [s validate {text}] s delete set result } {1 0 0 1} test schema-10.3 {any} { tdom::schema create s s define { defelement doc { element a any ? element b } defelement a {} defelement b {} } set result [s validate {}] lappend result [s validate {}] lappend result [s validate {}] lappend result [s validate {text}] s delete set result } {1 0 0 1} test schema-10.4 {any} { tdom::schema create s s define { defelement doc { element a any 2 element b } defelement a {} defelement b {} } set result [list] foreach xml { {} {} {} {text} } { lappend result [s validate $xml] } s delete set result } {0 1 0 0} test schema-10.5 {any} { tdom::schema create s s define { defelement doc { element a any http://foo.bar 2 element b } defelement a {} defelement b {} } set result [list] foreach xml { {} {} {} {text} {some} {some} {some} } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 1 1 0} test schema-10.6 {any} { tdom::schema create s s define { defelement doc { any } } set result [list] foreach xml { {} } { lappend result [s validate $xml] } s delete set result } {1} test schema-10.7 {any} { set xmls { {} {} {} {text} {some} {} } set result [list] foreach schema { { defelement doc { element a any element b } } { defelement doc { element a any {""} element b } } { defelement doc { element a any {"" http://foo.grill} element b } } { defelement doc { element a any {http://foo.grill http://foo.bar} element b } } { prefixns {bar http://foo.bar grill http://foo.grill} defelement doc { element a any {bar grill} element b } } } { tdom::schema create s s define $schema foreach xml $xmls { lappend result [s validate $xml] } s delete } set result } {1 1 0 1 1 1 1 1 0 1 0 0 1 1 0 1 0 1 0 0 0 0 1 1 0 0 0 0 1 1} test schema-10.8 {any -not} { set xmls { {} {} {} {text} {some} {} } set result [list] foreach schema { { defelement doc { element a any -not {} element b } } { defelement doc { element a any -not {""} element b } } { defelement doc { element a any -not {"" http://foo.grill} element b } } { defelement doc { element a any -not {http://foo.grill http://foo.bar} element b } } { prefixns {bar http://foo.bar grill http://foo.grill} defelement doc { element a any -not {bar grill} element b } } } { tdom::schema create s s define $schema foreach xml $xmls { lappend result [s validate $xml] } s delete } set result } {1 1 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 1 1 0 1 0 0 1 1 0 1 0 0} test schema-10.9 {any --} { set xmls { {} {some} {some} } tdom::schema create s s define { defelement doc { element a any -- -not element b } } set result "" foreach xml $xmls { lappend result [s validate $xml] } s delete set result } {0 1 0} test schema-10.10 {any} { set xmls { {} {} {} {text} {some} {} } set result [list] foreach schema { { defelement doc { element a any -- element b } } { defelement doc { element a any -- {""} element b } } { defelement doc { element a any -- {"" http://foo.grill} element b } } { defelement doc { element a any -- {http://foo.grill http://foo.bar} element b } } { prefixns {bar http://foo.bar grill http://foo.grill} defelement doc { element a any -- {bar grill} element b } } } { tdom::schema create s s define $schema foreach xml $xmls { lappend result [s validate $xml] } s delete } set result } {1 1 0 1 1 1 1 0 0 1 0 0 1 0 0 1 0 1 0 0 0 0 1 1 0 0 0 0 1 1} test schema-11.1 {attribute} { tdom::schema create s s define { defelement doc { attribute attr1 attribute attr2 ? } } set result [s validate {}] lappend result [s validate {}] lappend result [s validate {}] lappend result [s validate {}] s delete set result } {1 1 0 0} test schema-11.1a {attribute} { tdom::schema create s s define { defelement doc { attribute attr1 attribute attr2 ? } } set result [list] foreach xml { {} {} {} {} } { lappend result [catch {set doc [dom parse -validateCmd s $xml]} errMsg] catch {$doc delete} s reset } s delete set result } {0 0 1 1} test schema-11.1b {attribute} { tdom::schema create s s define { defelement doc { attribute attr1 attribute attr2 ? } } ::xml::parser p -validateCmd s set result [list] foreach xml { {} {} {} {} } { lappend result [catch {p parse $xml} errMsg] p reset s reset } s delete p delete set result } {0 0 1 1} test schema-11.2 {attribute} { tdom::schema create s s define { defelement e { attribute attr1 element e 1 { attribute attr3 ? attribute attr4 ! } attribute attr2 ? } } set result [s validate {}] lappend result [s validate {}] lappend result [s validate {}] lappend result [s validate {}] lappend result [s validate {}] s delete set result } {1 1 0 1 0} test schema-11.2a {attribute} { tdom::schema create s s define { defelement e { attribute attr1 element e 1 { attribute attr3 ? attribute attr4 ! } attribute attr2 ? } } set result [list] foreach xml { {} {} {} {} {} } { lappend result [catch {set doc [dom parse -validateCmd s $xml]} errMsg] catch {$doc delete} s reset } s delete set result } {0 0 1 0 1} test schema-11.2b {attribute} { tdom::schema create s s define { defelement e { attribute attr1 element e 1 { attribute attr3 ? attribute attr4 ! } attribute attr2 ? } } ::xml::parser p -validateCmd s set result [list] foreach xml { {} {} {} {} {} } { lappend result [catch {p parse $xml} errMsg] p reset s reset } p delete s delete set result } {0 0 1 0 1} test schema-11.3 {attribute} { tdom::schema create s s define { defelement e { attribute attr1 attribute attr3 ? attribute attr4 ! attribute attr2 ? } } set result [s validate errMsg] lappend result $errMsg s delete set result } {0 {error "Missing mandatory attribute(s): attr1 attr4" at line 1 character 4}} test schema-11.3a {attribute} { tdom::schema create s s define { defelement e { attribute attr1 attribute attr3 ? attribute attr4 ! attribute attr2 ? } } set result [catch {dom parse -validateCmd s } errMsg] lappend result $errMsg s delete set result } {1 {Missing mandatory attribute(s): attr1 attr4, referenced at line 1 character 4}} test schema-11.3b {attribute} { tdom::schema create s s define { defelement e { attribute attr1 attribute attr3 ? attribute attr4 ! attribute attr2 ? } } ::xml::parser p -validateCmd s set result [catch {p parse } errMsg] lappend result $errMsg p delete s delete set result } {1 {Missing mandatory attribute(s): attr1 attr4}} test schema-11.4 {attribute} { tdom::schema create s s define { defelement doc { element e 1 { attribute foo nsattribute lang http://www.w3.org/XML/1998/namespace ? } } } set result [s validate {}] s delete set result } {1} test schema-11.4_1 {attribute} { tdom::schema create s s prefixns {1 http://www.w3.org/XML/1998/namespace} s define { defelement doc { element e 1 { attribute foo nsattribute lang 1 ? } } } set result [s validate {}] s delete set result } {1} test schema-11.4a {attribute} { tdom::schema create s s define { defelement doc { element e 1 { attribute foo nsattribute lang http://www.w3.org/XML/1998/namespace ? } } } set result [catch {set doc [dom parse -validateCmd s {}]}] s delete $doc delete set result } 0 test schema-11.4b {attribute} { tdom::schema create s s define { defelement doc { element e 1 { attribute foo nsattribute lang http://www.w3.org/XML/1998/namespace } } } set result [s validate {}] s delete set result } {1} test schema-11.5 {nsattribute} { tdom::schema create s s define { defelement doc { element e 1 { attribute foo nsattribute lang http://www.w3.org/XML/1998/namespace ? } } } set result [catch {set doc [dom parse -validateCmd s {}]}] s delete $doc delete set result } 0 test schema-11.5a {nsattribute} { tdom::schema create s s prefixns {ns1 http://www.w3.org/XML/1998/namespace} s define { defelement doc { element e 1 { attribute foo nsattribute lang ns1 ? } } } set result [catch {set doc [dom parse -validateCmd s {}]}] s delete $doc delete set result } 0 test schema-11.6 {nsattribute} { tdom::schema create s s define { defelement doc { element e 1 { attribute foo nsattribute lang http://www.w3.org/XML/1998/namespace } } } set result [list] foreach xml { {} {} {} {} } { lappend result [catch {set doc [dom parse -validateCmd s $xml]} errMsg] lappend result $errMsg s reset } s delete set result } {1 {Missing mandatory attribute(s): http://www.w3.org/XML/1998/namespace:lang, referenced at line 1 character 19} 1 {Missing mandatory attribute(s): foo, referenced at line 1 character 23} 1 {Unknown attribute "unknown", referenced at line 1 character 24} 1 {Missing mandatory attribute(s): foo http://www.w3.org/XML/1998/namespace:lang, referenced at line 1 character 9}} test schema-11.6 {nsattribute} { tdom::schema create s s prefixns {ns1 http://www.w3.org/XML/1998/namespace} s define { defelement doc { element e 1 { attribute foo nsattribute lang ns1 } } } set result [list] foreach xml { {} {} {} {} } { lappend result [catch {set doc [dom parse -validateCmd s $xml]} errMsg] lappend result $errMsg s reset } s delete set result } {1 {Missing mandatory attribute(s): http://www.w3.org/XML/1998/namespace:lang, referenced at line 1 character 19} 1 {Missing mandatory attribute(s): foo, referenced at line 1 character 23} 1 {Unknown attribute "unknown", referenced at line 1 character 24} 1 {Missing mandatory attribute(s): foo http://www.w3.org/XML/1998/namespace:lang, referenced at line 1 character 9}} test schema-11.7 {attribute} { set defs { {defelement doc {attribute foo}} {defelement doc {group {attribute foo}}} {defpattern some {attribute foo}} {defelement doc {element {attribute foo}}} } set result [list] foreach def $defs { tdom::schema create s lappend result [catch {s define $def}] s delete } set result } {0 1 1 0} test schema-11.8 {attribute} { tdom::schema s s define { defelement doc { element e ! { attribute abc attribute def attribute ghi attribute jkl attribute mno attribute pqr } } } set result [list] foreach xml { {} {} {} } { lappend result [s validate $xml] } s delete set result } {1 0 0} test schema-11.8a {attribute} { tdom::schema s s define { defelement doc { element e ! { attribute abc attribute def attribute ghi attribute optional ? attribute jkl attribute mno attribute pqr } } } set result [list] foreach xml { {} {} {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {1 0 0 1 0 0} proc schema-11.8b {scmd errType} { lappend ::result $errType lappend ::result [$scmd info vaction name] lappend ::result [$scmd info vaction namespace] } test schema-11.8b {attribute} { tdom::schema s s define { defelement doc { element e ! { attribute abc attribute def attribute ghi attribute optional ? attribute jkl attribute mno attribute pqr } } } s reportcmd schema-11.8b set result [list] foreach xml { {} {} {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {1 MISSING_ATTRIBUTE mno {} 1 UNKNOWN_ATTRIBUTE unknown {} 1 1 MISSING_ATTRIBUTE mno {} 1 UNKNOWN_ATTRIBUTE unknown {} 1} test schema-11.9 {attribute} { tdom::schema s s define { prefixns {ns1 http://foo.bar ns2 http://foo.grill ns3 http://bar.grill} defelement doc { element e ! { nsattribute abc ns1 nsattribute abc ns2 attribute abc attribute def attribute optional ? nsattribute optional ns3 ? attribute ghi attribute jkl attribute mno attribute pqr } } } set result [list] foreach xml { {} {} {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {0 1 0 0 1 0} test schema-11.10 {attribute} { tdom::schema s s define { prefixns {ns1 http://foo.bar ns2 http://foo.grill} defelement doc { element e ! { nsattribute abc ns1 nsattribute abc ns2 attribute abc attribute def attribute ghi attribute jkl attribute mno attribute pqr } } } set result [list] foreach xml { {} {} {} } { dom parse $xml doc lappend result [s domvalidate $doc] $doc delete } s delete set result } {0 1 0} test schema-11.10a {attribute} { tdom::schema s s define { prefixns {ns1 http://foo.bar ns2 http://foo.grill ns3 http://bar.grill} defelement doc { element e ! { nsattribute abc ns1 nsattribute abc ns2 attribute abc attribute def attribute optional ? nsattribute optional ns3 ? attribute ghi attribute jkl attribute mno attribute pqr } } } s reportcmd schema-11.8b set result [list] foreach xml { {} {} {} {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {MISSING_ATTRIBUTE abc {} 1 1 MISSING_ATTRIBUTE abc http://foo.bar 1 UNKNOWN_ATTRIBUTE abc http://bar.grill 1 MISSING_ATTRIBUTE abc {} 1 1 UNKNOWN_ATTRIBUTE abc http://bar.grill 1} proc schema-11.11 {scmd errType} { lappend ::result $errType } test schema-11.11 {attribute - required missing} { tdom::schema s s defelement doc { element a + { attribute mode } } s reportcmd schema-11.11 set result "" set doc [dom parse ] lappend result [s domvalidate $doc] $doc delete s delete set result } {MISSING_ATTRIBUTE 1} test schema-12.1 {domvalidate} { tdom::schema s s define { defelement addressBook { element card * } defelement card { element name element email } foreach e {name email} { defelement $e {text} } } set doc [dom parse { John Smith js@example.com Fred Bloggs fb@example.net }] set result [s domvalidate $doc] lappend result [s domvalidate [$doc documentElement]] lappend result [s domvalidate [[$doc documentElement] firstChild]] lappend result [s domvalidate [[[$doc documentElement] firstChild] firstChild]] $doc delete s delete set result } {1 1 1 1} test schema-12.2 {domvalidate} { tdom::schema s s define { defelement addressBook { element card * } defelement card { element name element email } foreach e {name email} { defelement $e {text} } } set doc [dom parse { John Smith js@example.com Fred Bloggs fb@example.net John Smith }] set result [s domvalidate $doc errMsg] lappend result $errMsg $doc delete s delete set result } {0 {/addressBook/card[2]/some: Element "some" doesn't match}} test schema-12.3 {domvalidate w/ attribute} { tdom::schema s s define { defelement doc { attribute type {fixed "1.2"} element a element b } foreach e {a b} { defelement $e {} } } set result [list] foreach xml { {} {} {} {} {} } { set doc [dom parse $xml] lappend result [s domvalidate [$doc documentElement]] lappend result [s validate $xml] $doc delete } s delete set result } {1 1 0 0 0 0 0 0 0 0} test schema-12.4 {domvalidate w/ text} { tdom::schema s s define { defelement doc { attribute type {fixed "1.2"} element a element b } foreach e {a b} { defelement $e text } } set result [list] foreach xml { {} {content} {contentsome text} {textcontentsome text} {some text} } { set doc [dom parse $xml] lappend result [s domvalidate [$doc documentElement]] lappend result [s validate $xml] $doc delete } s delete set result } {1 1 1 1 1 1 0 0 0 0} test schema-12.5 {domvalidate doch w/ xml namespace} { tdom::schema s s define { defelement addressBook http://foo.bar { element card * } defelement card http://foo.bar { element name element email } foreach e {name email} { defelement $e http://foo.bar {text} } } set doc [dom parse { John Smith js@example.com Fred Bloggs fb@example.net }] set result [s domvalidate $doc] lappend result [s domvalidate [$doc documentElement]] lappend result [s domvalidate [[$doc documentElement] firstChild]] lappend result [s domvalidate [[[$doc documentElement] firstChild] firstChild]] $doc delete set doc [dom parse { John Smith js@example.com Fred Bloggs fb@example.net }] lappend result [s domvalidate $doc] lappend result [s domvalidate [$doc documentElement]] lappend result [s domvalidate [[$doc documentElement] firstChild]] lappend result [s domvalidate [[[$doc documentElement] firstChild] firstChild]] $doc delete s delete set result } {1 1 1 1 1 1 1 1} test schema-12.5a {domvalidate doc w/ xml namespace} { tdom::schema s s prefixns {fb http://foo.bar} s define { defelement addressBook fb { element card * } defelement card fb { element name element email } foreach e {name email} { defelement $e fb {text} } } set doc [dom parse { John Smith js@example.com Fred Bloggs fb@example.net }] set result [s domvalidate $doc] lappend result [s domvalidate [$doc documentElement]] lappend result [s domvalidate [[$doc documentElement] firstChild]] lappend result [s domvalidate [[[$doc documentElement] firstChild] firstChild]] $doc delete set doc [dom parse { John Smith js@example.com Fred Bloggs fb@example.net }] lappend result [s domvalidate $doc] lappend result [s domvalidate [$doc documentElement]] lappend result [s domvalidate [[$doc documentElement] firstChild]] lappend result [s domvalidate [[[$doc documentElement] firstChild] firstChild]] $doc delete s delete set result } {1 1 1 1 1 1 1 1} test schema-12.6 {domvalidate only root} { tdom::schema s s reportcmd dummycallback s start doc set doc [dom parse ] set result [s domvalidate $doc] s defelement doc {} lappend result [s domvalidate $doc] s delete $doc delete set result } {1 1} test schema-12.7 {domvalidate invalid root} { tdom::schema s s start doc s reportcmd dummycallback set doc [dom parse ] set result [s domvalidate $doc] s delete $doc delete set result } 1 dom createNodeCmd textNode t test schema-12.8 {domvalidate - successive text nodes} { tdom::schema s s define { defelement doc { text integer text { oneOf { integer fixed "foo" } } text number } } set result "" foreach input { {1 2 3} {1 foo 3.2} {1 2 3 4} } { set doc [dom createDocument doc] set root [$doc documentElement] $root appendFromScript { foreach value $input { t $value } } lappend result [s domvalidate $doc] $doc delete } s delete set result } {1 1 0} test schema-13.1 {XML namespaces} { tdom::schema create s s defelement doc ns1 { # Forward defined element inherits child namespace element elm1 element elm2 } s defelement elm1 ns2 {} s defelement elm1 ns1 { choice { element fooElem element barElem + } } s defelement elm2 ns1 {} s defelement fooElem ns1 {} s defelement barElem ns1 {} set result [list] foreach xml { {} {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 0} test schema-13.2 {XML namespaces} { tdom::schema create s s defelement doc ns1 { namespace ns2 { element elm1 } # Forward defined element inherits child namespace element elm2 } s defelement elm1 ns2 {} s defelement elm1 ns1 { choice { element fooElem element barElem + } } s defelement elm2 ns1 {} s defelement fooElem ns1 {} s defelement barElem ns1 {} set result [list] foreach xml { {} {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 1} test schema-13.3 {Not namespaced elements inside namespaced ones} { tdom::schema s s define { defelement doc ns1 { namespace "" { element e } } defelement e {text {fixed "here"}} } set result "" foreach xml { {here} {here} {here} {here} } { lappend result [s validate $xml] } s delete set result } {1 1 1 0} test schema-14.1 {text: integer} { tdom::schema s s defelement doc { text { integer } } set result [list] foreach xml { 5 eeee 56666 { } { 97 } } { lappend result [s validate $xml] } s delete set result } {0 0 1 0 1 0 0} test schema-14.1.1 {text: integer} { tdom::schema s s defelement doc { text { integer tcl } } set result [list] foreach xml { 5 eeee 56666 { } { +34 } {034} {0034 } {0xAB} } { lappend result [s validate $xml] } s delete set result } {0 0 1 0 1 0 1 1 1 1} test schema-14.1.2 {text: integer} { tdom::schema s s defelement doc { text { integer xsd } } set result [list] foreach xml { 5 eeee 56666 { } { +34 } {034} {0034 } {0xAB} } { lappend result [s validate $xml] } s delete set result } {0 0 1 0 1 0 0 1 0 0} proc proc-14.2 {param text} { if {$text in {one two tree}} { return true } return false } test schema-14.2 {text: tcl} {8.5} { tdom::schema s s define { defelement doc { element a element b } defelement a { text {tcl string is lower -strict} } defelement b { text {tcl proc-14.2 foo} } } set result [list] foreach xml { abctwo aBctwo abcfour } { lappend result [s validate $xml] } s delete set result } {0 0 1 0 0} test schema-14.3 {attribute text: tcl} {8.5} { tdom::schema s s define { defelement doc { element e 1 { attribute a ! {tcl string is lower -strict} attribute b ? {tcl proc-14.2 foo} } } } set result [list] foreach xml { {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {1 0 0 1} test schema-14.4 {text: fixed} { tdom::schema s s define { defelement doc { element e * } defelement e { attribute a ! {fixed enabled} text {fixed something} } } set result [list] foreach xml { {something} {something} {something else} {somethingsomething} {somethingnot} } { lappend result [s validate $xml] } s delete set result } {1 1 0 0 0 0} test schema-14.5 {text: enumeration} { tdom::schema s s define { defelement doc { element e * } defelement e { attribute a {enumeration {enabled disabled}} text {enumeration {enabled disabled "a third"}} } } set result [list] foreach xml { {disabled} {disableda third} {something} {something else} {enabled disabled} } { lappend result [s validate $xml] } s delete set result } {1 1 1 0 0 0} test schema-14.6 {text: match (glob style)} { tdom::schema s s define { defelement doc { element e * } defelement e { text {match {[a-zA-Z]*1[_!]}} } } set result [list] foreach xml { {disabled1_} {dis able1_} {something} {a1!} {a1!/} } { lappend result [s validate $xml] } s delete set result } {1 1 1 0 1 0} test schema-14.6a {text: match (glob style) -nocase} { tdom::schema s s define { defelement doc { element e * } defelement e { text {match -nocase {[A-Z]*1[_!]}} } } set result [list] foreach xml { {disabled1_} {dis able1_} {something} {a1!} {a1!/} } { lappend result [s validate $xml] } s delete set result } {1 1 1 0 1 0} test schema-14.7 {text: regexp} { tdom::schema s s define { defelement doc { element e * } defelement e { text {regexp {^[a-zA-Z]*1[_!]$}} } } set result [list] foreach xml { {disabled1_} {dis able1_} {something} {a1!} {a1!/} } { lappend result [s validate $xml] } s delete set result } {1 0 0 1 0} test schema-14.8 {text: nmtoken, nmtokens} { tdom::schema s s define { defelement doc { attribute a {nmtoken} attribute b {nmtokens} attribute c ? } } set result [list] foreach xml { {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {1 1 1 0 0 1 1 1 1 1 1 1 0 0 0} test schema-14.9 {text: date} { tdom::schema s s define { defelement doc { text date } } set result [list] foreach xml { foo 1 12 1234-12-31 1234-14-31 1234-12-00 1234-02-31 2000-02-29 2001-02-29 2004-02-29 -2004-02-29 1900-02-29 1234-02-01 1234-08-10 1234-08-222 { 1234-08-22} {1234-08-22 } 11234-08-22 0000-02-01 10000-08-22 10000-02-29 10000-02-29Z 2012-03-07Z {2012-03-07Z } 2012-03-07a 2012-03-07+ 2012-03-07+00:00 2012-03-07-00:00 2012-03-07+02:00 2012-03-07+02:70 2012-03-07+12:30 2012-03-07+14:30 2012-03-07+14:00 2012-03-07-14:00 2012-03-07-14:01 2012-03-07-2:30 2012-03-07-02:30Z {2012-03-07-02:30 } 02027-02-01 } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 0 1 0 0 0 1 0 1 1 0 1 1 0 0 0 1 0 1 1 1 1 0 0 0 1 1 1 0 1 0 1 1 0 0 0 0 0} test schema-14.10 {text: number tcl} { tdom::schema s s define { defelement doc { text {number tcl} } } set result [list] foreach xml { { } foo 1 12 1234-12-31 -14.23 .777 -1.2e5 { -1.2e5 } { -1.2e5 e} } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 1 1 0 1 1 1 1 0} test schema-14.10a {text: number xsd} { tdom::schema s s define { defelement doc { text number } } set result [list] foreach xml { { } foo 1 { 1} {1 } { 1 } 12 1234-12-31 -14.23 .777 -1.2e5 { -1.2e5 } { -1.2e5 e} } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 1 0 0 0 1 0 1 1 0 0 0} test schema-14.11 {text: maxLength} { tdom::schema s s define { defelement doc { text { maxLength 6 } } } set result [list] foreach xml { foo 1 12 1234-12-31 -14.23 👮ሴሴሴሴሴ 👮ሴሴሴሴሴ👮 } { lappend result [s validate $xml] } s delete set result } {1 1 1 1 1 0 1 1 0} test schema-14.12 {text: maxLength} { tdom::schema s s define { defelement doc { text {minLength 6} } } set result [list] foreach xml { foo 1 12 1234-12-31 -14.23 👮ሴሴሴሴ 👮ሴሴሴሴሴ 👮ሴሴሴሴሴ👮 } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 0 1 1 0 1 1} test schema-14.13 {text: two constraints} { tdom::schema s s define { defelement doc { text { minLength 6 maxLength 8 } } } set result [list] foreach xml { foo 1 12 1234-12-31 -14.23 👮ሴሴሴሴ 👮ሴሴሴሴሴ 👮ሴሴሴሴሴ👮 1234567890 12345678901234567890 } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 1 0 1 1 0 0} test schema-14.14 {text: one of two types} { tdom::schema s s define { defelement doc { choice { text { minLength 1 maxLength 3 } text {date} } } } set result [list] foreach xml { foo 1 12 1234-12-31 -14.23 👮ሴሴሴሴ 1234-12 12345678901234567890 } { lappend result [s validate $xml] } s delete set result } {0 0 1 1 1 1 0 0 0 0} test schema-14.15 {text: oneOf} { tdom::schema s s define { defelement doc { text { oneOf { maxLength 3 date } } } } set result [list] foreach xml { foo 1 12 1234-12-31 -14.23 👮ሴሴሴሴ 1234-12 12345678901234567890 } { lappend result [s validate $xml] } s delete set result } {1 1 1 1 1 1 0 0 0 0} test schema-14.16 {text: oneOf} { tdom::schema s s define { defelement doc { text { minLength 1 oneOf { maxLength 3 date } } } } set result [list] foreach xml { foo 1 12 1234-12-31 -14.23 👮ሴሴሴሴ 1234-12 12345678901234567890 } { lappend result [s validate $xml] } s delete set result } {0 0 1 1 1 1 0 0 0 0} test schema-14.17 {text: oneOf w/ allOf} { tdom::schema s s define { defelement doc { text { minLength 1 oneOf { allOf { maxLength 3 minLength 1 } date } } } } set result [list] foreach xml { foo 1 12 1234-12-31 -14.23 👮ሴሴሴሴ 1234-12 12345678901234567890 } { lappend result [s validate $xml] } s delete set result } {0 0 1 1 1 1 0 0 0 0} test schema-14.18 {deftexttype} { tdom::schema s s deftexttype len2-4 { minLength 2 maxLength 4 } s defelement doc { element e ! {text type len2-4} } set result [list] foreach xml { { } {1} {12} { } {123} {1234} {1234 } {12345} {123ሴ} } { lappend result [s validate $xml] set rc [catch {dom parse -validateCmd s $xml doc}] if {$rc == 0} { $doc delete } lappend result $rc } s delete set result } {0 1 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0 0 1 0 1 1 0} test schema-14.18a {deftexttype} { tdom::schema s s define { deftexttype len2-4 { minLength 2 maxLength 4 } defelement doc { element e ! {text type len2-4} } } set result [list] foreach xml { { } {1} {12} { } {123} {1234} {1234 } {12345} {123ሴ} } { lappend result [s validate $xml] set rc [catch {dom parse -validateCmd s $xml doc}] if {$rc == 0} { $doc delete } lappend result $rc } s delete set result } {0 1 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0 0 1 0 1 1 0} test schema-14.18b {deftexttype} { tdom::schema s s define { deftexttype len2-4 { minLength 2 maxLength 4 } tdom::schema s1 s1 define { deftexttype len2-4 { minLength 2 maxLength 4 } defelement doc { element e ! {text type len2-4} } } defelement doc { element e ! {text type len2-4} } } set result [list] foreach xml { { } {1} {12} { } {123} {1234} {1234 } {12345} {123ሴ} } { lappend result [s validate $xml] lappend result [s1 validate $xml] set rc [catch {dom parse -validateCmd s $xml doc}] if {$rc == 0} { $doc delete } lappend result $rc set rc [catch {dom parse -validateCmd s1 $xml doc}] if {$rc == 0} { $doc delete } lappend result $rc } s1 delete s delete set result } {0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 0 0 1 1 0 0 1 1 1 1 0 0} test schema-14.19 {deftexttype} { tdom::schema s s deftexttype len2-4 { minLength 2 maxLength 4 } s defelement doc { element e } s defelement e { attribute this type len2-4 attribute foo ? type len2-4 } set result [list] foreach xml { {} {} {} {} {} {} {} {} {} } { lappend result [s validate $xml errMsg] set rc [catch {dom parse -validateCmd s $xml doc}] if {$rc == 0} { $doc delete } lappend result $rc } s delete set result } {0 1 0 1 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 1} test schema-14.19a {deftexttype} { tdom::schema s s deftexttype len2-4 { minLength 2 maxLength 4 } s defelement doc { element e ! { attribute this type len2-4 attribute foo ? type len2-4 } } set result [list] foreach xml { {} {} {} {} {} {} {} {} {} } { lappend result [s validate $xml] set rc [catch {dom parse -validateCmd s $xml doc}] if {$rc == 0} { $doc delete } lappend result $rc } s delete set result } {0 1 0 1 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 1} test schema-14.20 {deftexttype} { tdom::schema s s deftexttype len2-4 { minLength 2 maxLength 4 } s defelement doc { element e ! { nsattribute this http://tdom.org/test { minLength 2 maxLength 4 } nsattribute foo http://tdom.org/test ? type len2-4 } } set result [list] foreach xml { {} {} {} {} {} {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {0 0 1 0 1 0 1 0 0 0} test schema-14.20a {deftexttype} { tdom::schema s s deftexttype len2-4 { minLength 2 maxLength 4 } s define { prefixns { ns2 http://tdom.org/test nsfoo http://foo.bar ns2 http://baz.boo } defelement doc { element e ! { nsattribute this ns2 { minLength 2 maxLength 4 } nsattribute foo ns2 ? type len2-4 } } } set result [list] foreach xml { {} {} {} {} {} {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {0 0 1 0 1 0 1 0 0 0} test schema-14.21 {strip} { tdom::schema s s define { defelement a { text { strip { minLength 3 maxLength 5 } } } } set result [list] foreach xml { { } { 3 } {123} { 123 } { 123 } {1234} {12345} {123456} { 12 34 } } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 1 1 1 1 1 0 1} test schema-14.22 {split} { tdom::schema s s define { defelement doc { element a 1 { text { split { number } } } } } set result [list] foreach xml { { } {1} {-2.1} { -2.1 } {-a} {-a b c} { 1 2 3.5} { 1 a 3.5} {1 2 fooo} {1 2 fooo } } { lappend result [s validate $xml] } s delete set result } {0 0 0 1 1 1 0 0 1 0 0 0} proc schema-14.23 {text} { return [split $text] } test schema-14.23 {split} { tdom::schema s s define { defelement doc { element a 1 { text { split tcl schema-14.23 { number } } } } } set result [list] foreach xml { { } {1} {-2.1} { -2.1 } {-a} {-a b c} {1 2 3.5} { 1 a 3.5} {1 2 fooo} {1 2 3 -4.5} } { lappend result [s validate $xml errMsg] } s delete set result } {0 0 0 1 1 0 0 0 0 0 0 1} proc schema-14.24 {text} { global schema-14.24 switch ${schema-14.24} { 1 {return {1 2 3}} 2 {return {-23.4 .5}} 3 {return {0 a 5}} default {error "Unexpected value of the global var schema-14.24."} } } test schema-14.24 {split} { set schema-14.24 0 tdom::schema s s define { defelement doc { element a 1 { text { split tcl schema-14.24 { number } } } } } set result [list] foreach xml { { } {-a} {1 2 3 -4.5} } { incr schema-14.24 lappend result [s validate $xml errMsg] } s delete set result } {1 1 0} proc schema-14.24a {arg1 arg2 text} { global schema-14.24a if {$arg1 ne "foo" || $arg2 ne "bar"} { error "Unexpected args" } switch ${schema-14.24a} { 1 {return {1 2 3}} 2 {return {-23.4 .5}} 3 {return {0 a 5}} default {error "Unexpected value of the global var schema-14.24."} } } test schema-14.24a {split} { set schema-14.24a 0 tdom::schema s s define { defelement doc { element a 1 { text { split tcl schema-14.24a foo bar { number } } } } } set result [list] foreach xml { { } {-a} {1 2 3 -4.5} } { incr schema-14.24a lappend result [s validate $xml] } s delete set result } {1 1 0} test schema-14.25 {element content id/idref} { tdom::schema s s define { defelement doc { interleave { element id * element idref * } } defelement id {text id} defelement idref {text idref} } set result [list] foreach xml { abc abc abcabc abcabc abcabcabc abcabcabc {abcabcab c} abcabcabc abc123 } { lappend result [s validate $xml] } s delete set result } {1 1 0 1 1 1 1 0 0 0} test schema-14.26 {attribute id/idref} { tdom::schema s s define { defelement doc { interleave { element id * element idref * } } defelement id {attribute id id} defelement idref {attribute idref idref} } set result [list] foreach xml { {} {} {} {} {} {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {1 1 0 1 1 1 1 0 0 0} test schema-14.27 {base64} { tdom::schema s s define { defelement doc { text base64 } } set result [list] foreach xml { {ZVL1} {zvL1} {zvü1} {0a BED E+9} {ub1sU3==} {abc} {===} } { lappend result [s validate $xml] } s delete set result } {1 1 1 0 1 1 0 0} test schema-14.28 {element content id/idref} { tdom::schema s s define { defelement doc { interleave { element id * element idref * element ida * element idrefa * } } defelement id {text id} defelement idref {text idref} defelement ida {text {id a}} defelement idrefa {text {idref a}} } set result [list] foreach xml { abcabc abc abcabc 1abcabcfooabc abcabcabcabc abcabcabcabc } { lappend result [s validate $xml] } s delete set result } {1 1 0 0 0 1 1} test schema-14.29 {element content id/idref} { tdom::schema s s define { defelement doc { interleave { element id * element idref * element ida * element idrefa * } } defelement id {text {id b}} defelement idref {text {idref b}} defelement ida {text {id a}} defelement idrefa {text {idref a}} } set result [list] foreach xml { abcabc abc abcabc 1abcabcfooabc abcabcabcabc abcabcabcabc } { lappend result [s validate $xml] } s delete set result } {1 1 0 0 0 1 1} test schema-14.30 {text: boolean (xsd)} { tdom::schema s s defelement doc { text boolean } set result [list] foreach xml { 5 00 01 1 11 false {false } False FALSE true { true} TrUe } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 0 1 0 1 0 0 0 1 0 0} test schema-14.30a {text: boolean (xsd)} { tdom::schema s s defelement doc { text {boolean xsd} } set result [list] foreach xml { 5 00 01 1 11 false {false } False FALSE true { true} TrUe } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 0 1 0 1 0 0 0 1 0 0} test schema-14.31 {text: boolean (tcl)} { tdom::schema s s defelement doc { text {boolean tcl} } set result [list] foreach xml { 5 0 01 1 11 false f no {no } n { n } {false } False FALSE true { true} TrUe ON } { lappend result [s validate $xml] } s delete set result } {0 0 0 1 0 1 0 1 1 1 0 1 0 0 1 1 1 0 1 1} test schema-14.32 {text: negativeInteger} { tdom::schema s s defelement doc { text negativeInteger } set result [list] foreach xml { 5782 3 +2 +002 1 01 +0 +000 0 -0 -000 -002 -1 -12345 - + { } { -23 } } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0} test schema-14.32.1 {text: negativeInteger tcl} { tdom::schema s s defelement doc { text {negativeInteger tcl} } set result [list] foreach xml { 5782 3 +2 +002 1 01 +0 +000 0 -0 -000 -002 -1 -12345 - + { } { -23 } } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1} test schema-14.33 {text: nonNegativeInteger} { tdom::schema s s defelement doc { text nonNegativeInteger } set result [list] foreach xml { 5782 3 +2 +002 1 01 +0 +000 0 -0 -000 -002 -1 -12345 - + { } } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0} test schema-14.33.1 {text: nonNegativeInteger tcl} { tdom::schema s s defelement doc { text {nonNegativeInteger tcl} } set result [list] foreach xml { 5782 3 +2 +002 1 01 +0 +000 0 -0 -000 -002 -1 -12345 - + { } } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0} test schema-14.34 {text: nonPositiveInteger} { tdom::schema s s defelement doc { text nonPositiveInteger } set result [list] foreach xml { 5782 3 +2 +002 1 01 +0 +000 0 -0 -000 -002 -1 -12345 - + { } } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0} test schema-14.34.1 {text: nonPositiveInteger tcl} { tdom::schema s s defelement doc { text {nonPositiveInteger tcl} } set result [list] foreach xml { 5782 3 +2 +002 1 01 +0 +000 0 -0 -000 -002 -1 -12345 - + { } } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0} test schema-14.35 {text: positiveInteger} { tdom::schema s s defelement doc { text positiveInteger } set result [list] foreach xml { 5782 3 +2 +002 1 01 +0 +000 0 -0 -000 -002 -1 -12345 - + { } } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0} test schema-14.35.1 {text: positiveInteger tcl} { tdom::schema s s defelement doc { text {positiveInteger tcl} } set result [list] foreach xml { 5782 3 +2 +002 1 01 +0 +000 0 -0 -000 -002 -1 -12345 - + { } } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0} test schema-14.36 {text: hexBinary} { tdom::schema s s defelement doc { text {hexBinary} } set result [list] foreach xml { 5782 3ABCDEF0 +2 2 abcd abcde abcdef abcdefg { a0123b} {a0123b } a0123b } { lappend result [s validate $xml] } s delete set result } {0 1 1 0 0 1 0 1 0 0 0 1} test schema-14.37 {text: unsignedByte} { tdom::schema s s defelement doc { text {unsignedByte} } set result [list] foreach xml { 7 +255 -255 -000255 256 65535 000000000000000065535 65536 4294967295 00000000000000004294967295 4294967296 18446744073709551615 018446744073709551615 18446744073709551616 28446744073709551614 3ABCDEF0 { a0123b} {a0123b } a0123b 1.2 } { lappend result [s validate $xml] } s delete set result } {0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0} test schema-14.38 {text: unsignedShort} { tdom::schema s s defelement doc { text {unsignedShort} } set result [list] foreach xml { 7 +255 -255 -000255 256 65535 000000000000000065535 65536 4294967295 00000000000000004294967295 4294967296 18446744073709551615 018446744073709551615 18446744073709551616 28446744073709551614 3ABCDEF0 { a0123b} {a0123b } a0123b 1.2 } { lappend result [s validate $xml] } s delete set result } {0 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0} test schema-14.39 {text: unsignedInt} { tdom::schema s s defelement doc { text {unsignedInt} } set result [list] foreach xml { 7 +255 -255 -000255 256 65535 000000000000000065535 65536 4294967295 00000000000000004294967295 4294967296 18446744073709551615 018446744073709551615 18446744073709551616 28446744073709551614 3ABCDEF0 { a0123b} {a0123b } a0123b 1.2 } { lappend result [s validate $xml] } s delete set result } {0 1 1 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0} test schema-14.40 {text: unsignedLong} { tdom::schema s s defelement doc { text {unsignedLong} } set result [list] foreach xml { 7 +255 -255 -000255 256 65535 000000000000000065535 65536 4294967295 00000000000000004294967295 4294967296 18446744073709551615 018446744073709551615 18446744073709551616 28446744073709551614 3ABCDEF0 { a0123b} {a0123b } a0123b 1.2 } { lappend result [s validate $xml] } s delete set result } {0 1 1 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0} test schema-14.37.1 {text: byte} { tdom::schema s s defelement doc { text {byte} } set result [list] foreach xml { 7 +127 -128 -129 -0002 128 { 34} 0 {101 } a } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 0 1 0 0 1 0 0} test schema-14.38.1 {text: short} { tdom::schema s s defelement doc { text {short} } set result [list] foreach xml { 7 +255 -255 -000255 256 32767 32768 -32768 -32769 -0 -b } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 1 1 1 0 1 0 1 0} test schema-14.41 {text constrains commands outside text constraint} {8.5} { set cmds [info command tdom::schema::text::*] set result {} tdom::schema s foreach cmd $cmds { lappend result [catch {$cmd "some text"}] lappend result [catch { s define [subst "{$cmd}"] } errMsg] lappend result [catch { s define [subst { start doc $cmd }] } errMsg] lappend result [catch { s define [subst { start doc defelement doc { $cmd } }] } errMsg] } if {$result eq [lrepeat [expr {[llength $cmds] * 4}] 1]} { set result 1 } else { set result 0 } set result } 1 test schema-14.43 {text constraint setvar} { tdom::schema s namespace eval ::schema-14.43 { } s defelement doc { text { setvar from_schema-14.43 setvar ::schema-14.43::foo } } s validate "this" s delete list ${::schema-14.43::foo} ${from_schema-14.43} } {this this} test schema-14.44 {text constraint setvar} { tdom::schema s namespace eval ::schema-14.43 { } s defelement doc { element a ! {text {setvar from_schema-14.44}} element b ! {text {setvar from_schema-14.44}} } set result [s validate "ab"] s delete lappend result ${from_schema-14.44} } {1 b} test schema-14.45 {text constraint whitespace} { tdom::schema s s defelement doc { text { whitespace preserve { oneOf { fixed foo allOf { minLength 5 integer } } } } } set result [list] foreach xml { foo 12345 1234 1234a } { lappend result [s validate $xml] } s delete set result } {0 0 1 1 0 0} test schema-14.46 {text constraint whitespace} { tdom::schema s s defelement doc { text { whitespace replace { fixed "foo bar" } } } set result [list] foreach xml { {foo bar} {foo bar} {foo bar} {foo bar} } { lappend result [s validate $xml] } s delete set result } {0 0 1 1 1 0} test schema-14.47 {text constraint whitespace} { tdom::schema s s defelement doc { text { whitespace collapse { fixed "foo bar" } } } set result [list] foreach xml { {foo bar} {foo bar} {foo bar} {foo bar} { foo bar } { foo bar rr} } { lappend result [s validate $xml] } s delete set result } {0 0 1 1 1 1 1 0} test schema-14.48 {text constraint whitespace} { tdom::schema s s defelement doc { text { whitespace preserve { fixed "foo[string repeat " " 300]bar" } } } set xmls { } lappend xmls "foo[string repeat " " 300]bar" set result [list] foreach xml $xmls { lappend result [s validate $xml] } s delete set result } {0 1} test schema-14.49 {text constraint whitespace} { tdom::schema s s defelement doc { text { whitespace collapse { fixed "foo [string repeat "x" 1200]bar" } } } set xmls { } lappend xmls "[string repeat " " 300]foo[string repeat " " 300][string repeat "x" 1200]bar[string repeat " " 300]" set result [list] foreach xml $xmls { lappend result [s validate $xml] } s delete set result } {0 1} test schema-14.50 {text constraint whitespace} { tdom::schema s s defelement doc { element b ! { text { whitespace replace { fixed "foo[string repeat " " 400]bar" } } } } set xml append xml foo [string repeat " \t " 100] bar append xml set result [s validate $xml] s delete set result } 1 test schema-14.51 {text constraint whitespace} { tdom::schema s s defelement doc { element a ! { text { whitespace collapse { fixed "foo [string repeat "x" 1200]bar" } } } element b ! { text { whitespace replace { fixed "foo[string repeat " " 8000]bar" } } } } set xml append xml [string repeat " " 20] foo " " [string repeat x 1200] bar \ [string repeat " " 8000] append xml foo [string repeat " \t " 2000] bar append xml set result [s validate $xml] s delete set result } 1 test schema-14.52 {text constraint whitespace} { tdom::schema s s defelement doc { element a + { text { not { fixed foo fixed bar } } } } set result "" foreach xml { foo bar grill grill bar } { lappend result [s validate $xml] } s delete set result } {0 0 1 1 1 0} test schema-14.54 {text constraint dateTime} { tdom::schema s s define { defelement doc { text dateTime } } set result "" foreach xml { foo 1 2020-07-08T15:58:17 2020-07-08T15:20:00 2020-07-08T15:20:17.7 2020-07-08T15:58:17+02:00 2020-07-08T15:20:17.789 2020-07-08T15:20:17.7890 2020-07-08T15:20:17.0 2020-07-08T15:20:17. 2020-07-08T15:20:17.+02:00 2020-07-08T15:20:17.Z 2020-07-08T15:20:17+Z 2020-07-08T00:20 2020-07-08T00:60:00 2020-07-08T24:00:00 2020-07-08T24:00:00.1 2020-07-08T24:01:00 2020-07-08T24:00:01 2020-12-2215:20:00 2020-12-22 2020-07-08T15:20:17.789+02:00 2020-07-08T15:20:17-02:00 2020-07-08T15:20:17-02:00.0 2020-07-08T15:20:17.0-02:00 " 2020-07-08T15:20:17.0-02:00" "2020-07-08T15:20:17.0-02:00 " } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0} test schema-14.55 {text constraint time} { tdom::schema s s define { defelement doc { text time } } set result "" foreach xml { foo 1 15:58:17 15:20:00 15:20:17.7 15:58:17+02:00 15:20:17.789 15:20:17.7890 15:20:17.0 15:20:17. 15:20:17.+02:00 15:20:17.Z 15:20:17+Z 00:20 00:60:00 24:00:00 24:00:00.1 24:01:00 24:00:01 15:20:17.789+02:00 15:20:17-02:00 15:20:17-02:00.0 15:20:17.0-02:00 " 15:20:17.0-02:00" "T15:20:17.0-02:00 " } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 1 1 0 1 0 0} test schema-14.56 {length} { tdom::schema s s defelement doc { element e ! { text {length 2} } } set result [list] foreach xml { {1} {12} { } {123} {1ሴ} } { lappend result [s validate $xml] set rc [catch {dom parse -validateCmd s $xml doc}] if {$rc == 0} { $doc delete } lappend result $rc } s delete set result } {0 1 0 1 0 1 1 0 1 0 0 1 1 0} test schema-14.57 {length} { tdom::schema s s defelement doc { element e ! { text {length 0} } } set result [list] foreach xml { {1} {12} { } } { lappend result [s validate $xml] } s delete set result } {1 1 0 0 0} test schema-14.58 {text constraint command syntax} { tdom::schema s s deftexttype len2-4 { minLength 2 maxLength 4 } set result [catch {s defelement doc { element e ! {text typs len2-4} }}] s delete set result } 1 test schema-14.59 {Tcl error in text constraint script} { tdom::schema s s defelement doc { element a } set result [catch { s defelement a { text {error "triggered"} } }] s delete set result } 1 test schema-14.60 {Empty element} { tdom::schema s s defelement doc { element a } s defelement a { attribute att ? } ::xml::parser p -validateCmd s set result [list] foreach xml { { } { } { } { } } { lappend result [s validate $xml] lappend result [catch {p parse $xml}] set doc "" lappend result [catch {set doc [dom parse -validateCmd s $xml]}] if {$doc ne ""} { $doc delete } } s delete p delete set result } {0 1 1 1 0 0 1 0 0 1 0 0 1 0 0 0 1 1} test schema-14.61 {Empty element} { tdom::schema s s defelement doc { element a } s defelement a { attribute att ? text } ::xml::parser p -validateCmd s set result [list] foreach xml { { } { } { } { } } { lappend result [s validate $xml] lappend result [catch {p parse $xml}] set doc "" lappend result [catch {set doc [dom parse -validateCmd s $xml]}] if {$doc ne ""} { $doc delete } } s delete p delete set result } {0 1 1 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0} test schema-14.62 {Empty element} { tdom::schema s s defelement doc { element a } ::xml::parser p -validateCmd s set result [list] foreach xml { { } { } { } { } } { lappend result [s validate $xml] lappend result [catch {p parse $xml}] set doc "" lappend result [catch {set doc [dom parse -validateCmd s $xml]}] if {$doc ne ""} { $doc delete } } s delete p delete set result } {0 1 1 1 0 0 1 0 0 1 0 0 0 1 1 0 1 1} test schema-14.63 {type} { tdom::schema s s define { defelement doc { element e + { text { type len2-4 integer } } } deftexttype len2-4 { minLength 2 maxLength 4 } } set result [list] foreach xml { 1 12 12a } { lappend result [s validate $xml] } s delete set result } {0 1 0} test schema-14.64 {text type} { tdom::schema s s define { defelement doc { element child 1 { attribute attr ? { type ns1:mytype } } } deftexttype ns1:mytype { integer } } set result [list] foreach xml { {} {} {} {} {} {} } { lappend result [s validate $xml] } set result } {1 1 0 0 0 0} test schema-14.65 {text type} { tdom::schema s s define { defelement doc { element child 1 { attribute attr ? { type ns1:mytype } } } } set result [list] foreach xml { {} {} {} {} {} {} } { lappend result [s validate $xml] } set result } {1 1 1 1 0 0} test schema-15.1 {constraint cmd tcl} { tdom::schema s s define { defelement a { tcl append ::schema-15.1 [self] element b tcl append ::schema-15.1 [self] } } set ::schema-15.1 "" set msg "nottouched" set result [s validate {} msg] s delete lappend result $msg ${::schema-15.1} set result } {1 nottouched ss} proc schema-15.2-astart {args} { append ::schema-15.2 astart } proc schema-15.2-aend {args} { append ::schema-15.2 aend } test schema-15.2 {constraint cmd tcl} { tdom::schema s s define { defelement doc { element a * } defelement a { tcl schema-15.2-astart element b ! text element c ! text tcl schema-15.2-aend } } set schema-15.2 "" set msg "nottouched" set result [s validate {foobar} msg] s delete lappend result $msg ${schema-15.2} set result } {1 nottouched astartaendastartaend} proc schema-15.3 {type cmd} { lappend ::schema-15.3 $type [$cmd info stack top] } test schema-15.3 {constraint cmd tcl} {8.5} { tdom::schema s s define { defelement doc { element a * } defelement a { tcl schema-15.3 astart [self] element b ! text element c ! text tcl schema-15.3 aend [self] } } set schema-15.3 "" set msg "nottouched" set result [s validate {foobar} msg] s delete lappend result $msg {*}${schema-15.3} set result } {1 nottouched astart a aend a astart a aend a} proc schema-15.4 {text cmd} { if {$text ne "in docContent"} {error "unexpected text argument"} set ::schema-15.4 [$cmd info stack inside] } test schema-15.4 {constraint cmd tcl} { tdom::schema s s define { defelement doc { ref docContent } defpattern docContent { element a tcl schema-15.4 "in docContent" [self] text element b } } set schema-15.4 "" set result [s validate {foo}] s delete lappend result [set schema-15.4] set result } {1 doc} test schema-16.1 {interleave} { tdom::schema s s define { defelement doc { interleave { element a element b element c } } foreach e {a b c} { defelement $e {} } } set result [list] foreach xml { 12 } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 0 0 0} # It's in fact a missing feature: handling ambiguity. # test schema-16.2 {interleave} {knownBug} { # tdom::schema s # s define { # defelement doc { # interleave { # element a 1 { # attribute type {fixed foo} # } # element a 1 { # attribute type {fixed bar} # } # element a 1 { # attribute type {fixed grill} # } # } # } # foreach e {a b c} { # defelement $e {} # } # } # set result [list] # foreach xml { # # {} # {} # {} # {} # {} # 12 # } { # lappend result [s validate $xml] # } # s delete # set result # } {0 1 1 1 0 0} test schema-16.3 {interleave} { tdom::schema s s define { defelement doc { interleave { element a element b + element c } } foreach e {a b c} { defelement $e {} } } set result [list] foreach xml { 12 } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 1 0 0} test schema-16.4 {interleave} { tdom::schema s s define { defelement doc { interleave { element a element b ? element c } } foreach e {a b c} { defelement $e {} } } set result [list] foreach xml { 12 } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 0 1 0} test schema-16.5 {interleave} { tdom::schema s s define { defelement doc { interleave { element a element b * element c } } foreach e {a b c} { defelement $e {} } } set result [list] foreach xml { 12 } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 1 1 0} test schema-16.6 {interleave} { tdom::schema s s define { foreach e {a b1 b2 c} { defelement $e {} } defelement doc { interleave { element a group * { element b1 element b2 } element c } } } set result [list] foreach xml { 12 } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 0 1 1 0} test schema-16.7 {interleave} { tdom::schema s s define { foreach e {a b1 b2 c} { defelement $e {} } defelement doc { interleave { element a group { element b1 element b2 } element c } } } set result [list] foreach xml { 12 } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 0 0 0 0} test schema-16.8 {interleave} { tdom::schema s s define { foreach e {a b1 b2 c} { defelement $e {} } defelement doc { interleave { element a group ? { element b1 element b2 } element c } } } set result [list] foreach xml { 12 } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 0 0 1 0} test schema-16.9 {interleave} { tdom::schema s s define { foreach e {a b1 b2 c} { defelement $e {} } defelement doc { interleave { element a group + { element b1 element b2 } element c } } } set result [list] foreach xml { 12 } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 0 1 0 0} test schema-16.10 {interleave} { tdom::schema s s define { foreach e {a b1 b2 c} { defelement $e {} } defelement doc { interleave { element a group ? { element b1 element b2 } element c } } } set result [list] foreach xml { 12 } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 0 0 1 0} test schema-16.11 {interleave} { tdom::schema s s define { foreach e {a b1 b2 c} { defelement $e {} } defelement doc { interleave { element a choice { element b1 element b2 } element c } } } set result [list] foreach xml { 12 } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 0 0 0 0} test schema-16.12 {interleave} { tdom::schema s s define { foreach e {a b1 b2 c} { defelement $e {} } defelement doc { interleave { element a choice ? { element b1 element b2 } element c } } } set result [list] foreach xml { 12 } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 0 0 1 0} test schema-16.13 {interleave} { tdom::schema s s define { foreach e {a b1 b2 c} { defelement $e {} } defelement doc { interleave { element a choice + { element b1 element b2 } element c } } } set result [list] foreach xml { 12 } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 1 1 0 0} test schema-16.14 {interleave} { tdom::schema s s define { foreach e {a b1 b2 c} { defelement $e {} } defelement doc { interleave { element a choice * { element b1 element b2 } element c } } } set result [list] foreach xml { 12 } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 1 1 1 0} test schema-16.15 {interleave} { tdom::schema s s define { foreach e {a b1 b11 b2 c} { defelement $e {} } defelement doc { interleave { element a choice * { element b1 group { element b11 element b2 } } element c } } } set result [list] foreach xml { 12 } { lappend result [s validate $xml] } s delete set result } {0 1 0 1 0 1 1 0} test schema-16.16 {interleave} { tdom::schema s s define { foreach e {a b1 b11 b2 c} { defelement $e {} } defelement items { interleave { element a element b ? } element c } defelement doc { element items + } } set result [list] foreach xml { {} {} {} } { lappend result [s validate $xml errMsg] } s delete set result } {1 1 0} test schema-16.17 {interleave with all child cp optional} { tdom::schema s s defelement doc { interleave { element a ? element b ? element c ? } element d } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 1 1 1 1 0 1} test schema-16.18 {interleave with all content cp optional} { tdom::schema s s defelement doc { interleave { element a ? element b ? choice { element c ? element c1 ? element c2 ? } } } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {1 1 1 1 1 1 1 0 1 1 0} test schema-16.19 {interleave with all child cp optional} { tdom::schema s s defelement doc { interleave { element a ? element b ? choice { element c ? element c1 ? element c2 ? } } element d } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 1 1 1 1 0 1} test schema-16.20 {interleave with all child cp optional} { tdom::schema s s defelement doc { interleave { element a ? element b ? group { element c ? element c1 ? element c2 ? } } element d } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 1 1 1 1 0 1} test schema-16.21 {interleave with all child cp optional} { tdom::schema s s defelement doc { interleave { element a ? element b ? group { element c ? element c1 ? element c2 ? } } } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {1 1 1 1 1 1 1 0 1 1 0 1 0 1 0} test schema-16.22 {interleave} { tdom::schema s s defelement doc { interleave { element a element b * } } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 1 0 1 1 1 1 0} test schema-17.1 {info} { tdom::schema s s define { foreach e {a b1 b11 b2 c} { defelement $e {} } } set result [lsort [s info definedElements]] s delete set result } {a b1 b11 b2 c} test schema-17.2 {info} { tdom::schema s s define { defelement b { element b1 element b2 } defelement a { element a1 element a2 } } set result [lsort [s info definedElements]] s delete set result } {a b} test schema-17.3 {info} { tdom::schema s s define { defelement b { element b1 1 text element a element b2 } defelement a { element a1 element a2 } } set result [lsort [s info definedElements]] s delete set result } {a b} test schema-17.3a {info definedElements} { tdom::schema s s define { prefixns {ns1 http://ns1.foo ns2 http://ns2.foo} defelement b ns1 { element b1 1 text element a element b2 } defelement b ns2 { element b1 1 text element a element b2 } defelement b { element b1 1 text element a element b2 } defelement a { element a1 element a2 } } set result [lsort -command sortcps [s info definedElements]] s delete set result } {a b {b http://ns1.foo} {b http://ns2.foo}} test schema-17.4 {info} { tdom::schema s s define { defelement b { element b1 1 text element a element b2 } defelement a { element a1 element a2 } } set result [s info definition b] s delete set result } {defelement b { element b1 1 text element a element b2 }} test schema-17.5 {info expected} { tdom::schema s s define { defelement doc { choice ? { element a element c element b } element toplevel ? element musthave element aftermust } } s event start doc set result [s info expected] s delete lsort $result } {a b c musthave toplevel} test schema-17.5a {info expected -ignorematched} { tdom::schema s s define { defelement doc { choice ? { element a element c element b } element toplevel ? element musthave element aftermust } } s event start doc set result [s info expected -ignorematched] s delete lsort $result } {a b c musthave toplevel} test schema-17.5b {info expected} { tdom::schema s s define { defelement doc { choice ? { element a element c element b } element toplevel ? element musthave element aftermust } } s event start doc set result [s info expected -onlymandatory] s delete lsort $result } {musthave} test schema-17.6 {info expected} { tdom::schema s s prefixns {foo http://foo.bar} s define { defelement doc { choice ? { element a element c element b } element toplevel ? namespace foo { element musthave } element aftermust } } s event start doc set result [s info expected] s delete lsort $result } {a b c {musthave http://foo.bar} toplevel} test schema-17.6a {info expected -ignorematched} { tdom::schema s s prefixns {foo http://foo.bar} s define { defelement doc { choice ? { element a element c element b } element toplevel ? namespace foo { element musthave } element aftermust } } s event start doc set result [s info expected -ignorematched] s delete lsort $result } {a b c {musthave http://foo.bar} toplevel} test schema-17.6b {info expected -onlymandatory} { tdom::schema s s prefixns {foo http://foo.bar} s define { defelement doc { choice ? { element a element c element b } element toplevel ? namespace foo { element musthave } element aftermust } } s event start doc set result [s info expected -onlymandatory] s delete lsort $result } {{musthave http://foo.bar}} test schema-17.7 {info expected} {listformat} { tdom::schema s s prefixns {foo http://foo.bar} s define { defelement doc { mixed { element a element c element b } element toplevel ? namespace foo { element musthave } element aftermust } } s event start doc set result [s info expected] s delete lsort $result } {a b c {musthave http://foo.bar} toplevel {{#text} {}}} test schema-17.7a {info expected -ignorematched} {listformat} { tdom::schema s s prefixns {foo http://foo.bar} s define { defelement doc { mixed { element a element c element b } element toplevel ? namespace foo { element musthave } element aftermust } } s event start doc set result [s info expected -ignorematched] s delete lsort $result } {a b c {musthave http://foo.bar} toplevel {{#text} {}}} test schema-17.7b {info expected -onlymandatory} { tdom::schema s s prefixns {foo http://foo.bar} s define { defelement doc { mixed { element a element c element b } element toplevel ? namespace foo { element musthave } element aftermust } } s event start doc set result [s info expected -onlymandatory] s delete lsort $result } {{musthave http://foo.bar}} test schema-17.8 {info expected} {8.5} { tdom::schema s s defelement doc { choice ? { element a element c element b } element toplevel ? element musthave element aftermust } set result [s info expected] s define { foreach elm {a b c} { defelement $elm {} } } lappend result {*}[lsort [s info expected]] s event start doc lappend result {*}[lsort [s info expected]] s event start c s event end lappend result {*}[lsort [s info expected]] s delete set result } {doc a b c doc a b c musthave toplevel musthave toplevel} test schema-17.8a {info expected -ignorematched} {8.5} { tdom::schema s s defelement doc { choice ? { element a element c element b } element toplevel ? element musthave element aftermust } set result [s info expected -ignorematched] s define { foreach elm {a b c} { defelement $elm {} } } lappend result {*}[lsort [s info expected -ignorematched]] s event start doc lappend result {*}[lsort [s info expected -ignorematched]] s event start c s event end lappend result {*}[lsort [s info expected -ignorematched]] s delete set result } {doc a b c doc a b c musthave toplevel musthave toplevel} test schema-17.8b {info expected -onlymandatory} {8.5} { tdom::schema s s defelement doc { choice ? { element a element c element b } element toplevel ? element musthave element aftermust } set result [s info expected -ignorematched] s define { foreach elm {a b c} { defelement $elm {} } } lappend result {*}[lsort [s info expected -onlymandatory]] s event start doc lappend result {*}[lsort [s info expected -onlymandatory]] s event start c s event end lappend result {*}[lsort [s info expected -onlymandatory]] s delete set result } {doc a b c doc musthave musthave} proc schema-17.9 {scmd} { global result foreach e [lsort [$scmd info expected]] { lappend result $e } } test schema-17.9 {info expected from scripted constrain} { tdom::schema s s define { defpattern some { element a ? group ? { element b ? tcl schema-17.9 [self] } element c } defelement doc { ref some ? element may ? element must } } set result "" lappend result [s validate {}] s delete set result } {a b c may must 1} test schema-17.9.1 {info expected from scripted constrain} { tdom::schema s s define { defpattern some { element a ? group ? { element b ? tcl schema-17.9 [self] } element c } defelement doc { element othermay ? ref some ? element may ? element must } } set result "" lappend result [s validate {}] s delete set result } {a b c may must othermay 1} proc schema-17.9a {scmd} { global result foreach e [lsort [$scmd info expected -onlymandatory]] { lappend result $e } } test schema-17.9a {info expected from scripted constrain} { tdom::schema s s define { defpattern some { element a ? group ? { element b ? tcl schema-17.9a [self] } element c } defelement doc { ref some ? element may ? element must } } set result "" lappend result [s validate {}] s delete set result } {must 1} test schema-17.9a.1 {info expected from scripted constrain} { tdom::schema s s define { defpattern some { element a ? group ? { element b ? tcl schema-17.9a [self] } choice ! { element c1 ref some ? } } defelement doc { ref some ? element may ? element must } } set result "" lappend result [s validate {}] s delete set result } {must 1} test schema-17.10 {info expected interleave} {8.5} { set defs { { interleave { element a ? element b element c ? } element d } { interleave { element a ? element b ? element c ? } element d } { interleave ? { element a ? element b element c ? } element d } } set result [list] foreach def $defs { tdom::schema s s defelement doc $def s event start doc lappend result {*}[lsort [s info expected]] s delete } set result } {a b c a b c d a b c d} test schema-17.10a {info expected interleave} {8.5} { set defs { { interleave { element a ? element b element c ? } element d } { interleave { element a ? element b ? element c ? } element d } { interleave ? { element a ? element b element c ? } element d } } set result [list] foreach def $defs { tdom::schema s s defelement doc $def s event start doc lappend result {*}[lsort [s info expected -ignorematched]] s delete } set result } {a b c a b c d a b c d} test schema-17.11 {info expected} { set defs { { group + { element c ? element a ? element b ? } element d } } set result [list] foreach def $defs { tdom::schema s s defelement doc $def s event start doc s event start b s event end set result [lsort [s info expected]] s delete } set result } {a b c d} test schema-17.11a {info expected} { set defs { { group + { element c ? element a ? element b ? } element d } } set result [list] foreach def $defs { tdom::schema s s defelement doc $def s event start doc s event start b s event end set result [lsort [s info expected -ignorematched]] s delete } set result } {d} test schema-17.12 {info expected} {8.5} { tdom::schema s s define { prefixns {ns1 http://foo.bar} defelement doc { element a any any ns1 ? element b ? } } s event start doc s event start a s event end set result [lsort [s info expected]] s event start something s event end lappend result {*}[lsort [s info expected]] s delete set result } {{ {}} { http://foo.bar} { {}} b} test schema-17.12a {info expected} {8.5} { tdom::schema s s define { prefixns {ns1 http://foo.bar} defelement doc { element a any any ns1 ? element b ? } } s event start doc s event start a s event end set result [lsort [s info expected -ignorematched]] s event start something s event end lappend result {*}[lsort [s info expected -ignorematched]] s delete set result } {{ {}} { http://foo.bar} { {}} b} test schema-17.12b {info expected} {8.5} { tdom::schema s s define { prefixns {ns1 http://foo.bar} defelement doc { element a any {""} any ns1 ? element b ? } } s event start doc s event start a s event end set result [lsort [s info expected]] s event start something s event end lappend result {*}[lsort [s info expected]] s delete set result } {{ {{}}} { http://foo.bar} { {}} b} test schema-17.12b {info expected} {8.5} { tdom::schema s s define { prefixns {ns1 http://foo.bar} defelement doc { element a any {"" ns1} any ns1 ? element b ? } } s event start doc s event start a s event end set result [lsort [s info expected]] s event start something s event end lappend result {*}[lsort [s info expected]] s delete set result } {{ {{} http://foo.bar}} { http://foo.bar} { {}} b} proc schema-17.13 {scmd args} { global fromReportCmd set fromReportCmd [lsort [$scmd info expected]] } test schema-17.13 {info expected} {8.5} { set defs { { element a element b ? } { element a ? element b } { element a ? element b ? } } set xmlinput { } set result [list] set defnr 0 foreach def $defs { tdom::schema s s defelement doc $def s reportcmd schema-17.13 set xmlnr 0 foreach xml $xmlinput { set fromReportCmd "" lappend result $defnr/$xmlnr: [s validate $xml errMsg] lappend result {*}$fromReportCmd incr xmlnr } s delete incr defnr } set result } {0/0: 1 a 0/1: 1 0/2: 1 a 0/3: 1 0/4: 1 a 0/5: 1 { {}} b 1/0: 1 a b 1/1: 1 b 1/2: 1 1/3: 1 1/4: 1 a b 1/5: 1 b 2/0: 1 2/1: 1 2/2: 1 2/3: 1 2/4: 1 { {}} a b 2/5: 1 { {}} b} proc schema-17.13a {scmd args} { global fromReportCmd set fromReportCmd [lsort [$scmd info expected -ignorematched]] } test schema-17.13a {info expected} {8.5} { set defs { { element a element b ? } { element a ? element b } { element a ? element b ? } } set xmlinput { } set result [list] set defnr 0 foreach def $defs { tdom::schema s s defelement doc $def s reportcmd schema-17.13a set xmlnr 0 foreach xml $xmlinput { set fromReportCmd "" lappend result $defnr/$xmlnr: [s validate $xml errMsg] lappend result {*}$fromReportCmd incr xmlnr } s delete incr defnr } set result } {0/0: 1 a 0/1: 1 0/2: 1 a 0/3: 1 0/4: 1 a 0/5: 1 { {}} b 1/0: 1 a b 1/1: 1 b 1/2: 1 1/3: 1 1/4: 1 a b 1/5: 1 b 2/0: 1 2/1: 1 2/2: 1 2/3: 1 2/4: 1 { {}} a b 2/5: 1 { {}} b} proc schema-17.14 {scmd args} { global result foreach e [lsort [$scmd info expected]] { lappend result $e } } test schema-17.14 {info expected} { set defs { { group + { element c ? element a ? element b ? } tcl schema-17.14 [self] element d } } set result [list] foreach def $defs { tdom::schema s s reportcmd schema-17.14 s defelement doc $def s event start doc s event start unknownElement s delete } set result } {a b c d a b c d} proc schema-17.14a {scmd args} { global result foreach e [lsort [$scmd info expected -ignorematched]] { lappend result $e } } test schema-17.14a {info expected} { set defs { { group + { element c ? element a ? element b ? } tcl schema-17.14 [self] element d } } set result [list] foreach def $defs { tdom::schema s s reportcmd schema-17.14 s defelement doc $def s event start doc s event start unknownElement s delete } set result } {a b c d a b c d} proc schema-17.15 {type cmd} { lappend ::result $type [$cmd info stack inside] } test schema-17.15 {info inside} { tdom::schema s s define { defelement doc { element a * } defelement a { tcl schema-17.15 astart [self] element b ! text element c ! text tcl schema-17.15 aend [self] } } set result {} s validate {foobar} s delete set result } {astart {a doc} aend {a doc} astart {a doc} aend {a doc}} test schema-17.16 {info expected} {8.5} { tdom::schema s s defelement doc { element a group { group { group { element aaaa element bbbb ? } element bbb ? } element bb ? } element b } set result [list] foreach xml { } { lappend result [s validate $xml] } s reportcmd schema-17.13 foreach xml { } { set fromReportCmd "" lappend result [s validate $xml] lappend result {*}$fromReportCmd } s delete set result } {0 0 1 1 aaaa 1 b bb bbb bbbb 1} test schema-17.16_1 {info expected} {8.5} { tdom::schema s s defelement doc { element a group { group { group { element aaaa element bbbb ? } element bbb ? } element bb ? } element b } set result [list] foreach xml { } { lappend result [s validate $xml] } s reportcmd schema-17.13 foreach xml { } { set fromReportCmd "" lappend result [s validate $xml] lappend result {*}$fromReportCmd } s delete set result } {0 0 1 1 aaaa 1 b bb bbb bbbb 1} test schema-17.16a {info expected} {8.5} { tdom::schema s s defelement doc { element a group { group { group { element aaaa * element bbbb ? } element bbb ? } element bb ? } element b } set result [list] foreach xml { } { lappend result [s validate $xml] } s reportcmd schema-17.13a foreach xml { } { set fromReportCmd "" lappend result [s validate $xml] lappend result {*}$fromReportCmd } s delete set result } {0 0 1 1 aaaa b bb bbb bbbb 1 b bb bbb bbbb 1} test schema-17.16a_1 {info expected} {8.5} { tdom::schema s s defelement doc { element a group { group { group { element aaaa * element bbbb ? } element bbb ? } element bb ? } element b } set result [list] foreach xml { } { lappend result [s validate $xml] } s reportcmd schema-17.13a foreach xml { } { set fromReportCmd "" lappend result [s validate $xml] lappend result {*}$fromReportCmd } s delete set result } {0 0 1 1 aaaa b bb bbb bbbb 1 b bb bbb bbbb 1} test schema-17.16b {info expected} {8.5} { tdom::schema s s defelement doc { element a group { group { group { element aaaa ? element bbbb ? } element bbb ? } element bb ? } element b } set result [list] foreach xml { } { lappend result [s validate $xml] } s reportcmd schema-17.13 foreach xml { } { set fromReportCmd "" lappend result [s validate $xml] lappend result {*}$fromReportCmd } s delete set result } {0 0 1 1 aaaa b bb bbb bbbb 1 b bb bbb bbbb 1} test schema-17.16c {info expected} {8.5} { tdom::schema s s defelement doc { element a group { group { group { element aaaa + element bbbb ? } element bbb ? } element bb ? } element b } set result [list] foreach xml { } { lappend result [s validate $xml] } s reportcmd schema-17.13 foreach xml { } { set fromReportCmd "" lappend result [s validate $xml] lappend result {*}$fromReportCmd } s delete set result } {0 0 1 1 aaaa 1 aaaa b bb bbb bbbb 1} proc schema-17.17 {scmd args} { global fromReportCmd set fromReportCmd [list [$scmd info line] [$scmd info column]] } test schema-17.17 {info expected} {8.5} { tdom::schema s s defelement doc { element a group { group { group { element aaaa + element bbbb ? } element bbb ? } element bb ? } element b } set result [list] foreach xml { } { lappend result [s validate $xml] } s reportcmd schema-17.17 foreach xml { } { set fromReportCmd "" lappend result [s validate $xml] lappend result {*}$fromReportCmd } s delete set result } {0 0 1 1 1 9 1 1 16 1} test schema-17.18 {info typedefinition} { tdom::schema s s prefixns {ns http://my.foo} s defelementtype a ns { element a type a element a type a2 } set result [s info typedefinition a ns] s delete set result } {defelementtype a http://my.foo { element a type a element a type a2 }} test schema-17.18a {info typedefinition} { tdom::schema s s prefixns {ns http://my.foo} s define { defelementtype a ns { element a type a element a type a2 } } set result [s info typedefinition a ns] s delete set result } {defelementtype a http://my.foo { element a type a element a type a2 }} proc schema-17.19 {schemacmd} { lappend ::result [$schemacmd info stack associated] } test schema-17.19 {info stack associated} { tdom::schema s s defelement doc { element a + } s defelement a { associate "fo bar baz" tcl schema-17.19 [self] } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {{fo bar baz} 1 {fo bar baz} {fo bar baz} 1} test schema-17.19a {info stack associated} { tdom::schema s s defelement doc { element a + } s defelement a { associate "fo bar baz" tcl schema-17.19 [self] element b } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {{fo bar baz} 1 {fo bar baz} {fo bar baz} 1} proc schema-17.20 {schemacmd args} { lappend ::result [$schemacmd info stack associated] } test schema-17.20 {info stack associated} { tdom::schema s s defelement doc { element a + } s defelement a { associate "fo bar baz" # Only local defined element b ? } s reportcmd schema-17.20 set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {{} 1 1 1 {fo bar baz} 1 {} 1} proc schema-17.21 {scmd errorInfo} { lappend ::result [$scmd info expected] } test schema-17.21 {info expected} { tdom::schema s s defelement doc { element a + {} element b ! {} } s reportcmd schema-17.21 set result "" lappend result [s validate {}] s delete set result } {{a b} 1} proc schema-17.21a {scmd errorInfo} { lappend ::result [$scmd info expected -ignorematched] } test schema-17.21a {info expected} { tdom::schema s s defelement doc { element a + {} element b ! {} } s reportcmd schema-17.21a set result "" lappend result [s validate {}] s delete set result } {b 1} proc schema-17.22 {scmd errorInfo} { global fromReportCmd if {[$scmd info vaction] eq "MATCH_ELEMENT_START"} { lappend fromReportCmd "matching [$scmd info vaction name]" "expecting [lsort [$scmd info expected]]" if {$errorInfo eq "MISSING_ELEMENT"} { return ignore } } else { lappend fromReportCmd "END_EVENT expecting [$scmd info expected]" } } test schema-17.22 {return "ignore" from recover script for MISSING_ELEMENT_MATCH_START} {8.5} { set defs { { element a element b element c } } set xmlinput { } set result [list] set defnr 0 foreach def $defs { tdom::schema s s defelement doc $def s reportcmd schema-17.22 set xmlnr 0 foreach xml $xmlinput { set fromReportCmd "" lappend result $defnr/$xmlnr: [s validate $xml errMsg] lappend result {*}$fromReportCmd incr xmlnr } s delete incr defnr } set result } {0/0: 1 {END_EVENT expecting a} 0/1: 1 {END_EVENT expecting b} 0/2: 1 {matching b} {expecting a} {END_EVENT expecting c} 0/3: 1 {matching c} {expecting a} {matching c} {expecting b} 0/4: 1 {END_EVENT expecting c} 0/5: 1 {matching c} {expecting b} 0/6: 1 {matching b} {expecting a} 0/7: 1 {matching unknown} {expecting a} {matching unknown} {expecting b} {matching unknown} {expecting c} {matching unknown} {expecting { {}}} 0/8: 1 {matching unknown} {expecting b} {matching unknown} {expecting c} {matching unknown} {expecting { {}}}} proc schema-17.23 {scmd errorInfo} { global fromReportCmd if {[$scmd info vaction] eq "MATCH_ELEMENT_START"} { lappend fromReportCmd "matching [$scmd info vaction name]" "expecting [lsort [$scmd info expected]]" if {$errorInfo in {"MISSING_ELEMENT" "UNEXPECTED_ELEMENT"}} { return vanish } } else { lappend fromReportCmd "END_EVENT expecting [$scmd info expected]" } } test schema-17.23 {return "vanish" from recover handler} {8.5} { set def { defelement doc { element a ref b element d ? } defpattern b { element b ref c } defpattern c { element c + } } set xmlinput { foocontentfoocontent } set result [list] tdom::schema s s define $def s reportcmd schema-17.23 set xmlnr 0 foreach xml $xmlinput { set fromReportCmd "" lappend result $xmlnr: [s validate $xml errMsg] lappend result {*}$fromReportCmd incr xmlnr } s delete set result } {0: 1 {END_EVENT expecting a} 1: 1 {END_EVENT expecting b} 2: 1 {matching b} {expecting a} {END_EVENT expecting a} 3: 1 {matching c} {expecting a} {END_EVENT expecting a} 4: 1 {END_EVENT expecting c} 5: 1 {matching c} {expecting b} {END_EVENT expecting b} 6: 1 {matching b} {expecting a} {matching c} {expecting a} {END_EVENT expecting a} 7: 1 {matching unknown} {expecting a} {END_EVENT expecting a} 8: 1 {matching unknown} {expecting b} {END_EVENT expecting b} 9: 1 {matching unknown} {expecting b} 10: 1 {matching unknown} {expecting b} 11: 1 {matching unknown} {expecting c} 12: 1 {matching unknown} {expecting c} 13: 1 {matching unknown} {expecting { {}} c d} 14: 1 {matching unknown} {expecting { {}} c d} 15: 1 {matching unknown} {expecting c} {matching unknown1} {expecting { {}} c d} {matching unknown2} {expecting { {}}} {matching unknown3} {expecting { {}}} 16: 1 {matching unknown} {expecting b} {matching unknown} {expecting c} 17: 1 {matching unknown1} {expecting c} {matching unknown2} {expecting c}} test schema-17.24 {info patterndefinition} { tdom::schema s set result "" s defpattern foo {element bar; element baz} lappend result [s info patterndefinition foo] s defpattern foo someNamespace {element e1; element e2} lappend result [s info patterndefinition foo someNamespace] lappend result [catch {s info patterndefinition dontexists} errMsg] lappend result $errMsg lappend result [catch {s info patterndefinition foo wrongNamespace} errMsg] lappend result $errMsg s delete set result } {{defpattern foo {element bar; element baz}} {defpattern foo someNamespace {element e1; element e2}} 1 {Unknown pattern definition} 1 {Unknown pattern definition}} test schema-17.25 {info definedPatterns} { tdom::schema create grammar grammar defpattern thisPattern { element a element b } grammar defpattern thatPattern someNamespace { element c element d } grammar defelement doc { ref thisPattern ref thatPattern ? } set result [lsort -index 0 [grammar info definedPatterns]] grammar delete set result } {{thatPattern someNamespace} thisPattern} proc schema-17.26 {scmd errorInfo} { global fromReportCmd if {$errorInfo eq "MISSING_ELEMENT" && [$scmd info vaction] eq "MATCH_ELEMENT_END"} { lappend fromReportCmd "END_EVENT [$scmd info vaction name]" "expecting [lsort [$scmd info expected]]" return "ignore" } else { lappend fromReportCmd "[$scmd info vaction] expecting [$scmd info expected]" } } test schema-17.26 {return "ignore" from recover handler for element end event} {8.5} { tdom::schema s s define { defelement doc { element a ref bpat element d } defpattern bpat { element b ref c } defpattern c { element c + } } s reportcmd schema-17.26 set result "" set xmlnr 0 foreach xml { } { set ::fromReportCmd "" lappend result $xmlnr: [s validate $xml errMsg] lappend result {*}$fromReportCmd incr xmlnr } s delete set result } {0: 1 {END_EVENT doc} {expecting a} {END_EVENT doc} {expecting b} {END_EVENT doc} {expecting d} 1: 1 {END_EVENT doc} {expecting b} {END_EVENT doc} {expecting d} 2: 1 {END_EVENT doc} {expecting c} {END_EVENT doc} {expecting d} 3: 1 {MATCH_ELEMENT_START expecting c} 4: 1 5: 1} test schema-17.27 {return "ignore" from recover handler for element end event} {8.5} { tdom::schema s s define { defelement doc { element a element b element c element d } } s reportcmd schema-17.26 set result "" set xmlnr 0 foreach xml { } { set ::fromReportCmd "" lappend result $xmlnr: [s validate $xml errMsg] lappend result {*}$fromReportCmd incr xmlnr } s delete set result } {0: 1 {END_EVENT doc} {expecting a} {END_EVENT doc} {expecting b} {END_EVENT doc} {expecting c} {END_EVENT doc} {expecting d} 1: 1 {END_EVENT doc} {expecting b} {END_EVENT doc} {expecting c} {END_EVENT doc} {expecting d} 2: 1 {END_EVENT doc} {expecting c} {END_EVENT doc} {expecting d} 3: 1 {MATCH_ELEMENT_START expecting c} 4: 1 5: 1 {MATCH_ELEMENT_START expecting d}} proc schema-17.28 {userarg scmd errType} { append ::result $userarg $scmd $errType } test schema-17.28 {reportcmd with additional args} { tdom::schema s s defelement doc { element a } s reportcmd "schema-17.28 foo" set result "" s validate }] lappend result $rc s delete set result } {s MISSING_TEXT 1} test schema-18.1a {reportcmd} { tdom::schema s s define { defelement doc { element e text {minLength 1} element e } } s reportcmd schema-18 set result "" set rc [s validate {}] lappend result $rc s delete set result } {s MISSING_TEXT 1} test schema-18.2 {reportcmd} { tdom::schema s s define { defelement doc { element a element b element c } } s reportcmd schema-18 set result "" set rc [s validate {}] lappend result $rc s delete set result } {s MISSING_ELEMENT 1} test schema-18.3 {reportcmd} { tdom::schema s s define { defelement doc { element a } } s reportcmd schema-18 set result "" foreach xml { baz bazgrill } { set rc [s validate $xml] lappend result $rc } s delete set result } {s UNKNOWN_ROOT_ELEMENT 1 s UNKNOWN_ROOT_ELEMENT 1 s UNKNOWN_ROOT_ELEMENT 1 s UNKNOWN_ROOT_ELEMENT 1} test schema-18.4 {reportcmd} { tdom::schema s s define { defelement doc { element items * { element item * { attribute ref {integer} } } } } s reportcmd schema-18 set result [list] foreach xml { {} {} } { lappend result [s validate $xml] } s delete set result } {1 s INVALID_ATTRIBUTE_VALUE s INVALID_ATTRIBUTE_VALUE 1} test schema-18.5 {reportcmd} { tdom::schema s s define { defelement doc { element items * { element item * { text {minLength 2} } } } } s reportcmd schema-18 set result [list] foreach xml { {1} {1} {>12ab} } { lappend result [s validate $xml] } s delete set result } {s INVALID_VALUE 1 s INVALID_VALUE s MISSING_TEXT 1 1} test schema-18.6 {reportcmd} { tdom::schema s s define { defelement item { text { key lang minLength 2 } } defelement items { keyspace lang { element item + } } defelement doc { element items + } } s reportcmd schema-18 set result [list] foreach xml { {12ab} {1212} {1212abcd} {1212abcd1212} } { lappend result [s validate $xml] } s delete set result } {1 s INVALID_VALUE 1 s INVALID_VALUE 1 s INVALID_VALUE s INVALID_VALUE 1} proc schema-18.7 {args} { global result lappend result "tclcallback" } test schema-18.7 {reportcmd} { tdom::schema s s define { defelement a {} defelement b {} defelement c {} defelement items { interleave { element a element b } tcl schema-18.7 element c } defelement doc { element items + } } s reportcmd schema-18 set result [list] foreach xml { {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {tclcallback 1 tclcallback tclcallback 1 tclcallback s MISSING_ELEMENT tclcallback 1 tclcallback s MISSING_ELEMENT tclcallback s MISSING_ELEMENT 1} test schema-18.8 {reportcmd} { tdom::schema s s define { defelement a {} defelement b {} defelement c {} defelement items { element a element b element c } defelement doc { element items + } } s reportcmd schema-18 set result [list] foreach xml { {} } { lappend result [s validate $xml] } s delete set result } {s MISSING_ELEMENT s MISSING_ELEMENT 1} test schema-18.9 {reportcmd} { tdom::schema s s define { defelement a {} defelement b {} defelement c {} defelement doc { group + { element a element b element c } } } s reportcmd schema-18 set result [list] foreach xml { {} } { lappend result [s validate $xml] } s delete set result } {s MISSING_ELEMENT 1} test schema-18.10 {reportcmd} { tdom::schema s s define { defelement a {} defelement b {} defelement c {} defelement doc { group + { element a element b group + { element c } } } } s reportcmd schema-18 set result [list] foreach xml { {} } { lappend result [s validate $xml] } s delete set result } {s MISSING_ELEMENT 1} test schema-18.11 {reportcmd} { tdom::schema s s define { defelement a {} defelement b {} defelement c {} defelement doc { element a element b element c } } s reportcmd schema-18 set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {1 s MISSING_ELEMENT 1 s MISSING_ELEMENT 1 s MISSING_ELEMENT 1 s MISSING_ELEMENT 1 s UNEXPECTED_ELEMENT 1} test schema-18.12 {non existing reportcmd cmd} { tdom::schema s s defelement doc { element a } s reportcmd ::tdom::_dontExists_ set result [catch {s validate } errMsg] lappend result $errMsg s delete set result } {1 {error "invalid command name "::tdom::_dontExists_"" at line 1 character 6}} proc 18-13 {scmd errType} { global result lappend result {reportcmd called} } test schema-18.13 {reportcmd} { tdom::schema s s define { defelement header { group { choice { group { element prevlocs element latestloc ? } group { element latestloc element prevlocs ? } } } } } s reportcmd 18-13 set result [list] foreach xml {
} { lappend result [s validate $xml] } s delete set result } {{reportcmd called} 1 1 1 1 1} proc schema-18.14 {scmd errortype} { lappend ::result $errortype lappend ::result [$scmd info expected] lappend ::result [$scmd info vaction] lappend ::result [$scmd info vaction name] lappend ::result [$scmd info vaction namespace] lappend ::result [$scmd info vaction text] } test schema-18.14 {info vaction in reportcmd} {listformat} { tdom::schema s s reportcmd schema-18.14 s define { defelement doc { element e + { attribute attr1 { fixed on } text { minLength 4 } } } } set result [list] foreach xml { 123 {1234} } { lappend result [s validate $xml] } s delete set result } {MISSING_ELEMENT e MATCH_ELEMENT_END doc {} {} 1 MISSING_ELEMENT e MATCH_ELEMENT_START b {} {} 1 MISSING_ATTRIBUTE {{{#text} {}}} MATCH_ELEMENT_START attr1 {} {} INVALID_VALUE {{{#text} {}}} MATCH_TEXT e {} 123 1 INVALID_ATTRIBUTE_VALUE {{{#text} {}}} MATCH_ATTRIBUTE_TEXT attr1 {} off 1} test schema-18.15 {info vaction in reportcmd} { tdom::schema s s reportcmd schema-18.14 s define { defelement doc { element e + { attribute attr1 attribute attr2 ? { minLength 3 } } } } set result [list] foreach xml { {} {} {} } { lappend result [s validate $xml] } s delete set result } {1 INVALID_ATTRIBUTE_VALUE {{ {}}} MATCH_ATTRIBUTE_TEXT attr2 {} a MISSING_ATTRIBUTE {{ {}}} MATCH_ELEMENT_START attr1 {} {} 1 UNKNOWN_ATTRIBUTE {{ {}}} MATCH_ELEMENT_START foo {} {} MISSING_ATTRIBUTE {{ {}}} MATCH_ELEMENT_START attr1 {} {} 1} proc appendtoresult {scmd errortype} { lappend ::result $errortype } test schema-18.16 {unexpected text} { set defs { { defelement doc { ref r1 } defpattern r1 { element e ? {} } } { defelement doc { element e ? {} } } } set result [list] foreach def $defs { tdom::schema s s reportcmd appendtoresult s define $def lappend result [s validate {unexpected text}] s delete } set result } {UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1} test schema-18.17 {unexpected text} { tdom::schema s s reportcmd appendtoresult s define { defelement doc { ref r1 element c ! {} } defpattern r1 { element a ! {} element b ! {} } } set result [list] foreach xml { unexpected_text
unexpected_text unexpected_text unexpected_text } { lappend result [s validate $xml] } s delete set result } {UNEXPECTED_TEXT MISSING_ELEMENT 1 UNEXPECTED_TEXT MISSING_ELEMENT 1 UNEXPECTED_TEXT MISSING_ELEMENT 1 UNEXPECTED_TEXT 1} proc schema-18.18 {scmd errortype} { lappend ::result $errortype lappend ::result [$scmd info expected] } test schema-18.18 {missing element at MATCH_ELEMENT_END} { set defs { { defelement doc { ref r1 } defpattern r1 { element a ! {} element b ! {} } } { defelement doc { element a 1 {} element b 1 {} } } { defelement doc { element a0 ! {} ref r1 } defpattern r1 { element a ! {} element b ! {} } } { defelement doc { element a0 ! {} ref r1 element b0 ! {} } defpattern r1 { element a ! {} element b ! {} } } } set result [list] foreach def $defs { tdom::schema s s reportcmd schema-18.18 s define $def lappend result [s validate {}] s delete } set result } {MISSING_ELEMENT a 1 MISSING_ELEMENT a 1 MISSING_ELEMENT a0 1 MISSING_ELEMENT a0 1} test schema-18.19 {unexpected text} { tdom::schema s s reportcmd appendtoresult s define { defelement doc { ref r1 ? element c ? {} } defpattern r1 { element a ? {} element b ? {} } } set result [list] foreach xml { unexpected_text unexpected_text unexpected_text unexpected_text unexpected_text unexpected_text } { lappend result [s validate $xml] } s delete set result } {UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1 UNEXPECTED_TEXT 1} test schema-18.20 {Missing element on element end} { tdom::schema s s reportcmd appendtoresult s define { defelement doc { element a * { element b ! {} element c ! {} } } } set result [list] foreach xml { unexpected_text unexpected_text unexpected } { lappend result [s validate $xml] } s delete set result } {1 1 MISSING_ELEMENT 1 UNEXPECTED_TEXT MISSING_ELEMENT 1 UNEXPECTED_TEXT MISSING_ELEMENT 1 MISSING_ELEMENT 1 MISSING_ELEMENT MISSING_ELEMENT 1 MISSING_ELEMENT UNEXPECTED_TEXT 1} test schema-18.21 {reportcmd argument handling} { tdom::schema s set result "" lappend result [s reportcmd] s reportcmd "" lappend result [s reportcmd] s reportcmd dummycallback lappend result [s reportcmd] s reportcmd "" s reportcmd "" lappend result [s reportcmd] s reportcmd dummycallback lappend result [s reportcmd] s delete set result } {{} {} dummycallback {} dummycallback} proc schema-18.22 {that scmd errorType} { lappend ::result $that $errorType } test schema-18.22 {reportcmd with arguments} { tdom::schema s s reportcmd "schema-18.22 this" s defelement doc { element a element b } set result "" lappend result [s validate {}] s delete set result } {this MISSING_ELEMENT 1} proc validatedSAX {g xml {keepEmpties 1}} { set args [list -validateCmd $g] if {!$keepEmpties} { lappend args -ignorewhitespace 1 } xml::parser p {*}$args set rc [catch {p parse $xml} errMsg] p delete return $rc } proc validatedDOM {g xml {keepEmpties 0}} { set args [list -validateCmd $g] if {$keepEmpties} { lappend args -keepEmpties } set rc [catch { set doc [dom parse {*}$args $xml] } errMsg] if {$doc ne ""} { $doc delete } return $rc } proc postValidation {g xml} { set doc [dom parse $xml] set rc [$g domvalidate $doc errMsg] #puts "error : $errMsg" $doc delete return $rc } test schema-19.1 {keyspace} { tdom::schema s s define { defelement doc { element items * { keyspace ref { element item * { attribute ref ? { key ref } } } } } } set result [list] foreach xml { {} {} {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {1 0 1 1 1 0} test schema-19.2 {keyspace} { tdom::schema s s define { defelement doc { element items * { keyspace ref { element item * { attribute ref ? { key ref } } } } } } s reportcmd schema-18 set result [list] foreach xml { {} {} } { lappend result [s validate $xml] } s delete set result } {s INVALID_ATTRIBUTE_VALUE s INVALID_ATTRIBUTE_VALUE 1 1} test schema-19.3 {keyspace} { tdom::schema s s define { defelement doc { element items * } defelement items { keyspace my { element item * } } defelement item { attribute id ? { key my } attribute ref ? { keyref my } } } s reportcmd schema-18 set result [list] foreach xml { {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {1 1 s INVALID_KEYREF 1 s INVALID_KEYREF 1} proc log19.4 {msg} { lappend ::result $msg } proc report19.4 {scmd errortype} { lappend ::result $errortype } test schema-19.4 {keyspace w/ recover} { tdom::schema s s define { defelement doc { element m * { tcl log19.4 "before a" element a ? { keyspace lang { element a1 ? { attribute lang ? {key lang} } } keyspace lang { element a2 ? {text {key lang}} } } tcl log19.4 "before b" element b ? { keyspace lang { element b1 ? { attribute lang ? {key lang} } } } } } } s reportcmd report19.4 set result [list] foreach xml { {} } { lappend result [s validate $xml] } s delete set result } {{before a} UNEXPECTED_ELEMENT {before b} {before a} {before b} UNEXPECTED_ELEMENT 1} test schema-20.1 {domunique} { set schema { prefixns {ns1 http://tdom.org/test} defelement doc { domunique ${::schema-20.1} @ref } } set result [list] foreach ::schema-20.1 { a ./../a /foo a/b {a | b} a|b (a|b) {a/b/c | b/c/d | c/d/e} .//a //a a/@ref a/b/c {a//b[1]/c} (.//b|a)/c ns1:a a/.//b/c {} { } " " } { tdom::schema s lappend result [catch {s define $schema} errMsg] #puts $errMsg s delete } set result } {0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1} test schema-20.2 {domunique} { tdom::schema s s define { defelement doc { domunique item @ref element item * { attribute ref ? } } } set result [list] foreach xml { {} {} {} {} } { lappend result [postValidation s $xml] } s delete set result } {1 0 1 0} test schema-20.2a {domunique} { tdom::schema s s define { defelement doc { domunique item @ref itemrefkey IGNORE_EMPTY_FIELD_SET element item * { attribute ref ? } } } set result [list] foreach xml { {} {} {} {} } { lappend result [postValidation s $xml] } s delete set result } {1 0 1 1} test schema-20.2b {domunique} { tdom::schema s s define { defelement doc { domunique item @ref itemrefkey EMPTY_FIELD_SET_VALUE abc element item * { attribute ref ? } } } set result [list] foreach xml { {} {} {} {} } { lappend result [postValidation s $xml] } s delete set result } {1 0 0 0} test schema-20.3 {domunique} { tdom::schema s s define { defelement doc { element items * { element item * { attribute ref ? } domunique item @ref } } } set result [list] foreach xml { {} {} {} {} {} {} } { lappend result [postValidation s $xml] } s delete set result } {1 0 1 1 1 0} test schema-20.4 {domunique} { tdom::schema s s define { defelement doc { domunique item {@ref @id} element item * { attribute ref ? attribute id ? } } } set result [list] foreach xml { {} {} {} {} {} } { lappend result [postValidation s $xml] } s delete set result } {1 0 1 0 1} test schema-20.5 {domunique} { tdom::schema s s define { defelement doc { domunique item ref element item * { element ref ! text } } } set result [list] foreach xml { {1foo} {11} } { lappend result [postValidation s $xml] } s delete set result } {1 0} proc schema-20.6 {scmd errortype} { lappend ::result $errortype \ [$scmd info vaction name] \ [$scmd info vaction text] \ [[$scmd info domNode] nodeName] } test schema-20.6 {domunique} { tdom::schema s s define { defelement doc { domunique item ref itemunique element item * { element ref ! text } } } s reportcmd schema-20.6 set result [list] foreach xml { {1foo} {foofoo} } { lappend result [postValidation s $xml] } s delete set result } {1 DOM_KEYCONSTRAINT itemunique foo doc 1} test schema-20.7 {domunique} { tdom::schema s set result [catch {s define { defelement doc { domunique item {} element item * { attribute ref ? } } }}] s delete set result } {1} test schema-21.1 {CONTENT_ARRAY_SIZE_INIT} { tdom::schema s s defelement doc { for {set i 1} {$i <= 30} {incr i} { element e ? } } set result [list] foreach xml [list \ [string repeat 9] \ [string repeat 27] \ [string repeat 37]] { lappend result [s validate $xml] } s delete set result } {1 1 1 0} test schema-22.1 {defelementtype} { tdom::schema s s defelementtype a_type { element e1 } s defelement doc { element a type a_type } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 0 1} test schema-22.2 {defelementtype} { tdom::schema s s defelement doc { element a type a_type } s defelementtype a_type { element e1 } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 0 1} test schema-22.3 {defelementtype} { tdom::schema s s defelement doc { element a type a element a type a2 } s defelementtype a { element e1 } s defelementtype a2 { element e2 } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 0 0 1 0 0} test schema-22.4 {defelementtype} { tdom::schema s catch {s defelement doc { element atype a element a type a2 error "my" }} s defelement doc { element a type a element a type a2 } catch {s defelementtype a { element e1 error my }} s defelementtype a { element e1 } catch {s defelementtype a2 { element e2 error my }} s defelementtype a2 { element e2 } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 0 0 1 0 0} test schema-22.5 {defelementtype} { tdom::schema s s prefixns {ns http://my.foo} s defelement doc ns { element a type a element a type a2 } s defelementtype a ns { element e1 } s defelementtype a2 ns { element e2 } set result [list] foreach xml { {} {} {} {} {} {} } { lappend result [s validate $xml] } s delete set result } {0 0 0 1 0 0} test schema-22.6 {defelementtype} { tdom::schema s s prefixns {ns http://my.foo} s defelement doc ns { element a type a element a type a2 } s defelementtype a ns { element e type e1 } s defelementtype a2 ns { element e type e2 } set result [lsort -index 0 [s info definedElementtypes]] s delete set result } {{a http://my.foo} {a2 http://my.foo}} test schema-22.6a {info definedElementtypes} { tdom::schema s s prefixns {ns1 http://ns1.foo ns2 http://ns2.foo} s defelementtype a ns1 { element e type e1 } s defelementtype a ns2 { element e type e2 } set result [lsort -command sortcps [s info definedElementtypes]] s delete set result } {{a http://ns1.foo} {a http://ns2.foo}} test schema-22.7 {defelementtype} { tdom::schema s s defelement doc { element e1 type e1type element e2 * type e2type } foreach e {e1 e2} { s defelementtype ${e}type {} } set result [list] foreach xml { } { lappend result [s validate $xml] } s delete set result } {0 1 1 1 1 0 0} test schema-22.8 {defelementtype} { tdom::schema s s defelement doc { element e1 type e1type element e2 * type e2type } set result [list] foreach xml { {} grill } { lappend result [s validate $xml] } s delete set result } {0 0 0 0 1 0 0 1} test schema-22.9 {defelementtype} { tdom::schema s catch { s define { defelement a { element a1 type a1type } defelement b { element b1 type e1type element b1 ? type e2type } defelementtype a1type { element a1 } defelementtype e1type text defelementtype e2type { element c for {set i 1} {$i <= 100} {incr i} { attribute att$i ? } attribute musthave } error "triggered" } } s define { defelement a { element a1 type a1type } defelement b { element b1 type e1type element b1 ? type e2type } defelementtype a1type { element a1 } defelementtype e1type text defelementtype e2type { element c for {set i 1} {$i <= 100} {incr i} { attribute att$i ? } attribute musthave ! } } s defelement doc { element e1 type e1type element e2 * type e2type element a element b + } set result [list] foreach xml { { foo } { foo } } { lappend result [s validate $xml] } s delete set result } {0 1} test schema-23.1 {validatefile} { tdom::schema s s define { set fd [open [file join [file dir [info script]] ../doc/tmml.schema] r] eval [read $fd] close $fd } set result [s validatefile [file join [file dir [info script]] ../doc/schema.xml]] s delete set result } 1 test schema-24.1 {validatechannel} { tdom::schema s s define { set fd [open [file join [file dir [info script]] ../doc/tmml.schema] r] eval [read $fd] close $fd } set fd [open [file join [file dir [info script]] ../doc/schema.xml] r] set result [s validatechannel $fd] close $fd s delete set result } 1 test schema-25.1 {domxpathboolean} { tdom::schema s s define { defelement doc { element width ! text element length ! text element height ! text domxpathboolean "width * length * height <= 20000" volumeconstraint } } set result [list] foreach xml { 135 2000.0100.02.0 2000.0100.0-2 2.33.57.6 11foo 112000-01-01 } { lappend result [postValidation s $xml] } s delete set result } {1 0 1 1 0 0 0} test schema-25.2 {domxpathboolean} { tdom::schema s s prefixns { this http://that.org other http://this.org } s define { defelement doc this { element width ! text namespace other { element length ! text } element height ! text domxpathboolean "this:width * other:length * this:height <= 20000" volumeconstraint } } set result [list] foreach xml { {135} {2000.0100.02.0} {2000.0100.0-2} {2.33.57.6} {11foo} {112000-01-01} {} } { lappend result [postValidation s $xml] } s delete set result } {1 0 1 1 0 0 0} proc schema-25.3 {scmd errortype} { lappend ::result $errortype [$scmd info vaction name] } test schema-25.3 {domxpathboolean} { tdom::schema s s define { defelement doc { element width ! text element length ! text element height ! text domxpathboolean "width * length * height <= 20000" volumeconstraint } } s reportcmd schema-25.3 set result [list] foreach xml { 135 2000.0100.02.0 2000.0100.0-2 2.33.57.6 11foo 112000-01-01 } { lappend result [postValidation s $xml] } s delete set result } {1 DOM_XPATH_BOOLEAN volumeconstraint 1 1 1 DOM_XPATH_BOOLEAN volumeconstraint 1 DOM_XPATH_BOOLEAN volumeconstraint 1 DOM_XPATH_BOOLEAN volumeconstraint 1} test schema-25.4 {domxpathboolean} { tdom::schema s s define { defelement doc { element width ! text element length ! text element height ! text domxpathboolean "width * length * height <= 20000" volume domunique width|length|height . unique domxpathboolean "width < length and length < height" sequence } } s reportcmd schema-25.3 set result [list] set nr 1 foreach xml { 135 2000.0100.02.0 2000.0100.0-2 2.33.57.6 11foo 112000-01-01 } { lappend result "Nr$nr:" incr nr lappend result [postValidation s $xml] } s delete set result } {Nr1: 1 Nr2: DOM_XPATH_BOOLEAN volume DOM_XPATH_BOOLEAN sequence 1 Nr3: DOM_XPATH_BOOLEAN sequence 1 Nr4: 1 Nr5: DOM_XPATH_BOOLEAN volume DOM_KEYCONSTRAINT unique DOM_XPATH_BOOLEAN sequence 1 Nr6: DOM_XPATH_BOOLEAN volume DOM_KEYCONSTRAINT unique DOM_XPATH_BOOLEAN sequence 1 Nr7: DOM_XPATH_BOOLEAN volume DOM_KEYCONSTRAINT unique DOM_XPATH_BOOLEAN sequence 1} test schema-25.5 {domxpathboolean - xpath argument invalid} { tdom::schema s set result [catch { s defelement doc { domxpathboolean "a + + b" } } errMsg] lappend result $errMsg s delete set result } {1 {Error in selector xpath: 'NodeTest: Expected "WCARDNAME" for 'a + + b' Parsed symbols: 0 WCARDNAME 0 000000000 0 a 1 PLUS 0 000000000 2 2 PLUS 0 000000000 4 3 WCARDNAME 0 000000000 6 b}} proc ::dom::xpathFunc::compare {ctxNode pos nodeListType nodeList args} { if {[llength $args] != 4} { error "XPath function date: Expected two arguments but got [expr {[llength $args] / 2}]" } lassign $args arg1Typ arg1Value arg2Typ arg2Value set arg1 [::dom::xpathFuncHelper::coerce2string $arg1Typ $arg1Value] set arg2 [::dom::xpathFuncHelper::coerce2string $arg2Typ $arg2Value] return [list number [string compare $arg1 $arg2]] } proc schema-25.6 {scmd errorType} { lappend ::result $errorType [$scmd info vaction name] } test schema-25.6 {domxpathboolean - scripted XPath function} {8.5} { tdom::schema s s reportcmd schema-25.6 s define { defelement doc { element a ! { text domxpathboolean {compare('foo','bar') > 0} first domxpathboolean {compare('foo','bar') < 0} second } } } set doc [dom parse {2020-07-30}] set result "" lappend result [s domvalidate $doc] set result } {DOM_XPATH_BOOLEAN second 1} proc schema-26.1 {scmd} { lappend ::result "fromtcl: [[$scmd info domNode] nodeName]" } test schema-26.1 {info domNode} { tdom::schema s s defelement doc { tcl schema-26.1 [self] element e ? } set result "" lappend result [s info domNode] foreach xml { {unexpected text} {unexpected text} {unexpected text} } { dom parse $xml doc lappend result [s domvalidate $doc] $doc delete } s delete set result } {{} {fromtcl: doc} 1 {fromtcl: doc} 1 {fromtcl: doc} 0 {fromtcl: doc} 0 {fromtcl: doc} 0 {fromtcl: doc} 0} proc schema-26.2 {scmd errortype} { lappend ::result $errortype [[$scmd info domNode] nodeName] } test schema-26.2 {info domNode} { tdom::schema s s defelement doc { tcl schema-26.1 [self] element e ? } s reportcmd schema-26.2 set result "" lappend result [s info domNode] foreach xml { {unexpected text} {unexpected text} {unexpected text} } { dom parse $xml doc lappend result [s domvalidate $doc] $doc delete } s delete set result } {{} {fromtcl: doc} 1 {fromtcl: doc} 1 {fromtcl: doc} UNEXPECTED_TEXT doc {fromtcl: doc} 1 {fromtcl: doc} UNEXPECTED_TEXT doc {fromtcl: doc} 1 {fromtcl: doc} UNEXPECTED_TEXT doc {fromtcl: doc} UNEXPECTED_ELEMENT unknown 1 {fromtcl: doc} UNEXPECTED_ELEMENT unknown 1} proc schema-26.3 {scmd errortype} { lappend ::result $errortype [$scmd info domNode] } test schema-26.3 {info domNode} { tdom::schema s s defelement doc { tcl schema-26.3 [self] "fromTcl" element e ? } s reportcmd schema-26.3 set result "" lappend result [s info domNode] foreach xml { {unexpected text} {unexpected text} {unexpected text} } { lappend result [s validate $xml] } s delete set result } {{} fromTcl {} 1 fromTcl {} 1 fromTcl {} UNEXPECTED_TEXT {} fromTcl {} 1 fromTcl {} UNEXPECTED_TEXT {} fromTcl {} 1 fromTcl {} UNEXPECTED_TEXT {} fromTcl {} UNEXPECTED_ELEMENT {} 1 fromTcl {} UNEXPECTED_ELEMENT {} 1} proc schema-27.1 {args} { lappend ::result [::tdom::type::time 23:24:45] } test schema-27.1 {Called from evaluated code} { tdom::schema s s defelement doc { tcl schema-27.1 element e 1 } set result "" lappend result [s validate ] s delete set result } {1 1} test schema-27.2 {Called from evaluated code} { tdom::schema s s defelement doc { text { tcl schema-27.1 } } set result "" lappend result [s validate foo] s delete set result } {1 1} test schema-27.3 {Called from recover script} { tdom::schema s s defelement doc { element e 1 } s reportcmd schema-27.1 set result "" lappend result [s validate ] s delete set result } {1 1} test schema-27.4 {Called as part of validation} { tdom::schema s s defelement doc { tcl schema-27.1 element e 1 } set result "" lappend result [s validate ] s delete set result } {1 1} test schema-27.5 {Called during schema script evaluation} { tdom::schema s set result "" s defelement doc { set ::result [::tdom::type::time 12:20:00] element e 1 } s delete set result } 1 test schema-27.6 {date outside schema context} { set result {} foreach txt { "" foo 1 12 1234-12-31 1234-14-31 1234-12-00 1234-02-31 2000-02-29 2001-02-29 2004-02-29 -2004-02-29 1900-02-29 1234-02-01 1234-08-10 1234-08-222 " 1234-08-22" "1234-08-22 " 11234-08-22 0000-02-01 10000-08-22 10000-02-29 10000-02-29Z 2012-03-07Z "2012-03-07Z " 2012-03-07a 2012-03-07+ 2012-03-07+00:00 2012-03-07-00:00 2012-03-07+02:00 2012-03-07+02:70 2012-03-07+12:30 2012-03-07+14:30 2012-03-07+14:00 2012-03-07-14:00 2012-03-07-14:01 2012-03-07-2:30 2012-03-07-02:30Z "2012-03-07-02:30 " 02027-02-01 } { lappend result [tdom::type::date $txt] } set result } {0 0 0 0 1 0 0 0 1 0 1 1 0 1 1 0 0 0 1 0 1 1 1 1 0 0 0 1 1 1 0 1 0 1 1 0 0 0 0 0} test schema-27.7 {dateTime outside schema context} { set result "" foreach txt { "" foo 1 2020-07-08T15:58:17 2020-07-08T15:20:00 2020-07-08T15:20:17.7 2020-07-08T15:58:17+02:00 2020-07-08T15:20:17.789 2020-07-08T15:20:17.7890 2020-07-08T15:20:17.0 2020-07-08T15:20:17. 2020-07-08T15:20:17.+02:00 2020-07-08T15:20:17.Z 2020-07-08T15:20:17+Z 2020-07-08T00:20 2020-07-08T00:60:00 2020-07-08T24:00:00 2020-07-08T24:00:00.1 2020-07-08T24:01:00 2020-07-08T24:00:01 2020-12-2215:20:00 2020-12-22 2020-07-08T15:20:17.789+02:00 2020-07-08T15:20:17-02:00 2020-07-08T15:20:17-02:00.0 2020-07-08T15:20:17.0-02:00 " 2020-07-08T15:20:17.0-02:00" "2020-07-08T15:20:17.0-02:00 " } { lappend result [tdom::type::dateTime $txt] } set result } {0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 1 0 0} test schema-27.8 {time outside schema context} { set result "" foreach txt { "" foo 1 07:15:00 07:15:00.023 07:15:00+05:00 07:15:00Z 00:00:00 24:00:00 7:15:00 07:15 07:15.4:23 12:60:12 12:61:12 12:71:12 24:31:12 25:31:12 55:31:12 12:31:60 12:31:61 12:31:77 } { lappend result [tdom::type::time $txt] } set result } {0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0} test schema-27.9 {duration outside schema context} { set result "" foreach txt { "" foo 1 P2Y6M5DT12H35M30S P1DT2H P20M PT20M P0Y20M0D P0Y -P60D PT1M30.5S P-20M P20MT P1YM5D P15.5Y P1D2H 1Y2M P2M1Y P PT15.S PT.5S } { lappend result [tdom::type::duration $txt] } set result } {0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0} test schema-28.1 {schema use in child interp while in schema context} { tdom::schema s set result [catch {s defelement doc { interp create childinterp load {} Tdom childinterp childinterp eval { ::tdom::schema::element fromchild } element this }}] if {$result} { s defelement doc { element this } } set result [s validate { }] s delete interp delete childinterp set result } 0 test schema-28.2 {called outside schema context} { catch {::tdom::schema::element elm} } 1 test schema-28.3 {schema use in child interp while in schema context} { tdom::schema s s defelement doc { interp create childinterp load {} Tdom childinterp childinterp eval { tdom::schema s s defelement doc { element child element this } } element this } set result "" foreach xml { } { lappend result [s validate $xml] } lappend result {*}[childinterp eval { set result "" foreach xml { } { lappend result [s validate $xml] } set result return {1 0} }] s delete interp delete childinterp set result } {0 1 1 0} test schema-29.1 {text constraint jsontype} { tdom::schema s s defelement JSON { element astring {text {jsontype STRING}} element anumber {text {jsontype NUMBER}} element atrue {text {jsontype TRUE}} element afalse {text {jsontype FALSE}} element anull {text {jsontype NULL}} } set result "" foreach json { {{ "astring": "0.123", "anumber": 0.123, "atrue": true, "afalse": false, "anull": null }} {{ "astring": "0.123", "anumber": "0.123", "atrue": true, "afalse": false, "anull": null }} } { set jdoc [dom parse -json -jsonroot JSON $json] lappend result [s domvalidate [$jdoc documentElement]] $jdoc delete } s delete set result } {1 0} test schema-29.2 {text constraint jsontype} { tdom::schema s s define { defelement JSON { element astring {text type jsonString} element anumber {text type jsonNumber} } deftexttype jsonString {jsontype STRING} deftexttype jsonNumber {jsontype NUMBER} } set result "" foreach json { {{ "astring": "0.123", "anumber": 0.123 }} {{ "astring": "0.123", "anumber": "0.123" }} } { set jdoc [dom parse -json -jsonroot JSON $json] lappend result [s domvalidate [$jdoc documentElement]] $jdoc delete } s delete set result } {1 0} test schema-29.3 {structure constraint jsontype} { tdom::schema s s define { defelement JSON { element aarray { jsontype ARRAY text {jsontype STRING} text {jsontype NUMBER} } element aobject { jsontype OBJECT interleave { element astring {text type jsonString} element anumber {text type jsonNumber} } } } deftexttype jsonString {jsontype STRING} deftexttype jsonNumber {jsontype NUMBER} } set result "" foreach json { {{ "aarray": ["some text", -23.45], "aobject": { "anumber": 3, "astring": "foo bar" } }} {{ "aarray": {"some key": -23.45}, "aobject": { "anumber": 3, "astring": "foo bar" } }} } { set jdoc [dom parse -json -jsonroot JSON $json] lappend result [s domvalidate [$jdoc documentElement] errMsg] $jdoc delete } s delete set result } {1 0} test schema-29.4 {structure constraint jsontype} { tdom::schema s s define { defelement JSON { element aobject {jsontype ARRAY} } } set result "" foreach json { {{ "aobject": {} }} {{ "aobject": [] }} } { set jdoc [dom parse -json -jsonroot JSON $json] lappend result [s domvalidate [$jdoc documentElement]] $jdoc delete } s delete set result } {0 1} test schema-29.5 {structure constraint jsontype} { tdom::schema s s define { defelement JSON { element aobject type jsonarry jsontype OBJECT } defelementtype jsonarry {jsontype ARRAY} } set result "" foreach json { {{ "aobject": {} }} {{ "aobject": [] }} } { set jdoc [dom parse -json -jsonroot JSON $json] lappend result [s domvalidate [$jdoc documentElement]] $jdoc delete } s delete set result } {0 1} } tdom-0.9.5-src/tests/pcdata.test0000644000175000017500000000460314703531020015240 0ustar rolfrolf# Features covered: PCDATA # # This file tests the parser's performance on PCDATA. # Sourcing this file into Tcl runs the tests and generates output # for errors. No output means no errors were found. # # Copyright (c) 1998-2000 Zveno Pty Ltd. # # $Id$ source [file join [file dir [info script]] loadtdom.tcl] catch {unset result} proc pcdata data { append ::result $data incr ::pcdataCounter } proc Estart {tagName attrList} { switch -- $tagName { Test { } default { incr ::element } } } proc EStop tagname { } test pcdata-1.1 {Simple PCDATA} { set ::result {} set ::element 0 set ::pcdataCounter 0 catch {rename xml::pcdata-1.1 {}} set parser [xml::parser xml::pcdata-1.1 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata] $parser parse { This is PCDATA } list $::result $::element } {{This is PCDATA} 0} test pcdata-1.2 {PCDATA section with Tcl specials} { set ::result {} set ::element 0 set ::pcdataCounter 0 catch {rename xml::pcdata-1.2 {}} set parser [xml::parser xml::pcdata-1.2 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata] $parser parse { Dollar $ backslash \ square brackets [ ] braces { } } list $::result $::element } {{Dollar $ backslash \ square brackets [ ] braces { }} 0} # Requested by Marshall Rose, 20/3/1999 test pcdata-1.3 {PCDATA with no entity expansion} { set ::result {} set ::element 0 set ::pcdataCounter 0 catch {rename xml::pcdata-1.3 {}} set parser [xml::parser xml::pcdata-1.3 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata] $parser parse { This is <PCDATA> } list $::result $::pcdataCounter } {{This is } 1} test pcdata-1.4 {keep all PCDATA for not white space only PCDATA content} { set ::result {} catch {rename xml::pcdata-1.4 {}} set parser [xml::parser xml::pcdata-1.4 \ -characterdatacommand pcdata \ -ignorewhitecdata 1] $parser parse { some content } set ::result } { some content } foreach parser [info commands pcdata-*] { $parser free } # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/decls.test0000644000175000017500000002346414703531020015104 0ustar rolfrolf# Features covered: Declarations # # This file tests the parser's performance on markup declarations. # Sourcing this file into Tcl runs the tests and generates output # for errors. No output means no errors were found. # # Copyright (c) 2000 Zveno Pty Ltd. # # $Id$ source [file join [file dir [info script]] loadtdom.tcl] set baseURI file://[file join [pwd] [file dir [info script]] decls.test] catch {unset elements} proc elementDecl {name cmodel} { set ::elements($name) $cmodel } catch {unset attrs} proc attlistDecl {name attName type dfltValue isrequired} { lappend ::attrs($name/$attName) $type $isrequired $dfltValue } catch {unset entities} proc entityDecl {name is_param value base systemId publicId notationName} { set ::entities($name) [list $is_param $value $base $systemId $publicId $notationName] } catch {unset cdata} proc CData data { append ::cdata [string trim $data] } proc extRefH {base systemId publicId} { if {![regexp {^[a-zA-Z]+://} $systemId]} { regsub {^[a-zA-Z]+://} $base {} base set basedir [file dirname $base] set systemId "[set basedir]/[set systemId]" } else { regsub {^[a-zA-Z]+://} $systemId systemId } if {[catch {set fd [open $systemId]}]} { return -code error \ -errorinfo "Failed to open external entity $systemId" } return [list channel $systemId $fd] } proc extRefHstr {base systemId publicId} { if {![regexp {^[a-zA-Z]+://} $systemId]} { regsub {^[a-zA-Z]+://} $base {} base set basedir [file dirname $base] set systemId "[set basedir]/[set systemId]" } else { regsub {^[a-zA-Z]+://} $systemId systemId } if {[catch {set fd [open $systemId]}]} { return -code error \ -errorinfo "Failed to open external entity $systemId" } return [list string $systemId [read $fd [file size $systemId]]] } # Internal DTD subset test decls-1.1 {element declaration} { catch {unset ::elements} array set ::elements {} catch {rename xml::decls-1.1 {}} set parser [xml::parser decls-1.1 \ -elementdeclcommand elementDecl] $parser parse { ]> } array get ::elements } {Test {MIXED {} {} {}}} test decls-2.1 {attribute list declaration, implied} { catch {unset ::attrs} array set ::attrs {} catch {rename xml::decls-2.1 {}} set parser [xml::parser decls-2.1 \ -attlistdeclcommand attlistDecl] $parser parse { ]> } array get ::attrs } {Test/test {CDATA 0 {}}} test decls-2.2 {attribute list declaration, enum} { catch {unset ::attrs} array set ::attrs {} catch {rename xml::decls-2.2 {}} set parser [xml::parser decls-2.2 \ -attlistdeclcommand attlistDecl] $parser parse { ]> } array get ::attrs } {Test/test {(LGL|OTH) 0 LGL}} test decls-3.1 {entity declarations} { catch {unset ::entities} array set ::entities {} catch {rename xml::decls-3.1 {}} set parser [xml::parser decls-3.1 \ -entitydeclcommand entityDecl] $parser parse { ]> } array get ::entities } {testEnt {0 {replacement text} {} {} {} {}}} test decls-4.1 {parameter entity declarations} { catch {unset ::entities} array set ::entities {} catch {unset ::elements} array set ::elements {} catch {rename xml::decls-4.1 {}} set parser [xml::parser decls-4.1 \ -paramentityparsing notstandalone \ -elementdeclcommand elementDecl] $parser parse { %PEnt; ]> } array get ::elements } {Test {MIXED {} {} {}}} # NB. entity.test tests entity replacement as well # External entities test decls-5.1 {external entity} { catch {unset ::elements} array set ::elements {} catch {rename xml::decls-5.1 {}} set parser [xml::parser decls-5.1 \ -paramentityparsing notstandalone \ -externalentitycommand extRefH \ -elementdeclcommand elementDecl \ -baseurl $baseURI] $parser parse { } array get ::elements } {Test {MIXED {} {} {}}} test decls-5.2 {external DTD subset} { catch {unset ::elements} array set ::elements {} catch {unset ::entities} array set ::entities {} catch {rename xml::decls-5.2 {}} set parser [xml::parser decls-5.2 \ -paramentityparsing notstandalone \ -externalentitycommand extRefH \ -elementdeclcommand elementDecl \ -baseurl $baseURI] $parser parse { } array get ::elements } {Test {MIXED {} {} {}}} test decls-5.3 {external entity} { catch {unset ::elements} array set ::elements {} catch {unset ::entities} array set ::entities {} catch {unset ::externals} array set ::externals {} catch {rename xml::decls-5.3 {}} set parser [xml::parser decls-5.3 \ -paramentityparsing notstandalone \ -externalentitycommand extRefH \ -elementdeclcommand elementDecl \ -baseurl $baseURI] $parser parse { %module; ]> } array get ::elements } {Test {MIXED {} {} {}}} test decls-5.4 {external entity} { catch {unset ::elements} array set ::elements {} catch {rename xml::decls-5.4 {}} set parser [xml::parser decls-5.4 \ -paramentityparsing notstandalone \ -externalentitycommand extRefHstr \ -elementdeclcommand elementDecl \ -baseurl $baseURI] $parser parse { } array get ::elements } {Test {MIXED {} {} {}}} test decls-5.5 {external DTD subset} { catch {unset ::elements} array set ::elements {} catch {unset ::entities} array set ::entities {} catch {rename xml::decls-5.5 {}} set parser [xml::parser decls-5.5 \ -paramentityparsing notstandalone \ -externalentitycommand extRefHstr \ -elementdeclcommand elementDecl \ -baseurl $baseURI] $parser parse { } array get ::elements } {Test {MIXED {} {} {}}} test decls-5.6 {external entity} { catch {unset ::elements} array set ::elements {} catch {unset ::entities} array set ::entities {} catch {unset ::externals} array set ::externals {} catch {rename xml::decls-5.6 {}} set parser [xml::parser decls-5.6 \ -paramentityparsing notstandalone \ -externalentitycommand extRefHstr \ -elementdeclcommand elementDecl \ -baseurl $baseURI] $parser parse { %module; ]> } array get ::elements } {Test {MIXED {} {} {}}} # Conditional Sections test decls-6.1 {conditional section: include} { catch {unset ::elements} array set ::elements {} catch {rename xml::decls-6.1 {}} set parser [xml::parser decls-6.1 \ -paramentityparsing notstandalone \ -externalentitycommand extRefH \ -elementdeclcommand elementDecl \ -baseurl $baseURI] $parser parse { } array get ::elements } {Test {MIXED {} {} {}}} test decls-6.2 {conditional section: include, empty} { catch {unset ::elements} array set ::elements {} catch {rename xml::decls-6.2 {}} set parser [xml::parser decls-6.2 \ -paramentityparsing notstandalone \ -externalentitycommand extRefH \ -elementdeclcommand elementDecl \ -baseurl $baseURI] $parser parse { } array get ::elements } {} test decls-6.3 {conditional section: include, empty} { catch {unset ::elements} array set ::elements {} catch {rename xml::decls-6.3 {}} set parser [xml::parser decls-6.3 \ -paramentityparsing notstandalone \ -externalentitycommand extRefH \ -elementdeclcommand elementDecl \ -baseurl $baseURI] $parser parse { } array get ::elements } {} test decls-6.4 {conditional section: include, nested} { catch {unset ::elements} array set ::elements {} catch {rename xml::decls-6.4 {}} set parser [xml::parser decls-6.4 \ -paramentityparsing notstandalone \ -externalentitycommand extRefH \ -elementdeclcommand elementDecl \ -baseurl $baseURI] $parser parse { } array size ::elements } 3 test decls-6.6 {conditional section/PE combo} { catch {unset ::elements} array set ::elements {} catch {rename xml::decls-6.6 {}} set parser [xml::parser decls-6.6 \ -paramentityparsing notstandalone \ -externalentitycommand extRefH \ -elementdeclcommand elementDecl \ -baseurl $baseURI] $parser parse { } array size ::elements } 2 foreach parser [info commands decls-*] { $parser free } # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/xmltest.test0000644000175000017500000000243014703531020015500 0ustar rolfrolf# Features covered: Conformance # # This file tests the parser's performance on conformance to the # XML specification. As such it is crude and does not test callback # features. # # Sourcing this file into Tcl runs the tests and generates output # for errors. No output means no errors were found. # # Copyright (c) 1999-2000 Zveno Pty Ltd. # # $Id$ source [file join [file dir [info script]] loadtdom.tcl] proc xmltest {expect dir subdir f} { set ch [open $f] set data [read $ch] close $ch test xmltest-$dir-$subdir-[file rootname [file tail $f]] "Document $dir $subdir [file tail $f]" { set parser [xml::parser xmltest] set code [catch {$parser parse $data}] rename $parser {} set code } $expect } # NB. Uses James Clark's test suite for WFF checking. # Need a framework to test against each file: it's too time- # consuming to setup a test proc for each one. set testDir [file join [pwd] xmltest] # These documents should fail foreach dir {not-wf} { foreach file [glob -nocomplain [file join $testDir $dir sa *.xml]] { xmltest 1 $dir sa $file } } # These documents should pass foreach dir {invalid valid} { foreach file [glob -nocomplain [file join $testDir $dir sa *.xml]] { xmltest 0 $dir sa $file } } # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/xslt.test0000644000175000017500000013060014703531020014773 0ustar rolfrolf# Features covered: XSLT transformation # # This file contains a collection of tests for the XSLT engine of # tDOM. It is focused mainly on the tcl interface of the engine and on # verification, that the created result tree behaves as if it would # have been parsed from an according XML source; the vaste majority of # xslt compliance tests are done outside the tcltest framework. # # Tested commands and object commands: # xslt-1.*: xpath Lexer/parser tests # xslt-2.*: xslt method command variants, -parameters option # xslt-3.*: xslt vars, scope, parameters # xslt-4.*: xslt transformations on modified/created from the scratch docs # xslt-5.*: External documents: document(), xsl:import, xsl:include # xslt-6.*: xsl:output # xslt-7.*: tests related to the created result doc # xslt-8.*: Additional xslt rec compliance tests (details not covered by # by the external xslt compliance test suite). # xslt-9.*: xslt transformations that are using scripted xpath functions # # Copyright (c) 2002 - 2005, 2013 Rolf Ade. # # RCS: @(#) $Id$ source [file join [file dir [info script]] loadtdom.tcl] test xslt-1.1 {unicode chars outside of US-ASCII in var name} { set xml [dom parse {}] set xslt [dom parse [tdom::xmlReadFile [file join [pwd] [file dir [info script]] data/xslt_1.xsl]]] set xmlroot [$xml documentElement] $xmlroot xslt $xslt resultDoc set resultroot [$resultDoc documentElement] set result [$resultroot asXML] $xml delete $xslt delete $resultDoc delete set result } {foo} test xslt-1.2 {xpath parse real number} { set xml [dom parse {}] set xslt [dom parse { }] set xmlroot [$xml documentElement] $xmlroot xslt $xslt resultDoc set resultroot [$resultDoc documentElement] set result [$resultroot asXML] $xml delete $xslt delete $resultDoc delete set result } {0.12345} test xslt-1.3 {xpath parse real number} { set xml [dom parse {}] set xslt [dom parse { }] set xmlroot [$xml documentElement] $xmlroot xslt $xslt resultDoc set resultroot [$resultDoc documentElement] set result [$resultroot asXML] $xml delete $xslt delete $resultDoc delete set result } {-0.12345} test xslt-1.4 {pattern IsFQElement with FillNodeList} { set xml [dom parse {}] set xslt [dom parse { }] $xml xslt $xslt resultDoc set result [$resultDoc asXML -indent none] $xslt delete $xml delete $resultDoc delete set result } {m:elem} test xslt-1.5 {space between \$ and varname} { set xml [dom parse {}] set xslt [dom parse { }] set xsltCmd [$xslt toXSLTcmd] set result [catch {set resultDoc [$xsltCmd transform $xml]} errMsg] $xsltCmd delete $xml delete lappend result $errMsg } {1 {Expected variable name}} test xslt-1.6 {space in nodetest node( )} { set xml [dom parse {text}] set xslt [dom parse { }] set xsltCmd [$xslt toXSLTcmd] set resultDoc [$xsltCmd transform $xml] $xsltCmd delete $xml delete set result [$resultDoc asText] $resultDoc delete set result } {3} test xslt-2.1 {xslt top level parameter: use default value} { set xml [dom parse {}] set xslt [dom parse { }] set xmlroot [$xml documentElement] $xmlroot xslt $xslt resultDoc set resultroot [$resultDoc documentElement] set result [$resultroot asXML] $xml delete $xslt delete $resultDoc delete set result } {parameter1Value} test xslt-2.2 {xslt top level parameter: overwrite default value with -parameters} { set xml [dom parse {}] set xslt [dom parse { }] set xmlroot [$xml documentElement] $xmlroot xslt -parameters {parameter1 startValue} $xslt resultDoc set resultroot [$resultDoc documentElement] set result [$resultroot asXML] $xml delete $xslt delete $resultDoc delete set result } {startValue} test xslt-2.3 {xslt top level parameter: overwrite default value with -parameters} { set xml [dom parse -keepEmpties {}] set xslt [dom parse -keepEmpties { }] set xmlroot [$xml documentElement] $xmlroot xslt -parameters {parameter1 startValue} $xslt resultDoc set resultroot [$resultDoc documentElement] set result [$resultroot asXML] $xml delete $xslt delete $resultDoc delete set result } {startValue parameter2Value} test xslt-2.4 {xslt top level parameter: overwrite default value with -parameters} { set xml [dom parse -keepEmpties {}] set xslt [dom parse -keepEmpties { }] set xmlroot [$xml documentElement] $xmlroot xslt -parameters {parameter1 startValue1 parameter2 startValue2} $xslt resultDoc set resultroot [$resultDoc documentElement] set result [$resultroot asXML] $xml delete $xslt delete $resultDoc delete set result } {startValue1 startValue2} test xslt-2.5 {xslt top level parameter: try to set nonexisted param} { set xml [dom parse -keepEmpties {}] set xslt [dom parse -keepEmpties { }] set xmlroot [$xml documentElement] catch {$xmlroot xslt -parameters {nonExistend foo} $xslt resultDoc} errMsg $xml delete $xslt delete set errMsg } {There isn't a parameter named "nonExistend" defined at top level in the stylesheet.} test xslt-2.6 {xslt top level parameter: try to set variable} { set xml [dom parse -keepEmpties {}] set xslt [dom parse -keepEmpties { }] set xmlroot [$xml documentElement] catch {$xmlroot xslt -parameters {variable1 foo} $xslt resultDoc} errMsg $xml delete $xslt delete set errMsg } {"variable1" is defined as variable, not as parameter.} test xslt-2.7 {xslt top level parameter} { set xml [dom parse -keepEmpties {}] set xslt [dom parse -keepEmpties { }] set xmlroot [$xml documentElement] catch {$xmlroot xslt -parameters {parameter2 foo} $xslt resultDoc} errMsg set resultroot [$resultDoc documentElement] set result [$resultroot asXML] $xml delete $xslt delete $resultDoc delete set result } {variable1Value foo} test xslt-2.8 {xslt top level parameter: wrong usage of -parameters option} { set xml [dom parse {}] set xslt [dom parse { }] set xmlroot [$xml documentElement] catch {$xmlroot xslt -parameters $xslt resultDoc} errMsg $xml delete $xslt delete set errMsg } {parameter value missing: the -parameters option needs a list of parameter name and parameter value pairs} test xslt-2.9 {xslt top level parameter: wrong usage of -parameters option} { set xml [dom parse {}] set xslt [dom parse { }] set xmlroot [$xml documentElement] catch {$xmlroot xslt -parameters {foo bar baz} $xslt resultDoc} errMsg $xml delete $xslt delete set errMsg } {parameter value missing: the -parameters option needs a list of parameter name and parameter value pairs} test xslt-2.10 {no resultDoc variable name} { set xml [dom parse {}] set xslt [dom parse { }] set xmlroot [$xml documentElement] set resultDoc [$xmlroot xslt $xslt] set resultroot [$resultDoc documentElement] set result [$resultroot asXML] $xml delete $xslt delete $resultDoc delete set result } {parameter1Value} test xslt-2.11 {xslt top level parameter: set with 'strange' value} { set xml [dom parse {}] set xslt [dom parse { }] set xmlroot [$xml documentElement] $xmlroot xslt -parameters {parameter1 foo\"'<>bar} $xslt resultDoc set resultroot [$resultDoc documentElement] set result [$resultroot asXML] $xml delete $xslt delete $resultDoc delete set result } {foo"'<>bar} # emacs: " test xslt-2.12 {xslt top level parameter: set FQ top-level param} { set xml [dom parse {}] set xslt [dom parse { }] set xmlroot [$xml documentElement] $xmlroot xslt -parameters {foo:parameter1 setValue} $xslt resultDoc set resultroot [$resultDoc documentElement] set result [$resultroot asXML] $xml delete $xslt delete $resultDoc delete set result } {setValue} test xslt-2.13 {xslt top level parameter: set FQ top-level param} { set xml [dom parse {}] set xslt [dom parse { }] set xmlroot [$xml documentElement] $xmlroot xslt -parameters {foo:parameter1 setValue} $xslt resultDoc set resultroot [$resultDoc documentElement] set result [$resultroot asXML] $xml delete $xslt delete $resultDoc delete set result } {setValue} test xslt-2.14 {xslt top level parameter: set FQ top-level param} { set xml [dom parse {}] set xslt [dom parse { }] set xmlroot [$xml documentElement] $xmlroot xslt -parameters {foo:parameter1 setValue} $xslt resultDoc set resultroot [$resultDoc documentElement] set result [$resultroot asXML] $xml delete $xslt delete $resultDoc delete set result } {setValue} test xslt-2.15 {xslt top level parameter:\ try to set nonexisted param with ignore} { set xml [dom parse -keepEmpties {}] set xslt [dom parse -keepEmpties { }] set xmlroot [$xml documentElement] set result [catch {$xmlroot xslt -ignoreUndeclaredParameters\ -parameters {nonExistend foo}\ $xslt resultDoc} errMsg] $resultDoc delete $xml delete $xslt delete set result } {0} test xslt-2.16 {xslt top level parameter: try to set nonexisted param with ignore} { set xml [dom parse -keepEmpties {}] set xslt [dom parse -keepEmpties { }] set xmlroot [$xml documentElement] $xmlroot xslt -ignoreUndeclaredParameters \ -parameters {nonExistend foo parameter2 givenValue} \ $xslt resultDoc set resultroot [$resultDoc documentElement] set result [$resultroot nodeValue] $resultDoc delete $xml delete $xslt delete set result } {parameter1Value givenValue} proc xsltmessagecmd {msg terminate} { global xsltMsgs global terminatingMsg append xsltMsgs "$msg terminate: $terminate " if {$terminate} { set terminatingMsg 1 } else { set terminatingMsg 0 } } test xslt-2.17 {xslt - to less arguments to the method} { set xml [dom parse {}] set result [catch {$xml xslt}] $xml delete set result } {1} test xslt-2.18 {xslt -xsltmessagecmd} { set xml [dom parse -keepEmpties {}] set xslt [dom parse -keepEmpties { some text 1. call 2. call 3. call }] set xmlroot [$xml documentElement] set ::xsltMsgs "" $xmlroot xslt -xsltmessagecmd xsltmessagecmd $xslt resultDoc $resultDoc delete $xml delete $xslt delete set ::xsltMsgs } {1. call terminate: 0 2. call terminate: 0 3. call terminate: 0 } test xslt-2.19 {xslt -xsltmessagecmd} { set xml [dom parse -keepEmpties {}] set xslt [dom parse -keepEmpties { some text 1. call 2. call 3. call }] set xmlroot [$xml documentElement] set ::xsltMsgs "" catch {$xmlroot xslt -xsltmessagecmd xsltmessagecmd $xslt resultDoc} $xml delete $xslt delete set ::terminatingMsg } {1} test xslt-2.20 {xslt top level parameter: use top level param to set a top level var} { set xml [dom parse -keepEmpties {}] set xslt [dom parse -keepEmpties { }] $xml xslt -parameters {sortentity "the parameter value"} $xslt resultDoc set result [$resultDoc asXML -indent none] $resultDoc delete $xml delete $xslt delete set result } {the parameter value} proc xslt-2.21-xsltmsgcmd {msg terminate} { global result if {$msg eq "3"} { return -code break } append result $msg } test xslt-2.21 {xslt -xsltmessagecmd return code break} { set result "" set xml [dom parse {}] set xslt [dom parse { }] catch {$xml xslt -xsltmessagecmd xslt-2.21-xsltmsgcmd $xslt resultDoc} errMsg append result $resultDoc $errMsg $xml delete $xslt delete set result } {12} test xslt-2.22 {xslt -xsltmessagecmd return code break} { set result "" set xml [dom parse {}] set xslt [dom parse { }] set resultDoc "untouched" catch {$xml xslt -ignoreUndeclaredParameters -xsltmessagecmd xslt-2.21-xsltmsgcmd $xslt resultDoc} errMsg append result $resultDoc $xml delete $xslt delete set result } {12} test xslt-2.23 {xslt outputVar} { set result "" set xml [dom parse {}] set xslt [dom parse { }] set resultDoc "untouched" catch {$xml xslt -foo $xslt resultDoc} errMsg append result $resultDoc $xml delete $xslt delete set result } {untouched} test xslt-2.24 {xslt outputVar} { set xml [dom parse {}] set xslt [dom parse { }] set result [catch {$xml xslt -foo $xslt }] $xml delete $xslt delete set result } {1} test xslt-2.25 {xslt outputVar} { set xml [dom parse {}] set xslt [dom parse { Here }] $xml xslt $xslt resultDoc $xml delete $xslt delete set result [$resultDoc asXML -indent none] $resultDoc delete set result } {} test xslt-2.26 {xslt -maxApplyDepth option} { set xml [dom parse {}] set xslt [dom parse { e }] catch {$xml xslt -maxApplyDepth 3 $xslt} errMsg $xml delete $xslt delete set errMsg } "Maximum nested apply templates reached (potential infinite template recursion?)." test xslt-3.1 {xslt variable scope} { set xml [dom parse {}] set xslt [dom parse { }] set xmlroot [$xml documentElement] catch {$xmlroot xslt $xslt resultDoc} errMsg $xml delete $xslt delete set errMsg } {Variable "main" has not been declared.} test xslt-3.2 {xslt error msg of variable redeclaration in one template} { set xml [dom parse {}] set xslt [dom parse { }] catch {$xml xslt $xslt resultDoc} errMsg $xml delete $xslt delete set errMsg } {Variable 'var' is already declared in this template} test xslt-3.3 {use top level var to set a top level var} { set xml [dom parse -keepEmpties {}] set xslt [dom parse -keepEmpties { }] $xml xslt $xslt resultDoc set result [$resultDoc asXML -indent none] $resultDoc delete $xml delete $xslt delete set result } {var1Value} test xslt-4.1 {xslt transformation of a source which was modifed after parsing} { dom parse -baseurl file:///tmp/abc.xml {} doc $doc documentElement root $root appendXML dom parse { } xslDoc $root xslt $xslDoc newDoc set result [$newDoc asXML -indent none] $doc delete $xslDoc delete $newDoc delete set result } {} set xslt { Data stored in the stylesheet } proc 5.1-extref {baseURI systemId publicId} { if {$baseURI != ""} { error "baseURI not empty" } if {$systemId != ""} { error "systemId not empty" } return [list string "" $::xslt] } test xslt-5.1 {xslt document('') with empty baseURI} { dom parse xmldoc dom parse -externalentitycommand 5.1-extref $xslt xsltdoc $xmldoc xslt $xsltdoc resultDoc set result [$resultDoc asXML -indent none] $resultDoc delete $xsltdoc delete $xmldoc delete set result } {Data stored in the stylesheet} proc xslt-5.2 {args} { error "script error in xslt-5.2 external enitity resolver" } set xslt { } test xslt-5.2 {xslt document() with script error in -externalentitycommand} { dom parse xmldoc dom parse -externalentitycommand xslt-5.2 $xslt xsltdoc set result [catch {$xmldoc xslt $xsltdoc resultDoc} errMsg] $xmldoc delete $xsltdoc delete lappend result $errMsg } {1 {script error in xslt-5.2 external enitity resolver}} proc xslt-5.3 {args} { return [list string file://some/base " xmldoc dom parse -externalentitycommand xslt-5.3 $xslt xsltdoc set result [catch {$xmldoc xslt $xsltdoc resultDoc} errMsg] $xmldoc delete $xsltdoc delete lappend result $errMsg } {1 {Error while processing external entity "foo": At line 1 character 15: not well-formed (invalid token)}} proc xslt-5.4 {base systemId publicId} { switch $systemId { "firstlevel" { return [list string file://some/base/first { }] } "secondlevel" { return [list string file://some/base/second " foo } test xslt-5.4 {xslt document() with script error in -externalentitycommand} { dom parse xmldoc dom parse -externalentitycommand xslt-5.4 $xslt xsltdoc set result [catch {$xmldoc xslt $xsltdoc resultDoc} errMsg] $xmldoc delete $xsltdoc delete lappend result $errMsg } {1 {Error while processing external entity "secondlevel": At line 1 character 15: not well-formed (invalid token)}} set xslt { foo } test xslt-5.5 {xsl:import href == ""} { dom parse xmldoc dom parse -externalentitycommand xslt-5.4 $xslt xsltdoc set result [catch {$xmldoc xslt $xsltdoc resultDoc} errMsg] $xmldoc delete $xsltdoc delete lappend result $errMsg } {1 {Recursive import/include: stylesheet tries to access itself.}} set xslt { } test xslt-6.1 {xsl:output} { dom parse xmldoc dom parse $xslt xsltdoc $xmldoc xslt $xsltdoc resultDoc set result [$resultDoc indent] lappend result [$resultDoc omit-xml-declaration] lappend result [$resultDoc encoding] lappend result [$resultDoc mediaType] lappend result [$resultDoc standalone] lappend result [$resultDoc getDefaultOutputMethod] $resultDoc delete $xsltdoc delete $xmldoc delete set result } {1 0 ISO-8859-1 text/foo 1 text} set xslt { } test xslt-7.1 {namespaces in the result doc} { dom parse xmldoc dom parse $xslt xsltdoc $xmldoc xslt $xsltdoc resultDoc set nodes [$resultDoc getElementsByTagNameNS "http://my.uri" element] set result "" foreach node $nodes { lappend result [$node nodeName] } $resultDoc delete $xmldoc delete $xsltdoc delete set result } {my:element} test xslt-7.2 {namespaces in the result doc} { dom parse xmldoc dom parse $xslt xsltdoc $xmldoc xslt $xsltdoc resultDoc set result [$resultDoc asXML -indent none] $resultDoc delete $xmldoc delete $xsltdoc delete set result } {} test xslt-7.3 {namespaces in the result doc} { dom parse xmldoc dom parse $xslt xsltdoc $xmldoc xslt $xsltdoc resultDoc $resultDoc documentElement root set my:element [$root firstChild] set result [${my:element} namespaceURI] $resultDoc delete $xmldoc delete $xsltdoc delete set result } {http://my.uri} set xslt { } test xslt-7.4 {namespaces in the result doc} { dom parse xmldoc dom parse $xslt xsltdoc $xmldoc xslt $xsltdoc resultDoc set nodes [$resultDoc getElementsByTagNameNS "" element] set result "" foreach node $nodes { lappend result [$node nodeName] } $resultDoc delete $xmldoc delete $xsltdoc delete set result } {element} test xslt-7.5 {namespaces in the result doc} { dom parse xmldoc dom parse $xslt xsltdoc $xmldoc xslt $xsltdoc resultDoc set nodes [$resultDoc getElementsByTagName element] set result "" foreach node $nodes { lappend result [$node nodeName] } $resultDoc delete $xmldoc delete $xsltdoc delete set result } {element} set xslt { } test xslt-7.6 {namespaces in the result doc} { dom parse xmldoc dom parse $xslt xsltdoc $xmldoc xslt $xsltdoc resultDoc set nodes [$resultDoc getElementsByTagNameNS "element.uri" *] set result "" foreach node $nodes { lappend result [$node nodeName] } $resultDoc delete $xmldoc delete $xsltdoc delete set result } {element} test xslt-7.7 {parent of the result doc documentElement} { dom parse xmldoc dom parse $xslt xsltdoc $xmldoc xslt $xsltdoc resultDoc set resultRoot [$resultDoc documentElement] set result [$resultRoot parentNode] $resultDoc delete $xmldoc delete $xsltdoc delete set result } {} set xslt { } test xslt-7.8 {namespaces in the result doc} { dom parse xmldoc dom parse $xslt xsltdoc $xmldoc xslt $xsltdoc resultDoc set nodes [$resultDoc getElementsByTagNameNS "http://my.uri" *] set result "" foreach node $nodes { lappend result [$node nodeName] } $resultDoc delete $xmldoc delete $xsltdoc delete set result } {my:element my:foo} set xslt { } test xslt-7.9 {parent of the result doc documentElement} { dom parse xmldoc dom parse $xslt xsltdoc $xmldoc xslt $xsltdoc resultDoc set resultRoot [$resultDoc documentElement] set result [list [$resultDoc asXML -indent none] [$resultRoot parentNode]] $resultDoc delete $xmldoc delete $xsltdoc delete set result } { {}} set xslt { } test xslt-7.10 {parent of the result doc documentElement} { dom parse xmldoc dom parse $xslt xsltdoc $xmldoc xslt $xsltdoc resultDoc set result [list [$resultDoc asXML -indent none]] foreach toplevelNode [$resultDoc childNodes] { lappend result [$toplevelNode parentNode] } $resultDoc delete $xmldoc delete $xsltdoc delete set result } { {} {}} set xslt { } set xml {} test xslt-8.1 {current() not allowed in pattern} { dom parse $xml xmldoc dom parse $xslt xsltdoc 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 {
} set xslt-8.2.xsl { } set xslt-8.2.output {
} test xslt-8.2 {namespace handling of copy-of} { dom parse -keepEmpties ${xslt-8.2.xml} xmldoc dom parse -keepEmpties ${xslt-8.2.xsl} xsltdoc $xmldoc xslt $xsltdoc resultDoc $xmldoc delete $xsltdoc delete set result [$resultDoc asXML -indent none] $resultDoc delete set result } ${xslt-8.2.output} test xslt-8.3 {format-number() runding} { set xml { 1.999 1.998 1.997 1.996 1.995 1.994 1.99 1.9 1. } set xslt { } dom parse -keepEmpties $xml xmldoc dom parse -keepEmpties $xslt xsltdoc $xmldoc xslt $xsltdoc resultDoc $xmldoc delete $xsltdoc delete set result [$resultDoc asXML -indent none] $resultDoc delete set result } {2.00 2.00 2.00 2.00 2.00 1.99 1.99 1.90 1.00 } test xslt-8.4 {Erroneous XPath expr as match attribute of a template} { set xmlDoc [dom parse {}] set xslt { } set xsltDoc [dom parse $xslt] set result [catch {$xmlDoc xslt $xsltDoc} errMsg] $xmlDoc delete $xsltDoc delete set result } {1} test xslt-8.5 {Minimal xslt 1.0 stylesheet} { set xmlDoc {} set xsltDoc {} dom parse -keepEmpties $xmlDoc xmldoc dom parse -keepEmpties $xsltDoc xsltdoc $xmldoc xslt $xsltdoc resultDoc set result [$resultDoc asXML -indent none] $xmldoc delete $xsltdoc delete $resultDoc delete set result } {} test xslt-8.6 {Almost minimal xslt 1.0 stylesheet} { set xmlDoc {} set xsltDoc { } dom parse -keepEmpties $xmlDoc xmldoc dom parse -keepEmpties $xsltDoc xsltdoc $xmldoc xslt $xsltdoc resultDoc set result [$resultDoc asXML -indent none] $xmldoc delete $xsltdoc delete $resultDoc delete set result } {} test xslt-8.7 {Minimal xslt 1.0 stylesheet returns text content of doc by default} { set xmlDoc {text} set xsltDoc {} dom parse -keepEmpties $xmlDoc xmldoc dom parse -keepEmpties $xsltDoc xsltdoc $xmldoc xslt $xsltdoc resultDoc set result [$resultDoc asXML -indent none] $xmldoc delete $xsltdoc delete $resultDoc delete set result } {text} test xslt-8.8 {Almost minimal xslt 1.0 stylesheet} { set xmlDoc {text} set xsltDoc { } dom parse -keepEmpties $xmlDoc xmldoc dom parse -keepEmpties $xsltDoc xsltdoc $xmldoc xslt $xsltdoc resultDoc set result [$resultDoc asXML -indent none] $xmldoc delete $xsltdoc delete $resultDoc delete set result } {} test xslt-8.9 {format-number} {knownBug} { set xmlDoc [dom parse ] set xsltDoc [dom parse { }] $xmlDoc xslt $xsltDoc resultDoc set result [$resultDoc asXML -indent none] $xmlDoc delete $xsltDoc delete $resultDoc delete set result 001 } {001} proc ::dom::xpathFunc::xslt-9.1 {ctxNode pos nodeListType nodeList args} { if {[llength $ctxNode] != 2} { error "::dom::xpathFunc::xslt-9.1: expected parent node / attribute \ name list as first argument." } return {string "bar"} } test xslt-9.1 {xslt using scripted xpath function} -setup { set xml {} set xsl { } set xsltDoc [dom parse -keepEmpties $xsl] set xmlDoc [dom parse $xml] } -body { $xmlDoc xslt $xsltDoc resultDoc $resultDoc asXML -indent none } -cleanup { $xsltDoc delete $xmlDoc delete $resultDoc delete } -result {} # Below is code, which replaces the dom cmd with a version, which parses # the xml into a dom tree, then transformations this dom tree with the # xslt identity transformation and returns the result tree of that # transformation. This is used to test, that the result tree of an xslt # transformation could be used as any 'ordinary' tree created with # [dom parse]. It is here, because I didn't want to hold it separated. # It is commented out, because some of the tests in the sourced test files # need line/column or baseURI information, to work correctly, and this # information is not preserved by an xslt identity transformation and # I was up to now too lazy, to trick around this few tests with some # test constraints. # # set identityTransformation [dom parse { # # # # # # }] # rename dom _dom # proc dom {args} { # global identityTransformation # switch [lindex $args 0] { # "parse" { # set resultdoc [uplevel 1 [linsert $args 0 _dom]] # return [$resultdoc xslt $identityTransformation] # } # default { # return [uplevel 1 [linsert $args 0 _dom]] # } # } # } # source [file join [file dir [info script]] i18n.test] # source [file join [file dir [info script]] dom.test] # rename dom {} # rename _dom dom # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/stackedhdl.test0000644000175000017500000002003214703531020016104 0ustar rolfrolf# Features covered: stacked handler, tdom command # # This file contains a collection of tests for using several handler scripts # for an event, and the mixed usage of tcl handler scripts and C coded # parser extensions. # # Copyright (c) 2002 Rolf Ade. # # RCS: @(#) $Id$ source [file join [file dir [info script]] loadtdom.tcl] proc Count {args} { if {![info exists ::count]} { set ::count 1 } else { incr ::count } } proc CharCount {name args} { if {![info exists ::charcount]} { set ::charcount [string length $name] } else { incr ::charcount [string length $name] } } proc CDataHandler {data} { if {![info exists ::cdata]} { set ::cdata [string length $data] } else { incr ::cdata [string length $data] } } catch {unset started} proc Start {name atList} { array set atts $atList if {![info exists ::started($name)]} { set ::started($name) 1 } else { incr ::started($name) } if {[info exists atts(class)]} { switch $atts(class) { continue { return -code continue } break { return -code break } error { return -code error "error condition in callback" } return { return -code return } default { return -code $atts(class) } } } } test stackedhdl-1.1 {two handlers for element start} { catch {unset ::count} catch {unset ::charcount} set p [expat -elementstartcommand Count \ -handlerset charcount -elementstartcommand CharCount] $p parse {} list $::count $::charcount } {3 6} test stackedhdl-1.2 {two handlers for element start} { catch {unset ::count} catch {unset ::charcount} set p [expat] $p configure -elementstartcommand Count $p configure -handlerset charcount -elementstartcommand CharCount $p parse {} list $::count $::charcount } {3 6} test stackedhdl-1.3 {two handlers for element start} { catch {unset ::count} catch {unset ::charcount} set p [expat] $p configure -handlerset charcount -elementstartcommand CharCount $p configure -elementstartcommand Count $p parse {} list $::count $::charcount } {3 6} test stackedhdl-1.4 {two handlers for element start and end} { catch {unset ::count} catch {unset ::charcount} set p [expat -elementstartcommand Count -elementendcommand Count \ -handlerset charcount -elementstartcommand CharCount \ -elementendcommand CharCount] $p parse {} list $::count $::charcount } {6 12} test stackedhdl-1.5 {two handlers for element start} { catch {unset ::count} catch {unset ::charcount} set p [expat] $p configure -elementstartcommand Count -elementendcommand Count $p configure -handlerset charcount -elementstartcommand CharCount \ -elementendcommand CharCount $p parse {} list $::count $::charcount } {6 12} test stackedhdl-1.6 {two handlers for element start} { catch {unset ::count} catch {unset ::charcount} set p [expat] $p configure -handlerset charcount -elementstartcommand CharCount \ -elementendcommand CharCount $p configure -elementstartcommand Count -elementendcommand Count $p parse {} list $::count $::charcount } {6 12} test stackedhdl-1.7 {two handlers for element start} { catch {unset ::count} catch {unset ::charcount} set p [expat] $p configure -handlerset charcount -elementstartcommand CharCount $p configure -elementstartcommand Count $p configure -handlerset charcount -elementendcommand CharCount $p configure -elementendcommand Count $p parse {} list $::count $::charcount } {6 12} test stackedhdl-1.8 {same handler script for the same event in differen handler sets} { catch {unset ::count} set p [expat -elementstartcommand Count \ -handlerset charcount -elementstartcommand Count] $p parse {} set ::count } {6} test stackedhdl-1.9 {same handler script for the same event in differen handler sets} { catch {unset ::count} set p [expat -elementendcommand Count \ -handlerset charcount -elementendcommand Count] $p parse {} set ::count } {6} test stackedhdl-1.10 {lots of handler sets, without default handler set} { catch {unset ::count} catch {unset ::charcount} catch {unset ::cdata} set p [expat] for {set x 0} {$x < 100} {incr x} { $p configure -handlerset set$x -elementstartcommand Count \ -elementendcommand CharCount \ -characterdatacommand CDataHandler } $p parse { } list $::count $::charcount $::cdata } {300 600 200} test stackedhdl-2.1 {tcl handler and C coded parser extension} { catch {unset ::count} set p [expat -elementstartcommand Count] tdom $p enable $p parse {boo} set doc [tdom $p getdoc] set root [$doc documentElement] set result [list $::count [llength [$root childNodes]]] $doc delete set result } {3 2} test stackedhdl-2.2 {tcl handler and C coded parser extension} { catch {unset ::count} set p [expat -elementstartcommand Count] tdom $p enable $p parse {boo} set doc [tdom $p getdoc] $p free set root [$doc documentElement] set result [list $::count [llength [$root childNodes]]] $doc delete set result } {3 2} test stackedhdl-2.3 {return -code return with tcl and C coded handler} -setup { catch {unset started} } -body { set p [expat -elementstartcommand Start] tdom $p enable set resultcode [catch {$p parse {}}] set result [list $resultcode $::started(e) [[tdom $p getdoc] asXML -indent none]] $p free set result } -result {0 2 {}} test stackedhdl-2.4 {return -code error with tcl and C coded handler} -setup { catch {unset started} } -body { set p [expat -elementstartcommand Start] tdom $p enable set resultcode [catch {$p parse {}} msg] set result [list $resultcode $msg $::started(e) [[tdom $p getdoc] asXML -indent none]] $p free set result } -result {1 {error condition in callback} 2 {}} test stackedhdl-2.5 {return -code return with tcl and C coded handler} -setup { catch {unset started} } -body { set p [expat -elementstartcommand Start] tdom $p enable set resultcode [catch {$p parse {}}] set result [list $resultcode $::started(e) [[tdom $p getdoc] asXML -indent none]] $p reset catch {unset started} set resultcode [catch {$p parse {}}] lappend result $resultcode $::started(e) [[tdom $p getdoc] asXML -indent none] $p free set result } -result {0 2 {} 0 3 } test stackedhdl-2.6 {return -code error with tcl and C coded handler} -setup { catch {unset started} } -body { set p [expat -elementstartcommand Start] tdom $p enable set resultcode [catch {$p parse {}} msg] set result [list $resultcode $msg $::started(e) [[tdom $p getdoc] asXML -indent none]] $p reset catch {unset started} set resultcode [catch {$p parse {}}] lappend result $resultcode $::started(e) [[tdom $p getdoc] asXML -indent none] $p free set result } -result {1 {error condition in callback} 2 {} 0 3 } test stackedhdl-3.1 {don't request the DOM tree from a tdom enabled parser} { set p [expat] tdom $p enable $p parse {boo} $p free } {} foreach parser [info commands xmlparser*] { $parser free } # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/domjson.test0000644000175000017500000056440514703531020015470 0ustar rolfrolf# Features covered: JSON parser # # This file contains a collection of tests for the JSON parser. # Tested functionalities: # json-1.*: JSON syntax tests # json-2.*: Valid JSON, that could not parsed into DOM # json-3.*: JSON unescaping # json-4.*: Unicode # json-5.*: Max nesting # json-6.*: asJSON # json-7.*: jsonType # json-8.*: appendFromScript # json-9.*: cloneNode # json-10.*: asTclValue # json-11.*: asTypedList # json-12.*: createFromTypedList # Copyright (c) 2017 Rolf Ade. source [file join [file dir [info script]] loadtdom.tcl] testConstraint needExpand 1 if {$tcl_version < 8.5} { testConstraint needExpand 0 } # See below the comment in proc dom for explanation if {[info commands _dom] eq ""} { testConstraint nonetest 1 } else { testConstraint nonetest 0 } namespace eval nodeCmds { dom createNodeCmd elementNode e1 dom createNodeCmd -jsonType ARRAY elementNode jae1 dom createNodeCmd elementNode e2 dom createNodeCmd commentNode c dom createNodeCmd textNode t dom createNodeCmd -jsonType TRUE textNode true dom createNodeCmd -jsonType FALSE textNode false dom createNodeCmd -jsonType NULL textNode null dom createNodeCmd -jsonType NUMBER textNode number dom createNodeCmd cdataNode cdata dom createNodeCmd piNode pi } test json-1.1 {Parse JSON} { set doc [dom parse -json {{"a":"avalue","b":"bvalue","c":0.123}}] set result [$doc asXML -indent none] $doc delete set result } "avaluebvalue0.123" test json-1.2 {Parse JSON} { set doc [dom parse -json { {"a" : [ "avalue" ] } }] set result [$doc asXML -indent none] $doc delete set result } {avalue} test json-1.3 {Parse JSON} { set doc [dom parse -json {{"a":"a value","b":"1value"}}] set result [$doc asXML -indent none] $doc delete set result } "a value1value" test json-1.4 {Parse JSON - nested object} { set doc [dom parse -json {{"a":{"aa":"aavalue","bb":"bbvalue"},"b":"bvalue","c":0.123}}] set result [$doc asXML -indent none] $doc delete set result } "aavaluebbvaluebvalue0.123" test json-1.5 {Parse JSON - array} { set doc [dom parse -json {{"a": [1,2,3,4,"abc"]}}] set result [$doc asXML -indent none] $doc delete set result } "1234abc" test json-1.6 {Parse JSON - true, false, null} { set doc [dom parse -json {{"a":true,"b":false,"c":null,"d":"true","e":""}}] set result [$doc asXML -indent none] $doc delete set result } {truefalsenulltrue} test json-1.7 {Parse JSON - array in nested object} { set doc [dom parse -json {{"a":{"aa":[1,2,3,4,"abc"]},"b":"bvalue"}}] set result [$doc asXML -indent none] $doc delete set result } "1234abcbvalue" test json-1.8 {Parse JSON - true, false, null} { set doc [dom parse -json -jsonroot "JSONObject" {{"a":true,"b":false,"c":null,"d":"true","e":""}}] set result [$doc asXML -indent none] $doc delete set result } {truefalsenulltrue} test json-1.9 {JSON syntax error} {nonetest} { set result [catch {dom parse -json {{"a" "a value"}}} errMsg] list $result $errMsg } {1 {error "JSON syntax error" at position 5 "{"a" " <--Error-- a value"}"}} test json-1.10 {JSON syntax error} {nonetest} { set result [catch {dom parse -json {{"a":00.23}}} errMsg] list $result $errMsg } {1 {error "JSON syntax error" at position 6 "{"a":00 <--Error-- .23}"}} test json-1.11 {JSON syntax error} {nonetest} { set result [catch {dom parse -json {{"a":-00.23}}} errMsg] list $result $errMsg } {1 {error "JSON syntax error" at position 7 "{"a":-00 <--Error-- .23}"}} test json-1.12 {JSON syntax error} {nonetest} { set result [catch {dom parse -json {{"a":.23}}} errMsg] list $result $errMsg } {1 {error "JSON syntax error" at position 5 "{"a":. <--Error-- 23}"}} test json-1.13 {JSON syntax error} {nonetest} { set result [catch {dom parse -json {{"a":-.23}}} errMsg] list $result $errMsg } {1 {error "JSON syntax error" at position 6 "{"a":-. <--Error-- 23}"}} test json-1.14 {JSON syntax error} {nonetest} { set result [catch {dom parse -json {{"a":-}}} errMsg] list $result $errMsg } {1 {error "JSON syntax error" at position 5 "{"a":- <--Error-- }"}} test json-1.15 {Parse JSON - nested object} { set doc [dom parse -json {["a",["aa","bb"],"b"]}] set result [$doc asXML -indent none] $doc delete set result } "aaabbb" set notJsons { {{null}} {{1.23}} {{"string"}} {{"e":}} } test json-1.16 {Invalid input} {nonetest} { set result "" set ind 0 foreach notJson $notJsons { if {![catch {dom parse -json $notJson docNode} errMsg]} { lappend result $errMsg } } set result } "" test json-1.17 {Literal binary 0 (NUL, '\0') is not allowed in input} {nonetest} { catch {dom parse -json "\"a\u0000\""} } 1 test json-1.18 {Escaped binary 0 (NUL, '\0') is OK} { dom parse -json "\"a\\u0000\"" doc set result [$doc asJSON] $doc delete set result } "\"a\\u0000\"" test json-1.19 {Invalid input - incomplete \u escape} {nonetest} { set result 1 foreach jsonstr { "ab\u00" "ab\ua" "ab\u12" "ab\u123" "ab\u123g" "ab\u12g" "ab\u1g" "ab\ug" "\u00" "\ua" "\u12" "\u123" "\u123g" "\u12g" "\u1g" "\ug" } { if {![catch {dom parse -json $jsonstr}]} { set result 0 break } } set result } 1 test json-1.20 {Escaped binary 0} {needExpand} { dom parse -json "\"a\\u0000\"" doc set textvalue [$doc selectNodes string(node())] set result [string length $textvalue] binary scan $textvalue c2 result2 lappend result {*}$result2 $doc delete set result } {2 97 0} test json-1.21 {Single \u encoded surrogate} { dom parse -json {"abc\uD835"} doc set result [$doc asXML -escapeNonASCII -indent none] $doc delete set result } {abc�} test json-1.22 {\u encoded surrogate pair} { dom parse -json {"abc\uD835\uDD38"} doc set result [$doc asXML -escapeNonASCII -indent none] $doc delete set result } {abc𝔸} test json-2.1 {invalid xml name} { set doc [dom parse -json {{"a":"a value","1b":"1value", "a\nb":"a\nb", "":"empty string"}}] set result [$doc asXML -indent none] $doc delete set result } {a value<1b>1valuea b<>empty string} test json-3.1 {Unescaping} { set doc [dom parse -json {{"a":"a\nvalue","b":"value\tvalue"}}] set result [$doc asXML -indent none] $doc delete set result } "a valuevalue\tvalue" test json-3.2 {Unescaping} { set doc [dom parse -json {{"a":"a\nvalue", "b":"12\u0077\u2221ec"}}] set result [$doc asXML -indent none -escapeNonASCII] $doc delete set result } "a value12w∡ec" test json-3.3 {Unescaping} { set doc [dom parse -json {{"a":"\u0077\u2221"}}] set result [$doc asXML -indent none -escapeNonASCII] $doc delete set result } "w∡" test json-3.4 {unescaping} { set doc [dom parse -jsonroot json -json {["\\a"]}] set result [$doc asXML -indent none] $doc delete set result } {\a} test json-3.4.1 {unescaping} { set doc [dom parse -jsonroot json -json {["\\a","\u0071"]}] set result [$doc asXML -indent none] $doc delete set result } {\aq} test json-3.5 {unescaping} {nonetest} { set result [catch {dom parse -json {{"this":"a\lb"}}} errMsg] list $result $errMsg } {1 {error "JSON syntax error" at position 11 "{"this":"a\l <--Error-- b"}"}} test json-3.6 {unescaping} { set doc [dom parse -json {{"this":"a\nbc"}}] set result [$doc asXML -indent none] $doc delete set result } {a bc} test json-3.7 {unescaping} { set doc [dom parse -json {{"this":"a\u0077\t\u0078bc"}}] set result [$doc asXML -indent none] $doc delete set result } "aw\txbc" test json-3.8 {unescaping} { set doc [dom parse -json {{"this":"a\u000b"}}] set result [$doc asXML -indent none] $doc delete set result } "a\u000b" test json-3.9 {unescaping} { set doc [dom parse -json {{"this":"a\u0077","that":"\t\u0078bc"}}] set result [$doc asXML -indent none] $doc delete set result } "aw\txbc" proc toutf8s s { set result "" foreach c [split $s ""] { set s [encoding convertto utf-8 $c] binary scan $s H* x append result [regsub -all -expanded {..} [string toupper $x] {\x&}] } return $result } test json-4.1 {html entities as JSON data} {Tcl9} { set file [file join [file dir [info script]] data/htmlmathml.json] set fd [open $file] set json [read $fd] close $fd set doc [dom parse -json $json] array unset entities set entities [list] set olentities [list] set maxe 0 set maxv 0 foreach entity [$doc selectNodes characters/*] { set ename [$entity nodeName] set evalue [[$entity firstChild] nodeValue] if {[string index $evalue 0] eq " "} { set evalue [string trim $evalue] } set eutf8 [toutf8s $evalue] if {[string length $ename] > $maxe} { set maxe [string length $ename] } if {[string length $eutf8] > $maxv} { set maxv [string length $eutf8] } if {[string length $ename] < [string length $eutf8]/4 - 2} { lappend olentities $ename $eutf8 $evalue } else { lappend entities $ename $eutf8 $evalue } } $doc delete set result "\n" incr maxe 4 incr maxv 4 foreach {name bytes glyphs} $entities { append result [format " { %-${maxe}s%-${maxv}s 0 },\n" \"$name\", \"$bytes\",] } set result } { { "AElig", "\xC3\x86", 0 }, { "AMP", "\x26", 0 }, { "Aacute", "\xC3\x81", 0 }, { "Abreve", "\xC4\x82", 0 }, { "Acirc", "\xC3\x82", 0 }, { "Acy", "\xD0\x90", 0 }, { "Afr", "\xF0\x9D\x94\x84", 0 }, { "Agrave", "\xC3\x80", 0 }, { "Alpha", "\xCE\x91", 0 }, { "Amacr", "\xC4\x80", 0 }, { "And", "\xE2\xA9\x93", 0 }, { "Aogon", "\xC4\x84", 0 }, { "Aopf", "\xF0\x9D\x94\xB8", 0 }, { "ApplyFunction", "\xE2\x81\xA1", 0 }, { "Aring", "\xC3\x85", 0 }, { "Ascr", "\xF0\x9D\x92\x9C", 0 }, { "Assign", "\xE2\x89\x94", 0 }, { "Atilde", "\xC3\x83", 0 }, { "Auml", "\xC3\x84", 0 }, { "Backslash", "\xE2\x88\x96", 0 }, { "Barv", "\xE2\xAB\xA7", 0 }, { "Barwed", "\xE2\x8C\x86", 0 }, { "Bcy", "\xD0\x91", 0 }, { "Because", "\xE2\x88\xB5", 0 }, { "Bernoullis", "\xE2\x84\xAC", 0 }, { "Beta", "\xCE\x92", 0 }, { "Bfr", "\xF0\x9D\x94\x85", 0 }, { "Bopf", "\xF0\x9D\x94\xB9", 0 }, { "Breve", "\xCB\x98", 0 }, { "Bscr", "\xE2\x84\xAC", 0 }, { "Bumpeq", "\xE2\x89\x8E", 0 }, { "CHcy", "\xD0\xA7", 0 }, { "COPY", "\xC2\xA9", 0 }, { "Cacute", "\xC4\x86", 0 }, { "Cap", "\xE2\x8B\x92", 0 }, { "CapitalDifferentialD", "\xE2\x85\x85", 0 }, { "Cayleys", "\xE2\x84\xAD", 0 }, { "Ccaron", "\xC4\x8C", 0 }, { "Ccedil", "\xC3\x87", 0 }, { "Ccirc", "\xC4\x88", 0 }, { "Cconint", "\xE2\x88\xB0", 0 }, { "Cdot", "\xC4\x8A", 0 }, { "Cedilla", "\xC2\xB8", 0 }, { "CenterDot", "\xC2\xB7", 0 }, { "Cfr", "\xE2\x84\xAD", 0 }, { "Chi", "\xCE\xA7", 0 }, { "CircleDot", "\xE2\x8A\x99", 0 }, { "CircleMinus", "\xE2\x8A\x96", 0 }, { "CirclePlus", "\xE2\x8A\x95", 0 }, { "CircleTimes", "\xE2\x8A\x97", 0 }, { "ClockwiseContourIntegral", "\xE2\x88\xB2", 0 }, { "CloseCurlyDoubleQuote", "\xE2\x80\x9D", 0 }, { "CloseCurlyQuote", "\xE2\x80\x99", 0 }, { "Colon", "\xE2\x88\xB7", 0 }, { "Colone", "\xE2\xA9\xB4", 0 }, { "Congruent", "\xE2\x89\xA1", 0 }, { "Conint", "\xE2\x88\xAF", 0 }, { "ContourIntegral", "\xE2\x88\xAE", 0 }, { "Copf", "\xE2\x84\x82", 0 }, { "Coproduct", "\xE2\x88\x90", 0 }, { "CounterClockwiseContourIntegral", "\xE2\x88\xB3", 0 }, { "Cross", "\xE2\xA8\xAF", 0 }, { "Cscr", "\xF0\x9D\x92\x9E", 0 }, { "Cup", "\xE2\x8B\x93", 0 }, { "CupCap", "\xE2\x89\x8D", 0 }, { "DD", "\xE2\x85\x85", 0 }, { "DDotrahd", "\xE2\xA4\x91", 0 }, { "DJcy", "\xD0\x82", 0 }, { "DScy", "\xD0\x85", 0 }, { "DZcy", "\xD0\x8F", 0 }, { "Dagger", "\xE2\x80\xA1", 0 }, { "Darr", "\xE2\x86\xA1", 0 }, { "Dashv", "\xE2\xAB\xA4", 0 }, { "Dcaron", "\xC4\x8E", 0 }, { "Dcy", "\xD0\x94", 0 }, { "Del", "\xE2\x88\x87", 0 }, { "Delta", "\xCE\x94", 0 }, { "Dfr", "\xF0\x9D\x94\x87", 0 }, { "DiacriticalAcute", "\xC2\xB4", 0 }, { "DiacriticalDot", "\xCB\x99", 0 }, { "DiacriticalDoubleAcute", "\xCB\x9D", 0 }, { "DiacriticalGrave", "\x60", 0 }, { "DiacriticalTilde", "\xCB\x9C", 0 }, { "Diamond", "\xE2\x8B\x84", 0 }, { "DifferentialD", "\xE2\x85\x86", 0 }, { "Dopf", "\xF0\x9D\x94\xBB", 0 }, { "Dot", "\xC2\xA8", 0 }, { "DotDot", "\xE2\x83\x9C", 0 }, { "DotEqual", "\xE2\x89\x90", 0 }, { "DoubleContourIntegral", "\xE2\x88\xAF", 0 }, { "DoubleDot", "\xC2\xA8", 0 }, { "DoubleDownArrow", "\xE2\x87\x93", 0 }, { "DoubleLeftArrow", "\xE2\x87\x90", 0 }, { "DoubleLeftRightArrow", "\xE2\x87\x94", 0 }, { "DoubleLeftTee", "\xE2\xAB\xA4", 0 }, { "DoubleLongLeftArrow", "\xE2\x9F\xB8", 0 }, { "DoubleLongLeftRightArrow", "\xE2\x9F\xBA", 0 }, { "DoubleLongRightArrow", "\xE2\x9F\xB9", 0 }, { "DoubleRightArrow", "\xE2\x87\x92", 0 }, { "DoubleRightTee", "\xE2\x8A\xA8", 0 }, { "DoubleUpArrow", "\xE2\x87\x91", 0 }, { "DoubleUpDownArrow", "\xE2\x87\x95", 0 }, { "DoubleVerticalBar", "\xE2\x88\xA5", 0 }, { "DownArrow", "\xE2\x86\x93", 0 }, { "DownArrowBar", "\xE2\xA4\x93", 0 }, { "DownArrowUpArrow", "\xE2\x87\xB5", 0 }, { "DownBreve", "\xCC\x91", 0 }, { "DownLeftRightVector", "\xE2\xA5\x90", 0 }, { "DownLeftTeeVector", "\xE2\xA5\x9E", 0 }, { "DownLeftVector", "\xE2\x86\xBD", 0 }, { "DownLeftVectorBar", "\xE2\xA5\x96", 0 }, { "DownRightTeeVector", "\xE2\xA5\x9F", 0 }, { "DownRightVector", "\xE2\x87\x81", 0 }, { "DownRightVectorBar", "\xE2\xA5\x97", 0 }, { "DownTee", "\xE2\x8A\xA4", 0 }, { "DownTeeArrow", "\xE2\x86\xA7", 0 }, { "Downarrow", "\xE2\x87\x93", 0 }, { "Dscr", "\xF0\x9D\x92\x9F", 0 }, { "Dstrok", "\xC4\x90", 0 }, { "ENG", "\xC5\x8A", 0 }, { "ETH", "\xC3\x90", 0 }, { "Eacute", "\xC3\x89", 0 }, { "Ecaron", "\xC4\x9A", 0 }, { "Ecirc", "\xC3\x8A", 0 }, { "Ecy", "\xD0\xAD", 0 }, { "Edot", "\xC4\x96", 0 }, { "Efr", "\xF0\x9D\x94\x88", 0 }, { "Egrave", "\xC3\x88", 0 }, { "Element", "\xE2\x88\x88", 0 }, { "Emacr", "\xC4\x92", 0 }, { "EmptySmallSquare", "\xE2\x97\xBB", 0 }, { "EmptyVerySmallSquare", "\xE2\x96\xAB", 0 }, { "Eogon", "\xC4\x98", 0 }, { "Eopf", "\xF0\x9D\x94\xBC", 0 }, { "Epsilon", "\xCE\x95", 0 }, { "Equal", "\xE2\xA9\xB5", 0 }, { "EqualTilde", "\xE2\x89\x82", 0 }, { "Equilibrium", "\xE2\x87\x8C", 0 }, { "Escr", "\xE2\x84\xB0", 0 }, { "Esim", "\xE2\xA9\xB3", 0 }, { "Eta", "\xCE\x97", 0 }, { "Euml", "\xC3\x8B", 0 }, { "Exists", "\xE2\x88\x83", 0 }, { "ExponentialE", "\xE2\x85\x87", 0 }, { "Fcy", "\xD0\xA4", 0 }, { "Ffr", "\xF0\x9D\x94\x89", 0 }, { "FilledSmallSquare", "\xE2\x97\xBC", 0 }, { "FilledVerySmallSquare", "\xE2\x96\xAA", 0 }, { "Fopf", "\xF0\x9D\x94\xBD", 0 }, { "ForAll", "\xE2\x88\x80", 0 }, { "Fouriertrf", "\xE2\x84\xB1", 0 }, { "Fscr", "\xE2\x84\xB1", 0 }, { "GJcy", "\xD0\x83", 0 }, { "GT", "\x3E", 0 }, { "Gamma", "\xCE\x93", 0 }, { "Gammad", "\xCF\x9C", 0 }, { "Gbreve", "\xC4\x9E", 0 }, { "Gcedil", "\xC4\xA2", 0 }, { "Gcirc", "\xC4\x9C", 0 }, { "Gcy", "\xD0\x93", 0 }, { "Gdot", "\xC4\xA0", 0 }, { "Gfr", "\xF0\x9D\x94\x8A", 0 }, { "Gg", "\xE2\x8B\x99", 0 }, { "Gopf", "\xF0\x9D\x94\xBE", 0 }, { "GreaterEqual", "\xE2\x89\xA5", 0 }, { "GreaterEqualLess", "\xE2\x8B\x9B", 0 }, { "GreaterFullEqual", "\xE2\x89\xA7", 0 }, { "GreaterGreater", "\xE2\xAA\xA2", 0 }, { "GreaterLess", "\xE2\x89\xB7", 0 }, { "GreaterSlantEqual", "\xE2\xA9\xBE", 0 }, { "GreaterTilde", "\xE2\x89\xB3", 0 }, { "Gscr", "\xF0\x9D\x92\xA2", 0 }, { "Gt", "\xE2\x89\xAB", 0 }, { "HARDcy", "\xD0\xAA", 0 }, { "Hacek", "\xCB\x87", 0 }, { "Hat", "\x5E", 0 }, { "Hcirc", "\xC4\xA4", 0 }, { "Hfr", "\xE2\x84\x8C", 0 }, { "HilbertSpace", "\xE2\x84\x8B", 0 }, { "Hopf", "\xE2\x84\x8D", 0 }, { "HorizontalLine", "\xE2\x94\x80", 0 }, { "Hscr", "\xE2\x84\x8B", 0 }, { "Hstrok", "\xC4\xA6", 0 }, { "HumpDownHump", "\xE2\x89\x8E", 0 }, { "HumpEqual", "\xE2\x89\x8F", 0 }, { "IEcy", "\xD0\x95", 0 }, { "IJlig", "\xC4\xB2", 0 }, { "IOcy", "\xD0\x81", 0 }, { "Iacute", "\xC3\x8D", 0 }, { "Icirc", "\xC3\x8E", 0 }, { "Icy", "\xD0\x98", 0 }, { "Idot", "\xC4\xB0", 0 }, { "Ifr", "\xE2\x84\x91", 0 }, { "Igrave", "\xC3\x8C", 0 }, { "Im", "\xE2\x84\x91", 0 }, { "Imacr", "\xC4\xAA", 0 }, { "ImaginaryI", "\xE2\x85\x88", 0 }, { "Implies", "\xE2\x87\x92", 0 }, { "Int", "\xE2\x88\xAC", 0 }, { "Integral", "\xE2\x88\xAB", 0 }, { "Intersection", "\xE2\x8B\x82", 0 }, { "InvisibleComma", "\xE2\x81\xA3", 0 }, { "InvisibleTimes", "\xE2\x81\xA2", 0 }, { "Iogon", "\xC4\xAE", 0 }, { "Iopf", "\xF0\x9D\x95\x80", 0 }, { "Iota", "\xCE\x99", 0 }, { "Iscr", "\xE2\x84\x90", 0 }, { "Itilde", "\xC4\xA8", 0 }, { "Iukcy", "\xD0\x86", 0 }, { "Iuml", "\xC3\x8F", 0 }, { "Jcirc", "\xC4\xB4", 0 }, { "Jcy", "\xD0\x99", 0 }, { "Jfr", "\xF0\x9D\x94\x8D", 0 }, { "Jopf", "\xF0\x9D\x95\x81", 0 }, { "Jscr", "\xF0\x9D\x92\xA5", 0 }, { "Jsercy", "\xD0\x88", 0 }, { "Jukcy", "\xD0\x84", 0 }, { "KHcy", "\xD0\xA5", 0 }, { "KJcy", "\xD0\x8C", 0 }, { "Kappa", "\xCE\x9A", 0 }, { "Kcedil", "\xC4\xB6", 0 }, { "Kcy", "\xD0\x9A", 0 }, { "Kfr", "\xF0\x9D\x94\x8E", 0 }, { "Kopf", "\xF0\x9D\x95\x82", 0 }, { "Kscr", "\xF0\x9D\x92\xA6", 0 }, { "LJcy", "\xD0\x89", 0 }, { "LT", "\x3C", 0 }, { "Lacute", "\xC4\xB9", 0 }, { "Lambda", "\xCE\x9B", 0 }, { "Lang", "\xE2\x9F\xAA", 0 }, { "Laplacetrf", "\xE2\x84\x92", 0 }, { "Larr", "\xE2\x86\x9E", 0 }, { "Lcaron", "\xC4\xBD", 0 }, { "Lcedil", "\xC4\xBB", 0 }, { "Lcy", "\xD0\x9B", 0 }, { "LeftAngleBracket", "\xE2\x9F\xA8", 0 }, { "LeftArrow", "\xE2\x86\x90", 0 }, { "LeftArrowBar", "\xE2\x87\xA4", 0 }, { "LeftArrowRightArrow", "\xE2\x87\x86", 0 }, { "LeftCeiling", "\xE2\x8C\x88", 0 }, { "LeftDoubleBracket", "\xE2\x9F\xA6", 0 }, { "LeftDownTeeVector", "\xE2\xA5\xA1", 0 }, { "LeftDownVector", "\xE2\x87\x83", 0 }, { "LeftDownVectorBar", "\xE2\xA5\x99", 0 }, { "LeftFloor", "\xE2\x8C\x8A", 0 }, { "LeftRightArrow", "\xE2\x86\x94", 0 }, { "LeftRightVector", "\xE2\xA5\x8E", 0 }, { "LeftTee", "\xE2\x8A\xA3", 0 }, { "LeftTeeArrow", "\xE2\x86\xA4", 0 }, { "LeftTeeVector", "\xE2\xA5\x9A", 0 }, { "LeftTriangle", "\xE2\x8A\xB2", 0 }, { "LeftTriangleBar", "\xE2\xA7\x8F", 0 }, { "LeftTriangleEqual", "\xE2\x8A\xB4", 0 }, { "LeftUpDownVector", "\xE2\xA5\x91", 0 }, { "LeftUpTeeVector", "\xE2\xA5\xA0", 0 }, { "LeftUpVector", "\xE2\x86\xBF", 0 }, { "LeftUpVectorBar", "\xE2\xA5\x98", 0 }, { "LeftVector", "\xE2\x86\xBC", 0 }, { "LeftVectorBar", "\xE2\xA5\x92", 0 }, { "Leftarrow", "\xE2\x87\x90", 0 }, { "Leftrightarrow", "\xE2\x87\x94", 0 }, { "LessEqualGreater", "\xE2\x8B\x9A", 0 }, { "LessFullEqual", "\xE2\x89\xA6", 0 }, { "LessGreater", "\xE2\x89\xB6", 0 }, { "LessLess", "\xE2\xAA\xA1", 0 }, { "LessSlantEqual", "\xE2\xA9\xBD", 0 }, { "LessTilde", "\xE2\x89\xB2", 0 }, { "Lfr", "\xF0\x9D\x94\x8F", 0 }, { "Ll", "\xE2\x8B\x98", 0 }, { "Lleftarrow", "\xE2\x87\x9A", 0 }, { "Lmidot", "\xC4\xBF", 0 }, { "LongLeftArrow", "\xE2\x9F\xB5", 0 }, { "LongLeftRightArrow", "\xE2\x9F\xB7", 0 }, { "LongRightArrow", "\xE2\x9F\xB6", 0 }, { "Longleftarrow", "\xE2\x9F\xB8", 0 }, { "Longleftrightarrow", "\xE2\x9F\xBA", 0 }, { "Longrightarrow", "\xE2\x9F\xB9", 0 }, { "Lopf", "\xF0\x9D\x95\x83", 0 }, { "LowerLeftArrow", "\xE2\x86\x99", 0 }, { "LowerRightArrow", "\xE2\x86\x98", 0 }, { "Lscr", "\xE2\x84\x92", 0 }, { "Lsh", "\xE2\x86\xB0", 0 }, { "Lstrok", "\xC5\x81", 0 }, { "Lt", "\xE2\x89\xAA", 0 }, { "Map", "\xE2\xA4\x85", 0 }, { "Mcy", "\xD0\x9C", 0 }, { "MediumSpace", "\xE2\x81\x9F", 0 }, { "Mellintrf", "\xE2\x84\xB3", 0 }, { "Mfr", "\xF0\x9D\x94\x90", 0 }, { "MinusPlus", "\xE2\x88\x93", 0 }, { "Mopf", "\xF0\x9D\x95\x84", 0 }, { "Mscr", "\xE2\x84\xB3", 0 }, { "Mu", "\xCE\x9C", 0 }, { "NJcy", "\xD0\x8A", 0 }, { "Nacute", "\xC5\x83", 0 }, { "Ncaron", "\xC5\x87", 0 }, { "Ncedil", "\xC5\x85", 0 }, { "Ncy", "\xD0\x9D", 0 }, { "NegativeMediumSpace", "\xE2\x80\x8B", 0 }, { "NegativeThickSpace", "\xE2\x80\x8B", 0 }, { "NegativeThinSpace", "\xE2\x80\x8B", 0 }, { "NegativeVeryThinSpace", "\xE2\x80\x8B", 0 }, { "NestedGreaterGreater", "\xE2\x89\xAB", 0 }, { "NestedLessLess", "\xE2\x89\xAA", 0 }, { "NewLine", "\x0A", 0 }, { "Nfr", "\xF0\x9D\x94\x91", 0 }, { "NoBreak", "\xE2\x81\xA0", 0 }, { "NonBreakingSpace", "\xC2\xA0", 0 }, { "Nopf", "\xE2\x84\x95", 0 }, { "Not", "\xE2\xAB\xAC", 0 }, { "NotCongruent", "\xE2\x89\xA2", 0 }, { "NotCupCap", "\xE2\x89\xAD", 0 }, { "NotDoubleVerticalBar", "\xE2\x88\xA6", 0 }, { "NotElement", "\xE2\x88\x89", 0 }, { "NotEqual", "\xE2\x89\xA0", 0 }, { "NotEqualTilde", "\xE2\x89\x82\xCC\xB8", 0 }, { "NotExists", "\xE2\x88\x84", 0 }, { "NotGreater", "\xE2\x89\xAF", 0 }, { "NotGreaterEqual", "\xE2\x89\xB1", 0 }, { "NotGreaterFullEqual", "\xE2\x89\xA7\xCC\xB8", 0 }, { "NotGreaterGreater", "\xE2\x89\xAB\xCC\xB8", 0 }, { "NotGreaterLess", "\xE2\x89\xB9", 0 }, { "NotGreaterSlantEqual", "\xE2\xA9\xBE\xCC\xB8", 0 }, { "NotGreaterTilde", "\xE2\x89\xB5", 0 }, { "NotHumpDownHump", "\xE2\x89\x8E\xCC\xB8", 0 }, { "NotHumpEqual", "\xE2\x89\x8F\xCC\xB8", 0 }, { "NotLeftTriangle", "\xE2\x8B\xAA", 0 }, { "NotLeftTriangleBar", "\xE2\xA7\x8F\xCC\xB8", 0 }, { "NotLeftTriangleEqual", "\xE2\x8B\xAC", 0 }, { "NotLess", "\xE2\x89\xAE", 0 }, { "NotLessEqual", "\xE2\x89\xB0", 0 }, { "NotLessGreater", "\xE2\x89\xB8", 0 }, { "NotLessLess", "\xE2\x89\xAA\xCC\xB8", 0 }, { "NotLessSlantEqual", "\xE2\xA9\xBD\xCC\xB8", 0 }, { "NotLessTilde", "\xE2\x89\xB4", 0 }, { "NotNestedGreaterGreater", "\xE2\xAA\xA2\xCC\xB8", 0 }, { "NotNestedLessLess", "\xE2\xAA\xA1\xCC\xB8", 0 }, { "NotPrecedes", "\xE2\x8A\x80", 0 }, { "NotPrecedesEqual", "\xE2\xAA\xAF\xCC\xB8", 0 }, { "NotPrecedesSlantEqual", "\xE2\x8B\xA0", 0 }, { "NotReverseElement", "\xE2\x88\x8C", 0 }, { "NotRightTriangle", "\xE2\x8B\xAB", 0 }, { "NotRightTriangleBar", "\xE2\xA7\x90\xCC\xB8", 0 }, { "NotRightTriangleEqual", "\xE2\x8B\xAD", 0 }, { "NotSquareSubset", "\xE2\x8A\x8F\xCC\xB8", 0 }, { "NotSquareSubsetEqual", "\xE2\x8B\xA2", 0 }, { "NotSquareSuperset", "\xE2\x8A\x90\xCC\xB8", 0 }, { "NotSquareSupersetEqual", "\xE2\x8B\xA3", 0 }, { "NotSubset", "\xE2\x8A\x82\xE2\x83\x92", 0 }, { "NotSubsetEqual", "\xE2\x8A\x88", 0 }, { "NotSucceeds", "\xE2\x8A\x81", 0 }, { "NotSucceedsEqual", "\xE2\xAA\xB0\xCC\xB8", 0 }, { "NotSucceedsSlantEqual", "\xE2\x8B\xA1", 0 }, { "NotSucceedsTilde", "\xE2\x89\xBF\xCC\xB8", 0 }, { "NotSuperset", "\xE2\x8A\x83\xE2\x83\x92", 0 }, { "NotSupersetEqual", "\xE2\x8A\x89", 0 }, { "NotTilde", "\xE2\x89\x81", 0 }, { "NotTildeEqual", "\xE2\x89\x84", 0 }, { "NotTildeFullEqual", "\xE2\x89\x87", 0 }, { "NotTildeTilde", "\xE2\x89\x89", 0 }, { "NotVerticalBar", "\xE2\x88\xA4", 0 }, { "Nscr", "\xF0\x9D\x92\xA9", 0 }, { "Ntilde", "\xC3\x91", 0 }, { "Nu", "\xCE\x9D", 0 }, { "OElig", "\xC5\x92", 0 }, { "Oacute", "\xC3\x93", 0 }, { "Ocirc", "\xC3\x94", 0 }, { "Ocy", "\xD0\x9E", 0 }, { "Odblac", "\xC5\x90", 0 }, { "Ofr", "\xF0\x9D\x94\x92", 0 }, { "Ograve", "\xC3\x92", 0 }, { "Omacr", "\xC5\x8C", 0 }, { "Omega", "\xCE\xA9", 0 }, { "Omicron", "\xCE\x9F", 0 }, { "Oopf", "\xF0\x9D\x95\x86", 0 }, { "OpenCurlyDoubleQuote", "\xE2\x80\x9C", 0 }, { "OpenCurlyQuote", "\xE2\x80\x98", 0 }, { "Or", "\xE2\xA9\x94", 0 }, { "Oscr", "\xF0\x9D\x92\xAA", 0 }, { "Oslash", "\xC3\x98", 0 }, { "Otilde", "\xC3\x95", 0 }, { "Otimes", "\xE2\xA8\xB7", 0 }, { "Ouml", "\xC3\x96", 0 }, { "OverBar", "\xE2\x80\xBE", 0 }, { "OverBrace", "\xE2\x8F\x9E", 0 }, { "OverBracket", "\xE2\x8E\xB4", 0 }, { "OverParenthesis", "\xE2\x8F\x9C", 0 }, { "PartialD", "\xE2\x88\x82", 0 }, { "Pcy", "\xD0\x9F", 0 }, { "Pfr", "\xF0\x9D\x94\x93", 0 }, { "Phi", "\xCE\xA6", 0 }, { "Pi", "\xCE\xA0", 0 }, { "PlusMinus", "\xC2\xB1", 0 }, { "Poincareplane", "\xE2\x84\x8C", 0 }, { "Popf", "\xE2\x84\x99", 0 }, { "Pr", "\xE2\xAA\xBB", 0 }, { "Precedes", "\xE2\x89\xBA", 0 }, { "PrecedesEqual", "\xE2\xAA\xAF", 0 }, { "PrecedesSlantEqual", "\xE2\x89\xBC", 0 }, { "PrecedesTilde", "\xE2\x89\xBE", 0 }, { "Prime", "\xE2\x80\xB3", 0 }, { "Product", "\xE2\x88\x8F", 0 }, { "Proportion", "\xE2\x88\xB7", 0 }, { "Proportional", "\xE2\x88\x9D", 0 }, { "Pscr", "\xF0\x9D\x92\xAB", 0 }, { "Psi", "\xCE\xA8", 0 }, { "QUOT", "\x22", 0 }, { "Qfr", "\xF0\x9D\x94\x94", 0 }, { "Qopf", "\xE2\x84\x9A", 0 }, { "Qscr", "\xF0\x9D\x92\xAC", 0 }, { "RBarr", "\xE2\xA4\x90", 0 }, { "REG", "\xC2\xAE", 0 }, { "Racute", "\xC5\x94", 0 }, { "Rang", "\xE2\x9F\xAB", 0 }, { "Rarr", "\xE2\x86\xA0", 0 }, { "Rarrtl", "\xE2\xA4\x96", 0 }, { "Rcaron", "\xC5\x98", 0 }, { "Rcedil", "\xC5\x96", 0 }, { "Rcy", "\xD0\xA0", 0 }, { "Re", "\xE2\x84\x9C", 0 }, { "ReverseElement", "\xE2\x88\x8B", 0 }, { "ReverseEquilibrium", "\xE2\x87\x8B", 0 }, { "ReverseUpEquilibrium", "\xE2\xA5\xAF", 0 }, { "Rfr", "\xE2\x84\x9C", 0 }, { "Rho", "\xCE\xA1", 0 }, { "RightAngleBracket", "\xE2\x9F\xA9", 0 }, { "RightArrow", "\xE2\x86\x92", 0 }, { "RightArrowBar", "\xE2\x87\xA5", 0 }, { "RightArrowLeftArrow", "\xE2\x87\x84", 0 }, { "RightCeiling", "\xE2\x8C\x89", 0 }, { "RightDoubleBracket", "\xE2\x9F\xA7", 0 }, { "RightDownTeeVector", "\xE2\xA5\x9D", 0 }, { "RightDownVector", "\xE2\x87\x82", 0 }, { "RightDownVectorBar", "\xE2\xA5\x95", 0 }, { "RightFloor", "\xE2\x8C\x8B", 0 }, { "RightTee", "\xE2\x8A\xA2", 0 }, { "RightTeeArrow", "\xE2\x86\xA6", 0 }, { "RightTeeVector", "\xE2\xA5\x9B", 0 }, { "RightTriangle", "\xE2\x8A\xB3", 0 }, { "RightTriangleBar", "\xE2\xA7\x90", 0 }, { "RightTriangleEqual", "\xE2\x8A\xB5", 0 }, { "RightUpDownVector", "\xE2\xA5\x8F", 0 }, { "RightUpTeeVector", "\xE2\xA5\x9C", 0 }, { "RightUpVector", "\xE2\x86\xBE", 0 }, { "RightUpVectorBar", "\xE2\xA5\x94", 0 }, { "RightVector", "\xE2\x87\x80", 0 }, { "RightVectorBar", "\xE2\xA5\x93", 0 }, { "Rightarrow", "\xE2\x87\x92", 0 }, { "Ropf", "\xE2\x84\x9D", 0 }, { "RoundImplies", "\xE2\xA5\xB0", 0 }, { "Rrightarrow", "\xE2\x87\x9B", 0 }, { "Rscr", "\xE2\x84\x9B", 0 }, { "Rsh", "\xE2\x86\xB1", 0 }, { "RuleDelayed", "\xE2\xA7\xB4", 0 }, { "SHCHcy", "\xD0\xA9", 0 }, { "SHcy", "\xD0\xA8", 0 }, { "SOFTcy", "\xD0\xAC", 0 }, { "Sacute", "\xC5\x9A", 0 }, { "Sc", "\xE2\xAA\xBC", 0 }, { "Scaron", "\xC5\xA0", 0 }, { "Scedil", "\xC5\x9E", 0 }, { "Scirc", "\xC5\x9C", 0 }, { "Scy", "\xD0\xA1", 0 }, { "Sfr", "\xF0\x9D\x94\x96", 0 }, { "ShortDownArrow", "\xE2\x86\x93", 0 }, { "ShortLeftArrow", "\xE2\x86\x90", 0 }, { "ShortRightArrow", "\xE2\x86\x92", 0 }, { "ShortUpArrow", "\xE2\x86\x91", 0 }, { "Sigma", "\xCE\xA3", 0 }, { "SmallCircle", "\xE2\x88\x98", 0 }, { "Sopf", "\xF0\x9D\x95\x8A", 0 }, { "Sqrt", "\xE2\x88\x9A", 0 }, { "Square", "\xE2\x96\xA1", 0 }, { "SquareIntersection", "\xE2\x8A\x93", 0 }, { "SquareSubset", "\xE2\x8A\x8F", 0 }, { "SquareSubsetEqual", "\xE2\x8A\x91", 0 }, { "SquareSuperset", "\xE2\x8A\x90", 0 }, { "SquareSupersetEqual", "\xE2\x8A\x92", 0 }, { "SquareUnion", "\xE2\x8A\x94", 0 }, { "Sscr", "\xF0\x9D\x92\xAE", 0 }, { "Star", "\xE2\x8B\x86", 0 }, { "Sub", "\xE2\x8B\x90", 0 }, { "Subset", "\xE2\x8B\x90", 0 }, { "SubsetEqual", "\xE2\x8A\x86", 0 }, { "Succeeds", "\xE2\x89\xBB", 0 }, { "SucceedsEqual", "\xE2\xAA\xB0", 0 }, { "SucceedsSlantEqual", "\xE2\x89\xBD", 0 }, { "SucceedsTilde", "\xE2\x89\xBF", 0 }, { "SuchThat", "\xE2\x88\x8B", 0 }, { "Sum", "\xE2\x88\x91", 0 }, { "Sup", "\xE2\x8B\x91", 0 }, { "Superset", "\xE2\x8A\x83", 0 }, { "SupersetEqual", "\xE2\x8A\x87", 0 }, { "Supset", "\xE2\x8B\x91", 0 }, { "THORN", "\xC3\x9E", 0 }, { "TRADE", "\xE2\x84\xA2", 0 }, { "TSHcy", "\xD0\x8B", 0 }, { "TScy", "\xD0\xA6", 0 }, { "Tab", "\x09", 0 }, { "Tau", "\xCE\xA4", 0 }, { "Tcaron", "\xC5\xA4", 0 }, { "Tcedil", "\xC5\xA2", 0 }, { "Tcy", "\xD0\xA2", 0 }, { "Tfr", "\xF0\x9D\x94\x97", 0 }, { "Therefore", "\xE2\x88\xB4", 0 }, { "Theta", "\xCE\x98", 0 }, { "ThickSpace", "\xE2\x81\x9F\xE2\x80\x8A", 0 }, { "ThinSpace", "\xE2\x80\x89", 0 }, { "Tilde", "\xE2\x88\xBC", 0 }, { "TildeEqual", "\xE2\x89\x83", 0 }, { "TildeFullEqual", "\xE2\x89\x85", 0 }, { "TildeTilde", "\xE2\x89\x88", 0 }, { "Topf", "\xF0\x9D\x95\x8B", 0 }, { "TripleDot", "\xE2\x83\x9B", 0 }, { "Tscr", "\xF0\x9D\x92\xAF", 0 }, { "Tstrok", "\xC5\xA6", 0 }, { "Uacute", "\xC3\x9A", 0 }, { "Uarr", "\xE2\x86\x9F", 0 }, { "Uarrocir", "\xE2\xA5\x89", 0 }, { "Ubrcy", "\xD0\x8E", 0 }, { "Ubreve", "\xC5\xAC", 0 }, { "Ucirc", "\xC3\x9B", 0 }, { "Ucy", "\xD0\xA3", 0 }, { "Udblac", "\xC5\xB0", 0 }, { "Ufr", "\xF0\x9D\x94\x98", 0 }, { "Ugrave", "\xC3\x99", 0 }, { "Umacr", "\xC5\xAA", 0 }, { "UnderBar", "\x5F", 0 }, { "UnderBrace", "\xE2\x8F\x9F", 0 }, { "UnderBracket", "\xE2\x8E\xB5", 0 }, { "UnderParenthesis", "\xE2\x8F\x9D", 0 }, { "Union", "\xE2\x8B\x83", 0 }, { "UnionPlus", "\xE2\x8A\x8E", 0 }, { "Uogon", "\xC5\xB2", 0 }, { "Uopf", "\xF0\x9D\x95\x8C", 0 }, { "UpArrow", "\xE2\x86\x91", 0 }, { "UpArrowBar", "\xE2\xA4\x92", 0 }, { "UpArrowDownArrow", "\xE2\x87\x85", 0 }, { "UpDownArrow", "\xE2\x86\x95", 0 }, { "UpEquilibrium", "\xE2\xA5\xAE", 0 }, { "UpTee", "\xE2\x8A\xA5", 0 }, { "UpTeeArrow", "\xE2\x86\xA5", 0 }, { "Uparrow", "\xE2\x87\x91", 0 }, { "Updownarrow", "\xE2\x87\x95", 0 }, { "UpperLeftArrow", "\xE2\x86\x96", 0 }, { "UpperRightArrow", "\xE2\x86\x97", 0 }, { "Upsi", "\xCF\x92", 0 }, { "Upsilon", "\xCE\xA5", 0 }, { "Uring", "\xC5\xAE", 0 }, { "Uscr", "\xF0\x9D\x92\xB0", 0 }, { "Utilde", "\xC5\xA8", 0 }, { "Uuml", "\xC3\x9C", 0 }, { "VDash", "\xE2\x8A\xAB", 0 }, { "Vbar", "\xE2\xAB\xAB", 0 }, { "Vcy", "\xD0\x92", 0 }, { "Vdash", "\xE2\x8A\xA9", 0 }, { "Vdashl", "\xE2\xAB\xA6", 0 }, { "Vee", "\xE2\x8B\x81", 0 }, { "Verbar", "\xE2\x80\x96", 0 }, { "Vert", "\xE2\x80\x96", 0 }, { "VerticalBar", "\xE2\x88\xA3", 0 }, { "VerticalLine", "\x7C", 0 }, { "VerticalSeparator", "\xE2\x9D\x98", 0 }, { "VerticalTilde", "\xE2\x89\x80", 0 }, { "VeryThinSpace", "\xE2\x80\x8A", 0 }, { "Vfr", "\xF0\x9D\x94\x99", 0 }, { "Vopf", "\xF0\x9D\x95\x8D", 0 }, { "Vscr", "\xF0\x9D\x92\xB1", 0 }, { "Vvdash", "\xE2\x8A\xAA", 0 }, { "Wcirc", "\xC5\xB4", 0 }, { "Wedge", "\xE2\x8B\x80", 0 }, { "Wfr", "\xF0\x9D\x94\x9A", 0 }, { "Wopf", "\xF0\x9D\x95\x8E", 0 }, { "Wscr", "\xF0\x9D\x92\xB2", 0 }, { "Xfr", "\xF0\x9D\x94\x9B", 0 }, { "Xi", "\xCE\x9E", 0 }, { "Xopf", "\xF0\x9D\x95\x8F", 0 }, { "Xscr", "\xF0\x9D\x92\xB3", 0 }, { "YAcy", "\xD0\xAF", 0 }, { "YIcy", "\xD0\x87", 0 }, { "YUcy", "\xD0\xAE", 0 }, { "Yacute", "\xC3\x9D", 0 }, { "Ycirc", "\xC5\xB6", 0 }, { "Ycy", "\xD0\xAB", 0 }, { "Yfr", "\xF0\x9D\x94\x9C", 0 }, { "Yopf", "\xF0\x9D\x95\x90", 0 }, { "Yscr", "\xF0\x9D\x92\xB4", 0 }, { "Yuml", "\xC5\xB8", 0 }, { "ZHcy", "\xD0\x96", 0 }, { "Zacute", "\xC5\xB9", 0 }, { "Zcaron", "\xC5\xBD", 0 }, { "Zcy", "\xD0\x97", 0 }, { "Zdot", "\xC5\xBB", 0 }, { "ZeroWidthSpace", "\xE2\x80\x8B", 0 }, { "Zeta", "\xCE\x96", 0 }, { "Zfr", "\xE2\x84\xA8", 0 }, { "Zopf", "\xE2\x84\xA4", 0 }, { "Zscr", "\xF0\x9D\x92\xB5", 0 }, { "aacute", "\xC3\xA1", 0 }, { "abreve", "\xC4\x83", 0 }, { "ac", "\xE2\x88\xBE", 0 }, { "acE", "\xE2\x88\xBE\xCC\xB3", 0 }, { "acd", "\xE2\x88\xBF", 0 }, { "acirc", "\xC3\xA2", 0 }, { "acute", "\xC2\xB4", 0 }, { "acy", "\xD0\xB0", 0 }, { "aelig", "\xC3\xA6", 0 }, { "af", "\xE2\x81\xA1", 0 }, { "afr", "\xF0\x9D\x94\x9E", 0 }, { "agrave", "\xC3\xA0", 0 }, { "alefsym", "\xE2\x84\xB5", 0 }, { "aleph", "\xE2\x84\xB5", 0 }, { "alpha", "\xCE\xB1", 0 }, { "amacr", "\xC4\x81", 0 }, { "amalg", "\xE2\xA8\xBF", 0 }, { "amp", "\x26", 0 }, { "and", "\xE2\x88\xA7", 0 }, { "andand", "\xE2\xA9\x95", 0 }, { "andd", "\xE2\xA9\x9C", 0 }, { "andslope", "\xE2\xA9\x98", 0 }, { "andv", "\xE2\xA9\x9A", 0 }, { "ang", "\xE2\x88\xA0", 0 }, { "ange", "\xE2\xA6\xA4", 0 }, { "angle", "\xE2\x88\xA0", 0 }, { "angmsd", "\xE2\x88\xA1", 0 }, { "angmsdaa", "\xE2\xA6\xA8", 0 }, { "angmsdab", "\xE2\xA6\xA9", 0 }, { "angmsdac", "\xE2\xA6\xAA", 0 }, { "angmsdad", "\xE2\xA6\xAB", 0 }, { "angmsdae", "\xE2\xA6\xAC", 0 }, { "angmsdaf", "\xE2\xA6\xAD", 0 }, { "angmsdag", "\xE2\xA6\xAE", 0 }, { "angmsdah", "\xE2\xA6\xAF", 0 }, { "angrt", "\xE2\x88\x9F", 0 }, { "angrtvb", "\xE2\x8A\xBE", 0 }, { "angrtvbd", "\xE2\xA6\x9D", 0 }, { "angsph", "\xE2\x88\xA2", 0 }, { "angst", "\xC3\x85", 0 }, { "angzarr", "\xE2\x8D\xBC", 0 }, { "aogon", "\xC4\x85", 0 }, { "aopf", "\xF0\x9D\x95\x92", 0 }, { "ap", "\xE2\x89\x88", 0 }, { "apE", "\xE2\xA9\xB0", 0 }, { "apacir", "\xE2\xA9\xAF", 0 }, { "ape", "\xE2\x89\x8A", 0 }, { "apid", "\xE2\x89\x8B", 0 }, { "apos", "\x27", 0 }, { "approx", "\xE2\x89\x88", 0 }, { "approxeq", "\xE2\x89\x8A", 0 }, { "aring", "\xC3\xA5", 0 }, { "ascr", "\xF0\x9D\x92\xB6", 0 }, { "ast", "\x2A", 0 }, { "asymp", "\xE2\x89\x88", 0 }, { "asympeq", "\xE2\x89\x8D", 0 }, { "atilde", "\xC3\xA3", 0 }, { "auml", "\xC3\xA4", 0 }, { "awconint", "\xE2\x88\xB3", 0 }, { "awint", "\xE2\xA8\x91", 0 }, { "bNot", "\xE2\xAB\xAD", 0 }, { "backcong", "\xE2\x89\x8C", 0 }, { "backepsilon", "\xCF\xB6", 0 }, { "backprime", "\xE2\x80\xB5", 0 }, { "backsim", "\xE2\x88\xBD", 0 }, { "backsimeq", "\xE2\x8B\x8D", 0 }, { "barvee", "\xE2\x8A\xBD", 0 }, { "barwed", "\xE2\x8C\x85", 0 }, { "barwedge", "\xE2\x8C\x85", 0 }, { "bbrk", "\xE2\x8E\xB5", 0 }, { "bbrktbrk", "\xE2\x8E\xB6", 0 }, { "bcong", "\xE2\x89\x8C", 0 }, { "bcy", "\xD0\xB1", 0 }, { "bdquo", "\xE2\x80\x9E", 0 }, { "becaus", "\xE2\x88\xB5", 0 }, { "because", "\xE2\x88\xB5", 0 }, { "bemptyv", "\xE2\xA6\xB0", 0 }, { "bepsi", "\xCF\xB6", 0 }, { "bernou", "\xE2\x84\xAC", 0 }, { "beta", "\xCE\xB2", 0 }, { "beth", "\xE2\x84\xB6", 0 }, { "between", "\xE2\x89\xAC", 0 }, { "bfr", "\xF0\x9D\x94\x9F", 0 }, { "bigcap", "\xE2\x8B\x82", 0 }, { "bigcirc", "\xE2\x97\xAF", 0 }, { "bigcup", "\xE2\x8B\x83", 0 }, { "bigodot", "\xE2\xA8\x80", 0 }, { "bigoplus", "\xE2\xA8\x81", 0 }, { "bigotimes", "\xE2\xA8\x82", 0 }, { "bigsqcup", "\xE2\xA8\x86", 0 }, { "bigstar", "\xE2\x98\x85", 0 }, { "bigtriangledown", "\xE2\x96\xBD", 0 }, { "bigtriangleup", "\xE2\x96\xB3", 0 }, { "biguplus", "\xE2\xA8\x84", 0 }, { "bigvee", "\xE2\x8B\x81", 0 }, { "bigwedge", "\xE2\x8B\x80", 0 }, { "bkarow", "\xE2\xA4\x8D", 0 }, { "blacklozenge", "\xE2\xA7\xAB", 0 }, { "blacksquare", "\xE2\x96\xAA", 0 }, { "blacktriangle", "\xE2\x96\xB4", 0 }, { "blacktriangledown", "\xE2\x96\xBE", 0 }, { "blacktriangleleft", "\xE2\x97\x82", 0 }, { "blacktriangleright", "\xE2\x96\xB8", 0 }, { "blank", "\xE2\x90\xA3", 0 }, { "blk12", "\xE2\x96\x92", 0 }, { "blk14", "\xE2\x96\x91", 0 }, { "blk34", "\xE2\x96\x93", 0 }, { "block", "\xE2\x96\x88", 0 }, { "bne", "\x3D\xE2\x83\xA5", 0 }, { "bnequiv", "\xE2\x89\xA1\xE2\x83\xA5", 0 }, { "bnot", "\xE2\x8C\x90", 0 }, { "bopf", "\xF0\x9D\x95\x93", 0 }, { "bot", "\xE2\x8A\xA5", 0 }, { "bottom", "\xE2\x8A\xA5", 0 }, { "bowtie", "\xE2\x8B\x88", 0 }, { "boxDL", "\xE2\x95\x97", 0 }, { "boxDR", "\xE2\x95\x94", 0 }, { "boxDl", "\xE2\x95\x96", 0 }, { "boxDr", "\xE2\x95\x93", 0 }, { "boxH", "\xE2\x95\x90", 0 }, { "boxHD", "\xE2\x95\xA6", 0 }, { "boxHU", "\xE2\x95\xA9", 0 }, { "boxHd", "\xE2\x95\xA4", 0 }, { "boxHu", "\xE2\x95\xA7", 0 }, { "boxUL", "\xE2\x95\x9D", 0 }, { "boxUR", "\xE2\x95\x9A", 0 }, { "boxUl", "\xE2\x95\x9C", 0 }, { "boxUr", "\xE2\x95\x99", 0 }, { "boxV", "\xE2\x95\x91", 0 }, { "boxVH", "\xE2\x95\xAC", 0 }, { "boxVL", "\xE2\x95\xA3", 0 }, { "boxVR", "\xE2\x95\xA0", 0 }, { "boxVh", "\xE2\x95\xAB", 0 }, { "boxVl", "\xE2\x95\xA2", 0 }, { "boxVr", "\xE2\x95\x9F", 0 }, { "boxbox", "\xE2\xA7\x89", 0 }, { "boxdL", "\xE2\x95\x95", 0 }, { "boxdR", "\xE2\x95\x92", 0 }, { "boxdl", "\xE2\x94\x90", 0 }, { "boxdr", "\xE2\x94\x8C", 0 }, { "boxh", "\xE2\x94\x80", 0 }, { "boxhD", "\xE2\x95\xA5", 0 }, { "boxhU", "\xE2\x95\xA8", 0 }, { "boxhd", "\xE2\x94\xAC", 0 }, { "boxhu", "\xE2\x94\xB4", 0 }, { "boxminus", "\xE2\x8A\x9F", 0 }, { "boxplus", "\xE2\x8A\x9E", 0 }, { "boxtimes", "\xE2\x8A\xA0", 0 }, { "boxuL", "\xE2\x95\x9B", 0 }, { "boxuR", "\xE2\x95\x98", 0 }, { "boxul", "\xE2\x94\x98", 0 }, { "boxur", "\xE2\x94\x94", 0 }, { "boxv", "\xE2\x94\x82", 0 }, { "boxvH", "\xE2\x95\xAA", 0 }, { "boxvL", "\xE2\x95\xA1", 0 }, { "boxvR", "\xE2\x95\x9E", 0 }, { "boxvh", "\xE2\x94\xBC", 0 }, { "boxvl", "\xE2\x94\xA4", 0 }, { "boxvr", "\xE2\x94\x9C", 0 }, { "bprime", "\xE2\x80\xB5", 0 }, { "breve", "\xCB\x98", 0 }, { "brvbar", "\xC2\xA6", 0 }, { "bscr", "\xF0\x9D\x92\xB7", 0 }, { "bsemi", "\xE2\x81\x8F", 0 }, { "bsim", "\xE2\x88\xBD", 0 }, { "bsime", "\xE2\x8B\x8D", 0 }, { "bsol", "\x5C", 0 }, { "bsolb", "\xE2\xA7\x85", 0 }, { "bsolhsub", "\xE2\x9F\x88", 0 }, { "bull", "\xE2\x80\xA2", 0 }, { "bullet", "\xE2\x80\xA2", 0 }, { "bump", "\xE2\x89\x8E", 0 }, { "bumpE", "\xE2\xAA\xAE", 0 }, { "bumpe", "\xE2\x89\x8F", 0 }, { "bumpeq", "\xE2\x89\x8F", 0 }, { "cacute", "\xC4\x87", 0 }, { "cap", "\xE2\x88\xA9", 0 }, { "capand", "\xE2\xA9\x84", 0 }, { "capbrcup", "\xE2\xA9\x89", 0 }, { "capcap", "\xE2\xA9\x8B", 0 }, { "capcup", "\xE2\xA9\x87", 0 }, { "capdot", "\xE2\xA9\x80", 0 }, { "caps", "\xE2\x88\xA9\xEF\xB8\x80", 0 }, { "caret", "\xE2\x81\x81", 0 }, { "caron", "\xCB\x87", 0 }, { "ccaps", "\xE2\xA9\x8D", 0 }, { "ccaron", "\xC4\x8D", 0 }, { "ccedil", "\xC3\xA7", 0 }, { "ccirc", "\xC4\x89", 0 }, { "ccups", "\xE2\xA9\x8C", 0 }, { "ccupssm", "\xE2\xA9\x90", 0 }, { "cdot", "\xC4\x8B", 0 }, { "cedil", "\xC2\xB8", 0 }, { "cemptyv", "\xE2\xA6\xB2", 0 }, { "cent", "\xC2\xA2", 0 }, { "centerdot", "\xC2\xB7", 0 }, { "cfr", "\xF0\x9D\x94\xA0", 0 }, { "chcy", "\xD1\x87", 0 }, { "check", "\xE2\x9C\x93", 0 }, { "checkmark", "\xE2\x9C\x93", 0 }, { "chi", "\xCF\x87", 0 }, { "cir", "\xE2\x97\x8B", 0 }, { "cirE", "\xE2\xA7\x83", 0 }, { "circ", "\xCB\x86", 0 }, { "circeq", "\xE2\x89\x97", 0 }, { "circlearrowleft", "\xE2\x86\xBA", 0 }, { "circlearrowright", "\xE2\x86\xBB", 0 }, { "circledR", "\xC2\xAE", 0 }, { "circledS", "\xE2\x93\x88", 0 }, { "circledast", "\xE2\x8A\x9B", 0 }, { "circledcirc", "\xE2\x8A\x9A", 0 }, { "circleddash", "\xE2\x8A\x9D", 0 }, { "cire", "\xE2\x89\x97", 0 }, { "cirfnint", "\xE2\xA8\x90", 0 }, { "cirmid", "\xE2\xAB\xAF", 0 }, { "cirscir", "\xE2\xA7\x82", 0 }, { "clubs", "\xE2\x99\xA3", 0 }, { "clubsuit", "\xE2\x99\xA3", 0 }, { "colon", "\x3A", 0 }, { "colone", "\xE2\x89\x94", 0 }, { "coloneq", "\xE2\x89\x94", 0 }, { "comma", "\x2C", 0 }, { "commat", "\x40", 0 }, { "comp", "\xE2\x88\x81", 0 }, { "compfn", "\xE2\x88\x98", 0 }, { "complement", "\xE2\x88\x81", 0 }, { "complexes", "\xE2\x84\x82", 0 }, { "cong", "\xE2\x89\x85", 0 }, { "congdot", "\xE2\xA9\xAD", 0 }, { "conint", "\xE2\x88\xAE", 0 }, { "copf", "\xF0\x9D\x95\x94", 0 }, { "coprod", "\xE2\x88\x90", 0 }, { "copy", "\xC2\xA9", 0 }, { "copysr", "\xE2\x84\x97", 0 }, { "crarr", "\xE2\x86\xB5", 0 }, { "cross", "\xE2\x9C\x97", 0 }, { "cscr", "\xF0\x9D\x92\xB8", 0 }, { "csub", "\xE2\xAB\x8F", 0 }, { "csube", "\xE2\xAB\x91", 0 }, { "csup", "\xE2\xAB\x90", 0 }, { "csupe", "\xE2\xAB\x92", 0 }, { "ctdot", "\xE2\x8B\xAF", 0 }, { "cudarrl", "\xE2\xA4\xB8", 0 }, { "cudarrr", "\xE2\xA4\xB5", 0 }, { "cuepr", "\xE2\x8B\x9E", 0 }, { "cuesc", "\xE2\x8B\x9F", 0 }, { "cularr", "\xE2\x86\xB6", 0 }, { "cularrp", "\xE2\xA4\xBD", 0 }, { "cup", "\xE2\x88\xAA", 0 }, { "cupbrcap", "\xE2\xA9\x88", 0 }, { "cupcap", "\xE2\xA9\x86", 0 }, { "cupcup", "\xE2\xA9\x8A", 0 }, { "cupdot", "\xE2\x8A\x8D", 0 }, { "cupor", "\xE2\xA9\x85", 0 }, { "cups", "\xE2\x88\xAA\xEF\xB8\x80", 0 }, { "curarr", "\xE2\x86\xB7", 0 }, { "curarrm", "\xE2\xA4\xBC", 0 }, { "curlyeqprec", "\xE2\x8B\x9E", 0 }, { "curlyeqsucc", "\xE2\x8B\x9F", 0 }, { "curlyvee", "\xE2\x8B\x8E", 0 }, { "curlywedge", "\xE2\x8B\x8F", 0 }, { "curren", "\xC2\xA4", 0 }, { "curvearrowleft", "\xE2\x86\xB6", 0 }, { "curvearrowright", "\xE2\x86\xB7", 0 }, { "cuvee", "\xE2\x8B\x8E", 0 }, { "cuwed", "\xE2\x8B\x8F", 0 }, { "cwconint", "\xE2\x88\xB2", 0 }, { "cwint", "\xE2\x88\xB1", 0 }, { "cylcty", "\xE2\x8C\xAD", 0 }, { "dArr", "\xE2\x87\x93", 0 }, { "dHar", "\xE2\xA5\xA5", 0 }, { "dagger", "\xE2\x80\xA0", 0 }, { "daleth", "\xE2\x84\xB8", 0 }, { "darr", "\xE2\x86\x93", 0 }, { "dash", "\xE2\x80\x90", 0 }, { "dashv", "\xE2\x8A\xA3", 0 }, { "dbkarow", "\xE2\xA4\x8F", 0 }, { "dblac", "\xCB\x9D", 0 }, { "dcaron", "\xC4\x8F", 0 }, { "dcy", "\xD0\xB4", 0 }, { "dd", "\xE2\x85\x86", 0 }, { "ddagger", "\xE2\x80\xA1", 0 }, { "ddarr", "\xE2\x87\x8A", 0 }, { "ddotseq", "\xE2\xA9\xB7", 0 }, { "deg", "\xC2\xB0", 0 }, { "delta", "\xCE\xB4", 0 }, { "demptyv", "\xE2\xA6\xB1", 0 }, { "dfisht", "\xE2\xA5\xBF", 0 }, { "dfr", "\xF0\x9D\x94\xA1", 0 }, { "dharl", "\xE2\x87\x83", 0 }, { "dharr", "\xE2\x87\x82", 0 }, { "diam", "\xE2\x8B\x84", 0 }, { "diamond", "\xE2\x8B\x84", 0 }, { "diamondsuit", "\xE2\x99\xA6", 0 }, { "diams", "\xE2\x99\xA6", 0 }, { "die", "\xC2\xA8", 0 }, { "digamma", "\xCF\x9D", 0 }, { "disin", "\xE2\x8B\xB2", 0 }, { "div", "\xC3\xB7", 0 }, { "divide", "\xC3\xB7", 0 }, { "divideontimes", "\xE2\x8B\x87", 0 }, { "divonx", "\xE2\x8B\x87", 0 }, { "djcy", "\xD1\x92", 0 }, { "dlcorn", "\xE2\x8C\x9E", 0 }, { "dlcrop", "\xE2\x8C\x8D", 0 }, { "dollar", "\x24", 0 }, { "dopf", "\xF0\x9D\x95\x95", 0 }, { "dot", "\xCB\x99", 0 }, { "doteq", "\xE2\x89\x90", 0 }, { "doteqdot", "\xE2\x89\x91", 0 }, { "dotminus", "\xE2\x88\xB8", 0 }, { "dotplus", "\xE2\x88\x94", 0 }, { "dotsquare", "\xE2\x8A\xA1", 0 }, { "doublebarwedge", "\xE2\x8C\x86", 0 }, { "downarrow", "\xE2\x86\x93", 0 }, { "downdownarrows", "\xE2\x87\x8A", 0 }, { "downharpoonleft", "\xE2\x87\x83", 0 }, { "downharpoonright", "\xE2\x87\x82", 0 }, { "drbkarow", "\xE2\xA4\x90", 0 }, { "drcorn", "\xE2\x8C\x9F", 0 }, { "drcrop", "\xE2\x8C\x8C", 0 }, { "dscr", "\xF0\x9D\x92\xB9", 0 }, { "dscy", "\xD1\x95", 0 }, { "dsol", "\xE2\xA7\xB6", 0 }, { "dstrok", "\xC4\x91", 0 }, { "dtdot", "\xE2\x8B\xB1", 0 }, { "dtri", "\xE2\x96\xBF", 0 }, { "dtrif", "\xE2\x96\xBE", 0 }, { "duarr", "\xE2\x87\xB5", 0 }, { "duhar", "\xE2\xA5\xAF", 0 }, { "dwangle", "\xE2\xA6\xA6", 0 }, { "dzcy", "\xD1\x9F", 0 }, { "dzigrarr", "\xE2\x9F\xBF", 0 }, { "eDDot", "\xE2\xA9\xB7", 0 }, { "eDot", "\xE2\x89\x91", 0 }, { "eacute", "\xC3\xA9", 0 }, { "easter", "\xE2\xA9\xAE", 0 }, { "ecaron", "\xC4\x9B", 0 }, { "ecir", "\xE2\x89\x96", 0 }, { "ecirc", "\xC3\xAA", 0 }, { "ecolon", "\xE2\x89\x95", 0 }, { "ecy", "\xD1\x8D", 0 }, { "edot", "\xC4\x97", 0 }, { "ee", "\xE2\x85\x87", 0 }, { "efDot", "\xE2\x89\x92", 0 }, { "efr", "\xF0\x9D\x94\xA2", 0 }, { "eg", "\xE2\xAA\x9A", 0 }, { "egrave", "\xC3\xA8", 0 }, { "egs", "\xE2\xAA\x96", 0 }, { "egsdot", "\xE2\xAA\x98", 0 }, { "el", "\xE2\xAA\x99", 0 }, { "elinters", "\xE2\x8F\xA7", 0 }, { "ell", "\xE2\x84\x93", 0 }, { "els", "\xE2\xAA\x95", 0 }, { "elsdot", "\xE2\xAA\x97", 0 }, { "emacr", "\xC4\x93", 0 }, { "empty", "\xE2\x88\x85", 0 }, { "emptyset", "\xE2\x88\x85", 0 }, { "emptyv", "\xE2\x88\x85", 0 }, { "emsp", "\xE2\x80\x83", 0 }, { "emsp13", "\xE2\x80\x84", 0 }, { "emsp14", "\xE2\x80\x85", 0 }, { "eng", "\xC5\x8B", 0 }, { "ensp", "\xE2\x80\x82", 0 }, { "eogon", "\xC4\x99", 0 }, { "eopf", "\xF0\x9D\x95\x96", 0 }, { "epar", "\xE2\x8B\x95", 0 }, { "eparsl", "\xE2\xA7\xA3", 0 }, { "eplus", "\xE2\xA9\xB1", 0 }, { "epsi", "\xCE\xB5", 0 }, { "epsilon", "\xCE\xB5", 0 }, { "epsiv", "\xCF\xB5", 0 }, { "eqcirc", "\xE2\x89\x96", 0 }, { "eqcolon", "\xE2\x89\x95", 0 }, { "eqsim", "\xE2\x89\x82", 0 }, { "eqslantgtr", "\xE2\xAA\x96", 0 }, { "eqslantless", "\xE2\xAA\x95", 0 }, { "equals", "\x3D", 0 }, { "equest", "\xE2\x89\x9F", 0 }, { "equiv", "\xE2\x89\xA1", 0 }, { "equivDD", "\xE2\xA9\xB8", 0 }, { "eqvparsl", "\xE2\xA7\xA5", 0 }, { "erDot", "\xE2\x89\x93", 0 }, { "erarr", "\xE2\xA5\xB1", 0 }, { "escr", "\xE2\x84\xAF", 0 }, { "esdot", "\xE2\x89\x90", 0 }, { "esim", "\xE2\x89\x82", 0 }, { "eta", "\xCE\xB7", 0 }, { "eth", "\xC3\xB0", 0 }, { "euml", "\xC3\xAB", 0 }, { "euro", "\xE2\x82\xAC", 0 }, { "excl", "\x21", 0 }, { "exist", "\xE2\x88\x83", 0 }, { "expectation", "\xE2\x84\xB0", 0 }, { "exponentiale", "\xE2\x85\x87", 0 }, { "fallingdotseq", "\xE2\x89\x92", 0 }, { "fcy", "\xD1\x84", 0 }, { "female", "\xE2\x99\x80", 0 }, { "ffilig", "\xEF\xAC\x83", 0 }, { "fflig", "\xEF\xAC\x80", 0 }, { "ffllig", "\xEF\xAC\x84", 0 }, { "ffr", "\xF0\x9D\x94\xA3", 0 }, { "filig", "\xEF\xAC\x81", 0 }, { "fjlig", "\x66\x6A", 0 }, { "flat", "\xE2\x99\xAD", 0 }, { "fllig", "\xEF\xAC\x82", 0 }, { "fltns", "\xE2\x96\xB1", 0 }, { "fnof", "\xC6\x92", 0 }, { "fopf", "\xF0\x9D\x95\x97", 0 }, { "forall", "\xE2\x88\x80", 0 }, { "fork", "\xE2\x8B\x94", 0 }, { "forkv", "\xE2\xAB\x99", 0 }, { "fpartint", "\xE2\xA8\x8D", 0 }, { "frac12", "\xC2\xBD", 0 }, { "frac13", "\xE2\x85\x93", 0 }, { "frac14", "\xC2\xBC", 0 }, { "frac15", "\xE2\x85\x95", 0 }, { "frac16", "\xE2\x85\x99", 0 }, { "frac18", "\xE2\x85\x9B", 0 }, { "frac23", "\xE2\x85\x94", 0 }, { "frac25", "\xE2\x85\x96", 0 }, { "frac34", "\xC2\xBE", 0 }, { "frac35", "\xE2\x85\x97", 0 }, { "frac38", "\xE2\x85\x9C", 0 }, { "frac45", "\xE2\x85\x98", 0 }, { "frac56", "\xE2\x85\x9A", 0 }, { "frac58", "\xE2\x85\x9D", 0 }, { "frac78", "\xE2\x85\x9E", 0 }, { "frasl", "\xE2\x81\x84", 0 }, { "frown", "\xE2\x8C\xA2", 0 }, { "fscr", "\xF0\x9D\x92\xBB", 0 }, { "gE", "\xE2\x89\xA7", 0 }, { "gEl", "\xE2\xAA\x8C", 0 }, { "gacute", "\xC7\xB5", 0 }, { "gamma", "\xCE\xB3", 0 }, { "gammad", "\xCF\x9D", 0 }, { "gap", "\xE2\xAA\x86", 0 }, { "gbreve", "\xC4\x9F", 0 }, { "gcirc", "\xC4\x9D", 0 }, { "gcy", "\xD0\xB3", 0 }, { "gdot", "\xC4\xA1", 0 }, { "ge", "\xE2\x89\xA5", 0 }, { "gel", "\xE2\x8B\x9B", 0 }, { "geq", "\xE2\x89\xA5", 0 }, { "geqq", "\xE2\x89\xA7", 0 }, { "geqslant", "\xE2\xA9\xBE", 0 }, { "ges", "\xE2\xA9\xBE", 0 }, { "gescc", "\xE2\xAA\xA9", 0 }, { "gesdot", "\xE2\xAA\x80", 0 }, { "gesdoto", "\xE2\xAA\x82", 0 }, { "gesdotol", "\xE2\xAA\x84", 0 }, { "gesl", "\xE2\x8B\x9B\xEF\xB8\x80", 0 }, { "gesles", "\xE2\xAA\x94", 0 }, { "gfr", "\xF0\x9D\x94\xA4", 0 }, { "gg", "\xE2\x89\xAB", 0 }, { "ggg", "\xE2\x8B\x99", 0 }, { "gimel", "\xE2\x84\xB7", 0 }, { "gjcy", "\xD1\x93", 0 }, { "gl", "\xE2\x89\xB7", 0 }, { "glE", "\xE2\xAA\x92", 0 }, { "gla", "\xE2\xAA\xA5", 0 }, { "glj", "\xE2\xAA\xA4", 0 }, { "gnE", "\xE2\x89\xA9", 0 }, { "gnap", "\xE2\xAA\x8A", 0 }, { "gnapprox", "\xE2\xAA\x8A", 0 }, { "gne", "\xE2\xAA\x88", 0 }, { "gneq", "\xE2\xAA\x88", 0 }, { "gneqq", "\xE2\x89\xA9", 0 }, { "gnsim", "\xE2\x8B\xA7", 0 }, { "gopf", "\xF0\x9D\x95\x98", 0 }, { "grave", "\x60", 0 }, { "gscr", "\xE2\x84\x8A", 0 }, { "gsim", "\xE2\x89\xB3", 0 }, { "gsime", "\xE2\xAA\x8E", 0 }, { "gsiml", "\xE2\xAA\x90", 0 }, { "gt", "\x3E", 0 }, { "gtcc", "\xE2\xAA\xA7", 0 }, { "gtcir", "\xE2\xA9\xBA", 0 }, { "gtdot", "\xE2\x8B\x97", 0 }, { "gtlPar", "\xE2\xA6\x95", 0 }, { "gtquest", "\xE2\xA9\xBC", 0 }, { "gtrapprox", "\xE2\xAA\x86", 0 }, { "gtrarr", "\xE2\xA5\xB8", 0 }, { "gtrdot", "\xE2\x8B\x97", 0 }, { "gtreqless", "\xE2\x8B\x9B", 0 }, { "gtreqqless", "\xE2\xAA\x8C", 0 }, { "gtrless", "\xE2\x89\xB7", 0 }, { "gtrsim", "\xE2\x89\xB3", 0 }, { "gvertneqq", "\xE2\x89\xA9\xEF\xB8\x80", 0 }, { "gvnE", "\xE2\x89\xA9\xEF\xB8\x80", 0 }, { "hArr", "\xE2\x87\x94", 0 }, { "hairsp", "\xE2\x80\x8A", 0 }, { "half", "\xC2\xBD", 0 }, { "hamilt", "\xE2\x84\x8B", 0 }, { "hardcy", "\xD1\x8A", 0 }, { "harr", "\xE2\x86\x94", 0 }, { "harrcir", "\xE2\xA5\x88", 0 }, { "harrw", "\xE2\x86\xAD", 0 }, { "hbar", "\xE2\x84\x8F", 0 }, { "hcirc", "\xC4\xA5", 0 }, { "hearts", "\xE2\x99\xA5", 0 }, { "heartsuit", "\xE2\x99\xA5", 0 }, { "hellip", "\xE2\x80\xA6", 0 }, { "hercon", "\xE2\x8A\xB9", 0 }, { "hfr", "\xF0\x9D\x94\xA5", 0 }, { "hksearow", "\xE2\xA4\xA5", 0 }, { "hkswarow", "\xE2\xA4\xA6", 0 }, { "hoarr", "\xE2\x87\xBF", 0 }, { "homtht", "\xE2\x88\xBB", 0 }, { "hookleftarrow", "\xE2\x86\xA9", 0 }, { "hookrightarrow", "\xE2\x86\xAA", 0 }, { "hopf", "\xF0\x9D\x95\x99", 0 }, { "horbar", "\xE2\x80\x95", 0 }, { "hscr", "\xF0\x9D\x92\xBD", 0 }, { "hslash", "\xE2\x84\x8F", 0 }, { "hstrok", "\xC4\xA7", 0 }, { "hybull", "\xE2\x81\x83", 0 }, { "hyphen", "\xE2\x80\x90", 0 }, { "iacute", "\xC3\xAD", 0 }, { "ic", "\xE2\x81\xA3", 0 }, { "icirc", "\xC3\xAE", 0 }, { "icy", "\xD0\xB8", 0 }, { "iecy", "\xD0\xB5", 0 }, { "iexcl", "\xC2\xA1", 0 }, { "iff", "\xE2\x87\x94", 0 }, { "ifr", "\xF0\x9D\x94\xA6", 0 }, { "igrave", "\xC3\xAC", 0 }, { "ii", "\xE2\x85\x88", 0 }, { "iiiint", "\xE2\xA8\x8C", 0 }, { "iiint", "\xE2\x88\xAD", 0 }, { "iinfin", "\xE2\xA7\x9C", 0 }, { "iiota", "\xE2\x84\xA9", 0 }, { "ijlig", "\xC4\xB3", 0 }, { "imacr", "\xC4\xAB", 0 }, { "image", "\xE2\x84\x91", 0 }, { "imagline", "\xE2\x84\x90", 0 }, { "imagpart", "\xE2\x84\x91", 0 }, { "imath", "\xC4\xB1", 0 }, { "imof", "\xE2\x8A\xB7", 0 }, { "imped", "\xC6\xB5", 0 }, { "in", "\xE2\x88\x88", 0 }, { "incare", "\xE2\x84\x85", 0 }, { "infin", "\xE2\x88\x9E", 0 }, { "infintie", "\xE2\xA7\x9D", 0 }, { "inodot", "\xC4\xB1", 0 }, { "int", "\xE2\x88\xAB", 0 }, { "intcal", "\xE2\x8A\xBA", 0 }, { "integers", "\xE2\x84\xA4", 0 }, { "intercal", "\xE2\x8A\xBA", 0 }, { "intlarhk", "\xE2\xA8\x97", 0 }, { "intprod", "\xE2\xA8\xBC", 0 }, { "iocy", "\xD1\x91", 0 }, { "iogon", "\xC4\xAF", 0 }, { "iopf", "\xF0\x9D\x95\x9A", 0 }, { "iota", "\xCE\xB9", 0 }, { "iprod", "\xE2\xA8\xBC", 0 }, { "iquest", "\xC2\xBF", 0 }, { "iscr", "\xF0\x9D\x92\xBE", 0 }, { "isin", "\xE2\x88\x88", 0 }, { "isinE", "\xE2\x8B\xB9", 0 }, { "isindot", "\xE2\x8B\xB5", 0 }, { "isins", "\xE2\x8B\xB4", 0 }, { "isinsv", "\xE2\x8B\xB3", 0 }, { "isinv", "\xE2\x88\x88", 0 }, { "it", "\xE2\x81\xA2", 0 }, { "itilde", "\xC4\xA9", 0 }, { "iukcy", "\xD1\x96", 0 }, { "iuml", "\xC3\xAF", 0 }, { "jcirc", "\xC4\xB5", 0 }, { "jcy", "\xD0\xB9", 0 }, { "jfr", "\xF0\x9D\x94\xA7", 0 }, { "jmath", "\xC8\xB7", 0 }, { "jopf", "\xF0\x9D\x95\x9B", 0 }, { "jscr", "\xF0\x9D\x92\xBF", 0 }, { "jsercy", "\xD1\x98", 0 }, { "jukcy", "\xD1\x94", 0 }, { "kappa", "\xCE\xBA", 0 }, { "kappav", "\xCF\xB0", 0 }, { "kcedil", "\xC4\xB7", 0 }, { "kcy", "\xD0\xBA", 0 }, { "kfr", "\xF0\x9D\x94\xA8", 0 }, { "kgreen", "\xC4\xB8", 0 }, { "khcy", "\xD1\x85", 0 }, { "kjcy", "\xD1\x9C", 0 }, { "kopf", "\xF0\x9D\x95\x9C", 0 }, { "kscr", "\xF0\x9D\x93\x80", 0 }, { "lAarr", "\xE2\x87\x9A", 0 }, { "lArr", "\xE2\x87\x90", 0 }, { "lAtail", "\xE2\xA4\x9B", 0 }, { "lBarr", "\xE2\xA4\x8E", 0 }, { "lE", "\xE2\x89\xA6", 0 }, { "lEg", "\xE2\xAA\x8B", 0 }, { "lHar", "\xE2\xA5\xA2", 0 }, { "lacute", "\xC4\xBA", 0 }, { "laemptyv", "\xE2\xA6\xB4", 0 }, { "lagran", "\xE2\x84\x92", 0 }, { "lambda", "\xCE\xBB", 0 }, { "lang", "\xE2\x9F\xA8", 0 }, { "langd", "\xE2\xA6\x91", 0 }, { "langle", "\xE2\x9F\xA8", 0 }, { "lap", "\xE2\xAA\x85", 0 }, { "laquo", "\xC2\xAB", 0 }, { "larr", "\xE2\x86\x90", 0 }, { "larrb", "\xE2\x87\xA4", 0 }, { "larrbfs", "\xE2\xA4\x9F", 0 }, { "larrfs", "\xE2\xA4\x9D", 0 }, { "larrhk", "\xE2\x86\xA9", 0 }, { "larrlp", "\xE2\x86\xAB", 0 }, { "larrpl", "\xE2\xA4\xB9", 0 }, { "larrsim", "\xE2\xA5\xB3", 0 }, { "larrtl", "\xE2\x86\xA2", 0 }, { "lat", "\xE2\xAA\xAB", 0 }, { "latail", "\xE2\xA4\x99", 0 }, { "late", "\xE2\xAA\xAD", 0 }, { "lates", "\xE2\xAA\xAD\xEF\xB8\x80", 0 }, { "lbarr", "\xE2\xA4\x8C", 0 }, { "lbbrk", "\xE2\x9D\xB2", 0 }, { "lbrace", "\x7B", 0 }, { "lbrack", "\x5B", 0 }, { "lbrke", "\xE2\xA6\x8B", 0 }, { "lbrksld", "\xE2\xA6\x8F", 0 }, { "lbrkslu", "\xE2\xA6\x8D", 0 }, { "lcaron", "\xC4\xBE", 0 }, { "lcedil", "\xC4\xBC", 0 }, { "lceil", "\xE2\x8C\x88", 0 }, { "lcub", "\x7B", 0 }, { "lcy", "\xD0\xBB", 0 }, { "ldca", "\xE2\xA4\xB6", 0 }, { "ldquo", "\xE2\x80\x9C", 0 }, { "ldquor", "\xE2\x80\x9E", 0 }, { "ldrdhar", "\xE2\xA5\xA7", 0 }, { "ldrushar", "\xE2\xA5\x8B", 0 }, { "ldsh", "\xE2\x86\xB2", 0 }, { "le", "\xE2\x89\xA4", 0 }, { "leftarrow", "\xE2\x86\x90", 0 }, { "leftarrowtail", "\xE2\x86\xA2", 0 }, { "leftharpoondown", "\xE2\x86\xBD", 0 }, { "leftharpoonup", "\xE2\x86\xBC", 0 }, { "leftleftarrows", "\xE2\x87\x87", 0 }, { "leftrightarrow", "\xE2\x86\x94", 0 }, { "leftrightarrows", "\xE2\x87\x86", 0 }, { "leftrightharpoons", "\xE2\x87\x8B", 0 }, { "leftrightsquigarrow", "\xE2\x86\xAD", 0 }, { "leftthreetimes", "\xE2\x8B\x8B", 0 }, { "leg", "\xE2\x8B\x9A", 0 }, { "leq", "\xE2\x89\xA4", 0 }, { "leqq", "\xE2\x89\xA6", 0 }, { "leqslant", "\xE2\xA9\xBD", 0 }, { "les", "\xE2\xA9\xBD", 0 }, { "lescc", "\xE2\xAA\xA8", 0 }, { "lesdot", "\xE2\xA9\xBF", 0 }, { "lesdoto", "\xE2\xAA\x81", 0 }, { "lesdotor", "\xE2\xAA\x83", 0 }, { "lesg", "\xE2\x8B\x9A\xEF\xB8\x80", 0 }, { "lesges", "\xE2\xAA\x93", 0 }, { "lessapprox", "\xE2\xAA\x85", 0 }, { "lessdot", "\xE2\x8B\x96", 0 }, { "lesseqgtr", "\xE2\x8B\x9A", 0 }, { "lesseqqgtr", "\xE2\xAA\x8B", 0 }, { "lessgtr", "\xE2\x89\xB6", 0 }, { "lesssim", "\xE2\x89\xB2", 0 }, { "lfisht", "\xE2\xA5\xBC", 0 }, { "lfloor", "\xE2\x8C\x8A", 0 }, { "lfr", "\xF0\x9D\x94\xA9", 0 }, { "lg", "\xE2\x89\xB6", 0 }, { "lgE", "\xE2\xAA\x91", 0 }, { "lhard", "\xE2\x86\xBD", 0 }, { "lharu", "\xE2\x86\xBC", 0 }, { "lharul", "\xE2\xA5\xAA", 0 }, { "lhblk", "\xE2\x96\x84", 0 }, { "ljcy", "\xD1\x99", 0 }, { "ll", "\xE2\x89\xAA", 0 }, { "llarr", "\xE2\x87\x87", 0 }, { "llcorner", "\xE2\x8C\x9E", 0 }, { "llhard", "\xE2\xA5\xAB", 0 }, { "lltri", "\xE2\x97\xBA", 0 }, { "lmidot", "\xC5\x80", 0 }, { "lmoust", "\xE2\x8E\xB0", 0 }, { "lmoustache", "\xE2\x8E\xB0", 0 }, { "lnE", "\xE2\x89\xA8", 0 }, { "lnap", "\xE2\xAA\x89", 0 }, { "lnapprox", "\xE2\xAA\x89", 0 }, { "lne", "\xE2\xAA\x87", 0 }, { "lneq", "\xE2\xAA\x87", 0 }, { "lneqq", "\xE2\x89\xA8", 0 }, { "lnsim", "\xE2\x8B\xA6", 0 }, { "loang", "\xE2\x9F\xAC", 0 }, { "loarr", "\xE2\x87\xBD", 0 }, { "lobrk", "\xE2\x9F\xA6", 0 }, { "longleftarrow", "\xE2\x9F\xB5", 0 }, { "longleftrightarrow", "\xE2\x9F\xB7", 0 }, { "longmapsto", "\xE2\x9F\xBC", 0 }, { "longrightarrow", "\xE2\x9F\xB6", 0 }, { "looparrowleft", "\xE2\x86\xAB", 0 }, { "looparrowright", "\xE2\x86\xAC", 0 }, { "lopar", "\xE2\xA6\x85", 0 }, { "lopf", "\xF0\x9D\x95\x9D", 0 }, { "loplus", "\xE2\xA8\xAD", 0 }, { "lotimes", "\xE2\xA8\xB4", 0 }, { "lowast", "\xE2\x88\x97", 0 }, { "lowbar", "\x5F", 0 }, { "loz", "\xE2\x97\x8A", 0 }, { "lozenge", "\xE2\x97\x8A", 0 }, { "lozf", "\xE2\xA7\xAB", 0 }, { "lpar", "\x28", 0 }, { "lparlt", "\xE2\xA6\x93", 0 }, { "lrarr", "\xE2\x87\x86", 0 }, { "lrcorner", "\xE2\x8C\x9F", 0 }, { "lrhar", "\xE2\x87\x8B", 0 }, { "lrhard", "\xE2\xA5\xAD", 0 }, { "lrm", "\xE2\x80\x8E", 0 }, { "lrtri", "\xE2\x8A\xBF", 0 }, { "lsaquo", "\xE2\x80\xB9", 0 }, { "lscr", "\xF0\x9D\x93\x81", 0 }, { "lsh", "\xE2\x86\xB0", 0 }, { "lsim", "\xE2\x89\xB2", 0 }, { "lsime", "\xE2\xAA\x8D", 0 }, { "lsimg", "\xE2\xAA\x8F", 0 }, { "lsqb", "\x5B", 0 }, { "lsquo", "\xE2\x80\x98", 0 }, { "lsquor", "\xE2\x80\x9A", 0 }, { "lstrok", "\xC5\x82", 0 }, { "lt", "\x3C", 0 }, { "ltcc", "\xE2\xAA\xA6", 0 }, { "ltcir", "\xE2\xA9\xB9", 0 }, { "ltdot", "\xE2\x8B\x96", 0 }, { "lthree", "\xE2\x8B\x8B", 0 }, { "ltimes", "\xE2\x8B\x89", 0 }, { "ltlarr", "\xE2\xA5\xB6", 0 }, { "ltquest", "\xE2\xA9\xBB", 0 }, { "ltrPar", "\xE2\xA6\x96", 0 }, { "ltri", "\xE2\x97\x83", 0 }, { "ltrie", "\xE2\x8A\xB4", 0 }, { "ltrif", "\xE2\x97\x82", 0 }, { "lurdshar", "\xE2\xA5\x8A", 0 }, { "luruhar", "\xE2\xA5\xA6", 0 }, { "lvertneqq", "\xE2\x89\xA8\xEF\xB8\x80", 0 }, { "lvnE", "\xE2\x89\xA8\xEF\xB8\x80", 0 }, { "mDDot", "\xE2\x88\xBA", 0 }, { "macr", "\xC2\xAF", 0 }, { "male", "\xE2\x99\x82", 0 }, { "malt", "\xE2\x9C\xA0", 0 }, { "maltese", "\xE2\x9C\xA0", 0 }, { "map", "\xE2\x86\xA6", 0 }, { "mapsto", "\xE2\x86\xA6", 0 }, { "mapstodown", "\xE2\x86\xA7", 0 }, { "mapstoleft", "\xE2\x86\xA4", 0 }, { "mapstoup", "\xE2\x86\xA5", 0 }, { "marker", "\xE2\x96\xAE", 0 }, { "mcomma", "\xE2\xA8\xA9", 0 }, { "mcy", "\xD0\xBC", 0 }, { "mdash", "\xE2\x80\x94", 0 }, { "measuredangle", "\xE2\x88\xA1", 0 }, { "mfr", "\xF0\x9D\x94\xAA", 0 }, { "mho", "\xE2\x84\xA7", 0 }, { "micro", "\xC2\xB5", 0 }, { "mid", "\xE2\x88\xA3", 0 }, { "midast", "\x2A", 0 }, { "midcir", "\xE2\xAB\xB0", 0 }, { "middot", "\xC2\xB7", 0 }, { "minus", "\xE2\x88\x92", 0 }, { "minusb", "\xE2\x8A\x9F", 0 }, { "minusd", "\xE2\x88\xB8", 0 }, { "minusdu", "\xE2\xA8\xAA", 0 }, { "mlcp", "\xE2\xAB\x9B", 0 }, { "mldr", "\xE2\x80\xA6", 0 }, { "mnplus", "\xE2\x88\x93", 0 }, { "models", "\xE2\x8A\xA7", 0 }, { "mopf", "\xF0\x9D\x95\x9E", 0 }, { "mp", "\xE2\x88\x93", 0 }, { "mscr", "\xF0\x9D\x93\x82", 0 }, { "mstpos", "\xE2\x88\xBE", 0 }, { "mu", "\xCE\xBC", 0 }, { "multimap", "\xE2\x8A\xB8", 0 }, { "mumap", "\xE2\x8A\xB8", 0 }, { "nGg", "\xE2\x8B\x99\xCC\xB8", 0 }, { "nGtv", "\xE2\x89\xAB\xCC\xB8", 0 }, { "nLeftarrow", "\xE2\x87\x8D", 0 }, { "nLeftrightarrow", "\xE2\x87\x8E", 0 }, { "nLl", "\xE2\x8B\x98\xCC\xB8", 0 }, { "nLtv", "\xE2\x89\xAA\xCC\xB8", 0 }, { "nRightarrow", "\xE2\x87\x8F", 0 }, { "nVDash", "\xE2\x8A\xAF", 0 }, { "nVdash", "\xE2\x8A\xAE", 0 }, { "nabla", "\xE2\x88\x87", 0 }, { "nacute", "\xC5\x84", 0 }, { "nang", "\xE2\x88\xA0\xE2\x83\x92", 0 }, { "nap", "\xE2\x89\x89", 0 }, { "napE", "\xE2\xA9\xB0\xCC\xB8", 0 }, { "napid", "\xE2\x89\x8B\xCC\xB8", 0 }, { "napos", "\xC5\x89", 0 }, { "napprox", "\xE2\x89\x89", 0 }, { "natur", "\xE2\x99\xAE", 0 }, { "natural", "\xE2\x99\xAE", 0 }, { "naturals", "\xE2\x84\x95", 0 }, { "nbsp", "\xC2\xA0", 0 }, { "nbump", "\xE2\x89\x8E\xCC\xB8", 0 }, { "nbumpe", "\xE2\x89\x8F\xCC\xB8", 0 }, { "ncap", "\xE2\xA9\x83", 0 }, { "ncaron", "\xC5\x88", 0 }, { "ncedil", "\xC5\x86", 0 }, { "ncong", "\xE2\x89\x87", 0 }, { "ncongdot", "\xE2\xA9\xAD\xCC\xB8", 0 }, { "ncup", "\xE2\xA9\x82", 0 }, { "ncy", "\xD0\xBD", 0 }, { "ndash", "\xE2\x80\x93", 0 }, { "ne", "\xE2\x89\xA0", 0 }, { "neArr", "\xE2\x87\x97", 0 }, { "nearhk", "\xE2\xA4\xA4", 0 }, { "nearr", "\xE2\x86\x97", 0 }, { "nearrow", "\xE2\x86\x97", 0 }, { "nedot", "\xE2\x89\x90\xCC\xB8", 0 }, { "nequiv", "\xE2\x89\xA2", 0 }, { "nesear", "\xE2\xA4\xA8", 0 }, { "nesim", "\xE2\x89\x82\xCC\xB8", 0 }, { "nexist", "\xE2\x88\x84", 0 }, { "nexists", "\xE2\x88\x84", 0 }, { "nfr", "\xF0\x9D\x94\xAB", 0 }, { "ngE", "\xE2\x89\xA7\xCC\xB8", 0 }, { "nge", "\xE2\x89\xB1", 0 }, { "ngeq", "\xE2\x89\xB1", 0 }, { "ngeqq", "\xE2\x89\xA7\xCC\xB8", 0 }, { "ngeqslant", "\xE2\xA9\xBE\xCC\xB8", 0 }, { "nges", "\xE2\xA9\xBE\xCC\xB8", 0 }, { "ngsim", "\xE2\x89\xB5", 0 }, { "ngt", "\xE2\x89\xAF", 0 }, { "ngtr", "\xE2\x89\xAF", 0 }, { "nhArr", "\xE2\x87\x8E", 0 }, { "nharr", "\xE2\x86\xAE", 0 }, { "nhpar", "\xE2\xAB\xB2", 0 }, { "ni", "\xE2\x88\x8B", 0 }, { "nis", "\xE2\x8B\xBC", 0 }, { "nisd", "\xE2\x8B\xBA", 0 }, { "niv", "\xE2\x88\x8B", 0 }, { "njcy", "\xD1\x9A", 0 }, { "nlArr", "\xE2\x87\x8D", 0 }, { "nlE", "\xE2\x89\xA6\xCC\xB8", 0 }, { "nlarr", "\xE2\x86\x9A", 0 }, { "nldr", "\xE2\x80\xA5", 0 }, { "nle", "\xE2\x89\xB0", 0 }, { "nleftarrow", "\xE2\x86\x9A", 0 }, { "nleftrightarrow", "\xE2\x86\xAE", 0 }, { "nleq", "\xE2\x89\xB0", 0 }, { "nleqq", "\xE2\x89\xA6\xCC\xB8", 0 }, { "nleqslant", "\xE2\xA9\xBD\xCC\xB8", 0 }, { "nles", "\xE2\xA9\xBD\xCC\xB8", 0 }, { "nless", "\xE2\x89\xAE", 0 }, { "nlsim", "\xE2\x89\xB4", 0 }, { "nlt", "\xE2\x89\xAE", 0 }, { "nltri", "\xE2\x8B\xAA", 0 }, { "nltrie", "\xE2\x8B\xAC", 0 }, { "nmid", "\xE2\x88\xA4", 0 }, { "nopf", "\xF0\x9D\x95\x9F", 0 }, { "not", "\xC2\xAC", 0 }, { "notin", "\xE2\x88\x89", 0 }, { "notinE", "\xE2\x8B\xB9\xCC\xB8", 0 }, { "notindot", "\xE2\x8B\xB5\xCC\xB8", 0 }, { "notinva", "\xE2\x88\x89", 0 }, { "notinvb", "\xE2\x8B\xB7", 0 }, { "notinvc", "\xE2\x8B\xB6", 0 }, { "notni", "\xE2\x88\x8C", 0 }, { "notniva", "\xE2\x88\x8C", 0 }, { "notnivb", "\xE2\x8B\xBE", 0 }, { "notnivc", "\xE2\x8B\xBD", 0 }, { "npar", "\xE2\x88\xA6", 0 }, { "nparallel", "\xE2\x88\xA6", 0 }, { "nparsl", "\xE2\xAB\xBD\xE2\x83\xA5", 0 }, { "npart", "\xE2\x88\x82\xCC\xB8", 0 }, { "npolint", "\xE2\xA8\x94", 0 }, { "npr", "\xE2\x8A\x80", 0 }, { "nprcue", "\xE2\x8B\xA0", 0 }, { "npre", "\xE2\xAA\xAF\xCC\xB8", 0 }, { "nprec", "\xE2\x8A\x80", 0 }, { "npreceq", "\xE2\xAA\xAF\xCC\xB8", 0 }, { "nrArr", "\xE2\x87\x8F", 0 }, { "nrarr", "\xE2\x86\x9B", 0 }, { "nrarrc", "\xE2\xA4\xB3\xCC\xB8", 0 }, { "nrarrw", "\xE2\x86\x9D\xCC\xB8", 0 }, { "nrightarrow", "\xE2\x86\x9B", 0 }, { "nrtri", "\xE2\x8B\xAB", 0 }, { "nrtrie", "\xE2\x8B\xAD", 0 }, { "nsc", "\xE2\x8A\x81", 0 }, { "nsccue", "\xE2\x8B\xA1", 0 }, { "nsce", "\xE2\xAA\xB0\xCC\xB8", 0 }, { "nscr", "\xF0\x9D\x93\x83", 0 }, { "nshortmid", "\xE2\x88\xA4", 0 }, { "nshortparallel", "\xE2\x88\xA6", 0 }, { "nsim", "\xE2\x89\x81", 0 }, { "nsime", "\xE2\x89\x84", 0 }, { "nsimeq", "\xE2\x89\x84", 0 }, { "nsmid", "\xE2\x88\xA4", 0 }, { "nspar", "\xE2\x88\xA6", 0 }, { "nsqsube", "\xE2\x8B\xA2", 0 }, { "nsqsupe", "\xE2\x8B\xA3", 0 }, { "nsub", "\xE2\x8A\x84", 0 }, { "nsubE", "\xE2\xAB\x85\xCC\xB8", 0 }, { "nsube", "\xE2\x8A\x88", 0 }, { "nsubset", "\xE2\x8A\x82\xE2\x83\x92", 0 }, { "nsubseteq", "\xE2\x8A\x88", 0 }, { "nsubseteqq", "\xE2\xAB\x85\xCC\xB8", 0 }, { "nsucc", "\xE2\x8A\x81", 0 }, { "nsucceq", "\xE2\xAA\xB0\xCC\xB8", 0 }, { "nsup", "\xE2\x8A\x85", 0 }, { "nsupE", "\xE2\xAB\x86\xCC\xB8", 0 }, { "nsupe", "\xE2\x8A\x89", 0 }, { "nsupset", "\xE2\x8A\x83\xE2\x83\x92", 0 }, { "nsupseteq", "\xE2\x8A\x89", 0 }, { "nsupseteqq", "\xE2\xAB\x86\xCC\xB8", 0 }, { "ntgl", "\xE2\x89\xB9", 0 }, { "ntilde", "\xC3\xB1", 0 }, { "ntlg", "\xE2\x89\xB8", 0 }, { "ntriangleleft", "\xE2\x8B\xAA", 0 }, { "ntrianglelefteq", "\xE2\x8B\xAC", 0 }, { "ntriangleright", "\xE2\x8B\xAB", 0 }, { "ntrianglerighteq", "\xE2\x8B\xAD", 0 }, { "nu", "\xCE\xBD", 0 }, { "num", "\x23", 0 }, { "numero", "\xE2\x84\x96", 0 }, { "numsp", "\xE2\x80\x87", 0 }, { "nvDash", "\xE2\x8A\xAD", 0 }, { "nvHarr", "\xE2\xA4\x84", 0 }, { "nvap", "\xE2\x89\x8D\xE2\x83\x92", 0 }, { "nvdash", "\xE2\x8A\xAC", 0 }, { "nvge", "\xE2\x89\xA5\xE2\x83\x92", 0 }, { "nvgt", "\x3E\xE2\x83\x92", 0 }, { "nvinfin", "\xE2\xA7\x9E", 0 }, { "nvlArr", "\xE2\xA4\x82", 0 }, { "nvle", "\xE2\x89\xA4\xE2\x83\x92", 0 }, { "nvlt", "\x3C\xE2\x83\x92", 0 }, { "nvltrie", "\xE2\x8A\xB4\xE2\x83\x92", 0 }, { "nvrArr", "\xE2\xA4\x83", 0 }, { "nvrtrie", "\xE2\x8A\xB5\xE2\x83\x92", 0 }, { "nvsim", "\xE2\x88\xBC\xE2\x83\x92", 0 }, { "nwArr", "\xE2\x87\x96", 0 }, { "nwarhk", "\xE2\xA4\xA3", 0 }, { "nwarr", "\xE2\x86\x96", 0 }, { "nwarrow", "\xE2\x86\x96", 0 }, { "nwnear", "\xE2\xA4\xA7", 0 }, { "oS", "\xE2\x93\x88", 0 }, { "oacute", "\xC3\xB3", 0 }, { "oast", "\xE2\x8A\x9B", 0 }, { "ocir", "\xE2\x8A\x9A", 0 }, { "ocirc", "\xC3\xB4", 0 }, { "ocy", "\xD0\xBE", 0 }, { "odash", "\xE2\x8A\x9D", 0 }, { "odblac", "\xC5\x91", 0 }, { "odiv", "\xE2\xA8\xB8", 0 }, { "odot", "\xE2\x8A\x99", 0 }, { "odsold", "\xE2\xA6\xBC", 0 }, { "oelig", "\xC5\x93", 0 }, { "ofcir", "\xE2\xA6\xBF", 0 }, { "ofr", "\xF0\x9D\x94\xAC", 0 }, { "ogon", "\xCB\x9B", 0 }, { "ograve", "\xC3\xB2", 0 }, { "ogt", "\xE2\xA7\x81", 0 }, { "ohbar", "\xE2\xA6\xB5", 0 }, { "ohm", "\xCE\xA9", 0 }, { "oint", "\xE2\x88\xAE", 0 }, { "olarr", "\xE2\x86\xBA", 0 }, { "olcir", "\xE2\xA6\xBE", 0 }, { "olcross", "\xE2\xA6\xBB", 0 }, { "oline", "\xE2\x80\xBE", 0 }, { "olt", "\xE2\xA7\x80", 0 }, { "omacr", "\xC5\x8D", 0 }, { "omega", "\xCF\x89", 0 }, { "omicron", "\xCE\xBF", 0 }, { "omid", "\xE2\xA6\xB6", 0 }, { "ominus", "\xE2\x8A\x96", 0 }, { "oopf", "\xF0\x9D\x95\xA0", 0 }, { "opar", "\xE2\xA6\xB7", 0 }, { "operp", "\xE2\xA6\xB9", 0 }, { "oplus", "\xE2\x8A\x95", 0 }, { "or", "\xE2\x88\xA8", 0 }, { "orarr", "\xE2\x86\xBB", 0 }, { "ord", "\xE2\xA9\x9D", 0 }, { "order", "\xE2\x84\xB4", 0 }, { "orderof", "\xE2\x84\xB4", 0 }, { "ordf", "\xC2\xAA", 0 }, { "ordm", "\xC2\xBA", 0 }, { "origof", "\xE2\x8A\xB6", 0 }, { "oror", "\xE2\xA9\x96", 0 }, { "orslope", "\xE2\xA9\x97", 0 }, { "orv", "\xE2\xA9\x9B", 0 }, { "oscr", "\xE2\x84\xB4", 0 }, { "oslash", "\xC3\xB8", 0 }, { "osol", "\xE2\x8A\x98", 0 }, { "otilde", "\xC3\xB5", 0 }, { "otimes", "\xE2\x8A\x97", 0 }, { "otimesas", "\xE2\xA8\xB6", 0 }, { "ouml", "\xC3\xB6", 0 }, { "ovbar", "\xE2\x8C\xBD", 0 }, { "par", "\xE2\x88\xA5", 0 }, { "para", "\xC2\xB6", 0 }, { "parallel", "\xE2\x88\xA5", 0 }, { "parsim", "\xE2\xAB\xB3", 0 }, { "parsl", "\xE2\xAB\xBD", 0 }, { "part", "\xE2\x88\x82", 0 }, { "pcy", "\xD0\xBF", 0 }, { "percnt", "\x25", 0 }, { "period", "\x2E", 0 }, { "permil", "\xE2\x80\xB0", 0 }, { "perp", "\xE2\x8A\xA5", 0 }, { "pertenk", "\xE2\x80\xB1", 0 }, { "pfr", "\xF0\x9D\x94\xAD", 0 }, { "phi", "\xCF\x86", 0 }, { "phiv", "\xCF\x95", 0 }, { "phmmat", "\xE2\x84\xB3", 0 }, { "phone", "\xE2\x98\x8E", 0 }, { "pi", "\xCF\x80", 0 }, { "pitchfork", "\xE2\x8B\x94", 0 }, { "piv", "\xCF\x96", 0 }, { "planck", "\xE2\x84\x8F", 0 }, { "planckh", "\xE2\x84\x8E", 0 }, { "plankv", "\xE2\x84\x8F", 0 }, { "plus", "\x2B", 0 }, { "plusacir", "\xE2\xA8\xA3", 0 }, { "plusb", "\xE2\x8A\x9E", 0 }, { "pluscir", "\xE2\xA8\xA2", 0 }, { "plusdo", "\xE2\x88\x94", 0 }, { "plusdu", "\xE2\xA8\xA5", 0 }, { "pluse", "\xE2\xA9\xB2", 0 }, { "plusmn", "\xC2\xB1", 0 }, { "plussim", "\xE2\xA8\xA6", 0 }, { "plustwo", "\xE2\xA8\xA7", 0 }, { "pm", "\xC2\xB1", 0 }, { "pointint", "\xE2\xA8\x95", 0 }, { "popf", "\xF0\x9D\x95\xA1", 0 }, { "pound", "\xC2\xA3", 0 }, { "pr", "\xE2\x89\xBA", 0 }, { "prE", "\xE2\xAA\xB3", 0 }, { "prap", "\xE2\xAA\xB7", 0 }, { "prcue", "\xE2\x89\xBC", 0 }, { "pre", "\xE2\xAA\xAF", 0 }, { "prec", "\xE2\x89\xBA", 0 }, { "precapprox", "\xE2\xAA\xB7", 0 }, { "preccurlyeq", "\xE2\x89\xBC", 0 }, { "preceq", "\xE2\xAA\xAF", 0 }, { "precnapprox", "\xE2\xAA\xB9", 0 }, { "precneqq", "\xE2\xAA\xB5", 0 }, { "precnsim", "\xE2\x8B\xA8", 0 }, { "precsim", "\xE2\x89\xBE", 0 }, { "prime", "\xE2\x80\xB2", 0 }, { "primes", "\xE2\x84\x99", 0 }, { "prnE", "\xE2\xAA\xB5", 0 }, { "prnap", "\xE2\xAA\xB9", 0 }, { "prnsim", "\xE2\x8B\xA8", 0 }, { "prod", "\xE2\x88\x8F", 0 }, { "profalar", "\xE2\x8C\xAE", 0 }, { "profline", "\xE2\x8C\x92", 0 }, { "profsurf", "\xE2\x8C\x93", 0 }, { "prop", "\xE2\x88\x9D", 0 }, { "propto", "\xE2\x88\x9D", 0 }, { "prsim", "\xE2\x89\xBE", 0 }, { "prurel", "\xE2\x8A\xB0", 0 }, { "pscr", "\xF0\x9D\x93\x85", 0 }, { "psi", "\xCF\x88", 0 }, { "puncsp", "\xE2\x80\x88", 0 }, { "qfr", "\xF0\x9D\x94\xAE", 0 }, { "qint", "\xE2\xA8\x8C", 0 }, { "qopf", "\xF0\x9D\x95\xA2", 0 }, { "qprime", "\xE2\x81\x97", 0 }, { "qscr", "\xF0\x9D\x93\x86", 0 }, { "quaternions", "\xE2\x84\x8D", 0 }, { "quatint", "\xE2\xA8\x96", 0 }, { "quest", "\x3F", 0 }, { "questeq", "\xE2\x89\x9F", 0 }, { "quot", "\x22", 0 }, { "rAarr", "\xE2\x87\x9B", 0 }, { "rArr", "\xE2\x87\x92", 0 }, { "rAtail", "\xE2\xA4\x9C", 0 }, { "rBarr", "\xE2\xA4\x8F", 0 }, { "rHar", "\xE2\xA5\xA4", 0 }, { "race", "\xE2\x88\xBD\xCC\xB1", 0 }, { "racute", "\xC5\x95", 0 }, { "radic", "\xE2\x88\x9A", 0 }, { "raemptyv", "\xE2\xA6\xB3", 0 }, { "rang", "\xE2\x9F\xA9", 0 }, { "rangd", "\xE2\xA6\x92", 0 }, { "range", "\xE2\xA6\xA5", 0 }, { "rangle", "\xE2\x9F\xA9", 0 }, { "raquo", "\xC2\xBB", 0 }, { "rarr", "\xE2\x86\x92", 0 }, { "rarrap", "\xE2\xA5\xB5", 0 }, { "rarrb", "\xE2\x87\xA5", 0 }, { "rarrbfs", "\xE2\xA4\xA0", 0 }, { "rarrc", "\xE2\xA4\xB3", 0 }, { "rarrfs", "\xE2\xA4\x9E", 0 }, { "rarrhk", "\xE2\x86\xAA", 0 }, { "rarrlp", "\xE2\x86\xAC", 0 }, { "rarrpl", "\xE2\xA5\x85", 0 }, { "rarrsim", "\xE2\xA5\xB4", 0 }, { "rarrtl", "\xE2\x86\xA3", 0 }, { "rarrw", "\xE2\x86\x9D", 0 }, { "ratail", "\xE2\xA4\x9A", 0 }, { "ratio", "\xE2\x88\xB6", 0 }, { "rationals", "\xE2\x84\x9A", 0 }, { "rbarr", "\xE2\xA4\x8D", 0 }, { "rbbrk", "\xE2\x9D\xB3", 0 }, { "rbrace", "\x7D", 0 }, { "rbrack", "\x5D", 0 }, { "rbrke", "\xE2\xA6\x8C", 0 }, { "rbrksld", "\xE2\xA6\x8E", 0 }, { "rbrkslu", "\xE2\xA6\x90", 0 }, { "rcaron", "\xC5\x99", 0 }, { "rcedil", "\xC5\x97", 0 }, { "rceil", "\xE2\x8C\x89", 0 }, { "rcub", "\x7D", 0 }, { "rcy", "\xD1\x80", 0 }, { "rdca", "\xE2\xA4\xB7", 0 }, { "rdldhar", "\xE2\xA5\xA9", 0 }, { "rdquo", "\xE2\x80\x9D", 0 }, { "rdquor", "\xE2\x80\x9D", 0 }, { "rdsh", "\xE2\x86\xB3", 0 }, { "real", "\xE2\x84\x9C", 0 }, { "realine", "\xE2\x84\x9B", 0 }, { "realpart", "\xE2\x84\x9C", 0 }, { "reals", "\xE2\x84\x9D", 0 }, { "rect", "\xE2\x96\xAD", 0 }, { "reg", "\xC2\xAE", 0 }, { "rfisht", "\xE2\xA5\xBD", 0 }, { "rfloor", "\xE2\x8C\x8B", 0 }, { "rfr", "\xF0\x9D\x94\xAF", 0 }, { "rhard", "\xE2\x87\x81", 0 }, { "rharu", "\xE2\x87\x80", 0 }, { "rharul", "\xE2\xA5\xAC", 0 }, { "rho", "\xCF\x81", 0 }, { "rhov", "\xCF\xB1", 0 }, { "rightarrow", "\xE2\x86\x92", 0 }, { "rightarrowtail", "\xE2\x86\xA3", 0 }, { "rightharpoondown", "\xE2\x87\x81", 0 }, { "rightharpoonup", "\xE2\x87\x80", 0 }, { "rightleftarrows", "\xE2\x87\x84", 0 }, { "rightleftharpoons", "\xE2\x87\x8C", 0 }, { "rightrightarrows", "\xE2\x87\x89", 0 }, { "rightsquigarrow", "\xE2\x86\x9D", 0 }, { "rightthreetimes", "\xE2\x8B\x8C", 0 }, { "ring", "\xCB\x9A", 0 }, { "risingdotseq", "\xE2\x89\x93", 0 }, { "rlarr", "\xE2\x87\x84", 0 }, { "rlhar", "\xE2\x87\x8C", 0 }, { "rlm", "\xE2\x80\x8F", 0 }, { "rmoust", "\xE2\x8E\xB1", 0 }, { "rmoustache", "\xE2\x8E\xB1", 0 }, { "rnmid", "\xE2\xAB\xAE", 0 }, { "roang", "\xE2\x9F\xAD", 0 }, { "roarr", "\xE2\x87\xBE", 0 }, { "robrk", "\xE2\x9F\xA7", 0 }, { "ropar", "\xE2\xA6\x86", 0 }, { "ropf", "\xF0\x9D\x95\xA3", 0 }, { "roplus", "\xE2\xA8\xAE", 0 }, { "rotimes", "\xE2\xA8\xB5", 0 }, { "rpar", "\x29", 0 }, { "rpargt", "\xE2\xA6\x94", 0 }, { "rppolint", "\xE2\xA8\x92", 0 }, { "rrarr", "\xE2\x87\x89", 0 }, { "rsaquo", "\xE2\x80\xBA", 0 }, { "rscr", "\xF0\x9D\x93\x87", 0 }, { "rsh", "\xE2\x86\xB1", 0 }, { "rsqb", "\x5D", 0 }, { "rsquo", "\xE2\x80\x99", 0 }, { "rsquor", "\xE2\x80\x99", 0 }, { "rthree", "\xE2\x8B\x8C", 0 }, { "rtimes", "\xE2\x8B\x8A", 0 }, { "rtri", "\xE2\x96\xB9", 0 }, { "rtrie", "\xE2\x8A\xB5", 0 }, { "rtrif", "\xE2\x96\xB8", 0 }, { "rtriltri", "\xE2\xA7\x8E", 0 }, { "ruluhar", "\xE2\xA5\xA8", 0 }, { "rx", "\xE2\x84\x9E", 0 }, { "sacute", "\xC5\x9B", 0 }, { "sbquo", "\xE2\x80\x9A", 0 }, { "sc", "\xE2\x89\xBB", 0 }, { "scE", "\xE2\xAA\xB4", 0 }, { "scap", "\xE2\xAA\xB8", 0 }, { "scaron", "\xC5\xA1", 0 }, { "sccue", "\xE2\x89\xBD", 0 }, { "sce", "\xE2\xAA\xB0", 0 }, { "scedil", "\xC5\x9F", 0 }, { "scirc", "\xC5\x9D", 0 }, { "scnE", "\xE2\xAA\xB6", 0 }, { "scnap", "\xE2\xAA\xBA", 0 }, { "scnsim", "\xE2\x8B\xA9", 0 }, { "scpolint", "\xE2\xA8\x93", 0 }, { "scsim", "\xE2\x89\xBF", 0 }, { "scy", "\xD1\x81", 0 }, { "sdot", "\xE2\x8B\x85", 0 }, { "sdotb", "\xE2\x8A\xA1", 0 }, { "sdote", "\xE2\xA9\xA6", 0 }, { "seArr", "\xE2\x87\x98", 0 }, { "searhk", "\xE2\xA4\xA5", 0 }, { "searr", "\xE2\x86\x98", 0 }, { "searrow", "\xE2\x86\x98", 0 }, { "sect", "\xC2\xA7", 0 }, { "semi", "\x3B", 0 }, { "seswar", "\xE2\xA4\xA9", 0 }, { "setminus", "\xE2\x88\x96", 0 }, { "setmn", "\xE2\x88\x96", 0 }, { "sext", "\xE2\x9C\xB6", 0 }, { "sfr", "\xF0\x9D\x94\xB0", 0 }, { "sfrown", "\xE2\x8C\xA2", 0 }, { "sharp", "\xE2\x99\xAF", 0 }, { "shchcy", "\xD1\x89", 0 }, { "shcy", "\xD1\x88", 0 }, { "shortmid", "\xE2\x88\xA3", 0 }, { "shortparallel", "\xE2\x88\xA5", 0 }, { "shy", "\xC2\xAD", 0 }, { "sigma", "\xCF\x83", 0 }, { "sigmaf", "\xCF\x82", 0 }, { "sigmav", "\xCF\x82", 0 }, { "sim", "\xE2\x88\xBC", 0 }, { "simdot", "\xE2\xA9\xAA", 0 }, { "sime", "\xE2\x89\x83", 0 }, { "simeq", "\xE2\x89\x83", 0 }, { "simg", "\xE2\xAA\x9E", 0 }, { "simgE", "\xE2\xAA\xA0", 0 }, { "siml", "\xE2\xAA\x9D", 0 }, { "simlE", "\xE2\xAA\x9F", 0 }, { "simne", "\xE2\x89\x86", 0 }, { "simplus", "\xE2\xA8\xA4", 0 }, { "simrarr", "\xE2\xA5\xB2", 0 }, { "slarr", "\xE2\x86\x90", 0 }, { "smallsetminus", "\xE2\x88\x96", 0 }, { "smashp", "\xE2\xA8\xB3", 0 }, { "smeparsl", "\xE2\xA7\xA4", 0 }, { "smid", "\xE2\x88\xA3", 0 }, { "smile", "\xE2\x8C\xA3", 0 }, { "smt", "\xE2\xAA\xAA", 0 }, { "smte", "\xE2\xAA\xAC", 0 }, { "smtes", "\xE2\xAA\xAC\xEF\xB8\x80", 0 }, { "softcy", "\xD1\x8C", 0 }, { "sol", "\x2F", 0 }, { "solb", "\xE2\xA7\x84", 0 }, { "solbar", "\xE2\x8C\xBF", 0 }, { "sopf", "\xF0\x9D\x95\xA4", 0 }, { "spades", "\xE2\x99\xA0", 0 }, { "spadesuit", "\xE2\x99\xA0", 0 }, { "spar", "\xE2\x88\xA5", 0 }, { "sqcap", "\xE2\x8A\x93", 0 }, { "sqcaps", "\xE2\x8A\x93\xEF\xB8\x80", 0 }, { "sqcup", "\xE2\x8A\x94", 0 }, { "sqcups", "\xE2\x8A\x94\xEF\xB8\x80", 0 }, { "sqsub", "\xE2\x8A\x8F", 0 }, { "sqsube", "\xE2\x8A\x91", 0 }, { "sqsubset", "\xE2\x8A\x8F", 0 }, { "sqsubseteq", "\xE2\x8A\x91", 0 }, { "sqsup", "\xE2\x8A\x90", 0 }, { "sqsupe", "\xE2\x8A\x92", 0 }, { "sqsupset", "\xE2\x8A\x90", 0 }, { "sqsupseteq", "\xE2\x8A\x92", 0 }, { "squ", "\xE2\x96\xA1", 0 }, { "square", "\xE2\x96\xA1", 0 }, { "squarf", "\xE2\x96\xAA", 0 }, { "squf", "\xE2\x96\xAA", 0 }, { "srarr", "\xE2\x86\x92", 0 }, { "sscr", "\xF0\x9D\x93\x88", 0 }, { "ssetmn", "\xE2\x88\x96", 0 }, { "ssmile", "\xE2\x8C\xA3", 0 }, { "sstarf", "\xE2\x8B\x86", 0 }, { "star", "\xE2\x98\x86", 0 }, { "starf", "\xE2\x98\x85", 0 }, { "straightepsilon", "\xCF\xB5", 0 }, { "straightphi", "\xCF\x95", 0 }, { "strns", "\xC2\xAF", 0 }, { "sub", "\xE2\x8A\x82", 0 }, { "subE", "\xE2\xAB\x85", 0 }, { "subdot", "\xE2\xAA\xBD", 0 }, { "sube", "\xE2\x8A\x86", 0 }, { "subedot", "\xE2\xAB\x83", 0 }, { "submult", "\xE2\xAB\x81", 0 }, { "subnE", "\xE2\xAB\x8B", 0 }, { "subne", "\xE2\x8A\x8A", 0 }, { "subplus", "\xE2\xAA\xBF", 0 }, { "subrarr", "\xE2\xA5\xB9", 0 }, { "subset", "\xE2\x8A\x82", 0 }, { "subseteq", "\xE2\x8A\x86", 0 }, { "subseteqq", "\xE2\xAB\x85", 0 }, { "subsetneq", "\xE2\x8A\x8A", 0 }, { "subsetneqq", "\xE2\xAB\x8B", 0 }, { "subsim", "\xE2\xAB\x87", 0 }, { "subsub", "\xE2\xAB\x95", 0 }, { "subsup", "\xE2\xAB\x93", 0 }, { "succ", "\xE2\x89\xBB", 0 }, { "succapprox", "\xE2\xAA\xB8", 0 }, { "succcurlyeq", "\xE2\x89\xBD", 0 }, { "succeq", "\xE2\xAA\xB0", 0 }, { "succnapprox", "\xE2\xAA\xBA", 0 }, { "succneqq", "\xE2\xAA\xB6", 0 }, { "succnsim", "\xE2\x8B\xA9", 0 }, { "succsim", "\xE2\x89\xBF", 0 }, { "sum", "\xE2\x88\x91", 0 }, { "sung", "\xE2\x99\xAA", 0 }, { "sup", "\xE2\x8A\x83", 0 }, { "sup1", "\xC2\xB9", 0 }, { "sup2", "\xC2\xB2", 0 }, { "sup3", "\xC2\xB3", 0 }, { "supE", "\xE2\xAB\x86", 0 }, { "supdot", "\xE2\xAA\xBE", 0 }, { "supdsub", "\xE2\xAB\x98", 0 }, { "supe", "\xE2\x8A\x87", 0 }, { "supedot", "\xE2\xAB\x84", 0 }, { "suphsol", "\xE2\x9F\x89", 0 }, { "suphsub", "\xE2\xAB\x97", 0 }, { "suplarr", "\xE2\xA5\xBB", 0 }, { "supmult", "\xE2\xAB\x82", 0 }, { "supnE", "\xE2\xAB\x8C", 0 }, { "supne", "\xE2\x8A\x8B", 0 }, { "supplus", "\xE2\xAB\x80", 0 }, { "supset", "\xE2\x8A\x83", 0 }, { "supseteq", "\xE2\x8A\x87", 0 }, { "supseteqq", "\xE2\xAB\x86", 0 }, { "supsetneq", "\xE2\x8A\x8B", 0 }, { "supsetneqq", "\xE2\xAB\x8C", 0 }, { "supsim", "\xE2\xAB\x88", 0 }, { "supsub", "\xE2\xAB\x94", 0 }, { "supsup", "\xE2\xAB\x96", 0 }, { "swArr", "\xE2\x87\x99", 0 }, { "swarhk", "\xE2\xA4\xA6", 0 }, { "swarr", "\xE2\x86\x99", 0 }, { "swarrow", "\xE2\x86\x99", 0 }, { "swnwar", "\xE2\xA4\xAA", 0 }, { "szlig", "\xC3\x9F", 0 }, { "target", "\xE2\x8C\x96", 0 }, { "tau", "\xCF\x84", 0 }, { "tbrk", "\xE2\x8E\xB4", 0 }, { "tcaron", "\xC5\xA5", 0 }, { "tcedil", "\xC5\xA3", 0 }, { "tcy", "\xD1\x82", 0 }, { "tdot", "\xE2\x83\x9B", 0 }, { "telrec", "\xE2\x8C\x95", 0 }, { "tfr", "\xF0\x9D\x94\xB1", 0 }, { "there4", "\xE2\x88\xB4", 0 }, { "therefore", "\xE2\x88\xB4", 0 }, { "theta", "\xCE\xB8", 0 }, { "thetasym", "\xCF\x91", 0 }, { "thetav", "\xCF\x91", 0 }, { "thickapprox", "\xE2\x89\x88", 0 }, { "thicksim", "\xE2\x88\xBC", 0 }, { "thinsp", "\xE2\x80\x89", 0 }, { "thkap", "\xE2\x89\x88", 0 }, { "thksim", "\xE2\x88\xBC", 0 }, { "thorn", "\xC3\xBE", 0 }, { "tilde", "\xCB\x9C", 0 }, { "times", "\xC3\x97", 0 }, { "timesb", "\xE2\x8A\xA0", 0 }, { "timesbar", "\xE2\xA8\xB1", 0 }, { "timesd", "\xE2\xA8\xB0", 0 }, { "tint", "\xE2\x88\xAD", 0 }, { "toea", "\xE2\xA4\xA8", 0 }, { "top", "\xE2\x8A\xA4", 0 }, { "topbot", "\xE2\x8C\xB6", 0 }, { "topcir", "\xE2\xAB\xB1", 0 }, { "topf", "\xF0\x9D\x95\xA5", 0 }, { "topfork", "\xE2\xAB\x9A", 0 }, { "tosa", "\xE2\xA4\xA9", 0 }, { "tprime", "\xE2\x80\xB4", 0 }, { "trade", "\xE2\x84\xA2", 0 }, { "triangle", "\xE2\x96\xB5", 0 }, { "triangledown", "\xE2\x96\xBF", 0 }, { "triangleleft", "\xE2\x97\x83", 0 }, { "trianglelefteq", "\xE2\x8A\xB4", 0 }, { "triangleq", "\xE2\x89\x9C", 0 }, { "triangleright", "\xE2\x96\xB9", 0 }, { "trianglerighteq", "\xE2\x8A\xB5", 0 }, { "tridot", "\xE2\x97\xAC", 0 }, { "trie", "\xE2\x89\x9C", 0 }, { "triminus", "\xE2\xA8\xBA", 0 }, { "triplus", "\xE2\xA8\xB9", 0 }, { "trisb", "\xE2\xA7\x8D", 0 }, { "tritime", "\xE2\xA8\xBB", 0 }, { "trpezium", "\xE2\x8F\xA2", 0 }, { "tscr", "\xF0\x9D\x93\x89", 0 }, { "tscy", "\xD1\x86", 0 }, { "tshcy", "\xD1\x9B", 0 }, { "tstrok", "\xC5\xA7", 0 }, { "twixt", "\xE2\x89\xAC", 0 }, { "twoheadleftarrow", "\xE2\x86\x9E", 0 }, { "twoheadrightarrow", "\xE2\x86\xA0", 0 }, { "uArr", "\xE2\x87\x91", 0 }, { "uHar", "\xE2\xA5\xA3", 0 }, { "uacute", "\xC3\xBA", 0 }, { "uarr", "\xE2\x86\x91", 0 }, { "ubrcy", "\xD1\x9E", 0 }, { "ubreve", "\xC5\xAD", 0 }, { "ucirc", "\xC3\xBB", 0 }, { "ucy", "\xD1\x83", 0 }, { "udarr", "\xE2\x87\x85", 0 }, { "udblac", "\xC5\xB1", 0 }, { "udhar", "\xE2\xA5\xAE", 0 }, { "ufisht", "\xE2\xA5\xBE", 0 }, { "ufr", "\xF0\x9D\x94\xB2", 0 }, { "ugrave", "\xC3\xB9", 0 }, { "uharl", "\xE2\x86\xBF", 0 }, { "uharr", "\xE2\x86\xBE", 0 }, { "uhblk", "\xE2\x96\x80", 0 }, { "ulcorn", "\xE2\x8C\x9C", 0 }, { "ulcorner", "\xE2\x8C\x9C", 0 }, { "ulcrop", "\xE2\x8C\x8F", 0 }, { "ultri", "\xE2\x97\xB8", 0 }, { "umacr", "\xC5\xAB", 0 }, { "uml", "\xC2\xA8", 0 }, { "uogon", "\xC5\xB3", 0 }, { "uopf", "\xF0\x9D\x95\xA6", 0 }, { "uparrow", "\xE2\x86\x91", 0 }, { "updownarrow", "\xE2\x86\x95", 0 }, { "upharpoonleft", "\xE2\x86\xBF", 0 }, { "upharpoonright", "\xE2\x86\xBE", 0 }, { "uplus", "\xE2\x8A\x8E", 0 }, { "upsi", "\xCF\x85", 0 }, { "upsih", "\xCF\x92", 0 }, { "upsilon", "\xCF\x85", 0 }, { "upuparrows", "\xE2\x87\x88", 0 }, { "urcorn", "\xE2\x8C\x9D", 0 }, { "urcorner", "\xE2\x8C\x9D", 0 }, { "urcrop", "\xE2\x8C\x8E", 0 }, { "uring", "\xC5\xAF", 0 }, { "urtri", "\xE2\x97\xB9", 0 }, { "uscr", "\xF0\x9D\x93\x8A", 0 }, { "utdot", "\xE2\x8B\xB0", 0 }, { "utilde", "\xC5\xA9", 0 }, { "utri", "\xE2\x96\xB5", 0 }, { "utrif", "\xE2\x96\xB4", 0 }, { "uuarr", "\xE2\x87\x88", 0 }, { "uuml", "\xC3\xBC", 0 }, { "uwangle", "\xE2\xA6\xA7", 0 }, { "vArr", "\xE2\x87\x95", 0 }, { "vBar", "\xE2\xAB\xA8", 0 }, { "vBarv", "\xE2\xAB\xA9", 0 }, { "vDash", "\xE2\x8A\xA8", 0 }, { "vangrt", "\xE2\xA6\x9C", 0 }, { "varepsilon", "\xCF\xB5", 0 }, { "varkappa", "\xCF\xB0", 0 }, { "varnothing", "\xE2\x88\x85", 0 }, { "varphi", "\xCF\x95", 0 }, { "varpi", "\xCF\x96", 0 }, { "varpropto", "\xE2\x88\x9D", 0 }, { "varr", "\xE2\x86\x95", 0 }, { "varrho", "\xCF\xB1", 0 }, { "varsigma", "\xCF\x82", 0 }, { "varsubsetneq", "\xE2\x8A\x8A\xEF\xB8\x80", 0 }, { "varsubsetneqq", "\xE2\xAB\x8B\xEF\xB8\x80", 0 }, { "varsupsetneq", "\xE2\x8A\x8B\xEF\xB8\x80", 0 }, { "varsupsetneqq", "\xE2\xAB\x8C\xEF\xB8\x80", 0 }, { "vartheta", "\xCF\x91", 0 }, { "vartriangleleft", "\xE2\x8A\xB2", 0 }, { "vartriangleright", "\xE2\x8A\xB3", 0 }, { "vcy", "\xD0\xB2", 0 }, { "vdash", "\xE2\x8A\xA2", 0 }, { "vee", "\xE2\x88\xA8", 0 }, { "veebar", "\xE2\x8A\xBB", 0 }, { "veeeq", "\xE2\x89\x9A", 0 }, { "vellip", "\xE2\x8B\xAE", 0 }, { "verbar", "\x7C", 0 }, { "vert", "\x7C", 0 }, { "vfr", "\xF0\x9D\x94\xB3", 0 }, { "vltri", "\xE2\x8A\xB2", 0 }, { "vnsub", "\xE2\x8A\x82\xE2\x83\x92", 0 }, { "vnsup", "\xE2\x8A\x83\xE2\x83\x92", 0 }, { "vopf", "\xF0\x9D\x95\xA7", 0 }, { "vprop", "\xE2\x88\x9D", 0 }, { "vrtri", "\xE2\x8A\xB3", 0 }, { "vscr", "\xF0\x9D\x93\x8B", 0 }, { "vsubnE", "\xE2\xAB\x8B\xEF\xB8\x80", 0 }, { "vsubne", "\xE2\x8A\x8A\xEF\xB8\x80", 0 }, { "vsupnE", "\xE2\xAB\x8C\xEF\xB8\x80", 0 }, { "vsupne", "\xE2\x8A\x8B\xEF\xB8\x80", 0 }, { "vzigzag", "\xE2\xA6\x9A", 0 }, { "wcirc", "\xC5\xB5", 0 }, { "wedbar", "\xE2\xA9\x9F", 0 }, { "wedge", "\xE2\x88\xA7", 0 }, { "wedgeq", "\xE2\x89\x99", 0 }, { "weierp", "\xE2\x84\x98", 0 }, { "wfr", "\xF0\x9D\x94\xB4", 0 }, { "wopf", "\xF0\x9D\x95\xA8", 0 }, { "wp", "\xE2\x84\x98", 0 }, { "wr", "\xE2\x89\x80", 0 }, { "wreath", "\xE2\x89\x80", 0 }, { "wscr", "\xF0\x9D\x93\x8C", 0 }, { "xcap", "\xE2\x8B\x82", 0 }, { "xcirc", "\xE2\x97\xAF", 0 }, { "xcup", "\xE2\x8B\x83", 0 }, { "xdtri", "\xE2\x96\xBD", 0 }, { "xfr", "\xF0\x9D\x94\xB5", 0 }, { "xhArr", "\xE2\x9F\xBA", 0 }, { "xharr", "\xE2\x9F\xB7", 0 }, { "xi", "\xCE\xBE", 0 }, { "xlArr", "\xE2\x9F\xB8", 0 }, { "xlarr", "\xE2\x9F\xB5", 0 }, { "xmap", "\xE2\x9F\xBC", 0 }, { "xnis", "\xE2\x8B\xBB", 0 }, { "xodot", "\xE2\xA8\x80", 0 }, { "xopf", "\xF0\x9D\x95\xA9", 0 }, { "xoplus", "\xE2\xA8\x81", 0 }, { "xotime", "\xE2\xA8\x82", 0 }, { "xrArr", "\xE2\x9F\xB9", 0 }, { "xrarr", "\xE2\x9F\xB6", 0 }, { "xscr", "\xF0\x9D\x93\x8D", 0 }, { "xsqcup", "\xE2\xA8\x86", 0 }, { "xuplus", "\xE2\xA8\x84", 0 }, { "xutri", "\xE2\x96\xB3", 0 }, { "xvee", "\xE2\x8B\x81", 0 }, { "xwedge", "\xE2\x8B\x80", 0 }, { "yacute", "\xC3\xBD", 0 }, { "yacy", "\xD1\x8F", 0 }, { "ycirc", "\xC5\xB7", 0 }, { "ycy", "\xD1\x8B", 0 }, { "yen", "\xC2\xA5", 0 }, { "yfr", "\xF0\x9D\x94\xB6", 0 }, { "yicy", "\xD1\x97", 0 }, { "yopf", "\xF0\x9D\x95\xAA", 0 }, { "yscr", "\xF0\x9D\x93\x8E", 0 }, { "yucy", "\xD1\x8E", 0 }, { "yuml", "\xC3\xBF", 0 }, { "zacute", "\xC5\xBA", 0 }, { "zcaron", "\xC5\xBE", 0 }, { "zcy", "\xD0\xB7", 0 }, { "zdot", "\xC5\xBC", 0 }, { "zeetrf", "\xE2\x84\xA8", 0 }, { "zeta", "\xCE\xB6", 0 }, { "zfr", "\xF0\x9D\x94\xB7", 0 }, { "zhcy", "\xD0\xB6", 0 }, { "zigrarr", "\xE2\x87\x9D", 0 }, { "zopf", "\xF0\x9D\x95\xAB", 0 }, { "zscr", "\xF0\x9D\x93\x8F", 0 }, { "zwj", "\xE2\x80\x8D", 0 }, { "zwnj", "\xE2\x80\x8C", 0 }, } test json-5.1 {-jsonmaxnesting 0} { set result [catch {dom parse -json -jsonmaxnesting 0 {{"this":"that"}}} errMsg] list $result $errMsg } {1 {error "Maximum JSON object/array nesting depth exceeded" at position 0 "{ <--Error-- "this":"that"}"}} test json-5.2 {-jsonmaxnesting 0} { set result [catch {dom parse -json -jsonmaxnesting 0 {["this","that"]}} errMsg] list $result $errMsg } {1 {error "Maximum JSON object/array nesting depth exceeded" at position 0 "[ <--Error-- "this","that"]"}} test json-5.3 {-jsonmaxnesting 0} { set result [catch {dom parse -jsonroot o -json -jsonmaxnesting 0 {["this","that"]}} errMsg] list $result $errMsg } {1 {error "Maximum JSON object/array nesting depth exceeded" at position 0 "[ <--Error-- "this","that"]"}} test json-5.4 {-jsonmaxnesting} { set doc [dom parse -json -jsonmaxnesting 2 {{"this":{"foo":"that"}}}] set result [$doc asXML -indent none] $doc delete set result } {that} test json-5.5 {-jsonmaxnesting} { set result [catch {dom parse -json -jsonmaxnesting 1 \ {{"this":{"foo":"that"}}}} errMsg] list $result $errMsg } {1 {error "Maximum JSON object/array nesting depth exceeded" at position 8 "{"this":{ <--Error-- "foo":"that"}}"}} test json-5.6 {-jsonmaxnesting} { set doc [dom parse -json -jsonmaxnesting 2 { { "this": { "foo":"that", "bar":"grill" }, "two": "value", "three": { "t1":"t1value", "t2":"t2value" }, "four": ["a","b","c"] }}] set result [$doc asXML] $doc delete set result } { that grill value t1value t2value abc } set jsons { {{"a":"avalue","b":"bvalue","c":0.123}} {{"a":["avalue"]}} {{"a":"a value","b":"1value"}} {{"a":{"aa":"aavalue","bb":"bbvalue"},"b":"bvalue","c":0.123}} {{"a":[1,2,3,4,"abc"]}} {{"a":true,"b":false,"c":null,"d":"true","e":""}} {{"a":{"aa":[1,2,3,4,"abc"]},"b":"bvalue"}} {{"a":true,"b":false,"c":null,"d":"true","e":""}} {["a",["aa","bb"],"b"]} {{"a":"a\nvalue","b":"value\tvalue"}} {["\\\\a"]} {["a\"b"]} {{"b":"a \"b c\" d","b":"a \"b c\" d"}} {{"this":"a\nbc"}} {{"this":{"foo":"that"}}} {{"this":{"foo":"that","bar":"grill"},"two":"value","three":{"t1":"t1value","t2":"t2value"},"four":["a","b","c"]}} {"only a string"} {null} {1.23} {true} {false} {{}} {[]} {[[]]} {[["x"]]} {""} {[[[[["a"]]]]]} {{"x":[{"id":"foo"}]}} {"http://foo.bar"} } test json-6.1 {asJSON} { set failedlist [list] set ind 0 foreach json $jsons { set doc [dom parse -json $json] set out [$doc asJSON] if {$json ne $out} { lappend failedlist "$ind : '$json' : '$out'" } incr ind } set failedlist } {} test json-6.2 {asJSON - slash will not be escaped while serializing} { set doc [dom parse -json {"http:\/\/foo.bar"}] set result [$doc asJSON] $doc delete set result } {"http://foo.bar"} test json-6.3 {asJSON - docNode serialization} { dom createDocumentNode docNode set result [$docNode asJSON] $docNode delete set result } {{}} test json-6.4 {asJSON - doc serialization} { dom createDocument root docNode set result [$docNode asJSON] $docNode delete set result } {{"root":""}} test json-6.5 {asJSON - serialization of control characters} { set doc [dom parse -json "\"a\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\u0008\\u0009\\u000A\\u000B\\u000C\\u000D\\u000E\\u000F\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F\\u0020b\""] set result [$doc asJSON] $doc delete set result } {"a\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f b"} test json-6.6 {asJSON -indent} { set doc [dom parse -json {{"a":{"aa":[1,2,3,4,"abc"]},"b":"bvalue"}}] set result [$doc asJSON -indent 2] $doc delete set result } {{ "a": { "aa": [ 1, 2, 3, 4, "abc" ] }, "b": "bvalue" }} test json-6.7 {asJSON -indent} { set doc [dom parse -json {{"a":{"aa":[1,2,3,4,"abc"]},"b":"bvalue"}}] set result [$doc asJSON -indent tabs] $doc delete set result } {{ "a": { "aa": [ 1, 2, 3, 4, "abc" ] }, "b": "bvalue" }} if {[info commands _dom] eq ""} { test json-7.1 {jsonType} { set doc [dom parse {foo}] set root [$doc documentElement] set result [list] lappend result [$root asJSON] lappend result [$root jsonType] $root jsonType ARRAY lappend result [$root asJSON] $doc delete set result } {{"foo"} NONE {["foo"]}} test json-7.2 {jsonType} { set doc [dom createDocumentNode] set result [$doc jsonType] lappend result [$doc asJSON] lappend result [catch {$doc jsonType foo}] $doc jsonType ARRAY lappend result [$doc asJSON] $doc jsonType OBJECT lappend result [$doc asJSON] $doc delete set result } {NONE {{}} 1 {[]} {{}}} test json-8.1 {appendFromScript} { set doc [dom createDocumentNode] $doc appendFromScript { nodeCmds::e1 } set result [list] lappend result [$doc asJSON] set root [$doc documentElement] lappend result [$root asJSON] $doc removeChild [$doc firstChild] $doc appendFromScript { nodeCmds::jae1 } lappend result [$doc asJSON] set root [$doc documentElement] lappend result [$root asJSON] lappend result [$root jsonType] $doc delete set result } {{{"e1":""}} {{}} {{"jae1":[]}} {[]} ARRAY} test json-8.2 {appendFromScript} { set doc [dom createDocumentNode] $doc appendFromScript { nodeCmds::t "some string" } set result [$doc asJSON] $doc delete set result } {"some string"} test json-8.3 {appendFromScript} { set doc [dom createDocumentNode] $doc appendFromScript { nodeCmds::t "" nodeCmds::true "" nodeCmds::false "" nodeCmds::null "" } set result [$doc asJSON] $doc delete set result } {["",true,false,null]} test json-8.4 {appendFromScript - text node with type NUMBER} { set doc [dom createDocumentNode] $doc appendFromScript { nodeCmds::number "" nodeCmds::number "0" nodeCmds::number "123456789012345678901234567890.12345679e-0003" nodeCmds::number "42 " nodeCmds::number " 42" nodeCmds::number "-" } set result [$doc asJSON] $doc delete set result } {["",0,123456789012345678901234567890.12345679e-0003,"42 "," 42","-"]} test json-8.5 {createNodeCmd - wrong jsonType} { catch {dom createNodeCmd -jsonType OBJECT textNode textNodeWithJsonTypeObject} } 1 test json-8.6 {text nodes with json type NULL, TRUE or FALSE} { set doc [dom createDocumentNode] $doc jsonType ARRAY $doc appendFromScript { nodeCmds::null nodeCmds::true nodeCmds::false } set result [$doc asJSON] $doc delete set result } {[null,true,false]} } test json-9.1 {cloneNode -deep} { dom parse -json {[["a",1,"b",{"foo":"bar","baz":"boo"},null],"",null]} doc dom createDocument some other $other documentElement root $root appendChild [[$doc firstChild] cloneNode -deep] set result [[$root firstChild] asJSON] $doc delete $other delete set result } {["a",1,"b",{"foo":"bar","baz":"boo"},null]} test json-9.2 {cloneNode} { dom parse -json {[["a",1,"b",{"foo":"bar","baz":"boo"},null],"",null]} doc dom createDocument some other $other documentElement root $root appendChild [[$doc firstChild] cloneNode] set result [[$root firstChild] asJSON] $doc delete $other delete set result } {[]} test json-9.3 {cloneNode} { dom parse -json {{"string":"bar","number":1,"boolean":true,"array":[1,2,3],"object":{"foo":"bar","baz":"boo"}}} doc dom createDocument some other $other documentElement root foreach child [$doc childNodes] { $root appendChild [$child cloneNode -deep] } set result [list] foreach child [$root childNodes] { lappend result [$child asJSON] } $doc delete $other delete set result } {{"bar"} 1 true {[1,2,3]} {{"foo":"bar","baz":"boo"}}} test json-10.1 {asDict} { set json {{ "Titel": "Wirtschaftsinformatik", "Keywords": "Documentation for Keywords", "Keywords": ["Introduction","Basics"] }} set doc [dom parse -json $json] set dict [::tdom::json::asDict $doc] $doc delete dict get $dict Keywords } {Introduction Basics} test json-10.2 {asDict object members named objectcontainer and arraycontainer} { set json {{ "Titel": "Wirtschaftsinformatik", "objectcontainer": {"a":"b","c":"d"}, "arraycontainer": ["Introduction","Basics"] }} set doc [dom parse -json $json] set dict [::tdom::json::asDict $doc] $doc delete set result "" lappend result [dict get $dict objectcontainer] lappend result [dict get $dict arraycontainer] } {{a b c d} {Introduction Basics}} test json-10.2.1 {asDict} { set json {{ "Titel": "Wirtschaftsinformatik", "Keywords": "Documentation for Keywords", "Keywords": ["Introduction","Basics"] }} set doc [dom parse -json $json] set dict [::tdom::json::asDict $doc] $doc delete dict get $dict Keywords } {Introduction Basics} test json-10.2.2 {asDict object members named objectcontainer and arraycontainer} { set json {{ "Titel": "Wirtschaftsinformatik", "objectcontainer": {"a":"b","c":"d"}, "arraycontainer": ["Introduction","Basics"] }} set doc [dom parse -json $json] set dict [::tdom::json::asDict $doc] $doc delete set result "" lappend result [dict get $dict objectcontainer] lappend result [dict get $dict arraycontainer] } {{a b c d} {Introduction Basics}} test json-10.3 {asTclValue} { set json {{ "Titel": "Wirtschaftsinformatik", "Keywords": "Documentation for Keywords", "Keywords": ["Introduction","Basics"] }} set doc [dom parse -json $json] set dict [$doc asTclValue] $doc delete dict get $dict Keywords } {Introduction Basics} test json-10.3.1 {asTclValue} { set json {{ "Titel": "Wirtschaftsinformatik", "Keywords": "Documentation for Keywords", "Keywords": ["Introduction","Basics"] }} set doc [dom parse -json -jsonroot myjson $json] set myjson [$doc documentElement] set dict [$myjson asTclValue] $doc delete dict get $dict Keywords } {Introduction Basics} test json-10.4 {asTclValue object members named objectcontainer and arraycontainer} { set json {{ "Titel": "Wirtschaftsinformatik", "objectcontainer": {"a":"b","c":"d"}, "arraycontainer": ["Introduction","Basics"] }} set doc [dom parse -json $json] set dict [$doc asTclValue] $doc delete set result "" lappend result [dict get $dict objectcontainer] lappend result [dict get $dict arraycontainer] } {{a b c d} {Introduction Basics}} test json-10.4.1 {asTclValue object members named objectcontainer and arraycontainer} { set json {{ "Titel": "Wirtschaftsinformatik", "objectcontainer": {"a":"b","c":"d"}, "arraycontainer": ["Introduction","Basics"] }} set doc [dom parse -json -jsonroot myjson $json] set myjson [$doc documentElement] set dict [$myjson asTclValue] $doc delete set result "" lappend result [dict get $dict objectcontainer] lappend result [dict get $dict arraycontainer] } {{a b c d} {Introduction Basics}} test json-10.5 {asTclValue} { set result "" foreach json { \"foo\" -1.23 null false true } { set doc [dom parse -json $json] lappend result [$doc asTclValue resulttype] $resulttype $doc delete } set result } {foo string -1.23 string null string false string true string} test json-10.5.1 {asTclValue} { set result "" foreach json { \"foo\" -1.23 null false true } { set doc [dom parse -json -jsonroot myjson $json] set myjson [$doc documentElement] lappend result [$myjson asTclValue resulttype] $resulttype $doc delete } set result } {foo string -1.23 string null string false string true string} test json-10.6 {asTclValue} { set result "" foreach json { ["bar"] [1,2] [null,true,false] } { set doc [dom parse -json $json] set thisresult [$doc asTclValue resulttype] lappend result $thisresult $resulttype [llength $thisresult] $doc delete } set result } {bar list 1 {1 2} list 2 {null true false} list 3} test json-10.6.1 {asTclValue} { set result "" foreach json { ["bar"] [1,2] [null,true,false] } { set doc [dom parse -json -jsonroot myjson $json] set myjson [$doc documentElement] set thisresult [$myjson asTclValue resulttype] lappend result $thisresult $resulttype [llength $thisresult] $doc delete } set result } {bar list 1 {1 2} list 2 {null true false} list 3} test json-10.7 {asTclValue} { set json {{ "Titel": "Wirtschaftsinformatik", "Keywords": ["Introduction","Basics"], "Year": 2022 }} set doc [dom parse -json $json] set dict [$doc asTclValue resulttype] $doc delete list $dict $resulttype } {{Titel Wirtschaftsinformatik Keywords {Introduction Basics} Year 2022} dict} test json-10.7.1 {asTclValue} { set json {{ "Titel": "Wirtschaftsinformatik", "Keywords": ["Introduction","Basics"], "Year": 2022 }} set doc [dom parse -json -jsonroot myjson $json] set myjson [$doc documentElement] set dict [$myjson asTclValue resulttype] $doc delete list $dict $resulttype } {{Titel Wirtschaftsinformatik Keywords {Introduction Basics} Year 2022} dict} test json-11.1 {asTypedList} { set json {{ "Titel": "Wirtschaftsinformatik", "Keywords": ["Introduction","Basics"], "Year": 2022 }} set doc [dom parse -json $json] set result [$doc asTypedList] $doc delete set result } {OBJECT {Titel {STRING Wirtschaftsinformatik} Keywords {ARRAY {{STRING Introduction} {STRING Basics}}} Year {NUMBER 2022}}} test json-11.2 {asTypedList} { set json {{ "stringproperty": "abc", "objectproperty": {"one": 1, "two": "two"}, "array": ["foo", -2.23, null, true, false, {"one": 1, "two": "two"}, [2,16,24]], "number": 2022, "null": null, "true": true, "false": false }} set doc [dom parse -json $json] set result [$doc asTypedList] $doc delete set result } {OBJECT {stringproperty {STRING abc} objectproperty {OBJECT {one {NUMBER 1} two {STRING two}}} array {ARRAY {{STRING foo} {NUMBER -2.23} NULL TRUE FALSE {OBJECT {one {NUMBER 1} two {STRING two}}} {ARRAY {{NUMBER 2} {NUMBER 16} {NUMBER 24}}}}} number {NUMBER 2022} null NULL true TRUE false FALSE}} test json-11.3 {asTypedList} { set json {{ "one two": "abc", "one\u007btwo": "abc", " one two ": "edf" }} set doc [dom parse -json $json] set result [$doc asTypedList] $doc delete set result } {OBJECT {{one two} {STRING abc} one\{two {STRING abc} { one two } {STRING edf}}} test json-11.4 {asTypedList} { set result "" foreach json { {"string foo"} null true false -1.23 } { set doc [dom parse -json $json] lappend result [$doc asTypedList] $doc delete } set result } {{STRING {string foo}} NULL TRUE FALSE {NUMBER -1.23}} test json-11.5 {asTypedList} { set result "" set json {{ "Keywords": ["Introduction","Basics"], "Data": {"one": "two", "three": true}, "Titel": "Wirtschaftsinformatik" }} set doc [dom parse -json $json] set node [$doc firstChild] while {$node ne ""} { lappend result [$node asTypedList] set node [$node nextSibling] } $doc delete set result } {{ARRAY {{STRING Introduction} {STRING Basics}}} {OBJECT {one {STRING two} three TRUE}} {STRING Wirtschaftsinformatik}} if {[info commands _dom] eq ""} { test json-12.1 {createFromTypedList} { set doc [dom createFromTypedList {OBJECT {Titel {STRING Wirtschaftsinformatik} Keywords {ARRAY {{STRING Introduction} {STRING Basics}}} Year {NUMBER 2022}}}] set result [$doc asJSON] $doc delete set result } {{"Titel":"Wirtschaftsinformatik","Keywords":["Introduction","Basics"],"Year":2022}} test json-12.2 {createFromTypedList} { set typedList {OBJECT {Titel {STRING Wirtschaftsinformatik} Keywords {ARRAY {{STRING Introduction} {STRING Basics}}} Year {NUMBER 2022}}} set doc [dom createFromTypedList $typedList] set result [$doc asTypedList] $doc delete expr {$typedList eq $result} } 1 proc createFromTypedList {list} { dom createFromTypedList $list doc if {$list eq [$doc asTypedList]} { return "" } error "Invalid turnaround." } test json-12.3 {createFromTypedList} { createFromTypedList {OBJECT {Titel {STRING Wirtschaftsinformatik} Keywords {ARRAY {{STRING Introduction} {STRING Basics}}} Year {NUMBER 2022}}} } {} test json-12.4 {createFromTypedList} { set result "" foreach json { {STRING foo} NULL TRUE FALSE {NUMBER -1.23} } { set doc [dom createFromTypedList $json] set this [$doc asTypedList] if {$json ne $this} { lappend result "json $json this $this" } else { lappend result 1 } $doc delete } set result } {1 1 1 1 1} test json-12.5 {createFromTypedList} { set result "" foreach wrong { NUL "" {one two} {STRING two three} } { catch {dom createFromTypedList $wrong} errMsg lappend result $errMsg } set result } {{Invalid typed list format: Unkown symbol "NUL".} {Invalid typed list format: Empty list.} {Invalid typed list format: Unkown symbol "one".} {Invalid typed list format: Too much list elements.}} test json-12.6 {createFromTypedList} { catch {dom createFromTypedList {OBJECT {one {STRING two} two {}}}} errMsg set errMsg } {Invalid typed list format: object property "two": Empty list.} test json-12.7 {createFromTypedList} { catch {dom createFromTypedList {OBJECT {one {STRING two} two {ARRAY {{NUMBER 1} {NULL foo}}}}}} errMsg set errMsg } {Invalid typed list format: object property "two": array element 2: No value expected for NULL.} } if {[info commands _dom] eq ""} { rename dom _dom proc dom {args} { if {[lindex $args 0] != "parse" || [lsearch -exact $args "-json"] < 0} { return [uplevel 1 [linsert $args 0 _dom]] } set haveData 0 set uplevelVar "" for {set x 1} {$x < [llength $args]} {incr x} { switch -- [lindex $args $x] { "-jsonroot" - "-jsonmaxnesting" - "-channel" - "-baseurl" - "-externalentitycommand" { incr x } "-json" - "--" - "-keepEmpties" - "-keepCDATA" { # do nothing, the options are flags } default { if {$haveData} { set uplevelVar [lindex $args $x] } else { set data [lindex $args $x] set haveData 1 } } } } if {[catch { _dom parse -json $data doc } errMsg]} { # Some tests check if invalid json data is detected. Since # we need valid json data for what is tested here that # tests should be marked with constraint nonetest. To # raise error here does not help much because if the test # data is expected to be invalid the command will be # [catch]ed. Therefore the puts to catch attention. puts "Unexpeced invalid json data '$data'" } set njson [$doc asJSON] set typedList [$doc asTypedList] _dom createFromTypedList $typedList docFromTyped if {$njson ne [$docFromTyped asJSON]} { error "Normalized json '$data' differs from normalized json created with createFromTypedList" } return [uplevel 1 [linsert $args 0 _dom]] } source [file join [file dir [info script]] domjson.test] rename dom {} rename _dom dom } tdom-0.9.5-src/tests/pushpull.bench0000644000175000017500000000521514703531020015760 0ustar rolfrolf# -*- tcl -*- # # This file contains a number of benchmarks for push (expat) and pull # (tdom::pullparser) parser. # # (c) 2018 Rolf Ade # # ### ### ### ######### ######### ######### ########################### ## Setting up the environment ... package require tdom # ### ### ### ######### ######### ######### ########################### ## Benchmarks. proc loopPullE {} { while {[set state [pullparser next]] ne "END_DOCUMENT"} { switch $state { "START_TAG" { append pullstr [pullparser tag] foreach {attname attvalue} [pullparser attributes] { append pullstr $attname $attvalue } } "TEXT" { append pullstr [pullparser text] } "END_TAG" { append pullstr /[pullparser tag] } } } return $pullstr } expat pushparserCanonical \ -elementstartcommand elementstart \ -elementendcommand elementend \ -characterdatacommand cdata proc elementstart {name atts} { global expatstr append expatstr $name foreach {attname attvalue} $atts { append expatstr $attname $attvalue } } proc elementend {name} { global expatstr append expatstr /$name } proc cdata {cdata} { global expatstr append expatstr $cdata } expat pushparserTricky \ -elementstartcommand elementstart \ -elementendcommand elementend \ -characterdatacommand cdata proc dopull {} { while {[set state [pullparser next]] ne "END_DOCUMENT"} { switch $state { "START_TAG" { append pullstr [pullparser tag] foreach {attname attvalue} [pullparser attributes] { append pullstr $attname $attvalue } } "TEXT" { append pullstr [pullparser text] } "END_TAG" { append pullstr /[pullparser tag] } } } return $pullstr } bench -desc "push/canonical mondial-europe.xml" -iters 5 -body { set expatstr "" pushparserCanonical parsefile ../tests/data/mondial-europe.xml pushparserCanonical reset } -post { pushparserCanonical free } bench -desc "push/tricky mondial-europe.xml" -iters 5 -body { set expatstr "" pushparserTricky parsefile ../tests/data/mondial-europe.xml pushparserTricky reset } -post { pushparserTricky free } tdom::pullparser pullparser bench -desc "pull mondial-europe.xml" -iters 5 -body { pullparser inputfile ../tests/data/mondial-europe.xml dopull pullparser reset } -post { pullparser delete } tdom-0.9.5-src/tests/comment.test0000644000175000017500000001145114703531020015445 0ustar rolfrolf# Features covered: comments # # This file tests the parser's performance on comments. # Sourcing this file into Tcl runs the tests and generates output # for errors. No output means no errors were found. # # Copyright (c) 1998-2000 Zveno Pty Ltd. # # $Id$ source [file join [file dir [info script]] loadtdom.tcl] catch {unset result} proc pcdata data { append ::result $data } proc comment data { append ::comment $data } proc Estart {tagName attrList} { switch -- $tagName { test - Test { } default { incr ::element } } } proc EStop tagname { } test comment-1.1 {Simple comment} { set ::result {} set ::comment {} set ::element 0 catch {rename xml::comment-1.1 {}} set parser [xml::parser comment-1.1 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata \ -commentcommand comment] $parser parse { } list $::comment $::result $::element } {{ This is a comment } {} 0} test comment-1.2 {Simple comment, no white space} { set ::result {} set ::comment {} set ::element 0 catch {rename xml::comment-1.2 {}} set parser [xml::parser comment-1.2 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata \ -commentcommand comment] $parser parse { } list $::comment $::result $::element } {{This is a comment} {} 0} test comment-1.3 {Simple comment, within PCDATA} { set ::result {} set ::comment {} set ::element 0 catch {rename xml::comment-1.3 {}} set parser [xml::parser comment-1.3 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata \ -commentcommand comment] $parser parse { surrounding PCDATA } list $::comment $::result $::element } {{This is a comment} {surrounding PCDATA} 0} test comment-1.4 {Simple comment, no white space} { set ::result {} set ::comment {} set ::element 0 catch {rename xml::comment-1.3 {}} set parser [xml::parser comment-1.3 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata \ -commentcommand comment] $parser parse { } list $::comment $::result $::element } {comment {} 0} test comment-1.5 {comment, with nested element} { set ::result {} set ::comment {} set ::element 0 catch {rename xml::comment-1.4 {}} set parser [xml::parser comment-1.4 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata \ -commentcommand comment] $parser parse { } list $::comment $::result $::element } {{ comment } {} 0} test comment-2.1 {comment with an angle bracket} { set ::result {} set ::comment {} set ::element 0 catch {rename xml::comment-2.1 {}} set parser [xml::parser comment-2.1 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata \ -commentcommand comment] $parser parse { } list $::comment $::result $::element } {{ This is a > greater than sign } {} 0} test comment-2.2 {comment with multiple angle brackets} { set ::result {} set ::comment {} set ::element 0 catch {rename xml::comment-2.2 {}} set parser [xml::parser comment-2.2 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata \ -commentcommand comment] $parser parse { } list $::comment $::result $::element } {{ } {} 0} set comment_2_3 [format {
} \}] test comment-2.3 {comment with entities} { set ::result {} set ::comment {} set ::element 0 catch {rename xml::comment-2.3 {}} set parser [xml::parser comment-2.3 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata \ -commentcommand comment] $parser parse " " list [string compare $::comment ${comment_2_3}] [string trim $::result] $::element } [list 0 {} 2] foreach parser [info commands comment-*] { $parser free } # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/domNode.test0000644000175000017500000033407314703531020015400 0ustar rolfrolf# Features covered: domNode command and nodeObj commands # # This file contains a collection of tests for the two interfaces to # DOM nodes, the token interface (the domNode command) and the tcl # command interface ([$nodeObj method ...]). # # domNode-1.*: domNode command syntax # domNode-2.*: selectNodes # domNode-3.*: documentElement # domNode-4.*: setAttributeNS # domNode-5.*: removeChild # domNode-6.*: appendChild # domNode-7.*: getElementsByTagName # domNode-8.*: getElementsByTagNameNS # domNode-9.*: nodeValue # domNode-10.*: setAttribute, again setAttributeNS # domNode-11.*: disableOutputEscaping # domNode-12.*: cloneNode # domNode-13.*: appendFromScript # domNode-14.*: appendFromList # domNode-15.*: delete # domNode-16.*: getAttribute # domNode-17.*: nodeType # domNode-18.*: attributes, attributeNames # domNode-19.*: removeAttribute, removeAttributeNS # domNode-20.*: parentNode # domNode-21.*: hasChildNodes # domNode-22.*: localName, prefix # domNode-23.*: replaceChild # domNode-24.*: getLine, getColumn, getByteIndex # domNode-25.*: hasAttribute, hasAttributeNS # domNode-26.*: appendXML # domNode-27.*: target, data # domNode-28.*: getAttributeNS # domNode-29.*: ownerDocument # domNode-30.*: precedes # domNode-31.*: insertBefore # domNode-32.*: asText # domNode-33.*: insertBeforeFromScript # domNode-34.*: getBaseURI # domNode-35.*: objCmd traces # domNode-36.*: nodeName # domNode-37.*: baseURI # domNode-38.*: toXPath # domNode-39.*: text # domNode-999.* Misc Tests # # Copyright (c) 2002 - 2005 Rolf Ade. # # RCS: @(#) $Id$ source [file join [file dir [info script]] loadtdom.tcl] if {[join [lrange [split [package present Tcl] .] 0 1] .] <= 8.4} { testConstraint threaded [info exists tcl_platform(threaded)] } else { testConstraint threaded [expr {[info exists tcl_platform(threaded)] || [package vsatisfies [package present Tcl] 9.0-]}] } test domNode-1.1 {too less arguments to nodecmd} { set doc [dom createDocument "root"] set root [$doc documentElement] set result [catch {$root}] $doc delete set result } {1} test domNode-1.2 {too less arguments to domNode token} { set doc [dom createDocument "root"] set root [$doc documentElement] set result [catch {domNode $root}] $doc delete set result } {1} test domNode-1.3 {too less arguments to domNode command} { catch {domNode} } {1} test domNode-1.4 {rename of domNodeObj cmd} {knownBug} { set doc [dom createDocument "root"] set root [$doc documentElement] rename $root my_domNode set result [llength [info commands my_domNode]] $doc delete lappend result [llength [info commands my_domNode]] catch {my_domNode nodeName} errMsg lappend result $errMsg } {1 0} test domNode-1.5 {domNode command: invalid token} { set xml {12} set doc [dom parse $xml] set root [domDoc $doc documentElement] set invalidToken [domNode $root firstChild] lappend invalidToken foo set result [catch {domNode $invalidToken selectNodes string(.)}] $doc delete set result } {1} test domNode-1.6 {domNode command: invalid token} { set xml {12} set doc [dom parse $xml] set root [domDoc $doc documentElement] set invalidToken [domNode $root firstChild] append invalidToken "\n" set result [catch {domNode $invalidToken selectNodes string(.)}] $doc delete set result } {1} proc domNode-1.7-traceproc {args} { error "error in nodeObjVar trace" } test domNode-1.7 {error in trace on nodeObjVar} { set xml {12} set doc [dom parse $xml] set root [$doc documentElement] trace add variable resultVar write domNode-1.7-traceproc set result [catch {$root firstChild resultVar} errMsg] lappend result $errMsg trace remove variable resultVar write domNode-1.7-traceproc $doc delete set result } {1 {can't set "resultVar": error in nodeObjVar trace}} test domNode-1.8 {cmd argument parsing} { set result [catch {domNode} errMsg] lappend result $errMsg catch {domNode foo} errMsg lappend result $errMsg } {1 {wrong # args: should be "domNode nodetoken subcommand ?arg ...?"} {wrong # args: should be "domNode nodetoken subcommand ?arg ...?"}} test domNode-1.9 {cmd argument parsing} { set storedMode [dom setObjectCommands] dom setObjectCommands token set doc [dom parse {}] set root [domDoc $doc documentElement] catch {domNode $root} result domDoc $doc delete dom setObjectCommands $storedMode set result } {wrong # args: should be "domNode nodetoken subcommand ?arg ...?"} test domNode-1.10 {cmd argument parsing} -body { set doc [dom parse {}] set root [$doc documentElement] catch {$root} result $doc delete set result } -match regexp -result {wrong # args: should be "domNode[^ ]+ subcommand \?arg ...\?"} test domNode-1.11 {cmd argument parsing} -body { set storedMode [dom setObjectCommands] dom setObjectCommands token set doc [dom parse {}] set root [domDoc $doc documentElement] catch {domNode $root invalid-method} result domDoc $doc delete dom setObjectCommands $storedMode set result } -match glob -result {bad method "invalid-method": must be *} test domNode-1.12 {cmd argument parsing} -body { set doc [dom parse {}] set root [$doc documentElement] catch {$root invalid-method} result $doc delete set result } -match glob -result {bad method "invalid-method": must be *} set doc [dom parse { }] set root [$doc documentElement] test domNode-2.1 {selectNodes - -namespace option: syntax} { set result [catch {$root selectNodes -namespaces elem1ns:elem1} errMsg] lappend result $errMsg } {1 {The "-namespaces" option requires a 'prefix namespace' pairs list as argument}} test domNode-2.2 {selectNodes - -namespace option} { set result [$root selectNodes -namespaces {} elem1] } {} test domNode-2.3 {selectNodes - -namespaces option} { set node [$root selectNodes -namespaces {my elem1NS} my:elem1] set result [list] lappend result [$node localName] [$node namespaceURI] } {elem1 elem1NS} test domNode-2.4 {selectNodes - -namespaces option} { set node [$root selectNodes -namespaces {my elem1NS my elem2NS} my:*] set result [list] lappend result [$node localName] [$node namespaceURI] } {elem1 elem1NS} test domNode-2.5 {selectNodes - -namespaces option} { set nsDef [list this elem2NS same elem2NS] set node [$root selectNodes -namespaces $nsDef {this:*|same:*}] set result [llength $node] lappend result [$node localName] [$node namespaceURI] } {1 elem2 elem2NS} test domNode-2.6 {selectNodes - -namespaces option} { set nsDef1 [list foo elem2NS bar elem2NS] set nsDef2 [list this elem2NS same elem2NS] set node [$root selectNodes -namespaces $nsDef1 \ -namespaces $nsDef2 {this:*|same:*}] set result [llength $node] lappend result [$node localName] [$node namespaceURI] } {1 elem2 elem2NS} test domNode-2.7 {selectNodes - -namespaces option} { set result [catch {$root selectNodes -namespaces elem1ns:elem1 typevar} errMsg] lappend result $errMsg } {1 {The "-namespaces" option requires a 'prefix namespace' pairs list as argument}} test domNode-2.8 {selectNodes - -namespaces option} { set nsDef1 [list foo elem2NS bar elem2NS] set nsDef2 [list this elem2NS same elem2NS] set node [$root selectNodes -namespaces $nsDef1 \ -namespaces $nsDef2 {this:*|same:*} typevar] set result [llength $node] lappend result [$node localName] [$node namespaceURI] $typevar } {1 elem2 elem2NS nodes} $doc delete set doc [dom parse { }] $doc documentElement root test domNode-2.9 {selectNodes - -cache option} { set result [catch {$root selectNodes -cache child} errMsg] lappend result $errMsg } {1 {expected boolean value but got "child"}} test domNode-2.10 {selectNodes - -cache option} { for {set x 0} {$x < 5} {incr x} { set nodes [$root selectNodes -cache 1 {child[2]}] } for {set x 0} {$x < 5} {incr x} { set otherNodes [$root selectNodes -cache 0 {child[2]}] } string equal $nodes $otherNodes } {1} test domNode-2.11 {selectNodes - -cache option} { set r1 [catch {$root selectNodes}] set r2 [catch {$root selectNodes -cache 1}] set r3 [catch {$root selectNodes -cache 0}] set r4 [catch {$root selectNodes ""}] set r5 [catch {$root selectNodes -cache 1 ""}] set r6 [catch {$root selectNodes -cache 0 ""}] list $r1 $r2 $r3 $r4 $r5 $r6 } {1 1 1 1 1 1} test domNode-2.12 {selectNodes - -cache option} { # Second usage of an invalid XPath expr with -cache 1 # See 97c0994ae4 catch {$root selectNodes -cache 1 "/foo bar"} catch {$root selectNodes -cache 1 "/foo bar"} } 1 $doc delete test domNode-3.1 {repetitived documentElement with objVar, then delete} { dom createDocument "root" doc $doc documentElement root $doc delete dom createDocument "\u00c4\u00d4\u00dc" doc $doc documentElement root set result [$root nodeName] $doc delete set result } "\u00c4\u00d4\u00dc" test domNode-3.2 {repetitived documentElement, then delete} { set doc [dom createDocument "root"] $doc documentElement root $doc delete set doc [dom createDocument "\u00c4\u00d4\u00dc"] $doc documentElement root set result [$root nodeName] $doc delete set result } "\u00c4\u00d4\u00dc" test domNode-3.3 {repetitived documentElement, then delete} { set doc [dom createDocument "root"] set root [$doc documentElement] $doc delete set doc [dom createDocument "\u00c4\u00d4\u00dc"] set root [$doc documentElement] set result [$root nodeName] $doc delete set result } "\u00c4\u00d4\u00dc" test domNode-4.1 {create nodes with same prefix, different uri's} { dom createDocumentNS "uri1" "p:a" doc set root [$doc documentElement] set node1 [$doc createElementNS "uri2" "p:b"] $root appendChild $node1 set node2 [$doc createElementNS "uri1" "p:c"] $node1 appendChild $node2 set result [$root asXML] $doc delete set result } { } test domNode-4.3 {setAttribute} { dom createDocumentNS "uri1" "p:root" doc set root [$doc documentElement] $root setAttribute attr1 attr1Value set result [$root asXML] $doc delete set result } { } test domNode-4.5 {setAttributeNS} { dom createDocument "root" doc set root [$doc documentElement] $root setAttributeNS "" xmlns:p uri $root setAttributeNS uri p:attr attrValue set result [$root asXML] $doc delete set result } { } test domNode-4.6 {setAttributeNS} { dom createDocument "root" doc set root [$doc documentElement] $root setAttributeNS uri p:attr attrValue $root setAttributeNS "" xmlns:p uri set result [$root asXML] $doc delete set result } { } test domNode-4.7 {setAttributeNS} { dom createDocument "root" doc set root [$doc documentElement] $root setAttributeNS uri p:attr1 attrValue set result [$root getAttributeNS uri attr1] $doc delete set result } {attrValue} test domNode-4.8 {setAttributeNS} { dom createDocument "root" doc set root [$doc documentElement] $root setAttributeNS "" xmlns:p uri $root setAttributeNS uri p:attr1 attrValue set result [$root getAttributeNS uri attr1] $doc delete set result } {attrValue} test domNode-4.9 {setAttributeNS} { dom createDocument "root" doc set root [$doc documentElement] $root setAttributeNS uri p:attr1 attrValue set result [$root attributes *] $doc delete set result } {{attr1 p uri}} test domNode-4.10 {setAttributeNS} { dom createDocument "root" doc set root [$doc documentElement] set result [catch {$root setAttributeNS {} p:attr1 attrValue}] $doc delete set result } {1} test domNode-4.11 {setAttributeNS} { dom createDocument "root" doc set root [$doc documentElement] set result [catch {$root setAttributeNS uri attr1 attrValue}] $doc delete set result } {1} test domNode-4.12 {setAttributeNS - special prefix "xml"} { dom createDocument "root" doc set root [$doc documentElement] $root setAttributeNS "" xml:attr1 attrValue set result [$root attributes *] $doc delete set result } {{attr1 xml http://www.w3.org/XML/1998/namespace}} test domNode-4.13 {setAttributeNS} { dom createDocument "root" doc set root [$doc documentElement] $root setAttributeNS uri p:attr1 attrValue $root setAttributeNS uri o:attr1 newValue set result [$root attributes *] $doc delete set result } {{attr1 p uri}} test domNode-4.14 {setAttributeNS} { dom createDocument "root" doc set root [$doc documentElement] $root setAttributeNS uri p:attr1 attrValue $root setAttributeNS uri o:attr1 newValue set result [$root getAttributeNS uri attr1] $doc delete set result } {newValue} test domNode-4.15 {setAttributeNS - use as setAttribute} { dom createDocument "root" doc set root [$doc documentElement] $root setAttributeNS "" attr1 attrValue set result [$root attributes *] $doc delete set result } {attr1} test domNode-4.16 {setAttributeNS - set multiple Attributes at once} { set doc [dom createDocumentNS uri1 "p1:root"] set root [$doc documentElement] $root setAttributeNS "" xmlns:p2 uri2 $root setAttributeNS uri1 p1:a1 1 uri1 p1:a2 2 uri2 p2:a3 3 "" a4 4 set result [$root asXML] $doc delete set result } { } test domNode-4.17 {setAttributeNS - set multiple Attribute with NS atts undermixed at once} { set doc [dom createDocumentNS uri1 "p1:root"] set root [$doc documentElement] $root setAttributeNS "" xmlns:p2 uri2 $root setAttributeNS uri1 p1:a1 1 "" xmlns uri3 uri1 p1:a2 2 "" xmlns:p4 uri4 uri4 p4:a1 a1 uri2 p2:a3 3 "" a4 4 set result [$root asXML] $doc delete set result } { } test domNode-4.18 {setAttributeNS - prefixed attribute name with empty namespace} { set doc [dom createDocument "root"] set root [$doc documentElement] catch {$root setAttributeNS "" ns:att attvalue} errMsg $doc delete set errMsg } {For all prefixed attributes with prefixes other than 'xml' or 'xmlns' you have to provide a namespace URI} test domNode-5.1 {removeChild} { dom parse {} doc $doc documentElement root $root removeChild [$root firstChild] set result [$doc asXML -indent none] $doc delete set result } {} test domNode-5.2 {removeChild - child to remove is not a child of node} { dom parse {} doc $doc documentElement root set one [$root firstChild] set two [$root lastChild] set result [catch {$one removeChild $two} errMsg] lappend result $errMsg $doc delete set result } {1 NOT_FOUND_ERR} test domNode-5.3 {removeChild - child to remove is not a child of node} { dom parse {} doc $doc documentElement root set newNode [$doc createElement new] set result [catch {$root removeChild $newNode} errMsg] lappend result $errMsg $doc delete set result } {1 NOT_FOUND_ERR} test domNode-6.1 {appendChild insert FQ Element} { set doc [dom parse {}] set root [$doc documentElement] set newNode [$doc createElementNS uri2 p:foo] $root appendChild $newNode set result [$root asXML] $doc delete set result } { } test domNode-6.2 {appendChild} { set doc [dom createDocument XMI] set root [$doc documentElement] set A1tag [$doc createElement "A1"] set A2subtag [$doc createElement "A2sub"] set A2tag [$doc createElement "A2"] $A2tag appendChild $A2subtag set Atag [$doc createElement "A"] $Atag appendChild $A1tag $Atag appendChild $A2tag set Btag [$doc createElement "B"] $Btag appendChild $Atag set Ctag [$doc createElement "C"] set result 0 if {$root == "[$doc documentElement]"} {set result 1} $doc delete set result } {1} test domNode-6.3 {appendChild} { dom parse {} doc $doc documentElement root $root appendChild [$root firstChild] set result [$doc asXML -indent none] $doc delete set result } {} test domNode-6.4 {appendChild} { dom parse {} doc $doc documentElement root $root appendChild [$root lastChild] set result [$doc asXML -indent none] $doc delete set result } {} test domNode-6.5 {appendChild} { dom parse {} doc $doc documentElement root $root appendChild [lindex [$root childNodes] 1] set result [$doc asXML -indent none] $doc delete set result } {} test domNode-6.6 {appendChild} { dom parse {} doc $doc documentElement root set node [$root appendChild [$root firstChild]] catch {unset result} lappend result [[$node parentNode] nodeName] while {$node != ""} { lappend result [$node nodeName] set node [$node previousSibling] } $doc delete set result } {root one three two} test domNode-6.7 {appendChild} { dom parse {} doc $doc documentElement root set node [$root appendChild [$root lastChild]] catch {unset result} lappend result [[$node parentNode] nodeName] while {$node != ""} { lappend result [$node nodeName] set node [$node previousSibling] } $doc delete set result } {root three two one} test domNode-6.8 {appendChild} { dom parse {} doc $doc documentElement root set node [$root appendChild [lindex [$root childNodes] 1]] catch {unset result} lappend result [[$node parentNode] nodeName] while {$node != ""} { lappend result [$node nodeName] set node [$node previousSibling] } $doc delete set result } {root two three one} test domNode-6.9 {appendChild} { dom parse {} doc $doc documentElement root $root appendChild [$root firstChild] catch {unset result} set node [$root firstChild] while {$node != ""} { lappend result [$node nodeName] set node [$node nextSibling] } $doc delete set result } {two three one} test domNode-6.10 {appendChild} { dom parse {} doc $doc documentElement root $root appendChild [$root lastChild] catch {unset result} set node [$root firstChild] while {$node != ""} { lappend result [$node nodeName] set node [$node nextSibling] } $doc delete set result } {one two three} test domNode-6.11 {appendChild} { dom parse {} doc $doc documentElement root $root appendChild [lindex [$root childNodes] 1] catch {unset result} set node [$root firstChild] while {$node != ""} { lappend result [$node nodeName] set node [$node nextSibling] } $doc delete set result } {one three two} test domNode-6.12 {appendChild} { dom parse {} doc $doc documentElement root set one [$root firstChild] $one appendChild [$root lastChild] set result [$doc asXML -indent none] $doc delete set result } {} test domNode-6.13 {appendChild} { dom parse {} doc $doc documentElement root set one [$root firstChild] set result [catch {$one appendChild $root} errMsg] lappend result $errMsg $doc delete set result } {1 HIERARCHY_REQUEST_ERR} test domNode-6.14 {appendChild} { dom parse {} doc $doc documentElement root set one [$root firstChild] set result [catch {$one appendChild $one} errMsg] lappend result $errMsg $doc delete set result } {1 HIERARCHY_REQUEST_ERR} test domNode-6.15 {appendChild} -setup { set fileList {} foreach {name content} { a "..." b "..." } { lappend fileList [makeFile $content $name] } } -body { set docs {} foreach rf $fileList { set doc [dom parse -baseurl [tdom::baseURL $rf] \ -externalentitycommand ::tdom::extRefHandler \ -keepEmpties \ [tdom::xmlReadFile $rf] ] lappend docs $doc } set resultDoc [dom createDocument new_report] set root [$resultDoc documentElement] foreach doc $docs { $root appendChild [$doc documentElement] } set result [$resultDoc asXML -indent none] foreach doc $docs { $doc delete } $resultDoc delete set result } -cleanup { removeFile a removeFile b } -result {......} test domNode-6.16 {appendChild} -setup { dom parse {} doc1 $doc1 documentElement root1 dom parse {} doc2 $doc2 documentElement root2 } -body { $root1 appendChild [$root2 cloneNode -deep] $root1 asXML -indent none } -cleanup { $doc1 delete $doc2 delete } -result {} test domNode-6.17 {appendChild} -setup { dom parse {} doc1 $doc1 documentElement root1 dom parse {} doc2 $doc2 documentElement root2 } -body { $root1 appendChild [$root2 cloneNode -deep] $root1 asXML -indent none } -cleanup { $doc1 delete $doc2 delete } -result {} set doc [dom parse {}] set root [$doc documentElement] test domNode-7.1 {getElementsByTagName - doc method} { llength [$doc getElementsByTagName a] } {2} test domNode-7.2 {getElementsByTagName - doc method} { llength [$doc getElementsByTagName c] } {1} test domNode-7.3 {getElementsByTagName - doc method} { llength [$doc getElementsByTagName foo] } {0} test domNode-7.4 {getElementsByTagName - node method} { llength [$root getElementsByTagName a] } {2} test domNode-7.5 {getElementsByTagName - node method} { llength [$root getElementsByTagName c] } {1} test domNode-7.6 {getElementsByTagName - node method} { llength [$root getElementsByTagName foo] } {0} test domNode-7.7 {getElementsByTagName - node method '*' wildcard} { llength [$root getElementsByTagName *] } {7} test domNode-7.8 {getElementsByTagName - doc method '*' wildcard} { llength [$doc getElementsByTagName *] } {8} test domNode-7.9 {getElementsByTagName - node method tcl glob style} { llength [$root getElementsByTagName foo*] } {2} test domNode-7.9 {getElementsByTagName - node method tcl glob style} { llength [$root getElementsByTagName *oo*] } {3} test domNode-7.10 {getElementsByTagName - doc method tcl glob style} { llength [$doc getElementsByTagName foo*] } {2} test domNode-7.11 {getElementsByTagName - doc method tcl glob style} { llength [$doc getElementsByTagName *oo*] } {4} test domNode-7.12 {getElementsByTagName - doc method empty result} { $doc getElementsByTagName noSuchANodeName } {} test domNode-7.13 {getElementsByTagName - node method empty result} { $root getElementsByTagName noSuchANodeName } {} test domNode-7.14 {getElementsByTagName - doc method: doc order of result} { set nodes [$doc getElementsByTagName *] set result "" foreach node $nodes { append result "[$node nodeName] " } set result } {root foobar barfoo foobaz a b a c } test domNode-7.15 {getElementsByTagName - node method: doc order of result} { set nodes [$root getElementsByTagName *] set result "" foreach node $nodes { append result "[$node nodeName] " } set result } {foobar barfoo foobaz a b a c } $doc delete set doc [dom parse { mixed content important more content again important }] set root [$doc documentElement] test domNode-7.16 {getElementsByTagName - node method mixed content} { llength [$doc getElementsByTagName elem] } {1} test domNode-7.17 {getElementsByTagName - node method mixed content} { llength [$root getElementsByTagName elem] } {1} test domNode-7.18 {getElementsByTagName - doc method mixed content} { llength [$doc getElementsByTagName b] } {3} test domNode-7.19 {getElementsByTagName - node method mixed content} { llength [$root getElementsByTagName b] } {3} test domNode-7.20 {getElementsByTagName - not a element node} { set textnode [$root selectNodes {descendant::text()[1]}] catch {$textnode getElementsByTagName b} errMsg set errMsg } {Node must be an element node.} $doc delete set doc [dom parse { IBM }] set root [$doc documentElement] test domNode-8.1 {getElementsByTagNameNS - root method} { [$root getElementsByTagNameNS "http://www.stock.org/stock" GetStockPrice] nodeName } {m:GetStockPrice} test domNode-8.2 {getElementsByTagNameNS - root method} { [$root getElementsByTagNameNS "*" GetStockPrice] nodeName } {m:GetStockPrice} test domNode-8.3 {getElementsByTagNameNS - root method} { llength [$root getElementsByTagNameNS "http://www.stock.org/stock" *] } {2} test domNode-8.4 {getElementsByTagNameNS - doc method} { [$doc getElementsByTagNameNS "http://www.stock.org/stock" GetStockPrice] nodeName } {m:GetStockPrice} test domNode-8.5 {getElementsByTagNameNS - doc method} { [$doc getElementsByTagNameNS "*" GetStockPrice] nodeName } {m:GetStockPrice} test domNode-8.6 {getElementsByTagNameNS - doc method} { llength [$doc getElementsByTagNameNS "http://www.stock.org/stock" *] } {2} $doc delete set doc [dom parse { mixed content important more content again important }] set root [$doc documentElement] test domNode-8.7 {getElementsByTagNameNS - doc method pathologic XML} { llength [$doc getElementsByTagNameNS "firstp" pathologic] } {2} test domNode-8.8 {getElementsByTagNameNS - doc method pathologic XML} { llength [$doc getElementsByTagNameNS "secondp" pathologic] } {1} test domNode-8.9 {getElementsByTagNameNS - doc method pathologic XML} { llength [$doc getElementsByTagNameNS "*" pathologic] } {3} test domNode-8.10 {getElementsByTagNameNS - node method pathologic XML} { llength [$root getElementsByTagNameNS "firstp" pathologic] } {2} test domNode-8.11 {getElementsByTagNameNS - node method pathologic XML} { llength [$root getElementsByTagNameNS "secondp" pathologic] } {1} test domNode-8.12 {getElementsByTagNameNS - node method pathologic XML} { llength [$root getElementsByTagNameNS "*" pathologic] } {3} test domNode-8.13 {getElementsByTagNameNS - doc method} { llength [$doc getElementsByTagNameNS "NS1" elem] } {1} test domNode-8.14 {getElementsByTagNameNS - doc method} { llength [$doc getElementsByTagNameNS "NS2" elem] } {1} test domNode-8.15 {getElementsByTagNameNS - doc method} { llength [$doc getElementsByTagNameNS "*" elem] } {3} test domNode-8.16 {getElementsByTagNameNS - node method} { llength [$root getElementsByTagNameNS "NS1" elem] } {1} test domNode-8.17 {getElementsByTagNameNS - node method} { llength [$root getElementsByTagNameNS "NS2" elem] } {1} test domNode-8.18 {getElementsByTagNameNS - node method} { llength [$root getElementsByTagNameNS "*" elem] } {3} test domNode-8.19 {getElementsByTagNameNS - doc method empty namespace} { set nodes [$doc getElementsByTagNameNS "" *] set result "" foreach node $nodes { append result "[$node nodeName] " } set result } {root elem b b } test domNode-8.19 {getElementsByTagNameNS - node method empty namespace} { set nodes [$root getElementsByTagNameNS "" *] set result "" foreach node $nodes { append result "[$node nodeName] " } set result } {elem b b } test domNode-8.20 {getElementsByTagNameNS - not a element node} { set textnode [$root selectNodes {descendant::text()[1]}] catch {$textnode getElementsByTagName b} errMsg set errMsg } {Node must be an element node.} $doc delete set doc [dom parse { }] set root [$doc documentElement] test domNode-8.21 {getElementsByTagNameNS - unset default NS} { set nodes [$root getElementsByTagNameNS "" *] set result "" foreach node $nodes { append result "[$node nodeName] " } set result } {elem1 elem3 } test domNode-8.22 {getElementsByTagName - unset default NS} { set nodes [$root getElementsByTagName *] set result "" foreach node $nodes { append result "[$node nodeName] " } set result } {elem1 elem2 elem3 } test domNode-8.23 {getElementsByTagNameNS - unset default NS} { set nodes [$root getElementsByTagNameNS * *] set result "" foreach node $nodes { append result "[$node nodeName] " } set result } {elem1 elem2 elem3 } test domNode-8.24 {getElementsByTagNameNS - unset default NS} { set nodes [$doc getElementsByTagNameNS * *] set result "" foreach node $nodes { append result "[$node nodeName] " } set result } {root elem1 elem2 elem3 } test domNode-8.25 {getElementsByTagNameNS - unset default NS} { set nodes [$root getElementsByTagNameNS "" *] set result "" foreach node $nodes { append result "[$node nodeName] " } set result } {elem1 elem3 } test domNode-8.26 {getElementsByTagNameNS - unset default NS} { set nodes [$doc getElementsByTagNameNS "" *] set result "" foreach node $nodes { append result "[$node nodeName] " } set result } {elem1 elem3 } $doc delete set doc [dom parse { text node}] set root [$doc documentElement] test domNode-9.1 {nodeValue - TEXT_NODE} { [$root firstChild] nodeValue } {text node} test domNode-9.2 {nodeValue - COMMENT_NODE} { set firstChild [$root firstChild] set commentNode [$firstChild nextSibling] $commentNode nodeValue } {comment node} test domNode-9.3 {nodeValue - PROCESSING_INSTRUCTION_NODE} { [$root lastChild] nodeValue } {PI node} test domNode-9.4 {nodeValue - CDATA_SECTION_NODE} { set cdNode [$doc createCDATASection "cdata section node"] $root appendChild $cdNode [$root lastChild] nodeValue } {cdata section node} test domNode-9.5 {nodeValue with set - TEXT_NODE} { set result [[$root firstChild] nodeValue "new text value"] append result "/" [[$root firstChild] nodeValue] } {text node/new text value} test domNode-9.6 {nodeValue with set - COMMENT_NODE} { set textNode [$root firstChild] set node [$textNode nextSibling] set result [$node nodeValue "new comment text"] append result "/" [$commentNode nodeValue] } {comment node/new comment text} test domNode-9.7 {nodeValue - PROCESSING_INSTRUCTION_NODE does not allow setting} { set piNode [$root selectNodes processing-instruction('mytarget')] catch {$piNode nodeValue "new pi value"} } {1} test domNode-9.8 {nodeValue - CDATA_SECTION_NODE} { set result [[$root lastChild] nodeValue "new text"] append result "/" [[$root lastChild] nodeValue] } {cdata section node/new text} $doc delete test domNode-9.9 {nodeValue - invalid new value} { set doc [dom parse text] $doc documentElement root set result [catch {[$root firstChild] nodeValue "ab\u0003\u0003cd"} \ errMsg] $doc delete lappend result $errMsg } [list 1 "Invalid text value 'ab\u0003\u0003cd'"] set doc [dom parse ] set root [$doc documentElement] test domNode-10.1 {setAttribute - set multiple attributes at once} { $root setAttribute a1 1 a2 2 a3 3 a4 4 a5 5 a6 6 a7 7 a8 8 $root asXML -indent none } {} $doc delete set doc [dom parse {&}] set root [$doc documentElement] set textnode [$root firstChild] test domNode-11.1 {disableOutputEscaping} { $textnode disableOutputEscaping } {0} test domNode-11.2 {disableOutputEscaping} { $textnode disableOutputEscaping 1 } {0} test domNode-11.3 {disableOutputEscaping} { $textnode disableOutputEscaping } {1} test domNode-11.4 {disableOutputEscaping} { $root asXML -indent none } {&} $doc delete test domNode-11.5 {disableOutputEscaping} { set doc [dom createDocument root] set textnode [$doc createTextNode "

some important text

"] $textnode disableOutputEscaping 1 set root [$doc documentElement] $root appendChild $textnode set result [$root asXML -indent none] $doc delete set result } {

some important text

} test domNode-11.6 {disableOutputEscaping} { set doc [dom createDocument root] set textnode [$doc createTextNode "

some important text

"] $textnode disableOutputEscaping 1 set root [$doc documentElement] $root appendChild $textnode set textnode [$doc createTextNode "&"] $root appendChild $textnode set result [$root asXML -indent none] $doc delete set result } {

some important text

&
} test domNode-11.7 {disableOutputEscaping} { set doc [dom createDocument root] set root [$doc documentElement] set textnode [$doc createTextNode "&"] $root appendChild $textnode set textnode [$doc createTextNode "

some important text

"] $textnode disableOutputEscaping 1 $root appendChild $textnode set result [$root asXML -indent none] $doc delete set result } {&

some important text

} test domNode-12.1 {cloneNode} { set doc [dom parse {}] set root [$doc documentElement] set newNode [$root cloneNode] $root appendChild $newNode set result [$root asXML -indent none] $doc delete set result } {} test domNode-12.2 {cloneNode} { set doc [dom parse {text}] set root [$doc documentElement] set newNode [$root cloneNode] $root appendChild $newNode set result [$root asXML -indent none] $doc delete set result } {text} test domNode-12.3 {cloneNode} { set doc [dom parse {text}] set root [$doc documentElement] set newNode [[$root firstChild] cloneNode] $root appendChild $newNode set result [$root asXML -indent none] $doc delete set result } {text} test domNode-12.4 {cloneNode} { set doc [dom parse {text}] set root [$doc documentElement] set newNode [[$root selectNodes {node()[2]}] cloneNode] $root appendChild $newNode set result [$root asXML -indent none] $doc delete set result } {texttext} test domNode-12.5 {cloneNode} { set doc [dom parse {text}] set root [$doc documentElement] set newNode [[$root selectNodes {node()[3]}] cloneNode] $root appendChild $newNode set result [$root asXML -indent none] $doc delete set result } {text} test domNode-12.5 {cloneNode} { set doc [dom parse {text}] set root [$doc documentElement] set newNode [[$root lastChild] cloneNode] $root appendChild $newNode set result [$root asXML -indent none] $doc delete set result } {text} test domNode-12.6 {cloneNode -deep} { set doc [dom parse {
text}] set root [$doc documentElement] set result [[[$root firstChild] cloneNode -deep] asXML -indent none] $doc delete set result } {text} test domNode-12.7 {cloneNode -deep} { set doc [dom parse {text}] set root [$doc documentElement] $root appendChild [[$root firstChild] cloneNode -deep] set result [$root asXML -indent none] $doc delete set result } {texttext} test domNode-12.8 {cloneNode -deep} { set doc [dom parse {text}] set root [$doc documentElement] set removedNode [$root removeChild [$root firstChild]] $root appendChild [[$root firstChild] cloneNode -deep] set result [$root asXML -indent none] $doc delete set result } {texttext} test domNode-12.9 {cloneNode -deep} { set doc [dom parse {text}] set root [$doc documentElement] set removedNode [$root removeChild [$root firstChild]] $root appendChild [[$root firstChild] cloneNode -deep] unset result lappend result [$removedNode nextSibling] lappend result [$removedNode previousSibling] $doc delete set result } {{} {}} test domNode-12.10 {cloneNode -deep} { set doc [dom parse {text}] set root [$doc documentElement] $root removeChild [$root firstChild] set removedNode [$root removeChild [$root firstChild]] $root appendChild [[$root firstChild] cloneNode -deep] unset result lappend result [[$removedNode nextSibling] nodeName] lappend result [$removedNode previousSibling] $doc delete set result } {y {}} test domNode-12.11 {cloneNode -deep w/ disableOutputEscaping} { dom parse "
} namespace eval nodeCmds { dom createNodeCmd elementNode e1 dom createNodeCmd elementNode e2 dom createNodeCmd commentNode c dom createNodeCmd textNode t dom createNodeCmd cdataNode cdata dom createNodeCmd piNode pi dom createNodeCmd parserNode parser } test domNode-13.1 {appendFromScript - elementNode} { set doc [dom createDocument root] set root [$doc documentElement] $root appendFromScript nodeCmds::e1 set result [$root asXML -indent none] $doc delete set result } {} test domNode-13.2 {appendFromScript - elementNode} { set doc [dom createDocument root] set root [$doc documentElement] namespace eval nodeCmds { $::root appendFromScript { e1 e2 } } set result [$root asXML -indent none] $doc delete set result } {} test domNode-13.3 {appendFromScript - elementNode} { set doc [dom createDocument root] set root [$doc documentElement] namespace eval nodeCmds { $::root appendFromScript { e1 { e2 { e1 } } e2 } } set result [$root asXML -indent none] $doc delete set result } {} test domNode-13.4 {appendFromScript - elementNode with attributes as options} { set doc [dom createDocument root] set root [$doc documentElement] namespace eval nodeCmds { $::root appendFromScript { e1 -attr1 attr1Value -attr2 "attr 2 Value" } } set result [$root asXML -indent none] $doc delete set result } {} test domNode-13.5 {appendFromScript - elementNode with attributes as list} { set doc [dom createDocument root] set root [$doc documentElement] set attlist [list -a1 "some & value" -a2 "another attvalue"] namespace eval nodeCmds { $::root appendFromScript { e1 $::attlist {} } } set result [$root asXML -indent none] $doc delete set result } {} test domNode-13.6 {appendFromScript - textnode, commentnode, cdatanode, pinode} { set doc [dom createDocument root] set root [$doc documentElement] namespace eval nodeCmds { $::root appendFromScript { t foo c "my comment" cdata {&"<>;} ;# emacs: " pi mypi "some pi data" } } set result [$root asXML -indent none] $doc delete set result } {foo;]]>} # emacs: " test domNode-13.7 {appendFromScript - textnode} { set doc [dom createDocument root] set root [$doc documentElement] namespace eval nodeCmds { $::root appendFromScript { t "

Some important stuff

" } } set result [$root asXML -indent none] $doc delete set result } {<p>Some <b>important</b> stuff</p>} test domNode-13.8 {appendFromScript - textnode with -disableOutputEscaping} { set doc [dom createDocument root] set root [$doc documentElement] namespace eval nodeCmds { $::root appendFromScript { t -disableOutputEscaping "

Some important stuff

" } } set result [$root asXML -indent none] $doc delete set result } {

Some important stuff

} test domNode-13.9 {appendFromScript while fragment list isn't empty} { set doc [dom parse text] set root [$doc documentElement] $root removeChild [$root firstChild] $root appendFromScript { nodeCmds::t "another text" } set result [llength [$root childNodes]] $doc delete set result } {1} test domNode-13.10 {appendFromScript - tcl error inside the script} { set doc [dom createDocument root] set root [$doc documentElement] set result [catch {$root appendFromScript { nodeCmds::e1 nodeCmds::e1 { # This is intentionally wrong set foo 1 + 1 } }}] lappend result [$doc asXML -indent none] $doc delete set result } {1 } test domNode-13.11 {appendFromScript - tcl error inside the script} { set doc [dom parse ] set root [$doc documentElement] set result [catch {$root appendFromScript { nodeCmds::e1 { nodeCmds::e2 { t foo } nodeCmds::e2 -attr attrvalue { nodeCmds::e2 -attr1 attrvalue attr2 attrvalue { t bar } } } nodeCmds::e1 { # This is intentionally wrong set foo 1 + 1 } }}] lappend result [$doc asXML -indent none] $doc delete set result } {1 } test domNode-13.12 {appendFromScript - node isn't ELEMENT_NODE} { dom parse text doc $doc documentElement root $root firstChild textNode set result [catch {$textNode appendFromScript { nodeCmds::e1 }} errMsg] lappend result $errMsg lappend result [$doc asXML -indent none] $doc delete set result } {1 {NOT_AN_ELEMENT : can't append nodes} text} test domNode-13.13 {createNodeCmd elementNode with invalide tag name} { set result [catch {dom createNodeCmd elementNode \ [list invalid name]} errMsg] lappend result $errMsg } {1 {Invalid tag name 'invalid name'}} namespace eval nodeCmds::thisCmds { } test domNode-13.14 {qualified nodeCmd name} { namespace eval nodeCmds { dom createNodeCmd elementNode thisCmds::thisE } set result [llength [info commands nodeCmds::thisE]] lappend result [llength [info commands nodeCmds::thisCmds::thisE]] set doc [dom createDocument root] set root [$doc documentElement] namespace eval nodeCmds { $::root appendFromScript { thisCmds::thisE } } lappend result [$doc asXML -indent none] $doc delete set result } {0 1 } set nsname "tricky nsname" namespace eval nodeCmds::$nsname { } test domNode-13.15 {qualified nodeCmds name} { namespace eval nodeCmds { dom createNodeCmd elementNode ${::nsname}::thisE } set result [llength [info commands nodeCmds::thisE]] lappend result [llength [info commands nodeCmds::${nsname}::thisE]] set doc [dom createDocument root] set root [$doc documentElement] namespace eval nodeCmds { $::root appendFromScript { ${::nsname}::thisE } } lappend result [$doc asXML -indent none] $doc delete set result } {0 1 } test domNode-13.16 {Invalid attribute name} { set doc [dom createDocument root] set root [$doc documentElement] set result [catch { namespace eval nodeCmds { $::root appendFromScript { e1 att1 att1Value "invalid attname" value {} } } } errMsg] lappend result $errMsg $doc delete set result } {1 {Invalid attribute name 'invalid attname'}} test domNode-13.17 {Invalid attribute value} { set doc [dom createDocument root] set root [$doc documentElement] set result [catch { namespace eval nodeCmds { $::root appendFromScript { e1 att1 att1Value att2 "invalid \u0003 value" {} } } } errMsg] lappend result $errMsg $doc delete set result } [list 1 "Invalid attribute value 'invalid \u0003 value'"] dom setNameCheck 0 namespace eval nodeCmds { dom createNodeCmd elementNode e1 } dom setNameCheck 1 test domNode-13.18 {Invalid attribute name - check disabled} { set doc [dom createDocument root] set root [$doc documentElement] set result [catch { namespace eval nodeCmds { $::root appendFromScript { e1 att1 att1Value "invalid attname" value {} } } }] $doc delete set result } {0} dom setTextCheck 0 namespace eval nodeCmds { dom createNodeCmd elementNode e1 } dom setTextCheck 1 test domNode-13.19 {Invalid attribute value - check disabled} { set doc [dom createDocument root] set root [$doc documentElement] set result [catch { namespace eval nodeCmds { $::root appendFromScript { e1 att1 att1Value att2 "invalid \u0003 value" {} } } }] $doc delete set result } 0 dom setTextCheck 0 dom setNameCheck 0 namespace eval nodeCmds { dom createNodeCmd elementNode e1 } dom setTextCheck 1 dom setNameCheck 1 test domNode-13.20 {Invalid att name, invalid att value, checks disabled} { set doc [dom createDocument root] set root [$doc documentElement] set result [catch { namespace eval nodeCmds { $::root appendFromScript { e1 att1 att1Value "invalid attName" "invalid \u0003 value" {} } } }] $doc delete set result } 0 namespace eval nodeCmds { dom createNodeCmd elementNode e1 } test domNode-13.21 {Invalid comment value} { set doc [dom createDocument root] set root [$doc documentElement] set result [catch { namespace eval nodeCmds { $::root appendFromScript { c "invalid -- comment" } } } errMsg] lappend result $errMsg $doc delete set result } {1 {Invalid comment value 'invalid -- comment'}} test domNode-13.22 {Invalid CDATA section value} { set doc [dom createDocument root] set root [$doc documentElement] set result [catch { namespace eval nodeCmds { $::root appendFromScript { cdata "invalid comment ]]>" } } } errMsg] lappend result $errMsg $doc delete set result } {1 {Invalid CDATA section value 'invalid comment ]]>'}} test domNode-13.23 {Invalid text node} { set doc [dom createDocument root] set root [$doc documentElement] set result [catch { namespace eval nodeCmds { $::root appendFromScript { t "invalid text \u0004" } } } errMsg] lappend result $errMsg $doc delete set result } [list 1 "Invalid text value 'invalid text \u0004'"] test domNode-13.24 {Invalid processing instruction} { set doc [dom createDocument root] set root [$doc documentElement] set result [catch { namespace eval nodeCmds { $::root appendFromScript { pi Xml "data" } } } errMsg] lappend result $errMsg $doc delete set result } [list 1 "Invalid processing instruction name 'Xml'"] test domNode-13.25 {Invalid processing instruction} { set doc [dom createDocument root] set root [$doc documentElement] set result [catch { namespace eval nodeCmds { $::root appendFromScript { pi Xmll "data ?>" } } } errMsg] lappend result $errMsg $doc delete set result } [list 1 "Invalid processing instruction value 'data ?>'"] test domNode-13.26 {appendFromScript with default namespace in scope} { set doc [dom parse {}] set root [$doc documentElement] namespace eval nodeCmds { $::root appendFromScript { e1 } } set result [$doc asXML -indent none] $doc delete set result } {} test domNode-13.27 {delete doc in appendFromScript script} { set doc [dom createDocument doc] set root [$doc documentElement] set result "" $root appendFromScript { ::nodeCmds::e1 { ::nodeCmds::e1 { $doc delete } } lappend result [info commands $doc] ::nodeCmds::e1 } lappend result [info commands $doc] } {{} {}} proc domNode-13.28 {} { dom createDocument doc doc set root [$doc documentElement] $root appendFromScript { ::nodeCmds::e1 { $doc delete } } info commands $doc } test domNode-13.28 {delete doc in appendFromScript script} { domNode-13.28 } {} test domNode-13.29 {tdom::fsinsertNode} { set doc [dom createDocument doc] set root [$doc documentElement] $root appendFromScript { ::nodeCmds::e1 { tdom::fsinsertNode [$doc createElement some] } } set result [$doc asXML -indent none] $doc delete set result } {} test domNode-13.30 {tdom::fsnewNode} { set doc [dom createDocument doc] set root [$doc documentElement] $root appendFromScript { tdom::fsnewNode e1 { tdom::fsinsertNode [$doc createElement some] } } set result [$doc asXML -indent none] $doc delete set result } {} test domNode-13.31 {tdom::fsnewNode} { set doc [dom createDocument doc] set root [$doc documentElement] $root appendFromScript { tdom::fsnewNode e1 { tdom::fsnewNode some att1 "att1 value" { ::nodeCmds::e1 } } } set result [$doc asXML -indent none] $doc delete set result } {} test domNode-13.32 {tdom::fsnewNode} { set doc [dom createDocument doc] set root [$doc documentElement] $root appendFromScript { tdom::fsnewNode e1 { tdom::fsnewNode some {att1 "att1 value"} { ::nodeCmds::e1 } } } set result [$doc asXML -indent none] $doc delete set result } {} test domNode-13.33 {tdom::fsnewNode} { set doc [dom createDocument doc] set root [$doc documentElement] $root appendFromScript { tdom::fsnewNode e1 { tdom::fsnewNode some {-att1 "att1 value" -att2 "att2 value"} { ::nodeCmds::e1 } } } set result [$doc asXML -indent none] $doc delete set result } {} test domNode-14.1 {appendFromList} { set doc [dom createDocument root] set root [$doc documentElement] set errMsg "" set result [catch {$root appendFromList {a b}} errMsg] lappend result $errMsg $doc delete set result } {1 {invalid element node list format!}} test domNode-14.2 {appendFromList} { set doc [dom createDocument root] set root [$doc documentElement] set errMsg "" set result [catch {$root appendFromList {a b c}} errMsg] lappend result $errMsg $doc delete set result } {1 {invalid attributes list format!}} test domNode-14.3 {appendFromList} { set doc [dom createDocument root] set root [$doc documentElement] $root appendFromList {a {} {}} set result [$root asXML -indent none] $doc delete set result } {
} test domNode-14.4 {appendFromList} { set doc [dom createDocument root] set root [$doc documentElement] $root appendFromList {#text "foo bar"} set result [$root asXML -indent none] $doc delete set result } {foo bar} test domNode-14.5 {appendFromList} { set doc [dom parse {texttext}] set elm [$doc documentElement] set elmList [$elm asList] $doc delete set doc [dom createDocument root] set root [$doc documentElement] $root appendFromList $elmList set result [$root asXML -indent none] $doc delete set result } {texttext} set doc [dom parse {text}] set docElem [$doc documentElement] test domNode-14.6 {asList of tree with comment nodes} { $docElem asList } [list elem {} [list [list \#comment " comment "] [list \#text text] [list child [list a v] [list [list \#comment comment]]]]] test domNode-14.7 {asList on a comment} { set commentNode [$docElem firstChild] $commentNode asList } [list \#comment " comment "] test domNode-14.8 {asList on a comment} { set commentNode [$docElem selectNodes {(//comment())[2]}] $commentNode asList } [list \#comment comment] test domNode-14.9 {appendFromList with comment nodes in the list} { set list [$docElem asList] set newDoc [dom createDocument newDoc] set newDocRoot [$newDoc documentElement] $newDocRoot appendFromList $list set result [$newDoc asXML -indent none] $newDoc delete set result } {text} $doc delete set doc [dom parse {text}] set docElem [$doc documentElement] test domNode->14.10 {asList of tree with PI nodes} { $docElem asList } [list elem {} [list [list \#pi myPI value] [list \#text text] [list child [list a v] [list [list \#pi myPI1 "the value"]]]]] test domNode->14.11 {asList on a PI} { set piNode [$docElem firstChild] $piNode asList } [list \#pi myPI value] test domNode->14.12 {asList on a PI} { set piNode [$docElem selectNodes {(//processing-instruction())[2]}] $piNode asList } [list \#pi myPI1 "the value"] test domNode-14.13 {appendFromList with comment node in the list} { set list [$docElem asList] set newDoc [dom createDocument newDoc] set newDocRoot [$newDoc documentElement] $newDocRoot appendFromList $list set result [$newDoc asXML -indent none] $newDoc delete set result } {text} $doc delete test domNode-14.14 {appendFromList - invalid tagname} { set doc [dom createDocument root] set root [$doc documentElement] set errMsg "" set result [catch {$root appendFromList {{invalid tagname} {} {}}} errMsg] lappend result $errMsg $doc delete set result } {1 {Invalid tag name 'invalid tagname'}} test domNode-14.15 {appendFromList - invalid processing instruction name} { set doc [dom createDocument root] set root [$doc documentElement] set errMsg "" set result [catch {$root appendFromList {\#pi "invalid pi name" piValue}} errMsg] lappend result $errMsg $doc delete set result } {1 {Invalid processing instruction name 'invalid pi name'}} set xml { text node text text text text } test domNode-15.1 {delete - text nodes} { set doc [dom parse $xml] set root [$doc documentElement] foreach node [$root selectNodes text()] { $node delete } set result [llength [$root childNodes]] $doc delete set result } {5} test domNode-15.2 {delete - comment nodes} { set doc [dom parse -keepEmpties $xml] set root [$doc documentElement] foreach node [$root selectNodes comment()] { $node delete } set result [llength [$root childNodes]] $doc delete set result } {6} test domNode-15.3 {delete - pi nodes} { set doc [dom parse -keepEmpties $xml] set root [$doc documentElement] foreach node [$root selectNodes processing-instruction()] { $node delete } set result [llength [$root childNodes]] $doc delete set result } {7} test domNode-15.4 {delete - pi nodes} { set doc [dom parse -keepEmpties $xml] set root [$doc documentElement] foreach node [$root selectNodes node()] { $node delete } set result [llength [$root childNodes]] $doc delete set result } {0} test domNode-15.5 {delete - threaded} -constraints { threaded } -setup { set xml { one two three } set doc [dom parse $xml] dom attachDocument $doc doc_ $doc documentElement root } -body { foreach node [$root selectNodes {//attr1 | //attr2}] { [$node firstChild] delete } set result "" } -cleanup { dom detachDocument $doc dom detachDocument $doc_ } -result "" test domNode-15.6 {delete - threaded} -constraints { threaded } -setup { set xml { } set doc [dom parse $xml] dom attachDocument $doc doc_ $doc documentElement root } -body { foreach node [$root selectNodes a] { $node delete } set result "" } -cleanup { dom detachDocument $doc dom detachDocument $doc_ } -result "" set doc [dom parse {}] set root [$doc documentElement] test domNode-16.1 {getAttribute} { $root getAttribute attr1 } {bingbaz} test domNode-16.2 {getAttribute} { $root getAttribute attr2 } {ab & zu} test domNode-16.3 {getAttribute} { $root getAttribute attr3 } {} test domNode-16.4 {getAttribute with default} { $root getAttribute attr1 "default not needed, because attr1 exists" } {bingbaz} test domNode-16.5 {getAttribute with default} { $root getAttribute notPresent "expect this given default value" } {expect this given default value} test domNode-16.6 {getAttribute - attr dosen't exists and no default} { catch {$root getAttribute notPresent} } {1} test domNode-16.7 {getAttribute shortcut} { $root @attr1 } {bingbaz} test domNode-16.8 {getAttribute shortcut} { $root @attr2 } {ab & zu} test domNode-16.9 {getAttribute shortcut} { $root @attr3 } {} test domNode-16.10 {getAttribute shortcut with default} { $root @attr1 "default not needed, because attr1 exists" } {bingbaz} test domNode-16.11 {getAttribute shortcut with default} { $root @notPresent "expect this given default value" } {expect this given default value} test domNode-16.12 {getAttribute shortcut - attr dosen't exists and no default} { catch {$root @notPresent} } {1} $doc delete set doc [dom parse {}] set root [$doc documentElement] test domNode-16.13 {getAttribute} { $root getAttribute xmlns } {uri2} test domNode-16.14 {getAttribute} { $root getAttribute xmlns:foo } {http://tdom.org/ns1} $doc delete set xml { text node text text text text } set doc [dom parse -keepEmpties $xml] set root [$doc documentElement] test domNode-17.1 {nodeType} { unset result foreach node [$root childNodes] { lappend result [$node nodeType] } set result } {TEXT_NODE ELEMENT_NODE COMMENT_NODE TEXT_NODE ELEMENT_NODE COMMENT_NODE PROCESSING_INSTRUCTION_NODE TEXT_NODE} test domNode-17.2 {nodeType} { set CDATAnode [$doc createCDATASection "a CDATA section"] $root insertBefore $CDATAnode [$root firstChild] [$root firstChild] nodeType } {CDATA_SECTION_NODE} $doc delete set doc [dom parse { text child}] set root [$doc documentElement] test domNode-18.1 {attributes} { $root attributes } {{foo foo {}} attr1 attr2 attr3 {attr1 foo http://tdom.org/ns} worble2} test domNode-18.2 {attributes} { $root attributes * } {{foo foo {}} attr1 attr2 attr3 {attr1 foo http://tdom.org/ns} worble2} test domNode-18.3 {attributes} { $root attributes attr* } {attr1 attr2 attr3} test domNode-18.4 {attributes} { $root attributes *2* } {attr2 worble2} test domNode-18.5 {attributes} { $root attributes worble2 } {worble2} test domNode-18.6 {attributes} { $root attributes *brab* } {} test domNode-18.7 {attributes} { [$root firstChild] attributes } {} test domNode-18.1.1 {attributeNames} { $root attributeNames } {xmlns:foo attr1 attr2 attr3 foo:attr1 worble2} test domNode-18.2.1 {attributeNames} { $root attributeNames * } {xmlns:foo attr1 attr2 attr3 foo:attr1 worble2} test domNode-18.3.1 {attributeNames} { $root attributeNames attr* } {attr1 attr2 attr3} test domNode-18.4.1 {attributeNames} { $root attributeNames *2* } {attr2 worble2} test domNode-18.5.1 {attributeNames} { $root attributeNames worble2 } {worble2} test domNode-18.6.1 {attributeNames} { $root attributeNames *brab* } {} test domNode-18.7.1 {attributeNames} { [$root firstChild] attributeNames } {} # Hmmm. This two following tests are mostly there to document the # behavior of the method, as it is. It may debatable if they should # behave this way. The optional attribute name pattern is a tDOM # DOM extension there is nothing in the rec, which could help to argue. # Therefore, it's the way, it is. test domNode-18.8 {attributes} { $root attributes *tdom* } {} test domNode-18.9 {attributes} { $root attributes foo* } {{attr1 foo http://tdom.org/ns}} test domNode-18.9.1 {attributeNames} { $root attributeNames foo:* } {foo:attr1} $doc delete set doc [dom parse {}] set root [$doc documentElement] test domNode-18.10 {attributes} { $root attributes } {{foo foo {}} {xmlns {} {}} attr1 {attr1 foo http://tdom.org/ns1} worble2} $doc delete set doc [dom parse { text child}] set root [$doc documentElement] test domNode-19.1 {removeAttribute} { $root removeAttribute attr1 $root attributes attr1 } {} $doc delete set doc [dom parse { text child}] set root [$doc documentElement] test domNode-19.2 {removeAttribute} { catch {$root removeAttribute attr1} errMsg set errMsg } {can't remove attribute 'attr1'} test domNode-19.3 {removeAttribute} { catch {$root removeAttribute} } {1} test domNode-19.4 {removeAttribute} { catch {$root removeAttribute attr2 attr3} } {1} test domNode-19.5 {removeAttributeNS} { $root removeAttributeNS http://tdom.org/ns attr1 $root hasAttributeNS http://tdom.org/ns attr1 } {0} test domNode-19.6 {removeAttributeNS} { catch {$root removeAttributeNS http://tdom.org attr1} } {1} test domNode-19.7 {removeAttributeNS} { catch {$root removeAttributeNS http://tdom.org/bar thisatt} } {0} $doc delete set doc [dom parse ] set root [$doc documentElement] test domNode-20.1 {parentNode} { $root parentNode } {} test domNode-20.2 {parentNode} { $root parentNode var set var } {} test domNode-20.3 {parentNode} { set child [$root firstChild] [$child parentNode] nodeName } {root} test domNode-20.4 {parentNode} { set child [$root firstChild] $root removeChild $child $child parentNode } {} $doc delete set doc [dom parse {text}] set root [$doc documentElement] test domNode-21.1 {hasChildNodes} { $root hasChildNodes } {1} test domNode-21.2 {hasChildNodes} { set node [$root firstChild] $node hasChildNodes } {0} test domNode-21.3 {hasChildNodes} { set node [$root lastChild] $node hasChildNodes } {1} $doc delete set doc [dom parse { text}] set root [$doc documentElement] test domNode-22.1 {localName} { $root localName } {} test domNode-22.2 {localName} { [$root firstChild] localName } {e1} test domNode-22.3 {localName} { set node [$root firstChild] [$node firstChild] localName } {e2} test domNode-22.4 {localName} { catch {[$root lastChild] localName} errMsg set errMsg } {} test domNode-22.5 {prefix} { [$root firstChild] prefix } {p1} test domNode-22.6 {prefix} { set node [$root firstChild] [$node firstChild] prefix } {} test domNode-22.7 {prefix} { $root prefix } {} $doc delete test domNode-23.1 {replaceChild} { set doc [dom parse {text}] set root [$doc documentElement] set removedNode [$root removeChild [$root firstChild]] $root replaceChild $removedNode [$root firstChild] set result [$root asXML -indent none] $doc delete set result } {} test domNode-23.2 {replaceChild} { set doc [dom parse {text}] set root [$doc documentElement] $root replaceChild [$root lastChild] [$root firstChild] set result [$root asXML -indent none] $doc delete set result } {text} test domNode-23.3 {replaceChild} { set doc [dom parse {text}] set root [$doc documentElement] set e1 [$root firstChild] set e2 [$root lastChild] $e2 replaceChild $e1 [$e2 firstChild] set result [$root asXML -indent none] $doc delete set result } {} test domNode-23.4 {replaceChild} { set doc [dom parse {}] set root [$doc documentElement] set childNodes [$root childNodes] for {set i 1} {$i < 4} {incr i} { $root removeChild [lindex $childNodes $i] } $root replaceChild [lindex $childNodes 1] [$root firstChild] set result [$root asXML -indent none] $doc delete set result } {} test domNode-23.5 {replaceChild} { set doc [dom parse {}] set root [$doc documentElement] set childNodes [$root childNodes] for {set i 1} {$i < 4} {incr i} { $root removeChild [lindex $childNodes $i] } $root replaceChild [lindex $childNodes 2] [$root firstChild] set result [$root asXML -indent none] $doc delete set result } {} test domNode-23.6 {replaceChild} { set doc [dom parse {}] set root [$doc documentElement] set childNodes [$root childNodes] for {set i 1} {$i < 4} {incr i} { $root removeChild [lindex $childNodes $i] } $root replaceChild [lindex $childNodes 3] [$root firstChild] set result [$root asXML -indent none] $doc delete set result } {} test domNode-23.7 {replaceChild} { set doc [dom parse {}] set root [$doc documentElement] set childNodes [$root childNodes] for {set i 1} {$i < 4} {incr i} { $root removeChild [lindex $childNodes $i] } foreach child $childNodes { $root replaceChild $child [$root firstChild] } set result [$root asXML -indent none] $doc delete set result } {} test domNode-24.1 {getLine} { set doc [dom parse ] set root [$doc documentElement] set result [catch {$root getLine}] $doc delete set result } {1} test domNode-24.1.1 {getColumn} { set doc [dom parse ] set root [$doc documentElement] set result [catch {$root getColumn} errMsg] $doc delete lappend result $errMsg } {1 {no line/column information available!}} test domNode-24.1.2 {getByteIndex} { set doc [dom parse ] set root [$doc documentElement] set result [catch {$root getByteIndex} errMsg] $doc delete lappend result $errMsg } {1 {no position information available!}} dom setStoreLineColumn 1 set doc [dom parse { }] set root [$doc documentElement] dom setStoreLineColumn 0 test domNode-24.2 {getLine} { $root getLine } {1} test domNode-24.3 {getColumn} { $root getColumn } {0} test domNode-24.4 {getLine} { [$root firstChild] getLine } {2} test domNode-24.5 {getLine getColumn} { set node [$root selectNodes //e2] set result [$node getLine].[$node getColumn] } {2.4} test domNode-24.6 {getByteIndex} { set node [$root selectNodes //e2] set result [$node getByteIndex] } {11} $doc delete dom setStoreLineColumn 1 test domNode-24.7 {getLine etc text node} { set doc [dom parse { Hello}] set root [$doc documentElement] set node [$root firstChild] set result [$node getLine].[$node getColumn] $doc delete set result } {1.6} test domNode-24.8 {getLine etc cdatasection node} { set doc [dom parse -keepCDATA {}] set root [$doc documentElement] set node [$root firstChild] set result [$node getLine].[$node getColumn] $doc delete set result } {1.6} test domNode-24.8.1 {getLine etc cdatasection node without -keepCDATA} { set doc [dom parse {}] set root [$doc documentElement] set node [$root firstChild] set result [$node getLine].[$node getColumn] $doc delete set result } {1.15} test domNode-24.9 {getLine etc pi node} { set doc [dom parse { }] set root [$doc documentElement] set node [$root firstChild] set result [$node getLine].[$node getColumn] $doc delete set result } {1.6} test domNode-24.10 {getLine etc comment node} { set doc [dom parse { }] set root [$doc documentElement] set node [$root firstChild] set result [$node getLine].[$node getColumn] $doc delete set result } {2.8} test domNode-24.11 {getLine etc multple text/CDATA nodes} { set doc [dom parse -keepCDATA { text}] set root [$doc documentElement] set e1 [$root firstChild] set node [$e1 firstChild] set result [$node getLine].[$node getColumn] $doc delete set result } {2.12} test domNode-24.12 {getLine etc multple text/CDATA nodes} { set doc [dom parse -keepCDATA { textmore text}] set root [$doc documentElement] set e1 [$root firstChild] set node [$e1 firstChild] set result [$node getLine].[$node getColumn]/ set node [$node nextSibling] append result [$node getLine].[$node getColumn]/ set node [$node nextSibling] append result [$node getLine].[$node getColumn] $doc delete set result } {2.12/2.16/3.20} dom setStoreLineColumn 0 set doc [dom parse { text child}] set root [$doc documentElement] test domNode-25.1 {hasAttribute} { $root hasAttribute attr3 } 1 test domNode-25.2 {hasAttribute} { $root hasAttribute attr4 } 0 test domNode-25.3 {hasAttributeNS} { $root hasAttributeNS http://tdom.org/ns attr1 } 1 test domNode-25.4 {hasAttributeNS} { $root hasAttributeNS http://tdom.org attr1 } 0 $doc delete test domNode-26.1 {appendXML} { set doc [dom createDocument root] set root [$doc documentElement] $root appendXML "text" set result [$root asXML -indent none] $doc delete set result } {text} test domNode-26.2 {appendXML} { set doc [dom parse ] set root [$doc documentElement] $root appendXML "text" set result [$root asXML -indent none] $doc delete set result } {text} set doc [dom parse { }] set root [$doc documentElement] test domNode-27.1 {target, data} { set piNode [$root selectNodes /processing-instruction()] set result [$piNode target].[$piNode data] } {piBeforeRoot.do this} test domNode-27.2 {target, data} { set piNodes [$root selectNodes processing-instruction()] set result "" foreach piNode $piNodes { set result "$result [$piNode target].[$piNode data]" } set result } { pi1.my & data pi2.data} $doc delete test domNode-28.1 {getAttributeNS} { set doc [dom parse { }] set root [$doc documentElement] set result [$root getAttributeNS "ns1" attr1] $doc delete set result } {p:attr1Value} test domNode-28.2 {getAttributeNS - default value} { set doc [dom parse { }] set root [$doc documentElement] set result [$root getAttributeNS "not" attr1 "default"] $doc delete set result } {default} test domNode-28.3 {getAttributeNS - default value} { set doc [dom parse { }] set root [$doc documentElement] set result [$root getAttributeNS "not" notexisting "some default"] $doc delete set result } {some default} test domNode-28.4 {getAttributeNS - default value} { set doc [dom parse { }] set root [$doc documentElement] set result [$root getAttributeNS "ns1" notexisting "some other default"] $doc delete set result } {some other default} proc domAppendChild {parent name} { $parent ownerDocument doc $doc createElement $name node $parent appendChild $node } test domNode-29.1 {ownerDocument} { dom createDocument document doc set root [$doc documentElement] domAppendChild $root foo1 domAppendChild $root foo2 set result [$doc asXML -indent none] $doc delete set result } {} set doc [dom parse {text}] set root [$doc documentElement] test domNode-30.1 {precedes} { catch {$root precedes} } {1} test domNode-30.2 {precedes} { set firstChild [$root firstChild] catch {$root start $firstChild foo} } {1} test domNode-30.3 {precedes} { set result [catch {$root precedes notaNode} errMsg] lappend result $errMsg } {1 {Parameter "notaNode" is not a domNode.}} test domNode-30.4 {precedes} { set firstChild [$root firstChild] $root precedes $firstChild } {1} test domNode-30.5 {precedes} { set firstChild [$root firstChild] $root precedes $firstChild } {1} test domNode-30.6 {precedes} { set firstChild [$root firstChild] $firstChild precedes $root } {0} test domNode-30.7 {precedes} { set firstChild [$root firstChild] $firstChild precedes $firstChild } {0} test domNode-30.8 {precedes} { set doc1 [dom parse ] set root1 [$doc1 documentElement] set result [catch {$root precedes $root1} errMsg] lappend result $errMsg $doc1 delete set result } {1 {Cannot compare the relative order of nodes out of different documents.}} test domNode-30.9 {precedes} { set firstChild [$root firstChild] set newNode [$doc createElement newNode] $root insertBefore $newNode $firstChild $newNode precedes $firstChild } {1} test domNode-30.10 {precedes} { set newNode [$doc createTextNode "new text node"] set result [catch {$root precedes $newNode} errMsg] lappend result $errMsg } {1 {Cannot compare the relative order of a node with a node out of the fragment list.}} $doc delete dom parse {} doc $doc documentElement root set e [$root selectNodes //e] set eee [$root selectNodes //eee] test domNode-30.11 {precedes} { $e precedes $eee } {1} test domNode-30.12 {precedes} { $eee precedes $e } {0} $doc delete test domNode-31.1 {insertBefore - syntax check} { set doc [dom parse ] set root [$doc documentElement] set result [catch {$root insertBefore}] $doc delete set result } {1} test domNode-31.2 {insertBefore - syntax check} { set doc [dom parse ] set root [$doc documentElement] set result [catch {$root insertBefore [$root firstChild]}] $doc delete set result } {1} test domNode-31.3 {insertBefore - tries to insert node as child of node} { set doc [dom parse ] set root [$doc documentElement] catch {$root insertBefore $root [$root lastChild]} errMsg $doc delete set errMsg } {HIERARCHY_REQUEST_ERR} test domNode-31.4 {insertBefore - refnode invalide} { set doc [dom parse ] set root [$doc documentElement] set newElement [$doc createElement new] catch {$root insertBefore $newElement $root} errMsg $doc delete set errMsg } {NOT_FOUND_ERR} # Prior to dom.c r1.63 insertBefore leaks the node to insert, if the refnode # isn't valid. test domNode-31.5 {insertBefore - refnode invalide} { set doc [dom parse ] set root [$doc documentElement] set oneChild [$root firstChild] set twoChild [$root lastChild] catch {$oneChild insertBefore [$oneChild firstChild] $root} errMsg set result [list $errMsg [llength [$oneChild childNodes]]] $doc delete set result } {NOT_FOUND_ERR 1} test domNode-31.6 {insertBefore - refnode and new node to insert are the same} { dom parse doc $doc documentElement root $root firstChild firstChild $root insertBefore $firstChild $firstChild set result [$doc asXML -indent none] $doc delete set result } {} test domNode-31.7 {insertBefore - insert a sibling of node} { dom parse {} doc set root [$doc documentElement] $root firstChild a $root lastChild b $a insertBefore $b [$a firstChild] set result [$doc asXML -indent none] $doc delete set result } {} test domNode-31.8 {insertBefore - new node is node} { dom parse doc $doc documentElement root $root firstChild firstChild catch {$root insertBefore $root $firstChild} errMsg $doc delete set errMsg } {HIERARCHY_REQUEST_ERR} test domNode-31.9 {insertBefore tries to insert a parent of node as child} { set doc [dom parse ] set root [$doc documentElement] $root firstChild a catch {$a insertBefore $root [$a firstChild]} errMsg $doc delete set errMsg } {HIERARCHY_REQUEST_ERR} test domNode-31.10 {insertBefore - node to insert is a sibling of ref node} { set doc [dom parse ] $doc documentElement root $root firstChild a $a insertBefore [$a lastChild] [$a firstChild] set result [$doc asXML -indent none] $doc delete set result } {} test domNode-31.11 {insertBefore - node to insert is a sibling of ref node} { set doc [dom parse ] $doc documentElement root $root firstChild a $a insertBefore [$a lastChild] [$a firstChild] catch {unset result} set node [$a firstChild] while {$node != ""} { lappend result [$node nodeName] set node [$node nextSibling] } $doc delete set result } {two one} test domNode-31.12 {insertBefore - node to insert is a sibling of ref node} { set doc [dom parse ] $doc documentElement root $root firstChild a $a insertBefore [$a lastChild] [$a firstChild] catch {unset result} set node [$a lastChild] while {$node != ""} { lappend result [$node nodeName] set node [$node previousSibling] } $doc delete set result } {one two} test domNode-31.13 {insertBefore - node to insert is a sibling of ref node} { set doc [dom parse ] $doc documentElement root $root firstChild a $a insertBefore [$a firstChild] [$a lastChild] set result [$doc asXML -indent none] $doc delete set result } {} test domNode-31.14 {insertBefore - node to insert is a sibling of ref node} { set doc [dom parse ] $doc documentElement root $root firstChild a $a insertBefore [$a firstChild] [$a lastChild] catch {unset result} set node [$a firstChild] while {$node != ""} { lappend result [$node nodeName] set node [$node nextSibling] } $doc delete set result } {one two} test domNode-31.15 {insertBefore - node to insert is a sibling of ref node} { set doc [dom parse ] $doc documentElement root $root firstChild a $a insertBefore [$a firstChild] [$a lastChild] catch {unset result} set node [$a lastChild] while {$node != ""} { lappend result [$node nodeName] set node [$node previousSibling] } $doc delete set result } {two one} test domNode-31.16 {insertBefore - empty ref node} { dom parse doc $doc documentElement root $doc createElement new newNode $root insertBefore $newNode "" set result [$doc asXML -indent none] $doc delete set result } {} test domNode-31.17 {insertBefore - empty ref node} { dom parse doc $doc documentElement root $doc createElement new newNode $root insertBefore $newNode "" set result [$doc asXML -indent none] $doc delete set result } {} test domNode-31.18 {insertBefore - try to insert the root node of the doc} { dom parse doc $doc documentElement root catch {$root insertBefore [$root selectNodes /] [$root firstChild]} errMsg $doc delete set errMsg } {HIERARCHY_REQUEST_ERR} test domNode-31.19 {insertBefore - empty ref node} { dom parse doc $doc documentElement root $root insertBefore [$root firstChild] "" set result [$doc asXML -indent none] $doc delete set result } {} test domNode-31.20 {insertBefore - empty ref node} { dom parse doc $doc documentElement root $root insertBefore [$root firstChild] "" catch {unset result} set node [$root firstChild] while {$node != ""} { lappend result [$node nodeName] set node [$node nextSibling] } $doc delete set result } {b c a} test domNode-31.21 {insertBefore - empty ref node} { dom parse doc $doc documentElement root $root insertBefore [$root firstChild] "" catch {unset result} set node [$root lastChild] while {$node != ""} { lappend result [$node nodeName] set node [$node previousSibling] } $doc delete set result } {a c b} test domNode-31.22 {insertBefore - empty ref node} { dom parse doc $doc documentElement root $root insertBefore [$root lastChild] "" set result [$doc asXML -indent none] $doc delete set result } {} test domNode-31.23 {insertBefore - empty ref node} { dom parse doc $doc documentElement root $root insertBefore [$root lastChild] "" catch {unset result} set node [$root firstChild] while {$node != ""} { lappend result [$node nodeName] set node [$node nextSibling] } $doc delete set result } {a b c} test domNode-31.24 {insertBefore - empty ref node} { dom parse doc $doc documentElement root $root insertBefore [$root lastChild] "" catch {unset result} set node [$root lastChild] while {$node != ""} { lappend result [$node nodeName] set node [$node previousSibling] } $doc delete set result } {c b a} test domNode-31.25 {insertBefore - empty ref node} { dom parse doc $doc documentElement root $root insertBefore [$root selectNodes {*[2]}] "" set result [$doc asXML -indent none] $doc delete set result } {} test domNode-31.26 {insertBefore - empty ref node} { dom parse doc $doc documentElement root $root insertBefore [$root selectNodes {*[2]}] "" catch {unset result} set node [$root firstChild] while {$node != ""} { lappend result [$node nodeName] set node [$node nextSibling] } $doc delete set result } {a c b} test domNode-31.27 {insertBefore - empty ref node} { dom parse doc $doc documentElement root $root insertBefore [$root selectNodes {*[2]}] "" catch {unset result} set node [$root lastChild] while {$node != ""} { lappend result [$node nodeName] set node [$node previousSibling] } $doc delete set result } {b c a} test domNode-31.28 {insertBefore - empty ref node} { dom parse doc $doc documentElement root $root firstChild a $root lastChild b $a insertBefore $b "" set result [$doc asXML -indent none] $doc delete set result } {} test domNode-31.29 {insertBefore - ref node is a node out of the fragment list} { dom parse {} doc $doc documentElement root set newNode [$doc createElement new] set result [catch {$root insertBefore [$root lastChild] $newNode} errMsg] lappend result $errMsg $doc delete set result } {1 NOT_FOUND_ERR} test domNode-31.30 {insertBefore - ref node not a node child, equal to new node} { dom parse {} doc $doc documentElement root set newNode [$doc createElement new] set result [catch {$root insertBefore $newNode $newNode} errMsg] lappend result $errMsg $doc delete set result } {1 NOT_FOUND_ERR} test domNode-32.1 {asText - syntax check} { dom parse doc $doc documentElement root set result [catch {$root asText foo}] $doc delete set result } {1} test domNode-32.2 {asText} { dom parse { pcdata foo bar grill } doc $doc documentElement root set result [$root asText] $doc delete set result } {pcdata foo bar grill} test domNode-32.3 {asText} { dom parse -keepEmpties \ {pcdata Hello, world!]]> more pcdata} doc $doc documentElement root set result [$root asText] $doc delete set result } {pcdata Hello, world! more pcdata} test domNode-32.4 {asText} { dom parse {pcdata} doc $doc documentElement root set newCDATAnode \ [$doc createCDATASection "Hello, world!"] $root appendChild $newCDATAnode set result [$root asText] $doc delete set result } {pcdata} set xml { some text } dom parse $xml doc $doc documentElement root test domNode-32.5 {asText} { $root asText } {some text} test domNode-32.6 {asText} { set result {} foreach child [$root childNodes] { lappend result [$child asText] } set result } {{some text} { A comment } {this is the testPI data }} $doc delete dom parse -keepEmpties $xml doc $doc documentElement root test domNode-32.7 {asText} { $root asText } { some text } $doc delete # The tests in domNode-33.* also uses the nodeCmds created for the # domNode-13.* tests. test domNode-33.1 {insertBeforeFromScript} { set doc [dom parse {}] $doc documentElement root $root insertBeforeFromScript { nodeCmds::e1 } [$root firstChild] set result [$doc asXML -indent none] $doc delete set result } {} test domNode-33.2 {insertBeforeFromScript} { set doc [dom parse {}] $doc documentElement root $root insertBeforeFromScript { nodeCmds::e1 } {} set result [$doc asXML -indent none] $doc delete set result } {} test domNode-33.3 {insertBeforeFromScript - error in the script} { set doc [dom parse {}] $doc documentElement root set result [catch {$root insertBeforeFromScript { nodeCmds::e1 nodeCmds::e1 { # This is intentionally wrong set foo 1 + 1 } } [$root firstChild]}] lappend result [$doc asXML -indent none] $doc delete set result } {1 } test domNode-33.4 {insertBeforeFromScript - insert more then one node} { set doc [dom parse {}] $doc documentElement root namespace eval nodeCmds { $::root insertBeforeFromScript { e1 e2 { t new } e1 } [lindex [$::root childNodes] 1] } set result [$doc asXML -indent none] $doc delete set result } {new} test domNode-33.5 {insertBeforeFromScript - insert more then one node} { set doc [dom parse {}] $doc documentElement root namespace eval nodeCmds { $::root insertBeforeFromScript { e1 e2 { t new } e1 } [lindex [$::root childNodes] 1] } set result "" foreach node [$root childNodes] { append result "[$node nodeName] " } $doc delete set result } {foo e1 e2 e1 bar grill } test domNode-33.6 {insertBeforeFromScript - insert more then one node} { set doc [dom parse {}] $doc documentElement root namespace eval nodeCmds { $::root insertBeforeFromScript { e1 e2 { t new } e1 } [lindex [$::root childNodes] 1] } set result "" set node [$root lastChild] while {$node != ""} { append result "[$node nodeName] " set node [$node previousSibling] } $doc delete set result } {grill bar e1 e2 e1 foo } test domNode-33.7 {insertBeforeFromScript - error in script} { set doc [dom parse {}] $doc documentElement root catch {namespace eval nodeCmds { $::root insertBeforeFromScript { e1 e2 { t new } e1 this is wrong } [lindex [$::root childNodes] 2] }} set result [$doc asXML -indent none] $doc delete set result } {} test domNode-33.8 {insertBeforeFromScript - wrong reference node} { set doc [dom parse {}] $doc documentElement root set result [catch {$root insertBeforeFromScript { nodeCmds::e1 } $root} errMsg] lappend result $errMsg $doc delete set result } {1 NOT_FOUND_ERR} test domNode-34.1 {getBaseURI} {need_uri} { makeFile domNode-34.1-e1.xml [file join [file dir [info script]] data] makeFile domNode-34.1-e2.xml [file join [file dir [info script]] data] set baseURI [tdom::baseURL [file join [pwd] [file dir [info script]] dom.test]] set doc [dom parse \ -baseurl $baseURI \ -externalentitycommand ::tdom::extRefHandler { ]> &a; &b; }] $doc documentElement root set result 1 foreach child [$root childNodes] { lappend baseURIs [$child getBaseURI] } if {([lindex $baseURIs 0] == [lindex $baseURIs 1]) || ([lindex $baseURIs 0] == [lindex $baseURIs 2]) || ([lindex $baseURIs 1] == [lindex $baseURIs 2]) || ([lindex $baseURIs 2] != [$root getBaseURI])} { set result 0 } $doc delete set result } {1} test domNode-34.2 {getBaseURI} {need_uri} { makeFile domNode-34.1-e1.xml [file join [file dir [info script]] data] makeFile domNode-34.1-e2.xml [file join [file dir [info script]] data] set baseURI [tdom::baseURL [file join [pwd] [file dir [info script]] dom.test]] set doc [dom parse \ -baseurl $baseURI \ -externalentitycommand ::tdom::extRefHandler { ]> &a; &b; }] $doc delete set doc [dom parse \ -baseurl $baseURI \ -externalentitycommand ::tdom::extRefHandler { ]> &a; &b; }] $doc documentElement root set result 1 foreach child [$root childNodes] { lappend baseURIs [$child getBaseURI] } if {([lindex $baseURIs 0] == [lindex $baseURIs 1]) || ([lindex $baseURIs 0] == [lindex $baseURIs 2]) || ([lindex $baseURIs 1] == [lindex $baseURIs 2]) || ([lindex $baseURIs 2] != [$root getBaseURI])} { set result 0 } $doc delete set result } {1} proc 35.1 {doc} { $doc documentElement root } test domNode-35.1 {objCmd traces} { for {set x 0} {$x < 1} {incr x} { set doc [dom parse {}] $doc documentElement root 35.1 $doc $doc delete } } {} proc 35.2.2 {doc} { $doc documentElement root } proc 35.2.1 {doc} { $doc documentElement root 35.2.2 $doc return $root } # test domNode-35.2 {objCmd traces} { # set doc [dom parse {}] # set rootCmdName [35.2.1 $doc] # set result [info commands $rootCmdName] # $doc delete # set result # } {} proc 35.3.2 {doc} { $doc documentElement root $doc delete } proc 35.3.1 {doc} { $doc documentElement root 35.3.2 $doc return $root } test domNode-35.3 {objCmd traces} { set doc [dom parse {}] set rootCmdName [35.3.1 $doc] set result [info commands $rootCmdName] set result } {} test domNode-36.1 {nodeName} { set doc [dom parse ] set cdataNode [$doc createCDATASection foo] set result [$cdataNode nodeName] $doc delete set result } \#cdata-section test domNode-36.2 {nodeName} { set doc [dom parse ] set commentNode [$doc createComment foo] set result [$commentNode nodeName] $doc delete set result } \#comment test domNode-36.3 {nodeName} { set doc [dom parse ] set piNode [$doc createProcessingInstruction p "p value"] set result [$piNode nodeName] $doc delete set result } p proc 37.1 {base system public} { return [list string file://this/that \ "External general parsed entity. Text and elements at\ toplevel mixed and so on"] } test domNode-37.1 {baseURI} { set doc [dom parse \ -baseurl "file://foo" \ -externalentitycommand 37.1 -keepEmpties { ]> &a;}] set root [$doc documentElement] set result [$root baseURI] foreach node [$root childNodes] { lappend result [expr {"file://this/that" == [$node baseURI]}] } $doc delete set result } {file://foo 0 1 1 1 1 0} test domNode-37.2 {baseURI} { set doc [dom parse \ -baseurl "file://foo" \ -externalentitycommand 37.1 -keepEmpties { ]> &a;}] set root [$doc documentElement] $root insertBefore [$root lastChild] [$root firstChild] set result {} foreach node [$root childNodes] { lappend result [$node baseURI] } $doc delete set result } {file://foo file://this/that file://this/that file://this/that} test domNode-37.3 {baseURI} { set doc [dom parse \ -baseurl "file://foo" \ -externalentitycommand 37.1 -keepEmpties { ]> &a;}] set root [$doc documentElement] $root appendChild [$root firstChild] set result {} foreach node [$root childNodes] { lappend result [$node baseURI] } $doc delete set result } {file://this/that file://this/that file://this/that file://foo} proc 37.4 {base systemId publicId} { switch $systemId { "a.xml" { return [list string file://base/2 "&b;"] } "b.xml" { return [list string file://base/3 ""] } default { error "error in text script" } } } test domNode-37.4 {baseURI} { set doc [dom parse \ -baseurl "file://base/1" \ -externalentitycommand 37.4 { ]> &a;}] set root [$doc documentElement] set result [$root baseURI] set rootchild [$root firstChild] lappend result [$rootchild baseURI] set rootchildchild [$rootchild firstChild] lappend result [$rootchildchild baseURI] lappend result [[$rootchildchild firstChild] baseURI] lappend result [[$rootchildchild nextSibling] baseURI] lappend result [[$rootchild nextSibling] baseURI] $doc delete set result } {file://base/1 file://base/2 file://base/3 file://base/3 file://base/2 file://base/1} proc 37.5 {base systemId publicId} { switch $systemId { "a.xml" { return [list string file://base/2 "&b;"] } "b.xml" { return [list string file://base/3 ""] } default { error "error in text script" } } } test domNode-37.5 {baseURI} { set doc [dom parse \ -baseurl "file://base/1" \ -externalentitycommand 37.5 { ]> &a;}] set result {} set node [$doc documentElement] while {$node != ""} { lappend result [$node baseURI] set node [$node firstChild] } $doc delete set result } {file://base/1 file://base/1 file://base/1 file://base/2 file://base/2 file://base/3 file://base/3 file://base/3} proc 37.6 {base systemId publicId} { switch $systemId { "a.xml" { return [list string file://base/2 "text"] } default { error "error in text script" } } } test domNode-37.6 {baseURI} { set doc [dom parse \ -baseurl "file://base/1" \ -externalentitycommand 37.6 { ]> &a;}] set result {} set root [$doc documentElement] foreach child [$root childNodes] { lappend result [$child baseURI] } $doc delete set result } {file://base/2 file://base/2 file://base/2 file://base/1} proc 37.7 {base systemId publicId} { switch $systemId { "a.xml" { return [list string file://base/2 "text - base2"] } default { error "error in text script" } } } test domNode-37.7 {baseURI} { set doc [dom parse \ -baseurl "file://base/1" \ -externalentitycommand 37.7 { ]> &a;text - base 1}] set result {} set root [$doc documentElement] foreach child [$root childNodes] { lappend result [$child baseURI] } $doc delete set result } {file://base/2 file://base/2 file://base/2 file://base/1 file://base/1} test domNode-38.1 {toXPath - comment node} { set doc [dom parse { foo}] set root [$doc documentElement] set result {} foreach comment [$root selectNodes comment()] { lappend result [$comment toXPath] } $doc delete set result } {/root/comment()} test domNode-38.2 {toXPath - top level comment} { set doc [dom parse { foo}] set result {} foreach toplevelcomment [$doc selectNodes /comment()] { lappend result [$toplevelcomment toXPath] } $doc delete set result } [list {/comment()[1]} {/comment()[2]} {/comment()[3]}] test domNode-38.3 {toXPath - syntax} -setup { set doc [dom parse ] set root [$doc documentElement] } -body { catch {$root toXPath foo bar} errMsg set errMsg } -cleanup { $doc delete } -match regexp -result {wrong # args: should be "domNode(0x)?[[:xdigit:]]+ toXPath \?-legacy\?"} test domNode-38.4 {toXPath - default xml namespace} -setup { set doc [dom parse {}] $doc selectNodesNamespaces {foo foo} set root [$doc documentElement] set foo1 [$root selectNodes foo:foo] set xfo1 [$foo1 toXPath] } -body { expr {$foo1 == [[$foo1 ownerDocument] selectNodes [$foo1 toXPath]]} } -cleanup { $doc delete } -result 1 test domNode-38.5 {toXPath - default xml namespace} -setup { set doc [dom parse { some text }] set root [$doc documentElement] $doc selectNodesNamespaces {foo foo} set foo2 [$root selectNodes {foo:foo[2]}] } -body { expr {$foo2 == [[$foo2 ownerDocument] selectNodes [$foo2 toXPath]]} } -cleanup { $doc delete } -result 1 test domNode-38.6 {toXPath - xml namespace} -setup { set doc [dom parse { some text }] set root [$doc documentElement] $doc selectNodesNamespaces {foo foo} set foo2 [$root selectNodes {foo:foo[2]}] } -body { expr {$foo2 == [[$foo2 ownerDocument] selectNodes [$foo2 toXPath]]} } -cleanup { $doc delete } -result 1 test domNode-38.7 {toXPath - pathological xml namespace} -setup { set doc [dom parse { some text }] set root [$doc documentElement] $doc selectNodesNamespaces {foo foo} set foo2 [$root selectNodes {foo:foo[2]}] } -body { expr {$foo2 == [[$foo2 ownerDocument] selectNodes [$foo2 toXPath]]} } -cleanup { $doc delete } -result 1 test domNode-38.8 {toXPath - pathological xml namespace} -setup { set doc [dom parse { text some text text }] } -body { set result "" foreach node [$doc selectNodes //node()] { if {$node != [[$node ownerDocument] selectNodes [$node toXPath]]} { set result [$node toXPath] break } } set result } -cleanup { $doc delete } -result "" test domNode-38.9 {toXPath - really long element name} -constraints { knownBug } -setup { set doc [dom parse "<[string repeat abc 100]/>"] set root [$doc documentElement] set firstChild [$root firstChild] } -body { $firstChild toXPath } -cleanup { $doc delete } -result "/doc/[string repeat abc 100]" test domNode-39.1 {text} { set doc [dom parse {text bold more text}] $doc documentElement root set result [$root text] $doc delete set result } {text more text} test domNode-40.1 {laststring} { set doc [dom parse {foobar}] $doc documentElement root set result [$root selectNodes string(e)] lappend result [$root selectNodes laststring(e)] lappend result [$root selectNodes laststring(dontExists)] $doc delete set result } {foo bar {}} test domNode-999.1 {move nodes from one doc to another} { set doc1 [dom parse {}] set doc2 [dom parse {text}] set root1 [$doc1 documentElement] set root2 [$doc2 documentElement] $root1 appendChild [$root2 firstChild] set textNode [[$root1 firstChild] firstChild] if {[$textNode ownerDocument] == $doc1} {set result 1} else {set result 0} $doc1 delete $doc2 delete set result } {1} test domNode-999.2 {node references should not change even after renumbering} { dom parse {} doc set root [$doc documentElement] set oldNode [lindex [$root childNodes] 1] dom parse {} tempDoc set tempNode [$tempDoc documentElement] $oldNode appendChild $tempNode set childList1 [$root childNodes] $root selectNodes {//child[@name='a']} set childList2 [$root childNodes] if {$childList1 == $childList2} { set result 1 } else { set result 0 } $doc delete $tempDoc delete set result } {1} # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/pi.test0000644000175000017500000000263014703531020014412 0ustar rolfrolf# Features covered: Processing Instructions # # This file tests the parser's performance on Processing Instructions. # Sourcing this file into Tcl runs the tests and generates output # for errors. No output means no errors were found. # # Copyright (c) 1998-2000 Zveno Pty Ltd. # # $Id$ source [file join [file dir [info script]] loadtdom.tcl] catch {unset result} proc PI {target data args} { lappend ::result $target $data } test pi-1.1 {PI} { set ::result {} set parser [xml::parser pi-1.1 \ -processinginstructioncommand PI] $parser parse { } $parser free set ::result } {Test {This is a processing instruction}} test pi-1.2 {PI: missing trailing ?} { set ::result {} set parser [xml::parser pi-1.2 \ -processinginstructioncommand PI] set returncode [catch {$parser parse { }} msg] $parser free list $returncode [regexp {error "unclosed token" at.+} $msg] } {1 1} test pi-2.1 {PI with special characters} { set ::result {} set parser [xml::parser pi-2.1 \ -processinginstructioncommand PI] $parser parse { } $parser free set ::result } {Test {[if !VMLRender]}} # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/doctype.test0000644000175000017500000000231014703531020015444 0ustar rolfrolf# Features covered: Document Type Declaration # # This file tests the parser's performance on Document Type Declarations. # Sourcing this file into Tcl runs the tests and generates output # for errors. No output means no errors were found. # # Copyright (c) 1998-2000 Zveno Pty Ltd. # # $Id$ source [file join [file dir [info script]] loadtdom.tcl] catch {unset result} proc doctype {name pub system dtd} { lappend ::result $name $pub $system $dtd } test doctype-1.1 {Document Type Declaration: no internal DTD subset} { set ::result {} catch {rename xml::doctype-1.1 {}} set parser [xml::parser doctype-1.1 \ -startdoctypedeclcommand doctype] $parser parse { } set ::result } {Test NULL NULL 0} test doctype-2.1 {Document Type Declaration: internal DTD subset} { set ::result {} catch {rename xml::doctype-2.1 {}} set parser [xml::parser doctype-2.1 \ -startdoctypedeclcommand doctype] $parser parse { ]> } set ::result } {Test NULL NULL 1} foreach parser [info commands doctype-*] { $parser free } # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/OASIS-suite.tcl0000644000175000017500000002774714703531020015632 0ustar rolfrolf# Helper script to run xslt 1.0 conformance test suite created by the # OASIS XSLT / XPath Conformance Technical Committee. catch {source uri.tcl} package require uri package require tdom # The following is not needed, given, that tDOM is correctly # installed. This code only ensures, that the tDOM script library gets # sourced, if the script is called with a tcldomsh out of the build # dir of a complete tDOM source installation. if {[info commands ::tdom::xmlReadFile] == ""} { # tcldomsh without the script library. Source the lib. source [file join [file dir [info script]] ../lib tdom.tcl] } # Import the tDOM helper procs namespace import tdom::* set catalogfile "" set loglevel 0 set skip [list] set match [list] set matchgroup [list] set matchfile [list] set matchcatalog [list] set verbose 0 proc putsUsage {{channel stderr}} { puts $channel "usage: $::argv0 ?options? path/to/catalog.xml" puts $channel "where options can be:" puts $channel "-loglevel " puts $channel "-skip patternlist" puts $channel "-match patternlist" puts $channel "-matchgroup patternlist" puts $channel "-matchfile patternlist" puts $channel "-matchcatalog patternlist" puts $channel "-verbose " } proc processArgs {argc argv} { variable catalogfile variable skip variable match variable matchgroup variable matchfile variable matchcatalog variable loglevel variable verbose if {$argc == 0 || $argc % 2 == 0} { putsUsage exit 1 } foreach {option value} $argv { if {$value eq ""} { break } switch $option { "-match" { set match $value } "-matchgroup" { set matchgroup $value } "-matchfile" { set matchfile $value } "-skip" { set skip $value } "-matchcatalog" { set matchcatalog $value } "-loglevel" { if {[string is integer -strict $value]} { set loglevel $value } else { putsUsage exit 1 } } "-verbose" { if {[string is boolean -strict $value]} { set verbose $value } else { putsUsage exit 1 } } default { puts stderr "Unknown option \"$option\"" putsUsage exit 1 } } } set catalogfile [lindex $argv end] } set compareOK 0 set compareDIFF 0 set compareFAILED 0 set failedOK 0 set failedXML 0 set failedXSLT 0 set failedProcessing 0 set notFailed 0 proc extRefHandler {base systemId publicId} { variable usageCounter set absolutURI [uri::resolve $base $systemId] incr usageCounter($absolutURI) if {$usageCounter($absolutURI) > 50} { error "Circular import/include?" } switch $systemId { "notfound.xml" { return [list string $absolutURI ""] } } array set uriData [uri::split $absolutURI] switch $uriData(scheme) { file { if {[catch { set xmlstr [xmlReadFile $uriData(path)] }]} { set pathlist [file split $uriData(path)] set file [findFile [lindex $pathlist end] [lrange $pathlist 0 end-1]] if {$file ne ""} { set xmlstr [xmlReadFile $file] } error "not resolved external entity. Base: $base SystemID: $systemId" } return [list string $absolutURI [xmlReadFile $uriData(path)]] } default { error "can only handle file URI's" } } } # This is the callback proc for xslt:message elements. This proc is # called once every time an xslt:message element is encountered during # processing the stylesheet. The callback proc simply sends the text # message to stderr. proc xsltmsgcmd {msg terminate} { variable loglevel if {$loglevel >= 0} { puts stderr "xslt message: '$msg'" } } proc readCatalog {catalogPath} { variable catalogDir variable infoset set fd [open $catalogPath] set doc [dom parse -channel $fd] close $fd set catalogDir [file dirname $catalogPath] set infosetxsl [file join $catalogDir .. TOOLS infoset.xsl] set infosetdoc [dom parse -keepEmpties [xmlReadFile $infosetxsl]] set infoset [$infosetdoc toXSLTcmd] return $doc } proc checkAgainstPattern {patternlist text} { if {![llength $patternlist]} { return 1 } foreach pattern $patternlist { if {[string match $pattern $text]} { return 1 } } return 0 } proc skip {id} { variable skip if {![llength $skip]} { return 0 } return [checkAgainstPattern $skip $id] } proc matchcatalog {testcatalog} { variable matchcatalog if {![llength $matchcatalog]} { return 1 } return [checkAgainstPattern $matchcatalog $testcatalog] } proc log {level text {detail ""}} { variable loglevel if {$level <= $loglevel} { puts $text } if {$detail ne "" && $level < $loglevel} { puts $detail } } proc findFile {filename path} { # The Microsoft testcatalog includes tests for which the physical # file name differ in case from the file name given by the test # definition. This proc tries to identify the correct file name in # such a case. log 3 "findFile called with $filename $path" set filelist [glob -nocomplain -tails -directory $path *] set nocasequal [lsearch -exact -nocase $filelist $filename] if {[llength $nocasequal] == 1} { if {$nocasequal >= 0} { return [file join $path [lindex $filelist $nocasequal]] } } return "" } proc runTest {testcase} { variable catalogDir variable majorpath variable matchgroup variable matchfile variable match variable infoset variable compareOK variable compareDIFF variable compareFAILED variable failedOK variable failedXML variable failedXSLT variable failedProcessing variable notFailed variable verbose variable usageCounter set filepath [$testcase selectNodes string(file-path)] if {![checkAgainstPattern $matchgroup $filepath]} { return } set scenario [$testcase selectNodes scenario] if {[llength $scenario] != 1 } { log 0 "Non-standard scenario!" log 0 [$testcase asXML] return } set operation [$scenario @operation] switch $operation { "standard" - "execution-error" {} default { log 0 "Non-standard scenario!" log 0 [$testcase asXML] return } } set xmlfile [$scenario selectNodes \ {string(input-file[@role="principal-data"])}] set xslfile [$scenario selectNodes \ {string(input-file[@role="principal-stylesheet"])}] set testid [$testcase @id ""] if {![checkAgainstPattern $match $testid]} { return } if {[skip $testid]} { log 1 "Skipping test id $testid (filepath: $filepath)" return } if {![checkAgainstPattern $matchfile $xslfile]} { log 1 "Skipping xslfile $xslfile" return } if {$verbose} { puts [$testcase @id "!!"] } set xmlfile [file join $catalogDir $majorpath $filepath $xmlfile] if {![file readable $xmlfile]} { set xmlfile [findFile $xmlfile \ [file join $catalogDir $majorpath $filepath]] if {$xmlfile eq ""} { log 0 "Couldn't find xmlfile \ [$scenario selectNodes \ {string(input-file[@role="principal-data"])}]" return } } if {![file readable $xslfile]} { set xslfile [findFile $xslfile \ [file join $catalogDir $majorpath $filepath]] if {$xslfile eq ""} { log 0 "Couldn't find xslfile \ [$scenario selectNodes \ {string(input-file[@role="principal-stylesheet"])}]" return } } set xslfile [file join $catalogDir $majorpath $filepath $xslfile] set xmlout [$scenario selectNodes \ {string(output-file[@role="principal" and @compare="XML"])}] set xmloutfile "" if {$xmlout ne ""} { set xmloutfile [file join $catalogDir $majorpath "REF_OUT" $filepath \ $xmlout] } array unset usageCounter if {[catch { set xmldoc [dom parse -baseurl [baseURL $xmlfile] \ -externalentitycommand extRefHandler \ -keepEmpties \ [xmlReadFile $xmlfile] ] } errMsg]} { incr failedXML log 0 "Unable to parse xml file '$xmlfile'. Reason:\n$errMsg" return } dom setStoreLineColumn 1 if {[catch { set xsltdoc [dom parse -baseurl [baseURL $xslfile] \ -externalentitycommand extRefHandler \ -keepEmpties \ [xmlReadFile $xslfile] ] } errMsg]} { dom setStoreLineColumn 0 incr failedXSLT log 0 "Unable to parse xsl file '$xslfile'. Reason:\n$errMsg" return } dom setStoreLineColumn 0 set resultDoc "" if {[catch {$xmldoc xslt -xsltmessagecmd xsltmsgcmd $xsltdoc resultDoc} \ errMsg]} { if {$operation eq "execution-error"} { incr failedOK log 2 $errMsg } else { incr failedProcessing log 0 $errMsg } } else { if {$operation eq "execution-error"} { incr notFailed log 0 "$xslfile - test should have failed, but didn't." } } if {$xmloutfile ne "" && [llength [info commands $resultDoc]]} { if {![catch { set refdoc [dom parse -keepEmpties [xmlReadFile $xmloutfile]] } errMsg]} { set refinfosetdoc [$infoset $refdoc] set resultinfosetdoc [$infoset $resultDoc] if {[$refinfosetdoc asXML -indent none] ne [$resultinfosetdoc asXML -indent none]} { incr compareDIFF log 1 "Result and ref differ." log 2 "Ref:" log 2 [$refinfosetdoc asXML -indent none] log 2 "Result:" log 2 [$resultinfosetdoc asXML -indent none] } else { incr compareOK } $refinfosetdoc delete $resultinfosetdoc delete } else { incr compareFAILED log 3 "Unable to parse REF doc. Reason:\n$errMsg" } } $xmldoc delete $xsltdoc delete catch {$resultDoc delete} } proc runTests {catalogRoot} { variable majorpath variable compareOK variable compareDIFF variable compareFAILED variable failedOK variable failedXML variable failedXSLT variable failedProcessing variable notFailed foreach testcatalog [$catalogRoot selectNodes test-catalog] { if {![matchcatalog [$testcatalog @submitter]]} { continue } set majorpath [$testcatalog selectNodes string(major-path)] foreach testcase [$testcatalog selectNodes test-case] { runTest $testcase } } # Always output the summary variable loglevel 0 log 0 "Finished." log 0 "XML parse failed: $failedXML" log 0 "XSLT parse failed: $failedXSLT" log 0 "Processing failed: $failedProcessing" log 0 "Compare OK: $compareOK" log 0 "Compare FAIL: $compareDIFF" log 0 "Compare BROKEN: $compareFAILED" log 0 "Not found errors: $notFailed" log 0 "Failed OK: $failedOK" } processArgs $argc $argv set catalogDoc [readCatalog $catalogfile] runTests [$catalogDoc documentElement] proc exit args {} tdom-0.9.5-src/tests/cdata.test0000644000175000017500000001722314703531020015062 0ustar rolfrolf# Features covered: CDATA sections # # This file tests the parser's performance on CDATA sections. # Sourcing this file into Tcl runs the tests and generates output # for errors. No output means no errors were found. # # Copyright (c) 1998-2000 Zveno Pty Ltd. # # $Id$ source [file join [file dir [info script]] loadtdom.tcl] catch {unset result} proc pcdata data { append ::result $data } proc Estart {tagName attrList} { switch -- $tagName { Test { } default { incr ::element } } } proc EStop tagname { } test cdata-1.1 {Simple CDATA section} { set ::result {} set ::element 0 catch {rename xml::cdata-1.1 {}} set parser [xml::parser cdata-1.1 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata] $parser parse { } list $::result $::element } {{This is CDATA} 0} test cdata-1.2 {CDATA test contributed by Richard Emberson (emberson@netintouch.com)} { set ::result {} set ::element 0 catch {rename xml::cdata-1.2 {}} set parser [xml::parser cdata-1.2 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata] $parser parse { } list $::result $::element } {{ 928806871035 } 1} # Test bug: ']]>' is not valid character data (XML Rec. subsect. 2.4) - # this should produce a warning. test cdata-2.0 {CDATA section interpersed with comment} { set ::result {} set ::element 0 catch {rename xml::cdata-2.0 {}} set parser [xml::parser cdata-2.0 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata] $parser parse { ]]> -->]]>} list $::result $::element } {{ ]]>} 0} test cdata-2.1 {CDATA section with an angle bracket} { set ::result {} set ::element 0 catch {rename xml::cdata-2.1 {}} set parser [xml::parser cdata-2.1 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata] $parser parse { greater than sign]]> } list $::result $::element } {{This is a > greater than sign} 0} # Test case contributed by Marshall Rose (mrose@dbc.mtview.ca.us) test cdata-2.2 {CDATA section with multiple angle brackets} { set ::result {} set ::element 0 catch {rename xml::cdata-2.2 {}} set parser [xml::parser cdata-2.2 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata] $parser parse { ... ]]> } list $::result $::element } {{ ... } 1} # Test case contributed by J. Linnenkohl (jlinnen@c-s-k.de) test cdata-2.3 {CDATA section with square brackets and curly braces} { set ::result {} set ::element 0 catch {rename xml::cdata-2.3 {}} set parser [xml::parser cdata-2.3 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata] $parser parse { } list $::result $::element } {{ proc arithmetic_add {groups inputs outputs atts} { set ret_val "" set t "Hello World" set l [string length $t] return $ret_val } } 1} test cdata-2.4 {CDATA section with angle brackets and curly braces} { set ::result {} set ::element 0 catch {rename xml::cdata-2.4 {}} set parser [xml::parser cdata-2.4 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata] $parser parse { 2] set t "Hello World" set l [string length $t] return $ret_val } ]]> } list $::result $::element } {{ proc arithmetic_add {groups inputs outputs atts} { set ret_val [expr 1 > 2] set t "Hello World" set l [string length $t] return $ret_val } } 1} test cdata-2.5 {CDATA section with angle brackets, Tcl specials trailing CDATA section} { set ::result {} set ::element 0 catch {rename xml::cdata-2.5 {}} set parser [xml::parser cdata-2.5 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata] $parser parse { 2] set t "Hello World" set l [string length $t] return $ret_val } ]]> that is {jolly} $good } list $::result $::element } {{ proc arithmetic_add {groups inputs outputs atts} { set ret_val [expr 1 > 2] set t "Hello World" set l [string length $t] return $ret_val } that is {jolly} $good } 1} # Test case contributed by Marshall Rose (mrose@dbc.mtview.ca.us) test cdata-3.1 {CDATA section with PI and Tcl special characters} { set ::result {} set ::element 0 catch {rename xml::cdata-3.1 {}} set parser [xml::parser cdata-3.1 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata] $parser parse { this is a \ test ]]> } list $::result $::element } {{ this is a \ test } 2} test cdata-4.1 {CDATA section with entity reference} { set ::result {} set ::element 0 catch {rename xml::cdata-4.1 {}} set parser [xml::parser cdata-4.1 \ -elementstartcommand Estart \ -elementendcommand EStop \ -characterdatacommand pcdata] $parser parse { } list $::result $::element } {{no entity <references>} 0} test cdata-5.1 {CDATA section whiteCDATAs} { set ::result {} set ::cdata {} catch {rename xml::cdata-5.1 {}} set parser [xml::parser cdata-5.1 \ -ignorewhitecdata 1 \ -characterdatacommand pcdata] $parser parse { foo } list $::result } {foo} test cdata-5.2 {CDATA section whiteCDATAs} { set ::result {} set ::cdata {} catch {rename xml::cdata-5.2 {}} set parser [xml::parser cdata-5.2 \ -characterdatacommand pcdata] $parser parse { foo } list $::result } {{ foo }} proc cdh-6.1 {suppliedData data} { if {$suppliedData == "first arg"} { set ::result 1 } else { set ::result 0 } } test cdata-6.1 {CDATA script} { set ::result 0 set p [xml::parser -characterdatacommand [list cdh-6.1 "first arg"]] $p parse {pcdata} $p free set ::result } {1} test cdata-6.2 {declare handler proc later} { catch {rename cdh-6.2 {}} catch {unset ::cdata} set p [xml::parser -characterdatacommand cdh-6.2] proc cdh-6.2 {data} { append ::cdata $data } $p parse {foodatamore data} $p free set ::cdata } {foodatamore data} foreach parser [info commands cdata-*] { $parser free } # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/html5reader.test0000644000175000017500000002653314703531020016226 0ustar rolfrolf# Features covered: HTML parser # # This file contains a collection of tests for the HTML parser. # Tested functionalities: # html5-1.*: Character encoding # html5-2.*: Parsing tests # html5-3.*: Bad data # html5-4.*: DOM building # html5-5.*: Namespaces # # Copyright (c) 2017 Rolf Ade. source [file join [file dir [info script]] loadtdom.tcl] testConstraint html5 [dom featureinfo html5] test html5-1.1 {HTML character entities} {html5} { set doc [dom parse -html5 -ignorexmlns { ¡Äü}] set root [$doc documentElement] set body [$root selectNodes body] set result [$body text] $doc delete set result } "\u00A0\u00A1\u00c4\u00fc" test html5-1.2 {character entities} {html5} { set doc [dom parse -html5 -ignorexmlns {ÖÄÄ}] set root [$doc documentElement] set body [$root selectNodes body] set result [$body text] $doc delete set result } "\u00d6\u00c4\u00c4" test html5-1.3 {character entities} {html5} { set doc [dom parse -html5 -ignorexmlns {€∋}] set root [$doc documentElement] set body [$root selectNodes body] set result [$body text] $doc delete set result } "\u20ac\u220b" test html5-1.4 {invalid characters} {html5} { set doc [dom parse -html5 -ignorexmlns {foo;}] set root [$doc documentElement] set body [$root selectNodes body] set result [$body text] $doc delete set result } "\u0001\u0002\u0003\u0004foo;" test html5-2.1 {not closed p tags} {html5} { set doc [dom parse -html5 -ignorexmlns {

Para 1

Para 2

Para 3 }] set result [$doc asXML -indent none] $doc delete set result } {

Para 1

Para 2

Para 3

} test html5-2.2 {HTML parsing} {html5} { set doc [dom parse -html5 -ignorexmlns {

HTML

}] set result [$doc asXML -indent none] $doc delete set result } {

HTML

} test html5-2.3 {HTML parsing} {html5} { set doc [dom parse -html5 -ignorexmlns {

HTML

}] set result [$doc asXML -indent none] $doc delete set result } {

HTML

} test html5-2.4 {HTML parsing} {html5} { set doc [dom parse -html5 -ignorexmlns {

HTML

}] $doc documentElement root set result [$root nodeName] $doc delete set result } {html} test html5-2.5 {HTML parsing} {html5} { set doc [dom parse -html5 -ignorexmlns {
}] $doc asHTML } {
} test html5-2.6 {HTML parsing} {html5} { set doc [dom parse -html5 -ignorexmlns {
}] $doc asHTML } {
} test html5-2.7 {HTML parsing} {html5} { set doc [dom parse -html5 -ignorexmlns {
}] $doc asHTML } {
} test html5-2.8 {HTML parsing} {html5} { set doc [dom parse -html5 -ignorexmlns {
}] $doc asHTML } {
} test html5-2.9 {HTML parsing} {64bit Tcl9 html5 longRunning} { set result [catch { dom parse -html5 "[string repeat [string repeat [string repeat abcde 1000] 1000] 1000]" } errMsg] lappend result $errMsg } {1 {The Gumbo library doesn't support strings longer than 4 gigabytes.}} # Gumbo has more limitations than just max 4 GByte input string length. # test html5-2.10 {HTML parsing} {64bit Tcl9 html5 knownBug} { # set xml [string repeat [string repeat [string repeat a 1000] 1000] 1000] # set doc [dom parse -html5 $xml] # $doc delete # } {} test html5-3.1 {Bad data} {html5} { set data {line 6 column 17 - Warning: } test html5-3.2 {Bad data} {html5} { set doc [dom parse -html5 -ignorexmlns {
}] set result [$doc asXML -indent none] $doc delete set result } {} test html5-4.1 {Tag name case normalization} {html5} { set doc [dom parse -html5 -ignorexmlns {}] set result [$doc asXML -indent none] $doc delete set result } {} test html5-4.2 {Tag name case normalization} {html5} { set doc [dom parse -html5 -ignorexmlns {}] set result [$doc asXML -indent none] $doc delete set result } {} test html5-4.3 {Attribute normalization} {html5} { set doc [dom parse -html5 -ignorexmlns {}] set result [$doc asXML -indent none] $doc delete set result } {} test html5-4.4 {ID Attribute handling} {html5} { set doc [dom parse -html5 -ignorexmlns {

}] set result [[$doc getElementById 1] getAttribute id] $doc delete set result } {1} set xhtml {h "http://www.w3.org/1999/xhtml"} set svg {svg "http://www.w3.org/2000/svg"} set mathml {mml "http://www.w3.org/1998/Math/MathML"} set xlink {xlink "http://www.w3.org/1999/xlink"} set html5 {

text

} test html5-5.1 {svg subtrees} {html5} { set doc [dom parse -html5 $html5] set result [$doc selectNodes -namespaces $xhtml {string(/h:html/h:body/h:p[2])}] $doc delete set result } {text} set html5 { HTML5 SVG demo

HTML5 SVG Demo

A nice green circle:
Created by DKS. This is free code
} test html5-5.2 {svg subtrees} {html5} { set doc [dom parse -html5 $html5] set svg [$doc selectNodes -namespaces $svg //svg:circle] set result [$svg @fill] $doc delete set result } {green} set html5 { Binomial Theorem

Binomial Theorem:

a + b 2 = a 2 + b 2 + 2 a b } test html5-5.3 {mathml subtrees} {html5} { set doc [dom parse -html5 $html5] set mis [$doc selectNodes -namespaces $mathml //mml:mi] set result "" foreach mi $mis { append result [$mi text] } $doc delete set result } {ababab} set html5 { } test html5-5.4 {xlink attribute} {html5} { set doc [dom parse -html5 $html5] set node [$doc selectNodes -namespaces $xlink {//*[@xlink:href]}] set result [$node getAttributeNS [lindex $xlink 1] href] $doc delete set result } {huge-red-circle.svg} test html5-5.5 {xlink attribute} {html5} { set doc [dom parse -html5 -ignorexmlns $html5] set node [$doc getElementById "image"] set result [$node getAttribute "xlink:href"] $doc delete set result } {huge-red-circle.svg} # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/pullparser.test0000644000175000017500000007302014703531020016174 0ustar rolfrolf# Features covered: Pull parser # # This file contains a collection of tests for the pull parser # interface. # Tested functionalities: # pp-1.*: Basics, interface # pp-2.*: Compare dom / pull parsing # pp-3.*: skip method # pp-4.*: find-element method # pp-5.*: CDATA section handling # pp-6.*: line/column methods # # Copyright (c) 2017-2018 Rolf Ade. source [file join [file dir [info script]] loadtdom.tcl] test pp-1.1 {Create} { tdom::pullparser pp pp delete } {} test pp-1.2 {Invalid create} { catch {tdom::pullparser pp foo} } 1 test pp-1.3 {Reset freshly created parser} { tdom::pullparser pp pp reset pp reset pp delete } {} test pp-1.4 {State after creation} { tdom::pullparser pp set result [pp state] lappend result [pp state] pp delete set result } {READY READY} proc walkDOM {node} { set str "" switch [$node nodeType] { "ELEMENT_NODE" { append str [$node nodeName] # Because the dom builder arranges attributes so that the # xmlns attributes come first we need to ensure a unify # attribute order for comparsion. set attpairs [list] foreach att [$node attributes] { if {[llength $att] == 3} { if {[lindex $att 2] eq ""} { lappend attpairs [list \ xmlns:[lindex $att 0] \ [$node getAttribute xmlns:[lindex $att 0]]] } else { lappend attpairs [list \ [lindex $att 1]:[lindex $att 0] \ [$node getAttribute [lindex $att 1]:[lindex $att 0]]] } } else { lappend attpairs [list $att [$node getAttribute $att]] } } foreach {name value} [lsort -index 0 $attpairs] { append str $name $value } foreach child [$node childNodes] { append str [walkDOM $child] } append str /[$node nodeName] } "TEXT_NODE" { append str [$node nodeValue] } default { # Ignore anything else } } return $str } proc loopPull {} { while {[set state [pp next]] ne "END_DOCUMENT"} { switch $state { "START_TAG" { append pullstr [pp tag] set attpairs [list] foreach {attname attvalue} [pp attributes] { lappend attpairs [list $attname $attvalue] } foreach {name value} [lsort -index 0 $attpairs] { append pullstr $name $value } } "TEXT" { append pullstr [pp text] } "END_TAG" { append pullstr /[pp tag] } } } return $pullstr } proc comparewithDOM {data {inputMethod input}} { if {$inputMethod eq "input"} { dom parse $data doc } elseif {$inputMethod eq "inputchannel"} { dom parse -channel $data doc } else { dom parse -keepEmpties [::tdom::xmlReadFile $data] doc } set domstr [walkDOM [$doc documentElement]] $doc delete tdom::pullparser pp pp $inputMethod $data set pullstr [loopPull] if {$domstr eq $pullstr} { return 1 } else { puts "*** DOM str:" puts $domstr puts "*** Pull str:" puts $pullstr return 0 } pp delete } proc fdata {file} { file join [file dir [info script]] data/$file } test pp-2.1 {dom/pull comparsion: mondial-europe.xml} {longRunning} { comparewithDOM [fdata mondial-europe.xml] inputfile } 1 test pp-2.2 {dom/pull comparsion: books.xml} { comparewithDOM [fdata books.xml] inputfile } 1 test pp-2.3 {dom/pull comparsion: i18n_1.xml} { comparewithDOM [fdata i18n_1.xml] inputfile } 1 test pp-2.4 {dom/pull comparsion: i18n_2.xml} { comparewithDOM [fdata i18n_2.xml] inputfile } 1 test pp-2.5 {dom/pull comparsion: REC-xslt-19991116.xml} {longRunning} { comparewithDOM [fdata REC-xslt-19991116.xml] inputfile } 1 test pp-2.6 {dom/pull comparsion: xslt_1.xsl} { comparewithDOM [fdata xslt_1.xsl] inputfile } 1 test pp-2.7 {dom/pull comparsion} { comparewithDOM {

This specification defines the syntax and semantics of XSLT, which is a language for transforming XML documents into other XML documents.

} } 1 test pp-2.8 {dom/pull comparsion} { comparewithDOM {

(see ), which is referred to in

} } 1 test pp-2.9 {dom/pull comparsion} { comparewithDOM {

This specification defines the syntax and semantics of the XSLT language. A transformation in the XSLT language is expressed as a well-formed XML document conforming

} } 1 proc loopPullE {} { while {[set state [pullparser next]] ne "END_DOCUMENT"} { switch $state { "START_TAG" { append pullstr [pullparser tag] foreach {attname attvalue} [pullparser attributes] { append pullstr $attname $attvalue } } "TEXT" { append pullstr [pullparser text] } "END_TAG" { append pullstr /[pullparser tag] } } } return $pullstr } proc elementstart {name atts} { global expatstr append expatstr $name foreach {attname attvalue} $atts { append expatstr $attname $attvalue } } proc elementend {name} { global expatstr append expatstr /$name } proc cdata {cdata} { global expatstr append expatstr $cdata } proc comparewithExpat {data {inputMethod ""}} { global expatstr set expatstr "" expat pushparser \ -elementstartcommand elementstart \ -elementendcommand elementend \ -characterdatacommand cdata pushparser parse$inputMethod $data tdom::pullparser pullparser pullparser input$inputMethod $data set pullstr [loopPullE] if {$expatstr eq $pullstr} { return 1 } else { puts $expatstr puts $pullstr return 0 } pushparser free pullparser delete } test pp-2.10 {expat/pull comparsion: mondial-europe.xml} {longRunning} { comparewithExpat [fdata mondial-europe.xml] file } 1 test pp-2.11 {expat/pull comparsion: books.xml} { comparewithExpat [fdata books.xml] file } 1 test pp-2.12 {expat/pull comparsion: i18n_1.xml} { comparewithExpat [fdata i18n_1.xml] file } 1 test pp-2.13 {expat/pull comparsion: i18n_2.xml} { comparewithExpat [fdata i18n_2.xml] file } 1 test pp-2.14 {expat/pull comparsion: REC-xslt-19991116.xml} {longRunning} { comparewithExpat [fdata REC-xslt-19991116.xml] file } 1 test pp-2.15 {expat/pull comparsion: xslt_1.xsl} { comparewithExpat [fdata xslt_1.xsl] file } 1 test pp-2.16 {expat/pull comparsion} { comparewithExpat {

This specification defines the syntax and semantics of XSLT, which is a language for transforming XML documents into other XML documents.

} } 1 test pp-2.17 {expat/pull comparsion} { comparewithExpat {

(see ), which is referred to in

} } 1 test pp-2.18 {expat/pull comparsion} { comparewithExpat {

This specification defines the syntax and semantics of the XSLT language. A transformation in the XSLT language is expressed as a well-formed XML document conforming

} } 1 test pp-3.1 {skip} { tdom::pullparser pp pp input set result [pp next] lappend result [pp tag] lappend result [pp skip] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_TAG doc END_TAG doc END_DOCUMENT} test pp-3.1.1 {skip} { tdom::pullparser pp pp input {} set result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] lappend result [pp skip] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_TAG doc START_TAG e END_TAG e END_TAG doc END_DOCUMENT} test pp-3.1.2 {skip} { tdom::pullparser pp pp input {texttext} set result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp skip] lappend result [pp tag] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_TAG doc TEXT text START_TAG e END_TAG e TEXT text END_TAG doc END_DOCUMENT} test pp-3.1.3 {skip} { tdom::pullparser pp pp input {textbarbaztexttext} set result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp skip] lappend result [pp tag] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_TAG doc TEXT text START_TAG e END_TAG e TEXT text END_TAG doc END_DOCUMENT} test pp-3.1.4 {skip} { tdom::pullparser pp pp input set result [pp next] lappend result [pp tag] lappend result [pp skip] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_TAG doc END_TAG doc END_DOCUMENT} test pp-3.1.5 {skip} { tdom::pullparser pp pp input { } set result [pp next] lappend result [pp tag] lappend result [pp skip] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_TAG doc END_TAG doc END_DOCUMENT} test pp-3.1.5 {skip} { tdom::pullparser pp -ignorewhitecdata pp input { } set result [pp next] lappend result [pp tag] lappend result [pp skip] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_TAG doc END_TAG doc END_DOCUMENT} test pp-3.2 {skip} { tdom::pullparser pp pp input {} set result [pp next] lappend result [pp tag] lappend result [pp skip] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_TAG doc END_TAG doc END_DOCUMENT} test pp-3.3 {skip} { tdom::pullparser pp pp input {foo bar} set result [pp next] lappend result [pp tag] lappend result [pp skip] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_TAG doc END_TAG doc END_DOCUMENT} test pp-3.4 {skip} { tdom::pullparser pp pp input {foo barbar} set result [pp next] lappend result [pp tag] lappend result [pp skip] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_TAG doc END_TAG doc END_DOCUMENT} test pp-3.5 {skip} { tdom::pullparser pp pp input {foo barbar} set result [list] while {[set state [pp next]] ne "END_DOCUMENT"} { lappend result $state if {$state eq "START_TAG"} { lappend result [pp tag] if {[pp tag] eq "e"} { pp skip continue } } if {[pp state] eq "END_TAG"} { lappend result [pp tag] } } pp delete set result } {START_TAG doc TEXT START_TAG e START_TAG e START_TAG e END_TAG doc} test pp-3.6 {skip} { tdom::pullparser pp pp input {foo barbarbaz} set result [list] while {[set state [pp next]] ne "END_DOCUMENT"} { lappend result $state if {$state eq "START_TAG"} { lappend result [pp tag] if {[pp tag] eq "e"} { pp skip continue } } if {[pp state] eq "END_TAG"} { lappend result [pp tag] } if {[pp state] eq "TEXT"} { lappend result [pp text] } } pp delete set result } {START_TAG doc TEXT {foo bar} START_TAG e START_TAG e START_TAG e TEXT baz END_TAG doc} test pp-3.7 {skip} { tdom::pullparser pp pp input {foo barbar} set result [pp next] lappend result [pp next]; # TEXT "foo bar" lappend result [pp next]; # START_TAG lappend result [pp tag]; # e lappend result [pp next]; # END_TAG lappend result [pp tag]; # e lappend result [pp next]; # START_TAG lappend result [pp tag]; # e lappend result [catch {pp skip} errMsg] lappend result $errMsg pp delete set result } {START_TAG TEXT START_TAG e END_TAG e START_TAG e 1 {error "mismatched tag" at line 1 column 24}} test pp-3.8 {skip} { tdom::pullparser pp pp input {foo barbar} set result [pp next] lappend result [pp skip] lappend result [pp tag] lappend result [pp next] lappend result [catch {pp next} errMsg] lappend result $errMsg pp delete set result } {START_TAG END_TAG doc END_DOCUMENT 1 {No next event after END_DOCUMENT}} test pp-3.9 {skip} { tdom::pullparser pp pp input {} set result [pp next] lappend result [catch {pp skip}] pp reset pp input {text} lappend result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp text] pp delete set result } {START_TAG 1 START_TAG doc TEXT text} test pp-4.1 {find-element} { tdom::pullparser pp pp input {
foo barbazgrillhere} set result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] lappend result [pp find-element d] lappend result [pp tag] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] while {[pp next] ne "END_DOCUMENT"} {} pp delete set result } {START_TAG doc START_TAG a START_TAG d TEXT here END_TAG d} test pp-4.2 {find-element} { tdom::pullparser pp pp input {foo barbazgrill} set result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] lappend result [pp find-element d] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] while {[pp next] ne "END_DOCUMENT"} {} pp delete set result } {START_TAG doc START_TAG a START_TAG d END_TAG d} test pp-4.3 {find-element} { tdom::pullparser pp pp input {foo barbazgrillsome} set result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] lappend result [pp find-element d] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] while {[pp next] ne "END_DOCUMENT"} {} pp delete set result } {START_TAG doc START_TAG a START_TAG d END_TAG d} test pp-4.4 {find-element} { tdom::pullparser pp pp input {grill} set result [pp next] lappend result [pp tag] lappend result [pp find-element d] lappend result [pp tag] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] while {[pp next] ne "END_DOCUMENT"} {} pp delete set result } {START_TAG doc START_TAG d TEXT grill END_TAG d END_TAG c} test pp-4.5 {find-element} { tdom::pullparser pp pp input {} set result [pp next] lappend result [pp tag] lappend result [pp find-element d] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] while {[pp next] ne "END_DOCUMENT"} {} pp delete set result } {START_TAG doc START_TAG d END_TAG d END_TAG c} test pp-4.6 {find-element} { tdom::pullparser pp pp input {} set result [pp next] lappend result [pp tag] lappend result [pp find-element d] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] while {[pp next] ne "END_DOCUMENT"} {} pp delete set result } {START_TAG doc START_TAG d END_TAG d END_TAG c} test pp-4.7 {find-element} { tdom::pullparser pp pp input {} set result [pp next] lappend result [pp tag] lappend result [pp find-element b] lappend result [pp tag] lappend result [pp find-element c] lappend result [pp tag] lappend result [pp find-element a] lappend result [pp tag] while {[pp next] ne "END_DOCUMENT"} {} pp delete set result } {START_TAG doc START_TAG b START_TAG c START_TAG a} test pp-4.8 {find-element} { tdom::pullparser pp pp input {} set result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] lappend result [pp find-element b] pp delete set result } {START_TAG doc END_TAG doc END_DOCUMENT} test pp-4.8.1 {find-element} { tdom::pullparser pp pp input {} set result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] lappend result [pp find-element b] pp delete set result } {START_TAG doc END_TAG doc END_DOCUMENT} test pp-4.8.2 {find-element} { tdom::pullparser pp pp input { } set result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp next] lappend result [pp tag] lappend result [pp find-element b] pp delete set result } {START_TAG doc TEXT END_TAG doc END_DOCUMENT} test pp-4.8.3 {find-element} { tdom::pullparser pp -ignorewhitecdata pp input { } set result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] lappend result [pp find-element b] pp delete set result } {START_TAG doc END_TAG doc END_DOCUMENT} test pp-4.9 {find-element} { tdom::pullparser pp pp input {} set result [pp next]; # START_TAG lappend result [pp tag]; # doc lappend result [pp next]; # START_TAG lappend result [pp tag]; # a lappend result [pp find-element b]; # START_TAG lappend result [pp tag]; #b lappend result [pp find-element c]; # START_TAG lappend result [pp tag]; #c lappend result [pp next]; # END_TAG lappend result [pp tag]; # c lappend result [pp find-element a]; # START_TAG lappend result [pp tag]; # a while {[pp next] ne "END_DOCUMENT"} {} pp delete set result } {START_TAG doc START_TAG a START_TAG b START_TAG c END_TAG c START_TAG a} test pp-4.10 {find-element} { tdom::pullparser pp pp input {foobargrillbaz} set result [pp next]; # START_TAG lappend result [pp tag]; # doc lappend result [pp find-element a]; # START_TAG lappend result [pp tag]; # a lappend result [pp next]; # END_TAG lappend result [pp tag]; # a lappend result [pp find-element a]; # START_TAG lappend result [pp tag]; #a lappend result [pp next]; # END_TAG lappend result [pp tag]; # a lappend result [pp next]; # TEXT lappend result [pp text]; # baz lappend result [pp next]; # END_TAG lappend result [pp tag]; # b while {[pp next] ne "END_DOCUMENT"} {} pp delete set result } {START_TAG doc START_TAG a END_TAG a START_TAG a END_TAG a TEXT baz END_TAG b} test pp-4.11 {find-element} { tdom::pullparser pp pp input {foobargrillbaz} set result [pp state] lappend result [pp find-element a]; # START_TAG lappend result [pp tag]; # a lappend result [pp next]; # END_TAG lappend result [pp tag]; # a lappend result [pp find-element a]; # START_TAG lappend result [pp tag]; #a lappend result [pp next]; # END_TAG lappend result [pp tag]; # a lappend result [pp next]; # TEXT lappend result [pp text]; # baz lappend result [pp next]; # END_TAG lappend result [pp tag]; # b while {[pp next] ne "END_DOCUMENT"} {} pp delete set result } {START_DOCUMENT START_TAG a END_TAG a START_TAG a END_TAG a TEXT baz END_TAG b} test pp-4.12 {find-element} { tdom::pullparser pp pp input {foobargrillbaz} set result [pp state] pp find-element a lappend result [pp find-element a]; # START_TAG lappend result [pp tag]; #a lappend result [pp next]; # END_TAG lappend result [pp tag]; # a lappend result [pp next]; # TEXT lappend result [pp text]; # baz lappend result [pp next]; # END_TAG lappend result [pp tag]; # b while {[pp next] ne "END_DOCUMENT"} {} pp delete set result } {START_DOCUMENT START_TAG a END_TAG a TEXT baz END_TAG b} test pp-4.13 {find-element} { tdom::pullparser pp pp input {} set result [pp state] lappend result [pp find-element a] pp delete set result } {START_DOCUMENT END_DOCUMENT} test pp-4.14 {find-element} { tdom::pullparser pp pp input {foo barbar} set result [pp next] lappend result [pp skip] lappend result [pp tag] lappend result [pp find-element b] lappend result [catch {pp next} errMsg] lappend result $errMsg pp delete set result } {START_TAG END_TAG doc END_DOCUMENT 1 {No next event after END_DOCUMENT}} test pp-4.15 {find-element} { tdom::pullparser pp pp input {} set result [pp next] lappend result [pp tag] for {set i 0} {$i < 3} {incr i} { lappend result [pp find-element -names {a b c}] lappend result [pp tag] } while {[pp next] ne "END_DOCUMENT"} {} pp delete set result } {START_TAG doc START_TAG a START_TAG b START_TAG a} test pp-5.1 {CDATA section} { tdom::pullparser pp pp input {} set result [pp state] lappend result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_DOCUMENT START_TAG doc TEXT { some text } END_TAG doc END_DOCUMENT} test pp-5.2 {CDATA section inside of text} { tdom::pullparser pp pp input {beforeafter} set result [pp state] lappend result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_DOCUMENT START_TAG doc TEXT {before some text after} END_TAG doc END_DOCUMENT} test pp-5.3 {CDATA section after text} { tdom::pullparser pp pp input {before} set result [pp state] lappend result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_DOCUMENT START_TAG doc TEXT {before some text } END_TAG doc END_DOCUMENT} test pp-5.4 {CDATA section before text} { tdom::pullparser pp pp input {after} set result [pp state] lappend result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_DOCUMENT START_TAG doc TEXT { some text after} END_TAG doc END_DOCUMENT} test pp-5.5 {White space only CDATA section inside text} { tdom::pullparser pp pp input {before after} set result [pp state] lappend result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_DOCUMENT START_TAG doc TEXT {before after} END_TAG doc END_DOCUMENT} test pp-5.6 {White space only CDATA section inside text with -ignorewhitecdata} { tdom::pullparser pp -ignorewhitecdata pp input {before after} set result [pp state] lappend result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_DOCUMENT START_TAG doc TEXT {before after} END_TAG doc END_DOCUMENT} test pp-5.6 {White space only CDATA section inside text with -ignorewhitecdata} { tdom::pullparser pp -ignorewhitecdata pp input {before after} set result [pp state] lappend result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_DOCUMENT START_TAG doc TEXT {before after} END_TAG doc END_DOCUMENT} test pp-5.7 {White space only CDATA section inside white space only text w/ -ignorewhitecdata} { tdom::pullparser pp -ignorewhitecdata pp input { } set result [pp state] lappend result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_DOCUMENT START_TAG doc END_TAG doc END_DOCUMENT} test pp-5.8 {White space only CDATA section before text w/ -ignorewhitecdata} { tdom::pullparser pp -ignorewhitecdata pp input { after} set result [pp state] lappend result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_DOCUMENT START_TAG doc TEXT { after} END_TAG doc END_DOCUMENT} test pp-5.9 {Successive CDATA sections} { tdom::pullparser pp pp input { after} set result [pp state] lappend result [pp next] lappend result [pp tag] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp next] pp delete set result } {START_DOCUMENT START_TAG doc TEXT { onetwo after} END_TAG doc END_DOCUMENT} test pp-6.1 {line} { tdom::pullparser pp set result [catch {pp line}] pp input { after} lappend result [pp line] lappend result [pp next] lappend result [pp tag] lappend result [pp line] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp line] lappend result [pp next] lappend result [pp line] pp delete set result } {1 0 START_TAG doc 1 TEXT { onetwo after} END_TAG doc 1 END_DOCUMENT 1} test pp-6.2 {column} { tdom::pullparser pp set result [catch {pp column}] pp input { after} lappend result [pp column] lappend result [pp next] lappend result [pp tag] lappend result [pp column] lappend result [pp next] lappend result [pp text] lappend result [pp next] lappend result [pp tag] lappend result [pp column] lappend result [pp next] lappend result [pp column] pp delete set result } {1 0 START_TAG doc 5 TEXT { onetwo after} END_TAG doc 62 END_DOCUMENT 62} test pp-6.3 {column} { tdom::pullparser pp pp input {foobargrill} set result [list] while {[pp next] ne "END_DOCUMENT"} { if {[pp state] eq "TEXT"} { lappend result [pp text] } else { lappend result [pp tag] lappend result [pp column] } } pp delete set result } {doc 5 foo b 11 bar b 18 grill doc 29} test pp-6.4 {line/column} { tdom::pullparser pp pp input {foo bar grill} set result [list] while {[pp next] ne "END_DOCUMENT"} { if {[pp state] eq "TEXT"} { lappend result [pp text] } else { lappend result [pp tag] lappend result [pp line]/[pp column] } } pp delete set result } {doc 1/5 {foo } b 2/3 {bar } b 3/4 grill doc 3/15} test pp-6.5 {column} { tdom::pullparser pp pp input {foobargrill} set result [list] while {[pp next] ne "END_DOCUMENT"} { if {[pp state] eq "TEXT"} { lappend result [pp text] } else { lappend result [pp tag] lappend result [pp column] } } lappend result [pp column] pp delete set result } {doc 20 foo b 36 bar b 43 grill doc 54 54} test pp-6.6 {line/column after parsing error} { tdom::pullparser pp pp input {an < xml error } pp next set result [catch {pp skip}] lappend result [pp line]/[pp column] pp delete set result } {1 2/9} tdom-0.9.5-src/tests/parser.test0000644000175000017500000006714514703531020015312 0ustar rolfrolf# Features covered: Parser functions # # This file tests the parser's basic functions. # # parser-1.*: parser creation # parser-2.*: return code 'break' from callback # parser-3.*: return code 'continue' from callback # parser-4.*: return code 'error' from callback # parser-5.*: parse input from channel # parser-6.*: reuse parser # parser-7.*: parser reset # parser-8.*: parser free # parser-9.*: parser parse # parser-10.*: return code 'return' from callback # parser-11.*: parser input from filename # parser-12.*: parser currentmarkup # parser-13.*: getline/column/byteindex # # Copyright (c) 1999-2000 Zveno Pty Ltd. # Copyright (c) 2002-2024 Rolf Ade # # $Id$ source [file join [file dir [info script]] loadtdom.tcl] proc parray arrayName { upvar #0 $arrayName arr foreach key [lsort [array names $arrayName]] { lappend result $key $arr($key) } return $result } catch {unset count} proc Count {args} { if {![info exists ::count]} { set ::count 1 } else { incr ::count } } catch {unset started} proc Start {name atList args} { array set opts $args array set atts $atList if {![info exists ::started($name)]} { set ::started($name) 1 } else { incr ::started($name) } if {[info exists atts(class)]} { switch $atts(class) { continue { return -code continue } break { return -code break } error { return -code error "error condition in callback" } return { return -code return } default { return -code $atts(class) } } } } catch {unset ended} proc End {name args} { array set opts $args if {![info exists ::ended($name)]} { set ::ended($name) 1 } else { incr ::ended($name) } } proc PI {name args} { return -code $name } catch {unset elList} proc ElStart {name atList args} { array set opts {-empty 0} array set opts $args lappend ::elList start $name $opts(-empty) } proc ElEnd {name args} { array set opts {-empty 0} array set opts $args lappend ::elList end $name $opts(-empty) } test parser-1.1 {parser creation} { set p [::xml::parser] regexp {^xmlparser[0-9]+$} $p } 1 test parser-1.2 {parser creation, only options} { set p [::xml::parser -elementstartcommand Start] regexp {^xmlparser[0-9]+$} $p } 1 test parser-1.3 {parser creation, named} { catch {rename parser-1.3 {}} ::xml::parser parser-1.3 } parser-1.3 test parser-1.4 {parser creation, named with options} { catch {rename parser-1.4 {}} ::xml::parser parser-1.4 -elementstartcommand Start } parser-1.4 test parser-1.5 {parser freeing, wrong nr of args} { set p [expat] if {[set result [catch {$p free wrongarg}]]} { $p free } set result } 1 test parser-1.6 {parser create syntax check} { set result [catch {set parser [expat -paramentityparsing wrong]} errMsg] lappend result $errMsg } {1 {bad value "wrong": must be always, never, or notstandalone}} test parser-1.7 {parser cget syntax} { catch {rename parser-1.7 {}} set parser [expat parser-1.7] set result [catch {$parser cget} errMsg] lappend result $errMsg } {1 {wrong # args: should be "parser-1.7 cget ?-handlerset handlersetname? switch"}} test parser-1.8 {parser cget syntax} { catch {rename parser-1.8 {}} set parser [expat parser-1.8] set result [catch {$parser cget -handlerset -final} errMsg] lappend result $errMsg } {1 {wrong # args: should be "?-handlerset handlersetname? switch"}} test parser-1.9 {parser cget syntax} { catch {rename parser-1.9 {}} set parser [expat parser-1.9] set result [catch {$parser cget -handlerset dontexist -baseurl} errMsg] lappend result $errMsg } {1 {invalid handlerset name: dontexist}} test parser-1.10 {parser cget syntax} { catch {rename parser-1.10 {}} set parser [expat parser-1.10] set result [$parser cget -handlerset default -baseurl] } {} test parser-1.11 {parser cget syntax} { catch {rename parser-1.11 {}} set parser [expat parser-1.11 -baseurl http://foo.org/] set result [$parser cget -handlerset default -baseurl] } {http://foo.org/} test parser-1.12 {parser cget} { catch {rename parser-1.12 {}} set parser [expat parser-1.12] set result [$parser cget -baseurl] } {} proc esh_1_13_1 {args} { incr ::esh_1_13_1 } proc esh_1_13_2 {args} { incr ::esh_1_13_2 } test parser-1.13 {parser configure} { set ::esh_1_13_1 0 set ::esh_1_13_2 0 catch {rename parser-1.13 {}} set p [expat parser-1.13 -elementstartcommand esh_1_13_1] $p configure -elementstartcommand esh_1_13_2 $p parse {} list $::esh_1_13_1 $::esh_1_13_2 } {0 3} test parser-1.14 {parser get} { catch {rename parser-1.14 {}} set parser [expat parser-1.14] set result [catch {$parser get}] $parser free set result } {1} test parser-1.15 {parser get} { catch {rename parser-1.15 {}} set parser [expat parser-1.15] set result [catch {$parser get foo bar}] $parser free set result } {1} test parser-1.16 {parser get} { catch {rename parser-1.16 {}} set parser [expat parser-1.16] set result [$parser get -currentbytecount] $parser free set result } {0} test parser-1.17 {parser delete} { expat parser-1.17 parser-1.17 delete } {} proc cdh-1.18 {data} { if {[string trim $data] ne ""} { append ::result "cdh:$data" } } proc dh-1.18 {data} { if {[string trim $data] ne ""} { append ::result "dh:$data" } } test parser-1.18 {parser option -noexpand} { catch {rename parser-1.18 {}} set parser [expat parser-1.18] $parser configure \ -noexpand 1 \ -defaultcommand dh-1.18 \ -characterdatacommand cdh-1.18 set result "" $parser parse { ]> foo&xxx;bar} set result } {cdh:foodh:&xxx;cdh:bar} test parser-1.19 {parser option -noexpand} { catch {rename parser-1.19 {}} set parser [expat parser-1.19] $parser configure \ -noexpand 0 \ -defaultcommand dh-1.18 \ -characterdatacommand cdh-1.18 set result "" $parser parse { ]> foo&xxx;bar} set result } {cdh:foothis was the xxx entitybar} test parser-1.20 {parser option -noexpand} { catch {rename parser-1.20 {}} set parser [expat parser-1.20] $parser configure \ -noexpand 1 \ -characterdatacommand cdh-1.18 set result "" $parser parse { ]> foo&xxx;bar} set result } {cdh:foocdh:bar} test parser-1.21 {parser option -noexpand} { catch {rename parser-1.21 {}} set parser [expat parser-1.21] $parser configure \ -noexpand 1 \ -defaultcommand dh-1.18 set result "" $parser parse { ]> foo&xxx;bar} set result } {dh:&xxx;} test parser-1.22 {parser option -noexpand} { catch {rename parser-1.22 {}} set parser [expat parser-1.18] $parser configure \ -noexpand 1 \ -defaultcommand dh-1.18 set result "" $parser parse { ]> foo&xxx;bar} set result } {dh:&xxx;} test parser-1.23 {Unknown option flag} { catch {rename xml::parser-1.23 {}} catch { set parser [xml::parser parser-1.23 \ -elementstartcommand EStart \ -boo] } } 1 test parser-1.24 {Missing option argument} { catch {rename xml::parser-1.24 {}} catch { set parser [xml::parser parser-1.24 \ -elementstartcommand] } } 1 test parser-1.25 {billion laughs attact proctection options} { catch {xml::parser-1.25 delete} xml::parser xml::parser-1.25 set result "" foreach {option value} { -billionLaughsAttackProtectionMaximumAmplification foo -billionLaughsAttackProtectionMaximumAmplification 0 -billionLaughsAttackProtectionMaximumAmplification -2.0 -billionLaughsAttackProtectionMaximumAmplification 23 -billionLaughsAttackProtectionActivationThreshold bar -billionLaughsAttackProtectionActivationThreshold 0 -billionLaughsAttackProtectionActivationThreshold -7 -billionLaughsAttackProtectionActivationThreshold 2000000000 } { lappend result [catch { xml::parser-1.25 configure $option $value }] } xml::parser-1.25 delete set result } {1 1 1 0 1 1 1 0} proc estart-1.26 {name attrs} { lappend ::result "estart-1.26 $name" } proc eend-1.26 {name} { lappend ::result "eend-1.26 $name" } proc cdata-1.26 {cdata} { lappend ::result "cdata-1.26 $cdata" } trace add execution estart-1.26 enter cmdtracer trace add execution eend-1.26 enter cmdtracer trace add execution cdata-1.26 enter cmdtracer proc cmdtracer {args} { lappend ::result "cmdtracer $args" } test parser-1.26 {-fastcall} { catch {xml::parser-1.26} set result "" xml::parser xml::parser-1.26 -final 0 -fastcall 1 xml::parser-1.26 configure -elementstartcommand estart-1.26 \ -elementendcommand eend-1.26 \ -characterdatacommand cdata-1.26 xml::parser-1.26 parse foo xml::parser-1.26 configure -fastcall 0 -final 1 \ -elementstartcommand estart-1.26 \ -elementendcommand eend-1.26 \ -characterdatacommand cdata-1.26 xml::parser-1.26 parse foo xml::parser-1.26 delete set result } {{estart-1.26 doc} {estart-1.26 a} {cdata-1.26 foo} {eend-1.26 a} {cmdtracer {estart-1.26 a {}} enter} {estart-1.26 a} {cmdtracer {cdata-1.26 foo} enter} {cdata-1.26 foo} {cmdtracer {eend-1.26 a} enter} {eend-1.26 a} {cmdtracer {eend-1.26 doc} enter} {eend-1.26 doc}} test parser-1.26.1 {-fastcall} { catch {xml::parser-1.26} set result "" xml::parser xml::parser-1.26 -final 0 -fastcall 1 xml::parser-1.26 configure -elementstartcommand estart-1.26 \ -elementendcommand eend-1.26 \ -characterdatacommand cdata-1.26 xml::parser-1.26 parse foo xml::parser-1.26 configure -fastcall 0 \ -elementstartcommand estart-1.26 \ -elementendcommand eend-1.26 \ -characterdatacommand cdata-1.26 xml::parser-1.26 parse foo xml::parser-1.26 configure -final 1 xml::parser-1.26 parse "" xml::parser-1.26 delete set result } {{estart-1.26 doc} {estart-1.26 a} {cdata-1.26 foo} {eend-1.26 a} {cmdtracer {estart-1.26 a {}} enter} {estart-1.26 a} {cmdtracer {cdata-1.26 foo} enter} {cdata-1.26 foo} {cmdtracer {eend-1.26 a} enter} {eend-1.26 a} {cmdtracer {eend-1.26 doc} enter} {eend-1.26 doc}} # Test break return code from callback test parser-2.1 {break in callback} { catch {unset ::started} catch {rename parser-2.1 {}} set p [::xml::parser parser-2.1 -elementstartcommand Start] $p parse { Should see this data Should not see this data Should not see this data } set ::started(Element) } 2 test parser-2.2 {break in callback} { catch {unset ::started} catch {rename parser-2.2 {}} set p [::xml::parser parser-2.2 -elementstartcommand Start] $p parse { Should see this data Should see this data Should not see this data } set ::started(Element) } 3 test parser-2.3 {break in callback} { catch {unset ::started} catch {rename parser-2.3 {}} set p [::xml::parser parser-2.3 -elementstartcommand Start] $p parse { Should see this data Should see this data Should not see this data } set ::started(Element) } 3 test parser-3.1 {continue in callback} { catch {unset ::started} catch {rename parser-3.1 {}} set p [::xml::parser parser-3.1 -elementstartcommand Start] $p parse { Should see this data Should not see this data Should see this data } set ::started(Element) } 3 test parser-3.2 {continue in callback} { catch {unset ::started} catch {rename parser-3.2 {}} set p [::xml::parser parser-3.2 -elementstartcommand Start] $p parse { Should see this data Should see this data Should not see this data Should see this data Should see this data } set ::started(Element) } 5 test parser-3.3 {continue in callback} { catch {unset ::started} catch {rename parser-3.3 {}} set p [::xml::parser parser-3.3 -elementstartcommand Start] $p parse { Should see this data Should see this data Should not see this data break will have no effect Should see this data Should see this data } set ::started(Element) } 5 proc esh-3.4 {name attList} { incr ::eshcounter return -code continue } proc eeh-3.4 {name} { incr ::eehcounter } proc cdh-3.4 {data} { incr ::cdhcounter } test parser-3.4 {continue} { set ::eshcounter 0 set ::eehcounter 0 set ::cdhcounter 0 set p [expat -elementstartcommand esh-3.4 -elementendcommand eeh-3.4 \ -characterdatacommand chd-3.4] $p parse {foofoofoo} $p free list $::eshcounter $::eehcounter $::cdhcounter } {1 1 0} proc esh-3.5 {name attList} { incr ::eshcounter2 } proc eeh-3.5 {name} { incr ::eehcounter2 } proc cdh-3.5 {data} { incr ::cdhcounter2 } test parser-3.5 {continue with more than one handlerset} { set ::eshcounter 0 set ::eehcounter 0 set ::cdhcounter 0 set ::eshcounter2 0 set ::eehcounter2 0 set ::cdhcounter2 0 set p [expat -elementstartcommand esh-3.4 -elementendcommand eeh-3.4 \ -characterdatacommand chd-3.4 -handlerset second \ -elementstartcommand esh-3.5 -elementendcommand eeh-3.5 \ -characterdatacommand cdh-3.5] $p parse {foofoofoo} $p free list $::eshcounter $::eehcounter $::cdhcounter \ $::eshcounter2 $::eehcounter2 $::cdhcounter2 } {1 1 0 5 5 3} test parser-4.1 {error in callback} { catch {unset ::started} catch {rename parser-4.1 {}} set p [::xml::parser parser-4.1 -elementstartcommand Start] set errcode [catch {$p parse { Should see this data Should not see this data }} result] list $errcode $::started(Element) } {1 2} test parser-4.2 {error in callback} { catch {unset ::started} catch {rename parser-4.2 {}} set p [::xml::parser parser-4.2 -elementstartcommand Start] set errcode [catch {$p parse { Should see this data Should not see this data }} result] list $::errcode $::started(Element) } {13 2} test parser-5.1 {parse channel input} { catch {unset ::count} catch {rename parser-5.1 {}} set parser [::xml::parser parser-5.1 -elementstartcommand Count] set fd [open [file join [pwd] [file dir [info script]] data/books.xml]] $parser parsechannel $fd close $fd list $::count } {42} proc elementstart {args} { global parser if {![info exists ::count]} { set ::count 1 } else { incr ::count } set fd [open [file join [pwd] [file dir [info script]] data/books.xml]] catch {$parser parsechannel $fd} close $fd } test parser-5.2 {parse channel input with catched try to recursive parsing} { catch {unset ::count} catch {rename parser-5.2 {}} set parser [::xml::parser parser-5.2 -elementstartcommand elementstart] set fd [open [file join [pwd] [file dir [info script]] data/books.xml]] $parser parsechannel $fd close $fd list $::count } {42} test parser-5.3 {parse channel - xml wrong} -setup { set xmlFile [makeFile {} parser.xml] } -body { set fd [open $xmlFile] catch {rename parser-5.3 {}} set parser [::xml::parser parser-5.3 -elementstartcommand elementstart] set result [catch {$parser parsechannel $fd}] close $fd set result } -cleanup { removeFile parser.xml } -result 1 proc elementstart-5.4 {args} { error "Error raised by elementstart-5.4" } test parser-5.4 {parse channel - error raised in handler} { catch {parser-5.4 free} ::xml::parser parser-5.4 -elementstartcommand elementstart-5.4 set file [file join [pwd] [file dir [info script]] data/books.xml] catch {parser-5.4 parsefile $file} errMsg parser-5.4 free set errMsg } "Error raised by elementstart-5.4" test parser-6.1 {reuse parser} { catch {rename parser-6.1 {}} set parser [expat parser-6.1 -baseurl file:///foo/bar] set result [$parser cget -baseurl] $parser parse lappend result [$parser cget -baseurl] $parser configure -baseurl file:///bar/foo lappend result [$parser cget -baseurl] $parser parse lappend result [$parser cget -baseurl] set result } {file:///foo/bar {} file:///bar/foo {}} proc elementstart {args} { global parser $parser reset } test parser-7.1 {parser reset called from within callback proc} { set parser [expat -elementstartcommand elementstart] set result [catch {$parser parse foo} errMsg] lappend result $errMsg $parser free set result } {1 {parser reset not allowed from within callback}} test parser-7.2 {parser reset} { set parser [expat -final 0] $parser parse "" $parser free set result } {1 {} 0 0} proc elementstart {args} { global parser $parser free } test parser-8.1 {parser free called from within callback proc} { set parser [expat -elementstartcommand elementstart] set result [catch {$parser parse foo} errMsg] lappend result $errMsg $parser free set result } {1 {parser delete not allowed from within callback}} proc elementstart {args} { global parser $parser parse {foo bar} } test parser-9.1 {try to use the parser from within one of its callbacks} { set parser [expat -elementstartcommand elementstart] set result [catch {$parser parse foo} errMsg] lappend result $errMsg $parser free set result } {1 {Parser already in use.}} proc calledFromElementstart {args} { global parser $parser parse {foo bar} } proc elementstart {args} { calledFromElementstart } test parser-9.2 {try to use the parser from within one of its callbacks} { set parser [expat -elementstartcommand elementstart] set result [catch {$parser parse foo} errMsg] lappend result $errMsg $parser free set result } {1 {Parser already in use.}} test parser-10.1 {return -code return in callback} { catch {unset ::started} catch {rename parser-10.1 {}} set p [::xml::parser parser-10.1 -elementstartcommand Start] set errcode [catch {$p parse { Should see this data Should not see this data }} result] list $errcode $::started(Element) } {0 2} test parser-10.2 {return -code return in callback} { catch {unset ::started} catch {rename parser-10.2 {}} set p [::xml::parser parser-10.2 -elementstartcommand Start] set errcode [catch {$p parse { Should see this data Should not see this data }} errMsg] set result [list $errcode $::started(Element)] $p reset catch {unset ::started} set errcode [catch {$p parse { Should see this data Should see this data }} errMsg] lappend result $errcode $::started(Element) } {0 2 0 3} test parser-11.1 {parse parsefile} { catch {unset ::count} catch {rename parser-11.1 {}} set parser [::xml::parser parser-11.1 -elementstartcommand Count] set file [file join [pwd] [file dir [info script]] data/books.xml] $parser parsefile $file set ::count } {42} proc elementstart-11.2 {args} { error "Error raised by elementstart-11.2" } test parser-11.2 {parse parsefile - error raised in handler} { catch {parser-11.2 free} ::xml::parser parser-11.2 -elementstartcommand elementstart-11.2 set file [file join [pwd] [file dir [info script]] data/books.xml] catch {parser-11.2 parsefile $file} errMsg parser-11.2 free set errMsg } "Error raised by elementstart-11.2" proc elementstart-12.1 {parser args} { global result append result [$parser currentmarkup] } proc elementend-12.1 {parser args} { global result append result [$parser currentmarkup] } test parser-12.1 {currentmarkup method} { catch {unset result} set result "" set p [expat parser-12.1] $p configure \ -elementstartcommand [list elementstart-12.1 $p] \ -elementendcommand [list elementend-12.1 $p] $p parse {textmore text} $p free set result } {} proc characterdata-12.2 {parser data} { global result append result [$parser currentmarkup] } test parser-12.2 {currentmarkup method} { catch {unset result} set result "" set p [expat parser-12.2] $p configure \ -characterdatacommand [list characterdata-12.2 $p] $p parse {textmore text} $p free set result } {} test parser-12.3 {currentmarkup method} { set p [expat parser-12.3] set result [$p currentmarkup] $p free set result } {} proc elementstart-12.4 {parser handlerset args} { global result append result "$handlerset: [$parser currentmarkup]\n" } proc elementend-12.4 {parser handlerset args} { global result append result "$handlerset: [$parser currentmarkup]\n" } test parser-12.4 {currentmarkup method - multiple handler set} { catch {unset result} set result "" set p [expat parser-12.4] $p configure \ -elementstartcommand [list elementstart-12.4 $p default] \ -elementendcommand [list elementend-12.4 $p default] \ -handlerset "additional" \ -elementstartcommand [list elementstart-12.4 $p "additional"] \ -elementendcommand [list elementend-12.4 $p "additional"] $p parse {textmore text} $p free set result } {default: additional: default: additional: default: additional: default: additional: default: additional: default: additional: } proc elementstart-12.5 {parser args} { global result append result "[$parser currentmarkup]" } test parser-12.5 {currentmarkup method - empty element shortcut -elementstartcommand} { catch {unset result} set result "" set p [expat parser-12.5] $p configure \ -elementstartcommand [list elementstart-12.5 $p] $p parse {} $p free set result } {} proc elementend-12.6 {parser args} { global result if {[$parser currentmarkup] eq ""} { append result "" } append result "[$parser currentmarkup]" } test parser-12.6 {currentmarkup method - empty element shortcut -elementendcommand} { catch {unset result} set result "" set p [expat parser-12.6] $p configure \ -elementendcommand [list elementend-12.6 $p] $p parse {} $p free set result } {} foreach parser [info commands xmlparser*] { $parser free } foreach parser [info commands parser-*] { $parser free } proc elementdeclcommand-12.7 {parser args} { global result append result "elementdeclcommand: [$parser currentmarkup]" } proc entitydeclcommand-12.7 {parser args} { global result append result "entitydeclcommand: [$parser currentmarkup]" } test parser-12.7 {currentmarkup method - not for doctype markup handler} { catch {unset result} set result "" set p [expat parser-12.7] $p configure \ -elementdeclcommand [list elementdeclcommand-12.7 $p] \ -entitydeclcommand [list entitydeclcommand-12.7 $p] $p parse { ' > %xx; ]> This sample shows a &tricky; method.} $p free set result } {elementdeclcommand: entitydeclcommand: entitydeclcommand: } proc pi-12.8 {parser args} { global result append result "pi: [$parser currentmarkup]" } test parser-12.8 {currentmarkup method - processing instruction} { catch {unset result} set result "" set p [expat parser-12.8] $p configure \ -processinginstructioncommand [list pi-12.8 $p] $p parse {} $p free set result } {pi: } proc comment-12.9 {parser args} { global result append result "comment: [$parser currentmarkup]" } test parser-12.9 {currentmarkup method - comment} { catch {unset result} set result "" set p [expat parser-12.9] $p configure \ -commentcommand [list comment-12.9 $p] $p parse {} $p free set result } {comment: } proc gethdl-13 {p args} { global result append result "/[$p get -currentlinenumber].[$p get -currentcolumnnumber]/" } test parser-13.1 {get -current*} { catch {unset result} set result "" set p [expat parser-13.1] $p configure \ -elementstartcommand [list gethdl-13 $p] $p parse { } $p free set result } /1.0//2.8//2.12/ test parser-13.2 {get -current*} { catch {unset result} set result "" set p [expat parser-13.2 -keepTextStart 1] $p configure \ -characterdatacommand [list gethdl-13 $p] $p parse { Hello} $p free set result } /1.6/ # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/htmlreader.test0000644000175000017500000041440114703531020016134 0ustar rolfrolf# Features covered: HTML parser # # This file contains a collection of tests for the HTML parser. # Tested functionalities: # html-1.*: Character encoding # html-2.*: Parsing tests # html-3.*: Bad data # html-4.*: DOM building # # Copyright (c) 2002-2007 Rolf Ade. # # RCS: @(#) $Id$ source [file join [file dir [info script]] loadtdom.tcl] test html-1.1 {HTML character entities} { set doc [dom parse -html { ¡Äü}] set root [$doc documentElement] set body [$root firstChild] set result [$body text] $doc delete set result } "\u00A0\u00A1\u00c4\u00fc" test html-1.2 {character entities} { set doc [dom parse -html {ÖÄÄ}] set root [$doc documentElement] set body [$root firstChild] set result [$body text] $doc delete set result } "\u00d6\u00c4\u00c4" test html-1.3 {character entities} { set doc [dom parse -html {€∋}] set root [$doc documentElement] set result [$root text] $doc delete set result } "\u20ac\u220b" test html-1.4 {Invalid numeric character entity} { set doc [dom parse -html {'xyz}] set root [$doc documentElement] set result [$root text] $doc delete set result } "'xyz" test html-1.5 {Numeric character entity} { set doc [dom parse -html {�}] set root [$doc documentElement] set result [$root text] $doc delete set result } "�" test html-1.6 {Numeric character entity} { set doc [dom parse -html {�}] set root [$doc documentElement] set result [$root text] $doc delete set result } "�" test html-1.7 {character entities} { set doc [dom parse -html {¼}] set root [$doc documentElement] set result [$root text] $doc delete set result } "\u00bc" proc toutf8 c { set s [encoding convertto utf-8 $c] binary scan $s H* x regsub -all -expanded {..} $x {\x&} } test html-1.8 {character entities} {Tcl9} { set result "" foreach {entity byteseq} { "AElig" "\\xC3\\x86" "AMP" "\\x26" "Aacute" "\\xC3\\x81" "Abreve" "\\xC4\\x82" "Acirc" "\\xC3\\x82" "Acy" "\\xD0\\x90" "Afr" "\\xF0\\x9D\\x94\\x84" "Agrave" "\\xC3\\x80" "Alpha" "\\xCE\\x91" "Amacr" "\\xC4\\x80" "And" "\\xE2\\xA9\\x93" "Aogon" "\\xC4\\x84" "Aopf" "\\xF0\\x9D\\x94\\xB8" "ApplyFunction" "\\xE2\\x81\\xA1" "Aring" "\\xC3\\x85" "Ascr" "\\xF0\\x9D\\x92\\x9C" "Assign" "\\xE2\\x89\\x94" "Atilde" "\\xC3\\x83" "Auml" "\\xC3\\x84" "Backslash" "\\xE2\\x88\\x96" "Barv" "\\xE2\\xAB\\xA7" "Barwed" "\\xE2\\x8C\\x86" "Bcy" "\\xD0\\x91" "Because" "\\xE2\\x88\\xB5" "Bernoullis" "\\xE2\\x84\\xAC" "Beta" "\\xCE\\x92" "Bfr" "\\xF0\\x9D\\x94\\x85" "Bopf" "\\xF0\\x9D\\x94\\xB9" "Breve" "\\xCB\\x98" "Bscr" "\\xE2\\x84\\xAC" "Bumpeq" "\\xE2\\x89\\x8E" "CHcy" "\\xD0\\xA7" "COPY" "\\xC2\\xA9" "Cacute" "\\xC4\\x86" "Cap" "\\xE2\\x8B\\x92" "CapitalDifferentialD" "\\xE2\\x85\\x85" "Cayleys" "\\xE2\\x84\\xAD" "Ccaron" "\\xC4\\x8C" "Ccedil" "\\xC3\\x87" "Ccirc" "\\xC4\\x88" "Cconint" "\\xE2\\x88\\xB0" "Cdot" "\\xC4\\x8A" "Cedilla" "\\xC2\\xB8" "CenterDot" "\\xC2\\xB7" "Cfr" "\\xE2\\x84\\xAD" "Chi" "\\xCE\\xA7" "CircleDot" "\\xE2\\x8A\\x99" "CircleMinus" "\\xE2\\x8A\\x96" "CirclePlus" "\\xE2\\x8A\\x95" "CircleTimes" "\\xE2\\x8A\\x97" "ClockwiseContourIntegral" "\\xE2\\x88\\xB2" "CloseCurlyDoubleQuote" "\\xE2\\x80\\x9D" "CloseCurlyQuote" "\\xE2\\x80\\x99" "Colon" "\\xE2\\x88\\xB7" "Colone" "\\xE2\\xA9\\xB4" "Congruent" "\\xE2\\x89\\xA1" "Conint" "\\xE2\\x88\\xAF" "ContourIntegral" "\\xE2\\x88\\xAE" "Copf" "\\xE2\\x84\\x82" "Coproduct" "\\xE2\\x88\\x90" "CounterClockwiseContourIntegral" "\\xE2\\x88\\xB3" "Cross" "\\xE2\\xA8\\xAF" "Cscr" "\\xF0\\x9D\\x92\\x9E" "Cup" "\\xE2\\x8B\\x93" "CupCap" "\\xE2\\x89\\x8D" "DD" "\\xE2\\x85\\x85" "DDotrahd" "\\xE2\\xA4\\x91" "DJcy" "\\xD0\\x82" "DScy" "\\xD0\\x85" "DZcy" "\\xD0\\x8F" "Dagger" "\\xE2\\x80\\xA1" "Darr" "\\xE2\\x86\\xA1" "Dashv" "\\xE2\\xAB\\xA4" "Dcaron" "\\xC4\\x8E" "Dcy" "\\xD0\\x94" "Del" "\\xE2\\x88\\x87" "Delta" "\\xCE\\x94" "Dfr" "\\xF0\\x9D\\x94\\x87" "DiacriticalAcute" "\\xC2\\xB4" "DiacriticalDot" "\\xCB\\x99" "DiacriticalDoubleAcute" "\\xCB\\x9D" "DiacriticalGrave" "\\x60" "DiacriticalTilde" "\\xCB\\x9C" "Diamond" "\\xE2\\x8B\\x84" "DifferentialD" "\\xE2\\x85\\x86" "Dopf" "\\xF0\\x9D\\x94\\xBB" "Dot" "\\xC2\\xA8" "DotDot" "\\xE2\\x83\\x9C" "DotEqual" "\\xE2\\x89\\x90" "DoubleContourIntegral" "\\xE2\\x88\\xAF" "DoubleDot" "\\xC2\\xA8" "DoubleDownArrow" "\\xE2\\x87\\x93" "DoubleLeftArrow" "\\xE2\\x87\\x90" "DoubleLeftRightArrow" "\\xE2\\x87\\x94" "DoubleLeftTee" "\\xE2\\xAB\\xA4" "DoubleLongLeftArrow" "\\xE2\\x9F\\xB8" "DoubleLongLeftRightArrow" "\\xE2\\x9F\\xBA" "DoubleLongRightArrow" "\\xE2\\x9F\\xB9" "DoubleRightArrow" "\\xE2\\x87\\x92" "DoubleRightTee" "\\xE2\\x8A\\xA8" "DoubleUpArrow" "\\xE2\\x87\\x91" "DoubleUpDownArrow" "\\xE2\\x87\\x95" "DoubleVerticalBar" "\\xE2\\x88\\xA5" "DownArrow" "\\xE2\\x86\\x93" "DownArrowBar" "\\xE2\\xA4\\x93" "DownArrowUpArrow" "\\xE2\\x87\\xB5" "DownBreve" "\\xCC\\x91" "DownLeftRightVector" "\\xE2\\xA5\\x90" "DownLeftTeeVector" "\\xE2\\xA5\\x9E" "DownLeftVector" "\\xE2\\x86\\xBD" "DownLeftVectorBar" "\\xE2\\xA5\\x96" "DownRightTeeVector" "\\xE2\\xA5\\x9F" "DownRightVector" "\\xE2\\x87\\x81" "DownRightVectorBar" "\\xE2\\xA5\\x97" "DownTee" "\\xE2\\x8A\\xA4" "DownTeeArrow" "\\xE2\\x86\\xA7" "Downarrow" "\\xE2\\x87\\x93" "Dscr" "\\xF0\\x9D\\x92\\x9F" "Dstrok" "\\xC4\\x90" "ENG" "\\xC5\\x8A" "ETH" "\\xC3\\x90" "Eacute" "\\xC3\\x89" "Ecaron" "\\xC4\\x9A" "Ecirc" "\\xC3\\x8A" "Ecy" "\\xD0\\xAD" "Edot" "\\xC4\\x96" "Efr" "\\xF0\\x9D\\x94\\x88" "Egrave" "\\xC3\\x88" "Element" "\\xE2\\x88\\x88" "Emacr" "\\xC4\\x92" "EmptySmallSquare" "\\xE2\\x97\\xBB" "EmptyVerySmallSquare" "\\xE2\\x96\\xAB" "Eogon" "\\xC4\\x98" "Eopf" "\\xF0\\x9D\\x94\\xBC" "Epsilon" "\\xCE\\x95" "Equal" "\\xE2\\xA9\\xB5" "EqualTilde" "\\xE2\\x89\\x82" "Equilibrium" "\\xE2\\x87\\x8C" "Escr" "\\xE2\\x84\\xB0" "Esim" "\\xE2\\xA9\\xB3" "Eta" "\\xCE\\x97" "Euml" "\\xC3\\x8B" "Exists" "\\xE2\\x88\\x83" "ExponentialE" "\\xE2\\x85\\x87" "Fcy" "\\xD0\\xA4" "Ffr" "\\xF0\\x9D\\x94\\x89" "FilledSmallSquare" "\\xE2\\x97\\xBC" "FilledVerySmallSquare" "\\xE2\\x96\\xAA" "Fopf" "\\xF0\\x9D\\x94\\xBD" "ForAll" "\\xE2\\x88\\x80" "Fouriertrf" "\\xE2\\x84\\xB1" "Fscr" "\\xE2\\x84\\xB1" "GJcy" "\\xD0\\x83" "GT" "\\x3E" "Gamma" "\\xCE\\x93" "Gammad" "\\xCF\\x9C" "Gbreve" "\\xC4\\x9E" "Gcedil" "\\xC4\\xA2" "Gcirc" "\\xC4\\x9C" "Gcy" "\\xD0\\x93" "Gdot" "\\xC4\\xA0" "Gfr" "\\xF0\\x9D\\x94\\x8A" "Gg" "\\xE2\\x8B\\x99" "Gopf" "\\xF0\\x9D\\x94\\xBE" "GreaterEqual" "\\xE2\\x89\\xA5" "GreaterEqualLess" "\\xE2\\x8B\\x9B" "GreaterFullEqual" "\\xE2\\x89\\xA7" "GreaterGreater" "\\xE2\\xAA\\xA2" "GreaterLess" "\\xE2\\x89\\xB7" "GreaterSlantEqual" "\\xE2\\xA9\\xBE" "GreaterTilde" "\\xE2\\x89\\xB3" "Gscr" "\\xF0\\x9D\\x92\\xA2" "Gt" "\\xE2\\x89\\xAB" "HARDcy" "\\xD0\\xAA" "Hacek" "\\xCB\\x87" "Hat" "\\x5E" "Hcirc" "\\xC4\\xA4" "Hfr" "\\xE2\\x84\\x8C" "HilbertSpace" "\\xE2\\x84\\x8B" "Hopf" "\\xE2\\x84\\x8D" "HorizontalLine" "\\xE2\\x94\\x80" "Hscr" "\\xE2\\x84\\x8B" "Hstrok" "\\xC4\\xA6" "HumpDownHump" "\\xE2\\x89\\x8E" "HumpEqual" "\\xE2\\x89\\x8F" "IEcy" "\\xD0\\x95" "IJlig" "\\xC4\\xB2" "IOcy" "\\xD0\\x81" "Iacute" "\\xC3\\x8D" "Icirc" "\\xC3\\x8E" "Icy" "\\xD0\\x98" "Idot" "\\xC4\\xB0" "Ifr" "\\xE2\\x84\\x91" "Igrave" "\\xC3\\x8C" "Im" "\\xE2\\x84\\x91" "Imacr" "\\xC4\\xAA" "ImaginaryI" "\\xE2\\x85\\x88" "Implies" "\\xE2\\x87\\x92" "Int" "\\xE2\\x88\\xAC" "Integral" "\\xE2\\x88\\xAB" "Intersection" "\\xE2\\x8B\\x82" "InvisibleComma" "\\xE2\\x81\\xA3" "InvisibleTimes" "\\xE2\\x81\\xA2" "Iogon" "\\xC4\\xAE" "Iopf" "\\xF0\\x9D\\x95\\x80" "Iota" "\\xCE\\x99" "Iscr" "\\xE2\\x84\\x90" "Itilde" "\\xC4\\xA8" "Iukcy" "\\xD0\\x86" "Iuml" "\\xC3\\x8F" "Jcirc" "\\xC4\\xB4" "Jcy" "\\xD0\\x99" "Jfr" "\\xF0\\x9D\\x94\\x8D" "Jopf" "\\xF0\\x9D\\x95\\x81" "Jscr" "\\xF0\\x9D\\x92\\xA5" "Jsercy" "\\xD0\\x88" "Jukcy" "\\xD0\\x84" "KHcy" "\\xD0\\xA5" "KJcy" "\\xD0\\x8C" "Kappa" "\\xCE\\x9A" "Kcedil" "\\xC4\\xB6" "Kcy" "\\xD0\\x9A" "Kfr" "\\xF0\\x9D\\x94\\x8E" "Kopf" "\\xF0\\x9D\\x95\\x82" "Kscr" "\\xF0\\x9D\\x92\\xA6" "LJcy" "\\xD0\\x89" "LT" "\\x3C" "Lacute" "\\xC4\\xB9" "Lambda" "\\xCE\\x9B" "Lang" "\\xE2\\x9F\\xAA" "Laplacetrf" "\\xE2\\x84\\x92" "Larr" "\\xE2\\x86\\x9E" "Lcaron" "\\xC4\\xBD" "Lcedil" "\\xC4\\xBB" "Lcy" "\\xD0\\x9B" "LeftAngleBracket" "\\xE2\\x9F\\xA8" "LeftArrow" "\\xE2\\x86\\x90" "LeftArrowBar" "\\xE2\\x87\\xA4" "LeftArrowRightArrow" "\\xE2\\x87\\x86" "LeftCeiling" "\\xE2\\x8C\\x88" "LeftDoubleBracket" "\\xE2\\x9F\\xA6" "LeftDownTeeVector" "\\xE2\\xA5\\xA1" "LeftDownVector" "\\xE2\\x87\\x83" "LeftDownVectorBar" "\\xE2\\xA5\\x99" "LeftFloor" "\\xE2\\x8C\\x8A" "LeftRightArrow" "\\xE2\\x86\\x94" "LeftRightVector" "\\xE2\\xA5\\x8E" "LeftTee" "\\xE2\\x8A\\xA3" "LeftTeeArrow" "\\xE2\\x86\\xA4" "LeftTeeVector" "\\xE2\\xA5\\x9A" "LeftTriangle" "\\xE2\\x8A\\xB2" "LeftTriangleBar" "\\xE2\\xA7\\x8F" "LeftTriangleEqual" "\\xE2\\x8A\\xB4" "LeftUpDownVector" "\\xE2\\xA5\\x91" "LeftUpTeeVector" "\\xE2\\xA5\\xA0" "LeftUpVector" "\\xE2\\x86\\xBF" "LeftUpVectorBar" "\\xE2\\xA5\\x98" "LeftVector" "\\xE2\\x86\\xBC" "LeftVectorBar" "\\xE2\\xA5\\x92" "Leftarrow" "\\xE2\\x87\\x90" "Leftrightarrow" "\\xE2\\x87\\x94" "LessEqualGreater" "\\xE2\\x8B\\x9A" "LessFullEqual" "\\xE2\\x89\\xA6" "LessGreater" "\\xE2\\x89\\xB6" "LessLess" "\\xE2\\xAA\\xA1" "LessSlantEqual" "\\xE2\\xA9\\xBD" "LessTilde" "\\xE2\\x89\\xB2" "Lfr" "\\xF0\\x9D\\x94\\x8F" "Ll" "\\xE2\\x8B\\x98" "Lleftarrow" "\\xE2\\x87\\x9A" "Lmidot" "\\xC4\\xBF" "LongLeftArrow" "\\xE2\\x9F\\xB5" "LongLeftRightArrow" "\\xE2\\x9F\\xB7" "LongRightArrow" "\\xE2\\x9F\\xB6" "Longleftarrow" "\\xE2\\x9F\\xB8" "Longleftrightarrow" "\\xE2\\x9F\\xBA" "Longrightarrow" "\\xE2\\x9F\\xB9" "Lopf" "\\xF0\\x9D\\x95\\x83" "LowerLeftArrow" "\\xE2\\x86\\x99" "LowerRightArrow" "\\xE2\\x86\\x98" "Lscr" "\\xE2\\x84\\x92" "Lsh" "\\xE2\\x86\\xB0" "Lstrok" "\\xC5\\x81" "Lt" "\\xE2\\x89\\xAA" "Map" "\\xE2\\xA4\\x85" "Mcy" "\\xD0\\x9C" "MediumSpace" "\\xE2\\x81\\x9F" "Mellintrf" "\\xE2\\x84\\xB3" "Mfr" "\\xF0\\x9D\\x94\\x90" "MinusPlus" "\\xE2\\x88\\x93" "Mopf" "\\xF0\\x9D\\x95\\x84" "Mscr" "\\xE2\\x84\\xB3" "Mu" "\\xCE\\x9C" "NJcy" "\\xD0\\x8A" "Nacute" "\\xC5\\x83" "Ncaron" "\\xC5\\x87" "Ncedil" "\\xC5\\x85" "Ncy" "\\xD0\\x9D" "NegativeMediumSpace" "\\xE2\\x80\\x8B" "NegativeThickSpace" "\\xE2\\x80\\x8B" "NegativeThinSpace" "\\xE2\\x80\\x8B" "NegativeVeryThinSpace" "\\xE2\\x80\\x8B" "NestedGreaterGreater" "\\xE2\\x89\\xAB" "NestedLessLess" "\\xE2\\x89\\xAA" "NewLine" "\\x0A" "Nfr" "\\xF0\\x9D\\x94\\x91" "NoBreak" "\\xE2\\x81\\xA0" "NonBreakingSpace" "\\xC2\\xA0" "Nopf" "\\xE2\\x84\\x95" "Not" "\\xE2\\xAB\\xAC" "NotCongruent" "\\xE2\\x89\\xA2" "NotCupCap" "\\xE2\\x89\\xAD" "NotDoubleVerticalBar" "\\xE2\\x88\\xA6" "NotElement" "\\xE2\\x88\\x89" "NotEqual" "\\xE2\\x89\\xA0" "NotEqualTilde" "\\xE2\\x89\\x82\\xCC\\xB8" "NotExists" "\\xE2\\x88\\x84" "NotGreater" "\\xE2\\x89\\xAF" "NotGreaterEqual" "\\xE2\\x89\\xB1" "NotGreaterFullEqual" "\\xE2\\x89\\xA7\\xCC\\xB8" "NotGreaterGreater" "\\xE2\\x89\\xAB\\xCC\\xB8" "NotGreaterLess" "\\xE2\\x89\\xB9" "NotGreaterSlantEqual" "\\xE2\\xA9\\xBE\\xCC\\xB8" "NotGreaterTilde" "\\xE2\\x89\\xB5" "NotHumpDownHump" "\\xE2\\x89\\x8E\\xCC\\xB8" "NotHumpEqual" "\\xE2\\x89\\x8F\\xCC\\xB8" "NotLeftTriangle" "\\xE2\\x8B\\xAA" "NotLeftTriangleBar" "\\xE2\\xA7\\x8F\\xCC\\xB8" "NotLeftTriangleEqual" "\\xE2\\x8B\\xAC" "NotLess" "\\xE2\\x89\\xAE" "NotLessEqual" "\\xE2\\x89\\xB0" "NotLessGreater" "\\xE2\\x89\\xB8" "NotLessLess" "\\xE2\\x89\\xAA\\xCC\\xB8" "NotLessSlantEqual" "\\xE2\\xA9\\xBD\\xCC\\xB8" "NotLessTilde" "\\xE2\\x89\\xB4" "NotNestedGreaterGreater" "\\xE2\\xAA\\xA2\\xCC\\xB8" "NotNestedLessLess" "\\xE2\\xAA\\xA1\\xCC\\xB8" "NotPrecedes" "\\xE2\\x8A\\x80" "NotPrecedesEqual" "\\xE2\\xAA\\xAF\\xCC\\xB8" "NotPrecedesSlantEqual" "\\xE2\\x8B\\xA0" "NotReverseElement" "\\xE2\\x88\\x8C" "NotRightTriangle" "\\xE2\\x8B\\xAB" "NotRightTriangleBar" "\\xE2\\xA7\\x90\\xCC\\xB8" "NotRightTriangleEqual" "\\xE2\\x8B\\xAD" "NotSquareSubset" "\\xE2\\x8A\\x8F\\xCC\\xB8" "NotSquareSubsetEqual" "\\xE2\\x8B\\xA2" "NotSquareSuperset" "\\xE2\\x8A\\x90\\xCC\\xB8" "NotSquareSupersetEqual" "\\xE2\\x8B\\xA3" "NotSubset" "\\xE2\\x8A\\x82\\xE2\\x83\\x92" "NotSubsetEqual" "\\xE2\\x8A\\x88" "NotSucceeds" "\\xE2\\x8A\\x81" "NotSucceedsEqual" "\\xE2\\xAA\\xB0\\xCC\\xB8" "NotSucceedsSlantEqual" "\\xE2\\x8B\\xA1" "NotSucceedsTilde" "\\xE2\\x89\\xBF\\xCC\\xB8" "NotSuperset" "\\xE2\\x8A\\x83\\xE2\\x83\\x92" "NotSupersetEqual" "\\xE2\\x8A\\x89" "NotTilde" "\\xE2\\x89\\x81" "NotTildeEqual" "\\xE2\\x89\\x84" "NotTildeFullEqual" "\\xE2\\x89\\x87" "NotTildeTilde" "\\xE2\\x89\\x89" "NotVerticalBar" "\\xE2\\x88\\xA4" "Nscr" "\\xF0\\x9D\\x92\\xA9" "Ntilde" "\\xC3\\x91" "Nu" "\\xCE\\x9D" "OElig" "\\xC5\\x92" "Oacute" "\\xC3\\x93" "Ocirc" "\\xC3\\x94" "Ocy" "\\xD0\\x9E" "Odblac" "\\xC5\\x90" "Ofr" "\\xF0\\x9D\\x94\\x92" "Ograve" "\\xC3\\x92" "Omacr" "\\xC5\\x8C" "Omega" "\\xCE\\xA9" "Omicron" "\\xCE\\x9F" "Oopf" "\\xF0\\x9D\\x95\\x86" "OpenCurlyDoubleQuote" "\\xE2\\x80\\x9C" "OpenCurlyQuote" "\\xE2\\x80\\x98" "Or" "\\xE2\\xA9\\x94" "Oscr" "\\xF0\\x9D\\x92\\xAA" "Oslash" "\\xC3\\x98" "Otilde" "\\xC3\\x95" "Otimes" "\\xE2\\xA8\\xB7" "Ouml" "\\xC3\\x96" "OverBar" "\\xE2\\x80\\xBE" "OverBrace" "\\xE2\\x8F\\x9E" "OverBracket" "\\xE2\\x8E\\xB4" "OverParenthesis" "\\xE2\\x8F\\x9C" "PartialD" "\\xE2\\x88\\x82" "Pcy" "\\xD0\\x9F" "Pfr" "\\xF0\\x9D\\x94\\x93" "Phi" "\\xCE\\xA6" "Pi" "\\xCE\\xA0" "PlusMinus" "\\xC2\\xB1" "Poincareplane" "\\xE2\\x84\\x8C" "Popf" "\\xE2\\x84\\x99" "Pr" "\\xE2\\xAA\\xBB" "Precedes" "\\xE2\\x89\\xBA" "PrecedesEqual" "\\xE2\\xAA\\xAF" "PrecedesSlantEqual" "\\xE2\\x89\\xBC" "PrecedesTilde" "\\xE2\\x89\\xBE" "Prime" "\\xE2\\x80\\xB3" "Product" "\\xE2\\x88\\x8F" "Proportion" "\\xE2\\x88\\xB7" "Proportional" "\\xE2\\x88\\x9D" "Pscr" "\\xF0\\x9D\\x92\\xAB" "Psi" "\\xCE\\xA8" "QUOT" "\\x22" "Qfr" "\\xF0\\x9D\\x94\\x94" "Qopf" "\\xE2\\x84\\x9A" "Qscr" "\\xF0\\x9D\\x92\\xAC" "RBarr" "\\xE2\\xA4\\x90" "REG" "\\xC2\\xAE" "Racute" "\\xC5\\x94" "Rang" "\\xE2\\x9F\\xAB" "Rarr" "\\xE2\\x86\\xA0" "Rarrtl" "\\xE2\\xA4\\x96" "Rcaron" "\\xC5\\x98" "Rcedil" "\\xC5\\x96" "Rcy" "\\xD0\\xA0" "Re" "\\xE2\\x84\\x9C" "ReverseElement" "\\xE2\\x88\\x8B" "ReverseEquilibrium" "\\xE2\\x87\\x8B" "ReverseUpEquilibrium" "\\xE2\\xA5\\xAF" "Rfr" "\\xE2\\x84\\x9C" "Rho" "\\xCE\\xA1" "RightAngleBracket" "\\xE2\\x9F\\xA9" "RightArrow" "\\xE2\\x86\\x92" "RightArrowBar" "\\xE2\\x87\\xA5" "RightArrowLeftArrow" "\\xE2\\x87\\x84" "RightCeiling" "\\xE2\\x8C\\x89" "RightDoubleBracket" "\\xE2\\x9F\\xA7" "RightDownTeeVector" "\\xE2\\xA5\\x9D" "RightDownVector" "\\xE2\\x87\\x82" "RightDownVectorBar" "\\xE2\\xA5\\x95" "RightFloor" "\\xE2\\x8C\\x8B" "RightTee" "\\xE2\\x8A\\xA2" "RightTeeArrow" "\\xE2\\x86\\xA6" "RightTeeVector" "\\xE2\\xA5\\x9B" "RightTriangle" "\\xE2\\x8A\\xB3" "RightTriangleBar" "\\xE2\\xA7\\x90" "RightTriangleEqual" "\\xE2\\x8A\\xB5" "RightUpDownVector" "\\xE2\\xA5\\x8F" "RightUpTeeVector" "\\xE2\\xA5\\x9C" "RightUpVector" "\\xE2\\x86\\xBE" "RightUpVectorBar" "\\xE2\\xA5\\x94" "RightVector" "\\xE2\\x87\\x80" "RightVectorBar" "\\xE2\\xA5\\x93" "Rightarrow" "\\xE2\\x87\\x92" "Ropf" "\\xE2\\x84\\x9D" "RoundImplies" "\\xE2\\xA5\\xB0" "Rrightarrow" "\\xE2\\x87\\x9B" "Rscr" "\\xE2\\x84\\x9B" "Rsh" "\\xE2\\x86\\xB1" "RuleDelayed" "\\xE2\\xA7\\xB4" "SHCHcy" "\\xD0\\xA9" "SHcy" "\\xD0\\xA8" "SOFTcy" "\\xD0\\xAC" "Sacute" "\\xC5\\x9A" "Sc" "\\xE2\\xAA\\xBC" "Scaron" "\\xC5\\xA0" "Scedil" "\\xC5\\x9E" "Scirc" "\\xC5\\x9C" "Scy" "\\xD0\\xA1" "Sfr" "\\xF0\\x9D\\x94\\x96" "ShortDownArrow" "\\xE2\\x86\\x93" "ShortLeftArrow" "\\xE2\\x86\\x90" "ShortRightArrow" "\\xE2\\x86\\x92" "ShortUpArrow" "\\xE2\\x86\\x91" "Sigma" "\\xCE\\xA3" "SmallCircle" "\\xE2\\x88\\x98" "Sopf" "\\xF0\\x9D\\x95\\x8A" "Sqrt" "\\xE2\\x88\\x9A" "Square" "\\xE2\\x96\\xA1" "SquareIntersection" "\\xE2\\x8A\\x93" "SquareSubset" "\\xE2\\x8A\\x8F" "SquareSubsetEqual" "\\xE2\\x8A\\x91" "SquareSuperset" "\\xE2\\x8A\\x90" "SquareSupersetEqual" "\\xE2\\x8A\\x92" "SquareUnion" "\\xE2\\x8A\\x94" "Sscr" "\\xF0\\x9D\\x92\\xAE" "Star" "\\xE2\\x8B\\x86" "Sub" "\\xE2\\x8B\\x90" "Subset" "\\xE2\\x8B\\x90" "SubsetEqual" "\\xE2\\x8A\\x86" "Succeeds" "\\xE2\\x89\\xBB" "SucceedsEqual" "\\xE2\\xAA\\xB0" "SucceedsSlantEqual" "\\xE2\\x89\\xBD" "SucceedsTilde" "\\xE2\\x89\\xBF" "SuchThat" "\\xE2\\x88\\x8B" "Sum" "\\xE2\\x88\\x91" "Sup" "\\xE2\\x8B\\x91" "Superset" "\\xE2\\x8A\\x83" "SupersetEqual" "\\xE2\\x8A\\x87" "Supset" "\\xE2\\x8B\\x91" "THORN" "\\xC3\\x9E" "TRADE" "\\xE2\\x84\\xA2" "TSHcy" "\\xD0\\x8B" "TScy" "\\xD0\\xA6" "Tab" "\\x09" "Tau" "\\xCE\\xA4" "Tcaron" "\\xC5\\xA4" "Tcedil" "\\xC5\\xA2" "Tcy" "\\xD0\\xA2" "Tfr" "\\xF0\\x9D\\x94\\x97" "Therefore" "\\xE2\\x88\\xB4" "Theta" "\\xCE\\x98" "ThickSpace" "\\xE2\\x81\\x9F\\xE2\\x80\\x8A" "ThinSpace" "\\xE2\\x80\\x89" "Tilde" "\\xE2\\x88\\xBC" "TildeEqual" "\\xE2\\x89\\x83" "TildeFullEqual" "\\xE2\\x89\\x85" "TildeTilde" "\\xE2\\x89\\x88" "Topf" "\\xF0\\x9D\\x95\\x8B" "TripleDot" "\\xE2\\x83\\x9B" "Tscr" "\\xF0\\x9D\\x92\\xAF" "Tstrok" "\\xC5\\xA6" "Uacute" "\\xC3\\x9A" "Uarr" "\\xE2\\x86\\x9F" "Uarrocir" "\\xE2\\xA5\\x89" "Ubrcy" "\\xD0\\x8E" "Ubreve" "\\xC5\\xAC" "Ucirc" "\\xC3\\x9B" "Ucy" "\\xD0\\xA3" "Udblac" "\\xC5\\xB0" "Ufr" "\\xF0\\x9D\\x94\\x98" "Ugrave" "\\xC3\\x99" "Umacr" "\\xC5\\xAA" "UnderBar" "\\x5F" "UnderBrace" "\\xE2\\x8F\\x9F" "UnderBracket" "\\xE2\\x8E\\xB5" "UnderParenthesis" "\\xE2\\x8F\\x9D" "Union" "\\xE2\\x8B\\x83" "UnionPlus" "\\xE2\\x8A\\x8E" "Uogon" "\\xC5\\xB2" "Uopf" "\\xF0\\x9D\\x95\\x8C" "UpArrow" "\\xE2\\x86\\x91" "UpArrowBar" "\\xE2\\xA4\\x92" "UpArrowDownArrow" "\\xE2\\x87\\x85" "UpDownArrow" "\\xE2\\x86\\x95" "UpEquilibrium" "\\xE2\\xA5\\xAE" "UpTee" "\\xE2\\x8A\\xA5" "UpTeeArrow" "\\xE2\\x86\\xA5" "Uparrow" "\\xE2\\x87\\x91" "Updownarrow" "\\xE2\\x87\\x95" "UpperLeftArrow" "\\xE2\\x86\\x96" "UpperRightArrow" "\\xE2\\x86\\x97" "Upsi" "\\xCF\\x92" "Upsilon" "\\xCE\\xA5" "Uring" "\\xC5\\xAE" "Uscr" "\\xF0\\x9D\\x92\\xB0" "Utilde" "\\xC5\\xA8" "Uuml" "\\xC3\\x9C" "VDash" "\\xE2\\x8A\\xAB" "Vbar" "\\xE2\\xAB\\xAB" "Vcy" "\\xD0\\x92" "Vdash" "\\xE2\\x8A\\xA9" "Vdashl" "\\xE2\\xAB\\xA6" "Vee" "\\xE2\\x8B\\x81" "Verbar" "\\xE2\\x80\\x96" "Vert" "\\xE2\\x80\\x96" "VerticalBar" "\\xE2\\x88\\xA3" "VerticalLine" "\\x7C" "VerticalSeparator" "\\xE2\\x9D\\x98" "VerticalTilde" "\\xE2\\x89\\x80" "VeryThinSpace" "\\xE2\\x80\\x8A" "Vfr" "\\xF0\\x9D\\x94\\x99" "Vopf" "\\xF0\\x9D\\x95\\x8D" "Vscr" "\\xF0\\x9D\\x92\\xB1" "Vvdash" "\\xE2\\x8A\\xAA" "Wcirc" "\\xC5\\xB4" "Wedge" "\\xE2\\x8B\\x80" "Wfr" "\\xF0\\x9D\\x94\\x9A" "Wopf" "\\xF0\\x9D\\x95\\x8E" "Wscr" "\\xF0\\x9D\\x92\\xB2" "Xfr" "\\xF0\\x9D\\x94\\x9B" "Xi" "\\xCE\\x9E" "Xopf" "\\xF0\\x9D\\x95\\x8F" "Xscr" "\\xF0\\x9D\\x92\\xB3" "YAcy" "\\xD0\\xAF" "YIcy" "\\xD0\\x87" "YUcy" "\\xD0\\xAE" "Yacute" "\\xC3\\x9D" "Ycirc" "\\xC5\\xB6" "Ycy" "\\xD0\\xAB" "Yfr" "\\xF0\\x9D\\x94\\x9C" "Yopf" "\\xF0\\x9D\\x95\\x90" "Yscr" "\\xF0\\x9D\\x92\\xB4" "Yuml" "\\xC5\\xB8" "ZHcy" "\\xD0\\x96" "Zacute" "\\xC5\\xB9" "Zcaron" "\\xC5\\xBD" "Zcy" "\\xD0\\x97" "Zdot" "\\xC5\\xBB" "ZeroWidthSpace" "\\xE2\\x80\\x8B" "Zeta" "\\xCE\\x96" "Zfr" "\\xE2\\x84\\xA8" "Zopf" "\\xE2\\x84\\xA4" "Zscr" "\\xF0\\x9D\\x92\\xB5" "aacute" "\\xC3\\xA1" "abreve" "\\xC4\\x83" "ac" "\\xE2\\x88\\xBE" "acE" "\\xE2\\x88\\xBE\\xCC\\xB3" "acd" "\\xE2\\x88\\xBF" "acirc" "\\xC3\\xA2" "acute" "\\xC2\\xB4" "acy" "\\xD0\\xB0" "aelig" "\\xC3\\xA6" "af" "\\xE2\\x81\\xA1" "afr" "\\xF0\\x9D\\x94\\x9E" "agrave" "\\xC3\\xA0" "alefsym" "\\xE2\\x84\\xB5" "aleph" "\\xE2\\x84\\xB5" "alpha" "\\xCE\\xB1" "amacr" "\\xC4\\x81" "amalg" "\\xE2\\xA8\\xBF" "amp" "\\x26" "and" "\\xE2\\x88\\xA7" "andand" "\\xE2\\xA9\\x95" "andd" "\\xE2\\xA9\\x9C" "andslope" "\\xE2\\xA9\\x98" "andv" "\\xE2\\xA9\\x9A" "ang" "\\xE2\\x88\\xA0" "ange" "\\xE2\\xA6\\xA4" "angle" "\\xE2\\x88\\xA0" "angmsd" "\\xE2\\x88\\xA1" "angmsdaa" "\\xE2\\xA6\\xA8" "angmsdab" "\\xE2\\xA6\\xA9" "angmsdac" "\\xE2\\xA6\\xAA" "angmsdad" "\\xE2\\xA6\\xAB" "angmsdae" "\\xE2\\xA6\\xAC" "angmsdaf" "\\xE2\\xA6\\xAD" "angmsdag" "\\xE2\\xA6\\xAE" "angmsdah" "\\xE2\\xA6\\xAF" "angrt" "\\xE2\\x88\\x9F" "angrtvb" "\\xE2\\x8A\\xBE" "angrtvbd" "\\xE2\\xA6\\x9D" "angsph" "\\xE2\\x88\\xA2" "angst" "\\xC3\\x85" "angzarr" "\\xE2\\x8D\\xBC" "aogon" "\\xC4\\x85" "aopf" "\\xF0\\x9D\\x95\\x92" "ap" "\\xE2\\x89\\x88" "apE" "\\xE2\\xA9\\xB0" "apacir" "\\xE2\\xA9\\xAF" "ape" "\\xE2\\x89\\x8A" "apid" "\\xE2\\x89\\x8B" "apos" "\\x27" "approx" "\\xE2\\x89\\x88" "approxeq" "\\xE2\\x89\\x8A" "aring" "\\xC3\\xA5" "ascr" "\\xF0\\x9D\\x92\\xB6" "ast" "\\x2A" "asymp" "\\xE2\\x89\\x88" "asympeq" "\\xE2\\x89\\x8D" "atilde" "\\xC3\\xA3" "auml" "\\xC3\\xA4" "awconint" "\\xE2\\x88\\xB3" "awint" "\\xE2\\xA8\\x91" "bNot" "\\xE2\\xAB\\xAD" "backcong" "\\xE2\\x89\\x8C" "backepsilon" "\\xCF\\xB6" "backprime" "\\xE2\\x80\\xB5" "backsim" "\\xE2\\x88\\xBD" "backsimeq" "\\xE2\\x8B\\x8D" "barvee" "\\xE2\\x8A\\xBD" "barwed" "\\xE2\\x8C\\x85" "barwedge" "\\xE2\\x8C\\x85" "bbrk" "\\xE2\\x8E\\xB5" "bbrktbrk" "\\xE2\\x8E\\xB6" "bcong" "\\xE2\\x89\\x8C" "bcy" "\\xD0\\xB1" "bdquo" "\\xE2\\x80\\x9E" "becaus" "\\xE2\\x88\\xB5" "because" "\\xE2\\x88\\xB5" "bemptyv" "\\xE2\\xA6\\xB0" "bepsi" "\\xCF\\xB6" "bernou" "\\xE2\\x84\\xAC" "beta" "\\xCE\\xB2" "beth" "\\xE2\\x84\\xB6" "between" "\\xE2\\x89\\xAC" "bfr" "\\xF0\\x9D\\x94\\x9F" "bigcap" "\\xE2\\x8B\\x82" "bigcirc" "\\xE2\\x97\\xAF" "bigcup" "\\xE2\\x8B\\x83" "bigodot" "\\xE2\\xA8\\x80" "bigoplus" "\\xE2\\xA8\\x81" "bigotimes" "\\xE2\\xA8\\x82" "bigsqcup" "\\xE2\\xA8\\x86" "bigstar" "\\xE2\\x98\\x85" "bigtriangledown" "\\xE2\\x96\\xBD" "bigtriangleup" "\\xE2\\x96\\xB3" "biguplus" "\\xE2\\xA8\\x84" "bigvee" "\\xE2\\x8B\\x81" "bigwedge" "\\xE2\\x8B\\x80" "bkarow" "\\xE2\\xA4\\x8D" "blacklozenge" "\\xE2\\xA7\\xAB" "blacksquare" "\\xE2\\x96\\xAA" "blacktriangle" "\\xE2\\x96\\xB4" "blacktriangledown" "\\xE2\\x96\\xBE" "blacktriangleleft" "\\xE2\\x97\\x82" "blacktriangleright" "\\xE2\\x96\\xB8" "blank" "\\xE2\\x90\\xA3" "blk12" "\\xE2\\x96\\x92" "blk14" "\\xE2\\x96\\x91" "blk34" "\\xE2\\x96\\x93" "block" "\\xE2\\x96\\x88" "bne" "\\x3D\\xE2\\x83\\xA5" "bnequiv" "\\xE2\\x89\\xA1\\xE2\\x83\\xA5" "bnot" "\\xE2\\x8C\\x90" "bopf" "\\xF0\\x9D\\x95\\x93" "bot" "\\xE2\\x8A\\xA5" "bottom" "\\xE2\\x8A\\xA5" "bowtie" "\\xE2\\x8B\\x88" "boxDL" "\\xE2\\x95\\x97" "boxDR" "\\xE2\\x95\\x94" "boxDl" "\\xE2\\x95\\x96" "boxDr" "\\xE2\\x95\\x93" "boxH" "\\xE2\\x95\\x90" "boxHD" "\\xE2\\x95\\xA6" "boxHU" "\\xE2\\x95\\xA9" "boxHd" "\\xE2\\x95\\xA4" "boxHu" "\\xE2\\x95\\xA7" "boxUL" "\\xE2\\x95\\x9D" "boxUR" "\\xE2\\x95\\x9A" "boxUl" "\\xE2\\x95\\x9C" "boxUr" "\\xE2\\x95\\x99" "boxV" "\\xE2\\x95\\x91" "boxVH" "\\xE2\\x95\\xAC" "boxVL" "\\xE2\\x95\\xA3" "boxVR" "\\xE2\\x95\\xA0" "boxVh" "\\xE2\\x95\\xAB" "boxVl" "\\xE2\\x95\\xA2" "boxVr" "\\xE2\\x95\\x9F" "boxbox" "\\xE2\\xA7\\x89" "boxdL" "\\xE2\\x95\\x95" "boxdR" "\\xE2\\x95\\x92" "boxdl" "\\xE2\\x94\\x90" "boxdr" "\\xE2\\x94\\x8C" "boxh" "\\xE2\\x94\\x80" "boxhD" "\\xE2\\x95\\xA5" "boxhU" "\\xE2\\x95\\xA8" "boxhd" "\\xE2\\x94\\xAC" "boxhu" "\\xE2\\x94\\xB4" "boxminus" "\\xE2\\x8A\\x9F" "boxplus" "\\xE2\\x8A\\x9E" "boxtimes" "\\xE2\\x8A\\xA0" "boxuL" "\\xE2\\x95\\x9B" "boxuR" "\\xE2\\x95\\x98" "boxul" "\\xE2\\x94\\x98" "boxur" "\\xE2\\x94\\x94" "boxv" "\\xE2\\x94\\x82" "boxvH" "\\xE2\\x95\\xAA" "boxvL" "\\xE2\\x95\\xA1" "boxvR" "\\xE2\\x95\\x9E" "boxvh" "\\xE2\\x94\\xBC" "boxvl" "\\xE2\\x94\\xA4" "boxvr" "\\xE2\\x94\\x9C" "bprime" "\\xE2\\x80\\xB5" "breve" "\\xCB\\x98" "brvbar" "\\xC2\\xA6" "bscr" "\\xF0\\x9D\\x92\\xB7" "bsemi" "\\xE2\\x81\\x8F" "bsim" "\\xE2\\x88\\xBD" "bsime" "\\xE2\\x8B\\x8D" "bsol" "\\x5C" "bsolb" "\\xE2\\xA7\\x85" "bsolhsub" "\\xE2\\x9F\\x88" "bull" "\\xE2\\x80\\xA2" "bullet" "\\xE2\\x80\\xA2" "bump" "\\xE2\\x89\\x8E" "bumpE" "\\xE2\\xAA\\xAE" "bumpe" "\\xE2\\x89\\x8F" "bumpeq" "\\xE2\\x89\\x8F" "cacute" "\\xC4\\x87" "cap" "\\xE2\\x88\\xA9" "capand" "\\xE2\\xA9\\x84" "capbrcup" "\\xE2\\xA9\\x89" "capcap" "\\xE2\\xA9\\x8B" "capcup" "\\xE2\\xA9\\x87" "capdot" "\\xE2\\xA9\\x80" "caps" "\\xE2\\x88\\xA9\\xEF\\xB8\\x80" "caret" "\\xE2\\x81\\x81" "caron" "\\xCB\\x87" "ccaps" "\\xE2\\xA9\\x8D" "ccaron" "\\xC4\\x8D" "ccedil" "\\xC3\\xA7" "ccirc" "\\xC4\\x89" "ccups" "\\xE2\\xA9\\x8C" "ccupssm" "\\xE2\\xA9\\x90" "cdot" "\\xC4\\x8B" "cedil" "\\xC2\\xB8" "cemptyv" "\\xE2\\xA6\\xB2" "cent" "\\xC2\\xA2" "centerdot" "\\xC2\\xB7" "cfr" "\\xF0\\x9D\\x94\\xA0" "chcy" "\\xD1\\x87" "check" "\\xE2\\x9C\\x93" "checkmark" "\\xE2\\x9C\\x93" "chi" "\\xCF\\x87" "cir" "\\xE2\\x97\\x8B" "cirE" "\\xE2\\xA7\\x83" "circ" "\\xCB\\x86" "circeq" "\\xE2\\x89\\x97" "circlearrowleft" "\\xE2\\x86\\xBA" "circlearrowright" "\\xE2\\x86\\xBB" "circledR" "\\xC2\\xAE" "circledS" "\\xE2\\x93\\x88" "circledast" "\\xE2\\x8A\\x9B" "circledcirc" "\\xE2\\x8A\\x9A" "circleddash" "\\xE2\\x8A\\x9D" "cire" "\\xE2\\x89\\x97" "cirfnint" "\\xE2\\xA8\\x90" "cirmid" "\\xE2\\xAB\\xAF" "cirscir" "\\xE2\\xA7\\x82" "clubs" "\\xE2\\x99\\xA3" "clubsuit" "\\xE2\\x99\\xA3" "colon" "\\x3A" "colone" "\\xE2\\x89\\x94" "coloneq" "\\xE2\\x89\\x94" "comma" "\\x2C" "commat" "\\x40" "comp" "\\xE2\\x88\\x81" "compfn" "\\xE2\\x88\\x98" "complement" "\\xE2\\x88\\x81" "complexes" "\\xE2\\x84\\x82" "cong" "\\xE2\\x89\\x85" "congdot" "\\xE2\\xA9\\xAD" "conint" "\\xE2\\x88\\xAE" "copf" "\\xF0\\x9D\\x95\\x94" "coprod" "\\xE2\\x88\\x90" "copy" "\\xC2\\xA9" "copysr" "\\xE2\\x84\\x97" "crarr" "\\xE2\\x86\\xB5" "cross" "\\xE2\\x9C\\x97" "cscr" "\\xF0\\x9D\\x92\\xB8" "csub" "\\xE2\\xAB\\x8F" "csube" "\\xE2\\xAB\\x91" "csup" "\\xE2\\xAB\\x90" "csupe" "\\xE2\\xAB\\x92" "ctdot" "\\xE2\\x8B\\xAF" "cudarrl" "\\xE2\\xA4\\xB8" "cudarrr" "\\xE2\\xA4\\xB5" "cuepr" "\\xE2\\x8B\\x9E" "cuesc" "\\xE2\\x8B\\x9F" "cularr" "\\xE2\\x86\\xB6" "cularrp" "\\xE2\\xA4\\xBD" "cup" "\\xE2\\x88\\xAA" "cupbrcap" "\\xE2\\xA9\\x88" "cupcap" "\\xE2\\xA9\\x86" "cupcup" "\\xE2\\xA9\\x8A" "cupdot" "\\xE2\\x8A\\x8D" "cupor" "\\xE2\\xA9\\x85" "cups" "\\xE2\\x88\\xAA\\xEF\\xB8\\x80" "curarr" "\\xE2\\x86\\xB7" "curarrm" "\\xE2\\xA4\\xBC" "curlyeqprec" "\\xE2\\x8B\\x9E" "curlyeqsucc" "\\xE2\\x8B\\x9F" "curlyvee" "\\xE2\\x8B\\x8E" "curlywedge" "\\xE2\\x8B\\x8F" "curren" "\\xC2\\xA4" "curvearrowleft" "\\xE2\\x86\\xB6" "curvearrowright" "\\xE2\\x86\\xB7" "cuvee" "\\xE2\\x8B\\x8E" "cuwed" "\\xE2\\x8B\\x8F" "cwconint" "\\xE2\\x88\\xB2" "cwint" "\\xE2\\x88\\xB1" "cylcty" "\\xE2\\x8C\\xAD" "dArr" "\\xE2\\x87\\x93" "dHar" "\\xE2\\xA5\\xA5" "dagger" "\\xE2\\x80\\xA0" "daleth" "\\xE2\\x84\\xB8" "darr" "\\xE2\\x86\\x93" "dash" "\\xE2\\x80\\x90" "dashv" "\\xE2\\x8A\\xA3" "dbkarow" "\\xE2\\xA4\\x8F" "dblac" "\\xCB\\x9D" "dcaron" "\\xC4\\x8F" "dcy" "\\xD0\\xB4" "dd" "\\xE2\\x85\\x86" "ddagger" "\\xE2\\x80\\xA1" "ddarr" "\\xE2\\x87\\x8A" "ddotseq" "\\xE2\\xA9\\xB7" "deg" "\\xC2\\xB0" "delta" "\\xCE\\xB4" "demptyv" "\\xE2\\xA6\\xB1" "dfisht" "\\xE2\\xA5\\xBF" "dfr" "\\xF0\\x9D\\x94\\xA1" "dharl" "\\xE2\\x87\\x83" "dharr" "\\xE2\\x87\\x82" "diam" "\\xE2\\x8B\\x84" "diamond" "\\xE2\\x8B\\x84" "diamondsuit" "\\xE2\\x99\\xA6" "diams" "\\xE2\\x99\\xA6" "die" "\\xC2\\xA8" "digamma" "\\xCF\\x9D" "disin" "\\xE2\\x8B\\xB2" "div" "\\xC3\\xB7" "divide" "\\xC3\\xB7" "divideontimes" "\\xE2\\x8B\\x87" "divonx" "\\xE2\\x8B\\x87" "djcy" "\\xD1\\x92" "dlcorn" "\\xE2\\x8C\\x9E" "dlcrop" "\\xE2\\x8C\\x8D" "dollar" "\\x24" "dopf" "\\xF0\\x9D\\x95\\x95" "dot" "\\xCB\\x99" "doteq" "\\xE2\\x89\\x90" "doteqdot" "\\xE2\\x89\\x91" "dotminus" "\\xE2\\x88\\xB8" "dotplus" "\\xE2\\x88\\x94" "dotsquare" "\\xE2\\x8A\\xA1" "doublebarwedge" "\\xE2\\x8C\\x86" "downarrow" "\\xE2\\x86\\x93" "downdownarrows" "\\xE2\\x87\\x8A" "downharpoonleft" "\\xE2\\x87\\x83" "downharpoonright" "\\xE2\\x87\\x82" "drbkarow" "\\xE2\\xA4\\x90" "drcorn" "\\xE2\\x8C\\x9F" "drcrop" "\\xE2\\x8C\\x8C" "dscr" "\\xF0\\x9D\\x92\\xB9" "dscy" "\\xD1\\x95" "dsol" "\\xE2\\xA7\\xB6" "dstrok" "\\xC4\\x91" "dtdot" "\\xE2\\x8B\\xB1" "dtri" "\\xE2\\x96\\xBF" "dtrif" "\\xE2\\x96\\xBE" "duarr" "\\xE2\\x87\\xB5" "duhar" "\\xE2\\xA5\\xAF" "dwangle" "\\xE2\\xA6\\xA6" "dzcy" "\\xD1\\x9F" "dzigrarr" "\\xE2\\x9F\\xBF" "eDDot" "\\xE2\\xA9\\xB7" "eDot" "\\xE2\\x89\\x91" "eacute" "\\xC3\\xA9" "easter" "\\xE2\\xA9\\xAE" "ecaron" "\\xC4\\x9B" "ecir" "\\xE2\\x89\\x96" "ecirc" "\\xC3\\xAA" "ecolon" "\\xE2\\x89\\x95" "ecy" "\\xD1\\x8D" "edot" "\\xC4\\x97" "ee" "\\xE2\\x85\\x87" "efDot" "\\xE2\\x89\\x92" "efr" "\\xF0\\x9D\\x94\\xA2" "eg" "\\xE2\\xAA\\x9A" "egrave" "\\xC3\\xA8" "egs" "\\xE2\\xAA\\x96" "egsdot" "\\xE2\\xAA\\x98" "el" "\\xE2\\xAA\\x99" "elinters" "\\xE2\\x8F\\xA7" "ell" "\\xE2\\x84\\x93" "els" "\\xE2\\xAA\\x95" "elsdot" "\\xE2\\xAA\\x97" "emacr" "\\xC4\\x93" "empty" "\\xE2\\x88\\x85" "emptyset" "\\xE2\\x88\\x85" "emptyv" "\\xE2\\x88\\x85" "emsp" "\\xE2\\x80\\x83" "emsp13" "\\xE2\\x80\\x84" "emsp14" "\\xE2\\x80\\x85" "eng" "\\xC5\\x8B" "ensp" "\\xE2\\x80\\x82" "eogon" "\\xC4\\x99" "eopf" "\\xF0\\x9D\\x95\\x96" "epar" "\\xE2\\x8B\\x95" "eparsl" "\\xE2\\xA7\\xA3" "eplus" "\\xE2\\xA9\\xB1" "epsi" "\\xCE\\xB5" "epsilon" "\\xCE\\xB5" "epsiv" "\\xCF\\xB5" "eqcirc" "\\xE2\\x89\\x96" "eqcolon" "\\xE2\\x89\\x95" "eqsim" "\\xE2\\x89\\x82" "eqslantgtr" "\\xE2\\xAA\\x96" "eqslantless" "\\xE2\\xAA\\x95" "equals" "\\x3D" "equest" "\\xE2\\x89\\x9F" "equiv" "\\xE2\\x89\\xA1" "equivDD" "\\xE2\\xA9\\xB8" "eqvparsl" "\\xE2\\xA7\\xA5" "erDot" "\\xE2\\x89\\x93" "erarr" "\\xE2\\xA5\\xB1" "escr" "\\xE2\\x84\\xAF" "esdot" "\\xE2\\x89\\x90" "esim" "\\xE2\\x89\\x82" "eta" "\\xCE\\xB7" "eth" "\\xC3\\xB0" "euml" "\\xC3\\xAB" "euro" "\\xE2\\x82\\xAC" "excl" "\\x21" "exist" "\\xE2\\x88\\x83" "expectation" "\\xE2\\x84\\xB0" "exponentiale" "\\xE2\\x85\\x87" "fallingdotseq" "\\xE2\\x89\\x92" "fcy" "\\xD1\\x84" "female" "\\xE2\\x99\\x80" "ffilig" "\\xEF\\xAC\\x83" "fflig" "\\xEF\\xAC\\x80" "ffllig" "\\xEF\\xAC\\x84" "ffr" "\\xF0\\x9D\\x94\\xA3" "filig" "\\xEF\\xAC\\x81" "fjlig" "\\x66\\x6A" "flat" "\\xE2\\x99\\xAD" "fllig" "\\xEF\\xAC\\x82" "fltns" "\\xE2\\x96\\xB1" "fnof" "\\xC6\\x92" "fopf" "\\xF0\\x9D\\x95\\x97" "forall" "\\xE2\\x88\\x80" "fork" "\\xE2\\x8B\\x94" "forkv" "\\xE2\\xAB\\x99" "fpartint" "\\xE2\\xA8\\x8D" "frac12" "\\xC2\\xBD" "frac13" "\\xE2\\x85\\x93" "frac14" "\\xC2\\xBC" "frac15" "\\xE2\\x85\\x95" "frac16" "\\xE2\\x85\\x99" "frac18" "\\xE2\\x85\\x9B" "frac23" "\\xE2\\x85\\x94" "frac25" "\\xE2\\x85\\x96" "frac34" "\\xC2\\xBE" "frac35" "\\xE2\\x85\\x97" "frac38" "\\xE2\\x85\\x9C" "frac45" "\\xE2\\x85\\x98" "frac56" "\\xE2\\x85\\x9A" "frac58" "\\xE2\\x85\\x9D" "frac78" "\\xE2\\x85\\x9E" "frasl" "\\xE2\\x81\\x84" "frown" "\\xE2\\x8C\\xA2" "fscr" "\\xF0\\x9D\\x92\\xBB" "gE" "\\xE2\\x89\\xA7" "gEl" "\\xE2\\xAA\\x8C" "gacute" "\\xC7\\xB5" "gamma" "\\xCE\\xB3" "gammad" "\\xCF\\x9D" "gap" "\\xE2\\xAA\\x86" "gbreve" "\\xC4\\x9F" "gcirc" "\\xC4\\x9D" "gcy" "\\xD0\\xB3" "gdot" "\\xC4\\xA1" "ge" "\\xE2\\x89\\xA5" "gel" "\\xE2\\x8B\\x9B" "geq" "\\xE2\\x89\\xA5" "geqq" "\\xE2\\x89\\xA7" "geqslant" "\\xE2\\xA9\\xBE" "ges" "\\xE2\\xA9\\xBE" "gescc" "\\xE2\\xAA\\xA9" "gesdot" "\\xE2\\xAA\\x80" "gesdoto" "\\xE2\\xAA\\x82" "gesdotol" "\\xE2\\xAA\\x84" "gesl" "\\xE2\\x8B\\x9B\\xEF\\xB8\\x80" "gesles" "\\xE2\\xAA\\x94" "gfr" "\\xF0\\x9D\\x94\\xA4" "gg" "\\xE2\\x89\\xAB" "ggg" "\\xE2\\x8B\\x99" "gimel" "\\xE2\\x84\\xB7" "gjcy" "\\xD1\\x93" "gl" "\\xE2\\x89\\xB7" "glE" "\\xE2\\xAA\\x92" "gla" "\\xE2\\xAA\\xA5" "glj" "\\xE2\\xAA\\xA4" "gnE" "\\xE2\\x89\\xA9" "gnap" "\\xE2\\xAA\\x8A" "gnapprox" "\\xE2\\xAA\\x8A" "gne" "\\xE2\\xAA\\x88" "gneq" "\\xE2\\xAA\\x88" "gneqq" "\\xE2\\x89\\xA9" "gnsim" "\\xE2\\x8B\\xA7" "gopf" "\\xF0\\x9D\\x95\\x98" "grave" "\\x60" "gscr" "\\xE2\\x84\\x8A" "gsim" "\\xE2\\x89\\xB3" "gsime" "\\xE2\\xAA\\x8E" "gsiml" "\\xE2\\xAA\\x90" "gt" "\\x3E" "gtcc" "\\xE2\\xAA\\xA7" "gtcir" "\\xE2\\xA9\\xBA" "gtdot" "\\xE2\\x8B\\x97" "gtlPar" "\\xE2\\xA6\\x95" "gtquest" "\\xE2\\xA9\\xBC" "gtrapprox" "\\xE2\\xAA\\x86" "gtrarr" "\\xE2\\xA5\\xB8" "gtrdot" "\\xE2\\x8B\\x97" "gtreqless" "\\xE2\\x8B\\x9B" "gtreqqless" "\\xE2\\xAA\\x8C" "gtrless" "\\xE2\\x89\\xB7" "gtrsim" "\\xE2\\x89\\xB3" "gvertneqq" "\\xE2\\x89\\xA9\\xEF\\xB8\\x80" "gvnE" "\\xE2\\x89\\xA9\\xEF\\xB8\\x80" "hArr" "\\xE2\\x87\\x94" "hairsp" "\\xE2\\x80\\x8A" "half" "\\xC2\\xBD" "hamilt" "\\xE2\\x84\\x8B" "hardcy" "\\xD1\\x8A" "harr" "\\xE2\\x86\\x94" "harrcir" "\\xE2\\xA5\\x88" "harrw" "\\xE2\\x86\\xAD" "hbar" "\\xE2\\x84\\x8F" "hcirc" "\\xC4\\xA5" "hearts" "\\xE2\\x99\\xA5" "heartsuit" "\\xE2\\x99\\xA5" "hellip" "\\xE2\\x80\\xA6" "hercon" "\\xE2\\x8A\\xB9" "hfr" "\\xF0\\x9D\\x94\\xA5" "hksearow" "\\xE2\\xA4\\xA5" "hkswarow" "\\xE2\\xA4\\xA6" "hoarr" "\\xE2\\x87\\xBF" "homtht" "\\xE2\\x88\\xBB" "hookleftarrow" "\\xE2\\x86\\xA9" "hookrightarrow" "\\xE2\\x86\\xAA" "hopf" "\\xF0\\x9D\\x95\\x99" "horbar" "\\xE2\\x80\\x95" "hscr" "\\xF0\\x9D\\x92\\xBD" "hslash" "\\xE2\\x84\\x8F" "hstrok" "\\xC4\\xA7" "hybull" "\\xE2\\x81\\x83" "hyphen" "\\xE2\\x80\\x90" "iacute" "\\xC3\\xAD" "ic" "\\xE2\\x81\\xA3" "icirc" "\\xC3\\xAE" "icy" "\\xD0\\xB8" "iecy" "\\xD0\\xB5" "iexcl" "\\xC2\\xA1" "iff" "\\xE2\\x87\\x94" "ifr" "\\xF0\\x9D\\x94\\xA6" "igrave" "\\xC3\\xAC" "ii" "\\xE2\\x85\\x88" "iiiint" "\\xE2\\xA8\\x8C" "iiint" "\\xE2\\x88\\xAD" "iinfin" "\\xE2\\xA7\\x9C" "iiota" "\\xE2\\x84\\xA9" "ijlig" "\\xC4\\xB3" "imacr" "\\xC4\\xAB" "image" "\\xE2\\x84\\x91" "imagline" "\\xE2\\x84\\x90" "imagpart" "\\xE2\\x84\\x91" "imath" "\\xC4\\xB1" "imof" "\\xE2\\x8A\\xB7" "imped" "\\xC6\\xB5" "in" "\\xE2\\x88\\x88" "incare" "\\xE2\\x84\\x85" "infin" "\\xE2\\x88\\x9E" "infintie" "\\xE2\\xA7\\x9D" "inodot" "\\xC4\\xB1" "int" "\\xE2\\x88\\xAB" "intcal" "\\xE2\\x8A\\xBA" "integers" "\\xE2\\x84\\xA4" "intercal" "\\xE2\\x8A\\xBA" "intlarhk" "\\xE2\\xA8\\x97" "intprod" "\\xE2\\xA8\\xBC" "iocy" "\\xD1\\x91" "iogon" "\\xC4\\xAF" "iopf" "\\xF0\\x9D\\x95\\x9A" "iota" "\\xCE\\xB9" "iprod" "\\xE2\\xA8\\xBC" "iquest" "\\xC2\\xBF" "iscr" "\\xF0\\x9D\\x92\\xBE" "isin" "\\xE2\\x88\\x88" "isinE" "\\xE2\\x8B\\xB9" "isindot" "\\xE2\\x8B\\xB5" "isins" "\\xE2\\x8B\\xB4" "isinsv" "\\xE2\\x8B\\xB3" "isinv" "\\xE2\\x88\\x88" "it" "\\xE2\\x81\\xA2" "itilde" "\\xC4\\xA9" "iukcy" "\\xD1\\x96" "iuml" "\\xC3\\xAF" "jcirc" "\\xC4\\xB5" "jcy" "\\xD0\\xB9" "jfr" "\\xF0\\x9D\\x94\\xA7" "jmath" "\\xC8\\xB7" "jopf" "\\xF0\\x9D\\x95\\x9B" "jscr" "\\xF0\\x9D\\x92\\xBF" "jsercy" "\\xD1\\x98" "jukcy" "\\xD1\\x94" "kappa" "\\xCE\\xBA" "kappav" "\\xCF\\xB0" "kcedil" "\\xC4\\xB7" "kcy" "\\xD0\\xBA" "kfr" "\\xF0\\x9D\\x94\\xA8" "kgreen" "\\xC4\\xB8" "khcy" "\\xD1\\x85" "kjcy" "\\xD1\\x9C" "kopf" "\\xF0\\x9D\\x95\\x9C" "kscr" "\\xF0\\x9D\\x93\\x80" "lAarr" "\\xE2\\x87\\x9A" "lArr" "\\xE2\\x87\\x90" "lAtail" "\\xE2\\xA4\\x9B" "lBarr" "\\xE2\\xA4\\x8E" "lE" "\\xE2\\x89\\xA6" "lEg" "\\xE2\\xAA\\x8B" "lHar" "\\xE2\\xA5\\xA2" "lacute" "\\xC4\\xBA" "laemptyv" "\\xE2\\xA6\\xB4" "lagran" "\\xE2\\x84\\x92" "lambda" "\\xCE\\xBB" "lang" "\\xE2\\x9F\\xA8" "langd" "\\xE2\\xA6\\x91" "langle" "\\xE2\\x9F\\xA8" "lap" "\\xE2\\xAA\\x85" "laquo" "\\xC2\\xAB" "larr" "\\xE2\\x86\\x90" "larrb" "\\xE2\\x87\\xA4" "larrbfs" "\\xE2\\xA4\\x9F" "larrfs" "\\xE2\\xA4\\x9D" "larrhk" "\\xE2\\x86\\xA9" "larrlp" "\\xE2\\x86\\xAB" "larrpl" "\\xE2\\xA4\\xB9" "larrsim" "\\xE2\\xA5\\xB3" "larrtl" "\\xE2\\x86\\xA2" "lat" "\\xE2\\xAA\\xAB" "latail" "\\xE2\\xA4\\x99" "late" "\\xE2\\xAA\\xAD" "lates" "\\xE2\\xAA\\xAD\\xEF\\xB8\\x80" "lbarr" "\\xE2\\xA4\\x8C" "lbbrk" "\\xE2\\x9D\\xB2" "lbrace" "\\x7B" "lbrack" "\\x5B" "lbrke" "\\xE2\\xA6\\x8B" "lbrksld" "\\xE2\\xA6\\x8F" "lbrkslu" "\\xE2\\xA6\\x8D" "lcaron" "\\xC4\\xBE" "lcedil" "\\xC4\\xBC" "lceil" "\\xE2\\x8C\\x88" "lcub" "\\x7B" "lcy" "\\xD0\\xBB" "ldca" "\\xE2\\xA4\\xB6" "ldquo" "\\xE2\\x80\\x9C" "ldquor" "\\xE2\\x80\\x9E" "ldrdhar" "\\xE2\\xA5\\xA7" "ldrushar" "\\xE2\\xA5\\x8B" "ldsh" "\\xE2\\x86\\xB2" "le" "\\xE2\\x89\\xA4" "leftarrow" "\\xE2\\x86\\x90" "leftarrowtail" "\\xE2\\x86\\xA2" "leftharpoondown" "\\xE2\\x86\\xBD" "leftharpoonup" "\\xE2\\x86\\xBC" "leftleftarrows" "\\xE2\\x87\\x87" "leftrightarrow" "\\xE2\\x86\\x94" "leftrightarrows" "\\xE2\\x87\\x86" "leftrightharpoons" "\\xE2\\x87\\x8B" "leftrightsquigarrow" "\\xE2\\x86\\xAD" "leftthreetimes" "\\xE2\\x8B\\x8B" "leg" "\\xE2\\x8B\\x9A" "leq" "\\xE2\\x89\\xA4" "leqq" "\\xE2\\x89\\xA6" "leqslant" "\\xE2\\xA9\\xBD" "les" "\\xE2\\xA9\\xBD" "lescc" "\\xE2\\xAA\\xA8" "lesdot" "\\xE2\\xA9\\xBF" "lesdoto" "\\xE2\\xAA\\x81" "lesdotor" "\\xE2\\xAA\\x83" "lesg" "\\xE2\\x8B\\x9A\\xEF\\xB8\\x80" "lesges" "\\xE2\\xAA\\x93" "lessapprox" "\\xE2\\xAA\\x85" "lessdot" "\\xE2\\x8B\\x96" "lesseqgtr" "\\xE2\\x8B\\x9A" "lesseqqgtr" "\\xE2\\xAA\\x8B" "lessgtr" "\\xE2\\x89\\xB6" "lesssim" "\\xE2\\x89\\xB2" "lfisht" "\\xE2\\xA5\\xBC" "lfloor" "\\xE2\\x8C\\x8A" "lfr" "\\xF0\\x9D\\x94\\xA9" "lg" "\\xE2\\x89\\xB6" "lgE" "\\xE2\\xAA\\x91" "lhard" "\\xE2\\x86\\xBD" "lharu" "\\xE2\\x86\\xBC" "lharul" "\\xE2\\xA5\\xAA" "lhblk" "\\xE2\\x96\\x84" "ljcy" "\\xD1\\x99" "ll" "\\xE2\\x89\\xAA" "llarr" "\\xE2\\x87\\x87" "llcorner" "\\xE2\\x8C\\x9E" "llhard" "\\xE2\\xA5\\xAB" "lltri" "\\xE2\\x97\\xBA" "lmidot" "\\xC5\\x80" "lmoust" "\\xE2\\x8E\\xB0" "lmoustache" "\\xE2\\x8E\\xB0" "lnE" "\\xE2\\x89\\xA8" "lnap" "\\xE2\\xAA\\x89" "lnapprox" "\\xE2\\xAA\\x89" "lne" "\\xE2\\xAA\\x87" "lneq" "\\xE2\\xAA\\x87" "lneqq" "\\xE2\\x89\\xA8" "lnsim" "\\xE2\\x8B\\xA6" "loang" "\\xE2\\x9F\\xAC" "loarr" "\\xE2\\x87\\xBD" "lobrk" "\\xE2\\x9F\\xA6" "longleftarrow" "\\xE2\\x9F\\xB5" "longleftrightarrow" "\\xE2\\x9F\\xB7" "longmapsto" "\\xE2\\x9F\\xBC" "longrightarrow" "\\xE2\\x9F\\xB6" "looparrowleft" "\\xE2\\x86\\xAB" "looparrowright" "\\xE2\\x86\\xAC" "lopar" "\\xE2\\xA6\\x85" "lopf" "\\xF0\\x9D\\x95\\x9D" "loplus" "\\xE2\\xA8\\xAD" "lotimes" "\\xE2\\xA8\\xB4" "lowast" "\\xE2\\x88\\x97" "lowbar" "\\x5F" "loz" "\\xE2\\x97\\x8A" "lozenge" "\\xE2\\x97\\x8A" "lozf" "\\xE2\\xA7\\xAB" "lpar" "\\x28" "lparlt" "\\xE2\\xA6\\x93" "lrarr" "\\xE2\\x87\\x86" "lrcorner" "\\xE2\\x8C\\x9F" "lrhar" "\\xE2\\x87\\x8B" "lrhard" "\\xE2\\xA5\\xAD" "lrm" "\\xE2\\x80\\x8E" "lrtri" "\\xE2\\x8A\\xBF" "lsaquo" "\\xE2\\x80\\xB9" "lscr" "\\xF0\\x9D\\x93\\x81" "lsh" "\\xE2\\x86\\xB0" "lsim" "\\xE2\\x89\\xB2" "lsime" "\\xE2\\xAA\\x8D" "lsimg" "\\xE2\\xAA\\x8F" "lsqb" "\\x5B" "lsquo" "\\xE2\\x80\\x98" "lsquor" "\\xE2\\x80\\x9A" "lstrok" "\\xC5\\x82" "lt" "\\x3C" "ltcc" "\\xE2\\xAA\\xA6" "ltcir" "\\xE2\\xA9\\xB9" "ltdot" "\\xE2\\x8B\\x96" "lthree" "\\xE2\\x8B\\x8B" "ltimes" "\\xE2\\x8B\\x89" "ltlarr" "\\xE2\\xA5\\xB6" "ltquest" "\\xE2\\xA9\\xBB" "ltrPar" "\\xE2\\xA6\\x96" "ltri" "\\xE2\\x97\\x83" "ltrie" "\\xE2\\x8A\\xB4" "ltrif" "\\xE2\\x97\\x82" "lurdshar" "\\xE2\\xA5\\x8A" "luruhar" "\\xE2\\xA5\\xA6" "lvertneqq" "\\xE2\\x89\\xA8\\xEF\\xB8\\x80" "lvnE" "\\xE2\\x89\\xA8\\xEF\\xB8\\x80" "mDDot" "\\xE2\\x88\\xBA" "macr" "\\xC2\\xAF" "male" "\\xE2\\x99\\x82" "malt" "\\xE2\\x9C\\xA0" "maltese" "\\xE2\\x9C\\xA0" "map" "\\xE2\\x86\\xA6" "mapsto" "\\xE2\\x86\\xA6" "mapstodown" "\\xE2\\x86\\xA7" "mapstoleft" "\\xE2\\x86\\xA4" "mapstoup" "\\xE2\\x86\\xA5" "marker" "\\xE2\\x96\\xAE" "mcomma" "\\xE2\\xA8\\xA9" "mcy" "\\xD0\\xBC" "mdash" "\\xE2\\x80\\x94" "measuredangle" "\\xE2\\x88\\xA1" "mfr" "\\xF0\\x9D\\x94\\xAA" "mho" "\\xE2\\x84\\xA7" "micro" "\\xC2\\xB5" "mid" "\\xE2\\x88\\xA3" "midast" "\\x2A" "midcir" "\\xE2\\xAB\\xB0" "middot" "\\xC2\\xB7" "minus" "\\xE2\\x88\\x92" "minusb" "\\xE2\\x8A\\x9F" "minusd" "\\xE2\\x88\\xB8" "minusdu" "\\xE2\\xA8\\xAA" "mlcp" "\\xE2\\xAB\\x9B" "mldr" "\\xE2\\x80\\xA6" "mnplus" "\\xE2\\x88\\x93" "models" "\\xE2\\x8A\\xA7" "mopf" "\\xF0\\x9D\\x95\\x9E" "mp" "\\xE2\\x88\\x93" "mscr" "\\xF0\\x9D\\x93\\x82" "mstpos" "\\xE2\\x88\\xBE" "mu" "\\xCE\\xBC" "multimap" "\\xE2\\x8A\\xB8" "mumap" "\\xE2\\x8A\\xB8" "nGg" "\\xE2\\x8B\\x99\\xCC\\xB8" "nGtv" "\\xE2\\x89\\xAB\\xCC\\xB8" "nLeftarrow" "\\xE2\\x87\\x8D" "nLeftrightarrow" "\\xE2\\x87\\x8E" "nLl" "\\xE2\\x8B\\x98\\xCC\\xB8" "nLtv" "\\xE2\\x89\\xAA\\xCC\\xB8" "nRightarrow" "\\xE2\\x87\\x8F" "nVDash" "\\xE2\\x8A\\xAF" "nVdash" "\\xE2\\x8A\\xAE" "nabla" "\\xE2\\x88\\x87" "nacute" "\\xC5\\x84" "nang" "\\xE2\\x88\\xA0\\xE2\\x83\\x92" "nap" "\\xE2\\x89\\x89" "napE" "\\xE2\\xA9\\xB0\\xCC\\xB8" "napid" "\\xE2\\x89\\x8B\\xCC\\xB8" "napos" "\\xC5\\x89" "napprox" "\\xE2\\x89\\x89" "natur" "\\xE2\\x99\\xAE" "natural" "\\xE2\\x99\\xAE" "naturals" "\\xE2\\x84\\x95" "nbsp" "\\xC2\\xA0" "nbump" "\\xE2\\x89\\x8E\\xCC\\xB8" "nbumpe" "\\xE2\\x89\\x8F\\xCC\\xB8" "ncap" "\\xE2\\xA9\\x83" "ncaron" "\\xC5\\x88" "ncedil" "\\xC5\\x86" "ncong" "\\xE2\\x89\\x87" "ncongdot" "\\xE2\\xA9\\xAD\\xCC\\xB8" "ncup" "\\xE2\\xA9\\x82" "ncy" "\\xD0\\xBD" "ndash" "\\xE2\\x80\\x93" "ne" "\\xE2\\x89\\xA0" "neArr" "\\xE2\\x87\\x97" "nearhk" "\\xE2\\xA4\\xA4" "nearr" "\\xE2\\x86\\x97" "nearrow" "\\xE2\\x86\\x97" "nedot" "\\xE2\\x89\\x90\\xCC\\xB8" "nequiv" "\\xE2\\x89\\xA2" "nesear" "\\xE2\\xA4\\xA8" "nesim" "\\xE2\\x89\\x82\\xCC\\xB8" "nexist" "\\xE2\\x88\\x84" "nexists" "\\xE2\\x88\\x84" "nfr" "\\xF0\\x9D\\x94\\xAB" "ngE" "\\xE2\\x89\\xA7\\xCC\\xB8" "nge" "\\xE2\\x89\\xB1" "ngeq" "\\xE2\\x89\\xB1" "ngeqq" "\\xE2\\x89\\xA7\\xCC\\xB8" "ngeqslant" "\\xE2\\xA9\\xBE\\xCC\\xB8" "nges" "\\xE2\\xA9\\xBE\\xCC\\xB8" "ngsim" "\\xE2\\x89\\xB5" "ngt" "\\xE2\\x89\\xAF" "ngtr" "\\xE2\\x89\\xAF" "nhArr" "\\xE2\\x87\\x8E" "nharr" "\\xE2\\x86\\xAE" "nhpar" "\\xE2\\xAB\\xB2" "ni" "\\xE2\\x88\\x8B" "nis" "\\xE2\\x8B\\xBC" "nisd" "\\xE2\\x8B\\xBA" "niv" "\\xE2\\x88\\x8B" "njcy" "\\xD1\\x9A" "nlArr" "\\xE2\\x87\\x8D" "nlE" "\\xE2\\x89\\xA6\\xCC\\xB8" "nlarr" "\\xE2\\x86\\x9A" "nldr" "\\xE2\\x80\\xA5" "nle" "\\xE2\\x89\\xB0" "nleftarrow" "\\xE2\\x86\\x9A" "nleftrightarrow" "\\xE2\\x86\\xAE" "nleq" "\\xE2\\x89\\xB0" "nleqq" "\\xE2\\x89\\xA6\\xCC\\xB8" "nleqslant" "\\xE2\\xA9\\xBD\\xCC\\xB8" "nles" "\\xE2\\xA9\\xBD\\xCC\\xB8" "nless" "\\xE2\\x89\\xAE" "nlsim" "\\xE2\\x89\\xB4" "nlt" "\\xE2\\x89\\xAE" "nltri" "\\xE2\\x8B\\xAA" "nltrie" "\\xE2\\x8B\\xAC" "nmid" "\\xE2\\x88\\xA4" "nopf" "\\xF0\\x9D\\x95\\x9F" "not" "\\xC2\\xAC" "notin" "\\xE2\\x88\\x89" "notinE" "\\xE2\\x8B\\xB9\\xCC\\xB8" "notindot" "\\xE2\\x8B\\xB5\\xCC\\xB8" "notinva" "\\xE2\\x88\\x89" "notinvb" "\\xE2\\x8B\\xB7" "notinvc" "\\xE2\\x8B\\xB6" "notni" "\\xE2\\x88\\x8C" "notniva" "\\xE2\\x88\\x8C" "notnivb" "\\xE2\\x8B\\xBE" "notnivc" "\\xE2\\x8B\\xBD" "npar" "\\xE2\\x88\\xA6" "nparallel" "\\xE2\\x88\\xA6" "nparsl" "\\xE2\\xAB\\xBD\\xE2\\x83\\xA5" "npart" "\\xE2\\x88\\x82\\xCC\\xB8" "npolint" "\\xE2\\xA8\\x94" "npr" "\\xE2\\x8A\\x80" "nprcue" "\\xE2\\x8B\\xA0" "npre" "\\xE2\\xAA\\xAF\\xCC\\xB8" "nprec" "\\xE2\\x8A\\x80" "npreceq" "\\xE2\\xAA\\xAF\\xCC\\xB8" "nrArr" "\\xE2\\x87\\x8F" "nrarr" "\\xE2\\x86\\x9B" "nrarrc" "\\xE2\\xA4\\xB3\\xCC\\xB8" "nrarrw" "\\xE2\\x86\\x9D\\xCC\\xB8" "nrightarrow" "\\xE2\\x86\\x9B" "nrtri" "\\xE2\\x8B\\xAB" "nrtrie" "\\xE2\\x8B\\xAD" "nsc" "\\xE2\\x8A\\x81" "nsccue" "\\xE2\\x8B\\xA1" "nsce" "\\xE2\\xAA\\xB0\\xCC\\xB8" "nscr" "\\xF0\\x9D\\x93\\x83" "nshortmid" "\\xE2\\x88\\xA4" "nshortparallel" "\\xE2\\x88\\xA6" "nsim" "\\xE2\\x89\\x81" "nsime" "\\xE2\\x89\\x84" "nsimeq" "\\xE2\\x89\\x84" "nsmid" "\\xE2\\x88\\xA4" "nspar" "\\xE2\\x88\\xA6" "nsqsube" "\\xE2\\x8B\\xA2" "nsqsupe" "\\xE2\\x8B\\xA3" "nsub" "\\xE2\\x8A\\x84" "nsubE" "\\xE2\\xAB\\x85\\xCC\\xB8" "nsube" "\\xE2\\x8A\\x88" "nsubset" "\\xE2\\x8A\\x82\\xE2\\x83\\x92" "nsubseteq" "\\xE2\\x8A\\x88" "nsubseteqq" "\\xE2\\xAB\\x85\\xCC\\xB8" "nsucc" "\\xE2\\x8A\\x81" "nsucceq" "\\xE2\\xAA\\xB0\\xCC\\xB8" "nsup" "\\xE2\\x8A\\x85" "nsupE" "\\xE2\\xAB\\x86\\xCC\\xB8" "nsupe" "\\xE2\\x8A\\x89" "nsupset" "\\xE2\\x8A\\x83\\xE2\\x83\\x92" "nsupseteq" "\\xE2\\x8A\\x89" "nsupseteqq" "\\xE2\\xAB\\x86\\xCC\\xB8" "ntgl" "\\xE2\\x89\\xB9" "ntilde" "\\xC3\\xB1" "ntlg" "\\xE2\\x89\\xB8" "ntriangleleft" "\\xE2\\x8B\\xAA" "ntrianglelefteq" "\\xE2\\x8B\\xAC" "ntriangleright" "\\xE2\\x8B\\xAB" "ntrianglerighteq" "\\xE2\\x8B\\xAD" "nu" "\\xCE\\xBD" "num" "\\x23" "numero" "\\xE2\\x84\\x96" "numsp" "\\xE2\\x80\\x87" "nvDash" "\\xE2\\x8A\\xAD" "nvHarr" "\\xE2\\xA4\\x84" "nvap" "\\xE2\\x89\\x8D\\xE2\\x83\\x92" "nvdash" "\\xE2\\x8A\\xAC" "nvge" "\\xE2\\x89\\xA5\\xE2\\x83\\x92" "nvgt" "\\x3E\\xE2\\x83\\x92" "nvinfin" "\\xE2\\xA7\\x9E" "nvlArr" "\\xE2\\xA4\\x82" "nvle" "\\xE2\\x89\\xA4\\xE2\\x83\\x92" "nvlt" "\\x3C\\xE2\\x83\\x92" "nvltrie" "\\xE2\\x8A\\xB4\\xE2\\x83\\x92" "nvrArr" "\\xE2\\xA4\\x83" "nvrtrie" "\\xE2\\x8A\\xB5\\xE2\\x83\\x92" "nvsim" "\\xE2\\x88\\xBC\\xE2\\x83\\x92" "nwArr" "\\xE2\\x87\\x96" "nwarhk" "\\xE2\\xA4\\xA3" "nwarr" "\\xE2\\x86\\x96" "nwarrow" "\\xE2\\x86\\x96" "nwnear" "\\xE2\\xA4\\xA7" "oS" "\\xE2\\x93\\x88" "oacute" "\\xC3\\xB3" "oast" "\\xE2\\x8A\\x9B" "ocir" "\\xE2\\x8A\\x9A" "ocirc" "\\xC3\\xB4" "ocy" "\\xD0\\xBE" "odash" "\\xE2\\x8A\\x9D" "odblac" "\\xC5\\x91" "odiv" "\\xE2\\xA8\\xB8" "odot" "\\xE2\\x8A\\x99" "odsold" "\\xE2\\xA6\\xBC" "oelig" "\\xC5\\x93" "ofcir" "\\xE2\\xA6\\xBF" "ofr" "\\xF0\\x9D\\x94\\xAC" "ogon" "\\xCB\\x9B" "ograve" "\\xC3\\xB2" "ogt" "\\xE2\\xA7\\x81" "ohbar" "\\xE2\\xA6\\xB5" "ohm" "\\xCE\\xA9" "oint" "\\xE2\\x88\\xAE" "olarr" "\\xE2\\x86\\xBA" "olcir" "\\xE2\\xA6\\xBE" "olcross" "\\xE2\\xA6\\xBB" "oline" "\\xE2\\x80\\xBE" "olt" "\\xE2\\xA7\\x80" "omacr" "\\xC5\\x8D" "omega" "\\xCF\\x89" "omicron" "\\xCE\\xBF" "omid" "\\xE2\\xA6\\xB6" "ominus" "\\xE2\\x8A\\x96" "oopf" "\\xF0\\x9D\\x95\\xA0" "opar" "\\xE2\\xA6\\xB7" "operp" "\\xE2\\xA6\\xB9" "oplus" "\\xE2\\x8A\\x95" "or" "\\xE2\\x88\\xA8" "orarr" "\\xE2\\x86\\xBB" "ord" "\\xE2\\xA9\\x9D" "order" "\\xE2\\x84\\xB4" "orderof" "\\xE2\\x84\\xB4" "ordf" "\\xC2\\xAA" "ordm" "\\xC2\\xBA" "origof" "\\xE2\\x8A\\xB6" "oror" "\\xE2\\xA9\\x96" "orslope" "\\xE2\\xA9\\x97" "orv" "\\xE2\\xA9\\x9B" "oscr" "\\xE2\\x84\\xB4" "oslash" "\\xC3\\xB8" "osol" "\\xE2\\x8A\\x98" "otilde" "\\xC3\\xB5" "otimes" "\\xE2\\x8A\\x97" "otimesas" "\\xE2\\xA8\\xB6" "ouml" "\\xC3\\xB6" "ovbar" "\\xE2\\x8C\\xBD" "par" "\\xE2\\x88\\xA5" "para" "\\xC2\\xB6" "parallel" "\\xE2\\x88\\xA5" "parsim" "\\xE2\\xAB\\xB3" "parsl" "\\xE2\\xAB\\xBD" "part" "\\xE2\\x88\\x82" "pcy" "\\xD0\\xBF" "percnt" "\\x25" "period" "\\x2E" "permil" "\\xE2\\x80\\xB0" "perp" "\\xE2\\x8A\\xA5" "pertenk" "\\xE2\\x80\\xB1" "pfr" "\\xF0\\x9D\\x94\\xAD" "phi" "\\xCF\\x86" "phiv" "\\xCF\\x95" "phmmat" "\\xE2\\x84\\xB3" "phone" "\\xE2\\x98\\x8E" "pi" "\\xCF\\x80" "pitchfork" "\\xE2\\x8B\\x94" "piv" "\\xCF\\x96" "planck" "\\xE2\\x84\\x8F" "planckh" "\\xE2\\x84\\x8E" "plankv" "\\xE2\\x84\\x8F" "plus" "\\x2B" "plusacir" "\\xE2\\xA8\\xA3" "plusb" "\\xE2\\x8A\\x9E" "pluscir" "\\xE2\\xA8\\xA2" "plusdo" "\\xE2\\x88\\x94" "plusdu" "\\xE2\\xA8\\xA5" "pluse" "\\xE2\\xA9\\xB2" "plusmn" "\\xC2\\xB1" "plussim" "\\xE2\\xA8\\xA6" "plustwo" "\\xE2\\xA8\\xA7" "pm" "\\xC2\\xB1" "pointint" "\\xE2\\xA8\\x95" "popf" "\\xF0\\x9D\\x95\\xA1" "pound" "\\xC2\\xA3" "pr" "\\xE2\\x89\\xBA" "prE" "\\xE2\\xAA\\xB3" "prap" "\\xE2\\xAA\\xB7" "prcue" "\\xE2\\x89\\xBC" "pre" "\\xE2\\xAA\\xAF" "prec" "\\xE2\\x89\\xBA" "precapprox" "\\xE2\\xAA\\xB7" "preccurlyeq" "\\xE2\\x89\\xBC" "preceq" "\\xE2\\xAA\\xAF" "precnapprox" "\\xE2\\xAA\\xB9" "precneqq" "\\xE2\\xAA\\xB5" "precnsim" "\\xE2\\x8B\\xA8" "precsim" "\\xE2\\x89\\xBE" "prime" "\\xE2\\x80\\xB2" "primes" "\\xE2\\x84\\x99" "prnE" "\\xE2\\xAA\\xB5" "prnap" "\\xE2\\xAA\\xB9" "prnsim" "\\xE2\\x8B\\xA8" "prod" "\\xE2\\x88\\x8F" "profalar" "\\xE2\\x8C\\xAE" "profline" "\\xE2\\x8C\\x92" "profsurf" "\\xE2\\x8C\\x93" "prop" "\\xE2\\x88\\x9D" "propto" "\\xE2\\x88\\x9D" "prsim" "\\xE2\\x89\\xBE" "prurel" "\\xE2\\x8A\\xB0" "pscr" "\\xF0\\x9D\\x93\\x85" "psi" "\\xCF\\x88" "puncsp" "\\xE2\\x80\\x88" "qfr" "\\xF0\\x9D\\x94\\xAE" "qint" "\\xE2\\xA8\\x8C" "qopf" "\\xF0\\x9D\\x95\\xA2" "qprime" "\\xE2\\x81\\x97" "qscr" "\\xF0\\x9D\\x93\\x86" "quaternions" "\\xE2\\x84\\x8D" "quatint" "\\xE2\\xA8\\x96" "quest" "\\x3F" "questeq" "\\xE2\\x89\\x9F" "quot" "\\x22" "rAarr" "\\xE2\\x87\\x9B" "rArr" "\\xE2\\x87\\x92" "rAtail" "\\xE2\\xA4\\x9C" "rBarr" "\\xE2\\xA4\\x8F" "rHar" "\\xE2\\xA5\\xA4" "race" "\\xE2\\x88\\xBD\\xCC\\xB1" "racute" "\\xC5\\x95" "radic" "\\xE2\\x88\\x9A" "raemptyv" "\\xE2\\xA6\\xB3" "rang" "\\xE2\\x9F\\xA9" "rangd" "\\xE2\\xA6\\x92" "range" "\\xE2\\xA6\\xA5" "rangle" "\\xE2\\x9F\\xA9" "raquo" "\\xC2\\xBB" "rarr" "\\xE2\\x86\\x92" "rarrap" "\\xE2\\xA5\\xB5" "rarrb" "\\xE2\\x87\\xA5" "rarrbfs" "\\xE2\\xA4\\xA0" "rarrc" "\\xE2\\xA4\\xB3" "rarrfs" "\\xE2\\xA4\\x9E" "rarrhk" "\\xE2\\x86\\xAA" "rarrlp" "\\xE2\\x86\\xAC" "rarrpl" "\\xE2\\xA5\\x85" "rarrsim" "\\xE2\\xA5\\xB4" "rarrtl" "\\xE2\\x86\\xA3" "rarrw" "\\xE2\\x86\\x9D" "ratail" "\\xE2\\xA4\\x9A" "ratio" "\\xE2\\x88\\xB6" "rationals" "\\xE2\\x84\\x9A" "rbarr" "\\xE2\\xA4\\x8D" "rbbrk" "\\xE2\\x9D\\xB3" "rbrace" "\\x7D" "rbrack" "\\x5D" "rbrke" "\\xE2\\xA6\\x8C" "rbrksld" "\\xE2\\xA6\\x8E" "rbrkslu" "\\xE2\\xA6\\x90" "rcaron" "\\xC5\\x99" "rcedil" "\\xC5\\x97" "rceil" "\\xE2\\x8C\\x89" "rcub" "\\x7D" "rcy" "\\xD1\\x80" "rdca" "\\xE2\\xA4\\xB7" "rdldhar" "\\xE2\\xA5\\xA9" "rdquo" "\\xE2\\x80\\x9D" "rdquor" "\\xE2\\x80\\x9D" "rdsh" "\\xE2\\x86\\xB3" "real" "\\xE2\\x84\\x9C" "realine" "\\xE2\\x84\\x9B" "realpart" "\\xE2\\x84\\x9C" "reals" "\\xE2\\x84\\x9D" "rect" "\\xE2\\x96\\xAD" "reg" "\\xC2\\xAE" "rfisht" "\\xE2\\xA5\\xBD" "rfloor" "\\xE2\\x8C\\x8B" "rfr" "\\xF0\\x9D\\x94\\xAF" "rhard" "\\xE2\\x87\\x81" "rharu" "\\xE2\\x87\\x80" "rharul" "\\xE2\\xA5\\xAC" "rho" "\\xCF\\x81" "rhov" "\\xCF\\xB1" "rightarrow" "\\xE2\\x86\\x92" "rightarrowtail" "\\xE2\\x86\\xA3" "rightharpoondown" "\\xE2\\x87\\x81" "rightharpoonup" "\\xE2\\x87\\x80" "rightleftarrows" "\\xE2\\x87\\x84" "rightleftharpoons" "\\xE2\\x87\\x8C" "rightrightarrows" "\\xE2\\x87\\x89" "rightsquigarrow" "\\xE2\\x86\\x9D" "rightthreetimes" "\\xE2\\x8B\\x8C" "ring" "\\xCB\\x9A" "risingdotseq" "\\xE2\\x89\\x93" "rlarr" "\\xE2\\x87\\x84" "rlhar" "\\xE2\\x87\\x8C" "rlm" "\\xE2\\x80\\x8F" "rmoust" "\\xE2\\x8E\\xB1" "rmoustache" "\\xE2\\x8E\\xB1" "rnmid" "\\xE2\\xAB\\xAE" "roang" "\\xE2\\x9F\\xAD" "roarr" "\\xE2\\x87\\xBE" "robrk" "\\xE2\\x9F\\xA7" "ropar" "\\xE2\\xA6\\x86" "ropf" "\\xF0\\x9D\\x95\\xA3" "roplus" "\\xE2\\xA8\\xAE" "rotimes" "\\xE2\\xA8\\xB5" "rpar" "\\x29" "rpargt" "\\xE2\\xA6\\x94" "rppolint" "\\xE2\\xA8\\x92" "rrarr" "\\xE2\\x87\\x89" "rsaquo" "\\xE2\\x80\\xBA" "rscr" "\\xF0\\x9D\\x93\\x87" "rsh" "\\xE2\\x86\\xB1" "rsqb" "\\x5D" "rsquo" "\\xE2\\x80\\x99" "rsquor" "\\xE2\\x80\\x99" "rthree" "\\xE2\\x8B\\x8C" "rtimes" "\\xE2\\x8B\\x8A" "rtri" "\\xE2\\x96\\xB9" "rtrie" "\\xE2\\x8A\\xB5" "rtrif" "\\xE2\\x96\\xB8" "rtriltri" "\\xE2\\xA7\\x8E" "ruluhar" "\\xE2\\xA5\\xA8" "rx" "\\xE2\\x84\\x9E" "sacute" "\\xC5\\x9B" "sbquo" "\\xE2\\x80\\x9A" "sc" "\\xE2\\x89\\xBB" "scE" "\\xE2\\xAA\\xB4" "scap" "\\xE2\\xAA\\xB8" "scaron" "\\xC5\\xA1" "sccue" "\\xE2\\x89\\xBD" "sce" "\\xE2\\xAA\\xB0" "scedil" "\\xC5\\x9F" "scirc" "\\xC5\\x9D" "scnE" "\\xE2\\xAA\\xB6" "scnap" "\\xE2\\xAA\\xBA" "scnsim" "\\xE2\\x8B\\xA9" "scpolint" "\\xE2\\xA8\\x93" "scsim" "\\xE2\\x89\\xBF" "scy" "\\xD1\\x81" "sdot" "\\xE2\\x8B\\x85" "sdotb" "\\xE2\\x8A\\xA1" "sdote" "\\xE2\\xA9\\xA6" "seArr" "\\xE2\\x87\\x98" "searhk" "\\xE2\\xA4\\xA5" "searr" "\\xE2\\x86\\x98" "searrow" "\\xE2\\x86\\x98" "sect" "\\xC2\\xA7" "semi" "\\x3B" "seswar" "\\xE2\\xA4\\xA9" "setminus" "\\xE2\\x88\\x96" "setmn" "\\xE2\\x88\\x96" "sext" "\\xE2\\x9C\\xB6" "sfr" "\\xF0\\x9D\\x94\\xB0" "sfrown" "\\xE2\\x8C\\xA2" "sharp" "\\xE2\\x99\\xAF" "shchcy" "\\xD1\\x89" "shcy" "\\xD1\\x88" "shortmid" "\\xE2\\x88\\xA3" "shortparallel" "\\xE2\\x88\\xA5" "shy" "\\xC2\\xAD" "sigma" "\\xCF\\x83" "sigmaf" "\\xCF\\x82" "sigmav" "\\xCF\\x82" "sim" "\\xE2\\x88\\xBC" "simdot" "\\xE2\\xA9\\xAA" "sime" "\\xE2\\x89\\x83" "simeq" "\\xE2\\x89\\x83" "simg" "\\xE2\\xAA\\x9E" "simgE" "\\xE2\\xAA\\xA0" "siml" "\\xE2\\xAA\\x9D" "simlE" "\\xE2\\xAA\\x9F" "simne" "\\xE2\\x89\\x86" "simplus" "\\xE2\\xA8\\xA4" "simrarr" "\\xE2\\xA5\\xB2" "slarr" "\\xE2\\x86\\x90" "smallsetminus" "\\xE2\\x88\\x96" "smashp" "\\xE2\\xA8\\xB3" "smeparsl" "\\xE2\\xA7\\xA4" "smid" "\\xE2\\x88\\xA3" "smile" "\\xE2\\x8C\\xA3" "smt" "\\xE2\\xAA\\xAA" "smte" "\\xE2\\xAA\\xAC" "smtes" "\\xE2\\xAA\\xAC\\xEF\\xB8\\x80" "softcy" "\\xD1\\x8C" "sol" "\\x2F" "solb" "\\xE2\\xA7\\x84" "solbar" "\\xE2\\x8C\\xBF" "sopf" "\\xF0\\x9D\\x95\\xA4" "spades" "\\xE2\\x99\\xA0" "spadesuit" "\\xE2\\x99\\xA0" "spar" "\\xE2\\x88\\xA5" "sqcap" "\\xE2\\x8A\\x93" "sqcaps" "\\xE2\\x8A\\x93\\xEF\\xB8\\x80" "sqcup" "\\xE2\\x8A\\x94" "sqcups" "\\xE2\\x8A\\x94\\xEF\\xB8\\x80" "sqsub" "\\xE2\\x8A\\x8F" "sqsube" "\\xE2\\x8A\\x91" "sqsubset" "\\xE2\\x8A\\x8F" "sqsubseteq" "\\xE2\\x8A\\x91" "sqsup" "\\xE2\\x8A\\x90" "sqsupe" "\\xE2\\x8A\\x92" "sqsupset" "\\xE2\\x8A\\x90" "sqsupseteq" "\\xE2\\x8A\\x92" "squ" "\\xE2\\x96\\xA1" "square" "\\xE2\\x96\\xA1" "squarf" "\\xE2\\x96\\xAA" "squf" "\\xE2\\x96\\xAA" "srarr" "\\xE2\\x86\\x92" "sscr" "\\xF0\\x9D\\x93\\x88" "ssetmn" "\\xE2\\x88\\x96" "ssmile" "\\xE2\\x8C\\xA3" "sstarf" "\\xE2\\x8B\\x86" "star" "\\xE2\\x98\\x86" "starf" "\\xE2\\x98\\x85" "straightepsilon" "\\xCF\\xB5" "straightphi" "\\xCF\\x95" "strns" "\\xC2\\xAF" "sub" "\\xE2\\x8A\\x82" "subE" "\\xE2\\xAB\\x85" "subdot" "\\xE2\\xAA\\xBD" "sube" "\\xE2\\x8A\\x86" "subedot" "\\xE2\\xAB\\x83" "submult" "\\xE2\\xAB\\x81" "subnE" "\\xE2\\xAB\\x8B" "subne" "\\xE2\\x8A\\x8A" "subplus" "\\xE2\\xAA\\xBF" "subrarr" "\\xE2\\xA5\\xB9" "subset" "\\xE2\\x8A\\x82" "subseteq" "\\xE2\\x8A\\x86" "subseteqq" "\\xE2\\xAB\\x85" "subsetneq" "\\xE2\\x8A\\x8A" "subsetneqq" "\\xE2\\xAB\\x8B" "subsim" "\\xE2\\xAB\\x87" "subsub" "\\xE2\\xAB\\x95" "subsup" "\\xE2\\xAB\\x93" "succ" "\\xE2\\x89\\xBB" "succapprox" "\\xE2\\xAA\\xB8" "succcurlyeq" "\\xE2\\x89\\xBD" "succeq" "\\xE2\\xAA\\xB0" "succnapprox" "\\xE2\\xAA\\xBA" "succneqq" "\\xE2\\xAA\\xB6" "succnsim" "\\xE2\\x8B\\xA9" "succsim" "\\xE2\\x89\\xBF" "sum" "\\xE2\\x88\\x91" "sung" "\\xE2\\x99\\xAA" "sup" "\\xE2\\x8A\\x83" "sup1" "\\xC2\\xB9" "sup2" "\\xC2\\xB2" "sup3" "\\xC2\\xB3" "supE" "\\xE2\\xAB\\x86" "supdot" "\\xE2\\xAA\\xBE" "supdsub" "\\xE2\\xAB\\x98" "supe" "\\xE2\\x8A\\x87" "supedot" "\\xE2\\xAB\\x84" "suphsol" "\\xE2\\x9F\\x89" "suphsub" "\\xE2\\xAB\\x97" "suplarr" "\\xE2\\xA5\\xBB" "supmult" "\\xE2\\xAB\\x82" "supnE" "\\xE2\\xAB\\x8C" "supne" "\\xE2\\x8A\\x8B" "supplus" "\\xE2\\xAB\\x80" "supset" "\\xE2\\x8A\\x83" "supseteq" "\\xE2\\x8A\\x87" "supseteqq" "\\xE2\\xAB\\x86" "supsetneq" "\\xE2\\x8A\\x8B" "supsetneqq" "\\xE2\\xAB\\x8C" "supsim" "\\xE2\\xAB\\x88" "supsub" "\\xE2\\xAB\\x94" "supsup" "\\xE2\\xAB\\x96" "swArr" "\\xE2\\x87\\x99" "swarhk" "\\xE2\\xA4\\xA6" "swarr" "\\xE2\\x86\\x99" "swarrow" "\\xE2\\x86\\x99" "swnwar" "\\xE2\\xA4\\xAA" "szlig" "\\xC3\\x9F" "target" "\\xE2\\x8C\\x96" "tau" "\\xCF\\x84" "tbrk" "\\xE2\\x8E\\xB4" "tcaron" "\\xC5\\xA5" "tcedil" "\\xC5\\xA3" "tcy" "\\xD1\\x82" "tdot" "\\xE2\\x83\\x9B" "telrec" "\\xE2\\x8C\\x95" "tfr" "\\xF0\\x9D\\x94\\xB1" "there4" "\\xE2\\x88\\xB4" "therefore" "\\xE2\\x88\\xB4" "theta" "\\xCE\\xB8" "thetasym" "\\xCF\\x91" "thetav" "\\xCF\\x91" "thickapprox" "\\xE2\\x89\\x88" "thicksim" "\\xE2\\x88\\xBC" "thinsp" "\\xE2\\x80\\x89" "thkap" "\\xE2\\x89\\x88" "thksim" "\\xE2\\x88\\xBC" "thorn" "\\xC3\\xBE" "tilde" "\\xCB\\x9C" "times" "\\xC3\\x97" "timesb" "\\xE2\\x8A\\xA0" "timesbar" "\\xE2\\xA8\\xB1" "timesd" "\\xE2\\xA8\\xB0" "tint" "\\xE2\\x88\\xAD" "toea" "\\xE2\\xA4\\xA8" "top" "\\xE2\\x8A\\xA4" "topbot" "\\xE2\\x8C\\xB6" "topcir" "\\xE2\\xAB\\xB1" "topf" "\\xF0\\x9D\\x95\\xA5" "topfork" "\\xE2\\xAB\\x9A" "tosa" "\\xE2\\xA4\\xA9" "tprime" "\\xE2\\x80\\xB4" "trade" "\\xE2\\x84\\xA2" "triangle" "\\xE2\\x96\\xB5" "triangledown" "\\xE2\\x96\\xBF" "triangleleft" "\\xE2\\x97\\x83" "trianglelefteq" "\\xE2\\x8A\\xB4" "triangleq" "\\xE2\\x89\\x9C" "triangleright" "\\xE2\\x96\\xB9" "trianglerighteq" "\\xE2\\x8A\\xB5" "tridot" "\\xE2\\x97\\xAC" "trie" "\\xE2\\x89\\x9C" "triminus" "\\xE2\\xA8\\xBA" "triplus" "\\xE2\\xA8\\xB9" "trisb" "\\xE2\\xA7\\x8D" "tritime" "\\xE2\\xA8\\xBB" "trpezium" "\\xE2\\x8F\\xA2" "tscr" "\\xF0\\x9D\\x93\\x89" "tscy" "\\xD1\\x86" "tshcy" "\\xD1\\x9B" "tstrok" "\\xC5\\xA7" "twixt" "\\xE2\\x89\\xAC" "twoheadleftarrow" "\\xE2\\x86\\x9E" "twoheadrightarrow" "\\xE2\\x86\\xA0" "uArr" "\\xE2\\x87\\x91" "uHar" "\\xE2\\xA5\\xA3" "uacute" "\\xC3\\xBA" "uarr" "\\xE2\\x86\\x91" "ubrcy" "\\xD1\\x9E" "ubreve" "\\xC5\\xAD" "ucirc" "\\xC3\\xBB" "ucy" "\\xD1\\x83" "udarr" "\\xE2\\x87\\x85" "udblac" "\\xC5\\xB1" "udhar" "\\xE2\\xA5\\xAE" "ufisht" "\\xE2\\xA5\\xBE" "ufr" "\\xF0\\x9D\\x94\\xB2" "ugrave" "\\xC3\\xB9" "uharl" "\\xE2\\x86\\xBF" "uharr" "\\xE2\\x86\\xBE" "uhblk" "\\xE2\\x96\\x80" "ulcorn" "\\xE2\\x8C\\x9C" "ulcorner" "\\xE2\\x8C\\x9C" "ulcrop" "\\xE2\\x8C\\x8F" "ultri" "\\xE2\\x97\\xB8" "umacr" "\\xC5\\xAB" "uml" "\\xC2\\xA8" "uogon" "\\xC5\\xB3" "uopf" "\\xF0\\x9D\\x95\\xA6" "uparrow" "\\xE2\\x86\\x91" "updownarrow" "\\xE2\\x86\\x95" "upharpoonleft" "\\xE2\\x86\\xBF" "upharpoonright" "\\xE2\\x86\\xBE" "uplus" "\\xE2\\x8A\\x8E" "upsi" "\\xCF\\x85" "upsih" "\\xCF\\x92" "upsilon" "\\xCF\\x85" "upuparrows" "\\xE2\\x87\\x88" "urcorn" "\\xE2\\x8C\\x9D" "urcorner" "\\xE2\\x8C\\x9D" "urcrop" "\\xE2\\x8C\\x8E" "uring" "\\xC5\\xAF" "urtri" "\\xE2\\x97\\xB9" "uscr" "\\xF0\\x9D\\x93\\x8A" "utdot" "\\xE2\\x8B\\xB0" "utilde" "\\xC5\\xA9" "utri" "\\xE2\\x96\\xB5" "utrif" "\\xE2\\x96\\xB4" "uuarr" "\\xE2\\x87\\x88" "uuml" "\\xC3\\xBC" "uwangle" "\\xE2\\xA6\\xA7" "vArr" "\\xE2\\x87\\x95" "vBar" "\\xE2\\xAB\\xA8" "vBarv" "\\xE2\\xAB\\xA9" "vDash" "\\xE2\\x8A\\xA8" "vangrt" "\\xE2\\xA6\\x9C" "varepsilon" "\\xCF\\xB5" "varkappa" "\\xCF\\xB0" "varnothing" "\\xE2\\x88\\x85" "varphi" "\\xCF\\x95" "varpi" "\\xCF\\x96" "varpropto" "\\xE2\\x88\\x9D" "varr" "\\xE2\\x86\\x95" "varrho" "\\xCF\\xB1" "varsigma" "\\xCF\\x82" "varsubsetneq" "\\xE2\\x8A\\x8A\\xEF\\xB8\\x80" "varsubsetneqq" "\\xE2\\xAB\\x8B\\xEF\\xB8\\x80" "varsupsetneq" "\\xE2\\x8A\\x8B\\xEF\\xB8\\x80" "varsupsetneqq" "\\xE2\\xAB\\x8C\\xEF\\xB8\\x80" "vartheta" "\\xCF\\x91" "vartriangleleft" "\\xE2\\x8A\\xB2" "vartriangleright" "\\xE2\\x8A\\xB3" "vcy" "\\xD0\\xB2" "vdash" "\\xE2\\x8A\\xA2" "vee" "\\xE2\\x88\\xA8" "veebar" "\\xE2\\x8A\\xBB" "veeeq" "\\xE2\\x89\\x9A" "vellip" "\\xE2\\x8B\\xAE" "verbar" "\\x7C" "vert" "\\x7C" "vfr" "\\xF0\\x9D\\x94\\xB3" "vltri" "\\xE2\\x8A\\xB2" "vnsub" "\\xE2\\x8A\\x82\\xE2\\x83\\x92" "vnsup" "\\xE2\\x8A\\x83\\xE2\\x83\\x92" "vopf" "\\xF0\\x9D\\x95\\xA7" "vprop" "\\xE2\\x88\\x9D" "vrtri" "\\xE2\\x8A\\xB3" "vscr" "\\xF0\\x9D\\x93\\x8B" "vsubnE" "\\xE2\\xAB\\x8B\\xEF\\xB8\\x80" "vsubne" "\\xE2\\x8A\\x8A\\xEF\\xB8\\x80" "vsupnE" "\\xE2\\xAB\\x8C\\xEF\\xB8\\x80" "vsupne" "\\xE2\\x8A\\x8B\\xEF\\xB8\\x80" "vzigzag" "\\xE2\\xA6\\x9A" "wcirc" "\\xC5\\xB5" "wedbar" "\\xE2\\xA9\\x9F" "wedge" "\\xE2\\x88\\xA7" "wedgeq" "\\xE2\\x89\\x99" "weierp" "\\xE2\\x84\\x98" "wfr" "\\xF0\\x9D\\x94\\xB4" "wopf" "\\xF0\\x9D\\x95\\xA8" "wp" "\\xE2\\x84\\x98" "wr" "\\xE2\\x89\\x80" "wreath" "\\xE2\\x89\\x80" "wscr" "\\xF0\\x9D\\x93\\x8C" "xcap" "\\xE2\\x8B\\x82" "xcirc" "\\xE2\\x97\\xAF" "xcup" "\\xE2\\x8B\\x83" "xdtri" "\\xE2\\x96\\xBD" "xfr" "\\xF0\\x9D\\x94\\xB5" "xhArr" "\\xE2\\x9F\\xBA" "xharr" "\\xE2\\x9F\\xB7" "xi" "\\xCE\\xBE" "xlArr" "\\xE2\\x9F\\xB8" "xlarr" "\\xE2\\x9F\\xB5" "xmap" "\\xE2\\x9F\\xBC" "xnis" "\\xE2\\x8B\\xBB" "xodot" "\\xE2\\xA8\\x80" "xopf" "\\xF0\\x9D\\x95\\xA9" "xoplus" "\\xE2\\xA8\\x81" "xotime" "\\xE2\\xA8\\x82" "xrArr" "\\xE2\\x9F\\xB9" "xrarr" "\\xE2\\x9F\\xB6" "xscr" "\\xF0\\x9D\\x93\\x8D" "xsqcup" "\\xE2\\xA8\\x86" "xuplus" "\\xE2\\xA8\\x84" "xutri" "\\xE2\\x96\\xB3" "xvee" "\\xE2\\x8B\\x81" "xwedge" "\\xE2\\x8B\\x80" "yacute" "\\xC3\\xBD" "yacy" "\\xD1\\x8F" "ycirc" "\\xC5\\xB7" "ycy" "\\xD1\\x8B" "yen" "\\xC2\\xA5" "yfr" "\\xF0\\x9D\\x94\\xB6" "yicy" "\\xD1\\x97" "yopf" "\\xF0\\x9D\\x95\\xAA" "yscr" "\\xF0\\x9D\\x93\\x8E" "yucy" "\\xD1\\x8E" "yuml" "\\xC3\\xBF" "zacute" "\\xC5\\xBA" "zcaron" "\\xC5\\xBE" "zcy" "\\xD0\\xB7" "zdot" "\\xC5\\xBC" "zeetrf" "\\xE2\\x84\\xA8" "zeta" "\\xCE\\xB6" "zfr" "\\xF0\\x9D\\x94\\xB7" "zhcy" "\\xD0\\xB6" "zigrarr" "\\xE2\\x87\\x9D" "zopf" "\\xF0\\x9D\\x95\\xAB" "zscr" "\\xF0\\x9D\\x93\\x8F" "zwj" "\\xE2\\x80\\x8D" "zwnj" "\\xE2\\x80\\x8C" } { set html "&$entity;" set doc [dom parse -html $html] set root [$doc documentElement] set body [$root firstChild] if {[toutf8 [$body text]] ne [string tolower $byteseq]} { lappend result $entity [toutf8 [$body text]] [string tolower $byteseq] } $doc delete } set result } "" test html-1.9 {non-existing character entities} { set doc [dom parse -html {&abcdef;}] set root [$doc documentElement] set result [$root text] $doc delete set result } "&abcdef;" test html-1.10 {non-BMP character reference} {Tcl9} { set doc [dom parse -html {𝒞𝒞}] set root [$doc documentElement] set result [$root text] $doc delete set result } "\U1d49e\U1d49e" test html-1.11 {Prematur end of entity reference with overlong repacement} {Tcl9} { set doc [dom parse -html {&nGt}] set root [$doc documentElement] set result [$root text] $doc delete set result } "&nGt" test html-1.12 {Entity reference with overlong repacement} {Tcl9} { set doc [dom parse -html {≫⃒}] set root [$doc documentElement] set result [$root text] $doc delete set result } "\u226B\u20D2" test html-1.13 {Entity reference with overlong repacement} {Tcl9} { set doc [dom parse -html {≫⃒abc≫⃒∡≪⃒≫⃒foobar}] set root [$doc documentElement] set result [$root text] $doc delete set result } "\u226B\u20D2abc\u226B\u20D2\u2221\u226A\u20D2\u226B\u20D2foobar" test html-1.14 {Entity reference with overlong repacement} {Tcl9} { set doc [dom parse -html {≫⃒abc}] set root [$doc documentElement] set result [$root text] $doc delete set result } "\u226B\u20D2abc" test html-2.1 {not closed p tags} { set doc [dom parse -html {

Para 1

Para 2

Para 3 }] set result [$doc asXML -indent none] $doc delete set result } {

Para 1

Para 2

Para 3

} test html-2.2 {HTML parsing} { set doc [dom parse -html {

HTML

}] set result [$doc asXML -indent none] $doc delete set result } {

HTML

} test html-2.3 {HTML parsing} { set doc [dom parse -html {

HTML

}] set result [$doc asXML -indent none] $doc delete set result } {

HTML

} test html-2.4 {HTML parsing} { set doc [dom parse -html {

HTML

}] $doc documentElement root set result [$root nodeName] $doc delete set result } {html} test html-2.5 {HTML parsing} { set doc [dom parse -html {
}] $doc asHTML } {
} test html-2.6 {HTML parsing} { set doc [dom parse -html {
}] $doc asHTML } {
} test html-2.7 {HTML parsing} { set doc [dom parse -html {
}] $doc asHTML } {
} test html-2.8 {HTML parsing} { set doc [dom parse -html {
}] $doc asHTML } {
} test html-2.9 {HTML parsing} {knownBug} { set doc [dom parse -html {x = 1 + 1}] set result [$doc asHTML] $doc delete set result } {<MATH-field>x = 1 + 1</MATH-field>foo}] set result [$doc asHTML] $doc delete set result } {foo} test html-2.11 {HTML parsing} { set doc [dom parse -html {x = 1 + 1}] set result [$doc asHTML] $doc delete set result } {x = 1 + 1} test html-3.1 {Bad data} { set data {line 6 column 17 - Warning: } test html-3.2 {Bad data} { set doc [dom parse -html {
}] set result [$doc asHTML] $doc delete set result } {} test html-3.3 {Single root} { set doc [dom parse -html {Sometext}] set result [$doc asXML -indent none] $doc delete set result } {Sometext} test html-3.4 {-forest} { set doc [dom parse -html -forest {Sometext}] set result [$doc asXML -indent none] $doc delete set result } {Sometext} test html-3.5 {-forest} { set doc [dom parse -html -forest {Sometext}] set result [$doc asXML -indent none] $doc delete set result } {Sometext} test html-4.1 {Tag name case normalization} { set doc [dom parse -html {}] set result [$doc asHTML] $doc delete set result } {} test html-4.2 {Tag name case normalization} {knownBug} { set doc [dom parse -html {}] set result [$doc asHTML] $doc delete set result } {} test html-4.3 {Attribute name case normalization} { set doc [dom parse -html {}] set result [$doc asHTML] $doc delete set result } {} test html-4.4 {ID Attribute handling} { set doc [dom parse -html {

}] set result [[$doc getElementById 1] getAttribute id] $doc delete set result } {1} test html-4.5 {-forest} { set doc [dom parse -html -forest {SomeOther}] set result [llength [$doc selectNodes //b]] $doc delete set result } 2 # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/xpath.test0000644000175000017500000012355614703531020015141 0ustar rolfrolf# Features covered: XPath capabilities # # This file contains a collection of tests for the XPath engine of # tDOM. # Tested commands and object commands: # xpath-1.*: Function tests # xpath-2.*: i18n # xpath-3.*: NaN/Inf, number conversion # xpath-4.*: Tcl coded XPath functions and additional Tcl coded # XPath functions # xpath-5.*: XPath lexer/parser tests # xpath-6.*: Doc order after modifying tree # xpath-7.*: Asorted XPath expressions, which are not occur in the xslt # tests outside this tcltest based test suite # # Copyright (c) 2002 - 2007 Rolf Ade. # # RCS: @(#) $Id$ source [file join [file dir [info script]] loadtdom.tcl] test xpath-1.1 {function normalize-space} { set doc [dom createDocument foo] set root [$doc documentElement] set r [$root selectNodes {normalize-space('f ')}] $doc delete string length $r } {1} set doc [dom createDocument foo] set root [$doc documentElement] test xpath-1.2 {starts-with, according errata to section 4.2} { $root selectNodes {starts-with('someString','')} } {1} test xpath-1.3 {starts-with, according errata to section 4.2} { $root selectNodes {starts-with('','')} } {1} test xpath-1.4 {contains, according errata to section 4.2} { $root selectNodes {contains('someString','')} } {1} test xpath-1.5 {contains, according errata to section 4.2} { $root selectNodes {contains('','')} } {1} test xpath-1.6 {substring-before, according errata to section 4.2} { $root selectNodes {substring-before('someString','')} } {} test xpath-1.7 {substring-before, according errata to section 4.2} { $root selectNodes {substring-before('','')} } {} test xpath-1.8 {substring-after, according errata to section 4.2} { $root selectNodes {substring-after('someString','')} } {someString} test xpath-1.9 {substring-after, according errata to section 4.2} { $root selectNodes {substring-after('','')} } {} test xpath-1.10 {floor, according errata to section 4.4} { $root selectNodes {floor('notANumber')} } {NaN} test xpath-1.11 {floor, according errata to section 4.4} { $root selectNodes {floor('+3.2')} } {NaN} test xpath-1.12 {floor, according errata to section 4.4} { $root selectNodes {floor('3.2e2')} } {NaN} test xpath-1.13 {ceiling, according errata to section 4.4} { $root selectNodes {ceiling('notANumber')} } {NaN} test xpath-1.14 {ceiling, according errata to section 4.4} { $root selectNodes {ceiling('+3.2')} } {NaN} test xpath-1.15 {ceiling, according errata to section 4.4} { $root selectNodes {ceiling('3.2e2')} } {NaN} test xpath-1.16 {floor} { $root selectNodes floor(1.1) } 1 test xpath-1.17 {floor} { $root selectNodes floor('1.1') } 1 test xpath-1.18 {floor} { $root selectNodes floor(1.9999) } 1 test xpath-1.19 {floor} { $root selectNodes floor(-1.9999) } -2 test xpath-1.20 {ceiling} { $root selectNodes ceiling(1.1) } 2 test xpath-1.21 {ceiling} { $root selectNodes ceiling('1.1') } 2 test xpath-1.22 {ceiling} { $root selectNodes ceiling(1.9999) } 2 test xpath-1.23 {ceiling} { $root selectNodes ceiling(-1.9999) } -1 test xpath-1.24 {round} { $root selectNodes round(1.1) } 1 test xpath-1.25 {round} { $root selectNodes round('1.1') } 1 test xpath-1.26 {round} { $root selectNodes round(1.9999) } 2 test xpath-1.27 {round} { $root selectNodes round(-1.9999) } -2 $doc delete test xpath-2.1 {non ASCII chars in element names} { set doc [dom parse "<\u00e4\u00f6\u00fc\u00df/>"] set root [$doc documentElement] set nodes [$root selectNodes /\u00e4\u00f6\u00fc\u00df] $doc delete llength $nodes } {1} set doc [dom createDocument foo] set root [$doc documentElement] test xpath-2.2 {non ASCII chars in string-length() call} { $root selectNodes "string-length('\u20AC')" } 1 test xpath-2.3 {non ASCII chars in substring() call} { $root selectNodes "substring('ab\u20ACde',3,3)" } \u20ACde test xpath-2.4 {non ASCII chars in substring() call} { $root selectNodes "substring('ab\u20ACde',4,3)" } de test xpath-2.5 {non ASCII chars in substring() call} { $root selectNodes "substring('ab\u20ACde',2,3)" } b\u20ACd test xpath-2.6 {non ASCII chars in substring-after() call} { $root selectNodes "substring-after('ab\u20ACde', '\u20AC')" } de test xpath-2.7 {non ASCII chars in substring-before() call} { $root selectNodes "substring-before('ab\u20ACde', '\u20AC')" } ab test xpath-3.1 {positive number mod by 0} { $root selectNodes {4 mod 0} } {NaN} test xpath-3.2 {0 mod 0} { $root selectNodes {0 mod 0} } {NaN} test xpath-3.3 {negative number mod 0} { $root selectNodes {-1 mod 0} } {NaN} test xpath-3.4 {positive number div by 0} { $root selectNodes {4 div 0} } {Infinity} test xpath-3.5 {0 div 0} { $root selectNodes {0 div 0} } {NaN} test xpath-3.6 {negative div 0} { $root selectNodes {-4 div 0} } {-Infinity} test xpath-3.7 {number value of a literal} { $root selectNodes {number('foobar')} } {NaN} test xpath-3.8 {number value of an empty node set} { $root selectNodes {number(noChilds)} } {NaN} test xpath-3.9 {propagation of NaN throu multiplication} { $root selectNodes {2 * (4 mod 0)} } {NaN} test xpath-3.10 {propagation of Infinity throu multiplication} { $root selectNodes {2 * (4 div 0)} } {Infinity} test xpath-3.11 {propagation of Infinity throu multiplication} { $root selectNodes {-2 * (3 div 0)} } {-Infinity} test xpath-3.12 {propagation of Infinity throu multiplication} { $root selectNodes {2 * (-7 div 0)} } {-Infinity} test xpath-3.13 {propagation of Infinity throu multiplication} { $root selectNodes {-2 * (-23 div 0)} } {Infinity} test xpath-3.14 {multiplication of Infinity with Infinity} { $root selectNodes {(2 div 0) * (3 div 0)} } {Infinity} test xpath-3.15 {multiplication of Infinity with -Infinity} { $root selectNodes {(2 div 0) * (-3 div 0)} } {-Infinity} test xpath-3.16 {positive number divided by Infinity} { $root selectNodes {2 div (23 div 0)} } {0} test xpath-3.17 {negative number divided by Infinity} { $root selectNodes {-2 div (23 div 0)} } {0} test xpath-3.18 {positive number divided by -Infinity} { $root selectNodes {2 div (-23 div 0)} } {0} test xpath-3.19 {negative number divided by -Infinity} { $root selectNodes {-2.2 div (-23.7 div 0)} } {0} test xpath-3.20 {Infinity divided by Infinity} { $root selectNodes {(2 div 0) div (3 div 0)} } {NaN} test xpath-3.21 {Infinity divided by positive number} { $root selectNodes {(2.7 div 0) div 23} } {Infinity} test xpath-3.22 {Infinity divided by negative number} { $root selectNodes {(2.7 div 0) div -23} } {-Infinity} test xpath-3.23 {-Infinity divided by positive number} { $root selectNodes {(-2.7 div 0) div 23} } {-Infinity} test xpath-3.24 {-Infinity divided by negative number} { $root selectNodes {(-2.7 div 0) div -23} } {Infinity} test xpath-3.25 {Infinity divided by NaN} { $root selectNodes {(2 div 0) div (2 mod 0)} } {NaN} test xpath-3.26 {NaN divided by Infinity} { $root selectNodes {(2 mod 0) div (2 div 0)} } {NaN} test xpath-3.27 {Infinity divided by zero} { $root selectNodes {(2 div 0) div 0} } {Infinity} test xpath-3.28 {-Infinity divided by zero} { $root selectNodes {(-2 div 0) div 0} } {-Infinity} test xpath-3.29 {Infinity plus positive number} { $root selectNodes {(1 div 0) + 345} } {Infinity} test xpath-3.30 {Infinity minus positive number} { $root selectNodes {(1 div 0) - 5} } {Infinity} test xpath-3.31 {number minus Infinity} { $root selectNodes {27 - (1 div 0)} } {-Infinity} test xpath-3.32 {number minus -Infinity} { $root selectNodes {5 - (-1 div 0)} } {Infinity} test xpath-3.33 {Infinity plus Infinity} { $root selectNodes {(1 div 0) + (1 div 0)} } {Infinity} test xpath-3.34 {Infinity plus -Infinity} { $root selectNodes {(1 div 0) + (-1 div 0)} } {NaN} test xpath-3.35 {Infinity minus -Infinity} { $root selectNodes {(1 div 0) - (-1 div 0)} } {Infinity} $doc delete set doc [dom parse { 1 4 6 7 0xA 0xB }] test xpath-3.36 {number conversion} { $doc selectNodes {count(/a/b[number>4])} } {2} test xpath-3.37 {number conversion} { $doc selectNodes {count(/a/b[4Foo}] set root [$doc documentElement] test xpath-4.1 {function-available} { $root selectNodes function-available('count') } {1} test xpath-4.2 {function-available} { $root selectNodes function-available('foobar') } {0} test xpath-4.3 {system-property} { $root selectNodes system-property('xsl:version') } {1.0} proc ::dom::xpathFunc::mycontains {ctxNode pos nodeListNode nodeList args} { if {[llength $args] != 4} { error "mycontains(): wrong # of args!" } foreach {arg1Typ arg1Value arg2Typ arg2Value} $args break set text [::dom::xpathFuncHelper::coerce2string $arg1Typ $arg1Value] set str [::dom::xpathFuncHelper::coerce2string $arg2Typ $arg2Value] if {[string first [string tolower $str] [string tolower $text]] != -1} { return [list bool true] } else { return [list bool false] } } test xpath-4.4 {tcl coded additional XPath function} { $root selectNodes {mycontains(., 'fo')} } {1} test xpath-4.5 {tcl coded additional XPath function} { $root selectNodes {mycontains(., 'bo')} } {0} test xpath-4.6 {tcl coded additional XPath function - error reported} { catch {$root selectNodes {mycontains(., 'bo', 'ba')}} errMsg set errMsg } {Tcl error while executing XPath extension function 'mycontains': mycontains(): wrong # of args!} proc ::dom::xpathFunc::wrongreturn {ctxNode pos nodeListNode nodeList args} { return [list footype "foo"] } test xpath-4.7 {tcl coded additional XPath function - unknown return type} { catch {$root selectNodes {wrongreturn('foo')}} errMsg set errMsg } {Unknown type of return value "footype" from Tcl coded XPath function "wrongreturn"!} proc ::dom::xpathFunc::returnnumber {ctxNode pos nodeListNode nodeList args} { return [list number "42"] } test xpath-4.8 {tcl coded additional XPath function - return number} { $root selectNodes {returnnumber()} } {42} test xpath-4.9 {tcl coded XPath function - erroneous function name} { catch {$root selectNodes {thisFunctiondoesNotExists('foo',.)}} errMsg set errMsg } {Unknown XPath function: "thisFunctiondoesNotExists"!} test xpath-4.10 {full qualified tcl coded XPath function - erroneous prefix} { catch {$root selectNodes notdefinedprefix:mycontains()} errMsg set errMsg } {Prefix doesn't resolve} namespace eval ::dom::xpathFunc::myNS { proc mycontains {ctxNode pos nodeListNode nodeList args} { if {[llength $args] != 4} { error "myNS::mycontains(): wrong # of args!" } foreach {arg1Typ arg1Value arg2Typ arg2Value} $args break set text [::dom::xpathFuncHelper::coerce2string $arg1Typ $arg1Value] set str [::dom::xpathFuncHelper::coerce2string $arg2Typ $arg2Value] if {[string first [string tolower $str] [string tolower $text]] != -1} { return [list bool true] } else { return [list bool false] } } } test xpath-4.11 {full qualified tcl coded XPath function} { $root selectNodes {myNS:mycontains(., 'fo')} } {1} test xpath-4.12 {full qualified tcl coded XPath function} { $root selectNodes {myNS:mycontains(., 'bo')} } {0} test xpath-4.13 {error in arg expr of tcl coded XPath function} { catch {$root selectNodes {mycontains(foo::bar, 'bo')}} errMsg } {1} test xpath-4.14 {error in arg expr of full qual. tcl coded XPath function} { catch {$root selectNodes {myNS:mycontains(foo::bar, 'bo')}} } {1} proc ::dom::xpathFunc::buggyproc {ctxNode pos nodeListNode nodeList args} { if {[llength $args] != 2} { error "returnstring(): wrong # of args!" } foreach {arg1Typ arg1Value} $args break set str [::dom::xpathFuncHelper::coerce2string $arg1Typ $arg1Value] # There isn't a [string split ..] - this will trigger the tcl error set charList [string split $str ""] set result "" foreach char $charList { set result $char$result } return [list string $result] } test xpath-4.15 {tcl coded XPath function - tcl error in XPath func} { catch {$root selectNodes {buggyproc('bambo')}} } {1} proc ::dom::xpathFunc::returnstring {ctxNode pos nodeListNode nodeList args} { if {[llength $args] != 2} { error "returnstring(): wrong # of args!" } foreach {arg1Typ arg1Value} $args break set str [::dom::xpathFuncHelper::coerce2string $arg1Typ $arg1Value] set charList [split $str ""] set result "" foreach char $charList { set result $char$result } return [list string $result] } test xpath-4.16 {tcl coded additional XPath function - tcl error in XPath func} { $root selectNodes {returnstring('bambo')} } {obmab} proc ::dom::xpathFunc::returnnodes {ctxNode pos nodeListNode nodeList args} { if {[llength $args] != 2} { error "returnnodes(): wrong # of args!" } foreach {arg1Typ arg1Value} $args break if {$arg1Typ != "nodes"} { error "returnnodes(): argument must be a nodeset" } set node [[lindex $arg1Value 0] selectNodes {/*[1]}] # This returns a node list with 2 nodes. Since both nodes are # the same, this node only shows up one time in the result set # of the query return [list nodes [list $node $node]] } test xpath-4.17 {tcl coded additional XPath function - return nodes} { set queryresult [$root selectNodes {returnnodes(.)}] if {$queryresult == $root} { set result 1 } else { set result 0 } set result } {1} # Called from ::dom::xpathFunc::errorStack proc ::dom::xpathFunc::errorStack1 {} { error "Some error" } proc ::dom::xpathFunc::errorStack {ctxNode pos nodeListNode nodeList args} { errorStack1 return [list string "Not reached"] } test xpath-4.18 {error stack in tcl coded additional XPath function} { set result [catch {$root selectNodes errorStack()} errMsg] lappend result $errMsg } {1 {Tcl error while executing XPath extension function 'errorStack': Some error}} proc ::dom::xpathFunc::stringReturn {args} {return x} test xpath-4.19 {tcl coded additional XPath function - return implicit string result} { $root selectNodes stringReturn(.) } {x} test xpath-4.20 {tcl coded additional XPath function - return implicit string result} { $root selectNodes stringReturn() } {x} proc ::dom::xpathFunc::ctxNode {ctxNode args} { return [list "nodes" $ctxNode] } test xpath-4.21 {tcl coded additional XPath function - return node} { $root selectNodes {string(ctxNode()/node())} } {Foo} dom parse { 1 2 3 4 5 } doc1 proc ::dom::xpathFunc::useXPath {ctxNode pos nodeListNode nodeList args} { if {[llength $args] != 2} { error "useXPath(): wrong # of args!" } foreach { arg1Typ arg1Value } $args break if {$arg1Typ ne "nodes" || [llength $arg1Value] != 1} { error "wrong argument: expecting one node" } set result [list] for {set i 5} {$i > 0} {incr i -2} { lappend result [$arg1Value selectNodes {*[position()=$i]}] } for {set i 1} {$i < 6} {incr i 2} { lappend result [$arg1Value selectNodes {*[position()=$i]}] } # Result will be a XPath result set, that means in document order # and de-duplicated. return [list "nodes" $result] } test xpath-4.22 {tcl coded additional XPath function - use XPath on the document in the function} { set result [list] foreach node [$doc1 selectNodes useXPath(/doc)] { lappend result [$node text] } join $result " " } {1 3 5} proc ::dom::xpathFunc::long0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789name {ctxNode args} { return [list "string" "fromlongprocname"] } test xpath-4.23 {tcl coded additional XPath function - long XPath function name} { $doc1 selectNodes long0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789name() } {fromlongprocname} proc ::dom::xpathFunc::toolong0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789name {ctxNode args} { return [list "string" "fromlongprocname"] } test xpath-4.24 {tcl coded additional XPath function - long XPath function name} { catch {$doc1 selectNodes toolong0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789name()} } {1} $doc1 delete 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 set errMsg } {Illegal character in localname} test xpath-5.5 {erroneous XPath expr} { catch {$root selectNodes {foo :bar}} errMsg set errMsg } {Unexpected token ':'} test xpath-5.6 {erroneous XPath expr} { catch {$root selectNodes {:foo}} errMsg set errMsg } {Unexpected token ':'} $doc delete dom parse {} doc $doc documentElement root test xpath-5.7 {White space after @ is allowed} { $root selectNodes {string(@ attr)} } {attrvalue} $doc delete test xpath-5.8 {xpath namespace axis} { set doc [dom parse {}] $doc selectNodesNamespaces {bar foo} set result [$doc selectNodes //namespace::*] $doc delete set result } {{xmlns:xml http://www.w3.org/XML/1998/namespace} {xmlns foo}} test xpath-5.9 {Illegal axis name with //} { set xml { boo boo boo } set doc [dom parse $xml] set result [catch {$doc selectNodes //bar::text()}] $doc delete set result } {1} test xpath-5.10 {White space between steps is allowed} { set xml {} set doc [dom parse $xml] set node [$doc selectNodes "doc / e1 \n\r\t / e2"] set result [$node nodeName] $doc delete set result } {e2} test xpath-5.11 {Parsing of floats} { set doc [dom createDocumentNode] set result [$doc selectNodes "1 + .2"] set result [expr {$result + [$doc selectNodes "1.0 + 0.2"]}] $doc delete set result } {2.4} test xpath-5.12 {Parsing of floats} { set doc [dom createDocumentNode] set result [catch {$doc selectNodes "1 + .2.2"}] $doc delete set result } {1} test xpath-5.13 {tcl var resolution in expr} { set doc [dom parse {footext}] set root [$doc documentElement] set var "foo" set resultNode [$root selectNodes {elem[@id=$var]}] set result [$resultNode text] $doc delete set result } {footext} test xpath-5.14 {tcl var resolution in expr} { set doc [dom parse {footext}] set root [$doc documentElement] set resultNode [$root selectNodes {elem[@id='foo']}] set result [$resultNode text] $doc delete set result } {footext} test xpath-5.15 {tcl var resolution in expr} { set doc [dom parse {footext}] set root [$doc documentElement] catch {unset dontExists} set result [catch {[$root selectNodes {elem[@id=$dontExists]}]} errMsg] $doc delete lappend result $errMsg } {1 {can't read "dontExists": no such variable}} proc xpath-5.16 {doc} { set root [$doc documentElement] set var "foo" set resultNode [$root selectNodes {elem[@id=$var]}] return [$resultNode text] } test xpath-5.16 {tcl var resolution in expr} { set doc [dom parse {footext}] catch {unset var} set result [xpath-5.16 $doc] $doc delete set result } {footext} proc xpath-5.17 {doc} { set root [$doc documentElement] set resultNode [$root selectNodes {elem[@id=$::var]}] return [$resultNode text] } test xpath-5.17 {tcl var resolution in expr} { set doc [dom parse {footext}] set var "foo" set result [xpath-5.17 $doc] $doc delete set result } {footext} proc xpath-5.18 {doc} { set root [$doc documentElement] set resultNode [$root selectNodes {elem[@id=${::uncommon varname}]}] return [$resultNode text] } test xpath-5.18 {tcl var resolution in expr} { set doc [dom parse {footext}] set {uncommon varname} "foo" set result [xpath-5.18 $doc] $doc delete set result } {footext} test xpath-5.19 {tcl var resolution in expr} { set doc [dom parse {footext}] set root [$doc documentElement] set array(key) "foo" set resultNode [$root selectNodes {elem[@id=$array(key)]}] set result [$resultNode text] $doc delete set result } {footext} test xpath-5.20 {tcl var resolution in expr} { set doc [dom parse {footext}] set root [$doc documentElement] set array(key) "foo" set var "key" set resultNode [$root selectNodes {elem[@id=$array($var)]}] set result [$resultNode text] $doc delete set result } {footext} proc xpath-5.21 {doc} { set root [$doc documentElement] set var "foo" set resultNode [$root selectNodes {elem[@id=$var]}] return [$resultNode text] } test xpath-5.21 {tcl var resolution in expr} { set doc [dom parse {footext}] set root [$doc documentElement] set var "bar" set result [xpath-5.21 $doc] $doc delete set result } {footext} proc xpath-5.22 {doc} { set root [$doc documentElement] set var "bar" return [$root selectNodes {elem[@id=$var]}] } test xpath-5.22 {tcl var resolution in expr} { set doc [dom parse {footext}] set root [$doc documentElement] set var "foo" set result [xpath-5.22 $doc] $doc delete set result } {} proc xpath-5.23 {doc} { set root [$doc documentElement] set result [catch {$root selectNodes {elem[@id=$var]}} errMsg] return [list $result $errMsg] } test xpath-5.23 {tcl var resolution in expr} { set doc [dom parse {footext}] set root [$doc documentElement] set var "foo" set result [xpath-5.23 $doc] $doc delete set result } {1 {can't read "var": no such variable}} test xpath-5.24 {tcl var resolution in expr} { set doc [dom parse {footext}] set root [$doc documentElement] set result [catch {$root selectNodes {elem[@id=$ or @id='bar']}} errMsg] $doc delete list $result $errMsg } {1 {Missing var name after '$'.}} test xpath-5.25 {tcl var resolution in expr} { set doc [dom createDocument doc] set a 2 set result [$doc selectNodes {2 + $a}] $doc delete set result } {4.0} test xpath-5.26 {erroneous XPath expr} { set doc [dom createDocument doc] set result [catch {$doc selectNodes {/[position()=1]}}] $doc delete set result } {1} test xpath-5.27 {erroneous XPath expr} { set doc [dom parse { }] set result [catch {$doc selectNodes {/[position()=1]}} errMsg] $doc delete set result } {1} test xpath-5.28 {afl-fuzz found seg faulting 'xpath expr'} { set doc [dom parse ] set result [catch {$doc selectNodes {@a//b::*}}] $doc delete set result } {1} test xpath-5.29 {afl-fuzz found seg faulting 'xpath expr'} { set doc [dom parse ] set result [catch {$doc selectNodes {a[1=a::a]}}] $doc delete set result } {1} test xpath-5.30 {afl-fuzz found seg faulting 'xpath expr'} { set doc [dom parse ] set result [catch {$doc selectNodes [string repeate 9 239]@d}] $doc delete set result } {1} test xpath-5.31 {Limits} { set doc [dom parse ] set result [$doc selectNodes {999999999999999 + 999999999999999}] $doc delete set result } {1999999999999998.0} test xpath-5.32 {Limits} { set doc [dom parse ] set result [$doc selectNodes {9999999999999999999 + 9999999999999999999}] $doc delete set result } {2e+19} test xpath-5.33 {afl-fuzz found seg faulting 'xpath expr'} { set doc [dom parse ] set result [catch {$doc selectNodes "[string repeat Q 1380](1)"}] $doc delete set result } {1} test xpath-5.34 {tcl var resolution in expr} { set doc [dom parse {}] set which 2 # Tcl var value is always seen as string by the xpath engine. Any # non empty string is always true set node [$doc selectNodes {/doc/e[$which]}] set result [llength $node] # If another xpath data type is needed, cast explicitly set node [$doc selectNodes {/doc/e[number($which)]}] lappend result [llength $node] lappend result [$node @att] set which "" # Empty string is false, by xpath converting rules set node [$doc selectNodes {/doc/e[$which]}] lappend result [llength $node] $doc delete set result } {3 1 2 0} test xpath-5.35 {tcl var resolution in xpath expr} { set doc [dom parse {1234}] set node [$doc documentElement] set i 2 set result [list] lappend result [$node selectNodes -cache 1 {string(*[position()=$i])}] set i 3 lappend result [$node selectNodes -cache 1 {string(*[position()=$i])}] $doc delete set result } {2 2} test xpath-5.36 {tcl var resolution in xpath expr} { set doc [dom parse {1234}] set node [$doc documentElement] set i 2 set result [list] lappend result [$node selectNodes {string(*[position()=$i])}] set i 3 lappend result [$node selectNodes {string(*[position()=$i])}] $doc delete set result } {2 3} proc xpath-5.37 {node} { set i 4 return [$node selectNodes -cache 1 {string(*[position()=$i])}] } test xpath-5.37 {tcl var resolution in xpath expr} { set doc [dom parse {1234}] set node [$doc documentElement] set i 2 set result [list] lappend result [$node selectNodes -cache 1 {string(*[position()=$i])}] lappend result [xpath-5.37 $node] set i 3 $doc delete set result } {2 2} test xpath-5.38 {tcl var resolution in xpath expr} { set doc [dom parse ] set xpath "/doc" for {set i 1} {$i <= 20} {incr i} { set var$i $i append xpath "/e\[position()=\$var$i\]" } set result [$doc selectNodes $xpath] $doc delete } {} test xpath-5.39 {tcl var resolution in xpath expr} { set xml { } set doc [dom parse $xml] set attvalue "b" set pos 2 set result [[$doc selectNodes {/doc/e[@att=$attvalue][position()=$pos]}] asXML -indent none] $doc delete set result } {} test xpath-5.40 {tcl var resolution in xpath expr} { set doc [dom parse {1234}] # What this test tests depend on NUM_STATIC_TOKENS. Which is 20 in # the tcl core distribution at the time, this test was written. unset -nocomplain a for {set i 0} {$i < 25} {} { set a($i) [incr i] } set a(25) 2 set xpath "string(/doc/e\[position()=" for {set i 0} {$i < 26} {incr i} { append xpath "\$a(" } append xpath 0 for {set i 0} {$i < 26} {incr i} { append xpath ")" } append xpath "\])" set result [$doc selectNodes $xpath] lappend result [$doc selectNodes -cache 1 $xpath] $doc delete unset a set result } {2 2} test xpath-5.41 {tcl var resolution in xpath expr} { set doc [dom parse {1234}] # What this test tests depend on NUM_STATIC_TOKENS. unset -nocomplain a for {set i 0} {$i < 25} {} { set a($i) [incr i] } set a(25) 2 set xpath "/doc" for {set i 1} {$i <= 20} {incr i} { set var$i $i append xpath "/e\[position()=\$var$i\]" } append xpath "/e\[position()=" for {set i 0} {$i < 26} {incr i} { append xpath "\$a(" } append xpath 0 for {set i 0} {$i < 26} {incr i} { append xpath ")" } append xpath "\]" set result [$doc selectNodes $xpath] append result [$doc selectNodes -cache 1 $xpath] $doc delete unset a set result } "" test xpath-5.42 {tcl var resolution in xpath expr} { set doc [dom parse {1234}] # What this test tests depend on NUM_STATIC_TOKENS. unset -nocomplain a for {set i 0} {$i < 25} {} { set a($i) [incr i] } set a(25) 2 set xpath "/doc/e\[position()=" for {set i 0} {$i < 26} {incr i} { append xpath "\$a(" } append xpath 0 for {set i 0} {$i < 26} {incr i} { append xpath ")" } append xpath "\]" for {set i 1} {$i <= 20} {incr i} { set var$i $i append xpath "/e\[position()=\$var$i\]" } set result [$doc selectNodes $xpath] append result [$doc selectNodes -cache 1 $xpath] $doc delete unset a set result } "" test xpath-5.43 {XPath is commutative} { set xml { eins zwei } set doc [dom parse $xml] set result [expr {[$doc selectNodes {doc/e[ee='zwei']}] == [$doc selectNodes {doc/e['zwei'=ee]}]}] lappend result [llength [$doc selectNodes {doc/e[ee='zwei']}]] lappend result [$doc selectNodes {string(doc/e[ee='zwei'])}] $doc delete set result } {1 1 zwei} test xpath-5.44 {Element name injected with tcl variable} { set doc [dom parse -json {{"member name with spaces":"the value"}}] set nodeName "member name with spaces" set node [$doc selectNodes %nodeName] set result [list] lappend result [$node nodeName] lappend result [$doc selectNodes string(%nodeName)] set node [$doc selectNodes /%nodeName] lappend result [$node nodeName] $doc delete set result } {{member name with spaces} {the value} {member name with spaces}} test xpath-5.45 {Element name injected with tcl variable} { set doc [dom parse -json {{"a":{"with spaces":"the value"},"a":{"with spaces":"another value"}}}] set nodeName "with spaces" set node [$doc selectNodes {a[%nodeName='another value']}] set result [list] lappend result [$node nodeName] lappend result [$doc selectNodes {string(a[%nodeName='another value'])}] $doc delete set result } {a {another value}} test xpath-5.46 {Element name injected with tcl variable - wrong xpath syntax} { set doc [dom parse -json {{"a":{"with spaces":"the value"},"a":{"with spaces":"another value"}}}] 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] lappend result [$doc selectNodes {string(a[%nodeName='another value'])}] $doc delete set result } {a {another value}} test xpath-5.48 {Element name injected with tcl variable} { set doc [dom parse -json {{"a":{"a\u0001b":"the value"},"a":{"a\u0001b":"another value"}}}] set nodeName "a\u0001b" set node [$doc selectNodes {a[%nodeName='another value']}] set result [list] lappend result [$node nodeName] lappend result [$doc selectNodes {string(a[%nodeName='another value'])}] $doc delete set result } {a {another value}} test xpath-5.49 {Element name injected with tcl variable} { set doc [dom parse -json {{"a":{"a\u0000b":"the value"},"a":{"a\u0000b":"another value"}}}] set nodeName "a\u0000b" set node [$doc selectNodes {a[%nodeName='another value']}] set result [list] lappend result [$node nodeName] lappend result [$doc selectNodes {string(a[%nodeName='another value'])}] $doc delete set result } {a {another value}} test xpath-5.50 {Element name injected with tcl variable} { set doc [dom parse -json {{"a":"1","*":"2","c":"3"}}] set nodeName "*" set result [llength [$doc selectNodes %nodeName]] $doc delete set result } {1} test xpath-5.51 {Element name injected with tcl variable} { set doc [dom parse -json {{"member name with spaces":"the value"}}] set nodeName "member name with spaces" set node [$doc selectNodes %nodeName] set result [list] lappend result [$node nodeName] lappend result [$doc selectNodes string(%nodeName)] set node [$doc selectNodes child::%nodeName] lappend result [$node nodeName] $doc delete set result } {{member name with spaces} {the value} {member name with spaces}} test xpath-5.52 {Element name injected with tcl variable} { set doc [dom parse -json {{"a:b":"value"}}] set nodeName "a:b" set result [$doc selectNodes string(%nodeName)] $doc delete set result } {value} test xpath-5.53 {Element name injected with tcl variable} { set doc [dom parse -json {{"a:b":"value"}}] set nodeName "a:b" set result [$doc selectNodes string(child::%nodeName)] $doc delete set result } {value} test xpath-5.54 {Element name injected with tcl variable} { set doc [dom parse -json {{"a:b":"value"}}] set nodeName "a:b" set result [$doc selectNodes string(descendant-or-self::%nodeName)] $doc delete set result } {value} test xpath-5.55 {Element name injected with tcl variable} { set doc [dom parse ] set nodeName "a/b" set result [llength [$doc selectNodes %nodeName]] lappend result [llength [$doc selectNodes a/b]] $doc delete set result } {0 1} test xpath-5.56 {Element name injected with tcl variable} { set doc [dom parse -json {{"a":{"a/b":"a/b"},"a":{"a":{"b":"b"}}}}] set nodeName0 "a" 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 "1111111111 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 { asub2 asub3 asub4 bsub1 bsub2 }] set root [$doc documentElement] test xpath-6.1 {document order in modified DOM tree} { set newAsub [$doc createElement asub] $newAsub appendChild [$doc createTextNode "asub1"] $root insertBefore $newAsub [$root firstChild] 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 { }] set root [$doc documentElement] test xpath-7.1 {preceding-sibling axis with documentElement als current node} { $root selectNodes {count(preceding-sibling::node())} } {4} test xpath-7.2 {following-sibling axis with documentElement als current node} { $root selectNodes {count(following-sibling::node())} } {4} $doc delete test xpath-7.3 {NCName equal to an operator in a union expr} { dom parse {

} doc $doc documentElement root set node [$root selectNodes {p|div}] set result [$node nodeName] $doc delete set result } {div} test xpath-7.4 {Name test * in a union expr} { dom parse {
} doc $doc documentElement root set node [$root selectNodes {processing-instruction()|*}] set result [$node nodeName] $doc delete set result } {div} test xpath-7.5 {ancestor-or-self axis on /} { dom parse {} doc set result [$doc selectNodes {count(./ancestor-or-self::*)}] lappend result [$doc selectNodes {count(ancestor-or-self::*)}] lappend result [$doc selectNodes {count(./ancestor-or-self::node())}] lappend result [$doc selectNodes {count(ancestor-or-self::node())}] $doc delete set result } {0 0 1 1} test xpath-7.6 {parent axis on /} { dom parse {} doc set result [$doc selectNodes {count(parent::*)}] lappend result [$doc selectNodes {count(parent::node())}] lappend result [$doc selectNodes {count(..)}] $doc delete set result } {0 0 0} test xpath-7.7 {Document order in complexer // expressions} -setup { set doc [dom parse { 1 11 2 22 3 4 33 }]} -body { set result [list] foreach node [$doc selectNodes //a/b] { lappend result [$node selectNodes string()] } join $result " - " } -cleanup { $doc delete } -result {1 - 11 - 2 - 22 - 3 - 4 - 33} test xpath-7.8 {Attribute node as context node of a lang() call} -setup { set doc [dom parse ] } -body { $doc selectNodes {/namespace::node()[lang('en')]} } -cleanup { $doc delete } -result "" test xpath-7.9 {Attribute node as context node of an id() call} -setup { set doc [dom parse {}] } -body { $doc selectNodes {doc/@foo[id(.)]} } -cleanup { $doc delete } -result "" test xpath-7.10 {processing-instruction with literal argument} -setup { set doc [dom parse { does not matter }] } -body { $doc selectNodes //processing-instruction('dontexist') } -cleanup { $doc delete } -result {} test xpath-7.11 {processing-instruction with literal argument} -setup { set doc [dom parse { does not matter }] } -body { [$doc selectNodes //processing-instruction('mypi')] asXML -indent none } -cleanup { $doc delete } -result {} test xpath-7.12 {string value of processing-instruction} -setup { set doc [dom parse { does not matter }] } -body { $doc selectNodes string(//processing-instruction('mypi')) } -cleanup { $doc delete } -result {whatever} test xpath-7.13 {string value of processing-instruction} -setup { set doc [dom parse { does not matter }] } -body { $doc selectNodes string(//processing-instruction('mypi')) } -cleanup { $doc delete } -result "whatever " test xpath-7.14 {local-name value of processing-instruction} -setup { set doc [dom parse { does not matter }] } -body { $doc selectNodes local-name(//processing-instruction('mypi')) } -cleanup { $doc delete } -result {mypi} # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/tdomcmd.bench0000644000175000017500000000612314703531020015532 0ustar rolfrolf# -*- tcl -*- # # This file contains benchmarks for DOM doc creation with dom and tdom # # (c) 2018 Rolf Ade # # ### ### ### ######### ######### ######### ########################### ## Setting up the environment ... package require tdom # ### ### ### ######### ######### ######### ########################### ## Benchmarks. bench -desc "dom mondial-europe.xml" -iters 20 -ipre { set fd [open ../tests/data/mondial-europe.xml] } -body { set doc [dom parse -channel $fd] } -ipost { close $fd $doc delete } bench -desc "tdom mondial-europe.xml" -iters 20 -ipre { set p [expat] tdom $p enable } -body { $p parsefile ../tests/data/mondial-europe.xml set doc [tdom $p getdoc] } -ipost { $doc delete $p free } bench -desc "tdom mondial-europe.xml / reuse parser" -iters 20 -pre { set p [expat] tdom $p enable } -body { $p parsefile ../tests/data/mondial-europe.xml set doc [tdom $p getdoc] } -ipost { $doc delete $p reset } -post { $p free } bench -desc "dom REC-xslt-19991116.xml" -iters 20 -ipre { set fd [open ../tests/data/REC-xslt-19991116.xml] } -body { set doc [dom parse -channel $fd] } -ipost { close $fd $doc delete } bench -desc "tdom REC-xslt-19991116.xml" -iters 20 -ipre { set p [expat] tdom $p enable } -body { $p parsefile ../tests/data/REC-xslt-19991116.xml set doc [tdom $p getdoc] } -ipost { $doc delete $p free } bench -desc "tdom REC-xslt-19991116.xml / reuse parser" -iters 20 -pre { set p [expat] tdom $p enable } -body { $p parsefile ../tests/data/REC-xslt-19991116.xml set doc [tdom $p getdoc] } -ipost { $doc delete $p reset } -post { $p free } if {![catch {package require tnc}]} { proc extresolver {base systemId publicId} { switch $publicId { "-//W3C//DTD Specification V2.0//EN" { set fd [open [file join [file dir [info script]] \ data/xmlspec-v20.dtd]] set xmlspec [read $fd] close $fd return [list "string" "" $xmlspec] } default { puts stderr "Unexpected systemId '$systemId'" return "" } } } bench -desc "tdom REC-xslt-19991116.xml / tnc " -iters 20 -ipre { set p [expat -externalentitycommand extresolver \ -paramentityparsing always] tdom $p enable tnc $p enable } -body { $p parsefile ../tests/data/REC-xslt-19991116.xml set doc [tdom $p getdoc] } -ipost { $doc delete $p free } bench -desc "tdom REC-xslt-19991116.xml / tnc / reuse parse" -iters 20 -pre { set p [expat -externalentitycommand extresolver \ -paramentityparsing always] tdom $p enable tnc $p enable } -body { $p parsefile ../tests/data/REC-xslt-19991116.xml set doc [tdom $p getdoc] } -ipost { $doc delete $p reset $p configure -paramentityparsing always } -post { $p free } } tdom-0.9.5-src/tests/data/0000755000175000017500000000000014703531020014011 5ustar rolfrolftdom-0.9.5-src/tests/data/i18n_2.xml0000644000175000017500000000027714703531020015541 0ustar rolfrolf german umlauts: tdom-0.9.5-src/tests/data/dtd-5.1.dtd0000644000175000017500000000003214703531020015555 0ustar rolfrolf tdom-0.9.5-src/tests/data/dtd-6.5.dtd0000644000175000017500000000013714703531020015570 0ustar rolfrolf ]]> tdom-0.9.5-src/tests/data/REC-xslt-19991116.xml0000644000175000017500000074325214703531020017073 0ustar rolfrolf ]>
XSL Transformations (XSLT) Version 1.0 &LEV;-xslt-&YYYYMMDD; W3C Recommendation &day;&month;&year; http://www.w3.org/TR/&year;/&LEV;-xslt-&YYYYMMDD; XML HTML http://www.w3.org/TR/xslt http://www.w3.org/TR/1999/PR-xslt-19991008 http://www.w3.org/1999/08/WD-xslt-19990813 http://www.w3.org/1999/07/WD-xslt-19990709 http://www.w3.org/TR/1999/WD-xslt-19990421 http://www.w3.org/TR/1998/WD-xsl-19981216 http://www.w3.org/TR/1998/WD-xsl-19980818 James Clark jjc@jclark.com

This document has been reviewed by W3C Members and other interested parties and has been endorsed by the Director as a W3C Recommendation. It is a stable document and may be used as reference material or cited as a normative reference from other documents. W3C's role in making the Recommendation is to draw attention to the specification and to promote its widespread deployment. This enhances the functionality and interoperability of the Web.

The list of known errors in this specification is available at http://www.w3.org/&year;/&MM;/&LEV;-xslt-&YYYYMMDD;-errata.

Comments on this specification may be sent to xsl-editors@w3.org; archives of the comments are available. Public discussion of XSL, including XSL Transformations, takes place on the XSL-List mailing list.

The English version of this specification is the only normative version. However, for translations of this document, see http://www.w3.org/Style/XSL/translations.html.

A list of current W3C Recommendations and other technical documents can be found at http://www.w3.org/TR.

This specification has been produced as part of the W3C Style activity.

This specification defines the syntax and semantics of XSLT, which is a language for transforming XML documents into other XML documents.

XSLT is designed for use as part of XSL, which is a stylesheet language for XML. In addition to XSLT, XSL includes an XML vocabulary for specifying formatting. XSL specifies the styling of an XML document by using XSLT to describe how the document is transformed into another XML document that uses the formatting vocabulary.

XSLT is also designed to be used independently of XSL. However, XSLT is not intended as a completely general-purpose XML transformation language. Rather it is designed primarily for the kinds of transformations that are needed when XSLT is used as part of XSL.

English EBNF See RCS log for revision history.
Introduction

This specification defines the syntax and semantics of the XSLT language. A transformation in the XSLT language is expressed as a well-formed XML document conforming to the Namespaces in XML Recommendation , which may include both elements that are defined by XSLT and elements that are not defined by XSLT. XSLT-defined elements are distinguished by belonging to a specific XML namespace (see ), which is referred to in this specification as the XSLT namespace. Thus this specification is a definition of the syntax and semantics of the XSLT namespace.

A transformation expressed in XSLT describes rules for transforming a source tree into a result tree. The transformation is achieved by associating patterns with templates. A pattern is matched against elements in the source tree. A template is instantiated to create part of the result tree. The result tree is separate from the source tree. The structure of the result tree can be completely different from the structure of the source tree. In constructing the result tree, elements from the source tree can be filtered and reordered, and arbitrary structure can be added.

A transformation expressed in XSLT is called a stylesheet. This is because, in the case when XSLT is transforming into the XSL formatting vocabulary, the transformation functions as a stylesheet.

This document does not specify how an XSLT stylesheet is associated with an XML document. It is recommended that XSL processors support the mechanism described in . When this or any other mechanism yields a sequence of more than one XSLT stylesheet to be applied simultaneously to a XML document, then the effect should be the same as applying a single stylesheet that imports each member of the sequence in order (see ).

A stylesheet contains a set of template rules. A template rule has two parts: a pattern which is matched against nodes in the source tree and a template which can be instantiated to form part of the result tree. This allows a stylesheet to be applicable to a wide class of documents that have similar source tree structures.

A template is instantiated for a particular source element to create part of the result tree. A template can contain elements that specify literal result element structure. A template can also contain elements from the XSLT namespace that are instructions for creating result tree fragments. When a template is instantiated, each instruction is executed and replaced by the result tree fragment that it creates. Instructions can select and process descendant source elements. Processing a descendant element creates a result tree fragment by finding the applicable template rule and instantiating its template. Note that elements are only processed when they have been selected by the execution of an instruction. The result tree is constructed by finding the template rule for the root node and instantiating its template.

In the process of finding the applicable template rule, more than one template rule may have a pattern that matches a given element. However, only one template rule will be applied. The method for deciding which template rule to apply is described in .

A single template by itself has considerable power: it can create structures of arbitrary complexity; it can pull string values out of arbitrary locations in the source tree; it can generate structures that are repeated according to the occurrence of elements in the source tree. For simple transformations where the structure of the result tree is independent of the structure of the source tree, a stylesheet can often consist of only a single template, which functions as a template for the complete result tree. Transformations on XML documents that represent data are often of this kind (see ). XSLT allows a simplified syntax for such stylesheets (see ).

When a template is instantiated, it is always instantiated with respect to a current node and a current node list. The current node is always a member of the current node list. Many operations in XSLT are relative to the current node. Only a few instructions change the current node list or the current node (see and ); during the instantiation of one of these instructions, the current node list changes to a new list of nodes and each member of this new list becomes the current node in turn; after the instantiation of the instruction is complete, the current node and current node list revert to what they were before the instruction was instantiated.

XSLT makes use of the expression language defined by for selecting elements for processing, for conditional processing and for generating text.

XSLT provides two hooks for extending the language, one hook for extending the set of instruction elements used in templates and one hook for extending the set of functions used in XPath expressions. These hooks are both based on XML namespaces. This version of XSLT does not define a mechanism for implementing the hooks. See .

The XSL WG intends to define such a mechanism in a future version of this specification or in a separate specification.

The element syntax summary notation used to describe the syntax of XSLT-defined elements is described in .

The MIME media types text/xml and application/xml should be used for XSLT stylesheets. It is possible that a media type will be registered specifically for XSLT stylesheets; if and when it is, that media type may also be used.

Stylesheet Structure XSLT Namespace

The XSLT namespace has the URI &XSLT.ns;.

The 1999 in the URI indicates the year in which the URI was allocated by the W3C. It does not indicate the version of XSLT being used, which is specified by attributes (see and ).

XSLT processors must use the XML namespaces mechanism to recognize elements and attributes from this namespace. Elements from the XSLT namespace are recognized only in the stylesheet not in the source document. The complete list of XSLT-defined elements is specified in . Vendors must not extend the XSLT namespace with additional elements or attributes. Instead, any extension must be in a separate namespace. Any namespace that is used for additional instruction elements must be identified by means of the extension element mechanism specified in .

This specification uses a prefix of xsl: for referring to elements in the XSLT namespace. However, XSLT stylesheets are free to use any prefix, provided that there is a namespace declaration that binds the prefix to the URI of the XSLT namespace.

An element from the XSLT namespace may have any attribute not from the XSLT namespace, provided that the expanded-name of the attribute has a non-null namespace URI. The presence of such attributes must not change the behavior of XSLT elements and functions defined in this document. Thus, an XSLT processor is always free to ignore such attributes, and must ignore such attributes without giving an error if it does not recognize the namespace URI. Such attributes can provide, for example, unique identifiers, optimization hints, or documentation.

It is an error for an element from the XSLT namespace to have attributes with expanded-names that have null namespace URIs (i.e. attributes with unprefixed names) other than attributes defined for the element in this document.

The conventions used for the names of XSLT elements, attributes and functions are that names are all lower-case, use hyphens to separate words, and use abbreviations only if they already appear in the syntax of a related language such as XML or HTML.

Stylesheet Element

A stylesheet is represented by an xsl:stylesheet element in an XML document. xsl:transform is allowed as a synonym for xsl:stylesheet.

An xsl:stylesheet element must have a version attribute, indicating the version of XSLT that the stylesheet requires. For this version of XSLT, the value should be 1.0. When the value is not equal to 1.0, forwards-compatible processing mode is enabled (see ).

The xsl:stylesheet element may contain the following types of elements:

xsl:import

xsl:include

xsl:strip-space

xsl:preserve-space

xsl:output

xsl:key

xsl:decimal-format

xsl:namespace-alias

xsl:attribute-set

xsl:variable

xsl:param

xsl:template

An element occurring as a child of an xsl:stylesheet element is called a top-level element.

This example shows the structure of a stylesheet. Ellipses (...) indicate where attribute values or content have been omitted. Although this example shows one of each type of allowed element, stylesheets may contain zero or more of each of these elements.

<xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;"> ... ... ... ... ... ]]>

The order in which the children of the xsl:stylesheet element occur is not significant except for xsl:import elements and for error recovery. Users are free to order the elements as they prefer, and stylesheet creation tools need not provide control over the order in which the elements occur.

In addition, the xsl:stylesheet element may contain any element not from the XSLT namespace, provided that the expanded-name of the element has a non-null namespace URI. The presence of such top-level elements must not change the behavior of XSLT elements and functions defined in this document; for example, it would not be permitted for such a top-level element to specify that xsl:apply-templates was to use different rules to resolve conflicts. Thus, an XSLT processor is always free to ignore such top-level elements, and must ignore a top-level element without giving an error if it does not recognize the namespace URI. Such elements can provide, for example,

information used by extension elements or extension functions (see ),

information about what to do with the result tree,

information about how to obtain the source tree,

metadata about the stylesheet,

structured documentation for the stylesheet.

Literal Result Element as Stylesheet

A simplified syntax is allowed for stylesheets that consist of only a single template for the root node. The stylesheet may consist of just a literal result element (see ). Such a stylesheet is equivalent to a stylesheet with an xsl:stylesheet element containing a template rule containing the literal result element; the template rule has a match pattern of /. For example

<html xsl:version="1.0" xmlns:xsl="&XSLT.ns;" xmlns="&XHTML.ns;"> Expense Report Summary

Total Amount:

]]>

has the same meaning as

<xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;" xmlns="&XHTML.ns;"> Expense Report Summary

Total Amount:

]]>

A literal result element that is the document element of a stylesheet must have an xsl:version attribute, which indicates the version of XSLT that the stylesheet requires. For this version of XSLT, the value should be 1.0; the value must be a Number. Other literal result elements may also have an xsl:version attribute. When the xsl:version attribute is not equal to 1.0, forwards-compatible processing mode is enabled (see ).

The allowed content of a literal result element when used as a stylesheet is no different from when it occurs within a stylesheet. Thus, a literal result element used as a stylesheet cannot contain top-level elements.

In some situations, the only way that a system can recognize that an XML document needs to be processed by an XSLT processor as an XSLT stylesheet is by examining the XML document itself. Using the simplified syntax makes this harder.

For example, another XML language (AXL) might also use an axl:version on the document element to indicate that an XML document was an AXL document that required processing by an AXL processor; if a document had both an axl:version attribute and an xsl:version attribute, it would be unclear whether the document should be processed by an XSLT processor or an AXL processor.

Therefore, the simplified syntax should not be used for XSLT stylesheets that may be used in such a situation. This situation can, for example, arise when an XSLT stylesheet is transmitted as a message with a MIME media type of text/xml or application/xml to a recipient that will use the MIME media type to determine how the message is processed.

Qualified Names

The name of an internal XSLT object, specifically a named template (see ), a mode (see ), an attribute set (see ), a key (see ), a decimal-format (see ), a variable or a parameter (see ) is specified as a QName. If it has a prefix, then the prefix is expanded into a URI reference using the namespace declarations in effect on the attribute in which the name occurs. The expanded-name consisting of the local part of the name and the possibly null URI reference is used as the name of the object. The default namespace is not used for unprefixed names.

Forwards-Compatible Processing

An element enables forwards-compatible mode for itself, its attributes, its descendants and their attributes if either it is an xsl:stylesheet element whose version attribute is not equal to 1.0, or it is a literal result element that has an xsl:version attribute whose value is not equal to 1.0, or it is a literal result element that does not have an xsl:version attribute and that is the document element of a stylesheet using the simplified syntax (see ). A literal result element that has an xsl:version attribute whose value is equal to 1.0 disables forwards-compatible mode for itself, its attributes, its descendants and their attributes.

If an element is processed in forwards-compatible mode, then:

if it is a top-level element and XSLT 1.0 does not allow such elements as top-level elements, then the element must be ignored along with its content;

if it is an element in a template and XSLT 1.0 does not allow such elements to occur in templates, then if the element is not instantiated, an error must not be signaled, and if the element is instantiated, the XSLT must perform fallback for the element as specified in ;

if the element has an attribute that XSLT 1.0 does not allow the element to have or if the element has an optional attribute with a value that the XSLT 1.0 does not allow the attribute to have, then the attribute must be ignored.

Thus, any XSLT 1.0 processor must be able to process the following stylesheet without error, although the stylesheet includes elements from the XSLT namespace that are not defined in this specification:

<xsl:stylesheet version="1.1" xmlns:xsl="&XSLT.ns;"> XSLT 1.1 required

Sorry, this stylesheet requires XSLT 1.1.

]]>

If a stylesheet depends crucially on a top-level element introduced by a version of XSL after 1.0, then the stylesheet can use an xsl:message element with terminate="yes" (see ) to ensure that XSLT processors implementing earlier versions of XSL will not silently ignore the top-level element. For example,

<xsl:stylesheet version="1.5" xmlns:xsl="&XSLT.ns;"> Sorry, this stylesheet requires XSLT 1.1. ... ... ]]>

If an expression occurs in an attribute that is processed in forwards-compatible mode, then an XSLT processor must recover from errors in the expression as follows:

if the expression does not match the syntax allowed by the XPath grammar, then an error must not be signaled unless the expression is actually evaluated;

if the expression calls a function with an unprefixed name that is not part of the XSLT library, then an error must not be signaled unless the function is actually called;

if the expression calls a function with a number of arguments that XSLT does not allow or with arguments of types that XSLT does not allow, then an error must not be signaled unless the function is actually called.

Combining Stylesheets

XSLT provides two mechanisms to combine stylesheets:

an inclusion mechanism that allows stylesheets to be combined without changing the semantics of the stylesheets being combined, and an import mechanism that allows stylesheets to override each other. Stylesheet Inclusion

An XSLT stylesheet may include another XSLT stylesheet using an xsl:include element. The xsl:include element has an href attribute whose value is a URI reference identifying the stylesheet to be included. A relative URI is resolved relative to the base URI of the xsl:include element (see ).

The xsl:include element is only allowed as a top-level element.

The inclusion works at the XML tree level. The resource located by the href attribute value is parsed as an XML document, and the children of the xsl:stylesheet element in this document replace the xsl:include element in the including document. The fact that template rules or definitions are included does not affect the way they are processed.

The included stylesheet may use the simplified syntax described in . The included stylesheet is treated the same as the equivalent xsl:stylesheet element.

It is an error if a stylesheet directly or indirectly includes itself.

Including a stylesheet multiple times can cause errors because of duplicate definitions. Such multiple inclusions are less obvious when they are indirect. For example, if stylesheet B includes stylesheet A, stylesheet C includes stylesheet A, and stylesheet D includes both stylesheet B and stylesheet C, then A will be included indirectly by D twice. If all of B, C and D are used as independent stylesheets, then the error can be avoided by separating everything in B other than the inclusion of A into a separate stylesheet B' and changing B to contain just inclusions of B' and A, similarly for C, and then changing D to include A, B', C'.

Stylesheet Import

An XSLT stylesheet may import another XSLT stylesheet using an xsl:import element. Importing a stylesheet is the same as including it (see ) except that definitions and template rules in the importing stylesheet take precedence over template rules and definitions in the imported stylesheet; this is described in more detail below. The xsl:import element has an href attribute whose value is a URI reference identifying the stylesheet to be imported. A relative URI is resolved relative to the base URI of the xsl:import element (see ).

The xsl:import element is only allowed as a top-level element. The xsl:import element children must precede all other element children of an xsl:stylesheet element, including any xsl:include element children. When xsl:include is used to include a stylesheet, any xsl:import elements in the included document are moved up in the including document to after any existing xsl:import elements in the including document.

For example,

<xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;"> italic ]]>

The xsl:stylesheet elements encountered during processing of a stylesheet that contains xsl:import elements are treated as forming an import tree. In the import tree, each xsl:stylesheet element has one import child for each xsl:import element that it contains. Any xsl:include elements are resolved before constructing the import tree. An xsl:stylesheet element in the import tree is defined to have lower import precedence than another xsl:stylesheet element in the import tree if it would be visited before that xsl:stylesheet element in a post-order traversal of the import tree (i.e. a traversal of the import tree in which an xsl:stylesheet element is visited after its import children). Each definition and template rule has import precedence determined by the xsl:stylesheet element that contains it.

For example, suppose

stylesheet A imports stylesheets B and C in that order;

stylesheet B imports stylesheet D;

stylesheet C imports stylesheet E.

Then the order of import precedence (lowest first) is D, B, E, C, A.

Since xsl:import elements are required to occur before any definitions or template rules, an implementation that processes imported stylesheets at the point at which it encounters the xsl:import element will encounter definitions and template rules in increasing order of import precedence.

In general, a definition or template rule with higher import precedence takes precedence over a definition or template rule with lower import precedence. This is defined in detail for each kind of definition and for template rules.

It is an error if a stylesheet directly or indirectly imports itself. Apart from this, the case where a stylesheet with a particular URI is imported in multiple places is not treated specially. The import tree will have a separate xsl:stylesheet for each place that it is imported.

If xsl:apply-imports is used (see ), the behavior may be different from the behavior if the stylesheet had been imported only at the place with the highest import precedence.

Embedding Stylesheets

Normally an XSLT stylesheet is a complete XML document with the xsl:stylesheet element as the document element. However, an XSLT stylesheet may also be embedded in another resource. Two forms of embedding are possible:

the XSLT stylesheet may be textually embedded in a non-XML resource, or the xsl:stylesheet element may occur in an XML document other than as the document element.

To facilitate the second form of embedding, the xsl:stylesheet element is allowed to have an ID attribute that specifies a unique identifier.

In order for such an attribute to be used with the XPath id function, it must actually be declared in the DTD as being an ID.

The following example shows how the xml-stylesheet processing instruction can be used to allow a document to contain its own stylesheet. The URI reference uses a relative URI with a fragment identifier to locate the xsl:stylesheet element:

xmlns:xsl="&XSLT.ns;" xmlns:fo="&XSLFO.ns;"> ... ]]>

A stylesheet that is embedded in the document to which it is to be applied or that may be included or imported into an stylesheet that is so embedded typically needs to contain a template rule that specifies that xsl:stylesheet elements are to be ignored.

Data Model

The data model used by XSLT is the same as that used by XPath with the additions described in this section. XSLT operates on source, result and stylesheet documents using the same data model. Any two XML documents that have the same tree will be treated the same by XSLT.

Processing instructions and comments in the stylesheet are ignored: the stylesheet is treated as if neither processing instruction nodes nor comment nodes were included in the tree that represents the stylesheet.

Root Node Children

The normal restrictions on the children of the root node are relaxed for the result tree. The result tree may have any sequence of nodes as children that would be possible for an element node. In particular, it may have text node children, and any number of element node children. When written out using the XML output method (see ), it is possible that a result tree will not be a well-formed XML document; however, it will always be a well-formed external general parsed entity.

When the source tree is created by parsing a well-formed XML document, the root node of the source tree will automatically satisfy the normal restrictions of having no text node children and exactly one element child. When the source tree is created in some other way, for example by using the DOM, the usual restrictions are relaxed for the source tree as for the result tree.

Base URI

Every node also has an associated URI called its base URI, which is used for resolving attribute values that represent relative URIs into absolute URIs. If an element or processing instruction occurs in an external entity, the base URI of that element or processing instruction is the URI of the external entity; otherwise, the base URI is the base URI of the document. The base URI of the document node is the URI of the document entity. The base URI for a text node, a comment node, an attribute node or a namespace node is the base URI of the parent of the node.

Unparsed Entities

The root node has a mapping that gives the URI for each unparsed entity declared in the document's DTD. The URI is generated from the system identifier and public identifier specified in the entity declaration. The XSLT processor may use the public identifier to generate a URI for the entity instead of the URI specified in the system identifier. If the XSLT processor does not use the public identifier to generate the URI, it must use the system identifier; if the system identifier is a relative URI, it must be resolved into an absolute URI using the URI of the resource containing the entity declaration as the base URI .

Whitespace Stripping

After the tree for a source document or stylesheet document has been constructed, but before it is otherwise processed by XSLT, some text nodes are stripped. A text node is never stripped unless it contains only whitespace characters. Stripping the text node removes the text node from the tree. The stripping process takes as input a set of element names for which whitespace must be preserved. The stripping process is applied to both stylesheets and source documents, but the set of whitespace-preserving element names is determined differently for stylesheets and for source documents.

A text node is preserved if any of the following apply:

The element name of the parent of the text node is in the set of whitespace-preserving element names.

The text node contains at least one non-whitespace character. As in XML, a whitespace character is #x20, #x9, #xD or #xA.

An ancestor element of the text node has an xml:space attribute with a value of preserve, and no closer ancestor element has xml:space with a value of default.

Otherwise, the text node is stripped.

The xml:space attributes are not stripped from the tree.

This implies that if an xml:space attribute is specified on a literal result element, it will be included in the result.

For stylesheets, the set of whitespace-preserving element names consists of just xsl:text.

For source documents, the set of whitespace-preserving element names is specified by xsl:strip-space and xsl:preserve-space top-level elements. These elements each have an elements attribute whose value is a whitespace-separated list of NameTests. Initially, the set of whitespace-preserving element names contains all element names. If an element name matches a NameTest in an xsl:strip-space element, then it is removed from the set of whitespace-preserving element names. If an element name matches a NameTest in an xsl:preserve-space element, then it is added to the set of whitespace-preserving element names. An element matches a NameTest if and only if the NameTest would be true for the element as an XPath node test. Conflicts between matches to xsl:strip-space and xsl:preserve-space elements are resolved the same way as conflicts between template rules (see ). Thus, the applicable match for a particular element name is determined as follows:

First, any match with lower import precedence than another match is ignored.

Next, any match with a NameTest that has a lower default priority than the default priority of the NameTest of another match is ignored.

It is an error if this leaves more than one match. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing, from amongst the matches that are left, the one that occurs last in the stylesheet.

Expressions

XSLT uses the expression language defined by XPath . Expressions are used in XSLT for a variety of purposes including:

selecting nodes for processing; specifying conditions for different ways of processing a node; generating text to be inserted in the result tree.

An expression must match the XPath production Expr.

Expressions occur as the value of certain attributes on XSLT-defined elements and within curly braces in attribute value templates.

In XSLT, an outermost expression (i.e. an expression that is not part of another expression) gets its context as follows:

the context node comes from the current node

the context position comes from the position of the current node in the current node list; the first position is 1

the context size comes from the size of the current node list

the variable bindings are the bindings in scope on the element which has the attribute in which the expression occurs (see )

the set of namespace declarations are those in scope on the element which has the attribute in which the expression occurs; this includes the implicit declaration of the prefix xml required by the the XML Namespaces Recommendation ; the default namespace (as declared by xmlns) is not part of this set

the function library consists of the core function library together with the additional functions defined in and extension functions as described in ; it is an error for an expression to include a call to any other function

Template Rules Processing Model

A list of source nodes is processed to create a result tree fragment. The result tree is constructed by processing a list containing just the root node. A list of source nodes is processed by appending the result tree structure created by processing each of the members of the list in order. A node is processed by finding all the template rules with patterns that match the node, and choosing the best amongst them; the chosen rule's template is then instantiated with the node as the current node and with the list of source nodes as the current node list. A template typically contains instructions that select an additional list of source nodes for processing. The process of matching, instantiation and selection is continued recursively until no new source nodes are selected for processing.

Implementations are free to process the source document in any way that produces the same result as if it were processed using this processing model.

Patterns

Template rules identify the nodes to which they apply by using a pattern. As well as being used in template rules, patterns are used for numbering (see ) and for declaring keys (see ). A pattern specifies a set of conditions on a node. A node that satisfies the conditions matches the pattern; a node that does not satisfy the conditions does not match the pattern. The syntax for patterns is a subset of the syntax for expressions. In particular, location paths that meet certain restrictions can be used as patterns. An expression that is also a pattern always evaluates to an object of type node-set. A node matches a pattern if the node is a member of the result of evaluating the pattern as an expression with respect to some possible context; the possible contexts are those whose context node is the node being matched or one of its ancestors.

Here are some examples of patterns:

para matches any para element

* matches any element

chapter|appendix matches any chapter element and any appendix element

olist/item matches any item element with an olist parent

appendix//para matches any para element with an appendix ancestor element

/ matches the root node

text() matches any text node

processing-instruction() matches any processing instruction

node() matches any node other than an attribute node and the root node

id("W11") matches the element with unique ID W11

para[1] matches any para element that is the first para child element of its parent

*[position()=1 and self::para] matches any para element that is the first child element of its parent

para[last()=1] matches any para element that is the only para child element of its parent

items/item[position()>1] matches any item element that has a items parent and that is not the first item child of its parent

item[position() mod 2 = 1] would be true for any item element that is an odd-numbered item child of its parent.

div[@class="appendix"]//p matches any p element with a div ancestor element that has a class attribute with value appendix

@class matches any class attribute (not any element that has a class attribute)

@* matches any attribute

A pattern must match the grammar for Pattern. A Pattern is a set of location path patterns separated by |. A location path pattern is a location path whose steps all use only the child or attribute axes. Although patterns must not use the descendant-or-self axis, patterns may use the // operator as well as the / operator. Location path patterns can also start with an id or key function call with a literal argument. Predicates in a pattern can use arbitrary expressions just like predicates in a location path.

Patterns Pattern LocationPathPattern | Pattern '|' LocationPathPattern LocationPathPattern '/' RelativePathPattern? | IdKeyPattern (('/' | '//') RelativePathPattern)? | '//'? RelativePathPattern IdKeyPattern 'id' '(' Literal ')' | 'key' '(' Literal ',' Literal ')' RelativePathPattern StepPattern | RelativePathPattern '/' StepPattern | RelativePathPattern '//' StepPattern StepPattern ChildOrAttributeAxisSpecifier NodeTest Predicate* ChildOrAttributeAxisSpecifier AbbreviatedAxisSpecifier | ('child' | 'attribute') '::'

A pattern is defined to match a node if and only if there is possible context such that when the pattern is evaluated as an expression with that context, the node is a member of the resulting node-set. When a node is being matched, the possible contexts have a context node that is the node being matched or any ancestor of that node, and a context node list containing just the context node.

For example, p matches any p element, because for any p if the expression p is evaluated with the parent of the p element as context the resulting node-set will contain that p element as one of its members.

This matches even a p element that is the document element, since the document root is the parent of the document element.

Although the semantics of patterns are specified indirectly in terms of expression evaluation, it is easy to understand the meaning of a pattern directly without thinking in terms of expression evaluation. In a pattern, | indicates alternatives; a pattern with one or more | separated alternatives matches if any one of the alternative matches. A pattern that consists of a sequence of StepPatterns separated by / or // is matched from right to left. The pattern only matches if the rightmost StepPattern matches and a suitable element matches the rest of the pattern; if the separator is / then only the parent is a suitable element; if the separator is //, then any ancestor is a suitable element. A StepPattern that uses the child axis matches if the NodeTest is true for the node and the node is not an attribute node. A StepPattern that uses the attribute axis matches if the NodeTest is true for the node and the node is an attribute node. When [] is present, then the first PredicateExpr in a StepPattern is evaluated with the node being matched as the context node and the siblings of the context node that match the NodeTest as the context node list, unless the node being matched is an attribute node, in which case the context node list is all the attributes that have the same parent as the attribute being matched and that match the NameTest.

For example

appendix//ulist/item[position()=1]

matches a node if and only if all of the following are true:

the NodeTest item is true for the node and the node is not an attribute; in other words the node is an item element

evaluating the PredicateExpr position()=1 with the node as context node and the siblings of the node that are item elements as the context node list yields true

the node has a parent that matches appendix//ulist; this will be true if the parent is a ulist element that has an appendix ancestor element.

Defining Template Rules

A template rule is specified with the xsl:template element. The match attribute is a Pattern that identifies the source node or nodes to which the rule applies. The match attribute is required unless the xsl:template element has a name attribute (see ). It is an error for the value of the match attribute to contain a VariableReference. The content of the xsl:template element is the template that is instantiated when the template rule is applied.

For example, an XML document might contain:

important point.]]>

The following template rule matches emph elements and produces a fo:inline-sequence formatting object with a font-weight property of bold.

]]>

Examples in this document use the fo: prefix for the namespace &XSLFO.ns;, which is the namespace of the formatting objects defined in .

As described next, the xsl:apply-templates element recursively processes the children of the source element.

Applying Template Rules

This example creates a block for a chapter element and then processes its immediate children.

]]>

In the absence of a select attribute, the xsl:apply-templates instruction processes all of the children of the current node, including text nodes. However, text nodes that have been stripped as specified in will not be processed. If stripping of whitespace nodes has not been enabled for an element, then all whitespace in the content of the element will be processed as text, and thus whitespace between child elements will count in determining the position of a child element as returned by the position function.

A select attribute can be used to process nodes selected by an expression instead of processing all children. The value of the select attribute is an expression. The expression must evaluate to a node-set. The selected set of nodes is processed in document order, unless a sorting specification is present (see ). The following example processes all of the author children of the author-group:

]]>

The following example processes all of the given-names of the authors that are children of author-group:

]]>

This example processes all of the heading descendant elements of the book element.

]]>

It is also possible to process elements that are not descendants of the current node. This example assumes that a department element has group children and employee descendants. It finds an employee's department and then processes the group children of the department.

Employee belongs to group ]]>

Multiple xsl:apply-templates elements can be used within a single template to do simple reordering. The following example creates two HTML tables. The first table is filled with domestic sales while the second table is filled with foreign sales.

" doc $doc createTextNode "a b" textnode $textnode disableOutputEscaping 1 $doc documentElement root $root firstChild td $td appendChild $textnode $root appendChild [$td cloneNode -deep] set result [$doc asXML -indent none] $doc delete set result } {a ba b
]]>

It is possible for there to be two matching descendants where one is a descendant of the other. This case is not treated specially: both descendants will be processed as usual. For example, given a source document

]]>

the rule

]]>

will process both the outer div and inner div elements.

Typically, xsl:apply-templates is used to process only nodes that are descendants of the current node. Such use of xsl:apply-templates cannot result in non-terminating processing loops. However, when xsl:apply-templates is used to process elements that are not descendants of the current node, the possibility arises of non-terminating loops. For example,

]]>

Implementations may be able to detect such loops in some cases, but the possibility exists that a stylesheet may enter a non-terminating loop that an implementation is unable to detect. This may present a denial of service security risk.

Conflict Resolution for Template Rules

It is possible for a source node to match more than one template rule. The template rule to be used is determined as follows:

First, all matching template rules that have lower import precedence than the matching template rule or rules with the highest import precedence are eliminated from consideration.

Next, all matching template rules that have lower priority than the matching template rule or rules with the highest priority are eliminated from consideration. The priority of a template rule is specified by the priority attribute on the template rule. The value of this must be a real number (positive or negative), matching the production Number with an optional leading minus sign (-). The default priority is computed as follows:

If the pattern contains multiple alternatives separated by |, then it is treated equivalently to a set of template rules, one for each alternative.

If the pattern has the form of a QName preceded by a ChildOrAttributeAxisSpecifier or has the form processing-instruction(Literal) preceded by a ChildOrAttributeAxisSpecifier, then the priority is 0.

If the pattern has the form NCName:* preceded by a ChildOrAttributeAxisSpecifier, then the priority is -0.25.

Otherwise, if the pattern consists of just a NodeTest preceded by a ChildOrAttributeAxisSpecifier, then the priority is -0.5.

Otherwise, the priority is 0.5.

Thus, the most common kind of pattern (a pattern that tests for a node with a particular type and a particular expanded-name) has priority 0. The next less specific kind of pattern (a pattern that tests for a node with a particular type and an expanded-name with a particular namespace URI) has priority -0.25. Patterns less specific than this (patterns that just tests for nodes with particular types) have priority -0.5. Patterns more specific than the most common kind of pattern have priority 0.5.

It is an error if this leaves more than one matching template rule. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing, from amongst the matching template rules that are left, the one that occurs last in the stylesheet.

Overriding Template Rules

A template rule that is being used to override a template rule in an imported stylesheet (see ) can use the xsl:apply-imports element to invoke the overridden template rule.

At any point in the processing of a stylesheet, there is a current template rule. Whenever a template rule is chosen by matching a pattern, the template rule becomes the current template rule for the instantiation of the rule's template. When an xsl:for-each element is instantiated, the current template rule becomes null for the instantiation of the content of the xsl:for-each element.

xsl:apply-imports processes the current node using only template rules that were imported into the stylesheet element containing the current template rule; the node is processed in the current template rule's mode. It is an error if xsl:apply-imports is instantiated when the current template rule is null.

For example, suppose the stylesheet doc.xsl contains a template rule for example elements:

]]>

Another stylesheet could import doc.xsl and modify the treatment of example elements as follows:

]]>

The combined effect would be to transform an example into an element of the form:

...
]]>
Modes

Modes allow an element to be processed multiple times, each time producing a different result.

Both xsl:template and xsl:apply-templates have an optional mode attribute. The value of the mode attribute is a QName, which is expanded as described in . If xsl:template does not have a match attribute, it must not have a mode attribute. If an xsl:apply-templates element has a mode attribute, then it applies only to those template rules from xsl:template elements that have a mode attribute with the same value; if an xsl:apply-templates element does not have a mode attribute, then it applies only to those template rules from xsl:template elements that do not have a mode attribute.

Built-in Template Rules

There is a built-in template rule to allow recursive processing to continue in the absence of a successful pattern match by an explicit template rule in the stylesheet. This template rule applies to both element nodes and the root node. The following shows the equivalent of the built-in template rule:

]]>

There is also a built-in template rule for each mode, which allows recursive processing to continue in the same mode in the absence of a successful pattern match by an explicit template rule in the stylesheet. This template rule applies to both element nodes and the root node. The following shows the equivalent of the built-in template rule for mode m.

<xsl:template match="*|/" mode="m"> <xsl:apply-templates mode="m"/> </xsl:template>

There is also a built-in template rule for text and attribute nodes that copies text through:

]]>

The built-in template rule for processing instructions and comments is to do nothing.

]]>

The built-in template rule for namespace nodes is also to do nothing. There is no pattern that can match a namespace node; so, the built-in template rule is the only template rule that is applied for namespace nodes.

The built-in template rules are treated as if they were imported implicitly before the stylesheet and so have lower import precedence than all other template rules. Thus, the author can override a built-in template rule by including an explicit template rule.

Named Templates

Templates can be invoked by name. An xsl:template element with a name attribute specifies a named template. The value of the name attribute is a QName, which is expanded as described in . If an xsl:template element has a name attribute, it may, but need not, also have a match attribute. An xsl:call-template element invokes a template by name; it has a required name attribute that identifies the template to be invoked. Unlike xsl:apply-templates, xsl:call-template does not change the current node or the current node list.

The match, mode and priority attributes on an xsl:template element do not affect whether the template is invoked by an xsl:call-template element. Similarly, the name attribute on an xsl:template element does not affect whether the template is invoked by an xsl:apply-templates element.

It is an error if a stylesheet contains more than one template with the same name and same import precedence.

Creating the Result Tree

This section describes instructions that directly create nodes in the result tree.

Creating Elements and Attributes Literal Result Elements

In a template, an element in the stylesheet that does not belong to the XSLT namespace and that is not an extension element (see ) is instantiated to create an element node with the same expanded-name. The content of the element is a template, which is instantiated to give the content of the created element node. The created element node will have the attribute nodes that were present on the element node in the stylesheet tree, other than attributes with names in the XSLT namespace.

The created element node will also have a copy of the namespace nodes that were present on the element node in the stylesheet tree with the exception of any namespace node whose string-value is the XSLT namespace URI (&XSLT.ns;), a namespace URI declared as an extension namespace (see ), or a namespace URI designated as an excluded namespace. A namespace URI is designated as an excluded namespace by using an exclude-result-prefixes attribute on an xsl:stylesheet element or an xsl:exclude-result-prefixes attribute on a literal result element. The value of both these attributes is a whitespace-separated list of namespace prefixes. The namespace bound to each of the prefixes is designated as an excluded namespace. It is an error if there is no namespace bound to the prefix on the element bearing the exclude-result-prefixes or xsl:exclude-result-prefixes attribute. The default namespace (as declared by xmlns) may be designated as an excluded namespace by including #default in the list of namespace prefixes. The designation of a namespace as an excluded namespace is effective within the subtree of the stylesheet rooted at the element bearing the exclude-result-prefixes or xsl:exclude-result-prefixes attribute; a subtree rooted at an xsl:stylesheet element does not include any stylesheets imported or included by children of that xsl:stylesheet element.

When a stylesheet uses a namespace declaration only for the purposes of addressing the source tree, specifying the prefix in the exclude-result-prefixes attribute will avoid superfluous namespace declarations in the result tree.

The value of an attribute of a literal result element is interpreted as an attribute value template: it can contain expressions contained in curly braces ({}).

A namespace URI in the stylesheet tree that is being used to specify a namespace URI in the result tree is called a literal namespace URI. This applies to:

the namespace URI in the expanded-name of a literal result element in the stylesheet

the namespace URI in the expanded-name of an attribute specified on a literal result element in the stylesheet

the string-value of a namespace node on a literal result element in the stylesheet

A stylesheet can use the xsl:namespace-alias element to declare that one namespace URI is an alias for another namespace URI. When a literal namespace URI has been declared to be an alias for another namespace URI, then the namespace URI in the result tree will be the namespace URI that the literal namespace URI is an alias for, instead of the literal namespace URI itself. The xsl:namespace-alias element declares that the namespace URI bound to the prefix specified by the stylesheet-prefix attribute is an alias for the namespace URI bound to the prefix specified by the result-prefix attribute. Thus, the stylesheet-prefix attribute specifies the namespace URI that will appear in the stylesheet, and the result-prefix attribute specifies the corresponding namespace URI that will appear in the result tree. The default namespace (as declared by xmlns) may be specified by using #default instead of a prefix. If a namespace URI is declared to be an alias for multiple different namespace URIs, then the declaration with the highest import precedence is used. It is an error if there is more than one such declaration. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing, from amongst the declarations with the highest import precedence, the one that occurs last in the stylesheet.

When literal result elements are being used to create element, attribute, or namespace nodes that use the XSLT namespace URI, the stylesheet must use an alias. For example, the stylesheet

<xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;" xmlns:fo="&XSLFO.ns;" xmlns:axsl="&XSLTA.ns;"> ]]>

will generate an XSLT stylesheet from a document of the form:

p h1 h2 h3 h4 ]]>

It may be necessary also to use aliases for namespaces other than the XSLT namespace URI. For example, literal result elements belonging to a namespace dealing with digital signatures might cause XSLT stylesheets to be mishandled by general-purpose security software; using an alias for the namespace would avoid the possibility of such mishandling.

Creating Elements with xsl:element

The xsl:element element allows an element to be created with a computed name. The expanded-name of the element to be created is specified by a required name attribute and an optional namespace attribute. The content of the xsl:element element is a template for the attributes and children of the created element.

The name attribute is interpreted as an attribute value template. It is an error if the string that results from instantiating the attribute value template is not a QName. An XSLT processor may signal the error; if it does not signal the error, then it must recover by making the the result of instantiating the xsl:element element be the sequence of nodes created by instantiating the content of the xsl:element element, excluding any initial attribute nodes. If the namespace attribute is not present then the QName is expanded into an expanded-name using the namespace declarations in effect for the xsl:element element, including any default namespace declaration.

If the namespace attribute is present, then it also is interpreted as an attribute value template. The string that results from instantiating the attribute value template should be a URI reference. It is not an error if the string is not a syntactically legal URI reference. If the string is empty, then the expanded-name of the element has a null namespace URI. Otherwise, the string is used as the namespace URI of the expanded-name of the element to be created. The local part of the QName specified by the name attribute is used as the local part of the expanded-name of the element to be created.

XSLT processors may make use of the prefix of the QName specified in the name attribute when selecting the prefix used for outputting the created element as XML; however, they are not required to do so.

Creating Attributes with xsl:attribute

The xsl:attribute element can be used to add attributes to result elements whether created by literal result elements in the stylesheet or by instructions such as xsl:element. The expanded-name of the attribute to be created is specified by a required name attribute and an optional namespace attribute. Instantiating an xsl:attribute element adds an attribute node to the containing result element node. The content of the xsl:attribute element is a template for the value of the created attribute.

The name attribute is interpreted as an attribute value template. It is an error if the string that results from instantiating the attribute value template is not a QName or is the string xmlns. An XSLT processor may signal the error; if it does not signal the error, it must recover by not adding the attribute to the result tree. If the namespace attribute is not present, then the QName is expanded into an expanded-name using the namespace declarations in effect for the xsl:attribute element, not including any default namespace declaration.

If the namespace attribute is present, then it also is interpreted as an attribute value template. The string that results from instantiating it should be a URI reference. It is not an error if the string is not a syntactically legal URI reference. If the string is empty, then the expanded-name of the attribute has a null namespace URI. Otherwise, the string is used as the namespace URI of the expanded-name of the attribute to be created. The local part of the QName specified by the name attribute is used as the local part of the expanded-name of the attribute to be created.

XSLT processors may make use of the prefix of the QName specified in the name attribute when selecting the prefix used for outputting the created attribute as XML; however, they are not required to do so and, if the prefix is xmlns, they must not do so. Thus, although it is not an error to do:

<xsl:attribute name="xmlns:xsl" namespace="whatever">&XSLT.ns;</xsl:attribute>

it will not result in a namespace declaration being output.

Adding an attribute to an element replaces any existing attribute of that element with the same expanded-name.

The following are all errors:

Adding an attribute to an element after children have been added to it; implementations may either signal the error or ignore the attribute.

Adding an attribute to a node that is not an element; implementations may either signal the error or ignore the attribute.

Creating nodes other than text nodes during the instantiation of the content of the xsl:attribute element; implementations may either signal the error or ignore the offending nodes.

When an xsl:attribute contains a text node with a newline, then the XML output must contain a character reference. For example,

x y]]>

will result in the output

(or with any equivalent character reference). The XML output cannot be

This is because XML 1.0 requires newline characters in attribute values to be normalized into spaces but requires character references to newline characters not to be normalized. The attribute values in the data model represent the attribute value after normalization. If a newline occurring in an attribute value in the tree were output as a newline character rather than as character reference, then the attribute value in the tree created by reparsing the XML would contain a space not a newline, which would mean that the tree had not been output correctly.

Named Attribute Sets

The xsl:attribute-set element defines a named set of attributes. The name attribute specifies the name of the attribute set. The value of the name attribute is a QName, which is expanded as described in . The content of the xsl:attribute-set element consists of zero or more xsl:attribute elements that specify the attributes in the set.

Attribute sets are used by specifying a use-attribute-sets attribute on xsl:element, xsl:copy (see ) or xsl:attribute-set elements. The value of the use-attribute-sets attribute is a whitespace-separated list of names of attribute sets. Each name is specified as a QName, which is expanded as described in . Specifying a use-attribute-sets attribute is equivalent to adding xsl:attribute elements for each of the attributes in each of the named attribute sets to the beginning of the content of the element with the use-attribute-sets attribute, in the same order in which the names of the attribute sets are specified in the use-attribute-sets attribute. It is an error if use of use-attribute-sets attributes on xsl:attribute-set elements causes an attribute set to directly or indirectly use itself.

Attribute sets can also be used by specifying an xsl:use-attribute-sets attribute on a literal result element. The value of the xsl:use-attribute-sets attribute is a whitespace-separated list of names of attribute sets. The xsl:use-attribute-sets attribute has the same effect as the use-attribute-sets attribute on xsl:element with the additional rule that attributes specified on the literal result element itself are treated as if they were specified by xsl:attribute elements before any actual xsl:attribute elements but after any xsl:attribute elements implied by the xsl:use-attribute-sets attribute. Thus, for a literal result element, attributes from attribute sets named in an xsl:use-attribute-sets attribute will be added first, in the order listed in the attribute; next, attributes specified on the literal result element will be added; finally, any attributes specified by xsl:attribute elements will be added. Since adding an attribute to an element replaces any existing attribute of that element with the same name, this means that attributes specified in attribute sets can be overridden by attributes specified on the literal result element itself.

The template within each xsl:attribute element in an xsl:attribute-set element is instantiated each time the attribute set is used; it is instantiated using the same current node and current node list as is used for instantiating the element bearing the use-attribute-sets or xsl:use-attribute-sets attribute. However, it is the position in the stylesheet of the xsl:attribute element rather than of the element bearing the use-attribute-sets or xsl:use-attribute-sets attribute that determines which variable bindings are visible (see ); thus, only variables and parameters declared by top-level xsl:variable and xsl:param elements are visible.

The following example creates a named attribute set title-style and uses it in a template rule.

12pt bold ]]>

Multiple definitions of an attribute set with the same expanded-name are merged. An attribute from a definition that has higher import precedence takes precedence over an attribute from a definition that has lower import precedence. It is an error if there are two attribute sets that have the same expanded-name and equal import precedence and that both contain the same attribute, unless there is a definition of the attribute set with higher import precedence that also contains the attribute. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing from amongst the definitions that specify the attribute that have the highest import precedence the one that was specified last in the stylesheet. Where the attributes in an attribute set were specified is relevant only in merging the attributes into the attribute set; it makes no difference when the attribute set is used.

Creating Text

A template can also contain text nodes. Each text node in a template remaining after whitespace has been stripped as specified in will create a text node with the same string-value in the result tree. Adjacent text nodes in the result tree are automatically merged.

Note that text is processed at the tree level. Thus, markup of &lt; in a template will be represented in the stylesheet tree by a text node that includes the character <. This will create a text node in the result tree that contains a < character, which will be represented by the markup &lt; (or an equivalent character reference) when the result tree is externalized as an XML document (unless output escaping is disabled as described in ).

Literal data characters may also be wrapped in an xsl:text element. This wrapping may change what whitespace characters are stripped (see ) but does not affect how the characters are handled by the XSLT processor thereafter.

The xml:lang and xml:space attributes are not treated specially by XSLT. In particular,

it is the responsibility of the stylesheet author explicitly to generate any xml:lang or xml:space attributes that are needed in the result;

specifying an xml:lang or xml:space attribute on an element in the XSLT namespace will not cause any xml:lang or xml:space attributes to appear in the result.

Creating Processing Instructions

The xsl:processing-instruction element is instantiated to create a processing instruction node. The content of the xsl:processing-instruction element is a template for the string-value of the processing instruction node. The xsl:processing-instruction element has a required name attribute that specifies the name of the processing instruction node. The value of the name attribute is interpreted as an attribute value template.

For example, this

href="book.css" type="text/css"]]>

would create the processing instruction

]]>

It is an error if the string that results from instantiating the name attribute is not both an NCName and a PITarget. An XSLT processor may signal the error; if it does not signal the error, it must recover by not adding the processing instruction to the result tree.

This means that xsl:processing-instruction cannot be used to output an XML declaration. The xsl:output element should be used instead (see ).

It is an error if instantiating the content of xsl:processing-instruction creates nodes other than text nodes. An XSLT processor may signal the error; if it does not signal the error, it must recover by ignoring the offending nodes together with their content.

It is an error if the result of instantiating the content of the xsl:processing-instruction contains the string ?>. An XSLT processor may signal the error; if it does not signal the error, it must recover by inserting a space after any occurrence of ? that is followed by a >.

Creating Comments

The xsl:comment element is instantiated to create a comment node in the result tree. The content of the xsl:comment element is a template for the string-value of the comment node.

For example, this

This file is automatically generated. Do not edit!]]>

would create the comment

]]>

It is an error if instantiating the content of xsl:comment creates nodes other than text nodes. An XSLT processor may signal the error; if it does not signal the error, it must recover by ignoring the offending nodes together with their content.

It is an error if the result of instantiating the content of the xsl:comment contains the string -- or ends with -. An XSLT processor may signal the error; if it does not signal the error, it must recover by inserting a space after any occurrence of - that is followed by another - or that ends the comment.

Copying

The xsl:copy element provides an easy way of copying the current node. Instantiating the xsl:copy element creates a copy of the current node. The namespace nodes of the current node are automatically copied as well, but the attributes and children of the node are not automatically copied. The content of the xsl:copy element is a template for the attributes and children of the created node; the content is instantiated only for nodes of types that can have attributes or children (i.e. root nodes and element nodes).

The xsl:copy element may have a use-attribute-sets attribute (see ). This is used only when copying element nodes.

The root node is treated specially because the root node of the result tree is created implicitly. When the current node is the root node, xsl:copy will not create a root node, but will just use the content template.

For example, the identity transformation can be written using xsl:copy as follows:

]]>

When the current node is an attribute, then if it would be an error to use xsl:attribute to create an attribute with the same name as the current node, then it is also an error to use xsl:copy (see ).

The following example shows how xml:lang attributes can be easily copied through from source to result. If a stylesheet defines the following named template:

]]>

then it can simply do

]]>

instead of

]]>

when it wants to copy the xml:lang attribute.

Computing Generated Text

Within a template, the xsl:value-of element can be used to compute generated text, for example by extracting text from the source tree or by inserting the value of a variable. The xsl:value-of element does this with an expression that is specified as the value of the select attribute. Expressions can also be used inside attribute values of literal result elements by enclosing the expression in curly braces ({}).

Generating Text with xsl:value-of

The xsl:value-of element is instantiated to create a text node in the result tree. The required select attribute is an expression; this expression is evaluated and the resulting object is converted to a string as if by a call to the string function. The string specifies the string-value of the created text node. If the string is empty, no text node will be created. The created text node will be merged with any adjacent text nodes.

The xsl:copy-of element can be used to copy a node-set over to the result tree without converting it to a string. See .

For example, the following creates an HTML paragraph from a person element with given-name and family-name attributes. The paragraph will contain the value of the given-name attribute of the current node followed by a space and the value of the family-name attribute of the current node.

]]>

For another example, the following creates an HTML paragraph from a person element with given-name and family-name children elements. The paragraph will contain the string-value of the first given-name child element of the current node followed by a space and the string-value of the first family-name child element of the current node.

]]>

The following precedes each procedure element with a paragraph containing the security level of the procedure. It assumes that the security level that applies to a procedure is determined by a security attribute on the procedure element or on an ancestor element of the procedure. It also assumes that if more than one such element has a security attribute then the security level is determined by the element that is closest to the procedure.

]]>
Attribute Value Templates

In an attribute value that is interpreted as an attribute value template, such as an attribute of a literal result element, an expression can be used by surrounding the expression with curly braces ({}). The attribute value template is instantiated by replacing the expression together with surrounding curly braces by the result of evaluating the expression and converting the resulting object to a string as if by a call to the string function. Curly braces are not recognized in an attribute value in an XSLT stylesheet unless the attribute is specifically stated to be one that is interpreted as an attribute value template; in an element syntax summary, the value of such attributes is surrounded by curly braces.

Not all attributes are interpreted as attribute value templates. Attributes whose value is an expression or pattern, attributes of top-level elements and attributes that refer to named XSLT objects are not interpreted as attribute value templates. In addition, xmlns attributes are not interpreted as attribute value templates; it would not be conformant with the XML Namespaces Recommendation to do this.

The following example creates an img result element from a photograph element in the source; the value of the src attribute of the img element is computed from the value of the image-dir variable and the string-value of the href child of the photograph element; the value of the width attribute of the img element is computed from the value of the width attribute of the size child of the photograph element:

/images ]]>

With this source

headquarters.jpg ]]>

the result would be

]]>

When an attribute value template is instantiated, a double left or right curly brace outside an expression will be replaced by a single curly brace. It is an error if a right curly brace occurs in an attribute value template outside an expression without being followed by a second right curly brace. A right curly brace inside a Literal in an expression is not recognized as terminating the expression.

Curly braces are not recognized recursively inside expressions. For example:

]]>

is not allowed. Instead, use simply:

]]>
Numbering

The xsl:number element is used to insert a formatted number into the result tree. The number to be inserted may be specified by an expression. The value attribute contains an expression. The expression is evaluated and the resulting object is converted to a number as if by a call to the number function. The number is rounded to an integer and then converted to a string using the attributes specified in ; in this context, the value of each of these attributes is interpreted as an attribute value template. After conversion, the resulting string is inserted in the result tree. For example, the following example numbers a sorted list:

]]>

If no value attribute is specified, then the xsl:number element inserts a number based on the position of the current node in the source tree. The following attributes control how the current node is to be numbered:

The level attribute specifies what levels of the source tree should be considered; it has the values single, multiple or any. The default is single.

The count attribute is a pattern that specifies what nodes should be counted at those levels. If count attribute is not specified, then it defaults to the pattern that matches any node with the same node type as the current node and, if the current node has an expanded-name, with the same expanded-name as the current node.

The from attribute is a pattern that specifies where counting starts.

In addition, the attributes specified in are used for number to string conversion, as in the case when the value attribute is specified.

The xsl:number element first constructs a list of positive integers using the level, count and from attributes:

When level="single", it goes up to the first node in the ancestor-or-self axis that matches the count pattern, and constructs a list of length one containing one plus the number of preceding siblings of that ancestor that match the count pattern. If there is no such ancestor, it constructs an empty list. If the from attribute is specified, then the only ancestors that are searched are those that are descendants of the nearest ancestor that matches the from pattern. Preceding siblings has the same meaning here as with the preceding-sibling axis.

When level="multiple", it constructs a list of all ancestors of the current node in document order followed by the element itself; it then selects from the list those nodes that match the count pattern; it then maps each node in the list to one plus the number of preceding siblings of that node that match the count pattern. If the from attribute is specified, then the only ancestors that are searched are those that are descendants of the nearest ancestor that matches the from pattern. Preceding siblings has the same meaning here as with the preceding-sibling axis.

When level="any", it constructs a list of length one containing the number of nodes that match the count pattern and belong to the set containing the current node and all nodes at any level of the document that are before the current node in document order, excluding any namespace and attribute nodes (in other words the union of the members of the preceding and ancestor-or-self axes). If the from attribute is specified, then only nodes after the first node before the current node that match the from pattern are considered.

The list of numbers is then converted into a string using the attributes specified in ; in this context, the value of each of these attributes is interpreted as an attribute value template. After conversion, the resulting string is inserted in the result tree.

The following would number the items in an ordered list:

. ]]>

The following two rules would number title elements. This is intended for a document that contains a sequence of chapters followed by a sequence of appendices, where both chapters and appendices contain sections, which in turn contain subsections. Chapters are numbered 1, 2, 3; appendices are numbered A, B, C; sections in chapters are numbered 1.1, 1.2, 1.3; sections in appendices are numbered A.1, A.2, A.3.

]]>

The following example numbers notes sequentially within a chapter:

]]>

The following example would number H4 elements in HTML with a three-part label:

. . ]]> Number to String Conversion Attributes

The following attributes are used to control conversion of a list of numbers into a string. The numbers are integers greater than 0. The attributes are all optional.

The main attribute is format. The default value for the format attribute is 1. The format attribute is split into a sequence of tokens where each token is a maximal sequence of alphanumeric characters or a maximal sequence of non-alphanumeric characters. Alphanumeric means any character that has a Unicode category of Nd, Nl, No, Lu, Ll, Lt, Lm or Lo. The alphanumeric tokens (format tokens) specify the format to be used for each number in the list. If the first token is a non-alphanumeric token, then the constructed string will start with that token; if the last token is non-alphanumeric token, then the constructed string will end with that token. Non-alphanumeric tokens that occur between two format tokens are separator tokens that are used to join numbers in the list. The nth format token will be used to format the nth number in the list. If there are more numbers than format tokens, then the last format token will be used to format remaining numbers. If there are no format tokens, then a format token of 1 is used to format all numbers. The format token specifies the string to be used to represent the number 1. Each number after the first will be separated from the preceding number by the separator token preceding the format token used to format that number, or, if there are no separator tokens, then by . (a period character).

Format tokens are a superset of the allowed values for the type attribute for the OL element in HTML 4.0 and are interpreted as follows:

Any token where the last character has a decimal digit value of 1 (as specified in the Unicode character property database), and the Unicode value of preceding characters is one less than the Unicode value of the last character generates a decimal representation of the number where each number is at least as long as the format token. Thus, a format token 1 generates the sequence 1 2 ... 10 11 12 ..., and a format token 01 generates the sequence 01 02 ... 09 10 11 12 ... 99 100 101.

A format token A generates the sequence A B C ... Z AA AB AC....

A format token a generates the sequence a b c ... z aa ab ac....

A format token i generates the sequence i ii iii iv v vi vii viii ix x ....

A format token I generates the sequence I II III IV V VI VII VIII IX X ....

Any other format token indicates a numbering sequence that starts with that token. If an implementation does not support a numbering sequence that starts with that token, it must use a format token of 1.

When numbering with an alphabetic sequence, the lang attribute specifies which language's alphabet is to be used; it has the same range of values as xml:lang ; if no lang value is specified, the language should be determined from the system environment. Implementers should document for which languages they support numbering.

Implementers should not make any assumptions about how numbering works in particular languages and should properly research the languages that they wish to support. The numbering conventions of many languages are very different from English.

The letter-value attribute disambiguates between numbering sequences that use letters. In many languages there are two commonly used numbering sequences that use letters. One numbering sequence assigns numeric values to letters in alphabetic sequence, and the other assigns numeric values to each letter in some other manner traditional in that language. In English, these would correspond to the numbering sequences specified by the format tokens a and i. In some languages, the first member of each sequence is the same, and so the format token alone would be ambiguous. A value of alphabetic specifies the alphabetic sequence; a value of traditional specifies the other sequence. If the letter-value attribute is not specified, then it is implementation-dependent how any ambiguity is resolved.

It is possible for two conforming XSLT processors not to convert a number to exactly the same string. Some XSLT processors may not support some languages. Furthermore, there may be variations possible in the way conversions are performed for any particular language that are not specifiable by the attributes on xsl:number. Future versions of XSLT may provide additional attributes to provide control over these variations. Implementations may also use implementation-specific namespaced attributes on xsl:number for this.

The grouping-separator attribute gives the separator used as a grouping (e.g. thousands) separator in decimal numbering sequences, and the optional grouping-size specifies the size (normally 3) of the grouping. For example, grouping-separator="," and grouping-size="3" would produce numbers of the form 1,000,000. If only one of the grouping-separator and grouping-size attributes is specified, then it is ignored.

Here are some examples of conversion specifications:

format="&#x30A2;" specifies Katakana numbering

format="&#x30A4;" specifies Katakana numbering in the iroha order

format="&#x0E51;" specifies numbering with Thai digits

format="&#x05D0;" letter-value="traditional" specifies traditional Hebrew numbering

format="&#x10D0;" letter-value="traditional" specifies Georgian numbering

format="&#x03B1;" letter-value="traditional" specifies classical Greek numbering

format="&#x0430;" letter-value="traditional" specifies Old Slavic numbering

Repetition

When the result has a known regular structure, it is useful to be able to specify directly the template for selected nodes. The xsl:for-each instruction contains a template, which is instantiated for each node selected by the expression specified by the select attribute. The select attribute is required. The expression must evaluate to a node-set. The template is instantiated with the selected node as the current node, and with a list of all of the selected nodes as the current node list. The nodes are processed in document order, unless a sorting specification is present (see ).

For example, given an XML document with this structure

... ... ... ... ... ... ]]>

the following would create an HTML document containing a table with a row for each customer element

Customers
]]>
Conditional Processing

There are two instructions in XSLT that support conditional processing in a template: xsl:if and xsl:choose. The xsl:if instruction provides simple if-then conditionality; the xsl:choose instruction supports selection of one choice when there are several possibilities.

Conditional Processing with xsl:if

The xsl:if element has a test attribute, which specifies an expression. The content is a template. The expression is evaluated and the resulting object is converted to a boolean as if by a call to the boolean function. If the result is true, then the content template is instantiated; otherwise, nothing is created. In the following example, the names in a group of names are formatted as a comma separated list:

, ]]>

The following colors every other table row yellow:

yellow ]]>
Conditional Processing with xsl:choose

The xsl:choose element selects one among a number of possible alternatives. It consists of a sequence of xsl:when elements followed by an optional xsl:otherwise element. Each xsl:when element has a single attribute, test, which specifies an expression. The content of the xsl:when and xsl:otherwise elements is a template. When an xsl:choose element is processed, each of the xsl:when elements is tested in turn, by evaluating the expression and converting the resulting object to a boolean as if by a call to the boolean function. The content of the first, and only the first, xsl:when element whose test is true is instantiated. If no xsl:when is true, the content of the xsl:otherwise element is instantiated. If no xsl:when element is true, and no xsl:otherwise element is present, nothing is created.

The following example enumerates items in an ordered list using arabic numerals, letters, or roman numerals depending on the depth to which the ordered lists are nested.

. ]]>
Sorting

Sorting is specified by adding xsl:sort elements as children of an xsl:apply-templates or xsl:for-each element. The first xsl:sort child specifies the primary sort key, the second xsl:sort child specifies the secondary sort key and so on. When an xsl:apply-templates or xsl:for-each element has one or more xsl:sort children, then instead of processing the selected nodes in document order, it sorts the nodes according to the specified sort keys and then processes them in sorted order. When used in xsl:for-each, xsl:sort elements must occur first. When a template is instantiated by xsl:apply-templates and xsl:for-each, the current node list list consists of the complete list of nodes being processed in sorted order.

xsl:sort has a select attribute whose value is an expression. For each node to be processed, the expression is evaluated with that node as the current node and with the complete list of nodes being processed in unsorted order as the current node list. The resulting object is converted to a string as if by a call to the string function; this string is used as the sort key for that node. The default value of the select attribute is ., which will cause the string-value of the current node to be used as the sort key.

This string serves as a sort key for the node. The following optional attributes on xsl:sort control how the list of sort keys are sorted; the values of all of these attributes are interpreted as attribute value templates.

order specifies whether the strings should be sorted in ascending or descending order; ascending specifies ascending order; descending specifies descending order; the default is ascending

lang specifies the language of the sort keys; it has the same range of values as xml:lang ; if no lang value is specified, the language should be determined from the system environment

data-type specifies the data type of the strings; the following values are allowed:

text specifies that the sort keys should be sorted lexicographically in the culturally correct manner for the language specified by lang

number specifies that the sort keys should be converted to numbers and then sorted according to the numeric value; the sort key is converted to a number as if by a call to the number function; the lang attribute is ignored

a QName with a prefix is expanded into an expanded-name as described in ; the expanded-name identifies the data-type; the behavior in this case is not specified by this document

The default value is text.

The XSL Working Group plans that future versions of XSLT will leverage XML Schemas to define further values for this attribute.

case-order has the value upper-first or lower-first; this applies when data-type="text", and specifies that upper-case letters should sort before lower-case letters or vice-versa respectively. For example, if lang="en", then A a B b are sorted with case-order="upper-first" and a A b B are sorted with case-order="lower-first". The default value is language dependent.

It is possible for two conforming XSLT processors not to sort exactly the same. Some XSLT processors may not support some languages. Furthermore, there may be variations possible in the sorting of any particular language that are not specified by the attributes on xsl:sort, for example, whether Hiragana or Katakana is sorted first in Japanese. Future versions of XSLT may provide additional attributes to provide control over these variations. Implementations may also use implementation-specific namespaced attributes on xsl:sort for this.

It is recommended that implementers consult for information on internationalized sorting.

The sort must be stable: in the sorted list of nodes, any sub list that has sort keys that all compare equal must be in document order.

For example, suppose an employee database has the form

James Clark ... ]]>

Then a list of employees sorted by name could be generated using:

  • ]]>
    Variables and Parameters

    A variable is a name that may be bound to a value. The value to which a variable is bound (the value of the variable) can be an object of any of the types that can be returned by expressions. There are two elements that can be used to bind variables: xsl:variable and xsl:param. The difference is that the value specified on the xsl:param variable is only a default value for the binding; when the template or stylesheet within which the xsl:param element occurs is invoked, parameters may be passed that are used in place of the default values.

    Both xsl:variable and xsl:param have a required name attribute, which specifies the name of the variable. The value of the name attribute is a QName, which is expanded as described in .

    For any use of these variable-binding elements, there is a region of the stylesheet tree within which the binding is visible; within this region, any binding of the variable that was visible on the variable-binding element itself is hidden. Thus, only the innermost binding of a variable is visible. The set of variable bindings in scope for an expression consists of those bindings that are visible at the point in the stylesheet where the expression occurs.

    Result Tree Fragments

    Variables introduce an additional data-type into the expression language. This additional data type is called result tree fragment. A variable may be bound to a result tree fragment instead of one of the four basic XPath data-types (string, number, boolean, node-set). A result tree fragment represents a fragment of the result tree. A result tree fragment is treated equivalently to a node-set that contains just a single root node. However, the operations permitted on a result tree fragment are a subset of those permitted on a node-set. An operation is permitted on a result tree fragment only if that operation would be permitted on a string (the operation on the string may involve first converting the string to a number or boolean). In particular, it is not permitted to use the /, //, and [] operators on result tree fragments. When a permitted operation is performed on a result tree fragment, it is performed exactly as it would be on the equivalent node-set.

    When a result tree fragment is copied into the result tree (see ), then all the nodes that are children of the root node in the equivalent node-set are added in sequence to the result tree.

    Expressions can only return values of type result tree fragment by referencing variables of type result tree fragment or calling extension functions that return a result tree fragment or getting a system property whose value is a result tree fragment.

    Values of Variables and Parameters

    A variable-binding element can specify the value of the variable in three alternative ways.

    If the variable-binding element has a select attribute, then the value of the attribute must be an expression and the value of the variable is the object that results from evaluating the expression. In this case, the content must be empty.

    If the variable-binding element does not have a select attribute and has non-empty content (i.e. the variable-binding element has one or more child nodes), then the content of the variable-binding element specifies the value. The content of the variable-binding element is a template, which is instantiated to give the value of the variable. The value is a result tree fragment equivalent to a node-set containing just a single root node having as children the sequence of nodes produced by instantiating the template. The base URI of the nodes in the result tree fragment is the base URI of the variable-binding element.

    It is an error if a member of the sequence of nodes created by instantiating the template is an attribute node or a namespace node, since a root node cannot have an attribute node or a namespace node as a child. An XSLT processor may signal the error; if it does not signal the error, it must recover by not adding the attribute node or namespace node.

    If the variable-binding element has empty content and does not have a select attribute, then the value of the variable is an empty string. Thus

    ]]>

    is equivalent to

    ]]>

    When a variable is used to select nodes by position, be careful not to do:

    2 ... ]]>

    This will output the value of the first item element, because the variable n will be bound to a result tree fragment, not a number. Instead, do either

    ... ]]>

    or

    2 ... ]]>

    One convenient way to specify the empty node-set as the default value of a parameter is:

    ]]>
    Using Values of Variables and Parameters with xsl:copy-of

    The xsl:copy-of element can be used to insert a result tree fragment into the result tree, without first converting it to a string as xsl:value-of does (see ). The required select attribute contains an expression. When the result of evaluating the expression is a result tree fragment, the complete fragment is copied into the result tree. When the result is a node-set, all the nodes in the set are copied in document order into the result tree; copying an element node copies the attribute nodes, namespace nodes and children of the element node as well as the element node itself; a root node is copied by copying its children. When the result is neither a node-set nor a result tree fragment, the result is converted to a string and then inserted into the result tree, as with xsl:value-of.

    Top-level Variables and Parameters

    Both xsl:variable and xsl:param are allowed as top-level elements. A top-level variable-binding element declares a global variable that is visible everywhere. A top-level xsl:param element declares a parameter to the stylesheet; XSLT does not define the mechanism by which parameters are passed to the stylesheet. It is an error if a stylesheet contains more than one binding of a top-level variable with the same name and same import precedence. At the top-level, the expression or template specifying the variable value is evaluated with the same context as that used to process the root node of the source document: the current node is the root node of the source document and the current node list is a list containing just the root node of the source document. If the template or expression specifying the value of a global variable x references a global variable y, then the value for y must be computed before the value of x. It is an error if it is impossible to do this for all global variable definitions; in other words, it is an error if the definitions are circular.

    This example declares a global variable para-font-size, which it references in an attribute value template.

    12pt ]]>
    Variables and Parameters within Templates

    As well as being allowed at the top-level, both xsl:variable and xsl:param are also allowed in templates. xsl:variable is allowed anywhere within a template that an instruction is allowed. In this case, the binding is visible for all following siblings and their descendants. Note that the binding is not visible for the xsl:variable element itself. xsl:param is allowed as a child at the beginning of an xsl:template element. In this context, the binding is visible for all following siblings and their descendants. Note that the binding is not visible for the xsl:param element itself.

    A binding shadows another binding if the binding occurs at a point where the other binding is visible, and the bindings have the same name. It is an error if a binding established by an xsl:variable or xsl:param element within a template shadows another binding established by an xsl:variable or xsl:param element also within the template. It is not an error if a binding established by an xsl:variable or xsl:param element in a template shadows another binding established by an xsl:variable or xsl:param top-level element. Thus, the following is an error:

    ]]>

    However, the following is allowed:

    ]]>

    The nearest equivalent in Java to an xsl:variable element in a template is a final local variable declaration with an initializer. For example,

    ]]>

    has similar semantics to

    final Object x = "value";

    XSLT does not provide an equivalent to the Java assignment operator

    x = "value";

    because this would make it harder to create an implementation that processes a document other than in a batch-like way, starting at the beginning and continuing through to the end.

    Passing Parameters to Templates

    Parameters are passed to templates using the xsl:with-param element. The required name attribute specifies the name of the parameter (the variable the value of whose binding is to be replaced). The value of the name attribute is a QName, which is expanded as described in . xsl:with-param is allowed within both xsl:call-template and xsl:apply-templates. The value of the parameter is specified in the same way as for xsl:variable and xsl:param. The current node and current node list used for computing the value specified by xsl:with-param element is the same as that used for the xsl:apply-templates or xsl:call-template element within which it occurs. It is not an error to pass a parameter x to a template that does not have an xsl:param element for x; the parameter is simply ignored.

    This example defines a named template for a numbered-block with an argument to control the format of the number.

    1. a. ]]>
    Additional Functions

    This section describes XSLT-specific additions to the core XPath function library. Some of these additional functions also make use of information specified by top-level elements in the stylesheet; this section also describes these elements.

    Multiple Source Documents

    The document function allows access to XML documents other than the main source document.

    When the document function has exactly one argument and the argument is a node-set, then the result is the union, for each node in the argument node-set, of the result of calling the document function with the first argument being the string-value of the node, and the second argument being a node-set with the node as its only member. When the document function has two arguments and the first argument is a node-set, then the result is the union, for each node in the argument node-set, of the result of calling the document function with the first argument being the string-value of the node, and with the second argument being the second argument passed to the document function.

    When the first argument to the document function is not a node-set, the first argument is converted to a string as if by a call to the string function. This string is treated as a URI reference; the resource identified by the URI is retrieved. The data resulting from the retrieval action is parsed as an XML document and a tree is constructed in accordance with the data model (see ). If there is an error retrieving the resource, then the XSLT processor may signal an error; if it does not signal an error, it must recover by returning an empty node-set. One possible kind of retrieval error is that the XSLT processor does not support the URI scheme used by the URI. An XSLT processor is not required to support any particular URI schemes. The documentation for an XSLT processor should specify which URI schemes the XSLT processor supports.

    If the URI reference does not contain a fragment identifier, then a node-set containing just the root node of the document is returned. If the URI reference does contain a fragment identifier, the function returns a node-set containing the nodes in the tree identified by the fragment identifier of the URI reference. The semantics of the fragment identifier is dependent on the media type of the result of retrieving the URI. If there is an error in processing the fragment identifier, the XSLT processor may signal the error; if it does not signal the error, it must recover by returning an empty node-set. Possible errors include:

    The fragment identifier identifies something that cannot be represented by an XSLT node-set (such as a range of characters within a text node).

    The XSLT processor does not support fragment identifiers for the media-type of the retrieval result. An XSLT processor is not required to support any particular media types. The documentation for an XSLT processor should specify for which media types the XSLT processor supports fragment identifiers.

    The data resulting from the retrieval action is parsed as an XML document regardless of the media type of the retrieval result; if the top-level media type is text, then it is parsed in the same way as if the media type were text/xml; otherwise, it is parsed in the same way as if the media type were application/xml.

    Since there is no top-level xml media type, data with a media type other than text/xml or application/xml may in fact be XML.

    The URI reference may be relative. The base URI (see ) of the node in the second argument node-set that is first in document order is used as the base URI for resolving the relative URI into an absolute URI. If the second argument is omitted, then it defaults to the node in the stylesheet that contains the expression that includes the call to the document function. Note that a zero-length URI reference is a reference to the document relative to which the URI reference is being resolved; thus document("") refers to the root node of the stylesheet; the tree representation of the stylesheet is exactly the same as if the XML document containing the stylesheet was the initial source document.

    Two documents are treated as the same document if they are identified by the same URI. The URI used for the comparison is the absolute URI into which any relative URI was resolved and does not include any fragment identifier. One root node is treated as the same node as another root node if the two nodes are from the same document. Thus, the following expression will always be true:

    generate-id(document("foo.xml"))=generate-id(document("foo.xml"))

    The document function gives rise to the possibility that a node-set may contain nodes from more than one document. With such a node-set, the relative document order of two nodes in the same document is the normal document order defined by XPath . The relative document order of two nodes in different documents is determined by an implementation-dependent ordering of the documents containing the two nodes. There are no constraints on how the implementation orders documents other than that it must do so consistently: an implementation must always use the same order for the same set of documents.

    Keys

    Keys provide a way to work with documents that contain an implicit cross-reference structure. The ID, IDREF and IDREFS attribute types in XML provide a mechanism to allow XML documents to make their cross-reference explicit. XSLT supports this through the XPath id function. However, this mechanism has a number of limitations:

    ID attributes must be declared as such in the DTD. If an ID attribute is declared as an ID attribute only in the external DTD subset, then it will be recognized as an ID attribute only if the XML processor reads the external DTD subset. However, XML does not require XML processors to read the external DTD, and they may well choose not to do so, especially if the document is declared standalone="yes".

    A document can contain only a single set of unique IDs. There cannot be separate independent sets of unique IDs.

    The ID of an element can only be specified in an attribute; it cannot be specified by the content of the element, or by a child element.

    An ID is constrained to be an XML name. For example, it cannot contain spaces.

    An element can have at most one ID.

    At most one element can have a particular ID.

    Because of these limitations XML documents sometimes contain a cross-reference structure that is not explicitly declared by ID/IDREF/IDREFS attributes.

    A key is a triple containing:

    the node which has the key

    the name of the key (an expanded-name)

    the value of the key (a string)

    A stylesheet declares a set of keys for each document using the xsl:key element. When this set of keys contains a member with node x, name y and value z, we say that node x has a key with name y and value z.

    Thus, a key is a kind of generalized ID, which is not subject to the same limitations as an XML ID:

    Keys are declared in the stylesheet using xsl:key elements.

    A key has a name as well as a value; each key name may be thought of as distinguishing a separate, independent space of identifiers.

    The value of a named key for an element may be specified in any convenient place; for example, in an attribute, in a child element or in content. An XPath expression is used to specify where to find the value for a particular named key.

    The value of a key can be an arbitrary string; it is not constrained to be a name.

    There can be multiple keys in a document with the same node, same key name, but different key values.

    There can be multiple keys in a document with the same key name, same key value, but different nodes.

    The xsl:key element is used to declare keys. The name attribute specifies the name of the key. The value of the name attribute is a QName, which is expanded as described in . The match attribute is a Pattern; an xsl:key element gives information about the keys of any node that matches the pattern specified in the match attribute. The use attribute is an expression specifying the values of the key; the expression is evaluated once for each node that matches the pattern. If the result is a node-set, then for each node in the node-set, the node that matches the pattern has a key of the specified name whose value is the string-value of the node in the node-set; otherwise, the result is converted to a string, and the node that matches the pattern has a key of the specified name with value equal to that string. Thus, a node x has a key with name y and value z if and only if there is an xsl:key element such that:

    x matches the pattern specified in the match attribute of the xsl:key element;

    the value of the name attribute of the xsl:key element is equal to y; and

    when the expression specified in the use attribute of the xsl:key element is evaluated with x as the current node and with a node list containing just x as the current node list resulting in an object u, then either z is equal to the result of converting u to a string as if by a call to the string function, or u is a node-set and z is equal to the string-value of one or more of the nodes in u.

    Note also that there may be more than one xsl:key element that matches a given node; all of the matching xsl:key elements are used, even if they do not have the same import precedence.

    It is an error for the value of either the use attribute or the match attribute to contain a VariableReference.

    The key function does for keys what the id function does for IDs. The first argument specifies the name of the key. The value of the argument must be a QName, which is expanded as described in . When the second argument to the key function is of type node-set, then the result is the union of the result of applying the key function to the string value of each of the nodes in the argument node-set. When the second argument to key is of any other type, the argument is converted to a string as if by a call to the string function; it returns a node-set containing the nodes in the same document as the context node that have a value for the named key equal to this string.

    For example, given a declaration

    ]]>

    an expression key("idkey",@ref) will return the same node-set as id(@ref), assuming that the only ID attribute declared in the XML source document is:

    ]]>

    and that the ref attribute of the current node contains no whitespace.

    Suppose a document describing a function library uses a prototype element to define functions

    ]]>

    and a function element to refer to function names

    key]]>

    Then the stylesheet could generate hyperlinks between the references and definitions as follows:

    Function: ...

    ]]>

    The key can be used to retrieve a key from a document other than the document containing the context node. For example, suppose a document contains bibliographic references in the form XSLT]]>, and there is a separate XML document bib.xml containing a bibliographic database with entries in the form:

    ...]]>

    Then the stylesheet could use the following to transform the bibref elements:

    ]]>
    Number Formatting

    The format-number function converts its first argument to a string using the format pattern string specified by the second argument and the decimal-format named by the third argument, or the default decimal-format, if there is no third argument. The format pattern string is in the syntax specified by the JDK 1.1 DecimalFormat class. The format pattern string is in a localized notation: the decimal-format determines what characters have a special meaning in the pattern (with the exception of the quote character, which is not localized). The format pattern must not contain the currency sign (#x00A4); support for this feature was added after the initial release of JDK 1.1. The decimal-format name must be a QName, which is expanded as described in . It is an error if the stylesheet does not contain a declaration of the decimal-format with the specified expanded-name.

    Implementations are not required to use the JDK 1.1 implementation, nor are implementations required to be implemented in Java.

    Stylesheets can use other facilities in XPath to control rounding.

    The xsl:decimal-format element declares a decimal-format, which controls the interpretation of a format pattern used by the format-number function. If there is a name attribute, then the element declares a named decimal-format; otherwise, it declares the default decimal-format. The value of the name attribute is a QName, which is expanded as described in . It is an error to declare either the default decimal-format or a decimal-format with a given name more than once (even with different import precedence), unless it is declared every time with the same value for all attributes (taking into account any default values).

    The other attributes on xsl:decimal-format correspond to the methods on the JDK 1.1 DecimalFormatSymbols class. For each get/set method pair there is an attribute defined for the xsl:decimal-format element.

    The following attributes both control the interpretation of characters in the format pattern and specify characters that may appear in the result of formatting the number:

    decimal-separator specifies the character used for the decimal sign; the default value is the period character (.)

    grouping-separator specifies the character used as a grouping (e.g. thousands) separator; the default value is the comma character (,)

    percent specifies the character used as a percent sign; the default value is the percent character (%)

    per-mille specifies the character used as a per mille sign; the default value is the Unicode per-mille character (#x2030)

    zero-digit specifies the character used as the digit zero; the default value is the digit zero (0)

    The following attributes control the interpretation of characters in the format pattern:

    digit specifies the character used for a digit in the format pattern; the default value is the number sign character (#)

    pattern-separator specifies the character used to separate positive and negative sub patterns in a pattern; the default value is the semi-colon character (;)

    The following attributes specify characters or strings that may appear in the result of formatting the number:

    infinity specifies the string used to represent infinity; the default value is the string Infinity

    NaN specifies the string used to represent the NaN value; the default value is the string NaN

    minus-sign specifies the character used as the default minus sign; the default value is the hyphen-minus character (-, #x2D)

    Miscellaneous Additional Functions

    The current function returns a node-set that has the current node as its only member. For an outermost expression (an expression not occurring within another expression), the current node is always the same as the context node. Thus,

    ]]>

    means the same as

    ]]>

    However, within square brackets the current node is usually different from the context node. For example,

    ]]>

    will process all item elements that have a glossary parent element and that have a name attribute with value equal to the value of the current node's ref attribute. This is different from

    ]]>

    which means the same as

    ]]>

    and so would process all item elements that have a glossary parent element and that have a name attribute and a ref attribute with the same value.

    It is an error to use the current function in a pattern.

    The unparsed-entity-uri returns the URI of the unparsed entity with the specified name in the same document as the context node (see ). It returns the empty string if there is no such entity.

    The generate-id function returns a string that uniquely identifies the node in the argument node-set that is first in document order. The unique identifier must consist of ASCII alphanumeric characters and must start with an alphabetic character. Thus, the string is syntactically an XML name. An implementation is free to generate an identifier in any convenient way provided that it always generates the same identifier for the same node and that different identifiers are always generated from different nodes. An implementation is under no obligation to generate the same identifiers each time a document is transformed. There is no guarantee that a generated unique identifier will be distinct from any unique IDs specified in the source document. If the argument node-set is empty, the empty string is returned. If the argument is omitted, it defaults to the context node.

    The argument must evaluate to a string that is a QName. The QName is expanded into a name using the namespace declarations in scope for the expression. The system-property function returns an object representing the value of the system property identified by the name. If there is no such system property, the empty string should be returned.

    Implementations must provide the following system properties, which are all in the XSLT namespace:

    xsl:version, a number giving the version of XSLT implemented by the processor; for XSLT processors implementing the version of XSLT specified by this document, this is the number 1.0 xsl:vendor, a string identifying the vendor of the XSLT processor xsl:vendor-url, a string containing a URL identifying the vendor of the XSLT processor; typically this is the host page (home page) of the vendor's Web site.
    Messages

    The xsl:message instruction sends a message in a way that is dependent on the XSLT processor. The content of the xsl:message instruction is a template. The xsl:message is instantiated by instantiating the content to create an XML fragment. This XML fragment is the content of the message.

    An XSLT processor might implement xsl:message by popping up an alert box or by writing to a log file.

    If the terminate attribute has the value yes, then the XSLT processor should terminate processing after sending the message. The default value is no.

    One convenient way to do localization is to put the localized information (message text, etc.) in an XML document, which becomes an additional input file to the stylesheet. For example, suppose messages for a language L are stored in an XML file resources/L.xml in the form:

    A problem was detected. An error was detected. ]]>

    Then a stylesheet could use the following approach to localize messages:

    problem ]]>
    Extensions

    XSLT allows two kinds of extension, extension elements and extension functions.

    This version of XSLT does not provide a mechanism for defining implementations of extensions. Therefore, an XSLT stylesheet that must be portable between XSLT implementations cannot rely on particular extensions being available. XSLT provides mechanisms that allow an XSLT stylesheet to determine whether the XSLT processor by which it is being processed has implementations of particular extensions available, and to specify what should happen if those extensions are not available. If an XSLT stylesheet is careful to make use of these mechanisms, it is possible for it to take advantage of extensions and still work with any XSLT implementation.

    Extension Elements

    The element extension mechanism allows namespaces to be designated as extension namespaces. When a namespace is designated as an extension namespace and an element with a name from that namespace occurs in a template, then the element is treated as an instruction rather than as a literal result element. The namespace determines the semantics of the instruction.

    Since an element that is a child of an xsl:stylesheet element is not occurring in a template, non-XSLT top-level elements are not extension elements as defined here, and nothing in this section applies to them.

    A namespace is designated as an extension namespace by using an extension-element-prefixes attribute on an xsl:stylesheet element or an xsl:extension-element-prefixes attribute on a literal result element or extension element. The value of both these attributes is a whitespace-separated list of namespace prefixes. The namespace bound to each of the prefixes is designated as an extension namespace. It is an error if there is no namespace bound to the prefix on the element bearing the extension-element-prefixes or xsl:extension-element-prefixes attribute. The default namespace (as declared by xmlns) may be designated as an extension namespace by including #default in the list of namespace prefixes. The designation of a namespace as an extension namespace is effective within the subtree of the stylesheet rooted at the element bearing the extension-element-prefixes or xsl:extension-element-prefixes attribute; a subtree rooted at an xsl:stylesheet element does not include any stylesheets imported or included by children of that xsl:stylesheet element.

    If the XSLT processor does not have an implementation of a particular extension element available, then the element-available function must return false for the name of the element. When such an extension element is instantiated, then the XSLT processor must perform fallback for the element as specified in . An XSLT processor must not signal an error merely because a template contains an extension element for which no implementation is available.

    If the XSLT processor has an implementation of a particular extension element available, then the element-available function must return true for the name of the element.

    Extension Functions

    If a FunctionName in a FunctionCall expression is not an NCName (i.e. if it contains a colon), then it is treated as a call to an extension function. The FunctionName is expanded to a name using the namespace declarations from the evaluation context.

    If the XSLT processor does not have an implementation of an extension function of a particular name available, then the function-available function must return false for that name. If such an extension function occurs in an expression and the extension function is actually called, the XSLT processor must signal an error. An XSLT processor must not signal an error merely because an expression contains an extension function for which no implementation is available.

    If the XSLT processor has an implementation of an extension function of a particular name available, then the function-available function must return true for that name. If such an extension is called, then the XSLT processor must call the implementation passing it the function call arguments; the result returned by the implementation is returned as the result of the function call.

    Fallback

    Normally, instantiating an xsl:fallback element does nothing. However, when an XSLT processor performs fallback for an instruction element, if the instruction element has one or more xsl:fallback children, then the content of each of the xsl:fallback children must be instantiated in sequence; otherwise, an error must be signaled. The content of an xsl:fallback element is a template.

    The following functions can be used with the xsl:choose and xsl:if instructions to explicitly control how a stylesheet should behave if particular elements or functions are not available.

    The argument must evaluate to a string that is a QName. The QName is expanded into an expanded-name using the namespace declarations in scope for the expression. The element-available function returns true if and only if the expanded-name is the name of an instruction. If the expanded-name has a namespace URI equal to the XSLT namespace URI, then it refers to an element defined by XSLT. Otherwise, it refers to an extension element. If the expanded-name has a null namespace URI, the element-available function will return false.

    The argument must evaluate to a string that is a QName. The QName is expanded into an expanded-name using the namespace declarations in scope for the expression. The function-available function returns true if and only if the expanded-name is the name of a function in the function library. If the expanded-name has a non-null namespace URI, then it refers to an extension function; otherwise, it refers to a function defined by XPath or XSLT.

    Output

    An XSLT processor may output the result tree as a sequence of bytes, although it is not required to be able to do so (see ). The xsl:output element allows stylesheet authors to specify how they wish the result tree to be output. If an XSLT processor outputs the result tree, it should do so as specified by the xsl:output element; however, it is not required to do so.

    The xsl:output element is only allowed as a top-level element.

    The method attribute on xsl:output identifies the overall method that should be used for outputting the result tree. The value must be a QName. If the QName does not have a prefix, then it identifies a method specified in this document and must be one of xml, html or text. If the QName has a prefix, then the QName is expanded into an expanded-name as described in ; the expanded-name identifies the output method; the behavior in this case is not specified by this document.

    The default for the method attribute is chosen as follows. If

    the root node of the result tree has an element child,

    the expanded-name of the first element child of the root node (i.e. the document element) of the result tree has local part html (in any combination of upper and lower case) and a null namespace URI, and

    any text nodes preceding the first element child of the root node of the result tree contain only whitespace characters,

    then the default output method is html; otherwise, the default output method is xml. The default output method should be used if there are no xsl:output elements or if none of the xsl:output elements specifies a value for the method attribute.

    The other attributes on xsl:output provide parameters for the output method. The following attributes are allowed:

    version specifies the version of the output method

    indent specifies whether the XSLT processor may add additional whitespace when outputting the result tree; the value must be yes or no

    encoding specifies the preferred character encoding that the XSLT processor should use to encode sequences of characters as sequences of bytes; the value of the attribute should be treated case-insensitively; the value must contain only characters in the range #x21 to #x7E (i.e. printable ASCII characters); the value should either be a charset registered with the Internet Assigned Numbers Authority , or start with X-

    media-type specifies the media type (MIME content type) of the data that results from outputting the result tree; the charset parameter should not be specified explicitly; instead, when the top-level media type is text, a charset parameter should be added according to the character encoding actually used by the output method

    doctype-system specifies the system identifier to be used in the document type declaration

    doctype-public specifies the public identifier to be used in the document type declaration

    omit-xml-declaration specifies whether the XSLT processor should output an XML declaration; the value must be yes or no

    standalone specifies whether the XSLT processor should output a standalone document declaration; the value must be yes or no

    cdata-section-elements specifies a list of the names of elements whose text node children should be output using CDATA sections

    The detailed semantics of each attribute will be described separately for each output method for which it is applicable. If the semantics of an attribute are not described for an output method, then it is not applicable to that output method.

    A stylesheet may contain multiple xsl:output elements and may include or import stylesheets that also contain xsl:output elements. All the xsl:output elements occurring in a stylesheet are merged into a single effective xsl:output element. For the cdata-section-elements attribute, the effective value is the union of the specified values. For other attributes, the effective value is the specified value with the highest import precedence. It is an error if there is more than one such value for an attribute. An XSLT processor may signal the error; if it does not signal the error, if should recover by using the value that occurs last in the stylesheet. The values of attributes are defaulted after the xsl:output elements have been merged; different output methods may have different default values for an attribute.

    XML Output Method

    The xml output method outputs the result tree as a well-formed XML external general parsed entity. If the root node of the result tree has a single element node child and no text node children, then the entity should also be a well-formed XML document entity. When the entity is referenced within a trivial XML document wrapper like this

    entity-URI ]> &e;]]>

    where entity-URI is a URI for the entity, then the wrapper document as a whole should be a well-formed XML document conforming to the XML Namespaces Recommendation . In addition, the output should be such that if a new tree was constructed by parsing the wrapper as an XML document as specified in , and then removing the document element, making its children instead be children of the root node, then the new tree would be the same as the result tree, with the following possible exceptions:

    The order of attributes in the two trees may be different.

    The new tree may contain namespace nodes that were not present in the result tree.

    An XSLT processor may need to add namespace declarations in the course of outputting the result tree as XML.

    If the XSLT processor generated a document type declaration because of the doctype-system attribute, then the above requirements apply to the entity with the generated document type declaration removed.

    The version attribute specifies the version of XML to be used for outputting the result tree. If the XSLT processor does not support this version of XML, it should use a version of XML that it does support. The version output in the XML declaration (if an XML declaration is output) should correspond to the version of XML that the processor used for outputting the result tree. The value of the version attribute should match the VersionNum production of the XML Recommendation . The default value is 1.0.

    The encoding attribute specifies the preferred encoding to use for outputting the result tree. XSLT processors are required to respect values of UTF-8 and UTF-16. For other values, if the XSLT processor does not support the specified encoding it may signal an error; if it does not signal an error it should use UTF-8 or UTF-16 instead. The XSLT processor must not use an encoding whose name does not match the EncName production of the XML Recommendation . If no encoding attribute is specified, then the XSLT processor should use either UTF-8 or UTF-16. It is possible that the result tree will contain a character that cannot be represented in the encoding that the XSLT processor is using for output. In this case, if the character occurs in a context where XML recognizes character references (i.e. in the value of an attribute node or text node), then the character should be output as a character reference; otherwise (for example if the character occurs in the name of an element) the XSLT processor should signal an error.

    If the indent attribute has the value yes, then the xml output method may output whitespace in addition to the whitespace in the result tree (possibly based on whitespace stripped from either the source document or the stylesheet) in order to indent the result nicely; if the indent attribute has the value no, it should not output any additional whitespace. The default value is no. The xml output method should use an algorithm to output additional whitespace that ensures that the result if whitespace were to be stripped from the output using the process described in with the set of whitespace-preserving elements consisting of just xsl:text would be the same when additional whitespace is output as when additional whitespace is not output.

    It is usually not safe to use indent="yes" with document types that include element types with mixed content.

    The cdata-section-elements attribute contains a whitespace-separated list of QNames. Each QName is expanded into an expanded-name using the namespace declarations in effect on the xsl:output element in which the QName occurs; if there is a default namespace, it is used for QNames that do not have a prefix. The expansion is performed before the merging of multiple xsl:output elements into a single effective xsl:output element. If the expanded-name of the parent of a text node is a member of the list, then the text node should be output as a CDATA section. For example,

    ]]>

    would cause a literal result element written in the stylesheet as

    <foo>]]>

    or as

    <example><![CDATA[<foo>]]></example>

    to be output as

    <example><![CDATA[<foo>]]></example>

    If the text node contains the sequence of characters ]]>, then the currently open CDATA section should be closed following the ]] and a new CDATA section opened before the >. For example, a literal result element written in the stylesheet as

    <example>]]&gt;</example>

    would be output as

    <example><![CDATA[]]]]><![CDATA[>]]></example>

    If the text node contains a character that is not representable in the character encoding being used to output the result tree, then the currently open CDATA section should be closed before the character, the character should be output using a character reference or entity reference, and a new CDATA section should be opened for any further characters in the text node.

    CDATA sections should not be used except for text nodes that the cdata-section-elements attribute explicitly specifies should be output using CDATA sections.

    The xml output method should output an XML declaration unless the omit-xml-declaration attribute has the value yes. The XML declaration should include both version information and an encoding declaration. If the standalone attribute is specified, it should include a standalone document declaration with the same value as the value as the value of the standalone attribute. Otherwise, it should not include a standalone document declaration; this ensures that it is both a XML declaration (allowed at the beginning of a document entity) and a text declaration (allowed at the beginning of an external general parsed entity).

    If the doctype-system attribute is specified, the xml output method should output a document type declaration immediately before the first element. The name following <!DOCTYPE should be the name of the first element. If doctype-public attribute is also specified, then the xml output method should output PUBLIC followed by the public identifier and then the system identifier; otherwise, it should output SYSTEM followed by the system identifier. The internal subset should be empty. The doctype-public attribute should be ignored unless the doctype-system attribute is specified.

    The media-type attribute is applicable for the xml output method. The default value for the media-type attribute is text/xml.

    HTML Output Method

    The html output method outputs the result tree as HTML; for example,

    <xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;"> ... ]]>

    The version attribute indicates the version of the HTML. The default value is 4.0, which specifies that the result should be output as HTML conforming to the HTML 4.0 Recommendation .

    The html output method should not output an element differently from the xml output method unless the expanded-name of the element has a null namespace URI; an element whose expanded-name has a non-null namespace URI should be output as XML. If the expanded-name of the element has a null namespace URI, but the local part of the expanded-name is not recognized as the name of an HTML element, the element should output in the same way as a non-empty, inline element such as span.

    The html output method should not output an end-tag for empty elements. For HTML 4.0, the empty elements are area, base, basefont, br, col, frame, hr, img, input, isindex, link, meta and param. For example, an element written as <br/> or <br></br> in the stylesheet should be output as <br>.

    The html output method should recognize the names of HTML elements regardless of case. For example, elements named br, BR or Br should all be recognized as the HTML br element and output without an end-tag.

    The html output method should not perform escaping for the content of the script and style elements. For example, a literal result element written in the stylesheet as

    if (a < b) foo()]]>

    or

    ]]>

    should be output as

    if (a < b) foo()]]>

    The html output method should not escape < characters occurring in attribute values.

    If the indent attribute has the value yes, then the html output method may add or remove whitespace as it outputs the result tree, so long as it does not change how an HTML user agent would render the output. The default value is yes.

    The html output method should escape non-ASCII characters in URI attribute values using the method recommended in Section B.2.1 of the HTML 4.0 Recommendation.

    The html output method may output a character using a character entity reference, if one is defined for it in the version of HTML that the output method is using.

    The html output method should terminate processing instructions with > rather than ?>.

    The html output method should output boolean attributes (that is attributes with only a single allowed value that is equal to the name of the attribute) in minimized form. For example, a start-tag written in the stylesheet as

    ]]>

    should be output as

    ]]>

    The html output method should not escape a & character occurring in an attribute value immediately followed by a { character (see Section B.7.1 of the HTML 4.0 Recommendation). For example, a start-tag written in the stylesheet as

    ]]>

    should be output as

    ]]>

    The encoding attribute specifies the preferred encoding to be used. If there is a HEAD element, then the html output method should add a META element immediately after the start-tag of the HEAD element specifying the character encoding actually used. For example,

    ...]]>

    It is possible that the result tree will contain a character that cannot be represented in the encoding that the XSLT processor is using for output. In this case, if the character occurs in a context where HTML recognizes character references, then the character should be output as a character entity reference or decimal numeric character reference; otherwise (for example, in a script or style element or in a comment), the XSLT processor should signal an error.

    If the doctype-public or doctype-system attributes are specified, then the html output method should output a document type declaration immediately before the first element. The name following <!DOCTYPE should be HTML or html. If the doctype-public attribute is specified, then the output method should output PUBLIC followed by the specified public identifier; if the doctype-system attribute is also specified, it should also output the specified system identifier following the public identifier. If the doctype-system attribute is specified but the doctype-public attribute is not specified, then the output method should output SYSTEM followed by the specified system identifier.

    The media-type attribute is applicable for the html output method. The default value is text/html.

    Text Output Method

    The text output method outputs the result tree by outputting the string-value of every text node in the result tree in document order without any escaping.

    The media-type attribute is applicable for the text output method. The default value for the media-type attribute is text/plain.

    The encoding attribute identifies the encoding that the text output method should use to convert sequences of characters to sequences of bytes. The default is system-dependent. If the result tree contains a character that cannot be represented in the encoding that the XSLT processor is using for output, the XSLT processor should signal an error.

    Disabling Output Escaping

    Normally, the xml output method escapes & and < (and possibly other characters) when outputting text nodes. This ensures that the output is well-formed XML. However, it is sometimes convenient to be able to produce output that is almost, but not quite well-formed XML; for example, the output may include ill-formed sections which are intended to be transformed into well-formed XML by a subsequent non-XML aware process. For this reason, XSLT provides a mechanism for disabling output escaping. An xsl:value-of or xsl:text element may have a disable-output-escaping attribute; the allowed values are yes or no; the default is no; if the value is yes, then a text node generated by instantiating the xsl:value-of or xsl:text element should be output without any escaping. For example,

    <]]>

    should generate the single character <.

    It is an error for output escaping to be disabled for a text node that is used for something other than a text node in the result tree. Thus, it is an error to disable output escaping for an xsl:value-of or xsl:text element that is used to generate the string-value of a comment, processing instruction or attribute node; it is also an error to convert a result tree fragment to a number or a string if the result tree fragment contains a text node for which escaping was disabled. In both cases, an XSLT processor may signal the error; if it does not signal the error, it must recover by ignoring the disable-output-escaping attribute.

    The disable-output-escaping attribute may be used with the html output method as well as with the xml output method. The text output method ignores the disable-output-escaping attribute, since it does not perform any output escaping.

    An XSLT processor will only be able to disable output escaping if it controls how the result tree is output. This may not always be the case. For example, the result tree may be used as the source tree for another XSLT transformation instead of being output. An XSLT processor is not required to support disabling output escaping. If an xsl:value-of or xsl:text specifies that output escaping should be disabled and the XSLT processor does not support this, the XSLT processor may signal an error; if it does not signal an error, it must recover by not disabling output escaping.

    If output escaping is disabled for a character that is not representable in the encoding that the XSLT processor is using for output, then the XSLT processor may signal an error; if it does not signal an error, it must recover by not disabling output escaping.

    Since disabling output escaping may not work with all XSLT processors and can result in XML that is not well-formed, it should be used only when there is no alternative.

    Conformance

    A conforming XSLT processor must be able to use a stylesheet to transform a source tree into a result tree as specified in this document. A conforming XSLT processor need not be able to output the result in XML or in any other form.

    Vendors of XSLT processors are strongly encouraged to provide a way to verify that their processor is behaving conformingly by allowing the result tree to be output as XML or by providing access to the result tree through a standard API such as the DOM or SAX.

    A conforming XSLT processor must signal any errors except for those that this document specifically allows an XSLT processor not to signal. A conforming XSLT processor may but need not recover from any errors that it signals.

    A conforming XSLT processor may impose limits on the processing resources consumed by the processing of a stylesheet.

    Notation

    The specification of each XSLT-defined element type is preceded by a summary of its syntax in the form of a model for elements of that element type. The meaning of syntax summary notation is as follows:

    An attribute is required if and only if its name is in bold.

    The string that occurs in the place of an attribute value specifies the allowed values of the attribute. If this is surrounded by curly braces, then the attribute value is treated as an attribute value template, and the string occurring within curly braces specifies the allowed values of the result of instantiating the attribute value template. Alternative allowed values are separated by |. A quoted string indicates a value equal to that specific string. An unquoted, italicized name specifies a particular type of value.

    If the element is allowed not to be empty, then the element contains a comment specifying the allowed content. The allowed content is specified in a similar way to an element type declaration in XML; template means that any mixture of text nodes, literal result elements, extension elements, and XSLT elements from the instruction category is allowed; top-level-elements means that any mixture of XSLT elements from the top-level-element category is allowed.

    The element is prefaced by comments indicating if it belongs to the instruction category or top-level-element category or both. The category of an element just affects whether it is allowed in the content of elements that allow a template or top-level-elements.

    References Normative References World Wide Web Consortium. Extensible Markup Language (XML) 1.0. W3C Recommendation. See http://www.w3.org/TR/1998/REC-xml-19980210 World Wide Web Consortium. Namespaces in XML. W3C Recommendation. See http://www.w3.org/TR/REC-xml-names World Wide Web Consortium. XML Path Language. W3C Recommendation. See http://www.w3.org/TR/xpath Other References World Wide Web Consortium. Cascading Style Sheets, level 2 (CSS2). W3C Recommendation. See http://www.w3.org/TR/1998/REC-CSS2-19980512 International Organization for Standardization, International Electrotechnical Commission. ISO/IEC 10179:1996. Document Style Semantics and Specification Language (DSSSL). International Standard. World Wide Web Consortium. HTML 4.0 specification. W3C Recommendation. See http://www.w3.org/TR/REC-html40 Internet Assigned Numbers Authority. Character Sets. See ftp://ftp.isi.edu/in-notes/iana/assignments/character-sets. N. Freed, J. Postel. IANA Charset Registration Procedures. IETF RFC 2278. See http://www.ietf.org/rfc/rfc2278.txt. E. Whitehead, M. Murata. XML Media Types. IETF RFC 2376. See http://www.ietf.org/rfc/rfc2376.txt. T. Berners-Lee, R. Fielding, and L. Masinter. Uniform Resource Identifiers (URI): Generic Syntax. IETF RFC 2396. See http://www.ietf.org/rfc/rfc2396.txt. Unicode Consortium. Unicode Technical Report #10. Unicode Collation Algorithm. Unicode Technical Report. See http://www.unicode.org/unicode/reports/tr10/index.html. World Wide Web Consortium. XHTML 1.0: The Extensible HyperText Markup Language. W3C Proposed Recommendation. See http://www.w3.org/TR/xhtml1 World Wide Web Consortium. XML Pointer Language (XPointer). W3C Working Draft. See http://www.w3.org/TR/xptr World Wide Web Consortium. Associating stylesheets with XML documents. W3C Recommendation. See http://www.w3.org/TR/xml-stylesheet World Wide Web Consortium. Extensible Stylesheet Language (XSL). W3C Working Draft. See http://www.w3.org/TR/WD-xsl Element Syntax Summary DTD Fragment for XSLT Stylesheets

    This DTD Fragment is not normative because XML 1.0 DTDs do not support XML Namespaces and thus cannot correctly describe the allowed structure of an XSLT stylesheet.

    The following entity can be used to construct a DTD for XSLT stylesheets that create instances of a particular result DTD. Before referencing the entity, the stylesheet DTD must define a result-elements parameter entity listing the allowed result element types. For example:

    ]]>

    Such result elements should be declared to have xsl:use-attribute-sets and xsl:extension-element-prefixes attributes. The following entity declares the result-element-atts parameter for this purpose. The content that XSLT allows for result elements is the same as it allows for the XSLT elements that are declared in the following entity with a content model of %template;. The DTD may use a more restrictive content model than %template; to reflect the constraints of the result DTD.

    The DTD may define the non-xsl-top-level parameter entity to allow additional top-level elements from namespaces other than the XSLT namespace.

    The use of the xsl: prefix in this DTD does not imply that XSLT stylesheets are required to use this prefix. Any of the elements declared in this DTD may have attributes whose name starts with xmlns: or is equal to xmlns in addition to the attributes declared in this DTD.

    &XSLT.ns; ]]>
    Examples Document Example

    This example is a stylesheet for transforming documents that conform to a simple DTD into XHTML . The DTD is:

    ]]>

    The stylesheet is:

    <xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;" xmlns="&XHTML.ns;"> <xsl:value-of select="title"/>

    NOTE:

    ]]>

    With the following input document

    Document Title Chapter Title
    Section Title This is a test. This is a note.
    Another Section Title This is another test. This is another note.
    ]]>

    it would produce the following result

    <?xml version="1.0" encoding="iso-8859-1"?> <html xmlns="&XHTML.ns;"> Document Title

    Document Title

    Chapter Title

    Section Title

    This is a test.

    NOTE: This is a note.

    Another Section Title

    This is another test.

    NOTE: This is another note.

    ]]>
    Data Example

    This is an example of transforming some data represented in XML using three different XSLT stylesheets to produce three different representations of the data, HTML, SVG and VRML.

    The input data is:

    10 9 7 4 3 4 6 -1.5 2 ]]>

    The following stylesheet, which uses the simplified syntax described in , transforms the data into HTML:

    <html xsl:version="1.0" xmlns:xsl="&XSLT.ns;" Sales Results By Division
    Division Revenue Growth Bonus
    color:red
    ]]>

    The HTML output is:

    Sales Results By Division
    DivisionRevenueGrowthBonus
    North1097
    West6-1.52
    South434
    ]]>

    The following stylesheet transforms the data into SVG:

    <xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;" Revenue Division ]]>

    The SVG output is:

    Revenue Division North 10 South 4 West 6 ]]>

    The following stylesheet transforms the data into VRML:

    <xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;"> #VRML V2.0 utf8 # externproto definition of a single bar element EXTERNPROTO bar [ field SFInt32 x field SFInt32 y field SFInt32 z field SFString name ] "http://www.vrml.org/WorkingGroups/dbwork/barProto.wrl" # inline containing the graph axes Inline { url "http://www.vrml.org/WorkingGroups/dbwork/barAxes.wrl" } bar { x y z name "" } ]]>

    The VRML output is:

    Acknowledgements

    The following have contributed to authoring this draft:

    Daniel Lipkin, Saba Jonathan Marsh, Microsoft Henry Thompson, University of Edinburgh Norman Walsh, Arbortext Steve Zilles, Adobe

    This specification was developed and approved for publication by the W3C XSL Working Group (WG). WG approval of this specification does not necessarily imply that all WG members voted for its approval. The current members of the XSL WG are:

    Sharon Adler IBM Co-Chair Anders Berglund IBM Perin Blanchard Novell Scott Boag Lotus Larry Cable Sun Jeff Caruso Bitstream James Clark Peter Danielsen Bell Labs Don Day IBM Stephen Deach Adobe Dwayne Dicks SoftQuad Andrew Greene Bitstream Paul Grosso Arbortext Eduardo Gutentag Sun Juliane Harbarth Software AG Mickey Kimchi Enigma Chris Lilley W3C Chris Maden Exemplary Technologies Jonathan Marsh Microsoft Alex Milowski Lexica Steve Muench Oracle Scott Parnell Xerox Vincent Quint W3C Dan Rapp Novell Gregg Reynolds Datalogics Jonathan Robie Software AG Mark Scardina Oracle Henry Thompson University of Edinburgh Philip Wadler Bell Labs Norman Walsh Arbortext Sanjiva Weerawarana IBM Steve Zilles Adobe Co-Chair
    Changes from Proposed Recommendation

    The following are the changes since the Proposed Recommendation:

    The xsl:version attribute is required on a literal result element used as a stylesheet (see ).

    The data-type attribute on xsl:sort can use a prefixed name to specify a data-type not defined by XSLT (see ).

    Features under Consideration for Future Versions of XSLT

    The following features are under consideration for versions of XSLT after XSLT 1.0:

    a conditional expression;

    support for XML Schema datatypes and archetypes;

    support for something like style rules in the original XSL submission;

    an attribute to control the default namespace for names occurring in XSLT attributes;

    support for entity references;

    support for DTDs in the data model;

    support for notations in the data model;

    a way to get back from an element to the elements that reference it (e.g. by IDREF attributes);

    an easier way to get an ID or key in another document;

    support for regular expressions for matching against any or all of text nodes, attribute values, attribute names, element type names;

    case-insensitive comparisons;

    normalization of strings before comparison, for example for compatibility characters;

    a function string resolve(node-set) function that treats the value of the argument as a relative URI and turns it into an absolute URI using the base URI of the node;

    multiple result documents;

    defaulting the select attribute on xsl:value-of to the current node;

    an attribute on xsl:attribute to control how the attribute value is normalized;

    additional attributes on xsl:sort to provide further control over sorting, such as relative order of scripts;

    a way to put the text of a resource identified by a URI into the result tree;

    allow unions in steps (e.g. foo/(bar|baz));

    allow for result tree fragments all operations that are allowed for node-sets;

    a way to group together consecutive nodes having duplicate subelements or attributes;

    features to make handling of the HTML style attribute more convenient.

    tdom-0.9.5-src/tests/data/books.xml0000644000175000017500000000361614703531020015656 0ustar rolfrolf Seven Years in Trenton Joe Bob Trenton Literary Review Honorable Mention 12 History of Trenton Mary Bob Selected Short Stories of Mary Bob 55 Tracking Trenton 2.50 Trenton Today, Trenton Tomorrow Toni Bob B.A. Ph.D. Pulizer Still in Trenton Trenton Forever 6.50

    It was a dark and stormy night.

    But then all nights in Trenton seem dark and stormy to someone who has gone through what I have.

    Trenton misery
    Who's Who in Trenton Robert Bob
    tdom-0.9.5-src/tests/data/REC-xslt-19991116-mod.xml0000644000175000017500000074342614703531020017653 0ustar rolfrolf ]>
    XSL Transformations (XSLT) Version 1.0 &LEV;-xslt-&YYYYMMDD; W3C Recommendation &day;&month;&year; http://www.w3.org/TR/&year;/&LEV;-xslt-&YYYYMMDD; XML HTML http://www.w3.org/TR/xslt http://www.w3.org/TR/1999/PR-xslt-19991008 http://www.w3.org/1999/08/WD-xslt-19990813 http://www.w3.org/1999/07/WD-xslt-19990709 http://www.w3.org/TR/1999/WD-xslt-19990421 http://www.w3.org/TR/1998/WD-xsl-19981216 http://www.w3.org/TR/1998/WD-xsl-19980818 James Clark jjc@jclark.com

    This document has been reviewed by W3C Members and other interested parties and has been endorsed by the Director as a W3C Recommendation. It is a stable document and may be used as reference material or cited as a normative reference from other documents. W3C's role in making the Recommendation is to draw attention to the specification and to promote its widespread deployment. This enhances the functionality and interoperability of the Web.

    The list of known errors in this specification is available at http://www.w3.org/&year;/&MM;/&LEV;-xslt-&YYYYMMDD;-errata.

    Comments on this specification may be sent to xsl-editors@w3.org; archives of the comments are available. Public discussion of XSL, including XSL Transformations, takes place on the XSL-List mailing list.

    The English version of this specification is the only normative version. However, for translations of this document, see http://www.w3.org/Style/XSL/translations.html.

    A list of current W3C Recommendations and other technical documents can be found at http://www.w3.org/TR.

    This specification has been produced as part of the W3C Style activity.

    This specification defines the syntax and semantics of XSLT, which is a language for transforming XML documents into other XML documents.

    XSLT is designed for use as part of XSL, which is a stylesheet language for XML. In addition to XSLT, XSL includes an XML vocabulary for specifying formatting. XSL specifies the styling of an XML document by using XSLT to describe how the document is transformed into another XML document that uses the formatting vocabulary.

    XSLT is also designed to be used independently of XSL. However, XSLT is not intended as a completely general-purpose XML transformation language. Rather it is designed primarily for the kinds of transformations that are needed when XSLT is used as part of XSL.

    English EBNF See RCS log for revision history.
    Introduction

    This specification defines the syntax and semantics of the XSLT language. A transformation in the XSLT language is expressed as a well-formed XML document conforming to the Namespaces in XML Recommendation , which may include both elements that are defined by XSLT and elements that are not defined by XSLT. XSLT-defined elements are distinguished by belonging to a specific XML namespace (see ), which is referred to in this specification as the XSLT namespace. Thus this specification is a definition of the syntax and semantics of the XSLT namespace.

    A transformation expressed in XSLT describes rules for transforming a source tree into a result tree. The transformation is achieved by associating patterns with templates. A pattern is matched against elements in the source tree. A template is instantiated to create part of the result tree. The result tree is separate from the source tree. The structure of the result tree can be completely different from the structure of the source tree. In constructing the result tree, elements from the source tree can be filtered and reordered, and arbitrary structure can be added.

    A transformation expressed in XSLT is called a stylesheet. This is because, in the case when XSLT is transforming into the XSL formatting vocabulary, the transformation functions as a stylesheet.

    This document does not specify how an XSLT stylesheet is associated with an XML document. It is recommended that XSL processors support the mechanism described in . When this or any other mechanism yields a sequence of more than one XSLT stylesheet to be applied simultaneously to a XML document, then the effect should be the same as applying a single stylesheet that imports each member of the sequence in order (see ).

    A stylesheet contains a set of template rules. A template rule has two parts: a pattern which is matched against nodes in the source tree and a template which can be instantiated to form part of the result tree. This allows a stylesheet to be applicable to a wide class of documents that have similar source tree structures.

    A template is instantiated for a particular source element to create part of the result tree. A template can contain elements that specify literal result element structure. A template can also contain elements from the XSLT namespace that are instructions for creating result tree fragments. When a template is instantiated, each instruction is executed and replaced by the result tree fragment that it creates. Instructions can select and process descendant source elements. Processing a descendant element creates a result tree fragment by finding the applicable template rule and instantiating its template. Note that elements are only processed when they have been selected by the execution of an instruction. The result tree is constructed by finding the template rule for the root node and instantiating its template.

    In the process of finding the applicable template rule, more than one template rule may have a pattern that matches a given element. However, only one template rule will be applied. The method for deciding which template rule to apply is described in .

    A single template by itself has considerable power: it can create structures of arbitrary complexity; it can pull string values out of arbitrary locations in the source tree; it can generate structures that are repeated according to the occurrence of elements in the source tree. For simple transformations where the structure of the result tree is independent of the structure of the source tree, a stylesheet can often consist of only a single template, which functions as a template for the complete result tree. Transformations on XML documents that represent data are often of this kind (see ). XSLT allows a simplified syntax for such stylesheets (see ).

    When a template is instantiated, it is always instantiated with respect to a current node and a current node list. The current node is always a member of the current node list. Many operations in XSLT are relative to the current node. Only a few instructions change the current node list or the current node (see and ); during the instantiation of one of these instructions, the current node list changes to a new list of nodes and each member of this new list becomes the current node in turn; after the instantiation of the instruction is complete, the current node and current node list revert to what they were before the instruction was instantiated.

    XSLT makes use of the expression language defined by for selecting elements for processing, for conditional processing and for generating text.

    XSLT provides two hooks for extending the language, one hook for extending the set of instruction elements used in templates and one hook for extending the set of functions used in XPath expressions. These hooks are both based on XML namespaces. This version of XSLT does not define a mechanism for implementing the hooks. See .

    The XSL WG intends to define such a mechanism in a future version of this specification or in a separate specification.

    The element syntax summary notation used to describe the syntax of XSLT-defined elements is described in .

    The MIME media types text/xml and application/xml should be used for XSLT stylesheets. It is possible that a media type will be registered specifically for XSLT stylesheets; if and when it is, that media type may also be used.

    Stylesheet Structure XSLT Namespace

    The XSLT namespace has the URI &XSLT.ns;.

    The 1999 in the URI indicates the year in which the URI was allocated by the W3C. It does not indicate the version of XSLT being used, which is specified by attributes (see and ).

    XSLT processors must use the XML namespaces mechanism to recognize elements and attributes from this namespace. Elements from the XSLT namespace are recognized only in the stylesheet not in the source document. The complete list of XSLT-defined elements is specified in . Vendors must not extend the XSLT namespace with additional elements or attributes. Instead, any extension must be in a separate namespace. Any namespace that is used for additional instruction elements must be identified by means of the extension element mechanism specified in .

    This specification uses a prefix of xsl: for referring to elements in the XSLT namespace. However, XSLT stylesheets are free to use any prefix, provided that there is a namespace declaration that binds the prefix to the URI of the XSLT namespace.

    An element from the XSLT namespace may have any attribute not from the XSLT namespace, provided that the expanded-name of the attribute has a non-null namespace URI. The presence of such attributes must not change the behavior of XSLT elements and functions defined in this document. Thus, an XSLT processor is always free to ignore such attributes, and must ignore such attributes without giving an error if it does not recognize the namespace URI. Such attributes can provide, for example, unique identifiers, optimization hints, or documentation.

    It is an error for an element from the XSLT namespace to have attributes with expanded-names that have null namespace URIs (i.e. attributes with unprefixed names) other than attributes defined for the element in this document.

    The conventions used for the names of XSLT elements, attributes and functions are that names are all lower-case, use hyphens to separate words, and use abbreviations only if they already appear in the syntax of a related language such as XML or HTML.

    Stylesheet Element

    A stylesheet is represented by an xsl:stylesheet element in an XML document. xsl:transform is allowed as a synonym for xsl:stylesheet.

    An xsl:stylesheet element must have a version attribute, indicating the version of XSLT that the stylesheet requires. For this version of XSLT, the value should be 1.0. When the value is not equal to 1.0, forwards-compatible processing mode is enabled (see ).

    The xsl:stylesheet element may contain the following types of elements:

    xsl:import

    xsl:include

    xsl:strip-space

    xsl:preserve-space

    xsl:output

    xsl:key

    xsl:decimal-format

    xsl:namespace-alias

    xsl:attribute-set

    xsl:variable

    xsl:param

    xsl:template

    An element occurring as a child of an xsl:stylesheet element is called a top-level element.

    This example shows the structure of a stylesheet. Ellipses (...) indicate where attribute values or content have been omitted. Although this example shows one of each type of allowed element, stylesheets may contain zero or more of each of these elements.

    <xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;"> ... ... ... ... ... ]]>

    The order in which the children of the xsl:stylesheet element occur is not significant except for xsl:import elements and for error recovery. Users are free to order the elements as they prefer, and stylesheet creation tools need not provide control over the order in which the elements occur.

    In addition, the xsl:stylesheet element may contain any element not from the XSLT namespace, provided that the expanded-name of the element has a non-null namespace URI. The presence of such top-level elements must not change the behavior of XSLT elements and functions defined in this document; for example, it would not be permitted for such a top-level element to specify that xsl:apply-templates was to use different rules to resolve conflicts. Thus, an XSLT processor is always free to ignore such top-level elements, and must ignore a top-level element without giving an error if it does not recognize the namespace URI. Such elements can provide, for example,

    information used by extension elements or extension functions (see ),

    information about what to do with the result tree,

    information about how to obtain the source tree,

    metadata about the stylesheet,

    structured documentation for the stylesheet.

    Literal Result Element as Stylesheet

    A simplified syntax is allowed for stylesheets that consist of only a single template for the root node. The stylesheet may consist of just a literal result element (see ). Such a stylesheet is equivalent to a stylesheet with an xsl:stylesheet element containing a template rule containing the literal result element; the template rule has a match pattern of /. For example

    <html xsl:version="1.0" xmlns:xsl="&XSLT.ns;" xmlns="&XHTML.ns;"> Expense Report Summary

    Total Amount:

    ]]>

    has the same meaning as

    <xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;" xmlns="&XHTML.ns;"> Expense Report Summary

    Total Amount:

    ]]>

    A literal result element that is the document element of a stylesheet must have an xsl:version attribute, which indicates the version of XSLT that the stylesheet requires. For this version of XSLT, the value should be 1.0; the value must be a Number. Other literal result elements may also have an xsl:version attribute. When the xsl:version attribute is not equal to 1.0, forwards-compatible processing mode is enabled (see ).

    The allowed content of a literal result element when used as a stylesheet is no different from when it occurs within a stylesheet. Thus, a literal result element used as a stylesheet cannot contain top-level elements.

    In some situations, the only way that a system can recognize that an XML document needs to be processed by an XSLT processor as an XSLT stylesheet is by examining the XML document itself. Using the simplified syntax makes this harder.

    For example, another XML language (AXL) might also use an axl:version on the document element to indicate that an XML document was an AXL document that required processing by an AXL processor; if a document had both an axl:version attribute and an xsl:version attribute, it would be unclear whether the document should be processed by an XSLT processor or an AXL processor.

    Therefore, the simplified syntax should not be used for XSLT stylesheets that may be used in such a situation. This situation can, for example, arise when an XSLT stylesheet is transmitted as a message with a MIME media type of text/xml or application/xml to a recipient that will use the MIME media type to determine how the message is processed.

    Qualified Names

    The name of an internal XSLT object, specifically a named template (see ), a mode (see ), an attribute set (see ), a key (see ), a decimal-format (see ), a variable or a parameter (see ) is specified as a QName. If it has a prefix, then the prefix is expanded into a URI reference using the namespace declarations in effect on the attribute in which the name occurs. The expanded-name consisting of the local part of the name and the possibly null URI reference is used as the name of the object. The default namespace is not used for unprefixed names.

    Forwards-Compatible Processing

    An element enables forwards-compatible mode for itself, its attributes, its descendants and their attributes if either it is an xsl:stylesheet element whose version attribute is not equal to 1.0, or it is a literal result element that has an xsl:version attribute whose value is not equal to 1.0, or it is a literal result element that does not have an xsl:version attribute and that is the document element of a stylesheet using the simplified syntax (see ). A literal result element that has an xsl:version attribute whose value is equal to 1.0 disables forwards-compatible mode for itself, its attributes, its descendants and their attributes.

    If an element is processed in forwards-compatible mode, then:

    if it is a top-level element and XSLT 1.0 does not allow such elements as top-level elements, then the element must be ignored along with its content;

    if it is an element in a template and XSLT 1.0 does not allow such elements to occur in templates, then if the element is not instantiated, an error must not be signaled, and if the element is instantiated, the XSLT must perform fallback for the element as specified in ;

    if the element has an attribute that XSLT 1.0 does not allow the element to have or if the element has an optional attribute with a value that the XSLT 1.0 does not allow the attribute to have, then the attribute must be ignored.

    Thus, any XSLT 1.0 processor must be able to process the following stylesheet without error, although the stylesheet includes elements from the XSLT namespace that are not defined in this specification:

    <xsl:stylesheet version="1.1" xmlns:xsl="&XSLT.ns;"> XSLT 1.1 required

    Sorry, this stylesheet requires XSLT 1.1.

    ]]>

    If a stylesheet depends crucially on a top-level element introduced by a version of XSL after 1.0, then the stylesheet can use an xsl:message element with terminate="yes" (see ) to ensure that XSLT processors implementing earlier versions of XSL will not silently ignore the top-level element. For example,

    <xsl:stylesheet version="1.5" xmlns:xsl="&XSLT.ns;"> Sorry, this stylesheet requires XSLT 1.1. ... ... ]]>

    If an expression occurs in an attribute that is processed in forwards-compatible mode, then an XSLT processor must recover from errors in the expression as follows:

    if the expression does not match the syntax allowed by the XPath grammar, then an error must not be signaled unless the expression is actually evaluated;

    if the expression calls a function with an unprefixed name that is not part of the XSLT library, then an error must not be signaled unless the function is actually called;

    if the expression calls a function with a number of arguments that XSLT does not allow or with arguments of types that XSLT does not allow, then an error must not be signaled unless the function is actually called.

    Combining Stylesheets

    XSLT provides two mechanisms to combine stylesheets:

    an inclusion mechanism that allows stylesheets to be combined without changing the semantics of the stylesheets being combined, and an import mechanism that allows stylesheets to override each other. Stylesheet Inclusion

    An XSLT stylesheet may include another XSLT stylesheet using an xsl:include element. The xsl:include element has an href attribute whose value is a URI reference identifying the stylesheet to be included. A relative URI is resolved relative to the base URI of the xsl:include element (see ).

    The xsl:include element is only allowed as a top-level element.

    The inclusion works at the XML tree level. The resource located by the href attribute value is parsed as an XML document, and the children of the xsl:stylesheet element in this document replace the xsl:include element in the including document. The fact that template rules or definitions are included does not affect the way they are processed.

    The included stylesheet may use the simplified syntax described in . The included stylesheet is treated the same as the equivalent xsl:stylesheet element.

    It is an error if a stylesheet directly or indirectly includes itself.

    Including a stylesheet multiple times can cause errors because of duplicate definitions. Such multiple inclusions are less obvious when they are indirect. For example, if stylesheet B includes stylesheet A, stylesheet C includes stylesheet A, and stylesheet D includes both stylesheet B and stylesheet C, then A will be included indirectly by D twice. If all of B, C and D are used as independent stylesheets, then the error can be avoided by separating everything in B other than the inclusion of A into a separate stylesheet B' and changing B to contain just inclusions of B' and A, similarly for C, and then changing D to include A, B', C'.

    Stylesheet Import

    An XSLT stylesheet may import another XSLT stylesheet using an xsl:import element. Importing a stylesheet is the same as including it (see ) except that definitions and template rules in the importing stylesheet take precedence over template rules and definitions in the imported stylesheet; this is described in more detail below. The xsl:import element has an href attribute whose value is a URI reference identifying the stylesheet to be imported. A relative URI is resolved relative to the base URI of the xsl:import element (see ).

    The xsl:import element is only allowed as a top-level element. The xsl:import element children must precede all other element children of an xsl:stylesheet element, including any xsl:include element children. When xsl:include is used to include a stylesheet, any xsl:import elements in the included document are moved up in the including document to after any existing xsl:import elements in the including document.

    For example,

    <xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;"> italic ]]>

    The xsl:stylesheet elements encountered during processing of a stylesheet that contains xsl:import elements are treated as forming an import tree. In the import tree, each xsl:stylesheet element has one import child for each xsl:import element that it contains. Any xsl:include elements are resolved before constructing the import tree. An xsl:stylesheet element in the import tree is defined to have lower import precedence than another xsl:stylesheet element in the import tree if it would be visited before that xsl:stylesheet element in a post-order traversal of the import tree (i.e. a traversal of the import tree in which an xsl:stylesheet element is visited after its import children). Each definition and template rule has import precedence determined by the xsl:stylesheet element that contains it.

    For example, suppose

    stylesheet A imports stylesheets B and C in that order;

    stylesheet B imports stylesheet D;

    stylesheet C imports stylesheet E.

    Then the order of import precedence (lowest first) is D, B, E, C, A.

    Since xsl:import elements are required to occur before any definitions or template rules, an implementation that processes imported stylesheets at the point at which it encounters the xsl:import element will encounter definitions and template rules in increasing order of import precedence.

    In general, a definition or template rule with higher import precedence takes precedence over a definition or template rule with lower import precedence. This is defined in detail for each kind of definition and for template rules.

    It is an error if a stylesheet directly or indirectly imports itself. Apart from this, the case where a stylesheet with a particular URI is imported in multiple places is not treated specially. The import tree will have a separate xsl:stylesheet for each place that it is imported.

    If xsl:apply-imports is used (see ), the behavior may be different from the behavior if the stylesheet had been imported only at the place with the highest import precedence.

    Embedding Stylesheets

    Normally an XSLT stylesheet is a complete XML document with the xsl:stylesheet element as the document element. However, an XSLT stylesheet may also be embedded in another resource. Two forms of embedding are possible:

    the XSLT stylesheet may be textually embedded in a non-XML resource, or the xsl:stylesheet element may occur in an XML document other than as the document element.

    To facilitate the second form of embedding, the xsl:stylesheet element is allowed to have an ID attribute that specifies a unique identifier.

    In order for such an attribute to be used with the XPath id function, it must actually be declared in the DTD as being an ID.

    The following example shows how the xml-stylesheet processing instruction can be used to allow a document to contain its own stylesheet. The URI reference uses a relative URI with a fragment identifier to locate the xsl:stylesheet element:

    xmlns:xsl="&XSLT.ns;" xmlns:fo="&XSLFO.ns;"> ... ]]>

    A stylesheet that is embedded in the document to which it is to be applied or that may be included or imported into an stylesheet that is so embedded typically needs to contain a template rule that specifies that xsl:stylesheet elements are to be ignored.

    Data Model

    The data model used by XSLT is the same as that used by XPath with the additions described in this section. XSLT operates on source, result and stylesheet documents using the same data model. Any two XML documents that have the same tree will be treated the same by XSLT.

    Processing instructions and comments in the stylesheet are ignored: the stylesheet is treated as if neither processing instruction nodes nor comment nodes were included in the tree that represents the stylesheet.

    Root Node Children

    The normal restrictions on the children of the root node are relaxed for the result tree. The result tree may have any sequence of nodes as children that would be possible for an element node. In particular, it may have text node children, and any number of element node children. When written out using the XML output method (see ), it is possible that a result tree will not be a well-formed XML document; however, it will always be a well-formed external general parsed entity.

    When the source tree is created by parsing a well-formed XML document, the root node of the source tree will automatically satisfy the normal restrictions of having no text node children and exactly one element child. When the source tree is created in some other way, for example by using the DOM, the usual restrictions are relaxed for the source tree as for the result tree.

    Base URI

    Every node also has an associated URI called its base URI, which is used for resolving attribute values that represent relative URIs into absolute URIs. If an element or processing instruction occurs in an external entity, the base URI of that element or processing instruction is the URI of the external entity; otherwise, the base URI is the base URI of the document. The base URI of the document node is the URI of the document entity. The base URI for a text node, a comment node, an attribute node or a namespace node is the base URI of the parent of the node.

    Unparsed Entities

    The root node has a mapping that gives the URI for each unparsed entity declared in the document's DTD. The URI is generated from the system identifier and public identifier specified in the entity declaration. The XSLT processor may use the public identifier to generate a URI for the entity instead of the URI specified in the system identifier. If the XSLT processor does not use the public identifier to generate the URI, it must use the system identifier; if the system identifier is a relative URI, it must be resolved into an absolute URI using the URI of the resource containing the entity declaration as the base URI .

    Whitespace Stripping

    After the tree for a source document or stylesheet document has been constructed, but before it is otherwise processed by XSLT, some text nodes are stripped. A text node is never stripped unless it contains only whitespace characters. Stripping the text node removes the text node from the tree. The stripping process takes as input a set of element names for which whitespace must be preserved. The stripping process is applied to both stylesheets and source documents, but the set of whitespace-preserving element names is determined differently for stylesheets and for source documents.

    A text node is preserved if any of the following apply:

    The element name of the parent of the text node is in the set of whitespace-preserving element names.

    The text node contains at least one non-whitespace character. As in XML, a whitespace character is #x20, #x9, #xD or #xA.

    An ancestor element of the text node has an xml:space attribute with a value of preserve, and no closer ancestor element has xml:space with a value of default.

    Otherwise, the text node is stripped.

    The xml:space attributes are not stripped from the tree.

    This implies that if an xml:space attribute is specified on a literal result element, it will be included in the result.

    For stylesheets, the set of whitespace-preserving element names consists of just xsl:text.

    For source documents, the set of whitespace-preserving element names is specified by xsl:strip-space and xsl:preserve-space top-level elements. These elements each have an elements attribute whose value is a whitespace-separated list of NameTests. Initially, the set of whitespace-preserving element names contains all element names. If an element name matches a NameTest in an xsl:strip-space element, then it is removed from the set of whitespace-preserving element names. If an element name matches a NameTest in an xsl:preserve-space element, then it is added to the set of whitespace-preserving element names. An element matches a NameTest if and only if the NameTest would be true for the element as an XPath node test. Conflicts between matches to xsl:strip-space and xsl:preserve-space elements are resolved the same way as conflicts between template rules (see ). Thus, the applicable match for a particular element name is determined as follows:

    First, any match with lower import precedence than another match is ignored.

    Next, any match with a NameTest that has a lower default priority than the default priority of the NameTest of another match is ignored.

    It is an error if this leaves more than one match. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing, from amongst the matches that are left, the one that occurs last in the stylesheet.

    Expressions

    XSLT uses the expression language defined by XPath . Expressions are used in XSLT for a variety of purposes including:

    selecting nodes for processing; specifying conditions for different ways of processing a node; generating text to be inserted in the result tree.

    An expression must match the XPath production Expr.

    Expressions occur as the value of certain attributes on XSLT-defined elements and within curly braces in attribute value templates.

    In XSLT, an outermost expression (i.e. an expression that is not part of another expression) gets its context as follows:

    the context node comes from the current node

    the context position comes from the position of the current node in the current node list; the first position is 1

    the context size comes from the size of the current node list

    the variable bindings are the bindings in scope on the element which has the attribute in which the expression occurs (see )

    the set of namespace declarations are those in scope on the element which has the attribute in which the expression occurs; this includes the implicit declaration of the prefix xml required by the the XML Namespaces Recommendation ; the default namespace (as declared by xmlns) is not part of this set

    the function library consists of the core function library together with the additional functions defined in and extension functions as described in ; it is an error for an expression to include a call to any other function

    Template Rules Processing Model

    A list of source nodes is processed to create a result tree fragment. The result tree is constructed by processing a list containing just the root node. A list of source nodes is processed by appending the result tree structure created by processing each of the members of the list in order. A node is processed by finding all the template rules with patterns that match the node, and choosing the best amongst them; the chosen rule's template is then instantiated with the node as the current node and with the list of source nodes as the current node list. A template typically contains instructions that select an additional list of source nodes for processing. The process of matching, instantiation and selection is continued recursively until no new source nodes are selected for processing.

    Implementations are free to process the source document in any way that produces the same result as if it were processed using this processing model.

    Patterns

    Template rules identify the nodes to which they apply by using a pattern. As well as being used in template rules, patterns are used for numbering (see ) and for declaring keys (see ). A pattern specifies a set of conditions on a node. A node that satisfies the conditions matches the pattern; a node that does not satisfy the conditions does not match the pattern. The syntax for patterns is a subset of the syntax for expressions. In particular, location paths that meet certain restrictions can be used as patterns. An expression that is also a pattern always evaluates to an object of type node-set. A node matches a pattern if the node is a member of the result of evaluating the pattern as an expression with respect to some possible context; the possible contexts are those whose context node is the node being matched or one of its ancestors.

    Here are some examples of patterns:

    para matches any para element

    * matches any element

    chapter|appendix matches any chapter element and any appendix element

    olist/item matches any item element with an olist parent

    appendix//para matches any para element with an appendix ancestor element

    / matches the root node

    text() matches any text node

    processing-instruction() matches any processing instruction

    node() matches any node other than an attribute node and the root node

    id("W11") matches the element with unique ID W11

    para[1] matches any para element that is the first para child element of its parent

    *[position()=1 and self::para] matches any para element that is the first child element of its parent

    para[last()=1] matches any para element that is the only para child element of its parent

    items/item[position()>1] matches any item element that has a items parent and that is not the first item child of its parent

    item[position() mod 2 = 1] would be true for any item element that is an odd-numbered item child of its parent.

    div[@class="appendix"]//p matches any p element with a div ancestor element that has a class attribute with value appendix

    @class matches any class attribute (not any element that has a class attribute)

    @* matches any attribute

    A pattern must match the grammar for Pattern. A Pattern is a set of location path patterns separated by |. A location path pattern is a location path whose steps all use only the child or attribute axes. Although patterns must not use the descendant-or-self axis, patterns may use the // operator as well as the / operator. Location path patterns can also start with an id or key function call with a literal argument. Predicates in a pattern can use arbitrary expressions just like predicates in a location path.

    Patterns Pattern LocationPathPattern | Pattern '|' LocationPathPattern LocationPathPattern '/' RelativePathPattern? | IdKeyPattern (('/' | '//') RelativePathPattern)? | '//'? RelativePathPattern IdKeyPattern 'id' '(' Literal ')' | 'key' '(' Literal ',' Literal ')' RelativePathPattern StepPattern | RelativePathPattern '/' StepPattern | RelativePathPattern '//' StepPattern StepPattern ChildOrAttributeAxisSpecifier NodeTest Predicate* ChildOrAttributeAxisSpecifier AbbreviatedAxisSpecifier | ('child' | 'attribute') '::'

    A pattern is defined to match a node if and only if there is possible context such that when the pattern is evaluated as an expression with that context, the node is a member of the resulting node-set. When a node is being matched, the possible contexts have a context node that is the node being matched or any ancestor of that node, and a context node list containing just the context node.

    For example, p matches any p element, because for any p if the expression p is evaluated with the parent of the p element as context the resulting node-set will contain that p element as one of its members.

    This matches even a p element that is the document element, since the document root is the parent of the document element.

    Although the semantics of patterns are specified indirectly in terms of expression evaluation, it is easy to understand the meaning of a pattern directly without thinking in terms of expression evaluation. In a pattern, | indicates alternatives; a pattern with one or more | separated alternatives matches if any one of the alternative matches. A pattern that consists of a sequence of StepPatterns separated by / or // is matched from right to left. The pattern only matches if the rightmost StepPattern matches and a suitable element matches the rest of the pattern; if the separator is / then only the parent is a suitable element; if the separator is //, then any ancestor is a suitable element. A StepPattern that uses the child axis matches if the NodeTest is true for the node and the node is not an attribute node. A StepPattern that uses the attribute axis matches if the NodeTest is true for the node and the node is an attribute node. When [] is present, then the first PredicateExpr in a StepPattern is evaluated with the node being matched as the context node and the siblings of the context node that match the NodeTest as the context node list, unless the node being matched is an attribute node, in which case the context node list is all the attributes that have the same parent as the attribute being matched and that match the NameTest.

    For example

    appendix//ulist/item[position()=1]

    matches a node if and only if all of the following are true:

    the NodeTest item is true for the node and the node is not an attribute; in other words the node is an item element

    evaluating the PredicateExpr position()=1 with the node as context node and the siblings of the node that are item elements as the context node list yields true

    the node has a parent that matches appendix//ulist; this will be true if the parent is a ulist element that has an appendix ancestor element.

    Defining Template Rules

    A template rule is specified with the xsl:template element. The match attribute is a Pattern that identifies the source node or nodes to which the rule applies. The match attribute is required unless the xsl:template element has a name attribute (see ). It is an error for the value of the match attribute to contain a VariableReference. The content of the xsl:template element is the template that is instantiated when the template rule is applied.

    For example, an XML document might contain:

    important point.]]>

    The following template rule matches emph elements and produces a fo:inline-sequence formatting object with a font-weight property of bold.

    ]]>

    Examples in this document use the fo: prefix for the namespace &XSLFO.ns;, which is the namespace of the formatting objects defined in .

    As described next, the xsl:apply-templates element recursively processes the children of the source element.

    Applying Template Rules

    This example creates a block for a chapter element and then processes its immediate children.

    ]]>

    In the absence of a select attribute, the xsl:apply-templates instruction processes all of the children of the current node, including text nodes. However, text nodes that have been stripped as specified in will not be processed. If stripping of whitespace nodes has not been enabled for an element, then all whitespace in the content of the element will be processed as text, and thus whitespace between child elements will count in determining the position of a child element as returned by the position function.

    A select attribute can be used to process nodes selected by an expression instead of processing all children. The value of the select attribute is an expression. The expression must evaluate to a node-set. The selected set of nodes is processed in document order, unless a sorting specification is present (see ). The following example processes all of the author children of the author-group:

    ]]>

    The following example processes all of the given-names of the authors that are children of author-group:

    ]]>

    This example processes all of the heading descendant elements of the book element.

    ]]>

    It is also possible to process elements that are not descendants of the current node. This example assumes that a department element has group children and employee descendants. It finds an employee's department and then processes the group children of the department.

    Employee belongs to group ]]>

    Multiple xsl:apply-templates elements can be used within a single template to do simple reordering. The following example creates two HTML tables. The first table is filled with domestic sales while the second table is filled with foreign sales.

    ]]>

    It is possible for there to be two matching descendants where one is a descendant of the other. This case is not treated specially: both descendants will be processed as usual. For example, given a source document

    ]]>

    the rule

    ]]>

    will process both the outer div and inner div elements.

    Typically, xsl:apply-templates is used to process only nodes that are descendants of the current node. Such use of xsl:apply-templates cannot result in non-terminating processing loops. However, when xsl:apply-templates is used to process elements that are not descendants of the current node, the possibility arises of non-terminating loops. For example,

    ]]>

    Implementations may be able to detect such loops in some cases, but the possibility exists that a stylesheet may enter a non-terminating loop that an implementation is unable to detect. This may present a denial of service security risk.

    Conflict Resolution for Template Rules

    It is possible for a source node to match more than one template rule. The template rule to be used is determined as follows:

    First, all matching template rules that have lower import precedence than the matching template rule or rules with the highest import precedence are eliminated from consideration.

    Next, all matching template rules that have lower priority than the matching template rule or rules with the highest priority are eliminated from consideration. The priority of a template rule is specified by the priority attribute on the template rule. The value of this must be a real number (positive or negative), matching the production Number with an optional leading minus sign (-). The default priority is computed as follows:

    If the pattern contains multiple alternatives separated by |, then it is treated equivalently to a set of template rules, one for each alternative.

    If the pattern has the form of a QName preceded by a ChildOrAttributeAxisSpecifier or has the form processing-instruction(Literal) preceded by a ChildOrAttributeAxisSpecifier, then the priority is 0.

    If the pattern has the form NCName:* preceded by a ChildOrAttributeAxisSpecifier, then the priority is -0.25.

    Otherwise, if the pattern consists of just a NodeTest preceded by a ChildOrAttributeAxisSpecifier, then the priority is -0.5.

    Otherwise, the priority is 0.5.

    Thus, the most common kind of pattern (a pattern that tests for a node with a particular type and a particular expanded-name) has priority 0. The next less specific kind of pattern (a pattern that tests for a node with a particular type and an expanded-name with a particular namespace URI) has priority -0.25. Patterns less specific than this (patterns that just tests for nodes with particular types) have priority -0.5. Patterns more specific than the most common kind of pattern have priority 0.5.

    It is an error if this leaves more than one matching template rule. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing, from amongst the matching template rules that are left, the one that occurs last in the stylesheet.

    Overriding Template Rules

    A template rule that is being used to override a template rule in an imported stylesheet (see ) can use the xsl:apply-imports element to invoke the overridden template rule.

    At any point in the processing of a stylesheet, there is a current template rule. Whenever a template rule is chosen by matching a pattern, the template rule becomes the current template rule for the instantiation of the rule's template. When an xsl:for-each element is instantiated, the current template rule becomes null for the instantiation of the content of the xsl:for-each element.

    xsl:apply-imports processes the current node using only template rules that were imported into the stylesheet element containing the current template rule; the node is processed in the current template rule's mode. It is an error if xsl:apply-imports is instantiated when the current template rule is null.

    For example, suppose the stylesheet doc.xsl contains a template rule for example elements:

    ]]>

    Another stylesheet could import doc.xsl and modify the treatment of example elements as follows:

    ]]>

    The combined effect would be to transform an example into an element of the form:

    ...
    ]]>
    Modes

    Modes allow an element to be processed multiple times, each time producing a different result.

    Both xsl:template and xsl:apply-templates have an optional mode attribute. The value of the mode attribute is a QName, which is expanded as described in . If xsl:template does not have a match attribute, it must not have a mode attribute. If an xsl:apply-templates element has a mode attribute, then it applies only to those template rules from xsl:template elements that have a mode attribute with the same value; if an xsl:apply-templates element does not have a mode attribute, then it applies only to those template rules from xsl:template elements that do not have a mode attribute.

    Built-in Template Rules

    There is a built-in template rule to allow recursive processing to continue in the absence of a successful pattern match by an explicit template rule in the stylesheet. This template rule applies to both element nodes and the root node. The following shows the equivalent of the built-in template rule:

    ]]>

    There is also a built-in template rule for each mode, which allows recursive processing to continue in the same mode in the absence of a successful pattern match by an explicit template rule in the stylesheet. This template rule applies to both element nodes and the root node. The following shows the equivalent of the built-in template rule for mode m.

    <xsl:template match="*|/" mode="m"> <xsl:apply-templates mode="m"/> </xsl:template>

    There is also a built-in template rule for text and attribute nodes that copies text through:

    ]]>

    The built-in template rule for processing instructions and comments is to do nothing.

    ]]>

    The built-in template rule for namespace nodes is also to do nothing. There is no pattern that can match a namespace node; so, the built-in template rule is the only template rule that is applied for namespace nodes.

    The built-in template rules are treated as if they were imported implicitly before the stylesheet and so have lower import precedence than all other template rules. Thus, the author can override a built-in template rule by including an explicit template rule.

    Named Templates

    Templates can be invoked by name. An xsl:template element with a name attribute specifies a named template. The value of the name attribute is a QName, which is expanded as described in . If an xsl:template element has a name attribute, it may, but need not, also have a match attribute. An xsl:call-template element invokes a template by name; it has a required name attribute that identifies the template to be invoked. Unlike xsl:apply-templates, xsl:call-template does not change the current node or the current node list.

    The match, mode and priority attributes on an xsl:template element do not affect whether the template is invoked by an xsl:call-template element. Similarly, the name attribute on an xsl:template element does not affect whether the template is invoked by an xsl:apply-templates element.

    It is an error if a stylesheet contains more than one template with the same name and same import precedence.

    Creating the Result Tree

    This section describes instructions that directly create nodes in the result tree.

    Creating Elements and Attributes Literal Result Elements

    In a template, an element in the stylesheet that does not belong to the XSLT namespace and that is not an extension element (see ) is instantiated to create an element node with the same expanded-name. The content of the element is a template, which is instantiated to give the content of the created element node. The created element node will have the attribute nodes that were present on the element node in the stylesheet tree, other than attributes with names in the XSLT namespace.

    The created element node will also have a copy of the namespace nodes that were present on the element node in the stylesheet tree with the exception of any namespace node whose string-value is the XSLT namespace URI (&XSLT.ns;), a namespace URI declared as an extension namespace (see ), or a namespace URI designated as an excluded namespace. A namespace URI is designated as an excluded namespace by using an exclude-result-prefixes attribute on an xsl:stylesheet element or an xsl:exclude-result-prefixes attribute on a literal result element. The value of both these attributes is a whitespace-separated list of namespace prefixes. The namespace bound to each of the prefixes is designated as an excluded namespace. It is an error if there is no namespace bound to the prefix on the element bearing the exclude-result-prefixes or xsl:exclude-result-prefixes attribute. The default namespace (as declared by xmlns) may be designated as an excluded namespace by including #default in the list of namespace prefixes. The designation of a namespace as an excluded namespace is effective within the subtree of the stylesheet rooted at the element bearing the exclude-result-prefixes or xsl:exclude-result-prefixes attribute; a subtree rooted at an xsl:stylesheet element does not include any stylesheets imported or included by children of that xsl:stylesheet element.

    When a stylesheet uses a namespace declaration only for the purposes of addressing the source tree, specifying the prefix in the exclude-result-prefixes attribute will avoid superfluous namespace declarations in the result tree.

    The value of an attribute of a literal result element is interpreted as an attribute value template: it can contain expressions contained in curly braces ({}).

    A namespace URI in the stylesheet tree that is being used to specify a namespace URI in the result tree is called a literal namespace URI. This applies to:

    the namespace URI in the expanded-name of a literal result element in the stylesheet

    the namespace URI in the expanded-name of an attribute specified on a literal result element in the stylesheet

    the string-value of a namespace node on a literal result element in the stylesheet

    A stylesheet can use the xsl:namespace-alias element to declare that one namespace URI is an alias for another namespace URI. When a literal namespace URI has been declared to be an alias for another namespace URI, then the namespace URI in the result tree will be the namespace URI that the literal namespace URI is an alias for, instead of the literal namespace URI itself. The xsl:namespace-alias element declares that the namespace URI bound to the prefix specified by the stylesheet-prefix attribute is an alias for the namespace URI bound to the prefix specified by the result-prefix attribute. Thus, the stylesheet-prefix attribute specifies the namespace URI that will appear in the stylesheet, and the result-prefix attribute specifies the corresponding namespace URI that will appear in the result tree. The default namespace (as declared by xmlns) may be specified by using #default instead of a prefix. If a namespace URI is declared to be an alias for multiple different namespace URIs, then the declaration with the highest import precedence is used. It is an error if there is more than one such declaration. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing, from amongst the declarations with the highest import precedence, the one that occurs last in the stylesheet.

    When literal result elements are being used to create element, attribute, or namespace nodes that use the XSLT namespace URI, the stylesheet must use an alias. For example, the stylesheet

    <xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;" xmlns:fo="&XSLFO.ns;" xmlns:axsl="&XSLTA.ns;"> ]]>

    will generate an XSLT stylesheet from a document of the form:

    p h1 h2 h3 h4 ]]>

    It may be necessary also to use aliases for namespaces other than the XSLT namespace URI. For example, literal result elements belonging to a namespace dealing with digital signatures might cause XSLT stylesheets to be mishandled by general-purpose security software; using an alias for the namespace would avoid the possibility of such mishandling.

    Creating Elements with xsl:element

    The xsl:element element allows an element to be created with a computed name. The expanded-name of the element to be created is specified by a required name attribute and an optional namespace attribute. The content of the xsl:element element is a template for the attributes and children of the created element.

    The name attribute is interpreted as an attribute value template. It is an error if the string that results from instantiating the attribute value template is not a QName. An XSLT processor may signal the error; if it does not signal the error, then it must recover by making the the result of instantiating the xsl:element element be the sequence of nodes created by instantiating the content of the xsl:element element, excluding any initial attribute nodes. If the namespace attribute is not present then the QName is expanded into an expanded-name using the namespace declarations in effect for the xsl:element element, including any default namespace declaration.

    If the namespace attribute is present, then it also is interpreted as an attribute value template. The string that results from instantiating the attribute value template should be a URI reference. It is not an error if the string is not a syntactically legal URI reference. If the string is empty, then the expanded-name of the element has a null namespace URI. Otherwise, the string is used as the namespace URI of the expanded-name of the element to be created. The local part of the QName specified by the name attribute is used as the local part of the expanded-name of the element to be created.

    XSLT processors may make use of the prefix of the QName specified in the name attribute when selecting the prefix used for outputting the created element as XML; however, they are not required to do so.

    Creating Attributes with xsl:attribute

    The xsl:attribute element can be used to add attributes to result elements whether created by literal result elements in the stylesheet or by instructions such as xsl:element. The expanded-name of the attribute to be created is specified by a required name attribute and an optional namespace attribute. Instantiating an xsl:attribute element adds an attribute node to the containing result element node. The content of the xsl:attribute element is a template for the value of the created attribute.

    The name attribute is interpreted as an attribute value template. It is an error if the string that results from instantiating the attribute value template is not a QName or is the string xmlns. An XSLT processor may signal the error; if it does not signal the error, it must recover by not adding the attribute to the result tree. If the namespace attribute is not present, then the QName is expanded into an expanded-name using the namespace declarations in effect for the xsl:attribute element, not including any default namespace declaration.

    If the namespace attribute is present, then it also is interpreted as an attribute value template. The string that results from instantiating it should be a URI reference. It is not an error if the string is not a syntactically legal URI reference. If the string is empty, then the expanded-name of the attribute has a null namespace URI. Otherwise, the string is used as the namespace URI of the expanded-name of the attribute to be created. The local part of the QName specified by the name attribute is used as the local part of the expanded-name of the attribute to be created.

    XSLT processors may make use of the prefix of the QName specified in the name attribute when selecting the prefix used for outputting the created attribute as XML; however, they are not required to do so and, if the prefix is xmlns, they must not do so. Thus, although it is not an error to do:

    <xsl:attribute name="xmlns:xsl" namespace="whatever">&XSLT.ns;</xsl:attribute>

    it will not result in a namespace declaration being output.

    Adding an attribute to an element replaces any existing attribute of that element with the same expanded-name.

    The following are all errors:

    Adding an attribute to an element after children have been added to it; implementations may either signal the error or ignore the attribute.

    Adding an attribute to a node that is not an element; implementations may either signal the error or ignore the attribute.

    Creating nodes other than text nodes during the instantiation of the content of the xsl:attribute element; implementations may either signal the error or ignore the offending nodes.

    When an xsl:attribute contains a text node with a newline, then the XML output must contain a character reference. For example,

    x y]]>

    will result in the output

    (or with any equivalent character reference). The XML output cannot be

    This is because XML 1.0 requires newline characters in attribute values to be normalized into spaces but requires character references to newline characters not to be normalized. The attribute values in the data model represent the attribute value after normalization. If a newline occurring in an attribute value in the tree were output as a newline character rather than as character reference, then the attribute value in the tree created by reparsing the XML would contain a space not a newline, which would mean that the tree had not been output correctly.

    Named Attribute Sets

    The xsl:attribute-set element defines a named set of attributes. The name attribute specifies the name of the attribute set. The value of the name attribute is a QName, which is expanded as described in . The content of the xsl:attribute-set element consists of zero or more xsl:attribute elements that specify the attributes in the set.

    Attribute sets are used by specifying a use-attribute-sets attribute on xsl:element, xsl:copy (see ) or xsl:attribute-set elements. The value of the use-attribute-sets attribute is a whitespace-separated list of names of attribute sets. Each name is specified as a QName, which is expanded as described in . Specifying a use-attribute-sets attribute is equivalent to adding xsl:attribute elements for each of the attributes in each of the named attribute sets to the beginning of the content of the element with the use-attribute-sets attribute, in the same order in which the names of the attribute sets are specified in the use-attribute-sets attribute. It is an error if use of use-attribute-sets attributes on xsl:attribute-set elements causes an attribute set to directly or indirectly use itself.

    Attribute sets can also be used by specifying an xsl:use-attribute-sets attribute on a literal result element. The value of the xsl:use-attribute-sets attribute is a whitespace-separated list of names of attribute sets. The xsl:use-attribute-sets attribute has the same effect as the use-attribute-sets attribute on xsl:element with the additional rule that attributes specified on the literal result element itself are treated as if they were specified by xsl:attribute elements before any actual xsl:attribute elements but after any xsl:attribute elements implied by the xsl:use-attribute-sets attribute. Thus, for a literal result element, attributes from attribute sets named in an xsl:use-attribute-sets attribute will be added first, in the order listed in the attribute; next, attributes specified on the literal result element will be added; finally, any attributes specified by xsl:attribute elements will be added. Since adding an attribute to an element replaces any existing attribute of that element with the same name, this means that attributes specified in attribute sets can be overridden by attributes specified on the literal result element itself.

    The template within each xsl:attribute element in an xsl:attribute-set element is instantiated each time the attribute set is used; it is instantiated using the same current node and current node list as is used for instantiating the element bearing the use-attribute-sets or xsl:use-attribute-sets attribute. However, it is the position in the stylesheet of the xsl:attribute element rather than of the element bearing the use-attribute-sets or xsl:use-attribute-sets attribute that determines which variable bindings are visible (see ); thus, only variables and parameters declared by top-level xsl:variable and xsl:param elements are visible.

    The following example creates a named attribute set title-style and uses it in a template rule.

    12pt bold ]]>

    Multiple definitions of an attribute set with the same expanded-name are merged. An attribute from a definition that has higher import precedence takes precedence over an attribute from a definition that has lower import precedence. It is an error if there are two attribute sets that have the same expanded-name and equal import precedence and that both contain the same attribute, unless there is a definition of the attribute set with higher import precedence that also contains the attribute. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing from amongst the definitions that specify the attribute that have the highest import precedence the one that was specified last in the stylesheet. Where the attributes in an attribute set were specified is relevant only in merging the attributes into the attribute set; it makes no difference when the attribute set is used.

    Creating Text

    A template can also contain text nodes. Each text node in a template remaining after whitespace has been stripped as specified in will create a text node with the same string-value in the result tree. Adjacent text nodes in the result tree are automatically merged.

    Note that text is processed at the tree level. Thus, markup of &lt; in a template will be represented in the stylesheet tree by a text node that includes the character <. This will create a text node in the result tree that contains a < character, which will be represented by the markup &lt; (or an equivalent character reference) when the result tree is externalized as an XML document (unless output escaping is disabled as described in ).

    Literal data characters may also be wrapped in an xsl:text element. This wrapping may change what whitespace characters are stripped (see ) but does not affect how the characters are handled by the XSLT processor thereafter.

    The xml:lang and xml:space attributes are not treated specially by XSLT. In particular,

    it is the responsibility of the stylesheet author explicitly to generate any xml:lang or xml:space attributes that are needed in the result;

    specifying an xml:lang or xml:space attribute on an element in the XSLT namespace will not cause any xml:lang or xml:space attributes to appear in the result.

    Creating Processing Instructions

    The xsl:processing-instruction element is instantiated to create a processing instruction node. The content of the xsl:processing-instruction element is a template for the string-value of the processing instruction node. The xsl:processing-instruction element has a required name attribute that specifies the name of the processing instruction node. The value of the name attribute is interpreted as an attribute value template.

    For example, this

    href="book.css" type="text/css"]]>

    would create the processing instruction

    ]]>

    It is an error if the string that results from instantiating the name attribute is not both an NCName and a PITarget. An XSLT processor may signal the error; if it does not signal the error, it must recover by not adding the processing instruction to the result tree.

    This means that xsl:processing-instruction cannot be used to output an XML declaration. The xsl:output element should be used instead (see ).

    It is an error if instantiating the content of xsl:processing-instruction creates nodes other than text nodes. An XSLT processor may signal the error; if it does not signal the error, it must recover by ignoring the offending nodes together with their content.

    It is an error if the result of instantiating the content of the xsl:processing-instruction contains the string ?>. An XSLT processor may signal the error; if it does not signal the error, it must recover by inserting a space after any occurrence of ? that is followed by a >.

    Creating Comments

    The xsl:comment element is instantiated to create a comment node in the result tree. The content of the xsl:comment element is a template for the string-value of the comment node.

    For example, this

    This file is automatically generated. Do not edit!]]>

    would create the comment

    ]]>

    It is an error if instantiating the content of xsl:comment creates nodes other than text nodes. An XSLT processor may signal the error; if it does not signal the error, it must recover by ignoring the offending nodes together with their content.

    It is an error if the result of instantiating the content of the xsl:comment contains the string -- or ends with -. An XSLT processor may signal the error; if it does not signal the error, it must recover by inserting a space after any occurrence of - that is followed by another - or that ends the comment.

    Copying

    The xsl:copy element provides an easy way of copying the current node. Instantiating the xsl:copy element creates a copy of the current node. The namespace nodes of the current node are automatically copied as well, but the attributes and children of the node are not automatically copied. The content of the xsl:copy element is a template for the attributes and children of the created node; the content is instantiated only for nodes of types that can have attributes or children (i.e. root nodes and element nodes).

    The xsl:copy element may have a use-attribute-sets attribute (see ). This is used only when copying element nodes.

    The root node is treated specially because the root node of the result tree is created implicitly. When the current node is the root node, xsl:copy will not create a root node, but will just use the content template.

    For example, the identity transformation can be written using xsl:copy as follows:

    ]]>

    When the current node is an attribute, then if it would be an error to use xsl:attribute to create an attribute with the same name as the current node, then it is also an error to use xsl:copy (see ).

    The following example shows how xml:lang attributes can be easily copied through from source to result. If a stylesheet defines the following named template:

    ]]>

    then it can simply do

    ]]>

    instead of

    ]]>

    when it wants to copy the xml:lang attribute.

    Computing Generated Text

    Within a template, the xsl:value-of element can be used to compute generated text, for example by extracting text from the source tree or by inserting the value of a variable. The xsl:value-of element does this with an expression that is specified as the value of the select attribute. Expressions can also be used inside attribute values of literal result elements by enclosing the expression in curly braces ({}).

    Generating Text with xsl:value-of

    The xsl:value-of element is instantiated to create a text node in the result tree. The required select attribute is an expression; this expression is evaluated and the resulting object is converted to a string as if by a call to the string function. The string specifies the string-value of the created text node. If the string is empty, no text node will be created. The created text node will be merged with any adjacent text nodes.

    The xsl:copy-of element can be used to copy a node-set over to the result tree without converting it to a string. See .

    For example, the following creates an HTML paragraph from a person element with given-name and family-name attributes. The paragraph will contain the value of the given-name attribute of the current node followed by a space and the value of the family-name attribute of the current node.

    ]]>

    For another example, the following creates an HTML paragraph from a person element with given-name and family-name children elements. The paragraph will contain the string-value of the first given-name child element of the current node followed by a space and the string-value of the first family-name child element of the current node.

    ]]>

    The following precedes each procedure element with a paragraph containing the security level of the procedure. It assumes that the security level that applies to a procedure is determined by a security attribute on the procedure element or on an ancestor element of the procedure. It also assumes that if more than one such element has a security attribute then the security level is determined by the element that is closest to the procedure.

    ]]>
    Attribute Value Templates

    In an attribute value that is interpreted as an attribute value template, such as an attribute of a literal result element, an expression can be used by surrounding the expression with curly braces ({}). The attribute value template is instantiated by replacing the expression together with surrounding curly braces by the result of evaluating the expression and converting the resulting object to a string as if by a call to the string function. Curly braces are not recognized in an attribute value in an XSLT stylesheet unless the attribute is specifically stated to be one that is interpreted as an attribute value template; in an element syntax summary, the value of such attributes is surrounded by curly braces.

    Not all attributes are interpreted as attribute value templates. Attributes whose value is an expression or pattern, attributes of top-level elements and attributes that refer to named XSLT objects are not interpreted as attribute value templates. In addition, xmlns attributes are not interpreted as attribute value templates; it would not be conformant with the XML Namespaces Recommendation to do this.

    The following example creates an img result element from a photograph element in the source; the value of the src attribute of the img element is computed from the value of the image-dir variable and the string-value of the href child of the photograph element; the value of the width attribute of the img element is computed from the value of the width attribute of the size child of the photograph element:

    /images ]]>

    With this source

    headquarters.jpg ]]>

    the result would be

    ]]>

    When an attribute value template is instantiated, a double left or right curly brace outside an expression will be replaced by a single curly brace. It is an error if a right curly brace occurs in an attribute value template outside an expression without being followed by a second right curly brace. A right curly brace inside a Literal in an expression is not recognized as terminating the expression.

    Curly braces are not recognized recursively inside expressions. For example:

    ]]>

    is not allowed. Instead, use simply:

    ]]>
    Numbering

    The xsl:number element is used to insert a formatted number into the result tree. The number to be inserted may be specified by an expression. The value attribute contains an expression. The expression is evaluated and the resulting object is converted to a number as if by a call to the number function. The number is rounded to an integer and then converted to a string using the attributes specified in ; in this context, the value of each of these attributes is interpreted as an attribute value template. After conversion, the resulting string is inserted in the result tree. For example, the following example numbers a sorted list:

    ]]>

    If no value attribute is specified, then the xsl:number element inserts a number based on the position of the current node in the source tree. The following attributes control how the current node is to be numbered:

    The level attribute specifies what levels of the source tree should be considered; it has the values single, multiple or any. The default is single.

    The count attribute is a pattern that specifies what nodes should be counted at those levels. If count attribute is not specified, then it defaults to the pattern that matches any node with the same node type as the current node and, if the current node has an expanded-name, with the same expanded-name as the current node.

    The from attribute is a pattern that specifies where counting starts.

    In addition, the attributes specified in are used for number to string conversion, as in the case when the value attribute is specified.

    The xsl:number element first constructs a list of positive integers using the level, count and from attributes:

    When level="single", it goes up to the first node in the ancestor-or-self axis that matches the count pattern, and constructs a list of length one containing one plus the number of preceding siblings of that ancestor that match the count pattern. If there is no such ancestor, it constructs an empty list. If the from attribute is specified, then the only ancestors that are searched are those that are descendants of the nearest ancestor that matches the from pattern. Preceding siblings has the same meaning here as with the preceding-sibling axis.

    When level="multiple", it constructs a list of all ancestors of the current node in document order followed by the element itself; it then selects from the list those nodes that match the count pattern; it then maps each node in the list to one plus the number of preceding siblings of that node that match the count pattern. If the from attribute is specified, then the only ancestors that are searched are those that are descendants of the nearest ancestor that matches the from pattern. Preceding siblings has the same meaning here as with the preceding-sibling axis.

    When level="any", it constructs a list of length one containing the number of nodes that match the count pattern and belong to the set containing the current node and all nodes at any level of the document that are before the current node in document order, excluding any namespace and attribute nodes (in other words the union of the members of the preceding and ancestor-or-self axes). If the from attribute is specified, then only nodes after the first node before the current node that match the from pattern are considered.

    The list of numbers is then converted into a string using the attributes specified in ; in this context, the value of each of these attributes is interpreted as an attribute value template. After conversion, the resulting string is inserted in the result tree.

    The following would number the items in an ordered list:

    . ]]>

    The following two rules would number title elements. This is intended for a document that contains a sequence of chapters followed by a sequence of appendices, where both chapters and appendices contain sections, which in turn contain subsections. Chapters are numbered 1, 2, 3; appendices are numbered A, B, C; sections in chapters are numbered 1.1, 1.2, 1.3; sections in appendices are numbered A.1, A.2, A.3.

    ]]>

    The following example numbers notes sequentially within a chapter:

    ]]>

    The following example would number H4 elements in HTML with a three-part label:

    . . ]]> Number to String Conversion Attributes

    The following attributes are used to control conversion of a list of numbers into a string. The numbers are integers greater than 0. The attributes are all optional.

    The main attribute is format. The default value for the format attribute is 1. The format attribute is split into a sequence of tokens where each token is a maximal sequence of alphanumeric characters or a maximal sequence of non-alphanumeric characters. Alphanumeric means any character that has a Unicode category of Nd, Nl, No, Lu, Ll, Lt, Lm or Lo. The alphanumeric tokens (format tokens) specify the format to be used for each number in the list. If the first token is a non-alphanumeric token, then the constructed string will start with that token; if the last token is non-alphanumeric token, then the constructed string will end with that token. Non-alphanumeric tokens that occur between two format tokens are separator tokens that are used to join numbers in the list. The nth format token will be used to format the nth number in the list. If there are more numbers than format tokens, then the last format token will be used to format remaining numbers. If there are no format tokens, then a format token of 1 is used to format all numbers. The format token specifies the string to be used to represent the number 1. Each number after the first will be separated from the preceding number by the separator token preceding the format token used to format that number, or, if there are no separator tokens, then by . (a period character).

    Format tokens are a superset of the allowed values for the type attribute for the OL element in HTML 4.0 and are interpreted as follows:

    Any token where the last character has a decimal digit value of 1 (as specified in the Unicode character property database), and the Unicode value of preceding characters is one less than the Unicode value of the last character generates a decimal representation of the number where each number is at least as long as the format token. Thus, a format token 1 generates the sequence 1 2 ... 10 11 12 ..., and a format token 01 generates the sequence 01 02 ... 09 10 11 12 ... 99 100 101.

    A format token A generates the sequence A B C ... Z AA AB AC....

    A format token a generates the sequence a b c ... z aa ab ac....

    A format token i generates the sequence i ii iii iv v vi vii viii ix x ....

    A format token I generates the sequence I II III IV V VI VII VIII IX X ....

    Any other format token indicates a numbering sequence that starts with that token. If an implementation does not support a numbering sequence that starts with that token, it must use a format token of 1.

    When numbering with an alphabetic sequence, the lang attribute specifies which language's alphabet is to be used; it has the same range of values as xml:lang ; if no lang value is specified, the language should be determined from the system environment. Implementers should document for which languages they support numbering.

    Implementers should not make any assumptions about how numbering works in particular languages and should properly research the languages that they wish to support. The numbering conventions of many languages are very different from English.

    The letter-value attribute disambiguates between numbering sequences that use letters. In many languages there are two commonly used numbering sequences that use letters. One numbering sequence assigns numeric values to letters in alphabetic sequence, and the other assigns numeric values to each letter in some other manner traditional in that language. In English, these would correspond to the numbering sequences specified by the format tokens a and i. In some languages, the first member of each sequence is the same, and so the format token alone would be ambiguous. A value of alphabetic specifies the alphabetic sequence; a value of traditional specifies the other sequence. If the letter-value attribute is not specified, then it is implementation-dependent how any ambiguity is resolved.

    It is possible for two conforming XSLT processors not to convert a number to exactly the same string. Some XSLT processors may not support some languages. Furthermore, there may be variations possible in the way conversions are performed for any particular language that are not specifiable by the attributes on xsl:number. Future versions of XSLT may provide additional attributes to provide control over these variations. Implementations may also use implementation-specific namespaced attributes on xsl:number for this.

    The grouping-separator attribute gives the separator used as a grouping (e.g. thousands) separator in decimal numbering sequences, and the optional grouping-size specifies the size (normally 3) of the grouping. For example, grouping-separator="," and grouping-size="3" would produce numbers of the form 1,000,000. If only one of the grouping-separator and grouping-size attributes is specified, then it is ignored.

    Here are some examples of conversion specifications:

    format="&#x30A2;" specifies Katakana numbering

    format="&#x30A4;" specifies Katakana numbering in the iroha order

    format="&#x0E51;" specifies numbering with Thai digits

    format="&#x05D0;" letter-value="traditional" specifies traditional Hebrew numbering

    format="&#x10D0;" letter-value="traditional" specifies Georgian numbering

    format="&#x03B1;" letter-value="traditional" specifies classical Greek numbering

    format="&#x0430;" letter-value="traditional" specifies Old Slavic numbering

    Repetition

    When the result has a known regular structure, it is useful to be able to specify directly the template for selected nodes. The xsl:for-each instruction contains a template, which is instantiated for each node selected by the expression specified by the select attribute. The select attribute is required. The expression must evaluate to a node-set. The template is instantiated with the selected node as the current node, and with a list of all of the selected nodes as the current node list. The nodes are processed in document order, unless a sorting specification is present (see ).

    For example, given an XML document with this structure

    ... ... ... ... ... ... ]]>

    the following would create an HTML document containing a table with a row for each customer element

    Customers
    ]]>
    Conditional Processing

    There are two instructions in XSLT that support conditional processing in a template: xsl:if and xsl:choose. The xsl:if instruction provides simple if-then conditionality; the xsl:choose instruction supports selection of one choice when there are several possibilities.

    Conditional Processing with xsl:if

    The xsl:if element has a test attribute, which specifies an expression. The content is a template. The expression is evaluated and the resulting object is converted to a boolean as if by a call to the boolean function. If the result is true, then the content template is instantiated; otherwise, nothing is created. In the following example, the names in a group of names are formatted as a comma separated list:

    , ]]>

    The following colors every other table row yellow:

    yellow ]]>
    Conditional Processing with xsl:choose

    The xsl:choose element selects one among a number of possible alternatives. It consists of a sequence of xsl:when elements followed by an optional xsl:otherwise element. Each xsl:when element has a single attribute, test, which specifies an expression. The content of the xsl:when and xsl:otherwise elements is a template. When an xsl:choose element is processed, each of the xsl:when elements is tested in turn, by evaluating the expression and converting the resulting object to a boolean as if by a call to the boolean function. The content of the first, and only the first, xsl:when element whose test is true is instantiated. If no xsl:when is true, the content of the xsl:otherwise element is instantiated. If no xsl:when element is true, and no xsl:otherwise element is present, nothing is created.

    The following example enumerates items in an ordered list using arabic numerals, letters, or roman numerals depending on the depth to which the ordered lists are nested.

    . ]]>
    Sorting

    Sorting is specified by adding xsl:sort elements as children of an xsl:apply-templates or xsl:for-each element. The first xsl:sort child specifies the primary sort key, the second xsl:sort child specifies the secondary sort key and so on. When an xsl:apply-templates or xsl:for-each element has one or more xsl:sort children, then instead of processing the selected nodes in document order, it sorts the nodes according to the specified sort keys and then processes them in sorted order. When used in xsl:for-each, xsl:sort elements must occur first. When a template is instantiated by xsl:apply-templates and xsl:for-each, the current node list list consists of the complete list of nodes being processed in sorted order.

    xsl:sort has a select attribute whose value is an expression. For each node to be processed, the expression is evaluated with that node as the current node and with the complete list of nodes being processed in unsorted order as the current node list. The resulting object is converted to a string as if by a call to the string function; this string is used as the sort key for that node. The default value of the select attribute is ., which will cause the string-value of the current node to be used as the sort key.

    This string serves as a sort key for the node. The following optional attributes on xsl:sort control how the list of sort keys are sorted; the values of all of these attributes are interpreted as attribute value templates.

    order specifies whether the strings should be sorted in ascending or descending order; ascending specifies ascending order; descending specifies descending order; the default is ascending

    lang specifies the language of the sort keys; it has the same range of values as xml:lang ; if no lang value is specified, the language should be determined from the system environment

    data-type specifies the data type of the strings; the following values are allowed:

    text specifies that the sort keys should be sorted lexicographically in the culturally correct manner for the language specified by lang

    number specifies that the sort keys should be converted to numbers and then sorted according to the numeric value; the sort key is converted to a number as if by a call to the number function; the lang attribute is ignored

    a QName with a prefix is expanded into an expanded-name as described in ; the expanded-name identifies the data-type; the behavior in this case is not specified by this document

    The default value is text.

    The XSL Working Group plans that future versions of XSLT will leverage XML Schemas to define further values for this attribute.

    case-order has the value upper-first or lower-first; this applies when data-type="text", and specifies that upper-case letters should sort before lower-case letters or vice-versa respectively. For example, if lang="en", then A a B b are sorted with case-order="upper-first" and a A b B are sorted with case-order="lower-first". The default value is language dependent.

    It is possible for two conforming XSLT processors not to sort exactly the same. Some XSLT processors may not support some languages. Furthermore, there may be variations possible in the sorting of any particular language that are not specified by the attributes on xsl:sort, for example, whether Hiragana or Katakana is sorted first in Japanese. Future versions of XSLT may provide additional attributes to provide control over these variations. Implementations may also use implementation-specific namespaced attributes on xsl:sort for this.

    It is recommended that implementers consult for information on internationalized sorting.

    The sort must be stable: in the sorted list of nodes, any sub list that has sort keys that all compare equal must be in document order.

    For example, suppose an employee database has the form

    James Clark ... ]]>

    Then a list of employees sorted by name could be generated using:

  • ]]>
    Variables and Parameters

    A variable is a name that may be bound to a value. The value to which a variable is bound (the value of the variable) can be an object of any of the types that can be returned by expressions. There are two elements that can be used to bind variables: xsl:variable and xsl:param. The difference is that the value specified on the xsl:param variable is only a default value for the binding; when the template or stylesheet within which the xsl:param element occurs is invoked, parameters may be passed that are used in place of the default values.

    Both xsl:variable and xsl:param have a required name attribute, which specifies the name of the variable. The value of the name attribute is a QName, which is expanded as described in .

    For any use of these variable-binding elements, there is a region of the stylesheet tree within which the binding is visible; within this region, any binding of the variable that was visible on the variable-binding element itself is hidden. Thus, only the innermost binding of a variable is visible. The set of variable bindings in scope for an expression consists of those bindings that are visible at the point in the stylesheet where the expression occurs.

    Result Tree Fragments

    Variables introduce an additional data-type into the expression language. This additional data type is called result tree fragment. A variable may be bound to a result tree fragment instead of one of the four basic XPath data-types (string, number, boolean, node-set). A result tree fragment represents a fragment of the result tree. A result tree fragment is treated equivalently to a node-set that contains just a single root node. However, the operations permitted on a result tree fragment are a subset of those permitted on a node-set. An operation is permitted on a result tree fragment only if that operation would be permitted on a string (the operation on the string may involve first converting the string to a number or boolean). In particular, it is not permitted to use the /, //, and [] operators on result tree fragments. When a permitted operation is performed on a result tree fragment, it is performed exactly as it would be on the equivalent node-set.

    When a result tree fragment is copied into the result tree (see ), then all the nodes that are children of the root node in the equivalent node-set are added in sequence to the result tree.

    Expressions can only return values of type result tree fragment by referencing variables of type result tree fragment or calling extension functions that return a result tree fragment or getting a system property whose value is a result tree fragment.

    Values of Variables and Parameters

    A variable-binding element can specify the value of the variable in three alternative ways.

    If the variable-binding element has a select attribute, then the value of the attribute must be an expression and the value of the variable is the object that results from evaluating the expression. In this case, the content must be empty.

    If the variable-binding element does not have a select attribute and has non-empty content (i.e. the variable-binding element has one or more child nodes), then the content of the variable-binding element specifies the value. The content of the variable-binding element is a template, which is instantiated to give the value of the variable. The value is a result tree fragment equivalent to a node-set containing just a single root node having as children the sequence of nodes produced by instantiating the template. The base URI of the nodes in the result tree fragment is the base URI of the variable-binding element.

    It is an error if a member of the sequence of nodes created by instantiating the template is an attribute node or a namespace node, since a root node cannot have an attribute node or a namespace node as a child. An XSLT processor may signal the error; if it does not signal the error, it must recover by not adding the attribute node or namespace node.

    If the variable-binding element has empty content and does not have a select attribute, then the value of the variable is an empty string. Thus

    ]]>

    is equivalent to

    ]]>

    When a variable is used to select nodes by position, be careful not to do:

    2 ... ]]>

    This will output the value of the first item element, because the variable n will be bound to a result tree fragment, not a number. Instead, do either

    ... ]]>

    or

    2 ... ]]>

    One convenient way to specify the empty node-set as the default value of a parameter is:

    ]]>
    Using Values of Variables and Parameters with xsl:copy-of

    The xsl:copy-of element can be used to insert a result tree fragment into the result tree, without first converting it to a string as xsl:value-of does (see ). The required select attribute contains an expression. When the result of evaluating the expression is a result tree fragment, the complete fragment is copied into the result tree. When the result is a node-set, all the nodes in the set are copied in document order into the result tree; copying an element node copies the attribute nodes, namespace nodes and children of the element node as well as the element node itself; a root node is copied by copying its children. When the result is neither a node-set nor a result tree fragment, the result is converted to a string and then inserted into the result tree, as with xsl:value-of.

    Top-level Variables and Parameters

    Both xsl:variable and xsl:param are allowed as top-level elements. A top-level variable-binding element declares a global variable that is visible everywhere. A top-level xsl:param element declares a parameter to the stylesheet; XSLT does not define the mechanism by which parameters are passed to the stylesheet. It is an error if a stylesheet contains more than one binding of a top-level variable with the same name and same import precedence. At the top-level, the expression or template specifying the variable value is evaluated with the same context as that used to process the root node of the source document: the current node is the root node of the source document and the current node list is a list containing just the root node of the source document. If the template or expression specifying the value of a global variable x references a global variable y, then the value for y must be computed before the value of x. It is an error if it is impossible to do this for all global variable definitions; in other words, it is an error if the definitions are circular.

    This example declares a global variable para-font-size, which it references in an attribute value template.

    12pt ]]>
    Variables and Parameters within Templates

    As well as being allowed at the top-level, both xsl:variable and xsl:param are also allowed in templates. xsl:variable is allowed anywhere within a template that an instruction is allowed. In this case, the binding is visible for all following siblings and their descendants. Note that the binding is not visible for the xsl:variable element itself. xsl:param is allowed as a child at the beginning of an xsl:template element. In this context, the binding is visible for all following siblings and their descendants. Note that the binding is not visible for the xsl:param element itself.

    A binding shadows another binding if the binding occurs at a point where the other binding is visible, and the bindings have the same name. It is an error if a binding established by an xsl:variable or xsl:param element within a template shadows another binding established by an xsl:variable or xsl:param element also within the template. It is not an error if a binding established by an xsl:variable or xsl:param element in a template shadows another binding established by an xsl:variable or xsl:param top-level element. Thus, the following is an error:

    ]]>

    However, the following is allowed:

    ]]>

    The nearest equivalent in Java to an xsl:variable element in a template is a final local variable declaration with an initializer. For example,

    ]]>

    has similar semantics to

    final Object x = "value";

    XSLT does not provide an equivalent to the Java assignment operator

    x = "value";

    because this would make it harder to create an implementation that processes a document other than in a batch-like way, starting at the beginning and continuing through to the end.

    Passing Parameters to Templates

    Parameters are passed to templates using the xsl:with-param element. The required name attribute specifies the name of the parameter (the variable the value of whose binding is to be replaced). The value of the name attribute is a QName, which is expanded as described in . xsl:with-param is allowed within both xsl:call-template and xsl:apply-templates. The value of the parameter is specified in the same way as for xsl:variable and xsl:param. The current node and current node list used for computing the value specified by xsl:with-param element is the same as that used for the xsl:apply-templates or xsl:call-template element within which it occurs. It is not an error to pass a parameter x to a template that does not have an xsl:param element for x; the parameter is simply ignored.

    This example defines a named template for a numbered-block with an argument to control the format of the number.

    1. a. ]]>
    Additional Functions

    This section describes XSLT-specific additions to the core XPath function library. Some of these additional functions also make use of information specified by top-level elements in the stylesheet; this section also describes these elements.

    Multiple Source Documents

    The document function allows access to XML documents other than the main source document.

    When the document function has exactly one argument and the argument is a node-set, then the result is the union, for each node in the argument node-set, of the result of calling the document function with the first argument being the string-value of the node, and the second argument being a node-set with the node as its only member. When the document function has two arguments and the first argument is a node-set, then the result is the union, for each node in the argument node-set, of the result of calling the document function with the first argument being the string-value of the node, and with the second argument being the second argument passed to the document function.

    When the first argument to the document function is not a node-set, the first argument is converted to a string as if by a call to the string function. This string is treated as a URI reference; the resource identified by the URI is retrieved. The data resulting from the retrieval action is parsed as an XML document and a tree is constructed in accordance with the data model (see ). If there is an error retrieving the resource, then the XSLT processor may signal an error; if it does not signal an error, it must recover by returning an empty node-set. One possible kind of retrieval error is that the XSLT processor does not support the URI scheme used by the URI. An XSLT processor is not required to support any particular URI schemes. The documentation for an XSLT processor should specify which URI schemes the XSLT processor supports.

    If the URI reference does not contain a fragment identifier, then a node-set containing just the root node of the document is returned. If the URI reference does contain a fragment identifier, the function returns a node-set containing the nodes in the tree identified by the fragment identifier of the URI reference. The semantics of the fragment identifier is dependent on the media type of the result of retrieving the URI. If there is an error in processing the fragment identifier, the XSLT processor may signal the error; if it does not signal the error, it must recover by returning an empty node-set. Possible errors include:

    The fragment identifier identifies something that cannot be represented by an XSLT node-set (such as a range of characters within a text node).

    The XSLT processor does not support fragment identifiers for the media-type of the retrieval result. An XSLT processor is not required to support any particular media types. The documentation for an XSLT processor should specify for which media types the XSLT processor supports fragment identifiers.

    The data resulting from the retrieval action is parsed as an XML document regardless of the media type of the retrieval result; if the top-level media type is text, then it is parsed in the same way as if the media type were text/xml; otherwise, it is parsed in the same way as if the media type were application/xml.

    Since there is no top-level xml media type, data with a media type other than text/xml or application/xml may in fact be XML.

    The URI reference may be relative. The base URI (see ) of the node in the second argument node-set that is first in document order is used as the base URI for resolving the relative URI into an absolute URI. If the second argument is omitted, then it defaults to the node in the stylesheet that contains the expression that includes the call to the document function. Note that a zero-length URI reference is a reference to the document relative to which the URI reference is being resolved; thus document("") refers to the root node of the stylesheet; the tree representation of the stylesheet is exactly the same as if the XML document containing the stylesheet was the initial source document.

    Two documents are treated as the same document if they are identified by the same URI. The URI used for the comparison is the absolute URI into which any relative URI was resolved and does not include any fragment identifier. One root node is treated as the same node as another root node if the two nodes are from the same document. Thus, the following expression will always be true:

    generate-id(document("foo.xml"))=generate-id(document("foo.xml"))

    The document function gives rise to the possibility that a node-set may contain nodes from more than one document. With such a node-set, the relative document order of two nodes in the same document is the normal document order defined by XPath . The relative document order of two nodes in different documents is determined by an implementation-dependent ordering of the documents containing the two nodes. There are no constraints on how the implementation orders documents other than that it must do so consistently: an implementation must always use the same order for the same set of documents.

    Keys

    Keys provide a way to work with documents that contain an implicit cross-reference structure. The ID, IDREF and IDREFS attribute types in XML provide a mechanism to allow XML documents to make their cross-reference explicit. XSLT supports this through the XPath id function. However, this mechanism has a number of limitations:

    ID attributes must be declared as such in the DTD. If an ID attribute is declared as an ID attribute only in the external DTD subset, then it will be recognized as an ID attribute only if the XML processor reads the external DTD subset. However, XML does not require XML processors to read the external DTD, and they may well choose not to do so, especially if the document is declared standalone="yes".

    A document can contain only a single set of unique IDs. There cannot be separate independent sets of unique IDs.

    The ID of an element can only be specified in an attribute; it cannot be specified by the content of the element, or by a child element.

    An ID is constrained to be an XML name. For example, it cannot contain spaces.

    An element can have at most one ID.

    At most one element can have a particular ID.

    Because of these limitations XML documents sometimes contain a cross-reference structure that is not explicitly declared by ID/IDREF/IDREFS attributes.

    A key is a triple containing:

    the node which has the key

    the name of the key (an expanded-name)

    the value of the key (a string)

    A stylesheet declares a set of keys for each document using the xsl:key element. When this set of keys contains a member with node x, name y and value z, we say that node x has a key with name y and value z.

    Thus, a key is a kind of generalized ID, which is not subject to the same limitations as an XML ID:

    Keys are declared in the stylesheet using xsl:key elements.

    A key has a name as well as a value; each key name may be thought of as distinguishing a separate, independent space of identifiers.

    The value of a named key for an element may be specified in any convenient place; for example, in an attribute, in a child element or in content. An XPath expression is used to specify where to find the value for a particular named key.

    The value of a key can be an arbitrary string; it is not constrained to be a name.

    There can be multiple keys in a document with the same node, same key name, but different key values.

    There can be multiple keys in a document with the same key name, same key value, but different nodes.

    The xsl:key element is used to declare keys. The name attribute specifies the name of the key. The value of the name attribute is a QName, which is expanded as described in . The match attribute is a Pattern; an xsl:key element gives information about the keys of any node that matches the pattern specified in the match attribute. The use attribute is an expression specifying the values of the key; the expression is evaluated once for each node that matches the pattern. If the result is a node-set, then for each node in the node-set, the node that matches the pattern has a key of the specified name whose value is the string-value of the node in the node-set; otherwise, the result is converted to a string, and the node that matches the pattern has a key of the specified name with value equal to that string. Thus, a node x has a key with name y and value z if and only if there is an xsl:key element such that:

    x matches the pattern specified in the match attribute of the xsl:key element;

    the value of the name attribute of the xsl:key element is equal to y; and

    when the expression specified in the use attribute of the xsl:key element is evaluated with x as the current node and with a node list containing just x as the current node list resulting in an object u, then either z is equal to the result of converting u to a string as if by a call to the string function, or u is a node-set and z is equal to the string-value of one or more of the nodes in u.

    Note also that there may be more than one xsl:key element that matches a given node; all of the matching xsl:key elements are used, even if they do not have the same import precedence.

    It is an error for the value of either the use attribute or the match attribute to contain a VariableReference.

    The key function does for keys what the id function does for IDs. The first argument specifies the name of the key. The value of the argument must be a QName, which is expanded as described in . When the second argument to the key function is of type node-set, then the result is the union of the result of applying the key function to the string value of each of the nodes in the argument node-set. When the second argument to key is of any other type, the argument is converted to a string as if by a call to the string function; it returns a node-set containing the nodes in the same document as the context node that have a value for the named key equal to this string.

    For example, given a declaration

    ]]>

    an expression key("idkey",@ref) will return the same node-set as id(@ref), assuming that the only ID attribute declared in the XML source document is:

    ]]>

    and that the ref attribute of the current node contains no whitespace.

    Suppose a document describing a function library uses a prototype element to define functions

    ]]>

    and a function element to refer to function names

    key]]>

    Then the stylesheet could generate hyperlinks between the references and definitions as follows:

    Function: ...

    ]]>

    The key can be used to retrieve a key from a document other than the document containing the context node. For example, suppose a document contains bibliographic references in the form XSLT]]>, and there is a separate XML document bib.xml containing a bibliographic database with entries in the form:

    ...]]>

    Then the stylesheet could use the following to transform the bibref elements:

    ]]>
    Number Formatting

    The format-number function converts its first argument to a string using the format pattern string specified by the second argument and the decimal-format named by the third argument, or the default decimal-format, if there is no third argument. The format pattern string is in the syntax specified by the JDK 1.1 DecimalFormat class. The format pattern string is in a localized notation: the decimal-format determines what characters have a special meaning in the pattern (with the exception of the quote character, which is not localized). The format pattern must not contain the currency sign (#x00A4); support for this feature was added after the initial release of JDK 1.1. The decimal-format name must be a QName, which is expanded as described in . It is an error if the stylesheet does not contain a declaration of the decimal-format with the specified expanded-name.

    Implementations are not required to use the JDK 1.1 implementation, nor are implementations required to be implemented in Java.

    Stylesheets can use other facilities in XPath to control rounding.

    The xsl:decimal-format element declares a decimal-format, which controls the interpretation of a format pattern used by the format-number function. If there is a name attribute, then the element declares a named decimal-format; otherwise, it declares the default decimal-format. The value of the name attribute is a QName, which is expanded as described in . It is an error to declare either the default decimal-format or a decimal-format with a given name more than once (even with different import precedence), unless it is declared every time with the same value for all attributes (taking into account any default values).

    The other attributes on xsl:decimal-format correspond to the methods on the JDK 1.1 DecimalFormatSymbols class. For each get/set method pair there is an attribute defined for the xsl:decimal-format element.

    The following attributes both control the interpretation of characters in the format pattern and specify characters that may appear in the result of formatting the number:

    decimal-separator specifies the character used for the decimal sign; the default value is the period character (.)

    grouping-separator specifies the character used as a grouping (e.g. thousands) separator; the default value is the comma character (,)

    percent specifies the character used as a percent sign; the default value is the percent character (%)

    per-mille specifies the character used as a per mille sign; the default value is the Unicode per-mille character (#x2030)

    zero-digit specifies the character used as the digit zero; the default value is the digit zero (0)

    The following attributes control the interpretation of characters in the format pattern:

    digit specifies the character used for a digit in the format pattern; the default value is the number sign character (#)

    pattern-separator specifies the character used to separate positive and negative sub patterns in a pattern; the default value is the semi-colon character (;)

    The following attributes specify characters or strings that may appear in the result of formatting the number:

    infinity specifies the string used to represent infinity; the default value is the string Infinity

    NaN specifies the string used to represent the NaN value; the default value is the string NaN

    minus-sign specifies the character used as the default minus sign; the default value is the hyphen-minus character (-, #x2D)

    Miscellaneous Additional Functions

    The current function returns a node-set that has the current node as its only member. For an outermost expression (an expression not occurring within another expression), the current node is always the same as the context node. Thus,

    ]]>

    means the same as

    ]]>

    However, within square brackets the current node is usually different from the context node. For example,

    ]]>

    will process all item elements that have a glossary parent element and that have a name attribute with value equal to the value of the current node's ref attribute. This is different from

    ]]>

    which means the same as

    ]]>

    and so would process all item elements that have a glossary parent element and that have a name attribute and a ref attribute with the same value.

    It is an error to use the current function in a pattern.

    The unparsed-entity-uri returns the URI of the unparsed entity with the specified name in the same document as the context node (see ). It returns the empty string if there is no such entity.

    The generate-id function returns a string that uniquely identifies the node in the argument node-set that is first in document order. The unique identifier must consist of ASCII alphanumeric characters and must start with an alphabetic character. Thus, the string is syntactically an XML name. An implementation is free to generate an identifier in any convenient way provided that it always generates the same identifier for the same node and that different identifiers are always generated from different nodes. An implementation is under no obligation to generate the same identifiers each time a document is transformed. There is no guarantee that a generated unique identifier will be distinct from any unique IDs specified in the source document. If the argument node-set is empty, the empty string is returned. If the argument is omitted, it defaults to the context node.

    The argument must evaluate to a string that is a QName. The QName is expanded into a name using the namespace declarations in scope for the expression. The system-property function returns an object representing the value of the system property identified by the name. If there is no such system property, the empty string should be returned.

    Implementations must provide the following system properties, which are all in the XSLT namespace:

    xsl:version, a number giving the version of XSLT implemented by the processor; for XSLT processors implementing the version of XSLT specified by this document, this is the number 1.0 xsl:vendor, a string identifying the vendor of the XSLT processor xsl:vendor-url, a string containing a URL identifying the vendor of the XSLT processor; typically this is the host page (home page) of the vendor's Web site.
    Messages

    The xsl:message instruction sends a message in a way that is dependent on the XSLT processor. The content of the xsl:message instruction is a template. The xsl:message is instantiated by instantiating the content to create an XML fragment. This XML fragment is the content of the message.

    An XSLT processor might implement xsl:message by popping up an alert box or by writing to a log file.

    If the terminate attribute has the value yes, then the XSLT processor should terminate processing after sending the message. The default value is no.

    One convenient way to do localization is to put the localized information (message text, etc.) in an XML document, which becomes an additional input file to the stylesheet. For example, suppose messages for a language L are stored in an XML file resources/L.xml in the form:

    A problem was detected. An error was detected. ]]>

    Then a stylesheet could use the following approach to localize messages:

    problem ]]>
    Extensions

    XSLT allows two kinds of extension, extension elements and extension functions.

    This version of XSLT does not provide a mechanism for defining implementations of extensions. Therefore, an XSLT stylesheet that must be portable between XSLT implementations cannot rely on particular extensions being available. XSLT provides mechanisms that allow an XSLT stylesheet to determine whether the XSLT processor by which it is being processed has implementations of particular extensions available, and to specify what should happen if those extensions are not available. If an XSLT stylesheet is careful to make use of these mechanisms, it is possible for it to take advantage of extensions and still work with any XSLT implementation.

    Extension Elements

    The element extension mechanism allows namespaces to be designated as extension namespaces. When a namespace is designated as an extension namespace and an element with a name from that namespace occurs in a template, then the element is treated as an instruction rather than as a literal result element. The namespace determines the semantics of the instruction.

    Since an element that is a child of an xsl:stylesheet element is not occurring in a template, non-XSLT top-level elements are not extension elements as defined here, and nothing in this section applies to them.

    A namespace is designated as an extension namespace by using an extension-element-prefixes attribute on an xsl:stylesheet element or an xsl:extension-element-prefixes attribute on a literal result element or extension element. The value of both these attributes is a whitespace-separated list of namespace prefixes. The namespace bound to each of the prefixes is designated as an extension namespace. It is an error if there is no namespace bound to the prefix on the element bearing the extension-element-prefixes or xsl:extension-element-prefixes attribute. The default namespace (as declared by xmlns) may be designated as an extension namespace by including #default in the list of namespace prefixes. The designation of a namespace as an extension namespace is effective within the subtree of the stylesheet rooted at the element bearing the extension-element-prefixes or xsl:extension-element-prefixes attribute; a subtree rooted at an xsl:stylesheet element does not include any stylesheets imported or included by children of that xsl:stylesheet element.

    If the XSLT processor does not have an implementation of a particular extension element available, then the element-available function must return false for the name of the element. When such an extension element is instantiated, then the XSLT processor must perform fallback for the element as specified in . An XSLT processor must not signal an error merely because a template contains an extension element for which no implementation is available.

    If the XSLT processor has an implementation of a particular extension element available, then the element-available function must return true for the name of the element.

    Extension Functions

    If a FunctionName in a FunctionCall expression is not an NCName (i.e. if it contains a colon), then it is treated as a call to an extension function. The FunctionName is expanded to a name using the namespace declarations from the evaluation context.

    If the XSLT processor does not have an implementation of an extension function of a particular name available, then the function-available function must return false for that name. If such an extension function occurs in an expression and the extension function is actually called, the XSLT processor must signal an error. An XSLT processor must not signal an error merely because an expression contains an extension function for which no implementation is available.

    If the XSLT processor has an implementation of an extension function of a particular name available, then the function-available function must return true for that name. If such an extension is called, then the XSLT processor must call the implementation passing it the function call arguments; the result returned by the implementation is returned as the result of the function call.

    Fallback

    Normally, instantiating an xsl:fallback element does nothing. However, when an XSLT processor performs fallback for an instruction element, if the instruction element has one or more xsl:fallback children, then the content of each of the xsl:fallback children must be instantiated in sequence; otherwise, an error must be signaled. The content of an xsl:fallback element is a template.

    The following functions can be used with the xsl:choose and xsl:if instructions to explicitly control how a stylesheet should behave if particular elements or functions are not available.

    The argument must evaluate to a string that is a QName. The QName is expanded into an expanded-name using the namespace declarations in scope for the expression. The element-available function returns true if and only if the expanded-name is the name of an instruction. If the expanded-name has a namespace URI equal to the XSLT namespace URI, then it refers to an element defined by XSLT. Otherwise, it refers to an extension element. If the expanded-name has a null namespace URI, the element-available function will return false.

    The argument must evaluate to a string that is a QName. The QName is expanded into an expanded-name using the namespace declarations in scope for the expression. The function-available function returns true if and only if the expanded-name is the name of a function in the function library. If the expanded-name has a non-null namespace URI, then it refers to an extension function; otherwise, it refers to a function defined by XPath or XSLT.

    Output

    An XSLT processor may output the result tree as a sequence of bytes, although it is not required to be able to do so (see ). The xsl:output element allows stylesheet authors to specify how they wish the result tree to be output. If an XSLT processor outputs the result tree, it should do so as specified by the xsl:output element; however, it is not required to do so.

    The xsl:output element is only allowed as a top-level element.

    The method attribute on xsl:output identifies the overall method that should be used for outputting the result tree. The value must be a QName. If the QName does not have a prefix, then it identifies a method specified in this document and must be one of xml, html or text. If the QName has a prefix, then the QName is expanded into an expanded-name as described in ; the expanded-name identifies the output method; the behavior in this case is not specified by this document.

    The default for the method attribute is chosen as follows. If

    the root node of the result tree has an element child,

    the expanded-name of the first element child of the root node (i.e. the document element) of the result tree has local part html (in any combination of upper and lower case) and a null namespace URI, and

    any text nodes preceding the first element child of the root node of the result tree contain only whitespace characters,

    then the default output method is html; otherwise, the default output method is xml. The default output method should be used if there are no xsl:output elements or if none of the xsl:output elements specifies a value for the method attribute.

    The other attributes on xsl:output provide parameters for the output method. The following attributes are allowed:

    version specifies the version of the output method

    indent specifies whether the XSLT processor may add additional whitespace when outputting the result tree; the value must be yes or no

    encoding specifies the preferred character encoding that the XSLT processor should use to encode sequences of characters as sequences of bytes; the value of the attribute should be treated case-insensitively; the value must contain only characters in the range #x21 to #x7E (i.e. printable ASCII characters); the value should either be a charset registered with the Internet Assigned Numbers Authority , or start with X-

    media-type specifies the media type (MIME content type) of the data that results from outputting the result tree; the charset parameter should not be specified explicitly; instead, when the top-level media type is text, a charset parameter should be added according to the character encoding actually used by the output method

    doctype-system specifies the system identifier to be used in the document type declaration

    doctype-public specifies the public identifier to be used in the document type declaration

    omit-xml-declaration specifies whether the XSLT processor should output an XML declaration; the value must be yes or no

    standalone specifies whether the XSLT processor should output a standalone document declaration; the value must be yes or no

    cdata-section-elements specifies a list of the names of elements whose text node children should be output using CDATA sections

    The detailed semantics of each attribute will be described separately for each output method for which it is applicable. If the semantics of an attribute are not described for an output method, then it is not applicable to that output method.

    A stylesheet may contain multiple xsl:output elements and may include or import stylesheets that also contain xsl:output elements. All the xsl:output elements occurring in a stylesheet are merged into a single effective xsl:output element. For the cdata-section-elements attribute, the effective value is the union of the specified values. For other attributes, the effective value is the specified value with the highest import precedence. It is an error if there is more than one such value for an attribute. An XSLT processor may signal the error; if it does not signal the error, if should recover by using the value that occurs last in the stylesheet. The values of attributes are defaulted after the xsl:output elements have been merged; different output methods may have different default values for an attribute.

    XML Output Method

    The xml output method outputs the result tree as a well-formed XML external general parsed entity. If the root node of the result tree has a single element node child and no text node children, then the entity should also be a well-formed XML document entity. When the entity is referenced within a trivial XML document wrapper like this

    entity-URI ]> &e;]]>

    where entity-URI is a URI for the entity, then the wrapper document as a whole should be a well-formed XML document conforming to the XML Namespaces Recommendation . In addition, the output should be such that if a new tree was constructed by parsing the wrapper as an XML document as specified in , and then removing the document element, making its children instead be children of the root node, then the new tree would be the same as the result tree, with the following possible exceptions:

    The order of attributes in the two trees may be different.

    The new tree may contain namespace nodes that were not present in the result tree.

    An XSLT processor may need to add namespace declarations in the course of outputting the result tree as XML.

    If the XSLT processor generated a document type declaration because of the doctype-system attribute, then the above requirements apply to the entity with the generated document type declaration removed.

    The version attribute specifies the version of XML to be used for outputting the result tree. If the XSLT processor does not support this version of XML, it should use a version of XML that it does support. The version output in the XML declaration (if an XML declaration is output) should correspond to the version of XML that the processor used for outputting the result tree. The value of the version attribute should match the VersionNum production of the XML Recommendation . The default value is 1.0.

    The encoding attribute specifies the preferred encoding to use for outputting the result tree. XSLT processors are required to respect values of UTF-8 and UTF-16. For other values, if the XSLT processor does not support the specified encoding it may signal an error; if it does not signal an error it should use UTF-8 or UTF-16 instead. The XSLT processor must not use an encoding whose name does not match the EncName production of the XML Recommendation . If no encoding attribute is specified, then the XSLT processor should use either UTF-8 or UTF-16. It is possible that the result tree will contain a character that cannot be represented in the encoding that the XSLT processor is using for output. In this case, if the character occurs in a context where XML recognizes character references (i.e. in the value of an attribute node or text node), then the character should be output as a character reference; otherwise (for example if the character occurs in the name of an element) the XSLT processor should signal an error.

    If the indent attribute has the value yes, then the xml output method may output whitespace in addition to the whitespace in the result tree (possibly based on whitespace stripped from either the source document or the stylesheet) in order to indent the result nicely; if the indent attribute has the value no, it should not output any additional whitespace. The default value is no. The xml output method should use an algorithm to output additional whitespace that ensures that the result if whitespace were to be stripped from the output using the process described in with the set of whitespace-preserving elements consisting of just xsl:text would be the same when additional whitespace is output as when additional whitespace is not output.

    It is usually not safe to use indent="yes" with document types that include element types with mixed content.

    The cdata-section-elements attribute contains a whitespace-separated list of QNames. Each QName is expanded into an expanded-name using the namespace declarations in effect on the xsl:output element in which the QName occurs; if there is a default namespace, it is used for QNames that do not have a prefix. The expansion is performed before the merging of multiple xsl:output elements into a single effective xsl:output element. If the expanded-name of the parent of a text node is a member of the list, then the text node should be output as a CDATA section. For example,

    ]]>

    would cause a literal result element written in the stylesheet as

    <foo>]]>

    or as

    <example><![CDATA[<foo>]]></example>

    to be output as

    <example><![CDATA[<foo>]]></example>

    If the text node contains the sequence of characters ]]>, then the currently open CDATA section should be closed following the ]] and a new CDATA section opened before the >. For example, a literal result element written in the stylesheet as

    <example>]]&gt;</example>

    would be output as

    <example><![CDATA[]]]]><![CDATA[>]]></example>

    If the text node contains a character that is not representable in the character encoding being used to output the result tree, then the currently open CDATA section should be closed before the character, the character should be output using a character reference or entity reference, and a new CDATA section should be opened for any further characters in the text node.

    CDATA sections should not be used except for text nodes that the cdata-section-elements attribute explicitly specifies should be output using CDATA sections.

    The xml output method should output an XML declaration unless the omit-xml-declaration attribute has the value yes. The XML declaration should include both version information and an encoding declaration. If the standalone attribute is specified, it should include a standalone document declaration with the same value as the value as the value of the standalone attribute. Otherwise, it should not include a standalone document declaration; this ensures that it is both a XML declaration (allowed at the beginning of a document entity) and a text declaration (allowed at the beginning of an external general parsed entity).

    If the doctype-system attribute is specified, the xml output method should output a document type declaration immediately before the first element. The name following <!DOCTYPE should be the name of the first element. If doctype-public attribute is also specified, then the xml output method should output PUBLIC followed by the public identifier and then the system identifier; otherwise, it should output SYSTEM followed by the system identifier. The internal subset should be empty. The doctype-public attribute should be ignored unless the doctype-system attribute is specified.

    The media-type attribute is applicable for the xml output method. The default value for the media-type attribute is text/xml.

    HTML Output Method

    The html output method outputs the result tree as HTML; for example,

    <xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;"> ... ]]>

    The version attribute indicates the version of the HTML. The default value is 4.0, which specifies that the result should be output as HTML conforming to the HTML 4.0 Recommendation .

    The html output method should not output an element differently from the xml output method unless the expanded-name of the element has a null namespace URI; an element whose expanded-name has a non-null namespace URI should be output as XML. If the expanded-name of the element has a null namespace URI, but the local part of the expanded-name is not recognized as the name of an HTML element, the element should output in the same way as a non-empty, inline element such as span.

    The html output method should not output an end-tag for empty elements. For HTML 4.0, the empty elements are area, base, basefont, br, col, frame, hr, img, input, isindex, link, meta and param. For example, an element written as <br/> or <br></br> in the stylesheet should be output as <br>.

    The html output method should recognize the names of HTML elements regardless of case. For example, elements named br, BR or Br should all be recognized as the HTML br element and output without an end-tag.

    The html output method should not perform escaping for the content of the script and style elements. For example, a literal result element written in the stylesheet as

    if (a < b) foo()]]>

    or

    ]]>

    should be output as

    if (a < b) foo()]]>

    The html output method should not escape < characters occurring in attribute values.

    If the indent attribute has the value yes, then the html output method may add or remove whitespace as it outputs the result tree, so long as it does not change how an HTML user agent would render the output. The default value is yes.

    The html output method should escape non-ASCII characters in URI attribute values using the method recommended in Section B.2.1 of the HTML 4.0 Recommendation.

    The html output method may output a character using a character entity reference, if one is defined for it in the version of HTML that the output method is using.

    The html output method should terminate processing instructions with > rather than ?>.

    The html output method should output boolean attributes (that is attributes with only a single allowed value that is equal to the name of the attribute) in minimized form. For example, a start-tag written in the stylesheet as

    ]]>

    should be output as

    ]]>

    The html output method should not escape a & character occurring in an attribute value immediately followed by a { character (see Section B.7.1 of the HTML 4.0 Recommendation). For example, a start-tag written in the stylesheet as

    ]]>

    should be output as

    ]]>

    The encoding attribute specifies the preferred encoding to be used. If there is a HEAD element, then the html output method should add a META element immediately after the start-tag of the HEAD element specifying the character encoding actually used. For example,

    ...]]>

    It is possible that the result tree will contain a character that cannot be represented in the encoding that the XSLT processor is using for output. In this case, if the character occurs in a context where HTML recognizes character references, then the character should be output as a character entity reference or decimal numeric character reference; otherwise (for example, in a script or style element or in a comment), the XSLT processor should signal an error.

    If the doctype-public or doctype-system attributes are specified, then the html output method should output a document type declaration immediately before the first element. The name following <!DOCTYPE should be HTML or html. If the doctype-public attribute is specified, then the output method should output PUBLIC followed by the specified public identifier; if the doctype-system attribute is also specified, it should also output the specified system identifier following the public identifier. If the doctype-system attribute is specified but the doctype-public attribute is not specified, then the output method should output SYSTEM followed by the specified system identifier.

    The media-type attribute is applicable for the html output method. The default value is text/html.

    Text Output Method

    The text output method outputs the result tree by outputting the string-value of every text node in the result tree in document order without any escaping.

    The media-type attribute is applicable for the text output method. The default value for the media-type attribute is text/plain.

    The encoding attribute identifies the encoding that the text output method should use to convert sequences of characters to sequences of bytes. The default is system-dependent. If the result tree contains a character that cannot be represented in the encoding that the XSLT processor is using for output, the XSLT processor should signal an error.

    Disabling Output Escaping

    Normally, the xml output method escapes & and < (and possibly other characters) when outputting text nodes. This ensures that the output is well-formed XML. However, it is sometimes convenient to be able to produce output that is almost, but not quite well-formed XML; for example, the output may include ill-formed sections which are intended to be transformed into well-formed XML by a subsequent non-XML aware process. For this reason, XSLT provides a mechanism for disabling output escaping. An xsl:value-of or xsl:text element may have a disable-output-escaping attribute; the allowed values are yes or no; the default is no; if the value is yes, then a text node generated by instantiating the xsl:value-of or xsl:text element should be output without any escaping. For example,

    <]]>

    should generate the single character <.

    It is an error for output escaping to be disabled for a text node that is used for something other than a text node in the result tree. Thus, it is an error to disable output escaping for an xsl:value-of or xsl:text element that is used to generate the string-value of a comment, processing instruction or attribute node; it is also an error to convert a result tree fragment to a number or a string if the result tree fragment contains a text node for which escaping was disabled. In both cases, an XSLT processor may signal the error; if it does not signal the error, it must recover by ignoring the disable-output-escaping attribute.

    The disable-output-escaping attribute may be used with the html output method as well as with the xml output method. The text output method ignores the disable-output-escaping attribute, since it does not perform any output escaping.

    An XSLT processor will only be able to disable output escaping if it controls how the result tree is output. This may not always be the case. For example, the result tree may be used as the source tree for another XSLT transformation instead of being output. An XSLT processor is not required to support disabling output escaping. If an xsl:value-of or xsl:text specifies that output escaping should be disabled and the XSLT processor does not support this, the XSLT processor may signal an error; if it does not signal an error, it must recover by not disabling output escaping.

    If output escaping is disabled for a character that is not representable in the encoding that the XSLT processor is using for output, then the XSLT processor may signal an error; if it does not signal an error, it must recover by not disabling output escaping.

    Since disabling output escaping may not work with all XSLT processors and can result in XML that is not well-formed, it should be used only when there is no alternative.

    Conformance

    A conforming XSLT processor must be able to use a stylesheet to transform a source tree into a result tree as specified in this document. A conforming XSLT processor need not be able to output the result in XML or in any other form.

    Vendors of XSLT processors are strongly encouraged to provide a way to verify that their processor is behaving conformingly by allowing the result tree to be output as XML or by providing access to the result tree through a standard API such as the DOM or SAX.

    A conforming XSLT processor must signal any errors except for those that this document specifically allows an XSLT processor not to signal. A conforming XSLT processor may but need not recover from any errors that it signals.

    A conforming XSLT processor may impose limits on the processing resources consumed by the processing of a stylesheet.

    Notation

    The specification of each XSLT-defined element type is preceded by a summary of its syntax in the form of a model for elements of that element type. The meaning of syntax summary notation is as follows:

    An attribute is required if and only if its name is in bold.

    The string that occurs in the place of an attribute value specifies the allowed values of the attribute. If this is surrounded by curly braces, then the attribute value is treated as an attribute value template, and the string occurring within curly braces specifies the allowed values of the result of instantiating the attribute value template. Alternative allowed values are separated by |. A quoted string indicates a value equal to that specific string. An unquoted, italicized name specifies a particular type of value.

    If the element is allowed not to be empty, then the element contains a comment specifying the allowed content. The allowed content is specified in a similar way to an element type declaration in XML; template means that any mixture of text nodes, literal result elements, extension elements, and XSLT elements from the instruction category is allowed; top-level-elements means that any mixture of XSLT elements from the top-level-element category is allowed.

    The element is prefaced by comments indicating if it belongs to the instruction category or top-level-element category or both. The category of an element just affects whether it is allowed in the content of elements that allow a template or top-level-elements.

    References Normative References World Wide Web Consortium. Extensible Markup Language (XML) 1.0. W3C Recommendation. See http://www.w3.org/TR/1998/REC-xml-19980210 World Wide Web Consortium. Namespaces in XML. W3C Recommendation. See http://www.w3.org/TR/REC-xml-names World Wide Web Consortium. XML Path Language. W3C Recommendation. See http://www.w3.org/TR/xpath Other References World Wide Web Consortium. Cascading Style Sheets, level 2 (CSS2). W3C Recommendation. See http://www.w3.org/TR/1998/REC-CSS2-19980512 International Organization for Standardization, International Electrotechnical Commission. ISO/IEC 10179:1996. Document Style Semantics and Specification Language (DSSSL). International Standard. World Wide Web Consortium. HTML 4.0 specification. W3C Recommendation. See http://www.w3.org/TR/REC-html40 Internet Assigned Numbers Authority. Character Sets. See ftp://ftp.isi.edu/in-notes/iana/assignments/character-sets. N. Freed, J. Postel. IANA Charset Registration Procedures. IETF RFC 2278. See http://www.ietf.org/rfc/rfc2278.txt. E. Whitehead, M. Murata. XML Media Types. IETF RFC 2376. See http://www.ietf.org/rfc/rfc2376.txt. T. Berners-Lee, R. Fielding, and L. Masinter. Uniform Resource Identifiers (URI): Generic Syntax. IETF RFC 2396. See http://www.ietf.org/rfc/rfc2396.txt. Unicode Consortium. Unicode Technical Report #10. Unicode Collation Algorithm. Unicode Technical Report. See http://www.unicode.org/unicode/reports/tr10/index.html. World Wide Web Consortium. XHTML 1.0: The Extensible HyperText Markup Language. W3C Proposed Recommendation. See http://www.w3.org/TR/xhtml1 World Wide Web Consortium. XML Pointer Language (XPointer). W3C Working Draft. See http://www.w3.org/TR/xptr World Wide Web Consortium. Associating stylesheets with XML documents. W3C Recommendation. See http://www.w3.org/TR/xml-stylesheet World Wide Web Consortium. Extensible Stylesheet Language (XSL). W3C Working Draft. See http://www.w3.org/TR/WD-xsl Element Syntax Summary DTD Fragment for XSLT Stylesheets

    This DTD Fragment is not normative because XML 1.0 DTDs do not support XML Namespaces and thus cannot correctly describe the allowed structure of an XSLT stylesheet.

    The following entity can be used to construct a DTD for XSLT stylesheets that create instances of a particular result DTD. Before referencing the entity, the stylesheet DTD must define a result-elements parameter entity listing the allowed result element types. For example:

    ]]>

    Such result elements should be declared to have xsl:use-attribute-sets and xsl:extension-element-prefixes attributes. The following entity declares the result-element-atts parameter for this purpose. The content that XSLT allows for result elements is the same as it allows for the XSLT elements that are declared in the following entity with a content model of %template;. The DTD may use a more restrictive content model than %template; to reflect the constraints of the result DTD.

    The DTD may define the non-xsl-top-level parameter entity to allow additional top-level elements from namespaces other than the XSLT namespace.

    The use of the xsl: prefix in this DTD does not imply that XSLT stylesheets are required to use this prefix. Any of the elements declared in this DTD may have attributes whose name starts with xmlns: or is equal to xmlns in addition to the attributes declared in this DTD.

    &XSLT.ns; ]]>
    Examples Document Example

    This example is a stylesheet for transforming documents that conform to a simple DTD into XHTML . The DTD is:

    ]]>

    The stylesheet is:

    <xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;" xmlns="&XHTML.ns;"> <xsl:value-of select="title"/>

    NOTE:

    ]]>

    With the following input document

    Document Title Chapter Title
    Section Title This is a test. This is a note.
    Another Section Title This is another test. This is another note.
    ]]>

    it would produce the following result

    <?xml version="1.0" encoding="iso-8859-1"?> <html xmlns="&XHTML.ns;"> Document Title

    Document Title

    Chapter Title

    Section Title

    This is a test.

    NOTE: This is a note.

    Another Section Title

    This is another test.

    NOTE: This is another note.

    ]]>
    Data Example

    This is an example of transforming some data represented in XML using three different XSLT stylesheets to produce three different representations of the data, HTML, SVG and VRML.

    The input data is:

    10 9 7 4 3 4 6 -1.5 2 ]]>

    The following stylesheet, which uses the simplified syntax described in , transforms the data into HTML:

    <html xsl:version="1.0" xmlns:xsl="&XSLT.ns;" Sales Results By Division
    Division Revenue Growth Bonus
    color:red
    ]]>

    The HTML output is:

    Sales Results By Division
    DivisionRevenueGrowthBonus
    North1097
    West6-1.52
    South434
    ]]>

    The following stylesheet transforms the data into SVG:

    <xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;" Revenue Division ]]>

    The SVG output is:

    Revenue Division North 10 South 4 West 6 ]]>

    The following stylesheet transforms the data into VRML:

    <xsl:stylesheet version="1.0" xmlns:xsl="&XSLT.ns;"> #VRML V2.0 utf8 # externproto definition of a single bar element EXTERNPROTO bar [ field SFInt32 x field SFInt32 y field SFInt32 z field SFString name ] "http://www.vrml.org/WorkingGroups/dbwork/barProto.wrl" # inline containing the graph axes Inline { url "http://www.vrml.org/WorkingGroups/dbwork/barAxes.wrl" } bar { x y z name "" } ]]>

    The VRML output is:

    Acknowledgements

    The following have contributed to authoring this draft:

    Daniel Lipkin, Saba Jonathan Marsh, Microsoft Henry Thompson, University of Edinburgh Norman Walsh, Arbortext Steve Zilles, Adobe

    This specification was developed and approved for publication by the W3C XSL Working Group (WG). WG approval of this specification does not necessarily imply that all WG members voted for its approval. The current members of the XSL WG are:

    Sharon Adler IBM Co-Chair Anders Berglund IBM Perin Blanchard Novell Scott Boag Lotus Larry Cable Sun Jeff Caruso Bitstream James Clark Peter Danielsen Bell Labs Don Day IBM Stephen Deach Adobe Dwayne Dicks SoftQuad Andrew Greene Bitstream Paul Grosso Arbortext Eduardo Gutentag Sun Juliane Harbarth Software AG Mickey Kimchi Enigma Chris Lilley W3C Chris Maden Exemplary Technologies Jonathan Marsh Microsoft Alex Milowski Lexica Steve Muench Oracle Scott Parnell Xerox Vincent Quint W3C Dan Rapp Novell Gregg Reynolds Datalogics Jonathan Robie Software AG Mark Scardina Oracle Henry Thompson University of Edinburgh Philip Wadler Bell Labs Norman Walsh Arbortext Sanjiva Weerawarana IBM Steve Zilles Adobe Co-Chair
    Changes from Proposed Recommendation

    The following are the changes since the Proposed Recommendation:

    The xsl:version attribute is required on a literal result element used as a stylesheet (see ).

    The data-type attribute on xsl:sort can use a prefixed name to specify a data-type not defined by XSLT (see ).

    Features under Consideration for Future Versions of XSLT

    The following features are under consideration for versions of XSLT after XSLT 1.0:

    a conditional expression;

    support for XML Schema datatypes and archetypes;

    support for something like style rules in the original XSL submission;

    an attribute to control the default namespace for names occurring in XSLT attributes;

    support for entity references;

    support for DTDs in the data model;

    support for notations in the data model;

    a way to get back from an element to the elements that reference it (e.g. by IDREF attributes);

    an easier way to get an ID or key in another document;

    support for regular expressions for matching against any or all of text nodes, attribute values, attribute names, element type names;

    case-insensitive comparisons;

    normalization of strings before comparison, for example for compatibility characters;

    a function string resolve(node-set) function that treats the value of the argument as a relative URI and turns it into an absolute URI using the base URI of the node;

    multiple result documents;

    defaulting the select attribute on xsl:value-of to the current node;

    an attribute on xsl:attribute to control how the attribute value is normalized;

    additional attributes on xsl:sort to provide further control over sorting, such as relative order of scripts;

    a way to put the text of a resource identified by a URI into the result tree;

    allow unions in steps (e.g. foo/(bar|baz));

    allow for result tree fragments all operations that are allowed for node-sets;

    a way to group together consecutive nodes having duplicate subelements or attributes;

    features to make handling of the HTML style attribute more convenient.

    features to make handling of the HTML style attribute more convenient.

    tdom-0.9.5-src/tests/data/dtd-5.2.dtd0000644000175000017500000000007214703531020015562 0ustar rolfrolf tdom-0.9.5-src/tests/data/mondial-europe.xml0000644000175000017500000132414014703531020017460 0ustar rolfrolf Albania AL 28750 3249136 1.34 49.2 4100 55 16 28 11 1912 emerging democracy 100 3 95 70 10 20 282 151 287 Tirane 10.7 46.2 192000 Shkoder 19.2 42.2 62000 Durres 19.3 41.2 60000 Vlore 19.3 40.3 56000 Elbasan 20.1 41.1 53000 Korce 20.5 40.4 52000 Greece GR 131940 10538594 0.42 7.4 101700 11.8 22.2 66 8.1 01 01 1829 parliamentary republic 100 98 1.3 98 282 228 494 206 Anatoliki Makedhonia kai Thraki 14157 574308 Attiki 3808 3522769 Athens 23.7167 37.9667 885737 Dhytiki Ellas 11350 702027 Dhytiki Makedhonia 9451 292751 Ionioi Nisoi 2307 191003 Ipiros 9203 339210 Kedriki Makedhonia 19147 1729581 Kriti 8336 537183 Notion Aiyaion 5286 262522 Peloponnisos 15490 605663 Sterea Ellas 15549 578876 Thessalia 14037 731030 Voreion Aiyaion 3836 189541 Macedonia MK 25333 2104035 0.46 29.7 1900 24 44 32 14.8 17 09 1991 emerging democracy 100 22 2 65 4 3 30 67 21 70 3 3 151 228 221 148 Skopje Serbia and Montenegro YU 102350 10614558 20600 20 11 04 1992 republic 100 63 14 6 4 19 4 1 65 5 95 287 221 151 527 266 318 476 Belgrade 20.4667 44.8 1407073 Andorra AND 450 72766 2.96 2.2 1000 parliamentary democracy that retains as its heads of state a coprincipality 100 6 61 30 100 60 65 Andorra la Vella 1.3 42.3 15600 France F 547030 58317450 0.34 5.3 1173000 2.4 26.5 71.1 1.7 republic 100 1 1 90 2 100 60 623 451 488 573 620 73 4.4 Alsace 8280 1624000 Strasbourg 7.76667 48.5833 252338 Mulhouse 108357 Aquitaine 41309 2796000 Bordeaux -0.4 44.51 210336 Auvergne 26013 1321000 Clermont Ferrand 3.4 45.5 136181 Basse Normandie 17589 1391000 Caen -0.2 49.3 112846 Bretagne 27209 2796000 Rennes -1.4 48.1 197536 Brest 147956 Bourgogne 31582 1609000 Dijon 5.2 47.2 146703 Centre 39151 2371000 Orleans 1.5 47.5 105111 Tours 129509 Champagne Ardenne 25606 1348000 Reims 180620 Chalons sur Marne Corse 8680 250000 Ajaccio 8.4 41.4 53500 Franche Comte 16202 1097000 Besancon 6.2 47.1 113828 Haute Normandie 12318 1737000 Rouen 1.5 49.3 102723 Le Havre 195854 Ile de France 12011 10660000 Paris 2.48333 48.8167 2152423 Boulogne Billancourt 101743 Languedoc Rousillon 27376 2115000 Montpellier 3.5 43.3 207996 Nimes 128471 Perpignan 105983 Limousin 16942 723000 Limoges 1.2 45.5 133464 Lorraine 23547 2306000 Metz 119594 Nancy 6.1 48.4 99351 Midi Pyrenees 45349 2431000 Toulouse 1.2 43.4 358688 Nord Pas de Calais 12413 3965000 Lille 3.3 50.37 172142 Pays de la Loire 32082 3059000 Nantes -1.56667 47.25 244995 Angers 141404 Le Mans 145502 Picardie 19399 1811000 Amiens 2.19 49.55 131872 Poitou Charentes 25809 1595000 Poitiers 0.2 46.4 79300 Provence Cote dAzur 31400 4258000 Marseille 5.2 43.2 800550 Nice 7.26667 43.7 342439 Toulon 167619 Aix en Provence 123842 Rhone Alpes 43698 5351000 Lyon 4.78333 45.7 415487 Grenoble 150758 Saint Etienne 199396 Villeurbanne 116872 Spain E 504750 39181114 0.16 6.3 565000 3.6 33.6 62.8 4.3 01 01 1492 parliamentary monarchy 100 100 99 null 17 7 2 65 623 1214 Andalusia 87600 7053043 Sevilla 714148 Almeria 167361 Cadiz -6.2 36.3 155438 Cordoba 315948 Granada 271180 Huelva 145049 Malaga 531443 Jerez de la Frontera 190390 Jaen 112772 Algeciras 103787 Aragon 47720 1183576 Zaragoza 606620 Asturias 10604 1083388 Oviedo 201712 Gijon 269644 Balearic Islands 4992 736865 Palma de Mallorca 322008 Basque Country 7235 2075561 Vitoria Gasteiz 214148 Bilbao 371876 Donostia 177929 Canary Islands 7447 1534897 Santa Cruz de Tenerife 203929 Las Palmas de Gran Canaria 371787 La Laguna 125183 Cantabria 5321 526090 Santander 194822 Castile and Leon 94224 2504371 Valladolid 336917 Albacete 141179 Burgos 166251 Leon 147311 Salamanca 167382 Castile La Mancha 79462 1656179 Toledo Catalonia 32113 6090107 Barcelona 2.15 41.4 1630867 Lleida 114234 Tarragona 114630 Hospitalet de Llobregat 266242 Badalona 219340 Sabadell 189006 Terrassa 161428 Santa Coloma de Gramanet 131764 Baracaldo 103594 Mataro 102117 Estremadura 41635 1050590 Badajoz 130153 Merida Galicia 29574 2720761 La Coruna 255087 Vigo 288573 Orense 108547 Santiago de Compostella Madrid 8028 5034548 Madrid -3.68333 40.4167 3041101 Mostoles 199141 Leganes 178162 Alcala de Henares 166250 Fuenlabrada 158212 Getafe 144368 Alcorcon 142165 Murcia 11314 1070401 Murcia 341531 Cartagena 179659 Navarre 10391 523614 Pamplona 182465 Rioja 5045 263437 Logrono 124823 Valencia 23255 3909047 Valencia -0.383333 39.4667 764293 Alacant 274964 Elx 191305 Castellon de la Plana 139094 Austria A 83850 8023244 0.41 6.2 152000 2 34 64 2.3 12 11 1918 federal republic 100 99.4 0.2 0.3 85 6 100 362 784 366 430 37 91 324 164 Burgenland 3965 273000 Eisenstadt 16 48 10102 Carinthia 9533 559000 Klagenfurt 14.21 46.38 87321 Vorarlberg 2601 341000 Bregenz 9.45 47.3 Vienna 415 1583000 Vienna 16.3667 48.25 1583000 Upper Austria 11979 1373000 Linz 14.18 48.18 203000 Tyrol 12647 649000 Innsbruck 11.22 47.17 118000 Styria 16386 1203000 Graz 15.26 47.4 238000 Salzburg 7154 501000 Salzburg 13.2 47.49 144000 Lower Austria 19170 1507000 St. Polten 15.38 48.13 51102 Czech Republic CZ 78703 10321120 -0.03 8.4 106200 5.8 40.7 53.5 9.1 01 01 1993 parliamentary democracy 100 0.5 0.6 0.3 0.2 94.4 3 39.2 4.6 3 362 646 214 658 Jihocesky 11345 702000 Ceske Budejovice 174000 Jihomoravsky 15028 2059000 Brno 393000 Zlin 198000 Severocesky 7819 1190000 Liberec 160000 Usti nad Labem Severomoravsky 11067 1976000 Ostrava 332000 Olomouc 225000 Praha 11490 2329000 Prague 14.4167 50.0833 1215000 Vychodocesky 11240 1240000 Hradec Kralove 164000 Pardubice 163000 Zapadocesky 10875 869000 Plzen 175000 Germany D 356910 83536115 0.67 6 1452200 1 34.2 64.8 18 01 1871 federal republic 100 0.4 2.3 95.1 0.7 0.4 37 45 100 451 784 646 334 456 167 138 577 68 Baden Wurttemberg 35742 10272069 Stuttgart 9.1 48.7 588482 Mannheim 8.46667 49.5667 316223 Karlsruhe 277011 Freiburg im Breisgau 198496 Heidelberg 138964 Heilbronn 122253 Pforzheim 117960 Ulm 115123 Reutlingen 107782 Bayern 70546 11921944 Munich 11.5667 48.15 1244676 Nurnberg 495845 Augsburg 262110 Oberhausen 225443 Wurzburg 127946 Regensburg 125608 Ingolstadt 110910 Furth 107799 Erlangen 101450 Berlin 889 3472009 Berlin 13.3 52.45 3472009 Brandenburg 29480 2536747 Potsdam 138268 Cottbus 125643 Bremen 404 680000 Bremen 8.5 53.7 549182 Bremerhaven 130847 Hamburg 755 1705872 Hamburg 9.96667 53.55 1705872 Hessen 21115 5980693 Wiesbaden 8.17 50.07 266081 Frankfurt am Main 652412 Kassel 201789 Darmstadt 139063 Offenbach am Main 116482 Mecklenburg Vorpommern 23170 1832298 Schwerin 118291 Rostock 232634 Niedersachsen 47609 7715363 Hannover 9.66667 52.4 525763 Braunschweig 254130 Osnabruck 168050 Oldenburg 149691 Gottingen 127519 Wolfsburg 126965 Salzgitter 117842 Hildesheim 106095 Nordrhein Westfalen 34077 17816079 Dusseldorf 572638 Koln 963817 Essen 617955 Dortmund 600918 Duisburg 536106 Bochum 401129 Wuppertal 383776 Bielefeld 324067 Gelsenkirchen 293542 Bonn 293072 Monchengladbach 266073 Munster 264887 Krefeld 249662 Aachen 247113 Hagen 213747 Hamm 184020 Herne 180029 Mulheim an der Ruhr 176513 Solingen 165973 Leverkusen 161832 Neuss 148870 Paderborn 131513 Recklinghausen 127139 Remscheid 123069 Bottrop 119669 Siegen 111541 Moers 107011 Witten 105423 Bergisch Gladbach 105122 Rheinland Pfalz 19851 3951573 Mainz 8.1 50 184627 Ludwigshafen 167883 Koblenz 109550 Kaiserslautern 101910 Saarland 2570 1084201 Saarbrucken 6.6 49.1 189012 Sachsen 18412 4584345 Dresden 474443 Leipzig 481121 Chemnitz 274162 Zwickau 104921 Sachsen Anhalt 20446 2759213 Magdeburg 265379 Halle 290051 Schleswig Holstein 15738 2708392 Kiel 10.7 54.2 246586 Lubeck 216854 Thuringen 16171 2517776 Erfurt 213472 Gera 126035 Jena 102204 Hungary H 93030 10002541 -0.68 12.3 72500 7.3 37.5 55.2 28.3 01 01 1001 republic 100 2 2.6 4 89.9 0.8 0.7 67.5 5 20 98.2 151 366 515 102 103 329 443 Baranya 4487 417100 Bacs Kiskun 8363 540800 Kecskemet 105000 Bekes 5632 404000 Bekescaba Borsod Abauj Zemplen 7248 749100 Csongrad 4263 437600 Hodmezovasarhely Fejer 4374 422500 Szekesfehervar 109000 Gyor Sopron 4012 426800 Hajdu Bihar 6212 549700 Heves 3637 330200 Eger Komarom Esztergom 2250 312900 Tatabanya Nograd 2544 222700 Salgotarjan Pest 6394 957900 Somogy 6035 340000 Kaposvar Szabolcs Szatmar 5938 563500 Nyiregyhaza 115000 Szolnok 5608 420900 Szolnok Tolna 3702 251000 Szekszard Vas 3337 273900 Szombathely Veszprem 4689 378300 Veszprem Zala 3786 302600 Zalaegerszeg Budapest (munic.) 525 2008500 Budapest 19.0333 47.5167 2016000 Debrecen (munic.) 446 217300 Debrecen 216000 Gyor (munic.) 175 130600 Gyor 130000 Miskolc (munic.) 224 191000 Miskolc 192000 Pecs (munic.) 113 171600 Pecs 171000 Szeged (munic.) 145 178500 Szeged 178000 Italy I 301230 57460274 0.13 6.9 1088600 2.9 31.6 65.5 5.4 17 03 1861 republic 100 98 488 430 235 740 3.2 39 Piemonte 25399 4307000 Novara 103349 Turin 7.39 45.5 991870 Valle dAosta 3262 118000 Aosta 7.22 45.45 Lombardia 23857 8901000 Bergamo 117886 Brescia 196766 Milan 9.28333 45.45 1432184 Monza 123188 Trentino Alto Adige 13618 904000 Bolzano 100380 Trento 102124 Veneto 18364 4415000 Padova 218186 Verona 258946 Vicenza 109333 Venice 12.2 45.27 317837 Friuli Venezia Giulia 7845 1193000 Trieste 231047 Liguria 5418 1663000 La Spezia 103008 Genua 8.58 44.25 701032 Emilia Romagna 22123 3924000 Bologna 11.22 44.3 411803 Ferrara 140600 Modena 177501 Parma 173991 Piacenza 103536 Ravenna 136724 Reggio nellEmilia 131880 Rimini 130896 Toscana 22992 3528000 Livorno 171265 Pisa 101500 Firenze 11.17 43.48 408403 Prato 166688 Umbria 8456 819000 Perugia 12.2 43.1 150576 Terni 109809 Marche 9693 1438000 Ancona 13.28 43.38 103268 Lazio 17203 5185000 Rome 12.6 41.8 2791354 Latina 103630 Abruzzo 10794 1263000 Pescara 128553 LAquila 13.2 42.24 Molise 4438 332000 Campobasso 14.5 41.5 Campania 13595 5709000 Salerno 151374 Napoli 14.15 40.5 1206013 Torre del Greco 102647 Puglia 19348 4066000 Bari 16.5 41.8 353032 Foggia 159541 Lecce 102344 Taranto 244033 Basilicata 9992 611000 Potenza 15.47 40.4 Calabria 15080 2080000 Catanzaro 16.35 38.55 103802 Cosenza 104483 Messina 274846 Reggio di Calabria 178496 Sicilia 25709 5025000 Palermo 13.2 38.1 734238 Catania 364176 Siracusa 125444 Sardegna 24090 1657000 Cagliari 9.5 39.15 211719 Sassari 120011 Liechtenstein FL 160 31122 1.08 5.3 630 5.4 23 01 1719 hereditary constitutional monarchy 100 5 95 87.3 8.3 37 41 Vaduz 9.3 47.08 27714 Slovakia SK 48845 5374362 0.34 10.7 39000 6.7 47.6 45.7 7.5 01 01 1993 parliamentary democracy 100 0.1 0.1 1.5 10.7 1 85.7 0.3 0.3 60.3 8.4 4.1 91 215 515 444 90 Bratislava Slovenia SLO 20256 1951443 -0.27 7.3 22600 5.3 39.9 54.8 8 25 06 1991 emerging democracy 100 2 91 1 3 1 96 91 7 324 102 235 546 Ljubljana Switzerland CH 41290 7207060 0.59 5.4 158500 3 33.5 63.5 1.8 federal republic 100 47.6 44.3 18 65 12 1 573 164 334 740 41 AG 1403 528887 Aarau AR 242 54104 Herisau AI 172 14750 Appenzell BL 517 252331 Liestal BS 37 195759 Basel 172768 BE 5960 941952 Bern 7.3 46.6 134393 Biel 53308 FR 1670 224552 Fribourg GE 282 395466 Geneva 6.9 46.12 167697 GL 685 39410 Glarus GR 7105 185063 Chur JU 836 69188 Delemont LU 1493 340536 Luzern 59811 NE 803 165258 Neuchatel NW 276 36466 Stans OW 490 31310 Sarnen SG 2025 442350 Sankt Gallen 74106 SH 298 74035 Schaffhausen SZ 908 122409 Schwyz SO 790 239264 Solothurn TG 990 223372 Frauenfeld TI 2812 305199 Bellinzona UR 1076 35876 Altdorf VS 5224 271291 Sion VD 3211 605677 Lausanne 123149 ZG 238 92392 Zug ZH 1728 1175457 Zurich 343106 Winterthur 86340 Belarus BY 207600 10415973 0.2 13.4 49200 21 49 30 244 25 08 1991 republic 100 4.1 2.9 13.2 77.9 60 141 502 605 891 959 Minsk 27.55 53.9 1540000 Latvia LV 64100 2468982 -1.39 21.2 14700 9 31 60 20 06 09 1991 republic 100 2.3 3.4 33.8 4.5 51.8 141 453 217 267 Riga 14.1 57 900000 Lithuania LT 65200 3646041 -0.35 17 13300 20 42 38 35 06 09 1991 republic 100 7.7 8.6 1.5 80.1 502 453 91 227 Vilnius 25.3 54.4 566000 Poland PL 312683 38642565 0.14 12.4 226700 7 38 55 21.6 11 11 1918 democratic state 100 1.3 97.6 0.6 0.5 95 100 658 456 444 605 91 428 206 Warszwaskie 3788 2421000 Warsaw 21.0333 52.2167 1655000 Bialskopodlaskie 5348 306700 Biala Podlaska Bialostockie 10055 697000 Bialystok 268000 Bielskie 3704 911500 Bielsko Biala 180000 Bydgoskie 10349 1120300 Bydgoszcz 380000 Chelmskie 3866 248500 Chelm Ciechanowskie 6362 431400 Ciechanow Czestochowskie 6182 748000 Czestochowa 258000 Elblaskie 6103 483200 Elblag 125000 Gdanskie 7394 1445000 Gdansk 465000 Gdynia 251000 Gorzowskie 8484 505600 Gorzow Wielkopolski 123000 Gorzow Wielkopolskie Jeleniogorskie 4379 519200 Jelenia Gora Kaliskie 6512 715600 Kalisz 106000 Katowickie 6650 4013200 Katowice 367000 Sosnowiec 259000 Bytom 230000 Gliwice 216000 Zabrze 203000 Tychy 190000 Ruda Slaska 170000 Rybnik 143000 Chorzow 133000 Wodzilaw Slaski 111000 Kieleckie 9211 1127700 Kielce 213000 Koninskie 5139 472400 Konin Koszalinskie 8470 513700 Koszalin 108000 Krakowskie 3254 1238100 Krakow 19.95 50.0667 748000 Krosnienskie 5702 500700 Krosno Legnickie 4037 521500 Legnica 104000 Leszczynskie 4154 391500 Leszno Lubelskie 6792 1022600 Lublin 350000 Lomzynskie 6684 349000 Lomza Lodzkie 1523 1132400 Lodz 852000 Nowosadeckie 5576 709500 Nowy Sacz Olsztynskie 12327 761300 Olsztyn 161000 Opolskie 8535 1023800 Opole 128000 Ostroleckie 6498 400500 Ostroleka Pilskie 8205 485700 Pila Piotrkowskie 6266 644200 Piottrkow Trybunalski Plockie 5117 518600 Plock 122000 Poznanskie 8151 1344200 Poznan 589000 Przemyskie 4437 409600 Przemysl Radomskie 7294 755500 Radom 226000 Rzeszowskie 4397 734100 Rzeszow 151000 Siedleckie 8499 655300 Siedlce Sieradzkie 4869 408700 Sieradz Skierniewickie 3960 421700 Skierniewice Slupskie 7453 419300 Slupsk Suwalskie 10490 477100 Suwalki Szczecinskie 9982 979500 Szczecin 412000 Tarnobrzeskie 6283 604300 Tarnobrzeg Tarnowskie 4151 678400 Tarnow 120000 Torunskie 5348 662600 Torun 201000 Grudziadz 101000 Walbrzyskie 4168 740000 Walbrzych 141000 Wloclawskie 4402 430800 Wloclawek 121000 Wroclawskie 6287 1132800 Wroclaw 642000 Zamojskie 6980 490800 Zamosc Zielonogorskie 8868 664700 Zielona Gora 113000 Ukraine UA 603700 50864009 -0.4 22.5 174600 31 43 26 9 01 12 1991 republic 100 73 22 1 103 90 891 428 1576 531 939 Cherkaska 20900 1530900 Cherkasy 297000 Chernihivska 31900 938600 Chernihiv 301000 Chernivetska 8100 1405800 Chernivtsi 257000 Dnipropetrovska 31900 3908700 Dnipropetrovsk 1187000 Kryvyy Rih 717000 Dniprodzerzhynsk 284000 Donetska 26500 5346700 Donetsk 1117000 Mariupol 520000 Makiyivka 427000 Horlivka 338000 Ivano Frankivska 13900 1442900 Ivano Frankivsk 220000 Kharkivska 31400 3194800 Kharkiv 36.2333 50 1618000 Khersonska 28500 1258700 Kherson 361000 Khmelnytska 20600 1520600 Khmelnytskyy 241000 Kyyivska 28900 4589800 Kiev 30.5 50.45 2616000 Kirovohradska 24600 1245300 Kirovohrad 274000 Luhanska 26700 2871100 Luhansk 501000 Lvivska 21800 2764400 Lviv 798000 Mykolayivska 24600 1342400 Mykolayiv 508000 Odeska 33300 2635300 Odesa 30.7333 46.4833 1106000 Poltavska 28800 1756900 Poltava 317000 Kremenchuk 238000 Rivnenska 20100 1176800 Rivne 233000 Sumska 23800 1430200 Sumy 296000 Ternopilska 13800 1175100 Ternopil 212000 Vinnytska 26500 1914400 Vinnytsya 379000 Volynska 20200 1069000 Lutsk 204000 Zakarpatska 12800 1265900 Uzhhorod Zaporizka 27200 2099600 Zaporizhzhya 891000 Zhytomyrska 29900 1510700 Zhytomyr 296000 Krym 27000 2549800 Simferopol 349000 Sevastopol 361000 Russia R 17075200 148178487 -0.07 24.7 796000 6 41 53 7 24 08 1991 federation 20 3 81.5 0.8 3.8 1.2 0.9 0.7 100 959 217 227 206 1576 290 1313 167 Rep. of Karelia 172400 785000 Petrozavodsk 280000 Rep. of Komi 415900 1185500 Syktyvkar 229000 Ukhta 106000 Vorkuta 104000 Arkhangelskaya oblast 587400 1520800 Arkhangelsk 40.5333 64.55 374000 Severodvinsk 241000 Vologodskaya oblast 145700 1349800 Vologda 299000 Cherepovets 320000 Murmanskaya oblast 144900 1048000 Murmansk 407000 Kaliningradskaya oblast 15100 932200 Kaliningrad 20.5 54.7167 419000 Sankt Peterburg 0 4801500 Sankt Peterburg 4838000 Leningradskaya oblast 85900 1675900 Kolpino 143000 Novgorodskaya oblast 55300 742600 Novgorod 233000 Pskovskaya oblast 55300 832300 Pskov 207000 Velikiye Luki 116000 Bryanskaya oblast 34900 1479700 Bryansk 462000 Vladimirskaya oblast 29000 1644700 Vladimir 339000 Kovrov 162000 Murom 126000 Ivanovskaya oblast 23900 1266400 Ivanovo 474000 Kineshma 103000 Kaluzhskaya oblast 29900 1097300 Kaluga 347000 Obninsk 108000 Kostromskaya oblast 60100 805700 Kostroma 285000 Moskva 0 8664400 Moscow 37.6667 55.7667 8717000 Moskovskaya oblast 47000 6596600 Podolsk 202000 Zelenograd 191000 Lyubertsy 166000 Kolomna 154000 Mytishchi 152000 Elektrostal 150000 Serpukhov 139000 Balashikha 136000 Khimki 134000 Odintsovo 129000 Orekhovo Zuyevo 126000 Noginsk 119000 Shchyolkovo 108000 Orlovskaya oblast 24700 914000 Orel 348000 Ryazanskaya oblast 39600 1325300 Ryazan 536000 Smolenskaya oblast 49800 1172400 Smolensk 355000 Tverskaya oblast 84100 1650600 Tver 455000 Tulskaya oblast 25700 1814500 Tula 532000 Novomoskovsk 144000 Yaroslavskaya oblast 36400 1451400 Yaroslavl 629000 Rybinsk 248000 Rep. of Mariy El 23200 766300 Yoshkar Ola 251000 Rep. of Mordovia 26200 955800 Saransk 320000 Chuvash Republic 18300 1360800 Cheboksary 450000 Novocheboksarsk 123000 Kirovskaya oblast 120800 1634500 Kirov 464000 Nizhegorodskaya oblast 74800 3726400 Nizhniy Novgorod 1383000 Dzerzhinsk 285000 Arzamas 112000 Belgorodskaya oblast 27100 1469100 Belgorod 322000 Stary Oskol 198000 Voronezhskaya oblast 52400 2503800 Voronezh 908000 Kurskaya oblast 29800 1346900 Kursk 442000 Lipetskaya oblast 24100 1250200 Lipetsk 474000 Yelets 119000 Tambovskaya oblast 34300 1310600 Tambov 316000 Michurinsk 108000 Rep. of Kalmykiya 76100 318500 Elista Rep. of Tatarstan 68000 3760500 Kazan 1085000 Naberezhnye Chelny 526000 Nizhnekamsk 210000 Almetyevsk 138000 Zelenodolysk 101000 Astrakhanskaya oblast 44100 1028900 Astrakhan 486000 Volgogradskaya oblast 113900 2703700 Volgograd 44.5167 48.7 1003000 Volzhsky 288000 Kamyshin 128000 Penzenskaya oblast 43200 1562300 Penza 534000 Kuznetsk 100000 Samarskaya oblast 53600 3311500 Samara 1184000 Tolyatti 702000 Syzran 177000 Novokuybyshevsk 115000 Saratovskaya oblast 100200 2739500 Saratov 895000 Balakovo 206000 Engels 186000 Ulyanovskaya oblast 37300 1495200 Simbirsk 678000 Dimitrovgrad 135000 Rostovskaya oblast 100800 4426400 Rostov na Donu 1026000 Taganrog 292000 Shakhty 230000 Novocherkassk 190000 Volgodonsk 183000 Novoshakhtinsk 107000 Rostov no Donu Rep. of Bashkortostan 143600 4096600 Ufa 1094000 Sterlitamak 259000 Salavat 156000 Oktyabrsky 110000 Udmurt Republic 42100 1639100 Izhevsk 654000 Sarapul 109000 Glazov 107000 Votkinsk 104000 Orenburgskaya oblast 124000 2228600 Orenburg 532000 Orsk 275000 Novotroitsk 110000 Permskaya oblast 160600 3009400 Perm 1032000 Berezniki 184000 Solikamsk 108000 Rep. of Adygeya 7600 450500 Maykop 165000 Rep. of Dagestan 50300 2097500 Makhachkala 339000 Rep. of Ingushetiya 3750 299700 Nazran Kabardino Balkar Rep. 12500 789900 Nalchik 239000 Karachayevo Cherkessk Rep. 14100 436300 Cherkessk 119000 Rep. of North Ossetiya 8000 662600 Vladikavkaz 312000 Chechen Rep. 12300 865100 Grozny 364000 Krasnodarsky kray 76000 5043900 Krasnodar 646000 Sochi 355000 Novorossiysk 202000 Armavir 164000 Stavropolsky kray 66500 2667000 Stavropol 342000 Pyatigorsk 133000 Nevinnomyssk 131000 Kislovodsk 120000 Neftekamsk 117000 Kurganskaya oblast 71000 1112200 Kurgan 363000 Sverdlovskaya oblast 194300 4686300 Yekaterinburg 1280000 Nizhniy Tagil 409000 Kamensk Uralskiy 197000 Pervouralsk 137000 Serov 100000 Chelyabinskaya oblast 87900 3688700 Chelyabinsk 1086000 Magnitogorsk 427000 Zlatoust 203000 Miass 167000 Rep. of Altay 92600 201600 Gorno Altaysk Altayskiy kray 169100 2690100 Barnaul 596000 Biysk 228000 Rubtsovsk 170000 Kemerovskaya oblast 95500 3063500 Kemerovo 503000 Novokuznetsk 572000 Prokopyevsk 253000 Leninsk Kuznetskiy 121000 Kiselyovsk 116000 Mezhdurechensk 105000 Anzhero Sudzhensk 101000 Novosibirskaya oblast 178200 2748600 Novosibirsk 1369000 Omskaya oblast 139700 2176400 Omsk 1163000 Tomskaya oblast 316900 1077600 Tomsk 470000 Tyumenskaya oblast 1435200 3169900 Tyumen 494000 Surgut 263000 Nizhnevartovsk 238000 Rep. of Buryatiya 351300 1052500 Ulan Ude 366000 Rep. of Tyva 170500 309700 Kyzyl Rep. of Khakassiya 61900 585800 Abakan 161000 Krasnoyarskiy kray 2339700 3105900 Krasnoyarsk 92.95 56.0167 869000 Norilsk 159000 Achinsk 123000 Kansk 109000 Irkutskaya oblast 767900 2795200 Irkutsk 585000 Angarsk 267000 Bratsk 257000 Ust Ilimsk 110000 Usolye Sibirskoye 106000 Chitinskaya oblast 431500 1295000 Chita 322000 Rep. of Sakha 3103200 1022800 Yakutsk 192000 Yevreyskaya avt. oblast 36000 209900 Birobidzhan Chukotsky ao 737700 90500 Anadyr Primorsky kray 165900 2255400 Vladivostok 131.917 43.1167 632000 Nakhodka 163000 Ussuriysk 162000 Khabarovskiy kray 752600 1571200 Khabarovsk 618000 Komsomolsk na Amure 309000 Amurskaya oblast 363700 1037800 Blagoveshchensk 214000 Kamchatskaya oblast 472300 411100 Petropavlovsk Kamchatsky 210000 Magadanskaya oblast 461400 258200 Magadan 128000 Sakhalinskaya oblast 87100 647800 Yuzhno Sakhalinsk 160000 Belgium B 30510 10170241 0.33 6.4 197000 2 28 70 1.6 04 10 1830 constitutional monarchy 100 55 33 75 25 32 1 56 620 167 148 450 Antwerp 2867 1610695 Antwerp 4.23 51.1 459072 Brabant 3358 2253794 Brussels 4.35 50.8 951580 East Flanders 2982 1340056 Ghent 3.5 51.4 227483 Hainaut 3787 1283252 Charleroi 206491 Mons 3.6 50.3 90720 Liege 3862 1006081 Liege 5.5 50.5 192393 Limburg 2422 755593 Hasselt 5.2 50.7 65348 Luxembourg 4441 234664 Arlon 5.5 49.4 23150 Namur 3665 426305 Namur 4.5 50.3 105014 West Flanders 3134 1111557 Bruges 116273 Brugge 2.08 51.1 117799 Luxembourg L 2586 415870 1.57 4.7 10000 1.4 33.7 64.9 3.6 constitutional monarchy 100 97 3 73 138 148 Luxembourg 6.08 49.4 76600 Netherlands NL 37330 15568034 0.56 4.9 301900 3.4 26.9 69.7 2.25 01 01 1579 constitutional monarchy 100 96 3 34 25 100 577 450 Groningen 2344 557995 Groningen 210708 Friesland 3361 609579 Leeuwarden Drenthe 2652 454864 Assen Overijssel 3337 1050389 Enschede 254480 Zwolle Flevoland 1425 262325 Lelystad Gelderland 4995 1864732 Arnhem 314159 Nijmegen 249490 Utrecht 1356 1063460 Utrecht 547070 Noord Holland 265978 2463611 Amsterdam 4.91667 52.3833 1101407 Haarlem 212631 Zaanstreek 147917 Velsen 134973 Hilversum 102023 Zuid Holland 2859 3325064 s Gravenhage 694249 Rotterdam 1078747 Dordrecht 213963 Leiden 194935 Zeeland 1791 365846 Middelburg Noord Brabant 4938 2276207 s Hertogenbosch 199127 Eindhoven 395612 Tilburg 237958 Breda 166616 Limburg 2167 1130050 Maastricht 164701 Heerlen 270952 Geleen 186011 Bosnia and Herzegovina BIH 51233 2656240 -2.84 43.2 1000 01 04 1992 emerging democracy 100 40 38 22 40 4 31 15 99 527 932 Sarajevo Croatia HR 56538 5004112 0.58 10.2 20100 12.7 30.6 56.7 3.7 25 06 1991 parliamentary democracy 100 12 0.5 0.9 78 0.5 0.4 11.1 76.5 1.2 96 266 329 546 932 Zagreb Bulgaria BG 110910 8612757 0.46 15.7 43200 12 36 52 35 22 09 1908 emerging democracy 100 2.5 2.6 0.2 8.5 85.3 0.3 13 0.8 0.5 85 0.2 100 494 148 318 608 240 Sofia 23.3333 42.7 1300000 Romania RO 237500 21657162 -1.21 23.2 105700 19.6 36.3 44.1 25 01 01 1881 republic 100 0.4 1.6 8.9 89.1 6 6 70 476 443 531 608 450 Alba 6231 428000 Alba Iulia Arad 7652 507000 Arad 191000 Arges 6801 678000 Pitesti 162000 Bacau 6606 731000 Bacau 193000 Bihor 7535 660000 Oradea 225000 Bistrita Nasaud 5305 328000 Bistrita Botosani 4965 468000 Botosani Braila 4724 404000 Braila 243000 Brasov 5351 695000 Brasov 353000 Bucuresti 1521 2319000 Bucharest 26.1 44.4167 2037000 Buzau 6072 524000 Buzau 145000 Calarasi 5075 351000 Calarasi Caras Severin 8503 408000 Resita Cluj 6650 743000 Cluj Napoca 318000 Constanta 7055 737000 Constanta 316000 Covasha 3705 238000 Sfintu Gheorghe Dimbovita 4035 570000 Tirgoviste Dolj 7413 772000 Craiova 300000 Galati 4425 642000 Galati 307000 Giurgiu 3810 325000 Giurgiu Gorj 5641 388000 Tirgu Jiu Harghita 6610 363000 Miercurea Ciuc Hunedoara 7016 567000 Deva Ialomita 4449 309000 Slobozia Iasi 5469 810000 Iasi 330000 Maramures 6215 556000 Baia Mare 150000 Mehedinti 4900 329000 Drobeta Turnu Severin Mures 6696 621000 Tirgu Mures 165000 Neamt 5890 580000 Piatra Neamt Olt 5507 535000 Slatina Prahova 4694 877000 Ploiesti Salaj 3850 269000 Zalau Satu Mare 4405 417000 Satu Mare 137000 Sibiu 5422 509000 Sibiu 184000 Suceava 8555 699000 Suceava Teleorman 5760 504000 Alexandria Timis 8692 726000 Timisoara 333000 Tulcea 8430 275000 Tulcea Vaslui 5297 468000 Vaslui Vilcea 5705 430000 Rimnicu Vilcea Vrancea 4863 394000 Focsani Turkey TR 780580 62484478 1.67 43.2 345700 15.5 33.2 51.3 94 29 10 1923 republican parliamentary democracy 32 80 20 99.8 206 240 Adana 17253 1934907 Adana 35.3 36.9833 1047300 Osmaniye 138000 Adiyaman 7614 513131 Adiyaman 128000 Afyon 14230 739223 Afyon Agri 11376 437093 Agri Aksaray 7626 326399 Aksaray Amasya 5520 357191 Amasya Ankara 25706 3236626 Ankara 32.8833 39.95 2782200 Antalya 20591 1132211 Antalya 497200 Artvin 7436 212833 Artvin Aydin 8007 824816 Aydin 121200 Balikesir 14292 973314 Balikesir 187600 Batman 4694 344669 Batman 182800 Bayburt 3652 107330 Bayburt Bilecik 4307 175526 Bilecik Bingol 8125 250966 Bingol Bitlis 6707 330115 Bitlis Bolu 11051 536869 Bolu Burdur 6887 254899 Burdur Bursa 11043 1603137 Bursa 996600 Canakkale 9737 432263 Canakkale Cankiri 8454 279129 Cankiri Corum 12820 609863 Corum Denizli 11868 750882 Denizli 234500 Diyarbakir 15355 1094996 Diyarbakir 448300 Edirne 6276 404599 Edirne 115500 Elazig 9153 498225 Elazig 222800 Erzincan 11903 299251 Erzincan Erzurum 25066 848201 Erzurum 250100 Eskisehir 13652 641057 Eskisehir 451000 Gaziantep 7642 1140594 Gaziantep 716000 Giresun 6934 499087 Giresun Gumushane 6575 169375 Gumushane Hakkari 7121 172479 Hakkari Hatay 5403 1109754 Iskenderun 156800 Antakya 137200 Icel 15853 1266995 Mersin 523000 Tarsus 225000 Isparta 8933 434771 Isparta 120900 Istanbul 5712 7309190 Istanbul 28.8333 40.9667 7615500 Izmir 11973 2694770 Izmir 27.1667 38.4333 1985300 Karaman 9163 217536 Karaman Karamanmaras 14327 892952 Karaman Maras 242200 Kars 18557 662155 Kars Kastamonu 13108 423611 Kastamonu Kayseri 16917 943484 Kayseri 454000 Kirikkale 4365 349396 Kirikkale 170300 Kirklareli 6550 309512 Kirklareli Kirsehir 6570 256862 Kirsehir Kocaeli 3626 936163 Izmit 275800 Kocaeli 256882 Gebze 237300 Adapazari 186000 Konya 38257 1750303 Konya 576000 Kutahya 11875 578020 Kutahya 140700 Malatya 12313 702055 Malatya 319700 Manisa 13810 1154418 Manisa 187500 Mardin 8891 557727 Mardin Mugla 13338 562809 Mugla Mus 8196 376543 Mus Nevsehir 5467 289509 Nevsehir Nigde 7312 305861 Nigde Ordu 6001 830105 Ordu 121300 Rize 3920 348776 Rize Sakarya 4817 683061 Sakarya Samsun 9579 1158400 Samsun 326900 Sanliurfa 18584 1001455 Urfa 357900 Siirt 5406 243435 Siirt Sinop 5862 265153 Sinop Sirnak 7172 262006 Sirnak Sivas 28488 767481 Sivas 240100 Tekirdag 6218 468842 Tekirdag Tokat 9958 719251 Tokat Trabzon 4685 795849 Trabzon 145400 Tunceli 7774 133143 Tunceli Usak 5341 290283 Usak 119900 Van 19069 637433 Van 194600 Yozgat 14123 579150 Yozgat Zonguldak 8629 1073560 Zonguldak 115900 Karabuk 113900 Denmark DK 43070 5249632 0.38 4.8 112800 3 23.5 73.5 2.4 constitutional monarchy 100 91 2 68 Copenhagen 12.55 55.6833 1358540 Aarhus 10.1 56.1 194345 Odense 10.2 55.3 136803 Aalborg 10 57 113865 Esbjerg 8.3 55.3 70975 Randers 10 56.3 55780 Estonia EW 45100 1459428 -1.13 17.4 12300 10 37 53 29 06 09 1991 republic 100 3.2 30.3 1.8 1.1 61.5 267 290 Tallinn 25 59.3 478000 Finland SF 337030 5105230 0.1 4.9 92400 4.6 28 67.4 2 06 12 1917 republic 100 1 89 6.3 93.5 1313 729 586 Aland 23000 Mariehamn 19.5 60.1 9500 Haeme 662000 Haemeenlinna 24.3 61 42000 Tampere 23.5 61.3 170097 Lahti 25.2 60.5 94234 Kuopio 252000 Kuopio 27.4 62.5 78571 Kymi 345000 Kotka 26.5 60.3 58345 Lappeenrenta 26.5 60.5 53922 Lappia 195000 Rovaniemi 24.4 66.3 31000 Mikkeli 209000 Mikkeli 27.2 61.4 28000 Suomi 242000 Jyvaeskylae 25.2 62.1 65511 Pohjols-Karjala 177000 Joensuu 29.5 62.4 44000 Oulu 415000 Oulu 25.2 65.3 97898 Turku-Pori 702000 Turku 22.1 60.3 161292 Pori 21.2 61.3 77763 Uusimaa 1119000 Helsinki 24.95 60.1667 487428 Espoo 24.3 60.2 160480 Vaasa 430000 Vaasa 21.3 63 54275 Norway N 324220 4383807 0.48 4.9 106200 2.9 34.7 62.4 2.5 26 10 1905 constitutional monarchy 100 87.8 3.8 100 167 729 1619 Oslo 449337 Oslo 10.7333 59.9333 449337 Akershus 393217 Oestfold 234941 Moss 10.4 59.3 24517 Hedmark 186355 Hamar 11.5 60.5 15685 Oppland 181791 Lillehammer 10.3 61.1 22118 Buskerud 219967 Drammen 10.1 59.4 50855 Vestfold 191600 Toensberg 10.2 59.2 8984 Telemark 162547 Skien 9.4 59.1 47010 Aust Agder 94688 Arendal 8.4 58.3 12174 Vest Agder 140232 Kristiansand 8 58.1 62640 Rogaland 323365 Stavanger 5.5 59 95089 Hordaland 399702 Bergen 5.2 60.2 207916 Sogn og Fjordane 106116 Hermannsverk 6.5 61.1 706 Moere og Romsdal 237290 Molde 7.1 62.5 21448 Soer Trondelag 246824 Trondheim 10.2 63.3 134426 Nord Trondelag 126692 Steinkjer 11.3 64 20480 Nordland 242268 Bodoe 14.2 67.2 34479 Svolvaer 14.3 68.2 4500 Narvik 17.3 68.3 18754 Troms 146736 Tromsoe 19 69.4 48109 Finnmark 75667 Vadsoe 29.5 70.5 5961 Hammerfest 23.4 70.4 7089 Sweden S 449964 8900954 0.56 4.5 177300 2 27 71 2.6 constitutional monarchy 100 12 1.5 94 1 100 586 1619 Ĭvsborg 11395 444259 Vanersborg Blekinge 2941 151168 Karlskrona 15.3 56.1 59007 Gavleborg 18191 289339 Gavle Goteborg och Bohus 5141 742550 Goteborg 449189 Gotland 3140 57383 Visby 18.2 57.3 20000 Halland 5454 257874 Halmstad 13 56.4 77601 Jamtland 49443 136009 Ostersund Jonkoping 9944 309738 Jonkoping 115429 Kalmar 11170 241883 Kalmar 16.3 56.4 54554 Kopparberg 28194 290388 Falun 15.3 60.3 51900 Kristianstad 6087 291468 Kristianstad 14 56 69941 Kronoberg 8458 178612 Vaxjo Malmohus 4938 786757 Malmo 245699 Helsingborg 114339 Norrbotten 98913 264834 Lulea Orebro 8519 273608 Orebro 119635 Ostergotland 10562 406100 Linkoping 131370 Norrkoping 123795 Skaraborg 7937 278162 Mariestad 13.5 58.4 24255 Sodermanland 6060 256818 Nykoping Stockholm 6488 1654511 Stockholm 18.0667 59.35 711119 Uppsala 6989 273918 Uppsala 17.4 59.5 183472 Varmland 17584 284187 Karlstad 13.3 59.3 74669 Vasterbotten 55401 253835 Umea Vasternorrland 21678 261280 Harnosand Vastmanland 6302 259438 Vasteras 123728 Monaco MC 1.9 31719 0.59 6.9 788 01 01 1419 constitutional monarchy 100 47 16 16 95 4.4 Monaco 7.2 43.7 1234 Holy See V 0.44 840 11 02 1929 monarchical sacerdotal state 100 100 3.2 Vatican City 12.3 41.5 392 Iceland IS 103000 270292 0.83 4.3 5000 9.6 22.1 68.3 2.5 17 06 1944 republic 100 100 96 3 100 Reykjavik 21.9333 64.1333 84000 Keflavik -22.5 64 6600 Hafnarfjoerdur -22 64 12000 Akureyri 18.3 65.4 13000 Ireland IRL 70280 3566833 -0.22 6.4 54600 6.8 35.3 57.9 2.8 06 12 1921 republic 100 93 3 Dublin -6.35 53.3667 502337 San Marino RSM 60 24521 0.82 5.5 380 5.5 01 01 0301 republic 100 100 100 39 San Marino 12.2 43.5 4416 Malta M 320 375576 1.01 6.9 4400 5 21 09 1964 parliamentary democracy 100 98 Valletta 14.2 35.08 9302 Moldova MD 33700 4463847 0.18 47.6 10400 33 36 31 24 27 08 1991 republic 100 13.8 13 1.5 2 3.5 64.5 1.5 98.5 null 939 450 Chisinau 28.1 47.2 663000 Portugal P 92080 9865114 0.02 7.6 116200 6 35.8 58.2 4.6 01 01 1140 republic 100 97 1 100 1214 Aveiro 2808 656000 Beja 10225 167900 Braga 2673 746100 Braga 63033 Braganca 6608 158300 Castelo Branco 6675 214700 Coimbra 3947 427600 Coimbra 74616 Evora 7393 173500 Faro 4960 340100 Guarda 5518 187800 Leiria 3515 427800 Lisbon 2761 2063800 Lisbon -9.13333 38.7167 807937 Amadora 95518 Barreiro 50863 Almada 42607 Portalegre 6065 134300 Porto 2395 1622300 Porto 327368 Vila Nova de Gaia 62468 Santarem 6747 442700 Setubal 5064 713700 Setubal 77885 Viana do Castelo 2255 248700 Vila Real 4328 237100 Viseu 5007 401000 Azores, The 2247 236700 Madeira 794 253000 Funchal 44111 United Kingdom GB 244820 58489975 0.22 6.4 1138400 1.7 27.7 70.6 3.1 01 01 1801 constitutional monarchy 100 81.5 2.4 1.9 9.6 1.8 360 Avon 1346 962000 Bristol 399200 Bedfordshire 1235 534300 Bedford 137300 Luton 178600 Berkshire 1259 752500 Reading 137700 Wokingham 142900 Newbury 141000 Windsor 136700 Slough 103500 Bracknell 101900 Buckinghamshire 1883 640200 Aylesbury 151600 Milton Keynes 184400 Wycombe 161400 Cambridgeshire 3409 669900 Cambridge 113800 Peterborough 156400 Huntingdon 148800 Cheshire 2329 966500 Chester 120800 Warrington 185000 Macclesfield 151400 Crewe 109500 Cleveland 583 557500 Middlesbrough 145800 Stockton on Tees 177800 Cornwall _ Isles of Scilly 3564 475200 Truro Cumbria 6810 489700 Carlisle 102900 Derbyshire 2631 938800 Derby 230500 Sutton in Ashfield 109800 Chesterfield 101200 Matlock Devon 6711 1040000 Plymouth 255800 Exeter 105100 Dorset 2654 662900 Bournemouth 159900 Poole 137200 Dorchester Durham 2436 604300 Darlington 100200 Durham East Sussex 1795 716500 Brighton 154400 Lewes Essex 3672 1548800 Chelmsford 155700 Southend on Sea 167500 Basildon 161700 Colchester 149100 Braintree 121800 Epping Forest 118200 Gloucestershire 2643 538800 Cheltenham 106700 Stroud 105400 Gloucester 104800 Glouchester Greater London 1579 6803100 London 0 51.4833 6967500 Greater Manchester 1287 2561600 Manchester 431100 Wigan 310000 Stockport 291400 Bolton 265200 Salford 230700 Tameside 221800 Oldham 220400 Trafford 218100 Rochdale 207100 Bury 181400 Hampshire 3777 1578700 Winchester 100500 Southampton 211700 Portsmouth 189100 Basingstoke 146500 Havant 117500 Eastleigh 109600 Fareham 101000 Hereford and Worcester 3927 696000 Worcester Hertfordshire 1634 989500 Saint Albans 127700 Hertford Humberside 3512 874400 Kingston upon Hull 269100 Beverley 115800 Hull Isle of Wight 381 126600 Kent 3731 1538800 Maidstone 138500 Rochester upon Medway 148200 Canterbury 132400 Swale 117200 Sevenoaks 109400 Dover 106100 Tonbridge 102100 Tunbridge Wells 101800 Lancashire 3064 1408300 Preston 132200 Blackpool 153600 Blackburn 139500 Lancaster 133600 Leicestershire 2553 890800 Leicester 293400 Leichester Lincolnshire 5915 592600 Lincoln Merseyside 652 1441100 Liverpool 474000 Wiral 331100 Sefton 292400 Saint Helens 180200 Knowsley 155300 Norfolk 5368 759400 Norwich 128100 Kings Lynn 131600 Northamptonshire 2367 587100 Northampton 187200 Northumberland 5032 307100 North Yorkshire 8309 720900 Harrogate 146500 Scarborough 108700 York 104000 Northallerton Nottinghamshire 2164 1015500 Nottingham 282400 Newark on Trent 104400 Mansfield 102100 Oxfordshire 2608 597700 Oxford 132000 Shropshire 3490 412500 Shrewsbury Somerset 3451 469400 Taunton South Yorkshire 1560 1292700 Barnsley 226500 Sheffield 530100 Doncaster 292500 Rotherham 256300 Staffordshire 2716 1047400 Stafford 121500 Stoke on Trent 254200 Newcastle under Lyme 123000 Suffolk 3797 661900 Ipswich 114800 Surrey 1679 1035500 Guildford 126200 Reigate 118800 Elmbridge 117300 Kingston Tyne and Wear 540 1125600 Sunderland 292200 Newcastle upon Tyne 283600 Gateshead 202400 Newcastle Warwickshire 1981 489900 Warwick 118600 Nuneaton 118500 Stratford on Avon 108600 West Midlands 899 2619000 Birmingham -1.93333 52.4833 1008400 Dudley 312200 Coventry 302500 Walsall 263900 Wolverhampton 245100 Solihull 202000 West Bromwich 154500 West Sussex 1989 713600 Chichester 102500 Horsham 112300 West Yorkshire 2039 2066200 Wakefield 317300 Leeds 724400 Bradford 481700 Kirklees 386900 Huddersfield 148500 Wiltshire 3480 575100 Salisbury 109800 Trowbridge Borders 4698 105700 Newtown St. Boswells Central 2700 273400 Stirling Dumfries and Galloway 6425 147800 Dumfries Fife 1319 352100 Glenrothes Grampian 8752 532500 Aberdeen 219100 Highland 26137 207500 Inverness Lothian 1770 758600 Edinburgh -3.18333 55.9167 447600 Strathclyde 13773 2287800 Glasgow -4.28333 55.8667 674800 Renfrew 201700 Tayside 7643 395000 Dundee 167600 Island Areas (munic.) 5566 72000 Island Areas Aberconwy and Colwyn 1130 110700 Colwyn Bay Anglesey 719 68500 Llangefni Blaenau Gwent 109 73300 Ebbw Vale Bridgend 246 130900 Bridgend Caerphilly 279 171000 Ystrad Fawr Cardiff 139 306600 Cardiff -3.16667 51.4667 300000 Carmarthenshire 2398 169000 Carmarthen Ceredigion 1797 69700 Aberystwyth Denbighshire 844 91300 Ruthin Flintshire 437 145300 Mold Gwynedd 2548 117000 Caernarfon Merthyr Tydfil 111 59500 Merthyr Tydfil Monmouthshire 851 84200 Cwmbran Neath and Port Talbot 441 140100 Port Talbot Newport 191 137400 Newport 137000 Pembrokeshire 1590 113600 Haverfordwest Powys 5204 121800 Llandrindod Wells Rhondda Cynon Taff 424 239000 Rhondda Swansea 378 230900 Swansea 189300 Torfaen 126 90600 Pontypool Vale of Glamorgan 337 119200 Rhymney Valley 104300 Barry Wrexham 499 123500 Wrexham Northern Ireland 14120 1594400 Belfast -5.91667 54.6 297100 Cyprus CY 9250 744609 1.11 8.4 7800 5.6 24.9 69.5 16 08 1960 republic 100 18 78 Nicosia 33.2 35.4 161100 Europe 9562488 Agency for Cultural and Technical Cooperation ACCT 21 03 1970 Bank for International Settlements BIS 20 01 1930 Benelux Economic Union Benelux 03 02 1958 Central European Initiative CEI 27 07 1991 Commonwealth C 31 12 1931 Commonwealth of Independent States CIS 08 12 1991 Council of Europe CE 05 05 1949 Customs Cooperation Council CCC 15 12 1950 Economic Commission for Europe ECE 28 03 1947 European Bank for Reconstruction and Development EBRD 15 04 1991 European Free Trade Association EFTA 04 01 1960 European Investment Bank EIB 25 03 1957 European Organization for Nuclear Research CERN 01 07 1953 European Space Agency ESA 31 07 1973 European Union EU 07 02 1992 Food and Agriculture Organization FAO 16 10 1945 Franc Zone FZ 20 12 1945 Group of 10 G-10 01 10 1962 International Atomic Energy Agency IAEA 26 10 1956 International Chamber of Commerce ICC 01 01 1919 International Confederation of Free Trade Unions ICFTU 01 12 1949 International Criminal Police Organization Interpol 13 06 1956 International Energy Agency IEA 15 11 1974 International Federation of Red Cross and Red Crescent Societies IFRCS 05 05 1919 International Fund for Agricultural Development IFAD 01 11 1974 International Labor Organization ILO 11 04 1919 International Maritime Organization IMO 17 03 1958 International Mobile Satellite Organization Inmarsat 03 09 1976 International Olympic Committee IOC 23 06 1894 International Organization for Migration IOM 05 12 1951 International Organization for Standardization ISO 01 02 1947 International Red Cross and Red Crescent Movement ICRM 01 01 1928 International Telecommunication Union ITU 09 12 1932 Nordic Council NC 16 03 1952 Nordic Investment Bank NIB 04 12 1975 North Atlantic Cooperation Council ANC 08 11 1991 North Atlantic Treaty Organization NATO 17 09 1949 Nuclear Suppliers Group NSG Organization for Economic Cooperation and Development OECD 14 12 1960 Organization for Security and Cooperation in Europe OSCE 01 01 1995 United Nations Conference on Trade and Development UNCTAD 30 12 1964 United Nations Educational, Scientific, and Cultural Organization UNESCO 16 11 1945 United Nations Industrial Development Organization UNIDO 17 11 1966 United Nations Office of the High Commissioner for Refugees UNHCR 03 12 1949 United Nations Relief and Works Agency for Palestine Refugees in the Near East UNRWA 08 12 1949 Universal Postal Union UPU 09 10 1874 Western European Union WEU 23 10 1954 World Confederation of Labor WCL 19 06 1920 World Federation of Trade Unions WFTU 03 10 1945 World Health Organization WHO 22 07 1946 World Intellectual Property Organization WIPO 14 07 1967 World Meteorological Organization WMO 11 10 1947 World Tourism Organization WToO 02 01 1975 Jezerce 19.4 42.3 2694 Korab 20.3 41.4 2751 Kebnekaise 18.3 67.5 2114 Sarektjokko 17.4 67.3 2090 Portefjaellen 17.4 67.1 2021 Tarrekaise 17.3 67 1850 Sulitjelma 16.2 67.1 1914 Galdhoeppig 8 61.4 2469 Jostedalsbre 5.5 61.4 2083 Glittertind 8.1 61.4 2452 Joekul 7.2 60.3 1876 Snoehetta 9 62.1 2286 Elbrus 42.26 43.21 5642 Kasbek 44.31 42.42 5033 Bjelucha 86.4 49.48 4506 Oeraefajoekull -17 64.1 2119 Snoefell -15.2 64.5 1833 Haltiatunturi 21.4 67 1328 Feldberg 7.5 47.5 1493 Grosser Arber 13 49.1 1456 Zugspitze 11.1 47.3 2963 Grossglockner 12.5 47 3797 Montblanc 6 45 4807 776 Seine North Sea 200 2850 Donau Black Sea 2211 1020 Western Dwina Baltic Sea 459 1068 Weichsel 2201 Dnepr 346 Thames 1364 Kura Caspian Sea 424200 1010 Loire Atlantic Ocean 9219 650 Garonne 812 Rhone Mediterranean Sea 5121 477 Weser 1144 Elbe 1320 Rhein Bodensee 538.5 347 Klaraelv Vaenern 5546 435 Moldau 93 Goetaaelv Umeaelv Ounasjoki 520 Kemijoki Oulujoki 169 Kokemaeenjoki 740 Northern Dwina Arctic Ocean 5220 4130 Jenissej 3531 Volga 74 Neva White Drin Drin 133 Black Drin 230 Thjorsa 206 Joekulsa a Fjoellum Norwegian Sea 3860 Oesterdalaelv 520 Dalaelv Vaesterdalaelv 375 Torneaelv 598 Gloma 4400 Lena 3680 Ob 2918 Amur 1809 Petschora 2513 Kolyma 1636 Chatanga 688 Bija 306 Katun 4248 Irtysch 1591 Tobol 2450 Ischim 560 Schilka 1620 Argun 708 Ingoda 1032 Onon 200 Ajan-Jurjach 300 Kulu 605 Grosser Jenissej 680 Kleiner Jenissej 562 Suchona 574 Jug 1480 Oka 1870 Don Sea of Azov 100 2428 Ural 292 Werra 218 Fulda Pacific Ocean 11034 Irish Sea 272 Sea of Japan 4036 Maelaren 1140 Vaettern 1900 Lake Kalla 900 Lake Saima 1460 Paeijaenne 1090 Lake Ori 200 Mjoesen 368 Lake Naesi 250 Lake Skutari 300 Ozero Baikal 31500 Lake Prespa 285 Lake Ohrid 367 Ozero Ladoga 18400 Ozero Onega 9610 Ozero Taimyr 4560 Ozero Chanka 4400 Ozero Pskovskoje 3550 Ozero Tschany 2500 Inari 1085 Lago di Garda 370 Arresee 40.2 Lac Leman 581 Lago Maggiore 216 Lago di Como 146 tdom-0.9.5-src/tests/data/dtd-6.3.dtd0000644000175000017500000000002014703531020015555 0ustar rolfrolf tdom-0.9.5-src/tests/data/xmlspec-v20.dtd0000644000175000017500000014575614703531020016610 0ustar rolfrolf tdom-0.9.5-src/tests/data/domCmd2.dtd0000644000175000017500000000005414703531020015772 0ustar rolfrolf tdom-0.9.5-src/tests/data/dtd-6.2.dtd0000644000175000017500000000001714703531020015562 0ustar rolfrolf tdom-0.9.5-src/tests/data/i18n_1.xml0000644000175000017500000000004214703531020015526 0ustar rolfrolfабвгдежзий tdom-0.9.5-src/tests/data/xslt_1.xsl0000644000175000017500000000042214703531020015751 0ustar rolfrolf tdom-0.9.5-src/tests/data/dtd-6.4.dtd0000644000175000017500000000015214703531020015564 0ustar rolfrolf ]]> ]]> tdom-0.9.5-src/tests/data/htmlmathml.json0000644000175000017500000014222314703531020017057 0ustar rolfrolf { "characters": { "AElig": "\u00C6", "AMP": "\u0026", "Aacute": "\u00C1", "Abreve": "\u0102", "Acirc": "\u00C2", "Acy": "\u0410", "Afr": "\uD835\uDD04", "Agrave": "\u00C0", "Alpha": "\u0391", "Amacr": "\u0100", "And": "\u2A53", "Aogon": "\u0104", "Aopf": "\uD835\uDD38", "ApplyFunction": "\u2061", "Aring": "\u00C5", "Ascr": "\uD835\uDC9C", "Assign": "\u2254", "Atilde": "\u00C3", "Auml": "\u00C4", "Backslash": "\u2216", "Barv": "\u2AE7", "Barwed": "\u2306", "Bcy": "\u0411", "Because": "\u2235", "Bernoullis": "\u212C", "Beta": "\u0392", "Bfr": "\uD835\uDD05", "Bopf": "\uD835\uDD39", "Breve": "\u02D8", "Bscr": "\u212C", "Bumpeq": "\u224E", "CHcy": "\u0427", "COPY": "\u00A9", "Cacute": "\u0106", "Cap": "\u22D2", "CapitalDifferentialD": "\u2145", "Cayleys": "\u212D", "Ccaron": "\u010C", "Ccedil": "\u00C7", "Ccirc": "\u0108", "Cconint": "\u2230", "Cdot": "\u010A", "Cedilla": "\u00B8", "CenterDot": "\u00B7", "Cfr": "\u212D", "Chi": "\u03A7", "CircleDot": "\u2299", "CircleMinus": "\u2296", "CirclePlus": "\u2295", "CircleTimes": "\u2297", "ClockwiseContourIntegral": "\u2232", "CloseCurlyDoubleQuote": "\u201D", "CloseCurlyQuote": "\u2019", "Colon": "\u2237", "Colone": "\u2A74", "Congruent": "\u2261", "Conint": "\u222F", "ContourIntegral": "\u222E", "Copf": "\u2102", "Coproduct": "\u2210", "CounterClockwiseContourIntegral": "\u2233", "Cross": "\u2A2F", "Cscr": "\uD835\uDC9E", "Cup": "\u22D3", "CupCap": "\u224D", "DD": "\u2145", "DDotrahd": "\u2911", "DJcy": "\u0402", "DScy": "\u0405", "DZcy": "\u040F", "Dagger": "\u2021", "Darr": "\u21A1", "Dashv": "\u2AE4", "Dcaron": "\u010E", "Dcy": "\u0414", "Del": "\u2207", "Delta": "\u0394", "Dfr": "\uD835\uDD07", "DiacriticalAcute": "\u00B4", "DiacriticalDot": "\u02D9", "DiacriticalDoubleAcute": "\u02DD", "DiacriticalGrave": "\u0060", "DiacriticalTilde": "\u02DC", "Diamond": "\u22C4", "DifferentialD": "\u2146", "Dopf": "\uD835\uDD3B", "Dot": "\u00A8", "DotDot": " \u20DC", "DotEqual": "\u2250", "DoubleContourIntegral": "\u222F", "DoubleDot": "\u00A8", "DoubleDownArrow": "\u21D3", "DoubleLeftArrow": "\u21D0", "DoubleLeftRightArrow": "\u21D4", "DoubleLeftTee": "\u2AE4", "DoubleLongLeftArrow": "\u27F8", "DoubleLongLeftRightArrow": "\u27FA", "DoubleLongRightArrow": "\u27F9", "DoubleRightArrow": "\u21D2", "DoubleRightTee": "\u22A8", "DoubleUpArrow": "\u21D1", "DoubleUpDownArrow": "\u21D5", "DoubleVerticalBar": "\u2225", "DownArrow": "\u2193", "DownArrowBar": "\u2913", "DownArrowUpArrow": "\u21F5", "DownBreve": " \u0311", "DownLeftRightVector": "\u2950", "DownLeftTeeVector": "\u295E", "DownLeftVector": "\u21BD", "DownLeftVectorBar": "\u2956", "DownRightTeeVector": "\u295F", "DownRightVector": "\u21C1", "DownRightVectorBar": "\u2957", "DownTee": "\u22A4", "DownTeeArrow": "\u21A7", "Downarrow": "\u21D3", "Dscr": "\uD835\uDC9F", "Dstrok": "\u0110", "ENG": "\u014A", "ETH": "\u00D0", "Eacute": "\u00C9", "Ecaron": "\u011A", "Ecirc": "\u00CA", "Ecy": "\u042D", "Edot": "\u0116", "Efr": "\uD835\uDD08", "Egrave": "\u00C8", "Element": "\u2208", "Emacr": "\u0112", "EmptySmallSquare": "\u25FB", "EmptyVerySmallSquare": "\u25AB", "Eogon": "\u0118", "Eopf": "\uD835\uDD3C", "Epsilon": "\u0395", "Equal": "\u2A75", "EqualTilde": "\u2242", "Equilibrium": "\u21CC", "Escr": "\u2130", "Esim": "\u2A73", "Eta": "\u0397", "Euml": "\u00CB", "Exists": "\u2203", "ExponentialE": "\u2147", "Fcy": "\u0424", "Ffr": "\uD835\uDD09", "FilledSmallSquare": "\u25FC", "FilledVerySmallSquare": "\u25AA", "Fopf": "\uD835\uDD3D", "ForAll": "\u2200", "Fouriertrf": "\u2131", "Fscr": "\u2131", "GJcy": "\u0403", "GT": "\u003E", "Gamma": "\u0393", "Gammad": "\u03DC", "Gbreve": "\u011E", "Gcedil": "\u0122", "Gcirc": "\u011C", "Gcy": "\u0413", "Gdot": "\u0120", "Gfr": "\uD835\uDD0A", "Gg": "\u22D9", "Gopf": "\uD835\uDD3E", "GreaterEqual": "\u2265", "GreaterEqualLess": "\u22DB", "GreaterFullEqual": "\u2267", "GreaterGreater": "\u2AA2", "GreaterLess": "\u2277", "GreaterSlantEqual": "\u2A7E", "GreaterTilde": "\u2273", "Gscr": "\uD835\uDCA2", "Gt": "\u226B", "HARDcy": "\u042A", "Hacek": "\u02C7", "Hat": "\u005E", "Hcirc": "\u0124", "Hfr": "\u210C", "HilbertSpace": "\u210B", "Hopf": "\u210D", "HorizontalLine": "\u2500", "Hscr": "\u210B", "Hstrok": "\u0126", "HumpDownHump": "\u224E", "HumpEqual": "\u224F", "IEcy": "\u0415", "IJlig": "\u0132", "IOcy": "\u0401", "Iacute": "\u00CD", "Icirc": "\u00CE", "Icy": "\u0418", "Idot": "\u0130", "Ifr": "\u2111", "Igrave": "\u00CC", "Im": "\u2111", "Imacr": "\u012A", "ImaginaryI": "\u2148", "Implies": "\u21D2", "Int": "\u222C", "Integral": "\u222B", "Intersection": "\u22C2", "InvisibleComma": "\u2063", "InvisibleTimes": "\u2062", "Iogon": "\u012E", "Iopf": "\uD835\uDD40", "Iota": "\u0399", "Iscr": "\u2110", "Itilde": "\u0128", "Iukcy": "\u0406", "Iuml": "\u00CF", "Jcirc": "\u0134", "Jcy": "\u0419", "Jfr": "\uD835\uDD0D", "Jopf": "\uD835\uDD41", "Jscr": "\uD835\uDCA5", "Jsercy": "\u0408", "Jukcy": "\u0404", "KHcy": "\u0425", "KJcy": "\u040C", "Kappa": "\u039A", "Kcedil": "\u0136", "Kcy": "\u041A", "Kfr": "\uD835\uDD0E", "Kopf": "\uD835\uDD42", "Kscr": "\uD835\uDCA6", "LJcy": "\u0409", "LT": "\u003C", "Lacute": "\u0139", "Lambda": "\u039B", "Lang": "\u27EA", "Laplacetrf": "\u2112", "Larr": "\u219E", "Lcaron": "\u013D", "Lcedil": "\u013B", "Lcy": "\u041B", "LeftAngleBracket": "\u27E8", "LeftArrow": "\u2190", "LeftArrowBar": "\u21E4", "LeftArrowRightArrow": "\u21C6", "LeftCeiling": "\u2308", "LeftDoubleBracket": "\u27E6", "LeftDownTeeVector": "\u2961", "LeftDownVector": "\u21C3", "LeftDownVectorBar": "\u2959", "LeftFloor": "\u230A", "LeftRightArrow": "\u2194", "LeftRightVector": "\u294E", "LeftTee": "\u22A3", "LeftTeeArrow": "\u21A4", "LeftTeeVector": "\u295A", "LeftTriangle": "\u22B2", "LeftTriangleBar": "\u29CF", "LeftTriangleEqual": "\u22B4", "LeftUpDownVector": "\u2951", "LeftUpTeeVector": "\u2960", "LeftUpVector": "\u21BF", "LeftUpVectorBar": "\u2958", "LeftVector": "\u21BC", "LeftVectorBar": "\u2952", "Leftarrow": "\u21D0", "Leftrightarrow": "\u21D4", "LessEqualGreater": "\u22DA", "LessFullEqual": "\u2266", "LessGreater": "\u2276", "LessLess": "\u2AA1", "LessSlantEqual": "\u2A7D", "LessTilde": "\u2272", "Lfr": "\uD835\uDD0F", "Ll": "\u22D8", "Lleftarrow": "\u21DA", "Lmidot": "\u013F", "LongLeftArrow": "\u27F5", "LongLeftRightArrow": "\u27F7", "LongRightArrow": "\u27F6", "Longleftarrow": "\u27F8", "Longleftrightarrow": "\u27FA", "Longrightarrow": "\u27F9", "Lopf": "\uD835\uDD43", "LowerLeftArrow": "\u2199", "LowerRightArrow": "\u2198", "Lscr": "\u2112", "Lsh": "\u21B0", "Lstrok": "\u0141", "Lt": "\u226A", "Map": "\u2905", "Mcy": "\u041C", "MediumSpace": "\u205F", "Mellintrf": "\u2133", "Mfr": "\uD835\uDD10", "MinusPlus": "\u2213", "Mopf": "\uD835\uDD44", "Mscr": "\u2133", "Mu": "\u039C", "NJcy": "\u040A", "Nacute": "\u0143", "Ncaron": "\u0147", "Ncedil": "\u0145", "Ncy": "\u041D", "NegativeMediumSpace": "\u200B", "NegativeThickSpace": "\u200B", "NegativeThinSpace": "\u200B", "NegativeVeryThinSpace": "\u200B", "NestedGreaterGreater": "\u226B", "NestedLessLess": "\u226A", "NewLine": "\u000A", "Nfr": "\uD835\uDD11", "NoBreak": "\u2060", "NonBreakingSpace": "\u00A0", "Nopf": "\u2115", "Not": "\u2AEC", "NotCongruent": "\u2262", "NotCupCap": "\u226D", "NotDoubleVerticalBar": "\u2226", "NotElement": "\u2209", "NotEqual": "\u2260", "NotEqualTilde": "\u2242\u0338", "NotExists": "\u2204", "NotGreater": "\u226F", "NotGreaterEqual": "\u2271", "NotGreaterFullEqual": "\u2267\u0338", "NotGreaterGreater": "\u226B\u0338", "NotGreaterLess": "\u2279", "NotGreaterSlantEqual": "\u2A7E\u0338", "NotGreaterTilde": "\u2275", "NotHumpDownHump": "\u224E\u0338", "NotHumpEqual": "\u224F\u0338", "NotLeftTriangle": "\u22EA", "NotLeftTriangleBar": "\u29CF\u0338", "NotLeftTriangleEqual": "\u22EC", "NotLess": "\u226E", "NotLessEqual": "\u2270", "NotLessGreater": "\u2278", "NotLessLess": "\u226A\u0338", "NotLessSlantEqual": "\u2A7D\u0338", "NotLessTilde": "\u2274", "NotNestedGreaterGreater": "\u2AA2\u0338", "NotNestedLessLess": "\u2AA1\u0338", "NotPrecedes": "\u2280", "NotPrecedesEqual": "\u2AAF\u0338", "NotPrecedesSlantEqual": "\u22E0", "NotReverseElement": "\u220C", "NotRightTriangle": "\u22EB", "NotRightTriangleBar": "\u29D0\u0338", "NotRightTriangleEqual": "\u22ED", "NotSquareSubset": "\u228F\u0338", "NotSquareSubsetEqual": "\u22E2", "NotSquareSuperset": "\u2290\u0338", "NotSquareSupersetEqual": "\u22E3", "NotSubset": "\u2282\u20D2", "NotSubsetEqual": "\u2288", "NotSucceeds": "\u2281", "NotSucceedsEqual": "\u2AB0\u0338", "NotSucceedsSlantEqual": "\u22E1", "NotSucceedsTilde": "\u227F\u0338", "NotSuperset": "\u2283\u20D2", "NotSupersetEqual": "\u2289", "NotTilde": "\u2241", "NotTildeEqual": "\u2244", "NotTildeFullEqual": "\u2247", "NotTildeTilde": "\u2249", "NotVerticalBar": "\u2224", "Nscr": "\uD835\uDCA9", "Ntilde": "\u00D1", "Nu": "\u039D", "OElig": "\u0152", "Oacute": "\u00D3", "Ocirc": "\u00D4", "Ocy": "\u041E", "Odblac": "\u0150", "Ofr": "\uD835\uDD12", "Ograve": "\u00D2", "Omacr": "\u014C", "Omega": "\u03A9", "Omicron": "\u039F", "Oopf": "\uD835\uDD46", "OpenCurlyDoubleQuote": "\u201C", "OpenCurlyQuote": "\u2018", "Or": "\u2A54", "Oscr": "\uD835\uDCAA", "Oslash": "\u00D8", "Otilde": "\u00D5", "Otimes": "\u2A37", "Ouml": "\u00D6", "OverBar": "\u203E", "OverBrace": "\u23DE", "OverBracket": "\u23B4", "OverParenthesis": "\u23DC", "PartialD": "\u2202", "Pcy": "\u041F", "Pfr": "\uD835\uDD13", "Phi": "\u03A6", "Pi": "\u03A0", "PlusMinus": "\u00B1", "Poincareplane": "\u210C", "Popf": "\u2119", "Pr": "\u2ABB", "Precedes": "\u227A", "PrecedesEqual": "\u2AAF", "PrecedesSlantEqual": "\u227C", "PrecedesTilde": "\u227E", "Prime": "\u2033", "Product": "\u220F", "Proportion": "\u2237", "Proportional": "\u221D", "Pscr": "\uD835\uDCAB", "Psi": "\u03A8", "QUOT": "\u0022", "Qfr": "\uD835\uDD14", "Qopf": "\u211A", "Qscr": "\uD835\uDCAC", "RBarr": "\u2910", "REG": "\u00AE", "Racute": "\u0154", "Rang": "\u27EB", "Rarr": "\u21A0", "Rarrtl": "\u2916", "Rcaron": "\u0158", "Rcedil": "\u0156", "Rcy": "\u0420", "Re": "\u211C", "ReverseElement": "\u220B", "ReverseEquilibrium": "\u21CB", "ReverseUpEquilibrium": "\u296F", "Rfr": "\u211C", "Rho": "\u03A1", "RightAngleBracket": "\u27E9", "RightArrow": "\u2192", "RightArrowBar": "\u21E5", "RightArrowLeftArrow": "\u21C4", "RightCeiling": "\u2309", "RightDoubleBracket": "\u27E7", "RightDownTeeVector": "\u295D", "RightDownVector": "\u21C2", "RightDownVectorBar": "\u2955", "RightFloor": "\u230B", "RightTee": "\u22A2", "RightTeeArrow": "\u21A6", "RightTeeVector": "\u295B", "RightTriangle": "\u22B3", "RightTriangleBar": "\u29D0", "RightTriangleEqual": "\u22B5", "RightUpDownVector": "\u294F", "RightUpTeeVector": "\u295C", "RightUpVector": "\u21BE", "RightUpVectorBar": "\u2954", "RightVector": "\u21C0", "RightVectorBar": "\u2953", "Rightarrow": "\u21D2", "Ropf": "\u211D", "RoundImplies": "\u2970", "Rrightarrow": "\u21DB", "Rscr": "\u211B", "Rsh": "\u21B1", "RuleDelayed": "\u29F4", "SHCHcy": "\u0429", "SHcy": "\u0428", "SOFTcy": "\u042C", "Sacute": "\u015A", "Sc": "\u2ABC", "Scaron": "\u0160", "Scedil": "\u015E", "Scirc": "\u015C", "Scy": "\u0421", "Sfr": "\uD835\uDD16", "ShortDownArrow": "\u2193", "ShortLeftArrow": "\u2190", "ShortRightArrow": "\u2192", "ShortUpArrow": "\u2191", "Sigma": "\u03A3", "SmallCircle": "\u2218", "Sopf": "\uD835\uDD4A", "Sqrt": "\u221A", "Square": "\u25A1", "SquareIntersection": "\u2293", "SquareSubset": "\u228F", "SquareSubsetEqual": "\u2291", "SquareSuperset": "\u2290", "SquareSupersetEqual": "\u2292", "SquareUnion": "\u2294", "Sscr": "\uD835\uDCAE", "Star": "\u22C6", "Sub": "\u22D0", "Subset": "\u22D0", "SubsetEqual": "\u2286", "Succeeds": "\u227B", "SucceedsEqual": "\u2AB0", "SucceedsSlantEqual": "\u227D", "SucceedsTilde": "\u227F", "SuchThat": "\u220B", "Sum": "\u2211", "Sup": "\u22D1", "Superset": "\u2283", "SupersetEqual": "\u2287", "Supset": "\u22D1", "THORN": "\u00DE", "TRADE": "\u2122", "TSHcy": "\u040B", "TScy": "\u0426", "Tab": "\u0009", "Tau": "\u03A4", "Tcaron": "\u0164", "Tcedil": "\u0162", "Tcy": "\u0422", "Tfr": "\uD835\uDD17", "Therefore": "\u2234", "Theta": "\u0398", "ThickSpace": "\u205F\u200A", "ThinSpace": "\u2009", "Tilde": "\u223C", "TildeEqual": "\u2243", "TildeFullEqual": "\u2245", "TildeTilde": "\u2248", "Topf": "\uD835\uDD4B", "TripleDot": " \u20DB", "Tscr": "\uD835\uDCAF", "Tstrok": "\u0166", "Uacute": "\u00DA", "Uarr": "\u219F", "Uarrocir": "\u2949", "Ubrcy": "\u040E", "Ubreve": "\u016C", "Ucirc": "\u00DB", "Ucy": "\u0423", "Udblac": "\u0170", "Ufr": "\uD835\uDD18", "Ugrave": "\u00D9", "Umacr": "\u016A", "UnderBar": "\u005F", "UnderBrace": "\u23DF", "UnderBracket": "\u23B5", "UnderParenthesis": "\u23DD", "Union": "\u22C3", "UnionPlus": "\u228E", "Uogon": "\u0172", "Uopf": "\uD835\uDD4C", "UpArrow": "\u2191", "UpArrowBar": "\u2912", "UpArrowDownArrow": "\u21C5", "UpDownArrow": "\u2195", "UpEquilibrium": "\u296E", "UpTee": "\u22A5", "UpTeeArrow": "\u21A5", "Uparrow": "\u21D1", "Updownarrow": "\u21D5", "UpperLeftArrow": "\u2196", "UpperRightArrow": "\u2197", "Upsi": "\u03D2", "Upsilon": "\u03A5", "Uring": "\u016E", "Uscr": "\uD835\uDCB0", "Utilde": "\u0168", "Uuml": "\u00DC", "VDash": "\u22AB", "Vbar": "\u2AEB", "Vcy": "\u0412", "Vdash": "\u22A9", "Vdashl": "\u2AE6", "Vee": "\u22C1", "Verbar": "\u2016", "Vert": "\u2016", "VerticalBar": "\u2223", "VerticalLine": "\u007C", "VerticalSeparator": "\u2758", "VerticalTilde": "\u2240", "VeryThinSpace": "\u200A", "Vfr": "\uD835\uDD19", "Vopf": "\uD835\uDD4D", "Vscr": "\uD835\uDCB1", "Vvdash": "\u22AA", "Wcirc": "\u0174", "Wedge": "\u22C0", "Wfr": "\uD835\uDD1A", "Wopf": "\uD835\uDD4E", "Wscr": "\uD835\uDCB2", "Xfr": "\uD835\uDD1B", "Xi": "\u039E", "Xopf": "\uD835\uDD4F", "Xscr": "\uD835\uDCB3", "YAcy": "\u042F", "YIcy": "\u0407", "YUcy": "\u042E", "Yacute": "\u00DD", "Ycirc": "\u0176", "Ycy": "\u042B", "Yfr": "\uD835\uDD1C", "Yopf": "\uD835\uDD50", "Yscr": "\uD835\uDCB4", "Yuml": "\u0178", "ZHcy": "\u0416", "Zacute": "\u0179", "Zcaron": "\u017D", "Zcy": "\u0417", "Zdot": "\u017B", "ZeroWidthSpace": "\u200B", "Zeta": "\u0396", "Zfr": "\u2128", "Zopf": "\u2124", "Zscr": "\uD835\uDCB5", "aacute": "\u00E1", "abreve": "\u0103", "ac": "\u223E", "acE": "\u223E\u0333", "acd": "\u223F", "acirc": "\u00E2", "acute": "\u00B4", "acy": "\u0430", "aelig": "\u00E6", "af": "\u2061", "afr": "\uD835\uDD1E", "agrave": "\u00E0", "alefsym": "\u2135", "aleph": "\u2135", "alpha": "\u03B1", "amacr": "\u0101", "amalg": "\u2A3F", "amp": "\u0026", "and": "\u2227", "andand": "\u2A55", "andd": "\u2A5C", "andslope": "\u2A58", "andv": "\u2A5A", "ang": "\u2220", "ange": "\u29A4", "angle": "\u2220", "angmsd": "\u2221", "angmsdaa": "\u29A8", "angmsdab": "\u29A9", "angmsdac": "\u29AA", "angmsdad": "\u29AB", "angmsdae": "\u29AC", "angmsdaf": "\u29AD", "angmsdag": "\u29AE", "angmsdah": "\u29AF", "angrt": "\u221F", "angrtvb": "\u22BE", "angrtvbd": "\u299D", "angsph": "\u2222", "angst": "\u00C5", "angzarr": "\u237C", "aogon": "\u0105", "aopf": "\uD835\uDD52", "ap": "\u2248", "apE": "\u2A70", "apacir": "\u2A6F", "ape": "\u224A", "apid": "\u224B", "apos": "\u0027", "approx": "\u2248", "approxeq": "\u224A", "aring": "\u00E5", "ascr": "\uD835\uDCB6", "ast": "\u002A", "asymp": "\u2248", "asympeq": "\u224D", "atilde": "\u00E3", "auml": "\u00E4", "awconint": "\u2233", "awint": "\u2A11", "bNot": "\u2AED", "backcong": "\u224C", "backepsilon": "\u03F6", "backprime": "\u2035", "backsim": "\u223D", "backsimeq": "\u22CD", "barvee": "\u22BD", "barwed": "\u2305", "barwedge": "\u2305", "bbrk": "\u23B5", "bbrktbrk": "\u23B6", "bcong": "\u224C", "bcy": "\u0431", "bdquo": "\u201E", "becaus": "\u2235", "because": "\u2235", "bemptyv": "\u29B0", "bepsi": "\u03F6", "bernou": "\u212C", "beta": "\u03B2", "beth": "\u2136", "between": "\u226C", "bfr": "\uD835\uDD1F", "bigcap": "\u22C2", "bigcirc": "\u25EF", "bigcup": "\u22C3", "bigodot": "\u2A00", "bigoplus": "\u2A01", "bigotimes": "\u2A02", "bigsqcup": "\u2A06", "bigstar": "\u2605", "bigtriangledown": "\u25BD", "bigtriangleup": "\u25B3", "biguplus": "\u2A04", "bigvee": "\u22C1", "bigwedge": "\u22C0", "bkarow": "\u290D", "blacklozenge": "\u29EB", "blacksquare": "\u25AA", "blacktriangle": "\u25B4", "blacktriangledown": "\u25BE", "blacktriangleleft": "\u25C2", "blacktriangleright": "\u25B8", "blank": "\u2423", "blk12": "\u2592", "blk14": "\u2591", "blk34": "\u2593", "block": "\u2588", "bne": "\u003D\u20E5", "bnequiv": "\u2261\u20E5", "bnot": "\u2310", "bopf": "\uD835\uDD53", "bot": "\u22A5", "bottom": "\u22A5", "bowtie": "\u22C8", "boxDL": "\u2557", "boxDR": "\u2554", "boxDl": "\u2556", "boxDr": "\u2553", "boxH": "\u2550", "boxHD": "\u2566", "boxHU": "\u2569", "boxHd": "\u2564", "boxHu": "\u2567", "boxUL": "\u255D", "boxUR": "\u255A", "boxUl": "\u255C", "boxUr": "\u2559", "boxV": "\u2551", "boxVH": "\u256C", "boxVL": "\u2563", "boxVR": "\u2560", "boxVh": "\u256B", "boxVl": "\u2562", "boxVr": "\u255F", "boxbox": "\u29C9", "boxdL": "\u2555", "boxdR": "\u2552", "boxdl": "\u2510", "boxdr": "\u250C", "boxh": "\u2500", "boxhD": "\u2565", "boxhU": "\u2568", "boxhd": "\u252C", "boxhu": "\u2534", "boxminus": "\u229F", "boxplus": "\u229E", "boxtimes": "\u22A0", "boxuL": "\u255B", "boxuR": "\u2558", "boxul": "\u2518", "boxur": "\u2514", "boxv": "\u2502", "boxvH": "\u256A", "boxvL": "\u2561", "boxvR": "\u255E", "boxvh": "\u253C", "boxvl": "\u2524", "boxvr": "\u251C", "bprime": "\u2035", "breve": "\u02D8", "brvbar": "\u00A6", "bscr": "\uD835\uDCB7", "bsemi": "\u204F", "bsim": "\u223D", "bsime": "\u22CD", "bsol": "\u005C", "bsolb": "\u29C5", "bsolhsub": "\u27C8", "bull": "\u2022", "bullet": "\u2022", "bump": "\u224E", "bumpE": "\u2AAE", "bumpe": "\u224F", "bumpeq": "\u224F", "cacute": "\u0107", "cap": "\u2229", "capand": "\u2A44", "capbrcup": "\u2A49", "capcap": "\u2A4B", "capcup": "\u2A47", "capdot": "\u2A40", "caps": "\u2229\uFE00", "caret": "\u2041", "caron": "\u02C7", "ccaps": "\u2A4D", "ccaron": "\u010D", "ccedil": "\u00E7", "ccirc": "\u0109", "ccups": "\u2A4C", "ccupssm": "\u2A50", "cdot": "\u010B", "cedil": "\u00B8", "cemptyv": "\u29B2", "cent": "\u00A2", "centerdot": "\u00B7", "cfr": "\uD835\uDD20", "chcy": "\u0447", "check": "\u2713", "checkmark": "\u2713", "chi": "\u03C7", "cir": "\u25CB", "cirE": "\u29C3", "circ": "\u02C6", "circeq": "\u2257", "circlearrowleft": "\u21BA", "circlearrowright": "\u21BB", "circledR": "\u00AE", "circledS": "\u24C8", "circledast": "\u229B", "circledcirc": "\u229A", "circleddash": "\u229D", "cire": "\u2257", "cirfnint": "\u2A10", "cirmid": "\u2AEF", "cirscir": "\u29C2", "clubs": "\u2663", "clubsuit": "\u2663", "colon": "\u003A", "colone": "\u2254", "coloneq": "\u2254", "comma": "\u002C", "commat": "\u0040", "comp": "\u2201", "compfn": "\u2218", "complement": "\u2201", "complexes": "\u2102", "cong": "\u2245", "congdot": "\u2A6D", "conint": "\u222E", "copf": "\uD835\uDD54", "coprod": "\u2210", "copy": "\u00A9", "copysr": "\u2117", "crarr": "\u21B5", "cross": "\u2717", "cscr": "\uD835\uDCB8", "csub": "\u2ACF", "csube": "\u2AD1", "csup": "\u2AD0", "csupe": "\u2AD2", "ctdot": "\u22EF", "cudarrl": "\u2938", "cudarrr": "\u2935", "cuepr": "\u22DE", "cuesc": "\u22DF", "cularr": "\u21B6", "cularrp": "\u293D", "cup": "\u222A", "cupbrcap": "\u2A48", "cupcap": "\u2A46", "cupcup": "\u2A4A", "cupdot": "\u228D", "cupor": "\u2A45", "cups": "\u222A\uFE00", "curarr": "\u21B7", "curarrm": "\u293C", "curlyeqprec": "\u22DE", "curlyeqsucc": "\u22DF", "curlyvee": "\u22CE", "curlywedge": "\u22CF", "curren": "\u00A4", "curvearrowleft": "\u21B6", "curvearrowright": "\u21B7", "cuvee": "\u22CE", "cuwed": "\u22CF", "cwconint": "\u2232", "cwint": "\u2231", "cylcty": "\u232D", "dArr": "\u21D3", "dHar": "\u2965", "dagger": "\u2020", "daleth": "\u2138", "darr": "\u2193", "dash": "\u2010", "dashv": "\u22A3", "dbkarow": "\u290F", "dblac": "\u02DD", "dcaron": "\u010F", "dcy": "\u0434", "dd": "\u2146", "ddagger": "\u2021", "ddarr": "\u21CA", "ddotseq": "\u2A77", "deg": "\u00B0", "delta": "\u03B4", "demptyv": "\u29B1", "dfisht": "\u297F", "dfr": "\uD835\uDD21", "dharl": "\u21C3", "dharr": "\u21C2", "diam": "\u22C4", "diamond": "\u22C4", "diamondsuit": "\u2666", "diams": "\u2666", "die": "\u00A8", "digamma": "\u03DD", "disin": "\u22F2", "div": "\u00F7", "divide": "\u00F7", "divideontimes": "\u22C7", "divonx": "\u22C7", "djcy": "\u0452", "dlcorn": "\u231E", "dlcrop": "\u230D", "dollar": "\u0024", "dopf": "\uD835\uDD55", "dot": "\u02D9", "doteq": "\u2250", "doteqdot": "\u2251", "dotminus": "\u2238", "dotplus": "\u2214", "dotsquare": "\u22A1", "doublebarwedge": "\u2306", "downarrow": "\u2193", "downdownarrows": "\u21CA", "downharpoonleft": "\u21C3", "downharpoonright": "\u21C2", "drbkarow": "\u2910", "drcorn": "\u231F", "drcrop": "\u230C", "dscr": "\uD835\uDCB9", "dscy": "\u0455", "dsol": "\u29F6", "dstrok": "\u0111", "dtdot": "\u22F1", "dtri": "\u25BF", "dtrif": "\u25BE", "duarr": "\u21F5", "duhar": "\u296F", "dwangle": "\u29A6", "dzcy": "\u045F", "dzigrarr": "\u27FF", "eDDot": "\u2A77", "eDot": "\u2251", "eacute": "\u00E9", "easter": "\u2A6E", "ecaron": "\u011B", "ecir": "\u2256", "ecirc": "\u00EA", "ecolon": "\u2255", "ecy": "\u044D", "edot": "\u0117", "ee": "\u2147", "efDot": "\u2252", "efr": "\uD835\uDD22", "eg": "\u2A9A", "egrave": "\u00E8", "egs": "\u2A96", "egsdot": "\u2A98", "el": "\u2A99", "elinters": "\u23E7", "ell": "\u2113", "els": "\u2A95", "elsdot": "\u2A97", "emacr": "\u0113", "empty": "\u2205", "emptyset": "\u2205", "emptyv": "\u2205", "emsp": "\u2003", "emsp13": "\u2004", "emsp14": "\u2005", "eng": "\u014B", "ensp": "\u2002", "eogon": "\u0119", "eopf": "\uD835\uDD56", "epar": "\u22D5", "eparsl": "\u29E3", "eplus": "\u2A71", "epsi": "\u03B5", "epsilon": "\u03B5", "epsiv": "\u03F5", "eqcirc": "\u2256", "eqcolon": "\u2255", "eqsim": "\u2242", "eqslantgtr": "\u2A96", "eqslantless": "\u2A95", "equals": "\u003D", "equest": "\u225F", "equiv": "\u2261", "equivDD": "\u2A78", "eqvparsl": "\u29E5", "erDot": "\u2253", "erarr": "\u2971", "escr": "\u212F", "esdot": "\u2250", "esim": "\u2242", "eta": "\u03B7", "eth": "\u00F0", "euml": "\u00EB", "euro": "\u20AC", "excl": "\u0021", "exist": "\u2203", "expectation": "\u2130", "exponentiale": "\u2147", "fallingdotseq": "\u2252", "fcy": "\u0444", "female": "\u2640", "ffilig": "\uFB03", "fflig": "\uFB00", "ffllig": "\uFB04", "ffr": "\uD835\uDD23", "filig": "\uFB01", "fjlig": "\u0066\u006A", "flat": "\u266D", "fllig": "\uFB02", "fltns": "\u25B1", "fnof": "\u0192", "fopf": "\uD835\uDD57", "forall": "\u2200", "fork": "\u22D4", "forkv": "\u2AD9", "fpartint": "\u2A0D", "frac12": "\u00BD", "frac13": "\u2153", "frac14": "\u00BC", "frac15": "\u2155", "frac16": "\u2159", "frac18": "\u215B", "frac23": "\u2154", "frac25": "\u2156", "frac34": "\u00BE", "frac35": "\u2157", "frac38": "\u215C", "frac45": "\u2158", "frac56": "\u215A", "frac58": "\u215D", "frac78": "\u215E", "frasl": "\u2044", "frown": "\u2322", "fscr": "\uD835\uDCBB", "gE": "\u2267", "gEl": "\u2A8C", "gacute": "\u01F5", "gamma": "\u03B3", "gammad": "\u03DD", "gap": "\u2A86", "gbreve": "\u011F", "gcirc": "\u011D", "gcy": "\u0433", "gdot": "\u0121", "ge": "\u2265", "gel": "\u22DB", "geq": "\u2265", "geqq": "\u2267", "geqslant": "\u2A7E", "ges": "\u2A7E", "gescc": "\u2AA9", "gesdot": "\u2A80", "gesdoto": "\u2A82", "gesdotol": "\u2A84", "gesl": "\u22DB\uFE00", "gesles": "\u2A94", "gfr": "\uD835\uDD24", "gg": "\u226B", "ggg": "\u22D9", "gimel": "\u2137", "gjcy": "\u0453", "gl": "\u2277", "glE": "\u2A92", "gla": "\u2AA5", "glj": "\u2AA4", "gnE": "\u2269", "gnap": "\u2A8A", "gnapprox": "\u2A8A", "gne": "\u2A88", "gneq": "\u2A88", "gneqq": "\u2269", "gnsim": "\u22E7", "gopf": "\uD835\uDD58", "grave": "\u0060", "gscr": "\u210A", "gsim": "\u2273", "gsime": "\u2A8E", "gsiml": "\u2A90", "gt": "\u003E", "gtcc": "\u2AA7", "gtcir": "\u2A7A", "gtdot": "\u22D7", "gtlPar": "\u2995", "gtquest": "\u2A7C", "gtrapprox": "\u2A86", "gtrarr": "\u2978", "gtrdot": "\u22D7", "gtreqless": "\u22DB", "gtreqqless": "\u2A8C", "gtrless": "\u2277", "gtrsim": "\u2273", "gvertneqq": "\u2269\uFE00", "gvnE": "\u2269\uFE00", "hArr": "\u21D4", "hairsp": "\u200A", "half": "\u00BD", "hamilt": "\u210B", "hardcy": "\u044A", "harr": "\u2194", "harrcir": "\u2948", "harrw": "\u21AD", "hbar": "\u210F", "hcirc": "\u0125", "hearts": "\u2665", "heartsuit": "\u2665", "hellip": "\u2026", "hercon": "\u22B9", "hfr": "\uD835\uDD25", "hksearow": "\u2925", "hkswarow": "\u2926", "hoarr": "\u21FF", "homtht": "\u223B", "hookleftarrow": "\u21A9", "hookrightarrow": "\u21AA", "hopf": "\uD835\uDD59", "horbar": "\u2015", "hscr": "\uD835\uDCBD", "hslash": "\u210F", "hstrok": "\u0127", "hybull": "\u2043", "hyphen": "\u2010", "iacute": "\u00ED", "ic": "\u2063", "icirc": "\u00EE", "icy": "\u0438", "iecy": "\u0435", "iexcl": "\u00A1", "iff": "\u21D4", "ifr": "\uD835\uDD26", "igrave": "\u00EC", "ii": "\u2148", "iiiint": "\u2A0C", "iiint": "\u222D", "iinfin": "\u29DC", "iiota": "\u2129", "ijlig": "\u0133", "imacr": "\u012B", "image": "\u2111", "imagline": "\u2110", "imagpart": "\u2111", "imath": "\u0131", "imof": "\u22B7", "imped": "\u01B5", "in": "\u2208", "incare": "\u2105", "infin": "\u221E", "infintie": "\u29DD", "inodot": "\u0131", "int": "\u222B", "intcal": "\u22BA", "integers": "\u2124", "intercal": "\u22BA", "intlarhk": "\u2A17", "intprod": "\u2A3C", "iocy": "\u0451", "iogon": "\u012F", "iopf": "\uD835\uDD5A", "iota": "\u03B9", "iprod": "\u2A3C", "iquest": "\u00BF", "iscr": "\uD835\uDCBE", "isin": "\u2208", "isinE": "\u22F9", "isindot": "\u22F5", "isins": "\u22F4", "isinsv": "\u22F3", "isinv": "\u2208", "it": "\u2062", "itilde": "\u0129", "iukcy": "\u0456", "iuml": "\u00EF", "jcirc": "\u0135", "jcy": "\u0439", "jfr": "\uD835\uDD27", "jmath": "\u0237", "jopf": "\uD835\uDD5B", "jscr": "\uD835\uDCBF", "jsercy": "\u0458", "jukcy": "\u0454", "kappa": "\u03BA", "kappav": "\u03F0", "kcedil": "\u0137", "kcy": "\u043A", "kfr": "\uD835\uDD28", "kgreen": "\u0138", "khcy": "\u0445", "kjcy": "\u045C", "kopf": "\uD835\uDD5C", "kscr": "\uD835\uDCC0", "lAarr": "\u21DA", "lArr": "\u21D0", "lAtail": "\u291B", "lBarr": "\u290E", "lE": "\u2266", "lEg": "\u2A8B", "lHar": "\u2962", "lacute": "\u013A", "laemptyv": "\u29B4", "lagran": "\u2112", "lambda": "\u03BB", "lang": "\u27E8", "langd": "\u2991", "langle": "\u27E8", "lap": "\u2A85", "laquo": "\u00AB", "larr": "\u2190", "larrb": "\u21E4", "larrbfs": "\u291F", "larrfs": "\u291D", "larrhk": "\u21A9", "larrlp": "\u21AB", "larrpl": "\u2939", "larrsim": "\u2973", "larrtl": "\u21A2", "lat": "\u2AAB", "latail": "\u2919", "late": "\u2AAD", "lates": "\u2AAD\uFE00", "lbarr": "\u290C", "lbbrk": "\u2772", "lbrace": "\u007B", "lbrack": "\u005B", "lbrke": "\u298B", "lbrksld": "\u298F", "lbrkslu": "\u298D", "lcaron": "\u013E", "lcedil": "\u013C", "lceil": "\u2308", "lcub": "\u007B", "lcy": "\u043B", "ldca": "\u2936", "ldquo": "\u201C", "ldquor": "\u201E", "ldrdhar": "\u2967", "ldrushar": "\u294B", "ldsh": "\u21B2", "le": "\u2264", "leftarrow": "\u2190", "leftarrowtail": "\u21A2", "leftharpoondown": "\u21BD", "leftharpoonup": "\u21BC", "leftleftarrows": "\u21C7", "leftrightarrow": "\u2194", "leftrightarrows": "\u21C6", "leftrightharpoons": "\u21CB", "leftrightsquigarrow": "\u21AD", "leftthreetimes": "\u22CB", "leg": "\u22DA", "leq": "\u2264", "leqq": "\u2266", "leqslant": "\u2A7D", "les": "\u2A7D", "lescc": "\u2AA8", "lesdot": "\u2A7F", "lesdoto": "\u2A81", "lesdotor": "\u2A83", "lesg": "\u22DA\uFE00", "lesges": "\u2A93", "lessapprox": "\u2A85", "lessdot": "\u22D6", "lesseqgtr": "\u22DA", "lesseqqgtr": "\u2A8B", "lessgtr": "\u2276", "lesssim": "\u2272", "lfisht": "\u297C", "lfloor": "\u230A", "lfr": "\uD835\uDD29", "lg": "\u2276", "lgE": "\u2A91", "lhard": "\u21BD", "lharu": "\u21BC", "lharul": "\u296A", "lhblk": "\u2584", "ljcy": "\u0459", "ll": "\u226A", "llarr": "\u21C7", "llcorner": "\u231E", "llhard": "\u296B", "lltri": "\u25FA", "lmidot": "\u0140", "lmoust": "\u23B0", "lmoustache": "\u23B0", "lnE": "\u2268", "lnap": "\u2A89", "lnapprox": "\u2A89", "lne": "\u2A87", "lneq": "\u2A87", "lneqq": "\u2268", "lnsim": "\u22E6", "loang": "\u27EC", "loarr": "\u21FD", "lobrk": "\u27E6", "longleftarrow": "\u27F5", "longleftrightarrow": "\u27F7", "longmapsto": "\u27FC", "longrightarrow": "\u27F6", "looparrowleft": "\u21AB", "looparrowright": "\u21AC", "lopar": "\u2985", "lopf": "\uD835\uDD5D", "loplus": "\u2A2D", "lotimes": "\u2A34", "lowast": "\u2217", "lowbar": "\u005F", "loz": "\u25CA", "lozenge": "\u25CA", "lozf": "\u29EB", "lpar": "\u0028", "lparlt": "\u2993", "lrarr": "\u21C6", "lrcorner": "\u231F", "lrhar": "\u21CB", "lrhard": "\u296D", "lrm": "\u200E", "lrtri": "\u22BF", "lsaquo": "\u2039", "lscr": "\uD835\uDCC1", "lsh": "\u21B0", "lsim": "\u2272", "lsime": "\u2A8D", "lsimg": "\u2A8F", "lsqb": "\u005B", "lsquo": "\u2018", "lsquor": "\u201A", "lstrok": "\u0142", "lt": "\u003C", "ltcc": "\u2AA6", "ltcir": "\u2A79", "ltdot": "\u22D6", "lthree": "\u22CB", "ltimes": "\u22C9", "ltlarr": "\u2976", "ltquest": "\u2A7B", "ltrPar": "\u2996", "ltri": "\u25C3", "ltrie": "\u22B4", "ltrif": "\u25C2", "lurdshar": "\u294A", "luruhar": "\u2966", "lvertneqq": "\u2268\uFE00", "lvnE": "\u2268\uFE00", "mDDot": "\u223A", "macr": "\u00AF", "male": "\u2642", "malt": "\u2720", "maltese": "\u2720", "map": "\u21A6", "mapsto": "\u21A6", "mapstodown": "\u21A7", "mapstoleft": "\u21A4", "mapstoup": "\u21A5", "marker": "\u25AE", "mcomma": "\u2A29", "mcy": "\u043C", "mdash": "\u2014", "measuredangle": "\u2221", "mfr": "\uD835\uDD2A", "mho": "\u2127", "micro": "\u00B5", "mid": "\u2223", "midast": "\u002A", "midcir": "\u2AF0", "middot": "\u00B7", "minus": "\u2212", "minusb": "\u229F", "minusd": "\u2238", "minusdu": "\u2A2A", "mlcp": "\u2ADB", "mldr": "\u2026", "mnplus": "\u2213", "models": "\u22A7", "mopf": "\uD835\uDD5E", "mp": "\u2213", "mscr": "\uD835\uDCC2", "mstpos": "\u223E", "mu": "\u03BC", "multimap": "\u22B8", "mumap": "\u22B8", "nGg": "\u22D9\u0338", "nGt": "\u226B\u20D2", "nGtv": "\u226B\u0338", "nLeftarrow": "\u21CD", "nLeftrightarrow": "\u21CE", "nLl": "\u22D8\u0338", "nLt": "\u226A\u20D2", "nLtv": "\u226A\u0338", "nRightarrow": "\u21CF", "nVDash": "\u22AF", "nVdash": "\u22AE", "nabla": "\u2207", "nacute": "\u0144", "nang": "\u2220\u20D2", "nap": "\u2249", "napE": "\u2A70\u0338", "napid": "\u224B\u0338", "napos": "\u0149", "napprox": "\u2249", "natur": "\u266E", "natural": "\u266E", "naturals": "\u2115", "nbsp": "\u00A0", "nbump": "\u224E\u0338", "nbumpe": "\u224F\u0338", "ncap": "\u2A43", "ncaron": "\u0148", "ncedil": "\u0146", "ncong": "\u2247", "ncongdot": "\u2A6D\u0338", "ncup": "\u2A42", "ncy": "\u043D", "ndash": "\u2013", "ne": "\u2260", "neArr": "\u21D7", "nearhk": "\u2924", "nearr": "\u2197", "nearrow": "\u2197", "nedot": "\u2250\u0338", "nequiv": "\u2262", "nesear": "\u2928", "nesim": "\u2242\u0338", "nexist": "\u2204", "nexists": "\u2204", "nfr": "\uD835\uDD2B", "ngE": "\u2267\u0338", "nge": "\u2271", "ngeq": "\u2271", "ngeqq": "\u2267\u0338", "ngeqslant": "\u2A7E\u0338", "nges": "\u2A7E\u0338", "ngsim": "\u2275", "ngt": "\u226F", "ngtr": "\u226F", "nhArr": "\u21CE", "nharr": "\u21AE", "nhpar": "\u2AF2", "ni": "\u220B", "nis": "\u22FC", "nisd": "\u22FA", "niv": "\u220B", "njcy": "\u045A", "nlArr": "\u21CD", "nlE": "\u2266\u0338", "nlarr": "\u219A", "nldr": "\u2025", "nle": "\u2270", "nleftarrow": "\u219A", "nleftrightarrow": "\u21AE", "nleq": "\u2270", "nleqq": "\u2266\u0338", "nleqslant": "\u2A7D\u0338", "nles": "\u2A7D\u0338", "nless": "\u226E", "nlsim": "\u2274", "nlt": "\u226E", "nltri": "\u22EA", "nltrie": "\u22EC", "nmid": "\u2224", "nopf": "\uD835\uDD5F", "not": "\u00AC", "notin": "\u2209", "notinE": "\u22F9\u0338", "notindot": "\u22F5\u0338", "notinva": "\u2209", "notinvb": "\u22F7", "notinvc": "\u22F6", "notni": "\u220C", "notniva": "\u220C", "notnivb": "\u22FE", "notnivc": "\u22FD", "npar": "\u2226", "nparallel": "\u2226", "nparsl": "\u2AFD\u20E5", "npart": "\u2202\u0338", "npolint": "\u2A14", "npr": "\u2280", "nprcue": "\u22E0", "npre": "\u2AAF\u0338", "nprec": "\u2280", "npreceq": "\u2AAF\u0338", "nrArr": "\u21CF", "nrarr": "\u219B", "nrarrc": "\u2933\u0338", "nrarrw": "\u219D\u0338", "nrightarrow": "\u219B", "nrtri": "\u22EB", "nrtrie": "\u22ED", "nsc": "\u2281", "nsccue": "\u22E1", "nsce": "\u2AB0\u0338", "nscr": "\uD835\uDCC3", "nshortmid": "\u2224", "nshortparallel": "\u2226", "nsim": "\u2241", "nsime": "\u2244", "nsimeq": "\u2244", "nsmid": "\u2224", "nspar": "\u2226", "nsqsube": "\u22E2", "nsqsupe": "\u22E3", "nsub": "\u2284", "nsubE": "\u2AC5\u0338", "nsube": "\u2288", "nsubset": "\u2282\u20D2", "nsubseteq": "\u2288", "nsubseteqq": "\u2AC5\u0338", "nsucc": "\u2281", "nsucceq": "\u2AB0\u0338", "nsup": "\u2285", "nsupE": "\u2AC6\u0338", "nsupe": "\u2289", "nsupset": "\u2283\u20D2", "nsupseteq": "\u2289", "nsupseteqq": "\u2AC6\u0338", "ntgl": "\u2279", "ntilde": "\u00F1", "ntlg": "\u2278", "ntriangleleft": "\u22EA", "ntrianglelefteq": "\u22EC", "ntriangleright": "\u22EB", "ntrianglerighteq": "\u22ED", "nu": "\u03BD", "num": "\u0023", "numero": "\u2116", "numsp": "\u2007", "nvDash": "\u22AD", "nvHarr": "\u2904", "nvap": "\u224D\u20D2", "nvdash": "\u22AC", "nvge": "\u2265\u20D2", "nvgt": "\u003E\u20D2", "nvinfin": "\u29DE", "nvlArr": "\u2902", "nvle": "\u2264\u20D2", "nvlt": "\u003C\u20D2", "nvltrie": "\u22B4\u20D2", "nvrArr": "\u2903", "nvrtrie": "\u22B5\u20D2", "nvsim": "\u223C\u20D2", "nwArr": "\u21D6", "nwarhk": "\u2923", "nwarr": "\u2196", "nwarrow": "\u2196", "nwnear": "\u2927", "oS": "\u24C8", "oacute": "\u00F3", "oast": "\u229B", "ocir": "\u229A", "ocirc": "\u00F4", "ocy": "\u043E", "odash": "\u229D", "odblac": "\u0151", "odiv": "\u2A38", "odot": "\u2299", "odsold": "\u29BC", "oelig": "\u0153", "ofcir": "\u29BF", "ofr": "\uD835\uDD2C", "ogon": "\u02DB", "ograve": "\u00F2", "ogt": "\u29C1", "ohbar": "\u29B5", "ohm": "\u03A9", "oint": "\u222E", "olarr": "\u21BA", "olcir": "\u29BE", "olcross": "\u29BB", "oline": "\u203E", "olt": "\u29C0", "omacr": "\u014D", "omega": "\u03C9", "omicron": "\u03BF", "omid": "\u29B6", "ominus": "\u2296", "oopf": "\uD835\uDD60", "opar": "\u29B7", "operp": "\u29B9", "oplus": "\u2295", "or": "\u2228", "orarr": "\u21BB", "ord": "\u2A5D", "order": "\u2134", "orderof": "\u2134", "ordf": "\u00AA", "ordm": "\u00BA", "origof": "\u22B6", "oror": "\u2A56", "orslope": "\u2A57", "orv": "\u2A5B", "oscr": "\u2134", "oslash": "\u00F8", "osol": "\u2298", "otilde": "\u00F5", "otimes": "\u2297", "otimesas": "\u2A36", "ouml": "\u00F6", "ovbar": "\u233D", "par": "\u2225", "para": "\u00B6", "parallel": "\u2225", "parsim": "\u2AF3", "parsl": "\u2AFD", "part": "\u2202", "pcy": "\u043F", "percnt": "\u0025", "period": "\u002E", "permil": "\u2030", "perp": "\u22A5", "pertenk": "\u2031", "pfr": "\uD835\uDD2D", "phi": "\u03C6", "phiv": "\u03D5", "phmmat": "\u2133", "phone": "\u260E", "pi": "\u03C0", "pitchfork": "\u22D4", "piv": "\u03D6", "planck": "\u210F", "planckh": "\u210E", "plankv": "\u210F", "plus": "\u002B", "plusacir": "\u2A23", "plusb": "\u229E", "pluscir": "\u2A22", "plusdo": "\u2214", "plusdu": "\u2A25", "pluse": "\u2A72", "plusmn": "\u00B1", "plussim": "\u2A26", "plustwo": "\u2A27", "pm": "\u00B1", "pointint": "\u2A15", "popf": "\uD835\uDD61", "pound": "\u00A3", "pr": "\u227A", "prE": "\u2AB3", "prap": "\u2AB7", "prcue": "\u227C", "pre": "\u2AAF", "prec": "\u227A", "precapprox": "\u2AB7", "preccurlyeq": "\u227C", "preceq": "\u2AAF", "precnapprox": "\u2AB9", "precneqq": "\u2AB5", "precnsim": "\u22E8", "precsim": "\u227E", "prime": "\u2032", "primes": "\u2119", "prnE": "\u2AB5", "prnap": "\u2AB9", "prnsim": "\u22E8", "prod": "\u220F", "profalar": "\u232E", "profline": "\u2312", "profsurf": "\u2313", "prop": "\u221D", "propto": "\u221D", "prsim": "\u227E", "prurel": "\u22B0", "pscr": "\uD835\uDCC5", "psi": "\u03C8", "puncsp": "\u2008", "qfr": "\uD835\uDD2E", "qint": "\u2A0C", "qopf": "\uD835\uDD62", "qprime": "\u2057", "qscr": "\uD835\uDCC6", "quaternions": "\u210D", "quatint": "\u2A16", "quest": "\u003F", "questeq": "\u225F", "quot": "\u0022", "rAarr": "\u21DB", "rArr": "\u21D2", "rAtail": "\u291C", "rBarr": "\u290F", "rHar": "\u2964", "race": "\u223D\u0331", "racute": "\u0155", "radic": "\u221A", "raemptyv": "\u29B3", "rang": "\u27E9", "rangd": "\u2992", "range": "\u29A5", "rangle": "\u27E9", "raquo": "\u00BB", "rarr": "\u2192", "rarrap": "\u2975", "rarrb": "\u21E5", "rarrbfs": "\u2920", "rarrc": "\u2933", "rarrfs": "\u291E", "rarrhk": "\u21AA", "rarrlp": "\u21AC", "rarrpl": "\u2945", "rarrsim": "\u2974", "rarrtl": "\u21A3", "rarrw": "\u219D", "ratail": "\u291A", "ratio": "\u2236", "rationals": "\u211A", "rbarr": "\u290D", "rbbrk": "\u2773", "rbrace": "\u007D", "rbrack": "\u005D", "rbrke": "\u298C", "rbrksld": "\u298E", "rbrkslu": "\u2990", "rcaron": "\u0159", "rcedil": "\u0157", "rceil": "\u2309", "rcub": "\u007D", "rcy": "\u0440", "rdca": "\u2937", "rdldhar": "\u2969", "rdquo": "\u201D", "rdquor": "\u201D", "rdsh": "\u21B3", "real": "\u211C", "realine": "\u211B", "realpart": "\u211C", "reals": "\u211D", "rect": "\u25AD", "reg": "\u00AE", "rfisht": "\u297D", "rfloor": "\u230B", "rfr": "\uD835\uDD2F", "rhard": "\u21C1", "rharu": "\u21C0", "rharul": "\u296C", "rho": "\u03C1", "rhov": "\u03F1", "rightarrow": "\u2192", "rightarrowtail": "\u21A3", "rightharpoondown": "\u21C1", "rightharpoonup": "\u21C0", "rightleftarrows": "\u21C4", "rightleftharpoons": "\u21CC", "rightrightarrows": "\u21C9", "rightsquigarrow": "\u219D", "rightthreetimes": "\u22CC", "ring": "\u02DA", "risingdotseq": "\u2253", "rlarr": "\u21C4", "rlhar": "\u21CC", "rlm": "\u200F", "rmoust": "\u23B1", "rmoustache": "\u23B1", "rnmid": "\u2AEE", "roang": "\u27ED", "roarr": "\u21FE", "robrk": "\u27E7", "ropar": "\u2986", "ropf": "\uD835\uDD63", "roplus": "\u2A2E", "rotimes": "\u2A35", "rpar": "\u0029", "rpargt": "\u2994", "rppolint": "\u2A12", "rrarr": "\u21C9", "rsaquo": "\u203A", "rscr": "\uD835\uDCC7", "rsh": "\u21B1", "rsqb": "\u005D", "rsquo": "\u2019", "rsquor": "\u2019", "rthree": "\u22CC", "rtimes": "\u22CA", "rtri": "\u25B9", "rtrie": "\u22B5", "rtrif": "\u25B8", "rtriltri": "\u29CE", "ruluhar": "\u2968", "rx": "\u211E", "sacute": "\u015B", "sbquo": "\u201A", "sc": "\u227B", "scE": "\u2AB4", "scap": "\u2AB8", "scaron": "\u0161", "sccue": "\u227D", "sce": "\u2AB0", "scedil": "\u015F", "scirc": "\u015D", "scnE": "\u2AB6", "scnap": "\u2ABA", "scnsim": "\u22E9", "scpolint": "\u2A13", "scsim": "\u227F", "scy": "\u0441", "sdot": "\u22C5", "sdotb": "\u22A1", "sdote": "\u2A66", "seArr": "\u21D8", "searhk": "\u2925", "searr": "\u2198", "searrow": "\u2198", "sect": "\u00A7", "semi": "\u003B", "seswar": "\u2929", "setminus": "\u2216", "setmn": "\u2216", "sext": "\u2736", "sfr": "\uD835\uDD30", "sfrown": "\u2322", "sharp": "\u266F", "shchcy": "\u0449", "shcy": "\u0448", "shortmid": "\u2223", "shortparallel": "\u2225", "shy": "\u00AD", "sigma": "\u03C3", "sigmaf": "\u03C2", "sigmav": "\u03C2", "sim": "\u223C", "simdot": "\u2A6A", "sime": "\u2243", "simeq": "\u2243", "simg": "\u2A9E", "simgE": "\u2AA0", "siml": "\u2A9D", "simlE": "\u2A9F", "simne": "\u2246", "simplus": "\u2A24", "simrarr": "\u2972", "slarr": "\u2190", "smallsetminus": "\u2216", "smashp": "\u2A33", "smeparsl": "\u29E4", "smid": "\u2223", "smile": "\u2323", "smt": "\u2AAA", "smte": "\u2AAC", "smtes": "\u2AAC\uFE00", "softcy": "\u044C", "sol": "\u002F", "solb": "\u29C4", "solbar": "\u233F", "sopf": "\uD835\uDD64", "spades": "\u2660", "spadesuit": "\u2660", "spar": "\u2225", "sqcap": "\u2293", "sqcaps": "\u2293\uFE00", "sqcup": "\u2294", "sqcups": "\u2294\uFE00", "sqsub": "\u228F", "sqsube": "\u2291", "sqsubset": "\u228F", "sqsubseteq": "\u2291", "sqsup": "\u2290", "sqsupe": "\u2292", "sqsupset": "\u2290", "sqsupseteq": "\u2292", "squ": "\u25A1", "square": "\u25A1", "squarf": "\u25AA", "squf": "\u25AA", "srarr": "\u2192", "sscr": "\uD835\uDCC8", "ssetmn": "\u2216", "ssmile": "\u2323", "sstarf": "\u22C6", "star": "\u2606", "starf": "\u2605", "straightepsilon": "\u03F5", "straightphi": "\u03D5", "strns": "\u00AF", "sub": "\u2282", "subE": "\u2AC5", "subdot": "\u2ABD", "sube": "\u2286", "subedot": "\u2AC3", "submult": "\u2AC1", "subnE": "\u2ACB", "subne": "\u228A", "subplus": "\u2ABF", "subrarr": "\u2979", "subset": "\u2282", "subseteq": "\u2286", "subseteqq": "\u2AC5", "subsetneq": "\u228A", "subsetneqq": "\u2ACB", "subsim": "\u2AC7", "subsub": "\u2AD5", "subsup": "\u2AD3", "succ": "\u227B", "succapprox": "\u2AB8", "succcurlyeq": "\u227D", "succeq": "\u2AB0", "succnapprox": "\u2ABA", "succneqq": "\u2AB6", "succnsim": "\u22E9", "succsim": "\u227F", "sum": "\u2211", "sung": "\u266A", "sup": "\u2283", "sup1": "\u00B9", "sup2": "\u00B2", "sup3": "\u00B3", "supE": "\u2AC6", "supdot": "\u2ABE", "supdsub": "\u2AD8", "supe": "\u2287", "supedot": "\u2AC4", "suphsol": "\u27C9", "suphsub": "\u2AD7", "suplarr": "\u297B", "supmult": "\u2AC2", "supnE": "\u2ACC", "supne": "\u228B", "supplus": "\u2AC0", "supset": "\u2283", "supseteq": "\u2287", "supseteqq": "\u2AC6", "supsetneq": "\u228B", "supsetneqq": "\u2ACC", "supsim": "\u2AC8", "supsub": "\u2AD4", "supsup": "\u2AD6", "swArr": "\u21D9", "swarhk": "\u2926", "swarr": "\u2199", "swarrow": "\u2199", "swnwar": "\u292A", "szlig": "\u00DF", "target": "\u2316", "tau": "\u03C4", "tbrk": "\u23B4", "tcaron": "\u0165", "tcedil": "\u0163", "tcy": "\u0442", "tdot": " \u20DB", "telrec": "\u2315", "tfr": "\uD835\uDD31", "there4": "\u2234", "therefore": "\u2234", "theta": "\u03B8", "thetasym": "\u03D1", "thetav": "\u03D1", "thickapprox": "\u2248", "thicksim": "\u223C", "thinsp": "\u2009", "thkap": "\u2248", "thksim": "\u223C", "thorn": "\u00FE", "tilde": "\u02DC", "times": "\u00D7", "timesb": "\u22A0", "timesbar": "\u2A31", "timesd": "\u2A30", "tint": "\u222D", "toea": "\u2928", "top": "\u22A4", "topbot": "\u2336", "topcir": "\u2AF1", "topf": "\uD835\uDD65", "topfork": "\u2ADA", "tosa": "\u2929", "tprime": "\u2034", "trade": "\u2122", "triangle": "\u25B5", "triangledown": "\u25BF", "triangleleft": "\u25C3", "trianglelefteq": "\u22B4", "triangleq": "\u225C", "triangleright": "\u25B9", "trianglerighteq": "\u22B5", "tridot": "\u25EC", "trie": "\u225C", "triminus": "\u2A3A", "triplus": "\u2A39", "trisb": "\u29CD", "tritime": "\u2A3B", "trpezium": "\u23E2", "tscr": "\uD835\uDCC9", "tscy": "\u0446", "tshcy": "\u045B", "tstrok": "\u0167", "twixt": "\u226C", "twoheadleftarrow": "\u219E", "twoheadrightarrow": "\u21A0", "uArr": "\u21D1", "uHar": "\u2963", "uacute": "\u00FA", "uarr": "\u2191", "ubrcy": "\u045E", "ubreve": "\u016D", "ucirc": "\u00FB", "ucy": "\u0443", "udarr": "\u21C5", "udblac": "\u0171", "udhar": "\u296E", "ufisht": "\u297E", "ufr": "\uD835\uDD32", "ugrave": "\u00F9", "uharl": "\u21BF", "uharr": "\u21BE", "uhblk": "\u2580", "ulcorn": "\u231C", "ulcorner": "\u231C", "ulcrop": "\u230F", "ultri": "\u25F8", "umacr": "\u016B", "uml": "\u00A8", "uogon": "\u0173", "uopf": "\uD835\uDD66", "uparrow": "\u2191", "updownarrow": "\u2195", "upharpoonleft": "\u21BF", "upharpoonright": "\u21BE", "uplus": "\u228E", "upsi": "\u03C5", "upsih": "\u03D2", "upsilon": "\u03C5", "upuparrows": "\u21C8", "urcorn": "\u231D", "urcorner": "\u231D", "urcrop": "\u230E", "uring": "\u016F", "urtri": "\u25F9", "uscr": "\uD835\uDCCA", "utdot": "\u22F0", "utilde": "\u0169", "utri": "\u25B5", "utrif": "\u25B4", "uuarr": "\u21C8", "uuml": "\u00FC", "uwangle": "\u29A7", "vArr": "\u21D5", "vBar": "\u2AE8", "vBarv": "\u2AE9", "vDash": "\u22A8", "vangrt": "\u299C", "varepsilon": "\u03F5", "varkappa": "\u03F0", "varnothing": "\u2205", "varphi": "\u03D5", "varpi": "\u03D6", "varpropto": "\u221D", "varr": "\u2195", "varrho": "\u03F1", "varsigma": "\u03C2", "varsubsetneq": "\u228A\uFE00", "varsubsetneqq": "\u2ACB\uFE00", "varsupsetneq": "\u228B\uFE00", "varsupsetneqq": "\u2ACC\uFE00", "vartheta": "\u03D1", "vartriangleleft": "\u22B2", "vartriangleright": "\u22B3", "vcy": "\u0432", "vdash": "\u22A2", "vee": "\u2228", "veebar": "\u22BB", "veeeq": "\u225A", "vellip": "\u22EE", "verbar": "\u007C", "vert": "\u007C", "vfr": "\uD835\uDD33", "vltri": "\u22B2", "vnsub": "\u2282\u20D2", "vnsup": "\u2283\u20D2", "vopf": "\uD835\uDD67", "vprop": "\u221D", "vrtri": "\u22B3", "vscr": "\uD835\uDCCB", "vsubnE": "\u2ACB\uFE00", "vsubne": "\u228A\uFE00", "vsupnE": "\u2ACC\uFE00", "vsupne": "\u228B\uFE00", "vzigzag": "\u299A", "wcirc": "\u0175", "wedbar": "\u2A5F", "wedge": "\u2227", "wedgeq": "\u2259", "weierp": "\u2118", "wfr": "\uD835\uDD34", "wopf": "\uD835\uDD68", "wp": "\u2118", "wr": "\u2240", "wreath": "\u2240", "wscr": "\uD835\uDCCC", "xcap": "\u22C2", "xcirc": "\u25EF", "xcup": "\u22C3", "xdtri": "\u25BD", "xfr": "\uD835\uDD35", "xhArr": "\u27FA", "xharr": "\u27F7", "xi": "\u03BE", "xlArr": "\u27F8", "xlarr": "\u27F5", "xmap": "\u27FC", "xnis": "\u22FB", "xodot": "\u2A00", "xopf": "\uD835\uDD69", "xoplus": "\u2A01", "xotime": "\u2A02", "xrArr": "\u27F9", "xrarr": "\u27F6", "xscr": "\uD835\uDCCD", "xsqcup": "\u2A06", "xuplus": "\u2A04", "xutri": "\u25B3", "xvee": "\u22C1", "xwedge": "\u22C0", "yacute": "\u00FD", "yacy": "\u044F", "ycirc": "\u0177", "ycy": "\u044B", "yen": "\u00A5", "yfr": "\uD835\uDD36", "yicy": "\u0457", "yopf": "\uD835\uDD6A", "yscr": "\uD835\uDCCE", "yucy": "\u044E", "yuml": "\u00FF", "zacute": "\u017A", "zcaron": "\u017E", "zcy": "\u0437", "zdot": "\u017C", "zeetrf": "\u2128", "zeta": "\u03B6", "zfr": "\uD835\uDD37", "zhcy": "\u0436", "zigrarr": "\u21DD", "zopf": "\uD835\uDD6B", "zscr": "\uD835\uDCCF", "zwj": "\u200D", "zwnj": "\u200C" }, "optional-;": ["AElig", "AMP", "Aacute", "Acirc", "Agrave", "Aring", "Atilde", "Auml", "COPY", "Ccedil", "ETH", "Eacute", "Ecirc", "Egrave", "Euml", "GT", "Iacute", "Icirc", "Igrave", "Iuml", "LT", "Ntilde", "Oacute", "Ocirc", "Ograve", "Oslash", "Otilde", "Ouml", "QUOT", "REG", "THORN", "Uacute", "Ucirc", "Ugrave", "Uuml", "Yacute", "aacute", "acirc", "acute", "aelig", "agrave", "amp", "aring", "atilde", "auml", "ccedil", "cedil", "copy", "curren", "deg", "divide", "eacute", "ecirc", "egrave", "eth", "euml", "frac12", "frac14", "frac34", "gt", "iacute", "icirc", "iexcl", "igrave", "iquest", "iuml", "laquo", "lt", "macr", "micro", "middot", "nbsp", "not", "ntilde", "oacute", "ocirc", "ograve", "ordf", "ordm", "oslash", "otilde", "ouml", "para", "plusmn", "pound", "quot", "raquo", "reg", "sect", "shy", "sup1", "sup2", "sup3", "szlig", "thorn", "times", "uacute", "ucirc", "ugrave", "uml", "uuml", "yacute", "yen", "yuml"] } tdom-0.9.5-src/tests/data/dtd-6.1.dtd0000644000175000017500000000005214703531020015560 0ustar rolfrolf ]]> tdom-0.9.5-src/tests/data/dtd-6.6.dtd0000644000175000017500000000014414703531020015567 0ustar rolfrolf ]]> tdom-0.9.5-src/tests/data/domCmd1.dtd0000644000175000017500000000005414703531020015771 0ustar rolfrolf tdom-0.9.5-src/tests/domDoc.test0000644000175000017500000016677714703531020015236 0ustar rolfrolf# Features covered: domDoc and docObj command # # This file contains a collection of tests for the two interfaces to # DOM docs, the token interface (the domDoc command) and the tcl # command interface ([$docObj method ...]). # # domDoc-1.*: asXML, asHTML # domDoc-2.*: publicId, systemId # domDoc-3.*: toXSLTcmd # domDoc-4.*: asText # domDoc-5.*: normalize # domDoc-6.*: nodetype # domDoc-7.*: insertBefore # domDoc-8.*: insertBeforeFromScript # domDoc-9.*: replaceChild # domDoc-10.*: getElementById # domDoc-11.*: firstChild # domDoc-12.*: lastChild # domDoc-13.*: appendChild # domDoc-14.*: removeChild # domDoc-15.*: hasChildNodes # domDoc-16.*: childNodes # domDoc-17.*: ownerDocument # domDoc-18.*: appendFromList # domDoc-19.*: appendXML # domDoc-20.*: selectNodes # domDoc-21.*: baseURI # domDoc-22.*: appendFromScript # domDoc-23.*: getElementsByTagNameNS # domDoc-24.*: cdataSectionElements # domDoc-25.*: selectNodesNamespaces # domDoc-26.*: fragments list # domDoc-27.*: deleteXPathCache # domDoc-28.*: createElementNS # domDoc-29.*: asCanonicalXML # domDoc-30.*: command argument parsing # # Copyright (c) 2004 - 2007 Rolf Ade. source [file join [file dir [info script]] loadtdom.tcl] test domDoc-1.1 {asXML -escapeNonASCII} { set doc [dom parse [tdom::xmlReadFile \ [file join [file dir [info script]] data/i18n_1.xml]]] set result [$doc asXML -escapeNonASCII] $doc delete set result } {абвгдежзий } test domDoc-1.2 {asXML -escapeNonASCII; comments and PI's are not altered} { set doc [dom parse [tdom::xmlReadFile \ [file join [file dir [info script]] data/i18n_2.xml]]] set result [$doc asXML -indent none -escapeNonASCII] $doc delete set result } " german umlauts: äöüß " test domDoc-1.3 {asHTML -escapeNonASCII -htmlEntities} { set doc [dom parse {äü„‟†}] set result [$doc asHTML -escapeNonASCII -htmlEntities] $doc delete set result } {äü„‟†} test domDoc-1.3.1 {asHTML -htmlEntities} { set doc [dom parse -html {&}] set result [$doc asHTML -htmlEntities] $doc delete set result } {&} test domDoc-1.3.2 {asHTML -htmlEntities} { set doc [dom parse -html "\u205F\u200A"] set result [$doc asHTML -htmlEntities] $doc delete set doc [dom parse -html "\u205F"] append result [$doc asHTML -htmlEntities] $doc delete set doc [dom parse -html "\u200A"] append result [$doc asHTML -htmlEntities] $doc delete set result } {    } test domDoc-1.3.3 {asHTML -htmlEntities} { set doc [dom parse -html "fj"] set result [$doc asHTML -htmlEntities] $doc delete set result } {fj} test domDoc-1.3.4 {asHTML -htmlEntities} { set doc [dom parse -html "≪̸≪≪⃒\u226A\u20D2"] set result [$doc asHTML -htmlEntities] $doc delete set result } {≪̸≪≪⃒≪⃒} test domDoc-1.3.3 {asHTML -htmlEntities} { set doc [dom parse -html "𝕫"] set result [$doc asHTML -htmlEntities] $doc delete set result } {𝕫} set doc [dom parse ] test domDoc-1.4 {asXML -doctypeDeclaration} { $doc asXML -doctypeDeclaration 1 } { } test domDoc-1.5 {asXML -doctypeDeclaration without boolean value (error)} { set errMsg "" catch {$doc asXML -doctypeDeclaration} errMsg set errMsg } {-doctypeDeclaration must have a boolean value as argument} test domDoc-1.6 {asXML -doctypeDeclaration 0} { $doc asXML -doctypeDeclaration 0 } { } $doc delete test domDoc-1.7 {asXML -doctypeDeclaration} { set doc [dom parse {}] set result [$doc asXML -doctypeDeclaration 1] $doc delete set result } { } test domDoc-1.8 {asXML -doctypeDeclaration} { set doc [dom parse {}] set result [$doc asXML -doctypeDeclaration 1] $doc delete set result } { } test domDoc-1.9 {asXML -doctypeDeclaration} { set doc [dom parse {}] set result [$doc asXML -doctypeDeclaration true] $doc delete set result } { } test domDoc-1.10 {asXML - unknown option} { set doc [dom parse {}] set errMsg "" catch {$doc asXML -fooOption 1} errMsg $doc delete set errMsg } {bad option "-fooOption": must be -indent, -channel, -escapeNonASCII, -doctypeDeclaration, -xmlDeclaration, -encString, -escapeAllQuot, -indentAttrs, -nogtescape, -noEmptyElementTag, -escapeCR, or -escapeTab} test domDoc-1.11 {asXML - non boolean value to -doctypeDeclaration} { set doc [dom parse {}] set errMsg "" catch {$doc asXML -doctypeDeclaration foo} errMsg $doc delete set errMsg } {expected boolean value but got "foo"} test domDoc-1.12 {asXML - shortened option} { set doc [dom parse {}] set result [$doc asXML -doctype 1] $doc delete set result } { } test domDoc-1.13 {asHTML -doctypeDeclaration} { set doc [dom createDocument HTML] set result [$doc asHTML -doctypeDeclaration 1] $doc delete set result } { } test domDoc-1.14 {asHTML -doctypeDeclaration} { set doc [dom parse {

    boo

    }] set result [$doc asHTML -doctypeDeclaration 1] $doc delete set result } {

    boo

    } test domDoc-1.15 {asXML - processing-instruction without pi value} { set doc [dom parse {}] set result [$doc asXML -indent none] $doc delete set result } {} test domDoc-1.16 {asXML - processing-instruction without pi value} { set doc [dom parse {}] set result [$doc asXML -indent none] $doc delete set result } {} test domDoc-1.17 {asHTML - content of script/style tags} { set doc [dom parse { }] set result [$doc asHTML] $doc delete set result } { } test domDoc-1.18 {asXML -escapeAllQuot} { set doc [dom parse {This is "strange"}] set result [$doc asXML -escapeAllQuot] $doc delete set result } {This is "strange" } test domDoc-1.19 {asXML -escapeAllQuot} { set doc [dom parse {This is "strange"}] set result [$doc asXML] $doc delete set result } {This is "strange" } test domDoc-1.20 {asXML - indentation of comments} { set doc [dom parse { }] set result [$doc asXML -indent 4] $doc delete set result } { } test domDoc-1.21 {asXML -indentAttrs} { set doc [dom parse {}] set result [$doc asXML -indentAttrs 4] $doc delete set result } { } test domDoc-1.22 {asXML} { set doc [dom createDocument doc] set result [$doc asXML] $doc delete set result } { } test domDoc-1.23 {asXML -xmlDeclaration} { set doc [dom createDocument doc] set result [$doc asXML -xmlDeclaration 1] $doc delete set result } { } test domDoc-1.23 {asXML -xmlDeclaration} { set doc [dom createDocument doc] set result [$doc asXML -xmlDeclaration 1] $doc delete set result } { } test domDoc-1.24 {asXML just -encString without -xmlDeclaration} { set doc [dom createDocument doc] set result [$doc asXML -encString foo] $doc delete set result } { } test domDoc-1.25 {asXML -xmlDeclaration -encString} { set doc [dom createDocument doc] set result [$doc asXML -xmlDeclaration 1 -encString foo] $doc delete set result } { } test domDoc-1.26 {asXML -xmlDeclaration, encoding set by encoding method} { set doc [dom createDocument doc] $doc encoding "foo" set result [$doc asXML -xmlDeclaration 1] $doc delete set result } { } test domDoc-1.27 {asXML -xmlDeclaration -encString} { set doc [dom createDocument doc] set result [catch { [$doc asXML -xmlDeclaration 1 -encString foo \ -encString bar -wrongOption] }] $doc delete set result } 1 test domDoc-1.28 {asXML -xmlDeclaration not xml compliant -encString} { set doc [dom createDocument doc] set result [$doc asXML -xmlDeclaration 1 -encString 1\u2345] $doc delete set result } [subst -nocommands -novariables { }] test domDoc-1.29 {asXML -nogtescape} { set doc [dom parse {>}] set result [$doc asXML -nogtescape -indent none] $doc delete set result } {>} test domDoc-1.30 {asXML -noEmptyElementTag} { set doc [dom parse {}] set result [$doc asXML -noEmptyElementTag -indent none] $doc delete set result } {} test domDoc-1.31 {asXML '"' in attribute value} { # emacs: " set doc [dom createDocument doc] set root [$doc documentElement] $root setAttribute attr "foo\"bar" set result [$doc asXML -indent none] $doc delete set result } {} test domDoc-1.32 {asXML -indent tabs} { set doc [dom parse {}] set result [$doc asXML -indent tabs] $doc delete set result } "\n\t\n\t\t\n\t\n\n" test domDoc-1.33 {asXML -indent tabs} { set doc [dom parse {}] set result [$doc asXML -indent tabs] $doc delete set result } "\n\t\n\t\t\n\t\n\t\n\t\t\n\t\t\t\n\t\t\n\t\n\t\n\n" test domDoc-1.34 {asXML -indent tabs -noEmptyElementTag} { set doc [dom parse {}] set result [$doc asXML -indent tabs -noEmptyElementTag] $doc delete set result } "\n\t\n\t\t\n\t\n\t\n\t\t\n\t\t\t\n\t\t\n\t\n\t\n\n" test domDoc-1.35 {asXML -indent tabs -indentAttrs tabs} { set doc [dom parse {}] set result [$doc asXML -indent tabs -indentAttrs tabs] $doc delete set result } "\n\t\n\t\t\n\t\n\t\n\t\t\n\t\t\t\n\t\t\n\t\n\t\n\n" test domDoc-1.36 {asXML -indent tabs -indentAttrs } { set doc [dom parse {}] set result [$doc asXML -indent tabs -indentAttrs 2] $doc delete set result } "\n\t\n\t\t\n\t\n\t\n\t\t\n\t\t\t\n\t\t\n\t\n\t\n\n" test domDoc-1.37 {asHTML -onlyContents} { set doc [dom parse {

    boo

    }] set result [[$doc documentElement] asHTML -onlyContents] $doc delete set result } {

    boo

    } test domDoc-1.38 {asHTML -breakLines} { set doc [dom parse {

    boo

    }] set result [$doc asHTML -breakLines] $doc delete set result } {

    boo

    } set doc [dom parse ] test domDoc-2.1 {publicId - no publicId there} { $doc publicId } {} test domDoc-2.2 {systemId - no systemId there} { $doc systemId } {} $doc delete set doc [dom parse {}] test domDoc-2.3 {publicId from parsed document} { $doc publicId } {-//foo//DTD bar x.y//EN} test domDoc-2.4 {systemId from parsed document} { $doc systemId } {file:///boo.baz} $doc delete set doc [dom parse {}] test domDoc-2.5 {publicId but document has only SYSTEM} { $doc publicId } {} test domDoc-2.6 {systemId, document has only SYSTEM} { $doc systemId } {file:///boo.baz} test domDoc-2.7 {publicId - set public identifier} { set result [$doc publicId "file:///woo.hoo"] append result " [$doc publicId]" } { file:///woo.hoo} test domDoc-2.8 {publicId - set public identifier} { $doc publicId "http://www.tdom.org" $doc asXML -indent no -doctypeDeclaration 1 } { } test domDoc-2.9 {systemId - set system identifier} { set result [$doc systemId "file:///woo.hoo"] append result " [$doc systemId]" } {file:///boo.baz file:///woo.hoo} test domDoc-2.10 {systemId - set system identifier} { $doc systemId "file:///whooze.moo" $doc asXML -indent no -doctypeDeclaration 1 } { } test domDoc-2.11 {publicId - set to empty string} { $doc publicId "" $doc asXML -indent no -doctypeDeclaration 1 } { } test domDoc-2.12 {systemId - set to empty string} { $doc systemId "" $doc asXML -indent no -doctypeDeclaration 1 } { } $doc delete set doc [dom parse ] set xslt1 { } test domDoc-3.1 {toXSLTcmd} { set xslt [dom parse -keepEmpties $xslt1] set xsltCmd [$xslt toXSLTcmd] $xsltCmd -parameters {param2 newValue param3 "this Value"} $doc resultDoc set result [$resultDoc asXML -indent none] $resultDoc delete $xsltCmd -parameters {param1 "that Value"} $doc resultDoc append result [$resultDoc asXML -indent none] $resultDoc delete $xsltCmd -parameters {param3 "another" param1 "and this"} $doc resultDoc append result [$resultDoc asXML -indent none] $resultDoc delete rename $xsltCmd {} set result } {param1Default newValue this Value that Value param2Default param3Default and this param2Default another } set xslt2 { dummy result This is from xsl:message } proc msgCmd1 {msg terminate} { global result append result "msgCmd1: $msg " } proc msgCmd2 {msg terminate} { global result append result "msgCmd2: $msg" } test domDoc-3.2 {toXSLTcmd} { set xslt [dom parse -keepEmpties $xslt2] set xsltCmd [$xslt toXSLTcmd] set result "" $xsltCmd -xsltmessagecmd msgCmd1 $doc resultDoc $resultDoc delete $xsltCmd -xsltmessagecmd msgCmd2 $doc resultDoc $resultDoc delete rename $xsltCmd {} set result } {msgCmd1: This is from xsl:message msgCmd2: This is from xsl:message} test domDoc-3.3 {toXSLTcmd} { set xslt [dom parse -keepEmpties $xslt1] set xsltCmd [$xslt toXSLTcmd] set result [catch {$xsltCmd -bogusOption foo $doc resultDoc} errMsg] lappend result $errMsg lappend result [catch {$xsltCmd $doc resultDoc}] lappend result [$resultDoc asXML -indent none] $resultDoc delete rename $xsltCmd {} set result } {1 {bad option "-bogusOption": must be -parameters, -ignoreUndeclaredParameters, -maxApplyDepth, or -xsltmessagecmd} 0 {param1Default param2Default param3Default }} test domDoc-3.4 {toXSLTcmd} { set xslt [dom parse -keepEmpties $xslt1] set xsltCmd [$xslt toXSLTcmd] set result [catch {$xsltCmd -xsltmessagecmd msgCmd1} errMsg] rename $xsltCmd {} lappend result $errMsg } {1 {wrong # args: should be "?-parameters parameterList? ?-ignoreUndeclaredParameters? ?-maxApplyDepth int? ?-xsltmessagecmd cmd? ?objVar?"}} test domDoc-3.5 {toXSLTcmd} { set xslt [dom parse -keepEmpties $xslt1] set xsltCmd [$xslt toXSLTcmd] set result [catch {$xsltCmd $doc resultDoc bogus} errMsg] rename $xsltCmd {} lappend result $errMsg } {1 {wrong # args: should be "?-parameters parameterList? ?-ignoreUndeclaredParameters? ?-maxApplyDepth int? ?-xsltmessagecmd cmd? ?objVar?"}} test domDoc-3.6 {toXSLTcmd} { set xslt [dom parse -keepEmpties $xslt1] set xsltCmd [$xslt toXSLTcmd] set result [catch {$xsltCmd -parameters {param1 foo} -parameters {param2 foo} $doc resultDoc} errMsg] rename $xsltCmd {} lappend result $errMsg } {1 {only one -parameters option allowed}} test domDoc-3.7 {toXSLTcmd} { set xslt [dom parse -keepEmpties $xslt1] set xsltCmd [$xslt toXSLTcmd] set result [catch {$xsltCmd}] $xsltCmd delete set result } {1} test domDoc-3.8 {toXSLTcmd} { set xslt [dom parse -keepEmpties $xslt1] set xsltCmd [$xslt toXSLTcmd] set result [catch {$xsltCmd delete bogus}] $xsltCmd delete set result } {1} test domDoc-3.9 {toXSLTcmd} { set xslt [dom parse -keepEmpties $xslt1] set xsltCmd [$xslt toXSLTcmd] set result [catch {$xsltCmd transform} errMsg] $xsltCmd delete set result } {1} test domDoc-3.10 {toXSLTcmd} { set xslt [dom parse -keepEmpties $xslt1] set xsltCmd [$xslt toXSLTcmd] $xsltCmd transform $doc resultDoc set result [$resultDoc asXML -indent none] $resultDoc delete $xsltCmd delete set result } {param1Default param2Default param3Default } set xslt3 { mixed element this is more text } test domDoc-3.11 {toXSLTcmd} { set xslt [dom parse -keepEmpties $xslt3] set xsltCmd [$xslt toXSLTcmd] set result [list] for {set x 0} {$x < 2} {incr x} { $xsltCmd $doc resultDoc lappend result [lsort [$resultDoc cdataSectionElements *]] lappend result [$resultDoc asXML -indent none] $resultDoc delete } $xsltCmd delete set result } {{b bar doc foo} {} {b bar doc foo} {}} $doc delete test domDoc-4.1 {asText - syntax check} { dom parse doc set result [catch {$doc asText foo}] $doc delete set result } {1} test domDoc-4.2 {asText} { dom parse {pcdata foo bar grill} doc set result [$doc asText] $doc delete set result } {pcdata foo bar grill} test domDoc-4.3 {asText} { dom parse {pcdata Hello, world!]]> more pcdata} doc set result [$doc asText] $doc delete set result } {pcdata Hello, world! more pcdata} test domDoc-4.4 {asText} { dom parse {pcdata} doc $doc documentElement root set newCDATAnode \ [$doc createCDATASection "Hello, world!"] $root appendChild $newCDATAnode set result [$doc asText] $doc delete set result } {pcdata} test domDoc-4.5 {asText} { dom parse {encoded chars: > < & " '} doc set result [$doc asText] $doc delete set result } {encoded chars: > < & " '} # emacs: " test domDoc-5.1 {normalize} { set doc [dom parse text] $doc documentElement root set cdataNode [$doc createCDATASection "cdata section text"] set child [$root firstChild] $child appendChild $cdataNode $doc normalize set result [llength [$child childNodes]] lappend result [[$child firstChild] data] $doc delete set result } {2 text} test domDoc-5.2 {normalize} { set doc [dom parse text] $doc documentElement root set cdataNode [$doc createCDATASection "cdata section text"] set child [$root firstChild] $child appendChild $cdataNode $doc normalize -forXPath set result [llength [$child childNodes]] lappend result [[$child firstChild] data] $doc delete set result } {1 {textcdata section text}} test domDoc-5.3 {normalize} { set doc [dom parse ] $doc documentElement root set cdataNode [$doc createCDATASection "cdata section text"] set textNode [$doc createTextNode text] set child [$root firstChild] $child appendChild $cdataNode $child appendChild $textNode set result [llength [$child childNodes]] $doc normalize -forXPath lappend result [llength [$child childNodes]] lappend result [[$child firstChild] data] $doc delete set result } {2 1 {cdata section texttext}} test domDoc-5.4 {normalize} { set doc [dom parse ] $doc documentElement root set cdataNode [$doc createCDATASection "cdata section text"] set child [$root firstChild] $child appendChild $cdataNode $doc normalize set result [$cdataNode nodeType] $doc normalize -forXPath lappend result [$cdataNode nodeType] $doc delete set result } {CDATA_SECTION_NODE TEXT_NODE} test domDoc-5.5 {normalize} { set doc [dom parse ] $doc documentElement root set textNode [$doc createTextNode ""] set child [$root firstChild] $child appendChild $textNode set result [llength [$child childNodes]] $doc normalize lappend result [llength [$child childNodes]] $doc delete set result } {1 0} test domDoc-5.6 {normalize} { set doc [dom parse ] $doc documentElement root set cdataNode [$doc createCDATASection ""] set child [$root firstChild] $child appendChild $cdataNode $doc normalize set result [llength [$child childNodes]] $doc normalize -forXPath lappend result [llength [$child childNodes]] $doc delete set result } {1 0} test domDoc-6.1 {nodeType} { set doc [dom parse ] set result [$doc nodeType] $doc delete set result } {DOCUMENT_NODE} test domDoc-6.2 {nodeType} { set doc [dom parse ] set result [catch {$doc nodeType foo}] $doc delete set result } {1} test domDoc-7.1 {insertBefore} { set doc [dom parse {}] set root [$doc documentElement] set newPI [$doc createProcessingInstruction myPI pivalue] $doc insertBefore $newPI $root set result [$doc asXML -indent none] $doc delete set result } {} test domDoc-7.2 {insertBefore} { set doc [dom parse {}] set newPI [$doc createProcessingInstruction myPI pivalue] $doc insertBefore $newPI "" set result [$doc asXML -indent none] $doc delete set result } {} test domDoc-7.3 {insertBefore} { set doc [dom parse {}] set newPI [$doc createProcessingInstruction myPI pivalue] set root [$doc documentElement] set child [$root firstChild] set result [catch {$doc insertBefore $newPI $child} errMsg] lappend result $errMsg $doc delete set result } {1 NOT_FOUND_ERR} namespace eval nodeCmds { dom createNodeCmd elementNode e1 dom createNodeCmd elementNode e2 dom createNodeCmd commentNode c dom createNodeCmd textNode t dom createNodeCmd cdataNode cdata dom createNodeCmd piNode pi dom createNodeCmd parserNode parser } test domDoc-8.1 {insertBeforeFromScript} { set doc [dom parse {}] $doc documentElement root $doc insertBeforeFromScript { nodeCmds::e1 } $root set result [$doc asXML -indent none] $doc delete set result } {} test domDoc-8.2 {insertBeforeFromScript} { set doc [dom parse {}] $doc insertBeforeFromScript { nodeCmds::e1 } "" set result [$doc asXML -indent none] $doc delete set result } {} test domDoc-8.3 {insertBeforeFromScript} { set doc [dom parse {}] $doc documentElement root set result [catch {$root insertBeforeFromScript { nodeCmds::e1 nodeCmds::e1 { # This is intentionally wrong set foo 1 + 1 } } $root}] lappend result [$doc asXML -indent none] $doc delete set result } {1 } test domDoc-9.1 {replaceChild} { set doc [dom parse {}] set root [$doc documentElement] set newNode [$doc createElement newNode] $doc replaceChild $newNode $root set result [$doc asXML -indent none] lappend result [[$doc documentElement] nodeName] $doc delete set result } { newNode} set getElementByIdSetup { set doc [dom parse { ]> }] } test domDoc-10.1 {getElementById} -setup $getElementByIdSetup -body { set result [[$doc getElementById "4a"] @name] lappend result [$doc getElementById "dontexists"] } -cleanup { $doc delete } -result {that {}} test domDoc-10.2 {getElementById - only IDs at parsing time will be found} \ -setup $getElementByIdSetup -body { set root [$doc documentElement] set elemNode [$root selectNodes {elem[3]}] if {[$elemNode hasAttribute id]} { error "error in the test code" } $elemNode setAttribute id "new" $doc getElementById "new" } -cleanup { $doc delete } -result {} test domDoc-10.3 {getElementById} -setup $getElementByIdSetup -body { set root [$doc documentElement] set elemNode [$root selectNodes {elem[2]}] if {![$elemNode hasAttribute id]} { error "error in the test code" } $elemNode setAttribute id "new" [$doc getElementById "new"] getAttribute name } -cleanup { $doc delete } -result that test domDoc-10.4 {getElementById} -setup $getElementByIdSetup -body { set root [$doc documentElement] set elemNode [$root selectNodes {elem[2]}] if {![$elemNode hasAttribute id]} { error "error in the test code" } $root removeChild $elemNode [$doc getElementById "4a"] getAttribute name } -cleanup { $doc delete } -result that test domDoc-10.5 {getElementById} -setup $getElementByIdSetup -body { set root [$doc documentElement] set elemNode [$root selectNodes {elem[2]}] if {![$elemNode hasAttribute id]} { error "error in the test code" } $elemNode removeAttribute id $doc getElementById "4a" } -cleanup { $doc delete } -result {} test domDoc-11.1 {firstChild} { set doc [dom createDocumentNode] set result [$doc firstChild] $doc delete set result } {} test domDoc-11.2 {firstChild} { set doc [dom parse ] set result [[$doc firstChild] nodeName] $doc delete set result } {root} test domDoc-11.3 {firstChild} { set doc [dom parse {}] set result [[$doc firstChild] nodeName] $doc delete set result } {beforeRoot} test domDoc-11.4 {firstChild} { set doc [dom parse {}] set node [$doc firstChild] set newNode [$doc createElement newNode] $doc insertBefore $newNode $node set result [[$doc firstChild] nodeName] $doc delete set result } {newNode} test domDoc-11.5 {Delete top level node} { set doc [dom parse {}] [$doc firstChild] delete set result [$doc asXML -indent none] $doc delete set result } {} test domDoc-11.6 {Delete top level node} { set doc [dom parse {}] [$doc documentElement] delete set result [$doc asXML -indent none] $doc delete set result } {} test domDoc-12.1 {lastChild} { set doc [dom createDocumentNode] set result [$doc lastChild] $doc delete set result } {} test domDoc-12.2 {lastChild} { set doc [dom parse ] set result [[$doc lastChild] nodeName] $doc delete set result } {root} test domDoc-12.3 {lastChild} { set doc [dom parse {}] set result [[$doc lastChild] nodeName] $doc delete set result } {afterRoot} test domDoc-12.4 {lastChild} { set doc [dom parse {}] set newNode [$doc createElement newNode] $doc appendChild $newNode set result [[$doc lastChild] nodeName] lappend result [[$doc lastChild] parentNode] $doc delete set result } {newNode {}} test domDoc-13.1 {appendChild} { set doc [dom parse {}] set newNode [$doc createElement newNode] $doc appendChild $newNode set newNode [$doc createComment "a comment"] $doc appendChild $newNode set newNode [$doc createProcessingInstruction this that] $doc appendChild $newNode set newNode [$doc createTextNode "text"] $doc appendChild $newNode set result [$doc asXML -indent none] $doc delete set result } {text} test domDoc-13.2 {appendChild} { set doc [dom createDocumentNode] set newNode [$doc createElement newNode] $doc appendChild $newNode set result [[$doc documentElement] nodeName] $doc delete set result } {newNode} test domDoc-13.3 {appendChild} { set doc [dom createDocumentNode] set newNode [$doc createElement newNode] $doc appendChild $newNode set result [[$doc documentElement] parentNode] $doc delete set result } {} test domDoc-14.1 {removeChild} { set doc [dom parse {}] $doc removeChild [$doc firstChild] set result [$doc documentElement] $doc delete set result } {} test domDoc-14.2 {removeChild} { set doc [dom parse {}] $doc removeChild [$doc firstChild] set result [$doc asXML -indent none] $doc delete set result } {} test domDoc-14.3 {removeChild} { set doc [dom createDocumentNode] set result [catch {$doc removeChild [$doc firstChild]}] $doc delete set result } {1} test domDoc-15.1 {hasChildNodes} { set doc [dom createDocumentNode] set result [$doc hasChildNodes] set newNode [$doc createElement newNode] $doc appendChild $newNode lappend result [$doc hasChildNodes] $doc delete set result } {0 1} test domDoc-16.1 {childNodes} { set doc [dom parse {}] set result {} foreach node [$doc childNodes] { lappend result [$node nodeName] } $doc delete set result } {beforeRoot root afterRoot} test domDoc-17.1 {ownerDocument} { set doc [dom parse ] set result [expr {$doc == [$doc ownerDocument]}] $doc delete set result } {1} test domDoc-18.1 {appendFromList} { set doc [dom createDocumentNode] $doc appendFromList {elem {} {}} set node [$doc documentElement] set result [list [$node nodeName] [$node parentNode]] $doc delete set result } {elem {}} test domDoc-19.1 {appendXML} { set doc [dom createDocumentNode] $doc appendXML footext set result [$doc asXML -indent none] $doc delete set result } {footext} test domDoc-19.2 {appendXML} { set doc [dom createDocumentNode] $doc appendXML footext set result [[$doc documentElement] nodeName] lappend result [[$doc documentElement] parentNode] lappend result [expr {$doc == [[$doc documentElement] ownerDocument]}] $doc delete set result } {test {} 1} test domDoc-19.3 {appendXML} { set doc [dom createDocument foo] $doc appendXML footext set result [[$doc documentElement] nodeName] set result [$doc asXML -indent none] $doc delete set result } {footext} test domDoc-20.1 {selectNodes} { set doc [dom parse {}] set result [[$doc selectNodes {root/child[2]}] getAttribute id] $doc delete set result } {2} test domDoc-20.2 {selectNodes} { set doc [dom parse {}] set result [[$doc selectNodes {/root/child[2]}] getAttribute id] $doc delete set result } {2} test domDoc-20.3 {selectNodes} { set doc [dom parse {}] set result [list] foreach node [$doc selectNodes *] { lappend result [$node nodeName] } set result } {root} test domDoc-20.4 {selectNodes} { set doc [dom parse {}] set result [list] foreach node [$doc selectNodes node()] { lappend result [$node nodeType] } set result } {COMMENT_NODE ELEMENT_NODE PROCESSING_INSTRUCTION_NODE} test domDoc-20.5 {selectNodes with -namespaces option} { set doc [dom createDocumentNS "http://tdom.org" tdom:doc] set node [$doc selectNodes \ -namespaces {tdom http://tdom.org} \ tdom:doc] set result [$node nodeName] set node [$doc selectNodes \ -namespaces {myPrefix http://tdom.org} \ myPrefix:doc] lappend result [$node nodeName] lappend result [$doc selectNodes -namespaces {} doc typeVar] lappend result $typeVar $doc delete set result } [list tdom:doc tdom:doc "" empty] test domDoc-20.6 {selectNodes with -namespaces option} { set doc [dom createDocumentNS "http://tdom.org" tdom:doc] set node [$doc selectNodes \ -namespaces {foo bar} \ -namespaces {a b c d} \ -namespaces {tdom http://tdom.org} \ tdom:doc] set result [$node nodeName] set node [$doc selectNodes \ -namespaces {myPrefix http://tdom.org} \ myPrefix:doc] lappend result [$node nodeName] lappend result [$doc selectNodes -namespaces {} doc typeVar] lappend result $typeVar $doc delete set result } [list tdom:doc tdom:doc "" empty] test domDoc-20.7 {selectNodes with -namespaces option} { set doc [dom createDocumentNS "http://tdom.org" tdom:doc] catch {set node [$doc selectNodes \ -namespaces {foo bar} \ -namespaces {a b c d} \ -namespaces {wrong_not_pair} \ tdom:doc]} errMsg $doc delete set errMsg } {The "-namespaces" option requires a 'prefix namespace' pairs list as argument} test domDoc-20.8 {selectNodes with -list option} { set doc [dom parse { one two three four }] set result [$doc selectNodes -list { doc/product/descshort string() }] $doc delete set result } {one two {three four}} test domDoc-20.9 {selectNodes - type result} { set doc [dom parse { one }] set result "" lappend result [$doc selectNodes {string(doc/product[1]/descshort)} typeVar] lappend result $typeVar lappend result [$doc selectNodes {string(doc/product[2]/descshort)} typeVar] lappend result $typeVar lappend result [$doc selectNodes {string(doc/product[3]/descshort)} typeVar] lappend result $typeVar $doc delete set result } {one string {} string {} string} test domDoc-20.10 {selectNodes with -list option} { set doc [dom parse { one two three four }] set result [$doc selectNodes -list { doc/product/descshort string() } typeVar] $doc delete lappend result $typeVar } {one two {three four} string} test domDoc-20.11 {selectNodes with -list option} { set doc [dom parse { one two three four }] set result [$doc selectNodes -list { doc/product/dontexists string() } typeVar] $doc delete list $result $typeVar } {{} empty} test domDoc-21.1 {baseURI} { set doc [dom createDocumentNode] set result [$doc baseURI] $doc delete set result } {} test domDoc-21.2 {baseURI} { set doc [dom parse -baseurl file://foo ] set result [$doc baseURI] $doc baseURI http://that.this lappend result [$doc baseURI] $doc delete set result } {file://foo http://that.this} namespace eval nodeCmds { dom createNodeCmd elementNode e1 dom createNodeCmd elementNode e2 dom createNodeCmd commentNode c dom createNodeCmd textNode t dom createNodeCmd cdataNode cdata dom createNodeCmd piNode pi dom createNodeCmd parserNode parser } test domDoc-22.1 {appendFromScript} { set doc [dom createDocumentNode] $doc appendFromScript nodeCmds::e1 set result [$doc asXML -indent none] lappend result [[$doc documentElement] nodeName] $doc delete set result } { e1} test domDoc-22.2 {appendFromScript} { set doc [dom parse ] $doc appendFromScript { nodeCmds::e1 nodeCmds::e2 } # namespace eval nodeCmds { # $doc appendFromScript { # e1 # e2 # } # } set result [$doc asXML -indent none] foreach node [$doc selectNodes *] { lappend result [$node parentNode] lappend result [expr {$doc == [$node ownerDocument]}] } $doc delete set result } { {} 1 {} 1 {} 1} test domDoc-22.3 {appendFromScript} { set doc [dom createDocumentNode] set nrOfNodeCmdsBefore [info commands domNode*] $doc appendFromScript { nodeCmds::e1 } $doc delete set nrOfNodeCmdsAfter [info commands domNode*] expr {$nrOfNodeCmdsBefore == $nrOfNodeCmdsAfter} } {1} test domDoc-22.4 {nodeCmd called outside of *FromScript context} { dom createNodeCmd elementNode e catch e } 1 test domDoc-22.5 {nodeCmd use in child interp while in nodeCmd context} { set doc [dom createDocument this] set root [$doc documentElement] dom createNodeCmd elementNode thise dom createNodeCmd textNode t interp create childinterp load {} Tdom childinterp childinterp eval { dom createNodeCmd elementNode childe dom createNodeCmd textNode t } set result [catch {$root appendFromScript { thise { childinterp eval { childe { t "other" } } t "some" } }}] $doc delete interp delete childinterp set result } {1} test domDoc-22.6 {nodeCmd use in child interp while in nodeCmd context} { set doc [dom createDocument this] set root [$doc documentElement] dom createNodeCmd elementNode thise dom createNodeCmd textNode t interp create childinterp load {} Tdom childinterp childinterp eval { dom createNodeCmd elementNode childe dom createNodeCmd textNode t set doc [dom createDocument child] set root [$doc documentElement] } $root appendFromScript { thise { childinterp eval { $root appendFromScript { childe { t "other" } } } t "some" } } set result [$doc asXML -indent none] append result [childinterp eval {$doc asXML -indent none}] $doc delete interp delete childinterp set result } {someother} test domDoc-23.1 {getElementsByTagNameNS} { dom createNodeCmd elementNode child set doc [dom createDocument root] $doc documentElement root $root appendFromScript { for {set x 0} {$x < 250} {incr x} { child [list xmlns ns$x] {} } } set xml [$doc asXML] $doc delete set doc [dom parse $xml] set result 1 for {set x 0} {$x < 250} {incr x} { set nodes [$doc getElementsByTagNameNS ns$x *] if {[llength $nodes] != 1} { set result 0 } } $doc delete set result } {1} test domDoc-24.1 {cdataSectionElements} { set doc [dom parse {Some Text}] set result [catch {$doc cdataSectionElements} errMsg] lappend result $errMsg $doc delete set result } {1 {wrong # args: should be " cdataSectionElements ?URI:?localname ?boolean?"}} test domDoc-24.2 {cdataSectionElements} { set doc [dom parse {Some Text}] set result [catch {$doc cdataSectionElements foo bar grill} errMsg] lappend result $errMsg $doc delete set result } {1 {wrong # args: should be " cdataSectionElements ?URI:?localname ?boolean?"}} test domDoc-24.3 {cdataSectionElements} { set doc [dom parse {Some Text}] set result [catch {$doc cdataSectionElements root foo} errMsg] lappend result $errMsg $doc delete set result } {1 {expected boolean value but got "foo"}} test domDoc-24.4 {cdataSectionElements} { set doc [dom parse {Some Text}] set result [$doc cdataSectionElements root] $doc delete set result } {0} test domDoc-24.5 {cdataSectionElements} { set doc [dom parse {Some Text}] set result [$doc cdataSectionElements root 0] lappend result [$doc cdataSectionElements root 1] lappend result [$doc cdataSectionElements root 0] $doc delete set result } {0 1 0} test domDoc-24.6 {cdataSectionElements} { set doc [dom parse {Some Text}] set result [$doc cdataSectionElements root 1] lappend result [$doc asXML -indent none] $doc delete set result } {1 {}} test domDoc-24.7 {cdataSectionElements} { set doc [dom parse {<foo>}] foreach element {foo root bar grill} { $doc cdataSectionElements $element 1 } set result [$doc asXML -indent none] $doc delete set result } {]]>} test domDoc-24.8 {cdataSectionElements} { set doc [dom parse {text ]}] $doc cdataSectionElements root 1 set result [$doc asXML -indent none] $doc delete set result } {} test domDoc-24.9 {cdataSectionElements} { set doc [dom parse {text ]]}] $doc cdataSectionElements root 1 set result [$doc asXML -indent none] $doc delete set result } {} test domDoc-24.10 {cdataSectionElements} { set doc [dom parse {text ]]>}] $doc cdataSectionElements root 1 set result [$doc asXML -indent none] $doc delete set result } {]]>} test domDoc-24.11 {cdataSectionElements} { set doc [dom parse {text ]]> text]]>text}] $doc cdataSectionElements root 1 set result [$doc asXML -indent none] $doc delete set result } { text]]]]>text]]>} test domDoc-24.12 {cdataSectionElements} { set doc [dom parse {text}] $doc cdataSectionElements http://foo.bar:root 1 set result [$doc asXML -indent none] $doc delete set result } {} test domDoc-24.13 {cdataSectionElements} { set doc [dom parse {text}] set result [$doc cdataSectionElements ""] $doc delete set result } {0} test domDoc-24.14 {cdataSectionElements} { set doc [dom parse {text}] set result [$doc cdataSectionElements *] $doc delete set result } {} test domDoc-24.15 {cdataSectionElements} { set doc [dom parse {text}] foreach elem {foo bar grill root http://www.foo.org:baz} { $doc cdataSectionElements $elem 1 } foreach elem {foo grill} { $doc cdataSectionElements $elem 0 } set result [lsort [$doc cdataSectionElements *]] $doc delete set result } {bar http://www.foo.org:baz root} test domDoc-24.16 {cdataSectionElements} { set doc [dom parse {some text}] $doc documentElement root set node [$root firstChild] $doc cdataSectionElements child 1 set result [$node asXML -indent none] $doc delete set result } {} test domDoc-24.17 {cdataSectionElements} { set doc [dom parse {some text more text text again}] $doc cdataSectionElements child 1 set result [$doc asXML -indent none] $doc delete set result } {more text} test domDoc-25.1 {selectNodesNamespaces} { set doc [dom createDocument foo] set result [$doc selectNodesNamespaces] $doc delete set result } {} test domDoc-25.2 {selectNodesNamespaces} { set doc [dom createDocument foo] set result [list [$doc selectNodesNamespaces] \ [$doc selectNodesNamespaces {}] \ [$doc selectNodesNamespaces]] $doc delete set result } {{} {} {}} test domDoc-25.3 {selectNodesNamespaces} { set doc [dom createDocument foo] set result [list [$doc selectNodesNamespaces] \ [$doc selectNodesNamespaces {prefix http://foo.org/uri}] \ [$doc selectNodesNamespaces] \ [$doc selectNodesNamespaces {}]] $doc delete set result } {{} {prefix http://foo.org/uri} {prefix http://foo.org/uri} {}} test domDoc-25.4 {selectNodesNamespaces} { set doc [dom createDocument foo] set result [catch {$doc selectNodesNamespaces wrong} errMsg] lappend result $errMsg $doc delete set result } {1 {The optional argument to selectNodesNamespaces must be a 'prefix namespace' pairs list}} test domDoc-25.5 {selectNodesNamespaces} { set doc [dom parse { }] $doc selectNodesNamespaces {default1 rootdefaultNS} set node [$doc selectNodes default1:root] set result [list [$node prefix] [$node localName]] $doc delete set result } {{} root} test domDoc-25.6 {selectNodesNamespaces} { set doc [dom parse { }] $doc selectNodesNamespaces {default2 elem1NS default1 rootdefaultNS} set node [$doc selectNodes default1:root/default2:elem1] set result [list [$node prefix] [$node localName]] set node [$doc selectNodes default1:root/default2:elem1/default2:elem11] lappend result [$node nodeName] [$node namespaceURI] $doc delete set result } {{} elem1 elem11 elem1NS} test domDoc-25.7 {selectNodesNamespaces} { set doc [dom parse { }] $doc selectNodesNamespaces {default2 elem1NS default1 rootdefaultNS} set node [$doc selectNodes default1:root/default2:elem1] set result [list [$node prefix] [$node localName]] set node [$doc selectNodes default1:root/default2:elem1/elem11] lappend result [$node nodeName] [$node namespaceURI] $doc delete set result } {{} elem1 elem11 {}} test domDoc-25.7.1 {selectNodesNamespaces} { set doc [dom parse { }] $doc documentElement root $root firstChild elem1 $doc createElement elem11 elem11 $elem1 appendChild $elem11 $doc selectNodesNamespaces {default2 elem1NS default1 rootdefaultNS} set node [$doc selectNodes default1:root/default2:elem1] set result [list [$node prefix] [$node localName]] set node [$doc selectNodes default1:root/default2:elem1/elem11] lappend result [$node nodeName] [$node namespaceURI] $doc delete set result } {{} elem1 elem11 {}} test domDoc-25.8 {selectNodesNamespaces} { set doc [dom parse { }] $doc selectNodesNamespaces {default2 elem1NS default1 rootdefaultNS} set result [catch {set node [$doc selectNodes \ -namespaces { dflt1 elem1NS dflt2 rootdefaultNS } \ default1:root/dflt1:elem1/elem11]} errMsg] lappend result $errMsg $doc delete set result } {1 {Prefix doesn't resolve}} test domDoc-25.9 {selectNodesNamespaces} { set doc [dom parse { }] $doc selectNodesNamespaces {default2 elem1NS default1 rootdefaultNS} set node [$doc selectNodes default1:root/default2:elem1] set result [list [$node prefix] [$node localName]] set node [$doc selectNodes \ -namespaces {dflt1 elem1NS dflt2 rootdefaultNS} \ dflt2:root/dflt1:elem1/elem11] lappend result [$node nodeName] [$node namespaceURI] $doc delete set result } {{} elem1 elem11 {}} test domDoc-26.1 {Fragment list} { set doc [dom parse { text1text2text3}] $doc removeChild [$doc firstChild] $doc documentElement root for {set i 1} {$i < 4} {incr i} { set removedNode$i [$root removeChild [$root firstChild]] } $removedNode2 delete $root appendChild $removedNode3 $root appendChild $removedNode1 set result [$doc asXML -indent none] $doc delete set result } {text3text1} test domDoc-27.1 {deleteXPathCache} { set doc [dom createDocument doc] set result [list] lappend result [$doc deleteXPathCache foo/bar] $doc selectNodes -cache 1 2+2 lappend result [$doc deleteXPathCache foo/bar] lappend result [$doc deleteXPathCache 2+2] lappend result [$doc deleteXPathCache] $doc selectNodes -cache 1 2+2 $doc delete set result } {{} {} {} {}} test domDoc-28.1 {createElementNS} { set doc [dom createDocument doc] set newElem [$doc createElementNS uri ns:e] $doc documentElement root $root appendChild $newElem set result [$doc asXML -indent none] $doc delete set result } {} test domDoc-28.2 {createElementNS} { set doc [dom createDocument doc] set newElem [$doc createElementNS uri ns:e] $newElem setAttributeNS uri ns:att value $doc documentElement root $root appendChild $newElem set result [$doc selectNodes -namespaces {ns uri} string(/doc/ns:e/@ns:att)] $doc delete set result } {value} test domDoc-28.3 {createElementNS} { set doc [dom createDocument doc] catch {$doc createElementNS "" e} errMsg $doc delete set errMsg } {Missing URI in Namespace declaration} test domDoc-29.1 {asCanonicalXML} { set doc [dom parse -keepEmpties { Hello, world! }] set result [$doc asCanonicalXML] $doc delete set result } { Hello, world! } test domDoc-29.2 {asCanonicalXML} { set doc [dom parse -keepEmpties { Hello, world! }] set result [$doc asCanonicalXML -comments 1] $doc delete set result } { Hello, world! } test domDoc-29.3 {asCanonicalXML} { set doc [dom parse -keepEmpties { A B A B A B C }] set result [$doc asCanonicalXML] $doc delete set result } { A B A B A B C } test domDoc-29.5 {asCanonicalXML} { set doc [dom parse -keepEmpties {]> }] set result [$doc asCanonicalXML] $doc delete set result } { } test domDoc-29.6 {asCanonicalXML} { set doc [dom parse -keepEmpties { ]> First line Second line 2 "0" && value<"10" ?"valid":"error"]]> valid }] set result [$doc asCanonicalXML] $doc delete set result } { First line Second line 2 value>"0" && value<"10" ?"valid":"error" valid } proc 29.7 {base system public} { switch $system { "world.txt" { return [list "string" "" "world"] } "earth.gif" { return [list "string" "" ""] } default { error "unexpected system URL '$system'" } } } test domDoc-29.7 {asCanonicalXML} { set doc [dom parse -externalentitycommand 29.7 -keepEmpties { ]> &ent1;, &ent2;! }] set result [$doc asCanonicalXML] $doc delete set result } { Hello, world! } test domDoc-29.8 {asCanonicalXML} { set doc [dom parse -keepEmpties { ©}] set result [$doc asCanonicalXML] $doc delete set result } "\u00A9" test domDoc-30.1 {cmd argument parsing} { set result [catch {domDoc} errMsg] lappend result $errMsg catch {domDoc foo} errMsg lappend result $errMsg } {1 {wrong # args: should be "domDoc doctoken subcommand ?arg ...?"} {wrong # args: should be "domDoc doctoken subcommand ?arg ...?"}} test domDoc-30.2 {cmd argument parsing} { set storedMode [dom setObjectCommands] dom setObjectCommands token set doc [dom parse {}] catch {domDoc $doc} result domDoc $doc delete dom setObjectCommands $storedMode set result } {wrong # args: should be "domDoc doctoken subcommand ?arg ...?"} test domDoc-30.3 {cmd argument parsing} -body { set doc [dom parse {}] catch {$doc} result $doc delete set result } -match regexp -result {wrong # args: should be "domDoc[^ ]+ subcommand \?arg ...\?"} test domDoc-30.4 {cmd argument parsing} -body { set storedMode [dom setObjectCommands] dom setObjectCommands token set doc [dom parse {}] catch {domDoc $doc invalid-method} result domDoc $doc delete dom setObjectCommands $storedMode set result } -match glob -result {bad method "invalid-method": must be *} test domDoc-30.5 {cmd argument parsing} -body { set doc [dom parse {}] catch {$doc invalid-method} result $doc delete set result } -match glob -result {bad method "invalid-method": must be *} # test domDoc-29.9 {asCanonicalXML} { # set doc [dom parse -keepEmpties {}] # set result [$doc asCanonicalXML] # $doc delete # set result # } {} # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/dom.test0000644000175000017500000022605514703531020014572 0ustar rolfrolf# Features covered: dom command # # This file contains a collection of tests for the dom command of # tDOM. # # dom-1.*: createDocument, createDocumentNS # dom-2.*: parse # dom-3.*: is* methods, clearString # dom-4.*: parse -useForeignDTD # dom-5.*: external entities # dom-6.*: use in slave interpreter # dom-7.*: setNameCheck, setTextCheck # dom-8.*: createDocumentNode, documentNodes # dom-9.*: setObjectCommands # dom-10.*: createNodeCmd # dom-11.*: featureinfo # dom-12.*: -feedbackAfter # dom-13.*: -forest # dom-14.*: command argument parsing # # Copyright (c) 2002, 2003, 2004 Rolf Ade. source [file join [file dir [info script]] loadtdom.tcl] test dom-1.1 {createDocument with root node name not a XML Name} { list [catch {dom createDocument "root node"} msg] $msg } "1 {Invalid root element name 'root node'}" test dom-1.2 {createDocument with root node name not a XML Name} { list [catch {dom createDocument "1root"} msg] $msg } "1 {Invalid root element name '1root'}" test dom-1.3 {createDocument - root name us-ascii} { dom createDocument "root" doc set root [$doc documentElement] set result [$root nodeName] $doc delete set result } "root" test dom-1.4 {createDocument - root name with UTF-8 chars} { dom createDocument "\u00c4\u00d4\u00dc" doc set root [$doc documentElement] set result [$root nodeName] $doc delete set result } "\u00c4\u00d4\u00dc" test dom-1.5 {createDocument with FQ root name} { dom createDocument "foo:bar" doc set root [$doc documentElement] set result [$root nodeName] $doc delete set result } "foo:bar" test dom-1.6 {createDocument with wrong # of args} { list [catch {dom createDocument "root" "http:/foo:bar" doc} msg] $msg } "1 {wrong \# args: should be \"createDocument docElemName ?newObjVar?\"}" test dom-1.7 {createDocumentNS - check root name} { set doc [dom createDocumentNS "http://foo.bar" "root"] set root [$doc documentElement] set result [$root nodeName] $doc delete set result } "root" test dom-1.8 {createDocumentNS - check the NS of the created root} { dom createDocumentNS "http://foo.bar" "root" doc set root [$doc documentElement] set result [$root namespaceURI] $doc delete set result } "http://foo.bar" test dom-1.9 {createDocumentNS with root name not a NCName} { list [catch {dom createDocumentNS "http://foo.bar" "foo bar" doc} msg] $msg } "1 {Invalid root element name 'foo bar'}" test dom-1.10 {createDocumentNS with root name not a NCName} { list [catch {dom createDocumentNS "http://foo.bar" "a:b:c" doc} msg] $msg } "1 {Invalid root element name 'a:b:c'}" test dom-1.11 {createDocumentNS with root name not a NCName} { list [catch {dom createDocumentNS "http://foo.bar" "a b:b" doc} msg] $msg } "1 {Invalid root element name 'a b:b'}" test dom-1.12 {createDocumentNS with root name not a NCName} { list [catch {dom createDocumentNS "http://foo.bar" "a:a b" doc} msg] $msg } "1 {Invalid root element name 'a:a b'}" test dom-1.13 {createDocumentNS - check root name} { set doc [dom createDocumentNS "http://foo.bar" foo:root] set root [$doc documentElement] set result [$root nodeName] $doc delete set result } "foo:root" test dom-1.14 {createDocument - rename the doc cmd} { set doc [dom createDocument root] if {[info commands fooCmd] == "fooCmd"} { rename fooCmd {} } rename $doc fooCmd set result [[fooCmd documentElement] nodeName] fooCmd delete set result } {root} test dom-1.15 {createDocument - rename the doc cmd} { if {[info commands fooCmd] == "fooCmd"} { rename fooCmd {} } set nrOfCommands [llength [info commands]] set doc [dom createDocument root] rename $doc fooCmd fooCmd delete expr {[llength [info commands]] == $nrOfCommands} } {1} test dom-1.16 {createDocumentNS - empty namespace, no prefix} { dom createDocumentNS "" doc doc set result [$doc asXML -indent none] $doc delete set result } {} test dom-1.17 {createDocumentNS - namespace, no prefix} { dom createDocumentNS "uri" doc doc set result [$doc asXML -indent none] $doc delete set result } {} test dom-1.18 {createDocumentNS - namespace, no prefix} { dom createDocumentNS "uri" doc doc set result [$doc selectNodes -namespaces {ns uri} count(/ns:doc)] $doc delete set result } 1 test dom-1.19 {createDocumentNS - namespace, prefix} { dom createDocumentNS "uri" n1:doc doc set result [$doc selectNodes -namespaces {ns uri} count(/ns:doc)] $doc delete set result } 1 test dom-1.20 {createDocumentNS - empty namespace, prefix} { catch {dom createDocumentNS "" n1:doc doc} errMsg set errMsg } {Missing URI in Namespace declaration} test dom-1.21 {Explicit delete of scoped doc with domDoc cmd} {} { dom createDocument test doc domDoc $doc delete unset doc } {} proc dom-1.22 {doc} { $doc delete } test dom-1.22 {Explicit delete of scoped doc in proc call from scope} {} { dom createDocument test doc dom-1.22 $doc unset doc } {} test dom-1.23 {Explicit delete of scoped doc} { dom createDocument test doc $doc delete unset doc } {} test dom-1.24 {Explicit delete of scoped doc} { dom createDocument test doc set result [catch {set doc foo} errMsg] lappend result $errMsg $doc delete unset doc set result } {1 {can't set "doc": var is read-only}} test dom-1.25 {Doc var} { dom parse doc dom parse doc unset doc } {} test dom-1.26 {Doc var} { dom parse doc set result [catch {$doc documentElement doc}] unset doc set result } {1} test dom-2.1 {Don't quash white space at start or end of non white space content} { set doc [dom parse { some content }] set root [$doc documentElement] $root text } { some content } test dom-2.2 {parse doc with various re-declaration of a prefix} { set doc [dom parse { }] set root [$doc documentElement] set result [$root asXML] $doc delete set result } { } test dom-2.3 {parse doc with default NS declaration} { set doc [dom parse { }] set root [$doc documentElement] set result [$root asXML] $doc delete set result } { } test dom-2.4 {parse method: syntax check} { set doc [dom parse -keepEmpties { text }] set result [$doc asXML -indent none] $doc delete set result } { text } test dom-2.5 {parse method: syntax check} { set doc [dom parse -useForeignDTD 0 -keepEmpties { text }] set result [$doc asXML -indent none] $doc delete set result } { text } test dom-2.6 {parse method: syntax check} -setup { set xmlFile [makeFile { } dom.xml] } -body { set fd [open $xmlFile] set doc [dom parse -channel $fd -keepEmpties] close $fd set root [$doc documentElement] set result [$root asXML -indent none] $doc delete set result } -cleanup { removeFile dom.xml } -result { } test dom-2.7 {parse method: syntax check} -setup { set xmlFile [makeFile { } dom.xml] } -body { catch {unset -keepEmpties} set fd [open $xmlFile] set doc [dom parse -channel $fd -keepEmpties] close $fd $doc delete info exists -keepEmpties } -cleanup { removeFile dom.xml } -result 0 test dom-2.8 {parse method: bogus option} -body { set result [catch {set doc [dom parse -bogusOption foo ]} errMsg] lappend result $errMsg } -match regexp -result {1 {bad option "-bogusOption": must be .*}} test dom-2.9 {parse method: bogus option} -setup { set xmlFile [makeFile { } dom.xml] } -body { catch {unset -keepEmpties} set fd [open $xmlFile] set result [catch {set doc [dom parse -channel $fd -bogusOption]} errMsg] close $fd lappend result $errMsg } -cleanup { removeFile dom.xml } -match regexp -result {1 {bad option "-bogusOption": must be .*}} set dom_dtd " " proc extRefResolver {base systemId publicId} { global dom_dtd if {$publicId == "DOMCMDTEST"} { return [list string $base $dom_dtd] } else { return [::tdom::extRefHandler $base $systemId $publicId] } } test dom-2.10 {parse method: -paramentityparsing default is 'always'} { set doc [dom parse -externalentitycommand extRefResolver { }] set root [$doc documentElement] set result [$root @lang] $doc delete set result } {en} test dom-2.11 {parse method: explicit -paramentityparsing always} { set doc [dom parse -externalentitycommand extRefResolver \ -paramentityparsing always { }] set root [$doc documentElement] set result [$root @lang] $doc delete set result } {en} test dom-2.12 {parse method: -paramentityparsing never} { set doc [dom parse -externalentitycommand extRefResolver \ -paramentityparsing never { }] set root [$doc documentElement] set result [catch {set result [$root @lang]} errMsg] $doc delete lappend result $errMsg set result } {1 {Attribute "lang" not found!}} test dom-2.13 {parse method: -paramentityparsing notstandalone} { set doc [dom parse -externalentitycommand extRefResolver \ -paramentityparsing notstandalone { }] set root [$doc documentElement] set result [$root @lang] $doc delete set result } {en} test dom-2.14 {parse method: -paramentityparsing notstandalone} { set doc [dom parse -externalentitycommand extRefResolver \ -paramentityparsing notstandalone \ { }] set root [$doc documentElement] set result [catch {set result [$root @lang]} errMsg] $doc delete lappend result $errMsg set result } {1 {Attribute "lang" not found!}} test dom-2.15 {parse method: -paramentityparsing notstandalone} { set doc [dom parse -externalentitycommand extRefResolver \ -paramentityparsing notstandalone \ { }] set root [$doc documentElement] set result [$root @lang] $doc delete set result } {en} test dom-2.16 {parse method: wrong value arg for -paramentityparsing} { set result [catch {set doc [dom parse -paramentityparsing wrong { }]} errMsg] lappend result $errMsg } {1 {bad value "wrong": must be always, never, or notstandalone}} # The following is syntactically wrong. It's used, to test the # error reporting in external DTDs set dom_dtd "" test dom-2.17 {parse method: test reporting of error in external subset} { set result [catch {set doc [dom parse \ -externalentitycommand extRefResolver { }]} errMsg] lappend result $errMsg } {1 {error "syntax error" in entity "dummysystemID" at line 1 character 20 "", referenced at line 2 character 58}} test dom-2.18 {parse document with nodes before and after the documentElement} { set doc [dom parse { }] set result [$doc asXML -indent none] $doc delete set result } {} test dom-2.19 {parse document - rename docCmd} { set doc [dom parse {foo}] if {[info commands fooCmd] == "fooCmd"} { rename fooCmd {} } rename $doc fooCmd set result [fooCmd asXML -indent none] fooCmd delete set result } {foo} test dom-2.20 {parse - doc with internal subset parsed with -keepEmpties} { set doc [dom parse -keepEmpties { ]> }] $doc documentElement root set result "" foreach node [$root selectNodes /node()] { switch [$node nodeType] { TEXT_NODE { lappend result TEXT_NODE lappend result [string length [$node value]] } COMMENT_NODE { lappend result COMMENT_NODE lappend result [string length [$node value]] } PROCESSING_INSTRUCTION_NODE { lappend result PROCESSING_INSTRUCTION_NODE lappend result [$node target] lappend result [$node data] } ELEMENT_NODE { lappend result ELEMENT_NODE lappend result [$node nodeName] } default { lappend result [$node nodeType] } } } $doc delete set result } {ELEMENT_NODE root} test dom-2.21 {parse - empty CDATA section} { set doc [dom parse {}] set root [$doc documentElement] set result [$root hasChildNodes] $doc delete set result } {0} test dom-2.22 {parse - empty comment section} { set doc [dom parse {}] set root [$doc documentElement] set result [$root hasChildNodes] lappend result [[$root firstChild] nodeValue] $doc delete set result } {1 {}} test dom-2.23 {parse - pi without pivalue} { set doc [dom parse {}] set pi [[$doc documentElement] firstChild] set result [list [$pi nodeName] [$pi nodeValue] [$pi target] [$pi data]] $doc delete set result } {p {} p {}} proc 2.24 {args} { error "2.24 external entitiy resolver script error" } test dom-2.24 {parse - script error in -externalentitycommand} { set result [catch { dom parse -externalentitycommand 2.24 { }} errMsg] lappend result $errMsg } {1 {2.24 external entitiy resolver script error}} test dom-2.25 {White space outside the document element is markup and ignored, even with -keepEmpties} { set doc [dom parse -keepEmpties { }] set result [$doc asXML -indent none] $doc delete set result } { } test dom-2.26 {Not well-formed input} { catch {dom parse {}} } 1 test dom-2.27 {parse -ignorexmlns} { set result [list] set doc [dom parse {}] set root [$doc documentElement] lappend result [$root localName] lappend result [$root namespaceURI] set child [$root firstChild] lappend result [$child localName] lappend result [$child namespaceURI] lappend result [$doc selectNodes count(/doc/child)] $doc delete set doc [dom parse -ignorexmlns {}] set root [$doc documentElement] lappend result [$root nodeName] lappend result [$root namespaceURI] set child [$root firstChild] lappend result [$child nodeName] lappend result [$child namespaceURI] lappend result [$doc selectNodes count(/doc/child)] $doc delete set result } {doc foo.bar child foo.bar 0 doc {} child {} 1} test dom-2.28 {parse document with undeclared xml prefix} { catch {dom parse {}} errMsg string range $errMsg 0 30 } {Namespace prefix is not defined} test dom-2.29 {parse not well-formed document with undeclared xml prefix} { catch {dom parse {}} errMsg string range $errMsg 0 30 } {Namespace prefix is not defined} test dom-2.30 {parse document with undeclared xml prefix} { catch {dom parse {}} errMsg string range $errMsg 0 30 } {Namespace prefix is not defined} proc dom-2.31 {base systemId publicId} { switch $publicId { "e1" { # Not well-formed set data "" } default { error "unknown public ID" } } return [list "string" $base $data] } test dom-2.31 {parse document with undeclared xml prefix} { catch {dom parse -externalentitycommand dom-2.31 \ {]> &e1;} } errMsg string range $errMsg 0 30 } {Namespace prefix is not defined} test dom-2.32 {parse document with undeclared xml prefix and -ignorexmlns} { set doc [dom parse -ignorexmlns {}] set result [[$doc documentElement] nodeName] $doc delete set result } {foo:e} test dom-2.33 {end of options option} { set doc [dom parse -json -- -0.123] set result [$doc asXML -indent none] $doc delete set result } -0.123 test dom-2.33.1 {JSON data starting with a dash (-)} { set doc [dom parse -json -0.123] set result [$doc asXML -indent none] $doc delete set result } -0.123 test dom-2.33.2 {JSON data starting with a dash (-)} { dom parse -json -0.123 doc set result [$doc asXML -indent none] $doc delete set result } -0.123 test dom-2.33.3 {JSON data starting with a dash (-)} { dom parse -json -0.123 -0.123 set result [${-0.123} asXML -indent none] ${-0.123} delete set result } -0.123 test dom-2.34 {XML prefix declaration with empty namespace} { catch {dom parse {}} errMsg set errMsg } {Missing URI in Namespace declaration, referenced at line 1 character 22} test dom-2.35 {-keepCDATA} { set doc [dom parse -keepCDATA {foo format]]> bar }] set result [$doc asXML -indent none] $doc delete set result } {foo format]]> bar } test dom-2.36 {-keepCDATA} { set doc [dom parse -keepCDATA {foo format]]> bar }] set root [$doc documentElement] set result [list] foreach child [$root childNodes] { lappend result [$child nodeType] } $doc delete set result } {TEXT_NODE CDATA_SECTION_NODE TEXT_NODE} test dom-2.37 {-keepCDATA} { set doc [dom parse -keepCDATA {}] set result [list] foreach child [$doc selectNodes doc/e/node()] { lappend result [$child nodeType] } $doc delete set result } {CDATA_SECTION_NODE} test dom-2.38 {-keepCDATA} { set doc [dom parse -keepCDATA {}] set result [list] foreach child [$doc selectNodes doc/e/node()] { lappend result [$child nodeType] } $doc delete set result } {CDATA_SECTION_NODE CDATA_SECTION_NODE} test dom-2.39 {-keepCDATA} { set doc [dom parse -keepCDATA {}] set result [$doc selectNodes count(doc/e/node())] $doc delete set result } 0 test dom-2.40 {-keepCDATA white space only CDATA section} { set doc [dom parse -keepCDATA {}] set result [$doc selectNodes count(doc/e/node())] $doc delete set result } 0 test dom-2.41 {-keepCDATA and -keepEmpties} { set doc [dom parse -keepCDATA -keepEmpties {}] set result [$doc selectNodes count(doc/e/node())] $doc delete set result } 1 test dom-2.42 {namespaces} { set doc [dom parse {
    notes
    }] $doc delete } {} test dom-2.43 {billion laughs attact proctection options} { set result "" foreach {option value} { -billionLaughsAttackProtectionMaximumAmplification foo -billionLaughsAttackProtectionMaximumAmplification 0 -billionLaughsAttackProtectionMaximumAmplification -2.0 -billionLaughsAttackProtectionMaximumAmplification 23 -billionLaughsAttackProtectionActivationThreshold bar -billionLaughsAttackProtectionActivationThreshold 0 -billionLaughsAttackProtectionActivationThreshold -7 -billionLaughsAttackProtectionActivationThreshold 2000000000 } { lappend result [catch { set doc [dom parse $option $value ] }] if {![lindex $result end]} { $doc delete } } set result } {1 1 1 0 1 1 1 0} test dom-2.44 {attribute order and XML namespace declaration} { set doc [dom parse -simple { foo }] set root [$doc documentElement] set result [$root attributeNames] $doc delete set result } {xmlns:p xmlns foo grill bar} test dom-2.45 {attribute order and XML namespace declaration} { set doc [dom parse { }] set root [$doc documentElement] set result [$root attributeNames] $doc delete set result } {xmlns:p xmlns foo grill bar} test dom-2.46 {parse long string} {64bit Tcl9 longRunning} { set str "[string repeat abc 1000000000]" set doc [dom parse $str] set result [string length [$doc selectNodes string(/doc)]] lappend result [string length [$doc selectNodes substring(doc,2999999999)]] lappend result [$doc selectNodes substring(doc,2999999995,3)] $doc delete set result } {3000000000 2 abc} test dom-2.47 {parse chunk ends in multbyte char} { set str "[string repeat \u1D8B 3000]" set doc [dom parse $str] set new [$doc asXML -indent none] $doc delete expr {$str eq $new ? 1 : 0} } 1 test dom-3.1 {isName} { dom isName ":foo" } {1} test dom-3.2 {isName} { dom isName "_foo" } {1} test dom-3.3 {isName} { dom isName "foo:bar:baz" } {1} test dom-3.4 {isName} { dom isName "-foo" } {0} test dom-3.5 {isName} { dom isName ".foo" } {0} test dom-3.6 {isName} { catch {dom isName} } {1} test dom-3.7 {isName} { catch {dom isName foo bar} } {1} # The following character classes are out of XML 1.0 Second Edition rec, # Appendix B (which is following the Unicode standard). set BaseChar { {0x0041 0x005A} {0x0061 0x007A} {0x00C0 0x00D6} {0x00D8 0x00F6} {0x00F8 0x00FF} {0x0100 0x0131} {0x0134 0x013E} {0x0141 0x0148} {0x014A 0x017E} {0x0180 0x01C3} {0x01CD 0x01F0} {0x01F4 0x01F5} {0x01FA 0x0217} {0x0250 0x02A8} {0x02BB 0x02C1} 0x0386 {0x0388 0x038A} 0x038C {0x038E 0x03A1} {0x03A3 0x03CE} {0x03D0 0x03D6} 0x03DA 0x03DC 0x03DE 0x03E0 {0x03E2 0x03F3} {0x0401 0x040C} {0x040E 0x044F} {0x0451 0x045C} {0x045E 0x0481} {0x0490 0x04C4} {0x04C7 0x04C8} {0x04CB 0x04CC} {0x04D0 0x04EB} {0x04EE 0x04F5} {0x04F8 0x04F9} {0x0531 0x0556} 0x0559 {0x0561 0x0586} {0x05D0 0x05EA} {0x05F0 0x05F2} {0x0621 0x063A} {0x0641 0x064A} {0x0671 0x06B7} {0x06BA 0x06BE} {0x06C0 0x06CE} {0x06D0 0x06D3} 0x06D5 {0x06E5 0x06E6} {0x0905 0x0939} 0x093D {0x0958 0x0961} {0x0985 0x098C} {0x098F 0x0990} {0x0993 0x09A8} {0x09AA 0x09B0} 0x09B2 {0x09B6 0x09B9} {0x09DC 0x09DD} {0x09DF 0x09E1} {0x09F0 0x09F1} {0x0A05 0x0A0A} {0x0A0F 0x0A10} {0x0A13 0x0A28} {0x0A2A 0x0A30} {0x0A32 0x0A33} {0x0A35 0x0A36} {0x0A38 0x0A39} {0x0A59 0x0A5C} 0x0A5E {0x0A72 0x0A74} {0x0A85 0x0A8B} 0x0A8D {0x0A8F 0x0A91} {0x0A93 0x0AA8} {0x0AAA 0x0AB0} {0x0AB2 0x0AB3} {0x0AB5 0x0AB9} 0x0ABD 0x0AE0 {0x0B05 0x0B0C} {0x0B0F 0x0B10} {0x0B13 0x0B28} {0x0B2A 0x0B30} {0x0B32 0x0B33} {0x0B36 0x0B39} 0x0B3D {0x0B5C 0x0B5D} {0x0B5F 0x0B61} {0x0B85 0x0B8A} {0x0B8E 0x0B90} {0x0B92 0x0B95} {0x0B99 0x0B9A} 0x0B9C {0x0B9E 0x0B9F} {0x0BA3 0x0BA4} {0x0BA8 0x0BAA} {0x0BAE 0x0BB5} {0x0BB7 0x0BB9} {0x0C05 0x0C0C} {0x0C0E 0x0C10} {0x0C12 0x0C28} {0x0C2A 0x0C33} {0x0C35 0x0C39} {0x0C60 0x0C61} {0x0C85 0x0C8C} {0x0C8E 0x0C90} {0x0C92 0x0CA8} {0x0CAA 0x0CB3} {0x0CB5 0x0CB9} 0x0CDE {0x0CE0 0x0CE1} {0x0D05 0x0D0C} {0x0D0E 0x0D10} {0x0D12 0x0D28} {0x0D2A 0x0D39} {0x0D60 0x0D61} {0x0E01 0x0E2E} 0x0E30 {0x0E32 0x0E33} {0x0E40 0x0E45} {0x0E81 0x0E82} 0x0E84 {0x0E87 0x0E88} 0x0E8A 0x0E8D {0x0E94 0x0E97} {0x0E99 0x0E9F} {0x0EA1 0x0EA3} 0x0EA5 0x0EA7 {0x0EAA 0x0EAB} {0x0EAD 0x0EAE} 0x0EB0 {0x0EB2 0x0EB3} 0x0EBD {0x0EC0 0x0EC4} {0x0F40 0x0F47} {0x0F49 0x0F69} {0x10A0 0x10C5} {0x10D0 0x10F6} 0x1100 {0x1102 0x1103} {0x1105 0x1107} 0x1109 {0x110B 0x110C} {0x110E 0x1112} 0x113C 0x113E 0x1140 0x114C 0x114E 0x1150 {0x1154 0x1155} 0x1159 {0x115F 0x1161} 0x1163 0x1165 0x1167 0x1169 {0x116D 0x116E} {0x1172 0x1173} 0x1175 0x119E 0x11A8 0x11AB {0x11AE 0x11AF} {0x11B7 0x11B8} 0x11BA {0x11BC 0x11C2} 0x11EB 0x11F0 0x11F9 {0x1E00 0x1E9B} {0x1EA0 0x1EF9} {0x1F00 0x1F15} {0x1F18 0x1F1D} {0x1F20 0x1F45} {0x1F48 0x1F4D} {0x1F50 0x1F57} 0x1F59 0x1F5B 0x1F5D {0x1F5F 0x1F7D} {0x1F80 0x1FB4} {0x1FB6 0x1FBC} 0x1FBE {0x1FC2 0x1FC4} {0x1FC6 0x1FCC} {0x1FD0 0x1FD3} {0x1FD6 0x1FDB} {0x1FE0 0x1FEC} {0x1FF2 0x1FF4} {0x1FF6 0x1FFC} 0x2126 {0x212A 0x212B} 0x212E {0x2180 0x2182} {0x3041 0x3094} {0x30A1 0x30FA} {0x3105 0x312C} {0xAC00 0xD7A3} } set Ideographic { {0x4E00 0x9FA5} 0x3007 {0x3021 0x3029} } set CombiningChar { {0x0300 0x0345} {0x0360 0x0361} {0x0483 0x0486} {0x0591 0x05A1} {0x05A3 0x05B9} {0x05BB 0x05BD} 0x05BF {0x05C1 0x05C2} 0x05C4 {0x064B 0x0652} 0x0670 {0x06D6 0x06DC} {0x06DD 0x06DF} {0x06E0 0x06E4} {0x06E7 0x06E8} {0x06EA 0x06ED} {0x0901 0x0903} 0x093C {0x093E 0x094C} 0x094D {0x0951 0x0954} {0x0962 0x0963} {0x0981 0x0983} 0x09BC 0x09BE 0x09BF {0x09C0 0x09C4} {0x09C7 0x09C8} {0x09CB 0x09CD} 0x09D7 {0x09E2 0x09E3} 0x0A02 0x0A3C 0x0A3E 0x0A3F {0x0A40 0x0A42} {0x0A47 0x0A48} {0x0A4B 0x0A4D} {0x0A70 0x0A71} {0x0A81 0x0A83} 0x0ABC {0x0ABE 0x0AC5} {0x0AC7 0x0AC9} {0x0ACB 0x0ACD} {0x0B01 0x0B03} 0x0B3C {0x0B3E 0x0B43} {0x0B47 0x0B48} {0x0B4B 0x0B4D} {0x0B56 0x0B57} {0x0B82 0x0B83} {0x0BBE 0x0BC2} {0x0BC6 0x0BC8} {0x0BCA 0x0BCD} 0x0BD7 {0x0C01 0x0C03} {0x0C3E 0x0C44} {0x0C46 0x0C48} {0x0C4A 0x0C4D} {0x0C55 0x0C56} {0x0C82 0x0C83} {0x0CBE 0x0CC4} {0x0CC6 0x0CC8} {0x0CCA 0x0CCD} {0x0CD5 0x0CD6} {0x0D02 0x0D03} {0x0D3E 0x0D43} {0x0D46 0x0D48} {0x0D4A 0x0D4D} 0x0D57 0x0E31 {0x0E34 0x0E3A} {0x0E47 0x0E4E} 0x0EB1 {0x0EB4 0x0EB9} {0x0EBB 0x0EBC} {0x0EC8 0x0ECD} {0x0F18 0x0F19} 0x0F35 0x0F37 0x0F39 0x0F3E 0x0F3F {0x0F71 0x0F84} {0x0F86 0x0F8B} {0x0F90 0x0F95} 0x0F97 {0x0F99 0x0FAD} {0x0FB1 0x0FB7} 0x0FB9 {0x20D0 0x20DC} 0x20E1 {0x302A 0x302F} 0x3099 0x309A } set Digit { {0x0030 0x0039} {0x0660 0x0669} {0x06F0 0x06F9} {0x0966 0x096F} {0x09E6 0x09EF} {0x0A66 0x0A6F} {0x0AE6 0x0AEF} {0x0B66 0x0B6F} {0x0BE7 0x0BEF} {0x0C66 0x0C6F} {0x0CE6 0x0CEF} {0x0D66 0x0D6F} {0x0E50 0x0E59} {0x0ED0 0x0ED9} {0x0F20 0x0F29} } set Extender { 0x00B7 0x02D0 0x02D1 0x0387 0x0640 0x0E46 0x0EC6 0x3005 {0x3031 0x3035} {0x309D 0x309E} {0x30FC 0x30FE} } proc sortCmd {a b} { if {[lindex $a 0] > [lindex $b 0]} { return 1 } else { return -1 } } # if {$tcl_version < 8.4} { # set nameStartChars [lsort -command sortCmd \ # [concat $BaseChar $Ideographic 0x005F 0x003A]] # } else { # set nameStartChars [lsort -integer -index 0 \ # [concat $BaseChar $Ideographic 0x005F 0x003A]] # } set nameStartChars [lsort -command sortCmd \ [concat $BaseChar $Ideographic 0x005F 0x003A]] # Append stop char needed by the test code to work properly. lappend nameStartChars 0x10000 test dom-3.8 {isName} {longRunning} { set ind 0 set nr 0 while {$nr < 65536} { set range [lindex $nameStartChars $ind] incr ind if {[llength $range] == 2} { foreach {min max} $range break } else { set min $range set max $range } while {$nr < $min} { if {[dom isName [subst \\u[format "%04x" $nr]]] != 0} { error "wrong 'isName' result for name start char #x[format "%04x" $nr] - should be illegal" } incr nr } if {$nr == 0x10000} {break} while {$nr <= $max} { if {[dom isName [subst \\u[format "%04x" $nr]]] != 1} { error "wrong 'isName' result for name start char #x[format "%04x" $nr] - should be legal" } incr nr } } set nr } {65536} set nameChars [lsort -command sortCmd \ [concat $BaseChar $Ideographic $Digit 0x002E 0x002D 0x005F 0x003A \ $CombiningChar $Extender]] # Append stop char needed by the test code to work properly. lappend nameChars 0x10000 test dom-3.9 {isName} { set ind 0 set nr 0 while {$nr < 65536} { set range [lindex $nameChars $ind] incr ind if {[llength $range] == 2} { foreach {min max} $range break } else { set min $range set max $range } while {$nr < $min} { if {[dom isName a[subst \\u[format "%04x" $nr]]] != 0} { error "wrong 'isName' result for name char #x[format "%04x" $nr] - should be illegal" } incr nr } if {$nr == 0x10000} {break} while {$nr <= $max} { if {[dom isName a[subst \\u[format "%04x" $nr]]] != 1} { error "wrong 'isName' result for name char #x[format "%04x" $nr] - should be legal" } incr nr } } set nr } {65536} test dom-3.10 {isNCName} { dom isNCName ":foo" } {0} test dom-3.11 {isNCName} { dom isNCName "_foo" } {1} test dom-3.12 {isNCName} { dom isNCName "foo:bar:baz" } {0} test dom-3.13 {isNCName} { dom isNCName "-foo" } {0} test dom-3.14 {isNCName} { dom isNCName ".foo" } {0} test dom-3.15 {isNCName} { catch {dom isNCName} } {1} test dom-3.16 {isNCName} { catch {dom isNCName foo bar} } {1} test dom-3.17 {isQName} { dom isQName ":foo" } {0} test dom-3.18 {isQName} { dom isQName "_foo" } {1} test dom-3.19 {isQName} { dom isQName "foo:bar:baz" } {0} test dom-3.20 {isQName} { dom isQName "-foo" } {0} test dom-3.21 {isQName} { dom isQName ".foo" } {0} test dom-3.22 {isQName} { dom isQName "foo:bar" } {1} test dom-3.23 {isQName} { catch {dom isQName} } {1} test dom-3.24 {isQName} { catch {dom isQName foo bar} } {1} test dom-3.25 {isQName} { dom isQName "foo bar" } {0} test dom-3.26 {isQName} { dom isQName "woozbiz:" } {0} test dom-3.26.1 {isQName} { dom isQName foo:1 } {0} test dom-3.26.2 {isQName} { dom isQName 1:foo } {0} set XMLChars { 0x9 0xA 0xD {0x20 0xD7FF} {0xE000 0xFFFD} {0x10000 0x10FFFF} } test dom-3.27 {isCharData} {longRunning} { set ind 0 set nr 1 while {$nr < 65536} { set range [lindex $XMLChars $ind] incr ind if {[llength $range] == 2} { foreach {min max} $range break } else { set min $range set max $range } while {$nr < $min} { if {[dom isCharData "a[subst \\u[format "%04x" $nr]]b"] != 0} { error "wrong 'isCharData' result for char #x[format "%04x" $nr] - should be illegal" } incr nr } if {$nr == 0x10000} {break} while {$nr <= $max} { if {[dom isCharData "a[subst \\u[format "%04x" $nr]]b"] != 1} { error "wrong 'isCharData' result for char #x[format "%04x" $nr] - should be legal" } incr nr } } set nr } {65536} test dom-3.28 {isPIName} { dom isPIName "target" } {1} test dom-3.29 {isPIName} { dom isPIName "foo:target" } {1} test dom-3.30 {isPIName} { dom isPIName "Xml" } {0} test dom-3.31 {isComment} { dom isComment "some comment" } {1} test dom-3.32 {isComment} { dom isComment "some invalid -- comment" } {0} test dom-3.33 {isComment} { dom isComment "some invalid comment-" } {0} test dom-3.34 {isCDATA} { dom isCDATA "some ]] CDATA " } {1} test dom-3.35 {isCDATA} { dom isCDATA "some ]]> CDATA " } {0} test dom-3.36 {isCDATA} { dom isCDATA "invalid: ]]>" } {0} test dom-3.37 {isCDATA} { dom isCDATA "valid: ]]> " } {0} test dom-3.38 {isCDATA} { dom isCDATA "\ud7fa\ud7fb\ud7fc\ud7fd\ud7fe\ud7ff]]>" } {0} test dom-3.39 {isPIValue} { dom isPIValue "some processing instruction data" } {1} test dom-3.40 {isPIValue} { dom isPIValue "some invalid ?> processing instruction data" } {0} test dom-3.41 {isPIValue} { dom isPIValue "some invalid processing instruction data?>" } {0} test dom-3.43 {clearString} { set result [list] foreach str { \u0001 a\u0002 \u0003b a\u0004b a\u0004\u0005b a\u0004c\u0005b a\u0004d\u0005\u0006b a\u0004d\u0005\uD800\uD801\uD802_foo_bar \uD800\uD801\uD802_foo_bar_baz\uD802_didum\uDFFF \uD800\uD801\uD802_foo_bar_baz\uD802_didum\uE000 \u0004\u0005\uDABC abc } { lappend result [dom clearString $str] } set result } [list {} a b ab ab acb adb ad_foo_bar _foo_bar_baz_didum _foo_bar_baz_didum\uE000 {} abc] test dom-3.44 {clearString -replace} { set result [list] foreach str { \u0001 a\u0002 \u0003b a\u0004b a\u0004\u0005b a\u0004c\u0005b a\u0004d\u0005\u0006b a\u0004d\u0005\uD800\uD801\uD802_foo_bar \uD800\uD801\uD802_foo_bar_baz\uD802_didum\uDFFF \uD800\uD801\uD802_foo_bar_baz\uD802_didum\uE000 \u0004\u0005\uDABC abc \u0004\u0005\u0001 } { lappend result [dom clearString -replace $str] } set result } [list \ufffd a\ufffd \ufffdb a\ufffdb a\ufffd\ufffdb a\ufffdc\ufffdb a\ufffdd\ufffd\ufffdb a\ufffdd\ufffd\ufffd\ufffd\ufffd_foo_bar \ufffd\ufffd\ufffd_foo_bar_baz\ufffd_didum\ufffd \ufffd\ufffd\ufffd_foo_bar_baz\ufffd_didum\uE000 \ufffd\ufffd\ufffd abc \ufffd\ufffd\ufffd] test dom-3.45 {clearString -replace with replacement} { set result [list] foreach str { \u0001 a\u0002 \u0003b a\u0004b a\u0004\u0005b a\u0004c\u0005b a\u0004d\u0005\u0006b a\u0004d\u0005\uD800\uD801\uD802_foo_bar \uD800\uD801\uD802_foo_bar_baz\uD802_didum\uDFFF \uD800\uD801\uD802_foo_bar_baz\uD802_didum\uE000 \u0004\u0005\uDABC abc \u0004\u0005\u0001 } { lappend result [dom clearString -replace some $str] } set result } [list some asome someb asomeb asomesomeb asomecsomeb asomedsomesomeb asomedsomesomesomesome_foo_bar somesomesome_foo_bar_bazsome_didumsome somesomesome_foo_bar_bazsome_didum\uE000 somesomesome abc somesomesome] test dom-3.46 {isHTML5CustomName} { set result [list] foreach str { abc ab-c ab-C -ab \u00E4b-c ab---c ab- ab-\u1d28 a\u00C4-b aA-b a\u00E4-b 0n-foo A-b font-face m\u00B7-. n-\uFDF0 o-\u3000 } { lappend result [dom isHTML5CustomName $str] } set result } {0 1 0 0 0 1 1 1 1 0 1 0 0 0 1 1 0} test dom-4.1 {-useForeignDTD 0} { set doc [dom parse -useForeignDTD 0 {}] $doc delete } {} test dom-4.2 {-useForeignDTD 1 with document with internal subset} {need_uri} { set baseURI [tdom::baseURL [file join [pwd] [file dir [info script]] dom.test]] set ::tdom::useForeignDTD "data/domCmd1.dtd" set doc [dom parse \ -useForeignDTD 1 \ -baseurl $baseURI \ -externalentitycommand ::tdom::extRefHandler { ]> }] set root [$doc documentElement] set result [$root @fixed] $doc delete set result } {toThat} test dom-4.3 {-useForeignDTD 1 with document with internal subset} {need_uri} { set baseURI [tdom::baseURL [file join [pwd] [file dir [info script]] dom.test]] set ::tdom::useForeignDTD "data/domCmd1.dtd" set doc [dom parse \ -useForeignDTD 1 \ -baseurl $baseURI \ -externalentitycommand ::tdom::extRefHandler { ]> }] set root [$doc documentElement] set result [$root @fixed] lappend result [$root @fixed2] $doc delete set result } {toThis toThat} test dom-4.4 {-useForeignDTD 1 with document without document declaration} {need_uri} { set baseURI [tdom::baseURL [file join [pwd] [file dir [info script]] dom.test]] set ::tdom::useForeignDTD "data/domCmd1.dtd" set doc [dom parse \ -useForeignDTD 1 \ -baseurl $baseURI \ -externalentitycommand ::tdom::extRefHandler ] set root [$doc documentElement] set result [$root @fixed] $doc delete set result } {toThis} test dom-4.5 {-useForeignDTD 1 does not overwrite a given external subset} {need_uri} { set baseURI [tdom::baseURL [file join [pwd] [file dir [info script]] dom.test]] set ::tdom::useForeignDTD "data/domCmd1.dtd" set doc [dom parse \ -useForeignDTD 1 \ -baseurl $baseURI \ -externalentitycommand ::tdom::extRefHandler { }] set root [$doc documentElement] set result [$root @fixed] $doc delete set result } {toThat} test dom-4.6 {-useForeignDTD with nonboolean arg} {need_uri} { set result [catch {set doc [dom parse -useForeignDTD foo ]} errMsg] lappend result $errMsg } {1 {expected boolean value but got "foo"}} test dom-5.1 {document with external subset} {need_uri} { set baseURI [tdom::baseURL [file join [pwd] [file dir [info script]] dom.test]] set doc [dom parse \ -baseurl $baseURI \ -externalentitycommand ::tdom::extRefHandler { }] set root [$doc documentElement] set result [$root @fixed] $doc delete set result } {toThat} proc dom-5.2 {myparm base systemId publicId} { set ::dom-5_2 $myparm return [list string dummy ""] } test dom-5.2 {-externalentitycommand} { set ::dom-5_2 "" set doc [dom parse \ -baseurl "dummy" \ -externalentitycommand [list dom-5.2 thisDoc] { }] $doc delete set ::dom-5_2 } {thisDoc} proc dom-5.3 {base systemId publicId} { switch $publicId { "e1" { # Not well-formed set data "" } default { error "unknown public ID" } } return [list "string" $base $data] } test dom-5.3 {-externalentitycommand - nested external entities} -body { set result [catch { dom parse -externalentitycommand dom-5.3 \ { ]> &e1;} } msg] list $result $msg } -result [list 1 {error "not well-formed (invalid token)" in entity "e1.xml" at line 1 character 2 "", referenced at line 4 character 21}] proc dom-5.4 {base systemId publicId} { switch $publicId { "e1" { set data "&e2;" } "e2" { set data "" } default { error "unknown public ID" } } return [list "string" $base $data] } test dom-5.4 {-externalentitycommand - nested external entities} -body { set result [catch { dom parse -externalentitycommand dom-5.4 \ { ]> &e1;} } msg] list $result $msg } -result [list 1 {error "not well-formed (invalid token)" in entity "e2.xml" at line 1 character 2 "", referenced in entity "e1.xml" at line 1 character 4, referenced at line 5 character 21}] proc dom-5.5 {base systemId publicId} { switch $publicId { "e1" { set data "&e2;" } "e2" { set data "&e3;" } "e3" { # Not well-formed set data "" } default { error "unknown public ID" } } return [list "string" $base $data] } test dom-5.5 {-externalentitycommand - nested external entities} -body { set result [catch { dom parse -externalentitycommand dom-5.5 \ { ]> &e1;} } msg] list $result $msg } -result [list 1 {error "not well-formed (invalid token)" in entity "e3.xml" at line 1 character 2 "", referenced in entity "e2.xml" at line 1 character 4, referenced in entity "e1.xml" at line 1 character 4, referenced at line 6 character 21}] proc dom-5.6 {base systemId publicId} { switch $publicId { "e1" { set data [open $::e1] } default { error "unknown public ID" } } lappend ::openChannels $data return [list "channel" $base $data] } test dom-5.6 {-externalentitycommand - nested external entities} -setup { set e1 [makeFile "" e1.xml] set openChannels [list] } -body { set result [catch { dom parse -externalentitycommand dom-5.6 \ { ]> &e1;} } msg] list $result $msg } -cleanup { foreach channel $openChannels {close $channel} removeFile e1.xml } -result [list 1 {error "not well-formed (invalid token)" in entity "e1.xml" at line 1 character 2, referenced at line 4 character 21}] proc dom-5.7 {base systemId publicId} { switch $publicId { "e1" { set data [open $::e1] } "e2" { set data [open $::e2] } default { error "unknown public ID" } } lappend ::openChannels $data return [list "channel" $base $data] } test dom-5.7 {-externalentitycommand - nested external entities} -setup { set e1 [makeFile "&e2;" e1.xml] set e2 [makeFile "" e2.xml] set openChannels [list] } -body { set result [catch { dom parse -externalentitycommand dom-5.7 \ { ]> &e1;} } msg] list $result $msg } -cleanup { foreach channel $openChannels {close $channel} removeFile e1.xml removeFile e2.xml } -result [list 1 {error "not well-formed (invalid token)" in entity "e2.xml" at line 1 character 2, referenced in entity "e1.xml" at line 1 character 4, referenced at line 5 character 21}] proc dom-5.8 {base systemId publicId} { switch $publicId { "e1" { set data [open $::e1] } "e2" { set data [open $::e2] } "e3" { set data [open $::e3] } default { error "unknown public ID" } } lappend ::openChannels $data return [list "channel" $base $data] } test dom-5.8 {-externalentitycommand - nested external entities} -setup { set e1 [makeFile "&e2;" e1.xml] set e2 [makeFile "&e3;" e2.xml] set e3 [makeFile "" e3.xml] set openChannels [list] } -body { set result [catch { dom parse -externalentitycommand dom-5.8 \ { ]> &e1;} } msg] list $result $msg } -cleanup { foreach channel $openChannels {close $channel} removeFile e1.xml removeFile e2.xml removeFile e3.xml } -result [list 1 {error "not well-formed (invalid token)" in entity "e3.xml" at line 1 character 2, referenced in entity "e2.xml" at line 1 character 4, referenced in entity "e1.xml" at line 1 character 4, referenced at line 6 character 21}] test dom-5.9 {Wrong option after -externalentitycommand} -body { set result [catch {dom parse -externalentitycommand ::tdom::extRefHandler \ -useForeignDTD foo}] } -result 1 proc dom-5.9 {args} { return [list string "" {text12more text}] } test dom-5.9 {-externalentitycommand - external entity is a forest} { set doc [dom parse -externalentitycommand dom-5.9 \ {]> &e1;}] set result [$doc asXML -indent none] $doc delete set result } {text12more text} test dom-6.1 {use in slave interpreter} { set slave [interp create] load {} Tdom $slave interp eval $slave { dom parse foo doc $doc documentElement root } interp delete $slave } {} test dom-6.2 {use in slave interpreter} { set slave [interp create] load {} Tdom $slave interp eval $slave { set doc [dom parse foo] set root [$doc documentElement] } interp delete $slave } {} test dom-7.1 {setNameCheck} { set result [dom setNameCheck] lappend result [dom setNameCheck 0] lappend result [dom setNameCheck] # set back to default lappend result [dom setNameCheck 1] set result } {1 0 0 1} set doc [dom createDocument root] # ensure, we've the default dom setNameCheck 1 test dom-7.2 {setNameCheck} { set result [catch {$doc createElement "invalid name"} errMsg] lappend result $errMsg } {1 {Invalid tag name 'invalid name'}} test dom-7.3 {setNameCheck} { catch {$doc createElement "valid:name"} } {0} test dom-7.4 {setNameCheck} { catch {$doc createElement "valid::name"} } {0} test dom-7.5 {setNameCheck} { dom setNameCheck 0 set result [catch {$doc createElement "invalid name"} errMsg] # set back to default dom setNameCheck 1 set result } {0} test dom-7.6 {setNameCheck} { set result [catch {$doc createElementNS "dummyns" "invalid name"} errMsg] lappend result $errMsg } {1 {Invalid full qualified tag name 'invalid name'}} test dom-7.7 {setNameCheck} { catch {$doc createElementNS "dummyns" "valid:name"} } {0} test dom-7.8 {setNameCheck} { set result [catch {$doc createElementNS "dummyns" "invalid::name"} errMsg] lappend result $errMsg } {1 {Invalid full qualified tag name 'invalid::name'}} test dom-7.9 {setNameCheck} { dom setNameCheck 0 set result [catch {$doc createElementNS "dummyns" "invalid name"} errMsg] # set back to default dom setNameCheck 1 set result } {0} test dom-7.10 {setTextCheck} { set result [catch {$doc createComment "valid comment"}] lappend result [catch {$doc createComment "invalid -- comment"}] dom setTextCheck 0 lappend result [catch {$doc createComment "invalid -- comment"}] dom setTextCheck 1 set result } {0 1 0} test dom-7.11 {setTextCheck} { set result [catch {$doc createCDATASection ""}] lappend result [catch {$doc createCDATASection "]]>]]>foo\u0003bar" test dom-7.19 {setTextCheck and appendFromScript - setTextCheck state at create time is crucial} { set doc [dom createDocumentNode] namespace eval nodeCmds { dom createNodeCmd elementNode doc dom createNodeCmd textNode t } dom setTextCheck 0 set result [catch {$doc appendFromScript { nodeCmds::doc { nodeCmds::t "foo\u0003bar" } }} errMsg] dom setTextCheck 1 $doc delete lappend result $errMsg } [list 1 "Invalid text value 'foo\u0003bar'"] test dom-7.19 {setNameCheck / createDocument} { dom setNameCheck 0 dom createDocument "foo bar" doc set result [$doc asXML -indent none] $doc delete dom setNameCheck 1 set result } {} test dom-7.20 {set*Check, setStoreLineColumn and setObjectCommands in child interp} { set storedNameCheck [dom setNameCheck] set storedTextCheck [dom setTextCheck] set storedLineColumn [dom setStoreLineColumn] set storedObjectCommands [dom setObjectCommands] dom setNameCheck 1 dom setTextCheck 1 dom setStoreLineColumn 0 dom setObjectCommands command interp create childinterp load {} Tdom childinterp childinterp eval { dom setNameCheck 0 dom setTextCheck 0 dom setStoreLineColumn 1 } set nrCommands [llength [info commands]] set doc [dom parse {some}] set result [expr {[llength [info commands]] - $nrCommands}] lappend result [catch {$doc createElement "foo bar" node}] lappend result [catch {$doc createTextNode "a\u0001z" textnode}] lappend result [catch {[$doc documentElement] getLine}] lappend result [catch {[$doc documentElement] getColumn}] if {[catch {$doc delete}]} { domDoc $doc delete } childinterp eval { dom setObjectCommands token } dom setNameCheck $storedNameCheck dom setTextCheck $storedTextCheck dom setStoreLineColumn $storedLineColumn dom setObjectCommands $storedObjectCommands lappend result {*}[childinterp eval { set nrCommands [llength [info commands]] set doc [dom parse {some}] set result [expr {[llength [info commands]] - $nrCommands}] lappend result [catch {domDoc $doc createElement "foo bar" node}] lappend result [catch {domDoc $doc createTextNode "a\u0001z" textnode}] lappend result [catch {domNode [domDoc $doc documentElement] getLine}] lappend result [catch {domNode [domDoc $doc documentElement] getColumn}] domDoc $doc delete set result }] interp delete childinterp set result } {1 1 1 1 1 0 0 0 0 0} test dom-8.1 {createDocumentNode} { set result [catch {dom createDocumentNode foo bar}] } {1} test dom-8.2 {createDocumentNode} { set docNode [dom createDocumentNode] set result [$docNode asXML -indent none] $docNode delete set result } {} test dom-8.3 {createDocumentNode} { dom createDocumentNode docNode set result [$docNode asXML -indent none] $docNode delete set result } {} test dom-8.4 {createDocumentNode} { set docNode [dom createDocumentNode] set result [$docNode nodeType] lappend result [$docNode documentElement] $docNode delete set result } {DOCUMENT_NODE {}} test dom-8.5 {createDocumentNode} { set docNode [dom createDocumentNode] set newNode [$docNode createComment "Comment before the document node"] $docNode appendChild $newNode set result [[$docNode documentElement] nodeType] set newNode [$docNode createElement firstChild] $docNode appendChild $newNode lappend result [[$docNode documentElement] nodeName] set newNode [$docNode createElement secondChild] $docNode appendChild $newNode lappend result [[$docNode documentElement] nodeName] $docNode delete set result } {COMMENT_NODE firstChild firstChild} test dom-8.6 {createDocumentNode} { set docNode [dom createDocumentNode] set doc [dom parse {some text}] set root [$doc documentElement] set listRep [$root asList] $doc delete $docNode appendFromList $listRep set result [$docNode asXML -indent none] $docNode delete set result } {some text} test dom-8.7 {createDocumentNode} { dom createDocumentNode docNode dom createDocumentNode docNode $docNode delete set result "" } "" test dom-8.8 {createDocumentNode} { dom createDocumentNode -jsonType ARRAY docNode set result [$docNode jsonType] $docNode delete set result } ARRAY test dom-8.9 {createDocumentNode} { set docNode [dom createDocumentNode -jsonType NUMBER] set result [$docNode jsonType] $docNode delete set result } NUMBER test dom-8.10 {createDocumentNode} { catch {dom createDocumentNode -foo NULL docNode} errMsg set errMsg } {bad option "-foo": must be -jsonType} test dom-8.10 {createDocumentNode} { catch {dom createDocumentNode -foo NULL docNode} errMsg set errMsg } {bad option "-foo": must be -jsonType} test dom-8.11 {createDocumentNode} { catch {dom createDocumentNode -jsonType FOO docNode} errMsg set errMsg } {bad jsonType "FOO": must be NONE, ARRAY, OBJECT, NULL, TRUE, FALSE, STRING, or NUMBER} test dom-8.12 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set result [$docNode documentElement] $docNode delete set result } {} test dom-8.13 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set result [$docNode getElementsByTagName foo] $docNode delete set result } {} test dom-8.14 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set result [$docNode getElementsByTagNameNS http://bar.org foo] $docNode delete set result } {} test dom-8.15 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set newElement [$docNode createElement child] set result [$newElement asXML -indent none] $docNode delete set result } {} test dom-8.16 {createDocumentNode - method check} { set docNode [dom createDocumentNode] $docNode delete } {} test dom-8.17 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set node [$docNode createCDATASection ""] set result [$node asXML -indent none] $docNode delete set result } {]]>} test dom-8.18 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set node [$docNode createTextNode "a&b"] set result [$node asXML -indent none] $docNode delete set result } {a&b} test dom-8.19 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set node [$docNode createComment "some comment"] set result [$node asXML -indent none] $docNode delete set result } {} test dom-8.20 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set node [$docNode createProcessingInstruction foo bar] set result [$node asXML -indent none] $docNode delete set result } {} test dom-8.21 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set node [$docNode createElementNS http://foo.org p:bar] $docNode appendChild $node set result [$docNode asXML -indent none] $docNode delete set result } {} test dom-8.22 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set result [$docNode getDefaultOutputMethod] $docNode delete set result } {xml} test dom-8.23 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set result [$docNode asXML -indent none] $docNode delete set result } {} test dom-8.24 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set result [$docNode asHTML] $docNode delete set result } {} test dom-8.25 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set identityTransformation [dom parse { }] set resultdoc [$docNode xslt $identityTransformation] set result [$resultdoc asXML -indent none] $resultdoc delete $identityTransformation delete $docNode delete set result } {} test dom-8.26 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set result "" lappend result [$docNode publicId] $docNode publicId data lappend result [$docNode publicId] $docNode delete set result } {{} data} test dom-8.27 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set result "" lappend result [$docNode systemId] $docNode systemId data lappend result [$docNode systemId] $docNode delete set result } {{} data} test dom-8.28 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set result "" lappend result [$docNode internalSubset] $docNode internalSubset data lappend result [$docNode internalSubset] $docNode delete set result } {{} data} test dom-8.29 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set result [catch {$docNode toXSLTcmd}] $docNode delete set result } {1} test dom-8.30 {createDocumentNode - method check} { set docNode [dom createDocumentNode] set result [$docNode asText] $docNode delete set result } {} test dom-8.31 {createDocumentNode - method check} { set docNode [dom createDocumentNode] $docNode normalize set result [$docNode asXML -indent none] $docNode delete set result } {} test dom-9.1 {setObjectCommands} { dom setObjectCommands } {automatic} test dom-9.2 {setObjectCommands} { dom setObjectCommands automatic } {automatic} test dom-9.3 {setObjectCommands} { set result [catch {dom setObjectCommands foobar} errMsg] lappend result $errMsg } {1 {bad mode value "foobar": must be automatic, command, or token}} test dom-9.4 {setObjectCommands} { set nrOfCmds [llength [info commands]] dom setObjectCommands automatic set docNode [dom createDocumentNode] set result [expr {$nrOfCmds + 1 == [llength [info commands]]}] $docNode delete lappend result [expr {$nrOfCmds == [llength [info commands]]}] dom setObjectCommands token set docNode [dom createDocumentNode] lappend result [expr {$nrOfCmds == [llength [info commands]]}] lappend result [domDoc $docNode hasChildNodes] domDoc $docNode delete lappend result [expr {$nrOfCmds == [llength [info commands]]}] # switch back to default dom setObjectCommands automatic set result } {1 1 1 0 1} test dom-9.5 {setObjectCommands} { dom setObjectCommands token set nrOfCmds [llength [info commands]] set doc [dom parse ] set root [domDoc $doc documentElement] set result [expr {$nrOfCmds == [llength [info commands]]}] dom setObjectCommands command set docCmd [domNode $root ownerDocument] lappend result [expr {$nrOfCmds + 1 == [llength [info commands]]}] $docCmd delete dom setObjectCommands automatic set result } {1 1} test dom-9.6 {node token with result var argument} { dom setObjectCommands token set doc [dom parse ] domDoc $doc documentElement var domNode $var firstChild var domNode $var nextSibling var domDoc $doc delete dom setObjectCommands automatic } {automatic} catch {namespace delete nodeCmds} namespace eval nodeCmds { dom createNodeCmd elementNode e1 dom createNodeCmd elementNode e2 dom createNodeCmd commentNode c dom createNodeCmd textNode t dom createNodeCmd cdataNode cdata dom createNodeCmd piNode pi dom createNodeCmd parserNode parser dom createNodeCmd -tagName foo elementNode bar } test dom-10.1 {createNodeCmd} { llength [info commands nodeCmds::*] } {8} namespace eval nodeCmds { rename e1 {} rename e2 {} rename c {} rename t {} rename cdata {} rename pi {} rename parser {} rename bar {} } test dom-10.2 {createNodeCmd} { llength [info commands nodeCmds::*] } {0} namespace eval nodeCmds { dom createNodeCmd elementNode e1 dom createNodeCmd textNode t } test dom-10.3 {node creating command called outside domNode context} { set result [catch {nodeCmds::t "some text"} errMsg] lappend result $errMsg } {1 {called outside domNode context}} test dom-10.4 {node creating command called outside domNode context} { dom createDocument docRoot doc $doc documentElement root $root appendFromScript { nodeCmds::t "Some text" } set result [list [$doc asXML -indent none]] $doc delete lappend result [catch {nodeCmds::t "Some text"} errMsg] lappend result $errMsg } {{Some text} 1 {called outside domNode context}} test dom-10.5 {node creating command called outside domNode context} { dom createDocument docRoot doc $doc documentElement root $root appendFromScript { nodeCmds::e1 { nodeCmds::t "Some text" } } set result [list [$doc asXML -indent none]] $doc delete lappend result [catch { nodeCmds::e1 { nodeCmds::t "Some text" }} errMsg] lappend result $errMsg } {{Some text} 1 {called outside domNode context}} namespace eval nodeCmds { dom createNodeCmd -tagName foo elementNode bar } test dom-10.6 {createNodeCmd - option -tagName} { set doc [dom createDocumentNode] $doc appendFromScript { nodeCmds::bar {} } set result [$doc asXML -indent none] $doc delete set result } {} namespace delete nodeCmds test dom-11.1 {featureinfo - expatversion} -body { dom featureinfo expatversion } -match regexp -result {expat_.*} test dom-11.2 {featureinfo - invalid arg} -body { catch {dom featureinfo foo} errMsg } -result 1 test dom-11.3 {featureinfo - expatmajorversion} -body { dom featureinfo expatmajorversion } -match regexp -result {(1|2)} test dom-11.4 {featureinfo - dtd} -body { dom featureinfo dtd } -match regexp -result {(0|1)} test dom-11.5 {featureinfo - jsonmaxnesting} { dom featureinfo jsonmaxnesting } 2000 test dom-11.6 {featureinfo - versionhash} { regexp {^[0-9a-fA-F]+$} [dom featureinfo versionhash] } 1 proc ::dom::domParseFeedback {} { return -code break } test dom-12.1 {-feedbackAfter -- cmd returns TCL_BREAK} -body { dom parse -feedbackAfter 1 {} } -result "" proc ::dom::domParseFeedback {} { error "Error in feedback cmd." } test dom-12.2 {-feedbackAfter -- cmd returns TCL_ERROR} -body { set result [catch { dom parse -feedbackAfter 1 {} } msg] list $result $msg } -result [list 1 "Error in feedback cmd."] proc ::dom::domParseFeedback {} { # Update progess dialog, check for cancel etc. return } test dom-12.3 {-feedbackAfter} -body { set doc [dom parse -feedbackAfter 1 {}] $doc selectNodes count(//*) } -result 4 test dom-12.4 {-feedbackAfter and -channel} -setup { set xmlFile [makeFile {} dom.xml] } -body { set fd [open $xmlFile] set doc [dom parse -channel $fd -feedbackAfter 1] close $fd $doc selectNodes count(//*) } -cleanup { removeFile dom.xml } -result 4 proc extRefResolver-12.5 {base systemId publicId} { switch $publicId { "a" { set data "" } "b" { set data "" } default { error "unknown public ID" } } return [list "string" $base $data] } test dom-12.5 {-feedbackAfter and external entities} -body { set doc [dom parse -externalentitycommand extRefResolver-12.5 \ -feedbackAfter 1 { ]> &a;&b;}] $doc selectNodes count(//*) } -result 4 set cancel 0 proc extRefResolver-12.6 {base systemId publicId} { global cancel switch $publicId { "a" { set cancel 1 set data "" } "b" { set data "" } default { error "unknown public ID" } } return [list "string" $base $data] } proc ::dom::domParseFeedback {} { global cancel if {$cancel} { return -code break } } test dom-12.6 {-feedbackAfter and external entities, with cancel} -body { dom parse -externalentitycommand extRefResolver-12.6 \ -feedbackAfter 1 { ]> &a;&b;} } -result "" proc ::dom::domParseFeedback {} { global cancel if {$cancel} { error "Error in feedback cmd." } } test dom-12.7 {-feedbackAfter and external entities, with error} -body { set result [catch {dom parse -externalentitycommand extRefResolver-12.6 \ -feedbackAfter 1 { ]> &a;&b;}} msg] list $result $msg } -result [list 1 "Error in feedback cmd."] test dom-12.8 {-feedbackAfter without -feedbackcmd} -setup { catch {rename ::dom::domParseFeedback ""} } -body { set result [catch {dom parse -feedbackAfter 100 } msg] list $result $msg } -result {1 {If -feedbackAfter is used, -feedbackcmd must also be used.}} proc feedbackcmd-12.9 {} { return -code break } test dom-12.9 {-feedbackAfter with -feedbackcmd -- cmd returns TCL_BREAK} -body { dom parse -feedbackAfter 1 -feedbackcmd feedbackcmd-12.9 \ {} } -result "" proc feedbackcmd-12.10 {} { error "Error in feedback cmd." } test dom-12.10 {-feedbackAfter with -feedbackcmd -- cmd returns TCL_ERROR} -body { set result [catch { dom parse -feedbackAfter 1 -feedbackcmd feedbackcmd-12.10 \ {} } msg] list $result $msg } -result [list 1 "Error in feedback cmd."] proc feedbackcmd-12.11 {} { # Update progess dialog, check for cancel etc. return } test dom-12.11 {-feedbackAfter with -feedbackcmd} -body { set doc [dom parse -feedbackAfter 1 -feedbackcmd feedbackcmd-12.11 \ {}] $doc selectNodes count(//*) } -result 4 test dom-12.12 {-feedbackAfter with -feedbackcmd and -channel} -setup { set xmlFile [makeFile {} dom.xml] } -body { set fd [open $xmlFile] set doc [dom parse -channel $fd -feedbackAfter 1 \ -feedbackcmd feedbackcmd-12.11] close $fd $doc selectNodes count(//*) } -cleanup { removeFile dom.xml } -result 4 test dom-12.13 {-feedbackAfter with -feedbackcmd and external entities} -body { set doc [dom parse -externalentitycommand extRefResolver-12.5 \ -feedbackcmd feedbackcmd-12.11 \ -feedbackAfter 1 { ]> &a;&b;}] $doc selectNodes count(//*) } -result 4 set cancel 0 proc feedbackcmd-12.14 {} { global cancel if {$cancel} { return -code break } } test dom-12.14 {-feedbackAfter with -feedbackcmd and external entities, with cancel} -body { dom parse -externalentitycommand extRefResolver-12.6 \ -feedbackcmd feedbackcmd-12.14 \ -feedbackAfter 1 { ]> &a;&b;} } -result "" set cancel 0 proc feedbackcmd-12.15 {} { global cancel if {$cancel} { error "Error in feedback cmd." } } test dom-12.15 {-feedbackAfter with -feedbackcmd and external entities, with error} -body { set result [catch {dom parse -externalentitycommand extRefResolver-12.6 \ -feedbackcmd feedbackcmd-12.15 \ -feedbackAfter 1 { ]> &a;&b;}} msg] list $result $msg } -result [list 1 "Error in feedback cmd."] proc feedbackcmd-12.16 {} { incr ::feedbackcmd-12.16 } test dom-12.16 {-feedbackcmd setting interp result w/ invalid XML} -body { set ::feedbackcmd-12.16 0 set result [catch {dom parse -feedbackcmd feedbackcmd-12.16 \ -feedbackAfter 1 {< <--Error-- /doc"}] test dom-13.1 {-forest} -body { dom parse -forest {12} doc set result [$doc asXML -indent none] $doc delete set result } -result {12} test dom-13.2 {-forest} -body { catch {dom parse -forest {12}} } -result {1} test dom-13.3 {-forest} -body { dom parse -forest {12some text} doc set result [$doc asXML -indent none] $doc delete set result } -result {12some text} test dom-13.4 {-forest -channel} -setup { set xmlfile [makeFile {12} dom.xml] } -body { set fd [open $xmlfile] set doc [dom parse -channel $fd -forest] close $fd set result [$doc asXML -indent none] $doc delete set result } -cleanup { removeFile dom.xml } -result {12} test dom-13.5 {-forest -channel} -setup { set xmlfile [makeFile {12} dom.xml] } -body { set fd [open $xmlfile] set result [catch {set doc [dom parse -channel $fd -forest]} errMsg] close $fd list $result $errMsg } -cleanup { removeFile dom.xml } -result {1 {error "asynchronous entity" at line 2 character 0}} test dom-13.6 {-forest -channel} -setup { # makeFile appends a newline at end set xmlfile [makeFile {12some text} dom.xml] } -body { set fd [open $xmlfile] set doc [dom parse -channel $fd -forest] close $fd set result [$doc asXML -indent none] $doc delete set result } -cleanup { removeFile dom.xml } -result {12some text } test dom-13.7 {-forest} -body { catch {dom parse -forest {12}} } -result {1} test dom-13.8 {-forest} { set xml {} catch {dom parse $xml} errMsg1 catch {dom parse -forest $xml} errMsg2 expr {$errMsg1 eq $errMsg2} } {1} test dom-13.9 {-forest} { catch {dom parse -forest {}} } 1 test dom-13.10 {-forest} { set xml {
    something
    something else
    } set doc [dom parse -forest $xml] set result "" foreach child [$doc selectNodes /*] { lappend result [$child parentNode] } $doc delete set result } {{} {}} test dom-14.1 {called without arguments} { set result [catch {dom} errMsg] lappend result $errMsg } {1 {wrong # args: should be "dom subcommand ?arg ...?"}} test dom-14.2 {wrong subcommand} -body { catch {dom invalid-method} errMsg set errMsg } -match glob -result {bad method "invalid-method": must be *} test dom-14.3 {Too less arguments to method parse} { catch {dom parse} errMsg set errMsg } {wrong # args: should be "parse ?options? ?data? ?objvar?"} # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/attribute.test0000644000175000017500000002121014703531020016000 0ustar rolfrolf# Features covered: Attribute Lists # # This file tests the parser's performance on Attribute Lists. # Sourcing this file into Tcl runs the tests and generates output # for errors. No output means no errors were found. # # Copyright (c) 1998-2000 Zveno Pty Ltd. # # $Id$ source [file join [file dir [info script]] loadtdom.tcl] catch {unset result} proc EStart {tagName attrList} { global result countAttributesOnly if {![llength $attrList] && !$countAttributesOnly} { if {[info exists result($tagName)]} { set count 0 while {[info exists result($tagName/[incr count])]} {} set result($tagName/$count) {} } else { set result($tagName) {} } return {} } foreach {name value} $attrList { if {[info exists result($tagName,$name)]} { set count 0 while {[info exists result($tagName,$name,[incr count])]} {} set result($tagName,$name,$count) $value } else { set result($tagName,$name) $value } } } catch {unset ::pcdata} proc pcdata t { append ::pcdata $t } test attrList-1.1 {empty attribute list} { catch {unset ::result} set ::countAttributesOnly 1 catch {rename xml::attrList-1.1 {}} set parser [xml::parser attrList-1.1 \ -elementstartcommand EStart] $parser parse { } array size result } 0 test attrList-1.2 {single attribute} { catch {unset ::result} set ::countAttributesOnly 1 catch {rename xml::attrList-1.2 {}} set parser [xml::parser attrList-1.2 \ -elementstartcommand EStart] $parser parse { } array get result } {Test,attr 1} test attrList-1.3 {multiple distinct attributes} { catch {unset ::result} set ::countAttributesOnly 1 catch {rename xml::attrList-1.3 {}} set parser [xml::parser attrList-1.3 \ -elementstartcommand EStart] $parser parse { } list [array size result] $result(Test,first) $result(Test,second) } {2 1 2} test attrList-1.4 {hyphen in attribute name} { catch {unset ::result} set ::countAttributesOnly 1 catch {rename xml::attrList-1.4 {}} set parser [xml::parser attrList-1.4 \ -elementstartcommand EStart] $parser parse { } array get result } {Test,first-attr 1} test attrList-2.1 {right angle bracket in attribute value} { catch {unset ::result} set ::countAttributesOnly 1 catch {rename xml::attrList-2.1 {}} set parser [xml::parser attrList-2.1 \ -elementstartcommand EStart] $parser parse { } array get result } {Test,attr value>} test attrList-2.2 {right angle bracket in attribute value} { catch {unset ::result} set ::countAttributesOnly 1 catch {rename xml::attrList-2.2 {}} set parser [xml::parser attrList-2.2 \ -elementstartcommand EStart] $parser parse { } array get result } {Test,attr value1>value2} test attrList-2.3 {right angle bracket in attribute value} { catch {unset ::result} set ::countAttributesOnly 1 catch {rename xml::attrList-2.3 {}} set parser [xml::parser attrList-2.3 \ -elementstartcommand EStart] $parser parse { } set r "" foreach key [lsort [array names result]] { lappend r $key $result($key) } set r } {Test,attr1 value1 Test,attr2 value2>} test attrList-2.4 {right angle bracket in attribute value} { catch {unset ::result} set ::countAttributesOnly 1 catch {rename xml::attrList-2.4 {}} set parser [xml::parser attrList-2.4 \ -elementstartcommand EStart] $parser parse { } set r "" foreach key [lsort [array names result]] { lappend r $key $result($key) } set r } {Test,attr1 value1 Test,attr2 value2>} test attrList-2.5 {right angle brackets in attribute values} { catch {unset ::result} set ::countAttributesOnly 1 catch {rename xml::attrList-2.5 {}} set parser [xml::parser attrList-2.5 \ -elementstartcommand EStart] $parser parse { } set r "" foreach key [lsort [array names result]] { lappend r $key $result($key) } set r } {Test,attr1 value>1 Test,attr2 value>2} test attrList-2.6 {right angle brackets in attribute values} { catch {unset ::result} catch {unset ::pcdata} set ::countAttributesOnly 1 catch {rename xml::attrList-2.6 {}} set parser [xml::parser attrList-2.6 \ -elementstartcommand EStart \ -characterdatacommand pcdata] $parser parse { some text } list [array get result] $::pcdata } {{Test,attr1 value>1} {some text}} test attrList-3.1 {unnested left brace in attribute value} { catch {unset ::result} set ::countAttributesOnly 1 catch {rename xml::attrList-3.1 {}} set parser [xml::parser attrList-3.1 \ -elementstartcommand EStart] $parser parse [format { } \{] array get result } [list Test,attr [format {%svalue} \{]] test attrList-3.2 {unnested right brace in attribute value} { catch {unset ::result} set ::countAttributesOnly 1 catch {rename xml::attrList-3.2 {}} set parser [xml::parser attrList-3.2 \ -elementstartcommand EStart] $parser parse [format { } \}] array get result } [list Test,attr [format {value%s} \}]] test attrList-3.3 {Tcl special characters in attribute value} { catch {unset ::result} set ::countAttributesOnly 1 catch {rename xml::attrList-3.3 {}} set parser [xml::parser attrList-3.3 \ -elementstartcommand EStart] $parser parse { } array get result } {Test,attr {dollar $ backslash \ brackets [puts hello]}} test attrList-4.1 {Unquoted attribute value} { catch {unset ::result} set ::countAttributesOnly 1 catch {rename xml::attrList-4.1 {}} set parser [xml::parser attrList-4.1 \ -elementstartcommand EStart] set retval [catch { $parser parse { }} msg] list $retval $msg } [list 1 {error "not well-formed (invalid token)" at line 3 character 11}] # Test case contributed by David Sutton test attrList-5.0 {Complicated attribute list} { catch {unset ::result} catch {unset ::pcdata} set ::countAttributesOnly 0 catch {rename xml::attrList-5.0 {}} set parser [xml::parser attrList-5.0 \ -elementstartcommand EStart \ -characterdatacommand pcdata] set retval [catch { $parser parse { LightState = LightCtl LOG(AlarmSwitch) DISABLE(BlinkLight) NOTIFY( AlarmSwitch,"Alarm has been reset") }} msg] regsub -all "\[ \t\n\]+" $::pcdata { } ::pcdata set sortedResult {} foreach key [lsort -dictionary [array names ::result]] { lappend sortedResult $key $::result($key) } list $retval $sortedResult $::pcdata } [list 0 {event,deleteOnCompletion no event,endDateTime {} event,ID 22 event,name LogAlarmReset event,startDateTime {} event,startDisabled no eventAction {} eventAction/1 {} eventAction/2 {} eventAction/3 {} stateChangeTrigger,condition {AlarmSwitch = FALSE} stateChangeTrigger,initialState true} { LightState = LightCtl LOG(AlarmSwitch) DISABLE(BlinkLight) NOTIFY( AlarmSwitch,"Alarm has been reset") }] # Test case contributed by Marshall Rose test attrList-5.1 {Attribute list with quoted value} { catch {unset ::result} set ::countAttributesOnly 0 catch {rename xml::attrList-5.1 {}} set parser [xml::parser attrList-5.1 \ -elementstartcommand EStart] set retval [catch { $parser parse {} }] list $retval [array get ::result] } {0 {test,example {isn't this legal?}}} foreach parser [info commands attrList-*] { $parser free } # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/xpath.bench0000644000175000017500000001352614703531020015234 0ustar rolfrolf# -*- tcl -*- # Tcl Benchmark File # # This file contains a number of benchmarks for XPath query speed. # This allow developers to monitor/gauge/track package performance. # # (c) 2006 Rolf Ade # # $Id$ # ### ### ### ######### ######### ######### ########################### ## Setting up the environment ... package require tdom # ### ### ### ######### ######### ######### ########################### ## Benchmarks. bench -desc "not() function - not cached" -pre { set doc [dom parse ] } -body { $doc selectNodes not(foo) } bench -desc "not() function - cached" -pre { set doc [dom parse ] } -body { $doc selectNodes -cache 1 not(foo) } bench -desc "path /foo/bar/baz - not cached" -pre { set doc [dom parse ] } -body { $doc selectNodes /foo/bar/baz } bench -desc "path /foo/bar/baz - cached" -pre { set doc [dom parse ] } -body { $doc selectNodes -cache 1 /foo/bar/baz } bench -desc "path with predicate - not cached" -pre { set doc [dom parse ] } -body { $doc selectNodes {/foo/bar/baz[not(grill) and @some='foo']} } bench -desc "path with predicate - cached" -pre { set doc [dom parse ] } -body { $doc selectNodes -cache 1 {/foo/bar/baz[not(grill) and @some='foo']} } namespace eval ::dom { namespace eval xpathFunc { } } proc ::dom::xpathFunc::myfunc {args} { return "foo" } dom createNodeCmd elementNode e1 foreach nrOf {1 10 20 30 40 50 60} { bench -desc "Tcl scripted XPath func with $nrOf nodes in the current nodelist" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 0} {$x < $nrOf} {incr x} { e1 } } } -body { $root selectNodes {e1[myfunc() = '']} } -post { $doc delete } } foreach nrOf {1 10 50 100} { bench -desc "string()" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 0} {$x < $nrOf} {incr x} { e1 } } $root selectNodes -cache 1 string(e1) } -body { $root selectNodes -cache 1 string(e1) } -post { $doc delete } } foreach nrOf {1 10 50 100} { bench -desc "count()" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 0} {$x < $nrOf} {incr x} { e1 } } $root selectNodes -cache 1 count(e1) } -body { $root selectNodes -cache 1 count(e1) } -post { $doc delete } } dom createNodeCmd elementNode e2 dom createDocument root doc $doc documentElement root $root appendFromScript { e2 for {set x 1} {$x < 1000} {incr x} { e1 } } bench -desc "Select unique element between 1000, at first, with pred" -body { $root selectNodes -cache 1 {e2[1]} } -post { $doc delete } bench -desc "Select unique element between 1000, at first, without pred" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { e2 for {set x 1} {$x < 1000} {incr x} { e1 } } } -body { $root selectNodes -cache 1 {e2} } -post { $doc delete } bench -desc "Select unique element between 1000, at first, with last() pred" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { e2 for {set x 1} {$x < 1000} {incr x} { e1 } } } -body { $root selectNodes -cache 1 {e2[last()]} } -post { $doc delete } bench -desc "Select unique element between 1000, at 500, with pred" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 1} {$x < 500} {incr x} { e1 } e2 for {set x 501} {$x <= 1000} {incr x} { e1 } } } -body { $root selectNodes -cache 1 {e2[1]} } -post { $doc delete } bench -desc "Select unique element between 1000, at 500, without pred" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 1} {$x < 500} {incr x} { e1 } e2 for {set x 501} {$x <= 1000} {incr x} { e1 } } } -body { $root selectNodes -cache 1 {e2} } -post { $doc delete } bench -desc "Select unique element between 1000, at 500, with last()" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 1} {$x < 500} {incr x} { e1 } e2 for {set x 501} {$x <= 1000} {incr x} { e1 } } } -body { $root selectNodes -cache 1 {e2[last()]} } -post { $doc delete } bench -desc "Select unique element between 1000, at 1000, with pred" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 1} {$x < 1000} {incr x} { e1 } e2 } } -body { $root selectNodes -cache 1 {e2[1]} } -post { $doc delete } bench -desc "Select unique element between 1000, at 1000, without pred" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 1} {$x < 1000} {incr x} { e1 } e2 } } -body { $root selectNodes -cache 1 {e2} } -post { $doc delete } bench -desc "Select unique element between 1000, at 1000, with last()" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 1} {$x < 1000} {incr x} { e1 } e2 } } -body { $root selectNodes -cache 1 {e2[last()]} } -post { $doc delete } tdom-0.9.5-src/tests/xmlsimple.test0000644000175000017500000001715414703531020016023 0ustar rolfrolf## Features covered: simple parser # # This file contains a collection of tests for the simple parser. # Tested functionalities: # simple-1.*: Basic function, parsing # simple-2.*: Character encoding # # Copyright (c) 2002 Rolf Ade. # # RCS: @(#) $Id$ source [file join [file dir [info script]] loadtdom.tcl] test simple-1.1 {document as only root node} { set doc [dom parse -simple {}] set root [$doc documentElement] set result [$root asXML -indent none] $doc delete set result } {} test simple-1.2 {parsing} { set doc [dom parse -simple {}] set root [$doc documentElement] set result [llength [$root childNodes]] $doc delete set result } {3} test simple-1.3 {simple parser - parsing} {knownBug} { set doc [dom parse -simple { }] set root [$doc documentElement] set result [$root asXML -indent none] $doc delete set result } {} test simple-1.4 {simple parser - parsing} { set doc [dom parse -simple { }] set root [$doc documentElement] set result [$root asXML -indent none] $doc delete set result } {} test simple-1.5 {simple parser - -keepEmpties} { set doc [dom parse -simple -keepEmpties {}] set root [$doc documentElement] set result [$root hasChildNodes] $doc delete set result } {0} test simple-1.6 {simple parser - empty CDATA section} { set doc [dom parse -simple -keepEmpties {}] set root [$doc documentElement] set result [$root hasChildNodes] $doc delete set result } {0} test simple-1.7 {simple parser - -keepEmpties} { set doc [dom parse -simple -keepEmpties { }] set result [$doc asXML -indent none] $doc delete set result } { } test simple-1.8 {simple parser - empty comment} { set doc [dom parse -simple {}] set root [$doc documentElement] set result [$root hasChildNodes] lappend result [[$root firstChild] nodeValue] $doc delete set result } {1 {}} test simple-1.9 {simple parser - not wellformed input} { catch {[dom parse -simple {}]} } 1 test simple-1.10 {simple parser - not wellformed input} { catch {[dom parse -simple {}} } 0 test simple-1.12 {CDATA section} { set doc [dom parse -simple {foo format]]> bar }] set result [$doc selectNodes count(doc/node())] $doc delete set result } 1 test simple-1.13 {CDATA section} { set doc [dom parse -simple {foo format]]> bar }] set root [$doc documentElement] set result [list] foreach child [$root childNodes] { lappend result [$child nodeType] } $doc delete set result } {TEXT_NODE} test simple-1.14 {CDATA section} { set doc [dom parse -simple {<foo & > format]]>' bar "}] set result [$doc selectNodes string(doc)] $doc delete set result } {test of & format' bar "} # emacs: " test simple-1.15 {-keepCDATA} { set doc [dom parse -simple -keepCDATA {foo format]]> bar }] set result [$doc asXML -indent none] $doc delete set result } {foo format]]> bar } test simple-1.16 {-keepCDATA} { set doc [dom parse -simple -keepCDATA {foo format]]> bar }] set root [$doc documentElement] set result [list] foreach child [$root childNodes] { lappend result [$child nodeType] } $doc delete set result } {TEXT_NODE CDATA_SECTION_NODE TEXT_NODE} test simple-1.17 {-keepCDATA} { set doc [dom parse -simple -keepCDATA {}] set result [list] foreach child [$doc selectNodes doc/e/node()] { lappend result [$child nodeType] } $doc delete set result } {CDATA_SECTION_NODE} test simple-1.18 {-keepCDATA} { set doc [dom parse -simple -keepCDATA {}] set result [list] foreach child [$doc selectNodes doc/e/node()] { lappend result [$child nodeType] } $doc delete set result } {CDATA_SECTION_NODE CDATA_SECTION_NODE} test simple-1.19 {-keepCDATA} { set doc [dom parse -simple -keepCDATA {}] set result [$doc selectNodes count(doc/e/node())] $doc delete set result } 0 test simple-1.20 {-keepCDATA white space only CDATA section} { set doc [dom parse -simple -keepCDATA {}] set result [$doc selectNodes count(doc/e/node())] $doc delete set result } 0 test simple-1.21 {-keepCDATA and -keepEmpties} { set doc [dom parse -simple -keepCDATA -keepEmpties {}] set result [$doc selectNodes count(doc/e/node())] $doc delete set result } 1 test simple-1.22 {namespaces} { set doc [dom parse -simple {
    notes
    }] $doc delete } {} test simple-1.23 {-forest} { set doc [dom parse -simple -forest {12}] set result [$doc asXML -indent none] $doc delete set result } {12} test simple-1.24 {-forest} { catch {dom parse -simple -forest {12}} } {1} test simple-1.25 {-forest} { set doc [dom parse -simple -forest {1some text2other text}] set result [$doc asXML -indent none] $doc delete set result } {1some text2other text} test simple-1.26 {-forest} { set xml {} catch {dom parse -simple $xml} errMsg1 catch {dom parse -simple -forest $xml} errMsg2 expr {$errMsg1 eq $errMsg2} } {1} test simple-1.27 {-forest} { set xml {} set doc [dom parse -simple -forest $xml] $doc documentElement root set result [llength [$root selectNodes //two]] $doc delete set result } 1 test simple-1.28 {-forest} { set xml {
    something
    something else
    } set doc [dom parse -simple -forest $xml] set result "" foreach child [$doc selectNodes /*] { lappend result [$child parentNode] } $doc delete set result } {{} {}} test simple-1.29 {parse long string} {64bit Tcl9 longRunning} { set doc [dom parse -simple "[string repeat [string repeat [string repeat abc 1000] 1000] 1000]"] set result [string length [$doc selectNodes string(/doc)]] lappend result [string length [$doc selectNodes substring(doc,2999999999)]] lappend result [$doc selectNodes substring(doc,2999999995,3)] $doc delete set result } {3000000000 2 abc} test simple-2.1 {XML build in entities} { set doc [dom parse -simple {<>&'"}] set root [$doc documentElement] set result [$root text] $doc delete set result } {<>&'"} # emacs: " test simple-2.2 {character entities} { set doc [dom parse -simple {AB}] set root [$doc documentElement] set result [$root text] $doc delete set result } {AB} test simple-2.3 {character entities} { set doc [dom parse -simple {ÖÄÄ}] set root [$doc documentElement] set result [$root text] $doc delete set result } "\u00d6\u00c4\u00c4" # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/domNode.bench0000644000175000017500000001657614703531020015505 0ustar rolfrolf# -*- tcl -*- # Tcl Benchmark File # # This file contains a number of benchmarks for the domNode methods. # This allow developers to monitor/gauge/track package performance. # # (c) 2006 Rolf Ade # # $Id$ # ### ### ### ######### ######### ######### ########################### ## Setting up the environment ... package require tdom # ### ### ### ######### ######### ######### ########################### ## Benchmarks. dom createNodeCmd elementNode e1 dom createNodeCmd elementNode e2 dom createNodeCmd commentNode c dom createNodeCmd textNode t dom createNodeCmd cdataNode cdata dom createNodeCmd piNode pi dom createNodeCmd parserNode parser namespace eval nodeCmds { dom createNodeCmd elementNode e1 dom createNodeCmd elementNode e2 dom createNodeCmd commentNode c dom createNodeCmd textNode t dom createNodeCmd cdataNode cdata dom createNodeCmd piNode pi dom createNodeCmd parserNode parser } bench -desc "appendFromScript-10-elements" -pre { set doc [dom parse ] set root [$doc documentElement] } -body { $root appendFromScript { e1 e2 e1 e2 e1 e2 e1 e2 e1 e2 } } -post { $doc delete } bench -desc "appendFromScript-10-elements2" -pre { set doc [dom parse ] set root [$doc documentElement] } -body { $root appendFromScript { e1 e1 e1 e1 e1 e1 e1 e1 e1 e1 } } -post { $doc delete } foreach nrOf {10 100 1000} { bench -desc "appendFromScript-nonamespace-element-$nrOf" -pre { set doc [dom parse ] set root [$doc documentElement] } -body { $root appendFromScript { for {set i 0} {$i < $nrOf} {incr i} { e1 } } } -post { $doc delete } bench -desc "appendFromScript-namespace-element-$nrOf" -pre { set doc [dom parse ] set root [$doc documentElement] } -body { $root appendFromScript { for {set i 0} {$i < $nrOf} {incr i} { nodeCmds::e1 } } } -post { $doc delete } bench -desc "appendFromScript-nonamespace-elementandtext-$nrOf" -pre { set doc [dom parse ] set root [$doc documentElement] } -body { $root appendFromScript { for {set i 0} {$i < $nrOf} {incr i} { e1 { t "This is text node $i" } } } } -post { $doc delete } bench -desc "appendFromScript-namespace-elementandtext-$nrOf" -pre { set doc [dom parse ] set root [$doc documentElement] } -body { $root appendFromScript { for {set i 0} {$i < $nrOf} {incr i} { nodeCmds::e1 { nodeCmds::t "This is text node $i" } } } } -post { $doc delete } } foreach nrOf {10 100 1000} { bench -desc "Create childs with dom methods $nrOf" -pre { dom createDocument root doc $doc documentElement root } -body { for {set x 0} {$x < $nrOf} {incr x} { $doc createElement e1 newNode $root appendChild $newNode } } -post { $doc delete } } foreach nrOf {10 100 1000} { bench -desc "Count returned domNode commands $nrOf" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 0} {$x < $nrOf} {incr x} { e1 } } } -body { llength [$doc selectNodes -cache 1 /root/e1] } -post { $doc delete } } foreach nrOf {1 10 100 1000} { bench -desc "Count returned domNode tokens $nrOf" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 0} {$x < $nrOf} {incr x} { e1 } } } -body { llength [domNode $root selectNodes -cache 1 /root/e1] } -post { $doc delete } } foreach nrOf {1 10 100 1000} { bench -desc "Use XPath to count returned nodes $nrOf" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 0} {$x < $nrOf} {incr x} { e1 } } } -body { $doc selectNodes -cache 1 count(/root/e1) } -post { $doc delete } } foreach nrOf {1 10 100 1000} { bench -desc "getElementsByTagName: $nrOf returned nodes" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 0} {$x < $nrOf} {incr x} { e1 } } } -body { $doc getElementsByTagName e1 } -post { $doc delete } } foreach nrOf {1 10 100 1000} { bench -desc "getElementsByTagName: $nrOf returned node tokens" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 0} {$x < $nrOf} {incr x} { e1 } } dom setObjectCommands token } -body { $doc getElementsByTagName e1 } -post { dom setObjectCommands automatic $doc delete } } bench -desc "firstChild node cmd" -pre { dom parse doc $doc documentElement root } -body { $root firstChild } -post { $doc delete } bench -desc "firstChild node token" -pre { dom parse doc $doc documentElement root dom setObjectCommands token } -body { $root firstChild } -post { $doc delete dom setObjectCommands automatic } bench -desc "firstChild node token from node token" -pre { dom parse doc dom setObjectCommands token $doc documentElement root } -body { domNode $root firstChild } -post { $doc delete dom setObjectCommands automatic } dom parse doc $doc documentElement root bench -desc "Check for text-only element - xpath - empty" -body { for {set x 0} {$x < 100} {incr x} { $doc selectNodes -cache 1 {count(node()) = 1 and node() = text()} } } bench -desc "Check for text-only element - xpath(uncached) - empty" -body { for {set x 0} {$x < 100} {incr x} { $doc selectNodes {count(node()) = 1 and node() = text()} } } bench -desc "Check for text-only element - tcl - empty" -body { for {set x 0} {$x < 100} {incr x} { expr {[llength [$root childNodes]] == 1 && [[$root firstChild] nodeType] == "TEXT_NODE"} } } $doc delete dom parse foo doc $doc documentElement root bench -desc "Check for text-only element - xpath - text-only" -body { for {set x 0} {$x < 100} {incr x} { $doc selectNodes -cache 1 {count(node()) = 1 and node() = text()} } } bench -desc "Check for text-only element - xpath(uncached) - text-only" -body { for {set x 0} {$x < 100} {incr x} { $doc selectNodes {count(node()) = 1 and node() = text()} } } bench -desc "Check for text-only element - tcl - text-only" -body { for {set x 0} {$x < 100} {incr x} { expr {[llength [$root childNodes]] == 1 && [[$root firstChild] nodeType] == "TEXT_NODE"} } } $doc delete tdom-0.9.5-src/tests/tdomcmd.test0000644000175000017500000001306514703531020015435 0ustar rolfrolf# Features covered: tdom cmd # # This file contains a collection of tests for the tdom cmd. # # Copyright (c) 2003 Rolf Ade. # # RCS: @(#) $Id$ source [file join [file dir [info script]] loadtdom.tcl] # To test, that DOM trees generated with a tdom enabled parser behaves # the same way, as the one generated with the [dom parse] cmd, we # rename the dom cmd and use instead a dom proc, which partly rebuilds # the [dom parse] interface with a tdom enabled parser. Then we just # [source] some of the test files, which heavily use [dom parse]. rename dom _dom set _main_parser [expat] tdom $_main_parser enable set parse_in_chunks 0 proc dom {args} { switch [lindex $args 0] { "parse" { set parseMethod "parse" set haveData 0 set uplevelVar "" tdom $::_main_parser keepEmpties 0 tdom $::_main_parser keepCDATA 0 tdom $::_main_parser keepTextStart 1 for {set x 1} {$x < [llength $args]} {incr x} { switch -- [lindex $args $x] { "-channel" { set parseMethod "parsechannel" incr x set data [lindex $args $x] set haveData 1 } "-keepEmpties" { tdom $::_main_parser keepEmpties 1 } "-keepCDATA" { tdom $::_main_parser keepCDATA 1 } "-baseurl" { incr x $::_main_parser configure -baseurl [lindex $args $x] } "-externalentitycommand" { incr x $::_main_parser configure -externalentitycommand \ [lindex $args $x] tdom $::_main_parser setExternalEntityResolver \ [lindex $args $x] } default { if {$haveData} { set uplevelVar [lindex $args $x] } else { set data [lindex $args $x] set haveData 1 } } } } if {$::parse_in_chunks && ($parseMethod == "parse")} { $::_main_parser configure -final 0 for {set x 0} {$x < [string length $data]} {incr x} { $::_main_parser parse [string index $data $x] } $::_main_parser configure -final 1 $::_main_parser parse "" } else { $::_main_parser $parseMethod $data } if {$uplevelVar != ""} { uplevel 1 set $uplevelVar [tdom $::_main_parser getdoc] } else { return [tdom $::_main_parser getdoc] } } "setStoreLineColumn" { tdom $::_main_parser setStoreLineColumn [lindex $args 1] } default { # Because the original command may be executed within a # namespace eval, we do an uplevel, to get the same context return [uplevel 1 [linsert $args 0 _dom]] } } } source [file join [file dir [info script]] i18n.test] source [file join [file dir [info script]] domNode.test] source [file join [file dir [info script]] xslt.test] # Un-comment this, to test tdom cmd together with expat parsing in chunks # set parse_in_chunks 1 # source [file join [file dir [info script]] i18n.test] # source [file join [file dir [info script]] domNode.test] # source [file join [file dir [info script]] xslt.test] rename dom {} rename _dom dom $_main_parser free test tdomcmd-1.1 {no doc available} { set parser [expat] tdom $parser enable set result [catch {tdom $parser getdoc} errMsg] $parser free lappend result $errMsg } {1 {No DOM tree available.}} test tdomcmd-1.2 {request dom tree in the middle of parsing} { set parser [expat -final 0] tdom $parser enable $parser parse {} set result [catch {tdom $parser getdoc} errMsg] lappend result $errMsg $parser parse {foo} lappend result [catch {tdom $parser getdoc} errMsg] lappend result $errMsg $parser configure -final 1 $parser parse {} lappend result [catch {set doc [tdom $parser getdoc]} errMsg] $doc delete $parser free set result } {1 {No DOM tree available.} 1 {No DOM tree available.} 0} proc es-tdomcmd-1.3 {parser name attlist} { tdom $parser enable } test tdomcmd-1.3 {Try to tdom enable a parser from its parsing callback} { set p [expat] $p configure -elementstartcommand [list es-tdomcmd-1.3 $p] set result [catch {$p parse {}}] $p free set result } {1} test tdomcmd-1.4 {keepCDATA} { set parser [expat] set result [catch {tdom $parser keepCDATA 1}] $parser free set result } 1 test tdomcmd-1.5 {keepCDATA} { set parser [expat] tdom $parser enable tdom $parser keepCDATA 1 $parser parse {textmore text} set doc [tdom $parser getdoc] set result [$doc asXML -indent none] $doc delete $parser reset tdom $parser keepCDATA 0 $parser parse {textmore text} set doc [tdom $parser getdoc] append result [$doc asXML -indent none] $doc delete $parser free set result } {textmore texttextHellomore text} # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/all.tcl0000644000175000017500000000107414703531020014356 0ustar rolfrolf# all.tcl -- # # This file contains a top-level script to run all of the Tcl # tests. Execute it by invoking "tclsh all.test". # # Copyright (c) 1998-1999 by Scriptics Corporation. # All rights reserved. # # RCS: @(#) $Id$ # source [file join [file dir [info script]] loadtdom.tcl] singleProcess 1 if {$tcl_version < 8.5} { # We still support 8.4 to some degree testsDirectory [file dirname [info script]] } else { configure {*}$argv -testdir [file dirname [info script]] } runAllTests # See http://mini.net/tcl/3248 for an explanation. proc exit args {} tdom-0.9.5-src/tests/namespace.test0000644000175000017500000001376214703531020015746 0ustar rolfrolf# Features covered: XML Namespaces # # This file tests the parser's performance on XML namespaces. # Sourcing this file into Tcl runs the tests and generates output # for errors. No output means no errors were found. # # Copyright (c) 2000 Zveno Pty Ltd. # # $Id$ source [file join [file dir [info script]] loadtdom.tcl] proc keysort args { array set keyvalue $args set result {} foreach key [lsort [array names keyvalue]] { lappend result $key $keyvalue($key) } return $result } catch {unset result} catch {unset nsdecls} proc EStart {tag attlist args} { global result nsdecls array set extra $args catch {eval lappend nsdecls $extra(-namespacedecls)} if {[info exists extra(-namespace)]} { lappend result $extra(-namespace)^$tag } else { lappend result $tag } } proc NSDeclStart {prefix uri} { global result lappend result $prefix lappend result $uri } test ns-1.1 {Namespace declaration} { set ::result {} set ::nsdecls {} catch {rename xml::ns-1.1 {}} set parser [xml::parser ns-1.1 \ -namespace \ -startnamespacedeclcommand NSDeclStart \ -elementstartcommand EStart] $parser parse { } list $::result $::nsdecls } {{test http://www.zveno.com/Schemas Test} {}} test ns-1.2 {Multiple namespace declarations} { set ::result {} set ::nsdecls {} catch {rename xml::ns-1.2 {}} set parser [xml::parser ns-1.2 \ -namespace \ -startnamespacedeclcommand NSDeclStart \ -elementstartcommand EStart] $parser parse { } list $::result [eval keysort $::nsdecls] } {{test http://www.zveno.com/Schemas x urn:schema Test} {}} test ns-1.3 {Default namespace declaration} { set ::result {} set ::nsdecls {} catch {rename xml::ns-1.3 {}} set parser [xml::parser ns-1.3 \ -namespace \ -startnamespacedeclcommand NSDeclStart \ -elementstartcommand EStart] $parser parse { } list $::result [eval keysort $::nsdecls] } {{{} http://www.zveno.com/Schemas x urn:schema http://www.zveno.com/Schemas:Test} {}} test ns-1.4 {Default namespace declaration w/- separate usage} { set ::result {} set ::nsdecls {} catch {rename xml::ns-1.4 {}} set parser [xml::parser ns-1.4 \ -namespace \ -startnamespacedeclcommand NSDeclStart \ -elementstartcommand EStart] $parser parse { } list $::result [eval keysort $::nsdecls] } {{{} http://www.zveno.com/Schemas x urn:schema urn:schema:Test http://www.zveno.com/Schemas:Test} {}} test ns-1.5 {Place of -namespace option in arg list} { set ::result {} set ::nsdecls {} catch {rename xml::ns-1.5 {}} set parser [xml::parser ns-1.4 \ -startnamespacedeclcommand NSDeclStart \ -namespace \ -elementstartcommand EStart] $parser parse { } list $::result [eval keysort $::nsdecls] } {{{} http://tdom.org/Schemas x urn:schema urn:schema:Test http://tdom.org/Schemas:Test} {}} test ns-2.0 {Multiple namespace declarations, same prefix} { set ::result {} set ::nsdecls {} catch {rename xml::ns-2.0 {}} set parser [xml::parser ns-2.0 \ -namespace \ -startnamespacedeclcommand NSDeclStart \ -elementstartcommand EStart] $parser parse { } list $::result [eval keysort $::nsdecls] } {{Test x http://www.zveno.com/Schemas http://www.zveno.com/Schemas:Test http://www.zveno.com/Schemas:y x urn:schema urn:schema:Test urn:schema:z} {}} test ns-3.1 {-namespaceseparator} { set result "" catch {rename xml::ns-3.1 {}} set parser [xml::parser ns-3.1 \ -namespace \ -namespaceseparator = \ -elementstartcommand EStart] $parser parse { } set result } {Test http://tdom.org/Schemas=Test http://tdom.org/Schemas=y urn:schema=Test urn:schema=z} test ns-3.2 {-namespaceseparator} { set result "" catch {rename xml::ns-3.2 {}} set parser [xml::parser ns-3.2 \ -namespace \ -namespaceseparator "" \ -elementstartcommand EStart] $parser parse { } set result } "Test http://tdom.org/SchemasTest http://tdom.org/Schemasy urn:schemaTest urn:schemaz" test ns-3.3 {-namespaceseparator} { set result "" catch {rename xml::ns-3.3 {}} set parser [xml::parser ns-3.3 \ -namespace \ -namespaceseparator \x00 \ -elementstartcommand EStart] $parser parse { } set result } "Test http://tdom.org/SchemasTest http://tdom.org/Schemasy urn:schemaTest urn:schemaz" test ns-3.4 {-namespaceseparator} { catch {rename xml::ns-3.4 {}} set parser [xml::parser ns-3.4 \ -namespaceseparator =] $parser cget -namespaceseparator } = foreach parser [info commands ns-*] { $parser free } # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/loadtdom.tcl0000644000175000017500000000214614703531020015412 0ustar rolfrolf# loadtdom.tcl -- # # This file is [source]d by all.tcl and all test files, to ensure, that # the tcltest package and the lastest tdom build is present. # # RCS: @(#) $Id$ # package require Tcl 8.5- package require tcltest 2.2 namespace import ::tcltest::* catch {tcltest::loadTestedCommands} if {[catch {package require -exact tdom 0.9.5}]} { if {[package vsatisfies [package provide Tcl] 9.0-]} { set libname libtcl9tdom0.9.5[info sharedlibextension] } else { set libname libtdom0.9.5[info sharedlibextension] } if {[catch {load [file join [file dir [info script]] ../unix/$libname]}]} { error "Unable to load the appropriate tDOM version!" } } if {[info commands ::tdom::xmlReadFile] == ""} { # tcldomsh without the script library. Source the lib. source [file join [file dir [info script]] ../lib tdom.tcl] } # Package internal test constraints if {[info procs ::tdom::extRefHandler] != ""} { testConstraint need_uri 1 } if {[package vsatisfies [package present Tcl] 9]} { testConstraint Tcl9 1 } testConstraint 64bit [expr {$tcl_platform(pointerSize) >= 8}] tdom-0.9.5-src/tests/i18n.test0000644000175000017500000000604114703531020014561 0ustar rolfrolf# Features covered: international issues # # Copyright (c) 2002 Rolf Ade. # # RCS: @(#) $Id$ source [file join [file dir [info script]] loadtdom.tcl] testConstraint beyondBMP [expr {[dom featureinfo TCL_UTF_MAX] > 3}] if {[join [lrange [split [package present Tcl] .] 0 1] .] <= 8.4} { testConstraint 8.6 false } else { testConstraint 8.6 [package vsatisfies [package present Tcl] 8.6-] } test i18n-1.1 {parse utf-8 string} { set russian "\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439" set doc [dom parse "$russian"] set root [$doc documentElement] set text [$root text] $doc delete string compare $text "\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439" } {0} test i18n-1.2 {parse utf-8 channel} { set fd [open [file join [pwd] [file dir [info script]] data/i18n_1.xml]] fconfigure $fd -encoding utf-8 set doc [dom parse -channel $fd] close $fd set root [$doc documentElement] set text [$root text] $doc delete string compare $text "\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439" } {0} test i18n-1.3 {parse utf-8 readFile} { set doc [dom parse [::tdom::xmlReadFile [file join [pwd] [file dir [info script]] data/i18n_1.xml]]] set root [$doc documentElement] set text [$root text] $doc delete string compare $text "\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439" } {0} test i18n-1.4 {pcdata outside BMP} -body { set doc [dom parse "👮👾💔"] set result [$doc asXML -indent none -escapeNonASCII] $doc delete set result } -result "👮👾💔" test i18n-1.5 {pcdata outside BMP} -body { set doc [dom parse "👮👾💔"] set result [$doc selectNodes string-length(/doc)] $doc delete set result } -result 3 test i18n-1.6 {pcdata outside BMP} -constraints { 8.6 beyondBMP } -body { set doc [dom parse "\U1F46E\U1F47E\U1F494"] set result [$doc asXML -indent none -escapeNonASCII] $doc delete set result } -result "👮👾💔" test i18n-1.7 {pcdata outside BMP} -body { set doc [dom parse "👮👾💔"] set result [dom isBMPCharData [$doc selectNodes string(/doc)]] $doc delete set result } -result 0 test i18n-1.8 {pcdata outside BMP} -constraints { beyondBMP 8.6 } -body { set doc [dom parse "\U1F46E\U1F47E\U1F494"] set result [$doc asXML -indent none] $doc delete set result } -result "👮👾💔" test i18n-1.10 {pcdata outside unicode} -body { set doc [dom parse "􏿿"] set result [$doc asXML -indent none -escapeNonASCII] $doc delete set result } -result "􏿿" test i18n-1.11 {pcdata outside unicode} -body { set result [catch {dom parse ""} msg] set msg } -match glob -result "*reference to invalid character number*" # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/all-bench.tcl0000644000175000017500000000672614703531020015444 0ustar rolfrolf# all-bench.tcl -- # # This file contains the top-level script to run the tDOM bench mark # suite. # # Copyright (c) 2007 by Rolf Ade (rolf@pointsman.de). # # $Id$ # # The script knows the options: # # -interppath # Adds a path to the list of pathes, which are searched for tclshs # with the pattern given by the -pattern option. Every time, this # option is given, the option value is added to the search list. If # not given, it is set to directory the tclsh, running the script, # lives in. # # -norm # See man bench, ::bench::norm # # -pattern # Specifies the search pattern for tclshs in the search # directories. Defaults to tclsh* # # -file # Specifies the search pattern for bench files in the same directory # as the all-bench.tcl. The default is *.bench. # # Every known option to ::bench::run (as of 0.3.1) are passed throu to # that command. See man bench for the details. # # Example: # tclsh all-bench.tcl \ # -interppath /usr/local/lib \ # -pkgdir ~/tdom/tdom-0.8.2 \ # -pkgdir ~/tdom/tdom-0.8.2-mod # # You can measure the same tDOM version against various tclshs, or # different tDOM versions with the same tclsh, or different tDOM # versions with differenct tclshs, all side by side. # # Don't run this script with a tcldomsh, until you know, what you're # doing. # bench 0.3.1 added the -pkgdir flag; we need at least that version, # if we want to compare more than one tDOM versions side by side. package require bench 0.3.1 package require bench::out::text # Defaults / Initialization set interpPattern tclsh* set benchFilePattern *.bench set interpPaths [list] set benchFlags [list] # Empty string means: no normalization set norm "" foreach {arg argValue} $argv { switch -- $arg { "-interppath" { lappend interpPaths $argValue } "-norm" { if {![string is integer -strict $argValue] || $argValue < 1} { puts stderr "The option -norm expects a postiv integer as\ value." exit 1 } set norm $argValue } "-pattern" { set interpPattern $argValue } "-file" { set benchFilePattern $argValue } default { switch -- $arg { "-errors" - "-threads" - "-match" - "-rmatch" - "-iters" - "-pkgdir" { lappend benchFlags $arg $argValue } default { puts stderr "Unknown option '$arg'" exit 1 } } } } } if {[llength $interpPaths] == 0} { lappend interpPaths [file dirname [info nameofexecutable]] } set interps [bench::locate $interpPattern $interpPaths] if {![llength $interps]} { puts stderr "No interpreters found" exit 1 } if {[llength $benchFlags]} { set cmd [linsert $benchFlags 0 bench::run] } else { set cmd [list bench::run] } set benchfiles [glob -nocomplain [file join [file dir [info script]] \ $benchFilePattern]] if {![llength $benchfiles]} { puts stderr "No benchmark files found." exit 1 } set results "" foreach interp $interps { set run $cmd lappend run $interp $benchfiles set results [::bench::merge $results [eval $run]] } if {$norm ne ""} { set results [::bench::norm $results $norm] } puts [::bench::out::text $results] tdom-0.9.5-src/tests/element.test0000644000175000017500000001027514703531020015437 0ustar rolfrolf# Features covered: Elements # # This file tests the parser's performance on elements. # Sourcing this file into Tcl runs the tests and generates output # for errors. No output means no errors were found. # # Copyright (c) 1999-2000 Zveno Pty Ltd. # Copyright (c) 2002-2005 Rolf Ade # # $Id$ source [file join [file dir [info script]] loadtdom.tcl] proc parray arrayName { upvar #0 $arrayName arr foreach key [lsort [array names $arrayName]] { lappend result $key $arr($key) } return $result } catch {unset started} proc Start {name atList args} { array set opts $args if {![info exists ::started($name)]} { set ::started($name) 1 } else { incr ::started($name) } } catch {unset ended} proc End {name args} { array set opts $args if {![info exists ::ended($name)]} { set ::ended($name) 1 } else { incr ::ended($name) } } catch {unset elList} proc ElStart {name atList args} { array set opts {-empty 0} array set opts $args lappend ::elList start $name $opts(-empty) } proc ElEnd {name args} { array set opts {-empty 0} array set opts $args lappend ::elList end $name $opts(-empty) } test element-1.1 {document element} { catch {unset ::started} catch {unset ::ended} catch {rename xml::element-1.1 {}} set parser [xml::parser element-1.1 \ -elementstartcommand Start \ -elementendcommand End] $parser parse {} list [array get ::started] [array get ::ended] } {{Test 1} {Test 1}} test element-1.2 {distinct elements} { catch {unset ::started} catch {unset ::ended} catch {rename xml::element-1.2 {}} set parser [xml::parser element-1.2 \ -elementstartcommand Start \ -elementendcommand End] $parser parse {} list [parray ::started] [parray ::ended] } {{Child1 1 Child2 1 Test 1} {Child1 1 Child2 1 Test 1}} proc esh-2.1 {parsername name attlist} { if {$parsername == "element-2.1"} { set ::result 1 } else { set ::result 0 } } test element-2.1 {handler script} { set ::result 0 set p [expat element-2.1 -elementstartcommand [list esh-2.1 element-2.1]] $p parse $p free set ::result } {1} proc eeh-2.2 {parsername name} { if {$parsername == "element-2.2"} { set ::result 1 } else { set ::result 0 } } test element-2.2 {handler script} { set ::result 0 set p [expat element-2.2] $p configure -elementendcommand [list eeh-2.2 element-2.2] $p parse $p free set ::result } {1} test element-2.3 {declare handler proc later} { set ::eshcounter 0 set ::eehcounter 0 catch {rename esh-2.3 {}} catch {rename eeh-2.3 {}} set p [expat -elementstartcommand esh-2.3 -elementendcommand eeh-2.3] proc esh-2.3 {args} { incr ::eshcounter } proc eeh-2.3 {args} { incr ::eehcounter } $p parse {
    } $p free list $::eshcounter $::eehcounter } {3 3} proc esh-3.1-1 {args} { $::p configure -elementstartcommand esh-3.1-2 incr ::esh-3.1-1 incr ::eshcounter } proc esh-3.1-2 {args} { $::p configure -elementstartcommand esh-3.1-1 incr ::esh-3.1-2 incr ::eshcounter } test element-3.1 {change handler from handler callback} { set ::esh-3.1-1 0 set ::esh-3.1-2 0 set ::eshcounter 0 set p [expat -elementstartcommand esh-3.1-1] $p parse {foo bar
    } $p free list ${::esh-3.1-1} ${::esh-3.1-2} $::eshcounter } {3 3 6} proc esh-3.2-1 {p args} { $p configure -elementstartcommand [list esh-3.2-2 $p] incr ::esh-3.2-1 incr ::eshcounter } proc esh-3.2-2 {p args} { $p configure -elementstartcommand [list esh-3.2-1 $p] incr ::esh-3.2-2 incr ::eshcounter } test element-3.2 {change handler from handler callback} { set ::esh-3.2-1 0 set ::esh-3.2-2 0 set ::eshcounter 0 set p [expat] $p configure -elementstartcommand [list esh-3.2-1 $p] $p parse {foo bar
    } $p free list ${::esh-3.2-1} ${::esh-3.2-2} $::eshcounter } {4 3 7} foreach parser [info commands element-*] { $parser free } # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/dom.bench0000644000175000017500000001524714703531020014671 0ustar rolfrolf# -*- tcl -*- # Tcl Benchmark File # # This file contains a number of benchmarks for the dom methods. # This allow developers to monitor/gauge/track package performance. # # (c) 2013 Rolf Ade # ### ### ### ######### ######### ######### ########################### ## Setting up the environment ... package require tdom # ### ### ### ######### ######### ######### ########################### ## Benchmarks. dom createNodeCmd elementNode e1 foreach nrOf {1 10 100 1000} { bench -desc "getElementsByTagName: $nrOf returned nodes" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 0} {$x < $nrOf} {incr x} { e1 } } } -body { $doc getElementsByTagName e1 } -post { $doc delete } } foreach nrOf {1 10 100 1000} { bench -desc "getElementsByTagName: $nrOf returned node tokens" -pre { dom createDocument root doc $doc documentElement root $root appendFromScript { for {set x 0} {$x < $nrOf} {incr x} { e1 } } dom setObjectCommands token } -body { $doc getElementsByTagName e1 } -post { dom setObjectCommands automatic $doc delete } } proc cloneImitated {source target} { foreach att [$source attributes] { $target setAttribute $att [$source @$att] } set targetDoc [$target ownerDocument] foreach child [$source childNodes] { switch [$child nodeType] { "ELEMENT_NODE" { set targetChild [$targetDoc createElement [$child nodeName]] } "TEXT_NODE" { set targetChild [$targetDoc createTextNode [$child nodeValue]] } "CDATA_SECTION_NODE" { set targetChild [$targetDoc createCDATASection \ [$child nodeValue]] } "PROCESSING_INSTRUCTION_NODE" { set targetChild [$targetDoc createProcessingInstruction \ [$child nodeName] [$child nodeValue]] } "COMMENT_NODE" { set targetChild [$targetDoc createComment [$child nodeValue]] } default { error "Unexpected node type [$child nodeType]" } } $target appendChild $targetChild cloneImitated $child $targetChild } } proc cloneImitated2 {source target} { foreach att [$source attributes] { $target setAttribute $att [$source @$att] } set targetDoc [$target ownerDocument] foreach child [$source childNodes] { switch [$child nodeType] { "ELEMENT_NODE" { $targetDoc createElement [$child nodeName] targetChild } "TEXT_NODE" { $targetDoc createTextNode [$child nodeValue] targetChild } "CDATA_SECTION_NODE" { $targetDoc createCDATASection [$child nodeValue] targetChild } "PROCESSING_INSTRUCTION_NODE" { $targetDoc createProcessingInstruction [$child nodeName] \ targetChild } "COMMENT_NODE" { $targetDoc createComment [$child nodeValue] targetChild } default { error "Unexpected node type [$child nodeType]" } } $target appendChild $targetChild cloneImitated2 $child $targetChild } } proc cloneImitatedToken {source target} { foreach att [domNode $source attributes] { domNode $target setAttribute $att [domNode $source @$att] } set targetDoc [domNode $target ownerDocument] foreach child [domNode $source childNodes] { switch [domNode $child nodeType] { "ELEMENT_NODE" { set targetChild [$targetDoc createElement \ [domNode $child nodeName]] } "TEXT_NODE" { set targetChild [$targetDoc createTextNode \ [domNode $child nodeValue]] } "CDATA_SECTION_NODE" { set targetChild [$targetDoc createCDATASection \ [domNode $child nodeValue]] } "PROCESSING_INSTRUCTION_NODE" { set targetChild [$targetDoc createProcessingInstruction \ [domNode $child nodeName] \ [domNode $child nodeValue]] } "COMMENT_NODE" { set targetChild [$targetDoc createComment \ [domNode $child nodeValue]] } default { error "Unexpected node type [domNode $child nodeType]" } } domNode $target appendChild $targetChild cloneImitatedToken $child $targetChild } } bench -desc "clone dom tree without clone method - cmds" -pre { set fd [open [file join [file dir [info script]] ../tests/data/mondial-europe.xml]] fconfigure $fd -encoding utf-8 set doc [dom parse -channel $fd] close $fd set root [$doc documentElement] set clone [dom createDocument [$root nodeName]] set cloneRoot [$clone documentElement] } -iters 5 -body { cloneImitated $root $cloneRoot } -post { $doc delete $clone delete } bench -desc "clone dom tree without clone method - cmds 2" -pre { set fd [open [file join [file dir [info script]] ../tests/data/mondial-europe.xml]] fconfigure $fd -encoding utf-8 set doc [dom parse -channel $fd] close $fd set root [$doc documentElement] set clone [dom createDocument [$root nodeName]] set cloneRoot [$clone documentElement] } -iters 5 -body { cloneImitated2 $root $cloneRoot } -post { $doc delete $clone delete } bench -desc "clone dom tree without clone method - token" -pre { set fd [open [file join [file dir [info script]] ../tests/data/mondial-europe.xml]] fconfigure $fd -encoding utf-8 set doc [dom parse -channel $fd] close $fd set root [$doc documentElement] set clone [dom createDocument [$root nodeName]] set cloneRoot [$clone documentElement] dom setObjectCommands token } -iters 5 -body { cloneImitatedToken $root $cloneRoot } -post { $doc delete $clone delete dom setObjectCommands automatic } foreach nrOf {1 10 100 1000} { bench -desc "Create document node: $nrOf" -pre { set doclist [list] } -body { lappend doclist [dom createDocumentNode] } -post { foreach doc $doclist { $doc delete } } } tdom-0.9.5-src/tests/domnamespace.test0000644000175000017500000003465314703531020016450 0ustar rolfrolf# Features covered: Namespace related DOM actions. # # This file contains a collection of tests for some namespace related # actions. # # domnamespace-1.*: misc tests # domnamespace-2.*: moving namespaced nodes from one document to another # domnamespace-3.*: moving namespaced nodes within a document # domnamespace-4.*: createNodeCmd and namespaces # # Copyright (c) 2002 Rolf Ade. # # RCS: @(#) $Id$ source [file join [file dir [info script]] loadtdom.tcl] test domnamespace-1.1 {multiple definition of the same namespace (same prefix/uri)} { set ch [open [file join [pwd] [file dir [info script]] data/REC-xslt-19991116.xml]] fconfigure $ch -encoding iso8859-1 set doc [dom parse -channel $ch] set root [$doc documentElement] set nodes [$root selectNodes //e:element-syntax] $doc delete llength $nodes } {35} test domnamespace-1.2 {more than 128 different namespaces in one doc} { set doc [dom parse { }] $doc documentElement root set result [[$root firstChild] namespace] lappend result [[$root lastChild] namespace] $doc delete set result } {n0 n129} test domnamespace-2.1 {moving namespaced nodes between documents} { set doc1 [dom parse {}] set root1 [$doc1 documentElement] set doc2 [dom parse {}] set root2 [$doc2 documentElement] $root2 appendChild [$root1 firstChild] set result [$root2 asXML -indent none] $doc1 delete $doc2 delete set result } {} test domnamespace-2.2 {moving namespaced nodes between documents} { set doc1 [dom parse {}] set root1 [$doc1 documentElement] set doc2 [dom parse {}] set root2 [$doc2 documentElement] set node [$root1 removeChild [$root1 firstChild]] $root2 appendChild $node set result [$root2 asXML -indent none] $doc1 delete $doc2 delete set result } {} test domnamespace-2.3 {moving namespaced nodes between documents} { set doc1 [dom parse {
    }] set root1 [$doc1 documentElement] set doc2 [dom parse {}] set root2 [$doc2 documentElement] set node [$root1 removeChild [$root1 firstChild]] $root2 appendChild $node set result [$root2 asXML -indent none] $doc1 delete $doc2 delete set result } {
    } test domnamespace-2.4 {moving namespaced nodes between documents} { set doc1 [dom parse {
    }] set root1 [$doc1 documentElement] set doc2 [dom parse {}] set root2 [$doc2 documentElement] set node [$root1 removeChild [$root1 firstChild]] $root2 appendChild $node set result [$root2 asXML -indent none] $doc1 delete $doc2 delete set result } {
    } test domnamespace-2.5 {moving namespaced nodes between documents} { set doc1 [dom parse {
    }] set root1 [$doc1 documentElement] set doc2 [dom parse {}] set root2 [$doc2 documentElement] set node [$root1 removeChild [$root1 firstChild]] $root2 appendChild $node set result [llength [$root2 getElementsByTagNameNS "" *]] $doc1 delete $doc2 delete set result } {2} test domnamespace-2.6 {moving namespaced nodes between documents} { set doc1 [dom parse {
    }] set root1 [$doc1 documentElement] set doc2 [dom parse {}] set root2 [$doc2 documentElement] set node [$root1 removeChild [$root1 firstChild]] $root2 appendChild $node set result [$root2 asXML -indent none] $doc1 delete $doc2 delete set result } {
    } test domnamespace-2.7 {moving namespaced nodes between documents} { set doc1 [dom parse {
    }] set root1 [$doc1 documentElement] set doc2 [dom parse {}] set root2 [$doc2 documentElement] $root2 appendChild [[$root1 firstChild] cloneNode -deep] set result [$root2 asXML -indent none] $doc1 delete $doc2 delete set result } {
    } test domnamespace-2.8 {moving namespaced nodes between documents} { set doc1 [dom parse {
    }] set root1 [$doc1 documentElement] set doc2 [dom parse {}] set root2 [$doc2 documentElement] $root2 appendChild [$root1 firstChild] set result [$root2 asXML -indent none] $doc1 delete $doc2 delete set result } {
    } test domnamespace-2.9 {moving namespaced nodes between documents} { set doc1 [dom parse {
    }] set root1 [$doc1 documentElement] set doc2 [dom parse {}] set root2 [$doc2 documentElement] $root2 appendChild [$root1 firstChild] set result [$root2 asXML -indent none] $doc1 delete $doc2 delete set result } {
    } test domnamespace-2.10 {moving nodes with attributes between documents} { set doc1 [dom parse {
    }] set root1 [$doc1 documentElement] set doc2 [dom parse {}] set root2 [$doc2 documentElement] set node [$root1 removeChild [$root1 firstChild]] $root2 appendChild $node set result [$root2 asXML -indent none] $doc1 delete $doc2 delete set result } {
    } test domnamespace-2.11 {moving nodes with namespaced attributes between documents} { set doc1 [dom parse {
    }] set root1 [$doc1 documentElement] set doc2 [dom parse {}] set root2 [$doc2 documentElement] set node [$root1 removeChild [$root1 firstChild]] $root2 appendChild $node set result [$root2 asXML -indent none] $doc1 delete $doc2 delete set result } {
    } test domnamespace-2.12 {moving nodes with namespaced attributes between documents} { set doc1 [dom parse {
    }] set root1 [$doc1 documentElement] set doc2 [dom parse {}] set root2 [$doc2 documentElement] set node [$root1 removeChild [$root1 firstChild]] $root2 appendChild $node $root2 setAttributeNS "" "xmlns:p" "foo" set result [$root2 selectNodes {//@p:*}] $doc1 delete $doc2 delete set result } {{p:b c}} test domnamespace-2.13 {moving nodes with namespaced attributes between documents} { set doc1 [dom parse {
    }] set root1 [$doc1 documentElement] set doc2 [dom parse {}] set root2 [$doc2 documentElement] set node [$root1 removeChild [$root1 firstChild]] $root2 setAttributeNS "" "xmlns:p" "foo" $root2 appendChild $node set result [$root2 asXML -indent none] $doc1 delete $doc2 delete set result } {
    } test domnamespace-2.14 {moving nodes with namespaced attributes between documents} { set doc1 [dom parse {
    }] set root1 [$doc1 documentElement] set doc2 [dom parse {}] set root2 [$doc2 documentElement] set node [$root1 removeChild [$root1 firstChild]] [$root2 firstChild] appendChild $node set result [$root2 asXML -indent none] $doc1 delete $doc2 delete set result } {
    } test domnamespace-2.15 {moving nodes with namespaced attributes between documents} { set doc1 [dom parse {
    }] set root1 [$doc1 documentElement] set doc2 [dom parse {}] set root2 [$doc2 documentElement] set node [$root1 removeChild [$root1 firstChild]] [$root2 firstChild] appendChild $node set nodes [$doc2 getElementsByTagNameNS "NS1" *] catch {unset result} foreach node $nodes { lappend result [$node nodeName] } $doc1 delete $doc2 delete set result } {doc1elem a} test domnamespace-2.16 {It is not recommended to create attributes that look like namespace declarations} { set doc [[dom parse {}] documentElement] set child [[dom parse {}] documentElement] $child setAttribute xmlns "foo" $doc appendChild $child $doc asXML -indent none } {} test domnamespace-2.17 {It is not recommended to create xml namespace declarations} { set doc [[dom parse {}] documentElement] set child [[dom parse {}] documentElement] $child setAttributeNS "" xmlns "foo" $doc appendChild $child $doc asXML -indent none } {} test domnamespace-3.1 {moving namespaced nodes within a document} { set doc [dom parse {}] set root [$doc documentElement] set nodeToMove [$doc selectNodes {/doc/node()[1]/node()[1]}] set newParent [$doc selectNodes {/doc/node()[2]}] $newParent appendChild $nodeToMove set result [$doc asXML -indent none] $doc delete set result } {} namespace eval nodeCmds { dom createNodeCmd -namespace foo.bar elementNode ns1:e1 dom createNodeCmd -namespace foo.bar elementNode e1 dom createNodeCmd textNode t dom createNodeCmd -tagName e1 elementNode e1NoNS } test domnamespace-4.1 {createNodeCmd and namespace} { dom createDocument doc doc $doc documentElement root $root appendFromScript { nodeCmds::ns1:e1 {nodeCmds::t "this"} } set result [$doc asXML -indent none] $doc delete set result } {this} test domnamespace-4.2 {createNodeCmd and namespace} { dom createDocumentNS foo.bar ns1:doc doc $doc documentElement root $root appendFromScript { nodeCmds::ns1:e1 {nodeCmds::t "this"} } set result [$doc asXML -indent none] $doc delete set result } {this} test domnamespace-4.3 {createNodeCmd and namespace} { dom createDocumentNS foo.bar doc doc $doc documentElement root $root appendFromScript { nodeCmds::ns1:e1 {nodeCmds::t "this"} } set result [$doc asXML -indent none] $doc delete set result } {this} test domnamespace-4.4 {createNodeCmd and namespace} { dom createDocumentNS foo.bar doc doc $doc documentElement root $root appendFromScript { nodeCmds::e1 { nodeCmds::e1NoNS att attValue {nodeCmds::t "this"} } } set result [$doc asXML -indent none] $doc delete set result } {this} test domnamespace-4.5 {createNodeCmd and namespace} { dom createDocumentNS foo.bar doc doc $doc documentElement root $root appendFromScript { nodeCmds::e1 { nodeCmds::e1NoNS att attValue {nodeCmds::t "this"} } } set result [$doc selectNodes -namespaces {fb foo.bar} string(/fb:doc/fb:e1/e1/@att)] $doc delete set result } {attValue} # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/tests/JSONTestSuite.tcl0000644000175000017500000000373714703531020016241 0ustar rolfrolf# The code in this file refers to the work done by: # # Parsing JSON is a Minefield # http://seriot.ch/parsing_json.php # https://github.com/nst/JSONTestSuite # # The dir argument should point to the test_parsing directory of that # repository package require tdom if {$argc > 1} { error "usage: $argv0 ?testdir?" } if {$argc} { set path [lindex $argv 0] if {[file isdirectory $path]} { set dir $path } else { set file $path } } else { set path "" set dir [pwd] } set skipfile [list] # Not all chars allowed in JSON strings are allowed as element names # or in XML char data. foreach file { y_string_escaped_control_character.json y_string_null_escape.json y_string_allowed_escapes.json y_object_empty_key.json y_object_escaped_null_in_key.json } { lappend skipfile $file } # UTF-8 edge cases and outside of BMP chars, for which tcl IO already # did the wrong thing. Or misuse of tcl internal string rep as if it # would be canonical UTF-8 (which it is not). foreach file { y_string_nonCharacterInUTF-8_U+FFFF.json y_string_nonCharacterInUTF-8_U+1FFFF.json n_string_unescaped_crtl_char.json } { lappend skipfile $file } foreach test [glob -directory $path "n_*"] { if {[file tail $test] in $skipfile} continue set fd [open $test] set input [read $fd] close $fd set result [catch {dom parse -json -jsonroot json -- $input}] if {!$result} { puts $test } } foreach test [glob -directory $path "y_*"] { if {[file tail $test] in $skipfile} continue set fd [open $test] set input [read $fd] close $fd set result [catch {dom parse -json -jsonroot json -- $input} errMsg] if {$result} { puts "$test $errMsg" } } # The 'some say so, some so' cases. Ignore result, just ensure no seg # fault */ foreach test [glob -directory $path "i_*"] { set fd [open $test] set input [read $fd] close $fd catch {dom parse -json -jsonroot json -- $input} } tdom-0.9.5-src/tdom.m40000644000175000017500000005117114703531020013150 0ustar rolfrolf #------------------------------------------------------------------------ # TDOM_ENABLE_DTD -- # # Allows the building with DTD support # # Arguments: # None # # Results: # # Adds the following arguments to configure: # --enable-dtd=yes|no # # Defines the following vars: # # Sets the following vars: # #------------------------------------------------------------------------ AC_DEFUN(TDOM_ENABLE_DTD, [ AC_MSG_CHECKING([whether to enable expat dtd support]) AC_ARG_ENABLE(dtd, AC_HELP_STRING([--enable-dtd], [build expat with dtd support (default: on)]), [tcl_ok=$enableval], [tcl_ok=yes]) if test "${enable_dtd+set}" = set; then enableval="$enable_dtd" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" ; then AC_MSG_RESULT([yes]) AC_DEFINE(XML_DTD) else AC_MSG_RESULT([no]) fi ]) #------------------------------------------------------------------------ # TDOM_CONTEXT_BYTES -- # # Allows to adjust the context bytes buffer size # # Arguments: # None # # Results: # # Adds the following arguments to configure: # --with-context-bytes= # # Defines the following vars: # # Sets the following vars: # #------------------------------------------------------------------------ AC_DEFUN(TDOM_CONTEXT_BYTES, [ AC_MSG_CHECKING([expat context bytes buffer size]) AC_ARG_WITH(contextbytes, AC_HELP_STRING([--with-context-bytes], [configure expat context bytes buffer size (default: 1024)]), , [with_contextbytes=1024]) AC_MSG_RESULT([${with_contextbytes}]) AC_DEFINE_UNQUOTED(XML_CONTEXT_BYTES, [${with_contextbytes}]) ]) #------------------------------------------------------------------------ # TDOM_ENABLE_NS -- # # Allows the building with namespace support # # Arguments: # None # # Results: # # Adds the following arguments to configure: # --enable-ns=yes|no # # Defines the following vars: # # Sets the following vars: # #------------------------------------------------------------------------ AC_DEFUN(TDOM_ENABLE_NS, [ AC_MSG_CHECKING([whether to enable namespace support]) AC_ARG_ENABLE(ns, AC_HELP_STRING([--enable-ns], [build with XML namespace support (default: on)]), [tcl_ok=$enableval], [tcl_ok=yes]) if test "${enable_ns+set}" = set; then enableval="$enable_ns" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" ; then AC_MSG_RESULT([yes]) AC_DEFINE(XML_NS) else AC_MSG_RESULT([no]) fi ]) #------------------------------------------------------------------------ # TDOM_ENABLE_UNKNOWN -- # # Allows the building with (or without) the custom unknown command # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-unknown=yes|no # # Defines the following vars: # # Sets the following vars: # #------------------------------------------------------------------------ AC_DEFUN(TDOM_ENABLE_UNKNOWN, [ AC_MSG_CHECKING([whether to enable built-in unknown command]) AC_ARG_ENABLE(ucmd, AC_HELP_STRING([--enable-unknown], [enable built-in unknown command (default: off)]), [tcl_ok=$enableval], [tcl_ok=no]) if test "${enable_unknown+set}" = set; then enableval="$enable_unknown" tcl_ok=$enableval else tcl_ok=no fi if test "$tcl_ok" = "no" ; then AC_MSG_RESULT([no]) AC_DEFINE(TDOM_NO_UNKNOWN_CMD) else AC_MSG_RESULT([yes]) fi ]) #------------------------------------------------------------------------ # TDOM_ENABLE_TDOMALLOC -- # # Allows the building with tDOMs block allocator for nodes # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-tdomalloc=yes|no # # Defines the following vars: # # Sets the following vars: # #------------------------------------------------------------------------ AC_DEFUN(TDOM_ENABLE_TDOMALLOC, [ AC_MSG_CHECKING([whether to enable tDOMs block allocator]) AC_ARG_ENABLE(tdomalloc, AC_HELP_STRING([--enable-tdomalloc], [build with the tDOM allocator (default: off)]), [tcl_ok=$enableval], [tcl_ok=no]) if test "${enable_tdomalloc+set}" = set; then enableval="$enable_tdomalloc" tcl_ok=$enableval else tcl_ok=no fi if test "$tcl_ok" = "yes" ; then AC_MSG_RESULT([yes]) TEA_ADD_SOURCES([generic/domalloc.c]) else AC_MSG_RESULT([no]) AC_DEFINE(USE_NORMAL_ALLOCATOR) fi ]) #------------------------------------------------------------------------ # TDOM_ENABLE_LESS_NS -- # # Building with lower limit of different XML namespace declarations # per document. # # Arguments: # None # # Results: # # Adds the following arguments to configure: # --enable-lessns=yes|no # # Defines the following vars: # # Sets the following vars: # #------------------------------------------------------------------------ AC_DEFUN(TDOM_ENABLE_LESS_NS, [ AC_MSG_CHECKING([whether to enable lower limit for XML ns declarations per document]) AC_ARG_ENABLE(lessns, AC_HELP_STRING([--enable-lessns], [build with lower limit for XML ns declarations (default: off)]), [tcl_ok=$enableval], [tcl_ok=no]) if test "${enable_lessns+set}" = set; then enableval="$enable_lessns" tcl_ok=$enableval else tcl_ok=no fi if test "$tcl_ok" = "yes" ; then AC_MSG_RESULT([yes]) AC_DEFINE(TDOM_LESS_NS) else AC_MSG_RESULT([no]) fi ]) #------------------------------------------------------------------------ # TDOM_ENABLE_SCHEMA -- # # Building with validation features. # # Arguments: # None # # Results: # # Adds the following arguments to configure: # --enable-validation=yes|no # # Defines the following vars: # # Sets the following vars: # #------------------------------------------------------------------------ AC_DEFUN(TDOM_ENABLE_SCHEMA, [ AC_MSG_CHECKING([whether to enable valiation features]) AC_ARG_ENABLE(schema, AC_HELP_STRING([--enable-schema], [build with valiation features (default: on)]), [tcl_ok=$enableval], [tcl_ok=yes]) if test "${enable_schema+set}" = set; then enableval="$enable_schema" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "no" ; then AC_MSG_RESULT([no]) AC_DEFINE(TDOM_NO_SCHEMA) else AC_MSG_RESULT([yes]) fi ]) #------------------------------------------------------------------------ # TDOM_ENABLE_HTML5 -- # # Building with gumbo support for HTML5 parsing (dom parse -html5) # # Arguments: # None # # Results: # # Adds the following arguments to configure: # --enable-html5=yes|no # # Defines the following vars: # # Sets the following vars: # #------------------------------------------------------------------------ AC_DEFUN(TDOM_ENABLE_HTML5, [ AC_PATH_TOOL([PKG_CONFIG],[pkg-config]) AC_MSG_CHECKING([whether to enable support for HTML5 parsing (using gumbo)]) AC_ARG_ENABLE(html5, AC_HELP_STRING([--enable-html5], [build with HTML5 parsing support (default: off)]), [tcl_ok=$enableval], [tcl_ok=no]) if test "${enable_html5+set}" = set; then enableval="$enable_html5" tcl_ok=$enableval else tcl_ok=no fi HTML5_LIBS="" HTML5_INCLUDES="" if test "$tcl_ok" = "yes" ; then # Check if pkg-config is available if test "x$PKG_CONFIG" = x; then tcl_ok=no AC_MSG_ERROR([cannot find pkg-config needed for --enable-html5.]) fi fi if test "$tcl_ok" = "yes" ; then HAVEGUMBO=`$PKG_CONFIG --exists gumbo && echo "1"` if test "$HAVEGUMBO" = "1" ; then AC_MSG_RESULT([yes]) AC_DEFINE(TDOM_HAVE_GUMBO) if test "${TEA_PLATFORM}" = "windows" ; then HTML5_LIBS="-Wl,-Bstatic `$PKG_CONFIG --static --libs gumbo` -Wl,-Bdynamic" else HTML5_LIBS="`$PKG_CONFIG --libs gumbo`" fi HTML5_INCLUDES="`$PKG_CONFIG --cflags gumbo`" else AC_MSG_ERROR([The required lib gumbo not found]) fi else AC_MSG_RESULT([no]) fi ]) #------------------------------------------------------------------------ # TDOM_PATH_AOLSERVER # # Allows the building with support for AOLserver # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-aolserver=... # # Defines the following vars: # AOL_DIR Full path to the directory containing AOLserver distro # # Sets the following vars: # NS_AOLSERVER #------------------------------------------------------------------------ AC_DEFUN(TDOM_PATH_AOLSERVER, [ AC_MSG_CHECKING([for AOLserver configuration]) AC_ARG_WITH(aol, AC_HELP_STRING([--with-aolserver], [directory with AOLserver distribution]), with_aolserver=${withval}) AC_CACHE_VAL(ac_cv_c_aolserver,[ if test x"${with_aolserver}" != x ; then if test -f "${with_aolserver}/include/ns.h" ; then ac_cv_c_aolserver=`(cd ${with_aolserver}; pwd)` else AC_MSG_ERROR([${with_aolserver} directory doesn't contain ns.h]) fi fi ]) if test x"${ac_cv_c_aolserver}" = x ; then AC_MSG_RESULT([none found]) else AOL_DIR=${ac_cv_c_aolserver} AOL_INCLUDES="-I\"${AOL_DIR}/include\"" if test "`uname -s`" = Darwin ; then aollibs=`ls ${AOL_DIR}/lib/libns* 2>/dev/null` if test x"$aollibs" != x ; then AOL_LIBS="-L\"${AOL_DIR}/lib\" -lnsd -lnsthread" fi fi AC_MSG_RESULT([found AOLserver in $AOL_DIR]) AC_DEFINE(NS_AOLSERVER) AC_DEFINE(USE_NORMAL_ALLOCATOR) fi ]) #------------------------------------------------------------------------ # TDOM_PATH_EXPAT # # Allows the building against a shared, system-wide expat library In # doubt, it falls back to the bundled expat copy # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-expat=... # # Defines the following vars: # # Sets the following vars: # #------------------------------------------------------------------------ AC_DEFUN(TDOM_PATH_EXPAT, [ AC_MSG_CHECKING([for expat]) AC_ARG_WITH(expat, AC_HELP_STRING([--with-expat], [directory with expat installation]), , [with_expat=no]) AC_CACHE_VAL(ac_cv_c_expat,[ case $with_expat in no) ;; yes) for f in /usr/local /usr; do if test -f "$f/include/expat.h" ; then ac_cv_c_expat=`(cd $f; pwd)` break fi done ;; *) if test -f "$with_expat/include/expat.h"; then ac_cv_c_expat=`(cd $with_expat; pwd)` else AC_MSG_ERROR([${with_expat} directory doesn't contain expat.h]) fi esac ]) if test x"${ac_cv_c_expat}" = x ; then AC_MSG_RESULT([Using bundled expat distribution]) TEA_ADD_SOURCES([expat/xmlrole.c \ expat/xmltok.c \ expat/xmlparse.c]) TEA_ADD_INCLUDES([-I${srcdir}/expat]) AC_DEFINE([XML_POOR_ENTROPY], 1, [Define to use poor entropy in lack of better source.]) else AC_MSG_RESULT([Using shared expat found in ${ac_cv_c_expat}]) TEA_ADD_INCLUDES(-I${ac_cv_c_expat}/include) TEA_ADD_LIBS([-lexpat]) fi ]) #------------------------------------------------------------------------ # TDOM_EXPAT_ENTROPY # # Only useful if building with the included expat. Allows to # determine the source of entropy used by the lib. If the argument # is something else then the default "auto", this argument value # will be a #define. Use XML_POOR_ENTROPY to fall back to the old # expat hash table salting. The default is to determine the best # available source and to use this. # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-entropy=... # # Defines the following vars: # # Sets the following vars: # #------------------------------------------------------------------------ AC_DEFUN(TDOM_EXPAT_ENTROPY, [ AC_MSG_NOTICE([checking which source of entropy to use]) AC_ARG_WITH(entropy, AC_HELP_STRING([--with-entropy], [source of entropy to use]), , [with_entropy=auto]) case $with_entropy in no) AC_DEFINE([XML_POOR_ENTROPY], 1, [Define to use poor entropy.]) ;; auto) AC_MSG_CHECKING([for arc4random_buf (BSD or libbsd)]) AC_LINK_IFELSE([AC_LANG_SOURCE([ #include /* for arc4random_buf on BSD, for NULL */ #if defined(HAVE_LIBBSD) # include #endif int main() { arc4random_buf(NULL, 0U); return 0; } ])], [ AC_DEFINE([HAVE_ARC4RANDOM_BUF], [1], [`arc4random_buf' function.]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_MSG_CHECKING([for arc4random (BSD, macOS or libbsd)]) AC_LINK_IFELSE([AC_LANG_SOURCE([ #if defined(HAVE_LIBBSD) # include #else # include #endif int main() { arc4random(); return 0; } ])], [ AC_DEFINE([HAVE_ARC4RANDOM], [1], [`arc4random' function.]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) ]) AC_MSG_CHECKING([for getrandom (Linux 3.17+, glibc 2.25+)]) AC_LINK_IFELSE([AC_LANG_SOURCE([ #include /* for NULL */ #include int main() { return getrandom(NULL, 0U, 0U); } ])], [ AC_DEFINE([HAVE_GETRANDOM], [1], [`getrandom' function.]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_MSG_CHECKING([for syscall SYS_getrandom (Linux 3.17+)]) AC_LINK_IFELSE([AC_LANG_SOURCE([ #include /* for NULL */ #include /* for syscall */ #include /* for SYS_getrandom */ int main() { syscall(SYS_getrandom, NULL, 0, 0); return 0; } ])], [ AC_DEFINE([HAVE_SYSCALL_GETRANDOM], [1], [`syscall' and `SYS_getrandom'.]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) ]) AC_DEFINE([XML_DEV_URANDOM], 1, [include code reading entropy from `/dev/urandom'.]) AC_DEFINE([XML_POOR_ENTROPY], 1, [Define to use poor entropy in lack of better source.]) ;; HAVE_GETRANDOM) AC_DEFINE([HAVE_GETRANDOM], 1, [Linux + glibc >=2.25]) ;; HAVE_SYSCALL_GETRANDOM) AC_DEFINE([HAVE_SYSCALL_GETRANDOM], 1, [Linux + glibc <2.25]) ;; HAVE_ARC4RANDOM_BUF) AC_DEFINE([HAVE_ARC4RANDOM_BUF], 1, [BSD / macOS >=10.7]) ;; HAVE_ARC4RANDOM) AC_DEFINE([HAVE_ARC4RANDOM], 1, [BSD / macOS <10.7]) ;; XML_DEV_URANDOM) AC_DEFINE([XML_DEV_URANDOM], 1, [Linux / BSD / macOS (/dev/urandom).]) ;; XML_POOR_ENTROPY) AC_DEFINE([XML_POOR_ENTROPY], 1, [Define to use poor entropy in lack of better source.]) ;; *) AC_MSG_ERROR([${with_entropy} not known.]) esac ]) #------------------------------------------------------------------------ # TDOM_PATH_CONFIG -- # # Locate the tdomConfig.sh file # # Arguments: # None # # Results: # # Adds the following arguments to configure: # --with-tdom=... # # Defines the following vars: # TDOM_BIN_DIR Full path to the directory with tdomConfig.sh #------------------------------------------------------------------------ AC_DEFUN(TDOM_PATH_CONFIG, [ if test x"${no_tdom}" = x ; then AC_MSG_CHECKING([for tDOM configuration]) AC_ARG_WITH(tdom, AC_HELP_STRING([--with-tdom], [directory containing tDOM configuration (tdomConfig.sh)]), with_tdomconfig=${withval}) no_tdom=true if test "${TEA_PLATFORM}" = "windows" ; then tdom_bindir=win else tdom_bindir=unix fi AC_CACHE_VAL(ac_cv_c_tdomconfig,[ # First check to see if --with-tdom was specified. if test x"${with_tdomconfig}" != x ; then if test -f "${with_tdomconfig}/tdomConfig.sh" ; then ac_cv_c_tdomconfig=`(cd ${with_tdomconfig}; pwd)` else AC_MSG_ERROR([${with_tdomconfig} directory doesn't contain tdomConfig.sh]) fi fi # Then check for a sibling installation if test x"${ac_cv_c_tdomconfig}" = x ; then for i in \ ../tdom `ls -dr ../tdom-* 2>/dev/null` \ ../../tdom `ls -dr ../../tdom-* 2>/dev/null` \ ../../../tdom `ls -dr ../../../tdom-* 2>/dev/null` ; do if test -f "$i/$tdom_bindir/tdomConfig.sh" ; then ac_cv_c_tdomconfig=`(cd $i/$tdom_bindir; pwd)` fi done fi # Then check if tnc/tdom are compilied in the source tree if test x"${ac_cv_c_tdomconfig}" = x ; then if test -f "../../$tdom_bindir/tdomConfig.sh" ; then ac_cv_c_tdomconfig=`(cd ../../$tdom_bindir; pwd)` fi fi # Check in a few common install locations if test x"${ac_cv_c_tdomconfig}" = x ; then for i in \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` ; do if test -f "$i/tdomConfig.sh" ; then ac_cv_c_tdomconfig=`(cd $i; pwd)` fi done fi # Check in a few other private locations if test x"${ac_cv_c_tdomconfig}" = x ; then for i in \ ${srcdir}/../tdom \ `ls -dr ${srcdir}/../tdom[[0-9]].[[0-9]]* 2>/dev/null` ; do if test -f "$i/$tdom_bindir/tdomConfig.sh" ; then ac_cv_c_tdomconfig=`(cd $i/$tdom_bindir; pwd)` fi done fi ]) if test x"${ac_cv_c_tdomconfig}" = x ; then TDOM_BIN_DIR="# no tDOM configuration file found" AC_MSG_WARN(Can't find tDOM configuration definitions) exit 0 else no_tdom= TDOM_BIN_DIR=${ac_cv_c_tdomconfig} AC_MSG_RESULT(found $TDOM_BIN_DIR/tdomConfig.sh) fi fi ]) #------------------------------------------------------------------------ # TDOM_LOAD_CONFIG -- # # Load the tdomConfig.sh file # # Arguments: # # Requires the following vars to be set: # TDOM_BIN_DIR # # Defines the following vars: # # Sets the following vars: # #------------------------------------------------------------------------ AC_DEFUN(TDOM_LOAD_CONFIG, [ AC_MSG_CHECKING([for existence of $TDOM_BIN_DIR/tdomConfig.sh]) if test -f "$TDOM_BIN_DIR/tdomConfig.sh" ; then AC_MSG_RESULT([loading]) . $TDOM_BIN_DIR/tdomConfig.sh else AC_MSG_RESULT([file not found]) fi if test -f "${TDOM_BIN_DIR}/Makefile" ; then TDOM_STUB_LIB_SPEC=${TDOM_BUILD_STUB_LIB_SPEC} fi AC_SUBST(TDOM_VERSION) AC_SUBST(TDOM_STUB_LIB_SPEC) AC_SUBST(TDOM_SRC_DIR) ]) # Local Variables: # mode: autoconf # End: # EOF tdom-0.9.5-src/win/0000755000175000017500000000000014703531020012533 5ustar rolfrolftdom-0.9.5-src/win/rules.vc0000644000175000017500000017256014703531020014232 0ustar rolfrolf#------------------------------------------------------------- -*- makefile -*- # rules.vc -- # # Part of the nmake based build system for Tcl and its extensions. # This file does all the hard work in terms of parsing build options, # compiler switches, defining common targets and macros. The Tcl makefile # directly includes this. Extensions include it via "rules-ext.vc". # # See TIP 477 (https://core.tcl-lang.org/tips/doc/main/tip/477.md) for # detailed documentation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # Copyright (c) 2001-2003 David Gravereaux. # Copyright (c) 2003-2008 Patrick Thoyts # Copyright (c) 2017 Ashok P. Nadkarni #------------------------------------------------------------------------------ !ifndef _RULES_VC _RULES_VC = 1 # The following macros define the version of the rules.vc nmake build system # For modifications that are not backward-compatible, you *must* change # the major version. RULES_VERSION_MAJOR = 1 RULES_VERSION_MINOR = 10 # The PROJECT macro must be defined by parent makefile. !if "$(PROJECT)" == "" !error *** Error: Macro PROJECT not defined! Please define it before including rules.vc !endif !if "$(PRJ_PACKAGE_TCLNAME)" == "" PRJ_PACKAGE_TCLNAME = $(PROJECT) !endif # Also special case Tcl and Tk to save some typing later DOING_TCL = 0 DOING_TK = 0 !if "$(PROJECT)" == "tcl" DOING_TCL = 1 !elseif "$(PROJECT)" == "tk" DOING_TK = 1 !endif !ifndef NEED_TK # Backwards compatibility !ifdef PROJECT_REQUIRES_TK NEED_TK = $(PROJECT_REQUIRES_TK) !else NEED_TK = 0 !endif !endif !ifndef NEED_TCL_SOURCE NEED_TCL_SOURCE = 0 !endif !ifdef NEED_TK_SOURCE !if $(NEED_TK_SOURCE) NEED_TK = 1 !endif !else NEED_TK_SOURCE = 0 !endif ################################################################ # Nmake is a pretty weak environment in syntax and capabilities # so this file is necessarily verbose. It's broken down into # the following parts. # # 0. Sanity check that compiler environment is set up and initialize # any built-in settings from the parent makefile # 1. First define the external tools used for compiling, copying etc. # as this is independent of everything else. # 2. Figure out our build structure in terms of the directory, whether # we are building Tcl or an extension, etc. # 3. Determine the compiler and linker versions # 4. Build the nmakehlp helper application # 5. Determine the supported compiler options and features # 6. Parse the OPTS macro value for user-specified build configuration # 7. Parse the STATS macro value for statistics instrumentation # 8. Parse the CHECKS macro for additional compilation checks # 9. Extract Tcl, and possibly Tk, version numbers from the headers # 10. Based on this selected configuration, construct the output # directory and file paths # 11. Construct the paths where the package is to be installed # 12. Set up the actual options passed to compiler and linker based # on the information gathered above. # 13. Define some standard build targets and implicit rules. These may # be optionally disabled by the parent makefile. # 14. (For extensions only.) Compare the configuration of the target # Tcl and the extensions and warn against discrepancies. # # One final note about the macro names used. They are as they are # for historical reasons. We would like legacy extensions to # continue to work with this make include file so be wary of # changing them for consistency or clarity. # 0. Sanity check compiler environment # Check to see we are configured to build with MSVC (MSDEVDIR, MSVCDIR or # VCINSTALLDIR) or with the MS Platform SDK (MSSDK or WindowsSDKDir) !if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(VCINSTALLDIR) && !defined(MSSDK) && !defined(WINDOWSSDKDIR) MSG = ^ Visual C++ compiler environment not initialized. !error $(MSG) !endif # We need to run from the directory the parent makefile is located in. # nmake does not tell us what makefile was used to invoke it so parent # makefile has to set the MAKEFILEVC macro or we just make a guess and # warn if we think that is not the case. !if "$(MAKEFILEVC)" == "" !if exist("$(PROJECT).vc") MAKEFILEVC = $(PROJECT).vc !elseif exist("makefile.vc") MAKEFILEVC = makefile.vc !endif !endif # "$(MAKEFILEVC)" == "" !if !exist("$(MAKEFILEVC)") MSG = ^ You must run nmake from the directory containing the project makefile.^ If you are doing that and getting this message, set the MAKEFILEVC^ macro to the name of the project makefile. !message WARNING: $(MSG) !endif ################################################################ # 1. Define external programs being used #---------------------------------------------------------- # Set the proper copy method to avoid overwrite questions # to the user when copying files and selecting the right # "delete all" method. #---------------------------------------------------------- RMDIR = rmdir /S /Q CPY = xcopy /i /y >NUL CPYDIR = xcopy /e /i /y >NUL COPY = copy /y >NUL MKDIR = mkdir ###################################################################### # 2. Figure out our build environment in terms of what we're building. # # (a) Tcl itself # (b) Tk # (c) a Tcl extension using libraries/includes from an *installed* Tcl # (d) a Tcl extension using libraries/includes from Tcl source directory # # This last is needed because some extensions still need # some Tcl interfaces that are not publicly exposed. # # The fragment will set the following macros: # ROOT - root of this module sources # COMPATDIR - source directory that holds compatibility sources # DOCDIR - source directory containing documentation files # GENERICDIR - platform-independent source directory # WIN_DIR - Windows-specific source directory # TESTDIR - directory containing test files # TOOLSDIR - directory containing build tools # _TCLDIR - root of the Tcl installation OR the Tcl sources. Not set # when building Tcl itself. # _INSTALLDIR - native form of the installation path. For Tcl # this will be the root of the Tcl installation. For extensions # this will be the lib directory under the root. # TCLINSTALL - set to 1 if _TCLDIR refers to # headers and libraries from an installed Tcl, and 0 if built against # Tcl sources. Not set when building Tcl itself. Yes, not very well # named. # _TCL_H - native path to the tcl.h file # # If Tk is involved, also sets the following # _TKDIR - native form Tk installation OR Tk source. Not set if building # Tk itself. # TKINSTALL - set 1 if _TKDIR refers to installed Tk and 0 if Tk sources # _TK_H - native path to the tk.h file # Root directory for sources and assumed subdirectories ROOT = $(MAKEDIR)\.. # The following paths CANNOT have spaces in them as they appear on the # left side of implicit rules. !ifndef COMPATDIR COMPATDIR = $(ROOT)\compat !endif !ifndef DOCDIR DOCDIR = $(ROOT)\doc !endif !ifndef GENERICDIR GENERICDIR = $(ROOT)\generic !endif !ifndef TOOLSDIR TOOLSDIR = $(ROOT)\tools !endif !ifndef TESTDIR TESTDIR = $(ROOT)\tests !endif !ifndef LIBDIR !if exist("$(ROOT)\library") LIBDIR = $(ROOT)\library !else LIBDIR = $(ROOT)\lib !endif !endif !ifndef DEMODIR !if exist("$(LIBDIR)\demos") DEMODIR = $(LIBDIR)\demos !else DEMODIR = $(ROOT)\demos !endif !endif # ifndef DEMODIR # Do NOT use WINDIR because it is Windows internal environment # variable to point to c:\windows! WIN_DIR = $(ROOT)\win !ifndef RCDIR !if exist("$(WIN_DIR)\rc") RCDIR = $(WIN_DIR)\rc !else RCDIR = $(WIN_DIR) !endif !endif RCDIR = $(RCDIR:/=\) # The target directory where the built packages and binaries will be installed. # INSTALLDIR is the (optional) path specified by the user. # _INSTALLDIR is INSTALLDIR using the backslash separator syntax !ifdef INSTALLDIR ### Fix the path separators. _INSTALLDIR = $(INSTALLDIR:/=\) !else ### Assume the normal default. _INSTALLDIR = $(HOMEDRIVE)\Tcl !endif !if $(DOING_TCL) # BEGIN Case 2(a) - Building Tcl itself # Only need to define _TCL_H _TCL_H = ..\generic\tcl.h # END Case 2(a) - Building Tcl itself !elseif $(DOING_TK) # BEGIN Case 2(b) - Building Tk TCLINSTALL = 0 # Tk always builds against Tcl source, not an installed Tcl !if "$(TCLDIR)" == "" !if [echo TCLDIR = \> nmakehlp.out] \ || [nmakehlp -L generic\tcl.h >> nmakehlp.out] !error *** Could not locate Tcl source directory. !endif !include nmakehlp.out !endif # TCLDIR == "" _TCLDIR = $(TCLDIR:/=\) _TCL_H = $(_TCLDIR)\generic\tcl.h !if !exist("$(_TCL_H)") !error Could not locate tcl.h. Please set the TCLDIR macro to point to the Tcl *source* directory. !endif _TK_H = ..\generic\tk.h # END Case 2(b) - Building Tk !else # BEGIN Case 2(c) or (d) - Building an extension other than Tk # If command line has specified Tcl location through TCLDIR, use it # else default to the INSTALLDIR setting !if "$(TCLDIR)" != "" _TCLDIR = $(TCLDIR:/=\) !if exist("$(_TCLDIR)\include\tcl.h") # Case 2(c) with TCLDIR defined TCLINSTALL = 1 _TCL_H = $(_TCLDIR)\include\tcl.h !elseif exist("$(_TCLDIR)\generic\tcl.h") # Case 2(d) with TCLDIR defined TCLINSTALL = 0 _TCL_H = $(_TCLDIR)\generic\tcl.h !endif !else # # Case 2(c) for extensions with TCLDIR undefined # Need to locate Tcl depending on whether it needs Tcl source or not. # If we don't, check the INSTALLDIR for an installed Tcl first !if exist("$(_INSTALLDIR)\include\tcl.h") && !$(NEED_TCL_SOURCE) TCLINSTALL = 1 TCLDIR = $(_INSTALLDIR)\.. # NOTE: we will be resetting _INSTALLDIR to _INSTALLDIR/lib for extensions # later so the \.. accounts for the /lib _TCLDIR = $(_INSTALLDIR)\.. _TCL_H = $(_TCLDIR)\include\tcl.h !else # exist(...) && !$(NEED_TCL_SOURCE) !if [echo _TCLDIR = \> nmakehlp.out] \ || [nmakehlp -L generic\tcl.h >> nmakehlp.out] !error *** Could not locate Tcl source directory. !endif !include nmakehlp.out TCLINSTALL = 0 TCLDIR = $(_TCLDIR) _TCL_H = $(_TCLDIR)\generic\tcl.h !endif # exist(...) && !$(NEED_TCL_SOURCE) !endif # TCLDIR !ifndef _TCL_H MSG =^ Failed to find tcl.h. The TCLDIR macro is set incorrectly or is not set and default path does not contain tcl.h. !error $(MSG) !endif # Now do the same to locate Tk headers and libs if project requires Tk !if $(NEED_TK) !if "$(TKDIR)" != "" _TKDIR = $(TKDIR:/=\) !if exist("$(_TKDIR)\include\tk.h") TKINSTALL = 1 _TK_H = $(_TKDIR)\include\tk.h !elseif exist("$(_TKDIR)\generic\tk.h") TKINSTALL = 0 _TK_H = $(_TKDIR)\generic\tk.h !endif !else # TKDIR not defined # Need to locate Tcl depending on whether it needs Tcl source or not. # If we don't, check the INSTALLDIR for an installed Tcl first !if exist("$(_INSTALLDIR)\include\tk.h") && !$(NEED_TK_SOURCE) TKINSTALL = 1 # NOTE: we will be resetting _INSTALLDIR to _INSTALLDIR/lib for extensions # later so the \.. accounts for the /lib _TKDIR = $(_INSTALLDIR)\.. _TK_H = $(_TKDIR)\include\tk.h TKDIR = $(_TKDIR) !else # exist("$(_INSTALLDIR)\include\tk.h") && !$(NEED_TK_SOURCE) !if [echo _TKDIR = \> nmakehlp.out] \ || [nmakehlp -L generic\tk.h >> nmakehlp.out] !error *** Could not locate Tk source directory. !endif !include nmakehlp.out TKINSTALL = 0 TKDIR = $(_TKDIR) _TK_H = $(_TKDIR)\generic\tk.h !endif # exist("$(_INSTALLDIR)\include\tk.h") && !$(NEED_TK_SOURCE) !endif # TKDIR !ifndef _TK_H MSG =^ Failed to find tk.h. The TKDIR macro is set incorrectly or is not set and default path does not contain tk.h. !error $(MSG) !endif !endif # NEED_TK !if $(NEED_TCL_SOURCE) && $(TCLINSTALL) MSG = ^ *** Warning: This extension requires the source distribution of Tcl.^ *** Please set the TCLDIR macro to point to the Tcl sources. !error $(MSG) !endif !if $(NEED_TK_SOURCE) !if $(TKINSTALL) MSG = ^ *** Warning: This extension requires the source distribution of Tk.^ *** Please set the TKDIR macro to point to the Tk sources. !error $(MSG) !endif !endif # If INSTALLDIR set to Tcl installation root dir then reset to the # lib dir for installing extensions !if exist("$(_INSTALLDIR)\include\tcl.h") _INSTALLDIR=$(_INSTALLDIR)\lib !endif # END Case 2(c) or (d) - Building an extension !endif # if $(DOING_TCL) ################################################################ # 3. Determine compiler version and architecture # In this section, we figure out the compiler version and the # architecture for which we are building. This sets the # following macros: # VCVERSION - the internal compiler version as 1200, 1400, 1910 etc. # This is also printed by the compiler in dotted form 19.10 etc. # VCVER - the "marketing version", for example Visual C++ 6 for internal # compiler version 1200. This is kept only for legacy reasons as it # does not make sense for recent Microsoft compilers. Only used for # output directory names. # ARCH - set to IX86, ARM64 or AMD64 depending on 32- or 64-bit target # NATIVE_ARCH - set to IX86, ARM64 or AMD64 for the host machine # MACHINE - same as $(ARCH) - legacy # _VC_MANIFEST_EMBED_{DLL,EXE} - commands for embedding a manifest if needed cc32 = $(CC) # built-in default. link32 = link lib32 = lib rc32 = $(RC) # built-in default. #---------------------------------------------------------------- # Figure out the compiler architecture and version by writing # the C macros to a file, preprocessing them with the C # preprocessor and reading back the created file _HASH=^# _VC_MANIFEST_EMBED_EXE= _VC_MANIFEST_EMBED_DLL= VCVER=0 !if ![echo VCVERSION=_MSC_VER > vercl.x] \ && ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \ && ![echo ARCH=IX86 >> vercl.x] \ && ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \ && ![echo ARCH=AMD64 >> vercl.x] \ && ![echo $(_HASH)elif defined(_M_ARM64) >> vercl.x] \ && ![echo ARCH=ARM64 >> vercl.x] \ && ![echo $(_HASH)endif >> vercl.x] \ && ![$(cc32) -nologo -TC -P vercl.x 2>NUL] !include vercl.i !if $(VCVERSION) < 1900 !if ![echo VCVER= ^\> vercl.vc] \ && ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc] !include vercl.vc !endif !else # The simple calculation above does not apply to new Visual Studio releases # Keep the compiler version in its native form. VCVER = $(VCVERSION) !endif !endif !if ![del 2>NUL /q/f vercl.x vercl.i vercl.vc] !endif #---------------------------------------------------------------- # The MACHINE macro is used by legacy makefiles so set it as well !ifdef MACHINE !if "$(MACHINE)" == "x86" !undef MACHINE MACHINE = IX86 !elseif "$(MACHINE)" == "arm64" !undef MACHINE MACHINE = ARM64 !elseif "$(MACHINE)" == "x64" !undef MACHINE MACHINE = AMD64 !endif !if "$(MACHINE)" != "$(ARCH)" !error Specified MACHINE macro $(MACHINE) does not match detected target architecture $(ARCH). !endif !else MACHINE=$(ARCH) !endif #--------------------------------------------------------------- # The PLATFORM_IDENTIFY macro matches the values returned by # the Tcl platform::identify command !if "$(MACHINE)" == "AMD64" PLATFORM_IDENTIFY = win32-x86_64 !elseif "$(MACHINE)" == "ARM64" PLATFORM_IDENTIFY = win32-arm !else PLATFORM_IDENTIFY = win32-ix86 !endif # The MULTIPLATFORM macro controls whether binary extensions are installed # in platform-specific directories. Intended to be set/used by extensions. !ifndef MULTIPLATFORM_INSTALL MULTIPLATFORM_INSTALL = 0 !endif #------------------------------------------------------------ # Figure out the *host* architecture by reading the registry !if ![reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | findstr /i x86] NATIVE_ARCH=IX86 !elseif ![reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | findstr /i ARM | findstr /i 64-bit] NATIVE_ARCH=ARM64 !else NATIVE_ARCH=AMD64 !endif # Since MSVC8 we must deal with manifest resources. !if $(VCVERSION) >= 1400 _VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1 _VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2 !endif ################################################################ # 4. Build the nmakehlp program # This is a helper app we need to overcome nmake's limiting # environment. We will call out to it to get various bits of # information about supported compiler options etc. # # Tcl itself will always use the nmakehlp.c program which is # in its own source. It will be kept updated there. # # Extensions built against an installed Tcl will use the installed # copy of Tcl's nmakehlp.c if there is one and their own version # otherwise. In the latter case, they would also be using their own # rules.vc. Note that older versions of Tcl do not install nmakehlp.c # or rules.vc. # # Extensions built against Tcl sources will use the one from the Tcl source. # # When building an extension using a sufficiently new version of Tcl, # rules-ext.vc will define NMAKEHLPC appropriately to point to the # copy of nmakehlp.c to be used. !ifndef NMAKEHLPC # Default to the one in the current directory (the extension's own nmakehlp.c) NMAKEHLPC = nmakehlp.c !if !$(DOING_TCL) !if $(TCLINSTALL) !if exist("$(_TCLDIR)\lib\nmake\nmakehlp.c") NMAKEHLPC = $(_TCLDIR)\lib\nmake\nmakehlp.c !endif !else # !$(TCLINSTALL) !if exist("$(_TCLDIR)\win\nmakehlp.c") NMAKEHLPC = $(_TCLDIR)\win\nmakehlp.c !endif !endif # $(TCLINSTALL) !endif # !$(DOING_TCL) !endif # NMAKEHLPC # We always build nmakehlp even if it exists since we do not know # what source it was built from. !if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "$(NATIVE_ARCH)" !if [$(cc32) -nologo "$(NMAKEHLPC)" -link -subsystem:console > nul] !endif !else !if [copy $(NMAKEHLPC:nmakehlp.c=x86_64-w64-mingw32-nmakehlp.exe) nmakehlp.exe >NUL] !endif !endif ################################################################ # 5. Test for compiler features # Visual C++ compiler options have changed over the years. Check # which options are supported by the compiler in use. # # The following macros are set: # OPTIMIZATIONS - the compiler flags to be used for optimized builds # DEBUGFLAGS - the compiler flags to be used for debug builds # LINKERFLAGS - Flags passed to the linker # # Note that these are the compiler settings *available*, not those # that will be *used*. The latter depends on the OPTS macro settings # which we have not yet parsed. # # Also note that some of the flags in OPTIMIZATIONS are not really # related to optimization. They are placed there only for legacy reasons # as some extensions expect them to be included in that macro. # -Op improves float consistency. Note only needed for older compilers # Newer compilers do not need or support this option. !if [nmakehlp -c -Op] FPOPTS = -Op !endif # Strict floating point semantics - present in newer compilers in lieu of -Op !if [nmakehlp -c -fp:strict] FPOPTS = $(FPOPTS) -fp:strict !endif !if "$(MACHINE)" == "IX86" ### test for pentium errata !if [nmakehlp -c -QI0f] !message *** Compiler has 'Pentium 0x0f fix' FPOPTS = $(FPOPTS) -QI0f !else !message *** Compiler does not have 'Pentium 0x0f fix' !endif !endif ### test for optimizations # /O2 optimization includes /Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy as per # documentation. Note we do NOT want /Gs as that inserts a _chkstk # stack probe at *every* function entry, not just those with more than # a page of stack allocation resulting in a performance hit. However, # /O2 documentation is misleading as its stack probes are simply the # default page size locals allocation probes and not what is implied # by an explicit /Gs option. OPTIMIZATIONS = $(FPOPTS) !if [nmakehlp -c -O2] OPTIMIZING = 1 OPTIMIZATIONS = $(OPTIMIZATIONS) -O2 !else # Legacy, really. All modern compilers support this !message *** Compiler does not have 'Optimizations' OPTIMIZING = 0 !endif # Checks for buffer overflows in local arrays !if [nmakehlp -c -GS] OPTIMIZATIONS = $(OPTIMIZATIONS) -GS !endif # Link time optimization. Note that this option (potentially) makes # generated libraries only usable by the specific VC++ version that # created it. Requires /LTCG linker option !if [nmakehlp -c -GL] OPTIMIZATIONS = $(OPTIMIZATIONS) -GL CC_GL_OPT_ENABLED = 1 !else # In newer compilers -GL and -YX are incompatible. !if [nmakehlp -c -YX] OPTIMIZATIONS = $(OPTIMIZATIONS) -YX !endif !endif # [nmakehlp -c -GL] DEBUGFLAGS = $(FPOPTS) # Run time error checks. Not available or valid in a release, non-debug build # RTC is for modern compilers, -GZ is legacy !if [nmakehlp -c -RTC1] DEBUGFLAGS = $(DEBUGFLAGS) -RTC1 !elseif [nmakehlp -c -GZ] DEBUGFLAGS = $(DEBUGFLAGS) -GZ !endif #---------------------------------------------------------------- # Linker flags # LINKER_TESTFLAGS are for internal use when we call nmakehlp to test # if the linker supports a specific option. Without these flags link will # return "LNK1561: entry point must be defined" error compiling from VS-IDE: # They are not passed through to the actual application / extension # link rules. !ifndef LINKER_TESTFLAGS LINKER_TESTFLAGS = /DLL /NOENTRY /OUT:nmakehlp.out !endif LINKERFLAGS = # If compiler has enabled link time optimization, linker must too with -ltcg !ifdef CC_GL_OPT_ENABLED !if [nmakehlp -l -ltcg $(LINKER_TESTFLAGS)] LINKERFLAGS = $(LINKERFLAGS) -ltcg !endif !endif ################################################################ # 6. Extract various version numbers from headers # For Tcl and Tk, version numbers are extracted from tcl.h and tk.h # respectively. For extensions, versions are extracted from the # configure.in or configure.ac from the TEA configuration if it # exists, and unset otherwise. # Sets the following macros: # TCL_MAJOR_VERSION # TCL_MINOR_VERSION # TCL_RELEASE_SERIAL # TCL_PATCH_LEVEL # TCL_PATCH_LETTER # TCL_VERSION # TK_MAJOR_VERSION # TK_MINOR_VERSION # TK_RELEASE_SERIAL # TK_PATCH_LEVEL # TK_PATCH_LETTER # TK_VERSION # DOTVERSION - set as (for example) 2.5 # VERSION - set as (for example 25) #-------------------------------------------------------------- !if [echo REM = This file is generated from rules.vc > versions.vc] !endif !if [echo TCL_MAJOR_VERSION = \>> versions.vc] \ && [nmakehlp -V "$(_TCL_H)" TCL_MAJOR_VERSION >> versions.vc] !endif !if [echo TCL_MINOR_VERSION = \>> versions.vc] \ && [nmakehlp -V "$(_TCL_H)" TCL_MINOR_VERSION >> versions.vc] !endif !if [echo TCL_RELEASE_SERIAL = \>> versions.vc] \ && [nmakehlp -V "$(_TCL_H)" TCL_RELEASE_SERIAL >> versions.vc] !endif !if [echo TCL_PATCH_LEVEL = \>> versions.vc] \ && [nmakehlp -V "$(_TCL_H)" TCL_PATCH_LEVEL >> versions.vc] !endif !if defined(_TK_H) !if [echo TK_MAJOR_VERSION = \>> versions.vc] \ && [nmakehlp -V $(_TK_H) TK_MAJOR_VERSION >> versions.vc] !endif !if [echo TK_MINOR_VERSION = \>> versions.vc] \ && [nmakehlp -V $(_TK_H) TK_MINOR_VERSION >> versions.vc] !endif !if [echo TK_RELEASE_SERIAL = \>> versions.vc] \ && [nmakehlp -V "$(_TK_H)" TK_RELEASE_SERIAL >> versions.vc] !endif !if [echo TK_PATCH_LEVEL = \>> versions.vc] \ && [nmakehlp -V $(_TK_H) TK_PATCH_LEVEL >> versions.vc] !endif !endif # _TK_H !include versions.vc TCL_VERSION = $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION) TCL_DOTVERSION = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION) !if [nmakehlp -f $(TCL_PATCH_LEVEL) "a"] TCL_PATCH_LETTER = a !elseif [nmakehlp -f $(TCL_PATCH_LEVEL) "b"] TCL_PATCH_LETTER = b !else TCL_PATCH_LETTER = . !endif !if defined(_TK_H) TK_VERSION = $(TK_MAJOR_VERSION)$(TK_MINOR_VERSION) TK_DOTVERSION = $(TK_MAJOR_VERSION).$(TK_MINOR_VERSION) !if [nmakehlp -f $(TK_PATCH_LEVEL) "a"] TK_PATCH_LETTER = a !elseif [nmakehlp -f $(TK_PATCH_LEVEL) "b"] TK_PATCH_LETTER = b !else TK_PATCH_LETTER = . !endif !endif # Set DOTVERSION and VERSION !if $(DOING_TCL) DOTVERSION = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION) VERSION = $(TCL_VERSION) !elseif $(DOING_TK) DOTVERSION = $(TK_DOTVERSION) VERSION = $(TK_VERSION) !else # Doing a non-Tk extension # If parent makefile has not defined DOTVERSION, try to get it from TEA # first from a configure.in file, and then from configure.ac !ifndef DOTVERSION !if [echo DOTVERSION = \> versions.vc] \ || [nmakehlp -V $(ROOT)\configure.in ^[$(PROJECT)^] >> versions.vc] !if [echo DOTVERSION = \> versions.vc] \ || [nmakehlp -V $(ROOT)\configure.ac ^[$(PROJECT)^] >> versions.vc] !error *** Could not figure out extension version. Please define DOTVERSION in parent makefile before including rules.vc. !endif !endif !include versions.vc !endif # DOTVERSION VERSION = $(DOTVERSION:.=) !endif # $(DOING_TCL) ... etc. # Windows RC files have 3 version components. Ensure this irrespective # of how many components the package has specified. Basically, ensure # minimum 4 components by appending 4 0's and then pick out the first 4. # Also take care of the fact that DOTVERSION may have "a" or "b" instead # of "." separating the version components. DOTSEPARATED=$(DOTVERSION:a=.) DOTSEPARATED=$(DOTSEPARATED:b=.) !if [echo RCCOMMAVERSION = \> versions.vc] \ || [for /f "tokens=1,2,3,4,5* delims=." %a in ("$(DOTSEPARATED).0.0.0.0") do echo %a,%b,%c,%d >> versions.vc] !error *** Could not generate RCCOMMAVERSION *** !endif !include versions.vc ######################################################################## # 7. Parse the OPTS macro to work out the requested build configuration. # Based on this, we will construct the actual switches to be passed to the # compiler and linker using the macros defined in the previous section. # The following macros are defined by this section based on OPTS # STATIC_BUILD - 0 -> Tcl is to be built as a shared library # 1 -> build as a static library and shell # TCL_THREADS - legacy but always 1 on Windows since winsock requires it. # DEBUG - 1 -> debug build, 0 -> release builds # SYMBOLS - 1 -> generate PDB's, 0 -> no PDB's # PROFILE - 1 -> generate profiling info, 0 -> no profiling # PGO - 1 -> profile based optimization, 0 -> no # MSVCRT - 1 -> link to dynamic C runtime even when building static Tcl build # 0 -> link to static C runtime for static Tcl build. # Does not impact shared Tcl builds (STATIC_BUILD == 0) # Default: 1 for Tcl 8.7 and up, 0 otherwise. # TCL_USE_STATIC_PACKAGES - 1 -> statically link the registry and dde extensions # in the Tcl and Wish shell. 0 -> keep them as shared libraries. Does # not impact shared Tcl builds. Implied by STATIC_BUILD since Tcl 8.7. # USE_THREAD_ALLOC - 1 -> Use a shared global free pool for allocation. # 0 -> Use the non-thread allocator. # UNCHECKED - 1 -> when doing a debug build with symbols, use the release # C runtime, 0 -> use the debug C runtime. # USE_STUBS - 1 -> compile to use stubs interfaces, 0 -> direct linking # CONFIG_CHECK - 1 -> check current build configuration against Tcl # configuration (ignored for Tcl itself) # _USE_64BIT_TIME_T - forces a build using 64-bit time_t for 32-bit build # (CRT library should support this, not needed for Tcl 9.x) # TCL_UTF_MAX=3 - forces a build using UTF-16 internally (not recommended). # Further, LINKERFLAGS are modified based on above. # Default values for all the above STATIC_BUILD = 0 TCL_THREADS = 1 DEBUG = 0 SYMBOLS = 0 PROFILE = 0 PGO = 0 MSVCRT = 1 TCL_USE_STATIC_PACKAGES = 0 USE_THREAD_ALLOC = 1 UNCHECKED = 0 CONFIG_CHECK = 1 !if $(DOING_TCL) USE_STUBS = 0 !else USE_STUBS = 1 !endif # If OPTS is not empty AND does not contain "none" which turns off all OPTS # set the above macros based on OPTS content !if "$(OPTS)" != "" && ![nmakehlp -f "$(OPTS)" "none"] # OPTS are specified, parse them !if [nmakehlp -f $(OPTS) "static"] !message *** Doing static STATIC_BUILD = 1 !endif !if [nmakehlp -f $(OPTS) "nostubs"] !message *** Not using stubs USE_STUBS = 0 !endif !if [nmakehlp -f $(OPTS) "nomsvcrt"] !message *** Doing nomsvcrt MSVCRT = 0 !else !if [nmakehlp -f $(OPTS) "msvcrt"] !message *** Doing msvcrt !else !if $(TCL_MAJOR_VERSION) == 8 && $(TCL_MINOR_VERSION) < 7 && $(STATIC_BUILD) MSVCRT = 0 !endif !endif !endif # [nmakehlp -f $(OPTS) "nomsvcrt"] !if [nmakehlp -f $(OPTS) "staticpkg"] && $(STATIC_BUILD) !message *** Doing staticpkg TCL_USE_STATIC_PACKAGES = 1 !endif !if [nmakehlp -f $(OPTS) "nothreads"] !message *** Compile explicitly for non-threaded tcl TCL_THREADS = 0 USE_THREAD_ALLOC= 0 !endif !if $(TCL_MAJOR_VERSION) == 8 !if [nmakehlp -f $(OPTS) "time64bit"] !message *** Force 64-bit time_t _USE_64BIT_TIME_T = 1 !endif !if [nmakehlp -f $(OPTS) "utf16"] !message *** Force UTF-16 internally TCL_UTF_MAX = 3 !endif !endif # Yes, it's weird that the "symbols" option controls DEBUG and # the "pdbs" option controls SYMBOLS. That's historical. !if [nmakehlp -f $(OPTS) "symbols"] !message *** Doing symbols DEBUG = 1 !else DEBUG = 0 !endif !if [nmakehlp -f $(OPTS) "pdbs"] !message *** Doing pdbs SYMBOLS = 1 !else SYMBOLS = 0 !endif !if [nmakehlp -f $(OPTS) "profile"] !message *** Doing profile PROFILE = 1 !else PROFILE = 0 !endif !if [nmakehlp -f $(OPTS) "pgi"] !message *** Doing profile guided optimization instrumentation PGO = 1 !elseif [nmakehlp -f $(OPTS) "pgo"] !message *** Doing profile guided optimization PGO = 2 !else PGO = 0 !endif !if [nmakehlp -f $(OPTS) "loimpact"] !message *** Warning: ignoring option "loimpact" - deprecated on modern Windows. !endif # TBD - should get rid of this option !if [nmakehlp -f $(OPTS) "thrdalloc"] !message *** Doing thrdalloc USE_THREAD_ALLOC = 1 !endif !if [nmakehlp -f $(OPTS) "tclalloc"] USE_THREAD_ALLOC = 0 !endif !if [nmakehlp -f $(OPTS) "unchecked"] !message *** Doing unchecked UNCHECKED = 1 !else UNCHECKED = 0 !endif !if [nmakehlp -f $(OPTS) "noconfigcheck"] CONFIG_CHECK = 1 !else CONFIG_CHECK = 0 !endif !endif # "$(OPTS)" != "" && ... parsing of OPTS # Set linker flags based on above !if $(PGO) > 1 !if [nmakehlp -l -ltcg:pgoptimize $(LINKER_TESTFLAGS)] LINKERFLAGS = $(LINKERFLAGS:-ltcg=) -ltcg:pgoptimize !else MSG=^ This compiler does not support profile guided optimization. !error $(MSG) !endif !elseif $(PGO) > 0 !if [nmakehlp -l -ltcg:pginstrument $(LINKER_TESTFLAGS)] LINKERFLAGS = $(LINKERFLAGS:-ltcg=) -ltcg:pginstrument !else MSG=^ This compiler does not support profile guided optimization. !error $(MSG) !endif !endif ################################################################ # 8. Parse the STATS macro to configure code instrumentation # The following macros are set by this section: # TCL_MEM_DEBUG - 1 -> enables memory allocation instrumentation # 0 -> disables # TCL_COMPILE_DEBUG - 1 -> enables byte compiler logging # 0 -> disables # Default both are off TCL_MEM_DEBUG = 0 TCL_COMPILE_DEBUG = 0 !if "$(STATS)" != "" && ![nmakehlp -f "$(STATS)" "none"] !if [nmakehlp -f $(STATS) "memdbg"] !message *** Doing memdbg TCL_MEM_DEBUG = 1 !else TCL_MEM_DEBUG = 0 !endif !if [nmakehlp -f $(STATS) "compdbg"] !message *** Doing compdbg TCL_COMPILE_DEBUG = 1 !else TCL_COMPILE_DEBUG = 0 !endif !endif #################################################################### # 9. Parse the CHECKS macro to configure additional compiler checks # The following macros are set by this section: # WARNINGS - compiler switches that control the warnings level # TCL_NO_DEPRECATED - 1 -> disable support for deprecated functions # 0 -> enable deprecated functions # Defaults - Permit deprecated functions and warning level 3 TCL_NO_DEPRECATED = 0 WARNINGS = -W3 !if "$(CHECKS)" != "" && ![nmakehlp -f "$(CHECKS)" "none"] !if [nmakehlp -f $(CHECKS) "nodep"] !message *** Doing nodep check TCL_NO_DEPRECATED = 1 !endif !if [nmakehlp -f $(CHECKS) "fullwarn"] !message *** Doing full warnings check WARNINGS = -W4 !if [nmakehlp -l -warn:3 $(LINKER_TESTFLAGS)] LINKERFLAGS = $(LINKERFLAGS) -warn:3 !endif !endif !if [nmakehlp -f $(CHECKS) "64bit"] && [nmakehlp -c -Wp64] !message *** Doing 64bit portability warnings WARNINGS = $(WARNINGS) -Wp64 !endif !endif ################################################################ # 10. Construct output directory and file paths # Figure-out how to name our intermediate and output directories. # In order to avoid inadvertent mixing of object files built using # different compilers, build configurations etc., # # Naming convention (suffixes): # t = full thread support. (Not used for Tcl >= 8.7) # s = static library (as opposed to an import library) # g = linked to the debug enabled C run-time. # x = special static build when it links to the dynamic C run-time. # # The following macros are set in this section: # SUFX - the suffix to use for binaries based on above naming convention # BUILDDIRTOP - the toplevel default output directory # is of the form {Release,Debug}[_AMD64][_COMPILERVERSION] # TMP_DIR - directory where object files are created # OUT_DIR - directory where output executables are created # Both TMP_DIR and OUT_DIR are defaulted only if not defined by the # parent makefile (or command line). The default values are # based on BUILDDIRTOP. # STUBPREFIX - name of the stubs library for this project # PRJIMPLIB - output path of the generated project import library # PRJLIBNAME - name of generated project library # PRJLIB - output path of generated project library # PRJSTUBLIBNAME - name of the generated project stubs library # PRJSTUBLIB - output path of the generated project stubs library # RESFILE - output resource file (only if not static build) SUFX = tsgx !if $(DEBUG) BUILDDIRTOP = Debug !else BUILDDIRTOP = Release !endif !if "$(MACHINE)" != "IX86" BUILDDIRTOP =$(BUILDDIRTOP)_$(MACHINE) !endif !if $(VCVER) > 6 BUILDDIRTOP =$(BUILDDIRTOP)_VC$(VCVER) !endif !if !$(DEBUG) || $(TCL_VERSION) > 86 || $(DEBUG) && $(UNCHECKED) SUFX = $(SUFX:g=) !endif TMP_DIRFULL = .\$(BUILDDIRTOP)\$(PROJECT)_ThreadedDynamicStaticX !if !$(STATIC_BUILD) TMP_DIRFULL = $(TMP_DIRFULL:Static=) SUFX = $(SUFX:s=) EXT = dll TMP_DIRFULL = $(TMP_DIRFULL:X=) SUFX = $(SUFX:x=) !else TMP_DIRFULL = $(TMP_DIRFULL:Dynamic=) EXT = lib !if !$(MSVCRT) TMP_DIRFULL = $(TMP_DIRFULL:X=) SUFX = $(SUFX:x=) !endif !endif !if !$(TCL_THREADS) || $(TCL_VERSION) > 86 TMP_DIRFULL = $(TMP_DIRFULL:Threaded=) SUFX = $(SUFX:t=) !endif !ifndef TMP_DIR TMP_DIR = $(TMP_DIRFULL) !ifndef OUT_DIR OUT_DIR = .\$(BUILDDIRTOP) !endif !else !ifndef OUT_DIR OUT_DIR = $(TMP_DIR) !endif !endif # Relative paths -> absolute !if [echo OUT_DIR = \> nmakehlp.out] \ || [nmakehlp -Q "$(OUT_DIR)" >> nmakehlp.out] !error *** Could not fully qualify path OUT_DIR=$(OUT_DIR) !endif !if [echo TMP_DIR = \>> nmakehlp.out] \ || [nmakehlp -Q "$(TMP_DIR)" >> nmakehlp.out] !error *** Could not fully qualify path TMP_DIR=$(TMP_DIR) !endif !include nmakehlp.out # The name of the stubs library for the project being built STUBPREFIX = $(PROJECT)stub # # Set up paths to various Tcl executables and libraries needed by extensions # # TIP 430. Unused for 8.6 but no harm defining it to allow a common rules.vc TCLSCRIPTZIPNAME = libtcl$(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)$(TCL_PATCH_LETTER)$(TCL_RELEASE_SERIAL).zip TKSCRIPTZIPNAME = libtk$(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)$(TK_PATCH_LETTER)$(TK_RELEASE_SERIAL).zip !if $(DOING_TCL) TCLSHNAME = $(PROJECT)sh$(VERSION)$(SUFX).exe TCLSH = $(OUT_DIR)\$(TCLSHNAME) TCLIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib TCLLIBNAME = $(PROJECT)$(VERSION)$(SUFX).$(EXT) TCLLIB = $(OUT_DIR)\$(TCLLIBNAME) TCLSCRIPTZIP = $(OUT_DIR)\$(TCLSCRIPTZIPNAME) TCLSTUBLIBNAME = $(STUBPREFIX)$(VERSION).lib TCLSTUBLIB = $(OUT_DIR)\$(TCLSTUBLIBNAME) TCL_INCLUDES = -I"$(WIN_DIR)" -I"$(GENERICDIR)" !else # !$(DOING_TCL) !if $(TCLINSTALL) # Building against an installed Tcl # When building extensions, we need to locate tclsh. Depending on version # of Tcl we are building against, this may or may not have a "t" suffix. # Try various possibilities in turn. TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX:t=).exe !if !exist("$(TCLSH)") TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX:t=).exe !endif TCLSTUBLIB = $(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX:t=).lib # When building extensions, may be linking against Tcl that does not add # "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility. !if !exist("$(TCLIMPLIB)") TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)t$(SUFX:t=).lib !endif TCL_LIBRARY = $(_TCLDIR)\lib TCLREGLIB = $(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib TCLDDELIB = $(_TCLDIR)\lib\tcldde14$(SUFX:t=).lib TCLSCRIPTZIP = $(_TCLDIR)\lib\$(TCLSCRIPTZIPNAME) TCLTOOLSDIR = \must\have\tcl\sources\to\build\this\target TCL_INCLUDES = -I"$(_TCLDIR)\include" !else # Building against Tcl sources TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX:t=).exe !if !exist($(TCLSH)) TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX:t=).exe !endif TCLSTUBLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX:t=).lib # When building extensions, may be linking against Tcl that does not add # "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility. !if !exist("$(TCLIMPLIB)") TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)t$(SUFX:t=).lib !endif TCL_LIBRARY = $(_TCLDIR)\library TCLREGLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib TCLDDELIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde14$(SUFX:t=).lib TCLSCRIPTZIP = $(_TCLDIR)\win\$(BUILDDIRTOP)\$(TCLSCRIPTZIPNAME) TCLTOOLSDIR = $(_TCLDIR)\tools TCL_INCLUDES = -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win" !endif # TCLINSTALL tcllibs = "$(TCLSTUBLIB)" "$(TCLIMPLIB)" !endif # $(DOING_TCL) # We need a tclsh that will run on the host machine as part of the build. # IX86 runs on all architectures. !ifndef TCLSH_NATIVE !if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "$(NATIVE_ARCH)" TCLSH_NATIVE = $(TCLSH) !else !error You must explicitly set TCLSH_NATIVE for cross-compilation !endif !endif # Do the same for Tk and Tk extensions that require the Tk libraries !if $(DOING_TK) || $(NEED_TK) WISHNAMEPREFIX = wish WISHNAME = $(WISHNAMEPREFIX)$(TK_VERSION)$(SUFX).exe TKLIBNAME8 = tk$(TK_VERSION)$(SUFX).$(EXT) TKLIBNAME9 = tcl9tk$(TK_VERSION)$(SUFX).$(EXT) !if $(TCL_MAJOR_VERSION) == 8 TKLIBNAME = tk$(TK_VERSION)$(SUFX).$(EXT) TKIMPLIBNAME = tk$(TK_VERSION)$(SUFX).lib !else TKLIBNAME = tcl9tk$(TK_VERSION)$(SUFX).$(EXT) TKIMPLIBNAME = tcl9tk$(TK_VERSION)$(SUFX).lib !endif TKSTUBLIBNAME = tkstub$(TK_VERSION).lib !if $(DOING_TK) WISH = $(OUT_DIR)\$(WISHNAME) TKSTUBLIB = $(OUT_DIR)\$(TKSTUBLIBNAME) TKIMPLIB = $(OUT_DIR)\$(TKIMPLIBNAME) TKLIB = $(OUT_DIR)\$(TKLIBNAME) TK_INCLUDES = -I"$(WIN_DIR)" -I"$(GENERICDIR)" TKSCRIPTZIP = $(OUT_DIR)\$(TKSCRIPTZIPNAME) !else # effectively NEED_TK !if $(TKINSTALL) # Building against installed Tk WISH = $(_TKDIR)\bin\$(WISHNAME) TKSTUBLIB = $(_TKDIR)\lib\$(TKSTUBLIBNAME) TKIMPLIB = $(_TKDIR)\lib\$(TKIMPLIBNAME) # When building extensions, may be linking against Tk that does not add # "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility. !if !exist("$(TKIMPLIB)") TKIMPLIBNAME = tk$(TK_VERSION)$(SUFX:t=).lib TKIMPLIB = $(_TKDIR)\lib\$(TKIMPLIBNAME) !endif TK_INCLUDES = -I"$(_TKDIR)\include" TKSCRIPTZIP = $(_TKDIR)\lib\$(TKSCRIPTZIPNAME) !else # Building against Tk sources WISH = $(_TKDIR)\win\$(BUILDDIRTOP)\$(WISHNAME) TKSTUBLIB = $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKSTUBLIBNAME) TKIMPLIB = $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKIMPLIBNAME) # When building extensions, may be linking against Tk that does not add # "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility. !if !exist("$(TKIMPLIB)") TKIMPLIBNAME = tk$(TK_VERSION)$(SUFX:t=).lib TKIMPLIB = $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKIMPLIBNAME) !endif TK_INCLUDES = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib" TKSCRIPTZIP = $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKSCRIPTZIPNAME) !endif # TKINSTALL tklibs = "$(TKSTUBLIB)" "$(TKIMPLIB)" !endif # $(DOING_TK) !endif # $(DOING_TK) || $(NEED_TK) # Various output paths PRJIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib PRJLIBNAME8 = $(PROJECT)$(VERSION)$(SUFX).$(EXT) PRJLIBNAME9 = tcl9$(PROJECT)$(VERSION)$(SUFX).$(EXT) !if $(TCL_MAJOR_VERSION) == 8 PRJLIBNAME = $(PRJLIBNAME8) !else PRJLIBNAME = $(PRJLIBNAME9) !endif PRJLIB = $(OUT_DIR)\$(PRJLIBNAME) PRJSTUBLIBNAME = $(STUBPREFIX)$(VERSION).lib PRJSTUBLIB = $(OUT_DIR)\$(PRJSTUBLIBNAME) # If extension parent makefile has not defined a resource definition file, # we will generate one from standard template. !if !$(DOING_TCL) && !$(DOING_TK) && !$(STATIC_BUILD) !ifdef RCFILE RESFILE = $(TMP_DIR)\$(RCFILE:.rc=.res) !else RESFILE = $(TMP_DIR)\$(PROJECT).res !endif !endif ################################################################### # 11. Construct the paths for the installation directories # The following macros get defined in this section: # LIB_INSTALL_DIR - where libraries should be installed # BIN_INSTALL_DIR - where the executables should be installed # DOC_INSTALL_DIR - where documentation should be installed # SCRIPT_INSTALL_DIR - where scripts should be installed # INCLUDE_INSTALL_DIR - where C include files should be installed # DEMO_INSTALL_DIR - where demos should be installed # PRJ_INSTALL_DIR - where package will be installed (not set for Tcl and Tk) !if $(DOING_TCL) || $(DOING_TK) LIB_INSTALL_DIR = $(_INSTALLDIR)\lib BIN_INSTALL_DIR = $(_INSTALLDIR)\bin DOC_INSTALL_DIR = $(_INSTALLDIR)\doc !if $(DOING_TCL) SCRIPT_INSTALL_DIR = $(_INSTALLDIR)\lib\$(PROJECT)$(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION) MODULE_INSTALL_DIR = $(_INSTALLDIR)\lib\tcl$(TCL_MAJOR_VERSION) !else # DOING_TK SCRIPT_INSTALL_DIR = $(_INSTALLDIR)\lib\$(PROJECT)$(TK_MAJOR_VERSION).$(TK_MINOR_VERSION) !endif DEMO_INSTALL_DIR = $(SCRIPT_INSTALL_DIR)\demos INCLUDE_INSTALL_DIR = $(_INSTALLDIR)\include !else # extension other than Tk PRJ_INSTALL_DIR = $(_INSTALLDIR)\$(PROJECT)$(DOTVERSION) !if $(MULTIPLATFORM_INSTALL) LIB_INSTALL_DIR = $(PRJ_INSTALL_DIR)\$(PLATFORM_IDENTIFY) BIN_INSTALL_DIR = $(PRJ_INSTALL_DIR)\$(PLATFORM_IDENTIFY) !else LIB_INSTALL_DIR = $(PRJ_INSTALL_DIR) BIN_INSTALL_DIR = $(PRJ_INSTALL_DIR) !endif DOC_INSTALL_DIR = $(PRJ_INSTALL_DIR) SCRIPT_INSTALL_DIR = $(PRJ_INSTALL_DIR) DEMO_INSTALL_DIR = $(PRJ_INSTALL_DIR)\demos INCLUDE_INSTALL_DIR = $(_INSTALLDIR)\..\include !endif ################################################################### # 12. Set up actual options to be passed to the compiler and linker # Now we have all the information we need, set up the actual flags and # options that we will pass to the compiler and linker. The main # makefile should use these in combination with whatever other flags # and switches are specific to it. # The following macros are defined, names are for historical compatibility: # OPTDEFINES - /Dxxx C macro flags based on user-specified OPTS # COMPILERFLAGS - /Dxxx C macro flags independent of any configuration opttions # crt - Compiler switch that selects the appropriate C runtime # cdebug - Compiler switches related to debug AND optimizations # cwarn - Compiler switches that set warning levels # cflags - complete compiler switches (subsumes cdebug and cwarn) # ldebug - Linker switches controlling debug information and optimization # lflags - complete linker switches (subsumes ldebug) except subsystem type # dlllflags - complete linker switches to build DLLs (subsumes lflags) # conlflags - complete linker switches for console program (subsumes lflags) # guilflags - complete linker switches for GUI program (subsumes lflags) # baselibs - minimum Windows libraries required. Parent makefile can # define PRJ_LIBS before including rules.rc if additional libs are needed OPTDEFINES = /DSTDC_HEADERS /DUSE_NMAKE=1 !if $(VCVERSION) > 1600 OPTDEFINES = $(OPTDEFINES) /DHAVE_STDINT_H=1 !else OPTDEFINES = $(OPTDEFINES) /DMP_NO_STDINT=1 !endif !if $(VCVERSION) >= 1800 OPTDEFINES = $(OPTDEFINES) /DHAVE_INTTYPES_H=1 /DHAVE_STDBOOL_H=1 !endif !if $(TCL_MEM_DEBUG) OPTDEFINES = $(OPTDEFINES) /DTCL_MEM_DEBUG !endif !if $(TCL_COMPILE_DEBUG) OPTDEFINES = $(OPTDEFINES) /DTCL_COMPILE_DEBUG /DTCL_COMPILE_STATS !endif !if $(TCL_THREADS) && $(TCL_VERSION) < 87 OPTDEFINES = $(OPTDEFINES) /DTCL_THREADS=1 !if $(USE_THREAD_ALLOC) && $(TCL_VERSION) < 87 OPTDEFINES = $(OPTDEFINES) /DUSE_THREAD_ALLOC=1 !endif !endif !if $(STATIC_BUILD) OPTDEFINES = $(OPTDEFINES) /DSTATIC_BUILD !elseif $(TCL_VERSION) > 86 OPTDEFINES = $(OPTDEFINES) /DTCL_WITH_EXTERNAL_TOMMATH !if "$(MACHINE)" == "AMD64" || "$(MACHINE)" == "ARM64" OPTDEFINES = $(OPTDEFINES) /DMP_64BIT !endif !endif !if $(TCL_NO_DEPRECATED) OPTDEFINES = $(OPTDEFINES) /DTCL_NO_DEPRECATED !endif !if $(USE_STUBS) # Note we do not define USE_TCL_STUBS even when building tk since some # test targets in tk do not use stubs !if !$(DOING_TCL) USE_STUBS_DEFS = /DUSE_TCL_STUBS /DUSE_TCLOO_STUBS !if $(NEED_TK) USE_STUBS_DEFS = $(USE_STUBS_DEFS) /DUSE_TK_STUBS !endif !endif !endif # USE_STUBS !if !$(DEBUG) OPTDEFINES = $(OPTDEFINES) /DNDEBUG !if $(OPTIMIZING) OPTDEFINES = $(OPTDEFINES) /DTCL_CFG_OPTIMIZED !endif !endif !if $(PROFILE) OPTDEFINES = $(OPTDEFINES) /DTCL_CFG_PROFILED !endif !if "$(MACHINE)" == "AMD64" || "$(MACHINE)" == "ARM64" OPTDEFINES = $(OPTDEFINES) /DTCL_CFG_DO64BIT !endif !if $(VCVERSION) < 1300 OPTDEFINES = $(OPTDEFINES) /DNO_STRTOI64=1 !endif !if "$(TCL_MAJOR_VERSION)" == "8" !if "$(_USE_64BIT_TIME_T)" == "1" OPTDEFINES = $(OPTDEFINES) /D_USE_64BIT_TIME_T=1 !endif # _ATL_XP_TARGETING - Newer SDK's need this to build for XP COMPILERFLAGS = /D_ATL_XP_TARGETING !endif !if "$(TCL_UTF_MAX)" == "3" OPTDEFINES = $(OPTDEFINES) /DTCL_UTF_MAX=3 !endif # Like the TEA system only set this non empty for non-Tk extensions # Note: some extensions use PACKAGE_NAME and others use PACKAGE_TCLNAME # so we pass both !if !$(DOING_TCL) && !$(DOING_TK) PKGNAMEFLAGS = /DPACKAGE_NAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \ /DPACKAGE_TCLNAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \ /DPACKAGE_VERSION="\"$(DOTVERSION)\"" \ /DMODULE_SCOPE=extern !endif # crt picks the C run time based on selected OPTS !if $(MSVCRT) !if $(DEBUG) && !$(UNCHECKED) crt = -MDd !else crt = -MD !endif !else !if $(DEBUG) && !$(UNCHECKED) crt = -MTd !else crt = -MT !endif !endif # cdebug includes compiler options for debugging as well as optimization. !if $(DEBUG) # In debugging mode, optimizations need to be disabled cdebug = -Zi -Od $(DEBUGFLAGS) !else cdebug = $(OPTIMIZATIONS) !if $(SYMBOLS) cdebug = $(cdebug) -Zi !endif !endif # $(DEBUG) # cwarn includes default warning levels, also C4090 (buggy) and C4146 is useless. cwarn = $(WARNINGS) -wd4090 -wd4146 !if "$(MACHINE)" == "AMD64" || "$(MACHINE)" == "ARM64" # Disable pointer<->int warnings related to cast between different sizes # There are a gadzillion of these due to use of ClientData and # clutter up compiler # output increasing chance of a real warning getting lost. So disable them. # Eventually some day, Tcl will be 64-bit clean. cwarn = $(cwarn) -wd4311 -wd4312 !endif ### Common compiler options that are architecture specific !if "$(MACHINE)" == "ARM" carch = /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE !else carch = !endif # cpuid is only available on intel machines !if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "AMD64" carch = $(carch) /DHAVE_CPUID=1 !endif !if $(DEBUG) # Turn warnings into errors cwarn = $(cwarn) -WX !endif INCLUDES = $(TCL_INCLUDES) $(TK_INCLUDES) $(PRJ_INCLUDES) !if !$(DOING_TCL) && !$(DOING_TK) INCLUDES = $(INCLUDES) -I"$(GENERICDIR)" -I"$(WIN_DIR)" -I"$(COMPATDIR)" !endif # These flags are defined roughly in the order of the pre-reform # rules.vc/makefile.vc to help visually compare that the pre- and # post-reform build logs # cflags contains generic flags used for building practically all object files cflags = -nologo -c $(COMPILERFLAGS) $(carch) $(cwarn) -Fp$(TMP_DIR)^\ $(cdebug) # appcflags contains $(cflags) and flags for building the application # object files (e.g. tclsh, or wish) pkgcflags contains $(cflags) plus # flags used for building shared object files The two differ in the # BUILD_$(PROJECT) macro which should be defined only for the shared # library *implementation* and not for its caller interface appcflags_nostubs = $(cflags) $(crt) $(INCLUDES) $(TCL_DEFINES) $(PRJ_DEFINES) $(OPTDEFINES) appcflags = $(appcflags_nostubs) $(USE_STUBS_DEFS) pkgcflags = $(appcflags) $(PKGNAMEFLAGS) /DBUILD_$(PROJECT) pkgcflags_nostubs = $(appcflags_nostubs) $(PKGNAMEFLAGS) /DBUILD_$(PROJECT) # stubscflags contains $(cflags) plus flags used for building a stubs # library for the package. Note: /DSTATIC_BUILD is defined in # $(OPTDEFINES) only if the OPTS configuration indicates a static # library. However the stubs library is ALWAYS static hence included # here irrespective of the OPTS setting. # # TBD - tclvfs has a comment that stubs libs should not be compiled with -GL # without stating why. Tcl itself compiled stubs libs with this flag. # so we do not remove it from cflags. -GL may prevent extensions # compiled with one VC version to fail to link against stubs library # compiled with another VC version. Check for this and fix accordingly. stubscflags = $(cflags) $(PKGNAMEFLAGS) $(PRJ_DEFINES) $(OPTDEFINES) /Zl /GL- /DSTATIC_BUILD $(INCLUDES) $(USE_STUBS_DEFS) # Link flags !if $(DEBUG) ldebug = -debug -debugtype:cv !else ldebug = -release -opt:ref -opt:icf,3 !if $(SYMBOLS) ldebug = $(ldebug) -debug -debugtype:cv !endif !endif # Note: Profiling is currently only possible with the Visual Studio Enterprise !if $(PROFILE) ldebug= $(ldebug) -profile !endif ### Declarations common to all linker versions lflags = -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug) !if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900 lflags = $(lflags) -nodefaultlib:libucrt.lib !endif dlllflags = $(lflags) -dll conlflags = $(lflags) -subsystem:console guilflags = $(lflags) -subsystem:windows # Libraries that are required for every image. # Extensions should define any additional libraries with $(PRJ_LIBS) winlibs = kernel32.lib advapi32.lib !if $(NEED_TK) winlibs = $(winlibs) gdi32.lib user32.lib uxtheme.lib !endif # Avoid 'unresolved external symbol __security_cookie' errors. # c.f. http://support.microsoft.com/?id=894573 !if "$(MACHINE)" == "AMD64" !if $(VCVERSION) > 1399 && $(VCVERSION) < 1500 winlibs = $(winlibs) bufferoverflowU.lib !endif !endif baselibs = $(winlibs) $(PRJ_LIBS) !if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900 baselibs = $(baselibs) ucrt.lib !endif ################################################################ # 13. Define standard commands, common make targets and implicit rules CCPKGCMD = $(cc32) $(pkgcflags) -Fo$(TMP_DIR)^\ CCAPPCMD = $(cc32) $(appcflags) -Fo$(TMP_DIR)^\ CCSTUBSCMD = $(cc32) $(stubscflags) -Fo$(TMP_DIR)^\ LIBCMD = $(lib32) -nologo $(LINKERFLAGS) -out:$@ DLLCMD = $(link32) $(dlllflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs) CONEXECMD = $(link32) $(conlflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs) GUIEXECMD = $(link32) $(guilflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs) RESCMD = $(rc32) -fo $@ -r -i "$(GENERICDIR)" -i "$(TMP_DIR)" \ $(TCL_INCLUDES) \ /DDEBUG=$(DEBUG) -d UNCHECKED=$(UNCHECKED) \ /DCOMMAVERSION=$(RCCOMMAVERSION) \ /DDOTVERSION=\"$(DOTVERSION)\" \ /DVERSION=\"$(VERSION)\" \ /DSUFX=\"$(SUFX)\" \ /DPROJECT=\"$(PROJECT)\" \ /DPRJLIBNAME=\"$(PRJLIBNAME)\" !ifndef DEFAULT_BUILD_TARGET DEFAULT_BUILD_TARGET = $(PROJECT) !endif default-target: $(DEFAULT_BUILD_TARGET) !if $(MULTIPLATFORM_INSTALL) default-pkgindex: @echo if {[package vsatisfies [package provide Tcl] 9.0-]} { > $(OUT_DIR)\pkgIndex.tcl @echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \ [list load [file join $$dir $(PLATFORM_IDENTIFY) $(PRJLIBNAME9)]] >> $(OUT_DIR)\pkgIndex.tcl @echo } else { >> $(OUT_DIR)\pkgIndex.tcl @echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \ [list load [file join $$dir $(PLATFORM_IDENTIFY) $(PRJLIBNAME8)]] >> $(OUT_DIR)\pkgIndex.tcl @echo } >> $(OUT_DIR)\pkgIndex.tcl !else default-pkgindex: @echo if {[package vsatisfies [package provide Tcl] 9.0-]} { > $(OUT_DIR)\pkgIndex.tcl @echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \ [list load [file join $$dir $(PRJLIBNAME9)]] >> $(OUT_DIR)\pkgIndex.tcl @echo } else { >> $(OUT_DIR)\pkgIndex.tcl @echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \ [list load [file join $$dir $(PRJLIBNAME8)]] >> $(OUT_DIR)\pkgIndex.tcl @echo } >> $(OUT_DIR)\pkgIndex.tcl !endif default-pkgindex-tea: @if exist $(ROOT)\pkgIndex.tcl.in nmakehlp -s << $(ROOT)\pkgIndex.tcl.in > $(OUT_DIR)\pkgIndex.tcl @PACKAGE_VERSION@ $(DOTVERSION) @PACKAGE_NAME@ $(PRJ_PACKAGE_TCLNAME) @PACKAGE_TCLNAME@ $(PRJ_PACKAGE_TCLNAME) @PKG_LIB_FILE@ $(PRJLIBNAME) @PKG_LIB_FILE8@ $(PRJLIBNAME8) @PKG_LIB_FILE9@ $(PRJLIBNAME9) << default-install: default-install-binaries default-install-libraries !if $(SYMBOLS) default-install: default-install-pdbs !endif # Again to deal with historical brokenness, there is some confusion # in terminlogy. For extensions, the "install-binaries" was used to # locate target directory for *binary shared libraries* and thus # the appropriate macro is LIB_INSTALL_DIR since BIN_INSTALL_DIR is # for executables (exes). On the other hand the "install-libraries" # target is for *scripts* and should have been called "install-scripts". default-install-binaries: $(PRJLIB) @echo Installing binaries to '$(LIB_INSTALL_DIR)' @if not exist "$(LIB_INSTALL_DIR)" mkdir "$(LIB_INSTALL_DIR)" @$(CPY) $(PRJLIB) "$(LIB_INSTALL_DIR)" >NUL # Alias for default-install-scripts default-install-libraries: default-install-scripts default-install-scripts: $(OUT_DIR)\pkgIndex.tcl @echo Installing libraries to '$(SCRIPT_INSTALL_DIR)' @if exist $(LIBDIR) $(CPY) $(LIBDIR)\*.tcl "$(SCRIPT_INSTALL_DIR)" @echo Installing package index in '$(SCRIPT_INSTALL_DIR)' @$(CPY) $(OUT_DIR)\pkgIndex.tcl $(SCRIPT_INSTALL_DIR) default-install-stubs: @echo Installing stubs library to '$(SCRIPT_INSTALL_DIR)' @if not exist "$(SCRIPT_INSTALL_DIR)" mkdir "$(SCRIPT_INSTALL_DIR)" @$(CPY) $(PRJSTUBLIB) "$(SCRIPT_INSTALL_DIR)" >NUL default-install-pdbs: @echo Installing PDBs to '$(LIB_INSTALL_DIR)' @if not exist "$(LIB_INSTALL_DIR)" mkdir "$(LIB_INSTALL_DIR)" @$(CPY) "$(OUT_DIR)\*.pdb" "$(LIB_INSTALL_DIR)\" # "emacs font-lock highlighting fix default-install-docs-html: @echo Installing documentation files to '$(DOC_INSTALL_DIR)' @if not exist "$(DOC_INSTALL_DIR)" mkdir "$(DOC_INSTALL_DIR)" @if exist $(DOCDIR) for %f in ("$(DOCDIR)\*.html" "$(DOCDIR)\*.css" "$(DOCDIR)\*.png") do @$(COPY) %f "$(DOC_INSTALL_DIR)" default-install-docs-n: @echo Installing documentation files to '$(DOC_INSTALL_DIR)' @if not exist "$(DOC_INSTALL_DIR)" mkdir "$(DOC_INSTALL_DIR)" @if exist $(DOCDIR) for %f in ("$(DOCDIR)\*.n") do @$(COPY) %f "$(DOC_INSTALL_DIR)" default-install-demos: @echo Installing demos to '$(DEMO_INSTALL_DIR)' @if not exist "$(DEMO_INSTALL_DIR)" mkdir "$(DEMO_INSTALL_DIR)" @if exist $(DEMODIR) $(CPYDIR) "$(DEMODIR)" "$(DEMO_INSTALL_DIR)" default-clean: @echo Cleaning $(TMP_DIR)\* ... @if exist $(TMP_DIR)\nul $(RMDIR) $(TMP_DIR) @echo Cleaning $(WIN_DIR)\nmakehlp.obj, nmakehlp.exe ... @if exist $(WIN_DIR)\nmakehlp.obj del $(WIN_DIR)\nmakehlp.obj @if exist $(WIN_DIR)\nmakehlp.exe del $(WIN_DIR)\nmakehlp.exe @if exist $(WIN_DIR)\nmakehlp.out del $(WIN_DIR)\nmakehlp.out @echo Cleaning $(WIN_DIR)\nmhlp-out.txt ... @if exist $(WIN_DIR)\nmhlp-out.txt del $(WIN_DIR)\nmhlp-out.txt @echo Cleaning $(WIN_DIR)\_junk.pch ... @if exist $(WIN_DIR)\_junk.pch del $(WIN_DIR)\_junk.pch @echo Cleaning $(WIN_DIR)\vercl.x, vercl.i ... @if exist $(WIN_DIR)\vercl.x del $(WIN_DIR)\vercl.x @if exist $(WIN_DIR)\vercl.i del $(WIN_DIR)\vercl.i @echo Cleaning $(WIN_DIR)\versions.vc, version.vc ... @if exist $(WIN_DIR)\versions.vc del $(WIN_DIR)\versions.vc @if exist $(WIN_DIR)\version.vc del $(WIN_DIR)\version.vc default-hose: default-clean @echo Hosing $(OUT_DIR)\* ... @if exist $(OUT_DIR)\nul $(RMDIR) $(OUT_DIR) # Only for backward compatibility default-distclean: default-hose default-setup: @if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR) @if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR) !if "$(TESTPAT)" != "" TESTFLAGS = $(TESTFLAGS) -file $(TESTPAT) !endif default-test: default-setup $(PROJECT) @set TCLLIBPATH=$(OUT_DIR:\=/) @if exist $(LIBDIR) for %f in ("$(LIBDIR)\*.tcl") do @$(COPY) %f "$(OUT_DIR)" cd "$(TESTDIR)" && $(DEBUGGER) $(TCLSH) all.tcl $(TESTFLAGS) default-shell: default-setup $(PROJECT) @set TCLLIBPATH=$(OUT_DIR:\=/) @if exist $(LIBDIR) for %f in ("$(LIBDIR)\*.tcl") do @$(COPY) %f "$(OUT_DIR)" $(DEBUGGER) $(TCLSH) # Generation of Windows version resource !ifdef RCFILE # Note: don't use $** in below rule because there may be other dependencies # and only the "main" rc must be passed to the resource compiler $(TMP_DIR)\$(PROJECT).res: $(RCDIR)\$(PROJECT).rc $(RESCMD) $(RCDIR)\$(PROJECT).rc !else # If parent makefile has not defined a resource definition file, # we will generate one from standard template. $(TMP_DIR)\$(PROJECT).res: $(TMP_DIR)\$(PROJECT).rc $(TMP_DIR)\$(PROJECT).rc: @$(COPY) << $(TMP_DIR)\$(PROJECT).rc #include VS_VERSION_INFO VERSIONINFO FILEVERSION COMMAVERSION PRODUCTVERSION COMMAVERSION FILEFLAGSMASK 0x3fL #ifdef DEBUG FILEFLAGS VS_FF_DEBUG #else FILEFLAGS 0x0L #endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "Tcl extension " PROJECT VALUE "OriginalFilename", PRJLIBNAME VALUE "FileVersion", DOTVERSION VALUE "ProductName", "Package " PROJECT " for Tcl" VALUE "ProductVersion", DOTVERSION END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END << !endif # ifdef RCFILE !ifndef DISABLE_IMPLICIT_RULES DISABLE_IMPLICIT_RULES = 0 !endif !if !$(DISABLE_IMPLICIT_RULES) # Implicit rule definitions - only for building library objects. For stubs and # main application, the makefile should define explicit rules. {$(ROOT)}.c{$(TMP_DIR)}.obj:: $(CCPKGCMD) @<< $< << {$(WIN_DIR)}.c{$(TMP_DIR)}.obj:: $(CCPKGCMD) @<< $< << {$(GENERICDIR)}.c{$(TMP_DIR)}.obj:: $(CCPKGCMD) @<< $< << {$(COMPATDIR)}.c{$(TMP_DIR)}.obj:: $(CCPKGCMD) @<< $< << {$(RCDIR)}.rc{$(TMP_DIR)}.res: $(RESCMD) $< {$(WIN_DIR)}.rc{$(TMP_DIR)}.res: $(RESCMD) $< {$(TMP_DIR)}.rc{$(TMP_DIR)}.res: $(RESCMD) $< .SUFFIXES: .SUFFIXES:.c .rc !endif ################################################################ # 14. Sanity check selected options against Tcl build options # When building an extension, certain configuration options should # match the ones used when Tcl was built. Here we check and # warn on a mismatch. !if !$(DOING_TCL) !if $(TCLINSTALL) # Building against an installed Tcl !if exist("$(_TCLDIR)\lib\nmake\tcl.nmake") TCLNMAKECONFIG = "$(_TCLDIR)\lib\nmake\tcl.nmake" !endif !else # !$(TCLINSTALL) - building against Tcl source !if exist("$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl.nmake") TCLNMAKECONFIG = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl.nmake" !endif !endif # TCLINSTALL !if $(CONFIG_CHECK) !ifdef TCLNMAKECONFIG !include $(TCLNMAKECONFIG) !if defined(CORE_MACHINE) && "$(CORE_MACHINE)" != "$(MACHINE)" !error ERROR: Build target ($(MACHINE)) does not match the Tcl library architecture ($(CORE_MACHINE)). !endif !if $(TCL_VERSION) < 87 && defined(CORE_USE_THREAD_ALLOC) && $(CORE_USE_THREAD_ALLOC) != $(USE_THREAD_ALLOC) !message WARNING: Value of USE_THREAD_ALLOC ($(USE_THREAD_ALLOC)) does not match its Tcl core value ($(CORE_USE_THREAD_ALLOC)). !endif !if defined(CORE_DEBUG) && $(CORE_DEBUG) != $(DEBUG) !message WARNING: Value of DEBUG ($(DEBUG)) does not match its Tcl library configuration ($(DEBUG)). !endif !endif !endif # TCLNMAKECONFIG !endif # !$(DOING_TCL) #---------------------------------------------------------- # Display stats being used. #---------------------------------------------------------- !if !$(DOING_TCL) !message *** Building against Tcl at '$(_TCLDIR)' !endif !if !$(DOING_TK) && $(NEED_TK) !message *** Building against Tk at '$(_TKDIR)' !endif !message *** Intermediate directory will be '$(TMP_DIR)' !message *** Output directory will be '$(OUT_DIR)' !message *** Installation, if selected, will be in '$(_INSTALLDIR)' !message *** Suffix for binaries will be '$(SUFX)' !message *** Compiler version $(VCVER). Target $(MACHINE), host $(NATIVE_ARCH). !endif # ifdef _RULES_VC tdom-0.9.5-src/win/pkgIndex.tcl0000644000175000017500000000056114703531020015012 0ustar rolfrolf# # Tcl package index file # if {[package vsatisfies [package provide Tcl] 9.0-]} { package ifneeded tdom 0.9.5 \ "[list load [file join $dir tcl9tdom094.dll]]; [list source [file join $dir tdom.tcl]]" } else { package ifneeded tdom 0.9.5 \ "[list load [file join $dir tdom094.dll]]; [list source [file join $dir tdom.tcl]]" } tdom-0.9.5-src/win/README0000644000175000017500000001310014703531020013406 0ustar rolfrolfThis file contains instructions for building tdom on Windows platforms. Windows builds may be done with either the MingW-W64 tool chain comprising of gcc and friends, or with the Microsoft Visual C++ and nmake tools. Each is described below. IMPORTANT NOTE: Building with either tool chain requires that the Tcl libraries that are linked have also been built with the same tool chain. The resulting binaries however can be loaded into a Tcl shell compiled with any tool chain provided the requisite C runtimes are present on the system. Building With The Mingw-W64 Tool Chain ====================================== Building with the MingW follows a similar process to the autoconf/TEA based Unix builds. 1. Start a shell using mingw32.exe or mingw64.exe for 32- and 64-bit fields respectively. Do NOT use msys2.exe directly. 2. Assuming you want to include HTML5 support using the Gumbo libraries, build the Gumbo libraries by running these commands in the top level directory where you extracted the Gumbo distribution. Note these shell commands must be run in the mingw32.exe or mingw64.exe shells as appropriate. ./autogen.sh ./configure make make install This will install the Gumbo libraries in the mingw32/mingw64 system directories as appropriate. 3. Change to a build directory and run the configure at the top level tdom directory. For example, if doing a 64-bit build in the win/build64 directory within a mingw64.exe shell, mkdir win/build cd win/build ../../configure --enable-threads --enable-html5 --enable-64bit --prefix=/c/tcl/mingw/85/x64 --with-tcl=/c/tcl/mingw/85/x64/lib make make install In the above sequence, we are building against Tcl 8.5 installed under c:\tcl\mingw\85\x64 on the system. The Gumbo libraries built in the previous step are automatically picked up from the mingw64.exe directories. Note that tdom on Windows binds against the static Gumbo library so there is no additional DLL to distribute. The 32-bit build is similar except omitting the --enable-64bit option (and of course pointing configure to a 32-bit installation of Tcl. 4. Build the tnc and tdomhtml extensions in similar fashion to the above except that the --enable-html5 option should be left out in both cases, and an additional option --with-tdom=path/to/tdom/build needs to be specified for the tnc configure step. IMPORTANT NOTE: Because the MinGW-built binaries link to the msvcrt 6.0 runtimes that is present on all Windows systems, the built tdom is usable on all Windows systems with a Tcl built with any tool chain without needing additional runtime libraries to be installed. Building with Visual Studio 2017 Community Edition (free) ========================================================= 1. Build the Gumbo libraries if HTML5 support is desired. 1a. Check out the git repository from https://github.com/apnadkarni/gumbo-parser. Do NOT use the original Gumbo repository as that does not contain a complete Visual Studio project file required for tdom. 1b. Switch to the tdom-libs branch. Open the visualc/gumbo.sln solution file in Visual Studio. Click the Batch Build... item under the Build menu. In the dialog box, select the Win32|Release|x86 and x64|Release|x64 project configurations and then click the Build or Rebuild button. This will build the 32-bit and 64-bit gumbo.lib libraries under visualc/Win32/Release and visualc/x64/Release respectively. 2. Next start a Visual Studio build command shell for 64-bit builds, usually from Windows Start menu->Visual Studio 2017 Folder->x64 Native Command shell 3. Change to the tdom\win directory and type the command nmake /s /nologo /f makefile.vc INSTALLDIR=c:\tcl\85-vs2017\x64 GUMBODIR=C:\src\gumbo nmake /s /nologo /f makefile.vc INSTALLDIR=c:\tcl\85-vs2017\x64 GUMBODIR=C:\src\gumbo install Here INSTALLDIR is the path to your Tcl installation and GUMBODIR is the path to the top level of the Gumbo sources. If GUMBODIR is not specified, tdom will build without HTML5 support. The 32-bit builds are similar except that - the commands need to be run from the Visual Studio x86 Native Tools command shell, and - the INSTALLDIR needs to point to a 32-bit Tcl installation - (Note GUMBODIR need not change) 4a. To build the tnc and tdomhtml extensions, cd extensions/tnc/win nmake /s /nologo /f makefile.vc INSTALLDIR=c:\tcl\85-vs2017\x64 nmake /s /nologo /f makefile.vc INSTALLDIR=c:\tcl\85-vs2017\x64 install cd extensions/tdomhtml/win nmake /s /nologo /f makefile.vc INSTALLDIR=c:\tcl\85-vs2017\x64 install Note no build step necessary for tdomhtml as it is pure Tcl. Similar steps for 32-bit builds with appropriate changes. IMPORTANT NOTE: The Visual Studio 2017 runtimes are not guaranteed to be installed on all Windows systems. Thus the built tdom package should only be used with a Tcl that is also built with Visual Studio 2017. # Building with Visual C++ 6 (32-bit) or Windows 2003 SDK (for 64-bit) ====================================================================== Building with Visual C++ 6 with the included expat isn't any more possible, because expat dropped support for this. If you still want to build with this toolset use an expat version prior to 2.2.8. Steps similar to above except that HTML5 support is not available due to Gumbo needing C99 support. The GUMBODIR option should be left out on the nmake build commands. IMPORTANT NOTE: Because the VC++ 6 and 2003 SDK link to the msvcrt 6.0 runtimes that is present on all Windows systems, the built tdom is usable on all Windows systems with a Tcl built with any tool chain without needing additional runtime libraries to be installed. tdom-0.9.5-src/win/makefile.vc0000644000175000017500000000532614703531020014650 0ustar rolfrolf#------------------------------------------------------------- -*- makefile -*- # # Makefile for tdom # # For basic build instructions see the README in this directory. # # For other build options (debug, static etc.), # See TIP 477 (https://core.tcl.tk/tips/doc/trunk/tip/477.md) for # detailed documentation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # #------------------------------------------------------------------------------ PROJECT = tdom PRJ_RCFILE = tdom.rc !if [echo VERSIONHASH = \> nmakehlp.out] \ || [type ..\manifest.uuid >> nmakehlp.out] !error *** Could not retrieve VERSIONHASH. !endif !include nmakehlp.out !include "rules-ext.vc" EXPATDIR = ..\expat PRJ_OBJS = \ $(TMP_DIR)\xmlrole.obj \ $(TMP_DIR)\xmltok.obj \ $(TMP_DIR)\xmlparse.obj \ $(TMP_DIR)\xmlsimple.obj \ $(TMP_DIR)\dom.obj \ $(TMP_DIR)\domhtml.obj \ $(TMP_DIR)\domhtml5.obj \ $(TMP_DIR)\domxslt.obj \ $(TMP_DIR)\nodecmd.obj \ $(TMP_DIR)\domxpath.obj \ $(TMP_DIR)\domlock.obj \ $(TMP_DIR)\domjson.obj \ $(TMP_DIR)\tclexpat.obj \ $(TMP_DIR)\tcldom.obj \ $(TMP_DIR)\tclpull.obj \ $(TMP_DIR)\datatypes.obj \ $(TMP_DIR)\schema.obj \ $(TMP_DIR)\tdomStubInit.obj\ $(TMP_DIR)\tdomStubLib.obj \ $(TMP_DIR)\tdominit.obj PRJ_STUBOBJS = $(TMP_DIR)\tdomStubLib.obj PRJ_DEFINES = \ -D _CRT_SECURE_NO_DEPRECATE -D _CRT_NONSTDC_NO_DEPRECATE \ -DHAVE_MEMMOVE -DXML_DTD=1 -DXML_NS=1 -DTDOM_NO_UNKNOWN_CMD=1 \ -DXML_GE=1 -DXML_CONTEXT_BYTES=0 -DUSE_NORMAL_ALLOCATOR \ -DXML_LARGE_SIZE=1 -DXMLIMPORT=__declspec(dllexport) # TBD - some of the code, like expat checks for Windows using the # WIN32 macro. This should really be changed to check _WIN32. For now, # define WIN32 ourselves PRJ_DEFINES = $(PRJ_DEFINES) -DWIN32 PRJ_INCLUDES = -I"$(EXPATDIR)" -I"$(TMP_DIR)" !if "$(GUMBODIR)" != "" PRJ_DEFINES = $(PRJ_DEFINES) -DTDOM_HAVE_GUMBO=1 PRJ_INCLUDES = $(PRJ_INCLUDES) -I"$(GUMBODIR)\src" !if "$(MACHINE)" == "AMD64" baselibs = $(baselibs) "$(GUMBODIR)\visualc\x64\Release\gumbo.lib" !else baselibs = $(baselibs) "$(GUMBODIR)\visualc\Win32\Release\gumbo.lib" !endif !endif # GUMBODIR !include "$(_RULESDIR)\targets.vc" $(TMP_DIR)\tcldom.obj: $(TMP_DIR)\versionhash.h $(TMP_DIR)\versionhash.h: $(ROOT)\manifest.uuid echo #define FOSSIL_HASH "$(VERSIONHASH)" > $(TMP_DIR)\versionhash.h install: default-install-docs-html default-install-stubs {$(EXPATDIR)}.c{$(TMP_DIR)}.obj:: $(CCPKGCMD) @<< $< << pkgindex: @type << >"$(OUT_DIR)\pkgIndex.tcl" package ifneeded $(PROJECT) $(DOTVERSION) "[list load [file join $$dir $(PRJLIBNAME)] Tdom]; [list source [file join $$dir tdom.tcl]]" << tdom-0.9.5-src/win/config.h0000644000175000017500000000005014703531020014144 0ustar rolfrolf/* an empty/fake config.h for expat */ tdom-0.9.5-src/win/nmakehlp.c0000644000175000017500000005127514703531020014510 0ustar rolfrolf/* * ---------------------------------------------------------------------------- * nmakehlp.c -- * * This is used to fix limitations within nmake and the environment. * * Copyright (c) 2002 by David Gravereaux. * Copyright (c) 2006 by Pat Thoyts * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * ---------------------------------------------------------------------------- */ #define _CRT_SECURE_NO_DEPRECATE #include #define NO_SHLWAPI_GDI #define NO_SHLWAPI_STREAM #define NO_SHLWAPI_REG #include #pragma comment (lib, "user32.lib") #pragma comment (lib, "kernel32.lib") #pragma comment (lib, "shlwapi.lib") #include #include /* * This library is required for x64 builds with _some_ versions of MSVC */ #if defined(_M_IA64) || defined(_M_AMD64) #if _MSC_VER >= 1400 && _MSC_VER < 1500 #pragma comment(lib, "bufferoverflowU") #endif #endif /* ISO hack for dumb VC++ */ #ifdef _MSC_VER #define snprintf _snprintf #endif /* protos */ static int CheckForCompilerFeature(const char *option); static int CheckForLinkerFeature(const char **options, int count); static int IsIn(const char *string, const char *substring); static int SubstituteFile(const char *substs, const char *filename); static int QualifyPath(const char *path); static int LocateDependency(const char *keyfile); static const char *GetVersionFromFile(const char *filename, const char *match, int numdots); static DWORD WINAPI ReadFromPipe(LPVOID args); /* globals */ #define CHUNK 25 #define STATICBUFFERSIZE 1000 typedef struct { HANDLE pipe; char buffer[STATICBUFFERSIZE]; } pipeinfo; pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'}; pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'}; /* * exitcodes: 0 == no, 1 == yes, 2 == error */ int main( int argc, char *argv[]) { char msg[300]; DWORD dwWritten; int chars; char *s; /* * Make sure children (cl.exe and link.exe) are kept quiet. */ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); /* * Make sure the compiler and linker aren't effected by the outside world. */ SetEnvironmentVariable("CL", ""); SetEnvironmentVariable("LINK", ""); if (argc > 1 && *argv[1] == '-') { switch (*(argv[1]+1)) { case 'c': if (argc != 3) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -c \n" "Tests for whether cl.exe supports an option\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return CheckForCompilerFeature(argv[2]); case 'l': if (argc < 3) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -l ? ...?\n" "Tests for whether link.exe supports an option\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return CheckForLinkerFeature(&argv[2], argc-2); case 'f': if (argc == 2) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -f \n" "Find a substring within another\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } else if (argc == 3) { /* * If the string is blank, there is no match. */ return 0; } else { return IsIn(argv[2], argv[3]); } case 's': if (argc == 2) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -s \n" "Perform a set of string map type substutitions on a file\n" "exitcodes: 0\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return SubstituteFile(argv[2], argv[3]); case 'V': if (argc != 4) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -V filename matchstring\n" "Extract a version from a file:\n" "eg: pkgIndex.tcl \"package ifneeded http\"", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 0; } s = GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0'); if (s && *s) { printf("%s\n", s); return 0; } else return 1; /* Version not found. Return non-0 exit code */ case 'Q': if (argc != 3) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -Q path\n" "Emit the fully qualified path\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return QualifyPath(argv[2]); case 'L': if (argc != 3) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -L keypath\n" "Emit the fully qualified path of directory containing keypath\n" "exitcodes: 0 == success, 1 == not found, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return LocateDependency(argv[2]); } } chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -c|-f|-l|-Q|-s|-V ...\n" "This is a little helper app to equalize shell differences between WinNT and\n" "Win9x and get nmake.exe to accomplish its job.\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } static int CheckForCompilerFeature( const char *option) { STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; DWORD threadID; char msg[300]; BOOL ok; HANDLE hProcess, h, pipeThreads[2]; char cmdline[100]; hProcess = GetCurrentProcess(); ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = INVALID_HANDLE_VALUE; ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = FALSE; /* * Create a non-inheritible pipe. */ CreatePipe(&Out.pipe, &h, &sa, 0); /* * Dupe the write side, make it inheritible, and close the original. */ DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); /* * Same as above, but for the error side. */ CreatePipe(&Err.pipe, &h, &sa, 0); DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); /* * Base command line. */ lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X -Fp.\\_junk.pch "); /* * Append our option for testing */ lstrcat(cmdline, option); /* * Filename to compile, which exists, but is nothing and empty. */ lstrcat(cmdline, " .\\nul"); ok = CreateProcess( NULL, /* Module name. */ cmdline, /* Command line. */ NULL, /* Process handle not inheritable. */ NULL, /* Thread handle not inheritable. */ TRUE, /* yes, inherit handles. */ DETACHED_PROCESS, /* No console for you. */ NULL, /* Use parent's environment block. */ NULL, /* Use parent's starting directory. */ &si, /* Pointer to STARTUPINFO structure. */ &pi); /* Pointer to PROCESS_INFORMATION structure. */ if (!ok) { DWORD err = GetLastError(); int chars = snprintf(msg, sizeof(msg) - 1, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars], (300-chars), 0); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL); return 2; } /* * Close our references to the write handles that have now been inherited. */ CloseHandle(si.hStdOutput); CloseHandle(si.hStdError); WaitForInputIdle(pi.hProcess, 5000); CloseHandle(pi.hThread); /* * Start the pipe reader threads. */ pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID); pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID); /* * Block waiting for the process to end. */ WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); /* * Wait for our pipe to get done reading, should it be a little slow. */ WaitForMultipleObjects(2, pipeThreads, TRUE, 500); CloseHandle(pipeThreads[0]); CloseHandle(pipeThreads[1]); /* * Look for the commandline warning code in both streams. * - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002. */ return !(strstr(Out.buffer, "D4002") != NULL || strstr(Err.buffer, "D4002") != NULL || strstr(Out.buffer, "D9002") != NULL || strstr(Err.buffer, "D9002") != NULL || strstr(Out.buffer, "D2021") != NULL || strstr(Err.buffer, "D2021") != NULL); } static int CheckForLinkerFeature( const char **options, int count) { STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; DWORD threadID; char msg[300]; BOOL ok; HANDLE hProcess, h, pipeThreads[2]; int i; char cmdline[255]; hProcess = GetCurrentProcess(); ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = INVALID_HANDLE_VALUE; ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* * Create a non-inheritible pipe. */ CreatePipe(&Out.pipe, &h, &sa, 0); /* * Dupe the write side, make it inheritible, and close the original. */ DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); /* * Same as above, but for the error side. */ CreatePipe(&Err.pipe, &h, &sa, 0); DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); /* * Base command line. */ lstrcpy(cmdline, "link.exe -nologo "); /* * Append our option for testing. */ for (i = 0; i < count; i++) { lstrcat(cmdline, " \""); lstrcat(cmdline, options[i]); lstrcat(cmdline, "\""); } ok = CreateProcess( NULL, /* Module name. */ cmdline, /* Command line. */ NULL, /* Process handle not inheritable. */ NULL, /* Thread handle not inheritable. */ TRUE, /* yes, inherit handles. */ DETACHED_PROCESS, /* No console for you. */ NULL, /* Use parent's environment block. */ NULL, /* Use parent's starting directory. */ &si, /* Pointer to STARTUPINFO structure. */ &pi); /* Pointer to PROCESS_INFORMATION structure. */ if (!ok) { DWORD err = GetLastError(); int chars = snprintf(msg, sizeof(msg) - 1, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars], (300-chars), 0); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL); return 2; } /* * Close our references to the write handles that have now been inherited. */ CloseHandle(si.hStdOutput); CloseHandle(si.hStdError); WaitForInputIdle(pi.hProcess, 5000); CloseHandle(pi.hThread); /* * Start the pipe reader threads. */ pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID); pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID); /* * Block waiting for the process to end. */ WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); /* * Wait for our pipe to get done reading, should it be a little slow. */ WaitForMultipleObjects(2, pipeThreads, TRUE, 500); CloseHandle(pipeThreads[0]); CloseHandle(pipeThreads[1]); /* * Look for the commandline warning code in the stderr stream. */ return !(strstr(Out.buffer, "LNK1117") != NULL || strstr(Err.buffer, "LNK1117") != NULL || strstr(Out.buffer, "LNK4044") != NULL || strstr(Err.buffer, "LNK4044") != NULL || strstr(Out.buffer, "LNK4224") != NULL || strstr(Err.buffer, "LNK4224") != NULL); } static DWORD WINAPI ReadFromPipe( LPVOID args) { pipeinfo *pi = (pipeinfo *) args; char *lastBuf = pi->buffer; DWORD dwRead; BOOL ok; again: if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) { CloseHandle(pi->pipe); return (DWORD)-1; } ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L); if (!ok || dwRead == 0) { CloseHandle(pi->pipe); return 0; } lastBuf += dwRead; goto again; return 0; /* makes the compiler happy */ } static int IsIn( const char *string, const char *substring) { return (strstr(string, substring) != NULL); } /* * GetVersionFromFile -- * Looks for a match string in a file and then returns the version * following the match where a version is anything acceptable to * package provide or package ifneeded. */ static const char * GetVersionFromFile( const char *filename, const char *match, int numdots) { size_t cbBuffer = 100; static char szBuffer[100]; char *szResult = NULL; FILE *fp = fopen(filename, "rt"); if (fp != NULL) { /* * Read data until we see our match string. */ while (fgets(szBuffer, cbBuffer, fp) != NULL) { LPSTR p, q; p = strstr(szBuffer, match); if (p != NULL) { /* * Skip to first digit after the match. */ p += strlen(match); while (*p && !isdigit(*p)) { ++p; } /* * Find ending whitespace. */ q = p; while (*q && (strchr("0123456789.ab", *q)) && ((!strchr(".ab", *q) && (!strchr("ab", q[-1])) || --numdots))) { ++q; } memcpy(szBuffer, p, q - p); szBuffer[q-p] = 0; szResult = szBuffer; break; } } fclose(fp); } return szResult; } /* * List helpers for the SubstituteFile function */ typedef struct list_item_t { struct list_item_t *nextPtr; char * key; char * value; } list_item_t; /* insert a list item into the list (list may be null) */ static list_item_t * list_insert(list_item_t **listPtrPtr, const char *key, const char *value) { list_item_t *itemPtr = malloc(sizeof(list_item_t)); if (itemPtr) { itemPtr->key = strdup(key); itemPtr->value = strdup(value); itemPtr->nextPtr = NULL; while(*listPtrPtr) { listPtrPtr = &(*listPtrPtr)->nextPtr; } *listPtrPtr = itemPtr; } return itemPtr; } static void list_free(list_item_t **listPtrPtr) { list_item_t *tmpPtr, *listPtr = *listPtrPtr; while (listPtr) { tmpPtr = listPtr; listPtr = listPtr->nextPtr; free(tmpPtr->key); free(tmpPtr->value); free(tmpPtr); } } /* * SubstituteFile -- * As windows doesn't provide anything useful like sed and it's unreliable * to use the tclsh you are building against (consider x-platform builds - * eg compiling AMD64 target from IX86) we provide a simple substitution * option here to handle autoconf style substitutions. * The substitution file is whitespace and line delimited. The file should * consist of lines matching the regular expression: * \s*\S+\s+\S*$ * * Usage is something like: * nmakehlp -S << $** > $@ * @PACKAGE_NAME@ $(PACKAGE_NAME) * @PACKAGE_VERSION@ $(PACKAGE_VERSION) * << */ static int SubstituteFile( const char *substitutions, const char *filename) { size_t cbBuffer = 1024; static char szBuffer[1024], szCopy[1024]; char *szResult = NULL; list_item_t *substPtr = NULL; FILE *fp, *sp; fp = fopen(filename, "rt"); if (fp != NULL) { /* * Build a list of substutitions from the first filename */ sp = fopen(substitutions, "rt"); if (sp != NULL) { while (fgets(szBuffer, cbBuffer, sp) != NULL) { unsigned char *ks, *ke, *vs, *ve; ks = (unsigned char*)szBuffer; while (ks && *ks && isspace(*ks)) ++ks; ke = ks; while (ke && *ke && !isspace(*ke)) ++ke; vs = ke; while (vs && *vs && isspace(*vs)) ++vs; ve = vs; while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve; *ke = 0, *ve = 0; list_insert(&substPtr, (char*)ks, (char*)vs); } fclose(sp); } /* debug: dump the list */ #ifdef _DEBUG { int n = 0; list_item_t *p = NULL; for (p = substPtr; p != NULL; p = p->nextPtr, ++n) { fprintf(stderr, "% 3d '%s' => '%s'\n", n, p->key, p->value); } } #endif /* * Run the substitutions over each line of the input */ while (fgets(szBuffer, cbBuffer, fp) != NULL) { list_item_t *p = NULL; for (p = substPtr; p != NULL; p = p->nextPtr) { char *m = strstr(szBuffer, p->key); if (m) { char *cp, *op, *sp; cp = szCopy; op = szBuffer; while (op != m) *cp++ = *op++; sp = p->value; while (sp && *sp) *cp++ = *sp++; op += strlen(p->key); while (*op) *cp++ = *op++; *cp = 0; memcpy(szBuffer, szCopy, sizeof(szCopy)); } } printf(szBuffer); } list_free(&substPtr); } fclose(fp); return 0; } /* * QualifyPath -- * * This composes the current working directory with a provided path * and returns the fully qualified and normalized path. * Mostly needed to setup paths for testing. */ static int QualifyPath( const char *szPath) { char szCwd[MAX_PATH + 1]; char szTmp[MAX_PATH + 1]; char *p; GetCurrentDirectory(MAX_PATH, szCwd); while ((p = strchr(szPath, '/')) && *p) *p = '\\'; PathCombine(szTmp, szCwd, szPath); PathCanonicalize(szCwd, szTmp); printf("%s\n", szCwd); return 0; } /* * Implements LocateDependency for a single directory. See that command * for an explanation. * Returns 0 if found after printing the directory. * Returns 1 if not found but no errors. * Returns 2 on any kind of error * Basically, these are used as exit codes for the process. */ static int LocateDependencyHelper(const char *dir, const char *keypath) { HANDLE hSearch; char path[MAX_PATH+1]; int dirlen, keylen, ret; WIN32_FIND_DATA finfo; if (dir == NULL || keypath == NULL) return 2; /* Have no real error reporting mechanism into nmake */ dirlen = strlen(dir); if ((dirlen + 3) > sizeof(path)) return 2; strncpy(path, dir, dirlen); strncpy(path+dirlen, "\\*", 3); /* Including terminating \0 */ keylen = strlen(keypath); #if 0 /* This function is not available in Visual C++ 6 */ /* * Use numerics 0 -> FindExInfoStandard, * 1 -> FindExSearchLimitToDirectories, * as these are not defined in Visual C++ 6 */ hSearch = FindFirstFileEx(path, 0, &finfo, 1, NULL, 0); #else hSearch = FindFirstFile(path, &finfo); #endif if (hSearch == INVALID_HANDLE_VALUE) return 1; /* Not found */ /* Loop through all subdirs checking if the keypath is under there */ ret = 1; /* Assume not found */ do { int sublen; /* * We need to check it is a directory despite the * FindExSearchLimitToDirectories in the above call. See SDK docs */ if ((finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) continue; sublen = strlen(finfo.cFileName); if ((dirlen+1+sublen+1+keylen+1) > sizeof(path)) continue; /* Path does not fit, assume not matched */ strncpy(path+dirlen+1, finfo.cFileName, sublen); path[dirlen+1+sublen] = '\\'; strncpy(path+dirlen+1+sublen+1, keypath, keylen+1); if (PathFileExists(path)) { /* Found a match, print to stdout */ path[dirlen+1+sublen] = '\0'; QualifyPath(path); ret = 0; break; } } while (FindNextFile(hSearch, &finfo)); FindClose(hSearch); return ret; } /* * LocateDependency -- * * Locates a dependency for a package. * keypath - a relative path within the package directory * that is used to confirm it is the correct directory. * The search path for the package directory is currently only * the parent and grandparent of the current working directory. * If found, the command prints * name_DIRPATH= * and returns 0. If not found, does not print anything and returns 1. */ static int LocateDependency(const char *keypath) { int i, ret; static char *paths[] = {"..", "..\\..", "..\\..\\.."}; for (i = 0; i < (sizeof(paths)/sizeof(paths[0])); ++i) { ret = LocateDependencyHelper(paths[i], keypath); if (ret == 0) return ret; } return ret; } /* * Local variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * indent-tabs-mode: t * tab-width: 8 * End: */ tdom-0.9.5-src/win/targets.vc0000644000175000017500000000505614703531020014544 0ustar rolfrolf#------------------------------------------------------------- -*- makefile -*- # targets.vc -- # # Part of the nmake based build system for Tcl and its extensions. # This file defines some standard targets for the convenience of extensions # and can be optionally included by the extension makefile. # See TIP 477 (https://core.tcl-lang.org/tips/doc/main/tip/477.md) for docs. $(PROJECT): setup pkgindex $(PRJLIB) !ifdef PRJ_STUBOBJS $(PROJECT): $(PRJSTUBLIB) $(PRJSTUBLIB): $(PRJ_STUBOBJS) $(LIBCMD) $** $(PRJ_STUBOBJS): $(CCSTUBSCMD) %s !endif # PRJ_STUBOBJS !ifdef PRJ_MANIFEST $(PROJECT): $(PRJLIB).manifest $(PRJLIB).manifest: $(PRJ_MANIFEST) @nmakehlp -s << $** >$@ @MACHINE@ $(MACHINE:IX86=X86) << !endif !if "$(PROJECT)" != "tcl" && "$(PROJECT)" != "tk" $(PRJLIB): $(PRJ_OBJS) $(RESFILE) !if $(STATIC_BUILD) $(LIBCMD) $** !else $(DLLCMD) $** $(_VC_MANIFEST_EMBED_DLL) !endif -@del $*.exp !endif !if "$(PRJ_HEADERS)" != "" && "$(PRJ_OBJS)" != "" $(PRJ_OBJS): $(PRJ_HEADERS) !endif # If parent makefile has defined stub objects, add their installation # to the default install !if "$(PRJ_STUBOBJS)" != "" default-install: default-install-stubs !endif # Unlike the other default targets, these cannot be in rules.vc because # the executed command depends on existence of macro PRJ_HEADERS_PUBLIC # that the parent makefile will not define until after including rules-ext.vc !if "$(PRJ_HEADERS_PUBLIC)" != "" default-install: default-install-headers default-install-headers: @echo Installing headers to '$(INCLUDE_INSTALL_DIR)' @for %f in ($(PRJ_HEADERS_PUBLIC)) do @$(COPY) %f "$(INCLUDE_INSTALL_DIR)" !endif !if "$(DISABLE_STANDARD_TARGETS)" == "" DISABLE_STANDARD_TARGETS = 0 !endif !if "$(DISABLE_TARGET_setup)" == "" DISABLE_TARGET_setup = 0 !endif !if "$(DISABLE_TARGET_install)" == "" DISABLE_TARGET_install = 0 !endif !if "$(DISABLE_TARGET_clean)" == "" DISABLE_TARGET_clean = 0 !endif !if "$(DISABLE_TARGET_test)" == "" DISABLE_TARGET_test = 0 !endif !if "$(DISABLE_TARGET_shell)" == "" DISABLE_TARGET_shell = 0 !endif !if !$(DISABLE_STANDARD_TARGETS) !if !$(DISABLE_TARGET_setup) setup: default-setup !endif !if !$(DISABLE_TARGET_install) install: default-install !endif !if !$(DISABLE_TARGET_clean) clean: default-clean realclean: hose hose: default-hose distclean: realclean default-distclean !endif !if !$(DISABLE_TARGET_test) test: default-test !endif !if !$(DISABLE_TARGET_shell) shell: default-shell !endif !endif # DISABLE_STANDARD_TARGETS tdom-0.9.5-src/win/tdom.rc0000644000175000017500000000162514703531020014030 0ustar rolfrolf// tdom.rc - Copyright (C) 2005 Pat Thoyts // // $Id$ #include VS_VERSION_INFO VERSIONINFO FILEVERSION COMMAVERSION PRODUCTVERSION COMMAVERSION FILEFLAGSMASK 0x3fL #ifdef DEBUG FILEFLAGS VS_FF_DEBUG #else FILEFLAGS 0x0L #endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "tdom " DOTVERSION " for Windows\0" VALUE "OriginalFilename", PRJLIBNAME VALUE "FileVersion", DOTVERSION VALUE "LegalCopyright", "Copyright \251 1998-2007 Jochen Loewer, Rolf Ade, et al.\0" VALUE "ProductName", "Package" PROJECT " for Tcl" VALUE "ProductVersion", DOTVERSION END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END tdom-0.9.5-src/win/rules-ext.vc0000644000175000017500000000732414703531020015023 0ustar rolfrolf# This file should only be included in makefiles for Tcl extensions, # NOT in the makefile for Tcl itself. !ifndef _RULES_EXT_VC # We need to run from the directory the parent makefile is located in. # nmake does not tell us what makefile was used to invoke it so parent # makefile has to set the MAKEFILEVC macro or we just make a guess and # warn if we think that is not the case. !if "$(MAKEFILEVC)" == "" !if exist("$(PROJECT).vc") MAKEFILEVC = $(PROJECT).vc !elseif exist("makefile.vc") MAKEFILEVC = makefile.vc !endif !endif # "$(MAKEFILEVC)" == "" !if !exist("$(MAKEFILEVC)") MSG = ^ You must run nmake from the directory containing the project makefile.^ If you are doing that and getting this message, set the MAKEFILEVC^ macro to the name of the project makefile. !message WARNING: $(MSG) !endif !if "$(PROJECT)" == "tcl" !error The rules-ext.vc file is not intended for Tcl itself. !endif # We extract version numbers using the nmakehlp program. For now use # the local copy of nmakehlp. Once we locate Tcl, we will use that # one if it is newer. !if [$(CC) -nologo -DNDEBUG "nmakehlp.c" -link -subsystem:console > nul] !endif # First locate the Tcl directory that we are working with. !if "$(TCLDIR)" != "" _RULESDIR = $(TCLDIR:/=\) !else # If an installation path is specified, that is also the Tcl directory. # Also Tk never builds against an installed Tcl, it needs Tcl sources !if defined(INSTALLDIR) && "$(PROJECT)" != "tk" _RULESDIR=$(INSTALLDIR:/=\) !else # Locate Tcl sources !if [echo _RULESDIR = \> nmakehlp.out] \ || [nmakehlp -L generic\tcl.h >> nmakehlp.out] _RULESDIR = ..\..\tcl !else !include nmakehlp.out !endif !endif # defined(INSTALLDIR).... !endif # ifndef TCLDIR # Now look for the targets.vc file under the Tcl root. Note we check this # file and not rules.vc because the latter also exists on older systems. !if exist("$(_RULESDIR)\lib\nmake\targets.vc") # Building against installed Tcl _RULESDIR = $(_RULESDIR)\lib\nmake !elseif exist("$(_RULESDIR)\win\targets.vc") # Building against Tcl sources _RULESDIR = $(_RULESDIR)\win !else # If we have not located Tcl's targets file, most likely we are compiling # against an older version of Tcl and so must use our own support files. _RULESDIR = . !endif !if "$(_RULESDIR)" != "." # Potentially using Tcl's support files. If this extension has its own # nmake support files, need to compare the versions and pick newer. !if exist("rules.vc") # The extension has its own copy !if [echo TCL_RULES_MAJOR = \> versions.vc] \ && [nmakehlp -V "$(_RULESDIR)\rules.vc" RULES_VERSION_MAJOR >> versions.vc] !endif !if [echo TCL_RULES_MINOR = \>> versions.vc] \ && [nmakehlp -V "$(_RULESDIR)\rules.vc" RULES_VERSION_MINOR >> versions.vc] !endif !if [echo OUR_RULES_MAJOR = \>> versions.vc] \ && [nmakehlp -V "rules.vc" RULES_VERSION_MAJOR >> versions.vc] !endif !if [echo OUR_RULES_MINOR = \>> versions.vc] \ && [nmakehlp -V "rules.vc" RULES_VERSION_MINOR >> versions.vc] !endif !include versions.vc # We have a newer version of the support files, use them !if ($(TCL_RULES_MAJOR) != $(OUR_RULES_MAJOR)) || ($(TCL_RULES_MINOR) < $(OUR_RULES_MINOR)) _RULESDIR = . !endif !endif # if exist("rules.vc") !endif # if $(_RULESDIR) != "." # Let rules.vc know what copy of nmakehlp.c to use. NMAKEHLPC = $(_RULESDIR)\nmakehlp.c # Get rid of our internal defines before calling rules.vc !undef TCL_RULES_MAJOR !undef TCL_RULES_MINOR !undef OUR_RULES_MAJOR !undef OUR_RULES_MINOR !if exist("$(_RULESDIR)\rules.vc") !message *** Using $(_RULESDIR)\rules.vc !include "$(_RULESDIR)\rules.vc" !else !error *** Could not locate rules.vc in $(_RULESDIR) !endif !endif # _RULES_EXT_VCtdom-0.9.5-src/ChangeLog0000644000175000017500000026047014703531020013521 0ustar rolfrolf NOTICE: This file isn't kept up to date anymore. Look at the timeline of the leading fossil repository (http://tdom.org) or at the backup repository at https://core.tcl.tk/tdom/timeline for detailed lists of code changes. User interface changes/enhancements and other important changes will still be documented in the CHANGES file. 2012-05-17 Rolf Ade * generic/dom.h * generic/tcldom.c: Compatibility with Tcl 8.6 - Beginning with 8.6, interp->errorLine isn't public visible anymore (TIP 330). * generic/domxslt.c: Fixed wrong size on memcpy on 64 bit (when sizeof(int)!=sizeof(int*)) 2009-11-10 Rolf Ade * expat/xmltok_impl.c: Fix for possible DoS attack (see CVE-2009-3720) 2008-08-27 Rolf Ade * Makefile.in: Added missing space in target pkgIndex.tcl-hand. Thanks to Gustaf Neumann for reporting the problem and providing a fix. 2008-05-25 Rolf Ade * lib/tdom.tcl: The XPath function element-available() should, according to the rec, return true "if and only if the is the name of an instruction". That is, not for all known XSLT elements. 2008-03-04 Rolf Ade * generic/tclexpat.c: Editorial changes. * generic/domhtml.c: * generic/domxslt.c: Added a few casts, to pacify picky compliers. 2007-12-26 Rolf Ade * generic/dom.c * generic/tcldom.c: Fixed a memory leak in case of --enable-threads. 2007-10-30 Rolf Ade * generic/domhtml.c: * tests/htmlreader.test: ID Attributes in HTML documents parsed with -html do now what you expect: you find it with getElementById. 2007-10-29 Rolf Ade * doc/domNode.* * doc/domDoc.*: Fixed documentation error in the documentation of the replaceChild method. 2007-10-08 Rolf Ade * generic/domhtml.c * tests/htmlreader.test: Fixed handling of attributes without value. Now, an attribute without value gets the attribute name as value. 2007-10-04 Rolf Ade * tests/domDoc.test: Fixed test domDoc-1.2: Test was broken in case of locale != ISO-8859-1 (or -15). 2007-10-03 Rolf Ade * win/makefile.vc: makefile.vc generated a pkgIndex.tcl file, that didn't work in case of spaces in the install path. Thanks to Koen Danckaert. 2007-09-28 Rolf Ade * tests/all-bench.tcl * tests/domNode.bench * tests/xpath.bench: Added this files: Start of a benchmark suite. 2007-09-25 Rolf Ade * win/makefile.vc * win/nmakehlp.c * win/rules.vc * win/tdom.rc: Updated. (Thanks to Pat Thoyts.) * tdom.m4 * extensions/tnc/configure: Fixes tnc building against uninstalled tdom. (Thanks to Daniel A. Steffen.) 2007-08-23 Rolf Ade * generic/domxpath.c * tests/dom.test * tests/xmlsimple.test * tests/xpath.test * tests/xslt.test: Fixed bug triggered by invalid XSLT XPath pattern (normal XPath expr (via selectNodes) wasn't infected). Checked the code for similar spots and fixed a few. Replaced a fprintf(stderr, ..) called in an 'impossible' case with a more appropriate domPanic call. 2007-08-18 Rolf Ade * generic/domxslt.c: Code cleanup in document() implementation. * generic/dom.c * generic/dom.h * generic/domxslt.c * generic/tcldom.c: More constification and clean up. * generic/dom.c * generic/dom.h * generic/domalloc.c * generic/domxpath.c * generic/domxpath.h * generic/domxslt.c * generic/tcldom.c * generic/xmlsimple.c: Big const ification. 2007-08-15 Rolf Ade * configure * configure.in * unix/CONFIG * tdom.m4: New default build: --disable-tdomalloc. * CHANGES: Updated. * README * README.AOL * configure * configure-tcl8.0.5 * configure.in * tests/loadtdom.tcl * mac/Prefix/tDOMPrefix.h * mac/Prefix/tDOMPrefix_OSX.h * win/makefile.vc * win/makefile805.vc: * win/pkgIndex.tcl: Bumped version to 0.8.3. --- Release 0.8.2, 14. Aug. 2007 --- 2007-08-13 Rolf Ade * win/pkgIndex.tcl: Bumped version to 0.8.2 2007-08-12 Rolf Ade * generic/tcldom.c: Corrected a typo in the doc cmd usage message. Updated the asXML related parts of the doc and node cmd usage msg. Corrected a typo in the error msg in case of wrong # of args to asXML. * generic/tdomStubLib.c: Ensure that the new code build also with tcl8.0.x (although that old versions doesn't have extension stubs tables.) * extensions/tnc/configure * extensions/tnc/configure.in * extensions/tnc/tnc.c: Tweaks to build tnc with win/msys/mingw. * tdom.m4: Removed irritating breaks in TDOM_PATH_CONFIG. * unix/tclAppInit.c: Editorial fix. * generic/tdomStubLib.c: Rewritten from the scratch. 2007-08-11 Rolf Ade * generic/domxslt.c: Code cosmetic. * generic/tcldom.c: Updated error msg in case of wrong # of args to the asXML method to the new added option -escapeAllQuot. * generic/tdom.h * generic/tclexpat.h: Fixed build problem with the build environment win/msys/mingw. * generic/aolstub.cpp: Fixed editorial mistake in comment. * unix/tclAppInit.c: Rewritten from the scratch. New feature: tcldomsh will read ~/.tcldomshrc at start up. 2007-08-07 Rolf Ade * generic/dom.h: Another change needed, to complete the new type of domDoc->documentNumber. 2007-08-07 Rolf Ade * generic/dom.c: Type gymnastic for 64 bit systems. * generic/dom.c * generic/dom.h * generic/tcldom.c: Changed domDoc->documentNumber, domUniqueNodeNr and domUniqueDocNr to unsigned long, to prevent hard to debug / reproduce problems on 64 bit systems. * win/makefile.vc: Don't use precompiled headers. * extensions/tnc/makefile.vc: Brought in sync with tdom core. * generic/tclexpat.c: Compiler pacifying. * generic/tdomDecls.h: Fixed a wrong function signature. * generic/tdomStubLib.c: Made the compiler happy. * generic/dom.c: Corrected an error msg. * generic/tclexpat.c: Still problems on 64bit w/ -externalentitycommand. This health the biggest pain. 2007-08-05 Rolf Ade * win/makefile.vc * win/makefile805.vc: Bumped version to 0.8.2. Missed that in 0.8.2rc1 * README * README.AOL * configure * configure-tcl8.0.5 * configure.in * tests/loadtdom.tcl * mac/Prefix/tDOMPrefix.h * mac/Prefix/tDOMPrefix_OSX.h: Bumped version to 0.8.2. * generic/domhtml.c * generic/domxpath.c * generic/domxslt.c * generic/tcldom.c * generic/xmlsimple.c: Casted arg of ctype.h is* macros/function calles to unsigned char to reduce compiler warning noise. * generic/tcldom.c: * tests/domDoc.test: In case of asXML with indentation: indent XML comments as well. * doc/domNode.* * doc/domDoc.*: Added documentation to the new variable references feature of the selectNodes method, for the deleteXPathCache method and the -escapeAllQuot option of the asXML method. * generic/tcldom.c: Fixed a mem leak introduced by deleteXPathCache. Added option -escapeAllQuot to the asXML method. * generic/tcldom.c * tests/domDoc.test: Added method deleteXPathCache: basic control over the xpath expression cache. * generic/tcldom.c * generic/domxpath.c * generic/domxpath.h * generic/domxslt.c * tests/xpath.test: Variable references (at the places allowed by the XPath syntax) will now be resoved as Tcl variables, relative to the scope of the expression. Ignoring the XPath syntax rules at this point, any valid Tcl variable name will work. 2007-08-03 Rolf Ade * generic/tcldom.c: Added doc method renameNode, without XML namespace awareness. There will be a final (XML namespace aware) method implementation after 0.8.2, therefore, this will slip in as hidden or 'unsupported' and at least undocumented method. 2007-07-31 Rolf Ade * generic/domxpath.c * tests/xpath.test: Bug fix: floats in xpath expressions starting with . could have an additional (erroneous) dot in it without detection. * expat/* * extensions/tnc/tnc.c * generic/dom.c * generic/domxslt.c * generic/tcldom.c * generic/tclexpat.c * generic/tdom.decls * generic/tdom.h * generic/tdomDecls.h: Update to expat 2.0.1; minor build cosmetic. 2007-07-27 Rolf Ade * tclconfig/tcl.m4 * tclconfig/README.txt * configure.in * configure * extensions/tnc/configure.in * extensions/tnc/configure: Updated to TEA 3.6. Rebuild configure. 2007-07-25 Rolf Ade * generic/dom.c: Fix for the -externalentitycommand problems on (some) 64-bit plattforms. * tests/xpath.test: Added a few tests related to white-space in XPath expressions. 2007-07-23 Rolf Ade * generic/domhtml.c * tests/htmlreader.test: Fix for problem reported by http://tech.groups.yahoo.com/group/tdom/message/1666 2007-04-18 Rolf Ade * doc/domDoc.*: Emendation. 2007-03-03 Rolf Ade * Makefile.in: Fixed (at least for most of the cases) bug in test target, in case the user builds in a dir elsewhere. 2007-02-04 Rolf Ade * tdom.m4 * configure * extensions/tnc/configure * README * unix/CONFIG: Modified the tdom.m4 configure macros to use the current documentation style of TEA in case of configure --help. Fixed a bug in the TDOM_ENABLE_DTD. Re-generated configure and tnc configure. Added some explanations about the tDOM specific configure options to unix/CONFIG and a pointer to that information to README. * extensions/tnc/tnc.c: Minor editorial changes. * extensions/tnc/test.tcl: Fixed the loading of the tDOM scripted library in case of run with tcldomsh. * generic/domxslt.c: Fixed bug in xsl:fallback handling. 2007-02-02 Rolf Ade * tdom.m4 * configure: Corrected spelling error in tdom.m4, re-generated configure. Thanks to Larry Virden for reporting. 2007-01-16 Rolf Ade * extensions/tnc/configure.in: The build tool combination TEA/cygwin/VC++ needs a crude hack. 2007-01-10 Rolf Ade * Makefile.in: More corrections: Did not install the tDOM stubs library. Minor other corrections related to distclean. Again thanks to Andreas Kupries. * extensions/tnc/Makefile.in: Don't call target install-doc while installing - the tnc doc is in the top level doc dir. * extensions/tnc/pkgIndex.tcl.in: Fixed the name of the shared lib. Now uses @PKG_LIB_FILE@ for the dll name. 2007-01-09 Rolf Ade * Makefile.in: Did not install tdomConfig.sh anymore, which causes trouble building tDOM extensions (including tnc). Thanks to Andreas Kupries for reporting the problem with analysis. 2007-01-05 Rolf Ade * generic/domxpath.c: In XPath expressions: Whitespace between the abbreviated attribute axis specifier @ and the attribute name is allowed. 2006-11-22 Rolf Ade * generic/domhtml.c: Normalize case of attribute also (not only elements). Accept space on both sides of the = of attribute values. 2006-11-08 Rolf Ade * generic/domxpath.c * tests/xpath.test: Fixed seg fault in XPath expr parser for a certain kind of erroneous XPath expressions. 2006-08-26 Rolf Ade * CHANGES * configure.in * Makefile.in * configure * tclconfig/README.txt * tclconfig/tcl.m4 * extensions/tnc/configure.in * extensions/tnc/configure * extensions/tnc/Makefile.in: Updated the TEA build system to 3.5. 2006-05-24 Rolf Ade * generic/dom.c * tests/dom.test: Fix of the isQName method: Strings with valid prefix and non-NCNameStart char as first char after the ':' wasn't detected as invalid QName. 2006-01-08 Rolf Ade * generic/domxslt.c * tests/xslt.test: Fixed a rounding bug of format-number() (http://groups.yahoo.com/group/tdom/message/1217). 2006-01-06 Rolf Ade * doc/domDoc.*: Fixed markup errors. 2005-12-10 Rolf Ade * generic/dom.c * generic/dom.h * generic/domxslt.c * tests/xslt.test: Fixed bug in namespace handling in xsl:copy-of. 2005-12-03 Rolf Ade * generic/dom.c * tests/domNode.test: Fix of the cloneNode method: if the node to clone (or, in case of -deep, a node within the subtree to clone) had a namespace declaration attribute then the result was wrong. * tests/domDoc.test: Added a test for the special handling of the content of script/style tags in case of asHTML. 2005-10-19 Rolf Ade * generic/domxpath.c * generic/domxpath.h * tests/xpath.test: Fixed string-length() and substring() to work on chars, as they should, not on bytes. 2005-09-27 Rolf Ade * tests/htmlreader.test: Added a test case, reported by Richard Suchenwirth, which crashes 0.8.0, but raises error with current cvs head, without any mem problems. 2005-09-24 Rolf Ade * generic/domxslt.c: Doh! The code detected ill grouping-size values and set errMsg accordingly, but didn't propagate the error. Fixed. Do memory cleanup after detecting wrong xsl:number level attribute value. Fixed memory leak in case of incorrect xslt attributes of included or imported xsl:stylesheet elements. Fixed memory leak in case of syntactically wrong xsl:key use attribute XPath expression. Fixed memory leak in case of toplevel parameter or variables which are syntactically incorrect, because they have both a select attribute and content. 2005-09-19 Rolf Ade * generic/domxpath.c: Improved detection/reporting of XPath syntax errors. Fixed two memory leaks in the XPath parser in case of some kind of erroneous XPath expressions. 2005-09-17 Rolf Ade * generic/domxpath.c: id() on an empty node set should return an empty string, according to the rec, not raise an error, as it did up to now. Fixed a memory leak in concat() in the case of xpath expressions as arguments, which raise error. Normally, XPath expressions doens't raise error at all; that's how XPath is designed. That is unfortunately not completely true with current tDOM, because tDOM doesn't do an as rigoros as possible argument check at XPath expression parsing time (that will change) and because of user defined XPath extension functions. 2005-09-16 Rolf Ade * generic/domxslt.c: Fixed memory fault in case of external documents resolved based on the base URI of a node of the source element. 2005-09-13 Rolf Ade * generic/domxpath.c: Bug fix: The namespace axis will be empty unless the context node is an element. * aclocal.m4 * configure * tdom.m4 * tdomConfig.sh.in * extensions/tnc/configure * extensions/tnc/configure.in: Improvement of the build system. Now works also with the tool combination cygwin/TEA/VC++. Thanks to Andreas Kupries for his patch. 2005-08-26 Rolf Ade * generic/tdominit.c: Removed tests about mt-ness of tclsh/tdom, due to popular demand. Mt compiled tDOM now will load into non-mt tclsh, as will a non-mt compiled tDOM into a mt tclsh. NOTES: Using a non-mt tDOM within only one thread of a mt tclsh should work just fine. But never ever use a non-mt tDOM in several threads of a mt tclsh. That may crash randomly. Use, how surprising, an mt-enabled tDOM for that. This will work fine. Using a mt aware tDOM within a non-tm tclsh is little bit slower and memory demanding. It will also have a few methods, that are superfluous within the non-tm tcl context. It should always work, but for best results use a non-mt tDOM with non-mt tclsh. 2005-08-20 Rolf Ade * generic/dom.c * generic/dom.h: Added function domPreviousSibling(). * generic/domxslt.c: Bug fix: Use domPreviousSibling() in xsltNumber() to prevent erroneous results, if attribute nodes are involved in the numbering. 2005-06-10 Rolf Ade * generic/dom.c * generic/dom.h * generic/domhtml.c * generic/tcldom.c * generic/xmlsimple.c: Internal dispersion: Cleaned up rootNode/toplevel nodes connection, added new function domSetDocumentElement. * tcldom.c: Closed memory leak in case of not well-formed input to the simple or html parser. * generic/domlock.h: Removed unused variable. * tests/dom.test: Added test, to document handling of white space outside the document element even in case of -keepEmpties (it's markup white space and will be removed). * tests/domDoc.test * tests/htmlreader.test * tests/xmlsimple.test: Added a few tests. 2005-05-13 Rolf Ade * tests/htmlreader.test * generic/domhtml.c: Fixed seg fault in case of some garbage input. 2005-05-12 Rolf Ade * tests/domNode.test * generic/tcldom.c: Fix: domNode nodeValue $newValue didn't check the newValue for being valid pcdata. 2005-05-02 Rolf Ade * tests/parser.test * generic/tclexpat.c: Bug fix: expat parser method parsechannel didn't (depending on the encoding of the channel) report parsing errors. 2005-04-11 Rolf Ade * tclconfig/ChangeLog * tclconfig/ac_c_bigendian_cross.m4: Deleted. * tclconfig/README.txt: Updated. * apps/xslt.tcl: Updated to request tdom 0.8.1. * Makefile.in * configure * configure.in * tdom.m4 * tdomConfig.sh.in * tclconfig/tcl.m4 * extensions/tnc/Makefile.in * extensions/tnc/configure * extensions/tnc/configure.in * extensions/tnc/tnc.c: Updated to use TEA 3.2. Thanks to Daniel A. Steffen and Andreas Kupries for input. 2005-04-04 Rolf Ade * expat/expat.h: Removed last comma in enum XML_Status declaration, to prevent compiler errors (xlc on AIX 64). (Current expat CVS head has the same fix.) 2005-03-26 Rolf Ade * tests/xslt.test * generic/dom.c: Fix in domAppendNewElementNode(), domAppendLiteralNode() and domAppendNewTextNode(): if the created node is a child of doc->root, set the parentNode according. * generic/domxslt.c: Removed (anyway not correctly working) work-around to set parent of the childs of doc->root (problem now correctly fixed by changes in dom.c). * tests/domNode.test * generic/nodecmd.c: Changes, to prepare adding of node creating cmds, which creates namespace aware nodes. 2005-03-21 Rolf Ade * tests/domDoc.test: Fixed flawed test, which slipped through, somehow. 2005-03-18 Rolf Ade * doc/domDoc.* * doc/domNode.* * CHANGES * tests/domDoc.test * generic/tcldom.c * generic/dom.h * generic/dom.c: Added document method selectNodesNamespaces, to provide a document global XPath prefix/namespace mapping. 2005-03-12 Rolf Ade * tests/xslt.test: Added two tests about two subtleties of the XPath syntax: white space between the $ and a varname are not allowed, while white space between the braces of node() is allowed. 2005-03-11 Rolf Ade * generic/nodecmd.c * tests/dom.test: Using of a node creating command outside of node context after that node creating command was already used in node context didn't raised error (as it should) but could have all kinds of effects (including seg fault). 2005-02-26 Rolf Ade * generic/tcldom.c: Fix for MT-enabled tDOM: If a doc was attached to more than one thread, nodeCmd creation was borken (only one thread got a nodeCmd for a given node). 2005-02-03 Rolf Ade * generic/domxslt.c: Bug fix: current() did not work in xsl:key use expressions. Moved setting of xs->current from all about the place into evalXPath. A bit code massage, to avoid bogus compiler warning. * doc/domDoc.* * tests/domDoc.test * generic/dom.c * generic/domxslt.c * generic/tcldom.c: Added support for xsl:output cdata-section-elements attribute. Added method cdataSectionElements to domDocs, as tcl interface to cdata-section-elements. * doc/domDoc.*: Added documentation for the domDoc method internalSubset. * generic/domxpath.c: Editorial changes. 2005-02-02 Rolf Ade * win/makefile.vc: Updated to provide the new defines PACKAGE_NAME and PACKAGE_VERSION introduced by the update to TEA-3 support. 2005-01-19 Rolf Ade * generic/dom.c * generic/dom.h * generic/domhtml.c * generic/xmlsimple.c: Renamed exported symbols attrNames and tagNames to tdom_attrNames and tdom_tagNames, to avoid name clash. startDoctypeDeclHandler() and endDoctypeDeclHandler(): added missing static. 2005-01-16 Zoran Vasiljevic * Makefile.in: Bumped version to 0.8.1. * configure: Added TEA-3 support. * configure.in: Made AOLserver 4.x virtual-server aware * tdom.m4: and added examples how to build the * generic/aolstub.cpp: lib as AOLserver module for 4.x series. * generic/tdominit.c: * README: * README.AOL: * mac/Prefix/tDOMPrefix.h: * mac/Prefix/tDOMPrefix_OSX.h: * win/makefile.vc: * win/makefile805.vc: * win/pkgIndex.tcl: * tclconfig/ChangeLog: * tclconfig/tcl.m4: * tests/loadtdom.tcl: * unix/CONFIG: 2005-01-11 Rolf Ade * doc/domDoc.* * doc/domNode.*: Added documentation for the -cache option of the selectNodes method. * lib/tdom.tcl: Scripted xpath function element-available: moved xsl:output to the available elements, since it's in fact available in the meantime (with exception of the 'version' and 'cdata-section-elements' attributes) - the output options can be queried from the result doc, but it's the responsibility of the application, to serialize the tree according to that settings. 2005-01-10 Rolf Ade * doc/dom.*: Corrected typo. * generic/dom.c: Fixed a leftover reference to embedded hash table in domDocument struct. 2005-01-10 Rolf Ade * generic/dom.c * generic/dom.h * generic/domxpath.c * generic/domxpath.h * generic/tcldom.c * tests/domNode.test: Don't embed Tcl_HashTables into dom Docs, use pointers to the hash table. Added -cache option to the selectNodes method. 2005-01-07 Rolf Ade * generic/dom.c * generic/domalloc.c * generic/domxslt.c * generic/domxpath.c * generic/tclexpat.c * generic/nodecmd.c * generic/nodecmd.h * generic/tcldom.c * tests/domDoc.test * generic/tcldom.h: Clean up, to decrease (innocuous) compiler warnings (thanks to Pat Thoyts for triggering input and patch). * win/makefile.vc: Improved VC++ compiler makefile. Thanks to Pat Thoyts for contribution. * win/nmakehlp.c * win/rules.vc * win/tdom.rc: Added this files. Thanks to Pat Thoyts for contribution. 2005-01-06 Rolf Ade * generic/tcldom.c * tests/domDoc.test * tests/domNode.test * doc/domDoc.* * doc/domNode:*: Handle multiple -namespaces options to selectNodes method. Added methods transform and delete to xsltCmds. Ensure, that documents created with the [dom createDocument* methods] are created as docCmds in case of 'auto' creation mode. * tests/dom.test Added a few tests: related to createNodeCmd * tests/element.test (dom), node text method (domNode), chancing * tests/parser.test callback from within a callback (element, * tests/xslt.test parser) and catching of recursive xsl include/import (xslt). 2004-12-21 Rolf Ade * generic/domxslt.c: xsl:key with match expressions, which matches attributes, did not work. Prevent, that a stylesheet import/include itself. Editorial changes. * generic/dom.c: domAppendNewElementNode(): Set the namespace of a per xslt transformation generated node wrong under certain circumstances. This fixes http://groups.yahoo.com/group/tdom/message/1008. Removed leftover (former local used) define TNODE. 2004-12-12 Rolf Ade * generic/domxpath.c * tests/xpath.test: xpath expressions ancestor-or-self::node() and parent::node() returned wrong result if the context node is /. 2004-12-10 Rolf Ade * doc/expat.* * generic/tclexpat.c * generic/tclexpat.h * tests/parser.test: Don't allow the methods parse, parsechannel, parsefile, free and reset from within a callback of the parser be used but raise a tcl error. 2004-10-25 Rolf Ade * doc/domNode.*: Added documentation for the '-namespaces' option of the selectNodes method. * doc/dom.*: Added a note to the -externalentitycommand option of the parse method, that the programmer is responsible for closing the channel, if the resolver script returns a channel. 2004-09-29 Rolf Ade * win/pkgIndex.tcl: First [load] the lib, which has [package provide tdom], so that a [package require tdom] within the script lib doesn't loop. * generic/tcldom.c: Added the with 0.8 added doc methods to the doc_usage. 2004-09-21 Rolf Ade * doc/domDoc.*: Add documentation for 'selectNodes' method. * generic/dom.c * generic/dom.h * generic/domxpath.c * generic/domxpath.h * generic/domxslt.c * generic/tcldom.c: Added the '-namespaces' option to the selectNodes method. Not resolved namespace prefixes within the xpath expression now raises an error. *** POTENTIAL INCOMPATIBILITY *** 2004-09-13 Rolf Ade * generic/domxslt.c: Corrected a typo in an error msg. 2004-09-08 Rolf Ade * generic/domxslt.c: Editorial changes. 2004-09-02 Rolf Ade * generic/domxpath.c * generic/tcldom.c * tests/domNode.test: toXPath method: fixed bug with non-element top level nodes, closed mem leak. 2004-08-23 Rolf Ade * README * README.AOL: Corrected typos (thanks to G. Neumann) 2004-08-20 Rolf Ade * expat/*: Update to expat 1.95.8. 2004-08-19 Rolf Ade * unix/CONFIG * generic/dom.h * generic/tcldom.c: Made tDOM work out of the box on 64-bit systems like Itanium 2 (though --disable-tdomalloc configure option at build time is still needed). 2004-08-17 Rolf Ade * generic/dom.h: Added fluff, to fix build problemx on AIX w/ xlc compiler. * generic/domxpath.c * generic/tcldom.c: Removed unused variables. 2004-08-15 Rolf Ade * generic/dom.h * generic/dom.c * generic/domxslt.c * generic/tcldom.c * generic/xmlsimple.h * generic/xmlsimple.c * tests/dom.test: Pass external entity resolver script around in string representation (insteand of Tcl_Obj), to avoid problems with mt builds. --- Release 0.8.0, 11. Aug. 2004 --- 2004-08-10 Rolf Ade * extensions/tnc/makefile.vc: Link against tDOM 0.8.0. * doc/dom.*: Corrected a spelling mistake. 2004-07-28 Rolf Ade * lib/tdom.tcl: [namespace export] the public procs in ::tDOM. Added a few more encodings to IANAEncoding2TclEncoding. 2004-07-27 Rolf Ade * test/dom.test * doc/dom.* * generic/dom.h * generic/tcldom.c: New (experimental) method setObjectCommands. * test/domNode.test * generic/dom.c * generic/tclexpat.c * generic/tcldom.c: Reworked internal base URI handling, to fix a bug of the old approach and to be closer to (though not fully support) what DOM 3 say about base URI handling. * tests/dom.test * doc/dom.* * generic/tcldom.c: New method createDocumentNode. * tests/domDoc.test * doc/domDoc.* * generic/dom.c * generic/tcldom.c: Added methods nodeType, getElementById, firstChild, lastChild, appendChild, removeChild, hasChildNodes, childNodes, ownerDocument, insertBefore, replaceChild, appendFromList, appendXML, selectNodes, baseURI, appendFromScript and insertBeforeFromScript to dom docs. Beside other things, this allows much easier handling of top level nodes. The result tree may not be an XML document, but a general parsed entity. * tests/domNode.test * doc/domNode.* * generic/tcldom.c: Improved speed of the getAttribute shortcut '@attname' (and, not so notable, of tcl coded methods of the dom, domDoc and domNode cmds). Corrected typo in domNode usage msg for getElementByID. Improved error msg for getAttribute, if attribute is not found. Changed behavior of getElementByID: if no element with the given id is found, returns now the empty string, not a TCL_ERROR (closer to DOM rec, getElementByID never raise an exception). Bug fix: nodeName now returns the per DOM rec correct values for comment and cdata section nodes (were as yet reported as if they where text nodes). * tests/entity.test * generic/tclexpat.c: Better error msg in case of 'filename' and not valid file name. * tests/xpath.test: Documented behaviour in case of using (senseless, wrong) 'xslt variable' in selectNode exprs. * tests/xslt.test: More tests for script errors in external entity handler or errors in the requested external entities. 2004-07-19 Rolf Ade * generic/domxslt.c: Better error msg in case of XML parsing errors in external entities. * generic/nodecmd.c: Bug fix: Check, if refnode given to insertBeforeFromScript is valid. 2004-07-13 Rolf Ade * generic/domxslt.c: Ensure, that the first element node of the result tree is the documentElement of the generated document. * tests/xmlsimple.test * generic/xmlsimple.c: Empty CDATA sections should not create a node. 2004-07-08 Rolf Ade * generic/tdominit.c: Test, if a non-mt tDOM is tried to load into a mt tclsh. 2004-05-26 Rolf Ade * doc/dom.* * tests/dom.test * tests/domNode.test * tests/tdomcmd.test * generic/tcldom.c * generic/dom.c * generic/dom.h * generic/nodecmd.h * generic/nodecmd.c: Added isPIName, isComment, isCDATA and isPIValue method to the dom command. Created new global (thread wide) flags for name and value checks (Names and FQ Names (element, attribute and processing instruction names), text nodes, comments, CDATA sections and processing instruction values). New methods setNameCheck and setTextCheck to control this flags. * generic/nodecmd.c: Bug fix in case of appendFromScript script. * generic/domxslt.c: Uses the new domIsComment, domIsPINAME and domIsPIValue API functions of dom.c. Improved xsl:processing-instruction processing (now instantiating the content). * generic/domxpath.c: Minor editorial changes. * tests/domCmd.test: Deleted this file, moved the tests to the new dom.test or domDoc.test. * tests/dom.test: Moved the tests from this file to the new domNode.test and collected dom command tests here. * tests/domDoc.test * tests/domNode.test: Created this files, tests from dom.test and domCmd.test. * doc/expat.* * tests/xpath.test * tests/xslt.test: Minor changes. 2004-05-11 Rolf Ade * apps/xslt.tcl: Fixed the test for running in a source tree with tcldomsh. (doh!) 2004-05-08 Rolf Ade * generic/xmlsimple.c: Removed superfluous arg baseURI from XML_SimpleParse(). * generic/domhtml.c * tests/htmlreader.test: Fixed html-2.1 and html-2.2. (This html reader is crusty stuff...) 2004-03-26 Rolf Ade * generic/domxpath.c: Fix of the template priority calculation and clearing out of xpathGetPrio(). 2004-03-14 Rolf Ade * generic/xmlsimple.c: Fixed a few simple parser seg faults in case of not-wf input. See xmlconf/xmltest/not-wf/sa/022.xml, xmlconf/xmltest/not-wf/sa/042.xml for examples. 2003-12-30 Rolf Ade * Makefile.in * extensions/tdomhtml/pkgIndex.tcl.in * extensions/tnc/Makefile.in: Doh! Undo the last changes; I fixed this already 2003-10-12. * generic/dom.c: Removed superfluous comma from the tdomMethod enum, which bothered the AIX xlc compiler. * generic/domxpath.c: Editorial change: Removed some superfluous casts to (char*) from tdomstrdup result - its defined to return char*. * generic/domxpath.h * generic/domxpath.c * tests/xslt.test * generic/domxslt.c: Implemented the special constraints on certain xpath pattern/expr (no current() func in pattern, no var references in template and key match pattern and key use expr, no key() func in key match pattern and use expr.) 2003-12-24 Rolf Ade * Makefile.in * win/pkgIndex.tcl: * extensions/tnc/pkgIndex.tcl.in * extensions/tdomhtml/pkgIndex.tcl.in * extensions/example/pkgIndex.tcl.in: Bug fix: Protect against spaces in the path to the package. 2003-12-20 Rolf Ade * win/pkgIndex.tcl: Also updated to new version nr 0.8.0. 2003-12-17 Rolf Ade * doc/domNode.* * generic/tcldom.c: Added baseURI method, which returns the current base URI and has an optional argument to set the base URI. (The getBaseURI is deprecated.) 2003-12-15 Rolf Ade * generic/dom.c * generic/domxslt.c: More fixes to ensure ns integrity of xslt result trees. 2003-12-14 Rolf Ade * tests/attribute.text: Made test results independent from the (undefined) order of [array get]. * tests/dom.test: Build expected result of some tests with [list], instead of providing a string rep. This hides the changes in list string rep by TIP 148, so that the tests work both with pre- and post TIP 148 tcl. 2003-12-11 Rolf Ade * tests/xslt.test * generic/domxpath.c: Bug fix: double mem free in case of pattern w/ FQ element with positional dependent predicate. * generic/dom.c * tests/domCmd.test * tests/pcdata.test * tests/tdomcmd.test * generic/tclexpat.c: Bug fix: Don't quash white space of non white space only content in trim mode. 2003-12-09 Rolf Ade * lib/tdom.tcl: Improved regexp to extract encoding. Corrected typo. * generic/domxslt.c * generic/domxpath.c * generic/dom.c: Bug fix in namespace handling: copy-of from result tree fragments could mess up ns handling, if a default namespace is already in scope in the result tree. 2003-12-08 Rolf Ade * win/makefile.vc * win/makefile805.vc: Also updated to verson nr. 0.8.0. 2003-11-28 Rolf Ade * generic/tcldom.c: Switched back to Tcl_Panic() in one case, to make MT builds work. * generic/domxslt.c * generic/dom.c: With MT tDOM, a domDoc extRefHandler script may be used within another thread. 2003-11-27 Rolf Ade * generic/domxslt.c * generic/dom.c * tests/xslt.tests: Another fix, to ensure namespace integrity of the result doc. 2003-11-26 Rolf Ade * generic/domxslt.c * tests/xslt.test: Fix, to ensure namespace integrity of the result doc. Fixed parentNode of documentElement and siblings of the result tree. 2003-11-24 Rolf Ade * tests/tdomcmd.test: Added this file. * generic/dom.c * tests/dom.test: Don't include PIs inside the internal subset into the tree. * generic/tcldom.c * generic/dom.h * generic/domxslt.c * tests/xslt.test * generic/dom.c: Added domDoc methods omit-xml-declaration, indent, standalone, encoding and mediaType. * generic/tclexpat.c * generic/tclexpat.h * generic/dom.c: Changed parserObj behavior: parser don't need a reset call after a final parse or parsing error. * tests/xslt.test * generic/domxslt.c: Bug fix: seg fault for document('') with stylesheet tree with empty baseURI. Minor optimizations. Fixed invalid memory read. * generic/tcldom.c * tests/dom.test: (Probably) temporarily disabled automatically clean up of nodeObjCmds, to work around bug: Storing the same node in different evaluation contexts with the optional objVar argument (as in [$doc documentElement root]) at the same time did not work. * generic/domxpath.c: Fixed a mem leak with some sum() calls with NaN result. Fixed invalid memory read. * generic/tcldom.c: Fixed mem leak with -externalentitycommand. Fixed mem leak with parsing xml document with external entity and parsing error in an external entity. Minor code clean up. * tests/parser.test: * generic/tclexpat.c: Fixed memory problem, if handler script return TCL_ERROR. Made the cget method work for the parser related options, even if there are no handler scripts set. * generic/tcldom.c * generic/dom.c * generic/tclexpat.c * generic/domlock.c: Always use domPanic as panic function. 2003-11-20 Rolf Ade * generic/domxslt.c: Bug fix: Setting a top-level xslt param with -parameters and using this param for setting another top level var could end in seg fauld. 2003-11-10 Rolf Ade * generic/tcldom.c: Replaced a C++ style comment with a C style comment. 2003-11-02 Rolf Ade * tests/xpath.test: Added a few tests related to declarations to chapter 4.2 and 4.4 in the errata to the XPath rec. * generic/domxpath.h: Fixed memory leak, if floor or ceiling are called with non-numbers. 2003-11-01 Rolf Ade * generic/domxslt.c: Minor bug fix: Special handling is needed, if xsl:copy-of is used, to copy namespace nodes. 2003-10-26 Rolf Ade * apps/xslt.tcl: Removed not needed code. * generic/dom.c * tests/dom.test: Bug fix: Under some circumstances it was possible, that an URI change for a subtree was not stored in the tree (resulting in wrong base URI for that nodes). * generic/domxpath.c: number() bug fix: Now works according to the XPath rec understanding of a Number, not with the libc understanding of a double. * generic/domxpath.c * generic/dom.h * generic/dom.domxslt.c: Globalized the macro IS_XML_WHITESPACE. 2003-10-24 Rolf Ade * generic/domxslt.c: Bug fix for document() func, if called with 2 args and first arg evaluates to the empty string. Improved error reporting, if an XSLT variable is tried to reset, although there is already such a variable in scope: now the name of the var is also reported in the error msg. * apps/xslt.tcl: Updated to use the new asText option. 2003-10-23 Rolf Ade * expat/* * CHANGES: Update to expat 1.95.7. 2003-10-22 Rolf Ade * generic/domxpath.c * tests/xpath.test: Bug fix in the xpath lexer: In a union expr, a NCName test with a name equal to an operator was wrongly interpreted as operator. 2003-10-21 Rolf Ade * generic/domxslt.c: Fixed bug with current(), if it is used in the select expr of an xsl:sort. * generic/domxpath.c * generic/domxpath.h * generic/domxslt.c: Changed handling of key node sets. It's a somewhat focused optimization, for the price of a very small overall cost. I've done it anyway, because it's a very notable speed up for an important xslt pattern (the so called Muenchian Method for grouping). * generic/tcldom.c: Removed two unused variables. 2003-10-17 Rolf Ade * generic/dom.c: Fixed dom parse -channel option, which got accidentally broken, due to the lately switch from Tcl_GetStringFromObj() to Tcl_GetString(). * generic/tcldom.c: Added again some recently implemented methods to domObj_usage and node_usage, which got accidentally removed by the lately editorial changes. 2003-10-16 Zoran Vasiljevic * generic/tcldom.c: added "dom detachDocument" command to match the already present "dom attachDocument". This is used only for threaded tdom builds. * generic/domlock.c: changed lock caching to accommodate for situation with huge number of created documnents Also, added new "domDoc" command as a first-class tdom citizen, analogous to the already existing "domNode". It operates on the document token. Attempt has been made to start to follow Tcl-style-guide but we still have a way to go. The first thing is to try to force the 78-chars margin where possible/feasible. Therefore, many of the source files have been cosmetically touched, without code or functionality changes. 2003-10-12 Rolf Ade * generic/domxpath.c * generic/domxslt.c: Removed not used vars. * generic/dom.c * generic/dom.h * generic/domhtml.c * generic/tcldom.c * generic/tclexpat.c * generic/tclexpat.h * generic/xmlsimple.c: Merged domCreateEmptyDoc() and domCreateDoc(), now there is only one API proc: domCreateDoc(). 2003-10-10 Rolf Ade * Makefile.in * extensions/tdomhtml/pkgIndex.tcl.in * extensions/tnc/Makefile.in: Fixed pkgIndex.tcl problem, if the path to the packages contains a space. * doc/domDoc.* * doc/domNode.* * CHANGES * generic/dom.h * generic/dom.c * generic/tcldom.c * tests/domCmd.test: Added implementation for new method normalize (and as a by-product a C implementation for the method appendData). 2003-10-09 Rolf Ade * tests/domCmd.test * generic/tcldom.c: Made code robust against renaming of domDoc cmds (well, unlikely, not to say very unlikely, but at least it also simplified code and reduces obj size by a few bytes). Changed sharedDocs hash table (only MT build) from TCL_STRING_KEYS to TCL_ONE_WORD_KEYS. 2003-10-08 Rolf Ade * generic/tcldom.c: Fixed the preliminary (and MT only) method renumber. 2003-10-07 Rolf Ade * generic/nodecmd.c * generic/nodecmd.h * generic/tcldom.c * tests/dom.test * doc/domNode.* * CHANGES: Added new method insertBeforeFromScript to domNodes. Bug fixes for appendFromScript: In case of error in the script, the tree will not be altered. The appendFromScript may only be used for ELEMENT_NODEs. 2003-10-04 Rolf Ade * generic/domxpath.h: Removed prototypes of functions, which are not implemented. Editorial changes. * generic/domxpath.h * generic/domxpath.c * generic/domxslt.c * generic/tcldom.c * tests/dom.test * tests/domCmd.test * CHANGES * doc/domDoc.* * doc/domNode.*: Added new method 'asText' to domDocs and domNodes. Renamed xpathGetTextValue() to xpathGetStringValue(), to be more according to the vocabular of the XPath rec. 2003-10-01 Rolf Ade * generic/dom.c: Removed unnecessary check of domModuleIsInitialized in domReadDocument(). Corrected typo in a comment. * generic/dom.c * generic/dom.h * generic/domxpath.c * generic/domxslt.c * generic/tcldom.c * tests/dom.test: Reworked usage of nodeNumber. It is now used only in one place, the new domPrecedes function. Also in domPrecedes is a fall-back mechanism, which is used if the document has an invalid node numbering. Removed the forced re-numbering in case of invalid node numbering of the doc for every single selectNodes. Added preliminary method renumber for MT-enabled builds. Carefully reviewed every rsAddNode usage in domxpath.c. Some minor editorial changes. 2003-09-28 Rolf Ade * generic/tclexpat.c: Removed two unused vars. * tests/domnamespace.test * generic/dom.h: Changed type of domNameSpaceIndex, domNodeFlags, domAttrFlags, domDocFlags and info in dom*Node structs from int to unsigned int. This fixes bug with docs with more than 128 different namespaces. * tests/xpath.test * generic/domxpath.c: Bug fix: preceding-sibling axes could give wrong results in case the context node is a child of rootNode (e.g the documentElement). * tests/dom.test * generic/tcldom.c * generic/dom.c: Bug fix for replaceChild: If the node to replace was wrong, the doc got mangled. Bug fix for appendChild, replaceChild: the new node could not be a sibling or child of node. Speed improvment in some cases for removeChild, replaceChild, appendChild. 2003-09-22 Rolf Ade * tests/dom.test * doc/domNode.* * generic/tcldom.c * generic/dom.c: Reworked insertBefore: Bug fix: If the refNode was invalid, the involved documents got mangled. Bug fix: Dead loop, if the node to insert was the node itself. Bug fix: the rootNode of node's document could be used as node to insert. Bug fix: It was not possible, to insert a node before refNode, which was already a children of node. Bug fix: It was not possible, to insert a sibling of node. Feature enhancement: If the refnode is the empty string, the newNode is inserted at the end of the children list of node. Optimization: Average speed was O(n/2) (n: number of childs of node) in case the node to insert was out of the tree, and 0((n+m)/2) (m: number of nodes in the fragments list) in case the node to insert was out of the fragments list. Now its O(1). * tests/dom.test: Removed 'knownBug' constraint from two tests, which documented known bugs, that are fixed in the meantime. 2003-09-17 Rolf Ade * tests/cdata,test * tests/element.test * tests/parser.test: Added a few tests related to the new flexibility of the -elementstartcommand, -elementendcommand and -characterdatacommand scripts. * doc/expat.*: Added documentation for the now implemented cget method. Added information about the default for the -paramentityparsing option. * generic/tclexpat.c * generic/tclexpat.h: Enhanced the new cget method of parserObjs to also report the state of -noexpand, -useForeignDTD, -paramentityparsing (those by doing the bookkeeping with an enhanced TclGenExpatInfo struct, because the expat parser do not proived an API to request this settings) and -namespace. Improved argument check of the parser obj method calls. Optimization for calling handler scripts. 2003-09-16 Zoran Vasiljevic * Makefile.in: added SHLIB_CFLAGS to set of compiler switches in order to silence the picky linker. 2003-09-14 Rolf Ade * lib/tdom.tcl: Fixed scripting bugs in ::dom::domDoc::importNode and ::dom::domNode::length * Makefile.in: dist target: Don't include CVS dirs and hidden files into the distribution file. 2003-09-14 Zoran Vasiljevic * Makefile.in * configure * configure.in: made more TEA-2 compatible by moving the tcldomsh target out. Also, honour the MATH_LIBS as calculated by the tcl.m4 instead of plumbing our own. Also, fixed "make dist" to produce distribution file. * tclconfig/ChangeLog * tclconfig/tcl.m4: imported fresh new versions from SF * unix/CONFIG: cleanup * macosx/README: cleanup 2003-09-14 Rolf Ade Merged fixes from 0.7.8 into HEAD. This includes: 2003-08-06 Zoran Vasiljevic * generic/nodecmd.c: removed optimized domAppendChild1 in favour of generic domAppendChild since former was trashing memory in certain situations. 2003-08-06 Rolf Ade * tests/all.tcl * tests/domCmd.test: Added contraint need_uri, so that the few tests, which needs the tcllib uri package are skipped, if the uri package isn't present. 2003-07-06 Rolf Ade * generic/tclexpat.c: Fixed bug in the subtree skipping feature of event handlers. Should be merged with HEAD. * lib/tdom.tcl: Fixed error reporting in tDOM::extRefHandler. 2003-07-03 Zoran Vasiljevic * generic/domlock.c: fixed double mutex unlock. * generic/tcldom.c: allows same thread to issue several "attachDocument" commands to artificially bump the document refcount thus making the document sticky. Also, fixed variable tracing issues when tearing down the dom document. Now, all node object command variables are automatically untraced. This prevents memory trashing when such variables are unset by user or by Tcl. 2003-09-14 Rolf Ade * generic/tclexpat.c: Added cget method implementation for all parser options with the exceptions of -namespace, -useForeignDTD and -paramentityparsing. Revamped behind the scene code for handling of the -elementstartcommand, -elementendcommand and -characterdatacommand options. Up to now, the arguments to this options must have been the name of an already defined tcl proc. This allowed a special high performance calling of that procs. The new code behaves exactly the same way for every script, which worked with previous versions. Additionally it allows, to specify a not already defined tcl proc and, probably more important, allows 'arbitrary' tcl scripts as argument to that options. All in this checkin in the work of Harry Moreau (hmoreau@online.ie). Many thanks for this contribution. 2003-06-13 Rolf Ade * generic/tcldom.c: Added an argument check for XSLTCmds. 2003-06-11 Rolf Ade * generic/domxslt.c: Fixed a bug in xsl:number. If there is no 'count' attribute given to xsl:number, it must default to the pattern that matches any node with the same node type as the current node and, if the current node has an expanded-name, with the same expanded-name as the current node. But in case of PROCESSING_INSTRUCTION_NODEs as the current node and no 'count' attribute, it counted all pi's regardless of the name. Now, the name is respected, as it should be. 2003-06-11 Zoran Vasiljevic * generic/domlock.c: fixed double mutex unlock. 2003-05-19 Rolf Ade * doc/dom.*: Corrected the documentation of the createDocumentNS method: the args uri and docElementName were documented in the wrong order (reported by Vico Klump). Minor markup changes. 2003-05-16 Zoran Vasiljevic * generic/dom.h * generic/tdom.decls * generic/tdomDecls.h * generic/tdomStubInit.c * generic/tdomStubLib.c * generic/tdominit.c: fixed so it compiles cleanly when -NS_AOLSERVER is defined. 2003-05-16 Rolf Ade * generic/dom.h * generic/tcldom.c * generic/domxslt.c * generic/tclexpat.c: Switched to use XML_ParserCreate_MM(), to be able (at tDOM build time) to make the expat parser use custom *alloc/free() functions (macro MEM_SUITE in dom.h). For TCL_MEM_DEBUG and NS_AOLSERVER builds the mem functions, used by the parser default now to Tcl_Alloc()/Tcl_Realloc()/Tcl_Free(). Switched to XML_FreeContentModel(), for freeing stored element content models. 2003-05-11 Rolf Ade * generic/dom.c * generic/domxslt.c * generic/xmlsimple.c: Renamed the documents rootNode (in the sense of the XPath data model, that is not the document element) from "(rootNode)" to "", in preparation for the promissed 'domDoc without documentElement' feature, to fix a somewhat outlying problem with xslt numbering and because it's clearly more the 'right thing' according to the rec. * generic/domxslt.c: Removed the arg xs from sortNodeSetFastMerge(), because it isn't used. 2003-04-20 Rolf Ade * extensions/tdomhtml/tdomhtml.tcl: Proc newdoc: New optional argument (list of names of local variables) allows the use of local variables (in the scope of the caller of newdoc) in the script argument of newdoc. Contributed by Chuck Ferril. 2003-04-16 Rolf Ade * generic/domxslt.c: Optimization: Improved caching of external documents. 2003-04-12 Rolf Ade * README * README.AOL * configure.in * configure * configure-8.0.5 * tests/loadtdom.tcl * mac/Prefix/tDOMPrefix.h * mac/Prefix/tDOMPrefix_OSX.h * extensions/tnc/tnc.c: Bumped version to 0.8.0 (alpha). 2003-04-09 Rolf Ade * generic/dom.c: Fixed a bug in the creation of the error msg in case of parsing errors in an external entity. * generic/dom.c * generic/dom.h * generic/domxslt.c * tests/domCmd.test * doc/dom.* * generic/tcldom.c: Added option -paramentityparsing to the [dom parse] method. [dom parse] option parsing now uses Tcl_GetIndexFromObj() (which additionally fixes a minor bug with the current option parsing). * generic/tcldom.c: Removed an unused variable. Improved error reporting in case of not found attribute. Better options check for the 'xslt' methods. Changed implementation of the dom method isQName to use the lately introduced API function domIsQNAME. * generic/tclexpat.c tests/parser.test: Fixed a bug in the value parsing of the -paramentityparsing option. * tests/domCmd.test: Added tests for the interface of the xsltCmds. * tests/xpath.test: Added test which documents the bug prior to domxpath.c r1.63. * doc/dom.*: Added 'package require tdom' to the syntax decription (http://groups.yahoo.com/group/tdom/message/446) * doc/domDoc.*: Added documentation for the toXSLTcmd method and the resulting xsltCmds. Corrected the documentation for the xslt method (missed -ignoreUndeclaredParameters and -xsltmessagecmd in the method syntax). 2003-04-05 Rolf Ade * generic/tclexpat.c: Bug fix: If the parsing state is already not TCL_OK return in the notstandalonehandler immediately success, otherwise the error msg will be overwritten with a false diagnostic. A few editorial changes. 2003-04-04 Rolf Ade * generic/dom.c * generic/dom.h: Added domIsQNAME. * generic/dom.c: Bug fix: For textNodes getLine/getColumn method report the position of the first char of the text node. * generic/domxpath.c: Bug fix: Detects now some erroneous XPath expressions. Added parameter number check to XPath functions substring and concat (the last two XPath functions, without such check, they must have slipped thou somehow, up to now). * generic/domxslt.c: Improved interal function reportError(), can now be used with all kind of nodes not only element nodes. Improved behavior in case of dubious numbering (negative roman number or latin letters fall back to default latin numbers). Fixed a potential memory leak (in case of overwriting named templates without match attribute with an other named template). Improved error reports: for more detected errors there is now a line/column number given. Plenty of improvements in detecting erroneous stylesheets: more checks for format-number formatting patters (although especically format-number patterns are still a can of worms), added parameter number check for additional XPath function current(), template, parameter, variable, sort, choose, copy, and message elements. 2003-03-26 Rolf Ade * generic/domxslt.c: Fixed some memory problems, mostly in case of erroneous stylesheets. --- Release 0.7.7, 25. Mar. 2003 --- 2003-03-25 Rolf Ade * configure.in * configure * configure-tcl8.0.5 * README * README.AOL * win/makefile.vc * extensions/tnc/makefile.vc * mac/Prefix/tDOMPrefix.h * mac/Prefix/tDOMPrefix_OSX.h * mac/tDOM_OSX.prj.xml: Bumped the version number to 0.7.7. * generic/tcldom.c: Fixed error, which prevents building 0.7.6 with -DTCL_THREADS=1. (Arrrg.) --- Release 0.7.6, 24. Mar. 2003 --- 2003-03-22 Rolf Ade * mac/Prefix/tDOMPrefix.h * mac/Prefix/tDOMPrefix_OSX.h * mac/Prefix/tncPrefix.h * mac/Prefix/tncPrefix_OSX.h * mac/tDOM_OSX.prj.xml: Final tweaking for 0.7.6. * expat/VERSION * expat/expat.h: Updated to an after 1.95.6 version, which fixes the problem, that some compilers had with the 1.95.6 version. 2003-03-22 Rolf Ade * README * README.AOL * configure.in * configure * configure-tcl8.0.5 * mac/tDOM.r * mac/tDOM_OSX.prj.xml * mac/tnc.r * extensions/tnc/makefile.vc: Updated to new version number 0.7.6. * mac/tDOM/*: Added dir/files, to have a version number independed output dir for the mac build. * mac/tDOM.0.7.5/* * mac/tDOM.0.7.5: Removed in favor of a version-less tDOM output directory. * configure * configure.in: tdomstub_BUILD_SPEC must point to the plattform specific build dir. * generic/tcldom.h: Removed hard coded version number, uses now VERSION define. * win/makefile.vc * win/makefile805.vc * win/pkgIndex.tcl: Updated to new version 0.7.6. * extensions/tnc/tnc.c * extensions/tnc/tests/tnc.c: Added code needed to handle effects of the -useForeignDTD option. * doc/domNode.* * generic/tcldom.c * tests/dom.test: Renamed 'startBefore' method to the better name 'precedes' and changed behavior: the method now returns simply a boolean value. 2003-03-19 Rolf Ade * generic/tcldom.c * generic/domxslt.c * generic/dom.h * generic/dom.c: Replaced a few exit() code with Tcl_Panic(), which ensures, that even windows users get a useful error msg. * generic/dom.c: Fixed a mem leak in handling external entities. * doc/expat.* * doc/dom.* * tests/domCmd.test * tests/data/domCmd1.dtd * tests/data/domCmd2.dtd * tests/entity.test * lib/tdom.tcl * tests/domCmd.test * generic/tclexpat.c * generic/tcldom.c * generic/domxslt.c * generic/dom.h * generic/dom.c: Added option -useForeignDTD to dom parse and expat. * generic/domxslt.c: Fixed several potential memory leaks while processing erroneous stylesheets. Bug fix: added missing memory clean to grouping-separator/grouping-size support. * generic/tcldom.c: Fixed potential memory problem while processing erroneous stylesheet. Improved error msg in case of script errors in the -externalentitycommand script. * doc/domNode.* * tests/dom.test * generic/tcldom.c: Added method 'startBefore', to compare the relative order of two nodes out of the same document. * generic/nodecmd.c: Added explicit memory clean up of the nodecmd stack, to reduce 'noice' while memory leak debugging. * tests/dom.test: Added a reminder for a minor known memory problem. * tests/data/mondial-europe.xml: Added this file (used by the usage example of xe). * xe/xe-input: Changed pathes to point to the location of mondial-europe.xml. 2003-03-19 Zoran Vasiljevic * Makefile.in: installs the tdomConfig.sh into the $(libdir) whatever that points to. 2003-03-08 Zoran Vasiljevic * expt/internal.h: disabled FASTCALL & friends since those do not work anywhere, as of my knowledge. 2003-03-06 Zoran Vasiljevic * generic/domalloc.c: removed include malloc.h since not needed nor not found on macosx * configure.in: adds "-lm" even when linking the shared image since Starkit users need that. Also, fixed alternative libdir usage when installing in non-standard (user-given) location. * unix/CONFIG: new file. Adds some examples how to build the extension on some common Unix platforms. * mac: added Bernards CodeWarrior files for Mac builds. * macosx: added directory where we will supply the ProjectBuilder files (hopefully :) 2003-03-03 Rolf Ade * tests/dom.test * generic/tcldom.c: Fixed bug with using the 'domNode' cmd without argument (spotted by Bernard Desgraupes). 2003-02-27 Rolf Ade * generic/domxslt.c: xsl:number attributes grouping-separator and grouping-size now also interpreted as attribute value templates. (The last two (missing up to now only by mistake) attribute value templates under the recognized xsl attributes.) 2003-02-26 Rolf Ade * generic/tcldom.c: Removed unused variables. * lib/tdom.tcl generic/dom.c: Improved ::tDOM::xml(Read|Open)File. Now handles also utf-16 files with BOM right. * generic/domxslt.c: Made some functions static. Removed a TODO note, which already was done. Improved some error msgs (now with line/column info, if available). Bug fix: xsltXPathFuncs must return -1 to signal error, because if the source of the function call was inside of domxslt.c the result code (rc) check rule is rc < 0. Fixed text in a xsl:attribute error msg. Fixed memory leak in error case in ExecAction, case forEach. Added a missing result code check in ExecAction, case procinstr. Bug fix: Even literal result element subtrees are relevant for xslt variable scope (default case of ExecAction). Bug fix: the expression context of the match expr of a xsl:template is the xsl:template node. Now the xslt white space stripping is done before the top level processing (was done after toplevel processing). 2003-02-25 Rolf Ade * expat/VERSION * expat/internal.h: Applied post 1.95.6 patch, to fix compiler warnings ("warning: `regparm' attribute directive ignored") from gcc on Solaris. 2003-02-22 Rolf Ade * generic/tcldom.c * generic/tdom.decls * generic/tdom.h * generic/tdomDecls.h * generic/tdomStubInit.c: Added tcldom_getNodeFromName(), tcldom_getDocumentFromName() and the dom.h typdefs to the tDOM stubs table. Needed for the new tnc feature (and elsewhere, on the long run). * doc/tnc.* * extensions/tnc/configure * extensions/tnc/configure.in * extensions/tnc/makefile.vc * extensions/tnc/test.tcl * extensions/tnc/tnc.c: Added new tnc method getValidateCmd. Changed to use the same memory allocator/free defines as the tDOM core. Bumped the version to 0.3. * extensions/tnc/tests * extensions/tnc/tests/all.tcl * extensions/tnc/tests/loadtnc.tcl extensions/tnc/tests/tnc.test: Started test suite for the tcl interface of the tnc command and the validator commands. * generic/tclexpat.c: Better eContents cleanup. Bug fix: of course we have to call the parserResetProcs of the registered C handler sets while reseting the expat parser command. * lib/tdom.tcl: Smaller fixes. Changed the values of the system-properties xsl:vendor (included me) and xsl:vendor-url (to http://www.tdom.org). 2003-02-22 Zoran Vasiljevic * generic/dom.h: Added (char*) cast to argument of Tcl_Free in the FREE macro. This avoids some compiler warnings. * generic/dom.c: Added some typecasts to MALLOC to avoid compiler warnings. 2003-02-21 Rolf Ade * generic/domxslt.c: Bug fixes: Return after detecting the error (xsltPathFuncs), ensure that savedLastNode is always set right (ExecAction, case copy). Editorial changes. * configure.in * Makefile.in * configure * configure-tcl8.0.5: Don't remove tdomConfig.sh with a 'make clean', only with a 'make distclean'. 2003-02-09 Rolf Ade * expat/*: Update to expat 1.95.6. * apps/xslt.tcl: Updated to use the new -xsltmessagecmd option of the xslt method and the -doctypeDeclaration of the asXML/asHTML methods. Added a few comments. 2003-02-09 Rolf Ade * generic/dom.c * generic/dom.h * generic/domxslt.c * generic/tcldom.c * doc/domDoc.* * tests/domCmd.test: Public and system identifier information are now stored (if parsed with the expat parser or generated by the xslt engine, if given), exposed to the script level (even writable, more than DOM 2 allows) and will be, on demand, respected while serializing. * generic/dom.c: Bug fix: Hold ID => node mapping consistent even after resetting or removal of known ID attributes. * generic/domxslt.c: Bug fix: invalid memory read. * generic/tcldom.c: Bug fix: invalid memory read. 2003-01-30 Rolf Ade * generic/dom.c * generic/tcldom.c * generic/xmlsimple.c * tests/xslt.tests: Fixed bug reported by Wilhelm Klink (http://groups.yahoo.com/group/tdom/message/404 see test xslt-4.1). Again a problem (sideeffect) of renumbering node->nodeNumber (which is necessary after modification of the tree for some XPath expr to work). The keys of the entries in the baseURIs hash table of the documents where the nodeNumber of the (subtree root) nodes with new baseURI. Since this nodeNumber isn't necessarily constant over the lifetime of a node (because of the possibility of re-numbering the tree), this could not work anymore. Instead the nodeNumber, we now use the pointer to the node structure as Key for the baseURIs hash table. This pointers stay always constant, even if the nodeNumber changes. Additional code was added to domFreeNode(), to ensure, that an entry in the baseURIs hash table gets freed, if the related node is in deed freed. Removed the yesterday added reseting of the domUniqueNodeNr counter, because it turned out in testing, that there are problems with sorting of resultSets, which includes nodes from different documents (which may happen with some special XSLT constructs (document() calls with a nodeset as argument)). The reseting of the domUniqueNodeNr is still desirable, but it turned out, that it should be carefully considered, when it should be done. 2003-01-29 Rolf Ade * generic/dom.c * generic/tcldom.c * tests/xslt.test: Changed escaping of serialized XML. The previous behavior wasn't 'wrong', but now we do it along the lines of almost all other (important) tools and it seems there's al least some xslt code out there, which banks on this 'common' way of serializing. Though, there is a small risk, that this is an incompatible change for a few users. * generic/dom.c * generic/dom.h * generic/xmlsimple.c * tests/dom.test: Fixed the problem of 'changing node references' under some circumstances (reported by Wilhelm Klink). This also decrease the possibility of a potential problem for extremely long running single threaded tDOM applications. * generic/dom.c * generic/tcldom.c * tests/dom.test: Fix for the problem with ownerDocument reported by Oleg Oleinick (see test dom-29.1). * generic/tcldom.c * tests/dom.test: Fixed bug with COMMENT_NODEs while using the asList method (problem reported by Ramon Ribó). While at it, also added code for handling processing instructions, which was also missing, up to now. 2003-01-11 Rolf Ade * generic/dom.c * generic/dom.h * generic/domxslt.c * generic/domxslt.h * generic/tcldom.c: Added conversion of XSLT stylesheet DOM trees to 'cached' xslt cmds (new domDoc method toXSLTcmd). Works for non threaded tcl; needs additional work for multi-threaded tcl and documentation. * generic/domxslt.c: Fixed a bug introduced during rework of the white space stripping for XML sources. * generic/tclexpat.c: Editorial change (Typo in comment) 2002-12-28 Rolf Ade * generic/domxslt.c * generic/domxslt.h * generic/tcldom.c * doc/domNode.* * doc/domDoc.* * tests/xslt.test: The xslt method now understands also the options -ignoreUndeclaredParameters and -xsltmessagecmd. * tests/xpath.test * generic/tcldom.h: Editorial changes. 2002-12-23 Rolf Ade * generic/domxslt.c: Reworked the white space stripping for XML sources a bit. Better white space handling in token lists. 2002-12-21 Rolf Ade * generic/domxpath.c: Fixed the changes by me in rev. 1.60 in the XPath Lexer. 2002-12-20 Zoran Vasiljevic (zoran@archiware.com) * generic/tcldom.c * generic/dom.c * generic/domxpath.c * generic/domalloc.c * generic/domhtml.c * generic/docxpath.c: added DBG macro around some fprintf's 2002-11-28 Rolf Ade * generic/domxslt.c: Reuse already parsed trees only if it is requested again for the same matter (as stylesheet or as source dir), otherwise create a new tree, because of the different white space stripping rules for stylesheets and source documents. 2002-11-27 Rolf Ade * win/makefile805.vc: Added this file. VC++ 6.0 makefile to compile against tcl8.0.5, contributed by Sumit Pokhariyal. * generic/domxpath.c: FQ names with a localname equal to a XPath 'keyword' (for example ns1:div) are now recognized as node test (they raised error up to now). Changed generate-id() to return the more generic named 'id' instead of the up to now used 'node'. --- Release 0.7.5, 27. Nov. 2002 --- 2002-11-24 Rolf Ade * Makefile.in: Changed the order of the include dirs, to avoid clash with tcldom.h out of TclDOM-2.4, which will be installed in the same directory as tcl.h 2002-11-22 Rolf Ade * configure-tcl8.0.5: Added this file. Special configure for Tcl8.0.5 users. * README: Updated notes for Tcl8.0.5 users. 2002-11-21 Rolf Ade * doc/expat.*: We don't have a 'provide expat' anymore, it's all tdom. Fixed a typo. 2002-11-17 Rolf Ade * generic/domxslt.c: Report error, if xsl:import elements not come first. * doc/tnc.*: Better wording. 2002-11-16 Rolf Ade * win/makefile.vc * extensions/tnc/makefile.vc: A bit final tweaking for 0.7.5. 2002-11-16 Zoran Vasiljevic * generic/dom.h * generic/dom.c * generic/tcldom.c * generic/tclStubLib.c: fixed references to panic (now Tcl_Panic) Also, fixed some 8.0.5 compilation issues. * README: added some 8.0.5 compilation notes 2002-11-16 Rolf Ade * generic/tcldom.c: Fixed bugs, which only raised there head if compiled against tcl8.0.5. * tests/all.tcl * tests/loadtdom.tcl * tests/domCmd.test * tests/domnamespace.test * tests/htmlreader.test * tests/i18n.test * tests/xmlsimple.test * tests/xslt.test: Made test suite also running under tcl8.0.5. Added constraint to the tests, which uses i18n tcl features. * doc/tnc.xml * doc/tnc.html * doc/tnc.n: Updated documentation. 2002-11-15 Zoran Vasiljevic * generic/dom.h: added IS_DELETED node flag Changed domFreeNode to accept one additional parameter. This parameter is used to signal the function to perform node-walk and invoke user-supplied callback w/o actually freeing the node. This functionality is required for example when a thread detaches from the shared DOM tree and wants to detach all eventual node commands from its interpreter. Added "struct domNode *deletedNodes" in the document structure This is the head of all nodes spliced out of the tree but not yet free'd. This is needed in order to avoid memory trashing when one thread deletes the node and the second thread still holds the reference to it over the nodecmd command. Added "struct domNode *nextDeleted" to maintain the list of deleted nodes, as explained above. * generic/tcldom.c: introduced changes in the way nodes are deleted from the tree in multi-threading shared-tree situations. We now do not delete nodes having references from nodecmds from different threads/interpreters. Instead, we put them on the deleted nodes list and tear-down this list when we delete the document. * generic/tcldom.c: when a thread detaches from the shared dom tree it will now properly delete all commands attached to nodes. Also, the dom object command barks when attempting to use already deleted node (the node put on the deletion list). 2002-11-15 Rolf Ade * tests/dom.test: Added some tests for as yet not covered node methods. * tests/htmlreader.test: Minor fix: added tcltest cleanup. * generic/tcldom.c: Changed 'attributes' method to return the empty string as result for non element nodes, according to the DOM 2 rec, chapter "Interface Node". Fixed a seg fault in hasAttributeNS. Closed a mem leak in appendXML. * lib/tdom.tcl: Added simple debugging feature to tDOM::extRefHandler. 2002-11-14 Zoran Vasiljevic * generic/tcldom.c: fixed UMR report from Purify 2002-11-12 Rolf Ade * win/makefile.vc * extensions/tnc/makefile.vc: Updated to the new version nr and the lib name convention of the new TEA 2 build system. 2002-11-09 Rolf Ade * generic/tcldom.c: HTML serializer: No content escaping for the HTML tags script and style, according to XSLT rec 16.2. Fixed a memory problem during interp deletion. * generic/dom.c * generic/domxpath.c: Minor changes. 2002-11-03 Rolf Ade * lib/tdom.tcl: tDOM::xmlOpenFile fix for files < 4 Byte size. * generic/domxpath.c * generic/domxpath.h: Fixed ridiculously long runtime of certain // expr on certain documents. During analysis and testing, it turned out, that it would have been an even simpler approach, to simply expand the abbreviation // in the according productions. Though, the chosen implementation seems often to be (slightly) faster and is a start to collect experiences with early predicate evaluation. 2002-11-02 Zoran Vasiljevic * lib/tdomhtml.tcl: removed in favour of new tdom extension * extensions/tdomhtml: added new tdom extension for HTML generation based on tdomhtml.tcl and internal tdom appendFromScript mechanism. This is a Tcl-only extension which merely needs to be "make install"'ed. * Makefile.in: removed traces of tdomhtml.tcl file since it now lives in its own extension * configure.in: * configure: added TDOM_LD_SEARCH_FLAGS processing to help runtime linker locate eventual custom shared libraries 2002-11-01 Rolf Ade * Makefile.in: Fixed 'missing separator' problem (using tab instead of white space). * lib/tdom.tcl: Updated function-available, corrected ridiculous typo by my (element-avaliable -> element-available). Somewhat fixed and updated element-available. * generic/domxpath.c * tests/xpath.c: Full qualified XPath function names now are accepted as syntactical correct expr. The function call is resolved to the Tcl proc dom::xpathFunc::::. * generic/dom.c * generic/dom.h * generic/domxslt.c * generic/nodecmd.c * generic/tcldom.c * tests/xpath.test: Fixed old problem with Combine Set XPath expressions and XSLT sorts on trees, in which new nodes are inserted after the initial parsing (doc order of result). 2002-10-31 Zoran Vasiljevic * lib/tdom.tcl: does now "package require tdom" only, instead of "package provide tdom 0.7.5". The "package provide" with a correct version is done by the C-module now (which is better). Some cosmetic changes as well (keep 80-columns wide!). * lib/tdomhtml.tcl: renamed version of domhtml.tcl Also did some simplification in html2tcl, renamed some internal private functions and added namespace-wide definitions of html command names. The _2tcl procedure now creates the missing elementNode commands as it parses the html code, on the fly. * Makefile.in: changed order of loads in the pkgIndex.tcl. First the C-module is loaded, followed by the tdom.tcl library file, followed by the tdomhtml.tcl library file. Thus, the tdomhtml.tcl has become the first class citizen. * CHANGES: added this file 2002-10-31 Rolf Ade * generic/tcldom.c * tests/dom.test: Fixed argument check of domObj method documentElement. Fixed domNode method appendFromList (wrong list format could result in seg fault). Thanks to Oleg Oleinick, for reporting both problems. * generic/domxslt.c * generic/domxpath.c * generic/dom.c: Fixed mem leaks/possible invalid read 2002-10-30 Zoran Vasiljevic * generic/domxslt.c: added proper cast to arguments passed to FREE() macro to avoid compiler barking at us. 2002-10-30 Rolf Ade * generic/tcldom.c: Added -escapeNonASCII and -htmlEntities also to node_usage and domObj_usage. * extensions/tnc/test.tcl: Updated to use new tDOM features. Made more usable. * apps/xslt.tcl: Updated to using domDoc xslt method, -escapeNonASCII for asXML and asHTML and additionally -htmlEntities for asHTML. * generic/domxslt.c: Implemented "Forwards-Compatible Processing" (XSLT rec 2.5), with limitations: xsl:version attributes on literal result elements are not supported. Fixed a bug in XPath func format-number(). XsltProcess now accepts also a domDoc. Improved the setting of the documentElement of the resultDoc. 2002-10-29 Rolf Ade * generic/tcldom.c: * doc/domDoc.* * doc/domNode.*: Added -escapeNonASCII as option to the asXML and asHTML methods and -htmlEntities as option to the asHTML method. Added "xslt" method to domDoc commands. * generic/dom.c: Better error reporting in case of parsing errors in external entities. * doc/expat.*: Fixed a documentation bug. 2002-10-29 Zoran Vasiljevic * generic/tcldom.c * generic/nodecmd.c * generic/nodecmd.h: modified "dom createNodeCmd" to accept the -returnNodeCmd" optional argument. All commands created with this option willreturn the dom object command for accessing the generated node. * ChangeLog: added this file tdom-0.9.5-src/manifest0000644000175000017500000004640614703531020013501 0ustar rolfrolfC Regenerated\sthe\sdomDoc\sdocumentation.\sFix\sfor\s[095e293157]. D 2024-10-15T18:18:56.747 F .fossil-settings/crlf-glob 3fc81610a0f32c43d5830d2e2b08d1a0cbfb74f5 F .fossil-settings/ignore-glob bdfbbdd88f6c9099755206650cd164eb37aca373 F .fossil-settings/manifest a09a968bf05a50058f3ad50132730b719bc39e76 F CHANGES 23f286095325f92085f2fc7ac301d1f021f271546b8d81bc4f3ffda075d9ca34 F ChangeLog 9b60ec8bfbae84e4f1a97aaee24be00ccea212b7 F LICENSE 7c00b00fe8e88c48498a54c103dd7df03faeeb039c783279d5fb54dfca307b77 F MPL_2.0.html 326b847674d6f5846c5b260fb437372e21232c23e3911f3a94f766a62459126c F Makefile.in 8752adb175f09928e5ed7d1b27f145691491ee10413ad0679028f013a56bb1bc F README.AOL ffc12d94884ccc619ec6004a55474e9c07b9ac9ea4ef6e01bbec80534ceaa5eb F README.md 53171cdf688c9164f05e123fb1a4fa1314e7aeb5739ec97b65e19d97360890ff F aclocal.m4 5d1a079a02416ab1653487c02261ecf7b7a3c2b7 F apps/toschema.tcl d9cb806e8f1a10ee9a6d6e8b3bd5944124a12001a086b5bc8511b6e92f9af620 F apps/xslt.tcl 64103132fbe0a1fbf61cf3506608cb7ea5cbfddd247d207d95d8e96a071e1846 F configure 29a0707314c2c667ddd9b79bf891dca5a1cc45d8de252ff0992bc60c04803c0e x F configure.ac 181ec174cdeba32ab0843ea0ac185f651fe4a85cd9d077342ad4e38747012648 F doc/INDEX.MAP 8b9f0c2e18efc29fcf581669e175dec860f54026ef7fef4b8d7403bca442fb71 F doc/README 706bce83708ba3eb9a81452364ab445c79e63ace F doc/category-index.html b4a8d2a4b261d8380849b9fa2b4026f1e08248aab543551db47a34b60a43c69a F doc/dom.html 08088b66afb73d14e90bb40f9a8e8820799ddbfea31f0c44f740c032e0a97b43 F doc/dom.n 36039c609ba666385150dc5670d6b448541e92ed7c2ab903046b73df5f31d057 F doc/dom.xml c19931acb2303e4b272aefb45ef1c70760b62a641fc055da4ee851f845e4fd3f F doc/domDoc.html 4bfb6ca4d655e8276aa1ec772450e2dc8f4f4a5ff182cbbff95d67579c63a5ec F doc/domDoc.n e6a096be1d924465b005718228ccc212c81da2d678ee4abcc5805585c66f0b6f F doc/domDoc.xml 0f02b326fae96fa07567195a4276d1b10586445fb1dca27f6a6f34b18160448e F doc/domNode.html 4b2cee76460497a89248ef7d7ff06ab65f83eb5069e554c6813d07324bfcb8ec F doc/domNode.n 878b3377fa12ab35b9ca174b6a53e1a92a7cfad11a6f50b0a4b69b29f0c85ca8 F doc/domNode.xml e4796905e6023220411c38f19f5300ca712d1df18c5463c5105ead2f459f9e38 F doc/expat.html 11beb7f63ba8a33eca588ae1c7c89f352d62834152f93bd14497b070ad6b81a4 F doc/expat.n 4bafabf8790fbfde99904f0498f74ebb9fafa3d6adf48f349cb1858e3ccc528f F doc/expat.xml 3fabc575f8af185bca350a4ce5e452e1ec084f8e2c1182ee637f3eb2f7b43b9d F doc/expatapi.html 7b3467af8fb48953e2474209ba25218b221e559cb3b1273a58ffc683d0068e53 F doc/expatapi.n 593e3175e9e797498c597b11eafc34327f00a1f6790fddbe9d2f1046c658d722 F doc/expatapi.xml 167fca5f81a6eea40a63384c7264288358e5b67ab7d8196711f9649f8c335523 F doc/index.html 9de197acba7e31c5aceca801668f743ec5ac0ee4cb4fa9c5e0aa13a5f4262501 F doc/keyword-index.html 154e20dd68e7b79579bd35374451ba9e1d1b74c571b63a66cfd5dfb7bc48ed1e F doc/manpage.css 3b4ec1d641048933a7e6bffc659de9519030a959 F doc/pullparser.html 41575ceab09859b89f40971de60f298ff32d129626da0410dc66525aea6930fd F doc/pullparser.n 4d47099aa552d6513b1a269247acd69df6488014d5bf0f51525187a875fd39e7 F doc/pullparser.xml 30132bb8d2afe3b3ab568da3145dcde6f090197be86bee74f8d028b83fdcfe8f F doc/schema.html 4ed42a9320a306b17bf2cec0535ca931f2af0b702bc513f441f9129f1d2ae035 F doc/schema.n 46cf6fc78cb23a252cf2d8f3024c8b867831fbb91def7575ca5efa65783fbc34 F doc/schema.xml 426edda0cdd6787e61ad86ef5b04915591684b680a1e6c20cec779694b42306b F doc/tDOM.xml 04db7d0ccfea39aae21f4fe07b8f05d5bff8a84193cfce2aa5faa2f42c076377 F doc/tdomcmd.html 4b954693f3994714c2b9bbe54d298b1330924a2b518e43029949e264e6bc7834 F doc/tdomcmd.n c06a5ff035f16a2a52636b69d9ebe6ba84ff5101922ed27b551146c4d61d6cda F doc/tdomcmd.xml fafa21389acf83585785f6cd7507cf71bf8fffcf48477137c020459acc1ebc53 F doc/tmml.dtd 63259dc9f69f9104f1515be445b85b195a1fb990 F doc/tmml.options 8a76115c6e9725e8dae55b3005e8ba9878023bbd F doc/tmml.rnc 65a2a69ac3347b19aa57e70bb127a4923f5dfc95 F doc/tmml.schema 0d252aeabfec23f7844bcac9029e93b32a5bc508dbd1d5533ceb0182ebd07c13 F doc/tnc.html af944e60c9df37798ce1d0bcd123000a9f3635935f94d19f911e26bf7de70a71 F doc/tnc.n 0e8fa5f4ba1f8f3763ca8357ee7968fb6f0496e4 F doc/tnc.xml f6d0115fbfac8393343b46e6fd1bba50deba17bc F expat/COPYING 476abf68489f02dcddfb6112d9e92f784a783622437dbc99bcb1fd7eb14b670e F expat/Changes 67fbff312ef0867c20482950855031a9c556f2baaa8e7b7f694a9bd536b04cc9 F expat/VERSION f7b89cd26ba1f8aa7183bc9932f136ae08edb47daa33b419d0146c632662f2a6 F expat/ascii.h e8752c5f09c75d1c5b6eaf50d359c8b2b173d5243ccb2f468b858e35d36d04c3 F expat/asciitab.h 7e665d7c5c93a5cd7f182a64dccd2a0771842d00f58706f99cc28e4554ddf9da F expat/expat.h b75b84113781746cec74c7c3a8579f70ac9ea4d81ba8fb3e1e91125f7475696b F expat/expat_external.h 22207c9c718f4a09ada2847842290117f178ecb9bdc1f0d6d4dc4cb8632b80b7 F expat/iasciitab.h de065bf25c951d50bf37f238c113b4c6b89d406592061bd67dcff5816e501459 F expat/internal.h b79f94bc8ced01b2f89a9e41fe592e5ba84fb89ede9e086cade1ccd0f8ec4ba3 F expat/latin1tab.h 2be294b7300ab6c6298ae7bb852778dcfd666a99dec3c779a7cca3826f76a260 F expat/nametab.h 30cd38454c40812806f55053f58791c8b1db8ce293d83e10b5d31ed517add4a9 F expat/siphash.h bc0f8bd627bf7d94895ad804d785cce28836bd97c59bf3fd68c2ce1e34e69c3c F expat/utf8tab.h 2f04b270d7c0d005f203477515a1a054e7538e1ed013cb48ecd4a4e2489b208b F expat/winconfig.h 047bdb572a458710a71517f96c00e69b24d952bedbbf6894ffeec45b97221ccd F expat/xmlparse.c bf6c4e8349a8a9d5fd46d1b7afce9e23aed7ded7c8b15aa8a44706222f166dce F expat/xmlrole.c cc9e5f37e88a115d8de2d2278798e76ef8732fe9571a38d858eef87b43cfe767 F expat/xmlrole.h 9212092e0ed62049175171ac81207aa8f8ac6ed79f3df5dde1206c6879d789f1 F expat/xmltok.c f8c21c747a60dc6501accffd2f4538a8c8f5024937afc53112694b8fa1df19a6 F expat/xmltok.h 2d5bcb73ce07a5c1178bf18c11646c6e47b05227dabaa322a882a51ff9ddfe3a F expat/xmltok_impl.c 33ecbcf27e1aeaa187a44dd20f12ad72755816b9c9e47dd3c76eecc60267c462 F expat/xmltok_impl.h 4aacd280def9b42097ad6136e714babb066df12736926473eab3886db8875dce F expat/xmltok_ns.c 13964b8b88a42b67b3273829e3ffa2a2de96ef1621c57cfcfabb6c97d69c4717 F extensions/example/Makefile.in 74af47e4786c4a89ba4a0df8655b474314c5c4902b4a65b98049d71183078a2a F extensions/example/aclocal.m4 4d6d980ca968b21ba6f8745304357edc44493e65 F extensions/example/configure efb0392d880434d3891efeeb51841dd64c4ef2aef43a357c7a0d3fc3fb280607 x F extensions/example/configure.in 68a3a3201a8a8b6ba56b40ba5feee1072b03dede F extensions/example/example.c d866b87b725b6897decaae13152ddf4479b8d8e01bfe225deaca983bee7cefab F extensions/example/exampletest.tcl 555d6982f352083a759a40178d99f8d4efcea63d29215a4c1b998285c5fb7ea6 F extensions/example/install-sh b087e5c4b92820c60bffb74acc1d9c2d40d80b8f x F extensions/example/pkgIndex.tcl.in e6cc33c6f45df109209f4d8412cf2d5ea434e34e F extensions/example/tcl.m4 9404ac273b962ddaf946d3170c5183e55d0984b3 F extensions/schemadtx/Makefile.in 74af47e4786c4a89ba4a0df8655b474314c5c4902b4a65b98049d71183078a2a F extensions/schemadtx/aclocal.m4 4d6d980ca968b21ba6f8745304357edc44493e65 F extensions/schemadtx/configure fa5552c28b938b5b4733bc03390502e9ecf0a26b1995b596b63533058013da57 x F extensions/schemadtx/configure.ac f7523142dbb77cde51d4333393d5dd8c1fd92ad995358a9723ecb1fc3739346f F extensions/schemadtx/pkgIndex.tcl.in 93156e39702854530db4e84803b1812b2d472449ac47358344810a29c56530a7 F extensions/schemadtx/schemadtx.c f63bcf5b442c37c7d57c7828ada18a19dffa1fa2c956452a2ecf034f24ca26b0 F extensions/schemadtx/tests/all.tcl 01c5540732680c9bc11b36f8b44fb7be2cd4621de7d536d97e72d88ed03102e7 F extensions/schemadtx/tests/loadschemadtx.tcl 3b669926e01801833d6caaf55e748ae92291438014d116ff10fbc658e678e603 F extensions/schemadtx/tests/schemadtx.test 6c36dec706e91edd4a05ddad059a3276dcbf6d4f71d60fe0a91d21ae8e6ad684 F extensions/schemadtx/win/makefile.vc 1377e9de79e06c7c90bb9414f8f11daa2a9f119e77a7a229c121dbe118133d6e F extensions/schemadtx/win/nmakehlp.c 194ae7c24886245c679cb4c9ea7e6daaaebb5fcd F extensions/schemadtx/win/rules-ext.vc e788fcfc1e69b11946e18b8f67e0870b3bd38913 F extensions/schemadtx/win/rules.vc 8157e2a811cf5e93683d6b0fbf5d91d153aa4535 F extensions/schemadtx/win/targets.vc 79dea1c6a94a94e6ed8bae9e0195149b25a69923 F extensions/tdomhtml/CONFIG 7a3703be0e018ead9b6558ce6d82f356620dbfd8 F extensions/tdomhtml/Makefile.in 1008fe906a0b7150e5b83f69e43a231886821db7 F extensions/tdomhtml/configure 47edbb79649c148c4c439b93a329e70e647e1225aa35236bbc5643c9e3484190 x F extensions/tdomhtml/configure.in 22c8425b9c44c0583ccbadaf3ea3cc7185987ceb F extensions/tdomhtml/doc/tdomhtml.n da39a3ee5e6b4b0d3255bfef95601890afd80709 F extensions/tdomhtml/doc/tdomhtml.tmml da39a3ee5e6b4b0d3255bfef95601890afd80709 F extensions/tdomhtml/install-sh b087e5c4b92820c60bffb74acc1d9c2d40d80b8f x F extensions/tdomhtml/pkgIndex.tcl.in 2612d2a8fd5a213a1379ad5570c229d82810dcb5 F extensions/tdomhtml/tdomhtml.tcl 6901a0fb8db80954dd635e181934b9e3ba3a1864551155f3d5c01355ddbf0a45 F extensions/tdomhtml/win/makefile.vc a6ba491c8f63a88c607c443e7a80f1369cb3c40c F extensions/tnc/Makefile.in c7f74cda510a493a7c1539f1db9118be38b9482b57d4f9b51618c9aaf38c4a9a F extensions/tnc/aclocal.m4 4d6d980ca968b21ba6f8745304357edc44493e65 F extensions/tnc/configure e4340f98323fdc8e4abba3bd37ea02405455aacc4c8bf8ffa7731e3399b79dbf x F extensions/tnc/configure.ac 4fd59a3f8af1b8ff8db46c2fb007e692e43a55088d00ad0b4d8b5328f8888d10 F extensions/tnc/install-sh bdd5e293591621ae60d9824d86a4b1c5f22c3d00 x F extensions/tnc/pkgIndex.tcl.in 5c4022af93826a1d4f13f6105e86600d20b914b8bc9a0f48c0d98b3108b00a06 F extensions/tnc/test.tcl 545cdec17e6702cef9f79184fdf1ce0166b8c412 F extensions/tnc/tests/all.tcl 845c9dab65c294c3570f69cc731d6fef62efbd03 F extensions/tnc/tests/loadtnc.tcl c9b49c87af627263d40dcfbdd005bfddbc2a6ab5c8636d25618034c724e91c71 F extensions/tnc/tests/tnc.test 689eb32d186e04de0b0809333ad39f8a23ec1467fa545b790e7959ed7b09556c F extensions/tnc/tnc.c 48ad58bc421cd51e29e30890d4fb8707dbb4dfe56c88dfae0e52f30f8b8fa03a F extensions/tnc/win/makefile.vc 51edf6f542aa90a9195b4a217d15ae7a4df488faa15c4ca723bc2705640b6bc9 F extensions/tnc/win/nmakehlp.c 194ae7c24886245c679cb4c9ea7e6daaaebb5fcd F extensions/tnc/win/rules-ext.vc 3c02944b3199014d35de617a1c146d0944af16395870da423374fb013ef57ecf F extensions/tnc/win/rules.vc afa89d3b334f5958efc447c985949447a9b05f6c891c7e1e8c0423ed226e89dc F extensions/tnc/win/targets.vc 3627f336071161bfb6bbaea40465b731e42f4ad750189a967e58b1ce40b4eb0b F generic/HTML5ent.inc c122e35eb1be8e325f8846080bbccc166978cfe7136e850d7e8aa477824d2b8f F generic/aolstub.cpp 0a4cd5a84d820496ca10237e934b8b4ccac8f827 F generic/datatypes.c 7c9f9edb50b4592b2317dfde3db6feaa342e80f1322aee4b747eb98c486d959b F generic/datatypes.h 3e41d07bcf50cf6959b6e14416dfcb0d7b5aafc65683322978ec185c2a259332 F generic/dom.c 4c6b86394c6a12f1d96aa0bbee278be905a29e0edb65aa9493aab00a29cc1652 F generic/dom.h 2f733ca4b641c2b7eb85a59a81ec661d948c81bee4bacc901c1a56170360b6cb F generic/domalloc.c ce41b8a16e855ee3a3db1d4b797f835a77f1f9260f24db4cb7dc73a07ee4670b F generic/domalloc.h 961f83bb46dec27dbcf36ed430ed81b1f485a1fdfaa2f7df8b60bbcf861d0fe3 F generic/domhtml.c 29adbc4af3af84881a8e97b151f8bc5add56e20d73821ae25d4c46f7e66483a1 F generic/domhtml.h cb031185e99066889bec37b32239ab0f932d673a5701c94429902b2332ff3784 F generic/domhtml5.c 53c3f44545864e51ddd6022e6de71c24bc5768ec009e5447c7a5e7bed556c6be F generic/domhtml5.h 5cca562a556e7662f2dce222640c32abb2777146 F generic/domjson.c e586b5c11069ca550078d0ed9cb776f0e9307fdf097e4e9a7a217ec66a4609c2 F generic/domjson.h 5cf49e967a4127b1c706ea2d7f5bf8be227cb59bfbdaae26cfcb9267b710fdf7 F generic/domlock.c 60f6c6f4dc95d6525f77cd589a07f6ec78f2068b12821067c5a075a2740abacb F generic/domxpath.c 9cc53657befca50d78ae9ef4aa97dc671f889d7732eab6a1b41adda1d480d9ec F generic/domxpath.h a98836ef133283a20855968b76821042bce16b57b664689a15c017e3fecdae2f F generic/domxslt.c 7f9ce337cd2c261192395d1ae94e1967b5a735a0afc84fc809623546ab9443fb F generic/domxslt.h aeaf957ee38a9e7564bd9f1bed1781de108767df476a0d0776615988d8f04e0f F generic/expat_config.h 560c148d431f87fc99ae8553cf998f0d01b0db82 F generic/nodecmd.c cd86d79364a11fd67444a82f8a1de2ad10c01a33154c1bed767d58fec6142547 F generic/nodecmd.h 36056ca2c262cb1991cabef8d27992ad628db718d09ff0eeaeaffd150f1549ec F generic/schema.c fc5ca4010cdca4737741ddd733b6e3dcd74e7010ffbb68edeeefa181fa2367af F generic/schema.h 5e20a348c3f98724e9c118760c8d9fcd661ae8f27d21652d90ab49492d001c75 F generic/tcldom.c 9ecc27300a81e9b0fc12029e75e92922562cde82c6f46c10ccf1d5a0d4892739 F generic/tcldom.h d8a198375e823af7d95b78f2ef695ac84b3f6d50232ab33ad82fcaa2502ea5e7 F generic/tclexpat.c dde665d8791e4e5f0dba6f695b842f270e0f45acacad1584f99e722e56e8e20b F generic/tclexpat.h 3844441852af770876f2de9b7444a0445e9c5c7f1fd5cc3a50e7455538d4e912 F generic/tclpull.c 8f7b6cca2519e19aeb68fff50c16238b4a68ed86b1db2c5927452f9e8d936629 F generic/tclpull.h 8e1aac98bdad497c669c901494939eecd6c2f57ea51c4f5d4dac502db48527d4 F generic/tdom.decls e41c101c51f9a988ef799442e6082283ac21a28ed1105b21b228a4913c13eb95 F generic/tdom.h 0ce348a4e4ae4c5a5e11d02ca2079ce2e8f1f705aecceb83c8d29b3ec80e5617 F generic/tdomDecls.h 93563f54a18aa836498d4e44587e42561518e59c6ba68c356ead6a715fad6f40 F generic/tdomStubInit.c e68ec41b2430f23300e37c584a043bcfc6f2cdf38d9f1e97059366ba4ed42e17 F generic/tdomStubLib.c 4a055f9c974246a9f7dd99de1a7686d1a96be8f02be699fdf4a760fdc813eb45 F generic/tdominit.c 925c91ddc69f9eda3f8eabe73b3f9d6260a4c4503b11e09c563964f7718849bd F generic/xmlsimple.c abb069b9e3754efa2830b2535e234670229b8c4c6e81b68754d7c2aca3fa3eda F generic/xmlsimple.h 6cbbc9208bcaec273624fd5e24aff3de07ef98d1da3be4576f3e6d4951516054 F lib/tdom.tcl cd3bdc7a05ea9c6d0d17fd12d68e72c92e64f501106ec74c19e85ac963ade570 F macosx/README 75fe1f6617f6cb7e4480cff5367b5c26fcd8dd207e2321f35dceebafccf4c99c F pkgIndex.tcl.in 2c2ecfb3b4176ae61af4445e022b34bb9071efdbf0446c2aa2d0f6cfcce3f120 F tclconfig/README.txt 22e2b8305785370b08ef9c18aa62408f5fe972655f3a4fbb0dc55bc8beb60e67 F tclconfig/install-sh 2182b3705d92e25753411e2c28cf788c69e35a48fbb8aa332e342dfc6b95b80d x F tclconfig/tcl.m4 284faa1d9cf66c1efb42817beb5c8a63626fb35bf903993d4f11fde75677cc1a F tdom.m4 e1a64242a30a7f3c94859c128e1dd26d78c8c6ecafab379b131e3608596304a2 F tdomConfig.sh.in 1f2f873de2a2a84a93949372767a78c56ee72e0700a156b87a2769884ad5ccf1 F tests/JSONTestSuite.tcl 907228f9bd31855951b9033df74c9c15778765af F tests/OASIS-suite.tcl 1da66ffffee97dd7c39d3f14482f5a9382000d4233668c7f2ed1c5825752904e F tests/all-bench.tcl 1444cd15eb49d934cb08f75f59b244363372dd23cff13470f5b14580cc33ca47 F tests/all.tcl 14e2ccb0550ad38328f58ad79b3353e6cc110779ed94ce21ecdd42853be0637a F tests/attribute.test 53ac8fb043e79b638c8c6f5e7da848f6103552d6 F tests/cdata.test 5a1dc3bee6353700186d12f0d11b15914849c6be F tests/comment.test ff9d1abbbcde4d3532bf93b1eb7e819997fa8178 F tests/data/REC-xslt-19991116-mod.xml f49602be921b5e3f24bf11fd3ce5cefd86d5afa94889a4071ed6638a65d2b64d F tests/data/REC-xslt-19991116.xml 037d39caac3e4cc8964848a7b0eb9a4b385520606a635e1f54f2aff9802b5fd4 F tests/data/books.xml 0b1ae696b2bbc1035303f5637a6ef67f041d0b9e F tests/data/domCmd1.dtd 2031a36d155dfac8f0a5ef3be69958d250f5459e F tests/data/domCmd2.dtd 42200fe458c04d2072e71d8fa00ade2cb1c59878 F tests/data/dtd-5.1.dtd 8f16a5c1ff5181e7136cd0d0f1255ae269c38e3c F tests/data/dtd-5.2.dtd 6a2dbcda86b1729c9789c40ea2d592fff9434939 F tests/data/dtd-6.1.dtd 705abb4c198575b4035af700a2943710318e3c83 F tests/data/dtd-6.2.dtd 2dc65db913747dc331f974383c2ca488cca78bed F tests/data/dtd-6.3.dtd 1a368d162a607f43d30a53932378678c6bb39c09 F tests/data/dtd-6.4.dtd 86c52ff258b73e9530a36452a21fa8b62d380f15 F tests/data/dtd-6.5.dtd 961850932623ee218b1cc2cbf544662a9942f2ce F tests/data/dtd-6.6.dtd a1036539ff132635da3e368604b59651a47909e4 F tests/data/htmlmathml.json 00ab0ff0335a64464df1b11c62e7a228cde203505e366094276c89638171dd3b F tests/data/i18n_1.xml 7b4282addd307b17940fffd818de016ca64311fa F tests/data/i18n_2.xml 4dc16d8ee2337fbd30061dd1159f6c49b2d0a52c F tests/data/mondial-europe.xml 61790f95c676755667358b6ddfc46eb8cc3f470b F tests/data/xmlspec-v20.dtd dcb796f8ff379dad58487ed43d12775eed7d6d0ead4658e461f7a731d86a5293 F tests/data/xslt_1.xsl e96e4c1f0cd3467141815c97fe917333b09e8de9 F tests/decls.test 06d0ba0cbc18e26a1524cb17a6ef9adf2a0fc864 F tests/doctype.test 015c514bd8919467c1074dc3068a527abb3988b5 F tests/dom.bench 5446ce379127b8d5700f18a5a0848e580313d0d7 F tests/dom.test b9f10b31f3ed7f67032bb19be19b3e3ad8df923515bd690dfcd0f54a5e04682d F tests/domDoc.test 03082c24746147cc0a5f048820ee3da5c730054828e2a1cdf99b58053ff660f0 F tests/domNode.bench 3d457513be7908bab88ac0e23e1864f7341e3090 F tests/domNode.test 873731415203a1a70be5977b613cf90f80f1791d82956d254e630c24440d318c F tests/domjson.test 0a2320eccd2e9083b4c5bfecfbebf097dea2e9a2a7a7367020014ca7a5affba1 F tests/domnamespace.test f68dee13e2325518e96b318bf9fe76ae6903dc38d5602c4b0f48f90c0dc3038c F tests/element.test 4c5f0094543ee9167f86748e2d667347f57eb911 F tests/entity.test 065c6c1af854db838faf9ad56151342eee478f8501a5f65778a144b106108574 F tests/html5reader.test 186ff343d2b75c8b784f3fe64fc664f8c83901f46c1f202077ce963f47b51983 F tests/htmlreader.test 1a7d62ad1bfd1066349b1115a8e7a561befb3d97fcd207cf312b7f56a4a871bf F tests/i18n.test 421e3998480ed5ce9420f4b596c384b8d5261e7fb4b33c0a7c12ef126d476939 F tests/loadtdom.tcl ade9a801033aeedb4763be5c1d4c71ed86a75875503799bcec9bf00ca1c0e4e7 F tests/namespace.test 0a13b2bf59bb088525ca7b64d0b2bce6a349c627ca3dd1c17a4cc969d16fe57c F tests/parser.test 87eed84aec743e2ac02959a7276cd715bb764c2f479f566a69fb243ff2d72f5e F tests/pcdata.test d24772594d762437300d6a48231f0eb16553855a F tests/pi.test 22a24ce658e1c84b05b986c0b2e010c5a94076fe F tests/pullparser.test 4ca2b332ec1eb31efb294b9e6556a58148a1d28a3c3d1cbb6800dc19f3887b79 F tests/pushpull.bench 664e8f512917537d96c4b71933d4d9a6da65fc6fe85bd7c459483830dc7d2faf F tests/schema.test bc98d97f924b20ab3e120af65bef4030d79272c347d962f7092640c5a3c15813 F tests/stackedhdl.test a3efca3d0f095cfdeddc3e67734b9d79567b0fd1 F tests/tdomcmd.bench b07448ed4de08ccaa9734cf3fe15c695fd7066c993da58ff48d465747940e417 F tests/tdomcmd.test e65bef309a8d7022fba8ca6808c1d0a8029e1e2063df6cdf9b651653b350f7b0 F tests/xmlsimple.test 240e936160a0eab98ddf43343943ba35c3c35fe84182c9f815f86126abeb4389 F tests/xmltest.test f8598eb3ee6a35248af7193d229a1fccd2061109 F tests/xpath.bench a8a90cbce1e276d05c6ff2c54ef04ffb3166c16e4094a543c694256ea4d68355 F tests/xpath.test 67045f566582c565d292180f759294614f0848d09292db2a1137ce48ed0cafd9 F tests/xslt.test 35a5408426b098bcc07bdecfb52f1ec4c8ac3e984224ba497e700420047621a4 F unix/CONFIG 431b82a51451df40e38261b91e1a37060797ef655e8f981fab761de59f1e01e9 F unix/speed-check.sh 7a8d91e7edf1cdc9bcfad5f28e1a068cb2843d05e49d8bd89d9b30a46511497d F unix/tclAppInit.c cd5fa5bcb9f4648e9bf7108727b99e20cd02c33713df359efb1da298715940b9 F win/README d480e01bbb3f480184671f66b4025d7e94e5a6fccb603d6559f6ad92d398d919 F win/config.h 560c148d431f87fc99ae8553cf998f0d01b0db82 F win/makefile.vc 305808a83bed1240b802508262365381ffb73e452f8e2150054b0bd60cb7fe25 F win/nmakehlp.c 194ae7c24886245c679cb4c9ea7e6daaaebb5fcd F win/pkgIndex.tcl 7d8e06a34f36dcf48426710316a6595e49157187ef9b9e9c6e2e98f19df1c989 F win/rules-ext.vc 3c02944b3199014d35de617a1c146d0944af16395870da423374fb013ef57ecf F win/rules.vc afa89d3b334f5958efc447c985949447a9b05f6c891c7e1e8c0423ed226e89dc F win/targets.vc 3627f336071161bfb6bbaea40465b731e42f4ad750189a967e58b1ce40b4eb0b F win/tdom.rc 1463128845bffe1fdf24ab99f562727830855516 F xe/README 91626be10fa0b48c38184bb73b09eea074008fb082559eaf5c0fb8bb83997903 F xe/xe 075a1f1c4a5758222c52a4688f9fe22dc3d925e366316cf50d84501c9ca3fdb1 x F xe/xe-input fb58cbefe5e3acceb9567a165ef7e655ad08b44e F xe/xe.bat 8622c5a70666a58d2316df568354c70593848098 P 38b704fd184326f99fec0a0d264ba90888a25a4d157a6bd30433dcf21ced8a0f R 8fb62d91bd04d096df7cf7e6a93fc0d6 U rolf Z 9a2dc0e847123e347dbf9d793a5a44f2 tdom-0.9.5-src/configure0000755000175000017500000107006414703531020013655 0ustar rolfrolf#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for tdom 0.9.5. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='tdom' PACKAGE_TARNAME='tdom' PACKAGE_VERSION='0.9.5' PACKAGE_STRING='tdom 0.9.5' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS PATCHLEVEL MINOR_VERSION MAJOR_VERSION tdom_STUB_LIB_PATH tdom_BUILD_STUB_LIB_PATH tdom_STUB_LIB_SPEC tdom_BUILD_STUB_LIB_SPEC tdom_LIB_SPEC tdom_BUILD_LIB_SPEC TDOMSHELL TCLSH_PROG VC_MANIFEST_EMBED_EXE VC_MANIFEST_EMBED_DLL RANLIB_STUB PKG_STUB_LIB_FILE MAKE_STUB_LIB MAKE_STATIC_LIB MAKE_SHARED_LIB MAKE_LIB LDFLAGS_DEFAULT CFLAGS_DEFAULT TDOM_LD_SEARCH_FLAGS LD_LIBRARY_PATH_VAR SHLIB_CFLAGS SHLIB_LD_LIBS SHLIB_LD STLIB_LD LDFLAGS_OPTIMIZE LDFLAGS_DEBUG CFLAGS_WARNING CFLAGS_OPTIMIZE CFLAGS_DEBUG LIBOBJS RC AR STUBS_BUILD SHARED_BUILD TCL_THREADS TCL_INCLUDES PKG_CONFIG PKG_OBJECTS PKG_SOURCES EGREP GREP RANLIB SET_MAKE CPP TCL_SHLIB_LD_LIBS TCL_LD_FLAGS TCL_EXTRA_CFLAGS TCL_DEFS TCL_LIBS CLEANFILES OBJEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC TCL_STUB_LIB_SPEC TCL_STUB_LIB_FLAG TCL_STUB_LIB_FILE TCL_LIB_SPEC TCL_LIB_FLAG TCL_LIB_FILE TCL_SRC_DIR TCL_BIN_DIR TCL_PATCH_LEVEL TCL_VERSION INSTALL_LIBRARY INSTALL_SCRIPT INSTALL_PROGRAM INSTALL_DATA INSTALL_DATA_DIR INSTALL PKG_CFLAGS PKG_LIBS PKG_INCLUDES PKG_HEADERS PKG_TCL_SOURCES PKG_STUB_OBJECTS PKG_STUB_SOURCES PKG_LIB_FILE9 PKG_LIB_FILE8 PKG_LIB_FILE EXEEXT CYGPATH target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_tcl with_tcl8 with_aol with_expat with_entropy enable_html5 with_tclinclude enable_threads enable_shared enable_stubs enable_64bit enable_64bit_vis enable_rpath enable_symbols enable_dtd enable_ns enable_ucmd enable_tdomalloc enable_lessns enable_schema ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures tdom 0.9.5 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/tdom] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of tdom 0.9.5:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-html5 build with HTML5 parsing support (default: off) --enable-threads build with threads (default: on) --enable-shared build and link with shared libraries (default: on) --enable-stubs build and link with stub libraries. Always true for shared builds (default: on) --enable-64bit enable 64bit support (default: off) --enable-64bit-vis enable 64bit Sparc VIS support (default: off) --disable-rpath disable rpath support (default: on) --enable-symbols build with debugging symbols (default: off) --enable-dtd build expat with dtd support (default: on) --enable-ns build with XML namespace support (default: on) --enable-unknown enable built-in unknown command (default: off) --enable-tdomalloc build with the tDOM allocator (default: off) --enable-lessns build with lower limit for XML ns declarations (default: off) --enable-schema build with valiation features (default: on) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-tcl directory containing tcl configuration (tclConfig.sh) --with-tcl8 Compile for Tcl8 in Tcl9 environment --with-aolserver directory with AOLserver distribution --with-expat directory with expat installation --with-entropy source of entropy to use --with-tclinclude directory containing the public Tcl header files Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF tdom configure 0.9.5 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by tdom $as_me 0.9.5, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. #-------------------------------------------------------------------- TEA_VERSION="3.13" { $as_echo "$as_me:${as_lineno-$LINENO}: checking TEA configuration" >&5 $as_echo_n "checking TEA configuration... " >&6; } if test x"${PACKAGE_NAME}" = x ; then as_fn_error $? " The PACKAGE_NAME variable must be defined by your TEA configure.ac" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok (TEA ${TEA_VERSION})" >&5 $as_echo "ok (TEA ${TEA_VERSION})" >&6; } # If the user did not set CFLAGS, set it now to keep macros # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2". if test "${CFLAGS+set}" != "set" ; then CFLAGS="" fi case "`uname -s`" in *win32*|*WIN32*|*MINGW32_*|*MINGW64_*|*MSYS_*) # Extract the first word of "cygpath", so it can be a program name with args. set dummy cygpath; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CYGPATH+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CYGPATH"; then ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CYGPATH="cygpath -m" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" fi fi CYGPATH=$ac_cv_prog_CYGPATH if test -n "$CYGPATH"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 $as_echo "$CYGPATH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi EXEEXT=".exe" TEA_PLATFORM="windows" ;; *CYGWIN_*) EXEEXT=".exe" # CYGPATH and TEA_PLATFORM are determined later in LOAD_TCLCONFIG ;; *) CYGPATH=echo # Maybe we are cross-compiling.... case ${host_alias} in *mingw32*) EXEEXT=".exe" TEA_PLATFORM="windows" ;; *) EXEEXT="" TEA_PLATFORM="unix" ;; esac ;; esac # Check if exec_prefix is set. If not use fall back to prefix. # Note when adjusted, so that TEA_PREFIX can correct for this. # This is needed for recursive configures, since autoconf propagates # $prefix, but not $exec_prefix (doh!). if test x$exec_prefix = xNONE ; then exec_prefix_default=yes exec_prefix=$prefix fi { $as_echo "$as_me:${as_lineno-$LINENO}: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&5 $as_echo "$as_me: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&6;} # This package name must be replaced statically for AC_SUBST to work # We AC_SUBST these here to ensure they are subst'ed, # in case the user doesn't call TEA_ADD_... # Configure the installer. INSTALL='$(SHELL) $(srcdir)/tclconfig/install-sh -c' INSTALL_DATA_DIR='${INSTALL} -d -m 755' INSTALL_DATA='${INSTALL} -m 644' INSTALL_PROGRAM='${INSTALL} -m 755' INSTALL_SCRIPT='${INSTALL} -m 755' { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5 $as_echo_n "checking system version... " >&6; } if ${tcl_cv_sys_version+:} false; then : $as_echo_n "(cached) " >&6 else # TEA specific: if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 $as_echo "$as_me: WARNING: can't find uname command" >&2;} tcl_cv_sys_version=unknown else if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then tcl_cv_sys_version=NetBSD-Debian fi fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 $as_echo "$tcl_cv_sys_version" >&6; } system=$tcl_cv_sys_version case $system in HP-UX-*) INSTALL_LIBRARY='${INSTALL} -m 755' ;; *) INSTALL_LIBRARY='${INSTALL} -m 644' ;; esac ac_aux_dir= for ac_dir in tclconfig "$srcdir"/tclconfig; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in tclconfig \"$srcdir\"/tclconfig" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. #-------------------------------------------------------------------- # Load the tclConfig.sh file #-------------------------------------------------------------------- # # Ok, lets find the tcl configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tcl # if test x"${no_tcl}" = x ; then # we reset no_tcl in case something fails here no_tcl=true # Check whether --with-tcl was given. if test "${with_tcl+set}" = set; then : withval=$with_tcl; with_tclconfig="${withval}" fi # Check whether --with-tcl8 was given. if test "${with_tcl8+set}" = set; then : withval=$with_tcl8; with_tcl8="${withval}" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl configuration" >&5 $as_echo_n "checking for Tcl configuration... " >&6; } if ${ac_cv_c_tclconfig+:} false; then : $as_echo_n "(cached) " >&6 else # First check to see if --with-tcl was specified. if test x"${with_tclconfig}" != x ; then case "${with_tclconfig}" in */tclConfig.sh ) if test -f "${with_tclconfig}"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5 $as_echo "$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&2;} with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" fi ;; esac if test -f "${with_tclconfig}/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" else as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5 fi fi # then check for a private Tcl installation if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ../tcl \ `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \ ../../tcl \ `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \ ../../../tcl \ `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi # on Darwin, check in Framework installation locations if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ `ls -d /Library/Frameworks 2>/dev/null` \ `ls -d /Network/Library/Frameworks 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Network/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Tcl.framework 2>/dev/null` \ ; do if test -f "$i/Tcl.framework/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" break fi done fi # TEA specific: on Windows, check in common installation locations if test "${TEA_PLATFORM}" = "windows" \ -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d C:/Tcl/lib 2>/dev/null` \ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ `ls -d /usr/lib/tcl9.0 2>/dev/null` \ `ls -d /usr/lib/tcl8.7 2>/dev/null` \ `ls -d /usr/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl9.0 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.7 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl9.0 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.7 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ${srcdir}/../tcl \ `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi fi if test x"${ac_cv_c_tclconfig}" = x ; then TCL_BIN_DIR="# no Tcl configs found" as_fn_error $? "Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" "$LINENO" 5 else no_tcl= TCL_BIN_DIR="${ac_cv_c_tclconfig}" { $as_echo "$as_me:${as_lineno-$LINENO}: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5 $as_echo "found ${TCL_BIN_DIR}/tclConfig.sh" >&6; } fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5 $as_echo_n "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... " >&6; } if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5 $as_echo "loading" >&6; } . "${TCL_BIN_DIR}/tclConfig.sh" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5 $as_echo "could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6; } fi # If the TCL_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable TCL_LIB_SPEC will be set to the value # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC # instead of TCL_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. if test -f "${TCL_BIN_DIR}/Makefile" ; then TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" elif test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use the libraries # from the framework at the given location so that linking works # against Tcl.framework installed in an arbitrary location. case ${TCL_DEFS} in *TCL_FRAMEWORK*) if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" break fi done fi if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" fi ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking platform" >&5 $as_echo_n "checking platform... " >&6; } hold_cc=$CC; CC="$TCL_CC" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifdef _WIN32 #error win32 #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # first test we've already retrieved platform (cross-compile), fallback to unix otherwise: TEA_PLATFORM="${TEA_PLATFORM-unix}" CYGPATH=echo else TEA_PLATFORM="windows" # Extract the first word of "cygpath", so it can be a program name with args. set dummy cygpath; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CYGPATH+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CYGPATH"; then ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CYGPATH="cygpath -m" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" fi fi CYGPATH=$ac_cv_prog_CYGPATH if test -n "$CYGPATH"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 $as_echo "$CYGPATH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CC=$hold_cc { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TEA_PLATFORM" >&5 $as_echo "$TEA_PLATFORM" >&6; } # The BUILD_$pkg is to define the correct extern storage class # handling when making this package cat >>confdefs.h <<_ACEOF #define BUILD_${PACKAGE_NAME} /**/ _ACEOF # Do this here as we have fully defined TEA_PLATFORM now if test "${TEA_PLATFORM}" = "windows" ; then EXEEXT=".exe" CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" fi # TEA specific: #-------------------------------------------------------------------- # Load the tkConfig.sh file if necessary (Tk extension) #-------------------------------------------------------------------- #TEA_PATH_TKCONFIG #TEA_LOAD_TKCONFIG #----------------------------------------------------------------------- # Handle the --prefix=... option by defaulting to what Tcl gave. # Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. #----------------------------------------------------------------------- if test "${prefix}" = "NONE"; then prefix_default=yes if test x"${TCL_PREFIX}" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&5 $as_echo "$as_me: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&6;} prefix=${TCL_PREFIX} else { $as_echo "$as_me:${as_lineno-$LINENO}: --prefix defaulting to /usr/local" >&5 $as_echo "$as_me: --prefix defaulting to /usr/local" >&6;} prefix=/usr/local fi fi if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ -o x"${exec_prefix_default}" = x"yes" ; then if test x"${TCL_EXEC_PREFIX}" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&5 $as_echo "$as_me: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&6;} exec_prefix=${TCL_EXEC_PREFIX} else { $as_echo "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to ${prefix}" >&5 $as_echo "$as_me: --exec-prefix defaulting to ${prefix}" >&6;} exec_prefix=$prefix fi fi #----------------------------------------------------------------------- # Standard compiler checks. # This sets up CC by using the CC env var, or looks for gcc otherwise. # This also calls AC_PROG_CC and a few others to create the basic setup # necessary to compile executables. #----------------------------------------------------------------------- # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) # in this macro, they need to go into TEA_SETUP_COMPILER instead. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu #-------------------------------------------------------------------- # Checks to see if the make program sets the $MAKE variable. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi #-------------------------------------------------------------------- # Find ranlib #-------------------------------------------------------------------- if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi #-------------------------------------------------------------------- # Determines the correct binary file extension (.o, .obj, .exe etc.) #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. #------------------------------------------------------------------------ # If we're using GCC, see if the compiler understands -pipe. If so, use it. # It makes compiling go faster. (This is only a performance feature.) #------------------------------------------------------------------------ if test -z "$no_pipe" -a -n "$GCC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler understands -pipe" >&5 $as_echo_n "checking if the compiler understands -pipe... " >&6; } if ${tcl_cv_cc_pipe+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_cc_pipe=yes else tcl_cv_cc_pipe=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe" >&5 $as_echo "$tcl_cv_cc_pipe" >&6; } if test $tcl_cv_cc_pipe = yes; then CFLAGS="$CFLAGS -pipe" fi fi if test "${TCL_MAJOR_VERSION}" -lt 9 -a "${TCL_MINOR_VERSION}" -lt 7; then $as_echo "#define Tcl_Size int" >>confdefs.h fi #-------------------------------------------------------------------- # Common compiler flag setup #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes; then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no else ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 $as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) # ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac #----------------------------------------------------------------------- # Those two are needed for compiling expat. #----------------------------------------------------------------------- for ac_func in memmove bcopy do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done #-------------------------------------------------------------------- # Add optional AOLserver includes #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AOLserver configuration" >&5 $as_echo_n "checking for AOLserver configuration... " >&6; } # Check whether --with-aol was given. if test "${with_aol+set}" = set; then : withval=$with_aol; with_aolserver=${withval} fi if ${ac_cv_c_aolserver+:} false; then : $as_echo_n "(cached) " >&6 else if test x"${with_aolserver}" != x ; then if test -f "${with_aolserver}/include/ns.h" ; then ac_cv_c_aolserver=`(cd ${with_aolserver}; pwd)` else as_fn_error $? "${with_aolserver} directory doesn't contain ns.h" "$LINENO" 5 fi fi fi if test x"${ac_cv_c_aolserver}" = x ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: none found" >&5 $as_echo "none found" >&6; } else AOL_DIR=${ac_cv_c_aolserver} AOL_INCLUDES="-I\"${AOL_DIR}/include\"" if test "`uname -s`" = Darwin ; then aollibs=`ls ${AOL_DIR}/lib/libns* 2>/dev/null` if test x"$aollibs" != x ; then AOL_LIBS="-L\"${AOL_DIR}/lib\" -lnsd -lnsthread" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: found AOLserver in $AOL_DIR" >&5 $as_echo "found AOLserver in $AOL_DIR" >&6; } $as_echo "#define NS_AOLSERVER 1" >>confdefs.h $as_echo "#define USE_NORMAL_ALLOCATOR 1" >>confdefs.h fi #-------------------------------------------------------------------- # Add shared expat includes and expat entropy #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for expat" >&5 $as_echo_n "checking for expat... " >&6; } # Check whether --with-expat was given. if test "${with_expat+set}" = set; then : withval=$with_expat; else with_expat=no fi if ${ac_cv_c_expat+:} false; then : $as_echo_n "(cached) " >&6 else case $with_expat in no) ;; yes) for f in /usr/local /usr; do if test -f "$f/include/expat.h" ; then ac_cv_c_expat=`(cd $f; pwd)` break fi done ;; *) if test -f "$with_expat/include/expat.h"; then ac_cv_c_expat=`(cd $with_expat; pwd)` else as_fn_error $? "${with_expat} directory doesn't contain expat.h" "$LINENO" 5 fi esac fi if test x"${ac_cv_c_expat}" = x ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using bundled expat distribution" >&5 $as_echo "Using bundled expat distribution" >&6; } vars="expat/xmlrole.c \ expat/xmltok.c \ expat/xmlparse.c" for i in $vars; do case $i in \$*) # allow $-var names PKG_SOURCES="$PKG_SOURCES $i" PKG_OBJECTS="$PKG_OBJECTS $i" ;; *) # check for existence - allows for generic/win/unix VPATH # To add more dirs here (like 'src'), you have to update VPATH # in Makefile.in as well if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ -a ! -f "${srcdir}/macosx/$i" \ ; then as_fn_error $? "could not find source file '$i'" "$LINENO" 5 fi PKG_SOURCES="$PKG_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" fi PKG_OBJECTS="$PKG_OBJECTS $j" ;; esac done vars="-I${srcdir}/expat" for i in $vars; do PKG_INCLUDES="$PKG_INCLUDES $i" done $as_echo "#define XML_POOR_ENTROPY 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using shared expat found in ${ac_cv_c_expat}" >&5 $as_echo "Using shared expat found in ${ac_cv_c_expat}" >&6; } vars="-I${ac_cv_c_expat}/include" for i in $vars; do PKG_INCLUDES="$PKG_INCLUDES $i" done vars="-lexpat" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([^-].*\)\.[lL][iI][bB]$/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking which source of entropy to use" >&5 $as_echo "$as_me: checking which source of entropy to use" >&6;} # Check whether --with-entropy was given. if test "${with_entropy+set}" = set; then : withval=$with_entropy; else with_entropy=auto fi case $with_entropy in no) $as_echo "#define XML_POOR_ENTROPY 1" >>confdefs.h ;; auto) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for arc4random_buf (BSD or libbsd)" >&5 $as_echo_n "checking for arc4random_buf (BSD or libbsd)... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* for arc4random_buf on BSD, for NULL */ #if defined(HAVE_LIBBSD) # include #endif int main() { arc4random_buf(NULL, 0U); return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : $as_echo "#define HAVE_ARC4RANDOM_BUF 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for arc4random (BSD, macOS or libbsd)" >&5 $as_echo_n "checking for arc4random (BSD, macOS or libbsd)... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined(HAVE_LIBBSD) # include #else # include #endif int main() { arc4random(); return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : $as_echo "#define HAVE_ARC4RANDOM 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getrandom (Linux 3.17+, glibc 2.25+)" >&5 $as_echo_n "checking for getrandom (Linux 3.17+, glibc 2.25+)... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* for NULL */ #include int main() { return getrandom(NULL, 0U, 0U); } _ACEOF if ac_fn_c_try_link "$LINENO"; then : $as_echo "#define HAVE_GETRANDOM 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for syscall SYS_getrandom (Linux 3.17+)" >&5 $as_echo_n "checking for syscall SYS_getrandom (Linux 3.17+)... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* for NULL */ #include /* for syscall */ #include /* for SYS_getrandom */ int main() { syscall(SYS_getrandom, NULL, 0, 0); return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : $as_echo "#define HAVE_SYSCALL_GETRANDOM 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext $as_echo "#define XML_DEV_URANDOM 1" >>confdefs.h $as_echo "#define XML_POOR_ENTROPY 1" >>confdefs.h ;; HAVE_GETRANDOM) $as_echo "#define HAVE_GETRANDOM 1" >>confdefs.h ;; HAVE_SYSCALL_GETRANDOM) $as_echo "#define HAVE_SYSCALL_GETRANDOM 1" >>confdefs.h ;; HAVE_ARC4RANDOM_BUF) $as_echo "#define HAVE_ARC4RANDOM_BUF 1" >>confdefs.h ;; HAVE_ARC4RANDOM) $as_echo "#define HAVE_ARC4RANDOM 1" >>confdefs.h ;; XML_DEV_URANDOM) $as_echo "#define XML_DEV_URANDOM 1" >>confdefs.h ;; XML_POOR_ENTROPY) $as_echo "#define XML_POOR_ENTROPY 1" >>confdefs.h ;; *) as_fn_error $? "${with_entropy} not known." "$LINENO" 5 esac #-------------------------------------------------------------------- # We need the UINT2PTR and PTR2UINT macros, so make sure that intptr_t # is defined. #-------------------------------------------------------------------- ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default" if test "x$ac_cv_type_uintptr_t" = xyes; then : $as_echo "#define HAVE_UINTPTR_T 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pointer-size unsigned integer type" >&5 $as_echo_n "checking for pointer-size unsigned integer type... " >&6; } if ${tcl_cv_uintptr_t+:} false; then : $as_echo_n "(cached) " >&6 else for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \ none; do if test "$tcl_cv_uintptr_t" != none; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($tcl_cv_uintptr_t))]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_ok=yes else tcl_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$tcl_ok" = yes && break; fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_uintptr_t" >&5 $as_echo "$tcl_cv_uintptr_t" >&6; } if test "$tcl_cv_uintptr_t" != none; then cat >>confdefs.h <<_ACEOF #define uintptr_t $tcl_cv_uintptr_t _ACEOF fi fi #-------------------------------------------------------------------- # Add HTML5 parsing support. #-------------------------------------------------------------------- if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable support for HTML5 parsing (using gumbo)" >&5 $as_echo_n "checking whether to enable support for HTML5 parsing (using gumbo)... " >&6; } # Check whether --enable-html5 was given. if test "${enable_html5+set}" = set; then : enableval=$enable_html5; tcl_ok=$enableval else tcl_ok=no fi if test "${enable_html5+set}" = set; then enableval="$enable_html5" tcl_ok=$enableval else tcl_ok=no fi HTML5_LIBS="" HTML5_INCLUDES="" if test "$tcl_ok" = "yes" ; then # Check if pkg-config is available if test "x$PKG_CONFIG" = x; then tcl_ok=no as_fn_error $? "cannot find pkg-config needed for --enable-html5." "$LINENO" 5 fi fi if test "$tcl_ok" = "yes" ; then HAVEGUMBO=`$PKG_CONFIG --exists gumbo && echo "1"` if test "$HAVEGUMBO" = "1" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define TDOM_HAVE_GUMBO 1" >>confdefs.h if test "${TEA_PLATFORM}" = "windows" ; then HTML5_LIBS="-Wl,-Bstatic `$PKG_CONFIG --static --libs gumbo` -Wl,-Bdynamic" else HTML5_LIBS="`$PKG_CONFIG --libs gumbo`" fi HTML5_INCLUDES="`$PKG_CONFIG --cflags gumbo`" else as_fn_error $? "The required lib gumbo not found" "$LINENO" 5 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi #----------------------------------------------------------------------- # __CHANGE__ # Specify the C source files to compile in TEA_ADD_SOURCES, # public headers that need to be installed in TEA_ADD_HEADERS, # stub library C source files to compile in TEA_ADD_STUB_SOURCES, # and runtime Tcl library files in TEA_ADD_TCL_SOURCES. # This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS # and PKG_TCL_SOURCES. #----------------------------------------------------------------------- vars="generic/xmlsimple.c \ generic/dom.c \ generic/domhtml.c \ generic/domhtml5.c \ generic/domjson.c \ generic/domxpath.c \ generic/domxslt.c \ generic/domlock.c \ generic/tcldom.c \ generic/nodecmd.c \ generic/tdominit.c \ generic/tclexpat.c \ generic/tclpull.c \ generic/schema.c \ generic/datatypes.c \ generic/tdomStubInit.c" for i in $vars; do case $i in \$*) # allow $-var names PKG_SOURCES="$PKG_SOURCES $i" PKG_OBJECTS="$PKG_OBJECTS $i" ;; *) # check for existence - allows for generic/win/unix VPATH # To add more dirs here (like 'src'), you have to update VPATH # in Makefile.in as well if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ -a ! -f "${srcdir}/macosx/$i" \ ; then as_fn_error $? "could not find source file '$i'" "$LINENO" 5 fi PKG_SOURCES="$PKG_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" fi PKG_OBJECTS="$PKG_OBJECTS $j" ;; esac done vars="generic/tdom.h" for i in $vars; do # check for existence, be strict because it is installed if test ! -f "${srcdir}/$i" ; then as_fn_error $? "could not find header file '${srcdir}/$i'" "$LINENO" 5 fi PKG_HEADERS="$PKG_HEADERS $i" done vars="-I${srcdir}/generic ${AOL_INCLUDES} ${HTML5_INCLUDES}" for i in $vars; do PKG_INCLUDES="$PKG_INCLUDES $i" done vars="${AOL_LIBS} ${HTML5_LIBS}" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([^-].*\)\.[lL][iI][bB]$/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done PKG_CFLAGS="$PKG_CFLAGS " vars="generic/tdomStubLib.c" for i in $vars; do # check for existence - allows for generic/win/unix VPATH if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ -a ! -f "${srcdir}/macosx/$i" \ ; then as_fn_error $? "could not find stub source file '$i'" "$LINENO" 5 fi PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" fi PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j" done vars="lib/tdom.tcl" for i in $vars; do # check for existence, be strict because it is installed if test ! -f "${srcdir}/$i" ; then as_fn_error $? "could not find tcl source file '${srcdir}/$i'" "$LINENO" 5 fi PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" done #-------------------------------------------------------------------- # __CHANGE__ # # You can add more files to clean if your extension creates any extra # files by extending CLEANFILES. # Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure # and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var. # # A few miscellaneous platform-specific items: # TEA_ADD_* any platform specific compiler/build info here. #-------------------------------------------------------------------- #CLEANFILES="$CLEANFILES pkgIndex.tcl" if test "${TEA_PLATFORM}" = "windows" ; then # Ensure no empty if clauses : #TEA_ADD_SOURCES([win/winFile.c]) #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"]) CLEANFILES="$CLEANFILES *.ilk vc*.pch" else # Ensure no empty else clauses : #TEA_ADD_SOURCES([unix/unixFile.c]) #TEA_ADD_LIBS([-lsuperfly]) CLEANFILES="$CLEANFILES tdom.tcl tcldomsh" fi #-------------------------------------------------------------------- # __CHANGE__ # Choose which headers you need. Extension authors should try very # hard to only rely on the Tcl public header files. Internal headers # contain private data structures and are subject to change without # notice. # This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl public headers" >&5 $as_echo_n "checking for Tcl public headers... " >&6; } # Check whether --with-tclinclude was given. if test "${with_tclinclude+set}" = set; then : withval=$with_tclinclude; with_tclinclude=${withval} fi if ${ac_cv_c_tclh+:} false; then : $as_echo_n "(cached) " >&6 else # Use the value from --with-tclinclude, if it was given if test x"${with_tclinclude}" != x ; then if test -f "${with_tclinclude}/tcl.h" ; then ac_cv_c_tclh=${with_tclinclude} else as_fn_error $? "${with_tclinclude} directory does not contain tcl.h" "$LINENO" 5 fi else list="" if test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use # the framework's Headers directory case ${TCL_DEFS} in *TCL_FRAMEWORK*) list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`" ;; esac fi # Look in the source dir only if Tcl is not installed, # and in that situation, look there before installed locations. if test -f "${TCL_BIN_DIR}/Makefile" ; then list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`" fi # Check order: pkg --prefix location, Tcl's --prefix location, # relative to directory of tclConfig.sh. eval "temp_includedir=${includedir}" list="$list \ `ls -d ${temp_includedir} 2>/dev/null` \ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then list="$list /usr/local/include /usr/include" if test x"${TCL_INCLUDE_SPEC}" != x ; then d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'` list="$list `ls -d ${d} 2>/dev/null`" fi fi for i in $list ; do if test -f "$i/tcl.h" ; then ac_cv_c_tclh=$i break fi done fi fi # Print a message based on how we determined the include path if test x"${ac_cv_c_tclh}" = x ; then as_fn_error $? "tcl.h not found. Please specify its location with --with-tclinclude" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ac_cv_c_tclh}" >&5 $as_echo "${ac_cv_c_tclh}" >&6; } fi # Convert to a native path and substitute into the output files. INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" #TEA_PRIVATE_TCL_HEADERS #TEA_PUBLIC_TK_HEADERS #TEA_PRIVATE_TK_HEADERS #TEA_PATH_X #-------------------------------------------------------------------- # Check whether --enable-threads or --disable-threads was given. # This auto-enables if Tcl was compiled threaded. #-------------------------------------------------------------------- # Check whether --enable-threads was given. if test "${enable_threads+set}" = set; then : enableval=$enable_threads; tcl_ok=$enableval else tcl_ok=yes fi if test "${enable_threads+set}" = set; then enableval="$enable_threads" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then TCL_THREADS=1 if test "${TEA_PLATFORM}" != "windows" ; then # We are always OK on Windows, so check what this platform wants: # USE_THREAD_ALLOC tells us to try the special thread-based # allocator that significantly reduces lock contention $as_echo "#define USE_THREAD_ALLOC 1" >>confdefs.h $as_echo "#define _REENTRANT 1" >>confdefs.h if test "`uname -s`" = "SunOS" ; then $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h fi $as_echo "#define _THREAD_SAFE 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5 $as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; } if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (); int main () { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_pthread_mutex_init=yes else ac_cv_lib_pthread_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "no"; then # Check a little harder for __pthread_mutex_init in the same # library, as some systems hide it there until pthread.h is # defined. We could alternatively do an AC_TRY_COMPILE with # pthread.h, but that will work with libpthread really doesn't # exist, like AIX 4.2. [Bug: 4359] { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5 $as_echo_n "checking for __pthread_mutex_init in -lpthread... " >&6; } if ${ac_cv_lib_pthread___pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char __pthread_mutex_init (); int main () { return __pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread___pthread_mutex_init=yes else ac_cv_lib_pthread___pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_pthread___pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes; then : tcl_ok=yes else tcl_ok=no fi fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthread" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5 $as_echo_n "checking for pthread_mutex_init in -lpthreads... " >&6; } if ${ac_cv_lib_pthreads_pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthreads $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (); int main () { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthreads_pthread_mutex_init=yes else ac_cv_lib_pthreads_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthreads" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5 $as_echo_n "checking for pthread_mutex_init in -lc... " >&6; } if ${ac_cv_lib_c_pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (); int main () { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_pthread_mutex_init=yes else ac_cv_lib_c_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_c_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5 $as_echo_n "checking for pthread_mutex_init in -lc_r... " >&6; } if ${ac_cv_lib_c_r_pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc_r $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (); int main () { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_r_pthread_mutex_init=yes else ac_cv_lib_c_r_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_c_r_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_c_r_pthread_mutex_init" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -pthread" else TCL_THREADS=0 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&5 $as_echo "$as_me: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&2;} fi fi fi fi fi else TCL_THREADS=0 fi # Do checking message here to not mess up interleaved configure output { $as_echo "$as_me:${as_lineno-$LINENO}: checking for building with threads" >&5 $as_echo_n "checking for building with threads... " >&6; } if test "${TCL_THREADS}" = 1; then $as_echo "#define TCL_THREADS 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (default)" >&5 $as_echo "yes (default)" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # TCL_THREADS sanity checking. See if our request for building with # threads is the same as the way Tcl was built. If not, warn the user. case ${TCL_DEFS} in *THREADS=1*) if test "${TCL_THREADS}" = "0"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Building ${PACKAGE_NAME} without threads enabled, but building against Tcl that IS thread-enabled. It is recommended to use --enable-threads." >&5 $as_echo "$as_me: WARNING: Building ${PACKAGE_NAME} without threads enabled, but building against Tcl that IS thread-enabled. It is recommended to use --enable-threads." >&2;} fi ;; esac #-------------------------------------------------------------------- # The statement below defines a collection of symbols related to # building as a shared library instead of a static library. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5 $as_echo_n "checking how to build libraries... " >&6; } # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; shared_ok=$enableval else shared_ok=yes fi if test "${enable_shared+set}" = set; then enableval="$enable_shared" shared_ok=$enableval else shared_ok=yes fi # Check whether --enable-stubs was given. if test "${enable_stubs+set}" = set; then : enableval=$enable_stubs; stubs_ok=$enableval else stubs_ok=yes fi if test "${enable_stubs+set}" = set; then enableval="$enable_stubs" stubs_ok=$enableval else stubs_ok=yes fi # Stubs are always enabled for shared builds if test "$shared_ok" = "yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: shared" >&5 $as_echo "shared" >&6; } SHARED_BUILD=1 STUBS_BUILD=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5 $as_echo "static" >&6; } SHARED_BUILD=0 $as_echo "#define STATIC_BUILD 1" >>confdefs.h if test "$stubs_ok" = "yes" ; then STUBS_BUILD=1 else STUBS_BUILD=0 fi fi if test "${STUBS_BUILD}" = "1" ; then $as_echo "#define USE_TCL_STUBS 1" >>confdefs.h $as_echo "#define USE_TCLOO_STUBS 1" >>confdefs.h if test "${TEA_WINDOWINGSYSTEM}" != ""; then $as_echo "#define USE_TK_STUBS 1" >>confdefs.h fi fi #-------------------------------------------------------------------- # This macro figures out what flags to use with the compiler/linker # when building shared/static debug/optimized objects. This information # can be taken from the tclConfig.sh file, but this figures it all out. #-------------------------------------------------------------------- if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi # Step 0.a: Enable 64 bit support? { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5 $as_echo_n "checking if 64bit support is requested... " >&6; } # Check whether --enable-64bit was given. if test "${enable_64bit+set}" = set; then : enableval=$enable_64bit; do64bit=$enableval else do64bit=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5 $as_echo "$do64bit" >&6; } # Step 0.b: Enable Solaris 64 bit VIS support? { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit Sparc VIS support is requested" >&5 $as_echo_n "checking if 64bit Sparc VIS support is requested... " >&6; } # Check whether --enable-64bit-vis was given. if test "${enable_64bit_vis+set}" = set; then : enableval=$enable_64bit_vis; do64bitVIS=$enableval else do64bitVIS=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bitVIS" >&5 $as_echo "$do64bitVIS" >&6; } # Force 64bit on with VIS if test "$do64bitVIS" = "yes"; then : do64bit=yes fi # Step 0.c: Check if visibility support is available. Do this here so # that platform specific alternatives can be used below if this fails. { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports visibility \"hidden\"" >&5 $as_echo_n "checking if compiler supports visibility \"hidden\"... " >&6; } if ${tcl_cv_cc_visibility_hidden+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ extern __attribute__((__visibility__("hidden"))) void f(void); void f(void) {} int main () { f(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_cc_visibility_hidden=yes else tcl_cv_cc_visibility_hidden=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_visibility_hidden" >&5 $as_echo "$tcl_cv_cc_visibility_hidden" >&6; } if test $tcl_cv_cc_visibility_hidden = yes; then : $as_echo "#define MODULE_SCOPE extern __attribute__((__visibility__(\"hidden\")))" >>confdefs.h $as_echo "#define HAVE_HIDDEN 1" >>confdefs.h fi # Step 0.d: Disable -rpath support? { $as_echo "$as_me:${as_lineno-$LINENO}: checking if rpath support is requested" >&5 $as_echo_n "checking if rpath support is requested... " >&6; } # Check whether --enable-rpath was given. if test "${enable_rpath+set}" = set; then : enableval=$enable_rpath; doRpath=$enableval else doRpath=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doRpath" >&5 $as_echo "$doRpath" >&6; } # Set the variable "system" to hold the name and version number # for the system. { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5 $as_echo_n "checking system version... " >&6; } if ${tcl_cv_sys_version+:} false; then : $as_echo_n "(cached) " >&6 else # TEA specific: if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 $as_echo "$as_me: WARNING: can't find uname command" >&2;} tcl_cv_sys_version=unknown else if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then tcl_cv_sys_version=NetBSD-Debian fi fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 $as_echo "$tcl_cv_sys_version" >&6; } system=$tcl_cv_sys_version # Require ranlib early so we can override it in special cases below. # Set configuration options based on system name and version. # This is similar to Tcl's unix/tcl.m4 except that we've added a # "windows" case and removed some core-only vars. do64bit_ok=no # default to '{$LIBS}' and set to "" on per-platform necessary basis SHLIB_LD_LIBS='${LIBS}' # When ld needs options to work in 64-bit mode, put them in # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] # is disabled by the user. [Bug 1016796] LDFLAGS_ARCH="" UNSHARED_LIB_SUFFIX="" # TEA specific: use PACKAGE_VERSION instead of VERSION TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' ECHO_VERSION='`echo ${PACKAGE_VERSION}`' TCL_LIB_VERSIONS_OK=ok CFLAGS_DEBUG=-g if test "$GCC" = yes; then : CFLAGS_OPTIMIZE=-O2 CFLAGS_WARNING="-Wall" else CFLAGS_OPTIMIZE=-O CFLAGS_WARNING="" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="${ac_tool_prefix}ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_AR" = x; then AR="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi else AR="$ac_cv_prog_AR" fi STLIB_LD='${AR} cr' LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" if test "x$SHLIB_VERSION" = x; then : SHLIB_VERSION="" else SHLIB_VERSION=".$SHLIB_VERSION" fi case $system in # TEA specific: windows) MACHINE="X86" if test "$do64bit" != "no" ; then case "$do64bit" in amd64|x64|yes) MACHINE="AMD64" ; # default to AMD64 64-bit build ;; arm64|aarch64) MACHINE="ARM64" ;; ia64) MACHINE="IA64" ;; esac fi if test "$GCC" != "yes" ; then if test "${SHARED_BUILD}" = "0" ; then runtime=-MT else runtime=-MD fi case "x`echo \${VisualStudioVersion}`" in x1[4-9]*) lflags="${lflags} -nodefaultlib:libucrt.lib" vars="ucrt.lib" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([^-].*\)\.[lL][iI][bB]$/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done ;; *) ;; esac if test "$do64bit" != "no" ; then CC="cl.exe" RC="rc.exe" lflags="${lflags} -nologo -MACHINE:${MACHINE} " LINKBIN="link.exe" CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d" CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" # Avoid 'unresolved external symbol __security_cookie' # errors, c.f. http://support.microsoft.com/?id=894573 vars="bufferoverflowU.lib" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([^-].*\)\.[lL][iI][bB]$/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done else RC="rc" lflags="${lflags} -nologo" LINKBIN="link" CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" fi fi if test "$GCC" = "yes"; then # mingw gcc mode if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args. set dummy ${ac_tool_prefix}windres; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RC"; then ac_cv_prog_RC="$RC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RC="${ac_tool_prefix}windres" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RC=$ac_cv_prog_RC if test -n "$RC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RC" >&5 $as_echo "$RC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RC"; then ac_ct_RC=$RC # Extract the first word of "windres", so it can be a program name with args. set dummy windres; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RC"; then ac_cv_prog_ac_ct_RC="$ac_ct_RC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RC="windres" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RC=$ac_cv_prog_ac_ct_RC if test -n "$ac_ct_RC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RC" >&5 $as_echo "$ac_ct_RC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RC" = x; then RC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RC=$ac_ct_RC fi else RC="$ac_cv_prog_RC" fi CFLAGS_DEBUG="-g" CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" SHLIB_LD='${CC} -shared' UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cross-compile version of gcc" >&5 $as_echo_n "checking for cross-compile version of gcc... " >&6; } if ${ac_cv_cross+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef _WIN32 #error cross-compiler #endif int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_cross=yes else ac_cv_cross=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cross" >&5 $as_echo "$ac_cv_cross" >&6; } if test "$ac_cv_cross" = "yes"; then case "$do64bit" in amd64|x64|yes) CC="x86_64-w64-mingw32-${CC}" LD="x86_64-w64-mingw32-ld" AR="x86_64-w64-mingw32-ar" RANLIB="x86_64-w64-mingw32-ranlib" RC="x86_64-w64-mingw32-windres" ;; arm64|aarch64) CC="aarch64-w64-mingw32-clang" LD="aarch64-w64-mingw32-ld" AR="aarch64-w64-mingw32-ar" RANLIB="aarch64-w64-mingw32-ranlib" RC="aarch64-w64-mingw32-windres" ;; *) CC="i686-w64-mingw32-${CC}" LD="i686-w64-mingw32-ld" AR="i686-w64-mingw32-ar" RANLIB="i686-w64-mingw32-ranlib" RC="i686-w64-mingw32-windres" ;; esac fi else SHLIB_LD="${LINKBIN} -dll ${lflags}" # link -lib only works when -lib is the first arg STLIB_LD="${LINKBIN} -lib ${lflags}" UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib' PATHTYPE=-w # For information on what debugtype is most useful, see: # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp # and also # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx # This essentially turns it all on. LDFLAGS_DEBUG="-debug -debugtype:cv" LDFLAGS_OPTIMIZE="-release" LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" fi SHLIB_SUFFIX=".dll" SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' TCL_LIB_VERSIONS_OK=nodots ;; AIX-*) if test "$GCC" != "yes"; then : # AIX requires the _r compiler when gcc isn't being used case "${CC}" in *_r|*_r\ *) # ok ... ;; *) # Make sure only first arg gets _r CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'` ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads" >&5 $as_echo "Using $CC for compiling with threads" >&6; } fi LIBS="$LIBS -lc" SHLIB_CFLAGS="" SHLIB_SUFFIX=".so" LD_LIBRARY_PATH_VAR="LIBPATH" # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = yes; then : if test "$GCC" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} else do64bit_ok=yes CFLAGS="$CFLAGS -q64" LDFLAGS_ARCH="-q64" RANLIB="${RANLIB} -X64" AR="${AR} -X64" SHLIB_LD_FLAGS="-b64" fi fi if test "`uname -m`" = ia64; then : # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC SHLIB_LD="/usr/ccs/bin/ld -G -z text" if test "$GCC" = yes; then : CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' else CC_SEARCH_FLAGS='"-R${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' else if test "$GCC" = yes; then : SHLIB_LD='${CC} -shared -Wl,-bexpall' else SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" LDFLAGS="$LDFLAGS -brtl" fi SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" CC_SEARCH_FLAGS='"-L${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} fi ;; BeOS*) SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} -nostart' SHLIB_SUFFIX=".so" #----------------------------------------------------------- # Check for inet_ntoa in -lbind, for BeOS (which also needs # -lsocket, even if the network functions are in -lnet which # is always linked to, for compatibility. #----------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lbind" >&5 $as_echo_n "checking for inet_ntoa in -lbind... " >&6; } if ${ac_cv_lib_bind_inet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbind $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inet_ntoa (); int main () { return inet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bind_inet_ntoa=yes else ac_cv_lib_bind_inet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_inet_ntoa" >&5 $as_echo "$ac_cv_lib_bind_inet_ntoa" >&6; } if test "x$ac_cv_lib_bind_inet_ntoa" = xyes; then : LIBS="$LIBS -lbind -lsocket" fi ;; BSD/OS-2.1*|BSD/OS-3*) SHLIB_CFLAGS="" SHLIB_LD="shlicc -r" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; BSD/OS-4.*) SHLIB_CFLAGS="-export-dynamic -fPIC" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".so" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; CYGWIN_*) SHLIB_CFLAGS="" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".dll" SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$@.a" EXEEXT=".exe" do64bit_ok=yes CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; dgux*) SHLIB_CFLAGS="-K PIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; Haiku*) LDFLAGS="$LDFLAGS -Wl,--export-dynamic" SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnetwork" >&5 $as_echo_n "checking for inet_ntoa in -lnetwork... " >&6; } if ${ac_cv_lib_network_inet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnetwork $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inet_ntoa (); int main () { return inet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_network_inet_ntoa=yes else ac_cv_lib_network_inet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_inet_ntoa" >&5 $as_echo "$ac_cv_lib_network_inet_ntoa" >&6; } if test "x$ac_cv_lib_network_inet_ntoa" = xyes; then : LIBS="$LIBS -lnetwork" fi ;; HP-UX-*.11.*) # Use updated header definitions where possible $as_echo "#define _XOPEN_SOURCE_EXTENDED 1" >>confdefs.h # TEA specific: Needed by Tcl, but not most extensions #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) #LIBS="$LIBS -lxnet" # Use the XOPEN network library if test "`uname -m`" = ia64; then : SHLIB_SUFFIX=".so" else SHLIB_SUFFIX=".sl" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = yes; then : SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."' LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."' LD_LIBRARY_PATH_VAR="SHLIB_PATH" fi if test "$GCC" = yes; then : SHLIB_LD='${CC} -shared' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} else CFLAGS="$CFLAGS -z" fi # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = "yes"; then : if test "$GCC" = yes; then : case `${CC} -dumpmachine` in hppa64*) # 64-bit gcc in use. Fix flags for GNU ld. do64bit_ok=yes SHLIB_LD='${CC} -shared' if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} ;; esac else do64bit_ok=yes CFLAGS="$CFLAGS +DD64" LDFLAGS_ARCH="+DD64" fi fi ;; HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) SHLIB_SUFFIX=".sl" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = yes; then : SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS="" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."' LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."' LD_LIBRARY_PATH_VAR="SHLIB_PATH" fi ;; IRIX-5.*) SHLIB_CFLAGS="" SHLIB_LD="ld -shared -rdata_shared" SHLIB_SUFFIX=".so" case " $LIBOBJS " in *" mkstemp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext" ;; esac if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"' fi ;; IRIX-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"' fi if test "$GCC" = yes; then : CFLAGS="$CFLAGS -mabi=n32" LDFLAGS="$LDFLAGS -mabi=n32" else case $system in IRIX-6.3) # Use to build 6.2 compatible binaries on 6.3. CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" ;; *) CFLAGS="$CFLAGS -n32" ;; esac LDFLAGS="$LDFLAGS -n32" fi ;; IRIX64-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"' fi # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = yes; then : if test "$GCC" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported by gcc" >&2;} else do64bit_ok=yes SHLIB_LD="ld -64 -shared -rdata_shared" CFLAGS="$CFLAGS -64" LDFLAGS_ARCH="-64" fi fi ;; Linux*|GNU*|NetBSD-Debian|DragonFly-*|FreeBSD-*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" # TEA specific: CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS_DEFAULT} -shared' LDFLAGS="$LDFLAGS -Wl,--export-dynamic" case $system in DragonFly-*|FreeBSD-*) if test "${TCL_THREADS}" = "1"; then : # The -pthread needs to go in the LDFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $PTHREAD_LIBS" fi ;; esac if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} if test "`uname -m`" = "alpha"; then : CFLAGS="$CFLAGS -mieee" fi if test $do64bit = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -m64 flag" >&5 $as_echo_n "checking if compiler accepts -m64 flag... " >&6; } if ${tcl_cv_cc_m64+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS CFLAGS="$CFLAGS -m64" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_cc_m64=yes else tcl_cv_cc_m64=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_m64" >&5 $as_echo "$tcl_cv_cc_m64" >&6; } if test $tcl_cv_cc_m64 = yes; then : CFLAGS="$CFLAGS -m64" do64bit_ok=yes fi fi # The combo of gcc + glibc has a bug related to inlining of # functions like strtod(). The -fno-builtin flag should address # this problem but it does not work. The -fno-inline flag is kind # of overkill but it works. Disable inlining only when one of the # files in compat/*.c is being linked in. if test x"${USE_COMPAT}" != x; then : CFLAGS="$CFLAGS -fno-inline" fi ;; Lynx*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE=-02 SHLIB_LD='${CC} -shared' LD_FLAGS="-Wl,--export-dynamic" if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi ;; OpenBSD-*) arch=`arch -s` case "$arch" in alpha|sparc64) SHLIB_CFLAGS="-fPIC" ;; *) SHLIB_CFLAGS="-fpic" ;; esac SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}' LDFLAGS="$LDFLAGS -Wl,-export-dynamic" CFLAGS_OPTIMIZE="-O2" # On OpenBSD: Compile with -pthread # Don't link with -lpthread LIBS=`echo $LIBS | sed s/-lpthread//` CFLAGS="$CFLAGS -pthread" # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; NetBSD-*) # NetBSD has ELF and can use 'cc -shared' to build shared libs SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" LDFLAGS="$LDFLAGS -export-dynamic" if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} # The -pthread needs to go in the CFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" ;; Darwin-*) CFLAGS_OPTIMIZE="-Os" SHLIB_CFLAGS="-fno-common" # To avoid discrepancies between what headers configure sees during # preprocessing tests and compiling tests, move any -isysroot and # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if ($i~/^(isysroot|mmacosx-version-min)/) print "-"$i}'`" CFLAGS="`echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if (!($i~/^(isysroot|mmacosx-version-min)/)) print "-"$i}'`" if test $do64bit = yes; then : case `arch` in ppc) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch ppc64 flag" >&5 $as_echo_n "checking if compiler accepts -arch ppc64 flag... " >&6; } if ${tcl_cv_cc_arch_ppc64+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_cc_arch_ppc64=yes else tcl_cv_cc_arch_ppc64=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_ppc64" >&5 $as_echo "$tcl_cv_cc_arch_ppc64" >&6; } if test $tcl_cv_cc_arch_ppc64 = yes; then : CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" do64bit_ok=yes fi;; i386) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch x86_64 flag" >&5 $as_echo_n "checking if compiler accepts -arch x86_64 flag... " >&6; } if ${tcl_cv_cc_arch_x86_64+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch x86_64" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_cc_arch_x86_64=yes else tcl_cv_cc_arch_x86_64=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_x86_64" >&5 $as_echo "$tcl_cv_cc_arch_x86_64" >&6; } if test $tcl_cv_cc_arch_x86_64 = yes; then : CFLAGS="$CFLAGS -arch x86_64" do64bit_ok=yes fi;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5 $as_echo "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};; esac else # Check for combined 32-bit and 64-bit fat build if echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '; then : fat_32_64=yes fi fi # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -single_module flag" >&5 $as_echo_n "checking if ld accepts -single_module flag... " >&6; } if ${tcl_cv_ld_single_module+:} false; then : $as_echo_n "(cached) " >&6 else hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { int i; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_ld_single_module=yes else tcl_cv_ld_single_module=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_single_module" >&5 $as_echo "$tcl_cv_ld_single_module" >&6; } if test $tcl_cv_ld_single_module = yes; then : SHLIB_LD="${SHLIB_LD} -Wl,-single_module" fi # TEA specific: link shlib with current and compatibility version flags vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([0-9]\{1,5\}\)\(\(\.[0-9]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" SHLIB_SUFFIX=".dylib" LDFLAGS="$LDFLAGS -headerpad_max_install_names" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag" >&5 $as_echo_n "checking if ld accepts -search_paths_first flag... " >&6; } if ${tcl_cv_ld_search_paths_first+:} false; then : $as_echo_n "(cached) " >&6 else hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-search_paths_first" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { int i; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_ld_search_paths_first=yes else tcl_cv_ld_search_paths_first=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_search_paths_first" >&5 $as_echo "$tcl_cv_ld_search_paths_first" >&6; } if test $tcl_cv_ld_search_paths_first = yes; then : LDFLAGS="$LDFLAGS -Wl,-search_paths_first" fi if test "$tcl_cv_cc_visibility_hidden" != yes; then : $as_echo "#define MODULE_SCOPE __private_extern__" >>confdefs.h tcl_cv_cc_visibility_hidden=yes fi CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" # TEA specific: for combined 32 & 64 bit fat builds of Tk # extensions, verify that 64-bit build is possible. if test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"; then : if test "${TEA_WINDOWINGSYSTEM}" = x11; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit X11" >&5 $as_echo_n "checking for 64-bit X11... " >&6; } if ${tcl_cv_lib_x11_64+:} false; then : $as_echo_n "(cached) " >&6 else for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { XrmInitialize(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_lib_x11_64=yes else tcl_cv_lib_x11_64=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_x11_64" >&5 $as_echo "$tcl_cv_lib_x11_64" >&6; } fi if test "${TEA_WINDOWINGSYSTEM}" = aqua; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit Tk" >&5 $as_echo_n "checking for 64-bit Tk... " >&6; } if ${tcl_cv_lib_tk_64+:} false; then : $as_echo_n "(cached) " >&6 else for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}" LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { Tk_InitStubs(NULL, "", 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_lib_tk_64=yes else tcl_cv_lib_tk_64=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_tk_64" >&5 $as_echo "$tcl_cv_lib_tk_64" >&6; } fi # remove 64-bit arch flags from CFLAGS et al. if configuration # does not support 64-bit. if test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no; then : { $as_echo "$as_me:${as_lineno-$LINENO}: Removing 64-bit architectures from compiler & linker flags" >&5 $as_echo "$as_me: Removing 64-bit architectures from compiler & linker flags" >&6;} for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' done fi fi ;; OS/390-*) CFLAGS_OPTIMIZE="" # Optimizer is buggy $as_echo "#define _OE_SOCKETS 1" >>confdefs.h ;; OSF1-V*) # Digital OSF/1 SHLIB_CFLAGS="" if test "$SHARED_BUILD" = 1; then : SHLIB_LD='ld -shared -expect_unresolved "*"' else SHLIB_LD='ld -non_shared -expect_unresolved "*"' fi SHLIB_SUFFIX=".so" if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' fi if test "$GCC" = yes; then : CFLAGS="$CFLAGS -mieee" else CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee" fi # see pthread_intro(3) for pthread support on osf1, k.furukawa CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" LIBS=`echo $LIBS | sed s/-lpthreads//` if test "$GCC" = yes; then : LIBS="$LIBS -lpthread -lmach -lexc" else CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" fi ;; QNX-6*) # QNX RTP # This may work for all QNX, but it was only reported for v6. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SCO_SV-3.2*) if test "$GCC" = yes; then : SHLIB_CFLAGS="-fPIC -melf" LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" else SHLIB_CFLAGS="-Kpic -belf" LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" fi SHLIB_LD="ld -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SunOS-5.[0-6]) # Careful to not let 5.10+ fall into this case # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. $as_echo "#define _REENTRANT 1" >>confdefs.h $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h SHLIB_CFLAGS="-KPIC" SHLIB_SUFFIX=".so" if test "$GCC" = yes; then : SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} else SHLIB_LD="/usr/ccs/bin/ld -G -z text" CC_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} fi ;; SunOS-5*) # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. $as_echo "#define _REENTRANT 1" >>confdefs.h $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h SHLIB_CFLAGS="-KPIC" # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = yes; then : arch=`isainfo` if test "$arch" = "sparcv9 sparc"; then : if test "$GCC" = yes; then : if test "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;} else do64bit_ok=yes CFLAGS="$CFLAGS -m64 -mcpu=v9" LDFLAGS="$LDFLAGS -m64 -mcpu=v9" SHLIB_CFLAGS="-fPIC" fi else do64bit_ok=yes if test "$do64bitVIS" = yes; then : CFLAGS="$CFLAGS -xarch=v9a" LDFLAGS_ARCH="-xarch=v9a" else CFLAGS="$CFLAGS -xarch=v9" LDFLAGS_ARCH="-xarch=v9" fi # Solaris 64 uses this as well #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" fi else if test "$arch" = "amd64 i386"; then : if test "$GCC" = yes; then : case $system in SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) do64bit_ok=yes CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};; esac else do64bit_ok=yes case $system in SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) CFLAGS="$CFLAGS -xarch=amd64" LDFLAGS="$LDFLAGS -xarch=amd64";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported for $arch" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;} fi fi fi SHLIB_SUFFIX=".so" if test "$GCC" = yes; then : SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} if test "$do64bit_ok" = yes; then : if test "$arch" = "sparcv9 sparc"; then : # We need to specify -static-libgcc or we need to # add the path to the sparv9 libgcc. # JH: static-libgcc is necessary for core Tcl, but may # not be necessary for extensions. SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" # for finding sparcv9 libgcc, get the regular libgcc # path, remove so name and append 'sparcv9' #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" else if test "$arch" = "amd64 i386"; then : # JH: static-libgcc is necessary for core Tcl, but may # not be necessary for extensions. SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" fi fi fi else case $system in SunOS-5.[1-9][0-9]*) # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';; *) SHLIB_LD='/usr/ccs/bin/ld -G -z text';; esac CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' fi ;; UNIX_SV* | UnixWare-5*) SHLIB_CFLAGS="-KPIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers # that don't grok the -Bexport option. Test that it does. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld accepts -Bexport flag" >&5 $as_echo_n "checking for ld accepts -Bexport flag... " >&6; } if ${tcl_cv_ld_Bexport+:} false; then : $as_echo_n "(cached) " >&6 else hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-Bexport" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { int i; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_ld_Bexport=yes else tcl_cv_ld_Bexport=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport" >&5 $as_echo "$tcl_cv_ld_Bexport" >&6; } if test $tcl_cv_ld_Bexport = yes; then : LDFLAGS="$LDFLAGS -Wl,-Bexport" fi CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; esac if test "$do64bit" = yes -a "$do64bit_ok" = no; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5 $as_echo "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;} fi # Add in the arch flags late to ensure it wasn't removed. # Not necessary in TEA, but this is aligned with core LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" # If we're running gcc, then change the C flags for compiling shared # libraries to the right flags for gcc, instead of those for the # standard manufacturer compiler. if test "$GCC" = yes; then : case $system in AIX-*) ;; BSD/OS*) ;; CYGWIN_*|MINGW32_*|MINGW64_*|MSYS_*) ;; IRIX*) ;; NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;; Darwin-*) ;; SCO_SV-3.2*) ;; windows) ;; *) SHLIB_CFLAGS="-fPIC" ;; esac fi if test "$tcl_cv_cc_visibility_hidden" != yes; then : $as_echo "#define MODULE_SCOPE extern" >>confdefs.h fi if test "$SHARED_LIB_SUFFIX" = ""; then : # TEA specific: use PACKAGE_VERSION instead of VERSION SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}' fi if test "$UNSHARED_LIB_SUFFIX" = ""; then : # TEA specific: use PACKAGE_VERSION instead of VERSION UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a' fi if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SEH support in compiler" >&5 $as_echo_n "checking for SEH support in compiler... " >&6; } if ${tcl_cv_seh+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : tcl_cv_seh=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main(int argc, char** argv) { int a, b = 0; __try { a = 666 / b; } __except (EXCEPTION_EXECUTE_HANDLER) { return 0; } return 1; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : tcl_cv_seh=yes else tcl_cv_seh=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_seh" >&5 $as_echo "$tcl_cv_seh" >&6; } if test "$tcl_cv_seh" = "no" ; then $as_echo "#define HAVE_NO_SEH 1" >>confdefs.h fi # # Check to see if the excpt.h include file provided contains the # definition for EXCEPTION_DISPOSITION; if not, which is the case # with Cygwin's version as of 2002-04-10, define it to be int, # sufficient for getting the current code to work. # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EXCEPTION_DISPOSITION support in include files" >&5 $as_echo_n "checking for EXCEPTION_DISPOSITION support in include files... " >&6; } if ${tcl_cv_eh_disposition+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # define WIN32_LEAN_AND_MEAN # include # undef WIN32_LEAN_AND_MEAN int main () { EXCEPTION_DISPOSITION x; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_eh_disposition=yes else tcl_cv_eh_disposition=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_eh_disposition" >&5 $as_echo "$tcl_cv_eh_disposition" >&6; } if test "$tcl_cv_eh_disposition" = "no" ; then $as_echo "#define EXCEPTION_DISPOSITION int" >>confdefs.h fi # Check to see if winnt.h defines CHAR, SHORT, and LONG # even if VOID has already been #defined. The win32api # used by mingw and cygwin is known to do this. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for winnt.h that ignores VOID define" >&5 $as_echo_n "checking for winnt.h that ignores VOID define... " >&6; } if ${tcl_cv_winnt_ignore_void+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define VOID void #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main () { CHAR c; SHORT s; LONG l; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_winnt_ignore_void=yes else tcl_cv_winnt_ignore_void=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_winnt_ignore_void" >&5 $as_echo "$tcl_cv_winnt_ignore_void" >&6; } if test "$tcl_cv_winnt_ignore_void" = "yes" ; then $as_echo "#define HAVE_WINNT_IGNORE_VOID 1" >>confdefs.h fi fi # See if the compiler supports casting to a union type. # This is used to stop gcc from printing a compiler # warning when initializing a union member. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5 $as_echo_n "checking for cast to union support... " >&6; } if ${tcl_cv_cast_to_union+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { union foo { int i; double d; }; union foo f = (union foo) (int) 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_cast_to_union=yes else tcl_cv_cast_to_union=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5 $as_echo "$tcl_cv_cast_to_union" >&6; } if test "$tcl_cv_cast_to_union" = "yes"; then $as_echo "#define HAVE_CAST_TO_UNION 1" >>confdefs.h fi ac_fn_c_check_header_mongrel "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default" if test "x$ac_cv_header_stdbool_h" = xyes; then : $as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h fi # These must be called after we do the basic CFLAGS checks and # verify any possible 64-bit or similar switches are necessary { $as_echo "$as_me:${as_lineno-$LINENO}: checking for required early compiler flags" >&5 $as_echo_n "checking for required early compiler flags... " >&6; } tcl_flags="" if ${tcl_cv_flag__isoc99_source+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { char *p = (char *)strtoll; char *q = (char *)strtoull; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_flag__isoc99_source=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _ISOC99_SOURCE 1 #include int main () { char *p = (char *)strtoll; char *q = (char *)strtoull; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_flag__isoc99_source=yes else tcl_cv_flag__isoc99_source=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "x${tcl_cv_flag__isoc99_source}" = "xyes" ; then $as_echo "#define _ISOC99_SOURCE 1" >>confdefs.h tcl_flags="$tcl_flags _ISOC99_SOURCE" fi if test "${TCL_MAJOR_VERSION}" -ne 8 ; then if ${tcl_cv_flag__file_offset_bits+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_flag__file_offset_bits=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include int main () { switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_flag__file_offset_bits=yes else tcl_cv_flag__file_offset_bits=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "x${tcl_cv_flag__file_offset_bits}" = "xyes" ; then $as_echo "#define _FILE_OFFSET_BITS 64" >>confdefs.h tcl_flags="$tcl_flags _FILE_OFFSET_BITS" fi fi if test "x${tcl_flags}" = "x" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}" >&5 $as_echo "${tcl_flags}" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit integer type" >&5 $as_echo_n "checking for 64-bit integer type... " >&6; } if ${tcl_cv_type_64bit+:} false; then : $as_echo_n "(cached) " >&6 else tcl_cv_type_64bit=none # See if the compiler knows natively about __int64 cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { __int64 value = (__int64) 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_type_64bit=__int64 else tcl_type_64bit="long long" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # See if we could use long anyway Note that we substitute in the # type that is our current guess for a 64-bit type inside this check # program, so it should be modified only carefully... cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { switch (0) { case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_type_64bit=${tcl_type_64bit} fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "${tcl_cv_type_64bit}" = none ; then $as_echo "#define TCL_WIDE_INT_IS_LONG 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } elif test "${tcl_cv_type_64bit}" = "__int64" \ -a "${TEA_PLATFORM}" = "windows" ; then # TEA specific: We actually want to use the default tcl.h checks in # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* { $as_echo "$as_me:${as_lineno-$LINENO}: result: using Tcl header defaults" >&5 $as_echo "using Tcl header defaults" >&6; } else cat >>confdefs.h <<_ACEOF #define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit} _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_cv_type_64bit}" >&5 $as_echo "${tcl_cv_type_64bit}" >&6; } # Now check for auxiliary declarations if test "${TCL_MAJOR_VERSION}" -ne 8 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit time_t" >&5 $as_echo_n "checking for 64-bit time_t... " >&6; } if ${tcl_cv_time_t_64+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;} ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_time_t_64=yes else tcl_cv_time_t_64=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_time_t_64" >&5 $as_echo "$tcl_cv_time_t_64" >&6; } if test "x${tcl_cv_time_t_64}" = "xno" ; then # Note that _TIME_BITS=64 requires _FILE_OFFSET_BITS=64 # which SC_TCL_EARLY_FLAGS has defined if necessary. { $as_echo "$as_me:${as_lineno-$LINENO}: checking if _TIME_BITS=64 enables 64-bit time_t" >&5 $as_echo_n "checking if _TIME_BITS=64 enables 64-bit time_t... " >&6; } if ${tcl_cv__time_bits+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _TIME_BITS 64 #include int main () { switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;} ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv__time_bits=yes else tcl_cv__time_bits=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv__time_bits" >&5 $as_echo "$tcl_cv__time_bits" >&6; } if test "x${tcl_cv__time_bits}" = "xyes" ; then $as_echo "#define _TIME_BITS 64" >>confdefs.h fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct dirent64" >&5 $as_echo_n "checking for struct dirent64... " >&6; } if ${tcl_cv_struct_dirent64+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct dirent64 p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_struct_dirent64=yes else tcl_cv_struct_dirent64=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64" >&5 $as_echo "$tcl_cv_struct_dirent64" >&6; } if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then $as_echo "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DIR64" >&5 $as_echo_n "checking for DIR64... " >&6; } if ${tcl_cv_DIR64+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct dirent64 *p; DIR64 d = opendir64("."); p = readdir64(d); rewinddir64(d); closedir64(d); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_DIR64=yes else tcl_cv_DIR64=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_DIR64" >&5 $as_echo "$tcl_cv_DIR64" >&6; } if test "x${tcl_cv_DIR64}" = "xyes" ; then $as_echo "#define HAVE_DIR64 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat64" >&5 $as_echo_n "checking for struct stat64... " >&6; } if ${tcl_cv_struct_stat64+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { struct stat64 p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_struct_stat64=yes else tcl_cv_struct_stat64=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_stat64" >&5 $as_echo "$tcl_cv_struct_stat64" >&6; } if test "x${tcl_cv_struct_stat64}" = "xyes" ; then $as_echo "#define HAVE_STRUCT_STAT64 1" >>confdefs.h fi for ac_func in open64 lseek64 do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for off64_t" >&5 $as_echo_n "checking for off64_t... " >&6; } if ${tcl_cv_type_off64_t+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { off64_t offset; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_type_off64_t=yes else tcl_cv_type_off64_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "x${tcl_cv_type_off64_t}" = "xyes" && \ test "x${ac_cv_func_lseek64}" = "xyes" && \ test "x${ac_cv_func_open64}" = "xyes" ; then $as_echo "#define HAVE_TYPE_OFF64_T 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi TDOM_LD_SEARCH_FLAGS=${LD_SEARCH_FLAGS} #-------------------------------------------------------------------- # Set the default compiler switches based on the --enable-symbols option. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5 $as_echo_n "checking for build with symbols... " >&6; } # Check whether --enable-symbols was given. if test "${enable_symbols+set}" = set; then : enableval=$enable_symbols; tcl_ok=$enableval else tcl_ok=no fi if test "$tcl_ok" = "no"; then CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG" LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define TCL_CFG_OPTIMIZED 1" >>confdefs.h else CFLAGS_DEFAULT="${CFLAGS_DEBUG}" LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" if test "$tcl_ok" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)" >&5 $as_echo "yes (standard debugging)" >&6; } fi fi if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then $as_echo "#define TCL_MEM_DEBUG 1" >>confdefs.h fi if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then if test "$tcl_ok" = "all"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled symbols mem debugging" >&5 $as_echo "enabled symbols mem debugging" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5 $as_echo "enabled $tcl_ok debugging" >&6; } fi fi #-------------------------------------------------------------------- # This macro generates a line to use when building a library. It # depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, # and TEA_LOAD_TCLCONFIG macros above. #-------------------------------------------------------------------- if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then MAKE_STATIC_LIB="\${STLIB_LD} -out:\$@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -out:\$@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined(_MSC_VER) && _MSC_VER >= 1400 print("manifest needed") #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "manifest needed" >/dev/null 2>&1; then : # Could do a CHECK_PROG for mt, but should always be with MSVC8+ VC_MANIFEST_EMBED_DLL="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;2 ; fi" VC_MANIFEST_EMBED_EXE="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;1 ; fi" MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" CLEANFILES="$CLEANFILES *.manifest" fi rm -f conftest* MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\$@ \$(PKG_STUB_OBJECTS)" else MAKE_STATIC_LIB="\${STLIB_LD} \$@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -o \$@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" MAKE_STUB_LIB="\${STLIB_LD} \$@ \$(PKG_STUB_OBJECTS)" fi if test "${SHARED_BUILD}" = "1" ; then MAKE_LIB="${MAKE_SHARED_LIB} " else MAKE_LIB="${MAKE_STATIC_LIB} " fi #-------------------------------------------------------------------- # Shared libraries and static libraries have different names. # Use the double eval to make sure any variables in the suffix is # substituted. (@@@ Might not be necessary anymore) #-------------------------------------------------------------------- PACKAGE_LIB_PREFIX8="${PACKAGE_LIB_PREFIX}" PACKAGE_LIB_PREFIX9="${PACKAGE_LIB_PREFIX}tcl9" if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX9}" else PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX8}" $as_echo "#define TCL_MAJOR_VERSION 8" >>confdefs.h fi if test "${TEA_PLATFORM}" = "windows" ; then if test "${SHARED_BUILD}" = "1" ; then # We force the unresolved linking of symbols that are really in # the private libraries of Tcl and Tk. if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" fi SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" if test "$GCC" = "yes"; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc" fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" else if test "$GCC" = "yes"; then PACKAGE_LIB_PREFIX=lib${PACKAGE_LIB_PREFIX} fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub.a" else eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" fi if test "$GCC" = "yes"; then PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} fi # These aren't needed on Windows (either MSVC or gcc) RANLIB=: RANLIB_STUB=: else RANLIB_STUB="${RANLIB}" if test "${SHARED_BUILD}" = "1" ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}" if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}" fi eval eval "PKG_LIB_FILE8=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=lib${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" RANLIB=: else eval eval "PKG_LIB_FILE8=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=lib${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub.a" else eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" fi fi # These are escaped so that only CFLAGS is picked up at configure time. # The other values will be substituted at make time. CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}" if test "${SHARED_BUILD}" = "1" ; then CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}" fi # Substitute STUB_LIB_FILE in case package creates a stub library too. #-------------------------------------------------------------------- # Determine the name of the tclsh and/or wish executables in the # Tcl and Tk build directories or the location they were installed # into. These paths are used to support running test cases only, # the Makefile should not be making use of these paths to generate # a pkgIndex.tcl file or anything else at extension build time. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5 $as_echo_n "checking for tclsh... " >&6; } if test -f "${TCL_BIN_DIR}/Makefile" ; then # tclConfig.sh is in Tcl build directory if test "${TEA_PLATFORM}" = "windows"; then if test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" fi else TCLSH_PROG="${TCL_BIN_DIR}/tclsh" fi else # tclConfig.sh is in install location if test "${TEA_PLATFORM}" = "windows"; then TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" else TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}" fi list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" for i in $list ; do if test -f "$i/${TCLSH_PROG}" ; then REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" break fi done TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${TCLSH_PROG}" >&5 $as_echo "${TCLSH_PROG}" >&6; } #TEA_PROG_WISH #-------------------------------------------------------------------- # Add some private preprocessor options #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable expat dtd support" >&5 $as_echo_n "checking whether to enable expat dtd support... " >&6; } # Check whether --enable-dtd was given. if test "${enable_dtd+set}" = set; then : enableval=$enable_dtd; tcl_ok=$enableval else tcl_ok=yes fi if test "${enable_dtd+set}" = set; then enableval="$enable_dtd" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define XML_DTD 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # If we expose XML_GetInputContext() at script level #TDOM_CONTEXT_BYTES $as_echo "#define XML_CONTEXT_BYTES 0" >>confdefs.h $as_echo "#define XML_GE 1" >>confdefs.h $as_echo "#define XML_LARGE_SIZE 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable namespace support" >&5 $as_echo_n "checking whether to enable namespace support... " >&6; } # Check whether --enable-ns was given. if test "${enable_ns+set}" = set; then : enableval=$enable_ns; tcl_ok=$enableval else tcl_ok=yes fi if test "${enable_ns+set}" = set; then enableval="$enable_ns" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define XML_NS 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable built-in unknown command" >&5 $as_echo_n "checking whether to enable built-in unknown command... " >&6; } # Check whether --enable-ucmd was given. if test "${enable_ucmd+set}" = set; then : enableval=$enable_ucmd; tcl_ok=$enableval else tcl_ok=no fi if test "${enable_unknown+set}" = set; then enableval="$enable_unknown" tcl_ok=$enableval else tcl_ok=no fi if test "$tcl_ok" = "no" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define TDOM_NO_UNKNOWN_CMD 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable tDOMs block allocator" >&5 $as_echo_n "checking whether to enable tDOMs block allocator... " >&6; } # Check whether --enable-tdomalloc was given. if test "${enable_tdomalloc+set}" = set; then : enableval=$enable_tdomalloc; tcl_ok=$enableval else tcl_ok=no fi if test "${enable_tdomalloc+set}" = set; then enableval="$enable_tdomalloc" tcl_ok=$enableval else tcl_ok=no fi if test "$tcl_ok" = "yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } vars="generic/domalloc.c" for i in $vars; do case $i in \$*) # allow $-var names PKG_SOURCES="$PKG_SOURCES $i" PKG_OBJECTS="$PKG_OBJECTS $i" ;; *) # check for existence - allows for generic/win/unix VPATH # To add more dirs here (like 'src'), you have to update VPATH # in Makefile.in as well if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ -a ! -f "${srcdir}/macosx/$i" \ ; then as_fn_error $? "could not find source file '$i'" "$LINENO" 5 fi PKG_SOURCES="$PKG_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" fi PKG_OBJECTS="$PKG_OBJECTS $j" ;; esac done else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define USE_NORMAL_ALLOCATOR 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable lower limit for XML ns declarations per document" >&5 $as_echo_n "checking whether to enable lower limit for XML ns declarations per document... " >&6; } # Check whether --enable-lessns was given. if test "${enable_lessns+set}" = set; then : enableval=$enable_lessns; tcl_ok=$enableval else tcl_ok=no fi if test "${enable_lessns+set}" = set; then enableval="$enable_lessns" tcl_ok=$enableval else tcl_ok=no fi if test "$tcl_ok" = "yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define TDOM_LESS_NS 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable valiation features" >&5 $as_echo_n "checking whether to enable valiation features... " >&6; } # Check whether --enable-schema was given. if test "${enable_schema+set}" = set; then : enableval=$enable_schema; tcl_ok=$enableval else tcl_ok=yes fi if test "${enable_schema+set}" = set; then enableval="$enable_schema" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "no" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define TDOM_NO_SCHEMA 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi TDOMSHELL=tcldomsh #-------------------------------------------------------------------- # These are for tdomConfig.sh #-------------------------------------------------------------------- # pkglibdir must be a fully qualified path and (not ${exec_prefix}/lib) eval pkglibdir="${libdir}/tdom${PACKAGE_VERSION}" if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then eval tdom_LIB_FLAG="-ltdom${PACKAGE_VERSION}" eval tdom_STUB_LIB_FLAG="-ltdomstub${PACKAGE_VERSION}" else eval tdom_LIB_FLAG="-ltdom`echo ${PACKAGE_VERSION} | tr -d .`" eval tdom_STUB_LIB_FLAG="-ltdomstub`echo ${PACKAGE_VERSION} | tr -d .`" fi if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then eval tdom_STUB_LIB_FLAG="-ltdomstub" fi tdom_BUILD_LIB_SPEC="-L`$CYGPATH $(pwd)` ${tdom_LIB_FLAG}" tdom_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` ${tdom_LIB_FLAG}" tdom_BUILD_STUB_LIB_SPEC="-L`$CYGPATH $(pwd)` ${tdom_STUB_LIB_FLAG}" tdom_STUB_LIB_SPEC="-L`$CYGPATH ${pkglibdir}` ${tdom_STUB_LIB_FLAG}" tdom_BUILD_STUB_LIB_PATH="`$CYGPATH $(pwd)`/${PKG_STUB_LIB_FILE}" tdom_STUB_LIB_PATH="`$CYGPATH ${pkglibdir}`/${PKG_STUB_LIB_FILE}" #-------------------------------------------------------------------- # Finally, substitute all of the various values into the Makefile. # You may alternatively have a special pkgIndex.tcl.in or other files # which require substituting the AC variables in. Include these here. #-------------------------------------------------------------------- ac_config_files="$ac_config_files Makefile pkgIndex.tcl tdomConfig.sh" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS="" : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by tdom $as_me 0.9.5, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ tdom config.status 0.9.5 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "pkgIndex.tcl") CONFIG_FILES="$CONFIG_FILES pkgIndex.tcl" ;; "tdomConfig.sh") CONFIG_FILES="$CONFIG_FILES tdomConfig.sh" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi tdom-0.9.5-src/LICENSE0000644000175000017500000000023214703531020012740 0ustar rolfrolf The tDOM specific source files come with the Mozilla Public License Version 2.0. For Expat XML parser package license look into the directory expat. tdom-0.9.5-src/xe/0000755000175000017500000000000014703531020012352 5ustar rolfrolftdom-0.9.5-src/xe/xe0000755000175000017500000023250314703531020012721 0ustar rolfrolf#!/usr/bin/env wish #---------------------------------------------------------------------------- # Copyright (c) 1999 - 2000 Jochen C. Loewer (loewerj@hotmail.com) #---------------------------------------------------------------------------- # # A XML/DOM/XPath evaluator/viewer... featuring the Tk text widget. # # # The contents of this file are subject to the Mozilla Public License # Version 2.0 (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) 1998, 1999 # Jochen Loewer. All Rights Reserved. # # Contributor(s): # # written by Jochen Loewer # December, 1999 # # # # Contains emacsbinds.tcl: # # Copyright 1993 by Paul Raines (raines@bohr.physics.upenn.edu) # # Permission to use, copy, modify, and distribute this # software and its documentation for any purpose and without # fee is hereby granted, provided that the above copyright # notice appear in all copies. The University of Pennsylvania # makes no representations about the suitability of this # software for any purpose. It is provided "as is" without # express or implied warranty. # #---------------------------------------------------------------------------- # ! All that needs some code cleanup! The code should be more readable! # ! Currently just use xe! #---------------------------------------------------------------------------- # Package/Includes #---------------------------------------------------------------------------- package require http 2 if {[catch { load ../unix/tdom0.6[info shared] }]} { catch { load ../win/tdom0.6.dll } } catch { package require tdom 0.6 } catch { source ../lib/tdom.tcl } #---------------------------------------------------------------------------- # Globals #---------------------------------------------------------------------------- set HttpProxyHost "" set HttpProxyPort "" #---------------------------------------------------------------------------- # $Header$ # # # p a n e implements the new widget 'pane' to realize a # resizing of the space between two sub windows # in fixed size outer window, the pane window. # Uses plain tcl/tk code # # # $Log$ # Revision 1.1 2002/02/22 01:05:35 rolf # Initial revision # # Revision 1.1 96/12/06 15:59:14 15:59:14 jolo (#Jochen Loewer) # Initial revision # # # # written by Jochen Loewer # July, 1996 # #---------------------------------------------------------------------------- #----------------------------------------------------------------------pane-- proc pane { path type width height } { global _pane_Priv set _pane_Priv(moving) no frame $path -height $height -width $width -relief flat frame $path.separator -height 7 -relief flat frame $path.separator.line -height 4 -relief ridge -borderwidth 1 frame $path.separator.handle -width 8 -height 8 -relief raised -borderwidth 1 place $path.separator.line -anchor nw -x 0 -rely 0.4 -relwidth 1.0 place $path.separator.handle -anchor center -relx 1.0 -rely 0.5 -x -8 place $path.separator -anchor nw -x 0 -y 0 -relwidth 1.0 $path.separator.handle config -cursor sb_v_double_arrow set _pane_Priv(maxy) $height set _pane_Priv(moving) no } #----------------------------------------------------------------------pane-- proc pane_place { path type ratio win1 win2 } { global _pane_Priv set _pane_Priv(moving) no update scan [winfo geometry $path] "%dx%d+%d+%d" w h x y set middley [expr $h*$ratio] place $path.separator -anchor nw -x 0 -y $middley -relwidth 1.0 update pane_partionize $path $win1 $win2 $path.separator.handle config -cursor sb_v_double_arrow bind $path.separator.handle "pane_down $path" bind $path.separator.handle "pane_motion $path" bind $path.separator.handle "pane_release $path $win1 $win2" bind $path "pane_resize $path $win1 $win2 %w %h" set _pane_Priv(maxy) $h set _pane_Priv(moving) no } #-----------------------------------------------------------------pane_down-- proc pane_down { pane } { global _pane_Priv $pane.separator.handle configure -relief sunken raise $pane.separator set _pane_Priv(rooty) [winfo pointery $pane] scan [winfo geometry $pane] "%dx%d+%d+%d" w h x y set _pane_Priv(maxy) $h scan [winfo geometry $pane.separator] "%dx%d+%d+%d" w h x y set _pane_Priv(oldy) $y set _pane_Priv(moving) yes } #---------------------------------------------------------------pane_motion-- proc pane_motion { pane } { global _pane_Priv set y [winfo pointery $pane] set delta [expr $y-$_pane_Priv(rooty)] set newy [expr $_pane_Priv(oldy)+$delta] if { ($newy > 8) && ([expr $newy+16] <$_pane_Priv(maxy)) } { place $pane.separator -anchor nw -x 0 -y $newy -relwidth 1.0 } } #--------------------------------------------------------------pane_release-- proc pane_partionize { pane win1 win2 } { scan [winfo geometry $pane.separator] "%dx%d+%d+%d" w h x y place $win1 -anchor nw -x 0 -y 0 -relwidth 1.0 -height $y -relheight {} set ywin2 [expr $y+$h] scan [winfo geometry $pane] "%dx%d+%d+%d" w h x y set hwin2 [expr $h-$ywin2-1] place $win2 -anchor se -relx 1.0 -rely 1.0 -relwidth 1.0 -height $hwin2 } #--------------------------------------------------------------pane_release-- proc pane_release { pane win1 win2 } { global _pane_Priv $pane.separator.handle configure -relief raised pane_partionize $pane $win1 $win2 set _pane_Priv(moving) no } #---------------------------------------------------------------pane_resize-- proc pane_resize { pane win1 win2 neww newh} { global _pane_Priv if { $_pane_Priv(moving) != "yes" } { scan [winfo geometry $pane.separator] "%dx%d+%d+%d" w h xp y set newy [expr ($y*$newh)/$_pane_Priv(maxy)] place $pane.separator -anchor nw -x 0 -y $newy -relwidth 1.0 update pane_partionize $pane $win1 $win2 } set _pane_Priv(maxy) $newh } ############################################################################ # include bindings.tk from TkMail (Thanks Paul!) ############################################################################ # # COPYRIGHT: # Copyright 1993 by Paul Raines (raines@bohr.physics.upenn.edu) # # Permission to use, copy, modify, and distribute this # software and its documentation for any purpose and without # fee is hereby granted, provided that the above copyright # notice appear in all copies. The University of Pennsylvania # makes no representations about the suitability of this # software for any purpose. It is provided "as is" without # express or implied warranty. # global bind_xnd btp # USER SETTINGS set btp(prevcmd) "begin-line" # maximum number of kills to save in ring set btp(maxkill) 10 # maximum number of marks to save in ring set btp(maxmark) 10 # syntax for letter not part of a "word" set btp(not-word) {[^a-zA-Z_0-9]} # procedure to use for errors set btp(error) error # procedure to use for beeping set btp(beep) "" # whether to bind Escape prefix commands also to the Meta modifier set btp(use-meta) 1 # column at which to line wrap set btp(fillcol) 0 # prefix for line wrapping (NOT REALLY WORKING YET) set btp(fillprefix) "" # PRIVATE SETTINGS set btp(lastkill) 0.0 set btp(killring) "" set btp(killptr) 0 set btp(killlen) 0 set btp(arg) def proc tk_entryForwspace w { set x [expr [$w index insert] - 1] catch {$w delete $x} } # selection_if_any - return selection if it exists, else {} # this is from kjx@comp.vuw.ac.nz (R. James Noble) proc selection_if_any {} { if {[catch {selection get} s]} {return ""} {return $s} } proc bind_cleanup { w } { global btp catch {unset btp($w,markring)} } proc bt:current-line { w } { return [lindex [split [$w index insert] .] 0] } proc bt:current-col { w } { return [lindex [split [$w index insert] .] 1] } proc bt:move-line { w {num 1} } { global btp set btp(lastkill) 0.0 if {$btp(arg) != "def"} { set num [expr $num*$btp(arg)] set btp(arg) def } if {$btp(prevcmd) != "move-line"} { set btp(goalcol) [lindex [split [$w index insert] .] 1] } if {$num > -1} {set num "+$num"} $w tag remove sel 1.0 end set ndx [$w index "insert $num line lineend"] set goalndx [lindex [split $ndx .] 0].$btp(goalcol) if {$btp(goalcol) < [lindex [split $ndx .] 1]} { $w mark set insert $goalndx } else { $w mark set insert $ndx } $w yview -pickplace insert set btp(prevcmd) move-line } proc bt:move-char { w {num 1} } { global btp set btp(lastkill) 0.0 if {$btp(arg) != "def"} { set num [expr $num*$btp(arg)] set btp(arg) def } if {$num > -1} {set num "+$num"} $w tag remove sel 1.0 end $w mark set insert "insert $num char" $w yview -pickplace insert set btp(prevcmd) "move-char" } proc bt:move-word {w {num 1}} { global btp set btp(lastkill) 0.0 $w tag remove sel 1.0 end if {$btp(arg) != "def"} { set num [expr $num*$btp(arg)] set btp(arg) def } if {$num > 0} { for {set i 0} {$i < $num } {incr i} { while {[regexp $btp(not-word) [$w get insert]]} { $w mark set insert insert+1c } $w mark set insert {insert wordend} } } else { for {set i 0} {$i > $num } {incr i -1} { $w mark set insert insert-1c while {[regexp $btp(not-word) [$w get insert]]} { $w mark set insert insert-1c } $w mark set insert {insert wordstart} } } $w yview -pickplace insert set btp(prevcmd) "move-word" } proc bt:begin-line { w {num 0}} { global btp set btp(lastkill) 0.0 if {$btp(arg) != "def"} { set num $btp(arg) set btp(arg) def } if {$num != 0} {set num [expr $num-1]} bt:move-line $w $num $w mark set insert {insert linestart} $w tag remove sel 1.0 end $w yview -pickplace insert set btp(prevcmd) "begin-line" } proc bt:end-line { w {num 0}} { global btp set btp(lastkill) 0.0 if {$btp(arg) != "def"} { set num $btp(arg) set btp(arg) def } if {$num != 0} {set num [expr $num-1]} bt:move-line $w $num $w mark set insert {insert lineend} $w tag remove sel 1.0 end $w yview -pickplace insert set btp(prevcmd) end-line } proc bt:begin-buffer { w {num 0}} { global btp set btp(lastkill) 0.0 if {$btp(arg) != "def"} { set num $btp(arg) set btp(arg) def } bt:set-mark $w set ndx [expr 1+[lindex [split [$w index end] .] 0]*$num/10] $w mark set insert $ndx.0 $w tag remove sel 1.0 end $w yview -pickplace insert set btp(prevcmd) begin-buffer } proc bt:end-buffer { w {num 0}} { global btp set btp(lastkill) 0.0 if {$btp(arg) != "def"} { set num $btp(arg) set btp(arg) def } bt:set-mark $w set ndx [expr [lindex [split [$w index end] .] 0]*$num/10] $w mark set insert "end - $ndx lines" $w tag remove sel 1.0 end $w yview -pickplace insert set btp(prevcmd) end-buffer } proc bt:scroll-next { w {num 1}} { global btp set btp(lastkill) 0.0 if {$btp(arg) != "def"} { set num $btp(arg) set btp(arg) def } $w tag remove sel 1.0 end set scr [lindex [lindex [$w configure -yscroll] 4] 0] $w mark set insert [lindex [$scr get] 3].0 $w yview insert-1l set btp(prevcmd) scroll-next } proc bt:scroll-prior { w {num 1}} { global btp set btp(lastkill) 0.0 if {$btp(arg) != "def"} { set num $btp(arg) set btp(arg) def } $w tag remove sel 1.0 end set scr [lindex [lindex [$w configure -yscroll] 4] 0] set tndx [expr [lindex [$scr get] 2]-[lindex [$scr get] 1]+5].0 if {$tndx < 1.0} {set tndx 1.0} $w mark set insert $tndx $w yview insert-1l set btp(prevcmd) scroll-prior } proc bt:delete-word { w {num 1}} { global btp $w tag remove sel 1.0 end if {[$w compare $btp(lastkill) == insert]} { set lastcut [bt:pop-cut] } else { set lastcut "" } set beg [$w index insert] if {$btp(arg) != "def"} { set num $btp(arg) set btp(arg) def } bt:move-word $w $num #puts "$num : $beg [$w index insert]" if {$beg < [$w index insert]} { bt:push-cut "$lastcut[$w get $beg insert]" $w delete $beg insert } else { bt:push-cut "[$w get insert $beg]$lastcut" $w delete insert $beg } set btp(lastkill) [$w index insert] $w yview -pickplace insert set btp(prevcmd) delete-word } proc bt:delete-line { w {num 0}} { global btp $w tag remove sel 1.0 end if {$btp(arg) != "def"} { set num $btp(arg) set btp(arg) def } if {[$w compare $btp(lastkill) == insert]} { set lastcut [bt:pop-cut] } else { set lastcut ""} # while {[$w get insert] == " "} { # $w mark set insert insert+1c # } if {[$w compare insert == "insert lineend"] && $num == 0} { set num 1 } set beg [$w index insert] if {$num != 0} { bt:move-line $w $num bt:begin-line $w if {$beg < [$w index insert]} { bt:push-cut "$lastcut[$w get $beg insert]" $w delete $beg insert } else { bt:push-cut "[$w get insert $beg]$lastcut" $w delete insert $beg } } else { bt:push-cut "$lastcut[$w get insert {insert lineend}]" $w delete insert {insert lineend}; $w yview -pickplace insert } $w yview -pickplace insert set btp(lastkill) [$w index insert] set btp(prevcmd) delete-line } proc bt:delete-back-char-or-sel { w {num 1} } { global btp if {$btp(arg) != "def"} { set num $btp(arg) } else {set btp(lastkill) 0.0} set num [expr -1*$num] if {$num > -1} {set num "+$num"} if {[$w compare $btp(lastkill) == insert]} { set lastcut [bt:pop-cut] } else { set lastcut ""} if [catch {set tmp [$w get sel.first sel.last]}] { if {$btp(arg) != "def"} { if {$num < 0} { bt:push-cut "[$w get "insert $num char" insert]$lastcut" $w delete "insert $num char" insert } else { bt:push-cut "$lastcut[$w get insert "insert $num char"]" $w delete insert "insert $num char" } set btp(lastkill) [$w index insert] } else { if {$num < 0} { $w delete "insert $num char" insert } else { $w delete insert "insert $num char" } set btp(lastkill) 0.0 } } else { $w delete sel.first sel.last bt:push-cut $tmp set btp(lastkill) 0.0 } set btp(arg) def $w yview -pickplace insert set btp(prevcmd) delete-back-char-or-sel } proc bt:delete-region-or-sel { w } { global btp if {[catch {set tmp [$w get sel.first sel.last]}]} { if {[catch "$w index emacs"]} { $btp(error) "No emacs mark has been set yet!" } if {[$w compare $btp(lastkill) == insert]} { set lastcut [bt:pop-cut] } else { set lastcut ""} if {[$w compare emacs < insert]} { bt:push-cut "$lastcut[$w get emacs insert]" $w delete emacs insert } else { bt:push-cut "[$w get insert emacs]$lastcut" $w delete insert emacs } set btp(lastkill) [$w index insert] } else { $w delete sel.first sel.last bt:push-cut $tmp set btp(lastkill) 0.0 } set btp(arg) def set btp(prevcmd) delete-region-or-sel } proc bt:copy-region-or-sel { w } { global btp if {[catch {set tmp [$w get sel.first sel.last]}]} { if {[catch "$w index emacs"]} { $btp(error) "No emacs mark has been set yet!" } if {[$w compare $btp(lastkill) == insert]} { set lastcut [bt:pop-cut] } else { set lastcut ""} if {[$w compare emacs < insert]} { bt:push-cut "$lastcut[$w get emacs insert]" } else { bt:push-cut "[$w get insert emacs]$lastcut" } bt:exchange-point-and-mark $w after 200 bt:exchange-point-and-mark $w } else { bt:push-cut $tmp } set btp(arg) def set btp(lastkill) 0.0 set btp(prevcmd) copy-region-or-sel } proc bt:append-next-kill { w } { global btp set btp(lastkill) [$w index insert] } proc bt:push-cut { txt } { global btp set btp(killlen) [llength [lappend btp(killring) $txt]] if { $btp(killlen) > $btp(maxkill)} { set btp(killring) [lreplace $btp(killring) 0 0] incr btp(killlen) -1 } set btp(killptr) 0 } proc bt:pop-cut { } { global btp if {$btp(killlen) == 0} {return ""} set txt [bt:get-cut 1] set ndx [expr $btp(killlen)-1] set btp(killring) [lreplace $btp(killring) $ndx $ndx ] incr btp(killlen) -1 set btp(killptr) 0 return $txt } proc bt:get-cut { {ndx 1} } { global btp set ndx [expr $ndx+$btp(killptr)] set btp(killptr) [expr $ndx-1] set ndx [expr $ndx%$btp(killlen)] if {$ndx == 0} {set ndx $btp(killlen)} return [lindex $btp(killring) [expr $btp(killlen)-$ndx]] } proc bt:yank { w {num 1}} { global btp $w tag remove sel 1.0 end if {$btp(arg) != "def"} { set num $btp(arg) set btp(arg) def } set btp(lastkill) 0.0 set tmp [$w index insert] $w insert insert [bt:get-cut $num] $w mark set emacs $tmp $w yview -pickplace insert set btp(prevcmd) yank } proc bt:yank-pop { w {num 1}} { global btp if {$btp(arg) != "def"} { set num $btp(arg) set btp(arg) def } if {$btp(prevcmd) != "yank"} return $w tag remove sel 1.0 end $w delete emacs insert set tmp [$w index insert] $w insert insert [bt:get-cut [expr $num+1]] $w mark set emacs $tmp $w yview -pickplace insert } proc bt:pop-mark { w } { global btp set ndx [expr [llength $btp($w,markring)]-1] set oldmark [lindex $btp($w,markring) $ndx] $w mark set emacs $oldmark set btp($w,markring) [concat $oldmark [lreplace $btp($w,markring) $ndx $ndx]] } proc bt:push-mark { w ndx } { global btp lappend btp($w,markring) $ndx $w tag remove emacssel 1.0 end } proc bt:set-mark { w {num def}} { global btp $w tag remove sel 1.0 end if {$btp(arg) != "def"} { set num $btp(arg) set btp(arg) def } if {$num != "def"} { if {[catch "$w index emacs"]} { $btp(error) "No emacs mark has been set yet!" } #puts stdout "$w.yview \n" $w yview -pickplace insert bt:pop-mark $w $w mark set insert emacs } else { bt:push-mark $w [$w index insert] $w mark set emacs insert } set btp(lastkill) 0.0 set btp(prevcmd) set-mark } proc bt:exchange-point-and-mark { w } { global btp if {[catch "$w index emacs"]} { $btp(error) "No emacs mark has been set yet!" } set tmp [$w index insert] $w mark set insert emacs $w mark set emacs $tmp set btp(lastkill) 0.0 set btp(prevcmd) set-mark } proc bt:open-line {w {num 1}} { global btp if {$btp(arg) != "def"} { set num $btp(arg) set btp(arg) def } catch {$w delete sel.first sel.last} for {set i 0} {$i < $num } {incr i} { $w insert insert \n } $w mark set insert insert-1c $w yview -pickplace insert set btp(prevcmd) open-line } proc bt:argkey { w a } { global btp set btp(arg) $a } proc bt:numkey { w a } { global btp if {$btp(arg) == "def"} { catch {%W delete sel.first sel.last} $w insert insert $a if {$btp(fillcol) && [bt:current-col $w] >= $btp(fillcol)} { bt:wrap-word $w } $w yview -pickplace insert set btp(lastkill) 0.0 set btp(prevcmd) self-insert } else { if {$a == "-"} { if {$btp(arg) == "-"} { set btp(arg) "0" } elseif {$btp(arg) == "0"} { set btp(arg) "-" } else { set btp(arg) [expr -1*$btp(arg)] } } else { append btp(arg) $a } } } proc bt:univ-arg { w } { global btp if {$btp(arg) == "def"} { set btp(arg) 4 } else { if {$btp(arg) == "-"} { set btp(arg) "-4" } else { set btp(arg) [expr 4*$btp(arg)] } } } proc bt:wrap-word { w } { global btp bt:move-word $w -1 $w insert insert \n bt:end-line $w } proc bt:set-fill-col { w {num 0}} { global btp if {$btp(arg) == "def"} { if {$num < 1} { set btp(fillcol) [bt:current-col $w] } else { set btp(fillcol) $num } } else { if {$btp(arg) < 1} { set btp(fillcol) [bt:current-col $w] } else { set btp(fillcol) $btp(arg) } } set btp(arg) def set btp(lastkill) 0.0 set btp(prevcmd) set-fill-col } proc bind_motiftext { tw } { global bind_xnd bind $tw { global btp if {"%A" != ""} {eval $btp(beep) } } # Some better bindings for text and entry bind $tw {bt:move-line %W -1} bind $tw {bt:move-line %W 1} bind $tw {bt:move-char %W -1} bind $tw {bt:move-char %W 1} bind $tw {bt:begin-line %W} bind $tw {bt:end-line %W} bind $tw {bt:begin-buffer %W} bind $tw {bt:end-buffer %W} bind $tw {bt:move-word %W -1} bind $tw {bt:move-word %W 1} bind $tw {bt:scroll-next %W} bind $tw {bt:scroll-prior %W} bind $tw { global btp set num 1 if {"%A" != ""} { if {$btp(arg) != "def"} { set num $btp(arg) set btp(arg) def } catch {%W delete sel.first sel.last} for {set i 0} { $i < $num} {incr i} {%W insert insert %A} if {$btp(fillcol) && [bt:current-col %W] >= $btp(fillcol)} { if {"%A" == " "} { %W insert insert \n } elseif {"%A" == "\t"} { %W insert insert \n\t } else { bt:wrap-word %W } } %W yview -pickplace insert set btp(lastkill) 0.0 set btp(prevcmd) self-insert } } bind $tw { global btp catch {%W delete sel.first sel.last} set num 1 if {$btp(arg) != "def"} { set num $btp(arg) set btp(arg) def } for {set i 0} { $i < $num} {incr i} {%W insert insert "\n"} %W yview -pickplace insert set btp(lastkill) 0.0 set btp(prevcmd) newline } bind $tw {bt:delete-back-char-or-sel %W 1} bind $tw {bt:delete-back-char-or-sel %W 1} bind $tw <1> "[bind Text <1>]; \ global btp; set btp(lastkill) 0.0; \ set btp(prevcmd) mouse-set" bind $tw <3> {%W tag remove sel 1.0 end} bind $tw {bind_textB1motion %W @%x,%y} set bind_xnd(b2-time) 0 set bind_xnd(b2-y) 0 bind $tw <2> { global bind_xnd %W scan mark %y set bind_xnd(b2-time) %t set bind_xnd(b2-y) %y } bind $tw { global bind_xnd if {[expr %t-$bind_xnd(b2-time)]<1000} { %W insert insert [selection_if_any] global btp set btp(lastkill) 0.0 set btp(prevcmd) mouse-insert } } # only one mouse, so no need have separate vars for each widget set bind_xnd(txnd) 0 set bind_xnd(xdelay) 100 proc bind_textB1motion { w loc } { global bind_xnd set ypos [lindex [split $loc ","] 1] if {$ypos > [winfo height $w]} { if {!$bind_xnd(txnd)} {after $bind_xnd(xdelay) bind_textExtend $w} set bind_xnd(txnd) 1 set bind_xnd(direction) down } elseif {$ypos < 0} { if {!$bind_xnd(txnd)} {after $bind_xnd(xdelay) bind_textExtend $w} set bind_xnd(txnd) 1 set bind_xnd(direction) up } else { set bind_xnd(txnd) 0 set bind_xnd(direction) 0 } if {!$bind_xnd(txnd)} { tk_textSelectTo $w $loc } } bind $tw { global bind_xnd btp set bind_xnd(txnd) 0 set btp(lastkill) 0.0 set btp(prevcmd) mouse-select } proc bind_textExtend { w } { global bind_xnd if {$bind_xnd(txnd)} { if {$bind_xnd(direction) == "down"} { tk_textSelectTo $w sel.last+1l $w yview -pickplace sel.last+1l } elseif {$bind_xnd(direction) == "up"} { tk_textSelectTo $w sel.first-1l $w yview -pickplace sel.first-1l } else { return } after $bind_xnd(xdelay) bind_textExtend $w } } } proc bind_emacstext { tw } { global btp bind $tw { if [catch {set tmp [%W get emacssel.first emacssel.last]}] { } else { %W tag remove emacssel 1.0 $first %W tag add emacssel $first $last %W tag remove emacssel $last end update idletasks } %W insert insert %A } # make Escape key simulate a state Alt key bind $tw { } bind $tw { global btp if {"%A" != ""} {eval $btp(beep) } } bind $tw {bt:begin-line %W} bind $tw {bt:end-line %W} bind $tw {bt:move-char %W 1} bind $tw {bt:move-char %W -1} bind $tw {bt:move-word %W 1} bind $tw {bt:move-word %W -1} bind $tw {bt:move-line %W 1} bind $tw {bt:move-line %W -1} bind $tw { %W yview -pickplace insert } bind $tw {bt:open-line %W 1} bind $tw {bt:delete-back-char-or-sel %W -1} bind $tw {bt:delete-word %W 1} bind $tw {bt:delete-back-char-or-sel %W -1} bind $tw {bt:delete-line %W 0} bind $tw {bt:delete-region-or-sel %W} bind $tw {bt:copy-region-or-sel %W} bind $tw {bt:yank %W} bind $tw {bt:yank-pop %W} bind $tw {bt:set-mark %W} bind $tw {bt:univ-arg %W} bind $tw {bt:numkey %W %A} bind $tw {bt:numkey %W %A} bind $tw {bt:numkey %W %A} bind $tw {bt:numkey %W %A} bind $tw {bt:numkey %W %A} bind $tw {bt:numkey %W %A} bind $tw {bt:numkey %W %A} bind $tw {bt:numkey %W %A} bind $tw {bt:numkey %W %A} bind $tw {bt:numkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} # make C-x key a state bind $tw { } bind $tw { global btp if {"%A" != ""} {eval $btp(beep) } } bind $tw {bt:exchange-point-and-mark %W} bind $tw {bt:set-fill-col %W} # Make Meta key like and Escape prefix if {$btp(use-meta)} { bind $tw { global btp if {"%A" != ""} {eval $btp(beep) } } bind $tw { global btp if {"%A" != ""} {eval $btp(beep) } } bind $tw {bt:move-word %W 1} bind $tw {bt:move-word %W -1} bind $tw {bt:delete-word %W 1} bind $tw {bt:copy-region-or-sel %W} bind $tw {bt:yank-pop %W} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} bind $tw {bt:argkey %W %A} } } #---------------------------------------------------------------------------- #---------------------------------------------------------------------------- # # The xe main code follows now ... # #---------------------------------------------------------------------------- #---------------------------------------------------------------------------- #--------------------------------------------------------------- # PrintOutputWindow # #--------------------------------------------------------------- proc PrintOutputWindow { printer_pipe } { set f [open "|$printer_pipe" w] puts $f [.pane.output.text get 1.0 end ] close $f } #--------------------------------------------------------------- # PrintPreDefined # #--------------------------------------------------------------- proc PrintPreDefined { } { global landscape doublesided nobanner prsize set printerName [.printdlg.input.predef.f.prname.name get] #puts stderr "printer_name: $printerName" #puts stderr "landscape: $landscape" #puts stderr "doublesided: $doublesided" #puts stderr "prsize: $prsize" array set sizeoption { yes-large { -o vsi7 -o fp16 -o landscape } yes-normal { -o vsi6 -o fp18 -o landscape -o height80 } yes-small { -o vsi5 -o fp20 -o landscape -o height90 } yes-smallest { -o vsi4 -o fp24 -o landscape -o height100 } yes-micro { -o vsi3 -o fp28 -o landscape -o height110 } no-large { -o vsi7 -o fp16 -o portrait } no-normal { -o vsi6 -o fp18 -o portrait } no-small { -o vsi5 -o fp20 -o portrait } no-smallest { -o vsi4 -o fp24 -o portrait } } set command $sizeoption(${landscape}-${prsize}) if {$doublesided == "yes"} { append command " -o duplex" } else { append command " -o simplex" } if {$nobanner == "yes"} { append command " -o nb" } append command " -d $printerName" PrintOutputWindow "lp $command" } #--------------------------------------------------------------- # PrintDialog # #--------------------------------------------------------------- proc PrintDialog { } { global dbname dbsname set w .printdlg catch {destroy $w} toplevel $w -class Dialog wm title $w "Print Output" wm iconname $w "Print Output" wm protocol $w WM_DELETE_WINDOW { } frame $w.input \ -relief flat -borderwidth 0 -highlightthickness 0 frame $w.buttons \ -relief flat -borderwidth 0 -highlightthickness 0 button $w.buttons.print \ -text " Print " \ -command "PrintPreDefined; destroy $w" button $w.buttons.cancel \ -text " Cancel " -command "destroy $w" pack $w.buttons.print $w.buttons.cancel -side top -pady 10 -fill x #----------------------------------------------- # pre-customized printer configuration #----------------------------------------------- frame $w.input.predef \ -relief flat -borderwidth 0 -highlightthickness 0 label $w.input.predef.h \ -text "Pre-customized Printer Configuration:" frame $w.input.predef.f \ -relief groove -borderwidth 2 -highlightthickness 0 pack $w.input.predef.h -anchor w -side top pack $w.input.predef.f -side top -ipadx 5 -ipady 5 -fill x frame $w.input.predef.f.prname \ -relief groove -borderwidth 0 -highlightthickness 0 label $w.input.predef.f.prname.l \ -text "Printer Name:" entry $w.input.predef.f.prname.name \ -relief sunken -borderwidth 1 -highlightthickness 1 \ -width 20 -background gray90 -exportselection yes pack $w.input.predef.f.prname.l -side left pack $w.input.predef.f.prname.name -side left -anchor w -fill x frame $w.input.predef.f.kind \ -relief groove -borderwidth 0 -highlightthickness 0 radiobutton $w.input.predef.f.kind.large \ -text "Large (100 char width) " -variable prsize -relief flat -value large radiobutton $w.input.predef.f.kind.normal \ -text "Normal (150 char width)" -variable prsize -relief flat -value normal radiobutton $w.input.predef.f.kind.small \ -text "Small (200 char width)" -variable prsize -relief flat -value small radiobutton $w.input.predef.f.kind.smallest \ -text "Smallest (240 char width)" -variable prsize -relief flat -value smallest radiobutton $w.input.predef.f.kind.micro \ -text "Micro (>240 char width)" -variable prsize -relief flat -value micro $w.input.predef.f.kind.small select pack $w.input.predef.f.kind.large \ $w.input.predef.f.kind.normal \ $w.input.predef.f.kind.small \ $w.input.predef.f.kind.smallest \ $w.input.predef.f.kind.micro -anchor w -side top frame $w.input.predef.f.optionskind \ -relief groove -borderwidth 0 -highlightthickness 0 checkbutton $w.input.predef.f.optionskind.landscape -text "landscape (-o landscape)" \ -variable landscape -onvalue "yes" -offvalue "no" -relief flat $w.input.predef.f.optionskind.landscape select checkbutton $w.input.predef.f.optionskind.double -text "double sided (-o duplex)" \ -variable doublesided -onvalue "yes" -offvalue "no" -relief flat checkbutton $w.input.predef.f.optionskind.nobanner -text "no banner (-o nb)" \ -variable nobanner -onvalue "yes" -offvalue "no" -relief flat pack $w.input.predef.f.optionskind.landscape \ $w.input.predef.f.optionskind.double \ $w.input.predef.f.optionskind.nobanner -anchor w -side top pack $w.input.predef.f.prname \ $w.input.predef.f.kind \ $w.input.predef.f.optionskind -side top -padx 1 -pady 5 -fill x #----------------------------------------------- # self printer configuration #----------------------------------------------- frame $w.input.self \ -relief flat -borderwidth 0 -highlightthickness 0 label $w.input.self.h \ -text "Full Command Line:" frame $w.input.self.f2 \ -relief groove -borderwidth 2 -highlightthickness 0 entry $w.input.self.f2.cmdline \ -relief sunken -borderwidth 2 -highlightthickness 1 \ -width 40 -background gray90 -exportselection yes button $w.input.self.f2.print \ -text " Print " -command { set printer_pipe [.printdlg.input.self.f2.cmdline get]; PrintOutputWindow "$printer_pipe" } pack $w.input.self.f2.cmdline $w.input.self.f2.print \ -side left -padx 5 pack $w.input.self.h -anchor w -side top pack $w.input.self.f2 -side top -ipadx 5 -ipady 5 #------------------------------------------------------------- pack $w.input.predef $w.input.self -side top -pady 10 -fill x pack $w.input -side left -padx 10 -pady 10 -fill x pack $w.buttons -side left -padx 10 -pady 30 -fill y } #---------------------------------------------------------------------------- # SaveTextWindow # #---------------------------------------------------------------------------- proc SaveTextWindow { textw filename } { set f [open $filename w ]; $textw mark set insert end #--remove the empty part at the bottom while {1} { set line [$textw get {insert linestart} {insert lineend}] if {$line != ""} { break; } $textw mark set insert {insert -1 line} if {[$textw compare insert < 3.0]} { break; } } puts $f [$textw get 1.0 {insert lineend} ] close $f } #---------------------------------------------------------------------------- # Base64Init # #---------------------------------------------------------------------------- proc Base64Init { } { global base64_b2c base64_c2b set i -1 foreach a { A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + / } { binary scan [binary format c1 [incr i]] B* v set base64_b2c([string range $v 2 end]) $a set base64_c2b($a) [string range $v 2 end] } } #---------------------------------------------------------------------------- # Base64EncodeBufferData # #---------------------------------------------------------------------------- proc Base64EncodeBufferData { data } { global base64_b2c # Get the bit stream binary scan $data B* bits # Convert groups of six bits to a list for easy traversal regsub -all {((0|1)(0|1)(0|1)(0|1)(0|1)(0|1))} $bits {\1 } bits foreach b $bits { append result $base64_b2c($b) } return $result } #---------------------------------------------------------------------------- # Base64Encode # #---------------------------------------------------------------------------- proc Base64Encode { data {buffersize 6144} } { global base64_b2c if { ![array exists base64_b2c] } { Base64Init } # Convert the data to a bitstream and then encode. # This approach requires a buffer eight times the size of the # data to be encoded, so just work on a buffer at a time. # The default buffer size is 6 * 1024 bytes (6KB). # This is a trade-off between speed and space. if {$buffersize % 3} { # Buffer must be a multiple of 3 bytes set buffersize [expr $buffersize - $buffersize % 3] } set linelen 0 while {[string length $data] > $buffersize} { # Get the buffer to work on set buffer [string range $data 0 [expr $buffersize - 1]] set data [string range $data $buffersize end] append result [Base64EncodeBufferData $buffer] } if {[string length $data]} { # Deal with remaining data # Encode to an even multiple of 3 bytes, and then # pad the rest set buffer [string range $data 0 [expr [string length $data] - [string length $data] % 3 - 1]] set remainder [string range $data [expr [string length $data] - [string length $data] % 3] end] append result [Base64EncodeBufferData $buffer] switch [string length $remainder] { 1 { binary scan $remainder B* bits append result $base64_b2c([string range $bits 0 5]) append result $base64_b2c([string range $bits 6 7]0000) append result == } 2 { binary scan $remainder B* bits append result $base64_b2c([string range $bits 0 5]) append result $base64_b2c([string range $bits 6 11]) append result $base64_b2c([string range $bits 12 15]00) append result = } } } # Ensure lines are no more than 76 characters regsub -all {(........................................................................)} \ $result "\\1\n" result return $result } #---------------------------------------------------------------------------- # IntroWindow # #---------------------------------------------------------------------------- proc IntroWindow { } { global HelvB12 Helv12 frame .splash -borderwidth 4 -relief raised label .splash.info1 -font $HelvB12 -text "XE - a simple XML/XPath Browser/Viewer" label .splash.info2 -font $Helv12 -text "Version 0.2" label .splash.info3 -font $Helv12 -text "Copyright (c) 1999,2001 Jochen Loewer (loewerj@hotmail.com)" pack .splash.info1 \ .splash.info2 \ .splash.info3 -padx 4 -pady 4 -anchor w place .splash -anchor c -relx .5 -rely .5 after 2500 destroy .splash update } #---------------------------------------------------------------------------- # ConfigureProxy # #---------------------------------------------------------------------------- proc ConfigureProxy { } { global HttpProxyHost HttpProxyPort gotProxy set gotProxy -1 set w .proxyDdlg catch {destroy $w} toplevel $w -class Dialog wm title $w "Configure HTTP Proxy" wm iconname $w "HTTP Proxy" wm protocol $w WM_DELETE_WINDOW { } frame $w.hdr \ -relief flat -borderwidth 0 -highlightthickness 0 label $w.hdr.icon -bitmap questhead label $w.hdr.msg -text "Specify HTTP proxy server: " frame $w.fields \ -relief flat -borderwidth 0 -highlightthickness 0 label $w.fields.hostlabel -text "Proxy Host:" entry $w.fields.hostvalue \ -relief sunken -borderwidth 1 -highlightthickness 1 \ -width 20 -background gray90 -exportselection yes label $w.fields.portlabel -text "Porxy Port:" entry $w.fields.portvalue \ -relief sunken -borderwidth 1 -highlightthickness 1 \ -width 20 -background gray90 -exportselection yes frame $w.buttons \ -relief flat -borderwidth 0 -highlightthickness 0 button $w.buttons.ok -text " OK " \ -command "set gotProxy \[list 1 \[$w.fields.hostvalue get\] \ \[$w.fields.portvalue get\] \]; \ destroy $w" bind $w.fields.portvalue " \ set gotProxy \[list 1 \[$w.fields.hostvalue get\] \ \[$w.fields.portvalue get\] \]; \ destroy $w" button $w.buttons.cancel -text " Cancel " \ -command "destroy $w; set gotProxy {0 {} {}}" $w.fields.hostvalue insert 0 $HttpProxyHost $w.fields.portvalue insert 0 $HttpProxyPort pack $w.hdr.icon $w.hdr.msg -side left grid $w.fields.hostlabel -in $w.fields -column 0 -row 0 -sticky e grid $w.fields.portlabel -in $w.fields -column 0 -row 1 -sticky e grid $w.fields.hostvalue -in $w.fields -column 1 -row 0 -sticky w grid $w.fields.portvalue -in $w.fields -column 1 -row 1 -sticky w pack $w.buttons.ok $w.buttons.cancel -side left pack $w.hdr \ $w.fields \ $w.buttons -side top -anchor w -padx 9 -pady 9 focus $w.fields.hostvalue while {$gotProxy == -1} { vwait gotProxy } if {[lindex $gotProxy 0]} { set HttpProxyHost [lindex $gotProxy 1] set HttpProxyPort [lindex $gotProxy 2] } } #---------------------------------------------------------------------------- # GetUserPassword # #---------------------------------------------------------------------------- proc GetUserPassword { state_var login_var password_var } { global gotPassword Login upvar $state_var state upvar $login_var login upvar $password_var password #parray state set server "" set realm "" regexp {http://([^/]*)/(.*)} $state(url) all server file array set meta $state(meta) if {[info exists meta(WWW-authenticate)]} { set realmStr [lindex $meta(WWW-authenticate) 1] regexp {realm="([^"]*)"} $realmStr all realm } #puts stderr "login='$login' password='$password' server='$server' realm='$realm'" if {[info exists Login($server,$realm)]} { foreach { new_login new_password } $Login($server,$realm) break if {($new_login != $login ) || ($new_password != $password)} { set login $new_login set password $new_password return 1 } } set gotPassword -1 set login "" set password "" set w .passwordDdlg catch {destroy $w} toplevel $w -class Dialog wm title $w "HTTP Password" wm iconname $w "HTTP Password" wm protocol $w WM_DELETE_WINDOW { } frame $w.hdr \ -relief flat -borderwidth 0 -highlightthickness 0 label $w.hdr.icon -bitmap questhead label $w.hdr.msg -text "Enter username for $realm at $server " frame $w.fields \ -relief flat -borderwidth 0 -highlightthickness 0 label $w.fields.userlabel -text "User name:" entry $w.fields.uservalue \ -relief sunken -borderwidth 1 -highlightthickness 1 \ -width 20 -background gray90 -exportselection yes label $w.fields.passlabel -text "Password:" entry $w.fields.passvalue \ -relief sunken -borderwidth 1 -highlightthickness 1 \ -width 20 -background gray90 -exportselection yes -show * frame $w.buttons \ -relief flat -borderwidth 0 -highlightthickness 0 button $w.buttons.ok -text " OK " \ -command "set gotPassword \[list 1 \[$w.fields.uservalue get\] \ \[$w.fields.passvalue get\] \]; \ destroy $w" bind $w.fields.passvalue " \ set gotPassword \[list 1 \[$w.fields.uservalue get\] \ \[$w.fields.passvalue get\] \]; \ destroy $w" button $w.buttons.cancel -text " Cancel " \ -command "destroy $w; set gotPassword {0 {} {}}" pack $w.hdr.icon $w.hdr.msg -side left grid $w.fields.userlabel -in $w.fields -column 0 -row 0 -sticky e grid $w.fields.passlabel -in $w.fields -column 0 -row 1 -sticky e grid $w.fields.uservalue -in $w.fields -column 1 -row 0 -sticky w grid $w.fields.passvalue -in $w.fields -column 1 -row 1 -sticky w pack $w.buttons.ok $w.buttons.cancel -side left pack $w.hdr \ $w.fields \ $w.buttons -side top -anchor w -padx 9 -pady 9 focus $w.fields.uservalue while {$gotPassword == -1} { vwait gotPassword } if {[lindex $gotPassword 0]} { set login [lindex $gotPassword 1] set password [lindex $gotPassword 2] set Login($server,$realm) [list $login $password] return 1 } return 0 } #---------------------------------------------------------------------------- # xmlEdit # #---------------------------------------------------------------------------- proc xmlEdit { {line 0} {column 0} } { global xml Cour12 Helv12 if {[winfo exists .edit]} { .edit.f.text mark set insert $line.$column .edit.f.text see insert focus .edit.f.text return } toplevel .edit wm title .edit "XML Source" set path .edit.f frame $path -relief flat -borderwidth 3 -highlightthickness 0 text $path.text -width 100 -height 30 -font $Cour12 \ -bg gray90 \ -exportselection yes -wrap none \ -yscrollcommand "$path.vsb set" \ -xscrollcommand "$path.hsb set" scrollbar $path.vsb -relief sunken -orient vertical \ -command "$path.text yview" scrollbar $path.hsb -relief sunken -orient horizontal \ -command "$path.text xview" button .edit.reload -text " Reload " -command xmlReload \ -font $Helv12 pack $path.vsb -side right -fill y -expand no pack $path.hsb -side bottom -fill x -expand no pack $path.text -side top -fill both -expand yes pack $path -expand yes -fill both pack .edit.reload -anchor e $path.text delete 1.0 end $path.text insert end $xml .edit.f.text mark set insert $line.$column .edit.f.text see insert focus .edit.f.text } #---------------------------------------------------------------------------- # xmlHighlight # #---------------------------------------------------------------------------- proc xmlHighlight { path pos tag highlight_tag} { set range [$path tag nextrange $tag $pos [$path index "$pos lineend"] ] if {$range == ""} { set range [$path tag prevrange $tag $pos [$path index "$pos linestart"] ] } if {$range != ""} { eval $path tag add $highlight_tag [lrange $range 0 1] } } #---------------------------------------------------------------------------- # xmlHighlightMotion # #---------------------------------------------------------------------------- proc xmlHighlightMotion { path pos tag highlight_tag} { set tags [$path tag names $pos] if {[lsearch -exact $tags $highlight_tag] < 0} { $path tag remove $highlight_tag 1.0 end } xmlHighlight $path $pos $tag $highlight_tag } #---------------------------------------------------------------------------- # xmlJump # #---------------------------------------------------------------------------- proc xmlJump { path pos } { foreach tag [$path tag names $pos] { if { ($tag != "tag") } { xmlEdit [$tag getLine] [$tag getColumn] } } } #---------------------------------------------------------------------------- # xmlOpen # #---------------------------------------------------------------------------- proc xmlOpen { path pos } { global levels foreach tag [$path tag names $pos] { if {($tag != "open") && ($tag != "hot") && ($tag != "sel")} { $path configure -state normal set start [$path index "$pos linestart"] set end [$path index "$start + 1 lines"] $path delete $start $end while 1 { set end [$path index "$start + 1 lines"] set nextLine [$path get $start $end] if {[string match "$levels($tag) *" $nextLine]} { $path delete $start $end } else { break } } $path mark set insert $start xmlWidgetLoad_Recurs $path 0 $levels($tag) $tag 2 $path see $start } } # that's a hack to remove selections, which occur sometimes after 50 "$path tag remove sel 1.0 end" } #---------------------------------------------------------------------------- # xmlClose # #---------------------------------------------------------------------------- proc xmlClose { path pos } { global levels foreach tag [$path tag names $pos] { if {($tag != "close") && ($tag != "hot") && ($tag != "sel")} { $path configure -state normal set start [$path index "$pos linestart"] set end [$path index "$start + 1 lines"] $path delete $start $end while 1 { set end [$path index "$start + 1 lines"] set nextLine [$path get $start $end] if {[string match "$levels($tag) *" $nextLine]} { $path delete $start $end } else { break } } $path mark set insert $start xmlWidgetLoad_Recurs $path 0 $levels($tag) $tag 1 $path see $start } } # that's a hack to remove selections, which occur sometimes after 50 "$path tag remove sel 1.0 end" } #---------------------------------------------------------------------------- # xmlWidget # #---------------------------------------------------------------------------- proc xmlWidget { path } { global Cour12 HelvB12 set tagFont $HelvB12 set attrFont $Cour12 set opnclFont $Cour12 frame $path -relief flat -borderwidth 0 -highlightthickness 0 text $path.text -width 100 -height 25 -font $Cour12 \ -bg gray85 -cursor left_ptr \ -exportselection yes -wrap none \ -yscrollcommand "$path.vsb set" \ -xscrollcommand "$path.hsb set" scrollbar $path.vsb -relief sunken -orient vertical \ -command "$path.text yview" scrollbar $path.hsb -relief sunken -orient horizontal \ -command "$path.text xview" pack $path.vsb -side right -fill y -expand no pack $path.hsb -side bottom -fill x -expand no pack $path.text -side top -fill both -expand yes #$path.text tag configure tag -font $tagFont \ # -background #ffffa666a666 \ # -foreground black $path.text tag configure tag -font $tagFont \ -foreground #40004000D000 $path.text tag configure comment -font $attrFont \ -background #d000e800d000 \ -foreground black $path.text tag configure textValue -font $attrFont \ -background #d200d200f000 \ -foreground black #$path.text tag configure attr -font $attrFont \ # -background #fae0d53fdaaa \ # -foreground black # -background #D000D000ffff \ $path.text tag configure attrName -font $attrFont \ -foreground black # -background #D000D000ffff \ # -background #e800d000d000 \ # -background gray90 \ # -foreground #d00000000000 $path.text tag configure attrValue -font $attrFont \ -background #f000d000d000 \ -foreground black $path.text tag configure header -background gray90 \ -foreground red2 $path.text tag configure query -background gray95 \ -foreground red2 $path.text tag configure hot -background #a666a666ffff $path.text tag configure open -font $opnclFont $path.text tag configure close -font $opnclFont $path.text tag configure leave -font $opnclFont $path.text tag bind tag <2> "xmlJump $path.text @%x,%y" $path.text tag bind open "xmlHighlight $path.text @%x,%y open hot" $path.text tag bind open "xmlHighlightMotion $path.text @%x,%y open hot" $path.text tag bind open "$path.text tag remove hot 1.0 end" $path.text tag bind open <1> "xmlOpen $path.text @%x,%y" $path.text tag bind close "xmlHighlight $path.text @%x,%y open hot" $path.text tag bind close "xmlHighlightMotion $path.text @%x,%y close hot" $path.text tag bind close "$path.text tag remove hot 1.0 end" $path.text tag bind close <1> "xmlClose $path.text @%x,%y" } #---------------------------------------------------------------------------- # xmlWidgetLoad_Recurs # #---------------------------------------------------------------------------- proc xmlWidgetLoad_Recurs { path doSiblings level node maxlevel } { global levels incr maxlevel -1 if {$maxlevel < 0} { return } while {$node != ""} { set levels($node) $level $path insert insert $level set type [$node nodeType] if { $type == "ELEMENT_NODE" } { set firstChild [$node firstChild] if {$firstChild == ""} { $path insert insert " = " leave } else { if {$maxlevel > 0} { $path insert insert " - " [list close $node] } else { $path insert insert " + " [list open $node] } } $path insert insert "[$node nodeName] " [list tag $node] set attr_line_width 0 set attr_name_width 0 set attr_value_width [string length $level] foreach attr [$node attributes] { if {[llength $attr] > 1} { if {[lindex $attr 1] == ""} { set attr [lindex $attr 0] } else { set attr "[lindex $attr 1]:[lindex $attr 0]" } } set l [string length $attr] if {$l > $attr_name_width} { set attr_name_width $l } incr attr_line_width $l set l [string length [$node getAttribute $attr]] if {$l > $attr_value_width} { set attr_value_width $l } incr attr_line_width $l } set recurseToChilds 1 set attrDisplayMode [expr $attr_line_width > 80] if {$attrDisplayMode} { foreach attr [$node attributes] { $path insert insert "\n" $path insert insert "$level " #$path insert insert [format " %-${attr_name_width}s = %-${attr_value_width}s " \ # $attr [$node getAttribute $attr] \ # ] attr if {[llength $attr] > 1} { if {[lindex $attr 1] == ""} { set attr [lindex $attr 0] } else { set attr "[lindex $attr 1]:[lindex $attr 0]" } } $path insert insert [format " %-${attr_name_width}s= " \ $attr \ ] attrName $path insert insert [$node getAttribute $attr] attrValue #$path insert insert [format "%-${attr_value_width}s " \ # '[$node getAttribute $attr]' \ # ] attrValue } $path insert insert "\n" } else { if {[$node attributes] == ""} { set childs [$node childNodes] if {[llength $childs] == 1} { if {[$childs nodeType] == "TEXT_NODE"} { set value [$childs nodeValue] if {([string length $value] < 60) && ([string first \n $value] == -1)} { $path insert insert $value textValue set recurseToChilds 0 } } } } else { foreach attr [$node attributes] { if {[llength $attr] > 1} { if {[lindex $attr 1] == ""} { set attr [lindex $attr 0] } else { set attr "[lindex $attr 1]:[lindex $attr 0]" } } $path insert insert " $attr=" attrName $path insert insert [$node getAttribute $attr] attrValue #$path insert insert ' attrName } } $path insert insert "\n" } set recurseToChilds 1 if {$recurseToChilds} { foreach child [$node childNodes] { xmlWidgetLoad_Recurs $path 1 "$level " $child $maxlevel } } } else { switch $type { COMMENT_NODE { $path insert insert " C " $path insert insert [$node nodeValue] comment $path insert insert "\n" } CDATA_SECTION_NODE - TEXT_NODE { set lines 0 foreach line [split [$node nodeValue] \n] { if {$lines == 0} { $path insert insert " T " } else { $path insert insert "$level " } if {$line == ""} { $path insert insert " " textValue } else { $path insert insert $line textValue } $path insert insert "\n" incr lines } } PROCESSING_INSTRUCTION_NODE { $path insert insert " P " $path insert insert [$node target] tag set lines 0 foreach line [split [$node data] \n] { if {$lines == 0} { $path insert insert " " } else { $path insert insert "$level " } $path insert insert $line attrValue $path insert insert "\n" incr lines } } default { $path insert insert " ? " $path insert insert [$node nodeValue] attrValue $path insert insert "\n" } } } if {!$doSiblings} { return } break #set node [$node nextSibling] } } #---------------------------------------------------------------------------- # xmlWidgetLoad # #---------------------------------------------------------------------------- proc xmlWidgetLoad { path mode location xml query } { global doc root keepEmpties useSimple if {$mode == "xml"} { if {$useSimple} { if {$keepEmpties} { set doc [dom parse -keepEmpties -simple $xml] } else { set doc [dom parse -simple $xml] } } else { if {$keepEmpties} { set doc [dom parse -keepEmpties $xml] } else { set doc [dom parse $xml] } } } else { if {$keepEmpties} { set doc [dom parse -keepEmpties -html $xml] } else { set doc [dom parse -html $xml] } } set root [$doc documentElement] set query [string trim $query] if {$query == ""} { set query / } $path insert end \n $path insert end xml( header $path insert end $location query $path insert end ") " header $path insert end $query query $path insert end \n set nodes 0 set rows 0 set results [$root selectNodes $query type] switch $type { nodes { foreach node $results { $path mark set insert end xmlWidgetLoad_Recurs $path 1 "" $node 2 $path insert end \n incr nodes } } attrnodes { foreach {attrName attrValue} $results { $path insert end $attrName attrName $path insert end " " $path insert end $attrValue attrValue $path insert end \n incr rows } } attrvalues { foreach result $results { $path insert end "$result\n" incr rows } } default { $path insert end "$results\n" } } if {$rows != 0} { $path insert end "---$rows result(s)---\n" } if {$nodes != 0} { $path insert end "---$nodes node(s)---\n" } $path yview -pickplace end } #---------------------------------------------------------------------------- # xmlReload # #---------------------------------------------------------------------------- proc xmlReload { } { global xml set xml [.edit.f.text get 1.0 end] xmlWidgetLoad .xml.text xml $xml } #---------------------------------------------------------------------------- # GetXML # #---------------------------------------------------------------------------- proc GetXML { url } { global Login HttpProxyHost HttpProxyPort if {[regexp { *file:(.*)} $url all path]} { #puts stderr "file path='$path'" set fd [open $path] set xml [read $fd [file size $path]] close $fd } if {[regexp { *http:(.*)} $url all path]} { #puts stderr "http url='$path'" set xml "" set login "" set password "" #------------------------------------------------------ # try to re-use old login and password # #------------------------------------------------------ regexp {//([^/]*)/(.*)} $url all server file set indexes [array names Login $server,*] if {[llength $indexes] == 1} { foreach { login password } $Login($indexes) break } while 1 { set hdrs {} if {$login != ""} { #------------------------------------------- # generate Basic Authenication header #------------------------------------------ set hdrs [list Authorization "Basic [Base64Encode $login:$password]" ] } #------------------------------------------- # do HTTP request #------------------------------------------- http::config -proxyhost $HttpProxyHost -proxyport $HttpProxyPort set token [http::geturl $url -headers $hdrs] #------------------------------------------- # wait till HTTP request finishes #------------------------------------------ http::wait $token upvar $token state set statuscode [lindex $state(http) 1] if {$statuscode != "200"} { if {$statuscode == "401"} { if {[GetUserPassword state login password]} { #puts stderr "login='$login' password='$password'" continue } else { return "" } } else { puts stderr "\n\n\nstatuscode=$statuscode" puts stderr "$state(http)" break } } else { set xml [http::data $token] break } } } return $xml } #---------------------------------------------------------------------------- # xmlExecute # #---------------------------------------------------------------------------- proc xmlExecute { sel } { #puts stderr $sel if {[regexp { *(xml|html)\(([^)]*)\)(.*)} $sel all mode location query]} { #puts stderr "'$sel' location='$location' query='$query'" .pane.output.text configure -cursor watch . configure -cursor watch update set xml [GetXML $location] if {$xml != ""} { xmlWidgetLoad .pane.output.text $mode $location $xml $query } .pane.output.text configure -cursor left_ptr . configure -cursor left_ptr } else { error "Not a complete query!!" } } #---------------------------------------------------------------------------- # GotoParent # #---------------------------------------------------------------------------- proc GotoParent { } { global PointerXY set pos $PointerXY set path .pane.output.text foreach tag [$path tag names $pos] { #puts stderr "tag=$tag" if {[string match domNode* $tag]} { set tag [$tag parentNode] if {$tag == ""} return $path configure -state normal set start [$path index "$pos linestart"] set end [$path index "$start + 1 lines"] regexp {$( *)} [$path index "$start + 1 lines"] all level $path delete $start $end while 1 { set end [$path index "$start + 1 lines"] set nextLine [$path get $start $end] if {[string match "$level *" $nextLine]} { $path delete $start $end } else { break } } $path mark set insert $start xmlWidgetLoad_Recurs $path 0 $level $tag 2 $path see $start } } } #---------------------------------------------------------------------------- # As # #---------------------------------------------------------------------------- proc As { method } { global PointerXY set path .pane.output.text foreach tag [$path tag names $PointerXY] { if {[string match domNode* $tag]} { set oldEnd [$path index end] $path insert end \n[$tag $method] $path see $oldEnd } } } #---------------------------------------------------------------------------- # ToXPath # #---------------------------------------------------------------------------- proc ToXPath { } { global PointerXY set path .pane.output.text foreach tag [$path tag names $PointerXY] { if {[string match domNode* $tag]} { set oldEnd [$path index end] $path insert end \n[$tag toXPath] $path see $oldEnd } } } #---------------------------------------------------------------------------- # begin main part #---------------------------------------------------------------------------- namespace eval ::dom::xpathFunc { proc names { ctxNode pos nodeListType nodeList args } { if {[llength $args] != 2} { error "wrong # of args for XPATH function 'names'" } foreach { type value } $args break if {($type != "nodes") && ($type != "attrnodes") } { error "names only applicable for node or attribute node lists!" } set n {} if {$type == "nodes"} { foreach node $value { lappend n [$node nodeName] } } else { foreach {attrName attrValue} $value { lappend n $attrName } } return [list string $n] } } set xe_save "~/.xe-input" set xe_config "~/.xe-config" if {[llength $argv] > 0} { set xe_save [lindex $argv 0] } set bgcolor "grey90" set fgcolor "black" switch $tcl_platform(platform) { unix { set Cour12 8x13 set CourB12 8x13b set Helv10 "-Adobe-helvetica-medium-r-normal--*-100-*" set Helv12 "-Adobe-helvetica-medium-r-normal--*-120-*" set HelvB10 "-Adobe-helvetica-bold-r-normal--*-100-*" set HelvB12 "-Adobe-helvetica-bold-r-normal--*-120-*" } windows { set Cour12 "{Courier New} 10" set CourB12 "{Courier New} 10 bold" set Helv10 "Arial 9" set Helv12 "Arial 10" set HelvB10 "Arial 9 bold" set HelvB12 "Arial 10 bold" } } option add *background gray80 option add *foreground black option add *selector black option add *Scrollbar.foreground #dfdfdf option add *Scrollbar.activeForeground #efefef option add *font $HelvB12 wm title . "xe - [lindex $argv 0]" wm minsize . 30 10 wm geometry . 80x20 #--------------------------------------- # set up iconwin #--------------------------------------- if {$tcl_platform(platform)== "unix"} { toplevel .icwin frame .icwin.f -relief flat -borderwidth 1 label .icwin.f.l1 -text xe -font $Helv12 label .icwin.f.l2 -text [lindex $argv 0] -font $Helv12 pack .icwin.f pack .icwin.f.l1 .icwin.f.l2 -anchor nw .icwin configure -relief ridge -borderwidth 2 wm geometry .icwin 60x60 wm iconwindow . .icwin } set keepEmpties 0 set useSimple 0 frame .menu -relief raised -borderwidth 1 -highlightthickness 0 #-- File -------------- menubutton .menu.file -text " File " -menu .menu.file.m menu .menu.file.m -tearoff 0 .menu.file.m add command -label " Clear Input Window " -command { .pane.upper.input.text delete 0.0 end } .menu.file.m add separator .menu.file.m add command -label " Save Output Window in ~/xe-out" -command { SaveTextWindow .pane.output.text "~/xe-out" } .menu.file.m add command -label " Print Output Window" -command { PrintDialog } .menu.file.m add separator .menu.file.m add command -label " Quit without Save" -command { exit } .menu.file.m add command -label " Save Input Window in $xe_save" -command { SaveTextWindow .pane.upper.input.text $xe_save } .menu.file.m add command -label " Quit and Save Input Window in $xe_save" \ -command { SaveTextWindow .pane.upper.input.text $xe_save exit } #-- Options -------------- menubutton .menu.options -text " Options " -menu .menu.options.m menu .menu.options.m -tearoff 0 .menu.options.m add command -label " http proxy " -command ConfigureProxy .menu.options.m add check -label " keep empties " \ -underline 1 -variable keepEmpties .menu.options.m add check -label " use simple parser " \ -underline 1 -variable useSimple pack .menu.file \ .menu.options -side left label .menu.info -text "XE " -font $HelvB12 pack .menu.info -side right pane .pane vertical 1000 1000 .pane configure -highlightthickness 0 frame .pane.upper -borderwidth 0 -highlightthickness 0 frame .pane.upper.input -borderwidth 2 -highlightthickness 0 text .pane.upper.input.text -relief sunken -bd 2 -height 10 -width 80 \ -bg $bgcolor -fg $fgcolor \ -font $Cour12 -padx 2 -pady 2 -setgrid 1 \ -yscrollcommand ".pane.upper.input.sb set" .pane.upper.input.text configure -exportselection yes .pane.upper.input.text tag configure search -background white -foreground black scrollbar .pane.upper.input.sb -relief sunken -command ".pane.upper.input.text yview" pack .pane.upper.input.sb -side right -fill y -expand no pack .pane.upper.input.text -side top -fill both -expand yes xmlWidget .pane.output pack .pane.output -side bottom -fill both -expand yes frame .pane.upper.buttons -borderwidth 1 -highlightthickness 0 label .pane.upper.buttons.searchL -text " search:" -underline 4 -font $Helv12 entry .pane.upper.buttons.search -width 20 -relief sunken -borderwidth 2 \ -textvariable searchString -exportselection yes \ -font $Cour12 -highlightthickness 1 \ -background gray90 button .pane.upper.buttons.padb1 -state disabled -relief flat \ -highlightthickness 0 \ -borderwidth 0 -padx 15 -pady 0 button .pane.upper.buttons.padb2 -state disabled -relief flat \ -highlightthickness 0 \ -borderwidth 0 -padx 15 -pady 0 button .pane.upper.buttons.execute -text "execute " -command { set sel [selection get] if {$sel != ""} { xmlExecute $sel } } -pady 2 button .pane.upper.buttons.clearoutput -text clearoutput -command { .pane.output.text delete 0.0 en foreach doc [info commands domDoc*] { $doc delete } } -pady 2 pack .pane.upper.buttons.searchL \ .pane.upper.buttons.search \ .pane.upper.buttons.padb1 \ .pane.upper.buttons.execute \ .pane.upper.buttons.padb2 \ .pane.upper.buttons.clearoutput -side left pack .pane.upper.buttons -anchor w pack .pane.upper.input -side top -fill both -expand yes pack .pane.upper.buttons -side bottom -fill x -expand no pack .pane.upper -fill both -expand yes pack .menu -fill x -side top -expand no pack .pane -side top -fill both -expand yes pane_place .pane vertical 0.25 .pane.upper .pane.output bind_emacstext Text menu .pane.output.m -tearoff 0 .pane.output.m add command -label " goto parent " -command GotoParent .pane.output.m add command -label " asXML " -command "As asXML" .pane.output.m add command -label " asHTML " -command "As asHTML" .pane.output.m add command -label " toXPath " -command ToXPath bind .pane.output.text <3> { .pane.output.text configure -cursor left_ptr set PointerXY @%x,%y eval tk_popup .pane.output.m [winfo pointerxy %W] } #-------------------------------------------------------------------- # search feature #-------------------------------------------------------------------- set origSearchWin .pane.upper.input.text .pane.output.text tag configure search -background white -foreground black .pane.upper.input.text tag configure search -background white -foreground black bind Text { global origSearchWin set origSearchWin %W focus .pane.upper.buttons.search } bind .pane.upper.buttons.search { set len [string length $searchString] .pane.upper.input.text tag remove search 0.0 end .pane.output.text tag remove search 0.0 end set curinsert [$origSearchWin index insert] set spos [$origSearchWin search -regexp $searchString insert] if {$spos != ""} { if {[$origSearchWin compare $curinsert == $spos]} { $origSearchWin mark set insert {insert +1char} } set spos [$origSearchWin search -regexp $searchString insert] if {$spos != ""} { $origSearchWin mark set insert $spos $origSearchWin see insert $origSearchWin tag add search insert "insert + $len char" } } break } #-------------------------------------------------------------------- # load the xe save file into the input window # #-------------------------------------------------------------------- if {[catch { set f [open $xe_save r ] }] == 0} { .pane.upper.input.text delete 1.0 end while { [gets $f i] >= 0 } { .pane.upper.input.text insert end $i .pane.upper.input.text insert end "\n" } close $f } IntroWindow # button .startedit -text " Edit plain XML " -font $Helv12 -command xmlEdit # button .dump -text " dump " -font $Helv12 -command {puts stderr [info commands xmlelem*]} # pack .xml -fill both -expand yes # pack .dump .startedit -anchor e # set fd [open [lindex $argv 0]] # set xml [read $fd] # close $fd # xmlWidgetLoad .pane.output.text $xml #---------------------------------------------------------------------------- # end of main part #---------------------------------------------------------------------------- tdom-0.9.5-src/xe/README0000644000175000017500000000042214703531020013230 0ustar rolfrolf XE saves the upper input window in the file ~/.xe-input, if it is called without arguments. Otherwise the first argument gives the file name for the saved input windos. To start playing with xe you could do either: 1) cp xe-input ~/.xe-input xe 2) xe xe-input tdom-0.9.5-src/xe/xe-input0000644000175000017500000000236714703531020014056 0ustar rolfrolf xml(file:../tests/data/mondial-europe.xml)/country[name='Germany'] xml(file:../tests/data/mondial-europe.xml) contains(//country[name='Germany']/name,"any") xml(file:../tests/data/mondial-europe.xml)//country[name='Germany']/province[population>5000000]/name xml(file:../tests/data/mondial-europe.xml)count(//country[name='Germany']/province) xml(file:../tests/data/mondial-europe.xml) //mountain[in_country[@ref = string(//country[name='Germany']/@id)]] xml(file:../tests/data/mondial-europe.xml)//country[name='France']/province/name xml(file:../tests/data/mondial-europe.xml)//country[name='Germany']//city[population>1000000] xml(file:../tests/data/mondial-europe.xml)//country[name='France']/province/city[population<100000] xml(file:../tests/data/mondial-europe.xml)//river[length>4000] xml(file:../tests/data/mondial-europe.xml)//river/name xml(file:../tests/data/mondial-europe.xml) //country/car_code/text() xml(file:../tests/data/books.xml) //book[@style="novel"] xml(file:../doc/domNode.xml) //method/text() xml(http://www.fernweh.com/wap/info.wml) xml(http://www.fernweh.com/wap/categories.wml) xml(http://wap.is.danet.de/lh/flugplan/index.wml) xml(http://wap.t-d1-wap.de/t-online/) xml(http://www.vbxml.com/downloads/files/dropdown_xsl.txt) tdom-0.9.5-src/xe/xe.bat0000644000175000017500000000004614703531020013456 0ustar rolfrolfd:\opt\tcl8.2.3\bin\wish82 xe xe-inputtdom-0.9.5-src/macosx/0000755000175000017500000000000014703531020013230 5ustar rolfrolftdom-0.9.5-src/macosx/README0000644000175000017500000000026114703531020014107 0ustar rolfrolf Please go to ../unix directory and inspect the CONFIG file. There you will find example on how to configure and make the library on macOS using GNU configure/make tools. -EOF tdom-0.9.5-src/tdomConfig.sh.in0000644000175000017500000000361014703531020014770 0ustar rolfrolf# # tdomConfig.sh -- # # This shell script (for Bourne sh and alike) is generated # automatically by tDOM configure script. It will create # shell variables for some of the configuration options # discovered by the configure. This script is intended to be # sourced by the configure scripts for tDOM extensions so # that they don't have to figure this all out for themselves. # This file does not duplicate information already provided # by tclConfig.sh, so you may need to use that file in addition # to this one. To be able to locate this file easily, extensions # might want to include the tdom.m4 file in their configure # scripts and use the TDOM_PATH_CONFIG and TDOM_LOAD_CONFIG. # # The information in this file is specific to a single platform. # # # tDOM version number # TDOM_VERSION='@PACKAGE_VERSION@' # The name of the TDOM library (may be either a .a file or a shared library): TDOM_LIB_FILE=@PKG_LIB_FILE@ # # The name of the tDOM stub library file # TDOM_STUB_LIB_FILE=@PKG_STUB_LIB_FILE@ # # String to pass to linker to pick up the tDOM library from # its build directory. # TDOM_BUILD_STUB_LIB_SPEC='@tdom_BUILD_STUB_LIB_SPEC@' # # String to pass to linker to pick up the tDOM library from # its installed directory. # TDOM_STUB_LIB_SPEC='@tdom_STUB_LIB_SPEC@' # String to pass to linker to pick up the TDOM stub library from its # build directory. # TDOM_BUILD_STUB_LIB_PATH='@tdom_BUILD_STUB_LIB_PATH@' # String to pass to linker to pick up the TDOM stub library from its # installed directory. # TDOM_STUB_LIB_PATH='@tdom_STUB_LIB_PATH@' # # Location of the top-level source directories from which tDOM # was built. This is the directory that contains generic, unix, # win etc. If tDOM was compiled in a different place than the # directory containing the source files, this points to the # location of the sources, not the location where tDOM was compiled. # TDOM_SRC_DIR='@srcdir@' # EOF tdom-0.9.5-src/Makefile.in0000644000175000017500000004622314703531020014012 0ustar rolfrolf# Makefile.in -- # # This file is a Makefile for the tdom TEA Extension. If it has the name # "Makefile.in" then it is a template for a Makefile; to generate the # actual Makefile, run "./configure", which is a configuration script # generated by the "autoconf" program (constructs like "@foo@" will get # replaced in the actual Makefile. # # Copyright (c) 2013-2020 Rolf Ade # # Derived from work # Copyright (c) 1999 Scriptics Corporation. # Copyright (c) 2002-2005 ActiveState Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. #======================================================================== # Add additional lines to handle any additional AC_SUBST cases that # have been added in a customized configure script. #======================================================================== AOL_DIR = @AOL_DIR@ TDOMSHELL = @TDOMSHELL@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ LIB_RUNTIME_DIR = $(libdir) TDOM_LD_SEARCH_FLAGS = @TDOM_LD_SEARCH_FLAGS@ #======================================================================== # This are additional flags to be appended to the test suite run #======================================================================== TESTFLAGS = -constraints longRunning #======================================================================== # Nothing of the variables below this line should need to be changed. # Please check the TARGETS section below to make sure the make targets # are correct. #======================================================================== #======================================================================== # The names of the source files is defined in the configure script. # The object files are used for linking into the final library. # This will be used when a dist target is added to the Makefile. # It is not important to specify the directory, as long as it is the # $(srcdir) or in the generic, win or unix subdirectory. #======================================================================== PKG_SOURCES = @PKG_SOURCES@ PKG_OBJECTS = @PKG_OBJECTS@ PKG_STUB_SOURCES = @PKG_STUB_SOURCES@ PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@ #======================================================================== # PKG_TCL_SOURCES identifies Tcl runtime files that are associated with # this package that need to be installed, if any. #======================================================================== PKG_TCL_SOURCES = @PKG_TCL_SOURCES@ #======================================================================== # This is a list of public header files to be installed, if any. #======================================================================== PKG_HEADERS = @PKG_HEADERS@ #======================================================================== # "PKG_LIB_FILE" refers to the library (dynamic or static as per # configuration options) composed of the named objects. #======================================================================== PKG_LIB_FILE = @PKG_LIB_FILE@ PKG_LIB_FILE8 = @PKG_LIB_FILE8@ PKG_LIB_FILE9 = @PKG_LIB_FILE9@ PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@ lib_BINARIES = $(PKG_LIB_FILE) $(PKG_STUB_LIB_FILE) BINARIES = $(lib_BINARIES) SHELL = @SHELL@ srcdir = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ includedir = @includedir@ datarootdir = @datarootdir@ runstatedir = @runstatedir@ datadir = @datadir@ mandir = @mandir@ DESTDIR = PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION) pkgdatadir = $(datadir)/$(PKG_DIR) pkglibdir = $(libdir)/$(PKG_DIR) pkgincludedir = $(includedir)/$(PKG_DIR) top_builddir = @abs_top_builddir@ INSTALL_OPTIONS = INSTALL = @INSTALL@ $(INSTALL_OPTIONS) INSTALL_DATA_DIR = @INSTALL_DATA_DIR@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_LIBRARY = @INSTALL_LIBRARY@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ CC = @CC@ CCLD = @CCLD@ CFLAGS_DEFAULT = @CFLAGS_DEFAULT@ CFLAGS_WARNING = @CFLAGS_WARNING@ EXEEXT = @EXEEXT@ LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@ MAKE_LIB = @MAKE_LIB@ MAKE_STUB_LIB = @MAKE_STUB_LIB@ OBJEXT = @OBJEXT@ RANLIB = @RANLIB@ RANLIB_STUB = @RANLIB_STUB@ SHLIB_CFLAGS = @SHLIB_CFLAGS@ SHLIB_LD = @SHLIB_LD@ SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ STLIB_LD = @STLIB_LD@ #TCL_DEFS = @TCL_DEFS@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_SRC_DIR = @TCL_SRC_DIR@ #TK_BIN_DIR = @TK_BIN_DIR@ #TK_SRC_DIR = @TK_SRC_DIR@ # Not used, but retained for reference of what libs Tcl required #TCL_LIBS = @TCL_LIBS@ TDOMSHELL_LIBS = @TCL_LIBS@ @SHLIB_LD_LIBS@ #======================================================================== # TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our # package without installing. The other environment variables allow us # to test against an uninstalled Tcl. Add special env vars that you # require for testing here (like TCLX_LIBRARY). #======================================================================== EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR) #EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR) TCLLIBPATH = $(top_builddir) TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` PKG_ENV = @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ PATH="$(EXTRA_PATH):$(PATH)" \ TCLLIBPATH="$(TCLLIBPATH)" TCLSH_PROG = @TCLSH_PROG@ TCLSH = $(TCLSH_ENV) $(PKG_ENV) $(TCLSH_PROG) #WISH_ENV = TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library` #WISH_PROG = @WISH_PROG@ #WISH = $(TCLSH_ENV) $(WISH_ENV) $(PKG_ENV) $(WISH_PROG) SHARED_BUILD = @SHARED_BUILD@ INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ -I$(top_builddir) #INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@ PKG_CFLAGS = @PKG_CFLAGS@ # TCL_DEFS is not strictly need here, but if you remove it, then you # must make sure that configure.ac checks for the necessary components # that your library may use. TCL_DEFS can actually be a problem if # you do not compile with a similar machine setup as the Tcl core was # compiled with. #DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS) DEFS = @DEFS@ $(PKG_CFLAGS) # Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl tdomConfig.sh versionhash.h CLEANFILES = @CLEANFILES@ CPPFLAGS = @CPPFLAGS@ LIBS = @PKG_LIBS@ @LIBS@ AR = @AR@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) \ $(CFLAGS_DEFAULT) $(CFLAGS_WARNING) $(SHLIB_CFLAGS) $(CFLAGS) GDB = gdb VALGRIND = valgrind VALGRINDARGS = --tool=memcheck --num-callers=20 --leak-resolution=high \ --leak-check=yes --show-reachable=yes -v .SUFFIXES: .c .$(OBJEXT) #======================================================================== # Start of user-definable TARGETS section #======================================================================== #======================================================================== # TEA TARGETS. Please note that the "libraries:" target refers to platform # independent files, and the "binaries:" target includes executable programs and # platform-dependent libraries. Modify these targets so that they install # the various pieces of your package. The make and install rules # for the BINARIES that you specified above have already been done. #======================================================================== all: binaries libraries doc #======================================================================== # TDOM enabled shell is build as an extra directive, since non TEA. #======================================================================== $(TDOMSHELL): binaries $(srcdir)/unix/tclAppInit.c $(COMPILE) -UUSE_TCL_STUBS -c `@CYGPATH@ $(srcdir)/unix/tclAppInit.c` $(CC) @LDFLAGS@ -o $@ tclAppInit.$(OBJEXT) $(PKG_OBJECTS) \ $(TCL_LIB_SPEC) $(TDOMSHELL_LIBS) $(TDOM_LD_SEARCH_FLAGS) #======================================================================== # The binaries target builds executable programs, Windows .dll's, unix # shared/static libraries, and any other platform-dependent files. # The list of targets to build for "binaries:" is specified at the top # of the Makefile, in the "BINARIES" variable. #======================================================================== binaries: $(top_builddir)/versionhash.h $(BINARIES) @cp $(srcdir)/lib/tdom.tcl . libraries: #======================================================================== # Your doc target should differentiate from doc builds (by the developer) # and doc installs (see install-doc), which just install the docs on the # end user machine when building from source. #======================================================================== doc: install: all install-binaries install-libraries install-doc install-binaries: binaries install-lib-binaries install-bin-binaries #======================================================================== # This rule installs platform-independent files, such as header files. # The list=...; for p in $$list handles the empty list case x-platform. #======================================================================== install-libraries: libraries @$(INSTALL_DATA_DIR) $(DESTDIR)$(includedir) @echo "Installing header files in $(DESTDIR)$(includedir)" @list='$(PKG_HEADERS)'; for i in $$list; do \ echo "Installing $(srcdir)/$$i" ; \ $(INSTALL_DATA) $(srcdir)/$$i "$(DESTDIR)$(includedir)" ; \ done; #======================================================================== # Install documentation. Unix manpages should go in the $(mandir) # directory. #======================================================================== install-doc: doc @$(INSTALL_DATA_DIR) $(DESTDIR)$(mandir)/mann @echo "Installing documentation in $(DESTDIR)$(mandir)" @list='$(srcdir)/doc/*.n'; for i in $$list; do \ echo "Installing $$i"; \ $(INSTALL_DATA) $$i "$(DESTDIR)$(mandir)/mann" ; \ done test: binaries libraries @cp $(srcdir)/lib/tdom.tcl . $(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) \ -load "package ifneeded $(PACKAGE_NAME) $(PACKAGE_VERSION) \ [list load `@CYGPATH@ $(PKG_LIB_FILE)` [string totitle $(PACKAGE_NAME)]]" shell: binaries libraries @$(TCLSH) $(SCRIPT) gdb: $(TCLSH_ENV) $(PKG_ENV) $(GDB) $(TCLSH_PROG) $(SCRIPT) gdb-test: binaries libraries $(TCLSH_ENV) $(PKG_ENV) $(GDB) \ --args $(TCLSH_PROG) `@CYGPATH@ $(srcdir)/tests/all.tcl` \ $(TESTFLAGS) -singleproc 1 \ -load "package ifneeded $(PACKAGE_NAME) $(PACKAGE_VERSION) \ [list load `@CYGPATH@ $(PKG_LIB_FILE)` [string totitle $(PACKAGE_NAME)]]" valgrind: binaries libraries $(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) \ `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) valgrindshell: binaries libraries $(TCLSH_ENV) $(PKG_ENV) $(VALGRIND) $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT) depend: #======================================================================== # $(PKG_LIB_FILE) should be listed as part of the BINARIES variable # mentioned above. That will ensure that this target is built when you # run "make binaries". # # The $(PKG_OBJECTS) objects are created and linked into the final # library. In most cases these object files will correspond to the # source files above. #======================================================================== $(PKG_LIB_FILE): $(PKG_OBJECTS) -rm -f $(PKG_LIB_FILE) ${MAKE_LIB} $(RANLIB) $(PKG_LIB_FILE) $(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS) -rm -f $(PKG_STUB_LIB_FILE) ${MAKE_STUB_LIB} $(RANLIB_STUB) $(PKG_STUB_LIB_FILE) #======================================================================== # We need to enumerate the list of .c to .o lines here. # # In the following lines, $(srcdir) refers to the toplevel directory # containing your extension. If your sources are in a subdirectory, # you will have to modify the paths to reflect this: # # sample.$(OBJEXT): $(srcdir)/generic/sample.c # $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@ # # Setting the VPATH variable to a list of paths will cause the makefile # to look into these paths when resolving .c to .obj dependencies. # As necessary, add $(srcdir):$(srcdir)/compat:.... #======================================================================== VPATH = $(srcdir):$(srcdir)/expat:$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win:$(srcdir)/macosx .c.@OBJEXT@: $(COMPILE) -c `@CYGPATH@ $<` -o $@ #======================================================================== # Create the pkgIndex.tcl file. #======================================================================== pkgIndex.tcl-hand: @(echo 'package ifneeded $(PACKAGE_NAME) $(PACKAGE_VERSION) \ "load [list [file join $$dir $(PKG_LIB_FILE)]];\ source [list [file join $$dir tdom.tcl]]"'\ ) > pkgIndex.tcl #======================================================================== # Create tdomDecls.h and tdomStubInit.c from tdom.decls #======================================================================== genstubs: $(srcdir)/generic/tdom.decls $(TCLSH_PROG) $(TCL_SRC_DIR)/tools/genStubs.tcl $(srcdir)/generic \ $(srcdir)/generic/tdom.decls #======================================================================== # Create a include file that #define the current fossil hash #======================================================================== $(top_builddir)/versionhash.h: $(srcdir)/manifest.uuid @echo "#define FOSSIL_HASH \"" | tr -d '\n\r' > $(top_builddir)/versionhash.h @cat $(srcdir)/manifest.uuid | tr -d '\n\r' >> $(top_builddir)/versionhash.h @echo "\"" >> $(top_builddir)/versionhash.h tcldom.o: $(srcdir)/generic/tcldom.c $(top_builddir)/versionhash.h #======================================================================== # Distribution creation # You may need to tweak this target to make it work correctly. #======================================================================== #COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar COMPRESS = tar zcvf $(PKG_DIR).tar.gz $(PKG_DIR) DIST_ROOT = /tmp/dist DIST_DIR = $(DIST_ROOT)/$(PKG_DIR) DIST_INSTALL_DATA = CPPROG='cp -p' $(INSTALL) -m 644 DIST_INSTALL_SCRIPT = CPPROG='cp -p' $(INSTALL) -m 755 dist-clean: rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.* dist: dist-clean $(INSTALL_DATA_DIR) $(DIST_DIR) # TEA files $(DIST_INSTALL_DATA) $(srcdir)/Makefile.in \ $(srcdir)/aclocal.m4 $(srcdir)/configure.ac \ $(DIST_DIR)/ $(DIST_INSTALL_SCRIPT) $(srcdir)/configure $(DIST_DIR)/ $(INSTALL_DATA_DIR) $(DIST_DIR)/tclconfig $(DIST_INSTALL_DATA) $(srcdir)/tclconfig/README.txt \ $(srcdir)/tclconfig/tcl.m4 $(srcdir)/tclconfig/install-sh \ $(DIST_DIR)/tclconfig/ # Extension files $(DIST_INSTALL_DATA) \ $(srcdir)/CHANGES \ $(srcdir)/ChangeLog \ $(srcdir)/LICENSE \ $(srcdir)/MPL_2.0.html \ $(srcdir)/README.md \ $(srcdir)/README.AOL \ $(srcdir)/manifest \ $(srcdir)/manifest.uuid \ $(srcdir)/tdomConfig.sh.in \ $(srcdir)/tdom.m4 \ $(srcdir)/pkgIndex.tcl.in \ $(DIST_DIR)/ list='apps doc expat generic lib macosx unix win xe'; \ for p in $$list; do \ $(INSTALL_DATA_DIR) $(DIST_DIR)/$$p; \ $(DIST_INSTALL_DATA) $(srcdir)/$$p/* $(DIST_DIR)/$$p/; \ done $(INSTALL_DATA_DIR) $(DIST_DIR)/tests/data $(DIST_INSTALL_DATA) $(srcdir)/tests/*.* $(DIST_DIR)/tests/ $(DIST_INSTALL_DATA) $(srcdir)/tests/data/*.* $(DIST_DIR)/tests/data/ $(INSTALL_DATA_DIR) $(DIST_DIR)/extensions cp -rp $(srcdir)/extensions/* $(DIST_DIR)/extensions/ (cd $(DIST_ROOT); $(COMPRESS);) #======================================================================== # End of user-definable section #======================================================================== #======================================================================== # Don't modify the file to clean here. Instead, set the "CLEANFILES" # variable in configure.ac #======================================================================== clean: -test -z "$(BINARIES)" || rm -f $(BINARIES) -rm -f *.$(OBJEXT) core *.core -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean: clean -rm -f *.tab.c -rm -f $(CONFIG_CLEAN_FILES) -rm -f config.cache config.log config.status #======================================================================== # Install binary object libraries. On Windows this includes both .dll and # .lib files. Because the .lib files are not explicitly listed anywhere, # we need to deduce their existence from the .dll file of the same name. # Library files go into the lib directory. # In addition, this will generate the pkgIndex.tcl # file in the install location (assuming it can find a usable tclsh shell) # # You should not have to modify this target. #======================================================================== install-lib-binaries: binaries @$(INSTALL_DATA_DIR) "$(DESTDIR)$(pkglibdir)" @list='$(lib_BINARIES)'; for p in $$list; do \ if test -f $$p; then \ echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \ $(INSTALL_LIBRARY) $$p "$(DESTDIR)$(pkglibdir)/$$p"; \ ext=`echo $$p|sed -e "s/.*\.//"`; \ if test "x$$ext" = "xdll"; then \ lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \ if test -f $$lib; then \ echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \ $(INSTALL_DATA) $$lib "$(DESTDIR)$(pkglibdir)/$$lib"; \ fi; \ fi; \ fi; \ done @echo "Installing tdomConfig.sh to $(DESTDIR)$(libdir)/" @$(INSTALL_DATA) tdomConfig.sh "$(DESTDIR)$(libdir)/tdomConfig.sh" @list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ if test -f $(srcdir)/$$p; then \ destp=`basename $$p`; \ echo "Installing $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \ $(INSTALL_DATA) $(srcdir)/$$p "$(DESTDIR)$(pkglibdir)/$$destp"; \ fi; \ done @if test "x$(SHARED_BUILD)" = "x1"; then \ echo "Installing pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \ $(INSTALL_DATA) pkgIndex.tcl "$(DESTDIR)$(pkglibdir)"; \ fi #======================================================================== # Install binary executables (e.g. .exe files and dependent .dll files) # This is for files that must go in the bin directory (located next to # wish and tclsh), like dependent .dll files on Windows. # # You should not have to modify this target, except to define bin_BINARIES # above if necessary. #======================================================================== install-bin-binaries: binaries @$(INSTALL_DATA_DIR) "$(DESTDIR)$(bindir)" @list='$(bin_BINARIES)'; for p in $$list; do \ if test -f $$p; then \ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \ $(INSTALL_PROGRAM) $$p "$(DESTDIR)$(bindir)/$$p"; \ fi; \ done Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status uninstall-binaries: list='$(lib_BINARIES)'; for p in $$list; do \ rm -f $(DESTDIR)$(pkglibdir)/$$p; \ done list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ p=`basename $$p`; \ rm -f "$(DESTDIR)$(pkglibdir)/$$p"; \ done list='$(bin_BINARIES)'; for p in $$list; do \ rm -f "$(DESTDIR)$(bindir)/$$p"; \ done .PHONY: all binaries clean depend distclean doc install libraries test .PHONY: gdb gdb-test valgrind valgrindshell # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: tdom-0.9.5-src/expat/0000755000175000017500000000000014703531020013057 5ustar rolfrolftdom-0.9.5-src/expat/Changes0000644000175000017500000022221714703531020014360 0ustar rolfrolf __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! Expat is UNDERSTAFFED and WITHOUT FUNDING. !! !! ~~~~~~~~~~~~ !! !! The following topics need *additional skilled C developers* to progress !! !! in a timely manner or at all (loosely ordered by descending priority): !! !! !! !! - fixing a complex non-public security issue, !! !! - teaming up on researching and fixing future security reports and !! !! ClusterFuzz findings with few-days-max response times in communication !! !! in order to (1) have a sound fix ready before the end of a 90 days !! !! grace period and (2) in a sustainable manner, !! !! - implementing and auto-testing XML 1.0r5 support !! !! (needs discussion before pull requests), !! !! - smart ideas on fixing the Autotools CMake files generation issue !! !! without breaking CI (needs discussion before pull requests), !! !! - the Windows binaries topic (needs requirements engineering first), !! !! - pushing migration from `int` to `size_t` further !! !! including edge-cases test coverage (needs discussion before anything). !! !! !! !! For details, please reach out via e-mail to sebastian@pipping.org so we !! !! can schedule a voice call on the topic, in English or German. !! !! !! !! THANK YOU! Sebastian Pipping -- Berlin, 2024-03-09 !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Release 2.6.2 Wed March 13 2024 Security fixes: #839 #842 CVE-2024-28757 -- Prevent billion laughs attacks with isolated use of external parsers. Please see the commit message of commit 1d50b80cf31de87750103656f6eb693746854aa8 for details. Bug fixes: #839 #841 Reject direct parameter entity recursion and avoid the related undefined behavior Other changes: #847 Autotools: Fix build for DOCBOOK_TO_MAN containing spaces #837 Add missing #821 and #824 to 2.6.1 change log #838 #843 Version info bumped from 10:1:9 (libexpat*.so.1.9.1) to 10:2:9 (libexpat*.so.1.9.2); see https://verbump.de/ for what these numbers do Special thanks to: Philippe Antoine Tomas Korbar and Clang UndefinedBehaviorSanitizer OSS-Fuzz / ClusterFuzz Release 2.6.1 Thu February 29 2024 Bug fixes: #817 Make tests independent of CPU speed, and thus more robust #828 #836 Expose billion laughs API with XML_DTD defined and XML_GE undefined, regression from 2.6.0 Other changes: #829 Hide test-only code behind new internal macro #833 Autotools: Reject expat_config.h.in defining SIZEOF_VOID_P #821 #824 Autotools: Fix "make clean" for case: ./configure --without-docbook && make clean all #819 Address compiler warnings #832 #834 Version info bumped from 10:0:9 (libexpat*.so.1.9.0) to 10:1:9 (libexpat*.so.1.9.1); see https://verbump.de/ for what these numbers do Infrastructure: #818 CI: Adapt to breaking changes in clang-format Special thanks to: David Hall Snild Dolkow Release 2.6.0 Tue February 6 2024 Security fixes: #789 #814 CVE-2023-52425 -- Fix quadratic runtime issues with big tokens that can cause denial of service, in partial where dealing with compressed XML input. Applications that parsed a document in one go -- a single call to functions XML_Parse or XML_ParseBuffer -- were not affected. The smaller the chunks/buffers you use for parsing previously, the bigger the problem prior to the fix. Backporters should be careful to no omit parts of pull request #789 and to include earlier pull request #771, in order to not break the fix. #777 CVE-2023-52426 -- Fix billion laughs attacks for users compiling *without* XML_DTD defined (which is not common). Users with XML_DTD defined have been protected since Expat >=2.4.0 (and that was CVE-2013-0340 back then). Bug fixes: #753 Fix parse-size-dependent "invalid token" error for external entities that start with a byte order mark #780 Fix NULL pointer dereference in setContext via XML_ExternalEntityParserCreate for compilation with XML_DTD undefined #812 #813 Protect against closing entities out of order Other changes: #723 Improve support for arc4random/arc4random_buf #771 #788 Improve buffer growth in XML_GetBuffer and XML_Parse #761 #770 xmlwf: Support --help and --version #759 #770 xmlwf: Support custom buffer size for XML_GetBuffer and read #744 xmlwf: Improve language and URL clickability in help output #673 examples: Add new example "element_declarations.c" #764 Be stricter about macro XML_CONTEXT_BYTES at build time #765 Make inclusion to expat_config.h consistent #726 #727 Autotools: configure.ac: Support --disable-maintainer-mode #678 #705 .. #706 #733 #792 Autotools: Sync CMake templates with CMake 3.26 #795 Autotools: Make installation of shipped man page doc/xmlwf.1 independent of docbook2man availability #815 Autotools|CMake: Add missing -DXML_STATIC to pkg-config file section "Cflags.private" in order to fix compilation against static libexpat using pkg-config on Windows #724 #751 Autotools|CMake: Require a C99 compiler (a de-facto requirement already since Expat 2.2.2 of 2017) #793 Autotools|CMake: Fix PACKAGE_BUGREPORT variable #750 #786 Autotools|CMake: Make test suite require a C++11 compiler #749 CMake: Require CMake >=3.5.0 #672 CMake: Lowercase off_t and size_t to help a bug in Meson #746 CMake: Sort xmlwf sources alphabetically #785 CMake|Windows: Fix generation of DLL file version info #790 CMake: Build tests/benchmark/benchmark.c as well for a build with -DEXPAT_BUILD_TESTS=ON #745 #757 docs: Document the importance of isFinal + adjust tests accordingly #736 docs: Improve use of "NULL" and "null" #713 docs: Be specific about version of XML (XML 1.0r4) and version of C (C99); (XML 1.0r5 will need a sponsor.) #762 docs: reference.html: Promote function XML_ParseBuffer more #779 docs: reference.html: Add HTML anchors to XML_* macros #760 docs: reference.html: Upgrade to OK.css 1.2.0 #763 #739 docs: Fix typos #696 docs|CI: Use HTTPS URLs instead of HTTP at various places #669 #670 .. #692 #703 .. #733 #772 Address compiler warnings #798 #800 Address clang-tidy warnings #775 #776 Version info bumped from 9:10:8 (libexpat*.so.1.8.10) to 10:0:9 (libexpat*.so.1.9.0); see https://verbump.de/ for what these numbers do Infrastructure: #700 #701 docs: Document security policy in file SECURITY.md #766 docs: Improve parse buffer variables in-code documentation #674 #738 .. #740 #747 .. #748 #781 #782 Refactor coverage and conformance tests #714 #716 Refactor debug level variables to unsigned long #671 Improve handling of empty environment variable value in function getDebugLevel (without visible user effect) #755 #774 .. #758 #783 .. #784 #787 tests: Improve test coverage with regard to parse chunk size #660 #797 #801 Fuzzing: Improve fuzzing coverage #367 #799 Fuzzing|CI: Start running OSS-Fuzz fuzzing regression tests #698 #721 CI: Resolve some Travis CI leftovers #669 CI: Be robust towards absence of Git tags #693 #694 CI: Set permissions to "contents: read" for security #709 CI: Pin all GitHub Actions to specific commits for security #739 CI: Reject spelling errors using codespell #798 CI: Enforce clang-tidy clean code #773 #808 .. #809 #810 CI: Upgrade Clang from 15 to 18 #796 CI: Start using Clang's Control Flow Integrity sanitizer #675 #720 #722 CI: Adapt to breaking changes in GitHub Actions Ubuntu images #689 CI: Adapt to breaking changes in Clang/LLVM Debian packaging #763 CI: Adapt to breaking changes in codespell #803 CI: Adapt to breaking changes in Cppcheck Special thanks to: Ivan Galkin Joyce Brum Philippe Antoine Rhodri James Snild Dolkow spookyahell Steven Garske and Clang AddressSanitizer Clang UndefinedBehaviorSanitizer codespell GCC Farm Project OSS-Fuzz Sony Mobile Release 2.5.0 Tue October 25 2022 Security fixes: #616 #649 #650 CVE-2022-43680 -- Fix heap use-after-free after overeager destruction of a shared DTD in function XML_ExternalEntityParserCreate in out-of-memory situations. Expected impact is denial of service or potentially arbitrary code execution. Bug fixes: #612 #645 Fix corruption from undefined entities #613 #654 Fix case when parsing was suspended while processing nested entities #616 #652 #653 Stop leaking opening tag bindings after a closing tag mismatch error where a parser is reset through XML_ParserReset and then reused to parse #656 CMake: Fix generation of pkg-config file #658 MinGW|CMake: Fix static library name Other changes: #663 Protect header expat_config.h from multiple inclusion #666 examples: Make use of XML_GetBuffer and be more consistent across examples #648 Address compiler warnings #667 #668 Version info bumped from 9:9:8 to 9:10:8; see https://verbump.de/ for what these numbers do Special thanks to: Jann Horn Mark Brand Osyotr Rhodri James and Google Project Zero Release 2.4.9 Tue September 20 2022 Security fixes: #629 #640 CVE-2022-40674 -- Heap use-after-free vulnerability in function doContent. Expected impact is denial of service or potentially arbitrary code execution. Bug fixes: #634 MinGW: Fix mis-compilation for -D__USE_MINGW_ANSI_STDIO=0 #614 docs: Fix documentation on effect of switch XML_DTD on symbol visibility in doc/reference.html Other changes: #638 MinGW: Make fix-xmltest-log.sh drop more Wine bug output #596 #625 Autotools: Sync CMake templates with CMake 3.22 #608 CMake: Migrate from use of CMAKE_*_POSTFIX to dedicated variables EXPAT_*_POSTFIX to stop affecting other projects #597 #599 Windows|CMake: Add missing -DXML_STATIC to test runners and fuzzers #512 #621 Windows|CMake: Render .def file from a template to fix linking with -DEXPAT_DTD=OFF and/or -DEXPAT_ATTR_INFO=ON #611 #621 MinGW|CMake: Apply MSVC .def file when linking #622 #624 MinGW|CMake: Sync library name with GNU Autotools, i.e. produce libexpat-1.dll rather than libexpat.dll by default. Filename libexpat.dll.a is unaffected. #632 MinGW|CMake: Set missing variable CMAKE_RC_COMPILER in toolchain file "cmake/mingw-toolchain.cmake" to avoid error "windres: Command not found" on e.g. Ubuntu 20.04 #597 #627 CMake: Unify inconsistent use of set() and option() in context of public build time options to take need for set(.. FORCE) in projects using Expat by means of add_subdirectory(..) off Expat's users' shoulders #626 #641 Stop exporting API symbols when building a static library #644 Resolve use of deprecated "fgrep" by "grep -F" #620 CMake: Make documentation on variables a bit more consistent #636 CMake: Drop leading whitespace from a #cmakedefine line in file expat_config.h.cmake #594 xmlwf: Fix harmless variable mix-up in function nsattcmp #592 #593 #610 Address Cppcheck warnings #643 Address Clang 15 compiler warnings #642 #644 Version info bumped from 9:8:8 to 9:9:8; see https://verbump.de/ for what these numbers do Infrastructure: #597 #598 CI: Windows: Start covering MSVC 2022 #619 CI: macOS: Migrate off deprecated macOS 10.15 #632 CI: Linux: Make migration off deprecated Ubuntu 18.04 work #643 CI: Upgrade Clang from 14 to 15 #637 apply-clang-format.sh: Add support for BSD find #633 coverage.sh: Exclude MinGW headers #635 coverage.sh: Fix name collision for -funsigned-char Special thanks to: David Faure Felix Wilhelm Frank Bergmann Rhodri James Rosen Penev Thijs Schreijer Vincent Torri and Google Project Zero Release 2.4.8 Mon March 28 2022 Other changes: #587 pkg-config: Move "-lm" to section "Libs.private" #587 CMake|MSVC: Fix pkg-config section "Libs" #55 #582 CMake|macOS: Start using linker arguments "-compatibility_version " and "-current_version " in a way compatible with GNU Libtool #590 #591 Version info bumped from 9:7:8 to 9:8:8; see https://verbump.de/ for what these numbers do Infrastructure: #589 CI: Upgrade Clang from 13 to 14 Special thanks to: evpobr Kai Pastor Sam James Release 2.4.7 Fri March 4 2022 Bug fixes: #572 #577 Relax fix to CVE-2022-25236 (introduced with release 2.4.5) with regard to all valid URI characters (RFC 3986), i.e. the following set (excluding whitespace): ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 % -._~ :/?#[]@ !$&'()*+,;= Other changes: #555 #570 #581 CMake|Windows: Store Expat version in the DLL #577 Document consequences of namespace separator choices not just in doc/reference.html but also in header #577 Document Expat's lack of validation of namespace URIs against RFC 3986, and that the XML 1.0r4 specification doesn't require Expat to validate namespace URIs, and that Expat may do more in that regard in future releases. If you find need for strict RFC 3986 URI validation on application level today, https://uriparser.github.io/ may be of interest. #579 Fix documentation of XML_EndDoctypeDeclHandler in #575 Document that a call to XML_FreeContentModel can be done at a later time from outside the element declaration handler #574 Make hardcoded namespace URIs easier to find in code #573 Update documentation on use of XML_POOR_ENTOPY on Solaris #569 #571 tests: Resolve use of macros NAN and INFINITY for GNU G++ 4.8.2 on Solaris. #578 #580 Version info bumped from 9:6:8 to 9:7:8; see https://verbump.de/ for what these numbers do Special thanks to: Jeffrey Walton Johnny Jazeix Thijs Schreijer Release 2.4.6 Sun February 20 2022 Bug fixes: #566 Fix a regression introduced by the fix for CVE-2022-25313 in release 2.4.5 that affects applications that (1) call function XML_SetElementDeclHandler and (2) are parsing XML that contains nested element declarations (e.g. ""). Other changes: #567 #568 Version info bumped from 9:5:8 to 9:6:8; see https://verbump.de/ for what these numbers do Special thanks to: Matt Sergeant Samanta Navarro Sergei Trofimovich and NixOS Perl XML::Parser Release 2.4.5 Fri February 18 2022 Security fixes: #562 CVE-2022-25235 -- Passing malformed 2- and 3-byte UTF-8 sequences (e.g. from start tag names) to the XML processing application on top of Expat can cause arbitrary damage (e.g. code execution) depending on how invalid UTF-8 is handled inside the XML processor; validation was not their job but Expat's. Exploits with code execution are known to exist. #561 CVE-2022-25236 -- Passing (one or more) namespace separator characters in "xmlns[:prefix]" attribute values made Expat send malformed tag names to the XML processor on top of Expat which can cause arbitrary damage (e.g. code execution) depending on such unexpectable cases are handled inside the XML processor; validation was not their job but Expat's. Exploits with code execution are known to exist. #558 CVE-2022-25313 -- Fix stack exhaustion in doctype parsing that could be triggered by e.g. a 2 megabytes file with a large number of opening braces. Expected impact is denial of service or potentially arbitrary code execution. #560 CVE-2022-25314 -- Fix integer overflow in function copyString; only affects the encoding name parameter at parser creation time which is often hardcoded (rather than user input), takes a value in the gigabytes to trigger, and a 64-bit machine. Expected impact is denial of service. #559 CVE-2022-25315 -- Fix integer overflow in function storeRawNames; needs input in the gigabytes and a 64-bit machine. Expected impact is denial of service or potentially arbitrary code execution. Other changes: #557 #564 Version info bumped from 9:4:8 to 9:5:8; see https://verbump.de/ for what these numbers do Special thanks to: Ivan Fratric Samanta Navarro and Google Project Zero JetBrains Release 2.4.4 Sun January 30 2022 Security fixes: #550 CVE-2022-23852 -- Fix signed integer overflow (undefined behavior) in function XML_GetBuffer (that is also called by function XML_Parse internally) for when XML_CONTEXT_BYTES is defined to >0 (which is both common and default). Impact is denial of service or more. #551 CVE-2022-23990 -- Fix unsigned integer overflow in function doProlog triggered by large content in element type declarations when there is an element declaration handler present (from a prior call to XML_SetElementDeclHandler). Impact is denial of service or more. Bug fixes: #544 #545 xmlwf: Fix a memory leak on output file opening error Other changes: #546 Autotools: Fix broken CMake support under Cygwin #554 Windows: Add missing files to the installer to fix compilation with CMake from installed sources #552 #554 Version info bumped from 9:3:8 to 9:4:8; see https://verbump.de/ for what these numbers do Special thanks to: Carlo Bramini hwt0415 Roland Illig Samanta Navarro and Clang LeakSan and the Clang team Release 2.4.3 Sun January 16 2022 Security fixes: #531 #534 CVE-2021-45960 -- Fix issues with left shifts by >=29 places resulting in a) realloc acting as free b) realloc allocating too few bytes c) undefined behavior depending on architecture and precise value for XML documents with >=2^27+1 prefixed attributes on a single XML tag a la "" where XML_ParserCreateNS is used to create the parser (which needs argument "-n" when running xmlwf). Impact is denial of service, or more. #532 #538 CVE-2021-46143 (ZDI-CAN-16157) -- Fix integer overflow on variable m_groupSize in function doProlog leading to realloc acting as free. Impact is denial of service or more. #539 CVE-2022-22822 to CVE-2022-22827 -- Prevent integer overflows near memory allocation at multiple places. Mitre assigned a dedicated CVE for each involved internal C function: - CVE-2022-22822 for function addBinding - CVE-2022-22823 for function build_model - CVE-2022-22824 for function defineAttribute - CVE-2022-22825 for function lookup - CVE-2022-22826 for function nextScaffoldPart - CVE-2022-22827 for function storeAtts Impact is denial of service or more. Other changes: #535 CMake: Make call to file(GENERATE [..]) work for CMake <3.19 #541 Autotools|CMake: MinGW: Make run.sh(.in) work for Cygwin and MSYS2 by not going through Wine on these platforms #527 #528 Address compiler warnings #533 #543 Version info bumped from 9:2:8 to 9:3:8; see https://verbump.de/ for what these numbers do Infrastructure: #536 CI: Check for realistic minimum CMake version #529 #539 CI: Cover compilation with -m32 #529 CI: Store coverage reports as artifacts for download #528 CI: Upgrade Clang from 11 to 13 Special thanks to: An anonymous whitehat Christopher Degawa J. Peter Mugaas Tyson Smith and GCC Farm Project Trend Micro Zero Day Initiative Release 2.4.2 Sun December 19 2021 Other changes: #509 #510 Link againgst libm for function "isnan" #513 #514 Include expat_config.h as early as possible #498 Autotools: Include files with release archives: - buildconf.sh - fuzz/*.c #507 #519 Autotools: Sync CMake templates with CMake 3.20 #495 #524 CMake: MinGW: Fix pkg-config section "Libs" for - non-release build types (e.g. -DCMAKE_BUILD_TYPE=Debug) - multi-config CMake generators (e.g. Ninja Multi-Config) #502 #503 docs: Document that function XML_GetBuffer may return NULL when asking for a buffer of 0 (zero) bytes size #522 #523 docs: Fix return value docs for both XML_SetBillionLaughsAttackProtection* functions #525 #526 Version info bumped from 9:1:8 to 9:2:8; see https://verbump.de/ for what these numbers do Special thanks to: Donghee Na Joergen Ibsen Kai Pastor Release 2.4.1 Sun May 23 2021 Bug fixes: #488 #490 Autotools: Fix installed header expat_config.h for multilib systems; regression introduced in 2.4.0 by pull request #486 Other changes: #491 #492 Version info bumped from 9:0:8 to 9:1:8; see https://verbump.de/ for what these numbers do Special thanks to: Gentoo's QA check "multilib_check_headers" Release 2.4.0 Sun May 23 2021 Security fixes: #34 #466 #484 CVE-2013-0340/CWE-776 -- Protect against billion laughs attacks (denial-of-service; flavors targeting CPU time or RAM or both, leveraging general entities or parameter entities or both) by tracking and limiting the input amplification factor ( := ( + ) / ). By conservative default, amplification up to a factor of 100.0 is tolerated and rejection only starts after 8 MiB of output bytes (= + ) have been processed. The fix adds the following to the API: - A new error code XML_ERROR_AMPLIFICATION_LIMIT_BREACH to signals this specific condition. - Two new API functions .. - XML_SetBillionLaughsAttackProtectionMaximumAmplification and - XML_SetBillionLaughsAttackProtectionActivationThreshold .. to further tighten billion laughs protection parameters when desired. Please see file "doc/reference.html" for details. If you ever need to increase the defaults for non-attack XML payload, please file a bug report with libexpat. - Two new XML_FEATURE_* constants .. - that can be queried using the XML_GetFeatureList function, and - that are shown in "xmlwf -v" output. - Two new environment variable switches .. - EXPAT_ACCOUNTING_DEBUG=(0|1|2|3) and - EXPAT_ENTITY_DEBUG=(0|1) .. for runtime debugging of accounting and entity processing. Specific behavior of these values may change in the future. - Two new command line arguments "-a FACTOR" and "-b BYTES" for xmlwf to further tighten billion laughs protection parameters when desired. If you ever need to increase the defaults for non-attack XML payload, please file a bug report with libexpat. Bug fixes: #332 #470 For (non-default) compilation with -DEXPAT_MIN_SIZE=ON (CMake) or CPPFLAGS=-DXML_MIN_SIZE (GNU Autotools): Fix segfault for UTF-16 payloads containing CDATA sections. #485 #486 Autotools: Fix generated CMake files for non-64bit and non-Linux platforms (e.g. macOS and MinGW in particular) that were introduced with release 2.3.0 Other changes: #468 #469 xmlwf: Improve help output and the xmlwf man page #463 xmlwf: Improve maintainability through some refactoring #477 xmlwf: Fix man page DocBook validity #456 Autotools: Sync CMake templates with CMake 3.18 #458 #459 CMake: Support absolute paths for both CMAKE_INSTALL_LIBDIR and CMAKE_INSTALL_INCLUDEDIR #471 #481 CMake: Add support for standard variable BUILD_SHARED_LIBS #457 Unexpose symbol _INTERNAL_trim_to_complete_utf8_characters #467 Resolve macro HAVE_EXPAT_CONFIG_H #472 Delete unused legacy helper file "conftools/PrintPath" #473 #483 Improve attribution #464 #465 #477 doc/reference.html: Fix XHTML validity #475 #478 doc/reference.html: Replace the 90s look by OK.css #479 Version info bumped from 8:0:7 to 9:0:8 due to addition of new symbols and error codes; see https://verbump.de/ for what these numbers do Infrastructure: #456 CI: Enable periodic runs #457 CI: Start covering the list of exported symbols #474 CI: Isolate coverage task #476 #482 CI: Adapt to breaking changes in image "ubuntu-18.04" #477 CI: Cover well-formedness and DocBook/XHTML validity of doc/reference.html and doc/xmlwf.xml Special thanks to: Dimitry Andric Eero Helenius Nick Wellnhofer Rhodri James Tomas Korbar Yury Gribov and Clang LeakSan JetBrains OSS-Fuzz Release 2.3.0 Thu March 25 2021 Bug fixes: #438 When calling XML_ParseBuffer without a prior successful call to XML_GetBuffer as a user, no longer trigger undefined behavior (by adding an integer to a NULL pointer) but rather return XML_STATUS_ERROR and set the error code to (new) code XML_ERROR_NO_BUFFER. Found by UBSan (UndefinedBehaviorSanitizer) of Clang 11 (but not Clang 9). #444 xmlwf: Exit status 2 was used for both: - malformed input files (documented) and - invalid command-line arguments (undocumented). The case of invalid command-line arguments now has its own exit status 4, resolving the ambiguity. Other changes: #439 xmlwf: Add argument -k to allow continuing after non-fatal errors #439 xmlwf: Add section about exit status to the -h help output #422 #426 #447 Windows: Drop support for Visual Studio <=14.0/2015 #434 Windows: CMake: Detect unsupported Visual Studio at configure time (rather than at compile time) #382 #428 testrunner: Make verbose mode (argument "-v") report about passed tests, and make default mode report about failures, as well. #442 CMake: Call "enable_language(CXX)" prior to tinkering with CMAKE_CXX_* variables #448 Document use of libexpat from a CMake-based project #451 Autotools: Install CMake files as generated by CMake 3.19.6 so that users with "find_package(expat [..] CONFIG [..])" are served on distributions that are *not* using the CMake build system inside for libexpat packaging #436 #437 Autotools: Drop obsolescent macro AC_HEADER_STDC #450 #452 Autotools: Resolve use of obsolete macro AC_CONFIG_HEADER #441 Address compiler warnings #443 Version info bumped from 7:12:6 to 8:0:7 due to addition of error code XML_ERROR_NO_BUFFER (see https://verbump.de/ for what these numbers do) Infrastructure: #435 #446 Replace Travis CI by GitHub Actions Special thanks to: Alexander Richardson Oleksandr Popovych Thomas Beutlich Tim Bray and Clang LeakSan, Clang 11 UBSan and the Clang team Release 2.2.10 Sat October 3 2020 Bug fixes: #390 #395 #398 Fix undefined behavior during parsing caused by pointer arithmetic with NULL pointers #404 #405 Fix reading uninitialized variable during parsing #406 xmlwf: Add missing check for malloc NULL return Other changes: #396 Windows: Drop support for Visual Studio <=8.0/2005 #409 Windows: Add missing file "Changes" to the installer to fix compilation with CMake from installed sources #403 xmlwf: Document exit codes in xmlwf manpage and exit with code 3 (rather than code 1) for output errors when used with "-d DIRECTORY" #356 #359 MinGW: Provide declaration of rand_s for mingwrt <5.3.0 #383 #392 Autotools: Use -Werror while configure tests the compiler for supported compile flags to avoid false positives #383 #393 #394 Autotools: Improve handling of user (C|CPP|CXX|LD)FLAGS, e.g. ensure that they have the last word over flags added while running ./configure #360 CMake: Create libexpatw.{dll,so} and expatw.pc (with emphasis on suffix "w") with -DEXPAT_CHAR_TYPE=(ushort|wchar_t) #360 CMake: Detect and deny unsupported build combinations involving -DEXPAT_CHAR_TYPE=(ushort|wchar_t) #360 CMake: Install pre-compiled shipped xmlwf.1 manpage in case of -DEXPAT_BUILD_DOCS=OFF #375 #380 #419 CMake: Fix use of Expat by means of add_subdirectory #407 #408 CMake: Keep expat target name constant at "expat" (i.e. refrain from using the target name to control build artifact filenames) #385 CMake: Fix compilation with -DEXPAT_SHARED_LIBS=OFF for Windows CMake: Expose man page compilation as target "xmlwf-manpage" #413 #414 CMake: Introduce option EXPAT_BUILD_PKGCONFIG to control generation of pkg-config file "expat.pc" #424 CMake: Add minimalistic support for building binary packages with CMake target "package"; based on CPack #366 CMake: Add option -DEXPAT_OSSFUZZ_BUILD=(ON|OFF) with default OFF to build fuzzer code against OSS-Fuzz and related environment variable LIB_FUZZING_ENGINE #354 Fix testsuite for -DEXPAT_DTD=OFF and -DEXPAT_NS=OFF, each #354 #355 .. #356 #412 Address compiler warnings #368 #369 Address pngcheck warnings with doc/*.png images #425 Version info bumped from 7:11:6 to 7:12:6 Special thanks to: asavah Ben Wagner Bhargava Shastry Frank Landgraf Jeffrey Walton Joe Orton Kleber Tarcísio Ma Lin Maciej Sroczyński Mohammed Khajapasha Vadim Zeitlin and Cppcheck 2.0 and the Cppcheck team Release 2.2.9 Wed September 25 2019 Other changes: examples: Drop executable bits from elements.c #349 Windows: Change the name of the Windows DLLs from expat*.dll to libexpat*.dll once more (regression from 2.2.8, first fixed in 1.95.3, issue #61 on SourceForge today, was issue #432456 back then); needs a fix due case-insensitive file systems on Windows and the fact that Perl's XML::Parser::Expat compiles into Expat.dll. #347 Windows: Only define _CRT_RAND_S if not defined Version info bumped from 7:10:6 to 7:11:6 Special thanks to: Ben Wagner Release 2.2.8 Fri September 13 2019 Security fixes: #317 #318 CVE-2019-15903 -- Fix heap overflow triggered by XML_GetCurrentLineNumber (or XML_GetCurrentColumnNumber), and deny internal entities closing the doctype; fixed in commit c20b758c332d9a13afbbb276d30db1d183a85d43 Bug fixes: #240 Fix cases where XML_StopParser did not have any effect when called from inside of an end element handler #341 xmlwf: Fix exit code for operation without "-d DIRECTORY"; previously, only "-d DIRECTORY" would give you a proper exit code: # xmlwf -d . <<<'' 2>/dev/null ; echo $? 2 # xmlwf <<<'' 2>/dev/null ; echo $? 0 Now both cases return exit code 2. Other changes: #299 #302 Windows: Replace LoadLibrary hack to access unofficial API function SystemFunction036 (RtlGenRandom) by using official API function rand_s (needs WinXP+) #325 Windows: Drop support for Visual Studio <=7.1/2003 and document supported compilers in README.md #286 Windows: Remove COM code from xmlwf; in case it turns out needed later, there will be a dedicated repository below https://github.com/libexpat/ for that code #322 Windows: Remove explicit MSVC solution and project files. You can generate Visual Studio solution files through CMake, e.g.: cmake -G"Visual Studio 15 2017" . #338 xmlwf: Make "xmlwf -h" help output more friendly #339 examples: Improve elements.c #244 #264 Autotools: Add argument --enable-xml-attr-info #239 #301 Autotools: Add arguments --with-getrandom --without-getrandom --with-sys-getrandom --without-sys-getrandom #312 #343 Autotools: Fix linking issues with "./configure LD=clang" Autotools: Fix "make run-xmltest" for out-of-source builds #329 #336 CMake: Pull all options from Expat <=2.2.7 into namespace prefix EXPAT_ with the exception of DOCBOOK_TO_MAN: - BUILD_doc -> EXPAT_BUILD_DOCS (plural) - BUILD_examples -> EXPAT_BUILD_EXAMPLES - BUILD_shared -> EXPAT_SHARED_LIBS - BUILD_tests -> EXPAT_BUILD_TESTS - BUILD_tools -> EXPAT_BUILD_TOOLS - DOCBOOK_TO_MAN -> DOCBOOK_TO_MAN (unchanged) - INSTALL -> EXPAT_ENABLE_INSTALL - MSVC_USE_STATIC_CRT -> EXPAT_MSVC_STATIC_CRT - USE_libbsd -> EXPAT_WITH_LIBBSD - WARNINGS_AS_ERRORS -> EXPAT_WARNINGS_AS_ERRORS - XML_CONTEXT_BYTES -> EXPAT_CONTEXT_BYTES - XML_DEV_URANDOM -> EXPAT_DEV_URANDOM - XML_DTD -> EXPAT_DTD - XML_NS -> EXPAT_NS - XML_UNICODE -> EXPAT_CHAR_TYPE=ushort (!) - XML_UNICODE_WCHAR_T -> EXPAT_CHAR_TYPE=wchar_t (!) #244 #264 CMake: Add argument -DEXPAT_ATTR_INFO=(ON|OFF), default OFF #326 CMake: Add argument -DEXPAT_LARGE_SIZE=(ON|OFF), default OFF #328 CMake: Add argument -DEXPAT_MIN_SIZE=(ON|OFF), default OFF #239 #277 CMake: Add arguments -DEXPAT_WITH_GETRANDOM=(ON|OFF|AUTO), default AUTO -DEXPAT_WITH_SYS_GETRANDOM=(ON|OFF|AUTO), default AUTO #326 CMake: Install expat_config.h to include directory #326 CMake: Generate and install configuration files for future find_package(expat [..] CONFIG [..]) CMake: Now produces a summary of applied configuration CMake: Require C++ compiler only when tests are enabled #330 CMake: Fix compilation for 16bit character types, i.e. ex -DXML_UNICODE=ON (and ex -DXML_UNICODE_WCHAR_T=ON) #265 CMake: Fix linking with MinGW #330 CMake: Add full support for MinGW; to enable, use -DCMAKE_TOOLCHAIN_FILE=[expat]/cmake/mingw-toolchain.cmake #330 CMake: Port "make run-xmltest" from GNU Autotools to CMake #316 CMake: Windows: Make binary postfix match MSVC Old: expat[d].lib New: expat[w][d][MD|MT].lib CMake: Migrate files from Windows to Unix line endings #308 CMake: Integrate OSS-Fuzz fuzzers, option -DEXPAT_BUILD_FUZZERS=(ON|OFF), default OFF #14 Drop an OpenVMS support leftover #235 #268 .. #270 #310 .. #313 #331 #333 Address compiler warnings #282 #283 .. #284 #285 Address cppcheck warnings #294 #295 Address Clang Static Analyzer warnings #24 #293 Mass-apply clang-format 9 (and ensure conformance during CI) Version info bumped from 7:9:6 to 7:10:6 Special thanks to: David Loffredo Joonun Jang Kishore Kunche Marco Maggi Mitch Phillips Mohammed Khajapasha Rolf Ade xantares Zhongyuan Zhou Release 2.2.7 Wed June 19 2019 Security fixes: #186 #262 CVE-2018-20843 -- Fix extraction of namespace prefixes from XML names; XML names with multiple colons could end up in the wrong namespace, and take a high amount of RAM and CPU resources while processing, opening the door to use for denial-of-service attacks Other changes: #195 #197 Autotools/CMake: Utilize -fvisibility=hidden to stop exporting non-API symbols #227 Autotools: Add --without-examples and --without-tests #228 Autotools: Modernize configure.ac #245 #246 Autotools: Fix check for -fvisibility=hidden for Clang #247 #248 Autotools: Fix compilation for lack of docbook2x-man #236 #258 Autotools: Produce .tar.{gz,lz,xz} release archives #212 CMake: Make libdir of pkgconfig expat.pc support multilib #158 #263 CMake: Build man page in PROJECT_BINARY_DIR not _SOURCE_DIR #219 Remove fallback to bcopy, assume that memmove(3) exists #257 Use portable "/usr/bin/env bash" shebang (e.g. for OpenBSD) #243 Windows: Fix syntax of .def module definition files Version info bumped from 7:8:6 to 7:9:6 Special thanks to: Benjamin Peterson Caolán McNamara Hanno Böck KangLin Kishore Kunche Marco Maggi Rhodri James Sebastian Dröge userwithuid Yury Gribov Release 2.2.6 Sun August 12 2018 Bug fixes: #170 #206 Avoid doing arithmetic with NULL pointers in XML_GetBuffer #204 #205 Fix 2.2.5 regression with suspend-resume while parsing a document like '' Other changes: #165 #168 Autotools: Fix docbook-related configure syntax error #166 Autotools: Avoid grep option `-q` for Solaris #167 Autotools: Support ./configure DOCBOOK_TO_MAN="xmlto man --skip-validation" #159 #167 Autotools: Support DOCBOOK_TO_MAN command which produces xmlwf.1 rather than XMLWF.1; also covers case insensitive file systems #181 Autotools: Drop -rpath option passed to libtool #188 Autotools: Detect and deny SGML docbook2man as ours is XML #188 Autotools/CMake: Support command db2x_docbook2man as well #174 CMake: Introduce option WARNINGS_AS_ERRORS, defaults to OFF #184 #185 CMake: Introduce option MSVC_USE_STATIC_CRT, defaults to OFF #207 #208 CMake: Introduce option XML_UNICODE and XML_UNICODE_WCHAR_T, both defaulting to OFF #175 CMake: Prefer check_symbol_exists over check_function_exists #176 CMake: Create the same pkg-config file as with GNU Autotools #178 #179 CMake: Use GNUInstallDirs module to set proper defaults for install directories #208 CMake: Utilize expat_config.h.cmake for XML_DEV_URANDOM #180 Windows: Fix compilation of test suite for Visual Studio 2008 #131 #173 #202 Address compiler warnings #187 #190 #200 Fix miscellaneous typos Version info bumped from 7:7:6 to 7:8:6 Special thanks to: Anton Maklakov Benjamin Peterson Brad King Franek Korta Frank Rast Joe Orton luzpaz Pedro Vicente Rainer Jung Rhodri James Rolf Ade Rolf Eike Beer Thomas Beutlich Tomasz Kłoczko Release 2.2.5 Tue October 31 2017 Bug fixes: #8 If the parser runs out of memory, make sure its internal state reflects the memory it actually has, not the memory it wanted to have. #11 The default handler wasn't being called when it should for a SYSTEM or PUBLIC doctype if an entity declaration handler was registered. #137 #138 Fix a case of mistakenly reported parsing success where XML_StopParser was called from an element handler #162 Function XML_ErrorString was returning NULL rather than a message for code XML_ERROR_INVALID_ARGUMENT introduced with release 2.2.1 Other changes: #106 xmlwf: Add argument -N adding notation declarations #75 #106 Test suite: Resolve expected failure cases where xmlwf output was incomplete #127 Windows: Fix test suite compilation #126 #127 Windows: Fix compilation for Visual Studio 2012 Windows: Upgrade shipped project files to Visual Studio 2017 #33 #132 tests: Mass-fix compilation for XML_UNICODE_WCHAR_T #129 examples: Fix compilation for XML_UNICODE_WCHAR_T #130 benchmark: Fix compilation for XML_UNICODE_WCHAR_T #144 xmlwf: Fix compilation for XML_UNICODE_WCHAR_T; still needs Windows or MinGW for 2-byte wchar_t #9 Address two Clang Static Analyzer false positives #59 Resolve troublesome macros hiding parser struct membership and dereferencing that pointer #6 Resolve superfluous internal malloc/realloc switch #153 #155 Improve docbook2x-man detection #160 Undefine NDEBUG in the test suite (rather than rejecting it) #161 Address compiler warnings Version info bumped from 7:6:6 to 7:7:6 Special thanks to: Benbuck Nason Hans Wennborg José Gutiérrez de la Concha Pedro Monreal Gonzalez Rhodri James Rolf Ade Stephen Groat and Core Infrastructure Initiative Release 2.2.4 Sat August 19 2017 Bug fixes: #115 Fix copying of partial characters for UTF-8 input Other changes: #109 Fix "make check" for non-x86 architectures that default to unsigned type char (-128..127 rather than 0..255) #109 coverage.sh: Cover -funsigned-char Autotools: Introduce --without-xmlwf argument #65 Autotools: Replace handwritten Makefile with GNU Automake #43 CMake: Auto-detect high quality entropy extractors, add new option USE_libbsd=ON to use arc4random_buf of libbsd #74 CMake: Add -fno-strict-aliasing only where supported #114 CMake: Always honor manually set BUILD_* options #114 CMake: Compile man page if docbook2x-man is available, only #117 Include file tests/xmltest.log.expected in source tarball (required for "make run-xmltest") #117 Include (existing) Visual Studio 2013 files in source tarball Improve test suite error output #111 Fix some typos in documentation Version info bumped from 7:5:6 to 7:6:6 Special thanks to: Jakub Wilk Joe Orton Lin Tian Rolf Eike Beer Release 2.2.3 Wed August 2 2017 Security fixes: #82 CVE-2017-11742 -- Windows: Fix DLL hijacking vulnerability using Steve Holme's LoadLibrary wrapper for/of cURL Bug fixes: #85 Fix a dangling pointer issue related to realloc Other changes: Increase code coverage #91 Linux: Allow getrandom to fail if nonblocking pool has not yet been initialized and read /dev/urandom then, instead. This is in line with what recent Python does. #81 Pre-10.7/Lion macOS: Support entropy from arc4random #86 Check that a UTF-16 encoding in an XML declaration has the right endianness #4 #5 #7 Recover correctly when some reallocations fail Repair "./configure && make" for systems without any provider of high quality entropy and try reading /dev/urandom on those Ensure that user-defined character encodings have converter functions when they are needed Fix mis-leading description of argument -c in xmlwf.1 Rely on macro HAVE_ARC4RANDOM_BUF (rather than __CloudABI__) for CloudABI #100 Fix use of SIPHASH_MAIN in siphash.h #23 Test suite: Fix memory leaks Version info bumped from 7:4:6 to 7:5:6 Special thanks to: Chanho Park Joe Orton Pascal Cuoq Rhodri James Simon McVittie Vadim Zeitlin Viktor Szakats and Core Infrastructure Initiative Release 2.2.2 Wed July 12 2017 Security fixes: #43 Protect against compilation without any source of high quality entropy enabled, e.g. with CMake build system; commit ff0207e6076e9828e536b8d9cd45c9c92069b895 #60 Windows with _UNICODE: Unintended use of LoadLibraryW with a non-wide string resulted in failure to load advapi32.dll and degradation in quality of used entropy when compiled with _UNICODE for Windows; you can launch existing binaries with EXPAT_ENTROPY_DEBUG=1 in the environment to inspect the quality of entropy used during runtime; commits * 95b95032f907ef1cd17ee7a9a1768010a825d61d * 73a5a2e9c081f49f2d775cf7ced864158b68dc80 [MOX-006] Fix non-NULL parser parameter validation in XML_Parse; resulted in NULL dereference, previously; commit ac256dafdffc9622ab0dc2c62fcecb0dfcfa71fe Bug fixes: #69 Fix improper use of unsigned long long integer literals Other changes: #73 Start requiring a C99 compiler #49 Fix "==" Bashism in configure script #50 Fix too eager getrandom detection for Debian GNU/kFreeBSD #52 and macOS #51 Address lack of stdint.h in Visual Studio 2003 to 2008 #58 Address compile warnings #68 Fix "./buildconf.sh && ./configure" for some versions of Dash for /bin/sh #72 CMake: Ease use of Expat in context of a parent project with multiple CMakeLists.txt files #72 CMake: Resolve mistaken executable permissions #76 Address compile warning with -DNDEBUG (not recommended!) #77 Address compile warning about macro redefinition Special thanks to: Alexander Bluhm Ben Boeckel Cătălin Răceanu Kerin Millar László Böszörményi S. P. Zeidler Segev Finer Václav Slavík Victor Stinner Viktor Szakats and Radically Open Security Release 2.2.1 Sat June 17 2017 Security fixes: CVE-2017-9233 -- External entity infinite loop DoS Details: https://libexpat.github.io/doc/cve-2017-9233/ Commit c4bf96bb51dd2a1b0e185374362ee136fe2c9d7f [MOX-002] CVE-2016-9063 -- Detect integer overflow; commit d4f735b88d9932bd5039df2335eefdd0723dbe20 (Fixed version of existing downstream patches!) (SF.net) #539 Fix regression from fix to CVE-2016-0718 cutting off longer tag names; commits * 896b6c1fd3b842f377d1b62135dccf0a579cf65d * af507cef2c93cb8d40062a0abe43a4f4e9158fb2 #16 * 0dbbf43fdb20f593ddf4fa1ff67288000dd4a7fd #25 More integer overflow detection (function poolGrow); commits * 810b74e4703dcfdd8f404e3cb177d44684775143 * 44178553f3539ce69d34abee77a05e879a7982ac [MOX-002] Detect overflow from len=INT_MAX call to XML_Parse; commits * 4be2cb5afcc018d996f34bbbce6374b7befad47f * 7e5b71b748491b6e459e5c9a1d090820f94544d8 [MOX-005] #30 Use high quality entropy for hash initialization: * arc4random_buf on BSD, systems with libbsd (when configured with --with-libbsd), CloudABI * RtlGenRandom on Windows XP / Server 2003 and later * getrandom on Linux 3.17+ In a way, that's still part of CVE-2016-5300. https://github.com/libexpat/libexpat/pull/30/commits [MOX-005] For the low quality entropy extraction fallback code, the parser instance address can no longer leak, commit 04ad658bd3079dd15cb60fc67087900f0ff4b083 [MOX-003] Prevent use of uninitialised variable; commit [MOX-004] a4dc944f37b664a3ca7199c624a98ee37babdb4b Add missing parameter validation to public API functions and dedicated error code XML_ERROR_INVALID_ARGUMENT: [MOX-006] * NULL checks; commits * d37f74b2b7149a3a95a680c4c4cd2a451a51d60a (merge/many) * 9ed727064b675b7180c98cb3d4f75efba6966681 * 6a747c837c50114dfa413994e07c0ba477be4534 * Negative length (XML_Parse); commit [MOX-002] 70db8d2538a10f4c022655d6895e4c3e78692e7f [MOX-001] #35 Change hash algorithm to William Ahern's version of SipHash to go further with fixing CVE-2012-0876. https://github.com/libexpat/libexpat/pull/39/commits Bug fixes: #32 Fix sharing of hash salt across parsers; relevant where XML_ExternalEntityParserCreate is called prior to XML_Parse, in particular (e.g. FBReader) #28 xmlwf: Auto-disable use of memory-mapping (and parsing as a single chunk) for files larger than ~1 GB (2^30 bytes) rather than failing with error "out of memory" #3 Fix double free after malloc failure in DTD code; commit 7ae9c3d3af433cd4defe95234eae7dc8ed15637f #17 Fix memory leak on parser error for unbound XML attribute prefix with new namespaces defined in the same tag; found by Google's OSS-Fuzz; commits * 16f87daae5a16132e479e4f71862128c7a915c73 * b47dbc9745932c160893d433220e462bd605f8cd xmlwf on Windows: Add missing calls to CloseHandle New features: #30 Introduced environment switch EXPAT_ENTROPY_DEBUG=1 for runtime debugging of entropy extraction Other changes: Increase code coverage #33 Reject use of XML_UNICODE_WCHAR_T with sizeof(wchar_t) != 2; XML_UNICODE_WCHAR_T was never meant to be used outside of Windows; 4-byte wchar_t is common on Linux (SF.net) #538 Start using -fno-strict-aliasing (SF.net) #540 Support compilation against cloudlibc of CloudABI Allow MinGW cross-compilation (SF.net) #534 CMake: Introduce option "BUILD_doc" (enabled by default) to bypass compilation of the xmlwf.1 man page (SF.net) pr2 CMake: Introduce option "INSTALL" (enabled by default) to bypass installation of expat files CMake: Fix ninja support Autotools: Add parameters --enable-xml-context [COUNT] and --disable-xml-context; default of context of 1024 bytes enabled unchanged #14 Drop AmigaOS 4.x code and includes #14 Drop ancient build systems: * Borland C++ Builder * OpenVMS * Open Watcom * Visual Studio 6.0 * Pre-X Mac OS (MPW Makefile) If you happen to rely on some of these, please get in touch for joining with maintenance. #10 Move from WIN32 to _WIN32 #13 Fix "make run-xmltest" order instability Address compile warnings Bump version info from 7:2:6 to 7:3:6 Add AUTHORS file Infrastructure: #1 Migrate from SourceForge to GitHub (except downloads): https://github.com/libexpat/ #1 Re-create http://libexpat.org/ project website Start utilizing Travis CI Special thanks to: Andy Wang Don Lewis Ed Schouten Karl Waclawek Pascal Cuoq Rhodri James Sergei Nikulov Tobias Taschner Viktor Szakats and Core Infrastructure Initiative Mozilla Foundation (MOSS Track 3: Secure Open Source) Radically Open Security Release 2.2.0 Tue June 21 2016 Security fixes: #537 CVE-2016-0718 -- Fix crash on malformed input CVE-2016-4472 -- Improve insufficient fix to CVE-2015-1283 / CVE-2015-2716 introduced with Expat 2.1.1 #499 CVE-2016-5300 -- Use more entropy for hash initialization than the original fix to CVE-2012-0876 #519 CVE-2012-6702 -- Resolve troublesome internal call to srand that was introduced with Expat 2.1.0 when addressing CVE-2012-0876 (issue #496) Bug fixes: Fix uninitialized reads of size 1 (e.g. in little2_updatePosition) Fix detection of UTF-8 character boundaries Other changes: #532 Fix compilation for Visual Studio 2010 (keyword "C99") Autotools: Resolve use of "$<" to better support bmake Autotools: Add QA script "qa.sh" (and make target "qa") Autotools: Respect CXXFLAGS if given Autotools: Fix "make run-xmltest" Autotools: Have "make run-xmltest" check for expected output p90 CMake: Fix static build (BUILD_shared=OFF) on Windows #536 CMake: Add soversion, support -DNO_SONAME=yes to bypass #323 CMake: Add suffix "d" to differentiate debug from release CMake: Define WIN32 with CMake on Windows Annotate memory allocators for GCC Address all currently known compile warnings Make sure that API symbols remain visible despite -fvisibility=hidden Remove executable flag from source files Resolve COMPILED_FROM_DSP in favor of WIN32 Special thanks to: Björn Lindahl Christian Heimes Cristian Rodríguez Daniel Krügler Gustavo Grieco Karl Waclawek László Böszörményi Marco Grassi Pascal Cuoq Sergei Nikulov Thomas Beutlich Warren Young Yann Droneaud Release 2.1.1 Sat March 12 2016 Security fixes: #582: CVE-2015-1283 - Multiple integer overflows in XML_GetBuffer Bug fixes: #502: Fix potential null pointer dereference #520: Symbol XML_SetHashSalt was not exported Output of "xmlwf -h" was incomplete Other changes: #503: Document behavior of calling XML_SetHashSalt with salt 0 Minor improvements to man page xmlwf(1) Improvements to the experimental CMake build system libtool now invoked with --verbose Release 2.1.0 Sat March 24 2012 - Security fixes: #2958794: CVE-2012-1148 - Memory leak in poolGrow. #2895533: CVE-2012-1147 - Resource leak in readfilemap.c. #3496608: CVE-2012-0876 - Hash DOS attack. #2894085: CVE-2009-3560 - Buffer over-read and crash in big2_toUtf8(). #1990430: CVE-2009-3720 - Parser crash with special UTF-8 sequences. - Bug Fixes: #1742315: Harmful XML_ParserCreateNS suggestion. #1785430: Expat build fails on linux-amd64 with gcc version>=4.1 -O3. #1983953, 2517952, 2517962, 2649838: Build modifications using autoreconf instead of buildconf.sh. #2815947, #2884086: OBJEXT and EXEEXT support while building. #2517938: xmlwf should return non-zero exit status if not well-formed. #2517946: Wrong statement about XMLDecl in xmlwf.1 and xmlwf.sgml. #2855609: Dangling positionPtr after error. #2990652: CMake support. #3010819: UNEXPECTED_STATE with a trailing "%" in entity value. #3206497: Uninitialized memory returned from XML_Parse. #3287849: make check fails on mingw-w64. - Patches: #1749198: pkg-config support. #3010222: Fix for bug #3010819. #3312568: CMake support. #3446384: Report byte offsets for attr names and values. - New Features / API changes: Added new API member XML_SetHashSalt() that allows setting an initial value (salt) for hash calculations. This is part of the fix for bug #3496608 to randomize hash parameters. When compiled with XML_ATTR_INFO defined, adds new API member XML_GetAttributeInfo() that allows retrieving the byte offsets for attribute names and values (patch #3446384). Added CMake build system. See bug #2990652 and patch #3312568. Added run-benchmark target to Makefile.in - relies on testdata module present in the same relative location as in the repository. Release 2.0.1 Tue June 5 2007 - Fixed bugs #1515266, #1515600: The character data handler's calling of XML_StopParser() was not handled properly; if the parser was stopped and the handler set to NULL, the parser would segfault. - Fixed bug #1690883: Expat failed on EBCDIC systems as it assumed some character constants to be ASCII encoded. - Minor cleanups of the test harness. - Fixed xmlwf bug #1513566: "out of memory" error on file size zero. - Fixed outline.c bug #1543233: missing a final XML_ParserFree() call. - Fixes and improvements for Windows platform: bugs #1409451, #1476160, #1548182, #1602769, #1717322. - Build fixes for various platforms: HP-UX, Tru64, Solaris 9: patch #1437840, bug #1196180. All Unix: #1554618 (refreshed config.sub/config.guess). #1490371, #1613457: support both, DESTDIR and INSTALL_ROOT, without relying on GNU-Make specific features. #1647805: Patched configure.in to work better with Intel compiler. - Fixes to Makefile.in to have make check work correctly: bugs #1408143, #1535603, #1536684. - Added Open Watcom support: patch #1523242. Release 2.0.0 Wed Jan 11 2006 - We no longer use the "check" library for C unit testing; we always use the (partial) internal implementation of the API. - Report XML_NS setting via XML_GetFeatureList(). - Fixed headers for use from C++. - XML_GetCurrentLineNumber() and XML_GetCurrentColumnNumber() now return unsigned integers. - Added XML_LARGE_SIZE switch to enable 64-bit integers for byte indexes and line/column numbers. - Updated to use libtool 1.5.22 (the most recent). - Added support for AmigaOS. - Some mostly minor bug fixes. SF issues include: #1006708, #1021776, #1023646, #1114960, #1156398, #1221160, #1271642. Release 1.95.8 Fri Jul 23 2004 - Major new feature: suspend/resume. Handlers can now request that a parse be suspended for later resumption or aborted altogether. See "Temporarily Stopping Parsing" in the documentation for more details. - Some mostly minor bug fixes, but compilation should no longer generate warnings on most platforms. SF issues include: #827319, #840173, #846309, #888329, #896188, #923913, #928113, #961698, #985192. Release 1.95.7 Mon Oct 20 2003 - Fixed enum XML_Status issue (reported on SourceForge many times), so compilers that are properly picky will be happy. - Introduced an XMLCALL macro to control the calling convention used by the Expat API; this macro should be used to annotate prototypes and definitions of callback implementations in code compiled with a calling convention other than the default convention for the host platform. - Improved ability to build without the configure-generated expat_config.h header. This is useful for applications which embed Expat rather than linking in the library. - Fixed a variety of bugs: see SF issues #458907, #609603, #676844, #679754, #692878, #692964, #695401, #699323, #699487, #820946. - Improved hash table lookups. - Added more regression tests and improved documentation. Release 1.95.6 Tue Jan 28 2003 - Added XML_FreeContentModel(). - Added XML_MemMalloc(), XML_MemRealloc(), XML_MemFree(). - Fixed a variety of bugs: see SF issues #615606, #616863, #618199, #653180, #673791. - Enhanced the regression test suite. - Man page improvements: includes SF issue #632146. Release 1.95.5 Fri Sep 6 2002 - Added XML_UseForeignDTD() for improved SAX2 support. - Added XML_GetFeatureList(). - Defined XML_Bool type and the values XML_TRUE and XML_FALSE. - Use an incomplete struct instead of a void* for the parser (may not retain). - Fixed UTF-8 decoding bug that caused legal UTF-8 to be rejected. - Finally fixed bug where default handler would report DTD events that were already handled by another handler. Initial patch contributed by Darryl Miles. - Removed unnecessary DllMain() function that caused static linking into a DLL to be difficult. - Added VC++ projects for building static libraries. - Reduced line-length for all source code and headers to be no longer than 80 characters, to help with AS/400 support. - Reduced memory copying during parsing (SF patch #600964). - Fixed a variety of bugs: see SF issues #580793, #434664, #483514, #580503, #581069, #584041, #584183, #584832, #585537, #596555, #596678, #598352, #598944, #599715, #600479, #600971. Release 1.95.4 Fri Jul 12 2002 - Added support for VMS, contributed by Craig Berry. See vms/README.vms for more information. - Added Mac OS (classic) support, with a makefile for MPW, contributed by Thomas Wegner and Daryle Walker. - Added Borland C++ Builder 5 / BCC 5.5 support, contributed by Patrick McConnell (SF patch #538032). - Fixed a variety of bugs: see SF issues #441449, #563184, #564342, #566334, #566901, #569461, #570263, #575168, #579196. - Made skippedEntityHandler conform to SAX2 (see source comment) - Re-implemented WFC: Entity Declared from XML 1.0 spec and added a new error "entity declared in parameter entity": see SF bug report #569461 and SF patch #578161 - Re-implemented section 5.1 from XML 1.0 spec: see SF bug report #570263 and SF patch #578161 Release 1.95.3 Mon Jun 3 2002 - Added a project to the MSVC workspace to create a wchar_t version of the library; the DLLs are named libexpatw.dll. - Changed the name of the Windows DLLs from expat.dll to libexpat.dll; this fixes SF bug #432456. - Added the XML_ParserReset() API function. - Fixed XML_SetReturnNSTriplet() to work for element names. - Made the XML_UNICODE builds usable (thanks, Karl!). - Allow xmlwf to read from standard input. - Install a man page for xmlwf on Unix systems. - Fixed many bugs; see SF bug reports #231864, #461380, #464837, #466885, #469226, #477667, #484419, #487840, #494749, #496505, #547350. Other bugs which we can't test as easily may also have been fixed, especially in the area of build support. Release 1.95.2 Fri Jul 27 2001 - More changes to make MSVC happy with the build; add a single workspace to support both the library and xmlwf application. - Added a Windows installer for Windows users; includes xmlwf.exe. - Added compile-time constants that can be used to determine the Expat version - Removed a lot of GNU-specific dependencies to aide portability among the various Unix flavors. - Fix the UTF-8 BOM bug. - Cleaned up warning messages for several compilers. - Added the -Wall, -Wstrict-prototypes options for GCC. Release 1.95.1 Sun Oct 22 15:11:36 EDT 2000 - Changes to get expat to build under Microsoft compiler - Removed all aborts and instead return an UNEXPECTED_STATE error. - Fixed a bug where a stray '%' in an entity value would cause an abort. - Defined XML_SetEndNamespaceDeclHandler. Thanks to Darryl Miles for finding this oversight. - Changed default patterns in lib/Makefile.in to fit non-GNU makes Thanks to robin@unrated.net for reporting and providing an account to test on. - The reference had the wrong label for XML_SetStartNamespaceDecl. Reported by an anonymous user. Release 1.95.0 Fri Sep 29 2000 - XML_ParserCreate_MM Allows you to set a memory management suite to replace the standard malloc,realloc, and free. - XML_SetReturnNSTriplet If you turn this feature on when namespace processing is in effect, then qualified, prefixed element and attribute names are returned as "uri|name|prefix" where '|' is whatever separator character is used in namespace processing. - Merged in features from perl-expat o XML_SetElementDeclHandler o XML_SetAttlistDeclHandler o XML_SetXmlDeclHandler o XML_SetEntityDeclHandler o StartDoctypeDeclHandler takes 3 additional parameters: sysid, pubid, has_internal_subset o Many paired handler setters (like XML_SetElementHandler) now have corresponding individual handler setters o XML_GetInputContext for getting the input context of the current parse position. - Added reference material - Packaged into a distribution that builds a sharable library tdom-0.9.5-src/expat/xmltok_ns.c0000644000175000017500000001104014703531020015235 0ustar rolfrolf/* This file is included! __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2002 Greg Stein Copyright (c) 2002 Fred L. Drake, Jr. Copyright (c) 2002-2006 Karl Waclawek Copyright (c) 2017-2021 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifdef XML_TOK_NS_C const ENCODING * NS(XmlGetUtf8InternalEncoding)(void) { return &ns(internal_utf8_encoding).enc; } const ENCODING * NS(XmlGetUtf16InternalEncoding)(void) { # if BYTEORDER == 1234 return &ns(internal_little2_encoding).enc; # elif BYTEORDER == 4321 return &ns(internal_big2_encoding).enc; # else const short n = 1; return (*(const char *)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc); # endif } static const ENCODING *const NS(encodings)[] = { &ns(latin1_encoding).enc, &ns(ascii_encoding).enc, &ns(utf8_encoding).enc, &ns(big2_encoding).enc, &ns(big2_encoding).enc, &ns(little2_encoding).enc, &ns(utf8_encoding).enc /* NO_ENC */ }; static int PTRCALL NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr); } static int PTRCALL NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr); } int NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name) { int i = getEncodingIndex(name); if (i == UNKNOWN_ENC) return 0; SET_INIT_ENC_INDEX(p, i); p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog); p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent); p->initEnc.updatePosition = initUpdatePosition; p->encPtr = encPtr; *encPtr = &(p->initEnc); return 1; } static const ENCODING * NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end) { # define ENCODING_MAX 128 char buf[ENCODING_MAX] = ""; char *p = buf; int i; XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1); if (ptr != end) return 0; *p = 0; if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2) return enc; i = getEncodingIndex(buf); if (i == UNKNOWN_ENC) return 0; return NS(encodings)[i]; } int NS(XmlParseXmlDecl)(int isGeneralTextEntity, const ENCODING *enc, const char *ptr, const char *end, const char **badPtr, const char **versionPtr, const char **versionEndPtr, const char **encodingName, const ENCODING **encoding, int *standalone) { return doParseXmlDecl(NS(findEncoding), isGeneralTextEntity, enc, ptr, end, badPtr, versionPtr, versionEndPtr, encodingName, encoding, standalone); } #endif /* XML_TOK_NS_C */ tdom-0.9.5-src/expat/utf8tab.h0000644000175000017500000000670214703531020014612 0ustar rolfrolf/* __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2002 Fred L. Drake, Jr. Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, /* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, /* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, /* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, /* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, /* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, /* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4, /* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML, /* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM, tdom-0.9.5-src/expat/expat_external.h0000644000175000017500000001361514703531020016261 0ustar rolfrolf/* __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2000-2004 Fred L. Drake, Jr. Copyright (c) 2001-2002 Greg Stein Copyright (c) 2002-2006 Karl Waclawek Copyright (c) 2016 Cristian Rodríguez Copyright (c) 2016-2019 Sebastian Pipping Copyright (c) 2017 Rhodri James Copyright (c) 2018 Yury Gribov Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef Expat_External_INCLUDED #define Expat_External_INCLUDED 1 /* External API definitions */ /* Expat tries very hard to make the API boundary very specifically defined. There are two macros defined to control this boundary; each of these can be defined before including this header to achieve some different behavior, but doing so it not recommended or tested frequently. XMLCALL - The calling convention to use for all calls across the "library boundary." This will default to cdecl, and try really hard to tell the compiler that's what we want. XMLIMPORT - Whatever magic is needed to note that a function is to be imported from a dynamically loaded library (.dll, .so, or .sl, depending on your platform). The XMLCALL macro was added in Expat 1.95.7. The only one which is expected to be directly useful in client code is XMLCALL. Note that on at least some Unix versions, the Expat library must be compiled with the cdecl calling convention as the default since system headers may assume the cdecl convention. */ #ifndef XMLCALL # if defined(_MSC_VER) # define XMLCALL __cdecl # elif defined(__GNUC__) && defined(__i386) && ! defined(__INTEL_COMPILER) # define XMLCALL __attribute__((cdecl)) # else /* For any platform which uses this definition and supports more than one calling convention, we need to extend this definition to declare the convention used on that platform, if it's possible to do so. If this is the case for your platform, please file a bug report with information on how to identify your platform via the C pre-processor and how to specify the same calling convention as the platform's malloc() implementation. */ # define XMLCALL # endif #endif /* not defined XMLCALL */ #if ! defined(XML_STATIC) && ! defined(XMLIMPORT) # ifndef XML_BUILDING_EXPAT /* using Expat from an application */ # if defined(_MSC_EXTENSIONS) && ! defined(__BEOS__) && ! defined(__CYGWIN__) # define XMLIMPORT __declspec(dllimport) # endif # endif #endif /* not defined XML_STATIC */ #ifndef XML_ENABLE_VISIBILITY # define XML_ENABLE_VISIBILITY 0 #endif #if ! defined(XMLIMPORT) && XML_ENABLE_VISIBILITY # define XMLIMPORT __attribute__((visibility("default"))) #endif /* If we didn't define it above, define it away: */ #ifndef XMLIMPORT # define XMLIMPORT #endif #if defined(__GNUC__) \ && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) # define XML_ATTR_MALLOC __attribute__((__malloc__)) #else # define XML_ATTR_MALLOC #endif #if defined(__GNUC__) \ && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) # define XML_ATTR_ALLOC_SIZE(x) __attribute__((__alloc_size__(x))) #else # define XML_ATTR_ALLOC_SIZE(x) #endif #define XMLPARSEAPI(type) XMLIMPORT type XMLCALL #ifdef __cplusplus extern "C" { #endif #ifdef XML_UNICODE_WCHAR_T # ifndef XML_UNICODE # define XML_UNICODE # endif # if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2) # error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc" # endif #endif #ifdef XML_UNICODE /* Information is UTF-16 encoded. */ # ifdef XML_UNICODE_WCHAR_T typedef wchar_t XML_Char; typedef wchar_t XML_LChar; # else typedef unsigned short XML_Char; typedef char XML_LChar; # endif /* XML_UNICODE_WCHAR_T */ #else /* Information is UTF-8 encoded. */ typedef char XML_Char; typedef char XML_LChar; #endif /* XML_UNICODE */ #ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */ typedef long long XML_Index; typedef unsigned long long XML_Size; #else typedef long XML_Index; typedef unsigned long XML_Size; #endif /* XML_LARGE_SIZE */ #ifdef __cplusplus } #endif #endif /* not Expat_External_INCLUDED */ tdom-0.9.5-src/expat/latin1tab.h0000644000175000017500000000676514703531020015125 0ustar rolfrolf/* __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2002 Fred L. Drake, Jr. Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, /* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME, /* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, /* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, /* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, /* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, /* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, tdom-0.9.5-src/expat/siphash.h0000644000175000017500000003132614703531020014674 0ustar rolfrolf/* ========================================================================== * siphash.h - SipHash-2-4 in a single header file * -------------------------------------------------------------------------- * Derived by William Ahern from the reference implementation[1] published[2] * by Jean-Philippe Aumasson and Daniel J. Berstein. * Minimal changes by Sebastian Pipping and Victor Stinner on top, see below. * Licensed under the CC0 Public Domain Dedication license. * * 1. https://www.131002.net/siphash/siphash24.c * 2. https://www.131002.net/siphash/ * -------------------------------------------------------------------------- * HISTORY: * * 2020-10-03 (Sebastian Pipping) * - Drop support for Visual Studio 9.0/2008 and earlier * * 2019-08-03 (Sebastian Pipping) * - Mark part of sip24_valid as to be excluded from clang-format * - Re-format code using clang-format 9 * * 2018-07-08 (Anton Maklakov) * - Add "fall through" markers for GCC's -Wimplicit-fallthrough * * 2017-11-03 (Sebastian Pipping) * - Hide sip_tobin and sip_binof unless SIPHASH_TOBIN macro is defined * * 2017-07-25 (Vadim Zeitlin) * - Fix use of SIPHASH_MAIN macro * * 2017-07-05 (Sebastian Pipping) * - Use _SIP_ULL macro to not require a C++11 compiler if compiled as C++ * - Add const qualifiers at two places * - Ensure <=80 characters line length (assuming tab width 4) * * 2017-06-23 (Victor Stinner) * - Address Win64 compile warnings * * 2017-06-18 (Sebastian Pipping) * - Clarify license note in the header * - Address C89 issues: * - Stop using inline keyword (and let compiler decide) * - Replace _Bool by int * - Turn macro siphash24 into a function * - Address invalid conversion (void pointer) by explicit cast * - Address lack of stdint.h for Visual Studio 2003 to 2008 * - Always expose sip24_valid (for self-tests) * * 2012-11-04 - Born. (William Ahern) * -------------------------------------------------------------------------- * USAGE: * * SipHash-2-4 takes as input two 64-bit words as the key, some number of * message bytes, and outputs a 64-bit word as the message digest. This * implementation employs two data structures: a struct sipkey for * representing the key, and a struct siphash for representing the hash * state. * * For converting a 16-byte unsigned char array to a key, use either the * macro sip_keyof or the routine sip_tokey. The former instantiates a * compound literal key, while the latter requires a key object as a * parameter. * * unsigned char secret[16]; * arc4random_buf(secret, sizeof secret); * struct sipkey *key = sip_keyof(secret); * * For hashing a message, use either the convenience macro siphash24 or the * routines sip24_init, sip24_update, and sip24_final. * * struct siphash state; * void *msg; * size_t len; * uint64_t hash; * * sip24_init(&state, key); * sip24_update(&state, msg, len); * hash = sip24_final(&state); * * or * * hash = siphash24(msg, len, key); * * To convert the 64-bit hash value to a canonical 8-byte little-endian * binary representation, use either the macro sip_binof or the routine * sip_tobin. The former instantiates and returns a compound literal array, * while the latter requires an array object as a parameter. * -------------------------------------------------------------------------- * NOTES: * * o Neither sip_keyof, sip_binof, nor siphash24 will work with compilers * lacking compound literal support. Instead, you must use the lower-level * interfaces which take as parameters the temporary state objects. * * o Uppercase macros may evaluate parameters more than once. Lowercase * macros should not exhibit any such side effects. * ========================================================================== */ #ifndef SIPHASH_H #define SIPHASH_H #include /* size_t */ #include /* uint64_t uint32_t uint8_t */ /* * Workaround to not require a C++11 compiler for using ULL suffix * if this code is included and compiled as C++; related GCC warning is: * warning: use of C++11 long long integer constant [-Wlong-long] */ #define SIP_ULL(high, low) ((((uint64_t)high) << 32) | (low)) #define SIP_ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b)))) #define SIP_U32TO8_LE(p, v) \ (p)[0] = (uint8_t)((v) >> 0); \ (p)[1] = (uint8_t)((v) >> 8); \ (p)[2] = (uint8_t)((v) >> 16); \ (p)[3] = (uint8_t)((v) >> 24); #define SIP_U64TO8_LE(p, v) \ SIP_U32TO8_LE((p) + 0, (uint32_t)((v) >> 0)); \ SIP_U32TO8_LE((p) + 4, (uint32_t)((v) >> 32)); #define SIP_U8TO64_LE(p) \ (((uint64_t)((p)[0]) << 0) | ((uint64_t)((p)[1]) << 8) \ | ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) \ | ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) \ | ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56)) #define SIPHASH_INITIALIZER {0, 0, 0, 0, {0}, 0, 0} struct siphash { uint64_t v0, v1, v2, v3; unsigned char buf[8], *p; uint64_t c; }; /* struct siphash */ #define SIP_KEYLEN 16 struct sipkey { uint64_t k[2]; }; /* struct sipkey */ #define sip_keyof(k) sip_tokey(&(struct sipkey){{0}}, (k)) static struct sipkey * sip_tokey(struct sipkey *key, const void *src) { key->k[0] = SIP_U8TO64_LE((const unsigned char *)src); key->k[1] = SIP_U8TO64_LE((const unsigned char *)src + 8); return key; } /* sip_tokey() */ #ifdef SIPHASH_TOBIN # define sip_binof(v) sip_tobin((unsigned char[8]){0}, (v)) static void * sip_tobin(void *dst, uint64_t u64) { SIP_U64TO8_LE((unsigned char *)dst, u64); return dst; } /* sip_tobin() */ #endif /* SIPHASH_TOBIN */ static void sip_round(struct siphash *H, const int rounds) { int i; for (i = 0; i < rounds; i++) { H->v0 += H->v1; H->v1 = SIP_ROTL(H->v1, 13); H->v1 ^= H->v0; H->v0 = SIP_ROTL(H->v0, 32); H->v2 += H->v3; H->v3 = SIP_ROTL(H->v3, 16); H->v3 ^= H->v2; H->v0 += H->v3; H->v3 = SIP_ROTL(H->v3, 21); H->v3 ^= H->v0; H->v2 += H->v1; H->v1 = SIP_ROTL(H->v1, 17); H->v1 ^= H->v2; H->v2 = SIP_ROTL(H->v2, 32); } } /* sip_round() */ static struct siphash * sip24_init(struct siphash *H, const struct sipkey *key) { H->v0 = SIP_ULL(0x736f6d65U, 0x70736575U) ^ key->k[0]; H->v1 = SIP_ULL(0x646f7261U, 0x6e646f6dU) ^ key->k[1]; H->v2 = SIP_ULL(0x6c796765U, 0x6e657261U) ^ key->k[0]; H->v3 = SIP_ULL(0x74656462U, 0x79746573U) ^ key->k[1]; H->p = H->buf; H->c = 0; return H; } /* sip24_init() */ #define sip_endof(a) (&(a)[sizeof(a) / sizeof *(a)]) static struct siphash * sip24_update(struct siphash *H, const void *src, size_t len) { const unsigned char *p = (const unsigned char *)src, *pe = p + len; uint64_t m; do { while (p < pe && H->p < sip_endof(H->buf)) *H->p++ = *p++; if (H->p < sip_endof(H->buf)) break; m = SIP_U8TO64_LE(H->buf); H->v3 ^= m; sip_round(H, 2); H->v0 ^= m; H->p = H->buf; H->c += 8; } while (p < pe); return H; } /* sip24_update() */ static uint64_t sip24_final(struct siphash *H) { const char left = (char)(H->p - H->buf); uint64_t b = (H->c + left) << 56; switch (left) { case 7: b |= (uint64_t)H->buf[6] << 48; /* fall through */ case 6: b |= (uint64_t)H->buf[5] << 40; /* fall through */ case 5: b |= (uint64_t)H->buf[4] << 32; /* fall through */ case 4: b |= (uint64_t)H->buf[3] << 24; /* fall through */ case 3: b |= (uint64_t)H->buf[2] << 16; /* fall through */ case 2: b |= (uint64_t)H->buf[1] << 8; /* fall through */ case 1: b |= (uint64_t)H->buf[0] << 0; /* fall through */ case 0: break; } H->v3 ^= b; sip_round(H, 2); H->v0 ^= b; H->v2 ^= 0xff; sip_round(H, 4); return H->v0 ^ H->v1 ^ H->v2 ^ H->v3; } /* sip24_final() */ static uint64_t siphash24(const void *src, size_t len, const struct sipkey *key) { struct siphash state = SIPHASH_INITIALIZER; return sip24_final(sip24_update(sip24_init(&state, key), src, len)); } /* siphash24() */ /* * SipHash-2-4 output with * k = 00 01 02 ... * and * in = (empty string) * in = 00 (1 byte) * in = 00 01 (2 bytes) * in = 00 01 02 (3 bytes) * ... * in = 00 01 02 ... 3e (63 bytes) */ static int sip24_valid(void) { /* clang-format off */ static const unsigned char vectors[64][8] = { { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, }, { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, }, { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, }, { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, }, { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, }, { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, }, { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, }, { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, }, { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, }, { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, }, { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, }, { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, }, { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, }, { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, }, { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, }, { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, }, { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, }, { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, }, { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, }, { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, }, { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, }, { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, }, { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, }, { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, }, { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, }, { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, }, { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, }, { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, }, { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, }, { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, }, { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, }, { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, }, { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, }, { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, }, { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, }, { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, }, { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, }, { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, }, { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, }, { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, }, { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, }, { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, }, { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, }, { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, }, { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, }, { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, }, { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, }, { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, }, { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, }, { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, }, { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, }, { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, }, { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, }, { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, }, { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, }, { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, }, { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, }, { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, }, { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, }, { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, }, { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, }, { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, }, { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, }, { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, } }; /* clang-format on */ unsigned char in[64]; struct sipkey k; size_t i; sip_tokey(&k, "\000\001\002\003\004\005\006\007\010\011" "\012\013\014\015\016\017"); for (i = 0; i < sizeof in; ++i) { in[i] = (unsigned char)i; if (siphash24(in, i, &k) != SIP_U8TO64_LE(vectors[i])) return 0; } return 1; } /* sip24_valid() */ #ifdef SIPHASH_MAIN # include int main(void) { const int ok = sip24_valid(); if (ok) puts("OK"); else puts("FAIL"); return ! ok; } /* main() */ #endif /* SIPHASH_MAIN */ #endif /* SIPHASH_H */ tdom-0.9.5-src/expat/VERSION0000644000175000017500000000001414703531020014122 0ustar rolfrolfexpat-2.6.3 tdom-0.9.5-src/expat/xmlrole.c0000644000175000017500000010522314703531020014710 0ustar rolfrolf/* __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2002 Greg Stein Copyright (c) 2002-2006 Karl Waclawek Copyright (c) 2002-2003 Fred L. Drake, Jr. Copyright (c) 2005-2009 Steven Solie Copyright (c) 2016-2023 Sebastian Pipping Copyright (c) 2017 Rhodri James Copyright (c) 2019 David Loffredo Copyright (c) 2021 Donghee Na Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "expat_config.h" #include #ifdef _WIN32 # include "winconfig.h" #endif #include "expat_external.h" #include "internal.h" #include "xmlrole.h" #include "ascii.h" /* Doesn't check: that ,| are not mixed in a model group content of literals */ static const char KW_ANY[] = {ASCII_A, ASCII_N, ASCII_Y, '\0'}; static const char KW_ATTLIST[] = {ASCII_A, ASCII_T, ASCII_T, ASCII_L, ASCII_I, ASCII_S, ASCII_T, '\0'}; static const char KW_CDATA[] = {ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0'}; static const char KW_DOCTYPE[] = {ASCII_D, ASCII_O, ASCII_C, ASCII_T, ASCII_Y, ASCII_P, ASCII_E, '\0'}; static const char KW_ELEMENT[] = {ASCII_E, ASCII_L, ASCII_E, ASCII_M, ASCII_E, ASCII_N, ASCII_T, '\0'}; static const char KW_EMPTY[] = {ASCII_E, ASCII_M, ASCII_P, ASCII_T, ASCII_Y, '\0'}; static const char KW_ENTITIES[] = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0'}; static const char KW_ENTITY[] = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0'}; static const char KW_FIXED[] = {ASCII_F, ASCII_I, ASCII_X, ASCII_E, ASCII_D, '\0'}; static const char KW_ID[] = {ASCII_I, ASCII_D, '\0'}; static const char KW_IDREF[] = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0'}; static const char KW_IDREFS[] = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0'}; #ifdef XML_DTD static const char KW_IGNORE[] = {ASCII_I, ASCII_G, ASCII_N, ASCII_O, ASCII_R, ASCII_E, '\0'}; #endif static const char KW_IMPLIED[] = {ASCII_I, ASCII_M, ASCII_P, ASCII_L, ASCII_I, ASCII_E, ASCII_D, '\0'}; #ifdef XML_DTD static const char KW_INCLUDE[] = {ASCII_I, ASCII_N, ASCII_C, ASCII_L, ASCII_U, ASCII_D, ASCII_E, '\0'}; #endif static const char KW_NDATA[] = {ASCII_N, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0'}; static const char KW_NMTOKEN[] = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0'}; static const char KW_NMTOKENS[] = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0'}; static const char KW_NOTATION[] = {ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, '\0'}; static const char KW_PCDATA[] = {ASCII_P, ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0'}; static const char KW_PUBLIC[] = {ASCII_P, ASCII_U, ASCII_B, ASCII_L, ASCII_I, ASCII_C, '\0'}; static const char KW_REQUIRED[] = {ASCII_R, ASCII_E, ASCII_Q, ASCII_U, ASCII_I, ASCII_R, ASCII_E, ASCII_D, '\0'}; static const char KW_SYSTEM[] = {ASCII_S, ASCII_Y, ASCII_S, ASCII_T, ASCII_E, ASCII_M, '\0'}; #ifndef MIN_BYTES_PER_CHAR # define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar) #endif #ifdef XML_DTD # define setTopLevel(state) \ ((state)->handler \ = ((state)->documentEntity ? internalSubset : externalSubset1)) #else /* not XML_DTD */ # define setTopLevel(state) ((state)->handler = internalSubset) #endif /* not XML_DTD */ typedef int PTRCALL PROLOG_HANDLER(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc); static PROLOG_HANDLER prolog0, prolog1, prolog2, doctype0, doctype1, doctype2, doctype3, doctype4, doctype5, internalSubset, entity0, entity1, entity2, entity3, entity4, entity5, entity6, entity7, entity8, entity9, entity10, notation0, notation1, notation2, notation3, notation4, attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6, attlist7, attlist8, attlist9, element0, element1, element2, element3, element4, element5, element6, element7, #ifdef XML_DTD externalSubset0, externalSubset1, condSect0, condSect1, condSect2, #endif /* XML_DTD */ declClose, error; static int FASTCALL common(PROLOG_STATE *state, int tok); static int PTRCALL prolog0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: state->handler = prolog1; return XML_ROLE_NONE; case XML_TOK_XML_DECL: state->handler = prolog1; return XML_ROLE_XML_DECL; case XML_TOK_PI: state->handler = prolog1; return XML_ROLE_PI; case XML_TOK_COMMENT: state->handler = prolog1; return XML_ROLE_COMMENT; case XML_TOK_BOM: return XML_ROLE_NONE; case XML_TOK_DECL_OPEN: if (! XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_DOCTYPE)) break; state->handler = doctype0; return XML_ROLE_DOCTYPE_NONE; case XML_TOK_INSTANCE_START: state->handler = error; return XML_ROLE_INSTANCE_START; } return common(state, tok); } static int PTRCALL prolog1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_PI: return XML_ROLE_PI; case XML_TOK_COMMENT: return XML_ROLE_COMMENT; case XML_TOK_BOM: /* This case can never arise. To reach this role function, the * parse must have passed through prolog0 and therefore have had * some form of input, even if only a space. At that point, a * byte order mark is no longer a valid character (though * technically it should be interpreted as a non-breaking space), * so will be rejected by the tokenizing stages. */ return XML_ROLE_NONE; /* LCOV_EXCL_LINE */ case XML_TOK_DECL_OPEN: if (! XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_DOCTYPE)) break; state->handler = doctype0; return XML_ROLE_DOCTYPE_NONE; case XML_TOK_INSTANCE_START: state->handler = error; return XML_ROLE_INSTANCE_START; } return common(state, tok); } static int PTRCALL prolog2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_PI: return XML_ROLE_PI; case XML_TOK_COMMENT: return XML_ROLE_COMMENT; case XML_TOK_INSTANCE_START: state->handler = error; return XML_ROLE_INSTANCE_START; } return common(state, tok); } static int PTRCALL doctype0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_DOCTYPE_NONE; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = doctype1; return XML_ROLE_DOCTYPE_NAME; } return common(state, tok); } static int PTRCALL doctype1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_DOCTYPE_NONE; case XML_TOK_OPEN_BRACKET: state->handler = internalSubset; return XML_ROLE_DOCTYPE_INTERNAL_SUBSET; case XML_TOK_DECL_CLOSE: state->handler = prolog2; return XML_ROLE_DOCTYPE_CLOSE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { state->handler = doctype3; return XML_ROLE_DOCTYPE_NONE; } if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { state->handler = doctype2; return XML_ROLE_DOCTYPE_NONE; } break; } return common(state, tok); } static int PTRCALL doctype2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_DOCTYPE_NONE; case XML_TOK_LITERAL: state->handler = doctype3; return XML_ROLE_DOCTYPE_PUBLIC_ID; } return common(state, tok); } static int PTRCALL doctype3(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_DOCTYPE_NONE; case XML_TOK_LITERAL: state->handler = doctype4; return XML_ROLE_DOCTYPE_SYSTEM_ID; } return common(state, tok); } static int PTRCALL doctype4(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_DOCTYPE_NONE; case XML_TOK_OPEN_BRACKET: state->handler = internalSubset; return XML_ROLE_DOCTYPE_INTERNAL_SUBSET; case XML_TOK_DECL_CLOSE: state->handler = prolog2; return XML_ROLE_DOCTYPE_CLOSE; } return common(state, tok); } static int PTRCALL doctype5(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_DOCTYPE_NONE; case XML_TOK_DECL_CLOSE: state->handler = prolog2; return XML_ROLE_DOCTYPE_CLOSE; } return common(state, tok); } static int PTRCALL internalSubset(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_DECL_OPEN: if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_ENTITY)) { state->handler = entity0; return XML_ROLE_ENTITY_NONE; } if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_ATTLIST)) { state->handler = attlist0; return XML_ROLE_ATTLIST_NONE; } if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_ELEMENT)) { state->handler = element0; return XML_ROLE_ELEMENT_NONE; } if (XmlNameMatchesAscii(enc, ptr + 2 * MIN_BYTES_PER_CHAR(enc), end, KW_NOTATION)) { state->handler = notation0; return XML_ROLE_NOTATION_NONE; } break; case XML_TOK_PI: return XML_ROLE_PI; case XML_TOK_COMMENT: return XML_ROLE_COMMENT; case XML_TOK_PARAM_ENTITY_REF: return XML_ROLE_PARAM_ENTITY_REF; case XML_TOK_CLOSE_BRACKET: state->handler = doctype5; return XML_ROLE_DOCTYPE_NONE; case XML_TOK_NONE: return XML_ROLE_NONE; } return common(state, tok); } #ifdef XML_DTD static int PTRCALL externalSubset0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { state->handler = externalSubset1; if (tok == XML_TOK_XML_DECL) return XML_ROLE_TEXT_DECL; return externalSubset1(state, tok, ptr, end, enc); } static int PTRCALL externalSubset1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_COND_SECT_OPEN: state->handler = condSect0; return XML_ROLE_NONE; case XML_TOK_COND_SECT_CLOSE: if (state->includeLevel == 0) break; state->includeLevel -= 1; return XML_ROLE_NONE; case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_CLOSE_BRACKET: break; case XML_TOK_NONE: if (state->includeLevel) break; return XML_ROLE_NONE; default: return internalSubset(state, tok, ptr, end, enc); } return common(state, tok); } #endif /* XML_DTD */ static int PTRCALL entity0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_PERCENT: state->handler = entity1; return XML_ROLE_ENTITY_NONE; case XML_TOK_NAME: state->handler = entity2; return XML_ROLE_GENERAL_ENTITY_NAME; } return common(state, tok); } static int PTRCALL entity1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_NAME: state->handler = entity7; return XML_ROLE_PARAM_ENTITY_NAME; } return common(state, tok); } static int PTRCALL entity2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { state->handler = entity4; return XML_ROLE_ENTITY_NONE; } if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { state->handler = entity3; return XML_ROLE_ENTITY_NONE; } break; case XML_TOK_LITERAL: state->handler = declClose; state->role_none = XML_ROLE_ENTITY_NONE; return XML_ROLE_ENTITY_VALUE; } return common(state, tok); } static int PTRCALL entity3(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_LITERAL: state->handler = entity4; return XML_ROLE_ENTITY_PUBLIC_ID; } return common(state, tok); } static int PTRCALL entity4(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_LITERAL: state->handler = entity5; return XML_ROLE_ENTITY_SYSTEM_ID; } return common(state, tok); } static int PTRCALL entity5(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_DECL_CLOSE: setTopLevel(state); return XML_ROLE_ENTITY_COMPLETE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_NDATA)) { state->handler = entity6; return XML_ROLE_ENTITY_NONE; } break; } return common(state, tok); } static int PTRCALL entity6(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_NAME: state->handler = declClose; state->role_none = XML_ROLE_ENTITY_NONE; return XML_ROLE_ENTITY_NOTATION_NAME; } return common(state, tok); } static int PTRCALL entity7(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { state->handler = entity9; return XML_ROLE_ENTITY_NONE; } if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { state->handler = entity8; return XML_ROLE_ENTITY_NONE; } break; case XML_TOK_LITERAL: state->handler = declClose; state->role_none = XML_ROLE_ENTITY_NONE; return XML_ROLE_ENTITY_VALUE; } return common(state, tok); } static int PTRCALL entity8(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_LITERAL: state->handler = entity9; return XML_ROLE_ENTITY_PUBLIC_ID; } return common(state, tok); } static int PTRCALL entity9(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_LITERAL: state->handler = entity10; return XML_ROLE_ENTITY_SYSTEM_ID; } return common(state, tok); } static int PTRCALL entity10(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ENTITY_NONE; case XML_TOK_DECL_CLOSE: setTopLevel(state); return XML_ROLE_ENTITY_COMPLETE; } return common(state, tok); } static int PTRCALL notation0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NOTATION_NONE; case XML_TOK_NAME: state->handler = notation1; return XML_ROLE_NOTATION_NAME; } return common(state, tok); } static int PTRCALL notation1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NOTATION_NONE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) { state->handler = notation3; return XML_ROLE_NOTATION_NONE; } if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) { state->handler = notation2; return XML_ROLE_NOTATION_NONE; } break; } return common(state, tok); } static int PTRCALL notation2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NOTATION_NONE; case XML_TOK_LITERAL: state->handler = notation4; return XML_ROLE_NOTATION_PUBLIC_ID; } return common(state, tok); } static int PTRCALL notation3(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NOTATION_NONE; case XML_TOK_LITERAL: state->handler = declClose; state->role_none = XML_ROLE_NOTATION_NONE; return XML_ROLE_NOTATION_SYSTEM_ID; } return common(state, tok); } static int PTRCALL notation4(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NOTATION_NONE; case XML_TOK_LITERAL: state->handler = declClose; state->role_none = XML_ROLE_NOTATION_NONE; return XML_ROLE_NOTATION_SYSTEM_ID; case XML_TOK_DECL_CLOSE: setTopLevel(state); return XML_ROLE_NOTATION_NO_SYSTEM_ID; } return common(state, tok); } static int PTRCALL attlist0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = attlist1; return XML_ROLE_ATTLIST_ELEMENT_NAME; } return common(state, tok); } static int PTRCALL attlist1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_DECL_CLOSE: setTopLevel(state); return XML_ROLE_ATTLIST_NONE; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = attlist2; return XML_ROLE_ATTRIBUTE_NAME; } return common(state, tok); } static int PTRCALL attlist2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_NAME: { static const char *const types[] = { KW_CDATA, KW_ID, KW_IDREF, KW_IDREFS, KW_ENTITY, KW_ENTITIES, KW_NMTOKEN, KW_NMTOKENS, }; int i; for (i = 0; i < (int)(sizeof(types) / sizeof(types[0])); i++) if (XmlNameMatchesAscii(enc, ptr, end, types[i])) { state->handler = attlist8; return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i; } } if (XmlNameMatchesAscii(enc, ptr, end, KW_NOTATION)) { state->handler = attlist5; return XML_ROLE_ATTLIST_NONE; } break; case XML_TOK_OPEN_PAREN: state->handler = attlist3; return XML_ROLE_ATTLIST_NONE; } return common(state, tok); } static int PTRCALL attlist3(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_NMTOKEN: case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = attlist4; return XML_ROLE_ATTRIBUTE_ENUM_VALUE; } return common(state, tok); } static int PTRCALL attlist4(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_CLOSE_PAREN: state->handler = attlist8; return XML_ROLE_ATTLIST_NONE; case XML_TOK_OR: state->handler = attlist3; return XML_ROLE_ATTLIST_NONE; } return common(state, tok); } static int PTRCALL attlist5(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_OPEN_PAREN: state->handler = attlist6; return XML_ROLE_ATTLIST_NONE; } return common(state, tok); } static int PTRCALL attlist6(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_NAME: state->handler = attlist7; return XML_ROLE_ATTRIBUTE_NOTATION_VALUE; } return common(state, tok); } static int PTRCALL attlist7(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_CLOSE_PAREN: state->handler = attlist8; return XML_ROLE_ATTLIST_NONE; case XML_TOK_OR: state->handler = attlist6; return XML_ROLE_ATTLIST_NONE; } return common(state, tok); } /* default value */ static int PTRCALL attlist8(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_POUND_NAME: if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end, KW_IMPLIED)) { state->handler = attlist1; return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE; } if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end, KW_REQUIRED)) { state->handler = attlist1; return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE; } if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end, KW_FIXED)) { state->handler = attlist9; return XML_ROLE_ATTLIST_NONE; } break; case XML_TOK_LITERAL: state->handler = attlist1; return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE; } return common(state, tok); } static int PTRCALL attlist9(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ATTLIST_NONE; case XML_TOK_LITERAL: state->handler = attlist1; return XML_ROLE_FIXED_ATTRIBUTE_VALUE; } return common(state, tok); } static int PTRCALL element0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = element1; return XML_ROLE_ELEMENT_NAME; } return common(state, tok); } static int PTRCALL element1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_EMPTY)) { state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; return XML_ROLE_CONTENT_EMPTY; } if (XmlNameMatchesAscii(enc, ptr, end, KW_ANY)) { state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; return XML_ROLE_CONTENT_ANY; } break; case XML_TOK_OPEN_PAREN: state->handler = element2; state->level = 1; return XML_ROLE_GROUP_OPEN; } return common(state, tok); } static int PTRCALL element2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_POUND_NAME: if (XmlNameMatchesAscii(enc, ptr + MIN_BYTES_PER_CHAR(enc), end, KW_PCDATA)) { state->handler = element3; return XML_ROLE_CONTENT_PCDATA; } break; case XML_TOK_OPEN_PAREN: state->level = 2; state->handler = element6; return XML_ROLE_GROUP_OPEN; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT; case XML_TOK_NAME_QUESTION: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_OPT; case XML_TOK_NAME_ASTERISK: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_REP; case XML_TOK_NAME_PLUS: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_PLUS; } return common(state, tok); } static int PTRCALL element3(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_CLOSE_PAREN: state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; return XML_ROLE_GROUP_CLOSE; case XML_TOK_CLOSE_PAREN_ASTERISK: state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; return XML_ROLE_GROUP_CLOSE_REP; case XML_TOK_OR: state->handler = element4; return XML_ROLE_ELEMENT_NONE; } return common(state, tok); } static int PTRCALL element4(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = element5; return XML_ROLE_CONTENT_ELEMENT; } return common(state, tok); } static int PTRCALL element5(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_CLOSE_PAREN_ASTERISK: state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; return XML_ROLE_GROUP_CLOSE_REP; case XML_TOK_OR: state->handler = element4; return XML_ROLE_ELEMENT_NONE; } return common(state, tok); } static int PTRCALL element6(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_OPEN_PAREN: state->level += 1; return XML_ROLE_GROUP_OPEN; case XML_TOK_NAME: case XML_TOK_PREFIXED_NAME: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT; case XML_TOK_NAME_QUESTION: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_OPT; case XML_TOK_NAME_ASTERISK: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_REP; case XML_TOK_NAME_PLUS: state->handler = element7; return XML_ROLE_CONTENT_ELEMENT_PLUS; } return common(state, tok); } static int PTRCALL element7(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_ELEMENT_NONE; case XML_TOK_CLOSE_PAREN: state->level -= 1; if (state->level == 0) { state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; } return XML_ROLE_GROUP_CLOSE; case XML_TOK_CLOSE_PAREN_ASTERISK: state->level -= 1; if (state->level == 0) { state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; } return XML_ROLE_GROUP_CLOSE_REP; case XML_TOK_CLOSE_PAREN_QUESTION: state->level -= 1; if (state->level == 0) { state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; } return XML_ROLE_GROUP_CLOSE_OPT; case XML_TOK_CLOSE_PAREN_PLUS: state->level -= 1; if (state->level == 0) { state->handler = declClose; state->role_none = XML_ROLE_ELEMENT_NONE; } return XML_ROLE_GROUP_CLOSE_PLUS; case XML_TOK_COMMA: state->handler = element6; return XML_ROLE_GROUP_SEQUENCE; case XML_TOK_OR: state->handler = element6; return XML_ROLE_GROUP_CHOICE; } return common(state, tok); } #ifdef XML_DTD static int PTRCALL condSect0(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_NAME: if (XmlNameMatchesAscii(enc, ptr, end, KW_INCLUDE)) { state->handler = condSect1; return XML_ROLE_NONE; } if (XmlNameMatchesAscii(enc, ptr, end, KW_IGNORE)) { state->handler = condSect2; return XML_ROLE_NONE; } break; } return common(state, tok); } static int PTRCALL condSect1(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_OPEN_BRACKET: state->handler = externalSubset1; state->includeLevel += 1; return XML_ROLE_NONE; } return common(state, tok); } static int PTRCALL condSect2(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return XML_ROLE_NONE; case XML_TOK_OPEN_BRACKET: state->handler = externalSubset1; return XML_ROLE_IGNORE_SECT; } return common(state, tok); } #endif /* XML_DTD */ static int PTRCALL declClose(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); switch (tok) { case XML_TOK_PROLOG_S: return state->role_none; case XML_TOK_DECL_CLOSE: setTopLevel(state); return state->role_none; } return common(state, tok); } /* This function will only be invoked if the internal logic of the * parser has broken down. It is used in two cases: * * 1: When the XML prolog has been finished. At this point the * processor (the parser level above these role handlers) should * switch from prologProcessor to contentProcessor and reinitialise * the handler function. * * 2: When an error has been detected (via common() below). At this * point again the processor should be switched to errorProcessor, * which will never call a handler. * * The result of this is that error() can only be called if the * processor switch failed to happen, which is an internal error and * therefore we shouldn't be able to provoke it simply by using the * library. It is a necessary backstop, however, so we merely exclude * it from the coverage statistics. * * LCOV_EXCL_START */ static int PTRCALL error(PROLOG_STATE *state, int tok, const char *ptr, const char *end, const ENCODING *enc) { UNUSED_P(state); UNUSED_P(tok); UNUSED_P(ptr); UNUSED_P(end); UNUSED_P(enc); return XML_ROLE_NONE; } /* LCOV_EXCL_STOP */ static int FASTCALL common(PROLOG_STATE *state, int tok) { #ifdef XML_DTD if (! state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF) return XML_ROLE_INNER_PARAM_ENTITY_REF; #else UNUSED_P(tok); #endif state->handler = error; return XML_ROLE_ERROR; } void XmlPrologStateInit(PROLOG_STATE *state) { state->handler = prolog0; #ifdef XML_DTD state->documentEntity = 1; state->includeLevel = 0; state->inEntityValue = 0; #endif /* XML_DTD */ } #ifdef XML_DTD void XmlPrologStateInitExternalEntity(PROLOG_STATE *state) { state->handler = externalSubset0; state->documentEntity = 0; state->includeLevel = 0; } #endif /* XML_DTD */ tdom-0.9.5-src/expat/xmltok.h0000644000175000017500000003113614703531020014552 0ustar rolfrolf/* __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2002 Fred L. Drake, Jr. Copyright (c) 2002-2005 Karl Waclawek Copyright (c) 2016-2024 Sebastian Pipping Copyright (c) 2017 Rhodri James Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef XmlTok_INCLUDED #define XmlTok_INCLUDED 1 #ifdef __cplusplus extern "C" { #endif /* The following token may be returned by XmlContentTok */ #define XML_TOK_TRAILING_RSQB \ -5 /* ] or ]] at the end of the scan; might be \ start of illegal ]]> sequence */ /* The following tokens may be returned by both XmlPrologTok and XmlContentTok. */ #define XML_TOK_NONE -4 /* The string to be scanned is empty */ #define XML_TOK_TRAILING_CR \ -3 /* A CR at the end of the scan; \ might be part of CRLF sequence */ #define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */ #define XML_TOK_PARTIAL -1 /* only part of a token */ #define XML_TOK_INVALID 0 /* The following tokens are returned by XmlContentTok; some are also returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok. */ #define XML_TOK_START_TAG_WITH_ATTS 1 #define XML_TOK_START_TAG_NO_ATTS 2 #define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag */ #define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4 #define XML_TOK_END_TAG 5 #define XML_TOK_DATA_CHARS 6 #define XML_TOK_DATA_NEWLINE 7 #define XML_TOK_CDATA_SECT_OPEN 8 #define XML_TOK_ENTITY_REF 9 #define XML_TOK_CHAR_REF 10 /* numeric character reference */ /* The following tokens may be returned by both XmlPrologTok and XmlContentTok. */ #define XML_TOK_PI 11 /* processing instruction */ #define XML_TOK_XML_DECL 12 /* XML decl or text decl */ #define XML_TOK_COMMENT 13 #define XML_TOK_BOM 14 /* Byte order mark */ /* The following tokens are returned only by XmlPrologTok */ #define XML_TOK_PROLOG_S 15 #define XML_TOK_DECL_OPEN 16 /* */ #define XML_TOK_NAME 18 #define XML_TOK_NMTOKEN 19 #define XML_TOK_POUND_NAME 20 /* #name */ #define XML_TOK_OR 21 /* | */ #define XML_TOK_PERCENT 22 #define XML_TOK_OPEN_PAREN 23 #define XML_TOK_CLOSE_PAREN 24 #define XML_TOK_OPEN_BRACKET 25 #define XML_TOK_CLOSE_BRACKET 26 #define XML_TOK_LITERAL 27 #define XML_TOK_PARAM_ENTITY_REF 28 #define XML_TOK_INSTANCE_START 29 /* The following occur only in element type declarations */ #define XML_TOK_NAME_QUESTION 30 /* name? */ #define XML_TOK_NAME_ASTERISK 31 /* name* */ #define XML_TOK_NAME_PLUS 32 /* name+ */ #define XML_TOK_COND_SECT_OPEN 33 /* */ #define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */ #define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */ #define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */ #define XML_TOK_COMMA 38 /* The following token is returned only by XmlAttributeValueTok */ #define XML_TOK_ATTRIBUTE_VALUE_S 39 /* The following token is returned only by XmlCdataSectionTok */ #define XML_TOK_CDATA_SECT_CLOSE 40 /* With namespace processing this is returned by XmlPrologTok for a name with a colon. */ #define XML_TOK_PREFIXED_NAME 41 #ifdef XML_DTD # define XML_TOK_IGNORE_SECT 42 #endif /* XML_DTD */ #ifdef XML_DTD # define XML_N_STATES 4 #else /* not XML_DTD */ # define XML_N_STATES 3 #endif /* not XML_DTD */ #define XML_PROLOG_STATE 0 #define XML_CONTENT_STATE 1 #define XML_CDATA_SECTION_STATE 2 #ifdef XML_DTD # define XML_IGNORE_SECTION_STATE 3 #endif /* XML_DTD */ #define XML_N_LITERAL_TYPES 2 #define XML_ATTRIBUTE_VALUE_LITERAL 0 #define XML_ENTITY_VALUE_LITERAL 1 /* The size of the buffer passed to XmlUtf8Encode must be at least this. */ #define XML_UTF8_ENCODE_MAX 4 /* The size of the buffer passed to XmlUtf16Encode must be at least this. */ #define XML_UTF16_ENCODE_MAX 2 typedef struct position { /* first line and first column are 0 not 1 */ XML_Size lineNumber; XML_Size columnNumber; } POSITION; typedef struct { const char *name; const char *valuePtr; const char *valueEnd; char normalized; } ATTRIBUTE; struct encoding; typedef struct encoding ENCODING; typedef int(PTRCALL *SCANNER)(const ENCODING *, const char *, const char *, const char **); enum XML_Convert_Result { XML_CONVERT_COMPLETED = 0, XML_CONVERT_INPUT_INCOMPLETE = 1, XML_CONVERT_OUTPUT_EXHAUSTED = 2 /* and therefore potentially input remaining as well */ }; struct encoding { SCANNER scanners[XML_N_STATES]; SCANNER literalScanners[XML_N_LITERAL_TYPES]; int(PTRCALL *nameMatchesAscii)(const ENCODING *, const char *, const char *, const char *); int(PTRFASTCALL *nameLength)(const ENCODING *, const char *); const char *(PTRFASTCALL *skipS)(const ENCODING *, const char *); int(PTRCALL *getAtts)(const ENCODING *enc, const char *ptr, int attsMax, ATTRIBUTE *atts); int(PTRFASTCALL *charRefNumber)(const ENCODING *enc, const char *ptr); int(PTRCALL *predefinedEntityName)(const ENCODING *, const char *, const char *); void(PTRCALL *updatePosition)(const ENCODING *, const char *ptr, const char *end, POSITION *); int(PTRCALL *isPublicId)(const ENCODING *enc, const char *ptr, const char *end, const char **badPtr); enum XML_Convert_Result(PTRCALL *utf8Convert)(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim); enum XML_Convert_Result(PTRCALL *utf16Convert)(const ENCODING *enc, const char **fromP, const char *fromLim, unsigned short **toP, const unsigned short *toLim); int minBytesPerChar; char isUtf8; char isUtf16; }; /* Scan the string starting at ptr until the end of the next complete token, but do not scan past eptr. Return an integer giving the type of token. Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set. Return XML_TOK_PARTIAL when the string does not contain a complete token; nextTokPtr will not be set. Return XML_TOK_INVALID when the string does not start a valid token; nextTokPtr will be set to point to the character which made the token invalid. Otherwise the string starts with a valid token; nextTokPtr will be set to point to the character following the end of that token. Each data character counts as a single token, but adjacent data characters may be returned together. Similarly for characters in the prolog outside literals, comments and processing instructions. */ #define XmlTok(enc, state, ptr, end, nextTokPtr) \ (((enc)->scanners[state])(enc, ptr, end, nextTokPtr)) #define XmlPrologTok(enc, ptr, end, nextTokPtr) \ XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr) #define XmlContentTok(enc, ptr, end, nextTokPtr) \ XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr) #define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \ XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr) #ifdef XML_DTD # define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \ XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr) #endif /* XML_DTD */ /* This is used for performing a 2nd-level tokenization on the content of a literal that has already been returned by XmlTok. */ #define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \ (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr)) #define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \ XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr) #define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \ XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr) #define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \ (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2)) #define XmlNameLength(enc, ptr) (((enc)->nameLength)(enc, ptr)) #define XmlSkipS(enc, ptr) (((enc)->skipS)(enc, ptr)) #define XmlGetAttributes(enc, ptr, attsMax, atts) \ (((enc)->getAtts)(enc, ptr, attsMax, atts)) #define XmlCharRefNumber(enc, ptr) (((enc)->charRefNumber)(enc, ptr)) #define XmlPredefinedEntityName(enc, ptr, end) \ (((enc)->predefinedEntityName)(enc, ptr, end)) #define XmlUpdatePosition(enc, ptr, end, pos) \ (((enc)->updatePosition)(enc, ptr, end, pos)) #define XmlIsPublicId(enc, ptr, end, badPtr) \ (((enc)->isPublicId)(enc, ptr, end, badPtr)) #define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \ (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim)) #define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \ (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim)) typedef struct { ENCODING initEnc; const ENCODING **encPtr; } INIT_ENCODING; int XmlParseXmlDecl(int isGeneralTextEntity, const ENCODING *enc, const char *ptr, const char *end, const char **badPtr, const char **versionPtr, const char **versionEndPtr, const char **encodingNamePtr, const ENCODING **namedEncodingPtr, int *standalonePtr); int XmlInitEncoding(INIT_ENCODING *p, const ENCODING **encPtr, const char *name); const ENCODING *XmlGetUtf8InternalEncoding(void); const ENCODING *XmlGetUtf16InternalEncoding(void); int FASTCALL XmlUtf8Encode(int charNumber, char *buf); int FASTCALL XmlUtf16Encode(int charNumber, unsigned short *buf); int XmlSizeOfUnknownEncoding(void); typedef int(XMLCALL *CONVERTER)(void *userData, const char *p); ENCODING *XmlInitUnknownEncoding(void *mem, int *table, CONVERTER convert, void *userData); int XmlParseXmlDeclNS(int isGeneralTextEntity, const ENCODING *enc, const char *ptr, const char *end, const char **badPtr, const char **versionPtr, const char **versionEndPtr, const char **encodingNamePtr, const ENCODING **namedEncodingPtr, int *standalonePtr); int XmlInitEncodingNS(INIT_ENCODING *p, const ENCODING **encPtr, const char *name); const ENCODING *XmlGetUtf8InternalEncodingNS(void); const ENCODING *XmlGetUtf16InternalEncodingNS(void); ENCODING *XmlInitUnknownEncodingNS(void *mem, int *table, CONVERTER convert, void *userData); #ifdef __cplusplus } #endif #endif /* not XmlTok_INCLUDED */ tdom-0.9.5-src/expat/expat.h0000644000175000017500000012604614703531020014362 0ustar rolfrolf/* __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2000-2005 Fred L. Drake, Jr. Copyright (c) 2001-2002 Greg Stein Copyright (c) 2002-2016 Karl Waclawek Copyright (c) 2016-2024 Sebastian Pipping Copyright (c) 2016 Cristian Rodríguez Copyright (c) 2016 Thomas Beutlich Copyright (c) 2017 Rhodri James Copyright (c) 2022 Thijs Schreijer Copyright (c) 2023 Hanno Böck Copyright (c) 2023 Sony Corporation / Snild Dolkow Copyright (c) 2024 Taichi Haradaguchi <20001722@ymail.ne.jp> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef Expat_INCLUDED #define Expat_INCLUDED 1 #include #include "expat_external.h" #ifdef __cplusplus extern "C" { #endif struct XML_ParserStruct; typedef struct XML_ParserStruct *XML_Parser; typedef unsigned char XML_Bool; #define XML_TRUE ((XML_Bool)1) #define XML_FALSE ((XML_Bool)0) /* The XML_Status enum gives the possible return values for several API functions. The preprocessor #defines are included so this stanza can be added to code that still needs to support older versions of Expat 1.95.x: #ifndef XML_STATUS_OK #define XML_STATUS_OK 1 #define XML_STATUS_ERROR 0 #endif Otherwise, the #define hackery is quite ugly and would have been dropped. */ enum XML_Status { XML_STATUS_ERROR = 0, #define XML_STATUS_ERROR XML_STATUS_ERROR XML_STATUS_OK = 1, #define XML_STATUS_OK XML_STATUS_OK XML_STATUS_SUSPENDED = 2 #define XML_STATUS_SUSPENDED XML_STATUS_SUSPENDED }; enum XML_Error { XML_ERROR_NONE, XML_ERROR_NO_MEMORY, XML_ERROR_SYNTAX, XML_ERROR_NO_ELEMENTS, XML_ERROR_INVALID_TOKEN, XML_ERROR_UNCLOSED_TOKEN, XML_ERROR_PARTIAL_CHAR, XML_ERROR_TAG_MISMATCH, XML_ERROR_DUPLICATE_ATTRIBUTE, XML_ERROR_JUNK_AFTER_DOC_ELEMENT, XML_ERROR_PARAM_ENTITY_REF, XML_ERROR_UNDEFINED_ENTITY, XML_ERROR_RECURSIVE_ENTITY_REF, XML_ERROR_ASYNC_ENTITY, XML_ERROR_BAD_CHAR_REF, XML_ERROR_BINARY_ENTITY_REF, XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, XML_ERROR_MISPLACED_XML_PI, XML_ERROR_UNKNOWN_ENCODING, XML_ERROR_INCORRECT_ENCODING, XML_ERROR_UNCLOSED_CDATA_SECTION, XML_ERROR_EXTERNAL_ENTITY_HANDLING, XML_ERROR_NOT_STANDALONE, XML_ERROR_UNEXPECTED_STATE, XML_ERROR_ENTITY_DECLARED_IN_PE, XML_ERROR_FEATURE_REQUIRES_XML_DTD, XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING, /* Added in 1.95.7. */ XML_ERROR_UNBOUND_PREFIX, /* Added in 1.95.8. */ XML_ERROR_UNDECLARING_PREFIX, XML_ERROR_INCOMPLETE_PE, XML_ERROR_XML_DECL, XML_ERROR_TEXT_DECL, XML_ERROR_PUBLICID, XML_ERROR_SUSPENDED, XML_ERROR_NOT_SUSPENDED, XML_ERROR_ABORTED, XML_ERROR_FINISHED, XML_ERROR_SUSPEND_PE, /* Added in 2.0. */ XML_ERROR_RESERVED_PREFIX_XML, XML_ERROR_RESERVED_PREFIX_XMLNS, XML_ERROR_RESERVED_NAMESPACE_URI, /* Added in 2.2.1. */ XML_ERROR_INVALID_ARGUMENT, /* Added in 2.3.0. */ XML_ERROR_NO_BUFFER, /* Added in 2.4.0. */ XML_ERROR_AMPLIFICATION_LIMIT_BREACH }; enum XML_Content_Type { XML_CTYPE_EMPTY = 1, XML_CTYPE_ANY, XML_CTYPE_MIXED, XML_CTYPE_NAME, XML_CTYPE_CHOICE, XML_CTYPE_SEQ }; enum XML_Content_Quant { XML_CQUANT_NONE, XML_CQUANT_OPT, XML_CQUANT_REP, XML_CQUANT_PLUS }; /* If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be XML_CQUANT_NONE, and the other fields will be zero or NULL. If type == XML_CTYPE_MIXED, then quant will be NONE or REP and numchildren will contain number of elements that may be mixed in and children point to an array of XML_Content cells that will be all of XML_CTYPE_NAME type with no quantification. If type == XML_CTYPE_NAME, then the name points to the name, and the numchildren field will be zero and children will be NULL. The quant fields indicates any quantifiers placed on the name. CHOICE and SEQ will have name NULL, the number of children in numchildren and children will point, recursively, to an array of XML_Content cells. The EMPTY, ANY, and MIXED types will only occur at top level. */ typedef struct XML_cp XML_Content; struct XML_cp { enum XML_Content_Type type; enum XML_Content_Quant quant; XML_Char *name; unsigned int numchildren; XML_Content *children; }; /* This is called for an element declaration. See above for description of the model argument. It's the user code's responsibility to free model when finished with it. See XML_FreeContentModel. There is no need to free the model from the handler, it can be kept around and freed at a later stage. */ typedef void(XMLCALL *XML_ElementDeclHandler)(void *userData, const XML_Char *name, XML_Content *model); XMLPARSEAPI(void) XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl); /* The Attlist declaration handler is called for *each* attribute. So a single Attlist declaration with multiple attributes declared will generate multiple calls to this handler. The "default" parameter may be NULL in the case of the "#IMPLIED" or "#REQUIRED" keyword. The "isrequired" parameter will be true and the default value will be NULL in the case of "#REQUIRED". If "isrequired" is true and default is non-NULL, then this is a "#FIXED" default. */ typedef void(XMLCALL *XML_AttlistDeclHandler)( void *userData, const XML_Char *elname, const XML_Char *attname, const XML_Char *att_type, const XML_Char *dflt, int isrequired); XMLPARSEAPI(void) XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl); /* The XML declaration handler is called for *both* XML declarations and text declarations. The way to distinguish is that the version parameter will be NULL for text declarations. The encoding parameter may be NULL for XML declarations. The standalone parameter will be -1, 0, or 1 indicating respectively that there was no standalone parameter in the declaration, that it was given as no, or that it was given as yes. */ typedef void(XMLCALL *XML_XmlDeclHandler)(void *userData, const XML_Char *version, const XML_Char *encoding, int standalone); XMLPARSEAPI(void) XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler xmldecl); typedef struct { void *(*malloc_fcn)(size_t size); void *(*realloc_fcn)(void *ptr, size_t size); void (*free_fcn)(void *ptr); } XML_Memory_Handling_Suite; /* Constructs a new parser; encoding is the encoding specified by the external protocol or NULL if there is none specified. */ XMLPARSEAPI(XML_Parser) XML_ParserCreate(const XML_Char *encoding); /* Constructs a new parser and namespace processor. Element type names and attribute names that belong to a namespace will be expanded; unprefixed attribute names are never expanded; unprefixed element type names are expanded only if there is a default namespace. The expanded name is the concatenation of the namespace URI, the namespace separator character, and the local part of the name. If the namespace separator is '\0' then the namespace URI and the local part will be concatenated without any separator. It is a programming error to use the separator '\0' with namespace triplets (see XML_SetReturnNSTriplet). If a namespace separator is chosen that can be part of a URI or part of an XML name, splitting an expanded name back into its 1, 2 or 3 original parts on application level in the element handler may end up vulnerable, so these are advised against; sane choices for a namespace separator are e.g. '\n' (line feed) and '|' (pipe). Note that Expat does not validate namespace URIs (beyond encoding) against RFC 3986 today (and is not required to do so with regard to the XML 1.0 namespaces specification) but it may start doing that in future releases. Before that, an application using Expat must be ready to receive namespace URIs containing non-URI characters. */ XMLPARSEAPI(XML_Parser) XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator); /* Constructs a new parser using the memory management suite referred to by memsuite. If memsuite is NULL, then use the standard library memory suite. If namespaceSeparator is non-NULL it creates a parser with namespace processing as described above. The character pointed at will serve as the namespace separator. All further memory operations used for the created parser will come from the given suite. */ XMLPARSEAPI(XML_Parser) XML_ParserCreate_MM(const XML_Char *encoding, const XML_Memory_Handling_Suite *memsuite, const XML_Char *namespaceSeparator); /* Prepare a parser object to be reused. This is particularly valuable when memory allocation overhead is disproportionately high, such as when a large number of small documnents need to be parsed. All handlers are cleared from the parser, except for the unknownEncodingHandler. The parser's external state is re-initialized except for the values of ns and ns_triplets. Added in Expat 1.95.3. */ XMLPARSEAPI(XML_Bool) XML_ParserReset(XML_Parser parser, const XML_Char *encoding); /* atts is array of name/value pairs, terminated by 0; names and values are 0 terminated. */ typedef void(XMLCALL *XML_StartElementHandler)(void *userData, const XML_Char *name, const XML_Char **atts); typedef void(XMLCALL *XML_EndElementHandler)(void *userData, const XML_Char *name); /* s is not 0 terminated. */ typedef void(XMLCALL *XML_CharacterDataHandler)(void *userData, const XML_Char *s, int len); /* target and data are 0 terminated */ typedef void(XMLCALL *XML_ProcessingInstructionHandler)(void *userData, const XML_Char *target, const XML_Char *data); /* data is 0 terminated */ typedef void(XMLCALL *XML_CommentHandler)(void *userData, const XML_Char *data); typedef void(XMLCALL *XML_StartCdataSectionHandler)(void *userData); typedef void(XMLCALL *XML_EndCdataSectionHandler)(void *userData); /* This is called for any characters in the XML document for which there is no applicable handler. This includes both characters that are part of markup which is of a kind that is not reported (comments, markup declarations), or characters that are part of a construct which could be reported but for which no handler has been supplied. The characters are passed exactly as they were in the XML document except that they will be encoded in UTF-8 or UTF-16. Line boundaries are not normalized. Note that a byte order mark character is not passed to the default handler. There are no guarantees about how characters are divided between calls to the default handler: for example, a comment might be split between multiple calls. */ typedef void(XMLCALL *XML_DefaultHandler)(void *userData, const XML_Char *s, int len); /* This is called for the start of the DOCTYPE declaration, before any DTD or internal subset is parsed. */ typedef void(XMLCALL *XML_StartDoctypeDeclHandler)(void *userData, const XML_Char *doctypeName, const XML_Char *sysid, const XML_Char *pubid, int has_internal_subset); /* This is called for the end of the DOCTYPE declaration when the closing > is encountered, but after processing any external subset. */ typedef void(XMLCALL *XML_EndDoctypeDeclHandler)(void *userData); /* This is called for entity declarations. The is_parameter_entity argument will be non-zero if the entity is a parameter entity, zero otherwise. For internal entities (), value will be non-NULL and systemId, publicID, and notationName will be NULL. The value string is NOT null-terminated; the length is provided in the value_length argument. Since it is legal to have zero-length values, do not use this argument to test for internal entities. For external entities, value will be NULL and systemId will be non-NULL. The publicId argument will be NULL unless a public identifier was provided. The notationName argument will have a non-NULL value only for unparsed entity declarations. Note that is_parameter_entity can't be changed to XML_Bool, since that would break binary compatibility. */ typedef void(XMLCALL *XML_EntityDeclHandler)( void *userData, const XML_Char *entityName, int is_parameter_entity, const XML_Char *value, int value_length, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName); XMLPARSEAPI(void) XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler); /* OBSOLETE -- OBSOLETE -- OBSOLETE This handler has been superseded by the EntityDeclHandler above. It is provided here for backward compatibility. This is called for a declaration of an unparsed (NDATA) entity. The base argument is whatever was set by XML_SetBase. The entityName, systemId and notationName arguments will never be NULL. The other arguments may be. */ typedef void(XMLCALL *XML_UnparsedEntityDeclHandler)( void *userData, const XML_Char *entityName, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName); /* This is called for a declaration of notation. The base argument is whatever was set by XML_SetBase. The notationName will never be NULL. The other arguments can be. */ typedef void(XMLCALL *XML_NotationDeclHandler)(void *userData, const XML_Char *notationName, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId); /* When namespace processing is enabled, these are called once for each namespace declaration. The call to the start and end element handlers occur between the calls to the start and end namespace declaration handlers. For an xmlns attribute, prefix will be NULL. For an xmlns="" attribute, uri will be NULL. */ typedef void(XMLCALL *XML_StartNamespaceDeclHandler)(void *userData, const XML_Char *prefix, const XML_Char *uri); typedef void(XMLCALL *XML_EndNamespaceDeclHandler)(void *userData, const XML_Char *prefix); /* This is called if the document is not standalone, that is, it has an external subset or a reference to a parameter entity, but does not have standalone="yes". If this handler returns XML_STATUS_ERROR, then processing will not continue, and the parser will return a XML_ERROR_NOT_STANDALONE error. If parameter entity parsing is enabled, then in addition to the conditions above this handler will only be called if the referenced entity was actually read. */ typedef int(XMLCALL *XML_NotStandaloneHandler)(void *userData); /* This is called for a reference to an external parsed general entity. The referenced entity is not automatically parsed. The application can parse it immediately or later using XML_ExternalEntityParserCreate. The parser argument is the parser parsing the entity containing the reference; it can be passed as the parser argument to XML_ExternalEntityParserCreate. The systemId argument is the system identifier as specified in the entity declaration; it will not be NULL. The base argument is the system identifier that should be used as the base for resolving systemId if systemId was relative; this is set by XML_SetBase; it may be NULL. The publicId argument is the public identifier as specified in the entity declaration, or NULL if none was specified; the whitespace in the public identifier will have been normalized as required by the XML spec. The context argument specifies the parsing context in the format expected by the context argument to XML_ExternalEntityParserCreate; context is valid only until the handler returns, so if the referenced entity is to be parsed later, it must be copied. context is NULL only when the entity is a parameter entity. The handler should return XML_STATUS_ERROR if processing should not continue because of a fatal error in the handling of the external entity. In this case the calling parser will return an XML_ERROR_EXTERNAL_ENTITY_HANDLING error. Note that unlike other handlers the first argument is the parser, not userData. */ typedef int(XMLCALL *XML_ExternalEntityRefHandler)(XML_Parser parser, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId); /* This is called in two situations: 1) An entity reference is encountered for which no declaration has been read *and* this is not an error. 2) An internal entity reference is read, but not expanded, because XML_SetDefaultHandler has been called. Note: skipped parameter entities in declarations and skipped general entities in attribute values cannot be reported, because the event would be out of sync with the reporting of the declarations or attribute values */ typedef void(XMLCALL *XML_SkippedEntityHandler)(void *userData, const XML_Char *entityName, int is_parameter_entity); /* This structure is filled in by the XML_UnknownEncodingHandler to provide information to the parser about encodings that are unknown to the parser. The map[b] member gives information about byte sequences whose first byte is b. If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar value c. If map[b] is -1, then the byte sequence is malformed. If map[b] is -n, where n >= 2, then b is the first byte of an n-byte sequence that encodes a single Unicode scalar value. The data member will be passed as the first argument to the convert function. The convert function is used to convert multibyte sequences; s will point to a n-byte sequence where map[(unsigned char)*s] == -n. The convert function must return the Unicode scalar value represented by this byte sequence or -1 if the byte sequence is malformed. The convert function may be NULL if the encoding is a single-byte encoding, that is if map[b] >= -1 for all bytes b. When the parser is finished with the encoding, then if release is not NULL, it will call release passing it the data member; once release has been called, the convert function will not be called again. Expat places certain restrictions on the encodings that are supported using this mechanism. 1. Every ASCII character that can appear in a well-formed XML document, other than the characters $@\^`{}~ must be represented by a single byte, and that byte must be the same byte that represents that character in ASCII. 2. No character may require more than 4 bytes to encode. 3. All characters encoded must have Unicode scalar values <= 0xFFFF, (i.e., characters that would be encoded by surrogates in UTF-16 are not allowed). Note that this restriction doesn't apply to the built-in support for UTF-8 and UTF-16. 4. No Unicode character may be encoded by more than one distinct sequence of bytes. */ typedef struct { int map[256]; void *data; int(XMLCALL *convert)(void *data, const char *s); void(XMLCALL *release)(void *data); } XML_Encoding; /* This is called for an encoding that is unknown to the parser. The encodingHandlerData argument is that which was passed as the second argument to XML_SetUnknownEncodingHandler. The name argument gives the name of the encoding as specified in the encoding declaration. If the callback can provide information about the encoding, it must fill in the XML_Encoding structure, and return XML_STATUS_OK. Otherwise it must return XML_STATUS_ERROR. If info does not describe a suitable encoding, then the parser will return an XML_ERROR_UNKNOWN_ENCODING error. */ typedef int(XMLCALL *XML_UnknownEncodingHandler)(void *encodingHandlerData, const XML_Char *name, XML_Encoding *info); XMLPARSEAPI(void) XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end); XMLPARSEAPI(void) XML_SetStartElementHandler(XML_Parser parser, XML_StartElementHandler handler); XMLPARSEAPI(void) XML_SetEndElementHandler(XML_Parser parser, XML_EndElementHandler handler); XMLPARSEAPI(void) XML_SetCharacterDataHandler(XML_Parser parser, XML_CharacterDataHandler handler); XMLPARSEAPI(void) XML_SetProcessingInstructionHandler(XML_Parser parser, XML_ProcessingInstructionHandler handler); XMLPARSEAPI(void) XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler); XMLPARSEAPI(void) XML_SetCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start, XML_EndCdataSectionHandler end); XMLPARSEAPI(void) XML_SetStartCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start); XMLPARSEAPI(void) XML_SetEndCdataSectionHandler(XML_Parser parser, XML_EndCdataSectionHandler end); /* This sets the default handler and also inhibits expansion of internal entities. These entity references will be passed to the default handler, or to the skipped entity handler, if one is set. */ XMLPARSEAPI(void) XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler); /* This sets the default handler but does not inhibit expansion of internal entities. The entity reference will not be passed to the default handler. */ XMLPARSEAPI(void) XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler); XMLPARSEAPI(void) XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start, XML_EndDoctypeDeclHandler end); XMLPARSEAPI(void) XML_SetStartDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start); XMLPARSEAPI(void) XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end); XMLPARSEAPI(void) XML_SetUnparsedEntityDeclHandler(XML_Parser parser, XML_UnparsedEntityDeclHandler handler); XMLPARSEAPI(void) XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler); XMLPARSEAPI(void) XML_SetNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start, XML_EndNamespaceDeclHandler end); XMLPARSEAPI(void) XML_SetStartNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start); XMLPARSEAPI(void) XML_SetEndNamespaceDeclHandler(XML_Parser parser, XML_EndNamespaceDeclHandler end); XMLPARSEAPI(void) XML_SetNotStandaloneHandler(XML_Parser parser, XML_NotStandaloneHandler handler); XMLPARSEAPI(void) XML_SetExternalEntityRefHandler(XML_Parser parser, XML_ExternalEntityRefHandler handler); /* If a non-NULL value for arg is specified here, then it will be passed as the first argument to the external entity ref handler instead of the parser object. */ XMLPARSEAPI(void) XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg); XMLPARSEAPI(void) XML_SetSkippedEntityHandler(XML_Parser parser, XML_SkippedEntityHandler handler); XMLPARSEAPI(void) XML_SetUnknownEncodingHandler(XML_Parser parser, XML_UnknownEncodingHandler handler, void *encodingHandlerData); /* This can be called within a handler for a start element, end element, processing instruction or character data. It causes the corresponding markup to be passed to the default handler. */ XMLPARSEAPI(void) XML_DefaultCurrent(XML_Parser parser); /* If do_nst is non-zero, and namespace processing is in effect, and a name has a prefix (i.e. an explicit namespace qualifier) then that name is returned as a triplet in a single string separated by the separator character specified when the parser was created: URI + sep + local_name + sep + prefix. If do_nst is zero, then namespace information is returned in the default manner (URI + sep + local_name) whether or not the name has a prefix. Note: Calling XML_SetReturnNSTriplet after XML_Parse or XML_ParseBuffer has no effect. */ XMLPARSEAPI(void) XML_SetReturnNSTriplet(XML_Parser parser, int do_nst); /* This value is passed as the userData argument to callbacks. */ XMLPARSEAPI(void) XML_SetUserData(XML_Parser parser, void *userData); /* Returns the last value set by XML_SetUserData or NULL. */ #define XML_GetUserData(parser) (*(void **)(parser)) /* This is equivalent to supplying an encoding argument to XML_ParserCreate. On success XML_SetEncoding returns non-zero, zero otherwise. Note: Calling XML_SetEncoding after XML_Parse or XML_ParseBuffer has no effect and returns XML_STATUS_ERROR. */ XMLPARSEAPI(enum XML_Status) XML_SetEncoding(XML_Parser parser, const XML_Char *encoding); /* If this function is called, then the parser will be passed as the first argument to callbacks instead of userData. The userData will still be accessible using XML_GetUserData. */ XMLPARSEAPI(void) XML_UseParserAsHandlerArg(XML_Parser parser); /* If useDTD == XML_TRUE is passed to this function, then the parser will assume that there is an external subset, even if none is specified in the document. In such a case the parser will call the externalEntityRefHandler with a value of NULL for the systemId argument (the publicId and context arguments will be NULL as well). Note: For the purpose of checking WFC: Entity Declared, passing useDTD == XML_TRUE will make the parser behave as if the document had a DTD with an external subset. Note: If this function is called, then this must be done before the first call to XML_Parse or XML_ParseBuffer, since it will have no effect after that. Returns XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING. Note: If the document does not have a DOCTYPE declaration at all, then startDoctypeDeclHandler and endDoctypeDeclHandler will not be called, despite an external subset being parsed. Note: If XML_DTD is not defined when Expat is compiled, returns XML_ERROR_FEATURE_REQUIRES_XML_DTD. Note: If parser == NULL, returns XML_ERROR_INVALID_ARGUMENT. */ XMLPARSEAPI(enum XML_Error) XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD); /* Sets the base to be used for resolving relative URIs in system identifiers in declarations. Resolving relative identifiers is left to the application: this value will be passed through as the base argument to the XML_ExternalEntityRefHandler, XML_NotationDeclHandler and XML_UnparsedEntityDeclHandler. The base argument will be copied. Returns XML_STATUS_ERROR if out of memory, XML_STATUS_OK otherwise. */ XMLPARSEAPI(enum XML_Status) XML_SetBase(XML_Parser parser, const XML_Char *base); XMLPARSEAPI(const XML_Char *) XML_GetBase(XML_Parser parser); /* Returns the number of the attribute/value pairs passed in last call to the XML_StartElementHandler that were specified in the start-tag rather than defaulted. Each attribute/value pair counts as 2; thus this corresponds to an index into the atts array passed to the XML_StartElementHandler. Returns -1 if parser == NULL. */ XMLPARSEAPI(int) XML_GetSpecifiedAttributeCount(XML_Parser parser); /* Returns the index of the ID attribute passed in the last call to XML_StartElementHandler, or -1 if there is no ID attribute or parser == NULL. Each attribute/value pair counts as 2; thus this corresponds to an index into the atts array passed to the XML_StartElementHandler. */ XMLPARSEAPI(int) XML_GetIdAttributeIndex(XML_Parser parser); #ifdef XML_ATTR_INFO /* Source file byte offsets for the start and end of attribute names and values. The value indices are exclusive of surrounding quotes; thus in a UTF-8 source file an attribute value of "blah" will yield: info->valueEnd - info->valueStart = 4 bytes. */ typedef struct { XML_Index nameStart; /* Offset to beginning of the attribute name. */ XML_Index nameEnd; /* Offset after the attribute name's last byte. */ XML_Index valueStart; /* Offset to beginning of the attribute value. */ XML_Index valueEnd; /* Offset after the attribute value's last byte. */ } XML_AttrInfo; /* Returns an array of XML_AttrInfo structures for the attribute/value pairs passed in last call to the XML_StartElementHandler that were specified in the start-tag rather than defaulted. Each attribute/value pair counts as 1; thus the number of entries in the array is XML_GetSpecifiedAttributeCount(parser) / 2. */ XMLPARSEAPI(const XML_AttrInfo *) XML_GetAttributeInfo(XML_Parser parser); #endif /* Parses some input. Returns XML_STATUS_ERROR if a fatal error is detected. The last call to XML_Parse must have isFinal true; len may be zero for this call (or any other). Though the return values for these functions has always been described as a Boolean value, the implementation, at least for the 1.95.x series, has always returned exactly one of the XML_Status values. */ XMLPARSEAPI(enum XML_Status) XML_Parse(XML_Parser parser, const char *s, int len, int isFinal); XMLPARSEAPI(void *) XML_GetBuffer(XML_Parser parser, int len); XMLPARSEAPI(enum XML_Status) XML_ParseBuffer(XML_Parser parser, int len, int isFinal); /* Stops parsing, causing XML_Parse() or XML_ParseBuffer() to return. Must be called from within a call-back handler, except when aborting (resumable = 0) an already suspended parser. Some call-backs may still follow because they would otherwise get lost. Examples: - endElementHandler() for empty elements when stopped in startElementHandler(), - endNameSpaceDeclHandler() when stopped in endElementHandler(), and possibly others. Can be called from most handlers, including DTD related call-backs, except when parsing an external parameter entity and resumable != 0. Returns XML_STATUS_OK when successful, XML_STATUS_ERROR otherwise. Possible error codes: - XML_ERROR_SUSPENDED: when suspending an already suspended parser. - XML_ERROR_FINISHED: when the parser has already finished. - XML_ERROR_SUSPEND_PE: when suspending while parsing an external PE. When resumable != 0 (true) then parsing is suspended, that is, XML_Parse() and XML_ParseBuffer() return XML_STATUS_SUSPENDED. Otherwise, parsing is aborted, that is, XML_Parse() and XML_ParseBuffer() return XML_STATUS_ERROR with error code XML_ERROR_ABORTED. *Note*: This will be applied to the current parser instance only, that is, if there is a parent parser then it will continue parsing when the externalEntityRefHandler() returns. It is up to the implementation of the externalEntityRefHandler() to call XML_StopParser() on the parent parser (recursively), if one wants to stop parsing altogether. When suspended, parsing can be resumed by calling XML_ResumeParser(). */ XMLPARSEAPI(enum XML_Status) XML_StopParser(XML_Parser parser, XML_Bool resumable); /* Resumes parsing after it has been suspended with XML_StopParser(). Must not be called from within a handler call-back. Returns same status codes as XML_Parse() or XML_ParseBuffer(). Additional error code XML_ERROR_NOT_SUSPENDED possible. *Note*: This must be called on the most deeply nested child parser instance first, and on its parent parser only after the child parser has finished, to be applied recursively until the document entity's parser is restarted. That is, the parent parser will not resume by itself and it is up to the application to call XML_ResumeParser() on it at the appropriate moment. */ XMLPARSEAPI(enum XML_Status) XML_ResumeParser(XML_Parser parser); enum XML_Parsing { XML_INITIALIZED, XML_PARSING, XML_FINISHED, XML_SUSPENDED }; typedef struct { enum XML_Parsing parsing; XML_Bool finalBuffer; } XML_ParsingStatus; /* Returns status of parser with respect to being initialized, parsing, finished, or suspended and processing the final buffer. XXX XML_Parse() and XML_ParseBuffer() should return XML_ParsingStatus, XXX with XML_FINISHED_OK or XML_FINISHED_ERROR replacing XML_FINISHED */ XMLPARSEAPI(void) XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status); /* Creates an XML_Parser object that can parse an external general entity; context is a '\0'-terminated string specifying the parse context; encoding is a '\0'-terminated string giving the name of the externally specified encoding, or NULL if there is no externally specified encoding. The context string consists of a sequence of tokens separated by formfeeds (\f); a token consisting of a name specifies that the general entity of the name is open; a token of the form prefix=uri specifies the namespace for a particular prefix; a token of the form =uri specifies the default namespace. This can be called at any point after the first call to an ExternalEntityRefHandler so longer as the parser has not yet been freed. The new parser is completely independent and may safely be used in a separate thread. The handlers and userData are initialized from the parser argument. Returns NULL if out of memory. Otherwise returns a new XML_Parser object. */ XMLPARSEAPI(XML_Parser) XML_ExternalEntityParserCreate(XML_Parser parser, const XML_Char *context, const XML_Char *encoding); enum XML_ParamEntityParsing { XML_PARAM_ENTITY_PARSING_NEVER, XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE, XML_PARAM_ENTITY_PARSING_ALWAYS }; /* Controls parsing of parameter entities (including the external DTD subset). If parsing of parameter entities is enabled, then references to external parameter entities (including the external DTD subset) will be passed to the handler set with XML_SetExternalEntityRefHandler. The context passed will be 0. Unlike external general entities, external parameter entities can only be parsed synchronously. If the external parameter entity is to be parsed, it must be parsed during the call to the external entity ref handler: the complete sequence of XML_ExternalEntityParserCreate, XML_Parse/XML_ParseBuffer and XML_ParserFree calls must be made during this call. After XML_ExternalEntityParserCreate has been called to create the parser for the external parameter entity (context must be 0 for this call), it is illegal to make any calls on the old parser until XML_ParserFree has been called on the newly created parser. If the library has been compiled without support for parameter entity parsing (ie without XML_DTD being defined), then XML_SetParamEntityParsing will return 0 if parsing of parameter entities is requested; otherwise it will return non-zero. Note: If XML_SetParamEntityParsing is called after XML_Parse or XML_ParseBuffer, then it has no effect and will always return 0. Note: If parser == NULL, the function will do nothing and return 0. */ XMLPARSEAPI(int) XML_SetParamEntityParsing(XML_Parser parser, enum XML_ParamEntityParsing parsing); /* Sets the hash salt to use for internal hash calculations. Helps in preventing DoS attacks based on predicting hash function behavior. This must be called before parsing is started. Returns 1 if successful, 0 when called after parsing has started. Note: If parser == NULL, the function will do nothing and return 0. */ XMLPARSEAPI(int) XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt); /* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then XML_GetErrorCode returns information about the error. */ XMLPARSEAPI(enum XML_Error) XML_GetErrorCode(XML_Parser parser); /* These functions return information about the current parse location. They may be called from any callback called to report some parse event; in this case the location is the location of the first of the sequence of characters that generated the event. When called from callbacks generated by declarations in the document prologue, the location identified isn't as neatly defined, but will be within the relevant markup. When called outside of the callback functions, the position indicated will be just past the last parse event (regardless of whether there was an associated callback). They may also be called after returning from a call to XML_Parse or XML_ParseBuffer. If the return value is XML_STATUS_ERROR then the location is the location of the character at which the error was detected; otherwise the location is the location of the last parse event, as described above. Note: XML_GetCurrentLineNumber and XML_GetCurrentColumnNumber return 0 to indicate an error. Note: XML_GetCurrentByteIndex returns -1 to indicate an error. */ XMLPARSEAPI(XML_Size) XML_GetCurrentLineNumber(XML_Parser parser); XMLPARSEAPI(XML_Size) XML_GetCurrentColumnNumber(XML_Parser parser); XMLPARSEAPI(XML_Index) XML_GetCurrentByteIndex(XML_Parser parser); /* Return the number of bytes in the current event. Returns 0 if the event is in an internal entity. */ XMLPARSEAPI(int) XML_GetCurrentByteCount(XML_Parser parser); /* If XML_CONTEXT_BYTES is >=1, returns the input buffer, sets the integer pointed to by offset to the offset within this buffer of the current parse position, and sets the integer pointed to by size to the size of this buffer (the number of input bytes). Otherwise returns a NULL pointer. Also returns a NULL pointer if a parse isn't active. NOTE: The character pointer returned should not be used outside the handler that makes the call. */ XMLPARSEAPI(const char *) XML_GetInputContext(XML_Parser parser, int *offset, int *size); /* For backwards compatibility with previous versions. */ #define XML_GetErrorLineNumber XML_GetCurrentLineNumber #define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber #define XML_GetErrorByteIndex XML_GetCurrentByteIndex /* Frees the content model passed to the element declaration handler */ XMLPARSEAPI(void) XML_FreeContentModel(XML_Parser parser, XML_Content *model); /* Exposing the memory handling functions used in Expat */ XMLPARSEAPI(void *) XML_ATTR_MALLOC XML_ATTR_ALLOC_SIZE(2) XML_MemMalloc(XML_Parser parser, size_t size); XMLPARSEAPI(void *) XML_ATTR_ALLOC_SIZE(3) XML_MemRealloc(XML_Parser parser, void *ptr, size_t size); XMLPARSEAPI(void) XML_MemFree(XML_Parser parser, void *ptr); /* Frees memory used by the parser. */ XMLPARSEAPI(void) XML_ParserFree(XML_Parser parser); /* Returns a string describing the error. */ XMLPARSEAPI(const XML_LChar *) XML_ErrorString(enum XML_Error code); /* Return a string containing the version number of this expat */ XMLPARSEAPI(const XML_LChar *) XML_ExpatVersion(void); typedef struct { int major; int minor; int micro; } XML_Expat_Version; /* Return an XML_Expat_Version structure containing numeric version number information for this version of expat. */ XMLPARSEAPI(XML_Expat_Version) XML_ExpatVersionInfo(void); /* Added in Expat 1.95.5. */ enum XML_FeatureEnum { XML_FEATURE_END = 0, XML_FEATURE_UNICODE, XML_FEATURE_UNICODE_WCHAR_T, XML_FEATURE_DTD, XML_FEATURE_CONTEXT_BYTES, XML_FEATURE_MIN_SIZE, XML_FEATURE_SIZEOF_XML_CHAR, XML_FEATURE_SIZEOF_XML_LCHAR, XML_FEATURE_NS, XML_FEATURE_LARGE_SIZE, XML_FEATURE_ATTR_INFO, /* Added in Expat 2.4.0. */ XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT, XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT, /* Added in Expat 2.6.0. */ XML_FEATURE_GE /* Additional features must be added to the end of this enum. */ }; typedef struct { enum XML_FeatureEnum feature; const XML_LChar *name; long int value; } XML_Feature; XMLPARSEAPI(const XML_Feature *) XML_GetFeatureList(void); #if defined(XML_DTD) || (defined(XML_GE) && XML_GE == 1) /* Added in Expat 2.4.0 for XML_DTD defined and * added in Expat 2.6.0 for XML_GE == 1. */ XMLPARSEAPI(XML_Bool) XML_SetBillionLaughsAttackProtectionMaximumAmplification( XML_Parser parser, float maximumAmplificationFactor); /* Added in Expat 2.4.0 for XML_DTD defined and * added in Expat 2.6.0 for XML_GE == 1. */ XMLPARSEAPI(XML_Bool) XML_SetBillionLaughsAttackProtectionActivationThreshold( XML_Parser parser, unsigned long long activationThresholdBytes); #endif /* Added in Expat 2.6.0. */ XMLPARSEAPI(XML_Bool) XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled); /* Expat follows the semantic versioning convention. See https://semver.org */ #define XML_MAJOR_VERSION 2 #define XML_MINOR_VERSION 6 #define XML_MICRO_VERSION 3 #ifdef __cplusplus } #endif #endif /* not Expat_INCLUDED */ tdom-0.9.5-src/expat/asciitab.h0000644000175000017500000000670014703531020015012 0ustar rolfrolf/* __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2002 Fred L. Drake, Jr. Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, /* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML, /* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, /* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, /* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, /* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, /* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, /* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, /* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, /* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, /* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, /* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, /* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, /* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, /* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, /* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, /* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, /* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, tdom-0.9.5-src/expat/xmltok_impl.h0000644000175000017500000000654614703531020015602 0ustar rolfrolf/* __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2017-2019 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ enum { BT_NONXML, /* e.g. noncharacter-FFFF */ BT_MALFORM, /* illegal, with regard to encoding */ BT_LT, /* less than = "<" */ BT_AMP, /* ampersand = "&" */ BT_RSQB, /* right square bracket = "[" */ BT_LEAD2, /* lead byte of a 2-byte UTF-8 character */ BT_LEAD3, /* lead byte of a 3-byte UTF-8 character */ BT_LEAD4, /* lead byte of a 4-byte UTF-8 character */ BT_TRAIL, /* trailing unit, e.g. second 16-bit unit of a 4-byte char. */ BT_CR, /* carriage return = "\r" */ BT_LF, /* line feed = "\n" */ BT_GT, /* greater than = ">" */ BT_QUOT, /* quotation character = "\"" */ BT_APOS, /* apostrophe = "'" */ BT_EQUALS, /* equal sign = "=" */ BT_QUEST, /* question mark = "?" */ BT_EXCL, /* exclamation mark = "!" */ BT_SOL, /* solidus, slash = "/" */ BT_SEMI, /* semicolon = ";" */ BT_NUM, /* number sign = "#" */ BT_LSQB, /* left square bracket = "[" */ BT_S, /* white space, e.g. "\t", " "[, "\r"] */ BT_NMSTRT, /* non-hex name start letter = "G".."Z" + "g".."z" + "_" */ BT_COLON, /* colon = ":" */ BT_HEX, /* hex letter = "A".."F" + "a".."f" */ BT_DIGIT, /* digit = "0".."9" */ BT_NAME, /* dot and middle dot = "." + chr(0xb7) */ BT_MINUS, /* minus = "-" */ BT_OTHER, /* known not to be a name or name start character */ BT_NONASCII, /* might be a name or name start character */ BT_PERCNT, /* percent sign = "%" */ BT_LPAR, /* left parenthesis = "(" */ BT_RPAR, /* right parenthesis = "(" */ BT_AST, /* asterisk = "*" */ BT_PLUS, /* plus sign = "+" */ BT_COMMA, /* comma = "," */ BT_VERBAR /* vertical bar = "|" */ }; #include tdom-0.9.5-src/expat/winconfig.h0000644000175000017500000000376614703531020015227 0ustar rolfrolf/* __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 2000 Clark Cooper Copyright (c) 2002 Greg Stein Copyright (c) 2005 Karl Waclawek Copyright (c) 2017-2023 Sebastian Pipping Copyright (c) 2023 Orgad Shaneh Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef WINCONFIG_H #define WINCONFIG_H #ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif #include #undef WIN32_LEAN_AND_MEAN #include #include #endif /* ndef WINCONFIG_H */ tdom-0.9.5-src/expat/xmlparse.c0000644000175000017500000106041314703531020015063 0ustar rolfrolf/* ba4cdf9bdb534f355a9def4c9e25d20ee8e72f95b0a4d930be52e563f5080196 (2.6.3+) __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2000-2006 Fred L. Drake, Jr. Copyright (c) 2001-2002 Greg Stein Copyright (c) 2002-2016 Karl Waclawek Copyright (c) 2005-2009 Steven Solie Copyright (c) 2016 Eric Rahm Copyright (c) 2016-2024 Sebastian Pipping Copyright (c) 2016 Gaurav Copyright (c) 2016 Thomas Beutlich Copyright (c) 2016 Gustavo Grieco Copyright (c) 2016 Pascal Cuoq Copyright (c) 2016 Ed Schouten Copyright (c) 2017-2022 Rhodri James Copyright (c) 2017 Václav Slavík Copyright (c) 2017 Viktor Szakats Copyright (c) 2017 Chanho Park Copyright (c) 2017 Rolf Eike Beer Copyright (c) 2017 Hans Wennborg Copyright (c) 2018 Anton Maklakov Copyright (c) 2018 Benjamin Peterson Copyright (c) 2018 Marco Maggi Copyright (c) 2018 Mariusz Zaborski Copyright (c) 2019 David Loffredo Copyright (c) 2019-2020 Ben Wagner Copyright (c) 2019 Vadim Zeitlin Copyright (c) 2021 Donghee Na Copyright (c) 2022 Samanta Navarro Copyright (c) 2022 Jeffrey Walton Copyright (c) 2022 Jann Horn Copyright (c) 2022 Sean McBride Copyright (c) 2023 Owain Davies Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow Copyright (c) 2024 Berkay Eren Ürün Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define XML_BUILDING_EXPAT 1 #include "expat_config.h" #if ! defined(XML_GE) || (1 - XML_GE - 1 == 2) || (XML_GE < 0) || (XML_GE > 1) # error XML_GE (for general entities) must be defined, non-empty, either 1 or 0 (0 to disable, 1 to enable; 1 is a common default) #endif #if defined(XML_DTD) && XML_GE == 0 # error Either undefine XML_DTD or define XML_GE to 1. #endif #if ! defined(XML_CONTEXT_BYTES) || (1 - XML_CONTEXT_BYTES - 1 == 2) \ || (XML_CONTEXT_BYTES + 0 < 0) # error XML_CONTEXT_BYTES must be defined, non-empty and >=0 (0 to disable, >=1 to enable; 1024 is a common default) #endif #if defined(HAVE_SYSCALL_GETRANDOM) # if ! defined(_GNU_SOURCE) # define _GNU_SOURCE 1 /* syscall prototype */ # endif #endif #ifdef _WIN32 /* force stdlib to define rand_s() */ # if ! defined(_CRT_RAND_S) # define _CRT_RAND_S # endif #endif #include #include #include /* memset(), memcpy() */ #include #include /* UINT_MAX */ #include /* fprintf */ #include /* getenv, rand_s */ #include /* uintptr_t */ #include /* isnan */ #ifdef _WIN32 # define getpid GetCurrentProcessId #else # include /* gettimeofday() */ # include /* getpid() */ # include /* getpid() */ # include /* O_RDONLY */ # include #endif #ifdef _WIN32 # include "winconfig.h" #endif #include "ascii.h" #include "expat.h" #include "siphash.h" #if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) # if defined(HAVE_GETRANDOM) # include /* getrandom */ # else # include /* syscall */ # include /* SYS_getrandom */ # endif # if ! defined(GRND_NONBLOCK) # define GRND_NONBLOCK 0x0001 # endif /* defined(GRND_NONBLOCK) */ #endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */ #if defined(HAVE_LIBBSD) \ && (defined(HAVE_ARC4RANDOM_BUF) || defined(HAVE_ARC4RANDOM)) # include #endif #if defined(_WIN32) && ! defined(LOAD_LIBRARY_SEARCH_SYSTEM32) # define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 #endif #if ! defined(HAVE_GETRANDOM) && ! defined(HAVE_SYSCALL_GETRANDOM) \ && ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) \ && ! defined(XML_DEV_URANDOM) && ! defined(_WIN32) \ && ! defined(XML_POOR_ENTROPY) # error You do not have support for any sources of high quality entropy \ enabled. For end user security, that is probably not what you want. \ \ Your options include: \ * Linux >=3.17 + glibc >=2.25 (getrandom): HAVE_GETRANDOM, \ * Linux >=3.17 + glibc (including <2.25) (syscall SYS_getrandom): HAVE_SYSCALL_GETRANDOM, \ * BSD / macOS >=10.7 / glibc >=2.36 (arc4random_buf): HAVE_ARC4RANDOM_BUF, \ * BSD / macOS (including <10.7) / glibc >=2.36 (arc4random): HAVE_ARC4RANDOM, \ * libbsd (arc4random_buf): HAVE_ARC4RANDOM_BUF + HAVE_LIBBSD, \ * libbsd (arc4random): HAVE_ARC4RANDOM + HAVE_LIBBSD, \ * Linux (including <3.17) / BSD / macOS (including <10.7) / Solaris >=8 (/dev/urandom): XML_DEV_URANDOM, \ * Windows >=Vista (rand_s): _WIN32. \ \ If insist on not using any of these, bypass this error by defining \ XML_POOR_ENTROPY; you have been warned. \ \ If you have reasons to patch this detection code away or need changes \ to the build system, please open a bug. Thank you! #endif #ifdef XML_UNICODE # define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX # define XmlConvert XmlUtf16Convert # define XmlGetInternalEncoding XmlGetUtf16InternalEncoding # define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS # define XmlEncode XmlUtf16Encode # define MUST_CONVERT(enc, s) (! (enc)->isUtf16 || (((uintptr_t)(s)) & 1)) typedef unsigned short ICHAR; #else # define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX # define XmlConvert XmlUtf8Convert # define XmlGetInternalEncoding XmlGetUtf8InternalEncoding # define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS # define XmlEncode XmlUtf8Encode # define MUST_CONVERT(enc, s) (! (enc)->isUtf8) typedef char ICHAR; #endif #ifndef XML_NS # define XmlInitEncodingNS XmlInitEncoding # define XmlInitUnknownEncodingNS XmlInitUnknownEncoding # undef XmlGetInternalEncodingNS # define XmlGetInternalEncodingNS XmlGetInternalEncoding # define XmlParseXmlDeclNS XmlParseXmlDecl #endif #ifdef XML_UNICODE # ifdef XML_UNICODE_WCHAR_T # define XML_T(x) (const wchar_t) x # define XML_L(x) L##x # else # define XML_T(x) (const unsigned short)x # define XML_L(x) x # endif #else # define XML_T(x) x # define XML_L(x) x #endif /* Round up n to be a multiple of sz, where sz is a power of 2. */ #define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1)) /* Do safe (NULL-aware) pointer arithmetic */ #define EXPAT_SAFE_PTR_DIFF(p, q) (((p) && (q)) ? ((p) - (q)) : 0) #define EXPAT_MIN(a, b) (((a) < (b)) ? (a) : (b)) #include "internal.h" #include "xmltok.h" #include "xmlrole.h" typedef const XML_Char *KEY; typedef struct { KEY name; } NAMED; typedef struct { NAMED **v; unsigned char power; size_t size; size_t used; const XML_Memory_Handling_Suite *mem; } HASH_TABLE; static size_t keylen(KEY s); static void copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key); /* For probing (after a collision) we need a step size relative prime to the hash table size, which is a power of 2. We use double-hashing, since we can calculate a second hash value cheaply by taking those bits of the first hash value that were discarded (masked out) when the table index was calculated: index = hash & mask, where mask = table->size - 1. We limit the maximum step size to table->size / 4 (mask >> 2) and make it odd, since odd numbers are always relative prime to a power of 2. */ #define SECOND_HASH(hash, mask, power) \ ((((hash) & ~(mask)) >> ((power) - 1)) & ((mask) >> 2)) #define PROBE_STEP(hash, mask, power) \ ((unsigned char)((SECOND_HASH(hash, mask, power)) | 1)) typedef struct { NAMED **p; NAMED **end; } HASH_TABLE_ITER; #define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */ #define INIT_DATA_BUF_SIZE 1024 #define INIT_ATTS_SIZE 16 #define INIT_ATTS_VERSION 0xFFFFFFFF #define INIT_BLOCK_SIZE 1024 #define INIT_BUFFER_SIZE 1024 #define EXPAND_SPARE 24 typedef struct binding { struct prefix *prefix; struct binding *nextTagBinding; struct binding *prevPrefixBinding; const struct attribute_id *attId; XML_Char *uri; int uriLen; int uriAlloc; } BINDING; typedef struct prefix { const XML_Char *name; BINDING *binding; } PREFIX; typedef struct { const XML_Char *str; const XML_Char *localPart; const XML_Char *prefix; int strLen; int uriLen; int prefixLen; } TAG_NAME; /* TAG represents an open element. The name of the element is stored in both the document and API encodings. The memory buffer 'buf' is a separately-allocated memory area which stores the name. During the XML_Parse()/ XML_ParseBuffer() when the element is open, the memory for the 'raw' version of the name (in the document encoding) is shared with the document buffer. If the element is open across calls to XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to contain the 'raw' name as well. A parser reuses these structures, maintaining a list of allocated TAG objects in a free list. */ typedef struct tag { struct tag *parent; /* parent of this element */ const char *rawName; /* tagName in the original encoding */ int rawNameLength; TAG_NAME name; /* tagName in the API encoding */ char *buf; /* buffer for name components */ char *bufEnd; /* end of the buffer */ BINDING *bindings; } TAG; typedef struct { const XML_Char *name; const XML_Char *textPtr; int textLen; /* length in XML_Chars */ int processed; /* # of processed bytes - when suspended */ const XML_Char *systemId; const XML_Char *base; const XML_Char *publicId; const XML_Char *notation; XML_Bool open; XML_Bool is_param; XML_Bool is_internal; /* true if declared in internal subset outside PE */ } ENTITY; typedef struct { enum XML_Content_Type type; enum XML_Content_Quant quant; const XML_Char *name; int firstchild; int lastchild; int childcnt; int nextsib; } CONTENT_SCAFFOLD; #define INIT_SCAFFOLD_ELEMENTS 32 typedef struct block { struct block *next; int size; XML_Char s[1]; } BLOCK; typedef struct { BLOCK *blocks; BLOCK *freeBlocks; const XML_Char *end; XML_Char *ptr; XML_Char *start; const XML_Memory_Handling_Suite *mem; } STRING_POOL; /* The XML_Char before the name is used to determine whether an attribute has been specified. */ typedef struct attribute_id { XML_Char *name; PREFIX *prefix; XML_Bool maybeTokenized; XML_Bool xmlns; } ATTRIBUTE_ID; typedef struct { const ATTRIBUTE_ID *id; XML_Bool isCdata; const XML_Char *value; } DEFAULT_ATTRIBUTE; typedef struct { unsigned long version; unsigned long hash; const XML_Char *uriName; } NS_ATT; typedef struct { const XML_Char *name; PREFIX *prefix; const ATTRIBUTE_ID *idAtt; int nDefaultAtts; int allocDefaultAtts; DEFAULT_ATTRIBUTE *defaultAtts; } ELEMENT_TYPE; typedef struct { HASH_TABLE generalEntities; HASH_TABLE elementTypes; HASH_TABLE attributeIds; HASH_TABLE prefixes; STRING_POOL pool; STRING_POOL entityValuePool; /* false once a parameter entity reference has been skipped */ XML_Bool keepProcessing; /* true once an internal or external PE reference has been encountered; this includes the reference to an external subset */ XML_Bool hasParamEntityRefs; XML_Bool standalone; #ifdef XML_DTD /* indicates if external PE has been read */ XML_Bool paramEntityRead; HASH_TABLE paramEntities; #endif /* XML_DTD */ PREFIX defaultPrefix; /* === scaffolding for building content model === */ XML_Bool in_eldecl; CONTENT_SCAFFOLD *scaffold; unsigned contentStringLen; unsigned scaffSize; unsigned scaffCount; int scaffLevel; int *scaffIndex; } DTD; typedef struct open_internal_entity { const char *internalEventPtr; const char *internalEventEndPtr; struct open_internal_entity *next; ENTITY *entity; int startTagLevel; XML_Bool betweenDecl; /* WFC: PE Between Declarations */ } OPEN_INTERNAL_ENTITY; enum XML_Account { XML_ACCOUNT_DIRECT, /* bytes directly passed to the Expat parser */ XML_ACCOUNT_ENTITY_EXPANSION, /* intermediate bytes produced during entity expansion */ XML_ACCOUNT_NONE /* i.e. do not account, was accounted already */ }; #if XML_GE == 1 typedef unsigned long long XmlBigCount; typedef struct accounting { XmlBigCount countBytesDirect; XmlBigCount countBytesIndirect; unsigned long debugLevel; float maximumAmplificationFactor; // >=1.0 unsigned long long activationThresholdBytes; } ACCOUNTING; typedef struct entity_stats { unsigned int countEverOpened; unsigned int currentDepth; unsigned int maximumDepthSeen; unsigned long debugLevel; } ENTITY_STATS; #endif /* XML_GE == 1 */ typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start, const char *end, const char **endPtr); static Processor prologProcessor; static Processor prologInitProcessor; static Processor contentProcessor; static Processor cdataSectionProcessor; #ifdef XML_DTD static Processor ignoreSectionProcessor; static Processor externalParEntProcessor; static Processor externalParEntInitProcessor; static Processor entityValueProcessor; static Processor entityValueInitProcessor; #endif /* XML_DTD */ static Processor epilogProcessor; static Processor errorProcessor; static Processor externalEntityInitProcessor; static Processor externalEntityInitProcessor2; static Processor externalEntityInitProcessor3; static Processor externalEntityContentProcessor; static Processor internalEntityProcessor; static enum XML_Error handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName); static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s, const char *next); static enum XML_Error initializeEncoding(XML_Parser parser); static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, int tok, const char *next, const char **nextPtr, XML_Bool haveMore, XML_Bool allowClosingDoctype, enum XML_Account account); static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl); static enum XML_Error doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, const char *start, const char *end, const char **endPtr, XML_Bool haveMore, enum XML_Account account); static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, const char *end, const char **nextPtr, XML_Bool haveMore, enum XML_Account account); #ifdef XML_DTD static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, const char *end, const char **nextPtr, XML_Bool haveMore); #endif /* XML_DTD */ static void freeBindings(XML_Parser parser, BINDING *bindings); static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, TAG_NAME *tagNamePtr, BINDING **bindingsPtr, enum XML_Account account); static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr); static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata, XML_Bool isId, const XML_Char *value, XML_Parser parser); static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, const char *ptr, const char *end, STRING_POOL *pool, enum XML_Account account); static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, const char *ptr, const char *end, STRING_POOL *pool, enum XML_Account account); static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType); #if XML_GE == 1 static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start, const char *end, enum XML_Account account); #else static enum XML_Error storeSelfEntityValue(XML_Parser parser, ENTITY *entity); #endif static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static int reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static void reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end); static const XML_Char *getContext(XML_Parser parser); static XML_Bool setContext(XML_Parser parser, const XML_Char *context); static void FASTCALL normalizePublicId(XML_Char *s); static DTD *dtdCreate(const XML_Memory_Handling_Suite *ms); /* do not call if m_parentParser != NULL */ static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms); static void dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms); static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms); static int copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable, STRING_POOL *newPool, const HASH_TABLE *oldTable); static NAMED *lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize); static void FASTCALL hashTableInit(HASH_TABLE *table, const XML_Memory_Handling_Suite *ms); static void FASTCALL hashTableClear(HASH_TABLE *table); static void FASTCALL hashTableDestroy(HASH_TABLE *table); static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table); static NAMED *FASTCALL hashTableIterNext(HASH_TABLE_ITER *iter); static void FASTCALL poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms); static void FASTCALL poolClear(STRING_POOL *pool); static void FASTCALL poolDestroy(STRING_POOL *pool); static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr, const char *end); static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc, const char *ptr, const char *end); static XML_Bool FASTCALL poolGrow(STRING_POOL *pool); static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool, const XML_Char *s); static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n); static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool, const XML_Char *s); static int FASTCALL nextScaffoldPart(XML_Parser parser); static XML_Content *build_model(XML_Parser parser); static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr, const char *end); static XML_Char *copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite); static unsigned long generate_hash_secret_salt(XML_Parser parser); static XML_Bool startParsing(XML_Parser parser); static XML_Parser parserCreate(const XML_Char *encodingName, const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep, DTD *dtd); static void parserInit(XML_Parser parser, const XML_Char *encodingName); #if XML_GE == 1 static float accountingGetCurrentAmplification(XML_Parser rootParser); static void accountingReportStats(XML_Parser originParser, const char *epilog); static void accountingOnAbort(XML_Parser originParser); static void accountingReportDiff(XML_Parser rootParser, unsigned int levelsAwayFromRootParser, const char *before, const char *after, ptrdiff_t bytesMore, int source_line, enum XML_Account account); static XML_Bool accountingDiffTolerated(XML_Parser originParser, int tok, const char *before, const char *after, int source_line, enum XML_Account account); static void entityTrackingReportStats(XML_Parser parser, ENTITY *entity, const char *action, int sourceLine); static void entityTrackingOnOpen(XML_Parser parser, ENTITY *entity, int sourceLine); static void entityTrackingOnClose(XML_Parser parser, ENTITY *entity, int sourceLine); static XML_Parser getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff); #endif /* XML_GE == 1 */ static unsigned long getDebugLevel(const char *variableName, unsigned long defaultDebugLevel); #define poolStart(pool) ((pool)->start) #define poolLength(pool) ((pool)->ptr - (pool)->start) #define poolChop(pool) ((void)--(pool->ptr)) #define poolLastChar(pool) (((pool)->ptr)[-1]) #define poolDiscard(pool) ((pool)->ptr = (pool)->start) #define poolFinish(pool) ((pool)->start = (pool)->ptr) #define poolAppendChar(pool, c) \ (((pool)->ptr == (pool)->end && ! poolGrow(pool)) \ ? 0 \ : ((*((pool)->ptr)++ = c), 1)) #if ! defined(XML_TESTING) const #endif XML_Bool g_reparseDeferralEnabledDefault = XML_TRUE; // write ONLY in runtests.c #if defined(XML_TESTING) unsigned int g_bytesScanned = 0; // used for testing only #endif struct XML_ParserStruct { /* The first member must be m_userData so that the XML_GetUserData macro works. */ void *m_userData; void *m_handlerArg; // How the four parse buffer pointers below relate in time and space: // // m_buffer <= m_bufferPtr <= m_bufferEnd <= m_bufferLim // | | | | // <--parsed-->| | | // <---parsing--->| | // <--unoccupied-->| // <---------total-malloced/realloced-------->| char *m_buffer; // malloc/realloc base pointer of parse buffer const XML_Memory_Handling_Suite m_mem; const char *m_bufferPtr; // first character to be parsed char *m_bufferEnd; // past last character to be parsed const char *m_bufferLim; // allocated end of m_buffer XML_Index m_parseEndByteIndex; const char *m_parseEndPtr; size_t m_partialTokenBytesBefore; /* used in heuristic to avoid O(n^2) */ XML_Bool m_reparseDeferralEnabled; int m_lastBufferRequestSize; XML_Char *m_dataBuf; XML_Char *m_dataBufEnd; XML_StartElementHandler m_startElementHandler; XML_EndElementHandler m_endElementHandler; XML_CharacterDataHandler m_characterDataHandler; XML_ProcessingInstructionHandler m_processingInstructionHandler; XML_CommentHandler m_commentHandler; XML_StartCdataSectionHandler m_startCdataSectionHandler; XML_EndCdataSectionHandler m_endCdataSectionHandler; XML_DefaultHandler m_defaultHandler; XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler; XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler; XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler; XML_NotationDeclHandler m_notationDeclHandler; XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler; XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler; XML_NotStandaloneHandler m_notStandaloneHandler; XML_ExternalEntityRefHandler m_externalEntityRefHandler; XML_Parser m_externalEntityRefHandlerArg; XML_SkippedEntityHandler m_skippedEntityHandler; XML_UnknownEncodingHandler m_unknownEncodingHandler; XML_ElementDeclHandler m_elementDeclHandler; XML_AttlistDeclHandler m_attlistDeclHandler; XML_EntityDeclHandler m_entityDeclHandler; XML_XmlDeclHandler m_xmlDeclHandler; const ENCODING *m_encoding; INIT_ENCODING m_initEncoding; const ENCODING *m_internalEncoding; const XML_Char *m_protocolEncodingName; XML_Bool m_ns; XML_Bool m_ns_triplets; void *m_unknownEncodingMem; void *m_unknownEncodingData; void *m_unknownEncodingHandlerData; void(XMLCALL *m_unknownEncodingRelease)(void *); PROLOG_STATE m_prologState; Processor *m_processor; enum XML_Error m_errorCode; const char *m_eventPtr; const char *m_eventEndPtr; const char *m_positionPtr; OPEN_INTERNAL_ENTITY *m_openInternalEntities; OPEN_INTERNAL_ENTITY *m_freeInternalEntities; XML_Bool m_defaultExpandInternalEntities; int m_tagLevel; ENTITY *m_declEntity; const XML_Char *m_doctypeName; const XML_Char *m_doctypeSysid; const XML_Char *m_doctypePubid; const XML_Char *m_declAttributeType; const XML_Char *m_declNotationName; const XML_Char *m_declNotationPublicId; ELEMENT_TYPE *m_declElementType; ATTRIBUTE_ID *m_declAttributeId; XML_Bool m_declAttributeIsCdata; XML_Bool m_declAttributeIsId; DTD *m_dtd; const XML_Char *m_curBase; TAG *m_tagStack; TAG *m_freeTagList; BINDING *m_inheritedBindings; BINDING *m_freeBindingList; int m_attsSize; int m_nSpecifiedAtts; int m_idAttIndex; ATTRIBUTE *m_atts; NS_ATT *m_nsAtts; unsigned long m_nsAttsVersion; unsigned char m_nsAttsPower; #ifdef XML_ATTR_INFO XML_AttrInfo *m_attInfo; #endif POSITION m_position; STRING_POOL m_tempPool; STRING_POOL m_temp2Pool; char *m_groupConnector; unsigned int m_groupSize; XML_Char m_namespaceSeparator; XML_Parser m_parentParser; XML_ParsingStatus m_parsingStatus; #ifdef XML_DTD XML_Bool m_isParamEntity; XML_Bool m_useForeignDTD; enum XML_ParamEntityParsing m_paramEntityParsing; #endif unsigned long m_hash_secret_salt; #if XML_GE == 1 ACCOUNTING m_accounting; ENTITY_STATS m_entity_stats; #endif }; #define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s))) #define REALLOC(parser, p, s) (parser->m_mem.realloc_fcn((p), (s))) #define FREE(parser, p) (parser->m_mem.free_fcn((p))) XML_Parser XMLCALL XML_ParserCreate(const XML_Char *encodingName) { return XML_ParserCreate_MM(encodingName, NULL, NULL); } XML_Parser XMLCALL XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) { XML_Char tmp[2] = {nsSep, 0}; return XML_ParserCreate_MM(encodingName, NULL, tmp); } // "xml=http://www.w3.org/XML/1998/namespace" static const XML_Char implicitContext[] = {ASCII_x, ASCII_m, ASCII_l, ASCII_EQUALS, ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'}; /* To avoid warnings about unused functions: */ #if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) # if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) /* Obtain entropy on Linux 3.17+ */ static int writeRandomBytes_getrandom_nonblock(void *target, size_t count) { int success = 0; /* full count bytes written? */ size_t bytesWrittenTotal = 0; const unsigned int getrandomFlags = GRND_NONBLOCK; do { void *const currentTarget = (void *)((char *)target + bytesWrittenTotal); const size_t bytesToWrite = count - bytesWrittenTotal; const int bytesWrittenMore = # if defined(HAVE_GETRANDOM) getrandom(currentTarget, bytesToWrite, getrandomFlags); # else syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags); # endif if (bytesWrittenMore > 0) { bytesWrittenTotal += bytesWrittenMore; if (bytesWrittenTotal >= count) success = 1; } } while (! success && (errno == EINTR)); return success; } # endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */ # if ! defined(_WIN32) && defined(XML_DEV_URANDOM) /* Extract entropy from /dev/urandom */ static int writeRandomBytes_dev_urandom(void *target, size_t count) { int success = 0; /* full count bytes written? */ size_t bytesWrittenTotal = 0; const int fd = open("/dev/urandom", O_RDONLY); if (fd < 0) { return 0; } do { void *const currentTarget = (void *)((char *)target + bytesWrittenTotal); const size_t bytesToWrite = count - bytesWrittenTotal; const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite); if (bytesWrittenMore > 0) { bytesWrittenTotal += bytesWrittenMore; if (bytesWrittenTotal >= count) success = 1; } } while (! success && (errno == EINTR)); close(fd); return success; } # endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */ #endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */ #if defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF) static void writeRandomBytes_arc4random(void *target, size_t count) { size_t bytesWrittenTotal = 0; while (bytesWrittenTotal < count) { const uint32_t random32 = arc4random(); size_t i = 0; for (; (i < sizeof(random32)) && (bytesWrittenTotal < count); i++, bytesWrittenTotal++) { const uint8_t random8 = (uint8_t)(random32 >> (i * 8)); ((uint8_t *)target)[bytesWrittenTotal] = random8; } } } #endif /* defined(HAVE_ARC4RANDOM) && ! defined(HAVE_ARC4RANDOM_BUF) */ #ifdef _WIN32 /* Provide declaration of rand_s() for MinGW-32 (not 64, which has it), as it didn't declare it in its header prior to version 5.3.0 of its runtime package (mingwrt, containing stdlib.h). The upstream fix was introduced at https://osdn.net/projects/mingw/ticket/39658 . */ # if defined(__MINGW32__) && defined(__MINGW32_VERSION) \ && __MINGW32_VERSION < 5003000L && ! defined(__MINGW64_VERSION_MAJOR) __declspec(dllimport) int rand_s(unsigned int *); # endif /* Obtain entropy on Windows using the rand_s() function which * generates cryptographically secure random numbers. Internally it * uses RtlGenRandom API which is present in Windows XP and later. */ static int writeRandomBytes_rand_s(void *target, size_t count) { size_t bytesWrittenTotal = 0; while (bytesWrittenTotal < count) { unsigned int random32 = 0; size_t i = 0; if (rand_s(&random32)) return 0; /* failure */ for (; (i < sizeof(random32)) && (bytesWrittenTotal < count); i++, bytesWrittenTotal++) { const uint8_t random8 = (uint8_t)(random32 >> (i * 8)); ((uint8_t *)target)[bytesWrittenTotal] = random8; } } return 1; /* success */ } #endif /* _WIN32 */ #if ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) static unsigned long gather_time_entropy(void) { # ifdef _WIN32 FILETIME ft; GetSystemTimeAsFileTime(&ft); /* never fails */ return ft.dwHighDateTime ^ ft.dwLowDateTime; # else struct timeval tv; int gettimeofday_res; gettimeofday_res = gettimeofday(&tv, NULL); # if defined(NDEBUG) (void)gettimeofday_res; # else assert(gettimeofday_res == 0); # endif /* defined(NDEBUG) */ /* Microseconds time is <20 bits entropy */ return tv.tv_usec; # endif } #endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */ static unsigned long ENTROPY_DEBUG(const char *label, unsigned long entropy) { if (getDebugLevel("EXPAT_ENTROPY_DEBUG", 0) >= 1u) { fprintf(stderr, "expat: Entropy: %s --> 0x%0*lx (%lu bytes)\n", label, (int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy)); } return entropy; } static unsigned long generate_hash_secret_salt(XML_Parser parser) { unsigned long entropy; (void)parser; /* "Failproof" high quality providers: */ #if defined(HAVE_ARC4RANDOM_BUF) arc4random_buf(&entropy, sizeof(entropy)); return ENTROPY_DEBUG("arc4random_buf", entropy); #elif defined(HAVE_ARC4RANDOM) writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy)); return ENTROPY_DEBUG("arc4random", entropy); #else /* Try high quality providers first .. */ # ifdef _WIN32 if (writeRandomBytes_rand_s((void *)&entropy, sizeof(entropy))) { return ENTROPY_DEBUG("rand_s", entropy); } # elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) { return ENTROPY_DEBUG("getrandom", entropy); } # endif # if ! defined(_WIN32) && defined(XML_DEV_URANDOM) if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) { return ENTROPY_DEBUG("/dev/urandom", entropy); } # endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */ /* .. and self-made low quality for backup: */ /* Process ID is 0 bits entropy if attacker has local access */ entropy = gather_time_entropy() ^ getpid(); /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */ if (sizeof(unsigned long) == 4) { return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647); } else { return ENTROPY_DEBUG("fallback(8)", entropy * (unsigned long)2305843009213693951ULL); } #endif } static unsigned long get_hash_secret_salt(XML_Parser parser) { if (parser->m_parentParser != NULL) return get_hash_secret_salt(parser->m_parentParser); return parser->m_hash_secret_salt; } static enum XML_Error callProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { const size_t have_now = EXPAT_SAFE_PTR_DIFF(end, start); if (parser->m_reparseDeferralEnabled && ! parser->m_parsingStatus.finalBuffer) { // Heuristic: don't try to parse a partial token again until the amount of // available data has increased significantly. const size_t had_before = parser->m_partialTokenBytesBefore; // ...but *do* try anyway if we're close to causing a reallocation. size_t available_buffer = EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer); #if XML_CONTEXT_BYTES > 0 available_buffer -= EXPAT_MIN(available_buffer, XML_CONTEXT_BYTES); #endif available_buffer += EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd); // m_lastBufferRequestSize is never assigned a value < 0, so the cast is ok const bool enough = (have_now >= 2 * had_before) || ((size_t)parser->m_lastBufferRequestSize > available_buffer); if (! enough) { *endPtr = start; // callers may expect this to be set return XML_ERROR_NONE; } } #if defined(XML_TESTING) g_bytesScanned += (unsigned)have_now; #endif const enum XML_Error ret = parser->m_processor(parser, start, end, endPtr); if (ret == XML_ERROR_NONE) { // if we consumed nothing, remember what we had on this parse attempt. if (*endPtr == start) { parser->m_partialTokenBytesBefore = have_now; } else { parser->m_partialTokenBytesBefore = 0; } } return ret; } static XML_Bool /* only valid for root parser */ startParsing(XML_Parser parser) { /* hash functions must be initialized before setContext() is called */ if (parser->m_hash_secret_salt == 0) parser->m_hash_secret_salt = generate_hash_secret_salt(parser); if (parser->m_ns) { /* implicit context only set for root parser, since child parsers (i.e. external entity parsers) will inherit it */ return setContext(parser, implicitContext); } return XML_TRUE; } XML_Parser XMLCALL XML_ParserCreate_MM(const XML_Char *encodingName, const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep) { return parserCreate(encodingName, memsuite, nameSep, NULL); } static XML_Parser parserCreate(const XML_Char *encodingName, const XML_Memory_Handling_Suite *memsuite, const XML_Char *nameSep, DTD *dtd) { XML_Parser parser; if (memsuite) { XML_Memory_Handling_Suite *mtemp; parser = memsuite->malloc_fcn(sizeof(struct XML_ParserStruct)); if (parser != NULL) { mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); mtemp->malloc_fcn = memsuite->malloc_fcn; mtemp->realloc_fcn = memsuite->realloc_fcn; mtemp->free_fcn = memsuite->free_fcn; } } else { XML_Memory_Handling_Suite *mtemp; parser = (XML_Parser)malloc(sizeof(struct XML_ParserStruct)); if (parser != NULL) { mtemp = (XML_Memory_Handling_Suite *)&(parser->m_mem); mtemp->malloc_fcn = malloc; mtemp->realloc_fcn = realloc; mtemp->free_fcn = free; } } if (! parser) return parser; parser->m_buffer = NULL; parser->m_bufferLim = NULL; parser->m_attsSize = INIT_ATTS_SIZE; parser->m_atts = (ATTRIBUTE *)MALLOC(parser, parser->m_attsSize * sizeof(ATTRIBUTE)); if (parser->m_atts == NULL) { FREE(parser, parser); return NULL; } #ifdef XML_ATTR_INFO parser->m_attInfo = (XML_AttrInfo *)MALLOC( parser, parser->m_attsSize * sizeof(XML_AttrInfo)); if (parser->m_attInfo == NULL) { FREE(parser, parser->m_atts); FREE(parser, parser); return NULL; } #endif parser->m_dataBuf = (XML_Char *)MALLOC(parser, INIT_DATA_BUF_SIZE * sizeof(XML_Char)); if (parser->m_dataBuf == NULL) { FREE(parser, parser->m_atts); #ifdef XML_ATTR_INFO FREE(parser, parser->m_attInfo); #endif FREE(parser, parser); return NULL; } parser->m_dataBufEnd = parser->m_dataBuf + INIT_DATA_BUF_SIZE; if (dtd) parser->m_dtd = dtd; else { parser->m_dtd = dtdCreate(&parser->m_mem); if (parser->m_dtd == NULL) { FREE(parser, parser->m_dataBuf); FREE(parser, parser->m_atts); #ifdef XML_ATTR_INFO FREE(parser, parser->m_attInfo); #endif FREE(parser, parser); return NULL; } } parser->m_freeBindingList = NULL; parser->m_freeTagList = NULL; parser->m_freeInternalEntities = NULL; parser->m_groupSize = 0; parser->m_groupConnector = NULL; parser->m_unknownEncodingHandler = NULL; parser->m_unknownEncodingHandlerData = NULL; parser->m_namespaceSeparator = ASCII_EXCL; parser->m_ns = XML_FALSE; parser->m_ns_triplets = XML_FALSE; parser->m_nsAtts = NULL; parser->m_nsAttsVersion = 0; parser->m_nsAttsPower = 0; parser->m_protocolEncodingName = NULL; poolInit(&parser->m_tempPool, &(parser->m_mem)); poolInit(&parser->m_temp2Pool, &(parser->m_mem)); parserInit(parser, encodingName); if (encodingName && ! parser->m_protocolEncodingName) { if (dtd) { // We need to stop the upcoming call to XML_ParserFree from happily // destroying parser->m_dtd because the DTD is shared with the parent // parser and the only guard that keeps XML_ParserFree from destroying // parser->m_dtd is parser->m_isParamEntity but it will be set to // XML_TRUE only later in XML_ExternalEntityParserCreate (or not at all). parser->m_dtd = NULL; } XML_ParserFree(parser); return NULL; } if (nameSep) { parser->m_ns = XML_TRUE; parser->m_internalEncoding = XmlGetInternalEncodingNS(); parser->m_namespaceSeparator = *nameSep; } else { parser->m_internalEncoding = XmlGetInternalEncoding(); } return parser; } static void parserInit(XML_Parser parser, const XML_Char *encodingName) { parser->m_processor = prologInitProcessor; XmlPrologStateInit(&parser->m_prologState); if (encodingName != NULL) { parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem)); } parser->m_curBase = NULL; XmlInitEncoding(&parser->m_initEncoding, &parser->m_encoding, 0); parser->m_userData = NULL; parser->m_handlerArg = NULL; parser->m_startElementHandler = NULL; parser->m_endElementHandler = NULL; parser->m_characterDataHandler = NULL; parser->m_processingInstructionHandler = NULL; parser->m_commentHandler = NULL; parser->m_startCdataSectionHandler = NULL; parser->m_endCdataSectionHandler = NULL; parser->m_defaultHandler = NULL; parser->m_startDoctypeDeclHandler = NULL; parser->m_endDoctypeDeclHandler = NULL; parser->m_unparsedEntityDeclHandler = NULL; parser->m_notationDeclHandler = NULL; parser->m_startNamespaceDeclHandler = NULL; parser->m_endNamespaceDeclHandler = NULL; parser->m_notStandaloneHandler = NULL; parser->m_externalEntityRefHandler = NULL; parser->m_externalEntityRefHandlerArg = parser; parser->m_skippedEntityHandler = NULL; parser->m_elementDeclHandler = NULL; parser->m_attlistDeclHandler = NULL; parser->m_entityDeclHandler = NULL; parser->m_xmlDeclHandler = NULL; parser->m_bufferPtr = parser->m_buffer; parser->m_bufferEnd = parser->m_buffer; parser->m_parseEndByteIndex = 0; parser->m_parseEndPtr = NULL; parser->m_partialTokenBytesBefore = 0; parser->m_reparseDeferralEnabled = g_reparseDeferralEnabledDefault; parser->m_lastBufferRequestSize = 0; parser->m_declElementType = NULL; parser->m_declAttributeId = NULL; parser->m_declEntity = NULL; parser->m_doctypeName = NULL; parser->m_doctypeSysid = NULL; parser->m_doctypePubid = NULL; parser->m_declAttributeType = NULL; parser->m_declNotationName = NULL; parser->m_declNotationPublicId = NULL; parser->m_declAttributeIsCdata = XML_FALSE; parser->m_declAttributeIsId = XML_FALSE; memset(&parser->m_position, 0, sizeof(POSITION)); parser->m_errorCode = XML_ERROR_NONE; parser->m_eventPtr = NULL; parser->m_eventEndPtr = NULL; parser->m_positionPtr = NULL; parser->m_openInternalEntities = NULL; parser->m_defaultExpandInternalEntities = XML_TRUE; parser->m_tagLevel = 0; parser->m_tagStack = NULL; parser->m_inheritedBindings = NULL; parser->m_nSpecifiedAtts = 0; parser->m_unknownEncodingMem = NULL; parser->m_unknownEncodingRelease = NULL; parser->m_unknownEncodingData = NULL; parser->m_parentParser = NULL; parser->m_parsingStatus.parsing = XML_INITIALIZED; #ifdef XML_DTD parser->m_isParamEntity = XML_FALSE; parser->m_useForeignDTD = XML_FALSE; parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; #endif parser->m_hash_secret_salt = 0; #if XML_GE == 1 memset(&parser->m_accounting, 0, sizeof(ACCOUNTING)); parser->m_accounting.debugLevel = getDebugLevel("EXPAT_ACCOUNTING_DEBUG", 0u); parser->m_accounting.maximumAmplificationFactor = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT; parser->m_accounting.activationThresholdBytes = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT; memset(&parser->m_entity_stats, 0, sizeof(ENTITY_STATS)); parser->m_entity_stats.debugLevel = getDebugLevel("EXPAT_ENTITY_DEBUG", 0u); #endif } /* moves list of bindings to m_freeBindingList */ static void FASTCALL moveToFreeBindingList(XML_Parser parser, BINDING *bindings) { while (bindings) { BINDING *b = bindings; bindings = bindings->nextTagBinding; b->nextTagBinding = parser->m_freeBindingList; parser->m_freeBindingList = b; } } XML_Bool XMLCALL XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) { TAG *tStk; OPEN_INTERNAL_ENTITY *openEntityList; if (parser == NULL) return XML_FALSE; if (parser->m_parentParser) return XML_FALSE; /* move m_tagStack to m_freeTagList */ tStk = parser->m_tagStack; while (tStk) { TAG *tag = tStk; tStk = tStk->parent; tag->parent = parser->m_freeTagList; moveToFreeBindingList(parser, tag->bindings); tag->bindings = NULL; parser->m_freeTagList = tag; } /* move m_openInternalEntities to m_freeInternalEntities */ openEntityList = parser->m_openInternalEntities; while (openEntityList) { OPEN_INTERNAL_ENTITY *openEntity = openEntityList; openEntityList = openEntity->next; openEntity->next = parser->m_freeInternalEntities; parser->m_freeInternalEntities = openEntity; } moveToFreeBindingList(parser, parser->m_inheritedBindings); FREE(parser, parser->m_unknownEncodingMem); if (parser->m_unknownEncodingRelease) parser->m_unknownEncodingRelease(parser->m_unknownEncodingData); poolClear(&parser->m_tempPool); poolClear(&parser->m_temp2Pool); FREE(parser, (void *)parser->m_protocolEncodingName); parser->m_protocolEncodingName = NULL; parserInit(parser, encodingName); dtdReset(parser->m_dtd, &parser->m_mem); return XML_TRUE; } enum XML_Status XMLCALL XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName) { if (parser == NULL) return XML_STATUS_ERROR; /* Block after XML_Parse()/XML_ParseBuffer() has been called. XXX There's no way for the caller to determine which of the XXX possible error cases caused the XML_STATUS_ERROR return. */ if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED) return XML_STATUS_ERROR; /* Get rid of any previous encoding name */ FREE(parser, (void *)parser->m_protocolEncodingName); if (encodingName == NULL) /* No new encoding name */ parser->m_protocolEncodingName = NULL; else { /* Copy the new encoding name into allocated memory */ parser->m_protocolEncodingName = copyString(encodingName, &(parser->m_mem)); if (! parser->m_protocolEncodingName) return XML_STATUS_ERROR; } return XML_STATUS_OK; } XML_Parser XMLCALL XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, const XML_Char *encodingName) { XML_Parser parser = oldParser; DTD *newDtd = NULL; DTD *oldDtd; XML_StartElementHandler oldStartElementHandler; XML_EndElementHandler oldEndElementHandler; XML_CharacterDataHandler oldCharacterDataHandler; XML_ProcessingInstructionHandler oldProcessingInstructionHandler; XML_CommentHandler oldCommentHandler; XML_StartCdataSectionHandler oldStartCdataSectionHandler; XML_EndCdataSectionHandler oldEndCdataSectionHandler; XML_DefaultHandler oldDefaultHandler; XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler; XML_NotationDeclHandler oldNotationDeclHandler; XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler; XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler; XML_NotStandaloneHandler oldNotStandaloneHandler; XML_ExternalEntityRefHandler oldExternalEntityRefHandler; XML_SkippedEntityHandler oldSkippedEntityHandler; XML_UnknownEncodingHandler oldUnknownEncodingHandler; XML_ElementDeclHandler oldElementDeclHandler; XML_AttlistDeclHandler oldAttlistDeclHandler; XML_EntityDeclHandler oldEntityDeclHandler; XML_XmlDeclHandler oldXmlDeclHandler; ELEMENT_TYPE *oldDeclElementType; void *oldUserData; void *oldHandlerArg; XML_Bool oldDefaultExpandInternalEntities; XML_Parser oldExternalEntityRefHandlerArg; #ifdef XML_DTD enum XML_ParamEntityParsing oldParamEntityParsing; int oldInEntityValue; #endif XML_Bool oldns_triplets; /* Note that the new parser shares the same hash secret as the old parser, so that dtdCopy and copyEntityTable can lookup values from hash tables associated with either parser without us having to worry which hash secrets each table has. */ unsigned long oldhash_secret_salt; XML_Bool oldReparseDeferralEnabled; /* Validate the oldParser parameter before we pull everything out of it */ if (oldParser == NULL) return NULL; /* Stash the original parser contents on the stack */ oldDtd = parser->m_dtd; oldStartElementHandler = parser->m_startElementHandler; oldEndElementHandler = parser->m_endElementHandler; oldCharacterDataHandler = parser->m_characterDataHandler; oldProcessingInstructionHandler = parser->m_processingInstructionHandler; oldCommentHandler = parser->m_commentHandler; oldStartCdataSectionHandler = parser->m_startCdataSectionHandler; oldEndCdataSectionHandler = parser->m_endCdataSectionHandler; oldDefaultHandler = parser->m_defaultHandler; oldUnparsedEntityDeclHandler = parser->m_unparsedEntityDeclHandler; oldNotationDeclHandler = parser->m_notationDeclHandler; oldStartNamespaceDeclHandler = parser->m_startNamespaceDeclHandler; oldEndNamespaceDeclHandler = parser->m_endNamespaceDeclHandler; oldNotStandaloneHandler = parser->m_notStandaloneHandler; oldExternalEntityRefHandler = parser->m_externalEntityRefHandler; oldSkippedEntityHandler = parser->m_skippedEntityHandler; oldUnknownEncodingHandler = parser->m_unknownEncodingHandler; oldElementDeclHandler = parser->m_elementDeclHandler; oldAttlistDeclHandler = parser->m_attlistDeclHandler; oldEntityDeclHandler = parser->m_entityDeclHandler; oldXmlDeclHandler = parser->m_xmlDeclHandler; oldDeclElementType = parser->m_declElementType; oldUserData = parser->m_userData; oldHandlerArg = parser->m_handlerArg; oldDefaultExpandInternalEntities = parser->m_defaultExpandInternalEntities; oldExternalEntityRefHandlerArg = parser->m_externalEntityRefHandlerArg; #ifdef XML_DTD oldParamEntityParsing = parser->m_paramEntityParsing; oldInEntityValue = parser->m_prologState.inEntityValue; #endif oldns_triplets = parser->m_ns_triplets; /* Note that the new parser shares the same hash secret as the old parser, so that dtdCopy and copyEntityTable can lookup values from hash tables associated with either parser without us having to worry which hash secrets each table has. */ oldhash_secret_salt = parser->m_hash_secret_salt; oldReparseDeferralEnabled = parser->m_reparseDeferralEnabled; #ifdef XML_DTD if (! context) newDtd = oldDtd; #endif /* XML_DTD */ /* Note that the magical uses of the pre-processor to make field access look more like C++ require that `parser' be overwritten here. This makes this function more painful to follow than it would be otherwise. */ if (parser->m_ns) { XML_Char tmp[2] = {parser->m_namespaceSeparator, 0}; parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd); } else { parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd); } if (! parser) return NULL; parser->m_startElementHandler = oldStartElementHandler; parser->m_endElementHandler = oldEndElementHandler; parser->m_characterDataHandler = oldCharacterDataHandler; parser->m_processingInstructionHandler = oldProcessingInstructionHandler; parser->m_commentHandler = oldCommentHandler; parser->m_startCdataSectionHandler = oldStartCdataSectionHandler; parser->m_endCdataSectionHandler = oldEndCdataSectionHandler; parser->m_defaultHandler = oldDefaultHandler; parser->m_unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler; parser->m_notationDeclHandler = oldNotationDeclHandler; parser->m_startNamespaceDeclHandler = oldStartNamespaceDeclHandler; parser->m_endNamespaceDeclHandler = oldEndNamespaceDeclHandler; parser->m_notStandaloneHandler = oldNotStandaloneHandler; parser->m_externalEntityRefHandler = oldExternalEntityRefHandler; parser->m_skippedEntityHandler = oldSkippedEntityHandler; parser->m_unknownEncodingHandler = oldUnknownEncodingHandler; parser->m_elementDeclHandler = oldElementDeclHandler; parser->m_attlistDeclHandler = oldAttlistDeclHandler; parser->m_entityDeclHandler = oldEntityDeclHandler; parser->m_xmlDeclHandler = oldXmlDeclHandler; parser->m_declElementType = oldDeclElementType; parser->m_userData = oldUserData; if (oldUserData == oldHandlerArg) parser->m_handlerArg = parser->m_userData; else parser->m_handlerArg = parser; if (oldExternalEntityRefHandlerArg != oldParser) parser->m_externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg; parser->m_defaultExpandInternalEntities = oldDefaultExpandInternalEntities; parser->m_ns_triplets = oldns_triplets; parser->m_hash_secret_salt = oldhash_secret_salt; parser->m_reparseDeferralEnabled = oldReparseDeferralEnabled; parser->m_parentParser = oldParser; #ifdef XML_DTD parser->m_paramEntityParsing = oldParamEntityParsing; parser->m_prologState.inEntityValue = oldInEntityValue; if (context) { #endif /* XML_DTD */ if (! dtdCopy(oldParser, parser->m_dtd, oldDtd, &parser->m_mem) || ! setContext(parser, context)) { XML_ParserFree(parser); return NULL; } parser->m_processor = externalEntityInitProcessor; #ifdef XML_DTD } else { /* The DTD instance referenced by parser->m_dtd is shared between the document's root parser and external PE parsers, therefore one does not need to call setContext. In addition, one also *must* not call setContext, because this would overwrite existing prefix->binding pointers in parser->m_dtd with ones that get destroyed with the external PE parser. This would leave those prefixes with dangling pointers. */ parser->m_isParamEntity = XML_TRUE; XmlPrologStateInitExternalEntity(&parser->m_prologState); parser->m_processor = externalParEntInitProcessor; } #endif /* XML_DTD */ return parser; } static void FASTCALL destroyBindings(BINDING *bindings, XML_Parser parser) { for (;;) { BINDING *b = bindings; if (! b) break; bindings = b->nextTagBinding; FREE(parser, b->uri); FREE(parser, b); } } void XMLCALL XML_ParserFree(XML_Parser parser) { TAG *tagList; OPEN_INTERNAL_ENTITY *entityList; if (parser == NULL) return; /* free m_tagStack and m_freeTagList */ tagList = parser->m_tagStack; for (;;) { TAG *p; if (tagList == NULL) { if (parser->m_freeTagList == NULL) break; tagList = parser->m_freeTagList; parser->m_freeTagList = NULL; } p = tagList; tagList = tagList->parent; FREE(parser, p->buf); destroyBindings(p->bindings, parser); FREE(parser, p); } /* free m_openInternalEntities and m_freeInternalEntities */ entityList = parser->m_openInternalEntities; for (;;) { OPEN_INTERNAL_ENTITY *openEntity; if (entityList == NULL) { if (parser->m_freeInternalEntities == NULL) break; entityList = parser->m_freeInternalEntities; parser->m_freeInternalEntities = NULL; } openEntity = entityList; entityList = entityList->next; FREE(parser, openEntity); } destroyBindings(parser->m_freeBindingList, parser); destroyBindings(parser->m_inheritedBindings, parser); poolDestroy(&parser->m_tempPool); poolDestroy(&parser->m_temp2Pool); FREE(parser, (void *)parser->m_protocolEncodingName); #ifdef XML_DTD /* external parameter entity parsers share the DTD structure parser->m_dtd with the root parser, so we must not destroy it */ if (! parser->m_isParamEntity && parser->m_dtd) #else if (parser->m_dtd) #endif /* XML_DTD */ dtdDestroy(parser->m_dtd, (XML_Bool)! parser->m_parentParser, &parser->m_mem); FREE(parser, (void *)parser->m_atts); #ifdef XML_ATTR_INFO FREE(parser, (void *)parser->m_attInfo); #endif FREE(parser, parser->m_groupConnector); FREE(parser, parser->m_buffer); FREE(parser, parser->m_dataBuf); FREE(parser, parser->m_nsAtts); FREE(parser, parser->m_unknownEncodingMem); if (parser->m_unknownEncodingRelease) parser->m_unknownEncodingRelease(parser->m_unknownEncodingData); FREE(parser, parser); } void XMLCALL XML_UseParserAsHandlerArg(XML_Parser parser) { if (parser != NULL) parser->m_handlerArg = parser; } enum XML_Error XMLCALL XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD) { if (parser == NULL) return XML_ERROR_INVALID_ARGUMENT; #ifdef XML_DTD /* block after XML_Parse()/XML_ParseBuffer() has been called */ if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED) return XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING; parser->m_useForeignDTD = useDTD; return XML_ERROR_NONE; #else UNUSED_P(useDTD); return XML_ERROR_FEATURE_REQUIRES_XML_DTD; #endif } void XMLCALL XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) { if (parser == NULL) return; /* block after XML_Parse()/XML_ParseBuffer() has been called */ if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED) return; parser->m_ns_triplets = do_nst ? XML_TRUE : XML_FALSE; } void XMLCALL XML_SetUserData(XML_Parser parser, void *p) { if (parser == NULL) return; if (parser->m_handlerArg == parser->m_userData) parser->m_handlerArg = parser->m_userData = p; else parser->m_userData = p; } enum XML_Status XMLCALL XML_SetBase(XML_Parser parser, const XML_Char *p) { if (parser == NULL) return XML_STATUS_ERROR; if (p) { p = poolCopyString(&parser->m_dtd->pool, p); if (! p) return XML_STATUS_ERROR; parser->m_curBase = p; } else parser->m_curBase = NULL; return XML_STATUS_OK; } const XML_Char *XMLCALL XML_GetBase(XML_Parser parser) { if (parser == NULL) return NULL; return parser->m_curBase; } int XMLCALL XML_GetSpecifiedAttributeCount(XML_Parser parser) { if (parser == NULL) return -1; return parser->m_nSpecifiedAtts; } int XMLCALL XML_GetIdAttributeIndex(XML_Parser parser) { if (parser == NULL) return -1; return parser->m_idAttIndex; } #ifdef XML_ATTR_INFO const XML_AttrInfo *XMLCALL XML_GetAttributeInfo(XML_Parser parser) { if (parser == NULL) return NULL; return parser->m_attInfo; } #endif void XMLCALL XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end) { if (parser == NULL) return; parser->m_startElementHandler = start; parser->m_endElementHandler = end; } void XMLCALL XML_SetStartElementHandler(XML_Parser parser, XML_StartElementHandler start) { if (parser != NULL) parser->m_startElementHandler = start; } void XMLCALL XML_SetEndElementHandler(XML_Parser parser, XML_EndElementHandler end) { if (parser != NULL) parser->m_endElementHandler = end; } void XMLCALL XML_SetCharacterDataHandler(XML_Parser parser, XML_CharacterDataHandler handler) { if (parser != NULL) parser->m_characterDataHandler = handler; } void XMLCALL XML_SetProcessingInstructionHandler(XML_Parser parser, XML_ProcessingInstructionHandler handler) { if (parser != NULL) parser->m_processingInstructionHandler = handler; } void XMLCALL XML_SetCommentHandler(XML_Parser parser, XML_CommentHandler handler) { if (parser != NULL) parser->m_commentHandler = handler; } void XMLCALL XML_SetCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start, XML_EndCdataSectionHandler end) { if (parser == NULL) return; parser->m_startCdataSectionHandler = start; parser->m_endCdataSectionHandler = end; } void XMLCALL XML_SetStartCdataSectionHandler(XML_Parser parser, XML_StartCdataSectionHandler start) { if (parser != NULL) parser->m_startCdataSectionHandler = start; } void XMLCALL XML_SetEndCdataSectionHandler(XML_Parser parser, XML_EndCdataSectionHandler end) { if (parser != NULL) parser->m_endCdataSectionHandler = end; } void XMLCALL XML_SetDefaultHandler(XML_Parser parser, XML_DefaultHandler handler) { if (parser == NULL) return; parser->m_defaultHandler = handler; parser->m_defaultExpandInternalEntities = XML_FALSE; } void XMLCALL XML_SetDefaultHandlerExpand(XML_Parser parser, XML_DefaultHandler handler) { if (parser == NULL) return; parser->m_defaultHandler = handler; parser->m_defaultExpandInternalEntities = XML_TRUE; } void XMLCALL XML_SetDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start, XML_EndDoctypeDeclHandler end) { if (parser == NULL) return; parser->m_startDoctypeDeclHandler = start; parser->m_endDoctypeDeclHandler = end; } void XMLCALL XML_SetStartDoctypeDeclHandler(XML_Parser parser, XML_StartDoctypeDeclHandler start) { if (parser != NULL) parser->m_startDoctypeDeclHandler = start; } void XMLCALL XML_SetEndDoctypeDeclHandler(XML_Parser parser, XML_EndDoctypeDeclHandler end) { if (parser != NULL) parser->m_endDoctypeDeclHandler = end; } void XMLCALL XML_SetUnparsedEntityDeclHandler(XML_Parser parser, XML_UnparsedEntityDeclHandler handler) { if (parser != NULL) parser->m_unparsedEntityDeclHandler = handler; } void XMLCALL XML_SetNotationDeclHandler(XML_Parser parser, XML_NotationDeclHandler handler) { if (parser != NULL) parser->m_notationDeclHandler = handler; } void XMLCALL XML_SetNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start, XML_EndNamespaceDeclHandler end) { if (parser == NULL) return; parser->m_startNamespaceDeclHandler = start; parser->m_endNamespaceDeclHandler = end; } void XMLCALL XML_SetStartNamespaceDeclHandler(XML_Parser parser, XML_StartNamespaceDeclHandler start) { if (parser != NULL) parser->m_startNamespaceDeclHandler = start; } void XMLCALL XML_SetEndNamespaceDeclHandler(XML_Parser parser, XML_EndNamespaceDeclHandler end) { if (parser != NULL) parser->m_endNamespaceDeclHandler = end; } void XMLCALL XML_SetNotStandaloneHandler(XML_Parser parser, XML_NotStandaloneHandler handler) { if (parser != NULL) parser->m_notStandaloneHandler = handler; } void XMLCALL XML_SetExternalEntityRefHandler(XML_Parser parser, XML_ExternalEntityRefHandler handler) { if (parser != NULL) parser->m_externalEntityRefHandler = handler; } void XMLCALL XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg) { if (parser == NULL) return; if (arg) parser->m_externalEntityRefHandlerArg = (XML_Parser)arg; else parser->m_externalEntityRefHandlerArg = parser; } void XMLCALL XML_SetSkippedEntityHandler(XML_Parser parser, XML_SkippedEntityHandler handler) { if (parser != NULL) parser->m_skippedEntityHandler = handler; } void XMLCALL XML_SetUnknownEncodingHandler(XML_Parser parser, XML_UnknownEncodingHandler handler, void *data) { if (parser == NULL) return; parser->m_unknownEncodingHandler = handler; parser->m_unknownEncodingHandlerData = data; } void XMLCALL XML_SetElementDeclHandler(XML_Parser parser, XML_ElementDeclHandler eldecl) { if (parser != NULL) parser->m_elementDeclHandler = eldecl; } void XMLCALL XML_SetAttlistDeclHandler(XML_Parser parser, XML_AttlistDeclHandler attdecl) { if (parser != NULL) parser->m_attlistDeclHandler = attdecl; } void XMLCALL XML_SetEntityDeclHandler(XML_Parser parser, XML_EntityDeclHandler handler) { if (parser != NULL) parser->m_entityDeclHandler = handler; } void XMLCALL XML_SetXmlDeclHandler(XML_Parser parser, XML_XmlDeclHandler handler) { if (parser != NULL) parser->m_xmlDeclHandler = handler; } int XMLCALL XML_SetParamEntityParsing(XML_Parser parser, enum XML_ParamEntityParsing peParsing) { if (parser == NULL) return 0; /* block after XML_Parse()/XML_ParseBuffer() has been called */ if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED) return 0; #ifdef XML_DTD parser->m_paramEntityParsing = peParsing; return 1; #else return peParsing == XML_PARAM_ENTITY_PARSING_NEVER; #endif } int XMLCALL XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) { if (parser == NULL) return 0; if (parser->m_parentParser) return XML_SetHashSalt(parser->m_parentParser, hash_salt); /* block after XML_Parse()/XML_ParseBuffer() has been called */ if (parser->m_parsingStatus.parsing == XML_PARSING || parser->m_parsingStatus.parsing == XML_SUSPENDED) return 0; parser->m_hash_secret_salt = hash_salt; return 1; } enum XML_Status XMLCALL XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) { if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) { if (parser != NULL) parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT; return XML_STATUS_ERROR; } switch (parser->m_parsingStatus.parsing) { case XML_SUSPENDED: parser->m_errorCode = XML_ERROR_SUSPENDED; return XML_STATUS_ERROR; case XML_FINISHED: parser->m_errorCode = XML_ERROR_FINISHED; return XML_STATUS_ERROR; case XML_INITIALIZED: if (parser->m_parentParser == NULL && ! startParsing(parser)) { parser->m_errorCode = XML_ERROR_NO_MEMORY; return XML_STATUS_ERROR; } /* fall through */ default: parser->m_parsingStatus.parsing = XML_PARSING; } #if XML_CONTEXT_BYTES == 0 if (parser->m_bufferPtr == parser->m_bufferEnd) { const char *end; int nLeftOver; enum XML_Status result; /* Detect overflow (a+b > MAX <==> b > MAX-a) */ if ((XML_Size)len > ((XML_Size)-1) / 2 - parser->m_parseEndByteIndex) { parser->m_errorCode = XML_ERROR_NO_MEMORY; parser->m_eventPtr = parser->m_eventEndPtr = NULL; parser->m_processor = errorProcessor; return XML_STATUS_ERROR; } // though this isn't a buffer request, we assume that `len` is the app's // preferred buffer fill size, and therefore save it here. parser->m_lastBufferRequestSize = len; parser->m_parseEndByteIndex += len; parser->m_positionPtr = s; parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal; parser->m_errorCode = callProcessor(parser, s, parser->m_parseEndPtr = s + len, &end); if (parser->m_errorCode != XML_ERROR_NONE) { parser->m_eventEndPtr = parser->m_eventPtr; parser->m_processor = errorProcessor; return XML_STATUS_ERROR; } else { switch (parser->m_parsingStatus.parsing) { case XML_SUSPENDED: result = XML_STATUS_SUSPENDED; break; case XML_INITIALIZED: case XML_PARSING: if (isFinal) { parser->m_parsingStatus.parsing = XML_FINISHED; return XML_STATUS_OK; } /* fall through */ default: result = XML_STATUS_OK; } } XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, end, &parser->m_position); nLeftOver = s + len - end; if (nLeftOver) { // Back up and restore the parsing status to avoid XML_ERROR_SUSPENDED // (and XML_ERROR_FINISHED) from XML_GetBuffer. const enum XML_Parsing originalStatus = parser->m_parsingStatus.parsing; parser->m_parsingStatus.parsing = XML_PARSING; void *const temp = XML_GetBuffer(parser, nLeftOver); parser->m_parsingStatus.parsing = originalStatus; // GetBuffer may have overwritten this, but we want to remember what the // app requested, not how many bytes were left over after parsing. parser->m_lastBufferRequestSize = len; if (temp == NULL) { // NOTE: parser->m_errorCode has already been set by XML_GetBuffer(). parser->m_eventPtr = parser->m_eventEndPtr = NULL; parser->m_processor = errorProcessor; return XML_STATUS_ERROR; } // Since we know that the buffer was empty and XML_CONTEXT_BYTES is 0, we // don't have any data to preserve, and can copy straight into the start // of the buffer rather than the GetBuffer return pointer (which may be // pointing further into the allocated buffer). memcpy(parser->m_buffer, end, nLeftOver); } parser->m_bufferPtr = parser->m_buffer; parser->m_bufferEnd = parser->m_buffer + nLeftOver; parser->m_positionPtr = parser->m_bufferPtr; parser->m_parseEndPtr = parser->m_bufferEnd; parser->m_eventPtr = parser->m_bufferPtr; parser->m_eventEndPtr = parser->m_bufferPtr; return result; } #endif /* XML_CONTEXT_BYTES == 0 */ void *buff = XML_GetBuffer(parser, len); if (buff == NULL) return XML_STATUS_ERROR; if (len > 0) { assert(s != NULL); // make sure s==NULL && len!=0 was rejected above memcpy(buff, s, len); } return XML_ParseBuffer(parser, len, isFinal); } enum XML_Status XMLCALL XML_ParseBuffer(XML_Parser parser, int len, int isFinal) { const char *start; enum XML_Status result = XML_STATUS_OK; if (parser == NULL) return XML_STATUS_ERROR; if (len < 0) { parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT; return XML_STATUS_ERROR; } switch (parser->m_parsingStatus.parsing) { case XML_SUSPENDED: parser->m_errorCode = XML_ERROR_SUSPENDED; return XML_STATUS_ERROR; case XML_FINISHED: parser->m_errorCode = XML_ERROR_FINISHED; return XML_STATUS_ERROR; case XML_INITIALIZED: /* Has someone called XML_GetBuffer successfully before? */ if (! parser->m_bufferPtr) { parser->m_errorCode = XML_ERROR_NO_BUFFER; return XML_STATUS_ERROR; } if (parser->m_parentParser == NULL && ! startParsing(parser)) { parser->m_errorCode = XML_ERROR_NO_MEMORY; return XML_STATUS_ERROR; } /* fall through */ default: parser->m_parsingStatus.parsing = XML_PARSING; } start = parser->m_bufferPtr; parser->m_positionPtr = start; parser->m_bufferEnd += len; parser->m_parseEndPtr = parser->m_bufferEnd; parser->m_parseEndByteIndex += len; parser->m_parsingStatus.finalBuffer = (XML_Bool)isFinal; parser->m_errorCode = callProcessor(parser, start, parser->m_parseEndPtr, &parser->m_bufferPtr); if (parser->m_errorCode != XML_ERROR_NONE) { parser->m_eventEndPtr = parser->m_eventPtr; parser->m_processor = errorProcessor; return XML_STATUS_ERROR; } else { switch (parser->m_parsingStatus.parsing) { case XML_SUSPENDED: result = XML_STATUS_SUSPENDED; break; case XML_INITIALIZED: case XML_PARSING: if (isFinal) { parser->m_parsingStatus.parsing = XML_FINISHED; return result; } default:; /* should not happen */ } } XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_bufferPtr, &parser->m_position); parser->m_positionPtr = parser->m_bufferPtr; return result; } void *XMLCALL XML_GetBuffer(XML_Parser parser, int len) { if (parser == NULL) return NULL; if (len < 0) { parser->m_errorCode = XML_ERROR_NO_MEMORY; return NULL; } switch (parser->m_parsingStatus.parsing) { case XML_SUSPENDED: parser->m_errorCode = XML_ERROR_SUSPENDED; return NULL; case XML_FINISHED: parser->m_errorCode = XML_ERROR_FINISHED; return NULL; default:; } // whether or not the request succeeds, `len` seems to be the app's preferred // buffer fill size; remember it. parser->m_lastBufferRequestSize = len; if (len > EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_bufferEnd) || parser->m_buffer == NULL) { #if XML_CONTEXT_BYTES > 0 int keep; #endif /* XML_CONTEXT_BYTES > 0 */ /* Do not invoke signed arithmetic overflow: */ int neededSize = (int)((unsigned)len + (unsigned)EXPAT_SAFE_PTR_DIFF( parser->m_bufferEnd, parser->m_bufferPtr)); if (neededSize < 0) { parser->m_errorCode = XML_ERROR_NO_MEMORY; return NULL; } #if XML_CONTEXT_BYTES > 0 keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer); if (keep > XML_CONTEXT_BYTES) keep = XML_CONTEXT_BYTES; /* Detect and prevent integer overflow */ if (keep > INT_MAX - neededSize) { parser->m_errorCode = XML_ERROR_NO_MEMORY; return NULL; } neededSize += keep; #endif /* XML_CONTEXT_BYTES > 0 */ if (parser->m_buffer && parser->m_bufferPtr && neededSize <= EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer)) { #if XML_CONTEXT_BYTES > 0 if (keep < EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer)) { int offset = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer) - keep; /* The buffer pointers cannot be NULL here; we have at least some bytes * in the buffer */ memmove(parser->m_buffer, &parser->m_buffer[offset], parser->m_bufferEnd - parser->m_bufferPtr + keep); parser->m_bufferEnd -= offset; parser->m_bufferPtr -= offset; } #else memmove(parser->m_buffer, parser->m_bufferPtr, EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr)); parser->m_bufferEnd = parser->m_buffer + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr); parser->m_bufferPtr = parser->m_buffer; #endif /* XML_CONTEXT_BYTES > 0 */ } else { char *newBuf; int bufferSize = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferLim, parser->m_buffer); if (bufferSize == 0) bufferSize = INIT_BUFFER_SIZE; do { /* Do not invoke signed arithmetic overflow: */ bufferSize = (int)(2U * (unsigned)bufferSize); } while (bufferSize < neededSize && bufferSize > 0); if (bufferSize <= 0) { parser->m_errorCode = XML_ERROR_NO_MEMORY; return NULL; } newBuf = (char *)MALLOC(parser, bufferSize); if (newBuf == 0) { parser->m_errorCode = XML_ERROR_NO_MEMORY; return NULL; } parser->m_bufferLim = newBuf + bufferSize; #if XML_CONTEXT_BYTES > 0 if (parser->m_bufferPtr) { memcpy(newBuf, &parser->m_bufferPtr[-keep], EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr) + keep); FREE(parser, parser->m_buffer); parser->m_buffer = newBuf; parser->m_bufferEnd = parser->m_buffer + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr) + keep; parser->m_bufferPtr = parser->m_buffer + keep; } else { /* This must be a brand new buffer with no data in it yet */ parser->m_bufferEnd = newBuf; parser->m_bufferPtr = parser->m_buffer = newBuf; } #else if (parser->m_bufferPtr) { memcpy(newBuf, parser->m_bufferPtr, EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr)); FREE(parser, parser->m_buffer); parser->m_bufferEnd = newBuf + EXPAT_SAFE_PTR_DIFF(parser->m_bufferEnd, parser->m_bufferPtr); } else { /* This must be a brand new buffer with no data in it yet */ parser->m_bufferEnd = newBuf; } parser->m_bufferPtr = parser->m_buffer = newBuf; #endif /* XML_CONTEXT_BYTES > 0 */ } parser->m_eventPtr = parser->m_eventEndPtr = NULL; parser->m_positionPtr = NULL; } return parser->m_bufferEnd; } enum XML_Status XMLCALL XML_StopParser(XML_Parser parser, XML_Bool resumable) { if (parser == NULL) return XML_STATUS_ERROR; switch (parser->m_parsingStatus.parsing) { case XML_SUSPENDED: if (resumable) { parser->m_errorCode = XML_ERROR_SUSPENDED; return XML_STATUS_ERROR; } parser->m_parsingStatus.parsing = XML_FINISHED; break; case XML_FINISHED: parser->m_errorCode = XML_ERROR_FINISHED; return XML_STATUS_ERROR; default: if (resumable) { #ifdef XML_DTD if (parser->m_isParamEntity) { parser->m_errorCode = XML_ERROR_SUSPEND_PE; return XML_STATUS_ERROR; } #endif parser->m_parsingStatus.parsing = XML_SUSPENDED; } else parser->m_parsingStatus.parsing = XML_FINISHED; } return XML_STATUS_OK; } enum XML_Status XMLCALL XML_ResumeParser(XML_Parser parser) { enum XML_Status result = XML_STATUS_OK; if (parser == NULL) return XML_STATUS_ERROR; if (parser->m_parsingStatus.parsing != XML_SUSPENDED) { parser->m_errorCode = XML_ERROR_NOT_SUSPENDED; return XML_STATUS_ERROR; } parser->m_parsingStatus.parsing = XML_PARSING; parser->m_errorCode = callProcessor( parser, parser->m_bufferPtr, parser->m_parseEndPtr, &parser->m_bufferPtr); if (parser->m_errorCode != XML_ERROR_NONE) { parser->m_eventEndPtr = parser->m_eventPtr; parser->m_processor = errorProcessor; return XML_STATUS_ERROR; } else { switch (parser->m_parsingStatus.parsing) { case XML_SUSPENDED: result = XML_STATUS_SUSPENDED; break; case XML_INITIALIZED: case XML_PARSING: if (parser->m_parsingStatus.finalBuffer) { parser->m_parsingStatus.parsing = XML_FINISHED; return result; } default:; } } XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_bufferPtr, &parser->m_position); parser->m_positionPtr = parser->m_bufferPtr; return result; } void XMLCALL XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status) { if (parser == NULL) return; assert(status != NULL); *status = parser->m_parsingStatus; } enum XML_Error XMLCALL XML_GetErrorCode(XML_Parser parser) { if (parser == NULL) return XML_ERROR_INVALID_ARGUMENT; return parser->m_errorCode; } XML_Index XMLCALL XML_GetCurrentByteIndex(XML_Parser parser) { if (parser == NULL) return -1; if (parser->m_eventPtr) return (XML_Index)(parser->m_parseEndByteIndex - (parser->m_parseEndPtr - parser->m_eventPtr)); return -1; } int XMLCALL XML_GetCurrentByteCount(XML_Parser parser) { if (parser == NULL) return 0; if (parser->m_eventEndPtr && parser->m_eventPtr) return (int)(parser->m_eventEndPtr - parser->m_eventPtr); return 0; } const char *XMLCALL XML_GetInputContext(XML_Parser parser, int *offset, int *size) { #if XML_CONTEXT_BYTES > 0 if (parser == NULL) return NULL; if (parser->m_eventPtr && parser->m_buffer) { if (offset != NULL) *offset = (int)(parser->m_eventPtr - parser->m_buffer); if (size != NULL) *size = (int)(parser->m_bufferEnd - parser->m_buffer); return parser->m_buffer; } #else (void)parser; (void)offset; (void)size; #endif /* XML_CONTEXT_BYTES > 0 */ return (const char *)0; } XML_Size XMLCALL XML_GetCurrentLineNumber(XML_Parser parser) { if (parser == NULL) return 0; if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) { XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_eventPtr, &parser->m_position); parser->m_positionPtr = parser->m_eventPtr; } return parser->m_position.lineNumber + 1; } XML_Size XMLCALL XML_GetCurrentColumnNumber(XML_Parser parser) { if (parser == NULL) return 0; if (parser->m_eventPtr && parser->m_eventPtr >= parser->m_positionPtr) { XmlUpdatePosition(parser->m_encoding, parser->m_positionPtr, parser->m_eventPtr, &parser->m_position); parser->m_positionPtr = parser->m_eventPtr; } return parser->m_position.columnNumber; } void XMLCALL XML_FreeContentModel(XML_Parser parser, XML_Content *model) { if (parser != NULL) FREE(parser, model); } void *XMLCALL XML_MemMalloc(XML_Parser parser, size_t size) { if (parser == NULL) return NULL; return MALLOC(parser, size); } void *XMLCALL XML_MemRealloc(XML_Parser parser, void *ptr, size_t size) { if (parser == NULL) return NULL; return REALLOC(parser, ptr, size); } void XMLCALL XML_MemFree(XML_Parser parser, void *ptr) { if (parser != NULL) FREE(parser, ptr); } void XMLCALL XML_DefaultCurrent(XML_Parser parser) { if (parser == NULL) return; if (parser->m_defaultHandler) { if (parser->m_openInternalEntities) reportDefault(parser, parser->m_internalEncoding, parser->m_openInternalEntities->internalEventPtr, parser->m_openInternalEntities->internalEventEndPtr); else reportDefault(parser, parser->m_encoding, parser->m_eventPtr, parser->m_eventEndPtr); } } const XML_LChar *XMLCALL XML_ErrorString(enum XML_Error code) { switch (code) { case XML_ERROR_NONE: return NULL; case XML_ERROR_NO_MEMORY: return XML_L("out of memory"); case XML_ERROR_SYNTAX: return XML_L("syntax error"); case XML_ERROR_NO_ELEMENTS: return XML_L("no element found"); case XML_ERROR_INVALID_TOKEN: return XML_L("not well-formed (invalid token)"); case XML_ERROR_UNCLOSED_TOKEN: return XML_L("unclosed token"); case XML_ERROR_PARTIAL_CHAR: return XML_L("partial character"); case XML_ERROR_TAG_MISMATCH: return XML_L("mismatched tag"); case XML_ERROR_DUPLICATE_ATTRIBUTE: return XML_L("duplicate attribute"); case XML_ERROR_JUNK_AFTER_DOC_ELEMENT: return XML_L("junk after document element"); case XML_ERROR_PARAM_ENTITY_REF: return XML_L("illegal parameter entity reference"); case XML_ERROR_UNDEFINED_ENTITY: return XML_L("undefined entity"); case XML_ERROR_RECURSIVE_ENTITY_REF: return XML_L("recursive entity reference"); case XML_ERROR_ASYNC_ENTITY: return XML_L("asynchronous entity"); case XML_ERROR_BAD_CHAR_REF: return XML_L("reference to invalid character number"); case XML_ERROR_BINARY_ENTITY_REF: return XML_L("reference to binary entity"); case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF: return XML_L("reference to external entity in attribute"); case XML_ERROR_MISPLACED_XML_PI: return XML_L("XML or text declaration not at start of entity"); case XML_ERROR_UNKNOWN_ENCODING: return XML_L("unknown encoding"); case XML_ERROR_INCORRECT_ENCODING: return XML_L("encoding specified in XML declaration is incorrect"); case XML_ERROR_UNCLOSED_CDATA_SECTION: return XML_L("unclosed CDATA section"); case XML_ERROR_EXTERNAL_ENTITY_HANDLING: return XML_L("error in processing external entity reference"); case XML_ERROR_NOT_STANDALONE: return XML_L("document is not standalone"); case XML_ERROR_UNEXPECTED_STATE: return XML_L("unexpected parser state - please send a bug report"); case XML_ERROR_ENTITY_DECLARED_IN_PE: return XML_L("entity declared in parameter entity"); case XML_ERROR_FEATURE_REQUIRES_XML_DTD: return XML_L("requested feature requires XML_DTD support in Expat"); case XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING: return XML_L("cannot change setting once parsing has begun"); /* Added in 1.95.7. */ case XML_ERROR_UNBOUND_PREFIX: return XML_L("unbound prefix"); /* Added in 1.95.8. */ case XML_ERROR_UNDECLARING_PREFIX: return XML_L("must not undeclare prefix"); case XML_ERROR_INCOMPLETE_PE: return XML_L("incomplete markup in parameter entity"); case XML_ERROR_XML_DECL: return XML_L("XML declaration not well-formed"); case XML_ERROR_TEXT_DECL: return XML_L("text declaration not well-formed"); case XML_ERROR_PUBLICID: return XML_L("illegal character(s) in public id"); case XML_ERROR_SUSPENDED: return XML_L("parser suspended"); case XML_ERROR_NOT_SUSPENDED: return XML_L("parser not suspended"); case XML_ERROR_ABORTED: return XML_L("parsing aborted"); case XML_ERROR_FINISHED: return XML_L("parsing finished"); case XML_ERROR_SUSPEND_PE: return XML_L("cannot suspend in external parameter entity"); /* Added in 2.0.0. */ case XML_ERROR_RESERVED_PREFIX_XML: return XML_L( "reserved prefix (xml) must not be undeclared or bound to another namespace name"); case XML_ERROR_RESERVED_PREFIX_XMLNS: return XML_L("reserved prefix (xmlns) must not be declared or undeclared"); case XML_ERROR_RESERVED_NAMESPACE_URI: return XML_L( "prefix must not be bound to one of the reserved namespace names"); /* Added in 2.2.5. */ case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */ return XML_L("invalid argument"); /* Added in 2.3.0. */ case XML_ERROR_NO_BUFFER: return XML_L( "a successful prior call to function XML_GetBuffer is required"); /* Added in 2.4.0. */ case XML_ERROR_AMPLIFICATION_LIMIT_BREACH: return XML_L( "limit on input amplification factor (from DTD and entities) breached"); } return NULL; } const XML_LChar *XMLCALL XML_ExpatVersion(void) { /* V1 is used to string-ize the version number. However, it would string-ize the actual version macro *names* unless we get them substituted before being passed to V1. CPP is defined to expand a macro, then rescan for more expansions. Thus, we use V2 to expand the version macros, then CPP will expand the resulting V1() macro with the correct numerals. */ /* ### I'm assuming cpp is portable in this respect... */ #define V1(a, b, c) XML_L(#a) XML_L(".") XML_L(#b) XML_L(".") XML_L(#c) #define V2(a, b, c) XML_L("expat_") V1(a, b, c) return V2(XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION); #undef V1 #undef V2 } XML_Expat_Version XMLCALL XML_ExpatVersionInfo(void) { XML_Expat_Version version; version.major = XML_MAJOR_VERSION; version.minor = XML_MINOR_VERSION; version.micro = XML_MICRO_VERSION; return version; } const XML_Feature *XMLCALL XML_GetFeatureList(void) { static const XML_Feature features[] = { {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"), sizeof(XML_Char)}, {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"), sizeof(XML_LChar)}, #ifdef XML_UNICODE {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0}, #endif #ifdef XML_UNICODE_WCHAR_T {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0}, #endif #ifdef XML_DTD {XML_FEATURE_DTD, XML_L("XML_DTD"), 0}, #endif #if XML_CONTEXT_BYTES > 0 {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"), XML_CONTEXT_BYTES}, #endif #ifdef XML_MIN_SIZE {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0}, #endif #ifdef XML_NS {XML_FEATURE_NS, XML_L("XML_NS"), 0}, #endif #ifdef XML_LARGE_SIZE {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0}, #endif #ifdef XML_ATTR_INFO {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0}, #endif #if XML_GE == 1 /* Added in Expat 2.4.0 for XML_DTD defined and * added in Expat 2.6.0 for XML_GE == 1. */ {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT, XML_L("XML_BLAP_MAX_AMP"), (long int) EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT}, {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT, XML_L("XML_BLAP_ACT_THRES"), EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT}, /* Added in Expat 2.6.0. */ {XML_FEATURE_GE, XML_L("XML_GE"), 0}, #endif {XML_FEATURE_END, NULL, 0}}; return features; } #if XML_GE == 1 XML_Bool XMLCALL XML_SetBillionLaughsAttackProtectionMaximumAmplification( XML_Parser parser, float maximumAmplificationFactor) { if ((parser == NULL) || (parser->m_parentParser != NULL) || isnan(maximumAmplificationFactor) || (maximumAmplificationFactor < 1.0f)) { return XML_FALSE; } parser->m_accounting.maximumAmplificationFactor = maximumAmplificationFactor; return XML_TRUE; } XML_Bool XMLCALL XML_SetBillionLaughsAttackProtectionActivationThreshold( XML_Parser parser, unsigned long long activationThresholdBytes) { if ((parser == NULL) || (parser->m_parentParser != NULL)) { return XML_FALSE; } parser->m_accounting.activationThresholdBytes = activationThresholdBytes; return XML_TRUE; } #endif /* XML_GE == 1 */ XML_Bool XMLCALL XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled) { if (parser != NULL && (enabled == XML_TRUE || enabled == XML_FALSE)) { parser->m_reparseDeferralEnabled = enabled; return XML_TRUE; } return XML_FALSE; } /* Initially tag->rawName always points into the parse buffer; for those TAG instances opened while the current parse buffer was processed, and not yet closed, we need to store tag->rawName in a more permanent location, since the parse buffer is about to be discarded. */ static XML_Bool storeRawNames(XML_Parser parser) { TAG *tag = parser->m_tagStack; while (tag) { int bufSize; int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1); size_t rawNameLen; char *rawNameBuf = tag->buf + nameLen; /* Stop if already stored. Since m_tagStack is a stack, we can stop at the first entry that has already been copied; everything below it in the stack is already been accounted for in a previous call to this function. */ if (tag->rawName == rawNameBuf) break; /* For reuse purposes we need to ensure that the size of tag->buf is a multiple of sizeof(XML_Char). */ rawNameLen = ROUND_UP(tag->rawNameLength, sizeof(XML_Char)); /* Detect and prevent integer overflow. */ if (rawNameLen > (size_t)INT_MAX - nameLen) return XML_FALSE; bufSize = nameLen + (int)rawNameLen; if (bufSize > tag->bufEnd - tag->buf) { char *temp = (char *)REALLOC(parser, tag->buf, bufSize); if (temp == NULL) return XML_FALSE; /* if tag->name.str points to tag->buf (only when namespace processing is off) then we have to update it */ if (tag->name.str == (XML_Char *)tag->buf) tag->name.str = (XML_Char *)temp; /* if tag->name.localPart is set (when namespace processing is on) then update it as well, since it will always point into tag->buf */ if (tag->name.localPart) tag->name.localPart = (XML_Char *)temp + (tag->name.localPart - (XML_Char *)tag->buf); tag->buf = temp; tag->bufEnd = temp + bufSize; rawNameBuf = temp + nameLen; } memcpy(rawNameBuf, tag->rawName, tag->rawNameLength); tag->rawName = rawNameBuf; tag = tag->parent; } return XML_TRUE; } static enum XML_Error PTRCALL contentProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { enum XML_Error result = doContent( parser, 0, parser->m_encoding, start, end, endPtr, (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT); if (result == XML_ERROR_NONE) { if (! storeRawNames(parser)) return XML_ERROR_NO_MEMORY; } return result; } static enum XML_Error PTRCALL externalEntityInitProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { enum XML_Error result = initializeEncoding(parser); if (result != XML_ERROR_NONE) return result; parser->m_processor = externalEntityInitProcessor2; return externalEntityInitProcessor2(parser, start, end, endPtr); } static enum XML_Error PTRCALL externalEntityInitProcessor2(XML_Parser parser, const char *start, const char *end, const char **endPtr) { const char *next = start; /* XmlContentTok doesn't always set the last arg */ int tok = XmlContentTok(parser->m_encoding, start, end, &next); switch (tok) { case XML_TOK_BOM: #if XML_GE == 1 if (! accountingDiffTolerated(parser, tok, start, next, __LINE__, XML_ACCOUNT_DIRECT)) { accountingOnAbort(parser); return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; } #endif /* XML_GE == 1 */ /* If we are at the end of the buffer, this would cause the next stage, i.e. externalEntityInitProcessor3, to pass control directly to doContent (by detecting XML_TOK_NONE) without processing any xml text declaration - causing the error XML_ERROR_MISPLACED_XML_PI in doContent. */ if (next == end && ! parser->m_parsingStatus.finalBuffer) { *endPtr = next; return XML_ERROR_NONE; } start = next; break; case XML_TOK_PARTIAL: if (! parser->m_parsingStatus.finalBuffer) { *endPtr = start; return XML_ERROR_NONE; } parser->m_eventPtr = start; return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: if (! parser->m_parsingStatus.finalBuffer) { *endPtr = start; return XML_ERROR_NONE; } parser->m_eventPtr = start; return XML_ERROR_PARTIAL_CHAR; } parser->m_processor = externalEntityInitProcessor3; return externalEntityInitProcessor3(parser, start, end, endPtr); } static enum XML_Error PTRCALL externalEntityInitProcessor3(XML_Parser parser, const char *start, const char *end, const char **endPtr) { int tok; const char *next = start; /* XmlContentTok doesn't always set the last arg */ parser->m_eventPtr = start; tok = XmlContentTok(parser->m_encoding, start, end, &next); /* Note: These bytes are accounted later in: - processXmlDecl - externalEntityContentProcessor */ parser->m_eventEndPtr = next; switch (tok) { case XML_TOK_XML_DECL: { enum XML_Error result; result = processXmlDecl(parser, 1, start, next); if (result != XML_ERROR_NONE) return result; switch (parser->m_parsingStatus.parsing) { case XML_SUSPENDED: *endPtr = next; return XML_ERROR_NONE; case XML_FINISHED: return XML_ERROR_ABORTED; default: start = next; } } break; case XML_TOK_PARTIAL: if (! parser->m_parsingStatus.finalBuffer) { *endPtr = start; return XML_ERROR_NONE; } return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: if (! parser->m_parsingStatus.finalBuffer) { *endPtr = start; return XML_ERROR_NONE; } return XML_ERROR_PARTIAL_CHAR; } parser->m_processor = externalEntityContentProcessor; parser->m_tagLevel = 1; return externalEntityContentProcessor(parser, start, end, endPtr); } static enum XML_Error PTRCALL externalEntityContentProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { enum XML_Error result = doContent(parser, 1, parser->m_encoding, start, end, endPtr, (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_ENTITY_EXPANSION); if (result == XML_ERROR_NONE) { if (! storeRawNames(parser)) return XML_ERROR_NO_MEMORY; } return result; } static enum XML_Error doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc, const char *s, const char *end, const char **nextPtr, XML_Bool haveMore, enum XML_Account account) { /* save one level of indirection */ DTD *const dtd = parser->m_dtd; const char **eventPP; const char **eventEndPP; if (enc == parser->m_encoding) { eventPP = &parser->m_eventPtr; eventEndPP = &parser->m_eventEndPtr; } else { eventPP = &(parser->m_openInternalEntities->internalEventPtr); eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr); } *eventPP = s; for (;;) { const char *next = s; /* XmlContentTok doesn't always set the last arg */ int tok = XmlContentTok(enc, s, end, &next); #if XML_GE == 1 const char *accountAfter = ((tok == XML_TOK_TRAILING_RSQB) || (tok == XML_TOK_TRAILING_CR)) ? (haveMore ? s /* i.e. 0 bytes */ : end) : next; if (! accountingDiffTolerated(parser, tok, s, accountAfter, __LINE__, account)) { accountingOnAbort(parser); return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; } #endif *eventEndPP = next; switch (tok) { case XML_TOK_TRAILING_CR: if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } *eventEndPP = end; if (parser->m_characterDataHandler) { XML_Char c = 0xA; parser->m_characterDataHandler(parser->m_handlerArg, &c, 1); } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, end); /* We are at the end of the final buffer, should we check for XML_SUSPENDED, XML_FINISHED? */ if (startTagLevel == 0) return XML_ERROR_NO_ELEMENTS; if (parser->m_tagLevel != startTagLevel) return XML_ERROR_ASYNC_ENTITY; *nextPtr = end; return XML_ERROR_NONE; case XML_TOK_NONE: if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } if (startTagLevel > 0) { if (parser->m_tagLevel != startTagLevel) return XML_ERROR_ASYNC_ENTITY; *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_NO_ELEMENTS; case XML_TOK_INVALID: *eventPP = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_PARTIAL_CHAR; case XML_TOK_ENTITY_REF: { const XML_Char *name; ENTITY *entity; XML_Char ch = (XML_Char)XmlPredefinedEntityName( enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (ch) { #if XML_GE == 1 /* NOTE: We are replacing 4-6 characters original input for 1 character * so there is no amplification and hence recording without * protection. */ accountingDiffTolerated(parser, tok, (char *)&ch, ((char *)&ch) + sizeof(XML_Char), __LINE__, XML_ACCOUNT_ENTITY_EXPANSION); #endif /* XML_GE == 1 */ if (parser->m_characterDataHandler) parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1); else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); break; } name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (! name) return XML_ERROR_NO_MEMORY; entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0); poolDiscard(&dtd->pool); /* First, determine if a check for an existing declaration is needed; if yes, check that the entity exists, and that it is internal, otherwise call the skipped entity or default handler. */ if (! dtd->hasParamEntityRefs || dtd->standalone) { if (! entity) return XML_ERROR_UNDEFINED_ENTITY; else if (! entity->is_internal) return XML_ERROR_ENTITY_DECLARED_IN_PE; } else if (! entity) { if (parser->m_skippedEntityHandler) parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0); else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); break; } if (entity->open) return XML_ERROR_RECURSIVE_ENTITY_REF; if (entity->notation) return XML_ERROR_BINARY_ENTITY_REF; if (entity->textPtr) { enum XML_Error result; if (! parser->m_defaultExpandInternalEntities) { if (parser->m_skippedEntityHandler) parser->m_skippedEntityHandler(parser->m_handlerArg, entity->name, 0); else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); break; } result = processInternalEntity(parser, entity, XML_FALSE); if (result != XML_ERROR_NONE) return result; } else if (parser->m_externalEntityRefHandler) { const XML_Char *context; entity->open = XML_TRUE; context = getContext(parser); entity->open = XML_FALSE; if (! context) return XML_ERROR_NO_MEMORY; if (! parser->m_externalEntityRefHandler( parser->m_externalEntityRefHandlerArg, context, entity->base, entity->systemId, entity->publicId)) return XML_ERROR_EXTERNAL_ENTITY_HANDLING; poolDiscard(&parser->m_tempPool); } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); break; } case XML_TOK_START_TAG_NO_ATTS: /* fall through */ case XML_TOK_START_TAG_WITH_ATTS: { TAG *tag; enum XML_Error result; XML_Char *toPtr; if (parser->m_freeTagList) { tag = parser->m_freeTagList; parser->m_freeTagList = parser->m_freeTagList->parent; } else { tag = (TAG *)MALLOC(parser, sizeof(TAG)); if (! tag) return XML_ERROR_NO_MEMORY; tag->buf = (char *)MALLOC(parser, INIT_TAG_BUF_SIZE); if (! tag->buf) { FREE(parser, tag); return XML_ERROR_NO_MEMORY; } tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE; } tag->bindings = NULL; tag->parent = parser->m_tagStack; parser->m_tagStack = tag; tag->name.localPart = NULL; tag->name.prefix = NULL; tag->rawName = s + enc->minBytesPerChar; tag->rawNameLength = XmlNameLength(enc, tag->rawName); ++parser->m_tagLevel; { const char *rawNameEnd = tag->rawName + tag->rawNameLength; const char *fromPtr = tag->rawName; toPtr = (XML_Char *)tag->buf; for (;;) { int bufSize; int convLen; const enum XML_Convert_Result convert_res = XmlConvert(enc, &fromPtr, rawNameEnd, (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1); convLen = (int)(toPtr - (XML_Char *)tag->buf); if ((fromPtr >= rawNameEnd) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) { tag->name.strLen = convLen; break; } bufSize = (int)(tag->bufEnd - tag->buf) << 1; { char *temp = (char *)REALLOC(parser, tag->buf, bufSize); if (temp == NULL) return XML_ERROR_NO_MEMORY; tag->buf = temp; tag->bufEnd = temp + bufSize; toPtr = (XML_Char *)temp + convLen; } } } tag->name.str = (XML_Char *)tag->buf; *toPtr = XML_T('\0'); result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings), account); if (result) return result; if (parser->m_startElementHandler) parser->m_startElementHandler(parser->m_handlerArg, tag->name.str, (const XML_Char **)parser->m_atts); else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); poolClear(&parser->m_tempPool); break; } case XML_TOK_EMPTY_ELEMENT_NO_ATTS: /* fall through */ case XML_TOK_EMPTY_ELEMENT_WITH_ATTS: { const char *rawName = s + enc->minBytesPerChar; enum XML_Error result; BINDING *bindings = NULL; XML_Bool noElmHandlers = XML_TRUE; TAG_NAME name; name.str = poolStoreString(&parser->m_tempPool, enc, rawName, rawName + XmlNameLength(enc, rawName)); if (! name.str) return XML_ERROR_NO_MEMORY; poolFinish(&parser->m_tempPool); result = storeAtts(parser, enc, s, &name, &bindings, XML_ACCOUNT_NONE /* token spans whole start tag */); if (result != XML_ERROR_NONE) { freeBindings(parser, bindings); return result; } poolFinish(&parser->m_tempPool); if (parser->m_startElementHandler) { parser->m_startElementHandler(parser->m_handlerArg, name.str, (const XML_Char **)parser->m_atts); noElmHandlers = XML_FALSE; } if (parser->m_endElementHandler) { if (parser->m_startElementHandler) *eventPP = *eventEndPP; parser->m_endElementHandler(parser->m_handlerArg, name.str); noElmHandlers = XML_FALSE; } if (noElmHandlers && parser->m_defaultHandler) reportDefault(parser, enc, s, next); poolClear(&parser->m_tempPool); freeBindings(parser, bindings); } if ((parser->m_tagLevel == 0) && (parser->m_parsingStatus.parsing != XML_FINISHED)) { if (parser->m_parsingStatus.parsing == XML_SUSPENDED) parser->m_processor = epilogProcessor; else return epilogProcessor(parser, next, end, nextPtr); } break; case XML_TOK_END_TAG: if (parser->m_tagLevel == startTagLevel) return XML_ERROR_ASYNC_ENTITY; else { int len; const char *rawName; TAG *tag = parser->m_tagStack; rawName = s + enc->minBytesPerChar * 2; len = XmlNameLength(enc, rawName); if (len != tag->rawNameLength || memcmp(tag->rawName, rawName, len) != 0) { *eventPP = rawName; return XML_ERROR_TAG_MISMATCH; } parser->m_tagStack = tag->parent; tag->parent = parser->m_freeTagList; parser->m_freeTagList = tag; --parser->m_tagLevel; if (parser->m_endElementHandler) { const XML_Char *localPart; const XML_Char *prefix; XML_Char *uri; localPart = tag->name.localPart; if (parser->m_ns && localPart) { /* localPart and prefix may have been overwritten in tag->name.str, since this points to the binding->uri buffer which gets reused; so we have to add them again */ uri = (XML_Char *)tag->name.str + tag->name.uriLen; /* don't need to check for space - already done in storeAtts() */ while (*localPart) *uri++ = *localPart++; prefix = tag->name.prefix; if (parser->m_ns_triplets && prefix) { *uri++ = parser->m_namespaceSeparator; while (*prefix) *uri++ = *prefix++; } *uri = XML_T('\0'); } parser->m_endElementHandler(parser->m_handlerArg, tag->name.str); } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); while (tag->bindings) { BINDING *b = tag->bindings; if (parser->m_endNamespaceDeclHandler) parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name); tag->bindings = tag->bindings->nextTagBinding; b->nextTagBinding = parser->m_freeBindingList; parser->m_freeBindingList = b; b->prefix->binding = b->prevPrefixBinding; } if ((parser->m_tagLevel == 0) && (parser->m_parsingStatus.parsing != XML_FINISHED)) { if (parser->m_parsingStatus.parsing == XML_SUSPENDED) parser->m_processor = epilogProcessor; else return epilogProcessor(parser, next, end, nextPtr); } } break; case XML_TOK_CHAR_REF: { int n = XmlCharRefNumber(enc, s); if (n < 0) return XML_ERROR_BAD_CHAR_REF; if (parser->m_characterDataHandler) { XML_Char buf[XML_ENCODE_MAX]; parser->m_characterDataHandler(parser->m_handlerArg, buf, XmlEncode(n, (ICHAR *)buf)); } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); } break; case XML_TOK_XML_DECL: return XML_ERROR_MISPLACED_XML_PI; case XML_TOK_DATA_NEWLINE: if (parser->m_characterDataHandler) { XML_Char c = 0xA; parser->m_characterDataHandler(parser->m_handlerArg, &c, 1); } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); break; case XML_TOK_CDATA_SECT_OPEN: { enum XML_Error result; if (parser->m_startCdataSectionHandler) parser->m_startCdataSectionHandler(parser->m_handlerArg); /* BEGIN disabled code */ /* Suppose you doing a transformation on a document that involves changing only the character data. You set up a defaultHandler and a characterDataHandler. The defaultHandler simply copies characters through. The characterDataHandler does the transformation and writes the characters out escaping them as necessary. This case will fail to work if we leave out the following two lines (because & and < inside CDATA sections will be incorrectly escaped). However, now we have a start/endCdataSectionHandler, so it seems easier to let the user deal with this. */ else if ((0) && parser->m_characterDataHandler) parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf, 0); /* END disabled code */ else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore, account); if (result != XML_ERROR_NONE) return result; else if (! next) { parser->m_processor = cdataSectionProcessor; return result; } } break; case XML_TOK_TRAILING_RSQB: if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } if (parser->m_characterDataHandler) { if (MUST_CONVERT(enc, s)) { ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf; XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd); parser->m_characterDataHandler( parser->m_handlerArg, parser->m_dataBuf, (int)(dataPtr - (ICHAR *)parser->m_dataBuf)); } else parser->m_characterDataHandler( parser->m_handlerArg, (const XML_Char *)s, (int)((const XML_Char *)end - (const XML_Char *)s)); } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, end); /* We are at the end of the final buffer, should we check for XML_SUSPENDED, XML_FINISHED? */ if (startTagLevel == 0) { *eventPP = end; return XML_ERROR_NO_ELEMENTS; } if (parser->m_tagLevel != startTagLevel) { *eventPP = end; return XML_ERROR_ASYNC_ENTITY; } *nextPtr = end; return XML_ERROR_NONE; case XML_TOK_DATA_CHARS: { XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler; if (charDataHandler) { if (MUST_CONVERT(enc, s)) { for (;;) { ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf; const enum XML_Convert_Result convert_res = XmlConvert( enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd); *eventEndPP = s; charDataHandler(parser->m_handlerArg, parser->m_dataBuf, (int)(dataPtr - (ICHAR *)parser->m_dataBuf)); if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) break; *eventPP = s; } } else charDataHandler(parser->m_handlerArg, (const XML_Char *)s, (int)((const XML_Char *)next - (const XML_Char *)s)); } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); } break; case XML_TOK_PI: if (! reportProcessingInstruction(parser, enc, s, next)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_COMMENT: if (! reportComment(parser, enc, s, next)) return XML_ERROR_NO_MEMORY; break; default: /* All of the tokens produced by XmlContentTok() have their own * explicit cases, so this default is not strictly necessary. * However it is a useful safety net, so we retain the code and * simply exclude it from the coverage tests. * * LCOV_EXCL_START */ if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); break; /* LCOV_EXCL_STOP */ } *eventPP = s = next; switch (parser->m_parsingStatus.parsing) { case XML_SUSPENDED: *nextPtr = next; return XML_ERROR_NONE; case XML_FINISHED: return XML_ERROR_ABORTED; default:; } } /* not reached */ } /* This function does not call free() on the allocated memory, merely * moving it to the parser's m_freeBindingList where it can be freed or * reused as appropriate. */ static void freeBindings(XML_Parser parser, BINDING *bindings) { while (bindings) { BINDING *b = bindings; /* m_startNamespaceDeclHandler will have been called for this * binding in addBindings(), so call the end handler now. */ if (parser->m_endNamespaceDeclHandler) parser->m_endNamespaceDeclHandler(parser->m_handlerArg, b->prefix->name); bindings = bindings->nextTagBinding; b->nextTagBinding = parser->m_freeBindingList; parser->m_freeBindingList = b; b->prefix->binding = b->prevPrefixBinding; } } /* Precondition: all arguments must be non-NULL; Purpose: - normalize attributes - check attributes for well-formedness - generate namespace aware attribute names (URI, prefix) - build list of attributes for startElementHandler - default attributes - process namespace declarations (check and report them) - generate namespace aware element name (URI, prefix) */ static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr, TAG_NAME *tagNamePtr, BINDING **bindingsPtr, enum XML_Account account) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ ELEMENT_TYPE *elementType; int nDefaultAtts; const XML_Char **appAtts; /* the attribute list for the application */ int attIndex = 0; int prefixLen; int i; int n; XML_Char *uri; int nPrefixes = 0; BINDING *binding; const XML_Char *localPart; /* lookup the element type name */ elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, tagNamePtr->str, 0); if (! elementType) { const XML_Char *name = poolCopyString(&dtd->pool, tagNamePtr->str); if (! name) return XML_ERROR_NO_MEMORY; elementType = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE)); if (! elementType) return XML_ERROR_NO_MEMORY; if (parser->m_ns && ! setElementTypePrefix(parser, elementType)) return XML_ERROR_NO_MEMORY; } nDefaultAtts = elementType->nDefaultAtts; /* get the attributes from the tokenizer */ n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts); /* Detect and prevent integer overflow */ if (n > INT_MAX - nDefaultAtts) { return XML_ERROR_NO_MEMORY; } if (n + nDefaultAtts > parser->m_attsSize) { int oldAttsSize = parser->m_attsSize; ATTRIBUTE *temp; #ifdef XML_ATTR_INFO XML_AttrInfo *temp2; #endif /* Detect and prevent integer overflow */ if ((nDefaultAtts > INT_MAX - INIT_ATTS_SIZE) || (n > INT_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) { return XML_ERROR_NO_MEMORY; } parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE; /* Detect and prevent integer overflow. * The preprocessor guard addresses the "always false" warning * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(ATTRIBUTE)) { parser->m_attsSize = oldAttsSize; return XML_ERROR_NO_MEMORY; } #endif temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts, parser->m_attsSize * sizeof(ATTRIBUTE)); if (temp == NULL) { parser->m_attsSize = oldAttsSize; return XML_ERROR_NO_MEMORY; } parser->m_atts = temp; #ifdef XML_ATTR_INFO /* Detect and prevent integer overflow. * The preprocessor guard addresses the "always false" warning * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ # if UINT_MAX >= SIZE_MAX if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(XML_AttrInfo)) { parser->m_attsSize = oldAttsSize; return XML_ERROR_NO_MEMORY; } # endif temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo, parser->m_attsSize * sizeof(XML_AttrInfo)); if (temp2 == NULL) { parser->m_attsSize = oldAttsSize; return XML_ERROR_NO_MEMORY; } parser->m_attInfo = temp2; #endif if (n > oldAttsSize) XmlGetAttributes(enc, attStr, n, parser->m_atts); } appAtts = (const XML_Char **)parser->m_atts; for (i = 0; i < n; i++) { ATTRIBUTE *currAtt = &parser->m_atts[i]; #ifdef XML_ATTR_INFO XML_AttrInfo *currAttInfo = &parser->m_attInfo[i]; #endif /* add the name and value to the attribute list */ ATTRIBUTE_ID *attId = getAttributeId(parser, enc, currAtt->name, currAtt->name + XmlNameLength(enc, currAtt->name)); if (! attId) return XML_ERROR_NO_MEMORY; #ifdef XML_ATTR_INFO currAttInfo->nameStart = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->name); currAttInfo->nameEnd = currAttInfo->nameStart + XmlNameLength(enc, currAtt->name); currAttInfo->valueStart = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->valuePtr); currAttInfo->valueEnd = parser->m_parseEndByteIndex - (parser->m_parseEndPtr - currAtt->valueEnd); #endif /* Detect duplicate attributes by their QNames. This does not work when namespace processing is turned on and different prefixes for the same namespace are used. For this case we have a check further down. */ if ((attId->name)[-1]) { if (enc == parser->m_encoding) parser->m_eventPtr = parser->m_atts[i].name; return XML_ERROR_DUPLICATE_ATTRIBUTE; } (attId->name)[-1] = 1; appAtts[attIndex++] = attId->name; if (! parser->m_atts[i].normalized) { enum XML_Error result; XML_Bool isCdata = XML_TRUE; /* figure out whether declared as other than CDATA */ if (attId->maybeTokenized) { int j; for (j = 0; j < nDefaultAtts; j++) { if (attId == elementType->defaultAtts[j].id) { isCdata = elementType->defaultAtts[j].isCdata; break; } } } /* normalize the attribute value */ result = storeAttributeValue( parser, enc, isCdata, parser->m_atts[i].valuePtr, parser->m_atts[i].valueEnd, &parser->m_tempPool, account); if (result) return result; appAtts[attIndex] = poolStart(&parser->m_tempPool); poolFinish(&parser->m_tempPool); } else { /* the value did not need normalizing */ appAtts[attIndex] = poolStoreString(&parser->m_tempPool, enc, parser->m_atts[i].valuePtr, parser->m_atts[i].valueEnd); if (appAtts[attIndex] == 0) return XML_ERROR_NO_MEMORY; poolFinish(&parser->m_tempPool); } /* handle prefixed attribute names */ if (attId->prefix) { if (attId->xmlns) { /* deal with namespace declarations here */ enum XML_Error result = addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr); if (result) return result; --attIndex; } else { /* deal with other prefixed names later */ attIndex++; nPrefixes++; (attId->name)[-1] = 2; } } else attIndex++; } /* set-up for XML_GetSpecifiedAttributeCount and XML_GetIdAttributeIndex */ parser->m_nSpecifiedAtts = attIndex; if (elementType->idAtt && (elementType->idAtt->name)[-1]) { for (i = 0; i < attIndex; i += 2) if (appAtts[i] == elementType->idAtt->name) { parser->m_idAttIndex = i; break; } } else parser->m_idAttIndex = -1; /* do attribute defaulting */ for (i = 0; i < nDefaultAtts; i++) { const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + i; if (! (da->id->name)[-1] && da->value) { if (da->id->prefix) { if (da->id->xmlns) { enum XML_Error result = addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr); if (result) return result; } else { (da->id->name)[-1] = 2; nPrefixes++; appAtts[attIndex++] = da->id->name; appAtts[attIndex++] = da->value; } } else { (da->id->name)[-1] = 1; appAtts[attIndex++] = da->id->name; appAtts[attIndex++] = da->value; } } } appAtts[attIndex] = 0; /* expand prefixed attribute names, check for duplicates, and clear flags that say whether attributes were specified */ i = 0; if (nPrefixes) { int j; /* hash table index */ unsigned long version = parser->m_nsAttsVersion; /* Detect and prevent invalid shift */ if (parser->m_nsAttsPower >= sizeof(unsigned int) * 8 /* bits per byte */) { return XML_ERROR_NO_MEMORY; } unsigned int nsAttsSize = 1u << parser->m_nsAttsPower; unsigned char oldNsAttsPower = parser->m_nsAttsPower; /* size of hash table must be at least 2 * (# of prefixed attributes) */ if ((nPrefixes << 1) >> parser->m_nsAttsPower) { /* true for m_nsAttsPower = 0 */ NS_ATT *temp; /* hash table size must also be a power of 2 and >= 8 */ while (nPrefixes >> parser->m_nsAttsPower++) ; if (parser->m_nsAttsPower < 3) parser->m_nsAttsPower = 3; /* Detect and prevent invalid shift */ if (parser->m_nsAttsPower >= sizeof(nsAttsSize) * 8 /* bits per byte */) { /* Restore actual size of memory in m_nsAtts */ parser->m_nsAttsPower = oldNsAttsPower; return XML_ERROR_NO_MEMORY; } nsAttsSize = 1u << parser->m_nsAttsPower; /* Detect and prevent integer overflow. * The preprocessor guard addresses the "always false" warning * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX if (nsAttsSize > (size_t)(-1) / sizeof(NS_ATT)) { /* Restore actual size of memory in m_nsAtts */ parser->m_nsAttsPower = oldNsAttsPower; return XML_ERROR_NO_MEMORY; } #endif temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts, nsAttsSize * sizeof(NS_ATT)); if (! temp) { /* Restore actual size of memory in m_nsAtts */ parser->m_nsAttsPower = oldNsAttsPower; return XML_ERROR_NO_MEMORY; } parser->m_nsAtts = temp; version = 0; /* force re-initialization of m_nsAtts hash table */ } /* using a version flag saves us from initializing m_nsAtts every time */ if (! version) { /* initialize version flags when version wraps around */ version = INIT_ATTS_VERSION; for (j = nsAttsSize; j != 0;) parser->m_nsAtts[--j].version = version; } parser->m_nsAttsVersion = --version; /* expand prefixed names and check for duplicates */ for (; i < attIndex; i += 2) { const XML_Char *s = appAtts[i]; if (s[-1] == 2) { /* prefixed */ ATTRIBUTE_ID *id; const BINDING *b; unsigned long uriHash; struct siphash sip_state; struct sipkey sip_key; copy_salt_to_sipkey(parser, &sip_key); sip24_init(&sip_state, &sip_key); ((XML_Char *)s)[-1] = 0; /* clear flag */ id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0); if (! id || ! id->prefix) { /* This code is walking through the appAtts array, dealing * with (in this case) a prefixed attribute name. To be in * the array, the attribute must have already been bound, so * has to have passed through the hash table lookup once * already. That implies that an entry for it already * exists, so the lookup above will return a pointer to * already allocated memory. There is no opportunaity for * the allocator to fail, so the condition above cannot be * fulfilled. * * Since it is difficult to be certain that the above * analysis is complete, we retain the test and merely * remove the code from coverage tests. */ return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */ } b = id->prefix->binding; if (! b) return XML_ERROR_UNBOUND_PREFIX; for (j = 0; j < b->uriLen; j++) { const XML_Char c = b->uri[j]; if (! poolAppendChar(&parser->m_tempPool, c)) return XML_ERROR_NO_MEMORY; } sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char)); while (*s++ != XML_T(ASCII_COLON)) ; sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char)); do { /* copies null terminator */ if (! poolAppendChar(&parser->m_tempPool, *s)) return XML_ERROR_NO_MEMORY; } while (*s++); uriHash = (unsigned long)sip24_final(&sip_state); { /* Check hash table for duplicate of expanded name (uriName). Derived from code in lookup(parser, HASH_TABLE *table, ...). */ unsigned char step = 0; unsigned long mask = nsAttsSize - 1; j = uriHash & mask; /* index into hash table */ while (parser->m_nsAtts[j].version == version) { /* for speed we compare stored hash values first */ if (uriHash == parser->m_nsAtts[j].hash) { const XML_Char *s1 = poolStart(&parser->m_tempPool); const XML_Char *s2 = parser->m_nsAtts[j].uriName; /* s1 is null terminated, but not s2 */ for (; *s1 == *s2 && *s1 != 0; s1++, s2++) ; if (*s1 == 0) return XML_ERROR_DUPLICATE_ATTRIBUTE; } if (! step) step = PROBE_STEP(uriHash, mask, parser->m_nsAttsPower); j < step ? (j += nsAttsSize - step) : (j -= step); } } if (parser->m_ns_triplets) { /* append namespace separator and prefix */ parser->m_tempPool.ptr[-1] = parser->m_namespaceSeparator; s = b->prefix->name; do { if (! poolAppendChar(&parser->m_tempPool, *s)) return XML_ERROR_NO_MEMORY; } while (*s++); } /* store expanded name in attribute list */ s = poolStart(&parser->m_tempPool); poolFinish(&parser->m_tempPool); appAtts[i] = s; /* fill empty slot with new version, uriName and hash value */ parser->m_nsAtts[j].version = version; parser->m_nsAtts[j].hash = uriHash; parser->m_nsAtts[j].uriName = s; if (! --nPrefixes) { i += 2; break; } } else /* not prefixed */ ((XML_Char *)s)[-1] = 0; /* clear flag */ } } /* clear flags for the remaining attributes */ for (; i < attIndex; i += 2) ((XML_Char *)(appAtts[i]))[-1] = 0; for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding) binding->attId->name[-1] = 0; if (! parser->m_ns) return XML_ERROR_NONE; /* expand the element type name */ if (elementType->prefix) { binding = elementType->prefix->binding; if (! binding) return XML_ERROR_UNBOUND_PREFIX; localPart = tagNamePtr->str; while (*localPart++ != XML_T(ASCII_COLON)) ; } else if (dtd->defaultPrefix.binding) { binding = dtd->defaultPrefix.binding; localPart = tagNamePtr->str; } else return XML_ERROR_NONE; prefixLen = 0; if (parser->m_ns_triplets && binding->prefix->name) { for (; binding->prefix->name[prefixLen++];) ; /* prefixLen includes null terminator */ } tagNamePtr->localPart = localPart; tagNamePtr->uriLen = binding->uriLen; tagNamePtr->prefix = binding->prefix->name; tagNamePtr->prefixLen = prefixLen; for (i = 0; localPart[i++];) ; /* i includes null terminator */ /* Detect and prevent integer overflow */ if (binding->uriLen > INT_MAX - prefixLen || i > INT_MAX - (binding->uriLen + prefixLen)) { return XML_ERROR_NO_MEMORY; } n = i + binding->uriLen + prefixLen; if (n > binding->uriAlloc) { TAG *p; /* Detect and prevent integer overflow */ if (n > INT_MAX - EXPAND_SPARE) { return XML_ERROR_NO_MEMORY; } /* Detect and prevent integer overflow. * The preprocessor guard addresses the "always false" warning * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX if ((unsigned)(n + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { return XML_ERROR_NO_MEMORY; } #endif uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char)); if (! uri) return XML_ERROR_NO_MEMORY; binding->uriAlloc = n + EXPAND_SPARE; memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char)); for (p = parser->m_tagStack; p; p = p->parent) if (p->name.str == binding->uri) p->name.str = uri; FREE(parser, binding->uri); binding->uri = uri; } /* if m_namespaceSeparator != '\0' then uri includes it already */ uri = binding->uri + binding->uriLen; memcpy(uri, localPart, i * sizeof(XML_Char)); /* we always have a namespace separator between localPart and prefix */ if (prefixLen) { uri += i - 1; *uri = parser->m_namespaceSeparator; /* replace null terminator */ memcpy(uri + 1, binding->prefix->name, prefixLen * sizeof(XML_Char)); } tagNamePtr->str = binding->uri; return XML_ERROR_NONE; } static XML_Bool is_rfc3986_uri_char(XML_Char candidate) { // For the RFC 3986 ANBF grammar see // https://datatracker.ietf.org/doc/html/rfc3986#appendix-A switch (candidate) { // From rule "ALPHA" (uppercase half) case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': // From rule "ALPHA" (lowercase half) case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': // From rule "DIGIT" case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': // From rule "pct-encoded" case '%': // From rule "unreserved" case '-': case '.': case '_': case '~': // From rule "gen-delims" case ':': case '/': case '?': case '#': case '[': case ']': case '@': // From rule "sub-delims" case '!': case '$': case '&': case '\'': case '(': case ')': case '*': case '+': case ',': case ';': case '=': return XML_TRUE; default: return XML_FALSE; } } /* addBinding() overwrites the value of prefix->binding without checking. Therefore one must keep track of the old value outside of addBinding(). */ static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr) { // "http://www.w3.org/XML/1998/namespace" static const XML_Char xmlNamespace[] = {ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_X, ASCII_M, ASCII_L, ASCII_SLASH, ASCII_1, ASCII_9, ASCII_9, ASCII_8, ASCII_SLASH, ASCII_n, ASCII_a, ASCII_m, ASCII_e, ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'}; static const int xmlLen = (int)sizeof(xmlNamespace) / sizeof(XML_Char) - 1; // "http://www.w3.org/2000/xmlns/" static const XML_Char xmlnsNamespace[] = {ASCII_h, ASCII_t, ASCII_t, ASCII_p, ASCII_COLON, ASCII_SLASH, ASCII_SLASH, ASCII_w, ASCII_w, ASCII_w, ASCII_PERIOD, ASCII_w, ASCII_3, ASCII_PERIOD, ASCII_o, ASCII_r, ASCII_g, ASCII_SLASH, ASCII_2, ASCII_0, ASCII_0, ASCII_0, ASCII_SLASH, ASCII_x, ASCII_m, ASCII_l, ASCII_n, ASCII_s, ASCII_SLASH, '\0'}; static const int xmlnsLen = (int)sizeof(xmlnsNamespace) / sizeof(XML_Char) - 1; XML_Bool mustBeXML = XML_FALSE; XML_Bool isXML = XML_TRUE; XML_Bool isXMLNS = XML_TRUE; BINDING *b; int len; /* empty URI is only valid for default namespace per XML NS 1.0 (not 1.1) */ if (*uri == XML_T('\0') && prefix->name) return XML_ERROR_UNDECLARING_PREFIX; if (prefix->name && prefix->name[0] == XML_T(ASCII_x) && prefix->name[1] == XML_T(ASCII_m) && prefix->name[2] == XML_T(ASCII_l)) { /* Not allowed to bind xmlns */ if (prefix->name[3] == XML_T(ASCII_n) && prefix->name[4] == XML_T(ASCII_s) && prefix->name[5] == XML_T('\0')) return XML_ERROR_RESERVED_PREFIX_XMLNS; if (prefix->name[3] == XML_T('\0')) mustBeXML = XML_TRUE; } for (len = 0; uri[len]; len++) { if (isXML && (len > xmlLen || uri[len] != xmlNamespace[len])) isXML = XML_FALSE; if (! mustBeXML && isXMLNS && (len > xmlnsLen || uri[len] != xmlnsNamespace[len])) isXMLNS = XML_FALSE; // NOTE: While Expat does not validate namespace URIs against RFC 3986 // today (and is not REQUIRED to do so with regard to the XML 1.0 // namespaces specification) we have to at least make sure, that // the application on top of Expat (that is likely splitting expanded // element names ("qualified names") of form // "[uri sep] local [sep prefix] '\0'" back into 1, 2 or 3 pieces // in its element handler code) cannot be confused by an attacker // putting additional namespace separator characters into namespace // declarations. That would be ambiguous and not to be expected. // // While the HTML API docs of function XML_ParserCreateNS have been // advising against use of a namespace separator character that can // appear in a URI for >20 years now, some widespread applications // are using URI characters (':' (colon) in particular) for a // namespace separator, in practice. To keep these applications // functional, we only reject namespaces URIs containing the // application-chosen namespace separator if the chosen separator // is a non-URI character with regard to RFC 3986. if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator) && ! is_rfc3986_uri_char(uri[len])) { return XML_ERROR_SYNTAX; } } isXML = isXML && len == xmlLen; isXMLNS = isXMLNS && len == xmlnsLen; if (mustBeXML != isXML) return mustBeXML ? XML_ERROR_RESERVED_PREFIX_XML : XML_ERROR_RESERVED_NAMESPACE_URI; if (isXMLNS) return XML_ERROR_RESERVED_NAMESPACE_URI; if (parser->m_namespaceSeparator) len++; if (parser->m_freeBindingList) { b = parser->m_freeBindingList; if (len > b->uriAlloc) { /* Detect and prevent integer overflow */ if (len > INT_MAX - EXPAND_SPARE) { return XML_ERROR_NO_MEMORY; } /* Detect and prevent integer overflow. * The preprocessor guard addresses the "always false" warning * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { return XML_ERROR_NO_MEMORY; } #endif XML_Char *temp = (XML_Char *)REALLOC( parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE)); if (temp == NULL) return XML_ERROR_NO_MEMORY; b->uri = temp; b->uriAlloc = len + EXPAND_SPARE; } parser->m_freeBindingList = b->nextTagBinding; } else { b = (BINDING *)MALLOC(parser, sizeof(BINDING)); if (! b) return XML_ERROR_NO_MEMORY; /* Detect and prevent integer overflow */ if (len > INT_MAX - EXPAND_SPARE) { return XML_ERROR_NO_MEMORY; } /* Detect and prevent integer overflow. * The preprocessor guard addresses the "always false" warning * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) { return XML_ERROR_NO_MEMORY; } #endif b->uri = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE)); if (! b->uri) { FREE(parser, b); return XML_ERROR_NO_MEMORY; } b->uriAlloc = len + EXPAND_SPARE; } b->uriLen = len; memcpy(b->uri, uri, len * sizeof(XML_Char)); if (parser->m_namespaceSeparator) b->uri[len - 1] = parser->m_namespaceSeparator; b->prefix = prefix; b->attId = attId; b->prevPrefixBinding = prefix->binding; /* NULL binding when default namespace undeclared */ if (*uri == XML_T('\0') && prefix == &parser->m_dtd->defaultPrefix) prefix->binding = NULL; else prefix->binding = b; b->nextTagBinding = *bindingsPtr; *bindingsPtr = b; /* if attId == NULL then we are not starting a namespace scope */ if (attId && parser->m_startNamespaceDeclHandler) parser->m_startNamespaceDeclHandler(parser->m_handlerArg, prefix->name, prefix->binding ? uri : 0); return XML_ERROR_NONE; } /* The idea here is to avoid using stack for each CDATA section when the whole file is parsed with one call. */ static enum XML_Error PTRCALL cdataSectionProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { enum XML_Error result = doCdataSection( parser, parser->m_encoding, &start, end, endPtr, (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT); if (result != XML_ERROR_NONE) return result; if (start) { if (parser->m_parentParser) { /* we are parsing an external entity */ parser->m_processor = externalEntityContentProcessor; return externalEntityContentProcessor(parser, start, end, endPtr); } else { parser->m_processor = contentProcessor; return contentProcessor(parser, start, end, endPtr); } } return result; } /* startPtr gets set to non-null if the section is closed, and to null if the section is not yet closed. */ static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, const char *end, const char **nextPtr, XML_Bool haveMore, enum XML_Account account) { const char *s = *startPtr; const char **eventPP; const char **eventEndPP; if (enc == parser->m_encoding) { eventPP = &parser->m_eventPtr; *eventPP = s; eventEndPP = &parser->m_eventEndPtr; } else { eventPP = &(parser->m_openInternalEntities->internalEventPtr); eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr); } *eventPP = s; *startPtr = NULL; for (;;) { const char *next = s; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */ int tok = XmlCdataSectionTok(enc, s, end, &next); #if XML_GE == 1 if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) { accountingOnAbort(parser); return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; } #else UNUSED_P(account); #endif *eventEndPP = next; switch (tok) { case XML_TOK_CDATA_SECT_CLOSE: if (parser->m_endCdataSectionHandler) parser->m_endCdataSectionHandler(parser->m_handlerArg); /* BEGIN disabled code */ /* see comment under XML_TOK_CDATA_SECT_OPEN */ else if ((0) && parser->m_characterDataHandler) parser->m_characterDataHandler(parser->m_handlerArg, parser->m_dataBuf, 0); /* END disabled code */ else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); *startPtr = next; *nextPtr = next; if (parser->m_parsingStatus.parsing == XML_FINISHED) return XML_ERROR_ABORTED; else return XML_ERROR_NONE; case XML_TOK_DATA_NEWLINE: if (parser->m_characterDataHandler) { XML_Char c = 0xA; parser->m_characterDataHandler(parser->m_handlerArg, &c, 1); } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); break; case XML_TOK_DATA_CHARS: { XML_CharacterDataHandler charDataHandler = parser->m_characterDataHandler; if (charDataHandler) { if (MUST_CONVERT(enc, s)) { for (;;) { ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf; const enum XML_Convert_Result convert_res = XmlConvert( enc, &s, next, &dataPtr, (ICHAR *)parser->m_dataBufEnd); *eventEndPP = next; charDataHandler(parser->m_handlerArg, parser->m_dataBuf, (int)(dataPtr - (ICHAR *)parser->m_dataBuf)); if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) break; *eventPP = s; } } else charDataHandler(parser->m_handlerArg, (const XML_Char *)s, (int)((const XML_Char *)next - (const XML_Char *)s)); } else if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); } break; case XML_TOK_INVALID: *eventPP = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL_CHAR: if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_PARTIAL_CHAR; case XML_TOK_PARTIAL: case XML_TOK_NONE: if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_UNCLOSED_CDATA_SECTION; default: /* Every token returned by XmlCdataSectionTok() has its own * explicit case, so this default case will never be executed. * We retain it as a safety net and exclude it from the coverage * statistics. * * LCOV_EXCL_START */ *eventPP = next; return XML_ERROR_UNEXPECTED_STATE; /* LCOV_EXCL_STOP */ } *eventPP = s = next; switch (parser->m_parsingStatus.parsing) { case XML_SUSPENDED: *nextPtr = next; return XML_ERROR_NONE; case XML_FINISHED: return XML_ERROR_ABORTED; default:; } } /* not reached */ } #ifdef XML_DTD /* The idea here is to avoid using stack for each IGNORE section when the whole file is parsed with one call. */ static enum XML_Error PTRCALL ignoreSectionProcessor(XML_Parser parser, const char *start, const char *end, const char **endPtr) { enum XML_Error result = doIgnoreSection(parser, parser->m_encoding, &start, end, endPtr, (XML_Bool)! parser->m_parsingStatus.finalBuffer); if (result != XML_ERROR_NONE) return result; if (start) { parser->m_processor = prologProcessor; return prologProcessor(parser, start, end, endPtr); } return result; } /* startPtr gets set to non-null is the section is closed, and to null if the section is not yet closed. */ static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr, const char *end, const char **nextPtr, XML_Bool haveMore) { const char *next = *startPtr; /* in case of XML_TOK_NONE or XML_TOK_PARTIAL */ int tok; const char *s = *startPtr; const char **eventPP; const char **eventEndPP; if (enc == parser->m_encoding) { eventPP = &parser->m_eventPtr; *eventPP = s; eventEndPP = &parser->m_eventEndPtr; } else { /* It's not entirely clear, but it seems the following two lines * of code cannot be executed. The only occasions on which 'enc' * is not 'encoding' are when this function is called * from the internal entity processing, and IGNORE sections are an * error in internal entities. * * Since it really isn't clear that this is true, we keep the code * and just remove it from our coverage tests. * * LCOV_EXCL_START */ eventPP = &(parser->m_openInternalEntities->internalEventPtr); eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr); /* LCOV_EXCL_STOP */ } *eventPP = s; *startPtr = NULL; tok = XmlIgnoreSectionTok(enc, s, end, &next); # if XML_GE == 1 if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, XML_ACCOUNT_DIRECT)) { accountingOnAbort(parser); return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; } # endif *eventEndPP = next; switch (tok) { case XML_TOK_IGNORE_SECT: if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); *startPtr = next; *nextPtr = next; if (parser->m_parsingStatus.parsing == XML_FINISHED) return XML_ERROR_ABORTED; else return XML_ERROR_NONE; case XML_TOK_INVALID: *eventPP = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL_CHAR: if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_PARTIAL_CHAR; case XML_TOK_PARTIAL: case XML_TOK_NONE: if (haveMore) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */ default: /* All of the tokens that XmlIgnoreSectionTok() returns have * explicit cases to handle them, so this default case is never * executed. We keep it as a safety net anyway, and remove it * from our test coverage statistics. * * LCOV_EXCL_START */ *eventPP = next; return XML_ERROR_UNEXPECTED_STATE; /* LCOV_EXCL_STOP */ } /* not reached */ } #endif /* XML_DTD */ static enum XML_Error initializeEncoding(XML_Parser parser) { const char *s; #ifdef XML_UNICODE char encodingBuf[128]; /* See comments about `protocolEncodingName` in parserInit() */ if (! parser->m_protocolEncodingName) s = NULL; else { int i; for (i = 0; parser->m_protocolEncodingName[i]; i++) { if (i == sizeof(encodingBuf) - 1 || (parser->m_protocolEncodingName[i] & ~0x7f) != 0) { encodingBuf[0] = '\0'; break; } encodingBuf[i] = (char)parser->m_protocolEncodingName[i]; } encodingBuf[i] = '\0'; s = encodingBuf; } #else s = parser->m_protocolEncodingName; #endif if ((parser->m_ns ? XmlInitEncodingNS : XmlInitEncoding)( &parser->m_initEncoding, &parser->m_encoding, s)) return XML_ERROR_NONE; return handleUnknownEncoding(parser, parser->m_protocolEncodingName); } static enum XML_Error processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s, const char *next) { const char *encodingName = NULL; const XML_Char *storedEncName = NULL; const ENCODING *newEncoding = NULL; const char *version = NULL; const char *versionend = NULL; const XML_Char *storedversion = NULL; int standalone = -1; #if XML_GE == 1 if (! accountingDiffTolerated(parser, XML_TOK_XML_DECL, s, next, __LINE__, XML_ACCOUNT_DIRECT)) { accountingOnAbort(parser); return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; } #endif if (! (parser->m_ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)( isGeneralTextEntity, parser->m_encoding, s, next, &parser->m_eventPtr, &version, &versionend, &encodingName, &newEncoding, &standalone)) { if (isGeneralTextEntity) return XML_ERROR_TEXT_DECL; else return XML_ERROR_XML_DECL; } if (! isGeneralTextEntity && standalone == 1) { parser->m_dtd->standalone = XML_TRUE; #ifdef XML_DTD if (parser->m_paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE) parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; #endif /* XML_DTD */ } if (parser->m_xmlDeclHandler) { if (encodingName != NULL) { storedEncName = poolStoreString( &parser->m_temp2Pool, parser->m_encoding, encodingName, encodingName + XmlNameLength(parser->m_encoding, encodingName)); if (! storedEncName) return XML_ERROR_NO_MEMORY; poolFinish(&parser->m_temp2Pool); } if (version) { storedversion = poolStoreString(&parser->m_temp2Pool, parser->m_encoding, version, versionend - parser->m_encoding->minBytesPerChar); if (! storedversion) return XML_ERROR_NO_MEMORY; } parser->m_xmlDeclHandler(parser->m_handlerArg, storedversion, storedEncName, standalone); } else if (parser->m_defaultHandler) reportDefault(parser, parser->m_encoding, s, next); if (parser->m_protocolEncodingName == NULL) { if (newEncoding) { /* Check that the specified encoding does not conflict with what * the parser has already deduced. Do we have the same number * of bytes in the smallest representation of a character? If * this is UTF-16, is it the same endianness? */ if (newEncoding->minBytesPerChar != parser->m_encoding->minBytesPerChar || (newEncoding->minBytesPerChar == 2 && newEncoding != parser->m_encoding)) { parser->m_eventPtr = encodingName; return XML_ERROR_INCORRECT_ENCODING; } parser->m_encoding = newEncoding; } else if (encodingName) { enum XML_Error result; if (! storedEncName) { storedEncName = poolStoreString( &parser->m_temp2Pool, parser->m_encoding, encodingName, encodingName + XmlNameLength(parser->m_encoding, encodingName)); if (! storedEncName) return XML_ERROR_NO_MEMORY; } result = handleUnknownEncoding(parser, storedEncName); poolClear(&parser->m_temp2Pool); if (result == XML_ERROR_UNKNOWN_ENCODING) parser->m_eventPtr = encodingName; return result; } } if (storedEncName || storedversion) poolClear(&parser->m_temp2Pool); return XML_ERROR_NONE; } static enum XML_Error handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName) { if (parser->m_unknownEncodingHandler) { XML_Encoding info; int i; for (i = 0; i < 256; i++) info.map[i] = -1; info.convert = NULL; info.data = NULL; info.release = NULL; if (parser->m_unknownEncodingHandler(parser->m_unknownEncodingHandlerData, encodingName, &info)) { ENCODING *enc; parser->m_unknownEncodingMem = MALLOC(parser, XmlSizeOfUnknownEncoding()); if (! parser->m_unknownEncodingMem) { if (info.release) info.release(info.data); return XML_ERROR_NO_MEMORY; } enc = (parser->m_ns ? XmlInitUnknownEncodingNS : XmlInitUnknownEncoding)( parser->m_unknownEncodingMem, info.map, info.convert, info.data); if (enc) { parser->m_unknownEncodingData = info.data; parser->m_unknownEncodingRelease = info.release; parser->m_encoding = enc; return XML_ERROR_NONE; } } if (info.release != NULL) info.release(info.data); } return XML_ERROR_UNKNOWN_ENCODING; } static enum XML_Error PTRCALL prologInitProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { enum XML_Error result = initializeEncoding(parser); if (result != XML_ERROR_NONE) return result; parser->m_processor = prologProcessor; return prologProcessor(parser, s, end, nextPtr); } #ifdef XML_DTD static enum XML_Error PTRCALL externalParEntInitProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { enum XML_Error result = initializeEncoding(parser); if (result != XML_ERROR_NONE) return result; /* we know now that XML_Parse(Buffer) has been called, so we consider the external parameter entity read */ parser->m_dtd->paramEntityRead = XML_TRUE; if (parser->m_prologState.inEntityValue) { parser->m_processor = entityValueInitProcessor; return entityValueInitProcessor(parser, s, end, nextPtr); } else { parser->m_processor = externalParEntProcessor; return externalParEntProcessor(parser, s, end, nextPtr); } } static enum XML_Error PTRCALL entityValueInitProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { int tok; const char *start = s; const char *next = start; parser->m_eventPtr = start; for (;;) { tok = XmlPrologTok(parser->m_encoding, start, end, &next); /* Note: Except for XML_TOK_BOM below, these bytes are accounted later in: - storeEntityValue - processXmlDecl */ parser->m_eventEndPtr = next; if (tok <= 0) { if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) { *nextPtr = s; return XML_ERROR_NONE; } switch (tok) { case XML_TOK_INVALID: return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: return XML_ERROR_PARTIAL_CHAR; case XML_TOK_NONE: /* start == end */ default: break; } /* found end of entity value - can store it now */ return storeEntityValue(parser, parser->m_encoding, s, end, XML_ACCOUNT_DIRECT); } else if (tok == XML_TOK_XML_DECL) { enum XML_Error result; result = processXmlDecl(parser, 0, start, next); if (result != XML_ERROR_NONE) return result; /* At this point, m_parsingStatus.parsing cannot be XML_SUSPENDED. For * that to happen, a parameter entity parsing handler must have attempted * to suspend the parser, which fails and raises an error. The parser can * be aborted, but can't be suspended. */ if (parser->m_parsingStatus.parsing == XML_FINISHED) return XML_ERROR_ABORTED; *nextPtr = next; /* stop scanning for text declaration - we found one */ parser->m_processor = entityValueProcessor; return entityValueProcessor(parser, next, end, nextPtr); } /* XmlPrologTok has now set the encoding based on the BOM it found, and we must move s and nextPtr forward to consume the BOM. If we didn't, and got XML_TOK_NONE from the next XmlPrologTok call, we would leave the BOM in the buffer and return. On the next call to this function, our XmlPrologTok call would return XML_TOK_INVALID, since it is not valid to have multiple BOMs. */ else if (tok == XML_TOK_BOM) { # if XML_GE == 1 if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, XML_ACCOUNT_DIRECT)) { accountingOnAbort(parser); return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; } # endif *nextPtr = next; s = next; } /* If we get this token, we have the start of what might be a normal tag, but not a declaration (i.e. it doesn't begin with "m_eventPtr = start; } } static enum XML_Error PTRCALL externalParEntProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { const char *next = s; int tok; tok = XmlPrologTok(parser->m_encoding, s, end, &next); if (tok <= 0) { if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) { *nextPtr = s; return XML_ERROR_NONE; } switch (tok) { case XML_TOK_INVALID: return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: return XML_ERROR_PARTIAL_CHAR; case XML_TOK_NONE: /* start == end */ default: break; } } /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM. However, when parsing an external subset, doProlog will not accept a BOM as valid, and report a syntax error, so we have to skip the BOM, and account for the BOM bytes. */ else if (tok == XML_TOK_BOM) { if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, XML_ACCOUNT_DIRECT)) { accountingOnAbort(parser); return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; } s = next; tok = XmlPrologTok(parser->m_encoding, s, end, &next); } parser->m_processor = prologProcessor; return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr, (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE, XML_ACCOUNT_DIRECT); } static enum XML_Error PTRCALL entityValueProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { const char *start = s; const char *next = s; const ENCODING *enc = parser->m_encoding; int tok; for (;;) { tok = XmlPrologTok(enc, start, end, &next); /* Note: These bytes are accounted later in: - storeEntityValue */ if (tok <= 0) { if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) { *nextPtr = s; return XML_ERROR_NONE; } switch (tok) { case XML_TOK_INVALID: return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: return XML_ERROR_PARTIAL_CHAR; case XML_TOK_NONE: /* start == end */ default: break; } /* found end of entity value - can store it now */ return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT); } start = next; } } #endif /* XML_DTD */ static enum XML_Error PTRCALL prologProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { const char *next = s; int tok = XmlPrologTok(parser->m_encoding, s, end, &next); return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr, (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE, XML_ACCOUNT_DIRECT); } static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end, int tok, const char *next, const char **nextPtr, XML_Bool haveMore, XML_Bool allowClosingDoctype, enum XML_Account account) { #ifdef XML_DTD static const XML_Char externalSubsetName[] = {ASCII_HASH, '\0'}; #endif /* XML_DTD */ static const XML_Char atypeCDATA[] = {ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0'}; static const XML_Char atypeID[] = {ASCII_I, ASCII_D, '\0'}; static const XML_Char atypeIDREF[] = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0'}; static const XML_Char atypeIDREFS[] = {ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0'}; static const XML_Char atypeENTITY[] = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0'}; static const XML_Char atypeENTITIES[] = {ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0'}; static const XML_Char atypeNMTOKEN[] = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0'}; static const XML_Char atypeNMTOKENS[] = {ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0'}; static const XML_Char notationPrefix[] = {ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, ASCII_LPAREN, '\0'}; static const XML_Char enumValueSep[] = {ASCII_PIPE, '\0'}; static const XML_Char enumValueStart[] = {ASCII_LPAREN, '\0'}; #ifndef XML_DTD UNUSED_P(account); #endif /* save one level of indirection */ DTD *const dtd = parser->m_dtd; const char **eventPP; const char **eventEndPP; enum XML_Content_Quant quant; if (enc == parser->m_encoding) { eventPP = &parser->m_eventPtr; eventEndPP = &parser->m_eventEndPtr; } else { eventPP = &(parser->m_openInternalEntities->internalEventPtr); eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr); } for (;;) { int role; XML_Bool handleDefault = XML_TRUE; *eventPP = s; *eventEndPP = next; if (tok <= 0) { if (haveMore && tok != XML_TOK_INVALID) { *nextPtr = s; return XML_ERROR_NONE; } switch (tok) { case XML_TOK_INVALID: *eventPP = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: return XML_ERROR_PARTIAL_CHAR; case -XML_TOK_PROLOG_S: tok = -tok; break; case XML_TOK_NONE: #ifdef XML_DTD /* for internal PE NOT referenced between declarations */ if (enc != parser->m_encoding && ! parser->m_openInternalEntities->betweenDecl) { *nextPtr = s; return XML_ERROR_NONE; } /* WFC: PE Between Declarations - must check that PE contains complete markup, not only for external PEs, but also for internal PEs if the reference occurs between declarations. */ if (parser->m_isParamEntity || enc != parser->m_encoding) { if (XmlTokenRole(&parser->m_prologState, XML_TOK_NONE, end, end, enc) == XML_ROLE_ERROR) return XML_ERROR_INCOMPLETE_PE; *nextPtr = s; return XML_ERROR_NONE; } #endif /* XML_DTD */ return XML_ERROR_NO_ELEMENTS; default: tok = -tok; next = end; break; } } role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc); #if XML_GE == 1 switch (role) { case XML_ROLE_INSTANCE_START: // bytes accounted in contentProcessor case XML_ROLE_XML_DECL: // bytes accounted in processXmlDecl # ifdef XML_DTD case XML_ROLE_TEXT_DECL: // bytes accounted in processXmlDecl # endif break; default: if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) { accountingOnAbort(parser); return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; } } #endif switch (role) { case XML_ROLE_XML_DECL: { enum XML_Error result = processXmlDecl(parser, 0, s, next); if (result != XML_ERROR_NONE) return result; enc = parser->m_encoding; handleDefault = XML_FALSE; } break; case XML_ROLE_DOCTYPE_NAME: if (parser->m_startDoctypeDeclHandler) { parser->m_doctypeName = poolStoreString(&parser->m_tempPool, enc, s, next); if (! parser->m_doctypeName) return XML_ERROR_NO_MEMORY; poolFinish(&parser->m_tempPool); parser->m_doctypePubid = NULL; handleDefault = XML_FALSE; } parser->m_doctypeSysid = NULL; /* always initialize to NULL */ break; case XML_ROLE_DOCTYPE_INTERNAL_SUBSET: if (parser->m_startDoctypeDeclHandler) { parser->m_startDoctypeDeclHandler( parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid, parser->m_doctypePubid, 1); parser->m_doctypeName = NULL; poolClear(&parser->m_tempPool); handleDefault = XML_FALSE; } break; #ifdef XML_DTD case XML_ROLE_TEXT_DECL: { enum XML_Error result = processXmlDecl(parser, 1, s, next); if (result != XML_ERROR_NONE) return result; enc = parser->m_encoding; handleDefault = XML_FALSE; } break; #endif /* XML_DTD */ case XML_ROLE_DOCTYPE_PUBLIC_ID: #ifdef XML_DTD parser->m_useForeignDTD = XML_FALSE; parser->m_declEntity = (ENTITY *)lookup( parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY)); if (! parser->m_declEntity) return XML_ERROR_NO_MEMORY; #endif /* XML_DTD */ dtd->hasParamEntityRefs = XML_TRUE; if (parser->m_startDoctypeDeclHandler) { XML_Char *pubId; if (! XmlIsPublicId(enc, s, next, eventPP)) return XML_ERROR_PUBLICID; pubId = poolStoreString(&parser->m_tempPool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (! pubId) return XML_ERROR_NO_MEMORY; normalizePublicId(pubId); poolFinish(&parser->m_tempPool); parser->m_doctypePubid = pubId; handleDefault = XML_FALSE; goto alreadyChecked; } /* fall through */ case XML_ROLE_ENTITY_PUBLIC_ID: if (! XmlIsPublicId(enc, s, next, eventPP)) return XML_ERROR_PUBLICID; alreadyChecked: if (dtd->keepProcessing && parser->m_declEntity) { XML_Char *tem = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (! tem) return XML_ERROR_NO_MEMORY; normalizePublicId(tem); parser->m_declEntity->publicId = tem; poolFinish(&dtd->pool); /* Don't suppress the default handler if we fell through from * the XML_ROLE_DOCTYPE_PUBLIC_ID case. */ if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_PUBLIC_ID) handleDefault = XML_FALSE; } break; case XML_ROLE_DOCTYPE_CLOSE: if (allowClosingDoctype != XML_TRUE) { /* Must not close doctype from within expanded parameter entities */ return XML_ERROR_INVALID_TOKEN; } if (parser->m_doctypeName) { parser->m_startDoctypeDeclHandler( parser->m_handlerArg, parser->m_doctypeName, parser->m_doctypeSysid, parser->m_doctypePubid, 0); poolClear(&parser->m_tempPool); handleDefault = XML_FALSE; } /* parser->m_doctypeSysid will be non-NULL in the case of a previous XML_ROLE_DOCTYPE_SYSTEM_ID, even if parser->m_startDoctypeDeclHandler was not set, indicating an external subset */ #ifdef XML_DTD if (parser->m_doctypeSysid || parser->m_useForeignDTD) { XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs; dtd->hasParamEntityRefs = XML_TRUE; if (parser->m_paramEntityParsing && parser->m_externalEntityRefHandler) { ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY)); if (! entity) { /* The external subset name "#" will have already been * inserted into the hash table at the start of the * external entity parsing, so no allocation will happen * and lookup() cannot fail. */ return XML_ERROR_NO_MEMORY; /* LCOV_EXCL_LINE */ } if (parser->m_useForeignDTD) entity->base = parser->m_curBase; dtd->paramEntityRead = XML_FALSE; if (! parser->m_externalEntityRefHandler( parser->m_externalEntityRefHandlerArg, 0, entity->base, entity->systemId, entity->publicId)) return XML_ERROR_EXTERNAL_ENTITY_HANDLING; if (dtd->paramEntityRead) { if (! dtd->standalone && parser->m_notStandaloneHandler && ! parser->m_notStandaloneHandler(parser->m_handlerArg)) return XML_ERROR_NOT_STANDALONE; } /* if we didn't read the foreign DTD then this means that there is no external subset and we must reset dtd->hasParamEntityRefs */ else if (! parser->m_doctypeSysid) dtd->hasParamEntityRefs = hadParamEntityRefs; /* end of DTD - no need to update dtd->keepProcessing */ } parser->m_useForeignDTD = XML_FALSE; } #endif /* XML_DTD */ if (parser->m_endDoctypeDeclHandler) { parser->m_endDoctypeDeclHandler(parser->m_handlerArg); handleDefault = XML_FALSE; } break; case XML_ROLE_INSTANCE_START: #ifdef XML_DTD /* if there is no DOCTYPE declaration then now is the last chance to read the foreign DTD */ if (parser->m_useForeignDTD) { XML_Bool hadParamEntityRefs = dtd->hasParamEntityRefs; dtd->hasParamEntityRefs = XML_TRUE; if (parser->m_paramEntityParsing && parser->m_externalEntityRefHandler) { ENTITY *entity = (ENTITY *)lookup(parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY)); if (! entity) return XML_ERROR_NO_MEMORY; entity->base = parser->m_curBase; dtd->paramEntityRead = XML_FALSE; if (! parser->m_externalEntityRefHandler( parser->m_externalEntityRefHandlerArg, 0, entity->base, entity->systemId, entity->publicId)) return XML_ERROR_EXTERNAL_ENTITY_HANDLING; if (dtd->paramEntityRead) { if (! dtd->standalone && parser->m_notStandaloneHandler && ! parser->m_notStandaloneHandler(parser->m_handlerArg)) return XML_ERROR_NOT_STANDALONE; } /* if we didn't read the foreign DTD then this means that there is no external subset and we must reset dtd->hasParamEntityRefs */ else dtd->hasParamEntityRefs = hadParamEntityRefs; /* end of DTD - no need to update dtd->keepProcessing */ } } #endif /* XML_DTD */ parser->m_processor = contentProcessor; return contentProcessor(parser, s, end, nextPtr); case XML_ROLE_ATTLIST_ELEMENT_NAME: parser->m_declElementType = getElementType(parser, enc, s, next); if (! parser->m_declElementType) return XML_ERROR_NO_MEMORY; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_NAME: parser->m_declAttributeId = getAttributeId(parser, enc, s, next); if (! parser->m_declAttributeId) return XML_ERROR_NO_MEMORY; parser->m_declAttributeIsCdata = XML_FALSE; parser->m_declAttributeType = NULL; parser->m_declAttributeIsId = XML_FALSE; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_CDATA: parser->m_declAttributeIsCdata = XML_TRUE; parser->m_declAttributeType = atypeCDATA; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_ID: parser->m_declAttributeIsId = XML_TRUE; parser->m_declAttributeType = atypeID; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_IDREF: parser->m_declAttributeType = atypeIDREF; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_IDREFS: parser->m_declAttributeType = atypeIDREFS; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_ENTITY: parser->m_declAttributeType = atypeENTITY; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES: parser->m_declAttributeType = atypeENTITIES; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN: parser->m_declAttributeType = atypeNMTOKEN; goto checkAttListDeclHandler; case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS: parser->m_declAttributeType = atypeNMTOKENS; checkAttListDeclHandler: if (dtd->keepProcessing && parser->m_attlistDeclHandler) handleDefault = XML_FALSE; break; case XML_ROLE_ATTRIBUTE_ENUM_VALUE: case XML_ROLE_ATTRIBUTE_NOTATION_VALUE: if (dtd->keepProcessing && parser->m_attlistDeclHandler) { const XML_Char *prefix; if (parser->m_declAttributeType) { prefix = enumValueSep; } else { prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE ? notationPrefix : enumValueStart); } if (! poolAppendString(&parser->m_tempPool, prefix)) return XML_ERROR_NO_MEMORY; if (! poolAppend(&parser->m_tempPool, enc, s, next)) return XML_ERROR_NO_MEMORY; parser->m_declAttributeType = parser->m_tempPool.start; handleDefault = XML_FALSE; } break; case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE: case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE: if (dtd->keepProcessing) { if (! defineAttribute(parser->m_declElementType, parser->m_declAttributeId, parser->m_declAttributeIsCdata, parser->m_declAttributeIsId, 0, parser)) return XML_ERROR_NO_MEMORY; if (parser->m_attlistDeclHandler && parser->m_declAttributeType) { if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN) || (*parser->m_declAttributeType == XML_T(ASCII_N) && parser->m_declAttributeType[1] == XML_T(ASCII_O))) { /* Enumerated or Notation type */ if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN)) || ! poolAppendChar(&parser->m_tempPool, XML_T('\0'))) return XML_ERROR_NO_MEMORY; parser->m_declAttributeType = parser->m_tempPool.start; poolFinish(&parser->m_tempPool); } *eventEndPP = s; parser->m_attlistDeclHandler( parser->m_handlerArg, parser->m_declElementType->name, parser->m_declAttributeId->name, parser->m_declAttributeType, 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE); handleDefault = XML_FALSE; } } poolClear(&parser->m_tempPool); break; case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE: case XML_ROLE_FIXED_ATTRIBUTE_VALUE: if (dtd->keepProcessing) { const XML_Char *attVal; enum XML_Error result = storeAttributeValue( parser, enc, parser->m_declAttributeIsCdata, s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool, XML_ACCOUNT_NONE); if (result) return result; attVal = poolStart(&dtd->pool); poolFinish(&dtd->pool); /* ID attributes aren't allowed to have a default */ if (! defineAttribute( parser->m_declElementType, parser->m_declAttributeId, parser->m_declAttributeIsCdata, XML_FALSE, attVal, parser)) return XML_ERROR_NO_MEMORY; if (parser->m_attlistDeclHandler && parser->m_declAttributeType) { if (*parser->m_declAttributeType == XML_T(ASCII_LPAREN) || (*parser->m_declAttributeType == XML_T(ASCII_N) && parser->m_declAttributeType[1] == XML_T(ASCII_O))) { /* Enumerated or Notation type */ if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_RPAREN)) || ! poolAppendChar(&parser->m_tempPool, XML_T('\0'))) return XML_ERROR_NO_MEMORY; parser->m_declAttributeType = parser->m_tempPool.start; poolFinish(&parser->m_tempPool); } *eventEndPP = s; parser->m_attlistDeclHandler( parser->m_handlerArg, parser->m_declElementType->name, parser->m_declAttributeId->name, parser->m_declAttributeType, attVal, role == XML_ROLE_FIXED_ATTRIBUTE_VALUE); poolClear(&parser->m_tempPool); handleDefault = XML_FALSE; } } break; case XML_ROLE_ENTITY_VALUE: if (dtd->keepProcessing) { #if XML_GE == 1 // This will store the given replacement text in // parser->m_declEntity->textPtr. enum XML_Error result = storeEntityValue(parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar, XML_ACCOUNT_NONE); if (parser->m_declEntity) { parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool); parser->m_declEntity->textLen = (int)(poolLength(&dtd->entityValuePool)); poolFinish(&dtd->entityValuePool); if (parser->m_entityDeclHandler) { *eventEndPP = s; parser->m_entityDeclHandler( parser->m_handlerArg, parser->m_declEntity->name, parser->m_declEntity->is_param, parser->m_declEntity->textPtr, parser->m_declEntity->textLen, parser->m_curBase, 0, 0, 0); handleDefault = XML_FALSE; } } else poolDiscard(&dtd->entityValuePool); if (result != XML_ERROR_NONE) return result; #else // This will store "&entity123;" in parser->m_declEntity->textPtr // to end up as "&entity123;" in the handler. if (parser->m_declEntity != NULL) { const enum XML_Error result = storeSelfEntityValue(parser, parser->m_declEntity); if (result != XML_ERROR_NONE) return result; if (parser->m_entityDeclHandler) { *eventEndPP = s; parser->m_entityDeclHandler( parser->m_handlerArg, parser->m_declEntity->name, parser->m_declEntity->is_param, parser->m_declEntity->textPtr, parser->m_declEntity->textLen, parser->m_curBase, 0, 0, 0); handleDefault = XML_FALSE; } } #endif } break; case XML_ROLE_DOCTYPE_SYSTEM_ID: #ifdef XML_DTD parser->m_useForeignDTD = XML_FALSE; #endif /* XML_DTD */ dtd->hasParamEntityRefs = XML_TRUE; if (parser->m_startDoctypeDeclHandler) { parser->m_doctypeSysid = poolStoreString(&parser->m_tempPool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (parser->m_doctypeSysid == NULL) return XML_ERROR_NO_MEMORY; poolFinish(&parser->m_tempPool); handleDefault = XML_FALSE; } #ifdef XML_DTD else /* use externalSubsetName to make parser->m_doctypeSysid non-NULL for the case where no parser->m_startDoctypeDeclHandler is set */ parser->m_doctypeSysid = externalSubsetName; #endif /* XML_DTD */ if (! dtd->standalone #ifdef XML_DTD && ! parser->m_paramEntityParsing #endif /* XML_DTD */ && parser->m_notStandaloneHandler && ! parser->m_notStandaloneHandler(parser->m_handlerArg)) return XML_ERROR_NOT_STANDALONE; #ifndef XML_DTD break; #else /* XML_DTD */ if (! parser->m_declEntity) { parser->m_declEntity = (ENTITY *)lookup( parser, &dtd->paramEntities, externalSubsetName, sizeof(ENTITY)); if (! parser->m_declEntity) return XML_ERROR_NO_MEMORY; parser->m_declEntity->publicId = NULL; } #endif /* XML_DTD */ /* fall through */ case XML_ROLE_ENTITY_SYSTEM_ID: if (dtd->keepProcessing && parser->m_declEntity) { parser->m_declEntity->systemId = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (! parser->m_declEntity->systemId) return XML_ERROR_NO_MEMORY; parser->m_declEntity->base = parser->m_curBase; poolFinish(&dtd->pool); /* Don't suppress the default handler if we fell through from * the XML_ROLE_DOCTYPE_SYSTEM_ID case. */ if (parser->m_entityDeclHandler && role == XML_ROLE_ENTITY_SYSTEM_ID) handleDefault = XML_FALSE; } break; case XML_ROLE_ENTITY_COMPLETE: #if XML_GE == 0 // This will store "&entity123;" in entity->textPtr // to end up as "&entity123;" in the handler. if (parser->m_declEntity != NULL) { const enum XML_Error result = storeSelfEntityValue(parser, parser->m_declEntity); if (result != XML_ERROR_NONE) return result; } #endif if (dtd->keepProcessing && parser->m_declEntity && parser->m_entityDeclHandler) { *eventEndPP = s; parser->m_entityDeclHandler( parser->m_handlerArg, parser->m_declEntity->name, parser->m_declEntity->is_param, 0, 0, parser->m_declEntity->base, parser->m_declEntity->systemId, parser->m_declEntity->publicId, 0); handleDefault = XML_FALSE; } break; case XML_ROLE_ENTITY_NOTATION_NAME: if (dtd->keepProcessing && parser->m_declEntity) { parser->m_declEntity->notation = poolStoreString(&dtd->pool, enc, s, next); if (! parser->m_declEntity->notation) return XML_ERROR_NO_MEMORY; poolFinish(&dtd->pool); if (parser->m_unparsedEntityDeclHandler) { *eventEndPP = s; parser->m_unparsedEntityDeclHandler( parser->m_handlerArg, parser->m_declEntity->name, parser->m_declEntity->base, parser->m_declEntity->systemId, parser->m_declEntity->publicId, parser->m_declEntity->notation); handleDefault = XML_FALSE; } else if (parser->m_entityDeclHandler) { *eventEndPP = s; parser->m_entityDeclHandler( parser->m_handlerArg, parser->m_declEntity->name, 0, 0, 0, parser->m_declEntity->base, parser->m_declEntity->systemId, parser->m_declEntity->publicId, parser->m_declEntity->notation); handleDefault = XML_FALSE; } } break; case XML_ROLE_GENERAL_ENTITY_NAME: { if (XmlPredefinedEntityName(enc, s, next)) { parser->m_declEntity = NULL; break; } if (dtd->keepProcessing) { const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); if (! name) return XML_ERROR_NO_MEMORY; parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, sizeof(ENTITY)); if (! parser->m_declEntity) return XML_ERROR_NO_MEMORY; if (parser->m_declEntity->name != name) { poolDiscard(&dtd->pool); parser->m_declEntity = NULL; } else { poolFinish(&dtd->pool); parser->m_declEntity->publicId = NULL; parser->m_declEntity->is_param = XML_FALSE; /* if we have a parent parser or are reading an internal parameter entity, then the entity declaration is not considered "internal" */ parser->m_declEntity->is_internal = ! (parser->m_parentParser || parser->m_openInternalEntities); if (parser->m_entityDeclHandler) handleDefault = XML_FALSE; } } else { poolDiscard(&dtd->pool); parser->m_declEntity = NULL; } } break; case XML_ROLE_PARAM_ENTITY_NAME: #ifdef XML_DTD if (dtd->keepProcessing) { const XML_Char *name = poolStoreString(&dtd->pool, enc, s, next); if (! name) return XML_ERROR_NO_MEMORY; parser->m_declEntity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, sizeof(ENTITY)); if (! parser->m_declEntity) return XML_ERROR_NO_MEMORY; if (parser->m_declEntity->name != name) { poolDiscard(&dtd->pool); parser->m_declEntity = NULL; } else { poolFinish(&dtd->pool); parser->m_declEntity->publicId = NULL; parser->m_declEntity->is_param = XML_TRUE; /* if we have a parent parser or are reading an internal parameter entity, then the entity declaration is not considered "internal" */ parser->m_declEntity->is_internal = ! (parser->m_parentParser || parser->m_openInternalEntities); if (parser->m_entityDeclHandler) handleDefault = XML_FALSE; } } else { poolDiscard(&dtd->pool); parser->m_declEntity = NULL; } #else /* not XML_DTD */ parser->m_declEntity = NULL; #endif /* XML_DTD */ break; case XML_ROLE_NOTATION_NAME: parser->m_declNotationPublicId = NULL; parser->m_declNotationName = NULL; if (parser->m_notationDeclHandler) { parser->m_declNotationName = poolStoreString(&parser->m_tempPool, enc, s, next); if (! parser->m_declNotationName) return XML_ERROR_NO_MEMORY; poolFinish(&parser->m_tempPool); handleDefault = XML_FALSE; } break; case XML_ROLE_NOTATION_PUBLIC_ID: if (! XmlIsPublicId(enc, s, next, eventPP)) return XML_ERROR_PUBLICID; if (parser ->m_declNotationName) { /* means m_notationDeclHandler != NULL */ XML_Char *tem = poolStoreString(&parser->m_tempPool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (! tem) return XML_ERROR_NO_MEMORY; normalizePublicId(tem); parser->m_declNotationPublicId = tem; poolFinish(&parser->m_tempPool); handleDefault = XML_FALSE; } break; case XML_ROLE_NOTATION_SYSTEM_ID: if (parser->m_declNotationName && parser->m_notationDeclHandler) { const XML_Char *systemId = poolStoreString(&parser->m_tempPool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (! systemId) return XML_ERROR_NO_MEMORY; *eventEndPP = s; parser->m_notationDeclHandler( parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase, systemId, parser->m_declNotationPublicId); handleDefault = XML_FALSE; } poolClear(&parser->m_tempPool); break; case XML_ROLE_NOTATION_NO_SYSTEM_ID: if (parser->m_declNotationPublicId && parser->m_notationDeclHandler) { *eventEndPP = s; parser->m_notationDeclHandler( parser->m_handlerArg, parser->m_declNotationName, parser->m_curBase, 0, parser->m_declNotationPublicId); handleDefault = XML_FALSE; } poolClear(&parser->m_tempPool); break; case XML_ROLE_ERROR: switch (tok) { case XML_TOK_PARAM_ENTITY_REF: /* PE references in internal subset are not allowed within declarations. */ return XML_ERROR_PARAM_ENTITY_REF; case XML_TOK_XML_DECL: return XML_ERROR_MISPLACED_XML_PI; default: return XML_ERROR_SYNTAX; } #ifdef XML_DTD case XML_ROLE_IGNORE_SECT: { enum XML_Error result; if (parser->m_defaultHandler) reportDefault(parser, enc, s, next); handleDefault = XML_FALSE; result = doIgnoreSection(parser, enc, &next, end, nextPtr, haveMore); if (result != XML_ERROR_NONE) return result; else if (! next) { parser->m_processor = ignoreSectionProcessor; return result; } } break; #endif /* XML_DTD */ case XML_ROLE_GROUP_OPEN: if (parser->m_prologState.level >= parser->m_groupSize) { if (parser->m_groupSize) { { /* Detect and prevent integer overflow */ if (parser->m_groupSize > (unsigned int)(-1) / 2u) { return XML_ERROR_NO_MEMORY; } char *const new_connector = (char *)REALLOC( parser, parser->m_groupConnector, parser->m_groupSize *= 2); if (new_connector == NULL) { parser->m_groupSize /= 2; return XML_ERROR_NO_MEMORY; } parser->m_groupConnector = new_connector; } if (dtd->scaffIndex) { /* Detect and prevent integer overflow. * The preprocessor guard addresses the "always false" warning * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) { return XML_ERROR_NO_MEMORY; } #endif int *const new_scaff_index = (int *)REALLOC( parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int)); if (new_scaff_index == NULL) return XML_ERROR_NO_MEMORY; dtd->scaffIndex = new_scaff_index; } } else { parser->m_groupConnector = (char *)MALLOC(parser, parser->m_groupSize = 32); if (! parser->m_groupConnector) { parser->m_groupSize = 0; return XML_ERROR_NO_MEMORY; } } } parser->m_groupConnector[parser->m_prologState.level] = 0; if (dtd->in_eldecl) { int myindex = nextScaffoldPart(parser); if (myindex < 0) return XML_ERROR_NO_MEMORY; assert(dtd->scaffIndex != NULL); dtd->scaffIndex[dtd->scaffLevel] = myindex; dtd->scaffLevel++; dtd->scaffold[myindex].type = XML_CTYPE_SEQ; if (parser->m_elementDeclHandler) handleDefault = XML_FALSE; } break; case XML_ROLE_GROUP_SEQUENCE: if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_PIPE) return XML_ERROR_SYNTAX; parser->m_groupConnector[parser->m_prologState.level] = ASCII_COMMA; if (dtd->in_eldecl && parser->m_elementDeclHandler) handleDefault = XML_FALSE; break; case XML_ROLE_GROUP_CHOICE: if (parser->m_groupConnector[parser->m_prologState.level] == ASCII_COMMA) return XML_ERROR_SYNTAX; if (dtd->in_eldecl && ! parser->m_groupConnector[parser->m_prologState.level] && (dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type != XML_CTYPE_MIXED)) { dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type = XML_CTYPE_CHOICE; if (parser->m_elementDeclHandler) handleDefault = XML_FALSE; } parser->m_groupConnector[parser->m_prologState.level] = ASCII_PIPE; break; case XML_ROLE_PARAM_ENTITY_REF: #ifdef XML_DTD case XML_ROLE_INNER_PARAM_ENTITY_REF: dtd->hasParamEntityRefs = XML_TRUE; if (! parser->m_paramEntityParsing) dtd->keepProcessing = dtd->standalone; else { const XML_Char *name; ENTITY *entity; name = poolStoreString(&dtd->pool, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar); if (! name) return XML_ERROR_NO_MEMORY; entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0); poolDiscard(&dtd->pool); /* first, determine if a check for an existing declaration is needed; if yes, check that the entity exists, and that it is internal, otherwise call the skipped entity handler */ if (parser->m_prologState.documentEntity && (dtd->standalone ? ! parser->m_openInternalEntities : ! dtd->hasParamEntityRefs)) { if (! entity) return XML_ERROR_UNDEFINED_ENTITY; else if (! entity->is_internal) { /* It's hard to exhaustively search the code to be sure, * but there doesn't seem to be a way of executing the * following line. There are two cases: * * If 'standalone' is false, the DTD must have no * parameter entities or we wouldn't have passed the outer * 'if' statement. That means the only entity in the hash * table is the external subset name "#" which cannot be * given as a parameter entity name in XML syntax, so the * lookup must have returned NULL and we don't even reach * the test for an internal entity. * * If 'standalone' is true, it does not seem to be * possible to create entities taking this code path that * are not internal entities, so fail the test above. * * Because this analysis is very uncertain, the code is * being left in place and merely removed from the * coverage test statistics. */ return XML_ERROR_ENTITY_DECLARED_IN_PE; /* LCOV_EXCL_LINE */ } } else if (! entity) { dtd->keepProcessing = dtd->standalone; /* cannot report skipped entities in declarations */ if ((role == XML_ROLE_PARAM_ENTITY_REF) && parser->m_skippedEntityHandler) { parser->m_skippedEntityHandler(parser->m_handlerArg, name, 1); handleDefault = XML_FALSE; } break; } if (entity->open) return XML_ERROR_RECURSIVE_ENTITY_REF; if (entity->textPtr) { enum XML_Error result; XML_Bool betweenDecl = (role == XML_ROLE_PARAM_ENTITY_REF ? XML_TRUE : XML_FALSE); result = processInternalEntity(parser, entity, betweenDecl); if (result != XML_ERROR_NONE) return result; handleDefault = XML_FALSE; break; } if (parser->m_externalEntityRefHandler) { dtd->paramEntityRead = XML_FALSE; entity->open = XML_TRUE; entityTrackingOnOpen(parser, entity, __LINE__); if (! parser->m_externalEntityRefHandler( parser->m_externalEntityRefHandlerArg, 0, entity->base, entity->systemId, entity->publicId)) { entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; return XML_ERROR_EXTERNAL_ENTITY_HANDLING; } entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; handleDefault = XML_FALSE; if (! dtd->paramEntityRead) { dtd->keepProcessing = dtd->standalone; break; } } else { dtd->keepProcessing = dtd->standalone; break; } } #endif /* XML_DTD */ if (! dtd->standalone && parser->m_notStandaloneHandler && ! parser->m_notStandaloneHandler(parser->m_handlerArg)) return XML_ERROR_NOT_STANDALONE; break; /* Element declaration stuff */ case XML_ROLE_ELEMENT_NAME: if (parser->m_elementDeclHandler) { parser->m_declElementType = getElementType(parser, enc, s, next); if (! parser->m_declElementType) return XML_ERROR_NO_MEMORY; dtd->scaffLevel = 0; dtd->scaffCount = 0; dtd->in_eldecl = XML_TRUE; handleDefault = XML_FALSE; } break; case XML_ROLE_CONTENT_ANY: case XML_ROLE_CONTENT_EMPTY: if (dtd->in_eldecl) { if (parser->m_elementDeclHandler) { XML_Content *content = (XML_Content *)MALLOC(parser, sizeof(XML_Content)); if (! content) return XML_ERROR_NO_MEMORY; content->quant = XML_CQUANT_NONE; content->name = NULL; content->numchildren = 0; content->children = NULL; content->type = ((role == XML_ROLE_CONTENT_ANY) ? XML_CTYPE_ANY : XML_CTYPE_EMPTY); *eventEndPP = s; parser->m_elementDeclHandler( parser->m_handlerArg, parser->m_declElementType->name, content); handleDefault = XML_FALSE; } dtd->in_eldecl = XML_FALSE; } break; case XML_ROLE_CONTENT_PCDATA: if (dtd->in_eldecl) { dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]].type = XML_CTYPE_MIXED; if (parser->m_elementDeclHandler) handleDefault = XML_FALSE; } break; case XML_ROLE_CONTENT_ELEMENT: quant = XML_CQUANT_NONE; goto elementContent; case XML_ROLE_CONTENT_ELEMENT_OPT: quant = XML_CQUANT_OPT; goto elementContent; case XML_ROLE_CONTENT_ELEMENT_REP: quant = XML_CQUANT_REP; goto elementContent; case XML_ROLE_CONTENT_ELEMENT_PLUS: quant = XML_CQUANT_PLUS; elementContent: if (dtd->in_eldecl) { ELEMENT_TYPE *el; const XML_Char *name; size_t nameLen; const char *nxt = (quant == XML_CQUANT_NONE ? next : next - enc->minBytesPerChar); int myindex = nextScaffoldPart(parser); if (myindex < 0) return XML_ERROR_NO_MEMORY; dtd->scaffold[myindex].type = XML_CTYPE_NAME; dtd->scaffold[myindex].quant = quant; el = getElementType(parser, enc, s, nxt); if (! el) return XML_ERROR_NO_MEMORY; name = el->name; dtd->scaffold[myindex].name = name; nameLen = 0; for (; name[nameLen++];) ; /* Detect and prevent integer overflow */ if (nameLen > UINT_MAX - dtd->contentStringLen) { return XML_ERROR_NO_MEMORY; } dtd->contentStringLen += (unsigned)nameLen; if (parser->m_elementDeclHandler) handleDefault = XML_FALSE; } break; case XML_ROLE_GROUP_CLOSE: quant = XML_CQUANT_NONE; goto closeGroup; case XML_ROLE_GROUP_CLOSE_OPT: quant = XML_CQUANT_OPT; goto closeGroup; case XML_ROLE_GROUP_CLOSE_REP: quant = XML_CQUANT_REP; goto closeGroup; case XML_ROLE_GROUP_CLOSE_PLUS: quant = XML_CQUANT_PLUS; closeGroup: if (dtd->in_eldecl) { if (parser->m_elementDeclHandler) handleDefault = XML_FALSE; dtd->scaffLevel--; dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel]].quant = quant; if (dtd->scaffLevel == 0) { if (! handleDefault) { XML_Content *model = build_model(parser); if (! model) return XML_ERROR_NO_MEMORY; *eventEndPP = s; parser->m_elementDeclHandler( parser->m_handlerArg, parser->m_declElementType->name, model); } dtd->in_eldecl = XML_FALSE; dtd->contentStringLen = 0; } } break; /* End element declaration stuff */ case XML_ROLE_PI: if (! reportProcessingInstruction(parser, enc, s, next)) return XML_ERROR_NO_MEMORY; handleDefault = XML_FALSE; break; case XML_ROLE_COMMENT: if (! reportComment(parser, enc, s, next)) return XML_ERROR_NO_MEMORY; handleDefault = XML_FALSE; break; case XML_ROLE_NONE: switch (tok) { case XML_TOK_BOM: handleDefault = XML_FALSE; break; } break; case XML_ROLE_DOCTYPE_NONE: if (parser->m_startDoctypeDeclHandler) handleDefault = XML_FALSE; break; case XML_ROLE_ENTITY_NONE: if (dtd->keepProcessing && parser->m_entityDeclHandler) handleDefault = XML_FALSE; break; case XML_ROLE_NOTATION_NONE: if (parser->m_notationDeclHandler) handleDefault = XML_FALSE; break; case XML_ROLE_ATTLIST_NONE: if (dtd->keepProcessing && parser->m_attlistDeclHandler) handleDefault = XML_FALSE; break; case XML_ROLE_ELEMENT_NONE: if (parser->m_elementDeclHandler) handleDefault = XML_FALSE; break; } /* end of big switch */ if (handleDefault && parser->m_defaultHandler) reportDefault(parser, enc, s, next); switch (parser->m_parsingStatus.parsing) { case XML_SUSPENDED: *nextPtr = next; return XML_ERROR_NONE; case XML_FINISHED: return XML_ERROR_ABORTED; default: s = next; tok = XmlPrologTok(enc, s, end, &next); } } /* not reached */ } static enum XML_Error PTRCALL epilogProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { parser->m_processor = epilogProcessor; parser->m_eventPtr = s; for (;;) { const char *next = NULL; int tok = XmlPrologTok(parser->m_encoding, s, end, &next); #if XML_GE == 1 if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, XML_ACCOUNT_DIRECT)) { accountingOnAbort(parser); return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; } #endif parser->m_eventEndPtr = next; switch (tok) { /* report partial linebreak - it might be the last token */ case -XML_TOK_PROLOG_S: if (parser->m_defaultHandler) { reportDefault(parser, parser->m_encoding, s, next); if (parser->m_parsingStatus.parsing == XML_FINISHED) return XML_ERROR_ABORTED; } *nextPtr = next; return XML_ERROR_NONE; case XML_TOK_NONE: *nextPtr = s; return XML_ERROR_NONE; case XML_TOK_PROLOG_S: if (parser->m_defaultHandler) reportDefault(parser, parser->m_encoding, s, next); break; case XML_TOK_PI: if (! reportProcessingInstruction(parser, parser->m_encoding, s, next)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_COMMENT: if (! reportComment(parser, parser->m_encoding, s, next)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_INVALID: parser->m_eventPtr = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: if (! parser->m_parsingStatus.finalBuffer) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_UNCLOSED_TOKEN; case XML_TOK_PARTIAL_CHAR: if (! parser->m_parsingStatus.finalBuffer) { *nextPtr = s; return XML_ERROR_NONE; } return XML_ERROR_PARTIAL_CHAR; default: return XML_ERROR_JUNK_AFTER_DOC_ELEMENT; } parser->m_eventPtr = s = next; switch (parser->m_parsingStatus.parsing) { case XML_SUSPENDED: *nextPtr = next; return XML_ERROR_NONE; case XML_FINISHED: return XML_ERROR_ABORTED; default:; } } } static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) { const char *textStart, *textEnd; const char *next; enum XML_Error result; OPEN_INTERNAL_ENTITY *openEntity; if (parser->m_freeInternalEntities) { openEntity = parser->m_freeInternalEntities; parser->m_freeInternalEntities = openEntity->next; } else { openEntity = (OPEN_INTERNAL_ENTITY *)MALLOC(parser, sizeof(OPEN_INTERNAL_ENTITY)); if (! openEntity) return XML_ERROR_NO_MEMORY; } entity->open = XML_TRUE; #if XML_GE == 1 entityTrackingOnOpen(parser, entity, __LINE__); #endif entity->processed = 0; openEntity->next = parser->m_openInternalEntities; parser->m_openInternalEntities = openEntity; openEntity->entity = entity; openEntity->startTagLevel = parser->m_tagLevel; openEntity->betweenDecl = betweenDecl; openEntity->internalEventPtr = NULL; openEntity->internalEventEndPtr = NULL; textStart = (const char *)entity->textPtr; textEnd = (const char *)(entity->textPtr + entity->textLen); /* Set a safe default value in case 'next' does not get set */ next = textStart; if (entity->is_param) { int tok = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next); result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, tok, next, &next, XML_FALSE, XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION); } else { result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding, textStart, textEnd, &next, XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION); } if (result == XML_ERROR_NONE) { if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) { entity->processed = (int)(next - textStart); parser->m_processor = internalEntityProcessor; } else if (parser->m_openInternalEntities->entity == entity) { #if XML_GE == 1 entityTrackingOnClose(parser, entity, __LINE__); #endif /* XML_GE == 1 */ entity->open = XML_FALSE; parser->m_openInternalEntities = openEntity->next; /* put openEntity back in list of free instances */ openEntity->next = parser->m_freeInternalEntities; parser->m_freeInternalEntities = openEntity; } } return result; } static enum XML_Error PTRCALL internalEntityProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { ENTITY *entity; const char *textStart, *textEnd; const char *next; enum XML_Error result; OPEN_INTERNAL_ENTITY *openEntity = parser->m_openInternalEntities; if (! openEntity) return XML_ERROR_UNEXPECTED_STATE; entity = openEntity->entity; textStart = ((const char *)entity->textPtr) + entity->processed; textEnd = (const char *)(entity->textPtr + entity->textLen); /* Set a safe default value in case 'next' does not get set */ next = textStart; if (entity->is_param) { int tok = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next); result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd, tok, next, &next, XML_FALSE, XML_TRUE, XML_ACCOUNT_ENTITY_EXPANSION); } else { result = doContent(parser, openEntity->startTagLevel, parser->m_internalEncoding, textStart, textEnd, &next, XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION); } if (result != XML_ERROR_NONE) return result; if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) { entity->processed = (int)(next - (const char *)entity->textPtr); return result; } #if XML_GE == 1 entityTrackingOnClose(parser, entity, __LINE__); #endif entity->open = XML_FALSE; parser->m_openInternalEntities = openEntity->next; /* put openEntity back in list of free instances */ openEntity->next = parser->m_freeInternalEntities; parser->m_freeInternalEntities = openEntity; // If there are more open entities we want to stop right here and have the // upcoming call to XML_ResumeParser continue with entity content, or it would // be ignored altogether. if (parser->m_openInternalEntities != NULL && parser->m_parsingStatus.parsing == XML_SUSPENDED) { return XML_ERROR_NONE; } if (entity->is_param) { int tok; parser->m_processor = prologProcessor; tok = XmlPrologTok(parser->m_encoding, s, end, &next); return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr, (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE, XML_ACCOUNT_DIRECT); } else { parser->m_processor = contentProcessor; /* see externalEntityContentProcessor vs contentProcessor */ result = doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding, s, end, nextPtr, (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT); if (result == XML_ERROR_NONE) { if (! storeRawNames(parser)) return XML_ERROR_NO_MEMORY; } return result; } } static enum XML_Error PTRCALL errorProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) { UNUSED_P(s); UNUSED_P(end); UNUSED_P(nextPtr); return parser->m_errorCode; } static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, const char *ptr, const char *end, STRING_POOL *pool, enum XML_Account account) { enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool, account); if (result) return result; if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20) poolChop(pool); if (! poolAppendChar(pool, XML_T('\0'))) return XML_ERROR_NO_MEMORY; return XML_ERROR_NONE; } static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata, const char *ptr, const char *end, STRING_POOL *pool, enum XML_Account account) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ #ifndef XML_DTD UNUSED_P(account); #endif for (;;) { const char *next = ptr; /* XmlAttributeValueTok doesn't always set the last arg */ int tok = XmlAttributeValueTok(enc, ptr, end, &next); #if XML_GE == 1 if (! accountingDiffTolerated(parser, tok, ptr, next, __LINE__, account)) { accountingOnAbort(parser); return XML_ERROR_AMPLIFICATION_LIMIT_BREACH; } #endif switch (tok) { case XML_TOK_NONE: return XML_ERROR_NONE; case XML_TOK_INVALID: if (enc == parser->m_encoding) parser->m_eventPtr = next; return XML_ERROR_INVALID_TOKEN; case XML_TOK_PARTIAL: if (enc == parser->m_encoding) parser->m_eventPtr = ptr; return XML_ERROR_INVALID_TOKEN; case XML_TOK_CHAR_REF: { XML_Char buf[XML_ENCODE_MAX]; int i; int n = XmlCharRefNumber(enc, ptr); if (n < 0) { if (enc == parser->m_encoding) parser->m_eventPtr = ptr; return XML_ERROR_BAD_CHAR_REF; } if (! isCdata && n == 0x20 /* space */ && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) break; n = XmlEncode(n, (ICHAR *)buf); /* The XmlEncode() functions can never return 0 here. That * error return happens if the code point passed in is either * negative or greater than or equal to 0x110000. The * XmlCharRefNumber() functions will all return a number * strictly less than 0x110000 or a negative value if an error * occurred. The negative value is intercepted above, so * XmlEncode() is never passed a value it might return an * error for. */ for (i = 0; i < n; i++) { if (! poolAppendChar(pool, buf[i])) return XML_ERROR_NO_MEMORY; } } break; case XML_TOK_DATA_CHARS: if (! poolAppend(pool, enc, ptr, next)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_TRAILING_CR: next = ptr + enc->minBytesPerChar; /* fall through */ case XML_TOK_ATTRIBUTE_VALUE_S: case XML_TOK_DATA_NEWLINE: if (! isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20)) break; if (! poolAppendChar(pool, 0x20)) return XML_ERROR_NO_MEMORY; break; case XML_TOK_ENTITY_REF: { const XML_Char *name; ENTITY *entity; char checkEntityDecl; XML_Char ch = (XML_Char)XmlPredefinedEntityName( enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar); if (ch) { #if XML_GE == 1 /* NOTE: We are replacing 4-6 characters original input for 1 character * so there is no amplification and hence recording without * protection. */ accountingDiffTolerated(parser, tok, (char *)&ch, ((char *)&ch) + sizeof(XML_Char), __LINE__, XML_ACCOUNT_ENTITY_EXPANSION); #endif /* XML_GE == 1 */ if (! poolAppendChar(pool, ch)) return XML_ERROR_NO_MEMORY; break; } name = poolStoreString(&parser->m_temp2Pool, enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar); if (! name) return XML_ERROR_NO_MEMORY; entity = (ENTITY *)lookup(parser, &dtd->generalEntities, name, 0); poolDiscard(&parser->m_temp2Pool); /* First, determine if a check for an existing declaration is needed; if yes, check that the entity exists, and that it is internal. */ if (pool == &dtd->pool) /* are we called from prolog? */ checkEntityDecl = #ifdef XML_DTD parser->m_prologState.documentEntity && #endif /* XML_DTD */ (dtd->standalone ? ! parser->m_openInternalEntities : ! dtd->hasParamEntityRefs); else /* if (pool == &parser->m_tempPool): we are called from content */ checkEntityDecl = ! dtd->hasParamEntityRefs || dtd->standalone; if (checkEntityDecl) { if (! entity) return XML_ERROR_UNDEFINED_ENTITY; else if (! entity->is_internal) return XML_ERROR_ENTITY_DECLARED_IN_PE; } else if (! entity) { /* Cannot report skipped entity here - see comments on parser->m_skippedEntityHandler. if (parser->m_skippedEntityHandler) parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0); */ /* Cannot call the default handler because this would be out of sync with the call to the startElementHandler. if ((pool == &parser->m_tempPool) && parser->m_defaultHandler) reportDefault(parser, enc, ptr, next); */ break; } if (entity->open) { if (enc == parser->m_encoding) { /* It does not appear that this line can be executed. * * The "if (entity->open)" check catches recursive entity * definitions. In order to be called with an open * entity, it must have gone through this code before and * been through the recursive call to * appendAttributeValue() some lines below. That call * sets the local encoding ("enc") to the parser's * internal encoding (internal_utf8 or internal_utf16), * which can never be the same as the principle encoding. * It doesn't appear there is another code path that gets * here with entity->open being TRUE. * * Since it is not certain that this logic is watertight, * we keep the line and merely exclude it from coverage * tests. */ parser->m_eventPtr = ptr; /* LCOV_EXCL_LINE */ } return XML_ERROR_RECURSIVE_ENTITY_REF; } if (entity->notation) { if (enc == parser->m_encoding) parser->m_eventPtr = ptr; return XML_ERROR_BINARY_ENTITY_REF; } if (! entity->textPtr) { if (enc == parser->m_encoding) parser->m_eventPtr = ptr; return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF; } else { enum XML_Error result; const XML_Char *textEnd = entity->textPtr + entity->textLen; entity->open = XML_TRUE; #if XML_GE == 1 entityTrackingOnOpen(parser, entity, __LINE__); #endif result = appendAttributeValue(parser, parser->m_internalEncoding, isCdata, (const char *)entity->textPtr, (const char *)textEnd, pool, XML_ACCOUNT_ENTITY_EXPANSION); #if XML_GE == 1 entityTrackingOnClose(parser, entity, __LINE__); #endif entity->open = XML_FALSE; if (result) return result; } } break; default: /* The only token returned by XmlAttributeValueTok() that does * not have an explicit case here is XML_TOK_PARTIAL_CHAR. * Getting that would require an entity name to contain an * incomplete XML character (e.g. \xE2\x82); however previous * tokenisers will have already recognised and rejected such * names before XmlAttributeValueTok() gets a look-in. This * default case should be retained as a safety net, but the code * excluded from coverage tests. * * LCOV_EXCL_START */ if (enc == parser->m_encoding) parser->m_eventPtr = ptr; return XML_ERROR_UNEXPECTED_STATE; /* LCOV_EXCL_STOP */ } ptr = next; } /* not reached */ } #if XML_GE == 1 static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *entityTextPtr, const char *entityTextEnd, enum XML_Account account) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ STRING_POOL *pool = &(dtd->entityValuePool); enum XML_Error result = XML_ERROR_NONE; # ifdef XML_DTD int oldInEntityValue = parser->m_prologState.inEntityValue; parser->m_prologState.inEntityValue = 1; # else UNUSED_P(account); # endif /* XML_DTD */ /* never return Null for the value argument in EntityDeclHandler, since this would indicate an external entity; therefore we have to make sure that entityValuePool.start is not null */ if (! pool->blocks) { if (! poolGrow(pool)) return XML_ERROR_NO_MEMORY; } for (;;) { const char *next = entityTextPtr; /* XmlEntityValueTok doesn't always set the last arg */ int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next); if (! accountingDiffTolerated(parser, tok, entityTextPtr, next, __LINE__, account)) { accountingOnAbort(parser); result = XML_ERROR_AMPLIFICATION_LIMIT_BREACH; goto endEntityValue; } switch (tok) { case XML_TOK_PARAM_ENTITY_REF: # ifdef XML_DTD if (parser->m_isParamEntity || enc != parser->m_encoding) { const XML_Char *name; ENTITY *entity; name = poolStoreString(&parser->m_tempPool, enc, entityTextPtr + enc->minBytesPerChar, next - enc->minBytesPerChar); if (! name) { result = XML_ERROR_NO_MEMORY; goto endEntityValue; } entity = (ENTITY *)lookup(parser, &dtd->paramEntities, name, 0); poolDiscard(&parser->m_tempPool); if (! entity) { /* not a well-formedness error - see XML 1.0: WFC Entity Declared */ /* cannot report skipped entity here - see comments on parser->m_skippedEntityHandler if (parser->m_skippedEntityHandler) parser->m_skippedEntityHandler(parser->m_handlerArg, name, 0); */ dtd->keepProcessing = dtd->standalone; goto endEntityValue; } if (entity->open || (entity == parser->m_declEntity)) { if (enc == parser->m_encoding) parser->m_eventPtr = entityTextPtr; result = XML_ERROR_RECURSIVE_ENTITY_REF; goto endEntityValue; } if (entity->systemId) { if (parser->m_externalEntityRefHandler) { dtd->paramEntityRead = XML_FALSE; entity->open = XML_TRUE; entityTrackingOnOpen(parser, entity, __LINE__); if (! parser->m_externalEntityRefHandler( parser->m_externalEntityRefHandlerArg, 0, entity->base, entity->systemId, entity->publicId)) { entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; result = XML_ERROR_EXTERNAL_ENTITY_HANDLING; goto endEntityValue; } entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; if (! dtd->paramEntityRead) dtd->keepProcessing = dtd->standalone; } else dtd->keepProcessing = dtd->standalone; } else { entity->open = XML_TRUE; entityTrackingOnOpen(parser, entity, __LINE__); result = storeEntityValue( parser, parser->m_internalEncoding, (const char *)entity->textPtr, (const char *)(entity->textPtr + entity->textLen), XML_ACCOUNT_ENTITY_EXPANSION); entityTrackingOnClose(parser, entity, __LINE__); entity->open = XML_FALSE; if (result) goto endEntityValue; } break; } # endif /* XML_DTD */ /* In the internal subset, PE references are not legal within markup declarations, e.g entity values in this case. */ parser->m_eventPtr = entityTextPtr; result = XML_ERROR_PARAM_ENTITY_REF; goto endEntityValue; case XML_TOK_NONE: result = XML_ERROR_NONE; goto endEntityValue; case XML_TOK_ENTITY_REF: case XML_TOK_DATA_CHARS: if (! poolAppend(pool, enc, entityTextPtr, next)) { result = XML_ERROR_NO_MEMORY; goto endEntityValue; } break; case XML_TOK_TRAILING_CR: next = entityTextPtr + enc->minBytesPerChar; /* fall through */ case XML_TOK_DATA_NEWLINE: if (pool->end == pool->ptr && ! poolGrow(pool)) { result = XML_ERROR_NO_MEMORY; goto endEntityValue; } *(pool->ptr)++ = 0xA; break; case XML_TOK_CHAR_REF: { XML_Char buf[XML_ENCODE_MAX]; int i; int n = XmlCharRefNumber(enc, entityTextPtr); if (n < 0) { if (enc == parser->m_encoding) parser->m_eventPtr = entityTextPtr; result = XML_ERROR_BAD_CHAR_REF; goto endEntityValue; } n = XmlEncode(n, (ICHAR *)buf); /* The XmlEncode() functions can never return 0 here. That * error return happens if the code point passed in is either * negative or greater than or equal to 0x110000. The * XmlCharRefNumber() functions will all return a number * strictly less than 0x110000 or a negative value if an error * occurred. The negative value is intercepted above, so * XmlEncode() is never passed a value it might return an * error for. */ for (i = 0; i < n; i++) { if (pool->end == pool->ptr && ! poolGrow(pool)) { result = XML_ERROR_NO_MEMORY; goto endEntityValue; } *(pool->ptr)++ = buf[i]; } } break; case XML_TOK_PARTIAL: if (enc == parser->m_encoding) parser->m_eventPtr = entityTextPtr; result = XML_ERROR_INVALID_TOKEN; goto endEntityValue; case XML_TOK_INVALID: if (enc == parser->m_encoding) parser->m_eventPtr = next; result = XML_ERROR_INVALID_TOKEN; goto endEntityValue; default: /* This default case should be unnecessary -- all the tokens * that XmlEntityValueTok() can return have their own explicit * cases -- but should be retained for safety. We do however * exclude it from the coverage statistics. * * LCOV_EXCL_START */ if (enc == parser->m_encoding) parser->m_eventPtr = entityTextPtr; result = XML_ERROR_UNEXPECTED_STATE; goto endEntityValue; /* LCOV_EXCL_STOP */ } entityTextPtr = next; } endEntityValue: # ifdef XML_DTD parser->m_prologState.inEntityValue = oldInEntityValue; # endif /* XML_DTD */ return result; } #else /* XML_GE == 0 */ static enum XML_Error storeSelfEntityValue(XML_Parser parser, ENTITY *entity) { // This will store "&entity123;" in entity->textPtr // to end up as "&entity123;" in the handler. const char *const entity_start = "&"; const char *const entity_end = ";"; STRING_POOL *const pool = &(parser->m_dtd->entityValuePool); if (! poolAppendString(pool, entity_start) || ! poolAppendString(pool, entity->name) || ! poolAppendString(pool, entity_end)) { poolDiscard(pool); return XML_ERROR_NO_MEMORY; } entity->textPtr = poolStart(pool); entity->textLen = (int)(poolLength(pool)); poolFinish(pool); return XML_ERROR_NONE; } #endif /* XML_GE == 0 */ static void FASTCALL normalizeLines(XML_Char *s) { XML_Char *p; for (;; s++) { if (*s == XML_T('\0')) return; if (*s == 0xD) break; } p = s; do { if (*s == 0xD) { *p++ = 0xA; if (*++s == 0xA) s++; } else *p++ = *s++; } while (*s); *p = XML_T('\0'); } static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) { const XML_Char *target; XML_Char *data; const char *tem; if (! parser->m_processingInstructionHandler) { if (parser->m_defaultHandler) reportDefault(parser, enc, start, end); return 1; } start += enc->minBytesPerChar * 2; tem = start + XmlNameLength(enc, start); target = poolStoreString(&parser->m_tempPool, enc, start, tem); if (! target) return 0; poolFinish(&parser->m_tempPool); data = poolStoreString(&parser->m_tempPool, enc, XmlSkipS(enc, tem), end - enc->minBytesPerChar * 2); if (! data) return 0; normalizeLines(data); parser->m_processingInstructionHandler(parser->m_handlerArg, target, data); poolClear(&parser->m_tempPool); return 1; } static int reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) { XML_Char *data; if (! parser->m_commentHandler) { if (parser->m_defaultHandler) reportDefault(parser, enc, start, end); return 1; } data = poolStoreString(&parser->m_tempPool, enc, start + enc->minBytesPerChar * 4, end - enc->minBytesPerChar * 3); if (! data) return 0; normalizeLines(data); parser->m_commentHandler(parser->m_handlerArg, data); poolClear(&parser->m_tempPool); return 1; } static void reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end) { if (MUST_CONVERT(enc, s)) { enum XML_Convert_Result convert_res; const char **eventPP; const char **eventEndPP; if (enc == parser->m_encoding) { eventPP = &parser->m_eventPtr; eventEndPP = &parser->m_eventEndPtr; } else { /* To get here, two things must be true; the parser must be * using a character encoding that is not the same as the * encoding passed in, and the encoding passed in must need * conversion to the internal format (UTF-8 unless XML_UNICODE * is defined). The only occasions on which the encoding passed * in is not the same as the parser's encoding are when it is * the internal encoding (e.g. a previously defined parameter * entity, already converted to internal format). This by * definition doesn't need conversion, so the whole branch never * gets executed. * * For safety's sake we don't delete these lines and merely * exclude them from coverage statistics. * * LCOV_EXCL_START */ eventPP = &(parser->m_openInternalEntities->internalEventPtr); eventEndPP = &(parser->m_openInternalEntities->internalEventEndPtr); /* LCOV_EXCL_STOP */ } do { ICHAR *dataPtr = (ICHAR *)parser->m_dataBuf; convert_res = XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)parser->m_dataBufEnd); *eventEndPP = s; parser->m_defaultHandler(parser->m_handlerArg, parser->m_dataBuf, (int)(dataPtr - (ICHAR *)parser->m_dataBuf)); *eventPP = s; } while ((convert_res != XML_CONVERT_COMPLETED) && (convert_res != XML_CONVERT_INPUT_INCOMPLETE)); } else parser->m_defaultHandler( parser->m_handlerArg, (const XML_Char *)s, (int)((const XML_Char *)end - (const XML_Char *)s)); } static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata, XML_Bool isId, const XML_Char *value, XML_Parser parser) { DEFAULT_ATTRIBUTE *att; if (value || isId) { /* The handling of default attributes gets messed up if we have a default which duplicates a non-default. */ int i; for (i = 0; i < type->nDefaultAtts; i++) if (attId == type->defaultAtts[i].id) return 1; if (isId && ! type->idAtt && ! attId->xmlns) type->idAtt = attId; } if (type->nDefaultAtts == type->allocDefaultAtts) { if (type->allocDefaultAtts == 0) { type->allocDefaultAtts = 8; type->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC( parser, type->allocDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); if (! type->defaultAtts) { type->allocDefaultAtts = 0; return 0; } } else { DEFAULT_ATTRIBUTE *temp; /* Detect and prevent integer overflow */ if (type->allocDefaultAtts > INT_MAX / 2) { return 0; } int count = type->allocDefaultAtts * 2; /* Detect and prevent integer overflow. * The preprocessor guard addresses the "always false" warning * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX if ((unsigned)count > (size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE)) { return 0; } #endif temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts, (count * sizeof(DEFAULT_ATTRIBUTE))); if (temp == NULL) return 0; type->allocDefaultAtts = count; type->defaultAtts = temp; } } att = type->defaultAtts + type->nDefaultAtts; att->id = attId; att->value = value; att->isCdata = isCdata; if (! isCdata) attId->maybeTokenized = XML_TRUE; type->nDefaultAtts += 1; return 1; } static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ const XML_Char *name; for (name = elementType->name; *name; name++) { if (*name == XML_T(ASCII_COLON)) { PREFIX *prefix; const XML_Char *s; for (s = elementType->name; s != name; s++) { if (! poolAppendChar(&dtd->pool, *s)) return 0; } if (! poolAppendChar(&dtd->pool, XML_T('\0'))) return 0; prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool), sizeof(PREFIX)); if (! prefix) return 0; if (prefix->name == poolStart(&dtd->pool)) poolFinish(&dtd->pool); else poolDiscard(&dtd->pool); elementType->prefix = prefix; break; } } return 1; } static ATTRIBUTE_ID * getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ ATTRIBUTE_ID *id; const XML_Char *name; if (! poolAppendChar(&dtd->pool, XML_T('\0'))) return NULL; name = poolStoreString(&dtd->pool, enc, start, end); if (! name) return NULL; /* skip quotation mark - its storage will be reused (like in name[-1]) */ ++name; id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, name, sizeof(ATTRIBUTE_ID)); if (! id) return NULL; if (id->name != name) poolDiscard(&dtd->pool); else { poolFinish(&dtd->pool); if (! parser->m_ns) ; else if (name[0] == XML_T(ASCII_x) && name[1] == XML_T(ASCII_m) && name[2] == XML_T(ASCII_l) && name[3] == XML_T(ASCII_n) && name[4] == XML_T(ASCII_s) && (name[5] == XML_T('\0') || name[5] == XML_T(ASCII_COLON))) { if (name[5] == XML_T('\0')) id->prefix = &dtd->defaultPrefix; else id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, name + 6, sizeof(PREFIX)); id->xmlns = XML_TRUE; } else { int i; for (i = 0; name[i]; i++) { /* attributes without prefix are *not* in the default namespace */ if (name[i] == XML_T(ASCII_COLON)) { int j; for (j = 0; j < i; j++) { if (! poolAppendChar(&dtd->pool, name[j])) return NULL; } if (! poolAppendChar(&dtd->pool, XML_T('\0'))) return NULL; id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool), sizeof(PREFIX)); if (! id->prefix) return NULL; if (id->prefix->name == poolStart(&dtd->pool)) poolFinish(&dtd->pool); else poolDiscard(&dtd->pool); break; } } } } return id; } #define CONTEXT_SEP XML_T(ASCII_FF) static const XML_Char * getContext(XML_Parser parser) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ HASH_TABLE_ITER iter; XML_Bool needSep = XML_FALSE; if (dtd->defaultPrefix.binding) { int i; int len; if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS))) return NULL; len = dtd->defaultPrefix.binding->uriLen; if (parser->m_namespaceSeparator) len--; for (i = 0; i < len; i++) { if (! poolAppendChar(&parser->m_tempPool, dtd->defaultPrefix.binding->uri[i])) { /* Because of memory caching, I don't believe this line can be * executed. * * This is part of a loop copying the default prefix binding * URI into the parser's temporary string pool. Previously, * that URI was copied into the same string pool, with a * terminating NUL character, as part of setContext(). When * the pool was cleared, that leaves a block definitely big * enough to hold the URI on the free block list of the pool. * The URI copy in getContext() therefore cannot run out of * memory. * * If the pool is used between the setContext() and * getContext() calls, the worst it can do is leave a bigger * block on the front of the free list. Given that this is * all somewhat inobvious and program logic can be changed, we * don't delete the line but we do exclude it from the test * coverage statistics. */ return NULL; /* LCOV_EXCL_LINE */ } } needSep = XML_TRUE; } hashTableIterInit(&iter, &(dtd->prefixes)); for (;;) { int i; int len; const XML_Char *s; PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter); if (! prefix) break; if (! prefix->binding) { /* This test appears to be (justifiable) paranoia. There does * not seem to be a way of injecting a prefix without a binding * that doesn't get errored long before this function is called. * The test should remain for safety's sake, so we instead * exclude the following line from the coverage statistics. */ continue; /* LCOV_EXCL_LINE */ } if (needSep && ! poolAppendChar(&parser->m_tempPool, CONTEXT_SEP)) return NULL; for (s = prefix->name; *s; s++) if (! poolAppendChar(&parser->m_tempPool, *s)) return NULL; if (! poolAppendChar(&parser->m_tempPool, XML_T(ASCII_EQUALS))) return NULL; len = prefix->binding->uriLen; if (parser->m_namespaceSeparator) len--; for (i = 0; i < len; i++) if (! poolAppendChar(&parser->m_tempPool, prefix->binding->uri[i])) return NULL; needSep = XML_TRUE; } hashTableIterInit(&iter, &(dtd->generalEntities)); for (;;) { const XML_Char *s; ENTITY *e = (ENTITY *)hashTableIterNext(&iter); if (! e) break; if (! e->open) continue; if (needSep && ! poolAppendChar(&parser->m_tempPool, CONTEXT_SEP)) return NULL; for (s = e->name; *s; s++) if (! poolAppendChar(&parser->m_tempPool, *s)) return 0; needSep = XML_TRUE; } if (! poolAppendChar(&parser->m_tempPool, XML_T('\0'))) return NULL; return parser->m_tempPool.start; } static XML_Bool setContext(XML_Parser parser, const XML_Char *context) { if (context == NULL) { return XML_FALSE; } DTD *const dtd = parser->m_dtd; /* save one level of indirection */ const XML_Char *s = context; while (*context != XML_T('\0')) { if (*s == CONTEXT_SEP || *s == XML_T('\0')) { ENTITY *e; if (! poolAppendChar(&parser->m_tempPool, XML_T('\0'))) return XML_FALSE; e = (ENTITY *)lookup(parser, &dtd->generalEntities, poolStart(&parser->m_tempPool), 0); if (e) e->open = XML_TRUE; if (*s != XML_T('\0')) s++; context = s; poolDiscard(&parser->m_tempPool); } else if (*s == XML_T(ASCII_EQUALS)) { PREFIX *prefix; if (poolLength(&parser->m_tempPool) == 0) prefix = &dtd->defaultPrefix; else { if (! poolAppendChar(&parser->m_tempPool, XML_T('\0'))) return XML_FALSE; prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&parser->m_tempPool), sizeof(PREFIX)); if (! prefix) return XML_FALSE; if (prefix->name == poolStart(&parser->m_tempPool)) { prefix->name = poolCopyString(&dtd->pool, prefix->name); if (! prefix->name) return XML_FALSE; } poolDiscard(&parser->m_tempPool); } for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0'); context++) if (! poolAppendChar(&parser->m_tempPool, *context)) return XML_FALSE; if (! poolAppendChar(&parser->m_tempPool, XML_T('\0'))) return XML_FALSE; if (addBinding(parser, prefix, NULL, poolStart(&parser->m_tempPool), &parser->m_inheritedBindings) != XML_ERROR_NONE) return XML_FALSE; poolDiscard(&parser->m_tempPool); if (*context != XML_T('\0')) ++context; s = context; } else { if (! poolAppendChar(&parser->m_tempPool, *s)) return XML_FALSE; s++; } } return XML_TRUE; } static void FASTCALL normalizePublicId(XML_Char *publicId) { XML_Char *p = publicId; XML_Char *s; for (s = publicId; *s; s++) { switch (*s) { case 0x20: case 0xD: case 0xA: if (p != publicId && p[-1] != 0x20) *p++ = 0x20; break; default: *p++ = *s; } } if (p != publicId && p[-1] == 0x20) --p; *p = XML_T('\0'); } static DTD * dtdCreate(const XML_Memory_Handling_Suite *ms) { DTD *p = ms->malloc_fcn(sizeof(DTD)); if (p == NULL) return p; poolInit(&(p->pool), ms); poolInit(&(p->entityValuePool), ms); hashTableInit(&(p->generalEntities), ms); hashTableInit(&(p->elementTypes), ms); hashTableInit(&(p->attributeIds), ms); hashTableInit(&(p->prefixes), ms); #ifdef XML_DTD p->paramEntityRead = XML_FALSE; hashTableInit(&(p->paramEntities), ms); #endif /* XML_DTD */ p->defaultPrefix.name = NULL; p->defaultPrefix.binding = NULL; p->in_eldecl = XML_FALSE; p->scaffIndex = NULL; p->scaffold = NULL; p->scaffLevel = 0; p->scaffSize = 0; p->scaffCount = 0; p->contentStringLen = 0; p->keepProcessing = XML_TRUE; p->hasParamEntityRefs = XML_FALSE; p->standalone = XML_FALSE; return p; } static void dtdReset(DTD *p, const XML_Memory_Handling_Suite *ms) { HASH_TABLE_ITER iter; hashTableIterInit(&iter, &(p->elementTypes)); for (;;) { ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); if (! e) break; if (e->allocDefaultAtts != 0) ms->free_fcn(e->defaultAtts); } hashTableClear(&(p->generalEntities)); #ifdef XML_DTD p->paramEntityRead = XML_FALSE; hashTableClear(&(p->paramEntities)); #endif /* XML_DTD */ hashTableClear(&(p->elementTypes)); hashTableClear(&(p->attributeIds)); hashTableClear(&(p->prefixes)); poolClear(&(p->pool)); poolClear(&(p->entityValuePool)); p->defaultPrefix.name = NULL; p->defaultPrefix.binding = NULL; p->in_eldecl = XML_FALSE; ms->free_fcn(p->scaffIndex); p->scaffIndex = NULL; ms->free_fcn(p->scaffold); p->scaffold = NULL; p->scaffLevel = 0; p->scaffSize = 0; p->scaffCount = 0; p->contentStringLen = 0; p->keepProcessing = XML_TRUE; p->hasParamEntityRefs = XML_FALSE; p->standalone = XML_FALSE; } static void dtdDestroy(DTD *p, XML_Bool isDocEntity, const XML_Memory_Handling_Suite *ms) { HASH_TABLE_ITER iter; hashTableIterInit(&iter, &(p->elementTypes)); for (;;) { ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter); if (! e) break; if (e->allocDefaultAtts != 0) ms->free_fcn(e->defaultAtts); } hashTableDestroy(&(p->generalEntities)); #ifdef XML_DTD hashTableDestroy(&(p->paramEntities)); #endif /* XML_DTD */ hashTableDestroy(&(p->elementTypes)); hashTableDestroy(&(p->attributeIds)); hashTableDestroy(&(p->prefixes)); poolDestroy(&(p->pool)); poolDestroy(&(p->entityValuePool)); if (isDocEntity) { ms->free_fcn(p->scaffIndex); ms->free_fcn(p->scaffold); } ms->free_fcn(p); } /* Do a deep copy of the DTD. Return 0 for out of memory, non-zero otherwise. The new DTD has already been initialized. */ static int dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_Handling_Suite *ms) { HASH_TABLE_ITER iter; /* Copy the prefix table. */ hashTableIterInit(&iter, &(oldDtd->prefixes)); for (;;) { const XML_Char *name; const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter); if (! oldP) break; name = poolCopyString(&(newDtd->pool), oldP->name); if (! name) return 0; if (! lookup(oldParser, &(newDtd->prefixes), name, sizeof(PREFIX))) return 0; } hashTableIterInit(&iter, &(oldDtd->attributeIds)); /* Copy the attribute id table. */ for (;;) { ATTRIBUTE_ID *newA; const XML_Char *name; const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter); if (! oldA) break; /* Remember to allocate the scratch byte before the name. */ if (! poolAppendChar(&(newDtd->pool), XML_T('\0'))) return 0; name = poolCopyString(&(newDtd->pool), oldA->name); if (! name) return 0; ++name; newA = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID)); if (! newA) return 0; newA->maybeTokenized = oldA->maybeTokenized; if (oldA->prefix) { newA->xmlns = oldA->xmlns; if (oldA->prefix == &oldDtd->defaultPrefix) newA->prefix = &newDtd->defaultPrefix; else newA->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes), oldA->prefix->name, 0); } } /* Copy the element type table. */ hashTableIterInit(&iter, &(oldDtd->elementTypes)); for (;;) { int i; ELEMENT_TYPE *newE; const XML_Char *name; const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter); if (! oldE) break; name = poolCopyString(&(newDtd->pool), oldE->name); if (! name) return 0; newE = (ELEMENT_TYPE *)lookup(oldParser, &(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE)); if (! newE) return 0; if (oldE->nDefaultAtts) { /* Detect and prevent integer overflow. * The preprocessor guard addresses the "always false" warning * from -Wtype-limits on platforms where * sizeof(int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX if ((size_t)oldE->nDefaultAtts > ((size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE))) { return 0; } #endif newE->defaultAtts = ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE)); if (! newE->defaultAtts) { return 0; } } if (oldE->idAtt) newE->idAtt = (ATTRIBUTE_ID *)lookup(oldParser, &(newDtd->attributeIds), oldE->idAtt->name, 0); newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts; if (oldE->prefix) newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes), oldE->prefix->name, 0); for (i = 0; i < newE->nDefaultAtts; i++) { newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup( oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0); newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata; if (oldE->defaultAtts[i].value) { newE->defaultAtts[i].value = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value); if (! newE->defaultAtts[i].value) return 0; } else newE->defaultAtts[i].value = NULL; } } /* Copy the entity tables. */ if (! copyEntityTable(oldParser, &(newDtd->generalEntities), &(newDtd->pool), &(oldDtd->generalEntities))) return 0; #ifdef XML_DTD if (! copyEntityTable(oldParser, &(newDtd->paramEntities), &(newDtd->pool), &(oldDtd->paramEntities))) return 0; newDtd->paramEntityRead = oldDtd->paramEntityRead; #endif /* XML_DTD */ newDtd->keepProcessing = oldDtd->keepProcessing; newDtd->hasParamEntityRefs = oldDtd->hasParamEntityRefs; newDtd->standalone = oldDtd->standalone; /* Don't want deep copying for scaffolding */ newDtd->in_eldecl = oldDtd->in_eldecl; newDtd->scaffold = oldDtd->scaffold; newDtd->contentStringLen = oldDtd->contentStringLen; newDtd->scaffSize = oldDtd->scaffSize; newDtd->scaffLevel = oldDtd->scaffLevel; newDtd->scaffIndex = oldDtd->scaffIndex; return 1; } /* End dtdCopy */ static int copyEntityTable(XML_Parser oldParser, HASH_TABLE *newTable, STRING_POOL *newPool, const HASH_TABLE *oldTable) { HASH_TABLE_ITER iter; const XML_Char *cachedOldBase = NULL; const XML_Char *cachedNewBase = NULL; hashTableIterInit(&iter, oldTable); for (;;) { ENTITY *newE; const XML_Char *name; const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter); if (! oldE) break; name = poolCopyString(newPool, oldE->name); if (! name) return 0; newE = (ENTITY *)lookup(oldParser, newTable, name, sizeof(ENTITY)); if (! newE) return 0; if (oldE->systemId) { const XML_Char *tem = poolCopyString(newPool, oldE->systemId); if (! tem) return 0; newE->systemId = tem; if (oldE->base) { if (oldE->base == cachedOldBase) newE->base = cachedNewBase; else { cachedOldBase = oldE->base; tem = poolCopyString(newPool, cachedOldBase); if (! tem) return 0; cachedNewBase = newE->base = tem; } } if (oldE->publicId) { tem = poolCopyString(newPool, oldE->publicId); if (! tem) return 0; newE->publicId = tem; } } else { const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr, oldE->textLen); if (! tem) return 0; newE->textPtr = tem; newE->textLen = oldE->textLen; } if (oldE->notation) { const XML_Char *tem = poolCopyString(newPool, oldE->notation); if (! tem) return 0; newE->notation = tem; } newE->is_param = oldE->is_param; newE->is_internal = oldE->is_internal; } return 1; } #define INIT_POWER 6 static XML_Bool FASTCALL keyeq(KEY s1, KEY s2) { for (; *s1 == *s2; s1++, s2++) if (*s1 == 0) return XML_TRUE; return XML_FALSE; } static size_t keylen(KEY s) { size_t len = 0; for (; *s; s++, len++) ; return len; } static void copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key) { key->k[0] = 0; key->k[1] = get_hash_secret_salt(parser); } static unsigned long FASTCALL hash(XML_Parser parser, KEY s) { struct siphash state; struct sipkey key; (void)sip24_valid; copy_salt_to_sipkey(parser, &key); sip24_init(&state, &key); sip24_update(&state, s, keylen(s) * sizeof(XML_Char)); return (unsigned long)sip24_final(&state); } static NAMED * lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) { size_t i; if (table->size == 0) { size_t tsize; if (! createSize) return NULL; table->power = INIT_POWER; /* table->size is a power of 2 */ table->size = (size_t)1 << INIT_POWER; tsize = table->size * sizeof(NAMED *); table->v = table->mem->malloc_fcn(tsize); if (! table->v) { table->size = 0; return NULL; } memset(table->v, 0, tsize); i = hash(parser, name) & ((unsigned long)table->size - 1); } else { unsigned long h = hash(parser, name); unsigned long mask = (unsigned long)table->size - 1; unsigned char step = 0; i = h & mask; while (table->v[i]) { if (keyeq(name, table->v[i]->name)) return table->v[i]; if (! step) step = PROBE_STEP(h, mask, table->power); i < step ? (i += table->size - step) : (i -= step); } if (! createSize) return NULL; /* check for overflow (table is half full) */ if (table->used >> (table->power - 1)) { unsigned char newPower = table->power + 1; /* Detect and prevent invalid shift */ if (newPower >= sizeof(unsigned long) * 8 /* bits per byte */) { return NULL; } size_t newSize = (size_t)1 << newPower; unsigned long newMask = (unsigned long)newSize - 1; /* Detect and prevent integer overflow */ if (newSize > (size_t)(-1) / sizeof(NAMED *)) { return NULL; } size_t tsize = newSize * sizeof(NAMED *); NAMED **newV = table->mem->malloc_fcn(tsize); if (! newV) return NULL; memset(newV, 0, tsize); for (i = 0; i < table->size; i++) if (table->v[i]) { unsigned long newHash = hash(parser, table->v[i]->name); size_t j = newHash & newMask; step = 0; while (newV[j]) { if (! step) step = PROBE_STEP(newHash, newMask, newPower); j < step ? (j += newSize - step) : (j -= step); } newV[j] = table->v[i]; } table->mem->free_fcn(table->v); table->v = newV; table->power = newPower; table->size = newSize; i = h & newMask; step = 0; while (table->v[i]) { if (! step) step = PROBE_STEP(h, newMask, newPower); i < step ? (i += newSize - step) : (i -= step); } } } table->v[i] = table->mem->malloc_fcn(createSize); if (! table->v[i]) return NULL; memset(table->v[i], 0, createSize); table->v[i]->name = name; (table->used)++; return table->v[i]; } static void FASTCALL hashTableClear(HASH_TABLE *table) { size_t i; for (i = 0; i < table->size; i++) { table->mem->free_fcn(table->v[i]); table->v[i] = NULL; } table->used = 0; } static void FASTCALL hashTableDestroy(HASH_TABLE *table) { size_t i; for (i = 0; i < table->size; i++) table->mem->free_fcn(table->v[i]); table->mem->free_fcn(table->v); } static void FASTCALL hashTableInit(HASH_TABLE *p, const XML_Memory_Handling_Suite *ms) { p->power = 0; p->size = 0; p->used = 0; p->v = NULL; p->mem = ms; } static void FASTCALL hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table) { iter->p = table->v; iter->end = iter->p ? iter->p + table->size : NULL; } static NAMED *FASTCALL hashTableIterNext(HASH_TABLE_ITER *iter) { while (iter->p != iter->end) { NAMED *tem = *(iter->p)++; if (tem) return tem; } return NULL; } static void FASTCALL poolInit(STRING_POOL *pool, const XML_Memory_Handling_Suite *ms) { pool->blocks = NULL; pool->freeBlocks = NULL; pool->start = NULL; pool->ptr = NULL; pool->end = NULL; pool->mem = ms; } static void FASTCALL poolClear(STRING_POOL *pool) { if (! pool->freeBlocks) pool->freeBlocks = pool->blocks; else { BLOCK *p = pool->blocks; while (p) { BLOCK *tem = p->next; p->next = pool->freeBlocks; pool->freeBlocks = p; p = tem; } } pool->blocks = NULL; pool->start = NULL; pool->ptr = NULL; pool->end = NULL; } static void FASTCALL poolDestroy(STRING_POOL *pool) { BLOCK *p = pool->blocks; while (p) { BLOCK *tem = p->next; pool->mem->free_fcn(p); p = tem; } p = pool->freeBlocks; while (p) { BLOCK *tem = p->next; pool->mem->free_fcn(p); p = tem; } } static XML_Char * poolAppend(STRING_POOL *pool, const ENCODING *enc, const char *ptr, const char *end) { if (! pool->ptr && ! poolGrow(pool)) return NULL; for (;;) { const enum XML_Convert_Result convert_res = XmlConvert( enc, &ptr, end, (ICHAR **)&(pool->ptr), (const ICHAR *)pool->end); if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) break; if (! poolGrow(pool)) return NULL; } return pool->start; } static const XML_Char *FASTCALL poolCopyString(STRING_POOL *pool, const XML_Char *s) { do { if (! poolAppendChar(pool, *s)) return NULL; } while (*s++); s = pool->start; poolFinish(pool); return s; } static const XML_Char * poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n) { if (! pool->ptr && ! poolGrow(pool)) { /* The following line is unreachable given the current usage of * poolCopyStringN(). Currently it is called from exactly one * place to copy the text of a simple general entity. By that * point, the name of the entity is already stored in the pool, so * pool->ptr cannot be NULL. * * If poolCopyStringN() is used elsewhere as it well might be, * this line may well become executable again. Regardless, this * sort of check shouldn't be removed lightly, so we just exclude * it from the coverage statistics. */ return NULL; /* LCOV_EXCL_LINE */ } for (; n > 0; --n, s++) { if (! poolAppendChar(pool, *s)) return NULL; } s = pool->start; poolFinish(pool); return s; } static const XML_Char *FASTCALL poolAppendString(STRING_POOL *pool, const XML_Char *s) { while (*s) { if (! poolAppendChar(pool, *s)) return NULL; s++; } return pool->start; } static XML_Char * poolStoreString(STRING_POOL *pool, const ENCODING *enc, const char *ptr, const char *end) { if (! poolAppend(pool, enc, ptr, end)) return NULL; if (pool->ptr == pool->end && ! poolGrow(pool)) return NULL; *(pool->ptr)++ = 0; return pool->start; } static size_t poolBytesToAllocateFor(int blockSize) { /* Unprotected math would be: ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char); ** ** Detect overflow, avoiding _signed_ overflow undefined behavior ** For a + b * c we check b * c in isolation first, so that addition of a ** on top has no chance of making us accept a small non-negative number */ const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */ if (blockSize <= 0) return 0; if (blockSize > (int)(INT_MAX / stretch)) return 0; { const int stretchedBlockSize = blockSize * (int)stretch; const int bytesToAllocate = (int)(offsetof(BLOCK, s) + (unsigned)stretchedBlockSize); if (bytesToAllocate < 0) return 0; return (size_t)bytesToAllocate; } } static XML_Bool FASTCALL poolGrow(STRING_POOL *pool) { if (pool->freeBlocks) { if (pool->start == 0) { pool->blocks = pool->freeBlocks; pool->freeBlocks = pool->freeBlocks->next; pool->blocks->next = NULL; pool->start = pool->blocks->s; pool->end = pool->start + pool->blocks->size; pool->ptr = pool->start; return XML_TRUE; } if (pool->end - pool->start < pool->freeBlocks->size) { BLOCK *tem = pool->freeBlocks->next; pool->freeBlocks->next = pool->blocks; pool->blocks = pool->freeBlocks; pool->freeBlocks = tem; memcpy(pool->blocks->s, pool->start, (pool->end - pool->start) * sizeof(XML_Char)); pool->ptr = pool->blocks->s + (pool->ptr - pool->start); pool->start = pool->blocks->s; pool->end = pool->start + pool->blocks->size; return XML_TRUE; } } if (pool->blocks && pool->start == pool->blocks->s) { BLOCK *temp; int blockSize = (int)((unsigned)(pool->end - pool->start) * 2U); size_t bytesToAllocate; /* NOTE: Needs to be calculated prior to calling `realloc` to avoid dangling pointers: */ const ptrdiff_t offsetInsideBlock = pool->ptr - pool->start; if (blockSize < 0) { /* This condition traps a situation where either more than * INT_MAX/2 bytes have already been allocated. This isn't * readily testable, since it is unlikely that an average * machine will have that much memory, so we exclude it from the * coverage statistics. */ return XML_FALSE; /* LCOV_EXCL_LINE */ } bytesToAllocate = poolBytesToAllocateFor(blockSize); if (bytesToAllocate == 0) return XML_FALSE; temp = (BLOCK *)pool->mem->realloc_fcn(pool->blocks, (unsigned)bytesToAllocate); if (temp == NULL) return XML_FALSE; pool->blocks = temp; pool->blocks->size = blockSize; pool->ptr = pool->blocks->s + offsetInsideBlock; pool->start = pool->blocks->s; pool->end = pool->start + blockSize; } else { BLOCK *tem; int blockSize = (int)(pool->end - pool->start); size_t bytesToAllocate; if (blockSize < 0) { /* This condition traps a situation where either more than * INT_MAX bytes have already been allocated (which is prevented * by various pieces of program logic, not least this one, never * mind the unlikelihood of actually having that much memory) or * the pool control fields have been corrupted (which could * conceivably happen in an extremely buggy user handler * function). Either way it isn't readily testable, so we * exclude it from the coverage statistics. */ return XML_FALSE; /* LCOV_EXCL_LINE */ } if (blockSize < INIT_BLOCK_SIZE) blockSize = INIT_BLOCK_SIZE; else { /* Detect overflow, avoiding _signed_ overflow undefined behavior */ if ((int)((unsigned)blockSize * 2U) < 0) { return XML_FALSE; } blockSize *= 2; } bytesToAllocate = poolBytesToAllocateFor(blockSize); if (bytesToAllocate == 0) return XML_FALSE; tem = pool->mem->malloc_fcn(bytesToAllocate); if (! tem) return XML_FALSE; tem->size = blockSize; tem->next = pool->blocks; pool->blocks = tem; if (pool->ptr != pool->start) memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char)); pool->ptr = tem->s + (pool->ptr - pool->start); pool->start = tem->s; pool->end = tem->s + blockSize; } return XML_TRUE; } static int FASTCALL nextScaffoldPart(XML_Parser parser) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ CONTENT_SCAFFOLD *me; int next; if (! dtd->scaffIndex) { /* Detect and prevent integer overflow. * The preprocessor guard addresses the "always false" warning * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX if (parser->m_groupSize > ((size_t)(-1) / sizeof(int))) { return -1; } #endif dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int)); if (! dtd->scaffIndex) return -1; dtd->scaffIndex[0] = 0; } if (dtd->scaffCount >= dtd->scaffSize) { CONTENT_SCAFFOLD *temp; if (dtd->scaffold) { /* Detect and prevent integer overflow */ if (dtd->scaffSize > UINT_MAX / 2u) { return -1; } /* Detect and prevent integer overflow. * The preprocessor guard addresses the "always false" warning * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX if (dtd->scaffSize > (size_t)(-1) / 2u / sizeof(CONTENT_SCAFFOLD)) { return -1; } #endif temp = (CONTENT_SCAFFOLD *)REALLOC( parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD)); if (temp == NULL) return -1; dtd->scaffSize *= 2; } else { temp = (CONTENT_SCAFFOLD *)MALLOC(parser, INIT_SCAFFOLD_ELEMENTS * sizeof(CONTENT_SCAFFOLD)); if (temp == NULL) return -1; dtd->scaffSize = INIT_SCAFFOLD_ELEMENTS; } dtd->scaffold = temp; } next = dtd->scaffCount++; me = &dtd->scaffold[next]; if (dtd->scaffLevel) { CONTENT_SCAFFOLD *parent = &dtd->scaffold[dtd->scaffIndex[dtd->scaffLevel - 1]]; if (parent->lastchild) { dtd->scaffold[parent->lastchild].nextsib = next; } if (! parent->childcnt) parent->firstchild = next; parent->lastchild = next; parent->childcnt++; } me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0; return next; } static XML_Content * build_model(XML_Parser parser) { /* Function build_model transforms the existing parser->m_dtd->scaffold * array of CONTENT_SCAFFOLD tree nodes into a new array of * XML_Content tree nodes followed by a gapless list of zero-terminated * strings. */ DTD *const dtd = parser->m_dtd; /* save one level of indirection */ XML_Content *ret; XML_Char *str; /* the current string writing location */ /* Detect and prevent integer overflow. * The preprocessor guard addresses the "always false" warning * from -Wtype-limits on platforms where * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */ #if UINT_MAX >= SIZE_MAX if (dtd->scaffCount > (size_t)(-1) / sizeof(XML_Content)) { return NULL; } if (dtd->contentStringLen > (size_t)(-1) / sizeof(XML_Char)) { return NULL; } #endif if (dtd->scaffCount * sizeof(XML_Content) > (size_t)(-1) - dtd->contentStringLen * sizeof(XML_Char)) { return NULL; } const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content) + (dtd->contentStringLen * sizeof(XML_Char))); ret = (XML_Content *)MALLOC(parser, allocsize); if (! ret) return NULL; /* What follows is an iterative implementation (of what was previously done * recursively in a dedicated function called "build_node". The old recursive * build_node could be forced into stack exhaustion from input as small as a * few megabyte, and so that was a security issue. Hence, a function call * stack is avoided now by resolving recursion.) * * The iterative approach works as follows: * * - We have two writing pointers, both walking up the result array; one does * the work, the other creates "jobs" for its colleague to do, and leads * the way: * * - The faster one, pointer jobDest, always leads and writes "what job * to do" by the other, once they reach that place in the * array: leader "jobDest" stores the source node array index (relative * to array dtd->scaffold) in field "numchildren". * * - The slower one, pointer dest, looks at the value stored in the * "numchildren" field (which actually holds a source node array index * at that time) and puts the real data from dtd->scaffold in. * * - Before the loop starts, jobDest writes source array index 0 * (where the root node is located) so that dest will have something to do * when it starts operation. * * - Whenever nodes with children are encountered, jobDest appends * them as new jobs, in order. As a result, tree node siblings are * adjacent in the resulting array, for example: * * [0] root, has two children * [1] first child of 0, has three children * [3] first child of 1, does not have children * [4] second child of 1, does not have children * [5] third child of 1, does not have children * [2] second child of 0, does not have children * * Or (the same data) presented in flat array view: * * [0] root, has two children * * [1] first child of 0, has three children * [2] second child of 0, does not have children * * [3] first child of 1, does not have children * [4] second child of 1, does not have children * [5] third child of 1, does not have children * * - The algorithm repeats until all target array indices have been processed. */ XML_Content *dest = ret; /* tree node writing location, moves upwards */ XML_Content *const destLimit = &ret[dtd->scaffCount]; XML_Content *jobDest = ret; /* next free writing location in target array */ str = (XML_Char *)&ret[dtd->scaffCount]; /* Add the starting job, the root node (index 0) of the source tree */ (jobDest++)->numchildren = 0; for (; dest < destLimit; dest++) { /* Retrieve source tree array index from job storage */ const int src_node = (int)dest->numchildren; /* Convert item */ dest->type = dtd->scaffold[src_node].type; dest->quant = dtd->scaffold[src_node].quant; if (dest->type == XML_CTYPE_NAME) { const XML_Char *src; dest->name = str; src = dtd->scaffold[src_node].name; for (;;) { *str++ = *src; if (! *src) break; src++; } dest->numchildren = 0; dest->children = NULL; } else { unsigned int i; int cn; dest->name = NULL; dest->numchildren = dtd->scaffold[src_node].childcnt; dest->children = jobDest; /* Append scaffold indices of children to array */ for (i = 0, cn = dtd->scaffold[src_node].firstchild; i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib) (jobDest++)->numchildren = (unsigned int)cn; } } return ret; } static ELEMENT_TYPE * getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr, const char *end) { DTD *const dtd = parser->m_dtd; /* save one level of indirection */ const XML_Char *name = poolStoreString(&dtd->pool, enc, ptr, end); ELEMENT_TYPE *ret; if (! name) return NULL; ret = (ELEMENT_TYPE *)lookup(parser, &dtd->elementTypes, name, sizeof(ELEMENT_TYPE)); if (! ret) return NULL; if (ret->name != name) poolDiscard(&dtd->pool); else { poolFinish(&dtd->pool); if (! setElementTypePrefix(parser, ret)) return NULL; } return ret; } static XML_Char * copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) { size_t charsRequired = 0; XML_Char *result; /* First determine how long the string is */ while (s[charsRequired] != 0) { charsRequired++; } /* Include the terminator */ charsRequired++; /* Now allocate space for the copy */ result = memsuite->malloc_fcn(charsRequired * sizeof(XML_Char)); if (result == NULL) return NULL; /* Copy the original into place */ memcpy(result, s, charsRequired * sizeof(XML_Char)); return result; } #if XML_GE == 1 static float accountingGetCurrentAmplification(XML_Parser rootParser) { // 1.........1.........12 => 22 const size_t lenOfShortestInclude = sizeof("") - 1; const XmlBigCount countBytesOutput = rootParser->m_accounting.countBytesDirect + rootParser->m_accounting.countBytesIndirect; const float amplificationFactor = rootParser->m_accounting.countBytesDirect ? (countBytesOutput / (float)(rootParser->m_accounting.countBytesDirect)) : ((lenOfShortestInclude + rootParser->m_accounting.countBytesIndirect) / (float)lenOfShortestInclude); assert(! rootParser->m_parentParser); return amplificationFactor; } static void accountingReportStats(XML_Parser originParser, const char *epilog) { const XML_Parser rootParser = getRootParserOf(originParser, NULL); assert(! rootParser->m_parentParser); if (rootParser->m_accounting.debugLevel == 0u) { return; } const float amplificationFactor = accountingGetCurrentAmplification(rootParser); fprintf(stderr, "expat: Accounting(%p): Direct " EXPAT_FMT_ULL( "10") ", indirect " EXPAT_FMT_ULL("10") ", amplification %8.2f%s", (void *)rootParser, rootParser->m_accounting.countBytesDirect, rootParser->m_accounting.countBytesIndirect, (double)amplificationFactor, epilog); } static void accountingOnAbort(XML_Parser originParser) { accountingReportStats(originParser, " ABORTING\n"); } static void accountingReportDiff(XML_Parser rootParser, unsigned int levelsAwayFromRootParser, const char *before, const char *after, ptrdiff_t bytesMore, int source_line, enum XML_Account account) { assert(! rootParser->m_parentParser); fprintf(stderr, " (+" EXPAT_FMT_PTRDIFF_T("6") " bytes %s|%d, xmlparse.c:%d) %*s\"", bytesMore, (account == XML_ACCOUNT_DIRECT) ? "DIR" : "EXP", levelsAwayFromRootParser, source_line, 10, ""); const char ellipis[] = "[..]"; const size_t ellipsisLength = sizeof(ellipis) /* because compile-time */ - 1; const unsigned int contextLength = 10; /* Note: Performance is of no concern here */ const char *walker = before; if ((rootParser->m_accounting.debugLevel >= 3u) || (after - before) <= (ptrdiff_t)(contextLength + ellipsisLength + contextLength)) { for (; walker < after; walker++) { fprintf(stderr, "%s", unsignedCharToPrintable(walker[0])); } } else { for (; walker < before + contextLength; walker++) { fprintf(stderr, "%s", unsignedCharToPrintable(walker[0])); } fprintf(stderr, ellipis); walker = after - contextLength; for (; walker < after; walker++) { fprintf(stderr, "%s", unsignedCharToPrintable(walker[0])); } } fprintf(stderr, "\"\n"); } static XML_Bool accountingDiffTolerated(XML_Parser originParser, int tok, const char *before, const char *after, int source_line, enum XML_Account account) { /* Note: We need to check the token type *first* to be sure that * we can even access variable , safely. * E.g. for XML_TOK_NONE may hold an invalid pointer. */ switch (tok) { case XML_TOK_INVALID: case XML_TOK_PARTIAL: case XML_TOK_PARTIAL_CHAR: case XML_TOK_NONE: return XML_TRUE; } if (account == XML_ACCOUNT_NONE) return XML_TRUE; /* because these bytes have been accounted for, already */ unsigned int levelsAwayFromRootParser; const XML_Parser rootParser = getRootParserOf(originParser, &levelsAwayFromRootParser); assert(! rootParser->m_parentParser); const int isDirect = (account == XML_ACCOUNT_DIRECT) && (originParser == rootParser); const ptrdiff_t bytesMore = after - before; XmlBigCount *const additionTarget = isDirect ? &rootParser->m_accounting.countBytesDirect : &rootParser->m_accounting.countBytesIndirect; /* Detect and avoid integer overflow */ if (*additionTarget > (XmlBigCount)(-1) - (XmlBigCount)bytesMore) return XML_FALSE; *additionTarget += bytesMore; const XmlBigCount countBytesOutput = rootParser->m_accounting.countBytesDirect + rootParser->m_accounting.countBytesIndirect; const float amplificationFactor = accountingGetCurrentAmplification(rootParser); const XML_Bool tolerated = (countBytesOutput < rootParser->m_accounting.activationThresholdBytes) || (amplificationFactor <= rootParser->m_accounting.maximumAmplificationFactor); if (rootParser->m_accounting.debugLevel >= 2u) { accountingReportStats(rootParser, ""); accountingReportDiff(rootParser, levelsAwayFromRootParser, before, after, bytesMore, source_line, account); } return tolerated; } unsigned long long testingAccountingGetCountBytesDirect(XML_Parser parser) { if (! parser) return 0; return parser->m_accounting.countBytesDirect; } unsigned long long testingAccountingGetCountBytesIndirect(XML_Parser parser) { if (! parser) return 0; return parser->m_accounting.countBytesIndirect; } static void entityTrackingReportStats(XML_Parser rootParser, ENTITY *entity, const char *action, int sourceLine) { assert(! rootParser->m_parentParser); if (rootParser->m_entity_stats.debugLevel == 0u) return; # if defined(XML_UNICODE) const char *const entityName = "[..]"; # else const char *const entityName = entity->name; # endif fprintf( stderr, "expat: Entities(%p): Count %9d, depth %2d/%2d %*s%s%s; %s length %d (xmlparse.c:%d)\n", (void *)rootParser, rootParser->m_entity_stats.countEverOpened, rootParser->m_entity_stats.currentDepth, rootParser->m_entity_stats.maximumDepthSeen, (rootParser->m_entity_stats.currentDepth - 1) * 2, "", entity->is_param ? "%" : "&", entityName, action, entity->textLen, sourceLine); } static void entityTrackingOnOpen(XML_Parser originParser, ENTITY *entity, int sourceLine) { const XML_Parser rootParser = getRootParserOf(originParser, NULL); assert(! rootParser->m_parentParser); rootParser->m_entity_stats.countEverOpened++; rootParser->m_entity_stats.currentDepth++; if (rootParser->m_entity_stats.currentDepth > rootParser->m_entity_stats.maximumDepthSeen) { rootParser->m_entity_stats.maximumDepthSeen++; } entityTrackingReportStats(rootParser, entity, "OPEN ", sourceLine); } static void entityTrackingOnClose(XML_Parser originParser, ENTITY *entity, int sourceLine) { const XML_Parser rootParser = getRootParserOf(originParser, NULL); assert(! rootParser->m_parentParser); entityTrackingReportStats(rootParser, entity, "CLOSE", sourceLine); rootParser->m_entity_stats.currentDepth--; } static XML_Parser getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) { XML_Parser rootParser = parser; unsigned int stepsTakenUpwards = 0; while (rootParser->m_parentParser) { rootParser = rootParser->m_parentParser; stepsTakenUpwards++; } assert(! rootParser->m_parentParser); if (outLevelDiff != NULL) { *outLevelDiff = stepsTakenUpwards; } return rootParser; } const char * unsignedCharToPrintable(unsigned char c) { switch (c) { case 0: return "\\0"; case 1: return "\\x1"; case 2: return "\\x2"; case 3: return "\\x3"; case 4: return "\\x4"; case 5: return "\\x5"; case 6: return "\\x6"; case 7: return "\\x7"; case 8: return "\\x8"; case 9: return "\\t"; case 10: return "\\n"; case 11: return "\\xB"; case 12: return "\\xC"; case 13: return "\\r"; case 14: return "\\xE"; case 15: return "\\xF"; case 16: return "\\x10"; case 17: return "\\x11"; case 18: return "\\x12"; case 19: return "\\x13"; case 20: return "\\x14"; case 21: return "\\x15"; case 22: return "\\x16"; case 23: return "\\x17"; case 24: return "\\x18"; case 25: return "\\x19"; case 26: return "\\x1A"; case 27: return "\\x1B"; case 28: return "\\x1C"; case 29: return "\\x1D"; case 30: return "\\x1E"; case 31: return "\\x1F"; case 32: return " "; case 33: return "!"; case 34: return "\\\""; case 35: return "#"; case 36: return "$"; case 37: return "%"; case 38: return "&"; case 39: return "'"; case 40: return "("; case 41: return ")"; case 42: return "*"; case 43: return "+"; case 44: return ","; case 45: return "-"; case 46: return "."; case 47: return "/"; case 48: return "0"; case 49: return "1"; case 50: return "2"; case 51: return "3"; case 52: return "4"; case 53: return "5"; case 54: return "6"; case 55: return "7"; case 56: return "8"; case 57: return "9"; case 58: return ":"; case 59: return ";"; case 60: return "<"; case 61: return "="; case 62: return ">"; case 63: return "?"; case 64: return "@"; case 65: return "A"; case 66: return "B"; case 67: return "C"; case 68: return "D"; case 69: return "E"; case 70: return "F"; case 71: return "G"; case 72: return "H"; case 73: return "I"; case 74: return "J"; case 75: return "K"; case 76: return "L"; case 77: return "M"; case 78: return "N"; case 79: return "O"; case 80: return "P"; case 81: return "Q"; case 82: return "R"; case 83: return "S"; case 84: return "T"; case 85: return "U"; case 86: return "V"; case 87: return "W"; case 88: return "X"; case 89: return "Y"; case 90: return "Z"; case 91: return "["; case 92: return "\\\\"; case 93: return "]"; case 94: return "^"; case 95: return "_"; case 96: return "`"; case 97: return "a"; case 98: return "b"; case 99: return "c"; case 100: return "d"; case 101: return "e"; case 102: return "f"; case 103: return "g"; case 104: return "h"; case 105: return "i"; case 106: return "j"; case 107: return "k"; case 108: return "l"; case 109: return "m"; case 110: return "n"; case 111: return "o"; case 112: return "p"; case 113: return "q"; case 114: return "r"; case 115: return "s"; case 116: return "t"; case 117: return "u"; case 118: return "v"; case 119: return "w"; case 120: return "x"; case 121: return "y"; case 122: return "z"; case 123: return "{"; case 124: return "|"; case 125: return "}"; case 126: return "~"; case 127: return "\\x7F"; case 128: return "\\x80"; case 129: return "\\x81"; case 130: return "\\x82"; case 131: return "\\x83"; case 132: return "\\x84"; case 133: return "\\x85"; case 134: return "\\x86"; case 135: return "\\x87"; case 136: return "\\x88"; case 137: return "\\x89"; case 138: return "\\x8A"; case 139: return "\\x8B"; case 140: return "\\x8C"; case 141: return "\\x8D"; case 142: return "\\x8E"; case 143: return "\\x8F"; case 144: return "\\x90"; case 145: return "\\x91"; case 146: return "\\x92"; case 147: return "\\x93"; case 148: return "\\x94"; case 149: return "\\x95"; case 150: return "\\x96"; case 151: return "\\x97"; case 152: return "\\x98"; case 153: return "\\x99"; case 154: return "\\x9A"; case 155: return "\\x9B"; case 156: return "\\x9C"; case 157: return "\\x9D"; case 158: return "\\x9E"; case 159: return "\\x9F"; case 160: return "\\xA0"; case 161: return "\\xA1"; case 162: return "\\xA2"; case 163: return "\\xA3"; case 164: return "\\xA4"; case 165: return "\\xA5"; case 166: return "\\xA6"; case 167: return "\\xA7"; case 168: return "\\xA8"; case 169: return "\\xA9"; case 170: return "\\xAA"; case 171: return "\\xAB"; case 172: return "\\xAC"; case 173: return "\\xAD"; case 174: return "\\xAE"; case 175: return "\\xAF"; case 176: return "\\xB0"; case 177: return "\\xB1"; case 178: return "\\xB2"; case 179: return "\\xB3"; case 180: return "\\xB4"; case 181: return "\\xB5"; case 182: return "\\xB6"; case 183: return "\\xB7"; case 184: return "\\xB8"; case 185: return "\\xB9"; case 186: return "\\xBA"; case 187: return "\\xBB"; case 188: return "\\xBC"; case 189: return "\\xBD"; case 190: return "\\xBE"; case 191: return "\\xBF"; case 192: return "\\xC0"; case 193: return "\\xC1"; case 194: return "\\xC2"; case 195: return "\\xC3"; case 196: return "\\xC4"; case 197: return "\\xC5"; case 198: return "\\xC6"; case 199: return "\\xC7"; case 200: return "\\xC8"; case 201: return "\\xC9"; case 202: return "\\xCA"; case 203: return "\\xCB"; case 204: return "\\xCC"; case 205: return "\\xCD"; case 206: return "\\xCE"; case 207: return "\\xCF"; case 208: return "\\xD0"; case 209: return "\\xD1"; case 210: return "\\xD2"; case 211: return "\\xD3"; case 212: return "\\xD4"; case 213: return "\\xD5"; case 214: return "\\xD6"; case 215: return "\\xD7"; case 216: return "\\xD8"; case 217: return "\\xD9"; case 218: return "\\xDA"; case 219: return "\\xDB"; case 220: return "\\xDC"; case 221: return "\\xDD"; case 222: return "\\xDE"; case 223: return "\\xDF"; case 224: return "\\xE0"; case 225: return "\\xE1"; case 226: return "\\xE2"; case 227: return "\\xE3"; case 228: return "\\xE4"; case 229: return "\\xE5"; case 230: return "\\xE6"; case 231: return "\\xE7"; case 232: return "\\xE8"; case 233: return "\\xE9"; case 234: return "\\xEA"; case 235: return "\\xEB"; case 236: return "\\xEC"; case 237: return "\\xED"; case 238: return "\\xEE"; case 239: return "\\xEF"; case 240: return "\\xF0"; case 241: return "\\xF1"; case 242: return "\\xF2"; case 243: return "\\xF3"; case 244: return "\\xF4"; case 245: return "\\xF5"; case 246: return "\\xF6"; case 247: return "\\xF7"; case 248: return "\\xF8"; case 249: return "\\xF9"; case 250: return "\\xFA"; case 251: return "\\xFB"; case 252: return "\\xFC"; case 253: return "\\xFD"; case 254: return "\\xFE"; case 255: return "\\xFF"; default: assert(0); /* never gets here */ return "dead code"; } assert(0); /* never gets here */ } #endif /* XML_GE == 1 */ static unsigned long getDebugLevel(const char *variableName, unsigned long defaultDebugLevel) { const char *const valueOrNull = getenv(variableName); if (valueOrNull == NULL) { return defaultDebugLevel; } const char *const value = valueOrNull; errno = 0; char *afterValue = NULL; unsigned long debugLevel = strtoul(value, &afterValue, 10); if ((errno != 0) || (afterValue == value) || (afterValue[0] != '\0')) { errno = 0; return defaultDebugLevel; } return debugLevel; } tdom-0.9.5-src/expat/COPYING0000644000175000017500000000217014703531020014112 0ustar rolfrolfCopyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper Copyright (c) 2001-2022 Expat maintainers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tdom-0.9.5-src/expat/iasciitab.h0000644000175000017500000000700614703531020015163 0ustar rolfrolf/* __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2002 Fred L. Drake, Jr. Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */ /* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, /* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML, /* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, /* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, /* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, /* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, /* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, /* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, /* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, /* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, /* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, /* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, /* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, /* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, /* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, /* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, /* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, /* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, /* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, /* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, tdom-0.9.5-src/expat/xmlrole.h0000644000175000017500000001110714703531020014712 0ustar rolfrolf/* __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2002 Karl Waclawek Copyright (c) 2002 Fred L. Drake, Jr. Copyright (c) 2017-2024 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef XmlRole_INCLUDED #define XmlRole_INCLUDED 1 #ifdef __VMS /* 0 1 2 3 0 1 2 3 1234567890123456789012345678901 1234567890123456789012345678901 */ # define XmlPrologStateInitExternalEntity XmlPrologStateInitExternalEnt #endif #include "xmltok.h" #ifdef __cplusplus extern "C" { #endif enum { XML_ROLE_ERROR = -1, XML_ROLE_NONE = 0, XML_ROLE_XML_DECL, XML_ROLE_INSTANCE_START, XML_ROLE_DOCTYPE_NONE, XML_ROLE_DOCTYPE_NAME, XML_ROLE_DOCTYPE_SYSTEM_ID, XML_ROLE_DOCTYPE_PUBLIC_ID, XML_ROLE_DOCTYPE_INTERNAL_SUBSET, XML_ROLE_DOCTYPE_CLOSE, XML_ROLE_GENERAL_ENTITY_NAME, XML_ROLE_PARAM_ENTITY_NAME, XML_ROLE_ENTITY_NONE, XML_ROLE_ENTITY_VALUE, XML_ROLE_ENTITY_SYSTEM_ID, XML_ROLE_ENTITY_PUBLIC_ID, XML_ROLE_ENTITY_COMPLETE, XML_ROLE_ENTITY_NOTATION_NAME, XML_ROLE_NOTATION_NONE, XML_ROLE_NOTATION_NAME, XML_ROLE_NOTATION_SYSTEM_ID, XML_ROLE_NOTATION_NO_SYSTEM_ID, XML_ROLE_NOTATION_PUBLIC_ID, XML_ROLE_ATTRIBUTE_NAME, XML_ROLE_ATTRIBUTE_TYPE_CDATA, XML_ROLE_ATTRIBUTE_TYPE_ID, XML_ROLE_ATTRIBUTE_TYPE_IDREF, XML_ROLE_ATTRIBUTE_TYPE_IDREFS, XML_ROLE_ATTRIBUTE_TYPE_ENTITY, XML_ROLE_ATTRIBUTE_TYPE_ENTITIES, XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN, XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS, XML_ROLE_ATTRIBUTE_ENUM_VALUE, XML_ROLE_ATTRIBUTE_NOTATION_VALUE, XML_ROLE_ATTLIST_NONE, XML_ROLE_ATTLIST_ELEMENT_NAME, XML_ROLE_IMPLIED_ATTRIBUTE_VALUE, XML_ROLE_REQUIRED_ATTRIBUTE_VALUE, XML_ROLE_DEFAULT_ATTRIBUTE_VALUE, XML_ROLE_FIXED_ATTRIBUTE_VALUE, XML_ROLE_ELEMENT_NONE, XML_ROLE_ELEMENT_NAME, XML_ROLE_CONTENT_ANY, XML_ROLE_CONTENT_EMPTY, XML_ROLE_CONTENT_PCDATA, XML_ROLE_GROUP_OPEN, XML_ROLE_GROUP_CLOSE, XML_ROLE_GROUP_CLOSE_REP, XML_ROLE_GROUP_CLOSE_OPT, XML_ROLE_GROUP_CLOSE_PLUS, XML_ROLE_GROUP_CHOICE, XML_ROLE_GROUP_SEQUENCE, XML_ROLE_CONTENT_ELEMENT, XML_ROLE_CONTENT_ELEMENT_REP, XML_ROLE_CONTENT_ELEMENT_OPT, XML_ROLE_CONTENT_ELEMENT_PLUS, XML_ROLE_PI, XML_ROLE_COMMENT, #ifdef XML_DTD XML_ROLE_TEXT_DECL, XML_ROLE_IGNORE_SECT, XML_ROLE_INNER_PARAM_ENTITY_REF, #endif /* XML_DTD */ XML_ROLE_PARAM_ENTITY_REF }; typedef struct prolog_state { int(PTRCALL *handler)(struct prolog_state *state, int tok, const char *ptr, const char *end, const ENCODING *enc); unsigned level; int role_none; #ifdef XML_DTD unsigned includeLevel; int documentEntity; int inEntityValue; #endif /* XML_DTD */ } PROLOG_STATE; void XmlPrologStateInit(PROLOG_STATE *state); #ifdef XML_DTD void XmlPrologStateInitExternalEntity(PROLOG_STATE *state); #endif /* XML_DTD */ #define XmlTokenRole(state, tok, ptr, end, enc) \ (((state)->handler)(state, tok, ptr, end, enc)) #ifdef __cplusplus } #endif #endif /* not XmlRole_INCLUDED */ tdom-0.9.5-src/expat/nametab.h0000644000175000017500000002152414703531020014643 0ustar rolfrolf/* __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 2000 Clark Cooper Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ static const unsigned namingBitmap[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE, 0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF, 0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF, 0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, 0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, 0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, 0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, 0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF, 0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000, 0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060, 0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003, 0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003, 0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000, 0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001, 0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003, 0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000, 0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003, 0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003, 0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000, 0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF, 0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB, 0x40000000, 0xF580C900, 0x00000007, 0x02010800, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, 0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF, 0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF, 0x00000000, 0x00004C40, 0x00000000, 0x00000000, 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF, 0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF, 0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000, 0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE, 0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF, 0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003, 0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, 0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, 0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, 0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, 0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF, 0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF, 0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF, 0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF, 0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF, 0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0, 0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1, 0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3, 0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80, 0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3, 0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3, 0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000, 0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000, 0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF, 0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1FFF0000, 0x00000002, 0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF, 0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF, }; static const unsigned char nmstrtPages[] = { 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static const unsigned char namePages[] = { 0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, 0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, 0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; tdom-0.9.5-src/expat/xmltok_impl.c0000644000175000017500000015073014703531020015570 0ustar rolfrolf/* This file is included (from xmltok.c, 1-3 times depending on XML_MIN_SIZE)! __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2002 Fred L. Drake, Jr. Copyright (c) 2002-2016 Karl Waclawek Copyright (c) 2016-2022 Sebastian Pipping Copyright (c) 2017 Rhodri James Copyright (c) 2018 Benjamin Peterson Copyright (c) 2018 Anton Maklakov Copyright (c) 2019 David Loffredo Copyright (c) 2020 Boris Kolpackov Copyright (c) 2022 Martin Ettl Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifdef XML_TOK_IMPL_C # ifndef IS_INVALID_CHAR // i.e. for UTF-16 and XML_MIN_SIZE not defined # define IS_INVALID_CHAR(enc, ptr, n) (0) # endif # define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \ case BT_LEAD##n: \ if (end - ptr < n) \ return XML_TOK_PARTIAL_CHAR; \ if (IS_INVALID_CHAR(enc, ptr, n)) { \ *(nextTokPtr) = (ptr); \ return XML_TOK_INVALID; \ } \ ptr += n; \ break; # define INVALID_CASES(ptr, nextTokPtr) \ INVALID_LEAD_CASE(2, ptr, nextTokPtr) \ INVALID_LEAD_CASE(3, ptr, nextTokPtr) \ INVALID_LEAD_CASE(4, ptr, nextTokPtr) \ case BT_NONXML: \ case BT_MALFORM: \ case BT_TRAIL: \ *(nextTokPtr) = (ptr); \ return XML_TOK_INVALID; # define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \ case BT_LEAD##n: \ if (end - ptr < n) \ return XML_TOK_PARTIAL_CHAR; \ if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NAME_CHAR(enc, ptr, n)) { \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ ptr += n; \ break; # define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \ case BT_NONASCII: \ if (! IS_NAME_CHAR_MINBPC(enc, ptr)) { \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ /* fall through */ \ case BT_NMSTRT: \ case BT_HEX: \ case BT_DIGIT: \ case BT_NAME: \ case BT_MINUS: \ ptr += MINBPC(enc); \ break; \ CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \ CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \ CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr) # define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \ case BT_LEAD##n: \ if ((end) - (ptr) < (n)) \ return XML_TOK_PARTIAL_CHAR; \ if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NMSTRT_CHAR(enc, ptr, n)) { \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ ptr += n; \ break; # define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \ case BT_NONASCII: \ if (! IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ /* fall through */ \ case BT_NMSTRT: \ case BT_HEX: \ ptr += MINBPC(enc); \ break; \ CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \ CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \ CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr) # ifndef PREFIX # define PREFIX(ident) ident # endif # define HAS_CHARS(enc, ptr, end, count) \ ((end) - (ptr) >= ((count) * MINBPC(enc))) # define HAS_CHAR(enc, ptr, end) HAS_CHARS(enc, ptr, end, 1) # define REQUIRE_CHARS(enc, ptr, end, count) \ { \ if (! HAS_CHARS(enc, ptr, end, count)) { \ return XML_TOK_PARTIAL; \ } \ } # define REQUIRE_CHAR(enc, ptr, end) REQUIRE_CHARS(enc, ptr, end, 1) /* ptr points to character following " */ switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) { case BT_S: case BT_CR: case BT_LF: case BT_PERCNT: *nextTokPtr = ptr; return XML_TOK_INVALID; } /* fall through */ case BT_S: case BT_CR: case BT_LF: *nextTokPtr = ptr; return XML_TOK_DECL_OPEN; case BT_NMSTRT: case BT_HEX: ptr += MINBPC(enc); break; default: *nextTokPtr = ptr; return XML_TOK_INVALID; } } return XML_TOK_PARTIAL; } static int PTRCALL PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end, int *tokPtr) { int upper = 0; UNUSED_P(enc); *tokPtr = XML_TOK_PI; if (end - ptr != MINBPC(enc) * 3) return 1; switch (BYTE_TO_ASCII(enc, ptr)) { case ASCII_x: break; case ASCII_X: upper = 1; break; default: return 1; } ptr += MINBPC(enc); switch (BYTE_TO_ASCII(enc, ptr)) { case ASCII_m: break; case ASCII_M: upper = 1; break; default: return 1; } ptr += MINBPC(enc); switch (BYTE_TO_ASCII(enc, ptr)) { case ASCII_l: break; case ASCII_L: upper = 1; break; default: return 1; } if (upper) return 0; *tokPtr = XML_TOK_XML_DECL; return 1; } /* ptr points to character following "= end) return XML_TOK_NONE; if (MINBPC(enc) > 1) { size_t n = end - ptr; if (n & (MINBPC(enc) - 1)) { n &= ~(MINBPC(enc) - 1); if (n == 0) return XML_TOK_PARTIAL; end = ptr + n; } } switch (BYTE_TYPE(enc, ptr)) { case BT_RSQB: ptr += MINBPC(enc); REQUIRE_CHAR(enc, ptr, end); if (! CHAR_MATCHES(enc, ptr, ASCII_RSQB)) break; ptr += MINBPC(enc); REQUIRE_CHAR(enc, ptr, end); if (! CHAR_MATCHES(enc, ptr, ASCII_GT)) { ptr -= MINBPC(enc); break; } *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_CDATA_SECT_CLOSE; case BT_CR: ptr += MINBPC(enc); REQUIRE_CHAR(enc, ptr, end); if (BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); *nextTokPtr = ptr; return XML_TOK_DATA_NEWLINE; case BT_LF: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DATA_NEWLINE; INVALID_CASES(ptr, nextTokPtr) default: ptr += MINBPC(enc); break; } while (HAS_CHAR(enc, ptr, end)) { switch (BYTE_TYPE(enc, ptr)) { # define LEAD_CASE(n) \ case BT_LEAD##n: \ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ *nextTokPtr = ptr; \ return XML_TOK_DATA_CHARS; \ } \ ptr += n; \ break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) # undef LEAD_CASE case BT_NONXML: case BT_MALFORM: case BT_TRAIL: case BT_CR: case BT_LF: case BT_RSQB: *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; default: ptr += MINBPC(enc); break; } } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; } /* ptr points to character following "= end) return XML_TOK_NONE; if (MINBPC(enc) > 1) { size_t n = end - ptr; if (n & (MINBPC(enc) - 1)) { n &= ~(MINBPC(enc) - 1); if (n == 0) return XML_TOK_PARTIAL; end = ptr + n; } } switch (BYTE_TYPE(enc, ptr)) { case BT_LT: return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_AMP: return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_CR: ptr += MINBPC(enc); if (! HAS_CHAR(enc, ptr, end)) return XML_TOK_TRAILING_CR; if (BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); *nextTokPtr = ptr; return XML_TOK_DATA_NEWLINE; case BT_LF: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DATA_NEWLINE; case BT_RSQB: ptr += MINBPC(enc); if (! HAS_CHAR(enc, ptr, end)) return XML_TOK_TRAILING_RSQB; if (! CHAR_MATCHES(enc, ptr, ASCII_RSQB)) break; ptr += MINBPC(enc); if (! HAS_CHAR(enc, ptr, end)) return XML_TOK_TRAILING_RSQB; if (! CHAR_MATCHES(enc, ptr, ASCII_GT)) { ptr -= MINBPC(enc); break; } *nextTokPtr = ptr; return XML_TOK_INVALID; INVALID_CASES(ptr, nextTokPtr) default: ptr += MINBPC(enc); break; } while (HAS_CHAR(enc, ptr, end)) { switch (BYTE_TYPE(enc, ptr)) { # define LEAD_CASE(n) \ case BT_LEAD##n: \ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \ *nextTokPtr = ptr; \ return XML_TOK_DATA_CHARS; \ } \ ptr += n; \ break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) # undef LEAD_CASE case BT_RSQB: if (HAS_CHARS(enc, ptr, end, 2)) { if (! CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) { ptr += MINBPC(enc); break; } if (HAS_CHARS(enc, ptr, end, 3)) { if (! CHAR_MATCHES(enc, ptr + 2 * MINBPC(enc), ASCII_GT)) { ptr += MINBPC(enc); break; } *nextTokPtr = ptr + 2 * MINBPC(enc); return XML_TOK_INVALID; } } /* fall through */ case BT_AMP: case BT_LT: case BT_NONXML: case BT_MALFORM: case BT_TRAIL: case BT_CR: case BT_LF: *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; default: ptr += MINBPC(enc); break; } } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; } /* ptr points to character following "%" */ static int PTRCALL PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { REQUIRE_CHAR(enc, ptr, end); switch (BYTE_TYPE(enc, ptr)) { CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) case BT_S: case BT_LF: case BT_CR: case BT_PERCNT: *nextTokPtr = ptr; return XML_TOK_PERCENT; default: *nextTokPtr = ptr; return XML_TOK_INVALID; } while (HAS_CHAR(enc, ptr, end)) { switch (BYTE_TYPE(enc, ptr)) { CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) case BT_SEMI: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_PARAM_ENTITY_REF; default: *nextTokPtr = ptr; return XML_TOK_INVALID; } } return XML_TOK_PARTIAL; } static int PTRCALL PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { REQUIRE_CHAR(enc, ptr, end); switch (BYTE_TYPE(enc, ptr)) { CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) default: *nextTokPtr = ptr; return XML_TOK_INVALID; } while (HAS_CHAR(enc, ptr, end)) { switch (BYTE_TYPE(enc, ptr)) { CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) case BT_CR: case BT_LF: case BT_S: case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR: *nextTokPtr = ptr; return XML_TOK_POUND_NAME; default: *nextTokPtr = ptr; return XML_TOK_INVALID; } } return -XML_TOK_POUND_NAME; } static int PTRCALL PREFIX(scanLit)(int open, const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { while (HAS_CHAR(enc, ptr, end)) { int t = BYTE_TYPE(enc, ptr); switch (t) { INVALID_CASES(ptr, nextTokPtr) case BT_QUOT: case BT_APOS: ptr += MINBPC(enc); if (t != open) break; if (! HAS_CHAR(enc, ptr, end)) return -XML_TOK_LITERAL; *nextTokPtr = ptr; switch (BYTE_TYPE(enc, ptr)) { case BT_S: case BT_CR: case BT_LF: case BT_GT: case BT_PERCNT: case BT_LSQB: return XML_TOK_LITERAL; default: return XML_TOK_INVALID; } default: ptr += MINBPC(enc); break; } } return XML_TOK_PARTIAL; } static int PTRCALL PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { int tok; if (ptr >= end) return XML_TOK_NONE; if (MINBPC(enc) > 1) { size_t n = end - ptr; if (n & (MINBPC(enc) - 1)) { n &= ~(MINBPC(enc) - 1); if (n == 0) return XML_TOK_PARTIAL; end = ptr + n; } } switch (BYTE_TYPE(enc, ptr)) { case BT_QUOT: return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_APOS: return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_LT: { ptr += MINBPC(enc); REQUIRE_CHAR(enc, ptr, end); switch (BYTE_TYPE(enc, ptr)) { case BT_EXCL: return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_QUEST: return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_NMSTRT: case BT_HEX: case BT_NONASCII: case BT_LEAD2: case BT_LEAD3: case BT_LEAD4: *nextTokPtr = ptr - MINBPC(enc); return XML_TOK_INSTANCE_START; } *nextTokPtr = ptr; return XML_TOK_INVALID; } case BT_CR: if (ptr + MINBPC(enc) == end) { *nextTokPtr = end; /* indicate that this might be part of a CR/LF pair */ return -XML_TOK_PROLOG_S; } /* fall through */ case BT_S: case BT_LF: for (;;) { ptr += MINBPC(enc); if (! HAS_CHAR(enc, ptr, end)) break; switch (BYTE_TYPE(enc, ptr)) { case BT_S: case BT_LF: break; case BT_CR: /* don't split CR/LF pair */ if (ptr + MINBPC(enc) != end) break; /* fall through */ default: *nextTokPtr = ptr; return XML_TOK_PROLOG_S; } } *nextTokPtr = ptr; return XML_TOK_PROLOG_S; case BT_PERCNT: return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); case BT_COMMA: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_COMMA; case BT_LSQB: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_OPEN_BRACKET; case BT_RSQB: ptr += MINBPC(enc); if (! HAS_CHAR(enc, ptr, end)) return -XML_TOK_CLOSE_BRACKET; if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) { REQUIRE_CHARS(enc, ptr, end, 2); if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_GT)) { *nextTokPtr = ptr + 2 * MINBPC(enc); return XML_TOK_COND_SECT_CLOSE; } } *nextTokPtr = ptr; return XML_TOK_CLOSE_BRACKET; case BT_LPAR: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_OPEN_PAREN; case BT_RPAR: ptr += MINBPC(enc); if (! HAS_CHAR(enc, ptr, end)) return -XML_TOK_CLOSE_PAREN; switch (BYTE_TYPE(enc, ptr)) { case BT_AST: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_CLOSE_PAREN_ASTERISK; case BT_QUEST: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_CLOSE_PAREN_QUESTION; case BT_PLUS: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_CLOSE_PAREN_PLUS; case BT_CR: case BT_LF: case BT_S: case BT_GT: case BT_COMMA: case BT_VERBAR: case BT_RPAR: *nextTokPtr = ptr; return XML_TOK_CLOSE_PAREN; } *nextTokPtr = ptr; return XML_TOK_INVALID; case BT_VERBAR: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_OR; case BT_GT: *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DECL_CLOSE; case BT_NUM: return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr); # define LEAD_CASE(n) \ case BT_LEAD##n: \ if (end - ptr < n) \ return XML_TOK_PARTIAL_CHAR; \ if (IS_INVALID_CHAR(enc, ptr, n)) { \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; \ } \ if (IS_NMSTRT_CHAR(enc, ptr, n)) { \ ptr += n; \ tok = XML_TOK_NAME; \ break; \ } \ if (IS_NAME_CHAR(enc, ptr, n)) { \ ptr += n; \ tok = XML_TOK_NMTOKEN; \ break; \ } \ *nextTokPtr = ptr; \ return XML_TOK_INVALID; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) # undef LEAD_CASE case BT_NMSTRT: case BT_HEX: tok = XML_TOK_NAME; ptr += MINBPC(enc); break; case BT_DIGIT: case BT_NAME: case BT_MINUS: # ifdef XML_NS case BT_COLON: # endif tok = XML_TOK_NMTOKEN; ptr += MINBPC(enc); break; case BT_NONASCII: if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { ptr += MINBPC(enc); tok = XML_TOK_NAME; break; } if (IS_NAME_CHAR_MINBPC(enc, ptr)) { ptr += MINBPC(enc); tok = XML_TOK_NMTOKEN; break; } /* fall through */ default: *nextTokPtr = ptr; return XML_TOK_INVALID; } while (HAS_CHAR(enc, ptr, end)) { switch (BYTE_TYPE(enc, ptr)) { CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) case BT_GT: case BT_RPAR: case BT_COMMA: case BT_VERBAR: case BT_LSQB: case BT_PERCNT: case BT_S: case BT_CR: case BT_LF: *nextTokPtr = ptr; return tok; # ifdef XML_NS case BT_COLON: ptr += MINBPC(enc); switch (tok) { case XML_TOK_NAME: REQUIRE_CHAR(enc, ptr, end); tok = XML_TOK_PREFIXED_NAME; switch (BYTE_TYPE(enc, ptr)) { CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) default: tok = XML_TOK_NMTOKEN; break; } break; case XML_TOK_PREFIXED_NAME: tok = XML_TOK_NMTOKEN; break; } break; # endif case BT_PLUS: if (tok == XML_TOK_NMTOKEN) { *nextTokPtr = ptr; return XML_TOK_INVALID; } *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_NAME_PLUS; case BT_AST: if (tok == XML_TOK_NMTOKEN) { *nextTokPtr = ptr; return XML_TOK_INVALID; } *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_NAME_ASTERISK; case BT_QUEST: if (tok == XML_TOK_NMTOKEN) { *nextTokPtr = ptr; return XML_TOK_INVALID; } *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_NAME_QUESTION; default: *nextTokPtr = ptr; return XML_TOK_INVALID; } } return -tok; } static int PTRCALL PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { const char *start; if (ptr >= end) return XML_TOK_NONE; else if (! HAS_CHAR(enc, ptr, end)) { /* This line cannot be executed. The incoming data has already * been tokenized once, so incomplete characters like this have * already been eliminated from the input. Retaining the paranoia * check is still valuable, however. */ return XML_TOK_PARTIAL; /* LCOV_EXCL_LINE */ } start = ptr; while (HAS_CHAR(enc, ptr, end)) { switch (BYTE_TYPE(enc, ptr)) { # define LEAD_CASE(n) \ case BT_LEAD##n: \ ptr += n; /* NOTE: The encoding has already been validated. */ \ break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) # undef LEAD_CASE case BT_AMP: if (ptr == start) return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_LT: /* this is for inside entity references */ *nextTokPtr = ptr; return XML_TOK_INVALID; case BT_LF: if (ptr == start) { *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DATA_NEWLINE; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_CR: if (ptr == start) { ptr += MINBPC(enc); if (! HAS_CHAR(enc, ptr, end)) return XML_TOK_TRAILING_CR; if (BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); *nextTokPtr = ptr; return XML_TOK_DATA_NEWLINE; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_S: if (ptr == start) { *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_ATTRIBUTE_VALUE_S; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; default: ptr += MINBPC(enc); break; } } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; } static int PTRCALL PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { const char *start; if (ptr >= end) return XML_TOK_NONE; else if (! HAS_CHAR(enc, ptr, end)) { /* This line cannot be executed. The incoming data has already * been tokenized once, so incomplete characters like this have * already been eliminated from the input. Retaining the paranoia * check is still valuable, however. */ return XML_TOK_PARTIAL; /* LCOV_EXCL_LINE */ } start = ptr; while (HAS_CHAR(enc, ptr, end)) { switch (BYTE_TYPE(enc, ptr)) { # define LEAD_CASE(n) \ case BT_LEAD##n: \ ptr += n; /* NOTE: The encoding has already been validated. */ \ break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) # undef LEAD_CASE case BT_AMP: if (ptr == start) return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr); *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_PERCNT: if (ptr == start) { int tok = PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr); return (tok == XML_TOK_PERCENT) ? XML_TOK_INVALID : tok; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_LF: if (ptr == start) { *nextTokPtr = ptr + MINBPC(enc); return XML_TOK_DATA_NEWLINE; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; case BT_CR: if (ptr == start) { ptr += MINBPC(enc); if (! HAS_CHAR(enc, ptr, end)) return XML_TOK_TRAILING_CR; if (BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); *nextTokPtr = ptr; return XML_TOK_DATA_NEWLINE; } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; default: ptr += MINBPC(enc); break; } } *nextTokPtr = ptr; return XML_TOK_DATA_CHARS; } # ifdef XML_DTD static int PTRCALL PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, const char *end, const char **nextTokPtr) { int level = 0; if (MINBPC(enc) > 1) { size_t n = end - ptr; if (n & (MINBPC(enc) - 1)) { n &= ~(MINBPC(enc) - 1); end = ptr + n; } } while (HAS_CHAR(enc, ptr, end)) { switch (BYTE_TYPE(enc, ptr)) { INVALID_CASES(ptr, nextTokPtr) case BT_LT: ptr += MINBPC(enc); REQUIRE_CHAR(enc, ptr, end); if (CHAR_MATCHES(enc, ptr, ASCII_EXCL)) { ptr += MINBPC(enc); REQUIRE_CHAR(enc, ptr, end); if (CHAR_MATCHES(enc, ptr, ASCII_LSQB)) { ++level; ptr += MINBPC(enc); } } break; case BT_RSQB: ptr += MINBPC(enc); REQUIRE_CHAR(enc, ptr, end); if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) { ptr += MINBPC(enc); REQUIRE_CHAR(enc, ptr, end); if (CHAR_MATCHES(enc, ptr, ASCII_GT)) { ptr += MINBPC(enc); if (level == 0) { *nextTokPtr = ptr; return XML_TOK_IGNORE_SECT; } --level; } } break; default: ptr += MINBPC(enc); break; } } return XML_TOK_PARTIAL; } # endif /* XML_DTD */ static int PTRCALL PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end, const char **badPtr) { ptr += MINBPC(enc); end -= MINBPC(enc); for (; HAS_CHAR(enc, ptr, end); ptr += MINBPC(enc)) { switch (BYTE_TYPE(enc, ptr)) { case BT_DIGIT: case BT_HEX: case BT_MINUS: case BT_APOS: case BT_LPAR: case BT_RPAR: case BT_PLUS: case BT_COMMA: case BT_SOL: case BT_EQUALS: case BT_QUEST: case BT_CR: case BT_LF: case BT_SEMI: case BT_EXCL: case BT_AST: case BT_PERCNT: case BT_NUM: # ifdef XML_NS case BT_COLON: # endif break; case BT_S: if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) { *badPtr = ptr; return 0; } break; case BT_NAME: case BT_NMSTRT: if (! (BYTE_TO_ASCII(enc, ptr) & ~0x7f)) break; /* fall through */ default: switch (BYTE_TO_ASCII(enc, ptr)) { case 0x24: /* $ */ case 0x40: /* @ */ break; default: *badPtr = ptr; return 0; } break; } } return 1; } /* This must only be called for a well-formed start-tag or empty element tag. Returns the number of attributes. Pointers to the first attsMax attributes are stored in atts. */ static int PTRCALL PREFIX(getAtts)(const ENCODING *enc, const char *ptr, int attsMax, ATTRIBUTE *atts) { enum { other, inName, inValue } state = inName; int nAtts = 0; int open = 0; /* defined when state == inValue; initialization just to shut up compilers */ for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) { switch (BYTE_TYPE(enc, ptr)) { # define START_NAME \ if (state == other) { \ if (nAtts < attsMax) { \ atts[nAtts].name = ptr; \ atts[nAtts].normalized = 1; \ } \ state = inName; \ } # define LEAD_CASE(n) \ case BT_LEAD##n: /* NOTE: The encoding has already been validated. */ \ START_NAME ptr += (n - MINBPC(enc)); \ break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) # undef LEAD_CASE case BT_NONASCII: case BT_NMSTRT: case BT_HEX: START_NAME break; # undef START_NAME case BT_QUOT: if (state != inValue) { if (nAtts < attsMax) atts[nAtts].valuePtr = ptr + MINBPC(enc); state = inValue; open = BT_QUOT; } else if (open == BT_QUOT) { state = other; if (nAtts < attsMax) atts[nAtts].valueEnd = ptr; nAtts++; } break; case BT_APOS: if (state != inValue) { if (nAtts < attsMax) atts[nAtts].valuePtr = ptr + MINBPC(enc); state = inValue; open = BT_APOS; } else if (open == BT_APOS) { state = other; if (nAtts < attsMax) atts[nAtts].valueEnd = ptr; nAtts++; } break; case BT_AMP: if (nAtts < attsMax) atts[nAtts].normalized = 0; break; case BT_S: if (state == inName) state = other; else if (state == inValue && nAtts < attsMax && atts[nAtts].normalized && (ptr == atts[nAtts].valuePtr || BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open)) atts[nAtts].normalized = 0; break; case BT_CR: case BT_LF: /* This case ensures that the first attribute name is counted Apart from that we could just change state on the quote. */ if (state == inName) state = other; else if (state == inValue && nAtts < attsMax) atts[nAtts].normalized = 0; break; case BT_GT: case BT_SOL: if (state != inValue) return nAtts; break; default: break; } } /* not reached */ } static int PTRFASTCALL PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr) { int result = 0; /* skip &# */ UNUSED_P(enc); ptr += 2 * MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_x)) { for (ptr += MINBPC(enc); ! CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) { int c = BYTE_TO_ASCII(enc, ptr); switch (c) { case ASCII_0: case ASCII_1: case ASCII_2: case ASCII_3: case ASCII_4: case ASCII_5: case ASCII_6: case ASCII_7: case ASCII_8: case ASCII_9: result <<= 4; result |= (c - ASCII_0); break; case ASCII_A: case ASCII_B: case ASCII_C: case ASCII_D: case ASCII_E: case ASCII_F: result <<= 4; result += 10 + (c - ASCII_A); break; case ASCII_a: case ASCII_b: case ASCII_c: case ASCII_d: case ASCII_e: case ASCII_f: result <<= 4; result += 10 + (c - ASCII_a); break; } if (result >= 0x110000) return -1; } } else { for (; ! CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) { int c = BYTE_TO_ASCII(enc, ptr); result *= 10; result += (c - ASCII_0); if (result >= 0x110000) return -1; } } return checkCharRefNumber(result); } static int PTRCALL PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr, const char *end) { UNUSED_P(enc); switch ((end - ptr) / MINBPC(enc)) { case 2: if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) { switch (BYTE_TO_ASCII(enc, ptr)) { case ASCII_l: return ASCII_LT; case ASCII_g: return ASCII_GT; } } break; case 3: if (CHAR_MATCHES(enc, ptr, ASCII_a)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_m)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_p)) return ASCII_AMP; } } break; case 4: switch (BYTE_TO_ASCII(enc, ptr)) { case ASCII_q: ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_u)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_o)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_t)) return ASCII_QUOT; } } break; case ASCII_a: ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_p)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_o)) { ptr += MINBPC(enc); if (CHAR_MATCHES(enc, ptr, ASCII_s)) return ASCII_APOS; } } break; } } return 0; } static int PTRCALL PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1, const char *end1, const char *ptr2) { UNUSED_P(enc); for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) { if (end1 - ptr1 < MINBPC(enc)) { /* This line cannot be executed. The incoming data has already * been tokenized once, so incomplete characters like this have * already been eliminated from the input. Retaining the * paranoia check is still valuable, however. */ return 0; /* LCOV_EXCL_LINE */ } if (! CHAR_MATCHES(enc, ptr1, *ptr2)) return 0; } return ptr1 == end1; } static int PTRFASTCALL PREFIX(nameLength)(const ENCODING *enc, const char *ptr) { const char *start = ptr; for (;;) { switch (BYTE_TYPE(enc, ptr)) { # define LEAD_CASE(n) \ case BT_LEAD##n: \ ptr += n; /* NOTE: The encoding has already been validated. */ \ break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) # undef LEAD_CASE case BT_NONASCII: case BT_NMSTRT: # ifdef XML_NS case BT_COLON: # endif case BT_HEX: case BT_DIGIT: case BT_NAME: case BT_MINUS: ptr += MINBPC(enc); break; default: return (int)(ptr - start); } } } static const char *PTRFASTCALL PREFIX(skipS)(const ENCODING *enc, const char *ptr) { for (;;) { switch (BYTE_TYPE(enc, ptr)) { case BT_LF: case BT_CR: case BT_S: ptr += MINBPC(enc); break; default: return ptr; } } } static void PTRCALL PREFIX(updatePosition)(const ENCODING *enc, const char *ptr, const char *end, POSITION *pos) { while (HAS_CHAR(enc, ptr, end)) { switch (BYTE_TYPE(enc, ptr)) { # define LEAD_CASE(n) \ case BT_LEAD##n: \ ptr += n; /* NOTE: The encoding has already been validated. */ \ pos->columnNumber++; \ break; LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4) # undef LEAD_CASE case BT_LF: pos->columnNumber = 0; pos->lineNumber++; ptr += MINBPC(enc); break; case BT_CR: pos->lineNumber++; ptr += MINBPC(enc); if (HAS_CHAR(enc, ptr, end) && BYTE_TYPE(enc, ptr) == BT_LF) ptr += MINBPC(enc); pos->columnNumber = 0; break; default: ptr += MINBPC(enc); pos->columnNumber++; break; } } } # undef DO_LEAD_CASE # undef MULTIBYTE_CASES # undef INVALID_CASES # undef CHECK_NAME_CASE # undef CHECK_NAME_CASES # undef CHECK_NMSTRT_CASE # undef CHECK_NMSTRT_CASES #endif /* XML_TOK_IMPL_C */ tdom-0.9.5-src/expat/xmltok.c0000644000175000017500000015211214703531020014543 0ustar rolfrolf/* __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 1997-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2001-2003 Fred L. Drake, Jr. Copyright (c) 2002 Greg Stein Copyright (c) 2002-2016 Karl Waclawek Copyright (c) 2005-2009 Steven Solie Copyright (c) 2016-2024 Sebastian Pipping Copyright (c) 2016 Pascal Cuoq Copyright (c) 2016 Don Lewis Copyright (c) 2017 Rhodri James Copyright (c) 2017 Alexander Bluhm Copyright (c) 2017 Benbuck Nason Copyright (c) 2017 José Gutiérrez de la Concha Copyright (c) 2019 David Loffredo Copyright (c) 2021 Donghee Na Copyright (c) 2022 Martin Ettl Copyright (c) 2022 Sean McBride Copyright (c) 2023 Hanno Böck Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "expat_config.h" #include #include /* memcpy */ #include #ifdef _WIN32 # include "winconfig.h" #endif #include "expat_external.h" #include "internal.h" #include "xmltok.h" #include "nametab.h" #ifdef XML_DTD # define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok) #else # define IGNORE_SECTION_TOK_VTABLE /* as nothing */ #endif #define VTABLE1 \ {PREFIX(prologTok), PREFIX(contentTok), \ PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE}, \ {PREFIX(attributeValueTok), PREFIX(entityValueTok)}, \ PREFIX(nameMatchesAscii), PREFIX(nameLength), PREFIX(skipS), \ PREFIX(getAtts), PREFIX(charRefNumber), PREFIX(predefinedEntityName), \ PREFIX(updatePosition), PREFIX(isPublicId) #define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16) #define UCS2_GET_NAMING(pages, hi, lo) \ (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1u << ((lo) & 0x1F))) /* A 2 byte UTF-8 representation splits the characters 11 bits between the bottom 5 and 6 bits of the bytes. We need 8 bits to index into pages, 3 bits to add to that index and 5 bits to generate the mask. */ #define UTF8_GET_NAMING2(pages, byte) \ (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \ + ((((byte)[0]) & 3) << 1) + ((((byte)[1]) >> 5) & 1)] \ & (1u << (((byte)[1]) & 0x1F))) /* A 3 byte UTF-8 representation splits the characters 16 bits between the bottom 4, 6 and 6 bits of the bytes. We need 8 bits to index into pages, 3 bits to add to that index and 5 bits to generate the mask. */ #define UTF8_GET_NAMING3(pages, byte) \ (namingBitmap \ [((pages)[((((byte)[0]) & 0xF) << 4) + ((((byte)[1]) >> 2) & 0xF)] \ << 3) \ + ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)] \ & (1u << (((byte)[2]) & 0x1F))) /* Detection of invalid UTF-8 sequences is based on Table 3.1B of Unicode 3.2: https://www.unicode.org/unicode/reports/tr28/ with the additional restriction of not allowing the Unicode code points 0xFFFF and 0xFFFE (sequences EF,BF,BF and EF,BF,BE). Implementation details: (A & 0x80) == 0 means A < 0x80 and (A & 0xC0) == 0xC0 means A > 0xBF */ #define UTF8_INVALID2(p) \ ((*p) < 0xC2 || ((p)[1] & 0x80) == 0 || ((p)[1] & 0xC0) == 0xC0) #define UTF8_INVALID3(p) \ (((p)[2] & 0x80) == 0 \ || ((*p) == 0xEF && (p)[1] == 0xBF ? (p)[2] > 0xBD \ : ((p)[2] & 0xC0) == 0xC0) \ || ((*p) == 0xE0 \ ? (p)[1] < 0xA0 || ((p)[1] & 0xC0) == 0xC0 \ : ((p)[1] & 0x80) == 0 \ || ((*p) == 0xED ? (p)[1] > 0x9F : ((p)[1] & 0xC0) == 0xC0))) #define UTF8_INVALID4(p) \ (((p)[3] & 0x80) == 0 || ((p)[3] & 0xC0) == 0xC0 || ((p)[2] & 0x80) == 0 \ || ((p)[2] & 0xC0) == 0xC0 \ || ((*p) == 0xF0 \ ? (p)[1] < 0x90 || ((p)[1] & 0xC0) == 0xC0 \ : ((p)[1] & 0x80) == 0 \ || ((*p) == 0xF4 ? (p)[1] > 0x8F : ((p)[1] & 0xC0) == 0xC0))) static int PTRFASTCALL isNever(const ENCODING *enc, const char *p) { UNUSED_P(enc); UNUSED_P(p); return 0; } static int PTRFASTCALL utf8_isName2(const ENCODING *enc, const char *p) { UNUSED_P(enc); return UTF8_GET_NAMING2(namePages, (const unsigned char *)p); } static int PTRFASTCALL utf8_isName3(const ENCODING *enc, const char *p) { UNUSED_P(enc); return UTF8_GET_NAMING3(namePages, (const unsigned char *)p); } #define utf8_isName4 isNever static int PTRFASTCALL utf8_isNmstrt2(const ENCODING *enc, const char *p) { UNUSED_P(enc); return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p); } static int PTRFASTCALL utf8_isNmstrt3(const ENCODING *enc, const char *p) { UNUSED_P(enc); return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p); } #define utf8_isNmstrt4 isNever static int PTRFASTCALL utf8_isInvalid2(const ENCODING *enc, const char *p) { UNUSED_P(enc); return UTF8_INVALID2((const unsigned char *)p); } static int PTRFASTCALL utf8_isInvalid3(const ENCODING *enc, const char *p) { UNUSED_P(enc); return UTF8_INVALID3((const unsigned char *)p); } static int PTRFASTCALL utf8_isInvalid4(const ENCODING *enc, const char *p) { UNUSED_P(enc); return UTF8_INVALID4((const unsigned char *)p); } struct normal_encoding { ENCODING enc; unsigned char type[256]; #ifdef XML_MIN_SIZE int(PTRFASTCALL *byteType)(const ENCODING *, const char *); int(PTRFASTCALL *isNameMin)(const ENCODING *, const char *); int(PTRFASTCALL *isNmstrtMin)(const ENCODING *, const char *); int(PTRFASTCALL *byteToAscii)(const ENCODING *, const char *); int(PTRCALL *charMatches)(const ENCODING *, const char *, int); #endif /* XML_MIN_SIZE */ int(PTRFASTCALL *isName2)(const ENCODING *, const char *); int(PTRFASTCALL *isName3)(const ENCODING *, const char *); int(PTRFASTCALL *isName4)(const ENCODING *, const char *); int(PTRFASTCALL *isNmstrt2)(const ENCODING *, const char *); int(PTRFASTCALL *isNmstrt3)(const ENCODING *, const char *); int(PTRFASTCALL *isNmstrt4)(const ENCODING *, const char *); int(PTRFASTCALL *isInvalid2)(const ENCODING *, const char *); int(PTRFASTCALL *isInvalid3)(const ENCODING *, const char *); int(PTRFASTCALL *isInvalid4)(const ENCODING *, const char *); }; #define AS_NORMAL_ENCODING(enc) ((const struct normal_encoding *)(enc)) #ifdef XML_MIN_SIZE # define STANDARD_VTABLE(E) \ E##byteType, E##isNameMin, E##isNmstrtMin, E##byteToAscii, E##charMatches, #else # define STANDARD_VTABLE(E) /* as nothing */ #endif #define NORMAL_VTABLE(E) \ E##isName2, E##isName3, E##isName4, E##isNmstrt2, E##isNmstrt3, \ E##isNmstrt4, E##isInvalid2, E##isInvalid3, E##isInvalid4 #define NULL_VTABLE \ /* isName2 */ NULL, /* isName3 */ NULL, /* isName4 */ NULL, \ /* isNmstrt2 */ NULL, /* isNmstrt3 */ NULL, /* isNmstrt4 */ NULL, \ /* isInvalid2 */ NULL, /* isInvalid3 */ NULL, /* isInvalid4 */ NULL static int FASTCALL checkCharRefNumber(int result); #include "xmltok_impl.h" #include "ascii.h" #ifdef XML_MIN_SIZE # define sb_isNameMin isNever # define sb_isNmstrtMin isNever #endif #ifdef XML_MIN_SIZE # define MINBPC(enc) ((enc)->minBytesPerChar) #else /* minimum bytes per character */ # define MINBPC(enc) 1 #endif #define SB_BYTE_TYPE(enc, p) \ (((const struct normal_encoding *)(enc))->type[(unsigned char)*(p)]) #ifdef XML_MIN_SIZE static int PTRFASTCALL sb_byteType(const ENCODING *enc, const char *p) { return SB_BYTE_TYPE(enc, p); } # define BYTE_TYPE(enc, p) (AS_NORMAL_ENCODING(enc)->byteType(enc, p)) #else # define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p) #endif #ifdef XML_MIN_SIZE # define BYTE_TO_ASCII(enc, p) (AS_NORMAL_ENCODING(enc)->byteToAscii(enc, p)) static int PTRFASTCALL sb_byteToAscii(const ENCODING *enc, const char *p) { UNUSED_P(enc); return *p; } #else # define BYTE_TO_ASCII(enc, p) (*(p)) #endif #define IS_NAME_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isName##n(enc, p)) #define IS_NMSTRT_CHAR(enc, p, n) (AS_NORMAL_ENCODING(enc)->isNmstrt##n(enc, p)) #ifdef XML_MIN_SIZE # define IS_INVALID_CHAR(enc, p, n) \ (AS_NORMAL_ENCODING(enc)->isInvalid##n \ && AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p)) #else # define IS_INVALID_CHAR(enc, p, n) \ (AS_NORMAL_ENCODING(enc)->isInvalid##n(enc, p)) #endif #ifdef XML_MIN_SIZE # define IS_NAME_CHAR_MINBPC(enc, p) \ (AS_NORMAL_ENCODING(enc)->isNameMin(enc, p)) # define IS_NMSTRT_CHAR_MINBPC(enc, p) \ (AS_NORMAL_ENCODING(enc)->isNmstrtMin(enc, p)) #else # define IS_NAME_CHAR_MINBPC(enc, p) (0) # define IS_NMSTRT_CHAR_MINBPC(enc, p) (0) #endif #ifdef XML_MIN_SIZE # define CHAR_MATCHES(enc, p, c) \ (AS_NORMAL_ENCODING(enc)->charMatches(enc, p, c)) static int PTRCALL sb_charMatches(const ENCODING *enc, const char *p, int c) { UNUSED_P(enc); return *p == c; } #else /* c is an ASCII character */ # define CHAR_MATCHES(enc, p, c) (*(p) == (c)) #endif #define PREFIX(ident) normal_##ident #define XML_TOK_IMPL_C #include "xmltok_impl.c" #undef XML_TOK_IMPL_C #undef MINBPC #undef BYTE_TYPE #undef BYTE_TO_ASCII #undef CHAR_MATCHES #undef IS_NAME_CHAR #undef IS_NAME_CHAR_MINBPC #undef IS_NMSTRT_CHAR #undef IS_NMSTRT_CHAR_MINBPC #undef IS_INVALID_CHAR enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */ UTF8_cval1 = 0x00, UTF8_cval2 = 0xc0, UTF8_cval3 = 0xe0, UTF8_cval4 = 0xf0 }; void _INTERNAL_trim_to_complete_utf8_characters(const char *from, const char **fromLimRef) { const char *fromLim = *fromLimRef; size_t walked = 0; for (; fromLim > from; fromLim--, walked++) { const unsigned char prev = (unsigned char)fromLim[-1]; if ((prev & 0xf8u) == 0xf0u) { /* 4-byte character, lead by 0b11110xxx byte */ if (walked + 1 >= 4) { fromLim += 4 - 1; break; } else { walked = 0; } } else if ((prev & 0xf0u) == 0xe0u) { /* 3-byte character, lead by 0b1110xxxx byte */ if (walked + 1 >= 3) { fromLim += 3 - 1; break; } else { walked = 0; } } else if ((prev & 0xe0u) == 0xc0u) { /* 2-byte character, lead by 0b110xxxxx byte */ if (walked + 1 >= 2) { fromLim += 2 - 1; break; } else { walked = 0; } } else if ((prev & 0x80u) == 0x00u) { /* 1-byte character, matching 0b0xxxxxxx */ break; } } *fromLimRef = fromLim; } static enum XML_Convert_Result PTRCALL utf8_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { bool input_incomplete = false; bool output_exhausted = false; /* Avoid copying partial characters (due to limited space). */ const ptrdiff_t bytesAvailable = fromLim - *fromP; const ptrdiff_t bytesStorable = toLim - *toP; UNUSED_P(enc); if (bytesAvailable > bytesStorable) { fromLim = *fromP + bytesStorable; output_exhausted = true; } /* Avoid copying partial characters (from incomplete input). */ { const char *const fromLimBefore = fromLim; _INTERNAL_trim_to_complete_utf8_characters(*fromP, &fromLim); if (fromLim < fromLimBefore) { input_incomplete = true; } } { const ptrdiff_t bytesToCopy = fromLim - *fromP; memcpy(*toP, *fromP, bytesToCopy); *fromP += bytesToCopy; *toP += bytesToCopy; } if (output_exhausted) /* needs to go first */ return XML_CONVERT_OUTPUT_EXHAUSTED; else if (input_incomplete) return XML_CONVERT_INPUT_INCOMPLETE; else return XML_CONVERT_COMPLETED; } static enum XML_Convert_Result PTRCALL utf8_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim, unsigned short **toP, const unsigned short *toLim) { enum XML_Convert_Result res = XML_CONVERT_COMPLETED; unsigned short *to = *toP; const char *from = *fromP; while (from < fromLim && to < toLim) { switch (SB_BYTE_TYPE(enc, from)) { case BT_LEAD2: if (fromLim - from < 2) { res = XML_CONVERT_INPUT_INCOMPLETE; goto after; } *to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f)); from += 2; break; case BT_LEAD3: if (fromLim - from < 3) { res = XML_CONVERT_INPUT_INCOMPLETE; goto after; } *to++ = (unsigned short)(((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f)); from += 3; break; case BT_LEAD4: { unsigned long n; if (toLim - to < 2) { res = XML_CONVERT_OUTPUT_EXHAUSTED; goto after; } if (fromLim - from < 4) { res = XML_CONVERT_INPUT_INCOMPLETE; goto after; } n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f); n -= 0x10000; to[0] = (unsigned short)((n >> 10) | 0xD800); to[1] = (unsigned short)((n & 0x3FF) | 0xDC00); to += 2; from += 4; } break; default: *to++ = *from++; break; } } if (from < fromLim) res = XML_CONVERT_OUTPUT_EXHAUSTED; after: *fromP = from; *toP = to; return res; } #ifdef XML_NS static const struct normal_encoding utf8_encoding_ns = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0}, { # include "asciitab.h" # include "utf8tab.h" }, STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)}; #endif static const struct normal_encoding utf8_encoding = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0}, { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "utf8tab.h" }, STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)}; #ifdef XML_NS static const struct normal_encoding internal_utf8_encoding_ns = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0}, { # include "iasciitab.h" # include "utf8tab.h" }, STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)}; #endif static const struct normal_encoding internal_utf8_encoding = {{VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0}, { #define BT_COLON BT_NMSTRT #include "iasciitab.h" #undef BT_COLON #include "utf8tab.h" }, STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)}; static enum XML_Convert_Result PTRCALL latin1_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { UNUSED_P(enc); for (;;) { unsigned char c; if (*fromP == fromLim) return XML_CONVERT_COMPLETED; c = (unsigned char)**fromP; if (c & 0x80) { if (toLim - *toP < 2) return XML_CONVERT_OUTPUT_EXHAUSTED; *(*toP)++ = (char)((c >> 6) | UTF8_cval2); *(*toP)++ = (char)((c & 0x3f) | 0x80); (*fromP)++; } else { if (*toP == toLim) return XML_CONVERT_OUTPUT_EXHAUSTED; *(*toP)++ = *(*fromP)++; } } } static enum XML_Convert_Result PTRCALL latin1_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim, unsigned short **toP, const unsigned short *toLim) { UNUSED_P(enc); while (*fromP < fromLim && *toP < toLim) *(*toP)++ = (unsigned char)*(*fromP)++; if ((*toP == toLim) && (*fromP < fromLim)) return XML_CONVERT_OUTPUT_EXHAUSTED; else return XML_CONVERT_COMPLETED; } #ifdef XML_NS static const struct normal_encoding latin1_encoding_ns = {{VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0}, { # include "asciitab.h" # include "latin1tab.h" }, STANDARD_VTABLE(sb_) NULL_VTABLE}; #endif static const struct normal_encoding latin1_encoding = {{VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0}, { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "latin1tab.h" }, STANDARD_VTABLE(sb_) NULL_VTABLE}; static enum XML_Convert_Result PTRCALL ascii_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { UNUSED_P(enc); while (*fromP < fromLim && *toP < toLim) *(*toP)++ = *(*fromP)++; if ((*toP == toLim) && (*fromP < fromLim)) return XML_CONVERT_OUTPUT_EXHAUSTED; else return XML_CONVERT_COMPLETED; } #ifdef XML_NS static const struct normal_encoding ascii_encoding_ns = {{VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0}, { # include "asciitab.h" /* BT_NONXML == 0 */ }, STANDARD_VTABLE(sb_) NULL_VTABLE}; #endif static const struct normal_encoding ascii_encoding = {{VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0}, { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON /* BT_NONXML == 0 */ }, STANDARD_VTABLE(sb_) NULL_VTABLE}; static int PTRFASTCALL unicode_byte_type(char hi, char lo) { switch ((unsigned char)hi) { /* 0xD800-0xDBFF first 16-bit code unit or high surrogate (W1) */ case 0xD8: case 0xD9: case 0xDA: case 0xDB: return BT_LEAD4; /* 0xDC00-0xDFFF second 16-bit code unit or low surrogate (W2) */ case 0xDC: case 0xDD: case 0xDE: case 0xDF: return BT_TRAIL; case 0xFF: switch ((unsigned char)lo) { case 0xFF: /* noncharacter-FFFF */ case 0xFE: /* noncharacter-FFFE */ return BT_NONXML; } break; } return BT_NONASCII; } #define DEFINE_UTF16_TO_UTF8(E) \ static enum XML_Convert_Result PTRCALL E##toUtf8( \ const ENCODING *enc, const char **fromP, const char *fromLim, \ char **toP, const char *toLim) { \ const char *from = *fromP; \ UNUSED_P(enc); \ fromLim = from + (((fromLim - from) >> 1) << 1); /* shrink to even */ \ for (; from < fromLim; from += 2) { \ int plane; \ unsigned char lo2; \ unsigned char lo = GET_LO(from); \ unsigned char hi = GET_HI(from); \ switch (hi) { \ case 0: \ if (lo < 0x80) { \ if (*toP == toLim) { \ *fromP = from; \ return XML_CONVERT_OUTPUT_EXHAUSTED; \ } \ *(*toP)++ = lo; \ break; \ } \ /* fall through */ \ case 0x1: \ case 0x2: \ case 0x3: \ case 0x4: \ case 0x5: \ case 0x6: \ case 0x7: \ if (toLim - *toP < 2) { \ *fromP = from; \ return XML_CONVERT_OUTPUT_EXHAUSTED; \ } \ *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \ *(*toP)++ = ((lo & 0x3f) | 0x80); \ break; \ default: \ if (toLim - *toP < 3) { \ *fromP = from; \ return XML_CONVERT_OUTPUT_EXHAUSTED; \ } \ /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \ *(*toP)++ = ((hi >> 4) | UTF8_cval3); \ *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \ *(*toP)++ = ((lo & 0x3f) | 0x80); \ break; \ case 0xD8: \ case 0xD9: \ case 0xDA: \ case 0xDB: \ if (toLim - *toP < 4) { \ *fromP = from; \ return XML_CONVERT_OUTPUT_EXHAUSTED; \ } \ if (fromLim - from < 4) { \ *fromP = from; \ return XML_CONVERT_INPUT_INCOMPLETE; \ } \ plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \ *(*toP)++ = (char)((plane >> 2) | UTF8_cval4); \ *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \ from += 2; \ lo2 = GET_LO(from); \ *(*toP)++ = (((lo & 0x3) << 4) | ((GET_HI(from) & 0x3) << 2) \ | (lo2 >> 6) | 0x80); \ *(*toP)++ = ((lo2 & 0x3f) | 0x80); \ break; \ } \ } \ *fromP = from; \ if (from < fromLim) \ return XML_CONVERT_INPUT_INCOMPLETE; \ else \ return XML_CONVERT_COMPLETED; \ } #define DEFINE_UTF16_TO_UTF16(E) \ static enum XML_Convert_Result PTRCALL E##toUtf16( \ const ENCODING *enc, const char **fromP, const char *fromLim, \ unsigned short **toP, const unsigned short *toLim) { \ enum XML_Convert_Result res = XML_CONVERT_COMPLETED; \ UNUSED_P(enc); \ fromLim = *fromP + (((fromLim - *fromP) >> 1) << 1); /* shrink to even */ \ /* Avoid copying first half only of surrogate */ \ if (fromLim - *fromP > ((toLim - *toP) << 1) \ && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) { \ fromLim -= 2; \ res = XML_CONVERT_INPUT_INCOMPLETE; \ } \ for (; *fromP < fromLim && *toP < toLim; *fromP += 2) \ *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \ if ((*toP == toLim) && (*fromP < fromLim)) \ return XML_CONVERT_OUTPUT_EXHAUSTED; \ else \ return res; \ } #define GET_LO(ptr) ((unsigned char)(ptr)[0]) #define GET_HI(ptr) ((unsigned char)(ptr)[1]) DEFINE_UTF16_TO_UTF8(little2_) DEFINE_UTF16_TO_UTF16(little2_) #undef GET_LO #undef GET_HI #define GET_LO(ptr) ((unsigned char)(ptr)[1]) #define GET_HI(ptr) ((unsigned char)(ptr)[0]) DEFINE_UTF16_TO_UTF8(big2_) DEFINE_UTF16_TO_UTF16(big2_) #undef GET_LO #undef GET_HI #define LITTLE2_BYTE_TYPE(enc, p) \ ((p)[1] == 0 ? SB_BYTE_TYPE(enc, p) : unicode_byte_type((p)[1], (p)[0])) #define LITTLE2_BYTE_TO_ASCII(p) ((p)[1] == 0 ? (p)[0] : -1) #define LITTLE2_CHAR_MATCHES(p, c) ((p)[1] == 0 && (p)[0] == (c)) #define LITTLE2_IS_NAME_CHAR_MINBPC(p) \ UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0]) #define LITTLE2_IS_NMSTRT_CHAR_MINBPC(p) \ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0]) #ifdef XML_MIN_SIZE static int PTRFASTCALL little2_byteType(const ENCODING *enc, const char *p) { return LITTLE2_BYTE_TYPE(enc, p); } static int PTRFASTCALL little2_byteToAscii(const ENCODING *enc, const char *p) { UNUSED_P(enc); return LITTLE2_BYTE_TO_ASCII(p); } static int PTRCALL little2_charMatches(const ENCODING *enc, const char *p, int c) { UNUSED_P(enc); return LITTLE2_CHAR_MATCHES(p, c); } static int PTRFASTCALL little2_isNameMin(const ENCODING *enc, const char *p) { UNUSED_P(enc); return LITTLE2_IS_NAME_CHAR_MINBPC(p); } static int PTRFASTCALL little2_isNmstrtMin(const ENCODING *enc, const char *p) { UNUSED_P(enc); return LITTLE2_IS_NMSTRT_CHAR_MINBPC(p); } # undef VTABLE # define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16 #else /* not XML_MIN_SIZE */ # undef PREFIX # define PREFIX(ident) little2_##ident # define MINBPC(enc) 2 /* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ # define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p) # define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(p) # define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(p, c) # define IS_NAME_CHAR(enc, p, n) 0 # define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(p) # define IS_NMSTRT_CHAR(enc, p, n) (0) # define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(p) # define XML_TOK_IMPL_C # include "xmltok_impl.c" # undef XML_TOK_IMPL_C # undef MINBPC # undef BYTE_TYPE # undef BYTE_TO_ASCII # undef CHAR_MATCHES # undef IS_NAME_CHAR # undef IS_NAME_CHAR_MINBPC # undef IS_NMSTRT_CHAR # undef IS_NMSTRT_CHAR_MINBPC # undef IS_INVALID_CHAR #endif /* not XML_MIN_SIZE */ #ifdef XML_NS static const struct normal_encoding little2_encoding_ns = {{VTABLE, 2, 0, # if BYTEORDER == 1234 1 # else 0 # endif }, { # include "asciitab.h" # include "latin1tab.h" }, STANDARD_VTABLE(little2_) NULL_VTABLE}; #endif static const struct normal_encoding little2_encoding = {{VTABLE, 2, 0, #if BYTEORDER == 1234 1 #else 0 #endif }, { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "latin1tab.h" }, STANDARD_VTABLE(little2_) NULL_VTABLE}; #if BYTEORDER != 4321 # ifdef XML_NS static const struct normal_encoding internal_little2_encoding_ns = {{VTABLE, 2, 0, 1}, { # include "iasciitab.h" # include "latin1tab.h" }, STANDARD_VTABLE(little2_) NULL_VTABLE}; # endif static const struct normal_encoding internal_little2_encoding = {{VTABLE, 2, 0, 1}, { # define BT_COLON BT_NMSTRT # include "iasciitab.h" # undef BT_COLON # include "latin1tab.h" }, STANDARD_VTABLE(little2_) NULL_VTABLE}; #endif #define BIG2_BYTE_TYPE(enc, p) \ ((p)[0] == 0 ? SB_BYTE_TYPE(enc, p + 1) : unicode_byte_type((p)[0], (p)[1])) #define BIG2_BYTE_TO_ASCII(p) ((p)[0] == 0 ? (p)[1] : -1) #define BIG2_CHAR_MATCHES(p, c) ((p)[0] == 0 && (p)[1] == (c)) #define BIG2_IS_NAME_CHAR_MINBPC(p) \ UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1]) #define BIG2_IS_NMSTRT_CHAR_MINBPC(p) \ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1]) #ifdef XML_MIN_SIZE static int PTRFASTCALL big2_byteType(const ENCODING *enc, const char *p) { return BIG2_BYTE_TYPE(enc, p); } static int PTRFASTCALL big2_byteToAscii(const ENCODING *enc, const char *p) { UNUSED_P(enc); return BIG2_BYTE_TO_ASCII(p); } static int PTRCALL big2_charMatches(const ENCODING *enc, const char *p, int c) { UNUSED_P(enc); return BIG2_CHAR_MATCHES(p, c); } static int PTRFASTCALL big2_isNameMin(const ENCODING *enc, const char *p) { UNUSED_P(enc); return BIG2_IS_NAME_CHAR_MINBPC(p); } static int PTRFASTCALL big2_isNmstrtMin(const ENCODING *enc, const char *p) { UNUSED_P(enc); return BIG2_IS_NMSTRT_CHAR_MINBPC(p); } # undef VTABLE # define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16 #else /* not XML_MIN_SIZE */ # undef PREFIX # define PREFIX(ident) big2_##ident # define MINBPC(enc) 2 /* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */ # define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p) # define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(p) # define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(p, c) # define IS_NAME_CHAR(enc, p, n) 0 # define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(p) # define IS_NMSTRT_CHAR(enc, p, n) (0) # define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(p) # define XML_TOK_IMPL_C # include "xmltok_impl.c" # undef XML_TOK_IMPL_C # undef MINBPC # undef BYTE_TYPE # undef BYTE_TO_ASCII # undef CHAR_MATCHES # undef IS_NAME_CHAR # undef IS_NAME_CHAR_MINBPC # undef IS_NMSTRT_CHAR # undef IS_NMSTRT_CHAR_MINBPC # undef IS_INVALID_CHAR #endif /* not XML_MIN_SIZE */ #ifdef XML_NS static const struct normal_encoding big2_encoding_ns = {{VTABLE, 2, 0, # if BYTEORDER == 4321 1 # else 0 # endif }, { # include "asciitab.h" # include "latin1tab.h" }, STANDARD_VTABLE(big2_) NULL_VTABLE}; #endif static const struct normal_encoding big2_encoding = {{VTABLE, 2, 0, #if BYTEORDER == 4321 1 #else 0 #endif }, { #define BT_COLON BT_NMSTRT #include "asciitab.h" #undef BT_COLON #include "latin1tab.h" }, STANDARD_VTABLE(big2_) NULL_VTABLE}; #if BYTEORDER != 1234 # ifdef XML_NS static const struct normal_encoding internal_big2_encoding_ns = {{VTABLE, 2, 0, 1}, { # include "iasciitab.h" # include "latin1tab.h" }, STANDARD_VTABLE(big2_) NULL_VTABLE}; # endif static const struct normal_encoding internal_big2_encoding = {{VTABLE, 2, 0, 1}, { # define BT_COLON BT_NMSTRT # include "iasciitab.h" # undef BT_COLON # include "latin1tab.h" }, STANDARD_VTABLE(big2_) NULL_VTABLE}; #endif #undef PREFIX static int FASTCALL streqci(const char *s1, const char *s2) { for (;;) { char c1 = *s1++; char c2 = *s2++; if (ASCII_a <= c1 && c1 <= ASCII_z) c1 += ASCII_A - ASCII_a; if (ASCII_a <= c2 && c2 <= ASCII_z) /* The following line will never get executed. streqci() is * only called from two places, both of which guarantee to put * upper-case strings into s2. */ c2 += ASCII_A - ASCII_a; /* LCOV_EXCL_LINE */ if (c1 != c2) return 0; if (! c1) break; } return 1; } static void PTRCALL initUpdatePosition(const ENCODING *enc, const char *ptr, const char *end, POSITION *pos) { UNUSED_P(enc); normal_updatePosition(&utf8_encoding.enc, ptr, end, pos); } static int toAscii(const ENCODING *enc, const char *ptr, const char *end) { char buf[1]; char *p = buf; XmlUtf8Convert(enc, &ptr, end, &p, p + 1); if (p == buf) return -1; else return buf[0]; } static int FASTCALL isSpace(int c) { switch (c) { case 0x20: case 0xD: case 0xA: case 0x9: return 1; } return 0; } /* Return 1 if there's just optional white space or there's an S followed by name=val. */ static int parsePseudoAttribute(const ENCODING *enc, const char *ptr, const char *end, const char **namePtr, const char **nameEndPtr, const char **valPtr, const char **nextTokPtr) { int c; char open; if (ptr == end) { *namePtr = NULL; return 1; } if (! isSpace(toAscii(enc, ptr, end))) { *nextTokPtr = ptr; return 0; } do { ptr += enc->minBytesPerChar; } while (isSpace(toAscii(enc, ptr, end))); if (ptr == end) { *namePtr = NULL; return 1; } *namePtr = ptr; for (;;) { c = toAscii(enc, ptr, end); if (c == -1) { *nextTokPtr = ptr; return 0; } if (c == ASCII_EQUALS) { *nameEndPtr = ptr; break; } if (isSpace(c)) { *nameEndPtr = ptr; do { ptr += enc->minBytesPerChar; } while (isSpace(c = toAscii(enc, ptr, end))); if (c != ASCII_EQUALS) { *nextTokPtr = ptr; return 0; } break; } ptr += enc->minBytesPerChar; } if (ptr == *namePtr) { *nextTokPtr = ptr; return 0; } ptr += enc->minBytesPerChar; c = toAscii(enc, ptr, end); while (isSpace(c)) { ptr += enc->minBytesPerChar; c = toAscii(enc, ptr, end); } if (c != ASCII_QUOT && c != ASCII_APOS) { *nextTokPtr = ptr; return 0; } open = (char)c; ptr += enc->minBytesPerChar; *valPtr = ptr; for (;; ptr += enc->minBytesPerChar) { c = toAscii(enc, ptr, end); if (c == open) break; if (! (ASCII_a <= c && c <= ASCII_z) && ! (ASCII_A <= c && c <= ASCII_Z) && ! (ASCII_0 <= c && c <= ASCII_9) && c != ASCII_PERIOD && c != ASCII_MINUS && c != ASCII_UNDERSCORE) { *nextTokPtr = ptr; return 0; } } *nextTokPtr = ptr + enc->minBytesPerChar; return 1; } static const char KW_version[] = {ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0'}; static const char KW_encoding[] = {ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d, ASCII_i, ASCII_n, ASCII_g, '\0'}; static const char KW_standalone[] = {ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a, ASCII_l, ASCII_o, ASCII_n, ASCII_e, '\0'}; static const char KW_yes[] = {ASCII_y, ASCII_e, ASCII_s, '\0'}; static const char KW_no[] = {ASCII_n, ASCII_o, '\0'}; static int doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *, const char *, const char *), int isGeneralTextEntity, const ENCODING *enc, const char *ptr, const char *end, const char **badPtr, const char **versionPtr, const char **versionEndPtr, const char **encodingName, const ENCODING **encoding, int *standalone) { const char *val = NULL; const char *name = NULL; const char *nameEnd = NULL; ptr += 5 * enc->minBytesPerChar; end -= 2 * enc->minBytesPerChar; if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr) || ! name) { *badPtr = ptr; return 0; } if (! XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) { if (! isGeneralTextEntity) { *badPtr = name; return 0; } } else { if (versionPtr) *versionPtr = val; if (versionEndPtr) *versionEndPtr = ptr; if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) { *badPtr = ptr; return 0; } if (! name) { if (isGeneralTextEntity) { /* a TextDecl must have an EncodingDecl */ *badPtr = ptr; return 0; } return 1; } } if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) { int c = toAscii(enc, val, end); if (! (ASCII_a <= c && c <= ASCII_z) && ! (ASCII_A <= c && c <= ASCII_Z)) { *badPtr = val; return 0; } if (encodingName) *encodingName = val; if (encoding) *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar); if (! parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) { *badPtr = ptr; return 0; } if (! name) return 1; } if (! XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone) || isGeneralTextEntity) { *badPtr = name; return 0; } if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) { if (standalone) *standalone = 1; } else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) { if (standalone) *standalone = 0; } else { *badPtr = val; return 0; } while (isSpace(toAscii(enc, ptr, end))) ptr += enc->minBytesPerChar; if (ptr != end) { *badPtr = ptr; return 0; } return 1; } static int FASTCALL checkCharRefNumber(int result) { switch (result >> 8) { case 0xD8: case 0xD9: case 0xDA: case 0xDB: case 0xDC: case 0xDD: case 0xDE: case 0xDF: return -1; case 0: if (latin1_encoding.type[result] == BT_NONXML) return -1; break; case 0xFF: if (result == 0xFFFE || result == 0xFFFF) return -1; break; } return result; } int FASTCALL XmlUtf8Encode(int c, char *buf) { enum { /* minN is minimum legal resulting value for N byte sequence */ min2 = 0x80, min3 = 0x800, min4 = 0x10000 }; if (c < 0) return 0; /* LCOV_EXCL_LINE: this case is always eliminated beforehand */ if (c < min2) { buf[0] = (char)(c | UTF8_cval1); return 1; } if (c < min3) { buf[0] = (char)((c >> 6) | UTF8_cval2); buf[1] = (char)((c & 0x3f) | 0x80); return 2; } if (c < min4) { buf[0] = (char)((c >> 12) | UTF8_cval3); buf[1] = (char)(((c >> 6) & 0x3f) | 0x80); buf[2] = (char)((c & 0x3f) | 0x80); return 3; } if (c < 0x110000) { buf[0] = (char)((c >> 18) | UTF8_cval4); buf[1] = (char)(((c >> 12) & 0x3f) | 0x80); buf[2] = (char)(((c >> 6) & 0x3f) | 0x80); buf[3] = (char)((c & 0x3f) | 0x80); return 4; } return 0; /* LCOV_EXCL_LINE: this case too is eliminated before calling */ } int FASTCALL XmlUtf16Encode(int charNum, unsigned short *buf) { if (charNum < 0) return 0; if (charNum < 0x10000) { buf[0] = (unsigned short)charNum; return 1; } if (charNum < 0x110000) { charNum -= 0x10000; buf[0] = (unsigned short)((charNum >> 10) + 0xD800); buf[1] = (unsigned short)((charNum & 0x3FF) + 0xDC00); return 2; } return 0; } struct unknown_encoding { struct normal_encoding normal; CONVERTER convert; void *userData; unsigned short utf16[256]; char utf8[256][4]; }; #define AS_UNKNOWN_ENCODING(enc) ((const struct unknown_encoding *)(enc)) int XmlSizeOfUnknownEncoding(void) { return sizeof(struct unknown_encoding); } static int PTRFASTCALL unknown_isName(const ENCODING *enc, const char *p) { const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); int c = uenc->convert(uenc->userData, p); if (c & ~0xFFFF) return 0; return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF); } static int PTRFASTCALL unknown_isNmstrt(const ENCODING *enc, const char *p) { const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); int c = uenc->convert(uenc->userData, p); if (c & ~0xFFFF) return 0; return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF); } static int PTRFASTCALL unknown_isInvalid(const ENCODING *enc, const char *p) { const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); int c = uenc->convert(uenc->userData, p); return (c & ~0xFFFF) || checkCharRefNumber(c) < 0; } static enum XML_Convert_Result PTRCALL unknown_toUtf8(const ENCODING *enc, const char **fromP, const char *fromLim, char **toP, const char *toLim) { const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); char buf[XML_UTF8_ENCODE_MAX]; for (;;) { const char *utf8; int n; if (*fromP == fromLim) return XML_CONVERT_COMPLETED; utf8 = uenc->utf8[(unsigned char)**fromP]; n = *utf8++; if (n == 0) { int c = uenc->convert(uenc->userData, *fromP); n = XmlUtf8Encode(c, buf); if (n > toLim - *toP) return XML_CONVERT_OUTPUT_EXHAUSTED; utf8 = buf; *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP] - (BT_LEAD2 - 2)); } else { if (n > toLim - *toP) return XML_CONVERT_OUTPUT_EXHAUSTED; (*fromP)++; } memcpy(*toP, utf8, n); *toP += n; } } static enum XML_Convert_Result PTRCALL unknown_toUtf16(const ENCODING *enc, const char **fromP, const char *fromLim, unsigned short **toP, const unsigned short *toLim) { const struct unknown_encoding *uenc = AS_UNKNOWN_ENCODING(enc); while (*fromP < fromLim && *toP < toLim) { unsigned short c = uenc->utf16[(unsigned char)**fromP]; if (c == 0) { c = (unsigned short)uenc->convert(uenc->userData, *fromP); *fromP += (AS_NORMAL_ENCODING(enc)->type[(unsigned char)**fromP] - (BT_LEAD2 - 2)); } else (*fromP)++; *(*toP)++ = c; } if ((*toP == toLim) && (*fromP < fromLim)) return XML_CONVERT_OUTPUT_EXHAUSTED; else return XML_CONVERT_COMPLETED; } ENCODING * XmlInitUnknownEncoding(void *mem, int *table, CONVERTER convert, void *userData) { int i; struct unknown_encoding *e = (struct unknown_encoding *)mem; memcpy(mem, &latin1_encoding, sizeof(struct normal_encoding)); for (i = 0; i < 128; i++) if (latin1_encoding.type[i] != BT_OTHER && latin1_encoding.type[i] != BT_NONXML && table[i] != i) return 0; for (i = 0; i < 256; i++) { int c = table[i]; if (c == -1) { e->normal.type[i] = BT_MALFORM; /* This shouldn't really get used. */ e->utf16[i] = 0xFFFF; e->utf8[i][0] = 1; e->utf8[i][1] = 0; } else if (c < 0) { if (c < -4) return 0; /* Multi-byte sequences need a converter function */ if (! convert) return 0; e->normal.type[i] = (unsigned char)(BT_LEAD2 - (c + 2)); e->utf8[i][0] = 0; e->utf16[i] = 0; } else if (c < 0x80) { if (latin1_encoding.type[c] != BT_OTHER && latin1_encoding.type[c] != BT_NONXML && c != i) return 0; e->normal.type[i] = latin1_encoding.type[c]; e->utf8[i][0] = 1; e->utf8[i][1] = (char)c; e->utf16[i] = (unsigned short)(c == 0 ? 0xFFFF : c); } else if (checkCharRefNumber(c) < 0) { e->normal.type[i] = BT_NONXML; /* This shouldn't really get used. */ e->utf16[i] = 0xFFFF; e->utf8[i][0] = 1; e->utf8[i][1] = 0; } else { if (c > 0xFFFF) return 0; if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff)) e->normal.type[i] = BT_NMSTRT; else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff)) e->normal.type[i] = BT_NAME; else e->normal.type[i] = BT_OTHER; e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1); e->utf16[i] = (unsigned short)c; } } e->userData = userData; e->convert = convert; if (convert) { e->normal.isName2 = unknown_isName; e->normal.isName3 = unknown_isName; e->normal.isName4 = unknown_isName; e->normal.isNmstrt2 = unknown_isNmstrt; e->normal.isNmstrt3 = unknown_isNmstrt; e->normal.isNmstrt4 = unknown_isNmstrt; e->normal.isInvalid2 = unknown_isInvalid; e->normal.isInvalid3 = unknown_isInvalid; e->normal.isInvalid4 = unknown_isInvalid; } e->normal.enc.utf8Convert = unknown_toUtf8; e->normal.enc.utf16Convert = unknown_toUtf16; return &(e->normal.enc); } /* If this enumeration is changed, getEncodingIndex and encodings must also be changed. */ enum { UNKNOWN_ENC = -1, ISO_8859_1_ENC = 0, US_ASCII_ENC, UTF_8_ENC, UTF_16_ENC, UTF_16BE_ENC, UTF_16LE_ENC, /* must match encodingNames up to here */ NO_ENC }; static const char KW_ISO_8859_1[] = {ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8, ASCII_5, ASCII_9, ASCII_MINUS, ASCII_1, '\0'}; static const char KW_US_ASCII[] = {ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S, ASCII_C, ASCII_I, ASCII_I, '\0'}; static const char KW_UTF_8[] = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0'}; static const char KW_UTF_16[] = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0'}; static const char KW_UTF_16BE[] = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_B, ASCII_E, '\0'}; static const char KW_UTF_16LE[] = {ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_L, ASCII_E, '\0'}; static int FASTCALL getEncodingIndex(const char *name) { static const char *const encodingNames[] = { KW_ISO_8859_1, KW_US_ASCII, KW_UTF_8, KW_UTF_16, KW_UTF_16BE, KW_UTF_16LE, }; int i; if (name == NULL) return NO_ENC; for (i = 0; i < (int)(sizeof(encodingNames) / sizeof(encodingNames[0])); i++) if (streqci(name, encodingNames[i])) return i; return UNKNOWN_ENC; } /* For binary compatibility, we store the index of the encoding specified at initialization in the isUtf16 member. */ #define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16) #define SET_INIT_ENC_INDEX(enc, i) ((enc)->initEnc.isUtf16 = (char)i) /* This is what detects the encoding. encodingTable maps from encoding indices to encodings; INIT_ENC_INDEX(enc) is the index of the external (protocol) specified encoding; state is XML_CONTENT_STATE if we're parsing an external text entity, and XML_PROLOG_STATE otherwise. */ static int initScan(const ENCODING *const *encodingTable, const INIT_ENCODING *enc, int state, const char *ptr, const char *end, const char **nextTokPtr) { const ENCODING **encPtr; if (ptr >= end) return XML_TOK_NONE; encPtr = enc->encPtr; if (ptr + 1 == end) { /* only a single byte available for auto-detection */ #ifndef XML_DTD /* FIXME */ /* a well-formed document entity must have more than one byte */ if (state != XML_CONTENT_STATE) return XML_TOK_PARTIAL; #endif /* so we're parsing an external text entity... */ /* if UTF-16 was externally specified, then we need at least 2 bytes */ switch (INIT_ENC_INDEX(enc)) { case UTF_16_ENC: case UTF_16LE_ENC: case UTF_16BE_ENC: return XML_TOK_PARTIAL; } switch ((unsigned char)*ptr) { case 0xFE: case 0xFF: case 0xEF: /* possibly first byte of UTF-8 BOM */ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE) break; /* fall through */ case 0x00: case 0x3C: return XML_TOK_PARTIAL; } } else { switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) { case 0xFEFF: if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE) break; *nextTokPtr = ptr + 2; *encPtr = encodingTable[UTF_16BE_ENC]; return XML_TOK_BOM; /* 00 3C is handled in the default case */ case 0x3C00: if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC || INIT_ENC_INDEX(enc) == UTF_16_ENC) && state == XML_CONTENT_STATE) break; *encPtr = encodingTable[UTF_16LE_ENC]; return XmlTok(*encPtr, state, ptr, end, nextTokPtr); case 0xFFFE: if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC && state == XML_CONTENT_STATE) break; *nextTokPtr = ptr + 2; *encPtr = encodingTable[UTF_16LE_ENC]; return XML_TOK_BOM; case 0xEFBB: /* Maybe a UTF-8 BOM (EF BB BF) */ /* If there's an explicitly specified (external) encoding of ISO-8859-1 or some flavour of UTF-16 and this is an external text entity, don't look for the BOM, because it might be a legal data. */ if (state == XML_CONTENT_STATE) { int e = INIT_ENC_INDEX(enc); if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC || e == UTF_16_ENC) break; } if (ptr + 2 == end) return XML_TOK_PARTIAL; if ((unsigned char)ptr[2] == 0xBF) { *nextTokPtr = ptr + 3; *encPtr = encodingTable[UTF_8_ENC]; return XML_TOK_BOM; } break; default: if (ptr[0] == '\0') { /* 0 isn't a legal data character. Furthermore a document entity can only start with ASCII characters. So the only way this can fail to be big-endian UTF-16 if it it's an external parsed general entity that's labelled as UTF-16LE. */ if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC) break; *encPtr = encodingTable[UTF_16BE_ENC]; return XmlTok(*encPtr, state, ptr, end, nextTokPtr); } else if (ptr[1] == '\0') { /* We could recover here in the case: - parsing an external entity - second byte is 0 - no externally specified encoding - no encoding declaration by assuming UTF-16LE. But we don't, because this would mean when presented just with a single byte, we couldn't reliably determine whether we needed further bytes. */ if (state == XML_CONTENT_STATE) break; *encPtr = encodingTable[UTF_16LE_ENC]; return XmlTok(*encPtr, state, ptr, end, nextTokPtr); } break; } } *encPtr = encodingTable[INIT_ENC_INDEX(enc)]; return XmlTok(*encPtr, state, ptr, end, nextTokPtr); } #define NS(x) x #define ns(x) x #define XML_TOK_NS_C #include "xmltok_ns.c" #undef XML_TOK_NS_C #undef NS #undef ns #ifdef XML_NS # define NS(x) x##NS # define ns(x) x##_ns # define XML_TOK_NS_C # include "xmltok_ns.c" # undef XML_TOK_NS_C # undef NS # undef ns ENCODING * XmlInitUnknownEncodingNS(void *mem, int *table, CONVERTER convert, void *userData) { ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData); if (enc) ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON; return enc; } #endif /* XML_NS */ tdom-0.9.5-src/expat/ascii.h0000644000175000017500000000714214703531020014324 0ustar rolfrolf/* __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 1999-2000 Thai Open Source Software Center Ltd Copyright (c) 2000 Clark Cooper Copyright (c) 2002 Fred L. Drake, Jr. Copyright (c) 2007 Karl Waclawek Copyright (c) 2017 Sebastian Pipping Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define ASCII_A 0x41 #define ASCII_B 0x42 #define ASCII_C 0x43 #define ASCII_D 0x44 #define ASCII_E 0x45 #define ASCII_F 0x46 #define ASCII_G 0x47 #define ASCII_H 0x48 #define ASCII_I 0x49 #define ASCII_J 0x4A #define ASCII_K 0x4B #define ASCII_L 0x4C #define ASCII_M 0x4D #define ASCII_N 0x4E #define ASCII_O 0x4F #define ASCII_P 0x50 #define ASCII_Q 0x51 #define ASCII_R 0x52 #define ASCII_S 0x53 #define ASCII_T 0x54 #define ASCII_U 0x55 #define ASCII_V 0x56 #define ASCII_W 0x57 #define ASCII_X 0x58 #define ASCII_Y 0x59 #define ASCII_Z 0x5A #define ASCII_a 0x61 #define ASCII_b 0x62 #define ASCII_c 0x63 #define ASCII_d 0x64 #define ASCII_e 0x65 #define ASCII_f 0x66 #define ASCII_g 0x67 #define ASCII_h 0x68 #define ASCII_i 0x69 #define ASCII_j 0x6A #define ASCII_k 0x6B #define ASCII_l 0x6C #define ASCII_m 0x6D #define ASCII_n 0x6E #define ASCII_o 0x6F #define ASCII_p 0x70 #define ASCII_q 0x71 #define ASCII_r 0x72 #define ASCII_s 0x73 #define ASCII_t 0x74 #define ASCII_u 0x75 #define ASCII_v 0x76 #define ASCII_w 0x77 #define ASCII_x 0x78 #define ASCII_y 0x79 #define ASCII_z 0x7A #define ASCII_0 0x30 #define ASCII_1 0x31 #define ASCII_2 0x32 #define ASCII_3 0x33 #define ASCII_4 0x34 #define ASCII_5 0x35 #define ASCII_6 0x36 #define ASCII_7 0x37 #define ASCII_8 0x38 #define ASCII_9 0x39 #define ASCII_TAB 0x09 #define ASCII_SPACE 0x20 #define ASCII_EXCL 0x21 #define ASCII_QUOT 0x22 #define ASCII_AMP 0x26 #define ASCII_APOS 0x27 #define ASCII_MINUS 0x2D #define ASCII_PERIOD 0x2E #define ASCII_COLON 0x3A #define ASCII_SEMI 0x3B #define ASCII_LT 0x3C #define ASCII_EQUALS 0x3D #define ASCII_GT 0x3E #define ASCII_LSQB 0x5B #define ASCII_RSQB 0x5D #define ASCII_UNDERSCORE 0x5F #define ASCII_LPAREN 0x28 #define ASCII_RPAREN 0x29 #define ASCII_FF 0x0C #define ASCII_SLASH 0x2F #define ASCII_HASH 0x23 #define ASCII_PIPE 0x7C #define ASCII_COMMA 0x2C tdom-0.9.5-src/expat/internal.h0000644000175000017500000001430714703531020015051 0ustar rolfrolf/* internal.h Internal definitions used by Expat. This is not needed to compile client code. The following calling convention macros are defined for frequently called functions: FASTCALL - Used for those internal functions that have a simple body and a low number of arguments and local variables. PTRCALL - Used for functions called though function pointers. PTRFASTCALL - Like PTRCALL, but for low number of arguments. inline - Used for selected internal functions for which inlining may improve performance on some platforms. Note: Use of these macros is based on judgement, not hard rules, and therefore subject to change. __ __ _ ___\ \/ /_ __ __ _| |_ / _ \\ /| '_ \ / _` | __| | __// \| |_) | (_| | |_ \___/_/\_\ .__/ \__,_|\__| |_| XML parser Copyright (c) 2002-2003 Fred L. Drake, Jr. Copyright (c) 2002-2006 Karl Waclawek Copyright (c) 2003 Greg Stein Copyright (c) 2016-2024 Sebastian Pipping Copyright (c) 2018 Yury Gribov Copyright (c) 2019 David Loffredo Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow Copyright (c) 2024 Taichi Haradaguchi <20001722@ymail.ne.jp> Licensed under the MIT license: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if defined(__GNUC__) && defined(__i386__) && ! defined(__MINGW32__) /* We'll use this version by default only where we know it helps. regparm() generates warnings on Solaris boxes. See SF bug #692878. Instability reported with egcs on a RedHat Linux 7.3. Let's comment out: #define FASTCALL __attribute__((stdcall, regparm(3))) and let's try this: */ # define FASTCALL __attribute__((regparm(3))) # define PTRFASTCALL __attribute__((regparm(3))) #endif /* Using __fastcall seems to have an unexpected negative effect under MS VC++, especially for function pointers, so we won't use it for now on that platform. It may be reconsidered for a future release if it can be made more effective. Likely reason: __fastcall on Windows is like stdcall, therefore the compiler cannot perform stack optimizations for call clusters. */ /* Make sure all of these are defined if they aren't already. */ #ifndef FASTCALL # define FASTCALL #endif #ifndef PTRCALL # define PTRCALL #endif #ifndef PTRFASTCALL # define PTRFASTCALL #endif #ifndef XML_MIN_SIZE # if ! defined(__cplusplus) && ! defined(inline) # ifdef __GNUC__ # define inline __inline # endif /* __GNUC__ */ # endif #endif /* XML_MIN_SIZE */ #ifdef __cplusplus # define inline inline #else # ifndef inline # define inline # endif #endif #include // ULONG_MAX #if defined(_WIN32) \ && (! defined(__USE_MINGW_ANSI_STDIO) \ || (1 - __USE_MINGW_ANSI_STDIO - 1 == 0)) # define EXPAT_FMT_ULL(midpart) "%" midpart "I64u" # if defined(_WIN64) // Note: modifiers "td" and "zu" do not work for MinGW # define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "I64d" # define EXPAT_FMT_SIZE_T(midpart) "%" midpart "I64u" # else # define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d" # define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u" # endif #else # define EXPAT_FMT_ULL(midpart) "%" midpart "llu" # if ! defined(ULONG_MAX) # error Compiler did not define ULONG_MAX for us # elif ULONG_MAX == 18446744073709551615u // 2^64-1 # define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld" # define EXPAT_FMT_SIZE_T(midpart) "%" midpart "lu" # else # define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d" # define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u" # endif #endif #ifndef UNUSED_P # define UNUSED_P(p) (void)p #endif /* NOTE BEGIN If you ever patch these defaults to greater values for non-attack XML payload in your environment, please file a bug report with libexpat. Thank you! */ #define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT \ 100.0f #define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT \ 8388608 // 8 MiB, 2^23 /* NOTE END */ #include "expat.h" // so we can use type XML_Parser below #ifdef __cplusplus extern "C" { #endif void _INTERNAL_trim_to_complete_utf8_characters(const char *from, const char **fromLimRef); #if defined(XML_GE) && XML_GE == 1 unsigned long long testingAccountingGetCountBytesDirect(XML_Parser parser); unsigned long long testingAccountingGetCountBytesIndirect(XML_Parser parser); const char *unsignedCharToPrintable(unsigned char c); #endif extern #if ! defined(XML_TESTING) const #endif XML_Bool g_reparseDeferralEnabledDefault; // written ONLY in runtests.c #if defined(XML_TESTING) extern unsigned int g_bytesScanned; // used for testing only #endif #ifdef __cplusplus } #endif tdom-0.9.5-src/manifest.uuid0000644000175000017500000000010114703531020014424 0ustar rolfrolf9cab6ddf3bb2f2b087bfc83579ba72d20a996fa3b965e95f335f0dad54225aff tdom-0.9.5-src/README.AOL0000644000175000017500000000371014703531020013231 0ustar rolfrolf tDOM - a XML/DOM/XPath/XSLT implementation for Tcl (Version 0.9.5) Jochen Loewer (loewerj@hotmail.com) Rolf Ade (rolf@pointsman.de) with some contributions by: Zoran Vasiljevic (zv@archiware.com) This file contains some remarks about using tDOM package under the AOLserver, a webserver from America Online. For general information, look in the "README" file in this directory. COMPILING tDOM -------------- Change to "unix" directory, edit the CONFIG file to select the correct configuration defaults and then do: sh CONFIG make INSTALLING tDOM --------------- Depending on whether you use the AOLserver 3.x or 4.x series, you need to install the library in a different way. For AOLserver 3.x: The tDOM is build as AOLserver module. Please consult the AOLserver documentation how to setup the server to load AOLserver module(s). For AOLserver 4.x: You can build tDOM as a regular AOLserver module or Tcl loadable extension. There are examples in the CONFIG file how to do either. When building the tDOM as AOLserver module, you will have to manually setup the servers's startup script to load the module. Please consult the AOLserver documentation how to do this. When building the tDOM as Tcl loadable extension, there is nothing special related to the AOLserver itself, except for the target directory/ies where the tDOM files will be installed when you do: make install All you need to do then is to use "ns_eval package require tdom" to load the library. This will make sure the tDOM is loaded in every connection (or other) thread. You should add this command to some of the Tcl startup files in modules/tcl, so it loads the library on every server startup. - EOF - tdom-0.9.5-src/README.md0000644000175000017500000001027314703531020013220 0ustar rolfrolf ## tDOM - a XML / DOM / XPath / XSLT / HTML / JSON implementation for Tcl ### Version 0.9.5 tDOM 0.9.5 works with Tcl 8.5, 8.6 and 9.0. ### tDOM contains: * for convenience expat 2.6.3, the XML parser originated from James Clark, although you're able to link tDOM with other expat versions or the library provided by the system. * building a DOM tree from XML in one go implemented in C for maximum performance and minimum memory usage, and DOM I and II methods to work on such a tree using either a OO-like or a handle syntax. * a Tcl interface to expat for event-like (SAX-like) XML parsing. * a complete, compliant and fast XPath implementation in C following the November 99 W3C recommendation for navigating and data extraction. * a fast XSLT implementation in C following the W3C Recommendation 16 November 1999. * optional DTD validation. * a rich and Tcl'ish language to describe structures and text content and to validate XML data or DOM trees or other forms of hierarchically data with that. * a JSON parser which parses any possible JSON input into a DOM tree without losing information. * an efficient and Tcl'ish way to create XML and HTML documents and JSON strings. * as build option an interface to the gumbo HTML5 parser, which also digests almost any other HTML. * an even faster simple XML parser for trusted XML input. * a slim Tcl interface to use expat as pull-parser. * a secure way to share DOM trees by threads * additional convenience methods. * and more. ### Documentation The documentation is included into the source distribution in HTML and man format. Alternatively, read it [online](http://tdom.org/index.html/doc/trunk/doc/index.html). ### Getting the code The development repository is hosted at and is mirrored at . You are invited to use trunk which you get as [tarball](http://tdom.org/index.html/tarball/trunk/tdom-trunk.tar.gz) or as [zip archive](http://tdom.org/index.html/zip/trunk/tdom-trunk.zip) The latest release is 0.9.5. Get the source code as [tarball](http://tdom.org/downloads/tdom-0.9.5-src.tgz) or as [zip archive](http://tdom.org/downloads/tdom-0.9.5-src.zip). Windows binaries of the 0.9.5 release are also available. Get it for [64 bit](http://tdom.org/downloads/tdom-0.9.5-windows-64.zip) or [32_bit](http://tdom.org/downloads/tdom-0.9.5-windows-32.zip). The zip archives include binaries for tDOM and the tDOM extension tcl for Tcl 8.6 and Tcl 9. The provided windows binaries include (statically linked) the HTML5 parser. ### Compiling tdom Depending on your platform (unix/mac or win), go to the corresponding directory and invoke the configure script: ../configure make make test make install Alternatively, you can build the tDOM package in just about any directory elsewhere on the filesystem (since TEA-compatible). You might also want to do "../configure --help" to get a list of all supported options of the configure script. In the "unix" directory there is a "CONFIG" file containing some examples on how to invoke the "configure" script for some common cases. You can peek there. This file also includes a short description of the tDOM specific configure options. Since tDOM is TEA-compatible you should be able to build it using the MinGW build environment for Windows. There is also the MSVC nmake file so you can compile the package with Microsoft tools. Refer to the README in the win directory for more details about building on Windows. The compile process will build the tDOM shared library suitable for loading into the Tcl shell using standard "package require" mechanism. ### Reporting bugs Open a [ticket](http://tdom.org/index.html/ticket). Log in as anonymous and report your findings. If you prefer to have an individual login write Rolf a mail. ### History tDOM was started by Jochen Loewer (loewerj@hotmail.com) and developed by Jochen and Rolf Ade (rolf@pointsman.de) with contributions by Zoran Vasiljevic (zv@archiware.com). Since more than two decades it is maintained and developed by Rolf Ade. ### ... ahh, Licensing!! Sigh. See LICENSE file. tdom-0.9.5-src/pkgIndex.tcl.in0000644000175000017500000000064114703531020014621 0ustar rolfrolf# # Tcl package index file # if {[package vsatisfies [package provide Tcl] 9.0-]} { package ifneeded @PACKAGE_NAME@ @PACKAGE_VERSION@ \ "[list load [file join $dir @PKG_LIB_FILE9@]]; [list source [file join $dir tdom.tcl]]" } else { package ifneeded @PACKAGE_NAME@ @PACKAGE_VERSION@ \ "[list load [file join $dir @PKG_LIB_FILE8@]]; [list source [file join $dir tdom.tcl]]" } tdom-0.9.5-src/.fossil-settings/0000755000175000017500000000000014703531020015151 5ustar rolfrolftdom-0.9.5-src/.fossil-settings/crlf-glob0000644000175000017500000000000614703531020016737 0ustar rolfrolf*.vc tdom-0.9.5-src/.fossil-settings/manifest0000644000175000017500000000000314703531020016673 0ustar rolfrolfon tdom-0.9.5-src/.fossil-settings/ignore-glob0000644000175000017500000000017014703531020017276 0ustar rolfrolf*/win/Debug* */win/Release* */win/version*.vc */win/nmakehlp.exe */win/nmakehlp.obj */win/nmakehlp.out */win/_junk.pch tdom-0.9.5-src/MPL_2.0.html0000644000175000017500000004161414703531020013641 0ustar rolfrolf Mozilla Public License, version 2.0

    Mozilla Public License
    Version 2.0

    1. Definitions

    1.1. “Contributor”

    means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software.

    1.2. “Contributor Version”

    means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor’s Contribution.

    1.3. “Contribution”

    means Covered Software of a particular Contributor.

    1.4. “Covered Software”

    means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof.

    1.5. “Incompatible With Secondary Licenses”

    means

    1. that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or

    2. that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License.

    1.6. “Executable Form”

    means any form of the work other than Source Code Form.

    1.7. “Larger Work”

    means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software.

    1.8. “License”

    means this document.

    1.9. “Licensable”

    means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License.

    1.10. “Modifications”

    means any of the following:

    1. any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or

    2. any new file in Source Code Form that contains any Covered Software.

    1.11. “Patent Claims” of a Contributor

    means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version.

    1.12. “Secondary License”

    means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses.

    1.13. “Source Code Form”

    means the form of the work preferred for making modifications.

    1.14. “You” (or “Your”)

    means an individual or a legal entity exercising rights under this License. For legal entities, “You” includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, “control” means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity.

    2. License Grants and Conditions

    2.1. Grants

    Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license:

    1. under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and

    2. under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version.

    2.2. Effective Date

    The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution.

    2.3. Limitations on Grant Scope

    The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor:

    1. for any code that a Contributor has removed from Covered Software; or

    2. for infringements caused by: (i) Your and any other third party’s modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or

    3. under Patent Claims infringed by Covered Software in the absence of its Contributions.

    This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4).

    2.4. Subsequent Licenses

    No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3).

    2.5. Representation

    Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License.

    2.6. Fair Use

    This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents.

    2.7. Conditions

    Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1.

    3. Responsibilities

    3.1. Distribution of Source Form

    All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients’ rights in the Source Code Form.

    3.2. Distribution of Executable Form

    If You distribute Covered Software in Executable Form then:

    1. such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and

    2. You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients’ rights in the Source Code Form under this License.

    3.3. Distribution of a Larger Work

    You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s).

    3.4. Notices

    You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies.

    3.5. Application of Additional Terms

    You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction.

    4. Inability to Comply Due to Statute or Regulation

    If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it.

    5. Termination

    5.1. The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice.

    5.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate.

    5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination.

    6. Disclaimer of Warranty

    Covered Software is provided under this License on an “as is” basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the Covered Software is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of the Covered Software is with You. Should any Covered Software prove defective in any respect, You (not any Contributor) assume the cost of any necessary servicing, repair, or correction. This disclaimer of warranty constitutes an essential part of this License. No use of any Covered Software is authorized under this License except under this disclaimer.

    7. Limitation of Liability

    Under no circumstances and under no legal theory, whether tort (including negligence), contract, or otherwise, shall any Contributor, or anyone who distributes Covered Software as permitted above, be liable to You for any direct, indirect, special, incidental, or consequential damages of any character including, without limitation, damages for lost profits, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages. This limitation of liability shall not apply to liability for death or personal injury resulting from such party’s negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You.

    8. Litigation

    Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party’s ability to bring cross-claims or counter-claims.

    9. Miscellaneous

    This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor.

    10. Versions of the License

    10.1. New Versions

    Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number.

    10.2. Effect of New Versions

    You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward.

    10.3. Modified Versions

    If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License).

    10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses

    If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached.

    Exhibit A - Source Code Form License Notice

    This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.

    If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice.

    You may add additional accurate notices of copyright ownership.

    Exhibit B - “Incompatible With Secondary Licenses” Notice

    This Source Code Form is “Incompatible With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0.

    tdom-0.9.5-src/generic/0000755000175000017500000000000014703531020013352 5ustar rolfrolftdom-0.9.5-src/generic/xmlsimple.h0000644000175000017500000000045014703531020015534 0ustar rolfrolf domDocument * XML_SimpleParseDocument ( char *xml, int ignoreWhiteSpaces, int keepCDATA, int forest, char *baseURI, Tcl_Obj *extResolver, domLength *pos, char **errStr ); tdom-0.9.5-src/generic/domalloc.h0000644000175000017500000000250414703531020015316 0ustar rolfrolf/*--------------------------------------------------------------------------- | Copyright (C) 1999-2000 Jochen C. Loewer (loewerj@hotmail.com) +---------------------------------------------------------------------------- | | A special memory allocator, which uses preallocated / bit masked | based administration of memory block with fixed sizes, like | DOM nodes. This will hopefully save some memory. | | | The contents of this file are subject to the Mozilla Public License | Version 2.0 (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) 1998, 1999 | Jochen Loewer. All Rights Reserved. | | Contributor(s): | | | written by Jochen Loewer | October, 2000 | \--------------------------------------------------------------------------*/ void domAllocInit(void); void * domAlloc(int size); void domFree(void *mem); tdom-0.9.5-src/generic/tdomStubLib.c0000644000175000017500000000500414703531020015745 0ustar rolfrolf/*---------------------------------------------------------------------------- | Copyright (c) 2007 Rolf Ade (rolf@pointsman.de) +----------------------------------------------------------------------------- | | Implements entry point, which has to be called by C coded extensions | to tDOM. Following http://wiki.tcl.tk/3358. | | The contents of this file are subject to the Mozilla Public License | Version 2.0 (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) 1998, 1999 | Jochen Loewer. All Rights Reserved. | | Contributor(s): | | | written by Rolf Ade | August, 2007 | \---------------------------------------------------------------------------*/ #ifndef USE_TCL_STUBS # define USE_TCL_STUBS #endif #undef USE_TCL_STUB_PROCS #include /* * Ensure that Tdom_InitStubs is built as an exported symbol. The other stub * functions should be built as non-exported symbols. */ #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLEXPORT const TdomStubs *tdomStubsPtr; /*---------------------------------------------------------------------------- | Tdom_InitStubs | \---------------------------------------------------------------------------*/ const char * Tdom_InitStubs ( Tcl_Interp *interp, char *version, int exact ) { const char *actualVersion; ClientData clientData = NULL; #if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION == 0) Tcl_SetResult(interp, "Too old Tcl version. Binary extensions " "to tDOM are not possible, with a that outdated " "Tcl version.", TCL_STATIC); return NULL; #else actualVersion = Tcl_PkgRequireEx(interp, "tdom", version, exact, (ClientData*) &clientData); tdomStubsPtr = (TdomStubs*)clientData; if (!actualVersion) { return NULL; } if (!tdomStubsPtr) { Tcl_SetResult(interp, "This implementation of Tdom does not " "support stubs", TCL_STATIC); return NULL; } return actualVersion; #endif } tdom-0.9.5-src/generic/tclpull.h0000644000175000017500000000017114703531020015201 0ustar rolfrolf int tDOM_PullParserCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); tdom-0.9.5-src/generic/aolstub.cpp0000644000175000017500000000434414703531020015534 0ustar rolfrolf/* * aolstub.cpp -- * * Adds interface for loading the extension into the AOLserver. * * See the file "LICENSE" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Rcsid: @(#)$Id$ * --------------------------------------------------------------------------- */ #if defined (NS_AOLSERVER) #include int Ns_ModuleVersion = 1; /* * Structure to pass to NsThread_Init. This holds the module * and virtual server name for proper interp initializations. * This is valid only for AOLservers 4.x or later. */ struct mydata { char *modname; char *server; }; /* *---------------------------------------------------------------------------- * * NsTdom_Init -- * * Loads the package in the Tcl interpreter. * * Results: * Standard Tcl result * * Side effects: * Package initialized. Tcl commands created. * *---------------------------------------------------------------------------- */ static int NsTdom_Init (Tcl_Interp *interp, void *cd) { struct mydata *md = (struct mydata*)cd; int ret = Tdom_Init(interp); if (ret != TCL_OK) { Ns_Log(Warning, "can't load module %s: %s", md->modname, Tcl_GetStringResult(interp)); } Tcl_SetAssocData(interp, "tdom:nsd", NULL, (ClientData)md); return TCL_OK; } /* *---------------------------------------------------------------------------- * * Ns_ModuleInit -- * * Called by the AOLserver when loading shared object file. * * Results: * Standard AOLserver result * * Side effects: * Many. Depends on the package. * *---------------------------------------------------------------------------- */ int Ns_ModuleInit(char *srv, char *mod) { struct mydata *md = NULL; md = (struct mydata*)ns_malloc(sizeof(struct mydata)); md->modname = strcpy(ns_malloc(strlen(mod)+1), mod); md->server = strcpy(ns_malloc(strlen(srv)+1), srv); return (Ns_TclInitInterps(srv, NsTdom_Init, (void*)md) == TCL_OK) ? NS_OK : NS_ERROR; } #endif /* NS_AOLSERVER */ /* EOF $RCSfile$ */ /* Emacs Setup Variables */ /* Local Variables: */ /* mode: C */ /* indent-tabs-mode: nil */ /* c-basic-offset: 4 */ /* End: */ tdom-0.9.5-src/generic/tclexpat.h0000644000175000017500000002054614703531020015356 0ustar rolfrolf #ifndef __TCL_EXPAT_H__ #define __TCL_EXPAT_H__ #include #include #include "dom.h" #include "schema.h" struct TclGenExpatInfo; typedef void (*CHandlerSet_userDataReset)(Tcl_Interp *interp, void *userData); typedef void (*CHandlerSet_userDataFree)(Tcl_Interp *interp, void *userData); typedef void (*CHandlerSet_parserReset)(XML_Parser parser, void *userData); typedef void (*CHandlerSet_initParse)(Tcl_Interp *interp, void *userData); typedef void(XMLCALL *tdom_CharacterDataHandler)(void *userData, const XML_Char *s, domLength len); typedef struct CHandlerSet { struct CHandlerSet *nextHandlerSet; char *name; /* refname of the handler set */ int ignoreWhiteCDATAs; /* ignore 'white' CDATA sections */ void *userData; /* Handler set specific Data Structure; the C handler set extension has to malloc the needed structure in his init func and has to provide a cleanup func (to free it). */ CHandlerSet_userDataReset resetProc; CHandlerSet_userDataFree freeProc; CHandlerSet_parserReset parserResetProc; CHandlerSet_initParse initParseProc; /* C func for element start */ XML_StartElementHandler elementstartcommand; /* C func for element end */ XML_EndElementHandler elementendcommand; /* C func for character data */ tdom_CharacterDataHandler datacommand; /* C func for namespace decl start */ XML_StartNamespaceDeclHandler startnsdeclcommand; /* C func for namespace decl end */ XML_EndNamespaceDeclHandler endnsdeclcommand; /* C func for processing instruction */ XML_ProcessingInstructionHandler picommand; /* C func for default data */ XML_DefaultHandler defaultcommand; /* C func for unparsed entity declaration */ XML_NotationDeclHandler notationcommand; /* C func for external entity */ XML_ExternalEntityRefHandler externalentitycommand; /* C func for unknown encoding */ XML_UnknownEncodingHandler unknownencodingcommand; /* C func for comments */ XML_CommentHandler commentCommand; /* C func for "not standalone" docs */ XML_NotStandaloneHandler notStandaloneCommand; /* C func for CDATA section start */ XML_StartCdataSectionHandler startCdataSectionCommand; /* C func for CDATA section end */ XML_EndCdataSectionHandler endCdataSectionCommand; /* C func for #include #ifdef _MSC_VER #include #else #include #endif #ifndef O_BINARY #ifdef _O_BINARY #define O_BINARY _O_BINARY #else #define O_BINARY 0 #endif #endif #ifndef TDOM_EXPAT_READ_SIZE # define TDOM_EXPAT_READ_SIZE (1024*8) #endif /* For information about why this work-around for a certain expat * version is necessary see * https://github.com/libexpat/libexpat/issues/204 */ #if (XML_MAJOR_VERSION == 2) && (XML_MINOR_VERSION == 2) && (XML_MICRO_VERSION == 5) # define EXPAT_RESUME_BUG #endif /* #define DEBUG */ /*---------------------------------------------------------------------------- | Debug Macros | \---------------------------------------------------------------------------*/ #ifdef DEBUG # define DBG(x) x #else # define DBG(x) #endif typedef enum { PULLPARSERSTATE_READY, PULLPARSERSTATE_START_DOCUMENT, PULLPARSERSTATE_END_DOCUMENT, PULLPARSERSTATE_START_TAG, PULLPARSERSTATE_END_TAG, PULLPARSERSTATE_TEXT, PULLPARSERSTATE_PARSE_ERROR } PullParserState; typedef enum { PULLPARSEMODE_NORMAL, PULLPARSEMODE_SKIP, PULLPARSEMODE_FIND } PullParseMode; typedef struct tDOM_PullParserInfo { XML_Parser parser; Tcl_Obj *inputStringObj; char *inputStr; domLength inputStrLen; Tcl_Channel inputChannel; int inputfd; PullParserState state; PullParserState nextState; PullParserState next2State; Tcl_DString *cdata; Tcl_HashTable *elmCache; Tcl_Obj *currentElm; const char **atts; Tcl_Obj *channelReadBuf; Tcl_Obj *start_tag; Tcl_Obj *end_tag; Tcl_Obj *text; int ignoreWhiteSpaces; PullParseMode mode; int skipDepth; Tcl_Obj **firstFindElement; domLength countFindElement; #ifdef EXPAT_RESUME_BUG long elmStartCounter; #endif } tDOM_PullParserInfo; #define SetResult(str) Tcl_ResetResult(interp); \ Tcl_SetStringObj(Tcl_GetObjResult(interp), (str), -1) DBG( static void printParserState ( XML_Parser parser ) { XML_ParsingStatus pstatus; XML_GetParsingStatus (parser, &pstatus); switch (pstatus.parsing) { case XML_INITIALIZED: fprintf (stderr, "parser status: XML_INITIALIZED\n"); break; case XML_PARSING: fprintf (stderr, "parser status: XML_PARSING\n"); break; case XML_FINISHED: fprintf (stderr, "parser status: XML_FINISHED\n"); break; case XML_SUSPENDED: fprintf (stderr, "parser status: XML_SUSPENDED\n"); break; default: fprintf (stderr, "unexpected parser status: %d\n", pstatus.parsing); break; } } ) static void characterDataHandler ( void *userData, const char *s, int len ) { tDOM_PullParserInfo *pullInfo = userData; DBG(fprintf(stderr, "cdata handler called\n")); Tcl_DStringAppend (pullInfo->cdata, s, len); } static void endElement ( void *userData, const char *name ) { tDOM_PullParserInfo *pullInfo = userData; XML_ParsingStatus status; int reportStartTag = 0, reportText = 0, hnew; Tcl_HashEntry *h; DBG(fprintf(stderr, "endElement tag %s\n", name)); if (pullInfo->mode == PULLPARSEMODE_SKIP) { if (pullInfo->skipDepth > 0) { pullInfo->skipDepth--; return; } pullInfo->mode = PULLPARSEMODE_NORMAL; XML_SetCharacterDataHandler (pullInfo->parser, characterDataHandler); } XML_GetParsingStatus (pullInfo->parser, &status); if (status.parsing == XML_SUSPENDED) { reportStartTag = 1; } if (Tcl_DStringLength (pullInfo->cdata) > 0) { if (pullInfo->ignoreWhiteSpaces) { char *pc; domLength len; len = Tcl_DStringLength(pullInfo->cdata); for (pc = Tcl_DStringValue (pullInfo->cdata); len > 0; len--, pc++) { if ( (*pc != ' ') && (*pc != '\t') && (*pc != '\n') && (*pc != '\r') ) { reportText = 1; break; } } } else { reportText = 1; } } if (reportStartTag && reportText) { /* This happens if in mixed content an empty element written * with the empty element syntax () follows text. */ DBG(fprintf(stderr, "schedule 2 events\n")); pullInfo->state = PULLPARSERSTATE_TEXT; pullInfo->nextState= PULLPARSERSTATE_START_TAG; pullInfo->next2State = PULLPARSERSTATE_END_TAG; } else if (reportStartTag) { /* This happens if not in mixed content and the parser saw an * empty element written with the empty element syntax. */ DBG(fprintf(stderr, "schedule 1 event (reportStartTag)\n")); pullInfo->state = PULLPARSERSTATE_START_TAG; pullInfo->nextState = PULLPARSERSTATE_END_TAG; #ifdef EXPAT_RESUME_BUG DBG(fprintf(stderr, "EXPAT_RESUME_BUG\n")); if (pullInfo->elmStartCounter == 1) { pullInfo->next2State = PULLPARSERSTATE_END_DOCUMENT; } #endif } else if (reportText) { DBG(fprintf(stderr, "schedule 1 event (reportText)\n")); pullInfo->state = PULLPARSERSTATE_TEXT; pullInfo->nextState = PULLPARSERSTATE_END_TAG; } else { pullInfo->state = PULLPARSERSTATE_END_TAG; } h = Tcl_FindHashEntry (pullInfo->elmCache, name); if (h == NULL) { /* The start tag entry creation was skipped during a * find-element, create it now. */ h = Tcl_CreateHashEntry (pullInfo->elmCache, name, &hnew); DBG(fprintf(stderr, "endElement: create tag hash table entry %s\n", name)); pullInfo->currentElm = Tcl_NewStringObj (name, -1); Tcl_IncrRefCount (pullInfo->currentElm); Tcl_SetHashValue (h, pullInfo->currentElm); } pullInfo->currentElm = (Tcl_Obj *) Tcl_GetHashValue(h); XML_StopParser(pullInfo->parser, 1); } static void startElement( void *userData, const char *name, const char **atts ) { tDOM_PullParserInfo *pullInfo = userData; int i, hnew; int match; Tcl_HashEntry *h; DBG(fprintf(stderr, "startElement tag %s\n", name)); #ifdef EXPAT_RESUME_BUG pullInfo->elmStartCounter++; #endif switch (pullInfo->mode) { case PULLPARSEMODE_SKIP: DBG(fprintf (stderr, "PULLPARSEMODE_SKIP\n")); pullInfo->skipDepth++; return; case PULLPARSEMODE_FIND: match = 0; for (i=0 ; i < pullInfo->countFindElement ; i++) { char * findElement = Tcl_GetString(pullInfo->firstFindElement[i]); DBG(fprintf (stderr, "PULLPARSEMODE_FIND this %s search for %s\n", name, findElement)); if (strcmp (name, findElement) == 0) { match = 1; break; } } if (!match) { return; } pullInfo->mode = PULLPARSEMODE_NORMAL; XML_SetCharacterDataHandler (pullInfo->parser, characterDataHandler); XML_SetEndElementHandler (pullInfo->parser, endElement); break; case PULLPARSEMODE_NORMAL: break; } if (Tcl_DStringLength (pullInfo->cdata) > 0) { if (pullInfo->ignoreWhiteSpaces) { char *pc; domLength len, wso = 1; len = Tcl_DStringLength(pullInfo->cdata); for (pc = Tcl_DStringValue (pullInfo->cdata); len > 0; len--, pc++) { if ( (*pc != ' ') && (*pc != '\t') && (*pc != '\n') && (*pc != '\r') ) { wso = 0; break; } } if (wso) { Tcl_DStringSetLength (pullInfo->cdata, 0); pullInfo->state = PULLPARSERSTATE_START_TAG; } else { DBG(fprintf(stderr, "schedule TEXT event\n")); pullInfo->state = PULLPARSERSTATE_TEXT; pullInfo->nextState = PULLPARSERSTATE_START_TAG; } } else { DBG(fprintf(stderr, "schedule TEXT event\n")); pullInfo->state = PULLPARSERSTATE_TEXT; pullInfo->nextState = PULLPARSERSTATE_START_TAG; } } else { pullInfo->state = PULLPARSERSTATE_START_TAG; } h = Tcl_CreateHashEntry (pullInfo->elmCache, name, &hnew); if (hnew) { DBG(fprintf(stderr, "startElement: create tag hash table entry %s\n", name)); pullInfo->currentElm = Tcl_NewStringObj (name, -1); Tcl_IncrRefCount (pullInfo->currentElm); Tcl_SetHashValue (h, pullInfo->currentElm); } else { pullInfo->currentElm = (Tcl_Obj *) Tcl_GetHashValue (h); } pullInfo->atts = atts; XML_StopParser(pullInfo->parser, 1); } static void tDOM_PullParserDeleteCmd ( ClientData clientdata ) { tDOM_PullParserInfo *pullInfo = clientdata; Tcl_HashEntry *entryPtr; Tcl_HashSearch search; XML_ParserFree (pullInfo->parser); if (pullInfo->inputStringObj) { Tcl_DecrRefCount (pullInfo->inputStringObj); } if (pullInfo->inputfd) { close (pullInfo->inputfd); } Tcl_DStringFree (pullInfo->cdata); FREE (pullInfo->cdata); if (pullInfo->channelReadBuf) { Tcl_DecrRefCount (pullInfo->channelReadBuf); } entryPtr = Tcl_FirstHashEntry(pullInfo->elmCache, &search); while (entryPtr) { Tcl_DecrRefCount ((Tcl_Obj*) Tcl_GetHashValue (entryPtr)); entryPtr = Tcl_NextHashEntry (&search); } Tcl_DeleteHashTable (pullInfo->elmCache); FREE (pullInfo->elmCache); Tcl_DecrRefCount(pullInfo->start_tag); Tcl_DecrRefCount(pullInfo->end_tag); Tcl_DecrRefCount(pullInfo->text); FREE (pullInfo); } static void tDOM_ReportXMLError ( Tcl_Interp *interp, tDOM_PullParserInfo *pullInfo ) { char s[255]; Tcl_ResetResult (interp); sprintf(s, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentLineNumber(pullInfo->parser)); Tcl_AppendResult(interp, "error \"", XML_ErrorString( XML_GetErrorCode(pullInfo->parser)), "\" at line ", s, " column ", NULL); sprintf(s, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentColumnNumber(pullInfo->parser)); Tcl_AppendResult(interp, s, NULL); } static void tDOM_CleanupInputSource ( tDOM_PullParserInfo *pullInfo ) { if (pullInfo->inputStringObj) { Tcl_DecrRefCount (pullInfo->inputStringObj); pullInfo->inputStringObj = NULL; pullInfo->inputStr = NULL; pullInfo->inputStrLen = 0; } pullInfo->inputChannel = NULL; if (pullInfo->inputfd) { close (pullInfo->inputfd); pullInfo->inputfd = 0; } } static int tDOM_resumeParseing ( Tcl_Interp *interp, tDOM_PullParserInfo *pullInfo ) { XML_ParsingStatus pstatus; int done, result; domLength len; char *data; switch (XML_ResumeParser (pullInfo->parser)) { case XML_STATUS_OK: XML_GetParsingStatus (pullInfo->parser, &pstatus); if (pstatus.parsing == XML_FINISHED) { tDOM_CleanupInputSource (pullInfo); pullInfo->state = PULLPARSERSTATE_END_DOCUMENT; break; } if (pullInfo->inputChannel) { do { len = Tcl_ReadChars (pullInfo->inputChannel, pullInfo->channelReadBuf, 1024, 0); done = (len < 1024); data = Tcl_GetStringFromObj ( pullInfo->channelReadBuf, &len ); result = XML_Parse (pullInfo->parser, data, (int)len, done); } while (result == XML_STATUS_OK && !done); } else if (pullInfo->inputfd) { /* inputfile */ do { char *fbuf = XML_GetBuffer (pullInfo->parser, TDOM_EXPAT_READ_SIZE); len = read (pullInfo->inputfd, fbuf, TDOM_EXPAT_READ_SIZE); done = (len < TDOM_EXPAT_READ_SIZE); result = XML_ParseBuffer (pullInfo->parser, (int)len, done); } while (result == XML_STATUS_OK && !done); } else { do { done = (pullInfo->inputStrLen < TDOM_PCS); result = XML_Parse ( pullInfo->parser, pullInfo->inputStr, (int)(done ? pullInfo->inputStrLen : TDOM_PCS), done); if (!done) { pullInfo->inputStr += TDOM_PCS; pullInfo->inputStrLen -= TDOM_PCS; } } while (!done && result == XML_STATUS_OK); } if (result == XML_STATUS_ERROR) { tDOM_CleanupInputSource (pullInfo); tDOM_ReportXMLError (interp, pullInfo); pullInfo->state = PULLPARSERSTATE_PARSE_ERROR; return TCL_ERROR; } if (done && result == XML_STATUS_OK) { tDOM_CleanupInputSource (pullInfo); pullInfo->state = PULLPARSERSTATE_END_DOCUMENT; } /* If here result == XML_STATUS_SUSPENDED, * state was set in handler, just take care to * report */ break; case XML_STATUS_ERROR: tDOM_CleanupInputSource (pullInfo); tDOM_ReportXMLError (interp, pullInfo); pullInfo->state = PULLPARSERSTATE_PARSE_ERROR; return TCL_ERROR; case XML_STATUS_SUSPENDED: /* Nothing to do here, state was set in handler, just * take care to report */ break; } return TCL_OK; } static int tDOM_PullParserInstanceCmd ( ClientData clientdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { tDOM_PullParserInfo *pullInfo = clientdata; int methodIndex, result, mode, fd, optionIndex, done; domLength len; char *data; const char **atts; Tcl_Obj *resultPtr; Tcl_Channel channel; static const char *const methods[] = { "input", "inputchannel", "inputfile", "next", "state", "tag", "attributes", "text", "delete", "reset", "skip", "find-element", "line", "column", NULL }; static const char *const findelement_options[] = { "-names", NULL }; enum method { m_input, m_inputchannel, m_inputfile, m_next, m_state, m_tag, m_attributes, m_text, m_delete, m_reset, m_skip, m_find_element, m_line, m_column }; if (objc == 1) { /* Default method call is next */ methodIndex = m_next; } else { if (Tcl_GetIndexFromObj (interp, objv[1], methods, "method", 0, &methodIndex) != TCL_OK) { return TCL_ERROR; } } switch ((enum method) methodIndex) { case m_input: if (objc != 3) { Tcl_WrongNumArgs (interp, 2, objv, ""); return TCL_ERROR; } if (pullInfo->state != PULLPARSERSTATE_READY) { SetResult ("Can't change input while already parsing."); return TCL_ERROR; } Tcl_IncrRefCount (objv[2]); pullInfo->inputStringObj = objv[2]; pullInfo->inputStr = Tcl_GetStringFromObj(pullInfo->inputStringObj, &pullInfo->inputStrLen); pullInfo->state = PULLPARSERSTATE_START_DOCUMENT; break; case m_inputchannel: if (objc != 3) { Tcl_WrongNumArgs (interp, 2, objv, ""); return TCL_ERROR; } if (pullInfo->state != PULLPARSERSTATE_READY) { SetResult ("Can't change input while already parsing."); return TCL_ERROR; } channel = Tcl_GetChannel (interp, Tcl_GetString(objv[2]), &mode); if (channel == NULL) { Tcl_ResetResult (interp); Tcl_AppendResult (interp, "\"", Tcl_GetString(objv[2]), "\" isn't a Tcl channel in this interpreter", NULL); return TCL_ERROR; } if (!(mode & TCL_READABLE)) { Tcl_ResetResult (interp); Tcl_AppendResult (interp, "channel \"", Tcl_GetString(objv[2]), "wasn't opened for reading", NULL); return TCL_ERROR; } pullInfo->inputChannel = channel; if (pullInfo->channelReadBuf == NULL) { pullInfo->channelReadBuf = Tcl_NewObj (); Tcl_IncrRefCount (pullInfo->channelReadBuf); Tcl_SetObjLength (pullInfo->channelReadBuf, 6144); } pullInfo->state = PULLPARSERSTATE_START_DOCUMENT; break; case m_inputfile: if (objc != 3) { Tcl_WrongNumArgs (interp, 2, objv, ""); return TCL_ERROR; } if (pullInfo->state != PULLPARSERSTATE_READY) { SetResult ("Can't change input while already parsing."); return TCL_ERROR; } fd = open(Tcl_GetString(objv[2]), O_BINARY|O_RDONLY); if (fd < 0) { Tcl_ResetResult (interp); Tcl_AppendResult (interp, "error opening file \"", Tcl_GetString(objv[2]), "\"", NULL); return TCL_ERROR; } pullInfo->inputfd = fd; pullInfo->state = PULLPARSERSTATE_START_DOCUMENT; break; case m_next: if (objc != 2) { Tcl_WrongNumArgs (interp, 2, objv, ""); return TCL_ERROR; } if (pullInfo->state == PULLPARSERSTATE_TEXT) { Tcl_DStringSetLength (pullInfo->cdata, 0); } if (pullInfo->next2State) { pullInfo->state = pullInfo->nextState; pullInfo->nextState = pullInfo->next2State; pullInfo->next2State = 0; } else if (pullInfo->nextState) { pullInfo->state = pullInfo->nextState; pullInfo->nextState = 0; } else { switch (pullInfo->state) { case PULLPARSERSTATE_READY: SetResult ("No input"); return TCL_ERROR; case PULLPARSERSTATE_PARSE_ERROR: SetResult ("Parsing stopped with XML parsing error."); return TCL_ERROR; case PULLPARSERSTATE_END_DOCUMENT: SetResult ("No next event after END_DOCUMENT"); return TCL_ERROR; case PULLPARSERSTATE_TEXT: /* Since PULLPARSERSTATE_TEXT always has nextState set * this case is handled in the if part of this if else * and this is never reached. It's just here to eat up * this case in the switch. */ break; case PULLPARSERSTATE_START_DOCUMENT: if (pullInfo->inputfd) { do { char *fbuf = XML_GetBuffer (pullInfo->parser, TDOM_EXPAT_READ_SIZE); len = read(pullInfo->inputfd, fbuf, TDOM_EXPAT_READ_SIZE); result = XML_ParseBuffer (pullInfo->parser, (int)len, len == 0); } while (result == XML_STATUS_OK); } else if (pullInfo->inputChannel) { do { len = Tcl_ReadChars (pullInfo->inputChannel, pullInfo->channelReadBuf, 1024, 0); data = Tcl_GetString (pullInfo->channelReadBuf); result = XML_Parse (pullInfo->parser, data, (int)len, len == 0); } while (result == XML_STATUS_OK); } else { do { done = (pullInfo->inputStrLen < TDOM_PCS); result = XML_Parse ( pullInfo->parser, pullInfo->inputStr, (int)(done ? pullInfo->inputStrLen : TDOM_PCS), done); if (!done) { pullInfo->inputStr += TDOM_PCS; pullInfo->inputStrLen -= TDOM_PCS; } } while (!done && result == XML_STATUS_OK); } switch (result) { case XML_STATUS_OK: tDOM_CleanupInputSource (pullInfo); pullInfo->state = PULLPARSERSTATE_END_DOCUMENT; break; case XML_STATUS_ERROR: tDOM_CleanupInputSource (pullInfo); tDOM_ReportXMLError (interp, pullInfo); pullInfo->state = PULLPARSERSTATE_PARSE_ERROR; return TCL_ERROR; case XML_STATUS_SUSPENDED: /* Nothing to do here, state was set in handler, just * take care to report */ break; } break; default: DBG (printParserState(pullInfo->parser)); if (tDOM_resumeParseing (interp, pullInfo) != TCL_OK) { return TCL_ERROR; } DBG (printParserState(pullInfo->parser)); break; } } /* To report state:*/ /* fall through */ case m_state: if (objc != 2) { Tcl_WrongNumArgs (interp, 2, objv, ""); return TCL_ERROR; } switch (pullInfo->state) { case PULLPARSERSTATE_READY: SetResult("READY"); break; case PULLPARSERSTATE_PARSE_ERROR: SetResult("PARSE_ERROR"); break; case PULLPARSERSTATE_START_DOCUMENT: SetResult("START_DOCUMENT"); break; case PULLPARSERSTATE_END_DOCUMENT: SetResult("END_DOCUMENT"); break; case PULLPARSERSTATE_START_TAG: Tcl_SetObjResult (interp, pullInfo->start_tag); break; case PULLPARSERSTATE_END_TAG: Tcl_SetObjResult (interp, pullInfo->end_tag); break; case PULLPARSERSTATE_TEXT: Tcl_SetObjResult (interp, pullInfo->text); break; } break; case m_tag: if (objc != 2) { Tcl_WrongNumArgs (interp, 2, objv, ""); return TCL_ERROR; } if (pullInfo->state != PULLPARSERSTATE_START_TAG && pullInfo->state != PULLPARSERSTATE_END_TAG) { SetResult("Invalid state"); return TCL_ERROR; } Tcl_SetObjResult (interp, pullInfo->currentElm); break; case m_attributes: if (objc != 2) { Tcl_WrongNumArgs (interp, 2, objv, ""); return TCL_ERROR; } if (pullInfo->state != PULLPARSERSTATE_START_TAG) { SetResult("Invalid state - attribute method is only valid in state START_TAG."); return TCL_ERROR; } Tcl_ResetResult(interp); resultPtr = Tcl_GetObjResult(interp); atts = pullInfo->atts; while (atts[0] != NULL) { Tcl_ListObjAppendElement (interp, resultPtr, Tcl_NewStringObj(atts[0], -1)); atts++; } break; case m_text: if (objc != 2) { Tcl_WrongNumArgs (interp, 2, objv, ""); return TCL_ERROR; } Tcl_ResetResult (interp); Tcl_SetStringObj ( Tcl_GetObjResult (interp), Tcl_DStringValue (pullInfo->cdata), Tcl_DStringLength (pullInfo->cdata) ); break; case m_skip: if (objc != 2) { Tcl_WrongNumArgs (interp, 2, objv, ""); return TCL_ERROR; } if (pullInfo->state != PULLPARSERSTATE_START_TAG) { SetResult("Invalid state - skip method is only valid in state START_TAG."); return TCL_ERROR; } if (pullInfo->nextState == PULLPARSERSTATE_END_TAG || pullInfo->next2State == PULLPARSERSTATE_END_TAG) { pullInfo->state = PULLPARSERSTATE_END_TAG; #ifdef EXPAT_RESUME_BUG if (pullInfo->next2State == PULLPARSERSTATE_END_DOCUMENT) { pullInfo->nextState = PULLPARSERSTATE_END_DOCUMENT; } else { pullInfo->nextState = 0; } #else pullInfo->nextState = 0; #endif pullInfo->next2State = 0; Tcl_DStringSetLength (pullInfo->cdata, 0); Tcl_SetObjResult (interp, pullInfo->end_tag); break; } pullInfo->mode = PULLPARSEMODE_SKIP; pullInfo->skipDepth = 0; Tcl_DStringSetLength (pullInfo->cdata, 0); XML_SetCharacterDataHandler (pullInfo->parser, NULL); if (tDOM_resumeParseing (interp, pullInfo) != TCL_OK) { return TCL_ERROR; } Tcl_SetObjResult (interp, pullInfo->end_tag); break; case m_find_element: if (objc < 3 || objc > 4) { Tcl_WrongNumArgs (interp, 2, objv, "-names list"); return TCL_ERROR; } else if (objc == 3) { /* Single argument version */ Tcl_ListObjGetElements(interp, objv[2], &pullInfo->countFindElement, &pullInfo->firstFindElement); } else { if (Tcl_GetIndexFromObj (interp, objv[2], findelement_options, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } else { Tcl_ListObjGetElements(interp, objv[3], &pullInfo->countFindElement, &pullInfo->firstFindElement); } } if (pullInfo->state != PULLPARSERSTATE_START_TAG && pullInfo->state != PULLPARSERSTATE_END_TAG && pullInfo->state != PULLPARSERSTATE_START_DOCUMENT) { SetResult("Invalid state - find-element method is only valid in states " "START_DOCUMENT, START_TAG and END_TAG."); return TCL_ERROR; } #ifdef EXPAT_RESUME_BUG if (pullInfo->state == PULLPARSERSTATE_END_TAG && pullInfo->nextState == PULLPARSERSTATE_END_DOCUMENT) { pullInfo->state = PULLPARSERSTATE_END_DOCUMENT; SetResult ("END_DOCUMENT"); break; } #endif pullInfo->mode = PULLPARSEMODE_FIND; /* As long as we don't evaluate any Tcl script code during a * pull parser method call this should be secure. */ Tcl_DStringSetLength (pullInfo->cdata, 0); XML_SetCharacterDataHandler (pullInfo->parser, NULL); XML_SetEndElementHandler (pullInfo->parser, NULL); if (pullInfo->state == PULLPARSERSTATE_START_DOCUMENT) { Tcl_Obj * thisObjv[2]; Tcl_Obj * thisMethod = Tcl_NewStringObj ("next", 4); Tcl_IncrRefCount (thisMethod); thisObjv[0] = objv[0]; thisObjv[1] = thisMethod; result = tDOM_PullParserInstanceCmd (pullInfo, interp, 2, thisObjv); Tcl_DecrRefCount (thisMethod); if (result != TCL_OK) { return TCL_ERROR; } } else { if (tDOM_resumeParseing (interp, pullInfo) != TCL_OK) { return TCL_ERROR; } } if (pullInfo->state == PULLPARSERSTATE_START_TAG) { Tcl_SetObjResult (interp, pullInfo->start_tag); } else { SetResult ("END_DOCUMENT"); } break; case m_line: case m_column: if (objc != 2) { Tcl_WrongNumArgs (interp, 2, objv, ""); return TCL_ERROR; } switch (pullInfo->state) { case PULLPARSERSTATE_READY: SetResult("No input"); return TCL_ERROR; case PULLPARSERSTATE_TEXT: SetResult("Invalid state"); return TCL_ERROR; case PULLPARSERSTATE_END_TAG: case PULLPARSERSTATE_START_TAG: case PULLPARSERSTATE_END_DOCUMENT: case PULLPARSERSTATE_PARSE_ERROR: if ((enum method) methodIndex == m_line) { Tcl_SetObjResult(interp, Tcl_NewWideIntObj (XML_GetCurrentLineNumber(pullInfo->parser))); } else { Tcl_SetObjResult(interp, Tcl_NewWideIntObj (XML_GetCurrentColumnNumber(pullInfo->parser))); } break; case PULLPARSERSTATE_START_DOCUMENT: Tcl_SetObjResult(interp, Tcl_NewIntObj (0)); break; } break; case m_delete: if (objc != 2) { Tcl_WrongNumArgs (interp, 2, objv, ""); return TCL_ERROR; } Tcl_DeleteCommand (interp, Tcl_GetString (objv[0])); break; case m_reset: if (objc != 2) { Tcl_WrongNumArgs (interp, 2, objv, ""); return TCL_ERROR; } tDOM_CleanupInputSource (pullInfo); pullInfo->state = PULLPARSERSTATE_READY; pullInfo->nextState = 0; pullInfo->mode = PULLPARSEMODE_NORMAL; Tcl_DStringSetLength (pullInfo->cdata, 0); if (XML_ParserReset (pullInfo->parser, NULL) != XML_TRUE) { SetResult ("Parser reset failed!"); return TCL_ERROR; } XML_SetElementHandler (pullInfo->parser, startElement, endElement); XML_SetCharacterDataHandler (pullInfo->parser, characterDataHandler); XML_SetUserData (pullInfo->parser, pullInfo); break; } return TCL_OK; } int tDOM_PullParserCmd ( ClientData UNUSED(dummy), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { tDOM_PullParserInfo *pullInfo; int flagIndex, ignoreWhiteSpaces = 0; static const char *const flags[] = { "-ignorewhitecdata", NULL }; enum flag { f_ignoreWhiteSpaces }; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs (interp, 1, objv, "cmdName ?-ignorewhitecdata?"); return TCL_ERROR; } if (objc == 3) { if (Tcl_GetIndexFromObj (interp, objv[2], flags, "flag", 0, &flagIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum flag) flagIndex) { case f_ignoreWhiteSpaces: ignoreWhiteSpaces = 1; break; } } pullInfo = (tDOM_PullParserInfo *) MALLOC(sizeof(tDOM_PullParserInfo)); memset (pullInfo, 0, sizeof (tDOM_PullParserInfo)); pullInfo->parser = XML_ParserCreate_MM(NULL, MEM_SUITE, NULL); XML_SetUserData (pullInfo->parser, pullInfo); XML_SetElementHandler (pullInfo->parser, startElement, endElement); XML_SetCharacterDataHandler (pullInfo->parser, characterDataHandler); pullInfo->cdata = (Tcl_DString*) MALLOC (sizeof (Tcl_DString)); Tcl_DStringInit (pullInfo->cdata); pullInfo->state = PULLPARSERSTATE_READY; pullInfo->start_tag = Tcl_NewStringObj("START_TAG", 9); Tcl_IncrRefCount (pullInfo->start_tag); pullInfo->end_tag = Tcl_NewStringObj("END_TAG", 7); Tcl_IncrRefCount (pullInfo->end_tag); pullInfo->text = Tcl_NewStringObj("TEXT", 4); Tcl_IncrRefCount (pullInfo->text); pullInfo->ignoreWhiteSpaces = ignoreWhiteSpaces; pullInfo->elmCache = (Tcl_HashTable *)MALLOC(sizeof (Tcl_HashTable)); Tcl_InitHashTable(pullInfo->elmCache, TCL_STRING_KEYS); pullInfo->mode = PULLPARSEMODE_NORMAL; #ifdef EXPAT_RESUME_BUG pullInfo->elmStartCounter = 0; #endif Tcl_CreateObjCommand (interp, Tcl_GetString(objv[1]), tDOM_PullParserInstanceCmd, (ClientData) pullInfo, tDOM_PullParserDeleteCmd); Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } #endif /* ifndef TDOM_NO_PULL */ tdom-0.9.5-src/generic/datatypes.c0000644000175000017500000017273214703531020015530 0ustar rolfrolf/*---------------------------------------------------------------------------- | Copyright (c) 2022 Rolf Ade (rolf@pointsman.de) |----------------------------------------------------------------------------- | | | The contents of this file are subject to the Mozilla Public License | Version 2.0 (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. | | Contributor(s): | | | written by Rolf Ade | 2022 | \---------------------------------------------------------------------------*/ #include #include #include #include #ifndef TDOM_NO_SCHEMA #define CHECK_TI \ if (!sdata) { \ SetResult ("Command called outside of schema context"); \ return TCL_ERROR; \ } \ if (!sdata->isTextConstraint) { \ SetResult ("Command called in invalid schema context"); \ return TCL_ERROR; \ } #if !defined(PTR2UINT) # if defined(HAVE_UINTPTR_T) || defined(uintptr_t) # define PTR2UINT(p) ((unsigned int)(uintptr_t)(p)) # else # define PTR2UINT(p) ((unsigned int)(p)) # endif #endif #if !defined(UINT2PTR) # if defined(HAVE_UINTPTR_T) || defined(uintptr_t) # define UINT2PTR(p) ((void *)(uintptr_t)(p)) # else # define UINT2PTR(p) ((void *)(p)) # endif #endif #ifndef WHITESPACETC_BUFFER_LEN_INIT # define WHITESPACETC_BUFFER_LEN_INIT 200 #endif #define SetResult(str) Tcl_ResetResult(interp); \ Tcl_SetStringObj(Tcl_GetObjResult(interp), (str), -1) static int integerImplXsd ( Tcl_Interp *UNUSED(interp), void *constraintData, char *text ) { char *c = text; if (*c == 0) return 0; switch ((intptr_t)constraintData) { case 0: /* integer */ if (*c == '-' || *c == '+') c++; break; case 1: /* negativeInteger */ if (*c != '-') return 0; c++; while (*c == '0') c++; break; case 2: /* nonNegativeInteger */ if (*c == '+') c++; else if (*c == '-') { c++; if (*c == '0') { c++; while (*c == '0') c++; if (*c == 0) return 1; } return 0; } break; case 3: /* nonPositiveInteger */ if (*c == '-') c++; else { if (*c == '+') c++; if (*c == 0) return 0; while (*c == '0') c++; if (*c == 0) return 1; return 0; } break; case 4: /* positiveInteger */ if (*c == '+') c++; while (*c == '0') c++; break; } if (*c == 0) return 0; while (isdigit(*c)) { c++; } if (*c != 0) return 0; return 1; } static int integerImplTcl ( Tcl_Interp *interp, void *constraintData, char *text ) { int n; if (Tcl_GetInt (interp, text, &n) != TCL_OK) { return 0; } switch ((intptr_t)constraintData) { case 0: /* integer */ break; case 1: /* negativeInteger */ if (n >= 0) return 0; break; case 2: /* nonNegativeInteger */ if (n < 0) return 0; break; case 3: /* nonPositiveInteger */ if (n > 0) return 0; break; case 4: /* positiveInteger */ if (n <= 0) return 0; break; } return 1; } static int integerTCObjCmd ( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; int type; static const char *types[] = { "xsd", "tcl", NULL }; enum typeSyms { t_xsd, t_tcl }; CHECK_TI checkNrArgs (1,2,"?xsd|tcl?"); if (objc == 1) { type = t_xsd; } else { if (Tcl_GetIndexFromObj (interp, objv[1], types, "type", 0, &type) != TCL_OK) { return TCL_ERROR; } } ADD_CONSTRAINT (sdata, sc) switch ((enum typeSyms) type) { case t_xsd: sc->constraint = integerImplXsd; break; case t_tcl: sc->constraint = integerImplTcl; break; } sc->constraintData = clientData; return TCL_OK; } typedef struct { int nrArg; Tcl_Obj **evalStub; SchemaData *sdata; } tclTCData; static void tclImplFree ( void *constraintData ) { tclTCData *tcdata = constraintData; int i; for (i = 0; i < tcdata->nrArg-1; i++) { Tcl_DecrRefCount (tcdata->evalStub[i]); } FREE (tcdata->evalStub); FREE (tcdata); } static int tclImpl ( Tcl_Interp *interp, void *constraintData, char *text ) { tclTCData *tcdata = constraintData; int result, bool; tcdata->evalStub[tcdata->nrArg-1] = Tcl_NewStringObj(text, -1); Tcl_IncrRefCount (tcdata->evalStub[tcdata->nrArg-1]); tcdata->sdata->currentEvals++; result = Tcl_EvalObjv (interp, tcdata->nrArg, tcdata->evalStub, TCL_EVAL_GLOBAL); tcdata->sdata->currentEvals--; Tcl_DecrRefCount (tcdata->evalStub[tcdata->nrArg-1]); if (result != TCL_OK) { tcdata->sdata->evalError = 1; return 0; } result = Tcl_GetBooleanFromObj (interp, Tcl_GetObjResult (interp), &bool); if (result != TCL_OK) { return 0; } if (bool) { return 1; } return 0; } static int tclTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; tclTCData *tcdata; int i; CHECK_TI if (objc < 2) { SetResult ("Expected: tclcmd ?arg arg ...?"); return TCL_ERROR; } ADD_CONSTRAINT (sdata, sc) sc->constraint = tclImpl; sc->freeData = tclImplFree; tcdata = TMALLOC (tclTCData); tcdata->nrArg = objc; tcdata->evalStub = MALLOC (sizeof (Tcl_Obj*) * objc); for (i = 1; i < objc; i++) { tcdata->evalStub[i-1] = objv[i]; Tcl_IncrRefCount (tcdata->evalStub[i-1]); } tcdata->sdata = sdata; sc->constraintData = tcdata; return TCL_OK; } static void fixedImplFree ( void *constraintData ) { FREE (constraintData); } static int fixedImpl ( Tcl_Interp *UNUSED(interp), void *constraintData, char *text ) { if (strcmp (text, (char *) constraintData) == 0) { return 1; } return 0; } static int fixedTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (2,2,"Expected: "); ADD_CONSTRAINT (sdata, sc) sc->constraint = fixedImpl; sc->freeData = fixedImplFree; sc->constraintData = tdomstrdup (Tcl_GetString (objv[1])); return TCL_OK; } static void enumerationImplFree ( void *constraintData ) { Tcl_HashTable *values = (Tcl_HashTable *) constraintData; Tcl_DeleteHashTable (values); FREE (values); } static int enumerationImpl ( Tcl_Interp *UNUSED(interp), void *constraintData, char *text ) { Tcl_HashTable *values = (Tcl_HashTable *) constraintData; if (Tcl_FindHashEntry(values, text)) return 1; return 0; } static int enumerationTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; Tcl_HashTable *values; domLength len, i; int hnew; Tcl_Obj *value; CHECK_TI checkNrArgs (2,2,"Expected: "); if (Tcl_ListObjLength (interp, objv[1], &len) != TCL_OK) { SetResult ("The argument must be a valid tcl list"); return TCL_ERROR; } ADD_CONSTRAINT (sdata, sc) sc->constraint = enumerationImpl; sc->freeData = enumerationImplFree; values = TMALLOC (Tcl_HashTable); Tcl_InitHashTable (values, TCL_STRING_KEYS); for (i = 0; i < len; i++) { Tcl_ListObjIndex (interp, objv[1], i, &value); Tcl_CreateHashEntry (values, Tcl_GetString (value), &hnew); } sc->constraintData = values; return TCL_OK; } static void matchImplFree ( void *constraintData ) { Tcl_DecrRefCount ((Tcl_Obj *) constraintData); } static int matchImpl ( Tcl_Interp *UNUSED(interp), void *constraintData, char *text ) { if (Tcl_StringCaseMatch (text, Tcl_GetString ((Tcl_Obj *) constraintData), 0)) return 1; return 0; } static int matchNocaseImpl ( Tcl_Interp *UNUSED(interp), void *constraintData, char *text ) { if (Tcl_StringCaseMatch (text, Tcl_GetString ((Tcl_Obj *) constraintData), TCL_MATCH_NOCASE)) return 1; return 0; } static int matchTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (2,3,"Expected: ?-nocase? "); if (objc == 3) { if (strcmp ("-nocase", Tcl_GetString (objv[1])) != 0) { SetResult ("Expected: ?-nocase? "); return TCL_ERROR; } objv++; } ADD_CONSTRAINT (sdata, sc) if (objc == 2) { sc->constraint = matchImpl; } else { sc->constraint = matchNocaseImpl; } sc->freeData = matchImplFree; Tcl_IncrRefCount (objv[1]); sc->constraintData = objv[1]; return TCL_OK; } static void regexpImplFree ( void *constraintData ) { Tcl_DecrRefCount ((Tcl_Obj *) constraintData); } static int regexpImpl ( Tcl_Interp *interp, void *constraintData, char *text ) { Tcl_Obj *textObj; int rc; textObj = Tcl_NewStringObj(text, -1); rc = Tcl_RegExpMatchObj (interp, textObj, (Tcl_Obj *) constraintData); Tcl_DecrRefCount (textObj); /* rc may be 1, 0, -1 */ if (rc == 1) { return 1; } return 0; } static int regexpTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (2,2,"Expected: "); /* Compile it as syntax test (plus caches the complied regexp in * the internal value) */ if (!Tcl_GetRegExpFromObj (interp, objv[1], TCL_REG_ADVANCED)) { return TCL_ERROR; } ADD_CONSTRAINT (sdata, sc) sc->constraint = regexpImpl; sc->freeData = regexpImplFree; Tcl_IncrRefCount (objv[1]); sc->constraintData = objv[1]; return TCL_OK; } static int nmtokenImpl ( Tcl_Interp *interp, void *UNUSED(constraintData), char *text ) { char *p; int clen, tokenSeen = 0; p = text; /* Skip leading space */ while (*p && *p == ' ') { p++; } while (*p && *p != ' ') { clen = UTF8_CHAR_LEN (*p); if (!clen) { SetResult ("Invalid UTF-8 character"); return 0; } if (!UTF8_GET_NAMING_NMTOKEN (p, clen)) { SetResult ("Attribute value isn't a NMTOKEN"); return 0; } tokenSeen = 1; p += clen; } /* Skip following space */ while (*p && *p == ' ') { p++; } if (*p) { SetResult ("Attribute value isn't a NMTOKEN"); return 0; } if (!*p && !tokenSeen) { SetResult ("Missing NMTOKEN value"); return 0; } return 1; } static int nmtokenTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const UNUSED(objv[]) ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (1,1,"No arguments expected"); ADD_CONSTRAINT (sdata, sc) sc->constraint = nmtokenImpl; return TCL_OK; } static int nmtokensImpl ( Tcl_Interp *interp, void *UNUSED(constraintData), char *text ) { char *p; int clen, tokenSeen = 0; p = text; /* Skip leading space */ while (*p && *p == ' ') { p++; } while (*p) { if (*p == ' ') { p++; continue; } clen = UTF8_CHAR_LEN (*p); if (!clen) { SetResult ("Invalid UTF-8 character"); return 0; } if (!UTF8_GET_NAMING_NMTOKEN (p, clen)) { SetResult ("Invalid character: attribute value isn't a NMTOKENS"); return 0; } tokenSeen = 1; p += clen; } /* Any following space is already skipped above */ if (!tokenSeen) { SetResult ("Missing NMTOKENS value"); return 0; } return 1; } static int nmtokensTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const UNUSED(objv[]) ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (1,1,"No arguments expected"); ADD_CONSTRAINT (sdata, sc) sc->constraint = nmtokensImpl; return TCL_OK; } static int numberImplXsd ( Tcl_Interp *UNUSED(interp), void *UNUSED(constraintData), char *text ) { char *c = text; if (!*c) return 0; if (*c == '-' || *c == '+') c++; while (isdigit(*c)) { c++; } if (*c == '.') c++; while (isdigit(*c)) { c++; } if (*c) return 0; return 1; } static int numberImplTcl ( Tcl_Interp *interp, void *UNUSED(constraintData), char *text ) { double d; if (Tcl_GetDouble (interp, text, &d) != TCL_OK) { return 0; } return 1; } static int numberTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; int type; static const char *types[] = { "xsd", "tcl", NULL }; enum typeSyms { t_xsd, t_tcl }; CHECK_TI checkNrArgs (1,2,"?xsd|tcl?"); if (objc == 1) { type = t_xsd; } else { if (Tcl_GetIndexFromObj (interp, objv[1], types, "type", 0, &type) != TCL_OK) { return TCL_ERROR; } } ADD_CONSTRAINT (sdata, sc) switch ((enum typeSyms) type) { case t_xsd: sc->constraint = numberImplXsd; break; case t_tcl: sc->constraint = numberImplTcl; break; } return TCL_OK; } static int booleanImplXsd ( Tcl_Interp *UNUSED(interp), void *UNUSED(constraintData), char *text ) { char *c = text; switch (*c) { case '0': case '1': c++; if (*c == 0) return 1; break; case 't': if (strcmp (text, "true") == 0) return 1; break; case 'f': if (strcmp (text, "false") == 0) return 1; break; } return 0; } static int booleanImplTcl ( Tcl_Interp *interp, void *UNUSED(constraintData), char *text ) { int b; if (Tcl_GetBoolean (interp, text, &b) != TCL_OK) { return 0; } return 1; } static int booleanTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; int type; static const char *types[] = { "xsd", "tcl", NULL }; enum typeSyms { t_xsd, t_tcl }; CHECK_TI checkNrArgs (1,2,"?xsd|tcl?"); if (objc == 1) { type = t_xsd; } else { if (Tcl_GetIndexFromObj (interp, objv[1], types, "type", 0, &type) != TCL_OK) { return TCL_ERROR; } } ADD_CONSTRAINT (sdata, sc) switch ((enum typeSyms) type) { case t_xsd: sc->constraint = booleanImplXsd; break; case t_tcl: sc->constraint = booleanImplTcl; break; } return TCL_OK; } static int isodateImpl ( Tcl_Interp *UNUSED(interp), void *constraintData, char *text ) { int i, y, m, d, h, min, s, zh, zm, seenNonzero = 0; if (constraintData < (void *)2) { if (*text == '-') { /* A bce date */ text++; } i = 1; /* Parse year */ while (*text >= '0' && *text <= '9') { if (*text > '0' && !seenNonzero) seenNonzero = i; text++; i++; } /* Premature end */ if (i < 5) return 0; if (i > 5) { /* The year has more than 4 digits. Only allowed if in fact * needed (no extra leading zeros). */ if (seenNonzero > 1) return 0; } if (*text != '-') return 0; /* We only need to know the modulo of the year for 4, 100 and 400, * for this the 4 last letters are enough */ y = atoi(text-4); /* There isn't a year 0. it's either 0001 or -0001 */ if (!seenNonzero) return 0; text++; /* Parse month */ for (i = 0; i < 2; i++) { if (*text < '0' || *text > '9') return 0; text++; } if (*text != '-') return 0; m = atoi(text-2); if (m < 1 || m > 12) return 0; text++; /* Parse day */ for (i = 0; i < 2; i++) { if (*text < '0' || *text > '9') return 0; text++; } d = atoi(text-2); if (d < 1) return 0; switch (m) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: if (d > 31) return 0; break; case 4: case 6: case 9: case 11: if (d > 30) return 0; break; case 2: if (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) { if (d > 29) return 0; } else { if (d > 28) return 0; } break; } } /* Date part end */ if (constraintData) { if (constraintData == (void *)1) { /* Time part starts */ if (*text != 'T') return 0; text++; } /* Parse hour part */ if (*text < '0' || *text > '9') return 0; h = (*text - 48) * 10; text++; if (*text < '0' || *text > '9') return 0; h += (*text - 48); if (h > 24) return 0; text++; if (*text != ':') return 0; text++; /* Parse minute part */ if (*text < '0' || *text > '9') return 0; min = (*text - 48) * 10; text++; if (*text < '0' || *text > '9') return 0; min += (*text - 48); if (min > 59) return 0; text++; if (*text != ':') return 0; text++; /* Parse seconds part */ if (*text < '0' || *text > '9') return 0; s = (*text - 48) * 10; text++; if (*text < '0' || *text > '9') return 0; s += (*text - 48); if (s > 59) return 0; text++; /* Check for optional fraction seconds part */ if (*text == '.') { if (h == 24) return 0; text++; /* Dangling decimal point is not allowed */ if (*text < '0' || *text > '9') return 0; text++; while (*text >= '0' && *text <= '9') text++; } if (h == 24 && (min > 0 || s > 0)) return 0; } if (*text == '\0') return 1; /* Parse optional timezone part */ switch (*text) { case 'Z': text++; if (*text != '\0') return 0; break; case '+': case '-': text++; for (i = 0; i < 2; i++) { if (*text < '0' || *text > '9') return 0; text++; } if (*text != ':') return 0; zh = atoi(text-2); if (zh > 14) return 0; text++; for (i = 0; i < 2; i++) { if (*text < '0' || *text > '9') return 0; text++; } if (*text != '\0') return 0; zm = atoi(text-2); if (zh < 14) { if (zm > 59) return 0; } else { if (zm != 0) return 0; } break; default: return 0; } return 1; } static int dateTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const UNUSED(objv[]) ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (1,1,"No arguments expected"); ADD_CONSTRAINT (sdata, sc) sc->constraint = isodateImpl; sc->constraintData = (void *) 0; return TCL_OK; } static int dateTimeTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const UNUSED(objv[]) ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (1,1,"No arguments expected"); ADD_CONSTRAINT (sdata, sc) sc->constraint = isodateImpl; sc->constraintData = (void *) 1; return TCL_OK; } static int timeTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const UNUSED(objv[]) ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (1,1,"No arguments expected"); ADD_CONSTRAINT (sdata, sc) sc->constraint = isodateImpl; sc->constraintData = (void *) 2; return TCL_OK; } static int maxLengthImpl ( Tcl_Interp *interp, void *constraintData, char *text ) { unsigned int len = 0, maxlen = PTR2UINT(constraintData); int clen; while (*text != '\0') { clen = UTF8_CHAR_LEN (*text); if (!clen) { SetResult ("Invalid UTF-8 character"); return 0; } len++; if (len > maxlen) return 0; text += clen; } return 1; } static int maxLengthTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; int len; CHECK_TI checkNrArgs (2,2,"Expected: "); if (Tcl_GetIntFromObj (interp, objv[1], &len) != TCL_OK) { SetResult ("Expected: "); return TCL_ERROR; } if (len < 1) { SetResult ("The maximum length must be at least 1"); } ADD_CONSTRAINT (sdata, sc) sc->constraint = maxLengthImpl; sc->constraintData = UINT2PTR(len); return TCL_OK; } static int minLengthImpl ( Tcl_Interp *interp, void *constraintData, char *text ) { unsigned int len = 0, minlen = PTR2UINT(constraintData); int clen; while (*text != '\0') { clen = UTF8_CHAR_LEN (*text); if (!clen) { SetResult ("Invalid UTF-8 character"); return 0; } len++; if (len >= minlen) return 1; text += clen; } return 0; } static int minLengthTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; int len; CHECK_TI checkNrArgs (2,2,"Expected: "); if (Tcl_GetIntFromObj (interp, objv[1], &len) != TCL_OK) { SetResult ("Expected: "); return TCL_ERROR; } if (len < 1) { SetResult ("The minimum length must be at least 1"); } ADD_CONSTRAINT (sdata, sc) sc->constraint = minLengthImpl; sc->constraintData = UINT2PTR(len); return TCL_OK; } static int oneOfImpl ( Tcl_Interp *interp, void *constraintData, char *text ) { SchemaCP *cp = (SchemaCP *) constraintData; SchemaConstraint *sc; unsigned int i; /* Look also at checkText */ for (i = 0; i < cp->nc; i++) { sc = (SchemaConstraint *) cp->content[i]; if ((sc->constraint) (interp, sc->constraintData, text)) { return 1; } } return 0; } static int oneOfTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaCP *cp; SchemaConstraint *sc; int rc; CHECK_TI checkNrArgs (2,2,"Expected: "); cp = initSchemaCP (SCHEMA_CTYPE_CHOICE, NULL, NULL); cp->type = SCHEMA_CTYPE_TEXT; REMEMBER_PATTERN (cp) rc = evalConstraints (interp, sdata, cp, objv[1]); if (rc == TCL_OK) { ADD_CONSTRAINT (sdata, sc) sc->constraint = oneOfImpl; sc->constraintData = (void *)cp; return TCL_OK; } return TCL_ERROR; } static int allOfTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaCP *cp; SchemaConstraint *sc; int rc; CHECK_TI checkNrArgs (2,2,"Expected: "); cp = initSchemaCP (SCHEMA_CTYPE_CHOICE, NULL, NULL); cp->type = SCHEMA_CTYPE_TEXT; REMEMBER_PATTERN (cp) rc = evalConstraints (interp, sdata, cp, objv[1]); if (rc == TCL_OK) { ADD_CONSTRAINT (sdata, sc) sc->constraint = tDOM_checkText; sc->constraintData = (void *)cp; return TCL_OK; } return TCL_ERROR; } static int stripImpl ( Tcl_Interp *interp, void *constraintData, char *text ) { SchemaCP *cp = (SchemaCP *) constraintData; int rc, restore = 0; char *end, saved; while(SPACE((unsigned char)*text)) text++; if(*text != 0) { /* Not white space only */ /* Trim trailing space */ end = text + strlen(text) - 1; while(end > text && SPACE((unsigned char)*end)) end--; saved = end[1]; restore = 1; end[1] = '\0'; } rc = checkText (interp, cp, text); if (restore) end[1] = saved; return rc; } static int stripTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaCP *cp; SchemaConstraint *sc; int rc; CHECK_TI checkNrArgs (2,2,"Expected: "); cp = initSchemaCP (SCHEMA_CTYPE_CHOICE, NULL, NULL); cp->type = SCHEMA_CTYPE_TEXT; REMEMBER_PATTERN (cp) rc = evalConstraints (interp, sdata, cp, objv[1]); if (rc == TCL_OK) { ADD_CONSTRAINT (sdata, sc) sc->constraint = stripImpl; sc->constraintData = (void *)cp; return TCL_OK; } return TCL_ERROR; } static int splitWhitespaceImpl ( Tcl_Interp *interp, void *constraintData, char *text ) { SchemaCP *cp = (SchemaCP *) constraintData; int rc = 0; char *p, *end, saved = 0; p = text; while (*p != 0) { while(SPACE (*p)) p++; if (*p == 0) break; end = p; end++; while (*end != 0 && !SPACE(*end)) end++; saved = *end; *end = 0; rc = checkText (interp, cp, p); *end = saved; p = end; if (!rc) break; } return rc; } typedef struct { int nrArg; Tcl_Obj **evalStub; SchemaData *sdata; SchemaCP *cp; } splitTclTCData; static int splitTclImpl ( Tcl_Interp *interp, void *constraintData, char *text ) { splitTclTCData *tcdata = (splitTclTCData *) constraintData; domLength listlen, i; int rc; Tcl_Obj *list, *listelm; tcdata->evalStub[tcdata->nrArg-1] = Tcl_NewStringObj(text, -1); Tcl_IncrRefCount (tcdata->evalStub[tcdata->nrArg-1]); tcdata->sdata->currentEvals++; rc = Tcl_EvalObjv (interp, tcdata->nrArg, tcdata->evalStub, TCL_EVAL_GLOBAL); tcdata->sdata->currentEvals--; Tcl_DecrRefCount (tcdata->evalStub[tcdata->nrArg-1]); if (rc != TCL_OK) { tcdata->sdata->evalError = 1; return 0; } list = Tcl_GetObjResult (interp); Tcl_IncrRefCount (list); Tcl_ResetResult (interp); if (Tcl_ListObjLength (interp, list, &listlen) != TCL_OK) { Tcl_DecrRefCount (list); tcdata->sdata->evalError = 1; return 0; } rc = 0; for (i = 0; i < listlen; i++) { Tcl_ListObjIndex (interp, list, i, &listelm); rc = checkText (interp, tcdata->cp, Tcl_GetString (listelm)); if (!rc) break; } Tcl_DecrRefCount (list); return rc; } static void splitTclImplFree ( void *constraintData ) { splitTclTCData *tcdata = constraintData; int i; for (i = 0; i < tcdata->nrArg-1; i++) { Tcl_DecrRefCount (tcdata->evalStub[i]); } FREE (tcdata->evalStub); FREE (tcdata); } static int splitTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaCP *cp; SchemaConstraint *sc; int methodIndex, rc, i; splitTclTCData *tcdata; static const char *methods[] = { "whitespace", "tcl", NULL }; enum method { m_whitespace, m_tcl }; CHECK_TI if (objc < 2) { SetResult("Expected: ?type ?args?? "); return TCL_ERROR; } if (objc == 2) { methodIndex = m_whitespace; } else { if (Tcl_GetIndexFromObj (interp, objv[1], methods, "type", 0, &methodIndex) != TCL_OK) { return TCL_ERROR; } } switch ((enum method) methodIndex) { case m_whitespace: if (objc > 2) { SetResult ("Type whitespace expects no argument."); return TCL_ERROR; } break; case m_tcl: if (objc < 3) { SetResult ("Expected: tclcmd ?arg ...?."); return TCL_ERROR; } } cp = initSchemaCP (SCHEMA_CTYPE_CHOICE, NULL, NULL); cp->type = SCHEMA_CTYPE_TEXT; REMEMBER_PATTERN (cp) rc = evalConstraints (interp, sdata, cp, objv[objc-1]); if (rc != TCL_OK) { return TCL_ERROR; } ADD_CONSTRAINT (sdata, sc) switch ((enum method) methodIndex) { case m_whitespace: sc->constraint = splitWhitespaceImpl; sc->constraintData = cp; break; case m_tcl: sc->constraint = splitTclImpl; sc->freeData = splitTclImplFree; tcdata = TMALLOC (splitTclTCData); tcdata->nrArg = objc - 2; tcdata->evalStub = MALLOC (sizeof (Tcl_Obj*) * (objc-2)); for (i = 2; i < objc -1; i++) { tcdata->evalStub[i-2] = objv[i]; Tcl_IncrRefCount (tcdata->evalStub[i-2]); } tcdata->sdata = sdata; tcdata->cp = cp; sc->constraintData = tcdata; } return TCL_OK; } static int idImpl ( Tcl_Interp *UNUSED(interp), void *constraintData, char *text ) { SchemaData *sdata = (SchemaData *) constraintData; int hnew; Tcl_HashEntry *h; h = Tcl_CreateHashEntry (&sdata->ids, text, &hnew); if (hnew) { Tcl_SetHashValue (h, 1); return 1; } if (Tcl_GetHashValue (h) == 0) { Tcl_SetHashValue (h, 1); sdata->unknownIDrefs--; return 1; } else { /* Duplicate ID value */ return 0; } } static int docidImpl ( Tcl_Interp *UNUSED(interp), void *constraintData, char *text ) { SchemaDocKey *dk = (SchemaDocKey *) constraintData; int hnew; Tcl_HashEntry *h; h = Tcl_CreateHashEntry (&dk->ids, text, &hnew); if (hnew) { Tcl_SetHashValue (h, 1); return 1; } if (Tcl_GetHashValue (h) == 0) { Tcl_SetHashValue (h, 1); dk->unknownIDrefs--; return 1; } /* Duplicate ID value */ return 0; } static int idTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; Tcl_HashEntry *h; int hnew; SchemaDocKey *dk; CHECK_TI checkNrArgs (1,2,"?key_space?"); ADD_CONSTRAINT (sdata, sc) if (objc == 1) { sc->constraint = idImpl; sc->constraintData = (void *)sdata; } else { h = Tcl_CreateHashEntry (&sdata->idTables, Tcl_GetString (objv[1]), &hnew); if (hnew) { dk = TMALLOC (SchemaDocKey); Tcl_InitHashTable (&dk->ids, TCL_STRING_KEYS); dk->unknownIDrefs = 0; Tcl_SetHashValue (h, dk); } else { dk = Tcl_GetHashValue (h); } sc->constraint = docidImpl; sc->constraintData = (void *)dk; } return TCL_OK; } static int idrefImpl ( Tcl_Interp *UNUSED(interp), void *constraintData, char *text ) { SchemaData *sdata = (SchemaData *) constraintData; int hnew; Tcl_HashEntry *h; h = Tcl_CreateHashEntry (&sdata->ids, text, &hnew); if (hnew) { Tcl_SetHashValue (h, 0); sdata->unknownIDrefs++; } return 1; } static int docidrefImpl ( Tcl_Interp *UNUSED(interp), void *constraintData, char *text ) { SchemaDocKey *dk = (SchemaDocKey *) constraintData; int hnew; Tcl_HashEntry *h; h = Tcl_CreateHashEntry (&dk->ids, text, &hnew); if (hnew) { Tcl_SetHashValue (h, 0); dk->unknownIDrefs++; } return 1; } static int idrefTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; Tcl_HashEntry *h; int hnew; SchemaDocKey *dk; CHECK_TI checkNrArgs (1,2,"?key_space?"); ADD_CONSTRAINT (sdata, sc) if (objc == 1) { sc->constraint = idrefImpl; sc->constraintData = (void *)sdata; } else { h = Tcl_CreateHashEntry (&sdata->idTables, Tcl_GetString (objv[1]), &hnew); if (hnew) { dk = TMALLOC (SchemaDocKey); Tcl_InitHashTable (&dk->ids, TCL_STRING_KEYS); dk->unknownIDrefs = 0; Tcl_SetHashValue (h, dk); } else { dk = Tcl_GetHashValue (h); } sc->constraint = docidrefImpl; sc->constraintData = (void *)dk; } return TCL_OK; } static int keyImpl ( Tcl_Interp *UNUSED(interp), void *constraintData, char *text ) { SchemaKeySpace *ks = (SchemaKeySpace *) constraintData; int hnew; Tcl_HashEntry *h; if (!ks->active) return 1; h = Tcl_CreateHashEntry (&ks->ids, text, &hnew); if (hnew) { Tcl_SetHashValue (h, 1); return 1; } if (Tcl_GetHashValue (h) == 0) { Tcl_SetHashValue (h, 1); ks->unknownIDrefs--; return 1; } else { /* Duplicate ID value */ return 0; } } static int keyTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; Tcl_HashEntry *h; int hnew; SchemaKeySpace *ks; CHECK_TI checkNrArgs (2,2,"key_space"); ADD_CONSTRAINT (sdata, sc) h = Tcl_CreateHashEntry (&sdata->keySpaces, Tcl_GetString (objv[1]), &hnew); if (hnew) { ks = TMALLOC (SchemaKeySpace); ks->active = 0; ks->unknownIDrefs = 0; Tcl_SetHashValue (h, ks); } else { ks = Tcl_GetHashValue (h); } sc->constraint = keyImpl; sc->constraintData = (void *) ks; return TCL_OK; } static int keyrefImpl ( Tcl_Interp *UNUSED(interp), void *constraintData, char *text ) { SchemaKeySpace *ks = (SchemaKeySpace *) constraintData; int hnew; Tcl_HashEntry *h; if (!ks->active) return 1; h = Tcl_CreateHashEntry (&ks->ids, text, &hnew); if (hnew) { Tcl_SetHashValue (h, 0); ks->unknownIDrefs++; } return 1; } static int keyrefTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; Tcl_HashEntry *h; int hnew; SchemaKeySpace *ks; CHECK_TI checkNrArgs (2,2,"key_space"); ADD_CONSTRAINT (sdata, sc) h = Tcl_CreateHashEntry (&sdata->keySpaces, Tcl_GetString (objv[1]), &hnew); if (hnew) { ks = TMALLOC (SchemaKeySpace); Tcl_InitHashTable (&ks->ids, TCL_STRING_KEYS); ks->unknownIDrefs = 0; Tcl_SetHashValue (h, ks); } else { ks = Tcl_GetHashValue (h); } sc->constraint = keyrefImpl; sc->constraintData = (void *)ks; return TCL_OK; } static int base64Impl ( Tcl_Interp *UNUSED(interp), void *UNUSED(constraintData), char *text ) { int chars = 0, equals = 0; while (*text != '\0') { if (SPACE(*text)) { text++; continue; } if ( (*text >= 'A' && *text <= 'Z') || (*text >= 'a' && *text <= 'z') || (*text >= '0' && *text <= '9') || (*text = '+') || (*text = '/')) { chars++; text++; continue; } if (equals < 2 && *text == '=') { equals++; text++; continue; } break; } if (*text) { return 0; } if ((chars + equals) % 4 != 0) { return 0; } return 1; } static int base64TCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const UNUSED(objv[]) ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (1,1,"No arguments expected"); ADD_CONSTRAINT (sdata, sc) sc->constraint = base64Impl; return TCL_OK; } static int nameImpl ( Tcl_Interp *UNUSED(interp), void *UNUSED(constraintData), char *text ) { return domIsNAME (text); } static int nameTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const UNUSED(objv[]) ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (1,1,"No arguments expected"); ADD_CONSTRAINT (sdata, sc) sc->constraint = nameImpl; return TCL_OK; } static int ncnameImpl ( Tcl_Interp *UNUSED(interp), void *UNUSED(constraintData), char *text ) { return domIsNCNAME (text); } static int ncnameTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const UNUSED(objv[]) ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (1,1,"No arguments expected"); ADD_CONSTRAINT (sdata, sc) sc->constraint = ncnameImpl; return TCL_OK; } static int qnameImpl ( Tcl_Interp *UNUSED(interp), void *UNUSED(constraintData), char *text ) { return domIsQNAME (text); } static int qnameTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const UNUSED(objv[]) ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (1,1,"No arguments expected"); ADD_CONSTRAINT (sdata, sc) sc->constraint = qnameImpl; return TCL_OK; } static int hexBinaryImpl ( Tcl_Interp *UNUSED(interp), void *UNUSED(constraintData), char *text ) { int count = 0; if (*text == 0) return 0; while (*text) { if ((*text >= '0' && *text <= '9') || (*text >= 'A' && *text <= 'F') || (*text >= 'a' && *text <= 'f')) { text++; count++; } else return 0; } if (count % 2 == 0) return 1; return 0; } static int hexBinaryTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const UNUSED(objv[]) ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (1,1,"No arguments expected"); ADD_CONSTRAINT (sdata, sc) sc->constraint = hexBinaryImpl; return TCL_OK; } static int unsignedIntTypesImpl ( Tcl_Interp *UNUSED(interp), void *constraintData, char *text ) { char *c; int count = 0; int nrDigits[] = {3, 5, 10, 20}; const char *max[] = { "255", "65535", "4294967295", "18446744073709551615" }; if (*text == '+') text++; if (*text == 0) return 0; if (*text == '0') { text++; while (*text == '0') text++; if (*text == 0) return 1; } c = text; while (*text) { if (*text >= '0' && *text <= '9') { text++; count++; } else return 0; } if (count < nrDigits[(intptr_t) constraintData]) return 1; if (count == nrDigits[(intptr_t) constraintData]) { if (strcmp (max[(intptr_t) constraintData], c) >= 0) { return 1; } } return 0; } static int unsignedIntTypesTCObjCmd ( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const UNUSED(objv[]) ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (1,1,"No arguments expected"); ADD_CONSTRAINT (sdata, sc) sc->constraint = unsignedIntTypesImpl; sc->constraintData = clientData; return TCL_OK; } static int intTypesImpl ( Tcl_Interp *UNUSED(interp), void *constraintData, char *text ) { char *c; int count = 0; int nrDigits[] = {3, 5, 10, 20}; const char *compare; const char *max[] = { "127", "32767", "2147483647", "9223372036854775807" }; const char *min[] = { "128", "32768", "2147483648", "9223372036854775808" }; if (*text == '-') { compare = min[(intptr_t) constraintData]; } else { compare = max[(intptr_t) constraintData]; } if (*text == '+' || *text == '-') text++; if (*text == 0) return 0; if (*text == '0') { text++; while (*text == '0') text++; if (*text == 0) return 1; } c = text; while (*text) { if (*text >= '0' && *text <= '9') { text++; count++; } else return 0; } if (count < nrDigits[(intptr_t) constraintData]) return 1; if (count == nrDigits[(intptr_t) constraintData]) { if (strcmp (compare, c) >= 0) return 1; } return 0; } static int intTypesTCObjCmd ( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const UNUSED(objv[]) ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (1,1,"No arguments expected"); ADD_CONSTRAINT (sdata, sc) sc->constraint = intTypesImpl; sc->constraintData = clientData; return TCL_OK; } static void setvarImplFree ( void *constraintData ) { FREE (constraintData); } static int setvarImpl ( Tcl_Interp *interp, void *constraintData, char *text ) { char *varName = (char *)constraintData; if (!Tcl_SetVar (interp, varName, text, TCL_LEAVE_ERR_MSG)) { return 0; } return 1; } static int setvarTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (2,2,""); ADD_CONSTRAINT (sdata, sc) sc->constraint = setvarImpl; sc->freeData = setvarImplFree; sc->constraintData = tdomstrdup (Tcl_GetString (objv[1])); return TCL_OK; } typedef struct { SchemaCP *cp; SchemaData *sdata; } WhitespaceTCData; static void whitespaceImplFree ( void *constraintData ) { WhitespaceTCData *wsdata = (WhitespaceTCData *) constraintData; FREE (wsdata); } static int whitespaceImplReplace ( Tcl_Interp *interp, void *constraintData, char *text ) { WhitespaceTCData *wsdata = (WhitespaceTCData *) constraintData; char *p, *c, *alloced; SchemaData *sdata; sdata = wsdata->sdata; p = text; c = sdata->wsbuf; alloced = sdata->wsbuf + sdata->wsbufLen; while (*p) { if (*p == '\t' || *p == '\n' || *p == '\r') { *c = ' '; } else { *c = *p; } c++; if (c == alloced) { sdata->wsbuf = REALLOC (sdata->wsbuf, 2 * sdata->wsbufLen); c = sdata->wsbuf + sdata->wsbufLen; sdata->wsbufLen *= 2; alloced = sdata->wsbuf + sdata->wsbufLen; } p++; } *c = '\0'; return checkText (interp, wsdata->cp, sdata->wsbuf); } static int whitespaceImplCollapse ( Tcl_Interp *interp, void *constraintData, char *text ) { WhitespaceTCData *wsdata = (WhitespaceTCData *) constraintData; char *p, *c, *alloced; SchemaData *sdata; sdata = wsdata->sdata; p = text; c = sdata->wsbuf; alloced = sdata->wsbuf + sdata->wsbufLen; while (SPACE(*p)) p++; while (*p) { if (SPACE (*p)) { *c = ' '; c++; if (c == alloced) { sdata->wsbuf = REALLOC (sdata->wsbuf, 2 * sdata->wsbufLen); c = sdata->wsbuf + sdata->wsbufLen; sdata->wsbufLen *= 2; alloced = sdata->wsbuf + sdata->wsbufLen; } p++; while (SPACE (*p)) p++; if (!*p) c--; } else { *c = *p; c++; if (c == alloced) { sdata->wsbuf = REALLOC (sdata->wsbuf, 2 * sdata->wsbufLen); c = sdata->wsbuf + sdata->wsbufLen; sdata->wsbufLen *= 2; alloced = sdata->wsbuf + sdata->wsbufLen; } p++; } } *c = '\0'; return checkText (interp, wsdata->cp, wsdata->sdata->wsbuf); } static int whitespaceTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaCP *cp; SchemaConstraint *sc; int type; WhitespaceTCData *wsdata; static const char *types[] = { "preserve", "replace", "collapse", NULL }; enum typeSyms { t_preserve, t_replace, t_collapse }; CHECK_TI checkNrArgs (3,3,"(\"preserve\"|\"replace\"|\"collapse\") " ""); if (Tcl_GetIndexFromObj (interp, objv[1], types, "type", 0, &type) != TCL_OK) { return TCL_ERROR; } cp = initSchemaCP (SCHEMA_CTYPE_CHOICE, NULL, NULL); cp->type = SCHEMA_CTYPE_TEXT; REMEMBER_PATTERN (cp) if (evalConstraints (interp, sdata, cp, objv[2]) != TCL_OK) { return TCL_ERROR; } if (type == t_preserve) { ADD_CONSTRAINT (sdata, sc) sc->constraint = tDOM_checkText; sc->constraintData = (void *)cp; return TCL_OK; } ADD_CONSTRAINT (sdata, sc) sc->freeData = whitespaceImplFree; if (sdata->wsbufLen == 0) { sdata->wsbuf = (char *) MALLOC (WHITESPACETC_BUFFER_LEN_INIT); sdata->wsbufLen = WHITESPACETC_BUFFER_LEN_INIT; } wsdata = TMALLOC (WhitespaceTCData); wsdata->sdata = sdata; wsdata->cp = cp; sc->constraintData = (void *)wsdata; if (type == t_replace) { sc->constraint = whitespaceImplReplace; } else { sc->constraint = whitespaceImplCollapse; } return TCL_OK; } static int notImpl ( Tcl_Interp *interp, void *constraintData, char *text ) { SchemaCP *cp = (SchemaCP *) constraintData; SchemaConstraint *sc; unsigned int i; /* Look also at checkText and oneOfImpl */ for (i = 0; i < cp->nc; i++) { sc = (SchemaConstraint *) cp->content[i]; if ((sc->constraint) (interp, sc->constraintData, text)) { return 0; } } return 1; } static int notTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaCP *cp; SchemaConstraint *sc; int rc; CHECK_TI checkNrArgs (2,2,"Expected: "); cp = initSchemaCP (SCHEMA_CTYPE_CHOICE, NULL, NULL); cp->type = SCHEMA_CTYPE_TEXT; REMEMBER_PATTERN (cp) rc = evalConstraints (interp, sdata, cp, objv[1]); if (rc == TCL_OK) { ADD_CONSTRAINT (sdata, sc) sc->constraint = notImpl; sc->constraintData = (void *)cp; return TCL_OK; } return TCL_ERROR; } static int durationImpl ( Tcl_Interp *UNUSED(interp), void *UNUSED(constraintData), char *text ) { /* PnYnMnDTnHnMnS */ int p, n, seen = 0, seenT = 0; char des[9] = " YMDTHMS"; if (*text == '-') { /* Negative duration is allowed */ text++; } if (*text != 'P') return 0; text++; p = 0; while (*text) { n = 0; while (*text >= '0' && *text <= '9') { n++; text++; } if (!*text) return 0; if (*text == '.') { if (p < 4 || !n) return 0; text++; if (!*text) return 0; /* Ensure at least one digit after . */ if (*text < '0' || *text > '9') return 0; text++; while (*text >= '0' && *text <= '9') text++; if (*text != 'S') return 0; text++; if (*text) return 0; return 1; } for (; p < 8; p++) { if (*text == des[p]) break; } if (p == 4) { if (n) return 0; seenT = 1; text++; if (!*text) return 0; continue; } else { if (!n) return 0; seen = 1; } if (p > 4 && !seenT) return 0; if (p == 8 || !seen) return 0; text++; } if (!p) return 0; return 1; } static int durationTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const UNUSED(objv[]) ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; CHECK_TI checkNrArgs (1,1,"No arguments expected"); ADD_CONSTRAINT (sdata, sc) sc->constraint = durationImpl; return TCL_OK; } static int lengthImpl ( Tcl_Interp *interp, void *constraintData, char *text ) { unsigned int len = 0, length = PTR2UINT(constraintData); int clen; while (*text != '\0') { clen = UTF8_CHAR_LEN (*text); if (!clen) { SetResult ("Invalid UTF-8 character"); return 0; } len++; if (len > length) return 0; text += clen; } if (len == length) return 1; return 0; } static int lengthTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; int len; CHECK_TI checkNrArgs (2,2,"Expected: "); if (Tcl_GetIntFromObj (interp, objv[1], &len) != TCL_OK) { SetResult ("Expected: "); return TCL_ERROR; } if (len < 0) { SetResult ("The length must be at least 0"); } ADD_CONSTRAINT (sdata, sc) sc->constraint = lengthImpl; sc->constraintData = UINT2PTR(len); return TCL_OK; } static int typeImpl ( Tcl_Interp *interp, void *constraintData, char *text ) { return checkText (interp, constraintData, text); } static int typeTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; Tcl_HashEntry *h; int hnew; SchemaCP *pattern = NULL; CHECK_TI checkNrArgs (2,2,"Expected: "); h = Tcl_CreateHashEntry (&sdata->textDef, Tcl_GetString (objv[1]), &hnew); if (hnew) { pattern = initSchemaCP (SCHEMA_CTYPE_CHOICE, NULL, NULL); pattern->type = SCHEMA_CTYPE_TEXT; REMEMBER_PATTERN (pattern) pattern->flags |= FORWARD_PATTERN_DEF; sdata->forwardPatternDefs++; Tcl_SetHashValue (h, pattern); } ADD_CONSTRAINT (sdata, sc) sc->constraint = typeImpl; sc->constraintData = Tcl_GetHashValue (h); return TCL_OK; } static const char *jsonTextTypes[] = { "NULL", "TRUE", "FALSE", "STRING", "NUMBER", NULL }; enum jsonTextType { jt_null, jt_true, jt_false, jt_string, jt_number }; typedef struct { enum jsonTextType type; SchemaData *sdata; } jsontypeTCData; static void jsontypeImplFree ( void *constraintData ) { jsontypeTCData *cd = (jsontypeTCData *) constraintData; FREE (cd); } static int jsontypeImpl ( Tcl_Interp *UNUSED(interp), void *constraintData, char *UNUSED(text) ) { jsontypeTCData *cd = (jsontypeTCData *) constraintData; domTextNode *textNode = cd->sdata->textNode; if (!textNode) { return 1; } switch (cd->type) { case jt_null: return textNode->info == JSON_NULL ? 1 : 0; case jt_true: return textNode->info == JSON_TRUE ? 1 : 0; case jt_false: return textNode->info == JSON_FALSE ? 1 : 0; case jt_string: return textNode->info == JSON_STRING ? 1 : 0; case jt_number: return textNode->info == JSON_NUMBER ? 1 : 0; } return 0; } static int jsontypeTCObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaConstraint *sc; int jsonType; jsontypeTCData *cd; CHECK_TI checkNrArgs (2,2,"Expected: "); if (Tcl_GetIndexFromObj (interp, objv[1], jsonTextTypes, "jsonType", 1, &jsonType) != TCL_OK) { return TCL_ERROR; } cd = TMALLOC (jsontypeTCData); cd->sdata = sdata; cd->type = jsonType; ADD_CONSTRAINT (sdata, sc) sc->constraint = jsontypeImpl; sc->constraintData = cd; sc->freeData = jsontypeImplFree; return TCL_OK; } static int dateObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { checkNrArgs (2,2,""); Tcl_SetObjResult (interp, Tcl_NewBooleanObj ( isodateImpl (interp, NULL, Tcl_GetString (objv[1])))); return TCL_OK; } static int dateTimeObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { checkNrArgs (2,2,""); Tcl_SetObjResult (interp, Tcl_NewBooleanObj ( isodateImpl (interp, (void *) 1, Tcl_GetString (objv[1])))); return TCL_OK; } static int timeObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { checkNrArgs (2,2,""); Tcl_SetObjResult (interp, Tcl_NewBooleanObj ( isodateImpl (interp, (void *) 2, Tcl_GetString (objv[1])))); return TCL_OK; } static int durationObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { checkNrArgs (2,2,""); Tcl_SetObjResult (interp, Tcl_NewBooleanObj ( durationImpl (interp, NULL, Tcl_GetString (objv[1])))); return TCL_OK; } void tDOM_DatatypesInit ( Tcl_Interp *interp ) { /* The text constraint commands */ Tcl_CreateObjCommand (interp,"tdom::schema::text::integer", integerTCObjCmd, (ClientData) 0, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::negativeInteger", integerTCObjCmd, (ClientData) 1, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::nonNegativeInteger", integerTCObjCmd, (ClientData) 2, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::nonPositiveInteger", integerTCObjCmd, (ClientData) 3, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::positiveInteger", integerTCObjCmd, (ClientData) 4, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::text::tcl", tclTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::text::fixed", fixedTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::text::enumeration", enumerationTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::text::match", matchTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::text::regexp", regexpTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::text::nmtoken", nmtokenTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::text::nmtokens", nmtokensTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::number", numberTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::boolean", booleanTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::date", dateTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::dateTime", dateTimeTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::time", timeTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::duration", durationTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::maxLength", maxLengthTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::minLength", minLengthTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::oneOf", oneOfTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::allOf", allOfTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::strip", stripTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::split", splitTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::id", idTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::idref", idrefTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::base64", base64TCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::key", keyTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::keyref", keyrefTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::name", nameTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::ncname", ncnameTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::qname", qnameTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::hexBinary", hexBinaryTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::unsignedByte", unsignedIntTypesTCObjCmd, (ClientData) 0, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::unsignedShort", unsignedIntTypesTCObjCmd, (ClientData) 1, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::unsignedInt", unsignedIntTypesTCObjCmd, (ClientData) 2, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::unsignedLong", unsignedIntTypesTCObjCmd, (ClientData) 3, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::byte", intTypesTCObjCmd, (ClientData) 0, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::short", intTypesTCObjCmd, (ClientData) 1, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::int", intTypesTCObjCmd, (ClientData) 2, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::long", intTypesTCObjCmd, (ClientData) 3, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::setvar", setvarTCObjCmd, (ClientData) 3, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::whitespace", whitespaceTCObjCmd, (ClientData) 3, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::not", notTCObjCmd, (ClientData) 3, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::length", lengthTCObjCmd, (ClientData) 3, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::type", typeTCObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::text::jsontype", jsontypeTCObjCmd, NULL, NULL); /* Exposed text type commands */ Tcl_CreateObjCommand (interp,"tdom::type::date", dateObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::type::dateTime", dateTimeObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::type::time", timeObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::type::duration", durationObjCmd, NULL, NULL); } #endif tdom-0.9.5-src/generic/domxslt.c0000644000175000017500000102770714703531020015226 0ustar rolfrolf/*---------------------------------------------------------------------------- | Copyright (c) 2000 Jochen Loewer (loewerj@hotmail.com) |----------------------------------------------------------------------------- | | A XSLT implementation for tDOM, according to the W3C | recommendation (16 Nov 1999). | See http://www.w3.org/TR/1999/REC-xslt-19991116 for details. | | | The contents of this file are subject to the Mozilla Public License | Version 2.0 (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, 2000 | Jochen Loewer. All Rights Reserved. | | Contributor(s): | Aug01 Rolf Ade xsl:include, xsl:import, xsl:apply-imports, | document() plus several bug fixes | | Fall/Winter 01 Rolf Ade rewrite of xsl:number, xsl:key/key(), | handling of top-level var/parameter, | plenty of fixes and enhancements all | over the place. | | 2001-2007 Rolf Ade All changes and enhancements. | | written by Jochen Loewer | June, 2000 | \---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- | Includes | \---------------------------------------------------------------------------*/ #include #include #include #include #include /* for hash tables */ #include #include #include /*---------------------------------------------------------------------------- | Defines | \---------------------------------------------------------------------------*/ #define XSLT_NAMESPACE "http://www.w3.org/1999/XSL/Transform" #define INITIAL_SIZE_FOR_KEYSETS 10 /* #define DEBUG */ /*---------------------------------------------------------------------------- | Debug Macros | \---------------------------------------------------------------------------*/ #ifdef DEBUG # define DBG(x) x #else # define DBG(x) #endif #define DBG(x) #define TRACE(x) DBG(fprintf(stderr,(x))) #define TRACE1(x,a) DBG(fprintf(stderr,(x),(a))) #define TRACE2(x,a,b) DBG(fprintf(stderr,(x),(a),(b))) #define TRACE3(x,a,b,c) DBG(fprintf(stderr,(x),(a),(b),(c))) #define TRACE4(x,a,b,c,d) DBG(fprintf(stderr,(x),(a),(b),(c),(d))) #define TRACE5(x,a,b,c,d,e) DBG(fprintf(stderr,(x),(a),(b),(c),(d),(e))) /*---------------------------------------------------------------------------- | Macros | \---------------------------------------------------------------------------*/ #define CHECK_RC if (rc < 0) return rc #define CHECK_RC1(x) if (rc < 0) {FREE((char*)(x)); return rc;} #define SET_TAG(t,n,s,v) if (strcmp(n,s)==0) { t->info = v; return v; } #define SETSCOPESTART xs->varFramesStack[xs->varFramesStackPtr].stop=1 #define SETPARAMDEF xs->varFramesStack[xs->varFramesStackPtr].stop=2 #if defined(_MSC_VER) # define STRCASECMP(a,b) stricmp (a,b) #else # define STRCASECMP(a,b) strcasecmp (a,b) #endif extern void printAst (int depth, ast t); /*-------------------------------------------------------------------------- | xsltTag | \-------------------------------------------------------------------------*/ typedef enum { unknown = 1, applyImports, applyTemplates, attribute, attributeSet, callTemplate, choose, comment, copy, copyOf, decimalFormat, element, fallback, forEach, xsltIf, import, include, key, message, namespaceAlias, number, output, otherwise, param, procinstr, preserveSpace, sort, stylesheet, stripSpace, text, template, transform, valueOf, variable, when, withParam } xsltTag; /*-------------------------------------------------------------------------- | xsltAttr | \-------------------------------------------------------------------------*/ typedef enum { a_caseorder = 1, a_count, a_dataType, a_disableOutputEscaping, a_doctypePublic, a_doctypeSystem, a_elements, a_encoding, a_format, a_from, a_href, a_lang, a_level, a_match, a_mediaType, a_method, a_mode, a_name, a_namespace, a_order, a_prio, a_select, a_space, a_terminate, a_test, a_use, a_useAttributeSets, a_value, a_groupingSeparator, a_groupingSize, a_decimalSeparator, a_infinity, a_minusSign, a_nan, a_percent, a_perMille, a_zeroDigit, a_digit, a_patternSeparator, a_version, a_excludeResultPrefixes, a_extensionElementPrefixes, a_stylesheetPrefix, a_resultPrefix, a_indent, a_omitXMLDeclaration, a_standalone, a_cdataSectionElements } xsltAttr; /*-------------------------------------------------------------------------- | xsltExclExtNS | \-------------------------------------------------------------------------*/ typedef struct xsltExclExtNS { char * uri; struct xsltExclExtNS * next; } xsltExclExtNS; /*-------------------------------------------------------------------------- | xsltSubDocs | \-------------------------------------------------------------------------*/ typedef struct xsltSubDoc { domDocument * doc; char * baseURI; Tcl_HashTable keyData; xsltExclExtNS * excludeNS; xsltExclExtNS * extensionNS; int fwCmpProcessing; int isStylesheet; int fixedXMLSource; int mustFree; struct xsltSubDoc * next; } xsltSubDoc; /*-------------------------------------------------------------------------- | xsltTemplate | \-------------------------------------------------------------------------*/ typedef struct xsltTemplate { char * match; const char * name; const char * nameURI; ast ast; const char * mode; const char * modeURI; double prio; domNode * content; double precedence; ast freeAst; xsltSubDoc * sDoc; struct xsltTemplate *next; } xsltTemplate; /*-------------------------------------------------------------------------- | xsltAttrSet | \-------------------------------------------------------------------------*/ typedef struct xsltAttrSet { const char * name; const char * uri; domNode * content; int inUse; struct xsltAttrSet *next; } xsltAttrSet; /*-------------------------------------------------------------------------- | xsltNodeSet | \-------------------------------------------------------------------------*/ typedef struct xsltNodeSet { domNode **nodes; domLength nr_nodes; domLength allocated; } xsltNodeSet; /*-------------------------------------------------------------------------- | xsltKeyInfo | \-------------------------------------------------------------------------*/ typedef struct xsltKeyInfo { domNode * node; char * match; ast matchAst; char * use; ast useAst; struct xsltKeyInfo * next; } xsltKeyInfo; /*-------------------------------------------------------------------------- | xsltVariable | \-------------------------------------------------------------------------*/ typedef struct xsltVariable { const char * name; const char * uri; domNode * node; xpathResultSet rs; int active; } xsltVariable; /*-------------------------------------------------------------------------- | xsltVarFrame | \-------------------------------------------------------------------------*/ typedef struct xsltVarFrame { xsltVariable * vars; int polluted; int nrOfVars; int varStartIndex; int stop; } xsltVarFrame; /*-------------------------------------------------------------------------- | xsltTopLevelVar | \-------------------------------------------------------------------------*/ typedef struct xsltTopLevelVar { domNode * node; char * name; int isParameter; double precedence; } xsltTopLevelVar; /*-------------------------------------------------------------------------- | xsltVarInProcess | \-------------------------------------------------------------------------*/ typedef struct xsltVarInProcess { char *name; struct xsltVarInProcess *next; } xsltVarInProcess; /*-------------------------------------------------------------------------- | xsltDecimalFormat | \-------------------------------------------------------------------------*/ typedef struct xsltDecimalFormat { char * name; char * uri; Tcl_UniChar decimalSeparator; Tcl_UniChar groupingSeparator; char * infinity; Tcl_UniChar minusSign; char * NaN; Tcl_UniChar percent; Tcl_UniChar perMille; Tcl_UniChar zeroDigit; Tcl_UniChar digit; Tcl_UniChar patternSeparator; struct xsltDecimalFormat * next; } xsltDecimalFormat; /*-------------------------------------------------------------------------- | xsltWSInfo | \-------------------------------------------------------------------------*/ typedef struct xsltWSInfo { int hasData; int stripAll; double wildcardPrec; Tcl_HashTable stripTokens; Tcl_HashTable preserveTokens; } xsltWSInfo; typedef struct xsltNSAlias { char *fromUri; char *toUri; double precedence; struct xsltNSAlias *next; } xsltNSAlias; /*-------------------------------------------------------------------------- | xsltState | \-------------------------------------------------------------------------*/ typedef struct { xsltTemplate * templates; int nestedApplyTemplates; int maxNestedApplyTemplates; Tcl_HashTable namedTemplates; Tcl_HashTable isElementTpls; xsltWSInfo wsInfo; domNode * xmlRootNode; domDocInfo doctype; int indentOutput; domDocument * resultDoc; domNode * lastNode; xsltVarFrame * varFramesStack; int varFramesStackPtr; int varFramesStackLen; xsltVariable * varStack; int varStackPtr; int varStackLen; xsltAttrSet * attrSets; Tcl_HashTable xpaths; Tcl_HashTable pattern; Tcl_HashTable formats; Tcl_HashTable topLevelVars; Tcl_HashTable keyInfos; xsltNSAlias * nsAliases; int nsUniqeNr; xsltVarInProcess * varsInProcess; xpathCBs cbs; xpathFuncCallback orig_funcCB; void * orig_funcClientData; xsltMsgCB xsltMsgCB; void * xsltMsgClientData; xsltDecimalFormat * decimalFormats; domNode * current; xsltSubDoc * subDocs; xsltSubDoc * currentSubDoc; xsltTemplate * currentTplRule; domNode * currentXSLTNode; domDocument * xsltDoc; } xsltState; typedef enum { latin_number, latin_upper, latin_lower, roman_upper, roman_lower } xsltNumberingType; /*-------------------------------------------------------------------------- | xsltNumberFormatToken | \-------------------------------------------------------------------------*/ typedef struct { xsltNumberingType type; int minlength; char *sepStart; int sepLen; } xsltNumberFormatToken; /*-------------------------------------------------------------------------- | xsltNumberFormat | \-------------------------------------------------------------------------*/ typedef struct { char *formatStr; int prologLen; xsltNumberFormatToken *tokens; int maxtokens; char *epilogStart; int epilogLen; } xsltNumberFormat; /*-------------------------------------------------------------------------- | Prototypes | \-------------------------------------------------------------------------*/ static int ApplyTemplates ( xsltState *xs, xpathResultSet *context, domNode *currentNode, domLength currentPos, domNode *actionNode, xpathResultSet *nodeList, const char *mode, const char *modeURI, char **errMsg); static int ApplyTemplate ( xsltState *xs, xpathResultSet *context, domNode *currentNode, domNode *exprContext, domLength currentPos, const char *mode, const char *modeURI, char **errMsg); static int ExecActions (xsltState *xs, xpathResultSet *context, domNode *currentNode, domLength currentPos, domNode *actionNode, char **errMsg); static domDocument * getExternalDocument (Tcl_Interp *interp, xsltState *xs, domDocument *xsltDoc, const char *baseURI, const char *href, int isStylesheet, int fixedXMLSource, char **errMsg); #ifdef DEBUG /*---------------------------------------------------------------------------- | printXML | \---------------------------------------------------------------------------*/ static void printXML (domNode *node, int level, int maxlevel) { domTextNode *tnode; domProcessingInstructionNode *pi; char tmp[80]; int i, l, n; n = 0; while (node) { for (i=0;inodeType == ELEMENT_NODE) { if (node->firstChild && node->firstChild->nodeType == TEXT_NODE) { tnode = (domTextNode*)node->firstChild; l = tnode->valueLength; if (l > 30) l = 30; memmove(tmp, tnode->nodeValue, l); tmp[l] = '\0'; fprintf(stderr, "<%s/domNode0x%p> '%s'\n", node->nodeName, node, tmp); } else { tmp[0] = '\0'; if ((level>=maxlevel) && (node->firstChild)) { strcpy( tmp, "..."); } fprintf(stderr, "<%s/domNode0x%p> %s\n", node->nodeName, node, tmp); } if (levelfirstChild) printXML(node->firstChild, level+1, maxlevel); } } if (node->nodeType == TEXT_NODE) { tnode = (domTextNode*)node; l = tnode->valueLength; if (l > 70) l = 70; memmove(tmp, tnode->nodeValue, l); tmp[l] = '\0'; fprintf(stderr, "'%s'\n", tmp); } if (node->nodeType == COMMENT_NODE) { tnode = (domTextNode*)node; l = tnode->valueLength; memmove (tmp, "", 3); tmp[7+l] = '\0'; fprintf(stderr, "'%s'\n", tmp); } if (node->nodeType == PROCESSING_INSTRUCTION_NODE) { pi = (domProcessingInstructionNode*)node; l = pi->targetLength; if (l > 70) l = 70; memmove(tmp, pi->targetValue, l); tmp[l] = '\0'; fprintf(stderr, "dataLength; if (l > 70) l = 70; memmove(tmp, pi->dataValue, l); tmp[l] = '\0'; fprintf(stderr, "%s?>\n", tmp); } node = node->nextSibling; n++; if (n>8) { fprintf(stderr, "...\n"); return; } } } #endif /* #ifdef DEBUG */ /*---------------------------------------------------------------------------- | reportError | \---------------------------------------------------------------------------*/ static void reportError ( domNode * node, char * str, char ** errMsg) { Tcl_DString dStr; char buffer[1024]; const char *baseURI; XML_Size line, column; XML_Index byteIndex; Tcl_DStringInit (&dStr); baseURI = findBaseURI (node); if (baseURI) { Tcl_DStringAppend (&dStr, "In entity ", 10); Tcl_DStringAppend (&dStr, baseURI, -1); } if (node->nodeFlags & HAS_LINE_COLUMN) { domGetLineColumn (node, &line, &column, &byteIndex); sprintf (buffer, " at line %" TDOM_LS_MODIFIER "d, column %" TDOM_LS_MODIFIER "d:\n", line, column); Tcl_DStringAppend (&dStr, buffer, -1); Tcl_DStringAppend (&dStr, str, -1); } else { if (baseURI) Tcl_DStringAppend (&dStr, ": ", 2); Tcl_DStringAppend (&dStr, str, -1); } if (*errMsg) FREE (*errMsg); *errMsg = tdomstrdup (Tcl_DStringValue (&dStr)); Tcl_DStringFree (&dStr); } /*---------------------------------------------------------------------------- | getAttr | \---------------------------------------------------------------------------*/ static char * getAttr ( domNode *node, char *name, xsltAttr attrTypeNo ) { domAttrNode *attr; attr = node->firstAttr; while (attr) { if (attr->info == (unsigned int)attrTypeNo) { return attr->nodeValue; } else if (attr->info == 0) { if (strcmp ((char*)attr->nodeName, name)==0) { attr->info = (unsigned int)attrTypeNo; return attr->nodeValue; } } attr = attr->nextSibling; } return NULL; } /*---------------------------------------------------------------------------- | getTag | \---------------------------------------------------------------------------*/ static xsltTag getTag ( domNode *node ) { const char *name; if (node->nodeType != ELEMENT_NODE) { node->info = (int)unknown; return unknown; } if (node->info != 0) { return (xsltTag)node->info; } name = domNamespaceURI(node); if ((name == NULL) || (strcmp(name, XSLT_NAMESPACE)!=0)) { node->info = (int)unknown; return unknown; } name = domGetLocalName(node->nodeName); switch (*name) { case 'a': SET_TAG(node,name,"apply-imports", applyImports); SET_TAG(node,name,"apply-templates",applyTemplates); SET_TAG(node,name,"attribute", attribute); SET_TAG(node,name,"attribute-set", attributeSet); break; case 'c': SET_TAG(node,name,"call-template", callTemplate); SET_TAG(node,name,"choose", choose); SET_TAG(node,name,"comment", comment); SET_TAG(node,name,"copy", copy); SET_TAG(node,name,"copy-of", copyOf); break; case 'd': SET_TAG(node,name,"decimal-format", decimalFormat); break; case 'e': SET_TAG(node,name,"element", element); break; case 'f': SET_TAG(node,name,"fallback", fallback); SET_TAG(node,name,"for-each", forEach); break; case 'i': SET_TAG(node,name,"if", xsltIf); SET_TAG(node,name,"import", import); SET_TAG(node,name,"include", include); break; case 'k': SET_TAG(node,name,"key", key); break; case 'm': SET_TAG(node,name,"message", message); break; case 'n': SET_TAG(node,name,"namespace-alias",namespaceAlias); SET_TAG(node,name,"number", number); break; case 'o': SET_TAG(node,name,"output", output); SET_TAG(node,name,"otherwise", otherwise); break; case 'p': SET_TAG(node,name,"param", param); SET_TAG(node,name,"preserve-space", preserveSpace); SET_TAG(node,name,"processing-instruction", procinstr); break; case 's': SET_TAG(node,name,"sort", sort); SET_TAG(node,name,"stylesheet", stylesheet); SET_TAG(node,name,"strip-space", stripSpace); break; case 't': SET_TAG(node,name,"template", template); SET_TAG(node,name,"text", text); SET_TAG(node,name,"transform", transform); break; case 'v': SET_TAG(node,name,"value-of", valueOf); SET_TAG(node,name,"variable", variable); break; case 'w': SET_TAG(node,name,"when", when); SET_TAG(node,name,"with-param", withParam); break; } node->info = (int)unknown; return unknown; } /*---------------------------------------------------------------------------- | xsltPopVarFrame | \---------------------------------------------------------------------------*/ static void xsltPopVarFrame ( xsltState * xs ) { int i; xsltVarFrame *frame; if (xs->varFramesStackPtr >= 0) { frame = &xs->varFramesStack[xs->varFramesStackPtr]; if (frame->nrOfVars) { for (i = frame->varStartIndex; i < frame->varStartIndex + frame->nrOfVars; i++) { xpathRSFree (&(&xs->varStack[i])->rs); } } xs->varStackPtr -= frame->nrOfVars; xs->varFramesStackPtr--; } } /*---------------------------------------------------------------------------- | xsltPushVarFrame | \---------------------------------------------------------------------------*/ static void xsltPushVarFrame ( xsltState * xs ) { xsltVarFrame * frame; xs->varFramesStackPtr++; if (xs->varFramesStackPtr >= xs->varFramesStackLen) { xs->varFramesStack = (xsltVarFrame *) REALLOC ((char*)xs->varFramesStack, sizeof (xsltVarFrame) * 2 * xs->varFramesStackLen); xs->varFramesStackLen *= 2; } frame = &(xs->varFramesStack[xs->varFramesStackPtr]); frame->polluted = 0; frame->nrOfVars = 0; frame->varStartIndex = -1; frame->stop = 0; } /*---------------------------------------------------------------------------- | xsltAddExternalDocument | \---------------------------------------------------------------------------*/ static int xsltAddExternalDocument ( xsltState * xs, const char * baseURI, const char * str, int fixedXMLSource, xpathResultSet * result, char ** errMsg ) { xsltSubDoc * sdoc; domDocument * extDocument; int found; DBG( fprintf (stderr, "xsltAddExternalDocument: baseURI '%s'\n", baseURI); fprintf (stderr, "xsltAddExternalDocument: systemID '%s'\n", str); ) found = 0; sdoc = xs->subDocs; if (str) { while (sdoc) { if (!sdoc->isStylesheet && sdoc->baseURI && strcmp (sdoc->baseURI, str)==0) { rsAddNode (result, sdoc->doc->rootNode); found = 1; break; } sdoc = sdoc->next; } } if (!found) { if (!xs->xsltDoc->extResolver) { *errMsg = tdomstrdup("Need resolver script for document() calls. " "(Use \"-externalentitycommand\")"); return -1; } extDocument = getExternalDocument ( (Tcl_Interp*)xs->orig_funcClientData, xs, xs->xsltDoc, baseURI, str, 0, fixedXMLSource, errMsg); if (extDocument) { rsAddNode (result, extDocument->rootNode); } else { return -1; } } return found; } /*---------------------------------------------------------------------------- | xsltNumberFormatTokenizer | \---------------------------------------------------------------------------*/ static xsltNumberFormat* xsltNumberFormatTokenizer ( xsltState *xs, char *formatStr, char **errMsg ) { char *p; int hnew, clen, nrOfTokens = 0; Tcl_HashEntry *h; xsltNumberFormat *format; /* TODO: make it l18n aware. */ h = Tcl_CreateHashEntry (&xs->formats, formatStr, &hnew); if (!hnew) { return (xsltNumberFormat *) Tcl_GetHashValue (h); } else { format = (xsltNumberFormat *)MALLOC(sizeof (xsltNumberFormat)); memset (format, 0 , sizeof (xsltNumberFormat)); format->tokens = (xsltNumberFormatToken *) MALLOC(sizeof (xsltNumberFormatToken) * 20); memset (format->tokens, 0, sizeof (xsltNumberFormatToken) * 20); format->maxtokens = 20; Tcl_SetHashValue (h, format); format->formatStr = p = Tcl_GetHashKey (&(xs->formats), h); } while (*p) { clen = UTF8_CHAR_LEN(*p); if (!clen) { reportError (xs->currentXSLTNode, "xsl:number: UTF-8 form of" " character longer than 4 Byte", errMsg); return NULL; } if (clen > 1) { /* hack: skip over multibyte chars - this may be wrong */ format->prologLen += clen; p += clen; continue; } if (isalnum((unsigned char)*p)) break; format->prologLen++; p++; } format->tokens[0].minlength = 1; if (!*p) { format->tokens[0].type = latin_number; return format; } #define addSeperator \ p++; \ if (*p) { \ format->tokens[nrOfTokens].sepStart = p; \ } \ while (*p) { \ clen = UTF8_CHAR_LEN(*p); \ if (!clen) { \ reportError (xs->currentXSLTNode, "xsl:number: UTF-8 form of character longer than 4 Byte", errMsg); \ return NULL; \ } \ if (clen > 1) { \ /* hack: skip over multibyte chars - this may be wrong */ \ format->tokens[nrOfTokens].sepLen += clen; \ p += clen; \ continue; \ } \ if (isalnum((unsigned char)*p)) break; \ format->tokens[nrOfTokens].sepLen++; \ p++; \ } \ if (*p) { \ if (format->tokens[nrOfTokens].sepLen == 0) goto wrongSyntax; \ } \ nrOfTokens++; \ if (nrOfTokens == format->maxtokens) { \ format->tokens = (xsltNumberFormatToken *) REALLOC ((char *)format->tokens, sizeof (xsltNumberFormatToken) * format->maxtokens * 2); \ format->maxtokens *= 2; \ } \ format->tokens[nrOfTokens].minlength = 1; \ continue; while (*p) { if (*p == '0') { format->tokens[nrOfTokens].minlength++; p++; continue; } if (*p == '1') { format->tokens[nrOfTokens].type = latin_number; addSeperator; } if (*p == 'A') { if (isalnum((unsigned char)*(p+1))) goto wrongSyntax; format->tokens[nrOfTokens].type = latin_upper; addSeperator; } if (*p == 'a') { if (isalnum((unsigned char)*(p+1))) goto wrongSyntax; format->tokens[nrOfTokens].type = latin_lower; addSeperator; } if (*p == 'I') { if (isalnum((unsigned char)*(p+1))) goto wrongSyntax; format->tokens[nrOfTokens].type = roman_upper; addSeperator; } if (*p == 'i') { if (isalnum((unsigned char)*(p+1))) goto wrongSyntax; format->tokens[nrOfTokens].type = roman_lower; addSeperator; } format->tokens[nrOfTokens].type = latin_number; while (isalnum((unsigned char)*(p+1))) { p++; } addSeperator; } format->epilogStart = format->tokens[nrOfTokens-1].sepStart; format->tokens[nrOfTokens-1].sepStart = NULL; format->epilogLen = format->tokens[nrOfTokens-1].sepLen; format->tokens[nrOfTokens-1].sepLen = 0; return format; wrongSyntax: reportError (xs->currentXSLTNode, "xsl:number: Wrong syntax in" " format attribute", errMsg); return NULL; } /*---------------------------------------------------------------------------- | formatValue | \---------------------------------------------------------------------------*/ static void formatValue ( xsltNumberFormat *f, int *useFormatToken, domLength value, Tcl_DString *str, char *groupingSeparator, long groupingSize, int addSeparater ) { domLength len, fulllen, gslen, m, i; int upper = 0, e, b, v, z; char tmp[80], *pt; Tcl_DString tmp1; static struct { const char *digit; const char *ldigit; int value; } RomanDigit[] = { { "M" , "m" , 1000, }, { "CM", "cm", 900, }, { "D" , "d" , 500, }, { "CD", "cd", 400, }, { "C" , "c" , 100, }, { "XC", "xc", 90, }, { "L" , "l" , 50, }, { "XL", "xl", 40, }, { "X" , "x" , 10, }, { "IX", "ix", 9, }, { "V" , "v" , 5, }, { "IV", "iv", 4, }, { "I" , "i" , 1 } }; switch (f->tokens[*useFormatToken].type) { case latin_number: sprintf (tmp, "%" TCL_SIZE_MODIFIER "d", value); fulllen = len = (domLength)strlen (tmp); if (f->tokens[*useFormatToken].minlength > fulllen) { fulllen = f->tokens[*useFormatToken].minlength; } if (groupingSeparator) { gslen = (domLength)strlen (groupingSeparator); Tcl_DStringInit (&tmp1); if (len < f->tokens[*useFormatToken].minlength) { for (i = 0; i < f->tokens[*useFormatToken].minlength - len; i++) { Tcl_DStringAppend (&tmp1, "0", 1); } } Tcl_DStringAppend (&tmp1, tmp, len); pt = Tcl_DStringValue (&tmp1); len = Tcl_DStringLength (&tmp1); m = len % groupingSize; if (m) { Tcl_DStringAppend (str, pt, m); pt += m; } i = len - m; while (i) { if (i != len) { Tcl_DStringAppend (str, groupingSeparator, gslen); } Tcl_DStringAppend (str, pt, groupingSize); pt += groupingSize; i -= groupingSize; } Tcl_DStringFree (&tmp1); } else { for (i = 0; i < fulllen - len; i++) { Tcl_DStringAppend (str, "0", 1); } Tcl_DStringAppend (str, tmp, len); } goto appendSeperator; break; case latin_upper: upper = 1; /* fall through */ case latin_lower: /* Home grown algorithm. (And I'm really not happy with it.) Please let rolf@pointsman.de know how to do this better / faster / more clever. */ if (value <= 0) { /* Hm, zero can't be expressed with letter sequences... What to do? One of the several cases, not mentioned by the spec. */ /* fall back to latin numbers */ sprintf (tmp, "%" TCL_SIZE_MODIFIER "d", value); break; } e = 1; m = b = 26; while (value > m) { b *= 26; m += b; e++; } m -= b; value -= m; for (i = 0; i < e; i++) { b /= 26; z = (int)(value / b); value = value - z*b; if (i < e -1) { if (value == 0) { value += b; } else { z++; } } if (upper) { tmp[i] = 64+z; } else { tmp[i] = 96+z; } } tmp[i] = '\0'; break; case roman_upper: upper = 1; /* fall through */ case roman_lower: /* Algorithm follows the idear of the converter at http://mini.net/cgi-bin/wikit/1749.html */ /* Side note: There exists a rarely used roman notation to express figures up to a few millions. Does somebody really need this? */ if (value > 3999 || value <= 0) { /* fall back to latin numbers */ sprintf (tmp, "%" TCL_SIZE_MODIFIER "d", value); break; } if (value == 0) { /* what to do with zero??? */ sprintf (tmp, "%d", 0); break; } v = 0; tmp[0] = '\0'; while (value > 0) { while (value >= RomanDigit[v].value) { if (upper) { strcat(tmp, RomanDigit[v].digit); } else { strcat(tmp, RomanDigit[v].ldigit); } value -= RomanDigit[v].value; } v++; } break; default: sprintf (tmp, "%" TCL_SIZE_MODIFIER "d", value); break; } len = (domLength)strlen (tmp); Tcl_DStringAppend (str, tmp, len); appendSeperator: if (addSeparater) { if (f->tokens[*useFormatToken].sepStart) { Tcl_DStringAppend (str, f->tokens[*useFormatToken].sepStart, f->tokens[*useFormatToken].sepLen); *useFormatToken += 1; } else { if (*useFormatToken > 0) { Tcl_DStringAppend (str, f->tokens[*useFormatToken-1].sepStart, f->tokens[*useFormatToken-1].sepLen); } else { /* insert default separator '.' */ Tcl_DStringAppend (str, ".", 1); } } } return; } /*---------------------------------------------------------------------------- | xsltFormatNumber | \---------------------------------------------------------------------------*/ static int addCurrencySymbol ( Tcl_UniChar *p, Tcl_UniChar *result, int *i ) { Tcl_DString dStr; Tcl_UniChar *p1, *currencySymbol; int move = 0; struct lconv *lc; setlocale (LC_MONETARY, ""); lc = localeconv(); Tcl_DStringInit (&dStr); if (*(p+1) == 0xa4) { if (lc->int_curr_symbol[0] == '\0') { currencySymbol = Tcl_UtfToUniCharDString ("$", -1, &dStr); } else { currencySymbol = Tcl_UtfToUniCharDString (lc->int_curr_symbol, -1, &dStr); } move = 1; } else { if (lc->currency_symbol[0] == '\0') { currencySymbol = Tcl_UtfToUniCharDString ("$", -1, &dStr); } else { currencySymbol = Tcl_UtfToUniCharDString (lc->currency_symbol, -1, &dStr); } } p1 = currencySymbol; while (*p1 && (*i < 79)) { result[(*i)++] = *p1; p1++; } Tcl_DStringFree (&dStr); return move; } static int xsltFormatNumber ( double number, char * formatStr, xsltDecimalFormat * df, char ** resultStr, domLength * resultLen, char ** errMsg ) { Tcl_UniChar prefix1[800], prefix2[800], suffix1[800], suffix2[800]; Tcl_UniChar save = '\0', save1, t, *prefix, *suffix, n[800], f[800]; Tcl_UniChar uniCharNull = '\0'; char stmp[240], ftmp[80], *tstr; char wrongFormat[] = "Unable to interpret format pattern."; domLength l, zl, gLen; int i, j, k, g, nZero, fHash, fZero, isNeg; int prefixMinux, percentMul = 0, perMilleMul = 0; Tcl_DString dStr, s; Tcl_UniChar *format, *negformat = NULL, *p, *p1; DBG(Tcl_DString bStr;) DBG(fprintf(stderr, "number: '%f'\nformatStr='%s' \n", number, formatStr);) prefix1[0] = '\0'; prefix2[0] = '\0'; suffix1[0] = '\0'; suffix2[0] = '\0'; n[0] = '\0'; f[0] = '\n'; prefix = NULL; suffix = NULL; Tcl_DStringInit (&s); Tcl_DStringInit (&dStr); if (number < 0.0) { isNeg = 1; number *= -1.0; } else if (number == 0.0) { sprintf (stmp, "%f", number); if (stmp[0] == '-') isNeg = 1; else isNeg = 0; } else { isNeg = 0; } format = Tcl_UtfToUniCharDString (formatStr, -1, &dStr); p = format; while (*p) { if (*p == df->patternSeparator) { save = *p; *p = '\0'; negformat = ++p; break; } p++; } /* Check for more than one patternSeparator in the formatStr */ while (*p) { if (*p == df->patternSeparator) { *errMsg = tdomstrdup("More than one patternSeparator in the pattern"); goto xsltFormatNumberError; } p++; } p = format; i = 0; while (*p && (*p!=df->zeroDigit) && (*p!=df->digit) && (*p!=df->groupingSeparator) && (*p!=df->decimalSeparator)) { if (*p == df->percent) (percentMul = 1); else if (*p == df->perMille) (perMilleMul = 1); if (i<79) { if (*p == 0xa4) { p += addCurrencySymbol (p, prefix1, &i); } else { prefix1[i++] = *p; } } p++; } prefix1[i] = '\0'; nZero = fHash = fZero = 0; gLen = -2222; while (*p) { if (*p==df->digit) { if (nZero) { *errMsg = tdomstrdup(wrongFormat); goto xsltFormatNumberError; } } else if (*p==df->zeroDigit) { nZero++; } else if (*p==df->groupingSeparator) { gLen=-1; } else break; p++; gLen++; } if (*p && (*p==df->decimalSeparator)) { p++; while (*p && (*p==df->zeroDigit)) { p++; fZero++; } while (*p && (*p==df->digit)) { p++; fHash++; } } i = 0; while (*p) { /* Check for more than one decimalSeparator */ if (*p == df->decimalSeparator) { *errMsg = tdomstrdup("More than one decimalSeparator in subpattern"); goto xsltFormatNumberError; } /* Check for groupingSeparator after decimalSeparator */ if (*p == df->groupingSeparator) { *errMsg = tdomstrdup("GroupingSeparator after decimalSeparator"); goto xsltFormatNumberError; } if (*p == df->percent) (percentMul = 1); else if (*p == df->perMille) (perMilleMul = 1); if (i<79) { if (*p == 0xa4) { p += addCurrencySymbol (p, suffix1, &i); } else { suffix1[i++] = *p; } } p++; } suffix1[i] = '\0'; if (save) *p = save; if (isNeg && negformat) { /* Only prefix and suffix are taken from the second format string */ percentMul = 0; perMilleMul = 0; p++; i = 0; while (*p && *p!=df->zeroDigit && *p!=df->digit && *p!=df->groupingSeparator && *p!=df->decimalSeparator) { if (*p == df->percent) (percentMul = 1); else if (*p == df->perMille) (perMilleMul = 1); if (i<79) { if (*p == 0xa4) { p += addCurrencySymbol (p, prefix2, &i); } else { prefix2[i++] = *p; } } p++; } prefix2[i] = '\0'; while (*p && ((*p==df->zeroDigit) || (*p==df->digit) || (*p==df->groupingSeparator) || (*p==df->decimalSeparator))) p++; i = 0; while (*p) { if (*p == df->percent) (percentMul = 1); else if (*p == df->perMille) (perMilleMul = 1); if (i<79) { if (*p == 0xa4) { p += addCurrencySymbol (p, suffix2, &i); } else { suffix2[i++] = *p; } } p++; } suffix2[i] = '\0'; } if (isNeg) { if (negformat) { prefixMinux = 1; p = prefix1; p1 = prefix2; while (prefixMinux) { if (*p != *p1) { prefixMinux = 0; break; } if (*p == 0) break; p++; p1++; } if (prefixMinux) { p = suffix1; p1 = suffix2; while (prefixMinux) { if (*p != *p1) { prefixMinux = 0; break; } if (*p == 0) break; p++; p1++; } } prefix = prefix2; suffix = suffix2; } else { prefixMinux = 1; prefix = prefix1; suffix = suffix1; } if (prefixMinux) { i = 0; save = prefix[0]; prefix[0] = df->minusSign; while (i < 79) { i++; save1 = prefix[i]; prefix[i] = save; if (save == 0) break; save = save1; } if (i == 79) prefix[79] = '\0'; } } else { prefix = prefix1; suffix = suffix1; } DBG( Tcl_DStringInit (&dbStr); fprintf (stderr, "prefix: '%s' ", Tcl_UniCharToUtfDString(prefix, Tcl_UniCharLen (prefix), &dbStr)); Tcl_DStringFree (&dbStr); Tcl_DStringInit (&dbStr); fprintf (stderr, "suffix: '%s'\n", Tcl_UniCharToUtfDString(suffix, Tcl_UniCharLen (suffix), &dbStr)); Tcl_DStringFree (&dbStr); ) if (percentMul) { number *= 100.0; } else if (perMilleMul) { number *= 1000.0; } if (fHash + fZero == 0) { i = (int) (number+0.5); } else { i = (int) number; /* format fraction part */ DBG(fprintf(stderr, "formatting fraction part: '%f', fZero+fHash: '%d'\n", number - i, fZero+fHash);) sprintf(ftmp,"%.*f", fZero+fHash, number -i); DBG(fprintf(stderr, "raw formatted fraction part: '%s'\n", ftmp);) if (ftmp[0] == '1') { i++; } } DBG(fprintf(stderr,"normal part nZero=%d i=%d glen=%d\n", nZero, i, gLen);) /* fill in grouping char */ if (gLen > 0) { sprintf(stmp,"%0*d", nZero, i); l = (domLength)strlen (stmp); for (j = 0; j < l; j++) { t = df->zeroDigit + stmp[j] - 48; Tcl_DStringAppend (&s, (char*)&t, sizeof (Tcl_UniChar)); } DBG( Tcl_DStringInit(&dbStr); fprintf (stderr, "'%s' ---> ..\n", stmp); fprintf(stderr,"s='%s' isNeg=%d'\n", Tcl_UniCharToUtfDString ( (Tcl_UniChar*)Tcl_DStringValue (&s), Tcl_UniCharLen((Tcl_UniChar*)Tcl_DStringValue(&s)), &dStr ), isNeg); Tcl_DStringFree (&dbStr); ) zl = l + ((l-1) / gLen); DBG(fprintf(stderr, "l=%d zl=%d \n", l, zl);) n[zl--] = '\0'; p = (Tcl_UniChar*)Tcl_DStringValue (&s) + l - 1; g = 0; while (zl>=0) { g++; n[zl--] = *p--; if ((g == gLen) && (zl>=1)) { n[zl--] = df->groupingSeparator; g = 0; } } Tcl_DStringSetLength (&s, 0); DBG( Tcl_DStringInit (&dbStr); fprintf(stderr,"s='%s' --> ", Tcl_UniCharToUtfDString ( (Tcl_UniChar*)Tcl_DStringValue (&s), Tcl_UniCharLen((Tcl_UniChar*)Tcl_DStringValue(&s)), &dStr)); Tcl_DStringFree (&dbStr); Tcl_DStringInit (&dbStr); fprintf(stderr,"n='%s'\n", Tcl_UniCharToUtfDString (n, Tcl_UniCharLen (n), &dbStr)); Tcl_DStringFree (&dbStr); ) } else { sprintf(stmp,"%0*d", nZero, i); l = (domLength)strlen (stmp); for (j = 0; j < l; j++) { n[j] = df->zeroDigit + (int) stmp[j] - 48; } n[l] = '\0'; DBG( Tcl_DStringInit (&dbStr); fprintf(stderr,"n='%s'\n", Tcl_UniCharToUtfDString(n, Tcl_UniCharLen (n), &dbStr)); Tcl_DStringFree (&dbStr); ) } DBG(fprintf(stderr, "number=%f fHash=%d fZero=%d \n", number, fHash, fZero);) if ((fHash+fZero) > 0) { l = (domLength)strlen(ftmp); while (l>0 && fHash>0) { /* strip not need 0's */ if (ftmp[l-1] == '0') { ftmp[l-1]='\0'; l--; fHash--; } else { break; } } k = 0; if ((number - i != 0.0) || (fZero > 0)) { while (ftmp[k] != '.') k++; k++; for (j = k ; j < l; j++) { f[j] = df->zeroDigit + (int) ftmp[j] - 48; } f[l] = '\0'; } DBG(fprintf(stderr, "f='%s'\n", f);) if (prefix) { Tcl_DStringAppend (&s, (char*) prefix, Tcl_UniCharLen (prefix) * sizeof(Tcl_UniChar)); } Tcl_DStringAppend (&s, (char*) n, Tcl_UniCharLen (n) * sizeof(Tcl_UniChar)); if (k) { Tcl_DStringAppend (&s, (char*)&df->decimalSeparator, sizeof (Tcl_UniChar)); Tcl_DStringAppend (&s, (char*)&(f[k]), Tcl_UniCharLen (&(f[k])) * sizeof(Tcl_UniChar)); } if (suffix) { Tcl_DStringAppend (&s, (char *) suffix, Tcl_UniCharLen (suffix) * sizeof(Tcl_UniChar)); } Tcl_DStringAppend (&s, (char *)&uniCharNull, sizeof (Tcl_UniChar)); } else { if (prefix) { Tcl_DStringAppend (&s, (char*) prefix, Tcl_UniCharLen (prefix) * sizeof(Tcl_UniChar)); } Tcl_DStringAppend (&s, (char*) n, Tcl_UniCharLen (n) * sizeof(Tcl_UniChar)); if (suffix) { Tcl_DStringAppend (&s, (char *) suffix, Tcl_UniCharLen (suffix) * sizeof(Tcl_UniChar)); } Tcl_DStringAppend (&s, (char *)&uniCharNull, sizeof (Tcl_UniChar)); } DBG( Tcl_DStringInit (&dbStr); fprintf(stderr, "returning s='%s' \n\n", Tcl_UniCharToUtfDString( (Tcl_UniChar*)Tcl_DStringValue (&s), Tcl_UniCharLen((Tcl_UniChar*)Tcl_DStringValue(&s)), &dStr )); Tcl_DStringFree (&dbStr); ) Tcl_DStringSetLength (&dStr, 0); tstr = Tcl_UniCharToUtfDString( (Tcl_UniChar*)Tcl_DStringValue (&s), Tcl_UniCharLen((Tcl_UniChar*)Tcl_DStringValue(&s)), &dStr ); *resultStr = tdomstrdup(tstr); Tcl_DStringFree (&dStr); Tcl_DStringFree (&s); *resultLen = (domLength)strlen(*resultStr); return 0; xsltFormatNumberError: Tcl_DStringFree (&dStr); Tcl_DStringFree (&s); return -1; } static xsltNodeSet * createXsltNodeSet (void) { xsltNodeSet * ns; ns = (xsltNodeSet *) MALLOC (sizeof(xsltNodeSet)); ns->nodes = (domNode**)MALLOC(INITIAL_SIZE_FOR_KEYSETS * sizeof(domNode*)); ns->allocated = INITIAL_SIZE_FOR_KEYSETS; ns->nr_nodes = 0; return ns; } /* Helper proc for buildKeyInfoForDoc. Adds node to the node set ns at the right position (in document order), if not already present. This is the same as the core of rsAddNode does. The used method to add may look a bit simpleminded, but experience shows, that in the vast majority of the cases node simply has to be appended to the array. */ static void nsAddNode ( xsltNodeSet *ns, domNode *node ) { domLength insertIndex, i; insertIndex = ns->nr_nodes; for (i = ns->nr_nodes - 1; i >= 0; i--) { if (node == ns->nodes[i]) return; if (!domPrecedes (node, ns->nodes[i])) { break; } insertIndex--; } if (ns->nr_nodes + 1 >= ns->allocated) { ns->nodes = (domNode**)REALLOC((void*)ns->nodes, 2 * ns->allocated * sizeof(domNode*)); ns->allocated *= 2; } if (insertIndex == ns->nr_nodes) { ns->nodes[ns->nr_nodes++] = node; } else { for (i = ns->nr_nodes - 1; i >= insertIndex; i--) { ns->nodes[i+1] = ns->nodes[i]; } ns->nodes[insertIndex] = node; ns->nr_nodes++; } } static int buildKeyInfoForDoc ( xsltSubDoc *sd, char *keyId, Tcl_HashTable *keyInfos, xsltState *xs, char **errMsg ) { int hnew, rc, docOrder, i; char *useValue; domNode *node, *savedCurrent; xpathResultSet rs, context; Tcl_HashTable *valueTable; Tcl_HashEntry *h; xsltKeyInfo *kinfo, *kinfoStart; xsltNodeSet *keyValues; h = Tcl_FindHashEntry (keyInfos, keyId); /* key must exist, this is already checked */ kinfoStart = (xsltKeyInfo *) Tcl_GetHashValue (h); /* this must be a new entry, no check for hnew==1 needed */ h = Tcl_CreateHashEntry (&(sd->keyData), keyId, &hnew); valueTable = (Tcl_HashTable *)MALLOC(sizeof (Tcl_HashTable)); Tcl_InitHashTable (valueTable, TCL_STRING_KEYS); Tcl_SetHashValue (h, valueTable); savedCurrent = xs->current; node = sd->doc->rootNode; while (node) { kinfo = kinfoStart; while (kinfo) { rc = xpathMatches (kinfo->matchAst, kinfo->node, node, &(xs->cbs), errMsg); if (rc < 0) { TRACE1("xpathMatches had errors '%s' \n", *errMsg); return rc; } if (rc > 0) { TRACE("found match for key !\n"); xpathRSInit (&rs); xpathRSInit (&context); rsAddNode (&context, node); DBG(printXML(node, 0, 2);) docOrder = 1; xs->current = node; rc = xpathEvalSteps (kinfo->useAst, &context, node, kinfo->node, 0, &docOrder, &(xs->cbs), &rs, errMsg); if (rc != XPATH_OK) { xpathRSFree (&rs); xpathRSFree (&context); return rc; } DBG(rsPrint(&rs)); if (rs.type == xNodeSetResult) { for (i = 0; i < rs.nr_nodes; i++) { useValue = xpathFuncStringForNode (rs.nodes[i]); TRACE1("use value = '%s'\n", useValue); h = Tcl_CreateHashEntry (valueTable, useValue, &hnew); if (hnew) { keyValues = createXsltNodeSet(); } else { keyValues = (xsltNodeSet *) Tcl_GetHashValue (h); } nsAddNode (keyValues, node); if (hnew) Tcl_SetHashValue (h, keyValues); FREE(useValue); } } else if (rs.type != EmptyResult) { useValue = xpathFuncString (&rs); TRACE1("use value = '%s'\n", useValue); h = Tcl_CreateHashEntry (valueTable, useValue, &hnew); if (hnew) { keyValues = createXsltNodeSet(); } else { keyValues = (xsltNodeSet *) Tcl_GetHashValue (h); } nsAddNode (keyValues, node); if (hnew) Tcl_SetHashValue (h, keyValues); FREE(useValue); } xpathRSFree( &context ); xpathRSFree( &rs ); } kinfo = kinfo->next; } if ((node->nodeType == ELEMENT_NODE) && (node->firstAttr)) { node = (domNode*) node->firstAttr; continue; } if (node->nodeType == ATTRIBUTE_NODE) { if (((domAttrNode*)node)->nextSibling) { node = (domNode*) ((domAttrNode*)node)->nextSibling; continue; } node = ((domAttrNode*)node)->parentNode; } if ((node->nodeType == ELEMENT_NODE) && (node->firstChild)) { node = node->firstChild; continue; } if (node->nextSibling) { node = node->nextSibling; continue; } while ( node->parentNode && (node->parentNode->nextSibling == NULL) ) { node = node->parentNode; } if (node->parentNode) { node = node->parentNode->nextSibling; } else { break; } } xs->current = savedCurrent; return 0; } /*---------------------------------------------------------------------------- | sortNodeSetByNodeNumber | \---------------------------------------------------------------------------*/ static void sortNodeSetByNodeNumber( domNode *nodes[], domLength n ) { domLength i, j, ln, rn; domNode *tmp; while (n > 1) { tmp = nodes[0]; nodes[0] = nodes[n/2]; nodes[n/2] = tmp; for (i = 0, j = n; ; ) { do { --j; } while (domPrecedes (nodes[0], nodes[j])); do { ++i; } while (i < j && domPrecedes (nodes[i], nodes[0])); if (i >= j) break; tmp = nodes[i]; nodes[i] = nodes[j]; nodes[j] = tmp; } tmp = nodes[j]; nodes[j] = nodes[0]; nodes[0] = tmp; ln = j; rn = n - ++j; if (ln < rn) { sortNodeSetByNodeNumber(nodes, ln); nodes += j; n = rn; } else { sortNodeSetByNodeNumber(&(nodes[j]), rn); n = ln; } } } /*---------------------------------------------------------------------------- | sortByDocOrder | \---------------------------------------------------------------------------*/ void sortByDocOrder ( xpathResultSet * rs ) { if (rs->type != xNodeSetResult) return; sortNodeSetByNodeNumber(rs->nodes, rs->nr_nodes); } /*---------------------------------------------------------------------------- | StripXMLSpace | \---------------------------------------------------------------------------*/ static void StripXMLSpace ( xsltState * xs, domNode * node ) { domNode *child, *newChild, *parent; size_t i, len; int onlySpace, found, strip; char *p, prefix[MAX_PREFIX_LEN]; const char *localName; double *f; domNS *ns; Tcl_HashEntry *h; Tcl_DString dStr; if (node->nodeType == TEXT_NODE) { p = ((domTextNode*)node)->nodeValue; len = ((domTextNode*)node)->valueLength; onlySpace = 1; for (i=0; iparentNode; while (parent) { p = getAttr(parent,"xml:space", a_space); if (p!=NULL) { if (strcmp(p,"preserve")==0) return; if (strcmp(p,"default")==0) break; } parent = parent->parentNode; } DBG(fprintf(stderr, "removing domNode0x%x(len %d) under '%s' \n", node, len, node->parentNode->nodeName);) domDeleteNode (node, NULL, NULL); } } else if (node->nodeType == ELEMENT_NODE) { if (node->firstChild == NULL) return; strip = xs->wsInfo.stripAll; found = 0; if (node->namespace) { domSplitQName (node->nodeName, prefix, &localName); } else { prefix[0] = '\0'; localName = node->nodeName; } ns = NULL; Tcl_DStringInit (&dStr); if (prefix[0] != '\0') { ns = domLookupPrefix (node, prefix); if (ns) { Tcl_DStringAppend (&dStr, ns->uri, -1); Tcl_DStringAppend (&dStr, ":*", 2); if (xs->wsInfo.stripAll) { h = Tcl_FindHashEntry (&xs->wsInfo.preserveTokens, Tcl_DStringValue (&dStr)); } else { h = Tcl_FindHashEntry (&xs->wsInfo.stripTokens, Tcl_DStringValue (&dStr)); } if (h) { f = Tcl_GetHashValue (h); if (*f >= xs->wsInfo.wildcardPrec) { strip = !xs->wsInfo.stripAll; found = 1; } } if (!found) { Tcl_DStringFree (&dStr); Tcl_DStringInit (&dStr); Tcl_DStringAppend (&dStr, ns->uri, -1); Tcl_DStringAppend (&dStr, ":", 1); } } } if (!found) { Tcl_DStringAppend (&dStr, localName, -1); if (xs->wsInfo.stripAll) { h = Tcl_FindHashEntry (&xs->wsInfo.preserveTokens, Tcl_DStringValue (&dStr)); } else { h = Tcl_FindHashEntry (&xs->wsInfo.stripTokens, Tcl_DStringValue (&dStr)); } if (h) { f = Tcl_GetHashValue (h); if (*f >= xs->wsInfo.wildcardPrec) { strip = !xs->wsInfo.stripAll; } } } Tcl_DStringFree (&dStr); if (strip) { child = node->firstChild; while (child) { newChild = child->nextSibling; StripXMLSpace (xs, child); child = newChild; } } else { child = node->firstChild; while (child) { if (child->nodeType == ELEMENT_NODE) { StripXMLSpace (xs, child); } child = child->nextSibling; } } } } /*---------------------------------------------------------------------------- | xsltXPathFuncs | \---------------------------------------------------------------------------*/ static int xsltXPathFuncs ( void * clientData, char * funcName, domNode * ctxNode, domLength ctxPos, xpathResultSet * ctx, domNode * exprContext, int argc, xpathResultSets * argv, xpathResultSet * result, char ** errMsg ) { xsltState * xs = clientData; char * keyId, *filterValue, *str = NULL; char prefix[MAX_PREFIX_LEN]; const char * localName, *baseURI, *nsStr; int rc, NaN, freeStr; domLength i, len, x; double n; xsltNodeSet * keyValues; Tcl_HashEntry * h; Tcl_HashTable * docKeyData; xsltSubDoc * sdoc; domDocument * ownerDoc; Tcl_DString dStr; domNS * ns; xsltDecimalFormat * df; DBG ( fprintf(stderr,"xsltXPathFuncs funcName='%s'\n",funcName); ) if (strcmp(funcName, "key")==0) { /*-------------------------------------------------------------------- | 'key' function \-------------------------------------------------------------------*/ DBG(fprintf(stderr,"xslt key function called!\n");) if (argc != 2) { reportError (exprContext, "key() needs two arguments!", errMsg); return -1; } /* check, if there is a key definition with the given name */ keyId = xpathFuncString(argv[0]); TRACE1("keyId='%s' \n", keyId); domSplitQName (keyId, prefix, &localName); Tcl_DStringInit (&dStr); if (prefix[0] != '\0') { ns = domLookupPrefix (exprContext, prefix); if (!ns) { reportError (exprContext, "There isn't a namespace bound to" " the prefix.", errMsg); FREE(keyId); return -1; } Tcl_DStringAppend (&dStr, ns->uri, -1); } Tcl_DStringAppend (&dStr, localName, -1); FREE(keyId); h = Tcl_FindHashEntry (&xs->keyInfos, Tcl_DStringValue (&dStr)); if (!h) { reportError (exprContext, "Unknown key in key() function call!", errMsg); Tcl_DStringFree (&dStr); return -1; } /* Short cut for empty result sets. */ if (argv[1]->type == EmptyResult) { Tcl_DStringFree (&dStr); return 0; } /* find the doc, the context node belongs to */ sdoc = xs->subDocs; if (ctxNode->nodeType == ATTRIBUTE_NODE) { ownerDoc = ((domAttrNode *)ctxNode)->parentNode->ownerDocument; } else { ownerDoc = ctxNode->ownerDocument; } while (sdoc) { if (sdoc->doc == ownerDoc) break; sdoc = sdoc->next; } DBG(if (!sdoc) fprintf (stderr, "key() function: ctxNode doesn't belong to a doc out of subDocs!!! This could not happen!. ERROR\n"); else (fprintf (stderr, "key() function: ctxNode belongs to doc %s\n", sdoc->baseURI));) h = Tcl_FindHashEntry (&(sdoc->keyData), Tcl_DStringValue (&dStr)); if (!h) { if (buildKeyInfoForDoc(sdoc, Tcl_DStringValue (&dStr), &(xs->keyInfos),xs,errMsg)<0) { Tcl_DStringFree (&dStr); return -1; } h = Tcl_FindHashEntry (&(sdoc->keyData), Tcl_DStringValue (&dStr)); } Tcl_DStringFree (&dStr); docKeyData = (Tcl_HashTable *) Tcl_GetHashValue (h); if (argv[1]->type == xNodeSetResult) { for (i = 0; i < argv[1]->nr_nodes; i++) { filterValue = xpathFuncStringForNode (argv[1]->nodes[i]); TRACE1("filterValue='%s' \n", filterValue); h = Tcl_FindHashEntry (docKeyData, filterValue); if (h) { keyValues = (xsltNodeSet *) Tcl_GetHashValue (h); if (result->type == EmptyResult) { result->type = xNodeSetResult; result->nodes = keyValues->nodes; result->intvalue = 1; result->nr_nodes = keyValues->nr_nodes; result->allocated = keyValues->allocated; } else { for (x = 0; x < keyValues->nr_nodes; x++) { rsAddNode(result, keyValues->nodes[x]); } } } FREE(filterValue); } } else { filterValue = xpathFuncString(argv[1]); TRACE1("filterValue='%s' \n", filterValue); h = Tcl_FindHashEntry (docKeyData, filterValue); if (h) { keyValues = (xsltNodeSet *) Tcl_GetHashValue (h); if (result->type == EmptyResult) { result->type = xNodeSetResult; result->nodes = keyValues->nodes; result->intvalue = 1; result->nr_nodes = keyValues->nr_nodes; result->allocated = keyValues->allocated; } else { for (x = 0; x < keyValues->nr_nodes; x++) { rsAddNode(result, keyValues->nodes[x]); } } } FREE(filterValue); } return 0; } else if (strcmp(funcName, "current")==0) { /*-------------------------------------------------------------------- | 'current' function \-------------------------------------------------------------------*/ DBG(fprintf(stderr, "xsltXPathFuncs 'current' = 'domNode0x%x' \n", xs->current);) if (argc != 0) { reportError (exprContext, "current() must not have any arguments", errMsg); return -1; } rsAddNode(result, xs->current); return 0; } else if (strcmp (funcName, "format-number")==0) { /*-------------------------------------------------------------------- | 'format-number' function \-------------------------------------------------------------------*/ DBG(fprintf(stderr, "before format-number argc=%d \n", argc);) if (argc == 3) { str = xpathFuncString (argv[2]); domSplitQName (str, prefix, &localName); ns = NULL; if (prefix[0] != '\0') { ns = domLookupPrefix (exprContext, prefix); if (!ns) { reportError (exprContext, "There isn't a namespace bound" " to the prefix.", errMsg); FREE(str); return -1; } } df = xs->decimalFormats->next; while (df) { if (strcmp(df->name, str)==0 && ((df->uri == NULL && ns == NULL) || (df->uri != NULL && ns != NULL && (strcmp (df->uri, ns->uri)==0)))) { break; } df = df->next; } FREE(str); if (df == NULL) { reportError (exprContext, "There isn't a decimal format with" " this name.", errMsg); return -1; } } else if (argc == 2) { df = xs->decimalFormats; } else { reportError (exprContext, "format-number: wrong # parameters:" " format-number(number, string, ?string?)!", errMsg); return -1; } NaN = 0; n = xpathFuncNumber (argv[0], &NaN); if (NaN) { if (NaN == 2) rsSetString (result, df->NaN); else if (NaN == 1) rsSetString (result, df->infinity); else { Tcl_DStringInit (&dStr); Tcl_DStringAppend (&dStr, "-", 1); Tcl_DStringAppend (&dStr, df->infinity, -1); rsSetString (result, Tcl_DStringValue (&dStr)); } return 0; } str = xpathFuncString (argv[1]); DBG(fprintf(stderr, "1 str='%s' \n", str);) result->type = StringResult; rc = xsltFormatNumber(n, str, df, &(result->string), &(result->string_len), errMsg); FREE(str); if (rc < 0) { result->type = EmptyResult; return rc; } DBG(fprintf(stderr, "after format-number \n");) return 0; } else if (strcmp (funcName, "document")==0) { /*-------------------------------------------------------------------- | 'document' function \-------------------------------------------------------------------*/ DBG(fprintf(stderr, "xsltXPathFuncs 'document' \n");) if (argc == 1) { if (argv[0]->type == xNodeSetResult) { for (i = 0; i < argv[0]->nr_nodes; i++) { freeStr = 0; if (argv[0]->nodes[i]->nodeType == ATTRIBUTE_NODE) { nsStr = ((domAttrNode*)argv[0]->nodes[i])->nodeValue; baseURI = findBaseURI (((domAttrNode*)argv[0]->nodes[i])->parentNode); } else { str = xpathGetStringValue (argv[0]->nodes[i], &len); nsStr = str; freeStr = 1; baseURI = findBaseURI (argv[0]->nodes[i]); } /* the case document('') */ if (*nsStr == '\0') { if (freeStr) { FREE(str); freeStr = 0; } nsStr = baseURI; } if (xsltAddExternalDocument(xs, baseURI, nsStr, 0, result, errMsg) < 0) { if (freeStr) FREE(str); return -1; } if (xs->wsInfo.hasData) { StripXMLSpace (xs, xs->subDocs->doc->documentElement); } if (freeStr) FREE(str); } } else { str = xpathFuncString (argv[0]); nsStr = str; if (xs->currentXSLTNode) { baseURI = findBaseURI (xs->currentXSLTNode); } else if (xs->currentTplRule) { baseURI = findBaseURI (xs->currentTplRule->content); } else { baseURI = findBaseURI (xs->xsltDoc->rootNode); } if (*nsStr == '\0') { nsStr = baseURI; } DBG (fprintf (stderr, "document() call, with 1 string arg = '%s'\n", str);) if (xsltAddExternalDocument(xs, baseURI, nsStr, 1, result, errMsg) < 0) { FREE(str); return -1; } if (xs->wsInfo.hasData) { StripXMLSpace (xs, xs->subDocs->doc->documentElement); } FREE(str); } } else if (argc == 2) { if (argv[1]->type != xNodeSetResult) { reportError (exprContext, "second arg of document() has to be" " a nodeset!", errMsg); return -1; } if (argv[1]->nodes[0]->nodeType == ATTRIBUTE_NODE) { baseURI = findBaseURI (((domAttrNode*)argv[1]->nodes[0])->parentNode); } else { baseURI = findBaseURI (argv[1]->nodes[0]); } if (argv[0]->type == xNodeSetResult) { for (i = 0; i < argv[0]->nr_nodes; i++) { freeStr = 0; if (argv[0]->nodes[i]->nodeType == ATTRIBUTE_NODE) { nsStr = ((domAttrNode*)argv[0]->nodes[i])->nodeValue; } else { str = xpathGetStringValue (argv[0]->nodes[i], &len); freeStr = 1; nsStr = str; } if (*nsStr == '\0') { FREE(str); freeStr = 0; nsStr = baseURI; } if (xsltAddExternalDocument(xs, baseURI, nsStr, 0, result, errMsg) < 0) { if (freeStr) FREE(str); return -1; } if (xs->wsInfo.hasData) { StripXMLSpace (xs, xs->subDocs->doc->documentElement); } if (freeStr) FREE(str); } } else { str = xpathFuncString (argv[0]); nsStr = str; if (*str == '\0') { nsStr = baseURI; } if (xsltAddExternalDocument(xs, baseURI, nsStr, 0, result, errMsg) < 0) { FREE(str); return -1; } if (xs->wsInfo.hasData) { StripXMLSpace (xs, xs->subDocs->doc->documentElement); } FREE(str); } } else { reportError (exprContext, "wrong # of args in document() call!", errMsg); return -1; } return 0; } else { /* chain back to original callback */ if (xs->orig_funcCB) { return (xs->orig_funcCB)(xs->orig_funcClientData, funcName, ctxNode, ctxPos, ctx, exprContext, argc, argv, result, errMsg); } } return 0; } /*---------------------------------------------------------------------------- | evalXPath | \---------------------------------------------------------------------------*/ static int evalXPath ( xsltState * xs, xpathResultSet * context, domNode * currentNode, domLength currentPos, char * xpath, xpathResultSet * rs, char ** errMsg ) { int rc, hnew, docOrder = 1; ast t; domNode *savedCurrent; Tcl_HashEntry *h; h = Tcl_CreateHashEntry (&(xs->xpaths), xpath, &hnew); if (!hnew) { t = (ast)Tcl_GetHashValue(h); } else { rc = xpathParse (xpath, xs->currentXSLTNode, XPATH_EXPR, NULL, NULL, &t, errMsg); if (rc < 0) { reportError (xs->currentXSLTNode, *errMsg, errMsg); return rc; } Tcl_SetHashValue(h, t); } xpathRSInit( rs ); DBG(fprintf (stderr, "evalXPath evaluating xpath:\n");) DBG(printAst(3,t);) savedCurrent = xs->current; xs->current = currentNode; rc = xpathEvalSteps( t, context, currentNode, xs->currentXSLTNode, currentPos, &docOrder, &(xs->cbs), rs, errMsg); xs->current = savedCurrent; if (rc != XPATH_OK) { reportError (xs->currentXSLTNode, *errMsg, errMsg); xpathRSFree( rs ); } return rc; } /*---------------------------------------------------------------------------- | nodeGreater | \---------------------------------------------------------------------------*/ static int nodeGreater ( int typeText, int asc, int upperFirst, char * strA, char * strB, double realA, double realB, int * greater ) { int rc; char *strAptr, *strBptr; domLength lenA, lenB, len; Tcl_UniChar unicharA, unicharB; *greater = 0; if (typeText) { lenA = Tcl_NumUtfChars (strA, -1); lenB = Tcl_NumUtfChars (strB, -1); len = (lenA < lenB ? lenA : lenB); rc = Tcl_UtfNcasecmp (strA, strB, len); if (rc == 0) { if (lenA > lenB) { rc = 1; } else if (lenA < lenB) { rc = -1; } } if (rc == 0) { strAptr = strA; strBptr = strB; while (len-- > 0) { strAptr += Tcl_UtfToUniChar(strAptr, &unicharA); strBptr += Tcl_UtfToUniChar(strBptr, &unicharB); if (unicharA != unicharB) { rc = unicharA - unicharB; break; } } if (!upperFirst) { rc *= -1; } } if (asc) *greater = (rc > 0); else *greater = (rc < 0); } else { DBG( fprintf(stderr, "nodeGreater realA='%f' realB='%f'\n",realA, realB);) if (IS_NAN (realA) || IS_NAN (realB)) { if (asc) { if (IS_NAN (realA) && !IS_NAN (realB)) { *greater = 0; } else { if (IS_NAN (realB) && !IS_NAN (realA)) *greater = 1; } } else { if (IS_NAN (realA) && !IS_NAN(realB)) { *greater = 1; } else { if (IS_NAN (realB) && !IS_NAN(realA)) *greater = 0; } } } else { if (asc) *greater = (realA > realB); else *greater = (realA < realB); } } return 0; } static int fastMergeSort ( int txt, int asc, int upperFirst, domNode * a[], domLength * posa, domNode * b[], domLength * posb, char ** vs, double * vd, char ** vstmp, double * vdtmp, domLength size, char ** errMsg ) { domNode *tmp; domLength tmpPos, lptr, rptr, middle, i, j; int gt, rc; char *tmpVs; double tmpVd; if (size < 10) { /* use simple and fast insertion for small sizes ! */ for (i = 1; i < size; i++) { tmp = a [i]; tmpPos = posa [i]; tmpVs = vs [i]; tmpVd = vd [i]; j = i; if (j>0) { rc = nodeGreater(txt, asc, upperFirst, vs[j-1], tmpVs, vd[j-1], tmpVd, >); CHECK_RC; } while ( j > 0 && gt) { a [j] = a [j-1]; posa[j] = posa[j-1]; vs [j] = vs [j-1]; vd [j] = vd [j-1]; j--; if (j>0) { rc = nodeGreater(txt, asc, upperFirst, vs[j-1], tmpVs, vd[j-1], tmpVd, >); CHECK_RC; } } a [j] = tmp; posa[j] = tmpPos; vs [j] = tmpVs; vd [j] = tmpVd; } return 0; } middle = size/2; rc = fastMergeSort(txt, asc, upperFirst, a, posa, b, posb, vs, vd, vstmp, vdtmp, middle, errMsg); CHECK_RC; rc = fastMergeSort(txt, asc, upperFirst, a+middle, posa+middle, b+middle, posb+middle, vs+middle, vd+middle, vstmp+middle, vdtmp+middle, size-middle, errMsg); CHECK_RC; lptr = 0; rptr = middle; for (i = 0; i < size; i++) { if (lptr == middle) { b [i] = a [rptr ]; posb [i] = posa[rptr ]; vstmp[i] = vs [rptr ]; vdtmp[i] = vd [rptr++]; } else if (rptr < size) { rc = nodeGreater(txt, asc, upperFirst, vs[lptr], vs[rptr], vd[lptr], vd[rptr], >); if (gt) { b [i] = a [rptr ]; posb [i] = posa[rptr ]; vstmp[i] = vs [rptr ]; vdtmp[i] = vd [rptr++]; } else { b [i] = a [lptr ]; posb [i] = posa[lptr ]; vstmp[i] = vs [lptr ]; vdtmp[i] = vd [lptr++]; } } else { b [i] = a [lptr ]; posb [i] = posa[lptr ]; vstmp[i] = vs [lptr ]; vdtmp[i] = vd [lptr++]; } } memcpy(a, b, size*sizeof(domNode*)); memcpy(posa, posb, size*sizeof(domLength)); memcpy(vs, vstmp, size*sizeof(char*)); memcpy(vd, vdtmp, size*sizeof(double)); return 0; } static int sortNodeSetFastMerge( int txt, int asc, int upperFirst, domNode * nodes[], domLength n, char ** vs, double * vd, domLength * pos, char ** errMsg ) { domNode **b; domLength *posb; char **vstmp; double *vdtmp; int rc; b = (domNode **)MALLOC(n * sizeof(domNode *)); posb = (domLength *)MALLOC(n * sizeof(domLength)); vstmp = (char **)MALLOC(sizeof (char *) * n); vdtmp = (double *)MALLOC(sizeof (double) * n); rc = fastMergeSort(txt, asc, upperFirst, nodes, pos, b, posb, vs, vd, vstmp, vdtmp, n, errMsg); FREE((char*)posb); FREE((char*)b); FREE((char*)vstmp); FREE((char*)vdtmp); CHECK_RC; return 0; } /*---------------------------------------------------------------------------- | xsltSetVar | \---------------------------------------------------------------------------*/ static int xsltSetVar ( xsltState * xs, char * variableName, xpathResultSet * context, domNode * currentNode, domLength currentPos, char * select, domNode * actionNode, int active, char ** errMsg ) { xsltVariable * var; int rc; xpathResultSet rs; xsltVarFrame *tmpFrame = NULL; domNode *fragmentNode, *savedLastNode; char prefix[MAX_PREFIX_LEN]; const char *localName; domNS *ns; TRACE1("xsltSetVar variableName='%s' \n", variableName); if (select!=NULL) { TRACE2("xsltSetVar variableName='%s' select='%s'\n", variableName, select); rc = evalXPath (xs, context, currentNode, currentPos, select, &rs, errMsg); CHECK_RC; } else { if (!actionNode->firstChild) { xpathRSInit (&rs); rsSetString (&rs, ""); } else { fragmentNode = domNewElementNode(xs->resultDoc, ""); savedLastNode = xs->lastNode; xs->lastNode = fragmentNode; /* process the children as well */ xsltPushVarFrame (xs); rc = ExecActions(xs, context, currentNode, currentPos, actionNode->firstChild, errMsg); xsltPopVarFrame (xs); CHECK_RC; xpathRSInit(&rs); rsAddNodeFast(&rs, fragmentNode); xs->lastNode = savedLastNode; } } tmpFrame = &xs->varFramesStack[xs->varFramesStackPtr]; xs->varStackPtr++; if (xs->varStackPtr >= xs->varStackLen) { xs->varStack = (xsltVariable *) REALLOC ((char*)xs->varStack, sizeof (xsltVariable) * 2 * xs->varStackLen); xs->varStackLen *= 2; } var = &(xs->varStack[xs->varStackPtr]); if (tmpFrame->varStartIndex == -1) { tmpFrame->varStartIndex = xs->varStackPtr; } tmpFrame->nrOfVars++; domSplitQName (variableName, prefix, &localName); if (prefix[0] != '\0') { ns = domLookupPrefix (actionNode, prefix); if (!ns) { reportError (actionNode, "There isn't a namespace bound to" " the prefix.", errMsg); return -1; } var->uri = ns->uri; var->name = localName; } else { var->uri = NULL; var->name = variableName; } tmpFrame->polluted = 1; var->node = actionNode; var->rs = rs; var->active = active; DBG(rsPrint(&(var->rs))); return 0; } /*---------------------------------------------------------------------------- | xsltVarExists | \---------------------------------------------------------------------------*/ static int xsltVarExists ( xsltState * xs, char * variableName, domNode * exprContext ) { int i, frameIndex, found = 0; char prefix[MAX_PREFIX_LEN]; const char *localName, *uri, *varName; domNS *ns; xsltVarFrame *frame; TRACE1("xsltVarExists variableName='%s' \n", variableName); domSplitQName (variableName, prefix, &localName); if (prefix[0]) { ns = domLookupPrefix (exprContext, prefix); if (!ns) { /* TODO: this is an error, not only 'not found' */ return 0; } uri = ns->uri; varName = localName; } else { uri = NULL; varName = variableName; } frameIndex = xs->varFramesStackPtr; while (frameIndex >= 0) { frame = &xs->varFramesStack[frameIndex]; for (i = frame->varStartIndex; i < frame->varStartIndex + frame->nrOfVars; i++) { if ( (uri && !((&xs->varStack[i])->uri)) || (!uri && (&xs->varStack[i])->uri) || (uri && (&xs->varStack[i])->uri && (strcmp (uri, (&xs->varStack[i])->uri)!=0)) ) continue; if (strcmp((&xs->varStack[i])->name, varName)==0) { found = 1; (&xs->varStack[i])->active = 1; break; /* found the variable */ } } if (found) return 1; if (frame->stop) break; frameIndex--; } return 0; } /*---------------------------------------------------------------------------- | xsltGetVar | \---------------------------------------------------------------------------*/ static int xsltGetVar ( void * clientData, char * variableName, char * varURI, xpathResultSet * result, char **errMsg ) { xsltState *xs = clientData; xsltVarFrame *frame; xsltVariable *var; int rc, i, frameIndex, parFrameSkiped = 0; char *select; Tcl_HashEntry *h; xsltTopLevelVar *topLevelVar; xsltVarInProcess *varInProcess, thisVarInProcess; xpathResultSet nodeList; domNode *savedCurrentXSLTNode; Tcl_DString dErrMsg; TRACE1("xsltGetVar variableName='%s' \n", variableName); frameIndex = xs->varFramesStackPtr; while (frameIndex >= 0) { frame = &xs->varFramesStack[frameIndex]; if (frame->stop == 2 && !parFrameSkiped) { parFrameSkiped = 1; frameIndex--; continue; } for (i = frame->varStartIndex; i < frame->varStartIndex + frame->nrOfVars; i++) { var = &xs->varStack[i]; if (!var->active) continue; if ( (varURI && !var->uri) || (!varURI && var->uri) || (varURI && var->uri && (strcmp (varURI, var->uri)!=0)) ) continue; if (strcmp(var->name, variableName)==0) { TRACE1("xsltGetVar '%s':\n", variableName); DBG(rsPrint(&(var->rs))); rsCopy(result, &(var->rs) ); return XPATH_OK; } } if ((frame->stop == 1) && frameIndex > 1) frameIndex = 1; frameIndex--; } if (xs->varsInProcess) { h = Tcl_FindHashEntry (&xs->topLevelVars, variableName); if (h) { topLevelVar = (xsltTopLevelVar *) Tcl_GetHashValue (h); /* check for circular definitions */ varInProcess = xs->varsInProcess; while (varInProcess) { if (strcmp(varInProcess->name, variableName)==0) { reportError (topLevelVar->node, "circular top level" " variabale definition detected", errMsg); return XPATH_EVAL_ERR; } varInProcess = varInProcess->next; } thisVarInProcess.name = variableName; thisVarInProcess.next = xs->varsInProcess; xs->varsInProcess = &thisVarInProcess; xpathRSInit( &nodeList ); rsAddNodeFast( &nodeList, xs->xmlRootNode); savedCurrentXSLTNode = xs->currentXSLTNode; xs->currentXSLTNode = topLevelVar->node; select = getAttr (topLevelVar->node, "select", a_select); rc = xsltSetVar (xs, variableName, &nodeList, xs->xmlRootNode, 0, select, topLevelVar->node, 1, errMsg); xpathRSFree ( &nodeList ); CHECK_RC; rc = xsltGetVar (xs, variableName, varURI, result, errMsg); CHECK_RC; /* remove var out of the varsInProcess list. Should be first in the list, shouldn't it? */ varInProcess = xs->varsInProcess; if (varInProcess != &thisVarInProcess) { reportError (topLevelVar->node, "Error in top level" " vars processing.", errMsg); return XPATH_EVAL_ERR; } xs->varsInProcess = varInProcess->next; xs->currentXSLTNode = savedCurrentXSLTNode; return XPATH_OK; } } Tcl_DStringInit (&dErrMsg); Tcl_DStringAppend (&dErrMsg, "Variable \"", -1); Tcl_DStringAppend (&dErrMsg, variableName, -1); Tcl_DStringAppend (&dErrMsg, "\" has not been declared.", -1); reportError (xs->currentXSLTNode, Tcl_DStringValue (&dErrMsg), errMsg); Tcl_DStringFree (&dErrMsg); return XPATH_EVAL_ERR; } /*---------------------------------------------------------------------------- | addMatch | \---------------------------------------------------------------------------*/ static int addMatch ( xsltState *xs, domNode *node, xsltTemplate *tpl, char *prioStr, ast a, char **errMsg ) { xsltTemplate *t, *prevTpl; int rc, hnew; Tcl_DString dStr; Tcl_HashEntry *h; if (a->type == CombinePath) { t = (xsltTemplate *)MALLOC(sizeof(xsltTemplate)); t->freeAst = NULL; t->name = NULL; t->nameURI = NULL; t->mode = tpl->mode; t->modeURI = tpl->modeURI; t->content = tpl->content; t->precedence = tpl->precedence; t->sDoc = tpl->sDoc; t->next = NULL; if (prioStr) { t->prio = tpl->prio; } rc = addMatch (xs, node, t, prioStr, a->child->child, errMsg); CHECK_RC1(t); tpl->ast = a->child->next->child; } else { tpl->ast = a; } if (!prioStr) { tpl->prio = xpathGetPrio(tpl->ast); TRACE1("prio = %f for \n", tpl->prio); DBG(printAst( 0, tpl->ast);) TRACE("\n"); } if ((tpl->ast->type == IsElement && tpl->ast->strvalue[0] != '*') || tpl->ast->type == IsFQElement) { Tcl_DStringInit (&dStr); if (tpl->ast->type == IsFQElement) { Tcl_DStringAppend (&dStr, tpl->ast->strvalue, -1); Tcl_DStringAppend (&dStr, ":", 1); } if (tpl->mode) { if (tpl->modeURI) { Tcl_DStringAppend (&dStr, tpl->modeURI, -1); Tcl_DStringAppend (&dStr, ":", 1); } Tcl_DStringAppend (&dStr, tpl->mode, -1); Tcl_DStringAppend (&dStr, ":", 1); } if (tpl->ast->type == IsFQElement) { Tcl_DStringAppend (&dStr, tpl->ast->child->strvalue, -1); } else { Tcl_DStringAppend (&dStr, tpl->ast->strvalue, -1); } h = Tcl_CreateHashEntry (&(xs->isElementTpls), Tcl_DStringValue (&dStr), &hnew); Tcl_DStringFree (&dStr); if (hnew) { tpl->next = NULL; Tcl_SetHashValue (h, tpl); } else { t = (xsltTemplate *) Tcl_GetHashValue (h); prevTpl = NULL; while ( t && t->precedence >= tpl->precedence && t->prio > tpl->prio) { prevTpl = t; t = t->next; } if (prevTpl) { tpl->next = t; prevTpl->next = tpl; } else { tpl->next = Tcl_GetHashValue (h); Tcl_SetHashValue (h, tpl); } } } else { if (xs->templates == NULL) { xs->templates = tpl; } else { t = xs->templates; prevTpl = NULL; while ( t && t->precedence >= tpl->precedence && t->prio > tpl->prio) { prevTpl = t; t = t->next; } if (prevTpl) { tpl->next = t; prevTpl->next = tpl; } else { tpl->next = xs->templates; xs->templates = tpl; } } } TRACE5("AddTemplate '%s' '%s' '%s' '%s' '%2.2f' \n\n", tpl->match, tpl->name, tpl->mode, tpl->modeURI, tpl->prio); return 0; } /*---------------------------------------------------------------------------- | xsltAddTemplate | \---------------------------------------------------------------------------*/ static int xsltAddTemplate ( 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; tpl = (xsltTemplate *)MALLOC(sizeof(xsltTemplate)); tpl->match = getAttr(node,"match", a_match); str = getAttr(node, "name", a_name); if (!tpl->match && !str) { reportError (node, " xsl:template must have a name or" " match attribute (or both)", errMsg); FREE ((char*)tpl); return -1; } tpl->name = NULL; tpl->nameURI = NULL; if (str) { if (!domIsQNAME (str)) { reportError (node, "The value of the \"name\" attribute must" " be a qname", errMsg); FREE ((char*)tpl); return -1; } domSplitQName (str, prefix, &localName); if (prefix[0] != '\0') { ns = domLookupPrefix (node, prefix); if (!ns) { reportError (node, "The prefix of the \"name\" attribute" " value isn't bound to a namespace.", errMsg); FREE ((char*)tpl); return -1; } tpl->nameURI = ns->uri; Tcl_DStringInit (&dStr); Tcl_DStringAppend (&dStr, ns->uri, -1); Tcl_DStringAppend (&dStr, ":", 1); Tcl_DStringAppend (&dStr, localName, -1); h = Tcl_CreateHashEntry (&(xs->namedTemplates), Tcl_DStringValue (&dStr), &hnew); Tcl_DStringFree (&dStr); } else { h = Tcl_CreateHashEntry (&(xs->namedTemplates), localName, &hnew); } tpl->name = localName; if (!hnew) { t = (xsltTemplate *) Tcl_GetHashValue (h); if (t->precedence == precedence) { reportError (node, "There is already a template with the" " same name and precedence.", errMsg); FREE ((char*)tpl); return -1; } if (!t->match) { FREE ((char*)t); } } Tcl_SetHashValue (h, tpl); TRACE3("Added named Template '%s' '%2.2f' '%2.2f' \n\n", tpl->name, tpl->precedence, tpl->prio); } tpl->ast = NULL; tpl->mode = NULL; tpl->modeURI = NULL; str = getAttr (node, "mode", a_mode); if (str) { rc = 0; if (!domIsQNAME (str)) { reportError (node, "The value of the \"mode\" attribute must" " be a qname.", errMsg); rc = -1; } if (!tpl->match) { reportError (node, "A template without a \"match\" attribute must" " not have a \"mode\" attribute.", errMsg); rc = -1; } domSplitQName (str, prefix, &localName); if (prefix[0] != '\0') { ns = domLookupPrefix (node, prefix); if (ns) { tpl->modeURI = ns->uri; } else { reportError (node, "The prefix of the \"mode\" attribute value" " isn't bound to a namespace.", errMsg); rc = -1; } } tpl->mode = localName; if (rc < 0) { /* If the template has a name attribute, it is already * stored in the namedTemplates hash table and will be * freed. */ if (!tpl->name) { FREE ((char*)tpl); } return -1; } } 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 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; TRACE1("compiling XPath '%s' ...\n", tpl->match); if (tpl->match) { rc = xpathParse(tpl->match, node, XPATH_TEMPMATCH_PATTERN, NULL, NULL, &(tpl->freeAst), errMsg); if (rc < 0) { reportError (node, *errMsg, errMsg); } else { rc = addMatch (xs, node, tpl, prioStr, tpl->freeAst, errMsg); } if (rc < 0) { if (tpl->name) { /* The template is already stored in the namedTemplates hash table. Therefore, we don't free tpl here, but set tpl->match to NULL, which ensures, that the tpl will be freed while the namedTemplates hash table is cleaned up. */ tpl->match = NULL; } else { FREE ((char*)tpl); } return rc; } } return 0; } /*---------------------------------------------------------------------------- | ExecUseAttributeSets | \---------------------------------------------------------------------------*/ static int ExecUseAttributeSets ( xsltState * xs, xpathResultSet * context, domNode * currentNode, domLength currentPos, domNode * actionNode, char * styles, char ** errMsg ) { xsltAttrSet *attrSet; char *pc, *aSet, save, *str, prefix[MAX_PREFIX_LEN]; const char *localName; int rc; domNS *ns; pc = styles; while (*pc) { while (*pc && IS_XML_WHITESPACE(*pc)) pc++; if (*pc == '\0') break; aSet = pc; while (*pc && !IS_XML_WHITESPACE(*pc)) pc++; save = *pc; *pc = '\0'; TRACE1("use-attribute-set '%s' \n", aSet); attrSet = xs->attrSets; while (attrSet) { TRACE2("use-Attr: '%s' == '%s' ? \n", attrSet->name, aSet); rc = 0; if (!attrSet->uri) { if (strcmp(attrSet->name, aSet)==0) rc = 1; } else { domSplitQName (aSet, prefix, &localName); if (prefix[0] != '\0') { ns = domLookupPrefix (actionNode, prefix); if (ns) { if (strcmp (ns->uri, attrSet->uri)==0) { if (strcmp (attrSet->name, localName)==0) rc = 1; } } } } if (rc) { if (attrSet->inUse) { attrSet->inUse = 0; *pc = save; reportError(actionNode, "Circular reference " "to attribute set", errMsg); return -1; } attrSet->inUse = 1; str = getAttr (attrSet->content, "use-attribute-sets", a_useAttributeSets); if (str) { rc = ExecUseAttributeSets (xs, context, currentNode, currentPos, attrSet->content, str, errMsg); if (rc < 0) { attrSet->inUse = 0; *pc = save; return rc; } } rc = ExecActions(xs, context, currentNode, currentPos, attrSet->content->firstChild, errMsg); attrSet->inUse = 0; if (rc < 0) { attrSet->inUse = 0; *pc = save; return rc; } } attrSet = attrSet->next; } *pc = save; } return 0; } /*---------------------------------------------------------------------------- | evalAttrTemplates | \---------------------------------------------------------------------------*/ static int evalAttrTemplates ( xsltState * xs, xpathResultSet * context, domNode * currentNode, domLength currentPos, char * str, char ** out, char ** errMsg ) { xpathResultSet rs; char *tplStart = NULL, *tplResult, *pc, literalChar; domLength aLen, p = 0; int rc, inTpl = 0, inLiteral = 0; aLen = 500; *out = MALLOC(aLen); while (*str) { if (inTpl) { if (!inLiteral) { if (*str == '\'') { inLiteral = 1; literalChar = '\''; } else if (*str == '"') { inLiteral = 1; literalChar = '"'; } } else { if (*str == literalChar) { inLiteral = 0; } } if (*str == '}' && !inLiteral) { *str = '\0'; TRACE1("attrTpl: '%s' \n", tplStart); rc = evalXPath (xs, context, currentNode, currentPos, tplStart, &rs, errMsg); *str = '}'; CHECK_RC1(*out); tplResult = xpathFuncString( &rs ); DBG(fprintf(stderr, "attrTpl tplResult='%s' \n", tplResult);) xpathRSFree( &rs ); pc = tplResult; while (*pc) { (*out)[p++] = *pc++; if (p>=aLen) { /* enlarge output buffer */ *out = REALLOC(*out, 2*aLen); aLen += aLen; } } inTpl = 0; FREE(tplResult); } } else { if (*str == '{') { if (*(str+1) == '{') { /*----------------------------------------------------- | read over escaped '{': | '{{text text}}' -> '{text text}' \----------------------------------------------------*/ str++; (*out)[p++] = *str++; if (p>=aLen) { /* enlarge output buffer */ *out = REALLOC(*out, 2*aLen); aLen += aLen; } while (*str && (*str != '}') && (*(str-1) != '}')) { (*out)[p++] = *str++; if (p>=aLen) { /* enlarge output buffer */ *out = REALLOC(*out, 2*aLen); aLen += aLen; } } if (!*str) break; } else { tplStart = str+1; inTpl = 1; inLiteral = 0; } } else { if (*str == '}' && *(str+1) == '}') { str++; } (*out)[p++] = *str; if (p>=aLen) { /* enlarge output buffer */ *out = REALLOC(*out, 2*aLen); aLen += aLen; } } } str++; } (*out)[p] = '\0'; DBG(fprintf(stderr, "evalAttrTemplates out='%s' \n", (*out) );) return 0; } /*---------------------------------------------------------------------------- | setParamVars | \---------------------------------------------------------------------------*/ static int setParamVars ( xsltState * xs, xpathResultSet * context, domNode * currentNode, domLength currentPos, domNode * actionNode, char ** errMsg ) { domNode *child; char *str, *select; int rc; child = actionNode->firstChild; while (child) { if (child->nodeType == ELEMENT_NODE) { TRACE1("setParamVars child '%s' \n", child->nodeName); if (child->info == withParam) { str = getAttr(child, "name", a_name); if (str) { TRACE1("setting with-param '%s' \n", str); xs->currentXSLTNode = child; select = getAttr(child, "select", a_select); if (select && child->firstChild) { reportError (child, "An xsl:parameter element with a" " select attribute must be empty", errMsg); return -1; } TRACE1("with-param select='%s'\n", select); rc = xsltSetVar(xs, str, context, currentNode, currentPos, select, child, 0, errMsg); CHECK_RC; } else { reportError (child, "xsl:with-param: missing mandatory" " attribute \"name\".", errMsg); return -1; } } } child = child->nextSibling; } return 0; } /*---------------------------------------------------------------------------- | doSortActions | \---------------------------------------------------------------------------*/ static int doSortActions ( xsltState * xs, xpathResultSet * nodelist, domNode * actionNode, xpathResultSet * context, domNode * currentNode, domLength currentPos, char ** errMsg ) { domNode *child; char *str, *evStr, *select; /* todo */ /* char *lang; */ char **vs = NULL; char prefix[MAX_PREFIX_LEN]; const char *localName; double *vd = NULL; int rc = 0, typeText, ascending, upperFirst, NaN; domLength i, *pos = NULL; xpathResultSet rs; child = actionNode->lastChild; /* do it backwards, so that multiple sort levels are correctly processed */ while (child) { if (child->nodeType == ELEMENT_NODE) { TRACE1("doSortActions child '%s' \n", child->nodeName); if (child->info == sort) { if (child->firstChild) { reportError (child, "xsl:sort has to be empty.", errMsg); rc = -1; break; } typeText = 1; ascending = 1; upperFirst = 1; select = getAttr(child, "select", a_select); if (!select) select = "."; xs->currentXSLTNode = child; str = getAttr(child, "data-type", a_dataType); if (str) { rc = evalAttrTemplates (xs, context, currentNode, currentPos, str, &evStr, errMsg); CHECK_RC; if (strcmp(evStr,"text")==0) typeText = 1; else if (strcmp(evStr,"number")==0) typeText = 0; else { domSplitQName (evStr, prefix, &localName); if (prefix[0] == '\0') { reportError (child, "data-type must be text, " "number or a prefixed name", errMsg); FREE(evStr); rc = -1; break; } /* OK, so it is a legal value. But we currently don't support non-standard data-types. We use the default, that is typeText = 1. */ } FREE(evStr); } str = getAttr(child, "order", a_order); if (str) { rc = evalAttrTemplates (xs, context, currentNode, currentPos, str, &evStr, errMsg); CHECK_RC; if (strcmp(evStr,"descending")==0) ascending = 0; else if (strcmp(evStr, "ascending")==0) ascending = 1; else { reportError (child, "order must be ascending or" " descending", errMsg); FREE(evStr); rc = -1; break; } FREE(evStr); } str = getAttr(child, "case-order", a_caseorder); if (str) { rc = evalAttrTemplates (xs, context, currentNode, currentPos, str, &evStr, errMsg); CHECK_RC; if (strcmp(evStr,"lower-first")==0) upperFirst = 0; else if (strcmp(evStr, "upper-first")==0) upperFirst = 1; else { reportError (child, "case-order must be lower-first" " or upper-first", errMsg); FREE(evStr); rc = -1; break; } FREE(evStr); } /* jcl: TODO */ /* lang = getAttr(child, "lang", a_lang); */ /* The getAttr call should be done, to set attr->info to the attribute type for faster checks in further runs */ getAttr(child, "lang", a_lang); TRACE4("sorting with '%s' typeText %d ascending %d nodeSetLen=%d\n", select, typeText, ascending, nodelist->nr_nodes); CHECK_RC; if (!pos) pos = (domLength*)MALLOC(sizeof(int) * nodelist->nr_nodes); for (i=0; inr_nodes;i++) pos[i] = i; xs->currentXSLTNode = child; if (!vs) { vs = (char **)MALLOC(sizeof (char *) * nodelist->nr_nodes); for (i=0; inr_nodes;i++) vs[i] = NULL; vd = (double *)MALLOC(sizeof (double) * nodelist->nr_nodes); for (i=0; inr_nodes;i++) vd[i] = 0.0; } for (i = 0; i < nodelist->nr_nodes; i++) { xpathRSInit (&rs); rc = evalXPath (xs, nodelist, nodelist->nodes[i], i, select, &rs, errMsg); if (rc < 0) goto doSortActionCleanUp; if (typeText) { vs[i] = xpathFuncString (&rs); } else { vd[i] = xpathFuncNumber (&rs, &NaN); } xpathRSFree (&rs); } rc = sortNodeSetFastMerge (typeText, ascending, upperFirst, nodelist->nodes, nodelist->nr_nodes, vs, vd, pos, errMsg); if (typeText) { for (i = 0; i < nodelist->nr_nodes; i++) { FREE(vs[i]); } } if (rc < 0) goto doSortActionCleanUp; } } child = child->previousSibling; } doSortActionCleanUp: if (pos) FREE((char*)pos); if (vs) FREE((char*)vs); if (vd) FREE((char*)vd); return rc; } /*---------------------------------------------------------------------------- | xsltNumber | \---------------------------------------------------------------------------*/ static int xsltNumber ( xsltState * xs, xpathResultSet * context, domNode * currentNode, domLength currentPos, domNode * actionNode, char ** errMsg ) { xpathResultSet rs; int rc, NaN, hnew, i, useFormatToken; domLength vs[20], *v, *vd = NULL, vVals = 0; long groupingSize = 0; char *value, *level, *count, *from, *str, *str1, *format; char *groupingSeparator = NULL, *groupingSizeStr = NULL; char *tail; ast t_count, t_from; domNode *node, *start; Tcl_HashEntry *h; xsltNumberFormat *f; Tcl_DString dStr; domProcessingInstructionNode *pi; v = vs; value = getAttr(actionNode, "value", a_value); str = getAttr(actionNode, "format", a_format); if (!str) str = "1"; xs->currentXSLTNode = actionNode; rc = evalAttrTemplates( xs, context, currentNode, currentPos, str, &format, errMsg); CHECK_RC; f = xsltNumberFormatTokenizer (xs, format, errMsg); if (!f) { FREE(format); return -1; } str = getAttr(actionNode, "grouping-separator", a_groupingSeparator); if (str) { str1 = getAttr (actionNode, "grouping-size", a_groupingSize); if (str1) { rc = evalAttrTemplates (xs, context, currentNode, currentPos, str, &groupingSeparator, errMsg); if (rc < 0) goto xsltNumberError; rc = evalAttrTemplates (xs, context, currentNode, currentPos, str1, &groupingSizeStr, errMsg); if (rc < 0) goto xsltNumberError; groupingSize = strtol (groupingSizeStr, &tail, 10); if (groupingSize <= 0) { /* This covers both cases: non integer value after evaluation and wrong (<= 0) integer value. */ reportError (actionNode, "The value of \"grouping-size\" must" " evaluate to a positive integer.", errMsg); goto xsltNumberError; } } } if (value) { TRACE2("xsltNumber value='%s' format='%s' \n", value, format); rc = evalXPath(xs, context, currentNode, currentPos, value, &rs, errMsg); if (rc < 0) goto xsltNumberError; vVals = 1; v[0] = xpathRound(xpathFuncNumber( &rs, &NaN )); /* MARK recoverable error */ /* This is one of the not so satisfying corners of the XSLT * rec. The rec doesn't say, what to do, if the value isn't a * (finit) number. E24 from the erratas doesn't makes things * much better - a little bit dubious wording and a not very * convincing decision. Well, at least saxon seems to follow * the words of E24. I'll postpone this topic. */ if (NaN) v[0] = 0; xpathRSFree( &rs ); } else { level = getAttr(actionNode, "level", a_level); if (!level) level = "single"; count = getAttr(actionNode, "count", a_count); from = getAttr(actionNode, "from", a_from); TRACE3("xsltNumber format='%s' count='%s' from='%s' \n", format, count, from); if (count) { h = Tcl_CreateHashEntry (&(xs->pattern), count, &hnew); if (!hnew) { t_count = (ast) Tcl_GetHashValue (h); } else { rc = xpathParse (count, actionNode, XPATH_FORMAT_PATTERN, NULL, NULL, &t_count, errMsg); if (rc < 0) goto xsltNumberError; Tcl_SetHashValue (h, t_count); } } else { Tcl_DStringInit (&dStr); if (currentNode->nodeType == ELEMENT_NODE) { if (!currentNode->parentNode && currentNode == currentNode->ownerDocument->rootNode) { Tcl_DStringAppend (&dStr, "/", 1); } else { /* TODO: This is wrong. Instead this should use the "expanded-name" of the current node. */ Tcl_DStringAppend (&dStr, currentNode->nodeName, -1); } } else if (currentNode->nodeType == ATTRIBUTE_NODE) { Tcl_DStringAppend (&dStr, "@", 1); Tcl_DStringAppend (&dStr, currentNode->nodeName, -1); } else if (currentNode->nodeType == COMMENT_NODE) { Tcl_DStringAppend (&dStr, "comment()", -1); } else if (currentNode->nodeType == TEXT_NODE) { Tcl_DStringAppend (&dStr, "text()", -1); } else if (currentNode->nodeType == PROCESSING_INSTRUCTION_NODE) { Tcl_DStringAppend (&dStr, "processing-instruction('", -1); pi = (domProcessingInstructionNode *)currentNode; Tcl_DStringAppend (&dStr, pi->targetValue, pi->targetLength); Tcl_DStringAppend (&dStr, "')", 2); } else { reportError (actionNode, "unknown node type!!!", errMsg); return -1; } h = Tcl_CreateHashEntry (&(xs->pattern), Tcl_DStringValue(&dStr), &hnew); if (!hnew) { t_count = (ast) Tcl_GetHashValue (h); } else { rc = xpathParse (Tcl_DStringValue (&dStr), actionNode, XPATH_FORMAT_PATTERN, NULL, NULL, &t_count, errMsg); if (rc < 0) { Tcl_DStringFree (&dStr); goto xsltNumberError; } Tcl_SetHashValue (h, t_count); } Tcl_DStringFree (&dStr); } if (from) { h = Tcl_CreateHashEntry (&(xs->pattern), from, &hnew); if (!hnew) { t_from = (ast) Tcl_GetHashValue (h); } else { rc = xpathParse (from, actionNode, XPATH_FORMAT_PATTERN, NULL, NULL, &t_from, errMsg); if (rc < 0) goto xsltNumberError; Tcl_SetHashValue (h, t_from); } } if (strcmp (level, "single")==0) { node = currentNode; start = NULL; if (from) { while (node) { rc = xpathMatches (t_from, actionNode, node, &(xs->cbs), errMsg); if (rc < 0) goto xsltNumberError; if (rc) break; if (node->nodeType == ATTRIBUTE_NODE) node = ((domAttrNode *)node)->parentNode; else node = node->parentNode; } } node = currentNode; while (node != start) { rc = xpathMatches (t_count, actionNode, node, &(xs->cbs), errMsg); if (rc < 0) goto xsltNumberError; if (rc) break; if (node->nodeType == ATTRIBUTE_NODE) node = ((domAttrNode *)node)->parentNode; else node = node->parentNode; } if (node == start) { domAppendNewTextNode (xs->lastNode, "", 0, TEXT_NODE, 0); FREE(format); return 0; } else { vVals = 1; v[0] = 1; node = domPreviousSibling (node); while (node) { rc = xpathMatches (t_count, actionNode, node, &(xs->cbs), errMsg); if (rc < 0) goto xsltNumberError; if (rc) v[0]++; node = domPreviousSibling (node); } } } else if (strcmp (level, "multiple")==0) { xpathRSInit (&rs); node = currentNode; while (node) { if (from) { rc = xpathMatches (t_from, actionNode, node, &(xs->cbs), errMsg); if (rc < 0) goto xsltNumberError; if (rc) break; } rc = xpathMatches (t_count, actionNode, node, &(xs->cbs), errMsg); if (rc < 0) goto xsltNumberError; if (rc) rsAddNode (&rs, node); if (node->nodeType == ATTRIBUTE_NODE) node = ((domAttrNode *)node)->parentNode; else node = node->parentNode; } if (rs.nr_nodes > 20) { vd = (domLength *)MALLOC(sizeof (domLength) * rs.nr_nodes); v = vd; } vVals = rs.nr_nodes; v[0] = 0; for (i = 0; i < rs.nr_nodes; i++) { node = domPreviousSibling (rs.nodes[i]); v[i] = 1; while (node) { rc = xpathMatches (t_count, actionNode, node, &(xs->cbs), errMsg); if (rc < 0) goto xsltNumberError; if (rc) v[i]++; node = domPreviousSibling (node); } } xpathRSFree (&rs); } else if (strcmp (level, "any")==0) { v[0] = 0; vVals = 1; node = currentNode; while (node) { if (from) { rc = xpathMatches (t_from, actionNode, node, &(xs->cbs), errMsg); if (rc < 0) goto xsltNumberError; if (rc) break; } rc = xpathMatches (t_count, actionNode, node, &(xs->cbs), errMsg); if (rc < 0) goto xsltNumberError; if (rc) v[0]++; if (domPreviousSibling (node)) { node = domPreviousSibling (node); while ((node->nodeType == ELEMENT_NODE) && node->lastChild) { node = node->lastChild; } continue; } if (node->nodeType == ATTRIBUTE_NODE) { node = ((domAttrNode *)node)->parentNode; } else { node = node->parentNode; } } } else { reportError (actionNode, "xsl:number: Wrong \"level\" attribute" " value!", errMsg); goto xsltNumberError; } } Tcl_DStringInit (&dStr); useFormatToken = 0; if (f->prologLen) { Tcl_DStringAppend (&dStr, f->formatStr, f->prologLen); } for (i = 0; i < vVals -1; i++) { formatValue (f, &useFormatToken, v[i], &dStr, groupingSeparator, groupingSize, 1); } if (vVals > 0) { formatValue (f, &useFormatToken, v[vVals-1], &dStr, groupingSeparator, groupingSize, 0); if (f->epilogLen) { Tcl_DStringAppend (&dStr, f->epilogStart, f->epilogLen); } domAppendNewTextNode(xs->lastNode, Tcl_DStringValue (&dStr), Tcl_DStringLength (&dStr), TEXT_NODE, 0); } FREE(format); if (groupingSeparator) FREE (groupingSeparator); if (groupingSizeStr) FREE (groupingSizeStr); if (vd) { FREE((char *)vd); } Tcl_DStringFree (&dStr); return 0; xsltNumberError: if (format) FREE (format); if (groupingSeparator) FREE (groupingSeparator); if (groupingSizeStr) FREE (groupingSizeStr); return -1; } /*---------------------------------------------------------------------------- | ExecAction | \---------------------------------------------------------------------------*/ static int ExecAction ( xsltState * xs, xpathResultSet * context, domNode * currentNode, domLength currentPos, domNode * actionNode, char ** errMsg ) { domNode *child, *n, *n1, *savedLastNode, *fragmentNode; xsltTemplate *tpl, *currentTplRule, *tplChoosen; domAttrNode *attr, *attr1; domTextNode *tnode; domNS *ns, *ns1; xsltSubDoc *sDoc, *currentSubDoc; xsltExclExtNS *eNS; xsltNSAlias *nsAlias; Tcl_DString dStr; domProcessingInstructionNode *pi; xpathResultSet rs, nodeList; char *str, *str2, *select, *pc, *nsAT, *out; const char *mode, *modeURI, *localName, *uri, *nsStr; char prefix[MAX_PREFIX_LEN], tmpErr[200]; int rc, b, i, terminate, chooseState, disableEsc = 0; domLength len; double currentPrio, currentPrec; Tcl_HashEntry *h; if (actionNode->nodeType == TEXT_NODE) { domAppendNewTextNode(xs->lastNode, ((domTextNode*)actionNode)->nodeValue, ((domTextNode*)actionNode)->valueLength, TEXT_NODE, 0); return 0; } if (actionNode->nodeType != ELEMENT_NODE) return 0; TRACE1("\nExecAction '%s' \n", actionNode->nodeName); DBG (printXML (currentNode, 3, 5);) xs->currentXSLTNode = actionNode; switch ( actionNode->info ) { case applyImports: if (actionNode->firstChild) { reportError(actionNode, "xsl:apply-imports has to be empty!", errMsg); return -1; } if (!xs->currentTplRule) { reportError(actionNode, "xsl:apply-imports not allowed here!", errMsg); return -1; } tplChoosen = NULL; currentPrio = -100000.0; currentPrec = 0.0; mode = xs->currentTplRule->mode; modeURI = xs->currentTplRule->modeURI; if (currentNode->nodeType == ELEMENT_NODE) { Tcl_DStringInit (&dStr); if (currentNode->namespace) { domSplitQName (currentNode->nodeName, prefix, &localName); Tcl_DStringAppend (&dStr, domNamespaceURI (currentNode), -1); Tcl_DStringAppend (&dStr, ":", 1); } if (mode) { if (modeURI) { Tcl_DStringAppend (&dStr, modeURI, -1); Tcl_DStringAppend (&dStr, ":", 1); } Tcl_DStringAppend (&dStr, mode, -1); Tcl_DStringAppend (&dStr, ":", 1); } if (currentNode->namespace) { Tcl_DStringAppend (&dStr, localName, -1); } else { Tcl_DStringAppend (&dStr, currentNode->nodeName, -1); } h = Tcl_FindHashEntry (&xs->isElementTpls, Tcl_DStringValue (&dStr)); Tcl_DStringFree (&dStr); if (h) { for (tpl = (xsltTemplate *) Tcl_GetHashValue (h); tpl != NULL; tpl = tpl->next) { if (tpl->precedence >= xs->currentTplRule->precedence || tpl == xs->currentTplRule) continue; TRACE3("testing element tpl match='%s' mode='%s' name='%s'\n", tpl->match, tpl->mode, tpl->name); TRACE4("tpl has prio='%f' precedence='%f'\n", tpl->prio, tpl->precedence, currentPrio, currentPrec); rc = xpathMatches ( tpl->ast, actionNode, currentNode, &(xs->cbs), errMsg); if (rc < 0) { TRACE1("xpathMatches had errors '%s' \n", *errMsg); return rc; } if (rc == 0) continue; TRACE3("matching '%s': %f > %f ? \n", tpl->match, tpl->prio , currentPrio); tplChoosen = tpl; currentPrio = tpl->prio; currentPrec = tpl->precedence; break; } } } TRACE2("apply-imports: current template precedence='%f' mode='%s'\n", xs->currentTplRule->precedence, xs->currentTplRule->mode); for (tpl = xs->templates; tpl != NULL; tpl = tpl->next) { TRACE4("testing tpl match='%s' mode='%s' modeURI='%s' name='%s'\n", tpl->match, tpl->mode, tpl->modeURI, tpl->name); /* exclude those, which don't match the current mode and the currentTplRule */ if ( ( mode && !tpl->mode) || (!mode && tpl->mode) || ( mode && tpl->mode && (strcmp(mode,tpl->mode)!=0)) || (!modeURI && tpl->modeURI) || ( modeURI && !tpl->modeURI) || ( modeURI && tpl->modeURI && (strcmp(modeURI, tpl->modeURI)!=0)) || (tpl == xs->currentTplRule) ) { TRACE("doesn't match mode\n"); continue; } TRACE4("tpl has prio='%f' precedence='%f', currentPrio='%f', currentPrec='%f'\n", tpl->prio, tpl->precedence, currentPrio, currentPrec); if (tpl->match && tpl->precedence < xs->currentTplRule->precedence && tpl->precedence >= currentPrec) { if (tpl->precedence > currentPrec || tpl->prio >= currentPrio) { rc = xpathMatches (tpl->ast, actionNode, currentNode, &(xs->cbs), errMsg); CHECK_RC; if (rc == 0) continue; TRACE3("matching '%s': %f > %f ? \n", tpl->match, tpl->prio , currentPrio); tplChoosen = tpl; currentPrec = tpl->precedence; currentPrio = tpl->prio; TRACE1("TAKING '%s' \n", tpl->match); } } } if (tplChoosen == NULL) { TRACE("nothing matches -> execute built-in template \n"); /*-------------------------------------------------------------------- | execute built-in template \-------------------------------------------------------------------*/ if (currentNode->nodeType == TEXT_NODE) { domAppendNewTextNode(xs->lastNode, ((domTextNode*)currentNode)->nodeValue, ((domTextNode*)currentNode)->valueLength, TEXT_NODE, 0); break; } else if (currentNode->nodeType == ELEMENT_NODE) { child = currentNode->firstChild; } else if (currentNode->nodeType == ATTRIBUTE_NODE) { domAppendNewTextNode (xs->lastNode, ((domAttrNode*)currentNode)->nodeValue, ((domAttrNode*)currentNode)->valueLength, TEXT_NODE, 0); break; } else { /* for all other node we don't have to recurse deeper */ break; } xpathRSInit( &rs ); while (child) { rsAddNodeFast ( &rs, child); child = child->nextSibling; } rc = ApplyTemplates (xs, context, currentNode, currentPos, actionNode, &rs, mode, modeURI, errMsg); xpathRSFree( &rs ); CHECK_RC; break; } xsltPushVarFrame (xs); SETSCOPESTART; currentTplRule = xs->currentTplRule; currentSubDoc = xs->currentSubDoc; xs->currentTplRule = tplChoosen; xs->currentSubDoc = tplChoosen->sDoc; rc = ExecActions(xs, context, currentNode, currentPos, tplChoosen->content->firstChild, errMsg); xsltPopVarFrame (xs); CHECK_RC; xs->currentTplRule = currentTplRule; xs->currentSubDoc = currentSubDoc; break; case applyTemplates: mode = NULL; modeURI = NULL; str = getAttr (actionNode, "mode", a_mode); if (str) { domSplitQName (str, prefix, &localName); if (prefix[0] != '\0') { ns = domLookupPrefix (actionNode, prefix); if (!ns) { reportError (actionNode, "The prefix of the \"name\"" " attribute value isn't bound to a" " namespace.", errMsg); return -1; } modeURI = ns->uri; } mode = localName; } select = getAttr(actionNode, "select", a_select); if (!select) { xpathRSInit (&rs); if (currentNode->nodeType == ELEMENT_NODE) { child = currentNode->firstChild; while (child) { rsAddNodeFast (&rs, child); child = child->nextSibling; } } } else { xpathRSInit( &nodeList ); rsAddNodeFast( &nodeList, currentNode ); DBG(rsPrint( &nodeList )); TRACE2("applyTemplates: select = '%s' mode='%s'\n", select, mode); rc = evalXPath(xs, &nodeList, currentNode, 1, select, &rs, errMsg); xpathRSFree( &nodeList ); CHECK_RC; TRACE1("applyTemplates: evalXPath for select = '%s' gave back:\n", select); DBG(rsPrint(&rs)); } if (rs.type == EmptyResult) break; else if (rs.type != xNodeSetResult) { reportError (actionNode, "The \"select\" expression of" " xsl:apply-templates elements must evaluate to" " a node set.", errMsg); xpathRSFree (&rs); return -1; } rc = doSortActions (xs, &rs, actionNode, context, currentNode, currentPos, errMsg); if (rc < 0) { xpathRSFree (&rs); return rc; } /* should not be necessary, because every node set is returned already in doc Order */ /* if (!sorted) sortByDocOrder(&rs); */ TRACE1(" evalXPath for select = '%s': (SORTED)\n", select); DBG(rsPrint(&rs)); rc = ApplyTemplates(xs, context, currentNode, currentPos, actionNode, &rs, mode, modeURI, errMsg); xpathRSFree( &rs ); CHECK_RC; break; case attribute: if (xs->lastNode->firstChild) { /* Adding an Attribute to an element after children have been added to it is an error. Ignore the attribute. */ break; } nsAT = getAttr(actionNode, "namespace", a_namespace); str = getAttr(actionNode, "name", a_name); if (!str) { reportError (actionNode, "xsl:attribute: missing mandatory" " attribute \"name\".", errMsg); return -1; } rc = evalAttrTemplates( xs, context, currentNode, currentPos, str, &str2, errMsg); CHECK_RC; domSplitQName (str2, prefix, &localName); if ((prefix[0] != '\0' && !domIsNCNAME (prefix)) || !domIsNCNAME (localName)) { reportError (actionNode, "xsl:attribute: Attribute name is not" " a valid QName.", errMsg); FREE(str2); return -1; } out = NULL; if (nsAT) { rc = evalAttrTemplates( xs, context, currentNode, currentPos, nsAT, &out, errMsg); CHECK_RC1(str2); } Tcl_DStringInit (&dStr); if (prefix[0] == '\0' && (strcmp(str2, "xmlns")==0)) { goto ignoreAttribute; } /* It isn't allowed to create namespace attributes with xsl:attribute, a "xmlns" prefix must be rewritten; see XSLT rec 7.1.3 */ if (prefix[0] && (strcmp(prefix, "xmlns")==0)) { sprintf (prefix, "ns%d", xs->nsUniqeNr++); Tcl_DStringAppend (&dStr, prefix, -1); Tcl_DStringAppend (&dStr, ":", 1); Tcl_DStringAppend (&dStr, localName, -1); } else { if (out) { if (out[0] == '\0') { if (prefix[0] != '\0') { Tcl_DStringAppend (&dStr, localName, -1); } else { Tcl_DStringAppend (&dStr, str2, -1); } FREE(out); out = NULL; } else { if (prefix[0] == '\0') { ns = domLookupURI (xs->lastNode, out); if (ns && (ns->prefix[0] != '\0')) { Tcl_DStringAppend (&dStr, ns->prefix, -1); Tcl_DStringAppend (&dStr, ":", 1); } else { sprintf (prefix, "ns%d", xs->nsUniqeNr++); Tcl_DStringAppend (&dStr, prefix, -1); Tcl_DStringAppend (&dStr, ":", 1); } } Tcl_DStringAppend (&dStr, str2, -1); } } else { if (prefix[0] != '\0') { ns = domLookupPrefix (actionNode, prefix); if (ns) out = tdomstrdup (ns->uri); else goto ignoreAttribute; } Tcl_DStringAppend (&dStr, str2, -1); } } savedLastNode = xs->lastNode; xs->lastNode = domNewElementNode (xs->resultDoc, "container"); xsltPushVarFrame (xs); rc = ExecActions(xs, context, currentNode, currentPos, actionNode->firstChild, errMsg); xsltPopVarFrame (xs); if (rc < 0) { if (out) FREE(out); FREE(str2); return rc; } pc = xpathGetStringValue (xs->lastNode, &len); DBG(fprintf (stderr, "xsl:attribute: create attribute \"%s\" with value \"%s\" in namespace \"%s\"\n", Tcl_DStringValue (&dStr), pc, out);) domSetAttributeNS (savedLastNode, Tcl_DStringValue (&dStr), pc, out, 1); FREE(pc); Tcl_DStringFree (&dStr); domDeleteNode (xs->lastNode, NULL, NULL); xs->lastNode = savedLastNode; ignoreAttribute: if (out) FREE(out); FREE(str2); break; case attributeSet: reportError (actionNode, "xsl:attribute-set is only allowed at" " top-level.", errMsg); return -1; case callTemplate: tplChoosen = NULL; currentPrec = INT_MIN; str = getAttr(actionNode, "name", a_name); if (!str) { reportError (actionNode, "xsl:call-template must have a" " \"name\" attribute", errMsg); return -1; } domSplitQName (str, prefix, &localName); uri = NULL; if (prefix[0] != '\0') { ns = domLookupPrefix (actionNode, prefix); if (!ns) { reportError (actionNode, "The prefix of the \"name\"" " attribute value isn't bound to a" " namespace.", errMsg); return -1; } uri = ns->uri; } if (uri) { Tcl_DStringInit (&dStr); Tcl_DStringAppend (&dStr, uri, -1); Tcl_DStringAppend (&dStr, ":", 1); Tcl_DStringAppend (&dStr, localName, -1); h = Tcl_FindHashEntry (&(xs->namedTemplates), Tcl_DStringValue (&dStr)); Tcl_DStringFree (&dStr); } else { h = Tcl_FindHashEntry (&(xs->namedTemplates), localName); } if (!h) { reportError (actionNode, "xsl:call-template calls a non" " existing template!", errMsg); return -1; } tplChoosen = (xsltTemplate *) Tcl_GetHashValue (h); xsltPushVarFrame (xs); SETPARAMDEF; TRACE3("call template %s match='%s' name='%s' \n", localName, tplChoosen->match, tplChoosen->name); DBG(printXML(xs->lastNode, 0, 2);) rc = setParamVars (xs, context, currentNode, currentPos, actionNode, errMsg); if (rc < 0) { xsltPopVarFrame (xs); return rc; } currentSubDoc = xs->currentSubDoc; xs->currentSubDoc = tplChoosen->sDoc; SETSCOPESTART; rc = ExecActions(xs, context, currentNode, currentPos, tplChoosen->content->firstChild, errMsg); TRACE2("called template '%s': ApplyTemplate/ExecActions rc = %d \n", localName, rc); xsltPopVarFrame (xs); CHECK_RC; xs->currentSubDoc = currentSubDoc; DBG(printXML(xs->lastNode, 0, 2);) break; case choose: chooseState = 0; for( child = actionNode->firstChild; child != NULL; child = child->nextSibling) { if (child->nodeType != ELEMENT_NODE) continue; switch (child->info) { case when: if (chooseState > 1) { reportError (actionNode, "\"otherwise\" clause" " must be after all \"when\"" " clauses", errMsg); return -1; } else { chooseState = 1; } str = getAttr(child, "test", a_test); if (str) { TRACE1("checking when test '%s' \n", str); rc = evalXPath(xs, context, currentNode, currentPos, str, &rs, errMsg); CHECK_RC; b = xpathFuncBoolean( &rs ); xpathRSFree( &rs ); if (b) { TRACE("test is true!\n"); /* process the children as well */ xsltPushVarFrame (xs); rc = ExecActions(xs, context, currentNode, currentPos, child->firstChild, errMsg); xsltPopVarFrame (xs); CHECK_RC; return 0; } } else { reportError (child, "xsl:when: missing mandatory" " attribute \"test\".", errMsg); return -1; } break; case otherwise: if (chooseState != 1) { if (chooseState == 0) { reportError (actionNode, "\"choose\" must" " have at least one \"when\"" " clause", errMsg); } else { reportError (child, "only one \"otherwise\"" " clause allowed inside a" " \"choose\"", errMsg); } return -1; } else { chooseState = 2; } /* process the children as well */ xsltPushVarFrame (xs); rc = ExecActions(xs, context, currentNode, currentPos, child->firstChild, errMsg); xsltPopVarFrame (xs); CHECK_RC; break; default: reportError (actionNode, "only otherwise or when" " allowed in choose!", errMsg); return -1; } } if (chooseState == 0) { reportError (actionNode, "\"choose\" must have at least" " one \"when\" clause", errMsg); return -1; } break; case comment: fragmentNode = domNewElementNode(xs->resultDoc, ""); savedLastNode = xs->lastNode; xs->lastNode = fragmentNode; xsltPushVarFrame (xs); rc = ExecActions(xs, context, currentNode, currentPos, actionNode->firstChild, errMsg); xsltPopVarFrame (xs); CHECK_RC; child = fragmentNode->firstChild; while (child) { if (child->nodeType != TEXT_NODE) { domDeleteNode (fragmentNode, NULL, NULL); reportError (actionNode, "xsl:comment must not create" " nodes other than text nodes.", errMsg); return -1; } child = child->nextSibling; } str = xpathGetStringValue (fragmentNode, &len); if (!domIsComment (str)) { reportError (actionNode, "Invalid comment value", errMsg); domDeleteNode (fragmentNode, NULL, NULL); FREE(str); return -1; } xs->lastNode = savedLastNode; domAppendNewTextNode(xs->lastNode, str, len, COMMENT_NODE, 0); domDeleteNode (fragmentNode, NULL, NULL); FREE(str); break; case copy: DBG(if (currentNode->nodeType == ATTRIBUTE_NODE) { fprintf(stderr, "copy '%s' \n", ((domAttrNode*)currentNode)->nodeName); } else { fprintf(stderr, "copy '%s' \n", currentNode->nodeName); }) if (currentNode->nodeType == TEXT_NODE) { DBG(fprintf(stderr, "node is TEXT_NODE \n");) tnode = (domTextNode*)currentNode; n = (domNode*) domAppendNewTextNode(xs->lastNode, tnode->nodeValue, tnode->valueLength, TEXT_NODE, 0); } else if (currentNode->nodeType == ELEMENT_NODE) { DBG(fprintf(stderr, "node is ELEMENT_NODE \n");) savedLastNode = xs->lastNode; if (currentNode != currentNode->ownerDocument->rootNode) { n = domAppendNewElementNode(xs->lastNode, currentNode->nodeName, domNamespaceURI(currentNode) ); xs->lastNode = n; str = getAttr(actionNode, "use-attribute-sets", a_useAttributeSets); domCopyNS (currentNode, xs->lastNode); if (str) { rc = ExecUseAttributeSets (xs, context, currentNode, currentPos, actionNode, str, errMsg); CHECK_RC; } } /* process the children only for root and element nodes */ xsltPushVarFrame (xs); rc = ExecActions(xs, context, currentNode, currentPos, actionNode->firstChild, errMsg); xsltPopVarFrame (xs); CHECK_RC; xs->lastNode = savedLastNode; } else if (currentNode->nodeType == PROCESSING_INSTRUCTION_NODE) { pi = (domProcessingInstructionNode*)currentNode; n = (domNode*) domNewProcessingInstructionNode (xs->lastNode->ownerDocument, pi->targetValue, pi->targetLength, pi->dataValue, pi->dataLength); domAppendChild (xs->lastNode, n); } else if (currentNode->nodeType == COMMENT_NODE) { DBG(fprintf(stderr, "node is COMMENT_NODE \n");) tnode = (domTextNode *)currentNode; n = (domNode *) domAppendNewTextNode (xs->lastNode, tnode->nodeValue, tnode->valueLength, COMMENT_NODE, 0); } else if (currentNode->nodeType == ATTRIBUTE_NODE) { DBG(fprintf(stderr, "node is ATTRIBUTE_NODE \n");) if (xs->lastNode->firstChild) { /* Adding an Attribute to an element after children have been added to it is an error. Ignore the attribute. */ break; } if (xs->lastNode == xs->resultDoc->rootNode) { reportError (actionNode, "Cannot write an attribute" " when there is no open start tag", errMsg); return -1; } attr = (domAttrNode *)currentNode; domSetAttributeNS (xs->lastNode, attr->nodeName, attr->nodeValue, domNamespaceURI (currentNode), 1); } break; case copyOf: if (actionNode->firstChild) { reportError (actionNode, "xsl:copy-of has to be empty.", errMsg); return -1; } select = getAttr(actionNode, "select", a_select); if (!select) { reportError (actionNode, "xsl:copy-of: missing mandatory" " attribute \"select\".", errMsg); return -1; } rc = evalXPath(xs, context, currentNode, currentPos, select, &rs, errMsg); CHECK_RC; TRACE1(" copyOf select='%s':\n", select); DBG(rsPrint(&rs)); if (rs.type == xNodeSetResult) { for (i=0; inodeType == ATTRIBUTE_NODE) { if (xs->lastNode->firstChild) { /* Adding an Attribute to an element after children have been added to it is an error. Ignore the attribute. */ continue; } attr = (domAttrNode*)rs.nodes[i]; if (attr ->nodeFlags & IS_NS_NODE) { /* If someone selects explicitly namespace nodes to copy-of with e.g. namespace::* (remember: @* doesn't select namespace nodes), we must this handle separately.*/ /* The xmlns:xml namespace node will always be in scope, but never needed to be copied, because the result tree will also always already have it. To suppress, that the result tree gets glutted with xmlns:xml declarations (they would not harm, but ev. irritate some and are unnecessary, we check this here as a special case */ if (attr->namespace == 1) { continue; } ns = NULL; } else { ns = domGetNamespaceByIndex ( attr->parentNode->ownerDocument, attr->namespace ); } if (ns) uri = ns->uri; else uri = NULL; if (xs->lastNode == xs->resultDoc->rootNode) { reportError (actionNode, "Cannot write an" " attribute when there is no open" " start tag", errMsg); xpathRSFree (&rs); return -1; } domSetAttributeNS(xs->lastNode, attr->nodeName, attr->nodeValue, uri, 1); } else { if (*(rs.nodes[i]->nodeName) == '\0') { /* The rootNode of the Document or the rootNode of a result tree fragment */ child = rs.nodes[i]->firstChild; while (child) { domCopyTo(child, xs->lastNode, 1); child = child->nextSibling; } } else { domCopyTo (rs.nodes[i], xs->lastNode, 1); } } } } else { str = xpathFuncString( &rs ); TRACE1("copyOf: xpathString='%s' \n", str); domAppendNewTextNode(xs->lastNode, str, (domLength)strlen(str), TEXT_NODE, 0); FREE(str); } xpathRSFree( &rs ); break; case decimalFormat: reportError (actionNode, "xsl:decimal-format is only allowed" " at top-level.", errMsg); return -1; case element: nsAT = getAttr(actionNode, "namespace", a_namespace); str = getAttr(actionNode, "name", a_name); if (!str) { reportError (actionNode, "xsl:element: missing mandatory" " attribute \"name\".", errMsg); return -1; } rc = evalAttrTemplates( xs, context, currentNode, currentPos, str, &str2, errMsg); CHECK_RC; if (!domIsQNAME (str2)) { reportError (actionNode, "xsl:element: Element name is not a" " valid QName.", errMsg); FREE(str2); return -1; } out = NULL; nsStr = NULL; if (nsAT) { rc = evalAttrTemplates( xs, context, currentNode, currentPos, nsAT, &out, errMsg); CHECK_RC1(str2); nsStr = out; } else { domSplitQName (str2, prefix, &localName); if ((prefix[0] != '\0' && !domIsNCNAME (prefix)) || !domIsNCNAME (localName)) { reportError (actionNode, "xsl:element: Element name is" " not a valid QName.", errMsg); FREE(str2); return -1; } ns = domLookupPrefix (actionNode, prefix); if (ns) nsStr = ns->uri; else { if (prefix[0] != '\0') { reportError (actionNode, "xsl:element: there isn't" " a URI associated with the prefix of" " the element name.", errMsg); FREE(str2); return -1; } } } savedLastNode = xs->lastNode; xs->lastNode = domAppendNewElementNode (xs->lastNode, str2, nsStr); FREE(str2); if (nsAT) FREE(out); str = getAttr(actionNode, "use-attribute-sets", a_useAttributeSets); if (str) { TRACE1("use-attribute-sets = '%s' \n", str); rc = ExecUseAttributeSets (xs, context, currentNode, currentPos, actionNode, str, errMsg); CHECK_RC; } /* process the children as well */ if (actionNode->firstChild) { xsltPushVarFrame (xs); rc = ExecActions(xs, context, currentNode, currentPos, actionNode->firstChild, errMsg); xsltPopVarFrame (xs); } xs->lastNode = savedLastNode; CHECK_RC; break; case fallback: return 0; case forEach: select = getAttr(actionNode, "select", a_select); if (!select) { reportError (actionNode, "xsl:for-each: The select attribute" " is required.", errMsg); return -1; } DBG ( if (currentNode->nodeType == ELEMENT_NODE) { fprintf (stderr, "forEach select from Element Node '%s' domNode0x%x:\n", currentNode->nodeName, currentNode); if (currentNode->firstChild) { fprintf(stderr, "forEach select from child '%s' domNode0x%x:\n", currentNode->firstChild->nodeName, currentNode->firstChild); } } else if (currentNode->nodeType == ATTRIBUTE_NODE) { fprintf (stderr, "forEach select from Attribute Node '%s' Value '%s'\n", ((domAttrNode *)currentNode)->nodeName, ((domAttrNode *)currentNode)->nodeValue); } else { fprintf (stderr, "forEach select from nodetype %d\n", currentNode->nodeType); } ) xpathRSInit( &nodeList ); rsAddNodeFast( &nodeList, currentNode ); DBG(rsPrint( &nodeList )); rc = evalXPath(xs, &nodeList, currentNode, 1, select, &rs, errMsg); xpathRSFree (&nodeList); if (rc < 0) { return rc; } CHECK_RC; TRACE1("forEach: evalXPath for select = '%s' gave back:\n", select); DBG(rsPrint(&rs)); if (rs.type == xNodeSetResult) { rc = doSortActions (xs, &rs, actionNode, context, currentNode, currentPos, errMsg); if (rc < 0) { xpathRSFree (&rs); return rc; } /* should not be necessary, because every node set is returned already in doc Order */ /* if (!sorted) sortByDocOrder(&rs); */ TRACE1(" forEach for select = '%s': (SORTED)\n", select); DBG(rsPrint(&rs)); currentTplRule = xs->currentTplRule; xs->currentTplRule = NULL; xsltPushVarFrame (xs); for (i=0; ifirstChild, errMsg); if (rc < 0) { xsltPopVarFrame (xs); xpathRSFree( &rs ); return rc; } if ((&xs->varFramesStack[xs->varFramesStackPtr])->polluted) { xsltPopVarFrame (xs); xsltPushVarFrame (xs); } } xsltPopVarFrame (xs); xs->currentTplRule = currentTplRule; } else { if (rs.type != EmptyResult) { reportError (actionNode, "The \"select\" expression of" " xsl:for-each elements must evaluate to a" " node set.", errMsg); xpathRSFree (&rs); return -1; } } xpathRSFree( &rs ); break; case xsltIf: str = getAttr(actionNode, "test", a_test); if (str) { rc = evalXPath(xs, context, currentNode, currentPos, str, &rs, errMsg); CHECK_RC; b = xpathFuncBoolean( &rs ); xpathRSFree( &rs ); if (b) { /* process the children as well */ xsltPushVarFrame (xs); rc = ExecActions(xs, context, currentNode, currentPos, actionNode->firstChild, errMsg); xsltPopVarFrame (xs); CHECK_RC; } } else { reportError (actionNode, "xsl:if: missing mandatory attribute" " \"test\".", errMsg); return -1; } break; case import: reportError (actionNode, "xsl:import is only allowed at top-level.", errMsg); return -1; case include: reportError (actionNode, "xsl:include is only allowed at" " top-level.", errMsg); return -1; case key: reportError (actionNode, "xsl:key is only allowed at top-level.", errMsg); return -1; case message: str = getAttr(actionNode,"terminate", a_terminate); if (!str) terminate = 0; else if (strcmp (str, "yes") == 0) terminate = 1; else if (strcmp (str, "no") == 0) terminate = 0; else { reportError (actionNode, "Allowed values for the 'terminate'" "attribute: 'yes' or 'no'", errMsg); return -1; } fragmentNode = domNewElementNode(xs->resultDoc, ""); savedLastNode = xs->lastNode; xs->lastNode = fragmentNode; xsltPushVarFrame (xs); rc = ExecActions(xs, context, currentNode, currentPos, actionNode->firstChild, errMsg); xsltPopVarFrame (xs); CHECK_RC; str2 = xpathGetStringValue(fragmentNode, &len); rc = xs->xsltMsgCB (xs->xsltMsgClientData, str2, len, terminate); FREE(str2); xs->lastNode = savedLastNode; domDeleteNode (fragmentNode, NULL, NULL); if (terminate) { reportError (actionNode, "xsl:message with attribute" " \"terminate\"=\"yes\"", errMsg); return -1; } switch (rc) { case 0: return 0; case 3: reportError (actionNode, "", errMsg); return -1; default: sprintf (tmpErr, "Error while executing message callback." " Message callback result code: %d", rc); reportError (actionNode, tmpErr, errMsg); return -1; } case namespaceAlias: reportError (actionNode, "xsl:namespaceAlias is only allowed" " at top-level.", errMsg); return -1; case number: if (actionNode->firstChild) { reportError (actionNode, "xsl:number has to be empty.", errMsg); return -1; } rc = xsltNumber(xs, context, currentNode, currentPos, actionNode, errMsg); CHECK_RC; break; case output: return 0; case otherwise: reportError (actionNode, "xsl:otherwise must be immediately" " within xsl:choose", errMsg); return -1; case param: str = getAttr(actionNode, "name", a_name); if (str) { TRACE1("setting param '%s' ??\n", str); if (!xsltVarExists(xs, str, actionNode)) { TRACE1("setting param '%s': yes \n", str); select = getAttr(actionNode, "select", a_select); if (select && actionNode->firstChild) { reportError (actionNode, "An xsl:parameter element " " with a select attribute must be empty", errMsg); return -1; } TRACE1("param select='%s'\n", select); rc = xsltSetVar(xs, str, context, currentNode, currentPos, select, actionNode, 1, errMsg); CHECK_RC; } } else { reportError (actionNode, "xsl:param: missing mandatory " " attribute \"name\".", errMsg); return -1; } break; case preserveSpace: return 0; case procinstr: str = getAttr(actionNode, "name", a_name); if (str) { rc = evalAttrTemplates( xs, context, currentNode, currentPos, str, &str2, errMsg); CHECK_RC; if (!domIsPINAME (str2) || !domIsNCNAME(str2)) { reportError (actionNode, "xsl:processing-instruction: " "Processing instruction name is invalid.", errMsg); FREE(str2); return -1; } } else { reportError (actionNode, "xsl:processing-instruction:" " missing mandatory attribute \"name\".", errMsg); return -1; } fragmentNode = domNewElementNode(xs->resultDoc, ""); savedLastNode = xs->lastNode; xs->lastNode = fragmentNode; xsltPushVarFrame (xs); rc = ExecActions(xs, context, currentNode, currentPos, actionNode->firstChild, errMsg); xsltPopVarFrame (xs); CHECK_RC; child = fragmentNode->firstChild; while (child) { if (child->nodeType != TEXT_NODE) { domDeleteNode (fragmentNode, NULL, NULL); reportError (actionNode, "xsl:processing-instruction must " "not create nodes other than text nodes.", errMsg); FREE(str2); return -1; } child = child->nextSibling; } str = xpathGetStringValue (fragmentNode, &len); if (!domIsPIValue (str)) { reportError (actionNode, "Invalid processing instruction " "value", errMsg); domDeleteNode (fragmentNode, NULL, NULL); FREE(str); FREE(str2); return -1; } xs->lastNode = savedLastNode; n = (domNode*)domNewProcessingInstructionNode( xs->resultDoc, str2, (domLength)strlen(str2), str, len); domAppendChild(xs->lastNode, n); domDeleteNode (fragmentNode, NULL, NULL); FREE(str2); FREE(str); break; case sort: case stylesheet: case stripSpace: case template: return 0; case text: str = getAttr(actionNode, "disable-output-escaping", a_disableOutputEscaping); if (str) { if (strcmp (str, "yes")==0) disableEsc = 1; } pc = xpathGetStringValue (actionNode, &len); DBG(fprintf(stderr, "text: pc='%s'%d \n", pc, len);) domAppendNewTextNode(xs->lastNode, pc, len, TEXT_NODE, disableEsc); FREE(pc); break; case transform: return 0; case valueOf: if (actionNode->firstChild) { reportError (actionNode, "xsl:value-of has to be empty.", errMsg); return -1; } str = getAttr(actionNode, "disable-output-escaping", a_disableOutputEscaping); if (str) { if (strcmp (str, "yes")==0) disableEsc = 1; } str = getAttr(actionNode, "select", a_select); if (str) { TRACE1("valueOf: str='%s' \n", str); rc = evalXPath(xs, context, currentNode, currentPos, str, &rs, errMsg); CHECK_RC; DBG(rsPrint(&rs)); str = xpathFuncString( &rs ); TRACE1("valueOf: xpathString='%s' \n", str); domAppendNewTextNode(xs->lastNode, str, (domLength)strlen(str), TEXT_NODE, disableEsc); xpathRSFree( &rs ); FREE(str); } else { reportError (actionNode, "xsl:value-of must have a" " \"select\" attribute!", errMsg); return -1; } break; case variable: str = getAttr(actionNode, "name", a_name); if (str) { if (xsltVarExists (xs, str, actionNode)) { Tcl_DStringInit (&dStr); Tcl_DStringAppend (&dStr, "Variable '", -1); Tcl_DStringAppend (&dStr, str, -1); Tcl_DStringAppend ( &dStr, "' is already declared in this template", -1); reportError (actionNode, Tcl_DStringValue (&dStr), errMsg); return -1; } select = getAttr(actionNode, "select", a_select); if (select && actionNode->firstChild) { reportError (actionNode, "An xsl:variable element with a" " select attribute must be empty", errMsg); return -1; } TRACE1("variable select='%s'\n", select); rc = xsltSetVar(xs, str, context, currentNode, currentPos, select, actionNode, 1, errMsg); CHECK_RC; } else { reportError (actionNode, "xsl:variable must have a \"name\"" " attribute!", errMsg); return -1; } break; case when: reportError (actionNode, "xsl:when must be immediately within" " xsl:choose", errMsg); return -1; case withParam: return 0; default: sDoc = xs->currentSubDoc; if (actionNode->namespace) { ns = actionNode->ownerDocument->namespaces[actionNode->namespace - 1]; eNS = sDoc->extensionNS; while (eNS) { if (eNS->uri) { if (strcmp (eNS->uri, ns->uri)==0) break; } else { if (ns->prefix[0] == '\0') break; } eNS = eNS->next; } if (eNS) { /* An extension element; process fallback */ child = actionNode->firstChild; while (child) { if (child->info == fallback) { xsltPushVarFrame (xs); rc = ExecActions (xs, context, currentNode, currentPos, child->firstChild, errMsg); xsltPopVarFrame (xs); CHECK_RC; } child = child->nextSibling; } return 0; } } savedLastNode = xs->lastNode; DBG(fprintf(stderr, "append new tag '%s' uri='%s' \n", actionNode->nodeName, domNamespaceURI(actionNode) );); xs->lastNode = domAppendLiteralNode (xs->lastNode, actionNode); n = actionNode; while (n) { attr = n->firstAttr; while (attr && (attr->nodeFlags & IS_NS_NODE)) { /* XSLT namespace isn't copied */ /* Well, XSLT implementers doesn't seem to agree at which point this rule out of the second paragraph of 7.1.1 must be applied: before or after applying the namespace aliases (or, in other words: is this rule (of not copying the XSLT namespace for lre) considered, at the time, the lre is found in the stylesheet or at the time, the lre is written to the result doc). In deed the rec doesn't clarify this explicitly. */ if (strcmp (attr->nodeValue, XSLT_NAMESPACE)==0){ attr = attr->nextSibling; continue; } ns = n->ownerDocument->namespaces[attr->namespace-1]; rc = 0; n1 = actionNode; while (n1 != n) { attr1 = n1->firstAttr; while (attr1 && (attr1->nodeFlags & IS_NS_NODE)) { ns1 = n1->ownerDocument->namespaces[attr1->namespace-1]; if (strcmp (ns1->prefix, ns->prefix)==0) { rc = 1; break; } attr1 = attr1->nextSibling; } if (rc) break; n1 = n1->parentNode; } if (rc) { attr = attr->nextSibling; continue; } str = ns->uri; nsAlias = xs->nsAliases; while (nsAlias) { if (strcmp (nsAlias->fromUri, ns->uri)==0) { ns->uri = nsAlias->toUri; break; } nsAlias = nsAlias->next; } eNS = sDoc->excludeNS; while (eNS) { if (eNS->uri) { if (strcmp (eNS->uri, ns->uri)==0) break; } else { if (ns->prefix[0] == '\0') break; } eNS = eNS->next; } if (!eNS) { eNS = sDoc->extensionNS; while (eNS) { if (eNS->uri) { if (strcmp (eNS->uri, ns->uri)==0) break; } else { if (ns->prefix[0] == '\0') break; } eNS = eNS->next; } if (!eNS) { domAddNSToNode (xs->lastNode, ns); } } ns->uri = str; attr = attr->nextSibling; } n = n->parentNode; } /* It's not clear, what to do, if the literal result element is in a namespace, that should be excluded. We follow saxon and xalan, which both add the namespace of the literal result element always to the result tree, to ensure that the result tree is conform to the XML namespace recommendation. */ if (actionNode->namespace) { ns = actionNode->ownerDocument->namespaces[actionNode->namespace-1]; str = ns->uri; nsAlias = xs->nsAliases; while (nsAlias) { if (strcmp (nsAlias->fromUri, ns->uri)==0) { ns->uri = nsAlias->toUri; break; } nsAlias = nsAlias->next; } ns1 = domAddNSToNode (xs->lastNode, ns); if (ns1) { xs->lastNode->namespace = ns1->index; } ns->uri = str; } else { ns = domLookupPrefix (xs->lastNode, ""); if (ns) { if (strcmp (ns->uri, "")!=0) { attr = domSetAttributeNS (xs->lastNode, "xmlns", "", NULL, 1); if (attr) { xs->lastNode->namespace = attr->namespace; } } else { xs->lastNode->namespace = ns->index; } } } n = xs->lastNode; /* process the attributes */ attr = actionNode->firstAttr; while (attr) { if (attr->nodeFlags & IS_NS_NODE) { attr = attr->nextSibling; continue; } /* TODO: xsl:exclude-result-prefixes attribute on literal elements on the ancestor-or-self axis */ uri = domNamespaceURI((domNode*)attr); if (uri && strcmp(uri, XSLT_NAMESPACE)==0) { domSplitQName((char*)attr->nodeName, prefix, &localName); if (strcmp(localName,"use-attribute-sets")==0) { str = attr->nodeValue; rc = ExecUseAttributeSets (xs, context, currentNode, currentPos, actionNode, str, errMsg); CHECK_RC; } } else { rc = evalAttrTemplates( xs, context, currentNode, currentPos, attr->nodeValue, &str, errMsg); CHECK_RC; if (uri) { nsAlias = xs->nsAliases; while (nsAlias) { if (strcmp (nsAlias->fromUri, uri)==0) { uri = nsAlias->toUri; break; } nsAlias = nsAlias->next; } } domSetAttributeNS (n, attr->nodeName, str, uri, 1); FREE(str); } attr = attr->nextSibling; } /* process the children as well */ xsltPushVarFrame (xs); rc = ExecActions(xs, context, currentNode, currentPos, actionNode->firstChild, errMsg); xsltPopVarFrame (xs); CHECK_RC; xs->lastNode = savedLastNode; return 0; } return 0; } /*---------------------------------------------------------------------------- | ExecActions | \---------------------------------------------------------------------------*/ static int ExecActions ( xsltState * xs, xpathResultSet * context, domNode * currentNode, domLength currentPos, domNode * actionNode, char ** errMsg ) { domNode *savedLastNode, *savedCurrentNode; int rc; savedLastNode = xs->lastNode; savedCurrentNode = xs->current; while (actionNode) { xs->current = currentNode; rc = ExecAction (xs, context, currentNode, currentPos, actionNode, errMsg); if (rc < 0) { xs->lastNode = savedLastNode; xs->current = savedCurrentNode; return rc; } actionNode = actionNode->nextSibling; } xs->lastNode = savedLastNode; xs->current = savedCurrentNode; return 0; } /*---------------------------------------------------------------------------- | ApplyTemplate | \---------------------------------------------------------------------------*/ static int ApplyTemplate ( xsltState * xs, xpathResultSet * context, domNode * currentNode, domNode * exprContext, domLength currentPos, const char * mode, const char * modeURI, char ** errMsg ) { xsltTemplate *tpl; xsltTemplate *tplChoosen, *currentTplRule; domNode *child; xpathResultSet rs; int rc; double currentPrio, currentPrec; char prefix[MAX_PREFIX_LEN]; const char *localName; Tcl_HashEntry *h; Tcl_DString dStr; xsltSubDoc *currentSubDoc; TRACE2("\n\nApplyTemplate mode='%s' currentPos=%d \n", mode, currentPos); DBG(printXML (currentNode, 0, 1);) /*-------------------------------------------------------------- | find template \-------------------------------------------------------------*/ tplChoosen = NULL; currentPrio = -100000.0; currentPrec = 0.0; if (currentNode->nodeType == ELEMENT_NODE) { Tcl_DStringInit (&dStr); if (currentNode->namespace) { domSplitQName (currentNode->nodeName, prefix, &localName); Tcl_DStringAppend (&dStr, domNamespaceURI (currentNode), -1); Tcl_DStringAppend (&dStr, ":", 1); } if (mode) { if (modeURI) { Tcl_DStringAppend (&dStr, modeURI, -1); Tcl_DStringAppend (&dStr, ":", 1); } Tcl_DStringAppend (&dStr, mode, -1); Tcl_DStringAppend (&dStr, ":", 1); } if (currentNode->namespace) { Tcl_DStringAppend (&dStr, localName, -1); } else { Tcl_DStringAppend (&dStr, currentNode->nodeName, -1); } h = Tcl_FindHashEntry (&xs->isElementTpls, Tcl_DStringValue (&dStr)); Tcl_DStringFree (&dStr); if (h) { for (tpl = (xsltTemplate *) Tcl_GetHashValue (h); tpl != NULL; tpl = tpl->next) { TRACE3("find element tpl match='%s' mode='%s' name='%s'\n", tpl->match, tpl->mode, tpl->name); TRACE4("tpl has prio='%f' precedence='%f'\n", tpl->prio, tpl->precedence, currentPrio, currentPrec); rc = xpathMatches ( tpl->ast, tpl->content, currentNode, &(xs->cbs), errMsg); if (rc < 0) { TRACE1("xpathMatches had errors '%s' \n", *errMsg); return rc; } if (rc == 0) continue; TRACE3("matching '%s': %f > %f ? \n", tpl->match, tpl->prio , currentPrio); tplChoosen = tpl; currentPrio = tpl->prio; currentPrec = tpl->precedence; break; } } } for( tpl = xs->templates; tpl != NULL; tpl = tpl->next) { TRACE3("find tpl match='%s' mode='%s' name='%s'\n", tpl->match, tpl->mode, tpl->name); /* exclude those, which don't match the current mode */ if ( ( mode && !tpl->mode) || (!mode && tpl->mode) || ( mode && tpl->mode && (strcmp(mode,tpl->mode)!=0)) || (!modeURI && tpl->modeURI) || ( modeURI && !tpl->modeURI) || ( modeURI && tpl->modeURI && (strcmp(modeURI, tpl->modeURI)!=0)) ) { TRACE("doesn't match mode\n"); continue; /* doesn't match mode */ } TRACE4("tpl has prio='%f' precedence='%f', currentPrio='%f', currentPrec='%f'\n", tpl->prio, tpl->precedence, currentPrio, currentPrec); /* According to XSLT rec 5.5: First test precedence */ if (tpl->precedence < currentPrec) break; if (tpl->precedence == currentPrec) { if (tpl->prio < currentPrio) break; if (tpl->prio == currentPrio && domPrecedes (tpl->content, tplChoosen->content)) break; } rc = xpathMatches ( tpl->ast, tpl->content, currentNode, &(xs->cbs), errMsg); TRACE1("xpathMatches = %d \n", rc); if (rc < 0) { TRACE1("xpathMatches had errors '%s' \n", *errMsg); return rc; } if (rc == 0) continue; TRACE3("matching '%s': %f > %f ? \n", tpl->match, tpl->prio , currentPrio); tplChoosen = tpl; TRACE1("TAKING '%s' \n", tpl->match); break; } if (tplChoosen == NULL) { TRACE("nothing matches -> execute built-in template \n"); /*-------------------------------------------------------------------- | execute built-in template \-------------------------------------------------------------------*/ if (currentNode->nodeType == TEXT_NODE) { domAppendNewTextNode(xs->lastNode, ((domTextNode*)currentNode)->nodeValue, ((domTextNode*)currentNode)->valueLength, TEXT_NODE, 0); return 0; } else if (currentNode->nodeType == DOCUMENT_NODE) { child = ((domDocument*)currentNode)->documentElement; } else if (currentNode->nodeType == ELEMENT_NODE) { child = currentNode->firstChild; } else if (currentNode->nodeType == ATTRIBUTE_NODE) { domAppendNewTextNode (xs->lastNode, ((domAttrNode*)currentNode)->nodeValue, ((domAttrNode*)currentNode)->valueLength, TEXT_NODE, 0); return 0; } else { return 0; /* for all other nodes we don't have to recurse deeper */ } xpathRSInit( &rs ); while (child) { rsAddNodeFast ( &rs, child); child = child->nextSibling; } rc = ApplyTemplates (xs, context, currentNode, currentPos, exprContext, &rs, mode, modeURI, errMsg); xpathRSFree( &rs ); CHECK_RC; } else { TRACE1("tplChoosen '%s' \n", tplChoosen->match); currentTplRule = xs->currentTplRule; currentSubDoc = xs->currentSubDoc; xs->currentTplRule = tplChoosen; xs->currentSubDoc = tplChoosen->sDoc; DBG(printXML (tplChoosen->content->firstChild, 0, 1);) rc = ExecActions(xs, context, currentNode, currentPos, tplChoosen->content->firstChild, errMsg); TRACE1("ApplyTemplate/ExecActions rc = %d \n", rc); xs->currentTplRule = currentTplRule; xs->currentSubDoc = currentSubDoc; CHECK_RC; } return 0; } /*---------------------------------------------------------------------------- | ApplyTemplates | \---------------------------------------------------------------------------*/ static int ApplyTemplates ( xsltState * xs, xpathResultSet * context, domNode * currentNode, domLength currentPos, domNode * actionNode, xpathResultSet * nodeList, const char * mode, const char * modeURI, char ** errMsg ) { domNode * savedLastNode; int rc, needNewVarFrame = 1; domLength i; if (nodeList->type == xNodeSetResult) { if (xs->nestedApplyTemplates > xs->maxNestedApplyTemplates) { *errMsg = tdomstrdup("Maximum nested apply templates reached " "(potential infinite template recursion?)."); return -1; } xs->nestedApplyTemplates++; savedLastNode = xs->lastNode; for (i=0; i < nodeList->nr_nodes; i++) { if (needNewVarFrame) { xsltPushVarFrame (xs); SETPARAMDEF; rc = setParamVars (xs, context, currentNode, currentPos, actionNode, errMsg); if (rc < 0) { xsltPopVarFrame (xs); xs->lastNode = savedLastNode; return rc; } SETSCOPESTART; (&xs->varFramesStack[xs->varFramesStackPtr])->polluted = 0; } rc = ApplyTemplate (xs, nodeList, nodeList->nodes[i], actionNode, i, mode, modeURI, errMsg); if (rc < 0) { xsltPopVarFrame (xs); xs->lastNode = savedLastNode; return rc; } if ((&xs->varFramesStack[xs->varFramesStackPtr])->polluted) { xsltPopVarFrame (xs); needNewVarFrame = 1; } else needNewVarFrame = 0; } if (!needNewVarFrame) { xsltPopVarFrame (xs); } xs->lastNode = savedLastNode; xs->nestedApplyTemplates--; } else { TRACE("ApplyTemplates: nodeList not a NodeSetResult !!!\n"); DBG(rsPrint(nodeList);) } return 0; } /*---------------------------------------------------------------------------- | fillElementList | \---------------------------------------------------------------------------*/ static int fillElementList ( xsltWSInfo * wsInfo, int strip, double precedence, domNode * node, char * str, char ** errMsg ) { char *pc, *start, save; char prefix[MAX_PREFIX_LEN]; const char *localName; double *f; int hnew; Tcl_HashEntry *h; Tcl_DString dStr; domNS *ns; pc = str; while (*pc) { while (*pc && IS_XML_WHITESPACE(*pc)) pc++; if (*pc == '\0') break; start = pc; while (*pc && !IS_XML_WHITESPACE(*pc)) pc++; save = *pc; *pc = '\0'; wsInfo->hasData = 1; if (strcmp (start, "*")==0) { if (strip) wsInfo->stripAll = 1; else wsInfo->stripAll = 0; wsInfo->wildcardPrec = precedence; } else { Tcl_DStringInit (&dStr); ns = NULL; domSplitQName (start, prefix, &localName); if (prefix[0] != '\0') { if (!domIsNCNAME (prefix)) { reportError (node, "Invalid token", errMsg); *pc = save; Tcl_DStringFree (&dStr); return -1; } ns = domLookupPrefix (node, prefix); if (!ns) { reportError (node, "prefix isn't bound to a namespace", errMsg); *pc = save; Tcl_DStringFree (&dStr); return -1; } Tcl_DStringAppend (&dStr, ns->uri, -1); Tcl_DStringAppend (&dStr, ":", 1); } if (strcmp ("*", localName) != 0) { if (!domIsNCNAME (localName)) { reportError (node, "Invalid token", errMsg); *pc = save; Tcl_DStringFree (&dStr); return -1; } } Tcl_DStringAppend (&dStr, localName, -1); if (strip) { h = Tcl_FindHashEntry (&wsInfo->preserveTokens, Tcl_DStringValue (&dStr)); } else { h = Tcl_FindHashEntry (&wsInfo->stripTokens, Tcl_DStringValue (&dStr)); } if (h) { FREE (Tcl_GetHashValue (h)); Tcl_DeleteHashEntry (h); } if (strip) { h = Tcl_CreateHashEntry (&wsInfo->stripTokens, Tcl_DStringValue (&dStr), &hnew); } else { h = Tcl_CreateHashEntry (&wsInfo->preserveTokens, Tcl_DStringValue (&dStr), &hnew); } if (hnew) { f = (double *)MALLOC(sizeof (double)); *f = precedence; Tcl_SetHashValue (h, f); } else { f = (double *)Tcl_GetHashValue (h); *f = precedence; } Tcl_DStringFree (&dStr); } *pc = save; } return 1; } /*---------------------------------------------------------------------------- | getCdataSectionElements | \---------------------------------------------------------------------------*/ static int getCdataSectionElements ( domNode * node, char * qnameList, Tcl_HashTable * HashTable, char ** errMsg ) { char *pc, *start, save, prefix[MAX_PREFIX_LEN]; const char *localName; int hnew; Tcl_DString dStr; domNS *ns; Tcl_DStringInit (&dStr); pc = qnameList; while (*pc) { while (*pc && IS_XML_WHITESPACE(*pc)) pc++; if (*pc == '\0') break; start = pc; while (*pc && !IS_XML_WHITESPACE(*pc)) pc++; save = *pc; *pc = '\0'; domSplitQName (start, prefix, &localName); if (prefix[0] != '\0') { if (!domIsNCNAME (prefix)) { Tcl_DStringSetLength (&dStr, 0); Tcl_DStringAppend (&dStr, "Invalid prefix '", -1); Tcl_DStringAppend (&dStr, prefix, -1); Tcl_DStringAppend (&dStr, "'.", 2); reportError (node, Tcl_DStringValue (&dStr), errMsg); Tcl_DStringFree (&dStr); return 0; } ns = domLookupPrefix (node, prefix); if (!ns) { Tcl_DStringSetLength (&dStr, 0); Tcl_DStringAppend (&dStr, "There isn't a namespace bound to" " the prefix '", -1); Tcl_DStringAppend (&dStr, prefix, -1); Tcl_DStringAppend (&dStr, "'.", 2); reportError (node, Tcl_DStringValue (&dStr), errMsg); Tcl_DStringFree (&dStr); return 0; } Tcl_DStringAppend (&dStr, ns->uri, -1); Tcl_DStringAppend (&dStr, ":", 1); } if (!domIsNCNAME (localName)) { Tcl_DStringSetLength (&dStr, 0); Tcl_DStringAppend (&dStr, "Invalid name '", -1); Tcl_DStringAppend (&dStr, prefix, -1); Tcl_DStringAppend (&dStr, "'.", 2); reportError (node, Tcl_DStringValue (&dStr), errMsg); Tcl_DStringFree (&dStr); return 0; } Tcl_DStringAppend (&dStr, localName, -1); Tcl_CreateHashEntry (HashTable, Tcl_DStringValue (&dStr), &hnew); Tcl_DStringSetLength (&dStr, 0); *pc = save; } return 1; } /*---------------------------------------------------------------------------- | StripXSLTSpace | \---------------------------------------------------------------------------*/ static void StripXSLTSpace ( domNode * node ) { domNode *child, *newChild, *parent; domLength i, len; int onlySpace; char *p; if (node->nodeType == TEXT_NODE) { node->info = (int)unknown; p = ((domTextNode*)node)->nodeValue; len = ((domTextNode*)node)->valueLength; onlySpace = 1; for (i=0; iparentNode && (node->parentNode->info == text)) { /* keep white texts below xsl:text elements */ return; } parent = node->parentNode; while (parent) { p = getAttr(parent,"xml:space", a_space); if (p!=NULL) { if (strcmp(p,"preserve")==0) return; if (strcmp(p,"default")==0) break; } parent = parent->parentNode; } DBG(fprintf(stderr, "removing domNode0x%x(len %d) under '%s' \n", node, len, node->parentNode->nodeName);) domDeleteNode (node, NULL, NULL); } } else if (node->nodeType == ELEMENT_NODE) { getTag(node); child = node->firstChild; while (child) { newChild = child->nextSibling; StripXSLTSpace (child); child = newChild; } } else { node->info = (int)unknown; } } /*---------------------------------------------------------------------------- | addExclExtNS | \---------------------------------------------------------------------------*/ static int parseList ( xsltSubDoc *docData, domNode *xsltRoot, char *str, int extensionNS, char **errMsg ) { xsltExclExtNS *eNS; char *pc, *start, save; domNS *ns; if (str) { pc = str; while (*pc) { while (*pc && IS_XML_WHITESPACE(*pc)) pc++; if (*pc == '\0') break; start = pc; while (*pc && !IS_XML_WHITESPACE(*pc)) pc++; save = *pc; *pc = '\0'; eNS = (xsltExclExtNS *)MALLOC(sizeof (xsltExclExtNS)); eNS->uri = NULL; if (extensionNS) { eNS->next = docData->extensionNS; docData->extensionNS = eNS; } else { eNS->next = docData->excludeNS; docData->excludeNS = eNS; } if (strcmp (start, "#default")==0) { ns = domLookupPrefix (xsltRoot, ""); if (!ns) { reportError (xsltRoot, "All prefixes listed in" " exclude-result-prefixes and" " extension-element-prefixes must be" " bound to a namespace.", errMsg); return -1; } } else { ns = domLookupPrefix (xsltRoot, start); if (!ns) { reportError (xsltRoot, "All prefixes listed in" " exclude-result-prefixes and" " extension-element-prefixes must be" " bound to a namespace.", errMsg); return -1; } eNS->uri = tdomstrdup (ns->uri); } *pc = save; } } return 1; } static int addExclExtNS ( xsltSubDoc *docData, domNode *xsltRoot, char **errMsg ) { char *str, *tailptr; int rc; double d; str = getAttr (xsltRoot, "version", a_version); if (!str) { reportError (xsltRoot, "missing mandatory attribute \"version\".", errMsg); return -1; } d = strtod (str, &tailptr); if (d == 0.0 && tailptr == str) { reportError (xsltRoot, "The value of the attribute \"version\" must" " be a number.", errMsg); return -1; } if (d > 1.0) { docData->fwCmpProcessing = 1; } else { if (d != 1.0) { reportError (xsltRoot, "Strange \"version\" value.", errMsg); return -1; } } str = getAttr (xsltRoot, "exclude-result-prefixes", a_excludeResultPrefixes); rc = parseList (docData, xsltRoot, str, 0, errMsg); CHECK_RC; str = getAttr (xsltRoot, "extension-element-prefixes", a_extensionElementPrefixes); rc = parseList (docData, xsltRoot, str, 1, errMsg); CHECK_RC; return 1; } /*---------------------------------------------------------------------------- | getExternalDocument | \---------------------------------------------------------------------------*/ static domDocument * getExternalDocument ( Tcl_Interp *interp, xsltState *xs, domDocument *xsltDoc, const char *baseURI, const char *href, int isStylesheet, int fixedXMLSource, char **errMsg ) { Tcl_Obj *cmdPtr, *resultObj, *extbaseObj, *xmlstringObj; Tcl_Obj *channelIdObj, *resultTypeObj; int mode, result, storeLineColumn; domLength len; int resultcode = 0; char *resultType, *extbase, *xmlstring, *channelId, s[20]; Tcl_Obj *extResolver = NULL; const char *str; domDocument *doc; xsltSubDoc *sdoc; XML_Parser parser; Tcl_Channel chan; Tcl_DString dStr; domParseForestErrorData forestError; if (isStylesheet && (href[0] == '\0')) { *errMsg = tdomstrdup("Recursive import/include: stylesheet tries " "to access itself."); return NULL; } DBG( fprintf (stderr, "getExternalDocument: baseURI '%s'\n", baseURI); fprintf (stderr, "getExternalDocument: systemID '%s'\n", href); ) cmdPtr = Tcl_NewStringObj (xsltDoc->extResolver, -1); Tcl_IncrRefCount (cmdPtr); if (baseURI) { Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj (baseURI, (domLength)strlen(baseURI))); } else { Tcl_ListObjAppendElement(interp, cmdPtr, Tcl_NewStringObj ("", 0)); } Tcl_ListObjAppendElement (interp, cmdPtr, (href ? Tcl_NewStringObj (href, (domLength)strlen (href)) : Tcl_NewStringObj ("", 0))); Tcl_ListObjAppendElement (interp, cmdPtr, Tcl_NewStringObj ("", 0)); result = Tcl_EvalObjEx (interp, cmdPtr, TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL); Tcl_DecrRefCount (cmdPtr); resultObj = Tcl_GetObjResult (interp); Tcl_IncrRefCount (resultObj); if (result != TCL_OK) { goto wrongScriptResult; } result = Tcl_ListObjLength (interp, resultObj, &len); if ((result != TCL_OK) || (len != 3)) { goto wrongScriptResult; } result = Tcl_ListObjIndex (interp, resultObj, 0, &resultTypeObj); if (result != TCL_OK) { goto wrongScriptResult; } resultType = Tcl_GetString(resultTypeObj); if (strcmp (resultType, "string") == 0) { result = Tcl_ListObjIndex (interp, resultObj, 2, &xmlstringObj); xmlstring = Tcl_GetStringFromObj (xmlstringObj, &len); chan = NULL; } else if (strcmp (resultType, "channel") == 0) { xmlstring = NULL; len = 0; result = Tcl_ListObjIndex (interp, resultObj, 2, &channelIdObj); channelId = Tcl_GetString(channelIdObj); chan = Tcl_GetChannel (interp, channelId, &mode); if (chan == (Tcl_Channel) NULL) { goto wrongScriptResult; } if ((mode & TCL_READABLE) == 0) { *errMsg = tdomstrdup("-externalentitycommand returned a channel that wasn't opened for reading"); return NULL; } } else if (strcmp (resultType, "filename") == 0) { *errMsg = tdomstrdup("-externalentitycommand result type \"filename\" not yet implemented"); return NULL; } else { goto wrongScriptResult; } result = Tcl_ListObjIndex (interp, resultObj, 1, &extbaseObj); extbase = Tcl_GetString(extbaseObj); /* Since stylesheets and source docouments have different white space stripping rules, an already parsed tree could only reused, if the 'usage type' of the already present tree is the same as for the currently requested document */ sdoc = xs->subDocs; while (sdoc) { if (isStylesheet == sdoc->isStylesheet && sdoc->baseURI && strcmp(sdoc->baseURI, extbase) == 0) { Tcl_DecrRefCount (resultObj); return sdoc->doc; } sdoc = sdoc->next; } if (xsltDoc->documentElement->nodeFlags & HAS_LINE_COLUMN) { storeLineColumn = 1; } else { storeLineColumn = 0; } parser = XML_ParserCreate_MM (NULL, MEM_SUITE, NULL); Tcl_ResetResult (interp); if (xsltDoc->extResolver) { extResolver = Tcl_NewStringObj(xsltDoc->extResolver, -1); Tcl_IncrRefCount (extResolver); } /* keep white space, no fiddling with the encoding (is this a good idea?) */ doc = domReadDocument (parser, xmlstring, len, 0, 0, storeLineColumn, 0, 0, NULL, chan, extbase, extResolver, 0, 0, (int) XML_PARAM_ENTITY_PARSING_ALWAYS, #ifndef TDOM_NO_SCHEMA NULL, #endif interp, &forestError, &resultcode); if (xsltDoc->extResolver) { Tcl_DecrRefCount (extResolver); } if (doc == NULL) { DBG(fprintf (stderr, "parse error, str len %d, xmlstring: -->%s<--\n", strlen (xmlstring), xmlstring);) Tcl_DStringInit (&dStr); Tcl_DStringAppend (&dStr, "Error while processing external entity \"", -1); Tcl_DStringAppend (&dStr, href, -1); Tcl_DStringAppend (&dStr, "\":\n", -1); str = Tcl_GetStringResult (interp); if (str[0] == '\0') { Tcl_DStringAppend (&dStr, "At line ", -1); sprintf (s, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentLineNumber (parser)); Tcl_DStringAppend (&dStr, s, -1); Tcl_DStringAppend (&dStr, " character ", -1); sprintf (s, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentColumnNumber (parser)); Tcl_DStringAppend (&dStr, s, -1); Tcl_DStringAppend (&dStr, ": ", 2); Tcl_DStringAppend (&dStr, XML_ErrorString (XML_GetErrorCode(parser)), -1); } else { Tcl_DStringAppend (&dStr, str, -1); } *errMsg = tdomstrdup (Tcl_DStringValue (&dStr)); Tcl_DStringFree (&dStr); XML_ParserFree (parser); Tcl_DecrRefCount (resultObj); return NULL; } XML_ParserFree (parser); /* TODO: If the stylesheet use the literal-result-element-as-stylesheet form, rewrite it to a "ordinary" stylesheet with root element xsl:stylesheet, with one template child with match pattern "/". */ sdoc = (xsltSubDoc*)MALLOC(sizeof (xsltSubDoc)); sdoc->doc = doc; sdoc->baseURI = tdomstrdup (extbase); Tcl_InitHashTable (&(sdoc->keyData), TCL_STRING_KEYS); sdoc->excludeNS = NULL; sdoc->extensionNS = NULL; sdoc->fwCmpProcessing = 0; sdoc->mustFree = 1; sdoc->isStylesheet = isStylesheet; sdoc->fixedXMLSource = fixedXMLSource; if (isStylesheet) { if (addExclExtNS (sdoc, doc->documentElement, errMsg) < 0) { Tcl_DeleteHashTable (&(sdoc->keyData)); domFreeDocument (sdoc->doc, NULL, NULL); FREE (sdoc->baseURI); FREE (sdoc); Tcl_DecrRefCount (resultObj); return NULL; } StripXSLTSpace (doc->rootNode); } sdoc->next = xs->subDocs; xs->subDocs = sdoc; Tcl_DecrRefCount (resultObj); return doc; wrongScriptResult: *errMsg = tdomstrdup(Tcl_GetStringResult(interp)); Tcl_DecrRefCount (resultObj); return NULL; } /*---------------------------------------------------------------------------- | processTopLevelVars | \---------------------------------------------------------------------------*/ static int processTopLevelVars ( domNode * xmlNode, xsltState * xs, char ** parameters, int ignoreUndeclaredParameters, char ** errMsg ) { int rc, i; char *select, prefix[MAX_PREFIX_LEN]; const char *localName; xpathResultSet nodeList, rs; Tcl_HashEntry *entryPtr; Tcl_HashSearch search; xsltTopLevelVar *topLevelVar; xsltVarInProcess varInProcess; xsltVariable *var; domNS *ns; Tcl_DString dStr; xpathRSInit (&nodeList); rsAddNodeFast (&nodeList, xmlNode); if (parameters) { i = 0; while (parameters[i]) { domSplitQName (parameters[i], prefix, &localName); ns = NULL; if (prefix[0] != '\0') { ns = domLookupPrefix (xs->xsltDoc->documentElement, prefix); if (!ns) { Tcl_DStringInit (&dStr); Tcl_DStringAppend (&dStr, "No namespace bound to prefix" " (passed parameter \"", -1); Tcl_DStringAppend (&dStr, parameters[i], -1); Tcl_DStringAppend (&dStr, "\")", -1); *errMsg = tdomstrdup (Tcl_DStringValue (&dStr)); Tcl_DStringFree (&dStr); xpathRSFree (&nodeList); return -1; } } Tcl_DStringInit (&dStr); if (ns) Tcl_DStringAppend (&dStr, ns->uri, -1); Tcl_DStringAppend (&dStr, localName, -1); entryPtr = Tcl_FindHashEntry (&xs->topLevelVars, Tcl_DStringValue (&dStr)); Tcl_DStringFree (&dStr); if (!entryPtr) { if (ignoreUndeclaredParameters) { i += 2; continue; } Tcl_DStringInit (&dStr); Tcl_DStringAppend (&dStr, "There isn't a parameter named \"", -1); Tcl_DStringAppend (&dStr, parameters[i], -1); Tcl_DStringAppend (&dStr, "\" defined at top level in the stylesheet.", -1); *errMsg = tdomstrdup (Tcl_DStringValue (&dStr)); Tcl_DStringFree (&dStr); xpathRSFree (&nodeList); return -1; } topLevelVar = (xsltTopLevelVar *) Tcl_GetHashValue (entryPtr); if (!topLevelVar->isParameter) { Tcl_DStringInit (&dStr); Tcl_DStringAppend (&dStr, "\"", 1); Tcl_DStringAppend (&dStr, parameters[i], -1); Tcl_DStringAppend (&dStr, "\" is defined as variable, not as parameter.", -1); *errMsg = tdomstrdup (Tcl_DStringValue (&dStr)); Tcl_DStringFree (&dStr); xpathRSFree (&nodeList); return -1; } if (xsltVarExists (xs, parameters[i], NULL)) { i += 2; continue; } xpathRSInit (&rs); rsSetString (&rs, parameters[i+1]); xs->varStackPtr++; if (xs->varStackPtr >= xs->varStackLen) { xs->varStack = (xsltVariable *) REALLOC ((char*)xs->varStack, sizeof (xsltVariable) * 2*xs->varStackLen); xs->varStackLen *= 2; } var = &(xs->varStack[xs->varStackPtr]); if (!xs->varFramesStack->nrOfVars) { xs->varFramesStack->varStartIndex = xs->varStackPtr; } xs->varFramesStack->nrOfVars++; var->name = localName; if (ns) var->uri = ns->uri; else var->uri = NULL; var->node = topLevelVar->node; var->rs = rs; var->active = 1; i += 2; } } for (entryPtr = Tcl_FirstHashEntry(&xs->topLevelVars, &search); entryPtr != (Tcl_HashEntry*) NULL; entryPtr = Tcl_NextHashEntry(&search)) { topLevelVar = (xsltTopLevelVar *)Tcl_GetHashValue (entryPtr); if (xsltVarExists (xs, topLevelVar->name, topLevelVar->node)) { continue; } varInProcess.name = topLevelVar->name; varInProcess.next = NULL; xs->varsInProcess = &varInProcess; xs->currentXSLTNode = topLevelVar->node; select = getAttr (topLevelVar->node, "select", a_select); if (select && topLevelVar->node->firstChild) { xpathRSFree (&nodeList); reportError (topLevelVar->node, "xsl:variable and xsl:param" " elements with a select attribute must be empty", errMsg); return -1; } rc = xsltSetVar(xs, topLevelVar->name, &nodeList, xmlNode, 0, select, topLevelVar->node, 1, errMsg); if (rc < 0) { xpathRSFree (&nodeList); return rc; } } xpathRSFree (&nodeList); xs->currentXSLTNode = NULL; xs->varsInProcess = NULL; return 0; } /*---------------------------------------------------------------------------- | processTopLevel | \---------------------------------------------------------------------------*/ static int processTopLevel ( Tcl_Interp * interp, domNode * xsltDocumentElement, xsltState * xs, double precedence, double * precedenceLowBound, char ** errMsg ) { domNode *node; domDocument *extStyleSheet; int rc, hnew, clen, newdf = 0, nonImportElemSeen = 0; int ignore; double childPrecedence, childLowBound; char *str, *name, *match, *use, *href; char prefix[MAX_PREFIX_LEN]; const char *localName, *baseURI; xsltTag tag; xsltAttrSet *attrSet; xsltKeyInfo *keyInfo; xsltDecimalFormat *df; xsltTopLevelVar *topLevelVar; xsltNSAlias *nsAlias; domNS *ns, *nsFrom, *nsTo; Tcl_HashEntry *h; Tcl_DString dStr; DBG(fprintf (stderr, "start processTopLevel. precedence: %f precedenceLowBound %f\n", precedence, *precedenceLowBound);); node = xsltDocumentElement->firstChild; while (node) { tag = getTag (node); if (!nonImportElemSeen && tag != unknown && tag != import) { nonImportElemSeen = 1; } switch ( tag ) { case attributeSet: str = getAttr(node, "name", a_name); if (str) { domSplitQName (str, prefix, &localName); ns = NULL; if (prefix[0] != '\0') { ns = domLookupPrefix (node, prefix); if (!ns) { reportError (node, "There isn't a namespace" " bound to the prefix.", errMsg); return -1; } } if (xs->attrSets) { attrSet = xs->attrSets; while (attrSet->next) attrSet = attrSet->next; attrSet->next = (xsltAttrSet*)MALLOC(sizeof(xsltAttrSet)); attrSet = attrSet->next; } else { attrSet = (xsltAttrSet*)MALLOC(sizeof(xsltAttrSet)); xs->attrSets = attrSet; } attrSet->next = NULL; attrSet->content = node; attrSet->name = localName; attrSet->inUse = 0; if (ns) { attrSet->uri = ns->uri; } else { attrSet->uri = NULL; } } else { reportError (node, "xsl:attribute-set: missing mandatory" " attribute \"name\".", errMsg); return -1; } break; case decimalFormat: if (node->firstChild) { reportError (node, "xsl:decimal-format has to be empty.", errMsg); return -1; } str = getAttr(node, "name", a_name); if (str) { domSplitQName (str, prefix, &localName); ns = NULL; if (prefix[0] != '\0') { ns = domLookupPrefix (node, prefix); if (!ns) { reportError (node, "There isn't a namespace bound" " to the prefix.", errMsg); return -1; } } /* a named decimal format */ df = xs->decimalFormats->next; while (df) { if (strcmp(df->name, str)==0 && ((df->uri == NULL && ns == NULL) || (df->uri != NULL && ns != NULL && (strcmp (df->uri, ns->uri)==0)))) { /* already existing, override it */ break; } df = df->next; } if (df == NULL) { df = (xsltDecimalFormat*)MALLOC(sizeof(xsltDecimalFormat)); memset (df, 0, sizeof (xsltDecimalFormat)); newdf = 1; /* initialize to defaults */ df->decimalSeparator = 46; df->groupingSeparator = 44; df->infinity = "Infinity"; df->minusSign = 45; df->NaN = "NaN"; df->percent = 37; df->perMille = 0x2030; df->zeroDigit = 48; df->digit = 35; df->patternSeparator = 59; df->name = tdomstrdup(str); if (ns) df->uri = tdomstrdup(ns->uri); else df->uri = NULL; /* prepend into list of decimal format after the default one */ df->next = xs->decimalFormats->next; xs->decimalFormats->next = df; } } else { /* definitions for default decimal format */ df = xs->decimalFormats; } str = getAttr(node, "decimal-separator", a_decimalSeparator); if (str) { clen = UTF8_CHAR_LEN (str[0]); if (!clen || str[clen] != '\0') { reportError (node, "decimal-separator has to be a" " single char", errMsg); if (newdf) FREE((char*)df); return -1; } Tcl_UtfToUniChar (str, &df->decimalSeparator); } str = getAttr(node, "grouping-separator", a_groupingSeparator); if (str) { clen = UTF8_CHAR_LEN (str[0]); if (!clen || str[clen] != '\0') { reportError (node, "groupingSeparator has to be a" " single char", errMsg); if (newdf) FREE((char*)df); return -1; } Tcl_UtfToUniChar (str, &df->groupingSeparator); } str = getAttr(node, "infinity", a_infinity); if (str) df->infinity = str; str = getAttr(node, "minus-sign", a_minusSign); if (str) { clen = UTF8_CHAR_LEN (str[0]); if (!clen || str[clen] != '\0') { reportError (node, "minus-sign has to be a single" " char", errMsg); if (newdf) FREE((char*)df); return -1; } Tcl_UtfToUniChar (str, &df->minusSign); } str = getAttr(node, "NaN", a_nan); if (str) df->NaN = str; str = getAttr(node, "percent", a_percent); if (str) { if (str[1] != '\0') { reportError (node, "percent has to be a single" " char", errMsg); return -1; } df->percent = str[0]; clen = UTF8_CHAR_LEN (str[0]); if (!clen || str[clen] != '\0') { reportError (node, "percent has to be a single" " char", errMsg); if (newdf) FREE((char*)df); return -1; } Tcl_UtfToUniChar (str, &df->percent); } str = getAttr(node, "per-mille", a_perMille); if (str) { clen = UTF8_CHAR_LEN (str[0]); if (!clen || str[clen] != '\0') { reportError (node, "per-mille has to be a single" " char", errMsg); if (newdf) FREE((char*)df); return -1; } Tcl_UtfToUniChar (str, &df->perMille); } str = getAttr(node, "zero-digit", a_zeroDigit); if (str) { clen = UTF8_CHAR_LEN (str[0]); if (!clen || str[clen] != '\0') { reportError (node, "zero-digit has to be a single" " char", errMsg); if (newdf) FREE((char*)df); return -1; } Tcl_UtfToUniChar (str, &df->zeroDigit); } str = getAttr(node, "digit", a_digit); if (str) { clen = UTF8_CHAR_LEN (str[0]); if (!clen || str[clen] != '\0') { reportError (node, "digit has to be a single char", errMsg); if (newdf) FREE((char*)df); return -1; } Tcl_UtfToUniChar (str, &df->digit); } str = getAttr(node, "pattern-separator", a_patternSeparator); if (str) { clen = UTF8_CHAR_LEN (str[0]); if (!clen || str[clen] != '\0') { reportError (node, "pattern-separator has to be a" " single char", errMsg); return -1; } Tcl_UtfToUniChar (str, &df->patternSeparator); } break; case import: if (nonImportElemSeen) { reportError (node, "xsl:import elements must come first", errMsg); return -1; } if (node->firstChild) { reportError (node, "xsl:import has to be empty!", errMsg); return -1; } if (!node->ownerDocument->extResolver) { reportError (node, "need resolver Script to include" " Stylesheet! (use" " \"-externalentitycommand\")", errMsg); return -1; } baseURI = findBaseURI (node); href = getAttr (node, "href", a_href); if (!href) { reportError (node, "xsl:import: missing mandatory" " attribute \"href\".", errMsg); return -1; } extStyleSheet = getExternalDocument (interp, xs, node->ownerDocument, baseURI, href, 1, 0, errMsg); if (!extStyleSheet) { return -1; } childPrecedence = (precedence + *precedenceLowBound) / 2; childLowBound = *precedenceLowBound; rc = processTopLevel (interp, extStyleSheet->documentElement, xs, childPrecedence, &childLowBound, errMsg); *precedenceLowBound = childPrecedence; if (rc != 0) { return rc; } break; case include: if (node->firstChild) { reportError (node, "xsl:include has to be empty.", errMsg); return -1; } if (!node->ownerDocument->extResolver) { reportError (node, "need resolver Script to include" "Stylesheet. (use" " \"-externalentitycommand\")", errMsg); return -1; } baseURI = findBaseURI (node); href = getAttr (node, "href", a_href); if (!href) { reportError (node, "xsl:include: missing mandatory" " attribute \"href\".", errMsg); return -1; } extStyleSheet = getExternalDocument (interp, xs, node->ownerDocument, baseURI, href, 1, 0, errMsg); if (!extStyleSheet) { return -1; } xs->currentXSLTNode = extStyleSheet->documentElement; rc = processTopLevel (interp, extStyleSheet->documentElement, xs, precedence, precedenceLowBound, errMsg); if (rc != 0) { return rc; } break; case key: if (node->firstChild) { reportError (node, "xsl:key has to be empty.", errMsg); return -1; } name = getAttr(node, "name", a_name); if (!name) { reportError (node, "xsl:key: missing mandatory" " attribute \"name\".", errMsg); return -1; } match = getAttr(node, "match", a_match); if (!match) { reportError (node, "xsl:key: missing mandatory" " attribute \"match\".", errMsg); return -1; } use = getAttr(node, "use", a_use); if (!use) { reportError (node, "xsl:key: missing mandatory" " attribute \"use\".", errMsg); return -1; } keyInfo = (xsltKeyInfo *)MALLOC(sizeof(xsltKeyInfo)); keyInfo->node = node; rc = xpathParse (match, node, XPATH_KEY_MATCH_PATTERN, NULL, NULL, &(keyInfo->matchAst), errMsg); if (rc < 0) { reportError (node, *errMsg, errMsg); FREE ((char*)keyInfo); return rc; } keyInfo->use = use; rc = xpathParse (use, node, XPATH_KEY_USE_EXPR, NULL, NULL, &(keyInfo->useAst), errMsg); if (rc < 0) { reportError (node, *errMsg, errMsg); xpathFreeAst (keyInfo->matchAst); FREE ((char*)keyInfo); return rc; } domSplitQName (name, prefix, &localName); Tcl_DStringInit (&dStr); if (prefix[0] != '\0') { ns = domLookupPrefix (node, prefix); if (!ns) { reportError (node, "There isn't a namespace bound" " to the prefix.", errMsg); xpathFreeAst (keyInfo->matchAst); xpathFreeAst (keyInfo->useAst); FREE((char*)keyInfo); return -1; } Tcl_DStringAppend (&dStr, ns->uri, -1); } Tcl_DStringAppend (&dStr, localName, -1); h = Tcl_CreateHashEntry (&(xs->keyInfos), Tcl_DStringValue (&dStr), &hnew); Tcl_DStringFree (&dStr); if (hnew) { keyInfo->next = NULL; } else { keyInfo->next = (xsltKeyInfo *)Tcl_GetHashValue (h); } Tcl_SetHashValue (h, keyInfo); break; case namespaceAlias: if (node->firstChild) { reportError (node, "xsl:namespace-alias has to be empty.", errMsg); return -1; } str = getAttr (node, "stylesheet-prefix", a_stylesheetPrefix); if (!str) { reportError (node, "xsl:namespace-alias: missing" " mandatory attribute" " \"stylesheet-prefix\".", errMsg); return -1 ; } if (strcmp (str, "#default")==0) { str = NULL; nsFrom = domLookupPrefix (node, ""); } else { nsFrom = domLookupPrefix (node, str); } if (!nsFrom) { reportError (node, "xsl:namespace-alias: no namespace" " bound to the \"stylesheet-prefix\".", errMsg); return -1; } str = getAttr (node, "result-prefix", a_resultPrefix); if (!str) { reportError (node, "xsl:namespace-alias: missing mandatory" " attribute \"result-prefix\".", errMsg); return -1; } if (strcmp (str, "#default")==0) { nsTo = domLookupPrefix (node, ""); } else { nsTo = domLookupPrefix (node, str); } if (!nsTo) { reportError (node, "xsl:namespace-alias: no namespace" " bound to the \"result-prefix\".", errMsg); return -1; } nsAlias = xs->nsAliases; ignore = 0; while (nsAlias) { if (strcmp (nsAlias->fromUri, nsFrom->uri)==0) { if (nsAlias->precedence > precedence) { ignore = 1; } break; } nsAlias = nsAlias->next; } if (ignore) break; if (nsAlias) { FREE(nsAlias->toUri); } else { nsAlias = (xsltNSAlias *)MALLOC(sizeof (xsltNSAlias)); nsAlias->fromUri = tdomstrdup (nsFrom->uri); nsAlias->next = xs->nsAliases; xs->nsAliases = nsAlias; } nsAlias->toUri = tdomstrdup (nsTo->uri); nsAlias->precedence = precedence; break; case output: if (node->firstChild) { reportError (node, "xsl:output has to be empty.", errMsg); return -1; } str = getAttr(node, "method", a_method); if (str) { if (xs->doctype.method) FREE(xs->doctype.method); xs->doctype.method = tdomstrdup(str); } str = getAttr(node, "encoding", a_encoding); if (str) { if (xs->doctype.encoding) FREE(xs->doctype.encoding); xs->doctype.encoding = tdomstrdup(str); } str = getAttr(node, "omit-xml-declaration", a_omitXMLDeclaration); if (str) { if (strcmp (str, "yes") == 0) { xs->doctype.omitXMLDeclaration = 1; } else if (strcmp (str, "no") == 0) { xs->doctype.omitXMLDeclaration = 0; } else { reportError (node, "Unexpected value for" " 'omit-xml-declaration' attribute", errMsg); return -1; } } str = getAttr(node, "standalone", a_standalone); if (str) { if (strcmp (str, "yes") == 0) { xs->doctype.standalone = 1; } else if (strcmp (str, "no") == 0) { xs->doctype.standalone = 0; } else { reportError (node, "Unexpected value for 'standalone'" " attribute", errMsg); return -1; } } str = getAttr(node, "doctype-public", a_doctypePublic); if (str) { if (xs->doctype.publicId) { FREE ((char*) xs->doctype.publicId); } xs->doctype.publicId = tdomstrdup(str); } str = getAttr(node, "doctype-system", a_doctypeSystem); if (str) { if (xs->doctype.systemId) { FREE ((char*) xs->doctype.systemId); } xs->doctype.systemId = tdomstrdup(str); } str = getAttr(node, "cdata-section-elements", a_cdataSectionElements); if (str) { if (!xs->doctype.cdataSectionElements) { xs->doctype.cdataSectionElements = (Tcl_HashTable *) MALLOC (sizeof (Tcl_HashTable)); Tcl_InitHashTable (xs->doctype.cdataSectionElements, TCL_STRING_KEYS); } if (!getCdataSectionElements (node, str, xs->doctype.cdataSectionElements, errMsg)) { return -1; } } str = getAttr(node, "indent", a_indent); if (str) { if (strcmp (str, "yes") == 0) { xs->indentOutput = 1; } else if (strcmp (str, "no") == 0) { xs->indentOutput = 0; } else { reportError (node, "Unexpected value for 'indent'" " attribute.", errMsg); return -1; } } str = getAttr(node, "media-type", a_mediaType); if (str) { if (xs->doctype.mediaType) FREE(xs->doctype.mediaType); xs->doctype.mediaType = tdomstrdup(str); } break; case preserveSpace: if (node->firstChild) { reportError (node, "xsl:preserve-space has to be empty.", errMsg); return -1; } str = getAttr(node, "elements", a_elements); if (str) { rc = fillElementList(&xs->wsInfo, 0, precedence, node, str, errMsg); CHECK_RC; } else { reportError (node, "xsl:preserve-space: missing required" " attribute \"elements\".", errMsg); return -1; } break; case stripSpace: if (node->firstChild) { reportError (node, "xsl:strip-space has to be empty.", errMsg); return -1; } str = getAttr(node, "elements", a_elements); if (str) { rc = fillElementList(&xs->wsInfo, 1, precedence, node, str, errMsg); CHECK_RC; } else { reportError (node, "xsl:strip-space: missing required" " attribute \"elements\".", errMsg); return -1; } break; case template: rc = xsltAddTemplate (xs, node, precedence, errMsg); CHECK_RC; break; case param: case variable: str = getAttr(node, "name", a_name); if (!str) { reportError (node, "xsl:variable and xsl:param elements" " must have a \"name\" attribute.", errMsg); return -1; } domSplitQName (str, prefix, &localName); ns = NULL; if (prefix[0] != '\0') { ns = domLookupPrefix (node, prefix); if (!ns) { reportError (node, "There isn't a namespace bound" " to the prefix.", errMsg); return -1; } } Tcl_DStringInit (&dStr); if (ns) { Tcl_DStringAppend (&dStr, ns->uri, -1); } Tcl_DStringAppend (&dStr, localName, -1); h = Tcl_CreateHashEntry (&(xs->topLevelVars), Tcl_DStringValue (&dStr), &hnew); Tcl_DStringFree (&dStr); if (!hnew) { topLevelVar = (xsltTopLevelVar *)Tcl_GetHashValue (h); /* Since imported stylesheets are processed at the point at which they encounters the definitions are already in increasing order of import precedence. Therefore, we have only to check, if there is a top level var or parm with the same precedence */ if (topLevelVar->precedence == precedence) { reportError (node, "There is already a variable" " or parameter with this name with the" " same import precedence.", errMsg); return -1; } } else { topLevelVar = (xsltTopLevelVar *) MALLOC (sizeof (xsltTopLevelVar)); Tcl_SetHashValue (h, topLevelVar); } topLevelVar->node = node; topLevelVar->name = str; if (tag == param) { topLevelVar->isParameter = 1; } else { topLevelVar->isParameter = 0; } topLevelVar->precedence = precedence; break; default: if (node->nodeType == ELEMENT_NODE) { if (!node->namespace) { reportError (node, "Top level elements must have a" " non-null namespace URI.", errMsg); return -1; } if (strcmp (XSLT_NAMESPACE, domNamespaceURI (node))==0) { if (!xs->currentSubDoc->fwCmpProcessing) { reportError (node, "XSLT element not allowed" " on top level or unknown XSLT" " element.", errMsg); return -1; } } } else if (node->nodeType == TEXT_NODE) { char *pc; int i, only_whites; only_whites = 1; for (i=0, pc = ((domTextNode*)node)->nodeValue; i < ((domTextNode*)node)->valueLength; i++, pc++) { if (!IS_XML_WHITESPACE(*pc)) { only_whites = 0; break; } } if (!only_whites) { reportError (node, "Non-whitespace text is not" " allowed between top level elements.", errMsg); return -1; } } break; } node = node->nextSibling; } return 0; } /*---------------------------------------------------------------------------- | xsltFreeState | \---------------------------------------------------------------------------*/ static void xsltFreeState ( xsltState * xs ) { xsltDecimalFormat *df, *dfsave; xsltKeyInfo *ki, *kisave; xsltNodeSet *kvalues; xsltSubDoc *sd, *sdsave; xsltAttrSet *as, *assave; xsltTemplate *tpl, *tplsave; xsltNumberFormat *nf; ast t; xsltTopLevelVar *tlv; xsltNSAlias *nsAlias, *nsAliasSave; xsltExclExtNS *eNS, *eNSsave; Tcl_HashEntry *entryPtr, *entryPtr1; Tcl_HashSearch search, search1; Tcl_HashTable *htable; double *f; if (xs->doctype.systemId) FREE(xs->doctype.systemId); if (xs->doctype.publicId) FREE(xs->doctype.publicId); if (xs->doctype.internalSubset) FREE(xs->doctype.internalSubset); if (xs->doctype.cdataSectionElements) { Tcl_DeleteHashTable (xs->doctype.cdataSectionElements); FREE (xs->doctype.cdataSectionElements); } for (entryPtr = Tcl_FirstHashEntry (&xs->namedTemplates, &search); entryPtr != (Tcl_HashEntry*) NULL; entryPtr = Tcl_NextHashEntry (&search)) { tpl = (xsltTemplate *) Tcl_GetHashValue (entryPtr); if (!tpl->match) { FREE(tpl); } } Tcl_DeleteHashTable (&xs->namedTemplates); for (entryPtr = Tcl_FirstHashEntry (&xs->isElementTpls, &search); entryPtr != (Tcl_HashEntry*) NULL; entryPtr = Tcl_NextHashEntry (&search)) { tpl = (xsltTemplate *) Tcl_GetHashValue (entryPtr); while (tpl) { if (tpl->freeAst) xpathFreeAst (tpl->freeAst); tplsave = tpl; tpl = tpl->next; FREE(tplsave); } } Tcl_DeleteHashTable (&xs->isElementTpls); for (entryPtr = Tcl_FirstHashEntry(&xs->xpaths, &search); entryPtr != (Tcl_HashEntry*) NULL; entryPtr = Tcl_NextHashEntry(&search)) { t = (ast) Tcl_GetHashValue (entryPtr); xpathFreeAst (t); } Tcl_DeleteHashTable(&xs->xpaths); for (entryPtr = Tcl_FirstHashEntry(&xs->pattern, &search); entryPtr != (Tcl_HashEntry*) NULL; entryPtr = Tcl_NextHashEntry(&search)) { t = (ast) Tcl_GetHashValue (entryPtr); xpathFreeAst (t); } Tcl_DeleteHashTable(&xs->pattern); for (entryPtr = Tcl_FirstHashEntry(&xs->formats, &search); entryPtr != (Tcl_HashEntry*) NULL; entryPtr = Tcl_NextHashEntry(&search)) { nf = (xsltNumberFormat *) Tcl_GetHashValue (entryPtr); FREE(nf->tokens); FREE(nf); } Tcl_DeleteHashTable(&xs->formats); for (entryPtr = Tcl_FirstHashEntry(&xs->topLevelVars, &search); entryPtr != (Tcl_HashEntry*) NULL; entryPtr = Tcl_NextHashEntry(&search)) { tlv = (xsltTopLevelVar *) Tcl_GetHashValue (entryPtr); FREE(tlv); } Tcl_DeleteHashTable (&xs->topLevelVars); /*--- free key definition information ---*/ for (entryPtr = Tcl_FirstHashEntry (&xs->keyInfos, &search); entryPtr != (Tcl_HashEntry*) NULL; entryPtr = Tcl_NextHashEntry (&search)) { ki = (xsltKeyInfo *) Tcl_GetHashValue (entryPtr); while (ki) { kisave = ki; ki = ki->next; xpathFreeAst (kisave->matchAst); xpathFreeAst (kisave->useAst); FREE(kisave); } } Tcl_DeleteHashTable (&xs->keyInfos); /*--- free sub documents ---*/ sd = xs->subDocs; while (sd) { sdsave = sd; sd = sd->next; for (entryPtr = Tcl_FirstHashEntry (&sdsave->keyData, &search); entryPtr != (Tcl_HashEntry*) NULL; entryPtr = Tcl_NextHashEntry (&search)) { htable = (Tcl_HashTable *) Tcl_GetHashValue (entryPtr); for (entryPtr1 = Tcl_FirstHashEntry (htable, &search1); entryPtr1 != (Tcl_HashEntry*) NULL; entryPtr1 = Tcl_NextHashEntry (&search1)) { kvalues = (xsltNodeSet *) Tcl_GetHashValue (entryPtr1); FREE(kvalues->nodes); FREE(kvalues); } Tcl_DeleteHashTable (htable); FREE(htable); } Tcl_DeleteHashTable (&sdsave->keyData); eNS = sdsave->excludeNS; while (eNS) { if (eNS->uri) FREE(eNS->uri); eNSsave = eNS; eNS = eNS->next; FREE(eNSsave); } eNS = sdsave->extensionNS; while (eNS) { if (eNS->uri) FREE(eNS->uri); eNSsave = eNS; eNS = eNS->next; FREE(eNSsave); } if (sdsave->baseURI) FREE(sdsave->baseURI); if (sdsave->mustFree) { domFreeDocument (sdsave->doc, NULL, NULL); } FREE(sdsave); } nsAlias = xs->nsAliases; while (nsAlias) { nsAliasSave = nsAlias; nsAlias = nsAlias->next; if (nsAliasSave->fromUri) FREE(nsAliasSave->fromUri); if (nsAliasSave->toUri) FREE(nsAliasSave->toUri); FREE(nsAliasSave); } /*--- free decimal formats ---*/ df = xs->decimalFormats; while (df) { dfsave = df; df = df->next; if (dfsave->name) FREE(dfsave->name); if (dfsave->uri) FREE(dfsave->uri); FREE(dfsave); } /*--- free attribute sets ---*/ as = xs->attrSets; while (as) { assave = as; as = as->next; FREE(assave); } /*--- free templates ---*/ tpl = xs->templates; while (tpl) { tplsave = tpl; if (tpl->freeAst) xpathFreeAst (tpl->freeAst); tpl = tpl->next; FREE(tplsave); } for (entryPtr = Tcl_FirstHashEntry (&(xs->wsInfo.stripTokens), &search); entryPtr != (Tcl_HashEntry*) NULL; entryPtr = Tcl_NextHashEntry (&search)) { f = (double *) Tcl_GetHashValue (entryPtr); FREE(f); } Tcl_DeleteHashTable (&(xs->wsInfo.stripTokens)); for (entryPtr = Tcl_FirstHashEntry (&(xs->wsInfo.preserveTokens), &search); entryPtr != (Tcl_HashEntry*) NULL; entryPtr = Tcl_NextHashEntry (&search)) { f = (double *) Tcl_GetHashValue (entryPtr); FREE(f); } Tcl_DeleteHashTable (&(xs->wsInfo.preserveTokens)); FREE(xs->varFramesStack); FREE(xs->varStack); if (xs->doctype.method) FREE(xs->doctype.method); if (xs->doctype.encoding) FREE(xs->doctype.encoding); if (xs->doctype.mediaType) FREE(xs->doctype.mediaType); FREE (xs); } void xsltFreeStateWrapper ( void *clientData ) { xsltFreeState ((xsltState *)clientData); } /*---------------------------------------------------------------------------- | xsltResetState | \---------------------------------------------------------------------------*/ static void xsltResetState ( xsltState * xs ) { xsltSubDoc *sd, *sdsave, *lastSubDoc = NULL; xsltNodeSet *kvalues; Tcl_HashEntry *entryPtr, *entryPtr1; Tcl_HashSearch search, search1; Tcl_HashTable *htable; /* Free the sub documents, which are resolved relative to nodes in * the xml source. */ /* XML documents don't have excludeNS and extensionNS information and the already parsed XSLT documents information is preserved, therefore, we don't touch excludeNS and extensionNS information */ /* This loop works only as coded, because, the first subdoc will * always be the primary XSLT doc, so xs->subDocs will not * change. Crusty stuff, this code. */ sd = xs->subDocs; while (sd) { sdsave = sd; sd = sd->next; if (sdsave->isStylesheet || sdsave->fixedXMLSource) { if (lastSubDoc) { lastSubDoc->next = sdsave; } else { xs->subDocs = sdsave; } lastSubDoc = sdsave; sdsave->next = NULL; } else { for (entryPtr = Tcl_FirstHashEntry (&sdsave->keyData, &search); entryPtr != (Tcl_HashEntry*) NULL; entryPtr = Tcl_NextHashEntry (&search)) { htable = (Tcl_HashTable *) Tcl_GetHashValue (entryPtr); for (entryPtr1 = Tcl_FirstHashEntry (htable, &search1); entryPtr1 != (Tcl_HashEntry*) NULL; entryPtr1 = Tcl_NextHashEntry (&search1)) { kvalues = (xsltNodeSet *) Tcl_GetHashValue (entryPtr1); FREE(kvalues->nodes); FREE(kvalues); } Tcl_DeleteHashTable (htable); FREE(htable); } Tcl_DeleteHashTable (&sdsave->keyData); if (sdsave->mustFree) { domFreeDocument (sdsave->doc, NULL, NULL); } if (sdsave->baseURI) FREE(sdsave->baseURI); FREE(sdsave); } } xs->nsUniqeNr = 0; /* In theory, the varFramesStack and varStack pointers should be always back to there initial state. But to be sure, we re-initialize, just in case of a bizarre error or something. */ xs->varFramesStackPtr = -1; xs->varStackPtr = -1; } /*---------------------------------------------------------------------------- | xsltCompileStylesheet | \---------------------------------------------------------------------------*/ void * xsltCompileStylesheet ( domDocument * xsltDoc, xpathFuncCallback funcCB, void * xpathFuncClientData, int guardXSLTTree, char ** errMsg ) { domNode *node; int rc; char *tailptr; const char *baseURI; double d, precedence, precedenceLowBound; xsltState *xs; xsltSubDoc *sdoc; domAttrNode *attr; xsltTemplate *tpl; if (!xsltDoc->documentElement) { *errMsg = tdomstrdup ("Document has no element node - can't be a valid " "XSLT 1.0 stylesheet."); return NULL; } *errMsg = NULL; xs = (xsltState *) MALLOC (sizeof (xsltState)); Tcl_InitHashTable ( &(xs->namedTemplates), TCL_STRING_KEYS); Tcl_InitHashTable ( &(xs->isElementTpls), TCL_STRING_KEYS); xs->cbs.varCB = xsltGetVar; xs->cbs.varClientData = (void*)xs; xs->cbs.funcCB = xsltXPathFuncs; xs->cbs.funcClientData = xs; xs->orig_funcCB = funcCB; xs->orig_funcClientData = xpathFuncClientData; xs->xsltMsgCB = NULL; xs->xsltMsgClientData = NULL; xs->varFramesStack = (xsltVarFrame *)MALLOC(sizeof (xsltVarFrame)*4); xs->varFramesStackPtr = -1; xs->varFramesStackLen = 4; xs->varStack = (xsltVariable *)MALLOC(sizeof (xsltVariable)*8); xs->varStackPtr = -1; xs->varStackLen = 8; xs->templates = NULL; xs->lastNode = NULL; xs->attrSets = NULL; xs->decimalFormats = (xsltDecimalFormat*)MALLOC(sizeof (xsltDecimalFormat)); xs->subDocs = NULL; xs->currentTplRule = NULL; xs->currentXSLTNode = NULL; xs->xsltDoc = xsltDoc; xs->varsInProcess = NULL; xs->nsAliases = NULL; xs->nsUniqeNr = 0; Tcl_InitHashTable ( &(xs->wsInfo.stripTokens), TCL_STRING_KEYS); Tcl_InitHashTable ( &(xs->wsInfo.preserveTokens), TCL_STRING_KEYS); xs->wsInfo.hasData = 0; xs->wsInfo.stripAll = 0; xs->wsInfo.wildcardPrec = 0.0; Tcl_InitHashTable ( &(xs->xpaths), TCL_STRING_KEYS); Tcl_InitHashTable ( &(xs->pattern), TCL_STRING_KEYS); Tcl_InitHashTable ( &(xs->formats), TCL_STRING_KEYS); Tcl_InitHashTable ( &(xs->topLevelVars), TCL_STRING_KEYS); Tcl_InitHashTable ( &(xs->keyInfos), TCL_STRING_KEYS); xs->decimalFormats->name = NULL; xs->decimalFormats->uri = NULL; xs->decimalFormats->decimalSeparator = 46; xs->decimalFormats->groupingSeparator = 44; xs->decimalFormats->minusSign = 45; xs->decimalFormats->percent = 37; xs->decimalFormats->perMille = 0x2030; xs->decimalFormats->zeroDigit = 48; xs->decimalFormats->digit = 35; xs->decimalFormats->patternSeparator = 59; xs->decimalFormats->infinity = "Infinity"; xs->decimalFormats->NaN = "NaN"; xs->decimalFormats->next = NULL; xs->indentOutput = 0; memset (&xs->doctype, 0, sizeof (domDocInfo)); node = xsltDoc->documentElement; /* add the XSLT doc to the doc list */ sdoc = (xsltSubDoc*)MALLOC(sizeof (xsltSubDoc)); sdoc->doc = xsltDoc; baseURI = findBaseURI (xsltDoc->documentElement); if (baseURI) { sdoc->baseURI = tdomstrdup (baseURI); } else { sdoc->baseURI = NULL; } Tcl_InitHashTable (&(sdoc->keyData), TCL_STRING_KEYS); sdoc->excludeNS = NULL; sdoc->extensionNS = NULL; sdoc->fwCmpProcessing = 0; sdoc->isStylesheet = 1; sdoc->next = xs->subDocs; sdoc->mustFree = !guardXSLTTree; sdoc->fixedXMLSource = 0; xs->subDocs = sdoc; xs->currentSubDoc = sdoc; if ((getTag(node) != stylesheet) && (getTag(node) != transform)) { /* Check for "Literal Result Element as Stylesheet" (XSLT rec 2.3) */ attr = domGetAttributeNodeNS (node, XSLT_NAMESPACE, "version"); if (!attr) { reportError (node, "The supplied DOM tree does not appear to be" " a stylesheet.", errMsg); goto error; } d = strtod (attr->nodeValue, &tailptr); if (d == 0.0 && tailptr == attr->nodeValue) { reportError (node, "The value of the attribute \"version\" must" " be a number.", errMsg); goto error; } if (d > 1.0) { sdoc->fwCmpProcessing = 1; } else if (d < 1.0) { reportError (node, "Strange \"xsl:version\" value, don't know," " how to handle.", errMsg); goto error; } StripXSLTSpace (xsltDoc->rootNode); /* According to XSLT rec 2.3 we add the literal result element as template, which matches "/" */ tpl = (xsltTemplate *) MALLOC (sizeof (xsltTemplate)); tpl->match = "/"; tpl->name = NULL; tpl->nameURI = NULL; tpl->mode = NULL; tpl->modeURI = NULL; tpl->prio = 0.5; tpl->content = node->ownerDocument->rootNode; tpl->precedence = 1.0; tpl->next = NULL; tpl->sDoc = sdoc; rc = xpathParse (tpl->match, node, XPATH_TEMPMATCH_PATTERN, NULL, NULL, &(tpl->freeAst), errMsg); tpl->ast = tpl->freeAst; xs->templates = tpl; if (rc < 0) goto error; } else { rc = addExclExtNS (sdoc, node, errMsg); if (rc < 0) goto error; StripXSLTSpace (xsltDoc->rootNode); precedence = 1.0; precedenceLowBound = 0.0; rc = processTopLevel (xpathFuncClientData, node, xs, precedence, &precedenceLowBound, errMsg); if (rc != 0) goto error; } return xs; error: xsltFreeState (xs); return NULL; } /*---------------------------------------------------------------------------- | xsltProcess | \---------------------------------------------------------------------------*/ int xsltProcess ( domDocument * xsltDoc, domNode * xmlNode, void * xsltCmdData, char ** parameters, int ignoreUndeclaredParameters, int maxApplyDepth, xpathFuncCallback funcCB, void * xpathFuncClientData, xsltMsgCB xsltMsgCB, void * xsltMsgClientData, char ** errMsg, domDocument ** resultDoc ) { xpathResultSet nodeList; domNode *node; int rc, hnew; const char *baseURI; xsltState *xs; xsltSubDoc *sdoc; Tcl_HashEntry *entryPtr; Tcl_HashSearch search; *errMsg = NULL; if (xsltCmdData) { xs = (xsltState *) xsltCmdData; } else { xs = (xsltState *) xsltCompileStylesheet (xsltDoc, funcCB, xpathFuncClientData, 1, errMsg); if (!xs) return -1; } xs->maxNestedApplyTemplates = maxApplyDepth; xs->nestedApplyTemplates = 0; if (xmlNode->nodeType == DOCUMENT_NODE) { xmlNode = ((domDocument *)xmlNode)->rootNode; } else { xmlNode = xmlNode->ownerDocument->rootNode; } DBG(printXML(xmlNode, 0, 1);) if (xmlNode->ownerDocument->nodeFlags & NEEDS_RENUMBERING) { domRenumberTree (xmlNode->ownerDocument->rootNode); xmlNode->ownerDocument->nodeFlags &= ~NEEDS_RENUMBERING; } xs->resultDoc = domCreateDoc(NULL, 0); if (xs->doctype.systemId) { xs->resultDoc->doctype = (domDocInfo *)MALLOC (sizeof (domDocInfo)); memset (xs->resultDoc->doctype, 0, (sizeof (domDocInfo))); xs->resultDoc->doctype->systemId = tdomstrdup (xs->doctype.systemId); } if (xs->doctype.publicId) { if (!xs->resultDoc->doctype) { xs->resultDoc->doctype = (domDocInfo*)MALLOC (sizeof (domDocInfo)); memset (xs->resultDoc->doctype, 0, (sizeof (domDocInfo))); } xs->resultDoc->doctype->publicId = tdomstrdup (xs->doctype.publicId); } if (xs->doctype.encoding) { if (!xs->resultDoc->doctype) { xs->resultDoc->doctype = (domDocInfo*)MALLOC (sizeof (domDocInfo)); memset (xs->resultDoc->doctype, 0, (sizeof (domDocInfo))); } xs->resultDoc->doctype->encoding = tdomstrdup (xs->doctype.encoding); } if (xs->doctype.mediaType) { if (!xs->resultDoc->doctype) { xs->resultDoc->doctype = (domDocInfo*)MALLOC (sizeof (domDocInfo)); memset (xs->resultDoc->doctype, 0, (sizeof (domDocInfo))); } xs->resultDoc->doctype->mediaType = tdomstrdup (xs->doctype.mediaType); } if (xs->doctype.standalone) { if (!xs->resultDoc->doctype) { xs->resultDoc->doctype = (domDocInfo*)MALLOC (sizeof (domDocInfo)); memset (xs->resultDoc->doctype, 0, (sizeof (domDocInfo))); } xs->resultDoc->doctype->standalone = 1; } if (xs->indentOutput) { xs->resultDoc->nodeFlags |= OUTPUT_DEFAULT_INDENT; } if (xs->doctype.cdataSectionElements) { if (!xs->resultDoc->doctype) { xs->resultDoc->doctype = (domDocInfo*)MALLOC (sizeof (domDocInfo)); memset (xs->resultDoc->doctype, 0, (sizeof (domDocInfo))); } xs->resultDoc->doctype->cdataSectionElements = (Tcl_HashTable *) MALLOC (sizeof (Tcl_HashTable)); Tcl_InitHashTable (xs->resultDoc->doctype->cdataSectionElements, TCL_STRING_KEYS); for (entryPtr = Tcl_FirstHashEntry (xs->doctype.cdataSectionElements, &search); entryPtr != (Tcl_HashEntry*) NULL; entryPtr = Tcl_NextHashEntry (&search)) { Tcl_CreateHashEntry (xs->resultDoc->doctype->cdataSectionElements, Tcl_GetHashKey ( xs->doctype.cdataSectionElements, entryPtr ), &hnew); } } xs->xmlRootNode = xmlNode; xs->lastNode = xs->resultDoc->rootNode; xs->xsltMsgCB = xsltMsgCB; xs->xsltMsgClientData = xsltMsgClientData; xsltPushVarFrame(xs); xpathRSInit( &nodeList ); rsAddNodeFast( &nodeList, xmlNode); /* strip space from the XML document, if necessary */ if (xs->wsInfo.hasData) { StripXMLSpace (xs, xmlNode); } /* add the XML doc to the doc list */ sdoc = (xsltSubDoc*)MALLOC(sizeof (xsltSubDoc)); sdoc->doc = xmlNode->ownerDocument; baseURI = findBaseURI (xmlNode); if (baseURI) { sdoc->baseURI = tdomstrdup (baseURI); } else { sdoc->baseURI = NULL; } Tcl_InitHashTable (&(sdoc->keyData), TCL_STRING_KEYS); sdoc->excludeNS = NULL; sdoc->extensionNS = NULL; sdoc->fwCmpProcessing = 0; sdoc->isStylesheet = 0; sdoc->mustFree = 0; sdoc->fixedXMLSource = 0; sdoc->next = xs->subDocs; xs->subDocs = sdoc; xs->currentSubDoc = sdoc; rc = processTopLevelVars (xmlNode, xs, parameters, ignoreUndeclaredParameters, errMsg); if (rc != 0) goto error; node = xs->xsltDoc->documentElement; rc = ApplyTemplates (xs, &nodeList, xmlNode, 0, node, &nodeList, NULL, NULL, errMsg); if (rc != 0) goto error; /* Rudimentary xsl:output support */ if (xs->doctype.method) { if (!xs->resultDoc->doctype) { xs->resultDoc->doctype = (domDocInfo*)MALLOC (sizeof (domDocInfo)); memset (xs->resultDoc->doctype, 0, (sizeof (domDocInfo))); } xs->resultDoc->doctype->method = tdomstrdup (xs->doctype.method); } else { /* default output method */ node = xs->resultDoc->rootNode->firstChild; while (node) { if (node->nodeType == TEXT_NODE) { char *pc; int i, only_whites; only_whites = 1; for (i=0, pc = ((domTextNode*)node)->nodeValue; i < ((domTextNode*)node)->valueLength; i++, pc++) { if (!IS_XML_WHITESPACE(*pc)) { only_whites = 0; break; } } if (!only_whites) break; } if (node->nodeType == ELEMENT_NODE) { if (STRCASECMP(node->nodeName, "html")==0) { if (!xs->resultDoc->doctype) { xs->resultDoc->doctype = (domDocInfo*)MALLOC (sizeof (domDocInfo)); memset (xs->resultDoc->doctype, 0, (sizeof (domDocInfo))); } xs->resultDoc->doctype->method = tdomstrdup ("html"); } break; } node = node->nextSibling; } } /* Make the first ELEMENT_NODE the documentElement. There could be text, comment or PI nodes before the first element node. If the root node doesn't have an element node under it's children, fall back to the firstChild as documentElement. */ domSetDocumentElement (xs->resultDoc); *resultDoc = xs->resultDoc; xsltPopVarFrame (xs); xpathRSFree( &nodeList ); if (xsltCmdData) { xsltResetState (xs); } else { xsltFreeState (xs); } return 0; error: xsltPopVarFrame (xs); xpathRSFree( &nodeList ); domFreeDocument (xs->resultDoc, NULL, NULL); xs->resultDoc = NULL; if (xsltCmdData) { xsltResetState (xs); } else { xsltFreeState (xs); } return -1; } /* xsltProcess */ tdom-0.9.5-src/generic/nodecmd.h0000644000175000017500000000472414703531020015143 0ustar rolfrolf/*---------------------------------------------------------------------------- | Copyright (C) 1999 Jochen C. Loewer (loewerj@hotmail.com) +----------------------------------------------------------------------------- | | The contents of this file are subject to the Mozilla Public License | Version 2.0 (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) 1998, 1999 | 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-2002 | Rolf Ade. All Rights Reserved. | | Written by Zoran Vasiljevic | July 12, 2000 | \---------------------------------------------------------------------------*/ int nodecmd_createNodeCmd (Tcl_Interp * interp, int objc, Tcl_Obj *const objv[], int checkName, int checkCharData); int nodecmd_appendFromScript (Tcl_Interp *interp, domNode *node, Tcl_Obj *cmdObj); int nodecmd_insertBeforeFromScript (Tcl_Interp *interp, domNode *node, Tcl_Obj *cmdObj, domNode *refChild); int nodecmd_processAttributes (Tcl_Interp *interp, domNode *node, int type, int objc, Tcl_Obj *const objv[], Tcl_Obj **cmdObj); domNode * nodecmd_currentNode (Tcl_Interp *interp); void nodecmd_init (Tcl_Interp *interp); /* EOF $RCSfile $ */ /* Emacs Setup Variables */ /* Local Variables: */ /* mode: C */ /* indent-tabs-mode: nil */ /* c-basic-offset: 4 */ /* End: */ tdom-0.9.5-src/generic/dom.c0000644000175000017500000054674614703531020014323 0ustar rolfrolf/*--------------------------------------------------------------------------- | Copyright (C) 1999 Jochen C. Loewer (loewerj@hotmail.com) +---------------------------------------------------------------------------- | | A DOM interface upon the expat XML parser for the C language | according to the W3C recommendation REC-DOM-Level-1-19981001 | | | The contents of this file are subject to the Mozilla Public License | Version 2.0 (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) 1998, 1999 | Jochen Loewer. All Rights Reserved. | | Contributor(s): | Sept99 Carsten Zerbst Added comment and processing instructions | nodes. | | June00 Zoran Vasiljevic Made thread-safe. | | 01 Rolf Ade baseURI stuff, ID support, external | entities, tdom command | | | written by Jochen Loewer | April 5, 1999 | \--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- | Includes | \--------------------------------------------------------------------------*/ #include #include #include #include #include /* #define DEBUG */ /*---------------------------------------------------------------------------- | Debug Macros | \---------------------------------------------------------------------------*/ #ifdef DEBUG # define DBG(x) x #else # define DBG(x) #endif #define MutationEvent() #define MutationEvent2(type,node) #define MutationEvent3(type,node,relatioNode) #define MCHK(a) if ((a)==NULL) { \ fprintf(stderr, \ "Memory alloc error line: %d",__LINE__); \ exit(1); \ } #define INITIAL_BASEURISTACK_SIZE 4; /*--------------------------------------------------------------------------- | Globals | In threading environment, some are located in domDocument structure | and some are handled differently (domUniqueNodeNr, domUniqueDocNr) | \--------------------------------------------------------------------------*/ #ifndef TCL_THREADS unsigned long domUniqueNodeNr = 0; unsigned long domUniqueDocNr = 0; Tcl_HashTable tdom_tagNames; Tcl_HashTable tdom_attrNames; #endif static int domModuleIsInitialized = 0; TDomThreaded(static Tcl_Mutex initMutex;) static const char *domException2StringTable [] = { "OK - no exception", "INDEX_SIZE_ERR", "DOMSTRING_SIZE_ERR", "HIERARCHY_REQUEST_ERR", "WRONG_DOCUMENT_ERR", "INVALID_CHARACTER_ERR", "NO_DATA_ALLOWED_ERR", "NO_MODIFICATION_ALLOWED_ERR", "NOT_FOUND_ERR", "NOT_SUPPORTED_ERR", "INUSE_ATTRIBUTE_ERR" }; static char tdom_usage[] = "Usage tdom , where subCommand can be:\n" " enable \n" " getdoc \n" " setStoreLineColumn \n" ; /*--------------------------------------------------------------------------- | type domBaseURIstackElem | \--------------------------------------------------------------------------*/ typedef struct _domActiveBaseURI { int depth; const char *baseURI; } domActiveBaseURI; /*--------------------------------------------------------------------------- | type domReadInfo | \--------------------------------------------------------------------------*/ /* Keep in sync with tdomCmdReadInfo below */ typedef struct _domReadInfo { XML_Parser parser; domDocument *document; domNode *currentNode; int depth; int ignoreWhiteSpaces; int cdataSection; Tcl_DString *cdata; int storeLineColumn; domLength textStartLine; domLength textStartColumn; domLength textStartByteIndex; int ignorexmlns; int feedbackAfter; Tcl_Obj *feedbackCmd; XML_Index nextFeedbackPosition; Tcl_Interp *interp; int activeNSsize; int activeNSpos; domActiveNS *activeNS; int baseURIstackSize; int baseURIstackPos; domActiveBaseURI *baseURIstack; int insideDTD; #ifndef TDOM_NO_SCHEMA SchemaData *sdata; #endif int status; } domReadInfo; /*---------------------------------------------------------------------------- | Prototypes | \---------------------------------------------------------------------------*/ static void DispatchPCDATA (domReadInfo *info); #ifndef TCL_THREADS /*--------------------------------------------------------------------------- | domModuleFinalize | \--------------------------------------------------------------------------*/ static void domModuleFinalize(ClientData unused) { Tcl_HashEntry *entryPtr; Tcl_HashSearch search; entryPtr = Tcl_FirstHashEntry(&tdom_tagNames, &search); while (entryPtr) { Tcl_DeleteHashEntry(entryPtr); entryPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&tdom_tagNames); entryPtr = Tcl_FirstHashEntry(&tdom_attrNames, &search); while (entryPtr) { Tcl_DeleteHashEntry(entryPtr); entryPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&tdom_attrNames); return; } #endif /* TCL_THREADS */ /*--------------------------------------------------------------------------- | domModuleInitialize | \--------------------------------------------------------------------------*/ void domModuleInitialize ( ) { if (domModuleIsInitialized == 0) { TDomThreaded(Tcl_MutexLock(&initMutex);) if (domModuleIsInitialized == 0) { domAllocInit(); TDomNotThreaded ( Tcl_InitHashTable(&tdom_tagNames, TCL_STRING_KEYS); Tcl_InitHashTable(&tdom_attrNames, TCL_STRING_KEYS); Tcl_CreateExitHandler(domModuleFinalize, NULL); ) TDomThreaded( Tcl_CreateExitHandler(domLocksFinalize, NULL); ) domModuleIsInitialized = 1; } TDomThreaded(Tcl_MutexUnlock(&initMutex);) } } /*--------------------------------------------------------------------------- | coercion routines for calling from C++ | \--------------------------------------------------------------------------*/ domAttrNode * coerceToAttrNode( domNode *n ) { return (domAttrNode *)n; } domTextNode * coerceToTextNode( domNode *n ) { return (domTextNode *)n; } domProcessingInstructionNode * coerceToProcessingInstructionNode( domNode *n ) { return (domProcessingInstructionNode *)n; } /*--------------------------------------------------------------------------- | domIsNAME | \--------------------------------------------------------------------------*/ int domIsNAME ( const char *name ) { const char *p; p = name; if (!isNameStart(p)) return 0; p += UTF8_CHAR_LEN(*p); while (*p) { if (isNameChar(p)) p += UTF8_CHAR_LEN(*p); else return 0; } return 1; } /*--------------------------------------------------------------------------- | domIsPINAME | \--------------------------------------------------------------------------*/ int domIsPINAME ( const char *name ) { if (strlen (name) == 3 && ((name[0] == 'x') || (name[0] == 'X')) && ((name[1] == 'm') || (name[1] == 'M')) && ((name[2] == 'l') || (name[2] == 'L')) ) { return 0; } return domIsNAME (name); } /*--------------------------------------------------------------------------- | domIsQNAME | \--------------------------------------------------------------------------*/ int domIsQNAME ( const char *name ) { const char *p; p = name; if (!isNCNameStart(p)) return 0; p += UTF8_CHAR_LEN(*p); while (*p) { if (isNCNameChar(p)) p += UTF8_CHAR_LEN(*p); else { if (*p == ':') { p += 1; if (!isNCNameStart(p)) return 0; p += UTF8_CHAR_LEN(*p); break; } else return 0; } } while (*p) { if (isNCNameChar(p)) p += UTF8_CHAR_LEN(*p); else return 0; } return 1; } /*--------------------------------------------------------------------------- | domIsNCNAME | \--------------------------------------------------------------------------*/ int domIsNCNAME ( const char *name ) { const char *p; p = name; if (!isNCNameStart(p)) return 0; p += UTF8_CHAR_LEN(*p); while (*p) { if (isNCNameChar(p)) p += UTF8_CHAR_LEN(*p); else return 0; } return 1; } /*--------------------------------------------------------------------------- | domIsChar | \--------------------------------------------------------------------------*/ int domIsChar ( const char *str ) { const char *p; int clen; p = str; while (*p) { clen = UTF8_CHAR_LEN(*p); if (!clen) return 0; if (UTF8_XMLCHAR((unsigned const char *)p,clen)) p += clen; else return 0; } return 1; } /*--------------------------------------------------------------------------- | domIsHTML5CustomName | \--------------------------------------------------------------------------*/ int domIsHTML5CustomName ( const char *str ) { const char *p; domLength clen; int dashseen = 0; Tcl_UniChar uniChar; p = str; if (*p < 'a' || *p > 'z') { return 0; } p++; while (*p) { clen = UTF8_CHAR_LEN(*p); if (clen == 0) return 0; if (clen == 1) { if (*p == '-') { dashseen = 1; p++; } else { if (*p == '.' || (*p >= '0' && *p <= '9') || *p == '_' || (*p >= 'a' && *p <= 'z')) { p++; } else { return 0; } } continue; } if (clen == 4) { p += clen; continue; } clen = Tcl_UtfToUniChar (p, &uniChar); if (uniChar == 0xB7 || (uniChar >= 0xC0 && uniChar <= 0xD6) || (uniChar >= 0xD8 && uniChar <= 0xF6) || (uniChar >= 0xF8 && uniChar <= 0x37D) || (uniChar >= 0x37F && uniChar <= 0x1FFF) || (uniChar >= 0x200C && uniChar <= 0x200D) || (uniChar >= 0x203F && uniChar <= 0x2040) || (uniChar >= 0x2070 && uniChar <= 0x218F) || (uniChar >= 0x2C00 && uniChar <= 0x2FEF) || (uniChar >= 0x3001 && uniChar <= 0xD7FF) || (uniChar >= 0xF900 && uniChar <= 0xFDCF) || (uniChar >= 0xFDF0 && uniChar <= 0xFFFD)) { p += clen; } else { return 0; } } if (!dashseen) return 0; switch (str[0]) { case 'a': if (!strcmp(str,"annotation-xml")) {return 0;} break; case 'c': if (!strcmp(str,"color-profile")) {return 0;} break; case 'f': if (!strcmp(str,"font-face") || !strcmp(str,"font-face-src") || !strcmp(str,"font-face-uri") || !strcmp(str,"font-face-format") || !strcmp(str,"font-face-name")) {return 0;} break; case 'm': if (!strcmp(str,"missing-glyph")) {return 0;} break; } return 1; } /*--------------------------------------------------------------------------- | domClearString | \--------------------------------------------------------------------------*/ void domClearString ( char *str, char *replacement, domLength repllen, Tcl_DString *clearedstr, int *changed ) { char *p, *s; int clen; *changed = 0; p = str; while (*p) { clen = UTF8_CHAR_LEN(*p); if (!clen || !UTF8_XMLCHAR((unsigned const char*)p,clen)) { *changed = 1; Tcl_DStringInit (clearedstr); break; } p += clen; } if (!*changed) { return; } Tcl_DStringAppend (clearedstr, str, (domLength)(p-str)); if (repllen) { Tcl_DStringAppend (clearedstr, replacement, repllen); } if (clen) { p += clen; } else { /* If it isn't a UTF-8 encoded character what is it? And how * many of whatever it is? */ p++; } s = p; while (*p) { clen = UTF8_CHAR_LEN(*p); if (!clen || !UTF8_XMLCHAR((unsigned const char*)p,clen)) { Tcl_DStringAppend (clearedstr, s, (domLength)(p-s)); if (repllen) { Tcl_DStringAppend (clearedstr, replacement, repllen); } if (clen) { p += clen; } else { p++; } s = p; } else { p += clen; } } Tcl_DStringAppend (clearedstr, s, (domLength)(p-s)); } /*--------------------------------------------------------------------------- | domIsBMPChar | \--------------------------------------------------------------------------*/ int domIsBMPChar ( const char *str ) { const char *p; int clen; p = str; while (*p) { clen = UTF8_CHAR_LEN(*p); if (clen > 3 || clen == 0) return 0; p += clen; } return 1; } /*--------------------------------------------------------------------------- | domIsComment | \--------------------------------------------------------------------------*/ int domIsComment ( const char *str ) { const char *p; domLength len, i = 0; p = str; len = (domLength)strlen (str); while (i < len) { if (*p == '-') { if (i == len - 1) return 0; p++; i++; if (*p == '-') return 0; } p++; i++; } return domIsChar (str); } /*--------------------------------------------------------------------------- | domIsCDATA | \--------------------------------------------------------------------------*/ int domIsCDATA ( const char *str ) { const char *p; domLength len, i = 0; p = str; len = (domLength)strlen (str); while (i < len - 2) { if ( *p == ']' && p[1] == ']' && p[2] == '>') return 0; p++; i++; } return domIsChar (str); } /*--------------------------------------------------------------------------- | domIsPIValue | \--------------------------------------------------------------------------*/ int domIsPIValue ( const char *str ) { const char *p; domLength len, i = 0; p = str; len = (domLength)strlen (str); while (i < len - 1) { if (*p == '?' && p[1] == '>') return 0; p++; i++; } return domIsChar (str); } /*--------------------------------------------------------------------------- | domLookupNamespace | \--------------------------------------------------------------------------*/ domNS * domLookupNamespace ( domDocument *doc, const char *prefix, const char *namespaceURI ) { domNS *ns; int i; if (prefix==NULL) return NULL; for (i = 0; i <= doc->nsptr; i++) { ns = doc->namespaces[i]; if ( (ns->prefix != NULL) && (strcmp(prefix,ns->prefix)==0) && (strcmp(namespaceURI, ns->uri)==0) ) { return ns; } } return NULL; } /* *---------------------------------------------------------------------- * * domPrecedes -- * * This helper procedure returns if node precedes other with regard * to their position in the document and according to the document * order. The two nodes could be out of the two documents. Both * nodes must not be out of the fragments list. * * Results: * 1 if node precedes other in document order, 0 otherwise. * * Side effects: * None. * *---------------------------------------------------------------------- */ int domPrecedes ( domNode *node, domNode *other ) { domNode *nodeAncestor, *otherAncestor; domAttrNode *attrN, *attrO; if (node == other) { return 0; } if (node->nodeType == ATTRIBUTE_NODE) { attrN = (domAttrNode*)node; if (other->nodeType == ATTRIBUTE_NODE) { attrO = (domAttrNode*)other; if (attrN->parentNode == attrO->parentNode) { attrN = attrN->nextSibling; while (attrN) { if (attrN == attrO) { return 1; } attrN = attrN->nextSibling; } return 0; } else { node = attrN->parentNode; other = attrO->parentNode; } } else { if (attrN->parentNode == other) { return 0; } else { node = attrN->parentNode; } } } if (other->nodeType == ATTRIBUTE_NODE) { attrO = (domAttrNode*)other; if (node == attrO->parentNode) { return 1; } else { other = attrO->parentNode; } } if (node->ownerDocument != other->ownerDocument) { /* For mt tdom, this does not, what it should: whatever relative order two nodes out of different documents ever have (that is not determined by the rec) it must return always the same order (that is required by the rec). */ return (node->ownerDocument->documentNumber < other->ownerDocument->documentNumber); } #ifndef TCL_THREADS if (node->ownerDocument->nodeFlags & NEEDS_RENUMBERING) { domRenumberTree (node->ownerDocument->rootNode); node->ownerDocument->nodeFlags &= ~NEEDS_RENUMBERING; } return (node->nodeNumber < other->nodeNumber); # else if (node->ownerDocument->nodeFlags & NEEDS_RENUMBERING && node->ownerDocument->refCount <= 1) { domRenumberTree (node->ownerDocument->rootNode); node->ownerDocument->nodeFlags &= ~NEEDS_RENUMBERING; } if (!(node->ownerDocument->nodeFlags & NEEDS_RENUMBERING)) { return (node->nodeNumber < other->nodeNumber); } #endif otherAncestor = other; while (otherAncestor->parentNode) { otherAncestor = otherAncestor->parentNode; if (otherAncestor == node) { return 1; } } nodeAncestor = node; while (nodeAncestor->parentNode) { otherAncestor = other; while (otherAncestor->parentNode) { if (nodeAncestor->parentNode == otherAncestor->parentNode) { nodeAncestor = nodeAncestor->nextSibling; while (nodeAncestor) { if (nodeAncestor == otherAncestor) { return 1; } nodeAncestor = nodeAncestor->nextSibling; } return 0; } otherAncestor = otherAncestor->parentNode; } nodeAncestor = nodeAncestor->parentNode; if (nodeAncestor == other) { return 0; } } nodeAncestor = nodeAncestor->nextSibling; while (nodeAncestor) { if (nodeAncestor == otherAncestor) { return 1; } nodeAncestor = nodeAncestor->nextSibling; } if (node == node->ownerDocument->rootNode) { return 1; } return 0; } /*--------------------------------------------------------------------------- | domRenumberTree | \--------------------------------------------------------------------------*/ void domRenumberTree ( domNode *node ) { while (node) { node->nodeNumber = NODE_NO(node->ownerDocument); if (node->nodeType == ELEMENT_NODE) { domRenumberTree (node->firstChild); } node = node->nextSibling; } } /*--------------------------------------------------------------------------- | domLookupPrefixWithMappings | \--------------------------------------------------------------------------*/ const char * domLookupPrefixWithMappings ( domNode *node, const char *prefix, char **prefixMappings ) { int i; domNS *ns; if (prefixMappings) { i = 0; while (prefixMappings[i]) { if (strcmp (prefix, prefixMappings[i]) == 0) { return prefixMappings[i+1]; } i += 2; } } ns = domLookupPrefix (node, prefix); if (ns) return ns->uri; else return NULL; } /*--------------------------------------------------------------------------- | domLookupPrefix | \--------------------------------------------------------------------------*/ domNS * domLookupPrefix ( domNode *node, const char *prefix ) { domAttrNode *NSattr; domNode *orgNode = node; int found; found = 0; while (node) { if (node->firstAttr && !(node->firstAttr->nodeFlags & IS_NS_NODE)) { node = node->parentNode; continue; } NSattr = node->firstAttr; while (NSattr && (NSattr->nodeFlags & IS_NS_NODE)) { if (prefix[0] == '\0') { if (NSattr->nodeName[5] == '\0') { found = 1; break; } } else { if (NSattr->nodeName[5] != '\0' && strcmp (&NSattr->nodeName[6], prefix)==0) { found = 1; break; } } NSattr = NSattr->nextSibling; } if (found) { return domGetNamespaceByIndex (node->ownerDocument, NSattr->namespace); } node = node->parentNode; } if (prefix && (strcmp (prefix, "xml")==0)) { NSattr = orgNode->ownerDocument->rootNode->firstAttr; return domGetNamespaceByIndex (orgNode->ownerDocument, NSattr->namespace); } return NULL; } /*--------------------------------------------------------------------------- | domIsNamespaceInScope | \--------------------------------------------------------------------------*/ int domIsNamespaceInScope ( domActiveNS *NSstack, int NSstackPos, const char *prefix, const char *namespaceURI ) { int i; for (i = NSstackPos; i >= 0; i--) { if (NSstack[i].namespace->prefix[0] && (strcmp(NSstack[i].namespace->prefix, prefix)==0)) { if (strcmp(NSstack[i].namespace->uri, namespaceURI)==0) { /* OK, exactly the same namespace declaration is in scope */ return 1; } else { /* This prefix is currently assigned to another uri, we need a new NS declaration, to override this one */ return 0; } } } return 0; } /*--------------------------------------------------------------------------- | domLookupURI | \--------------------------------------------------------------------------*/ domNS * domLookupURI ( domNode *node, char *uri ) { domAttrNode *NSattr; int found, alreadyHaveDefault; found = 0; alreadyHaveDefault = 0; while (node) { if (node->firstAttr && !(node->firstAttr->nodeFlags & IS_NS_NODE)) { node = node->parentNode; continue; } NSattr = node->firstAttr; while (NSattr && (NSattr->nodeFlags & IS_NS_NODE)) { if (NSattr->nodeName[5] == '\0') { if (!alreadyHaveDefault) { if (strcmp (NSattr->nodeValue, uri)==0) { found = 1; break; } else { alreadyHaveDefault = 1; } } } else { if (strcmp (NSattr->nodeValue, uri)==0) { found = 1; break; } } NSattr = NSattr->nextSibling; } if (found) { return domGetNamespaceByIndex (node->ownerDocument, NSattr->namespace); } node = node->parentNode; } return NULL; } /*--------------------------------------------------------------------------- | domGetNamespaceByIndex | \--------------------------------------------------------------------------*/ domNS * domGetNamespaceByIndex ( domDocument *doc, unsigned int nsIndex ) { if (!nsIndex) return NULL; return doc->namespaces[nsIndex-1]; } /*--------------------------------------------------------------------------- | domNewNamespace | \--------------------------------------------------------------------------*/ domNS* domNewNamespace ( domDocument *doc, const char *prefix, const char *namespaceURI ) { domNS *ns = NULL; DBG(fprintf(stderr, "domNewNamespace '%s' --> '%s' \n", prefix, namespaceURI);) ns = domLookupNamespace (doc, prefix, namespaceURI); if (ns != NULL) return ns; doc->nsptr++; #ifdef TDOM_LESS_NS if (doc->nsptr > 254) { DBG(fprintf (stderr, "maximum number of namespaces exceeded!!!\n");) domPanic("domNewNamespace: maximum number of namespaces exceeded!"); } #endif if (doc->nsptr >= doc->nslen) { doc->namespaces = (domNS**) REALLOC ((char*) doc->namespaces, sizeof (domNS*) * 2 * doc->nslen); doc->nslen *= 2; } doc->namespaces[doc->nsptr] = (domNS*)MALLOC (sizeof (domNS)); ns = doc->namespaces[doc->nsptr]; if (prefix == NULL) { ns->prefix = tdomstrdup(""); } else { ns->prefix = tdomstrdup(prefix); } if (namespaceURI == NULL) { ns->uri = tdomstrdup(""); } else { ns->uri = tdomstrdup(namespaceURI); } ns->index = doc->nsptr + 1; return ns; } /*--------------------------------------------------------------------------- | domSplitQName - extract namespace prefix (if any) | \--------------------------------------------------------------------------*/ int domSplitQName ( const char *name, char *prefix, const char **localName ) { const char *s; char *p, *prefixEnd; s = name; p = prefix; prefixEnd = &prefix[MAX_PREFIX_LEN-1]; while (*s && (*s != ':')) { if (p < prefixEnd) *p++ = *s; s++; } if (*s != ':') { *prefix = '\0'; *localName = name; return 0; } *p++ = '\0'; *localName = ++s; DBG(fprintf(stderr, "domSplitName %s -> '%s' '%s'\n", name, prefix, *localName); ) return 1; } /*--------------------------------------------------------------------------- | domNamespaceURI | \--------------------------------------------------------------------------*/ const char * domNamespaceURI ( domNode *node ) { domAttrNode *attr; domNS *ns; if (node->nodeType == ATTRIBUTE_NODE) { attr = (domAttrNode*)node; if (!attr->namespace) return NULL; if (attr->nodeFlags & IS_NS_NODE) return NULL; ns = attr->parentNode->ownerDocument->namespaces[attr->namespace-1]; } else if (node->nodeType == ELEMENT_NODE) { if (!node->namespace) return NULL; ns = node->ownerDocument->namespaces[node->namespace-1]; } else { return NULL; } return ns->uri; } /*--------------------------------------------------------------------------- | domNamespacePrefix | \--------------------------------------------------------------------------*/ const char * domNamespacePrefix ( domNode *node ) { domAttrNode *attr; domNS *ns; if (node->nodeType == ATTRIBUTE_NODE) { attr = (domAttrNode*)node; if (!attr->namespace) return NULL; ns = attr->parentNode->ownerDocument->namespaces[attr->namespace-1]; } else if (node->nodeType == ELEMENT_NODE) { if (!node->namespace) return NULL; ns = node->ownerDocument->namespaces[node->namespace-1]; } else { return NULL; } if (ns) return ns->prefix; return NULL; } /*--------------------------------------------------------------------------- | domGetLocalName | \--------------------------------------------------------------------------*/ const char * domGetLocalName ( const char *nodeName ) { char prefix[MAX_PREFIX_LEN]; const char *localName; domSplitQName (nodeName, prefix, &localName); return localName; } /* *---------------------------------------------------------------------- * * domGetAttributeNodeNS -- * * Search a given node for an attribute with namespace "uri" and * localname "localname". * * Results: * Returns a pointer to the attribute, if there is one with the * given namespace and localname. Otherwise returns NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ domAttrNode * domGetAttributeNodeNS ( domNode *node, /* The attributes of this node are searched for a matching attribute; the node must exist */ const char *uri, /* The namespace of the demanded attribute */ const char *localname /* The localname of the demanded attribute */ ) { domAttrNode *attr; domNS *ns; int noNS; char prefix[MAX_PREFIX_LEN]; const char *attrLocalName; if (uri[0] == '\0') noNS = 1; else noNS = 0; attr = node->firstAttr; while (attr) { if (noNS) { if (!attr->namespace && strcmp (attr->nodeName, localname) == 0) { return attr; } } else { if (attr->namespace) { domSplitQName (attr->nodeName, prefix, &attrLocalName); if (strcmp (localname, attrLocalName) == 0) { ns = domGetNamespaceByIndex (node->ownerDocument, attr->namespace); if (strcmp (ns->uri, uri) == 0) { return attr; } } } } attr = attr->nextSibling; } return NULL; } /* *---------------------------------------------------------------------- * * domPreviousSibling -- * * Returns the previous node to the given node or NULL, if there * is no previous node. This function is needed in situations, * where the given node may also be an domAttrNode. Namespace * declaring attributes are treated as any other * attributes. Since the domAttrNode struct doesn't has an * element for the previous attribute, we need a function for the * relatively rare cases, the 'previous attribute' is * needed. Remember, that the XML rec say, that there is no * specific order of the attributes of a node. * * Results: * A pointer to the previous node of the given one * or NULL, if there isn't a previous node. * * Side effects: * None. * *---------------------------------------------------------------------- */ domNode * domPreviousSibling ( domNode *node /* The reference attribute */ ) { domAttrNode *attr, *attr1; if (node->nodeType != ATTRIBUTE_NODE) { return node->previousSibling; } attr = (domAttrNode*) node; if (attr->parentNode->firstAttr == attr) { return NULL; } attr1 = attr->parentNode->firstAttr; while (attr1) { if (attr1->nextSibling == attr) { return (domNode*)attr1; } attr1 = attr1->nextSibling; } /* Not reached */ return NULL; } #ifndef TDOM_NO_EXPAT /*--------------------------------------------------------------------------- | startElement | \--------------------------------------------------------------------------*/ static void startElement( void *userData, const char *name, const char **atts ) { domReadInfo *info = userData; domNode *node, *parentNode; domLineColumn *lc; domAttrNode *attrnode, *lastAttr; const char **atPtr, **idAttPtr; Tcl_HashEntry *h; size_t len; int hnew, pos, idatt, newNS, result; const char *xmlns, *localname; char tagPrefix[MAX_PREFIX_LEN]; char prefix[MAX_PREFIX_LEN]; domNS *ns; char feedbackCmd[24]; if (info->feedbackAfter) { if (info->nextFeedbackPosition <= XML_GetCurrentByteIndex (info->parser) ) { if (info->feedbackCmd) { result = Tcl_GlobalEvalObj(info->interp, info->feedbackCmd); } else { sprintf(feedbackCmd, "%s", "::dom::domParseFeedback"); result = Tcl_Eval(info->interp, feedbackCmd); } if (result != TCL_OK) { DBG(fprintf(stderr, "%s\n", Tcl_GetStringResult (info->interp));); info->status = result; XML_StopParser(info->parser, 1); return; } info->nextFeedbackPosition = XML_GetCurrentByteIndex (info->parser) + info->feedbackAfter; Tcl_ResetResult (info->interp); } } DispatchPCDATA (info); h = Tcl_CreateHashEntry(&HASHTAB(info->document,tdom_tagNames), name, &hnew); if (info->storeLineColumn) { node = (domNode*) domAlloc(sizeof(domNode) + sizeof(domLineColumn)); } else { node = (domNode*) domAlloc(sizeof(domNode)); } memset(node, 0, sizeof(domNode)); node->nodeType = ELEMENT_NODE; node->nodeName = (char *)&(h->key); node->nodeNumber = NODE_NO(info->document); node->ownerDocument = info->document; if (info->baseURIstack[info->baseURIstackPos].baseURI != XML_GetBase (info->parser)) { h = Tcl_CreateHashEntry (info->document->baseURIs, (char*) node, &hnew); Tcl_SetHashValue (h, tdomstrdup (XML_GetBase (info->parser))); node->nodeFlags |= HAS_BASEURI; info->baseURIstackPos++; if (info->baseURIstackPos >= info->baseURIstackSize) { info->baseURIstack = (domActiveBaseURI*) REALLOC( (char*)info->baseURIstack, sizeof(domActiveBaseURI) * 2 * info->baseURIstackSize); info->baseURIstackSize = 2 * info->baseURIstackSize; } info->baseURIstack[info->baseURIstackPos].baseURI = XML_GetBase (info->parser); info->baseURIstack[info->baseURIstackPos].depth = info->depth; } if (info->depth == 0) { if (info->document->rootNode->lastChild) { info->document->rootNode->lastChild->nextSibling = node; node->previousSibling = info->document->rootNode->lastChild; } else { info->document->rootNode->firstChild = node; } info->document->rootNode->lastChild = node; } else { parentNode = info->currentNode; node->parentNode = parentNode; if (parentNode->firstChild) { parentNode->lastChild->nextSibling = node; node->previousSibling = parentNode->lastChild; parentNode->lastChild = node; } else { parentNode->firstChild = parentNode->lastChild = node; } } info->currentNode = node; if (info->storeLineColumn) { lc = (domLineColumn*) ( ((char*)node) + sizeof(domNode)); node->nodeFlags |= HAS_LINE_COLUMN; lc->line = XML_GetCurrentLineNumber (info->parser); lc->column = XML_GetCurrentColumnNumber (info->parser); lc->byteIndex = XML_GetCurrentByteIndex (info->parser); } lastAttr = NULL; /*-------------------------------------------------------------- | process namespace declarations | \-------------------------------------------------------------*/ if (!info->ignorexmlns) { for (atPtr = atts; atPtr[0] && atPtr[1]; atPtr += 2) { if (strncmp(atPtr[0], "xmlns", 5) == 0) { xmlns = atPtr[0]; newNS = 1; if (xmlns[5] == ':') { if (atPtr[1][0] == '\0') { Tcl_SetResult (info->interp, "Missing URI in Namespace " "declaration", NULL); XML_StopParser(info->parser, 0); return; } if (domIsNamespaceInScope (info->activeNS, info->activeNSpos, &(xmlns[6]), atPtr[1])) { ns = domLookupPrefix (info->currentNode, &(xmlns[6])); newNS = 0; } else { ns = domNewNamespace(info->document, &xmlns[6], atPtr[1]); } } else { ns = domNewNamespace(info->document, "", atPtr[1]); } if (newNS) { /* push active namespace */ info->activeNSpos++; if (info->activeNSpos >= info->activeNSsize) { info->activeNS = (domActiveNS*) REALLOC( (char*)info->activeNS, sizeof(domActiveNS) * 2 * info->activeNSsize); info->activeNSsize = 2 * info->activeNSsize; } info->activeNS[info->activeNSpos].depth = info->depth; info->activeNS[info->activeNSpos].namespace = ns; } h = Tcl_CreateHashEntry(&HASHTAB(info->document, tdom_attrNames), atPtr[0], &hnew); attrnode = (domAttrNode*) domAlloc(sizeof(domAttrNode)); memset(attrnode, 0, sizeof(domAttrNode)); attrnode->nodeType = ATTRIBUTE_NODE; attrnode->nodeFlags = IS_NS_NODE; attrnode->namespace = ns->index; attrnode->nodeName = (char *)&(h->key); attrnode->parentNode = node; len = strlen(atPtr[1]); attrnode->valueLength = (domLength)len; attrnode->nodeValue = (char*)MALLOC(len+1); strcpy(attrnode->nodeValue, atPtr[1]); if (node->firstAttr) { lastAttr->nextSibling = attrnode; } else { node->firstAttr = attrnode; } lastAttr = attrnode; } } /*---------------------------------------------------------- | look for namespace of element \---------------------------------------------------------*/ domSplitQName (name, tagPrefix, &localname); for (pos = info->activeNSpos; pos >= 0; pos--) { if ( ((tagPrefix[0] == '\0') && (info->activeNS[pos].namespace->prefix[0] == '\0')) || ((tagPrefix[0] != '\0') && (info->activeNS[pos].namespace->prefix[0] != '\0') && (strcmp(tagPrefix, info->activeNS[pos].namespace->prefix) == 0)) ) { if (info->activeNS[pos].namespace->prefix[0] == '\0' && info->activeNS[pos].namespace->uri[0] == '\0' && tagPrefix[0] == '\0') { /* xml-names rec. 5.2: "The default namespace can be set to the empty string. This has the same effect, within the scope of the declaration, of there being no default namespace." */ goto elemNSfound; } node->namespace = info->activeNS[pos].namespace->index; DBG(fprintf(stderr, "tag='%s' uri='%s' \n", node->nodeName, info->activeNS[pos].namespace->uri); ) goto elemNSfound; } } if (tagPrefix[0] != '\0') { if (strcmp (tagPrefix, "xml")==0) { node->namespace = info->document->rootNode->firstAttr->namespace; } else { /* Since where here, this means, the element has a up to now not declared namespace prefix. */ Tcl_SetResult (info->interp, "Namespace prefix is not " "defined", NULL); XML_StopParser(info->parser, 0); return; } } } elemNSfound: /*-------------------------------------------------------------- | add the attribute nodes | \-------------------------------------------------------------*/ if ((idatt = XML_GetIdAttributeIndex (info->parser)) != -1) { if (!info->document->ids) { info->document->ids = TMALLOC (Tcl_HashTable); Tcl_InitHashTable (info->document->ids, TCL_STRING_KEYS); } h = Tcl_CreateHashEntry (info->document->ids, atts[idatt+1], &hnew); /* if hnew isn't 1 this is a validation error. Hm, no clear way to report this. And more, XSLT and XPath can process not valid XML, the spec mentioned this even within the context of id(). If some elements share the same ID, the first in document order should be used. Doing it this way, this is guaranteed for unchanged DOM trees. There are problems, if the DOM tree is changed, before using id() */ if (hnew) { Tcl_SetHashValue (h, node); } idAttPtr = atts + idatt; } else { idAttPtr = NULL; } /* lastAttr already set right, either to NULL above, or to the last NS attribute */ for (atPtr = atts; atPtr[0] && atPtr[1]; atPtr += 2) { if (!info->ignorexmlns) { if (strncmp(atPtr[0], "xmlns", 5) == 0) { continue; } } h = Tcl_CreateHashEntry(&HASHTAB(info->document, tdom_attrNames), atPtr[0], &hnew); attrnode = (domAttrNode*) domAlloc(sizeof(domAttrNode)); memset(attrnode, 0, sizeof(domAttrNode)); attrnode->nodeType = ATTRIBUTE_NODE; if (atPtr == idAttPtr) { attrnode->nodeFlags |= IS_ID_ATTRIBUTE; } attrnode->nodeName = (char *)&(h->key); attrnode->parentNode = node; len = strlen(atPtr[1]); attrnode->valueLength = (domLength)len; attrnode->nodeValue = (char*)MALLOC(len+1); strcpy(attrnode->nodeValue, (char *)atPtr[1]); if (node->firstAttr) { lastAttr->nextSibling = attrnode; } else { node->firstAttr = attrnode; } lastAttr = attrnode; if (!info->ignorexmlns) { /*---------------------------------------------------------- | look for attribute namespace \---------------------------------------------------------*/ domSplitQName (attrnode->nodeName, prefix, &localname); if (prefix[0] != '\0') { for (pos = info->activeNSpos; pos >= 0; pos--) { if ( ((prefix[0] == '\0') && (info->activeNS[pos].namespace->prefix[0] == '\0')) || ((prefix[0] != '\0') && (info->activeNS[pos].namespace->prefix[0] != '\0') && (strcmp(prefix, info->activeNS[pos].namespace->prefix) == 0)) ) { attrnode->namespace = info->activeNS[pos].namespace->index; DBG(fprintf(stderr, "attr='%s' uri='%s' \n", attrnode->nodeName, info->activeNS[pos].namespace->uri); ) goto attrNSfound; } } if (strcmp (prefix, "xml")==0) { attrnode->namespace = info->document->rootNode->firstAttr->namespace; } else { /* Since where here, this means, the attribute has a up to now not declared namespace prefix. We probably should return this as an error, shouldn't we?*/ } attrNSfound: ; } } } #ifndef TDOM_NO_SCHEMA if (info->sdata) { if (tDOM_probeElement (info->interp, info->sdata, node->nodeName, node->namespace ? info->document->namespaces[node->namespace-1]->uri : NULL) != TCL_OK) { XML_StopParser(info->parser, 0); } else { if (tDOM_probeDomAttributes (info->interp, info->sdata, node->firstAttr) != TCL_OK) { XML_StopParser(info->parser, 0); } } } #endif info->depth++; } /*--------------------------------------------------------------------------- | endElement | \--------------------------------------------------------------------------*/ static void endElement ( void *userData, const char *UNUSED(name) ) { domReadInfo *info = userData; DispatchPCDATA (info); info->depth--; if (!info->ignorexmlns) { /* pop active namespaces */ while ( (info->activeNSpos >= 0) && (info->activeNS[info->activeNSpos].depth == info->depth) ) { info->activeNSpos--; } } if (info->depth != -1) { info->currentNode = info->currentNode->parentNode; } else { info->currentNode = NULL; } if (info->depth) { if (info->baseURIstack[info->baseURIstackPos].depth == info->depth) { info->baseURIstackPos--; } } #ifndef TDOM_NO_SCHEMA if (info->sdata) { if (tDOM_probeElementEnd (info->interp, info->sdata) != TCL_OK) { XML_StopParser(info->parser, 0); } } #endif } /*--------------------------------------------------------------------------- | characterDataHandler | \--------------------------------------------------------------------------*/ static void characterDataHandler ( void *userData, const char *s, int len ) { domReadInfo *info = userData; Tcl_DStringAppend (info->cdata, s, len); if (info->storeLineColumn) { /* This works because the result of XML_GetCurrentLineNumber() * is always at least 1 */ if (!info->textStartLine) { info->textStartLine = (domLength)XML_GetCurrentLineNumber (info->parser); info->textStartColumn = (domLength)XML_GetCurrentColumnNumber (info->parser); info->textStartByteIndex = (domLength)XML_GetCurrentByteIndex (info->parser); } } return; } /*--------------------------------------------------------------------------- | startCDATA | \--------------------------------------------------------------------------*/ static void startCDATA ( void *userData ) { domReadInfo *info = userData; DispatchPCDATA (info); info->cdataSection = 1; if (info->storeLineColumn) { if (!info->textStartLine) { info->textStartLine = (domLength)XML_GetCurrentLineNumber (info->parser); info->textStartColumn = (domLength)XML_GetCurrentColumnNumber (info->parser); info->textStartByteIndex = (domLength)XML_GetCurrentByteIndex (info->parser); } } } /*--------------------------------------------------------------------------- | endCDATA | \--------------------------------------------------------------------------*/ static void endCDATA ( void *userData ) { domReadInfo *info = userData; DispatchPCDATA (info); info->cdataSection = 0; } /*--------------------------------------------------------------------------- | DispatchPCDATA | \--------------------------------------------------------------------------*/ static void DispatchPCDATA ( domReadInfo *info ) { domTextNode *node; domNode *parentNode; domLineColumn *lc; Tcl_HashEntry *h; char *s; int hnew, only_whites; domLength len; len = Tcl_DStringLength (info->cdata); #ifndef TDOM_NO_SCHEMA if (!len && !info->cdataSection && !(info->sdata && info->sdata->stack && info->sdata->stack->pattern->flags & CONSTRAINT_TEXT_CHILD)) { info->textStartLine = 0; return; } #else if (!len && !info->cdataSection) { info->textStartLine = 0; return; } #endif s = Tcl_DStringValue (info->cdata); parentNode = info->currentNode; if (!parentNode) { return; } if ( parentNode->lastChild && parentNode->lastChild->nodeType == TEXT_NODE && !info->cdataSection) { /* normalize text node, i.e. there are no adjacent text nodes */ node = (domTextNode*)parentNode->lastChild; node->nodeValue = REALLOC(node->nodeValue, node->valueLength + len); memmove(node->nodeValue + node->valueLength, s, len); node->valueLength += len; only_whites = 0; } else { if (info->ignoreWhiteSpaces) { char *pc; int i; only_whites = 1; for (i=0, pc = s; i < len; i++, pc++) { if ( (*pc != ' ') && (*pc != '\t') && (*pc != '\n') && (*pc != '\r') ) { only_whites = 0; break; } } if (only_whites) { goto checkTextConstraints; } } if (info->storeLineColumn) { node = (domTextNode*) domAlloc(sizeof(domTextNode) + sizeof(domLineColumn)); } else { node = (domTextNode*) domAlloc(sizeof(domTextNode)); } memset(node, 0, sizeof(domTextNode)); if (info->cdataSection) node->nodeType = CDATA_SECTION_NODE; else node->nodeType = TEXT_NODE; node->nodeNumber = NODE_NO(info->document); node->valueLength = len; node->nodeValue = (char*)MALLOC(len); memmove(node->nodeValue, s, len); node->ownerDocument = info->document; if (info->currentNode) { node->parentNode = parentNode; } if (parentNode->nodeType == ELEMENT_NODE) { if (parentNode->firstChild) { parentNode->lastChild->nextSibling = (domNode*)node; node->previousSibling = parentNode->lastChild; } else { parentNode->firstChild = (domNode*)node; } parentNode->lastChild = (domNode*)node; } if (info->baseURIstack[info->baseURIstackPos].baseURI != XML_GetBase (info->parser)) { h = Tcl_CreateHashEntry (info->document->baseURIs, (char*) node, &hnew); Tcl_SetHashValue (h, tdomstrdup (XML_GetBase (info->parser))); node->nodeFlags |= HAS_BASEURI; } if (info->storeLineColumn) { lc = (domLineColumn*) ( ((char*)node) + sizeof(domTextNode) ); node->nodeFlags |= HAS_LINE_COLUMN; lc->line = info->textStartLine; lc->column = info->textStartColumn; lc->byteIndex = info->textStartByteIndex; } } checkTextConstraints: #ifndef TDOM_NO_SCHEMA if (info->sdata) { if (tDOM_probeText (info->interp, info->sdata, s, &only_whites) != TCL_OK) { XML_StopParser(info->parser, 0); } } #endif info->textStartLine = 0; Tcl_DStringSetLength (info->cdata, 0); } /*--------------------------------------------------------------------------- | commentHandler | \--------------------------------------------------------------------------*/ static void commentHandler ( void *userData, const char *s ) { domReadInfo *info = userData; domTextNode *node; domNode *parentNode; domLineColumn *lc; size_t len; int hnew; Tcl_HashEntry *h; if (info->insideDTD) { DBG(fprintf (stderr, "commentHandler: insideDTD, skipping\n");) return; } DispatchPCDATA (info); len = strlen(s); parentNode = info->currentNode; if (info->storeLineColumn) { node = (domTextNode*) domAlloc(sizeof(domTextNode) + sizeof(domLineColumn)); } else { node = (domTextNode*) domAlloc(sizeof(domTextNode)); } memset(node, 0, sizeof(domTextNode)); node->nodeType = COMMENT_NODE; node->nodeNumber = NODE_NO(info->document); node->valueLength = (domLength)len; node->nodeValue = (char*)MALLOC(len); memmove(node->nodeValue, s, len); node->ownerDocument = info->document; node->parentNode = parentNode; if (parentNode == NULL) { if (info->document->rootNode->lastChild) { info->document->rootNode->lastChild->nextSibling = (domNode*)node; node->previousSibling = info->document->rootNode->lastChild; } else { info->document->rootNode->firstChild = (domNode*)node; } info->document->rootNode->lastChild = (domNode*)node; } else if(parentNode->nodeType == ELEMENT_NODE) { if (parentNode->firstChild) { parentNode->lastChild->nextSibling = (domNode*)node; node->previousSibling = parentNode->lastChild; parentNode->lastChild = (domNode*)node; } else { parentNode->firstChild = parentNode->lastChild = (domNode*)node; } } if (info->baseURIstack[info->baseURIstackPos].baseURI != XML_GetBase (info->parser)) { h = Tcl_CreateHashEntry (info->document->baseURIs, (char*) node, &hnew); Tcl_SetHashValue (h, tdomstrdup (XML_GetBase (info->parser))); node->nodeFlags |= HAS_BASEURI; } if (info->storeLineColumn) { lc = (domLineColumn*) ( ((char*)node) + sizeof(domTextNode) ); node->nodeFlags |= HAS_LINE_COLUMN; lc->line = XML_GetCurrentLineNumber (info->parser); lc->column = XML_GetCurrentColumnNumber(info->parser); lc->byteIndex = XML_GetCurrentByteIndex (info->parser); } } /*--------------------------------------------------------------------------- | processingInstructionHandler | \--------------------------------------------------------------------------*/ static void processingInstructionHandler( void *userData, const char *target, const char *data ) { domProcessingInstructionNode *node; domReadInfo *info = userData; domNode *parentNode; domLineColumn *lc; size_t len; int hnew; Tcl_HashEntry *h; if (info->insideDTD) { DBG(fprintf (stderr, "processingInstructionHandler: insideDTD, skipping\n");) return; } DispatchPCDATA (info); parentNode = info->currentNode; if (info->storeLineColumn) { node = (domProcessingInstructionNode*) domAlloc(sizeof(domProcessingInstructionNode) + sizeof(domLineColumn)); } else { node = (domProcessingInstructionNode*) domAlloc(sizeof(domProcessingInstructionNode)); } memset(node, 0, sizeof(domProcessingInstructionNode)); node->nodeType = PROCESSING_INSTRUCTION_NODE; node->nodeNumber = NODE_NO(info->document); if (info->baseURIstack[info->baseURIstackPos].baseURI != XML_GetBase (info->parser)) { h = Tcl_CreateHashEntry (info->document->baseURIs, (char*) node, &hnew); Tcl_SetHashValue (h, tdomstrdup (XML_GetBase (info->parser))); node->nodeFlags |= HAS_BASEURI; } len = strlen(target); node->targetLength = (domLength)len; node->targetValue = (char*)MALLOC(len); memmove(node->targetValue, target, len); len = strlen(data); node->dataLength = (domLength)len; node->dataValue = (char*)MALLOC(len); memmove(node->dataValue, data, len); node->ownerDocument = info->document; node->parentNode = parentNode; if (parentNode == NULL) { if (info->document->rootNode->lastChild) { info->document->rootNode->lastChild->nextSibling = (domNode*)node; node->previousSibling = info->document->rootNode->lastChild; } else { info->document->rootNode->firstChild = (domNode*)node; } info->document->rootNode->lastChild = (domNode*)node; } else if(parentNode->nodeType == ELEMENT_NODE) { if (parentNode->firstChild) { parentNode->lastChild->nextSibling = (domNode*)node; node->previousSibling = parentNode->lastChild; parentNode->lastChild = (domNode*)node; } else { parentNode->firstChild = parentNode->lastChild = (domNode*)node; } } if (info->storeLineColumn) { lc = (domLineColumn*)(((char*)node)+sizeof(domProcessingInstructionNode)); node->nodeFlags |= HAS_LINE_COLUMN; lc->line = XML_GetCurrentLineNumber (info->parser); lc->column = XML_GetCurrentColumnNumber(info->parser); lc->byteIndex = XML_GetCurrentByteIndex (info->parser); } } /*--------------------------------------------------------------------------- | entityDeclHandler | \--------------------------------------------------------------------------*/ static void entityDeclHandler ( void *userData, const char *entityName, int UNUSED(is_parameter_entity), const char *UNUSED(value), int UNUSED(value_length), const char *UNUSED(base), const char *systemId, const char *UNUSED(publicId), const char *notationName ) { domReadInfo *info = (domReadInfo *) userData; Tcl_HashEntry *entryPtr; int hnew; if (notationName) { if (!info->document->unparsedEntities) { info->document->unparsedEntities = TMALLOC (Tcl_HashTable); Tcl_InitHashTable (info->document->unparsedEntities, TCL_STRING_KEYS); } entryPtr = Tcl_CreateHashEntry (info->document->unparsedEntities, entityName, &hnew); if (hnew) { Tcl_SetHashValue (entryPtr, tdomstrdup (systemId)); } } } /*--------------------------------------------------------------------------- | externalEntityRefHandler | \--------------------------------------------------------------------------*/ static int externalEntityRefHandler ( XML_Parser parser, const char *openEntityNames, const char *base, const char *systemId, const char *publicId ) { domReadInfo *info = (domReadInfo *) XML_GetUserData (parser); Tcl_Obj *cmdPtr, *resultObj, *resultTypeObj, *extbaseObj, *xmlstringObj; Tcl_Obj *channelIdObj; int result, mode, done, keepresult = 0; domLength len, tclLen; XML_Parser extparser, oldparser = NULL; char buf[4096], *resultType, *extbase, *xmlstring, *xmlstringstart, *channelId, s[50]; Tcl_Channel chan = (Tcl_Channel) NULL; enum XML_Status status; XML_Index storedNextFeedbackPosition; const char *interpResult; if (info->document->extResolver == NULL) { Tcl_AppendResult (info->interp, "Can't read external entity \"", systemId, "\": No -externalentitycommand given", NULL); return 0; } DispatchPCDATA (info); /* * Take a copy of the callback script so that arguments may be appended. */ cmdPtr = Tcl_NewStringObj(info->document->extResolver, -1); Tcl_IncrRefCount(cmdPtr); if (base) { Tcl_ListObjAppendElement(info->interp, cmdPtr, Tcl_NewStringObj(base, (domLength)strlen(base))); } else { Tcl_ListObjAppendElement(info->interp, cmdPtr, Tcl_NewObj()); } /* For a document with doctype declaration, the systemId is always != NULL. But if the document doesn't have a doctype declaration and the user uses -useForeignDTD 1, the externalEntityRefHandler will be called with a systemId (and publicId and openEntityNames) == NULL. */ if (systemId) { Tcl_ListObjAppendElement(info->interp, cmdPtr, Tcl_NewStringObj(systemId, (domLength)strlen(systemId))); } else { Tcl_ListObjAppendElement(info->interp, cmdPtr, Tcl_NewObj()); } if (publicId) { Tcl_ListObjAppendElement(info->interp, cmdPtr, Tcl_NewStringObj(publicId, (domLength)strlen(publicId))); } else { Tcl_ListObjAppendElement(info->interp, cmdPtr, Tcl_NewObj()); } result = Tcl_EvalObjEx (info->interp, cmdPtr, TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL); Tcl_DecrRefCount(cmdPtr); if (result != TCL_OK) { info->status = result; return 0; } extparser = XML_ExternalEntityParserCreate (parser, openEntityNames, 0); resultObj = Tcl_GetObjResult (info->interp); Tcl_IncrRefCount (resultObj); result = Tcl_ListObjLength (info->interp, resultObj, &tclLen); if ((result != TCL_OK) || (tclLen != 3)) { goto wrongScriptResult; } result = Tcl_ListObjIndex (info->interp, resultObj, 0, &resultTypeObj); if (result != TCL_OK) { goto wrongScriptResult; } resultType = Tcl_GetString(resultTypeObj); if (strcmp (resultType, "string") == 0) { result = Tcl_ListObjIndex (info->interp, resultObj, 2, &xmlstringObj); xmlstring = Tcl_GetStringFromObj (xmlstringObj, &len); chan = NULL; } else if (strcmp (resultType, "channel") == 0) { xmlstring = NULL; len = 0; result = Tcl_ListObjIndex (info->interp, resultObj, 2, &channelIdObj); channelId = Tcl_GetString(channelIdObj); chan = Tcl_GetChannel (info->interp, channelId, &mode); if (chan == (Tcl_Channel) NULL) { goto wrongScriptResult; } if ((mode & TCL_READABLE) == 0) { return 0; } } else if (strcmp (resultType, "filename") == 0) { /* result type "filename" not yet implemented */ return 0; } else { goto wrongScriptResult; } result = Tcl_ListObjIndex (info->interp, resultObj, 1, &extbaseObj); if (result != TCL_OK) { goto wrongScriptResult; } extbase = Tcl_GetString(extbaseObj); /* TODO: what to do, if this document was already parsed before ? */ if (!extparser) { Tcl_DecrRefCount (resultObj); Tcl_SetResult (info->interp, "unable to create expat external entity parser", NULL); return 0; } oldparser = info->parser; info->parser = extparser; XML_SetBase (extparser, extbase); storedNextFeedbackPosition = info->nextFeedbackPosition; info->nextFeedbackPosition = info->feedbackAfter; Tcl_ResetResult (info->interp); result = 1; xmlstringstart = xmlstring; if (chan == NULL) { do { done = (len < TDOM_PCS); status = XML_Parse (extparser, xmlstring, (int)(done ? len : TDOM_PCS), done); if (!done) { xmlstring += TDOM_PCS; len -= TDOM_PCS; } } while (!done && status == XML_STATUS_OK); switch (status) { case XML_STATUS_ERROR: interpResult = Tcl_GetStringResult(info->interp); if (interpResult[0] == '\0') { tcldom_reportErrorLocation ( info->interp, 20, 40, XML_GetCurrentLineNumber(extparser), XML_GetCurrentColumnNumber(extparser), xmlstringstart, systemId, XML_GetCurrentByteIndex(extparser), XML_ErrorString(XML_GetErrorCode(extparser)) ); } else { sprintf(s, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentLineNumber(extparser)); Tcl_AppendResult(info->interp, ", referenced in entity \"", systemId, "\" at line ", s, " character ", NULL); sprintf(s, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentColumnNumber(extparser)); Tcl_AppendResult(info->interp, s, NULL); } keepresult = 1; result = 0; break; case XML_STATUS_SUSPENDED: XML_StopParser (oldparser, 1); keepresult = 1; break; default: break; } } else { do { len = Tcl_Read (chan, buf, sizeof(buf)); done = len < sizeof(buf); status = XML_Parse (extparser, buf, (int)len, done); switch (status) { case XML_STATUS_ERROR: interpResult = Tcl_GetStringResult(info->interp); sprintf(s, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentLineNumber(extparser)); if (interpResult[0] == '\0') { Tcl_ResetResult (info->interp); Tcl_AppendResult(info->interp, "error \"", XML_ErrorString(XML_GetErrorCode(extparser)), "\" in entity \"", systemId, "\" at line ", s, " character ", NULL); sprintf(s, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentColumnNumber(extparser)); Tcl_AppendResult(info->interp, s, NULL); } else { Tcl_AppendResult(info->interp, ", referenced in entity \"", systemId, "\" at line ", s, " character ", NULL); sprintf(s, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentColumnNumber(extparser)); Tcl_AppendResult(info->interp, s, NULL); } result = 0; keepresult = 1; done = 1; break; case XML_STATUS_SUSPENDED: XML_StopParser (oldparser, 1); keepresult = 1; done = 1; break; default: break; } } while (!done); } if (result) { DispatchPCDATA (info); } if (!keepresult) { Tcl_ResetResult (info->interp); } XML_ParserFree (extparser); info->parser = oldparser; info->nextFeedbackPosition = storedNextFeedbackPosition; Tcl_DecrRefCount (resultObj); return result; wrongScriptResult: Tcl_DecrRefCount (resultObj); Tcl_ResetResult (info->interp); XML_ParserFree (extparser); if (oldparser) { info->parser = oldparser; } info->status = TCL_ERROR; Tcl_AppendResult (info->interp, "The -externalentitycommand script " "has to return a Tcl list with 3 elements.\n" "Syntax: {string|channel|filename }\n", NULL); return 0; } /*--------------------------------------------------------------------------- | startDoctypeDeclHandler | \--------------------------------------------------------------------------*/ static void startDoctypeDeclHandler ( void *userData, const char *UNUSED(doctypeName), const char *sysid, const char *pubid, int UNUSED(has_internal_subset) ) { domReadInfo *info = (domReadInfo *) userData; if (pubid) { info->document->doctype = (domDocInfo*)MALLOC (sizeof (domDocInfo)); memset (info->document->doctype, 0, sizeof (domDocInfo)); info->document->doctype->systemId = tdomstrdup (sysid); info->document->doctype->publicId = tdomstrdup (pubid); } else if (sysid) { info->document->doctype = (domDocInfo*)MALLOC (sizeof (domDocInfo)); memset (info->document->doctype, 0, sizeof (domDocInfo)); info->document->doctype->systemId = tdomstrdup (sysid); } info->insideDTD = 1; } /*--------------------------------------------------------------------------- | endDoctypeDeclHandler | \--------------------------------------------------------------------------*/ static void endDoctypeDeclHandler ( void *userData ) { domReadInfo *info = (domReadInfo *) userData; info->insideDTD = 0; } /*--------------------------------------------------------------------------- | domReadDocument | \--------------------------------------------------------------------------*/ domDocument * domReadDocument ( XML_Parser parser, char *xml, domLength length, int ignoreWhiteSpaces, int keepCDATA, int storeLineColumn, int ignorexmlns, int feedbackAfter, Tcl_Obj *feedbackCmd, Tcl_Channel channel, const char *baseurl, Tcl_Obj *extResolver, int useForeignDTD, int forest, int paramEntityParsing, #ifndef TDOM_NO_SCHEMA SchemaData *sdata, #endif Tcl_Interp *interp, domParseForestErrorData *forestError, int *resultcode ) { int done; domLength tclLen, len; enum XML_Status status; domReadInfo info; char buf[8192]; Tcl_Obj *bufObj; Tcl_DString dStr; int useBinary = 0; char *str; domDocument *doc = domCreateDoc(baseurl, storeLineColumn); domNode *thisNode; if (extResolver) { doc->extResolver = tdomstrdup (Tcl_GetString (extResolver)); } if (ignorexmlns) { doc->nodeFlags |= IGNORE_XMLNS; } info.parser = parser; info.document = doc; info.currentNode = NULL; info.depth = 0; info.ignoreWhiteSpaces = ignoreWhiteSpaces; info.cdata = (Tcl_DString*) MALLOC (sizeof (Tcl_DString)); Tcl_DStringInit (info.cdata); info.cdataSection = 0; info.storeLineColumn = storeLineColumn; info.textStartLine = 0; info.ignorexmlns = ignorexmlns; info.feedbackAfter = feedbackAfter; info.feedbackCmd = feedbackCmd; info.nextFeedbackPosition = feedbackAfter; info.interp = interp; info.activeNSpos = -1; info.activeNSsize = 8; info.activeNS = (domActiveNS*) MALLOC (sizeof(domActiveNS) * info.activeNSsize); info.baseURIstackPos = 0; info.baseURIstackSize = INITIAL_BASEURISTACK_SIZE; info.baseURIstack = (domActiveBaseURI*) MALLOC (sizeof(domActiveBaseURI) * info.baseURIstackSize); info.insideDTD = 0; info.status = 0; #ifndef TDOM_NO_SCHEMA info.sdata = sdata; #endif XML_SetUserData(parser, &info); XML_SetBase (parser, baseurl); /* We must use XML_GetBase(), because XML_SetBase copies the baseURI, and we want to compare the pointers */ info.baseURIstack[0].baseURI = XML_GetBase (parser); info.baseURIstack[0].depth = 0; XML_UseForeignDTD (parser, (unsigned char) useForeignDTD); XML_SetElementHandler(parser, startElement, endElement); XML_SetCharacterDataHandler(parser, characterDataHandler); XML_SetCommentHandler(parser, commentHandler); XML_SetProcessingInstructionHandler(parser, processingInstructionHandler); XML_SetEntityDeclHandler (parser, entityDeclHandler); if (extResolver) { XML_SetExternalEntityRefHandler (parser, externalEntityRefHandler); } XML_SetParamEntityParsing (parser, (enum XML_ParamEntityParsing) paramEntityParsing); XML_SetDoctypeDeclHandler (parser, startDoctypeDeclHandler, endDoctypeDeclHandler); if (keepCDATA) { XML_SetCdataSectionHandler(parser, startCDATA, endCDATA); } if (forest) { /* The created external entity parser inherits all the * configuration and will happily parse a forest. */ parser = XML_ExternalEntityParserCreate (parser, "forest", 0); info.parser = parser; info.currentNode = doc->rootNode; } if (channel == NULL) { do { done = (length < TDOM_PCS); status = XML_Parse (parser, xml, (int)(done ? length : TDOM_PCS), done); if (!done) { xml += TDOM_PCS; length -= TDOM_PCS; } } while (!done && status == XML_STATUS_OK); } else { Tcl_DStringInit (&dStr); if (Tcl_GetChannelOption (interp, channel, "-encoding", &dStr) != TCL_OK) { domFreeDocument (doc, NULL, NULL); *resultcode = TCL_ERROR; doc = NULL; goto cleanup; } if (strcmp (Tcl_DStringValue (&dStr), "utf-8")==0 ) { useBinary = 1; } else { bufObj = Tcl_NewObj(); Tcl_SetObjLength (bufObj, 6144); } Tcl_DStringFree (&dStr); do { if (useBinary) { len = Tcl_Read (channel, buf, sizeof(buf)); done = len < sizeof(buf); } else { len = Tcl_ReadChars (channel, bufObj, 1024, 0); done = (len < 1024); str = Tcl_GetStringFromObj (bufObj, &tclLen); } if (useBinary) { status = XML_Parse (parser, buf, (int)len, done); } else { status = XML_Parse (parser, str, (int)tclLen, done); } } while (!done && status == XML_STATUS_OK); } switch (status) { case XML_STATUS_SUSPENDED: DBG(fprintf(stderr, "XML_STATUS_SUSPENDED\n");) if (info.status == TCL_BREAK) { Tcl_ResetResult(interp); } /* fall through */ case XML_STATUS_ERROR: DBG(fprintf(stderr, "XML_STATUS_ERROR\n");) domFreeDocument (doc, NULL, NULL); *resultcode = info.status; doc = NULL; if (forest) { forestError->errorLine = XML_GetCurrentLineNumber(parser); forestError->errorColumn = XML_GetCurrentColumnNumber(parser); forestError->byteIndex = XML_GetCurrentByteIndex(parser); forestError->errorCode = XML_GetErrorCode(parser); } break; case XML_STATUS_OK: if (forest) { info.currentNode = doc->rootNode; DispatchPCDATA (&info); thisNode = doc->rootNode->firstChild; while (thisNode) { thisNode->parentNode = NULL; thisNode = thisNode->nextSibling; } } break; } if (!useBinary && channel != NULL) { Tcl_DecrRefCount (bufObj); } cleanup: FREE ( info.activeNS ); FREE ( info.baseURIstack ); Tcl_DStringFree (info.cdata); FREE ( info.cdata); if (forest) { /* This is the external entity parser, the main parser will be * freed in caller context. */ XML_ParserFree (parser); } if (doc) domSetDocumentElement (doc); return doc; } #endif /* ifndef TDOM_NO_EXPAT */ /*--------------------------------------------------------------------------- | domException2String | \--------------------------------------------------------------------------*/ const char * domException2String ( domException exception ) { return domException2StringTable[exception]; } /*--------------------------------------------------------------------------- | domGetLineColumn | \--------------------------------------------------------------------------*/ int domGetLineColumn ( domNode *node, XML_Size *line, XML_Size *column, XML_Index *byteIndex ) { char *v; domLineColumn *lc; *line = -1; *column = -1; if (node->nodeFlags & HAS_LINE_COLUMN) { v = (char*)node; switch (node->nodeType) { case ELEMENT_NODE: v = v + sizeof(domNode); break; case TEXT_NODE: case CDATA_SECTION_NODE: case COMMENT_NODE: v = v + sizeof(domTextNode); break; case PROCESSING_INSTRUCTION_NODE: v = v + sizeof(domProcessingInstructionNode); break; default: return -1; } lc = (domLineColumn *)v; *line = lc->line; *column = lc->column; *byteIndex = lc->byteIndex; return 0; } else { return -1; } } domAttrNode * domCreateXMLNamespaceNode ( domNode *parent ) { Tcl_HashEntry *h; int hnew; domAttrNode *attr; domNS *ns; attr = (domAttrNode *) domAlloc (sizeof (domAttrNode)); memset (attr, 0, sizeof (domAttrNode)); h = Tcl_CreateHashEntry(&HASHTAB(parent->ownerDocument,tdom_attrNames), "xmlns:xml", &hnew); ns = domNewNamespace (parent->ownerDocument, "xml", XML_NAMESPACE); attr->nodeType = ATTRIBUTE_NODE; attr->nodeFlags = IS_NS_NODE; attr->namespace = ns->index; attr->nodeName = (char *)&(h->key); attr->parentNode = parent; attr->valueLength = (domLength)strlen (XML_NAMESPACE); attr->nodeValue = tdomstrdup (XML_NAMESPACE); return attr; } /* *---------------------------------------------------------------------- * * domCreateDoc -- * * This procedure allocates a new domDocument, initialize it and * creates its rootNode (with initialization). * * Results: * The domDocument node: * * Side effects: * Allocates memory for the returned domDocument and its * rootNode. * *---------------------------------------------------------------------- */ domDocument * domCreateDoc ( const char * baseURI, int storeLineColumn ) { Tcl_HashEntry *h; int hnew; domNode *rootNode; domDocument *doc; domLineColumn *lc; doc = (domDocument *) MALLOC (sizeof (domDocument)); memset(doc, 0, sizeof(domDocument)); doc->nodeType = DOCUMENT_NODE; doc->documentNumber = DOC_NO(doc); doc->nsptr = -1; doc->nslen = 4; doc->namespaces = (domNS**) MALLOC (sizeof (domNS*) * doc->nslen); /* We malloc and initialize the baseURIs hash table here to avoid cluttering of the code all over the place with checks. */ doc->baseURIs = TMALLOC (Tcl_HashTable); Tcl_InitHashTable (doc->baseURIs, TCL_ONE_WORD_KEYS); TDomThreaded( domLocksAttach(doc); Tcl_InitHashTable(&doc->tdom_tagNames, TCL_STRING_KEYS); Tcl_InitHashTable(&doc->tdom_attrNames, TCL_STRING_KEYS); ) if (storeLineColumn) { rootNode = (domNode*) domAlloc(sizeof(domNode)+sizeof(domLineColumn)); } else { rootNode = (domNode*) domAlloc(sizeof(domNode)); } memset(rootNode, 0, sizeof(domNode)); rootNode->nodeType = ELEMENT_NODE; if (baseURI) { h = Tcl_CreateHashEntry (doc->baseURIs, (char*)rootNode, &hnew); Tcl_SetHashValue (h, tdomstrdup (baseURI)); rootNode->nodeFlags |= HAS_BASEURI; } rootNode->namespace = 0; h = Tcl_CreateHashEntry(&HASHTAB(doc,tdom_tagNames), "", &hnew); rootNode->nodeName = (char *)&(h->key); rootNode->nodeNumber = NODE_NO(doc); rootNode->ownerDocument = doc; rootNode->parentNode = NULL; rootNode->firstChild = rootNode->lastChild = NULL; rootNode->firstAttr = domCreateXMLNamespaceNode (rootNode); if (storeLineColumn) { lc = (domLineColumn*) ( ((char*)rootNode) + sizeof(domNode)); rootNode->nodeFlags |= HAS_LINE_COLUMN; lc->line = 0; lc->column = 0; lc->byteIndex = 0; } doc->rootNode = rootNode; return doc; } /*--------------------------------------------------------------------------- | domCreateDocument | \--------------------------------------------------------------------------*/ domDocument * domCreateDocument ( const char *uri, char *documentElementTagName ) { Tcl_HashEntry *h; int hnew; domNode *node; domDocument *doc; char prefix[MAX_PREFIX_LEN]; const char *localName; domNS *ns = NULL; if (uri) { domSplitQName (documentElementTagName, prefix, &localName); DBG(fprintf(stderr, "rootName: -->%s<--, prefix: -->%s<--, localName: -->%s<--\n", documentElementTagName, prefix, localName);); } doc = domCreateDoc (NULL, 0); h = Tcl_CreateHashEntry(&HASHTAB(doc, tdom_tagNames), documentElementTagName, &hnew); node = (domNode*) domAlloc(sizeof(domNode)); memset(node, 0, sizeof(domNode)); node->nodeType = ELEMENT_NODE; node->nodeNumber = NODE_NO(doc); node->ownerDocument = doc; node->nodeName = (char *)&(h->key); doc->documentElement = node; if (uri) { ns = domNewNamespace (doc, prefix, uri); node->namespace = ns->index; domAddNSToNode (node, ns); } doc->rootNode->firstChild = doc->rootNode->lastChild = doc->documentElement; return doc; } /*--------------------------------------------------------------------------- | domSetDocumentElement | \--------------------------------------------------------------------------*/ void domSetDocumentElement ( domDocument *doc ) { domNode *node; doc->documentElement = NULL; node = doc->rootNode->firstChild; while (node) { if (node->nodeType == ELEMENT_NODE) { doc->documentElement = node; break; } node = node->nextSibling; } if (!doc->documentElement) { doc->documentElement = doc->rootNode->firstChild; } } /*--------------------------------------------------------------------------- | domFreeNode | \--------------------------------------------------------------------------*/ void domFreeNode ( domNode * node, domFreeCallback freeCB, void * clientData, int dontfree ) { int shared = 0; domNode *child, *ctemp; domAttrNode *atemp, *attr, *aprev; Tcl_HashEntry *entryPtr; if (node == NULL) { DBG(fprintf (stderr, "null ptr in domFreeNode (dom.c) !\n");) return; } TDomThreaded ( shared = node->ownerDocument && node->ownerDocument->refCount > 1; ) /*---------------------------------------------------------------- | dontfree instruct us to walk the node tree and apply the | user-supplied callback, *w/o* actually deleting nodes. | This is normally done when a thread detaches from the | shared DOM tree and wants to garbage-collect all nodecmds | in it's interpreter which attached to the tree nodes. \---------------------------------------------------------------*/ if (dontfree) { shared = 1; } else { node->nodeFlags |= IS_DELETED; } if (node->nodeType == ATTRIBUTE_NODE && !shared) { attr = ((domAttrNode*)node)->parentNode->firstAttr; aprev = NULL; while (attr && (attr != (domAttrNode*)node)) { aprev = attr; attr = attr->nextSibling; } if (attr) { if (aprev) { aprev->nextSibling = attr->nextSibling; } else { ((domAttrNode*)node)->parentNode->firstAttr = attr->nextSibling; } FREE (attr->nodeValue); domFree ((void*)attr); } } else if (node->nodeType == ELEMENT_NODE) { child = node->lastChild; while (child) { ctemp = child->previousSibling; if (freeCB) { freeCB(child, clientData); } domFreeNode (child, freeCB, clientData, dontfree); child = ctemp; } if (shared) { return; } attr = node->firstAttr; while (attr) { atemp = attr; attr = attr->nextSibling; FREE (atemp->nodeValue); domFree ((void*)atemp); } if (node->nodeFlags & HAS_BASEURI) { entryPtr = Tcl_FindHashEntry (node->ownerDocument->baseURIs, (char*)node); if (entryPtr) { FREE ((char *) Tcl_GetHashValue (entryPtr)); Tcl_DeleteHashEntry (entryPtr); } } domFree ((void*)node); } else if (node->nodeType == PROCESSING_INSTRUCTION_NODE && !shared) { FREE (((domProcessingInstructionNode*)node)->dataValue); FREE (((domProcessingInstructionNode*)node)->targetValue); domFree ((void*)node); } else if (!shared) { FREE (((domTextNode*)node)->nodeValue); domFree ((void*)node); } } /*--------------------------------------------------------------------------- | domDeleteNode - unlinks node from tree and free all child nodes | and itself | \--------------------------------------------------------------------------*/ domException domDeleteNode ( domNode * node, domFreeCallback freeCB, void * clientData ) { TDomThreaded(int shared = 0;) domDocument *doc; if (node->nodeType == ATTRIBUTE_NODE) { domPanic("domDeleteNode on ATTRIBUTE_NODE not supported!"); } TDomThreaded ( shared = node->ownerDocument->refCount > 1; ) doc = node->ownerDocument; /*---------------------------------------------------------------- | unlink node from child or fragment list \---------------------------------------------------------------*/ if (node->previousSibling) { node->previousSibling->nextSibling = node->nextSibling; } else { if (node->parentNode) { node->parentNode->firstChild = node->nextSibling; } else { /* Node may be a top level node */ if (doc->rootNode->firstChild == node) { doc->rootNode->firstChild = node->nextSibling; } } } if (node->nextSibling) { node->nextSibling->previousSibling = node->previousSibling; } else { if (node->parentNode) { node->parentNode->lastChild = node->previousSibling; } else { /* Node may be a top level node */ if (doc->rootNode->lastChild == node) { doc->rootNode->lastChild = node->previousSibling; } } } if (doc->fragments == node) { doc->fragments = node->nextSibling; } if (!node->parentNode) { domSetDocumentElement (doc); } /*---------------------------------------------------------------- | for shared docs, append node to the delete nodes list | otherwise delete the node physically \---------------------------------------------------------------*/ if (freeCB) { freeCB(node, clientData); } TDomThreaded ( if (shared) { if (doc->deletedNodes) { node->nextSibling = doc->deletedNodes; } else { node->nextSibling = NULL; } doc->deletedNodes = node; node->nodeFlags |= IS_DELETED; } ) MutationEvent3(DOMNodeRemoved, childToRemove, node); MutationEvent2(DOMSubtreeModified, node); domFreeNode(node, freeCB, clientData, 0); return OK; } /*--------------------------------------------------------------------------- | domFreeDocument | \--------------------------------------------------------------------------*/ void domFreeDocument ( domDocument * doc, domFreeCallback freeCB, void * clientData ) { domNode *node, *next; domNS *ns; int i, dontfree = 0; Tcl_HashEntry *entryPtr; Tcl_HashSearch search; if (doc->nodeFlags & DONT_FREE) { doc->nodeFlags &= ~DONT_FREE; dontfree = 1; } /*----------------------------------------------------------- | delete main trees, including top level PIs, etc. \-----------------------------------------------------------*/ node = doc->rootNode; if (node) { if (freeCB) { freeCB(node, clientData); } domFreeNode (node, freeCB, clientData, dontfree); } /*----------------------------------------------------------- | delete fragment trees \-----------------------------------------------------------*/ node = doc->fragments; while (node) { next = node->nextSibling; if (freeCB) { freeCB(node, clientData); } domFreeNode (node, freeCB, clientData, dontfree); node = next; } if (dontfree) return; /*----------------------------------------------------------- | delete namespaces \-----------------------------------------------------------*/ for (i = 0; i <= doc->nsptr; i++) { ns = doc->namespaces[i]; FREE(ns->uri); FREE(ns->prefix); FREE ((char*) ns); } FREE ((char *)doc->namespaces); /*----------------------------------------------------------- | delete global selectNodes prefix namespace mappings \-----------------------------------------------------------*/ if (doc->prefixNSMappings) { i = 0; while (doc->prefixNSMappings[i]) { FREE (doc->prefixNSMappings[i]); i++; } FREE (doc->prefixNSMappings); } /*----------------------------------------------------------- | delete doctype info \-----------------------------------------------------------*/ if (doc->doctype) { #define DOCINFO_FREE(item) if (doc->doctype->item) FREE(doc->doctype->item) DOCINFO_FREE(systemId); DOCINFO_FREE(publicId); DOCINFO_FREE(internalSubset); DOCINFO_FREE(encoding); DOCINFO_FREE(mediaType); DOCINFO_FREE(method); if (doc->doctype->cdataSectionElements) { Tcl_DeleteHashTable (doc->doctype->cdataSectionElements); FREE (doc->doctype->cdataSectionElements); } FREE((char*) doc->doctype); } /*----------------------------------------------------------- | delete ID hash table \-----------------------------------------------------------*/ if (doc->ids) { Tcl_DeleteHashTable (doc->ids); FREE (doc->ids); } /*----------------------------------------------------------- | delete unparsed entities hash table \-----------------------------------------------------------*/ if (doc->unparsedEntities) { entryPtr = Tcl_FirstHashEntry (doc->unparsedEntities, &search); while (entryPtr) { FREE (Tcl_GetHashValue (entryPtr)); entryPtr = Tcl_NextHashEntry (&search); } Tcl_DeleteHashTable (doc->unparsedEntities); FREE (doc->unparsedEntities); } /*----------------------------------------------------------- | delete base URIs hash table \-----------------------------------------------------------*/ entryPtr = Tcl_FirstHashEntry (doc->baseURIs, &search); while (entryPtr) { FREE (Tcl_GetHashValue (entryPtr)); entryPtr = Tcl_NextHashEntry (&search); } Tcl_DeleteHashTable (doc->baseURIs); FREE (doc->baseURIs); /*----------------------------------------------------------- | delete XPath cache hash table \-----------------------------------------------------------*/ if (doc->xpathCache) { entryPtr = Tcl_FirstHashEntry (doc->xpathCache, &search); while (entryPtr) { xpathFreeAst((ast)Tcl_GetHashValue (entryPtr)); entryPtr = Tcl_NextHashEntry (&search); } Tcl_DeleteHashTable (doc->xpathCache); FREE (doc->xpathCache); } if (doc->extResolver) { FREE (doc->extResolver); } /*----------------------------------------------------------- | delete tag/attribute hash tables (for threaded builds only) \-----------------------------------------------------------*/ TDomThreaded ( { Tcl_HashEntry *entryPtr; Tcl_HashSearch search; entryPtr = Tcl_FirstHashEntry(&doc->tdom_tagNames, &search); while (entryPtr) { Tcl_DeleteHashEntry(entryPtr); entryPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&doc->tdom_tagNames); entryPtr = Tcl_FirstHashEntry(&doc->tdom_attrNames, &search); while (entryPtr) { Tcl_DeleteHashEntry(entryPtr); entryPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&doc->tdom_attrNames); domLocksDetach(doc); node = doc->deletedNodes; while (node) { next = node->nextSibling; domFreeNode (node, freeCB, clientData, 0); node = next; } } ) FREE ((char*)doc); } /*--------------------------------------------------------------------------- | domSetAttribute | \--------------------------------------------------------------------------*/ domAttrNode * domSetAttribute ( domNode *node, const char *attributeName, const char *attributeValue ) { domAttrNode *attr, *lastAttr; Tcl_HashEntry *h; int hnew; if (!node || node->nodeType != ELEMENT_NODE) { return NULL; } /*---------------------------------------------------- | try to find an existing attribute \---------------------------------------------------*/ attr = node->firstAttr; while (attr && strcmp(attr->nodeName, attributeName)) { attr = attr->nextSibling; } if (attr) { if (attr->nodeFlags & IS_ID_ATTRIBUTE) { h = Tcl_FindHashEntry (node->ownerDocument->ids, attr->nodeValue); if (h) { Tcl_DeleteHashEntry (h); h = Tcl_CreateHashEntry (node->ownerDocument->ids, attributeValue, &hnew); /* XXX what to do, if hnew = 0 ??? */ Tcl_SetHashValue (h, node); } } FREE (attr->nodeValue); attr->valueLength = (domLength)strlen(attributeValue); attr->nodeValue = (char*)MALLOC(attr->valueLength+1); strcpy(attr->nodeValue, attributeValue); } else { /*----------------------------------------------- | add a complete new attribute node \----------------------------------------------*/ attr = (domAttrNode*) domAlloc(sizeof(domAttrNode)); memset(attr, 0, sizeof(domAttrNode)); h = Tcl_CreateHashEntry(&HASHTAB(node->ownerDocument,tdom_attrNames), attributeName, &hnew); attr->nodeType = ATTRIBUTE_NODE; attr->nodeFlags = 0; attr->namespace = 0; attr->nodeName = (char *)&(h->key); attr->parentNode = node; attr->valueLength = (domLength)strlen(attributeValue); attr->nodeValue = (char*)MALLOC(attr->valueLength+1); strcpy(attr->nodeValue, attributeValue); if (node->firstAttr) { lastAttr = node->firstAttr; /* move to the end of the attribute list */ while (lastAttr->nextSibling) lastAttr = lastAttr->nextSibling; lastAttr->nextSibling = attr; } else { node->firstAttr = attr; } } MutationEvent(); return attr; } /*--------------------------------------------------------------------------- | domSetAttributeNS | \--------------------------------------------------------------------------*/ domAttrNode * domSetAttributeNS ( domNode *node, const char *attributeName, const char *attributeValue, const char *uri, int createNSIfNeeded ) { domAttrNode *attr, *lastAttr; Tcl_HashEntry *h; int hnew, hasUri = 1, isNSAttr = 0, isDftNS = 0; domNS *ns; char prefix[MAX_PREFIX_LEN]; const char *localName, *newLocalName; Tcl_DString dStr; DBG(fprintf (stderr, "domSetAttributeNS: attributeName %s, attributeValue %s, uri %s\n", attributeName, attributeValue, uri);) if (!node || node->nodeType != ELEMENT_NODE) { return NULL; } domSplitQName (attributeName, prefix, &localName); if (!uri || uri[0]=='\0') hasUri = 0; if (hasUri && (prefix[0] == '\0')) return NULL; if ((prefix[0] == '\0' && strcmp (localName, "xmlns")==0) || (strcmp (prefix, "xmlns")==0)) { isNSAttr = 1; createNSIfNeeded = 0; if (prefix[0] == '\0') { isDftNS = 1; ns = domLookupPrefix (node, ""); } else { ns = domLookupPrefix (node, prefix); } if (ns && (strcmp (ns->uri, attributeValue)==0)) return NULL; if (!hasUri) { uri = attributeValue; isNSAttr = 1; hasUri = 1; if (strcmp (localName, "xmlns")==0) isDftNS = 1; } else { return NULL; } } if (!hasUri) { if (prefix[0] != '\0' && strcmp (prefix, "xml")==0) { uri = "http://www.w3.org/XML/1998/namespace"; hasUri = 1; } } if (!hasUri && prefix[0] != '\0') return NULL; /*---------------------------------------------------- | try to find an existing attribute \---------------------------------------------------*/ attr = node->firstAttr; while (attr) { if (hasUri) { if (attr->nodeFlags & IS_NS_NODE) { if (isNSAttr) { if (strcmp (attributeName, attr->nodeName)==0) { break; } } } else { if (attr->namespace && !isNSAttr) { ns = domGetNamespaceByIndex (node->ownerDocument, attr->namespace); if (strcmp (uri, ns->uri)==0) { newLocalName = localName; domSplitQName (attr->nodeName, prefix, &localName); if (strcmp (newLocalName, localName)==0) break; } } } } else { if (!attr->namespace) { if (strcmp (attr->nodeName, localName)==0) break; } } attr = attr->nextSibling; } if (attr) { DBG(fprintf (stderr, "domSetAttributeNS: resetting existing attribute %s ; old value: %s\n", attr->nodeName, attr->nodeValue);) if (attr->nodeFlags & IS_ID_ATTRIBUTE) { h = Tcl_FindHashEntry (node->ownerDocument->ids, attr->nodeValue); if (h) { Tcl_DeleteHashEntry (h); h = Tcl_CreateHashEntry (node->ownerDocument->ids, attributeValue, &hnew); Tcl_SetHashValue (h, node); } } FREE (attr->nodeValue); attr->valueLength = (domLength)strlen(attributeValue); attr->nodeValue = (char*)MALLOC(attr->valueLength+1); strcpy(attr->nodeValue, attributeValue); } else { /*-------------------------------------------------------- | add a complete new attribute node \-------------------------------------------------------*/ attr = (domAttrNode*) domAlloc(sizeof(domAttrNode)); memset(attr, 0, sizeof(domAttrNode)); h = Tcl_CreateHashEntry(&HASHTAB(node->ownerDocument,tdom_attrNames), attributeName, &hnew); attr->nodeType = ATTRIBUTE_NODE; if (hasUri) { if (isNSAttr) { if (isDftNS) { ns = domLookupNamespace (node->ownerDocument, "", uri); } else { ns = domLookupNamespace (node->ownerDocument, localName, uri); } } else { ns = domLookupPrefix (node, prefix); if (ns && (strcmp (ns->uri, uri)!=0)) ns = NULL; } if (!ns) { if (isNSAttr) { if (isDftNS) { ns = domNewNamespace (node->ownerDocument, "", uri); } else { ns = domNewNamespace (node->ownerDocument, localName, uri); } } else { ns = domNewNamespace (node->ownerDocument, prefix, uri); if (createNSIfNeeded) { if (prefix[0] == '\0') { domSetAttributeNS (node, "xmlns", uri, NULL, 0); } else { Tcl_DStringInit (&dStr); Tcl_DStringAppend (&dStr, "xmlns:", 6); Tcl_DStringAppend (&dStr, prefix, -1); domSetAttributeNS (node, Tcl_DStringValue (&dStr), uri, NULL, 0); } } } } attr->namespace = ns->index; if (isNSAttr) { attr->nodeFlags = IS_NS_NODE; } } attr->nodeName = (char *)&(h->key); attr->parentNode = node; attr->valueLength = (domLength)strlen(attributeValue); attr->nodeValue = (char*)MALLOC(attr->valueLength+1); strcpy(attr->nodeValue, attributeValue); if (isNSAttr) { if (node->firstAttr && (node->firstAttr->nodeFlags & IS_NS_NODE)) { lastAttr = node->firstAttr; while (lastAttr->nextSibling && (lastAttr->nextSibling->nodeFlags & IS_NS_NODE)) { lastAttr = lastAttr->nextSibling; } attr->nextSibling = lastAttr->nextSibling; lastAttr->nextSibling = attr; } else { attr->nextSibling = node->firstAttr; node->firstAttr = attr; } } else { if (node->firstAttr) { lastAttr = node->firstAttr; /* move to the end of the attribute list */ while (lastAttr->nextSibling) lastAttr = lastAttr->nextSibling; lastAttr->nextSibling = attr; } else { node->firstAttr = attr; } } } MutationEvent(); return attr; } /*--------------------------------------------------------------------------- | domRemoveAttribute | \--------------------------------------------------------------------------*/ int domRemoveAttribute ( domNode *node, const char *attributeName ) { domAttrNode *attr, *previous = NULL; Tcl_HashEntry *h; if (!node || node->nodeType != ELEMENT_NODE) { return -1; } /*---------------------------------------------------- | try to find the attribute \---------------------------------------------------*/ attr = node->firstAttr; while (attr && strcmp(attr->nodeName, attributeName)) { previous = attr; attr = attr->nextSibling; } if (attr) { if (previous) { previous->nextSibling = attr->nextSibling; } else { attr->parentNode->firstAttr = attr->nextSibling; } if (attr->nodeFlags & IS_ID_ATTRIBUTE) { h = Tcl_FindHashEntry (node->ownerDocument->ids, attr->nodeValue); if (h) Tcl_DeleteHashEntry (h); } FREE (attr->nodeValue); MutationEvent(); domFree ((void*)attr); return 0; } return -1; } /*--------------------------------------------------------------------------- | domRemoveAttributeNS | \--------------------------------------------------------------------------*/ int domRemoveAttributeNS ( domNode *node, const char *uri, const char *localName ) { domAttrNode *attr, *previous = NULL; domNS *ns = NULL; char prefix[MAX_PREFIX_LEN]; const char *str; Tcl_HashEntry *h; if (!node || node->nodeType != ELEMENT_NODE) { return -1; } attr = node->firstAttr; while (attr) { domSplitQName (attr->nodeName, prefix, &str); if (strcmp(localName,str)==0) { ns = domGetNamespaceByIndex(node->ownerDocument, attr->namespace); if (ns && strcmp(ns->uri, uri)==0) { if (previous) { previous->nextSibling = attr->nextSibling; } else { attr->parentNode->firstAttr = attr->nextSibling; } if (attr->nodeFlags & IS_ID_ATTRIBUTE) { h = Tcl_FindHashEntry (node->ownerDocument->ids, attr->nodeValue); if (h) Tcl_DeleteHashEntry (h); } FREE (attr->nodeValue); MutationEvent(); domFree ((void*)attr); return 0; } } previous = attr; attr = attr->nextSibling; } return -1; } /*--------------------------------------------------------------------------- | __dbgAttr | \--------------------------------------------------------------------------*/ DBG( static void __dbgAttr (domAttrNode *node) { DBG(fprintf(stderr, " %s=%s", node->nodeName, node->nodeValue);) if (node->nextSibling) __dbgAttr(node->nextSibling); } ) /*--------------------------------------------------------------------------- | domSetDocument | \--------------------------------------------------------------------------*/ void domSetDocument ( domNode *node, domDocument *doc ) { domNode *child; domNS *ns, *origNS; domDocument *origDoc; domAttrNode *attr; Tcl_HashEntry *h; TDomThreaded ( int hnew; ) if (node->nodeFlags & HAS_BASEURI) { h = Tcl_FindHashEntry (node->ownerDocument->baseURIs, (char*)node); if (h) { FREE ((char *) Tcl_GetHashValue (h)); Tcl_DeleteHashEntry (h); } node->nodeFlags &= ~HAS_BASEURI; } if (node->nodeType == ELEMENT_NODE) { origDoc = node->ownerDocument; node->ownerDocument = doc; for (attr = node->firstAttr; attr != NULL; attr = attr->nextSibling) { if (attr->nodeFlags & IS_NS_NODE) { origNS = origDoc->namespaces[attr->namespace-1]; ns = domNewNamespace (doc, origNS->prefix, origNS->uri); attr->namespace = ns->index; } else if (attr->namespace) { ns = domAddNSToNode (node, origDoc->namespaces[attr->namespace-1]); if (ns) attr->namespace = ns->index; } } if (node->namespace) { ns = domAddNSToNode (node, origDoc->namespaces[node->namespace-1]); if (ns) node->namespace = ns->index; } else { ns = domAddNSToNode (node, NULL); if (ns) { node->namespace = ns->index; } } DBG(fprintf(stderr, "domSetDocument node%s ", node->nodeName); __dbgAttr(node->firstAttr); fprintf(stderr, "\n"); ) TDomThreaded ( if (origDoc != doc) { /* Make hash table entries as necessary for * tdom_tagNames and tdom_attrNames. */ h = Tcl_CreateHashEntry(&doc->tdom_tagNames, node->nodeName, &hnew); node->nodeName = (domString) &(h->key); for (attr = node->firstAttr; attr != NULL; attr = attr->nextSibling) { h = Tcl_CreateHashEntry(&doc->tdom_attrNames, attr->nodeName, &hnew); attr->nodeName = (domString) &(h->key); } } ) child = node->firstChild; while (child != NULL) { domSetDocument (child, doc); child = child->nextSibling; } } else { node->ownerDocument = doc; } DBG(fprintf(stderr, "end domSetDocument node %s\n", node->nodeName);) } /*--------------------------------------------------------------------------- | domSetNodeValue | \--------------------------------------------------------------------------*/ domException domSetNodeValue ( domNode *node, const char *nodeValue, domLength valueLen ) { domTextNode *textnode; if ((node->nodeType != TEXT_NODE) && (node->nodeType != CDATA_SECTION_NODE) && (node->nodeType != COMMENT_NODE) ) { return NO_MODIFICATION_ALLOWED_ERR; } textnode = (domTextNode*) node; FREE(textnode->nodeValue); textnode->nodeValue = MALLOC (valueLen); textnode->valueLength = valueLen; memmove(textnode->nodeValue, nodeValue, valueLen); MutationEvent(); return OK; } /* *---------------------------------------------------------------------- * * domRemoveChild -- * * This procedure implements the dom method removeChild. Removes * child from the list of children of node. * * Results: * Returns a domException: * * NOT_FOUND_ERR: Raised if the node child is not a child of node. * * OK: otherwise * * Side effects: * Alters the involved document. * *---------------------------------------------------------------------- */ domException domRemoveChild ( domNode *node, domNode *child ) { domNode *n; /* check, if node is in deed the parent of child */ if (child->parentNode != node) { /* If node is the root node of a document and child is in deed a child of this node, then child->parentNode will be NULL. In this case, we loop throu the children of node, to see, if the child is valid. */ if (node->ownerDocument->rootNode == node) { n = node->firstChild; while (n) { if (n == child) { /* child is in deed a child of node */ break; } n = n->nextSibling; } if (!n) { return NOT_FOUND_ERR; } } else { return NOT_FOUND_ERR; } } if (child->previousSibling) { child->previousSibling->nextSibling = child->nextSibling; } else { node->firstChild = child->nextSibling; } if (child->nextSibling) { child->nextSibling->previousSibling = child->previousSibling; } else { node->lastChild = child->previousSibling; } /* link child into the fragments list */ if (child->ownerDocument->fragments) { child->nextSibling = child->ownerDocument->fragments; child->ownerDocument->fragments->previousSibling = child; child->ownerDocument->fragments = child; } else { child->ownerDocument->fragments = child; child->nextSibling = NULL; } child->parentNode = NULL; child->previousSibling = NULL; MutationEvent3(DOMNodeRemoved, child, node); MutationEvent2(DOMSubtreeModified, node); return OK; } /* *---------------------------------------------------------------------- * * domAppendChild -- * * This procedure implements the dom method appendChild. Adds the * node newChild to the end of the list of children of this * node. If the newChild is already in the tree, it is first * removed. * * Results: * Returns a domException: * * HIERARCHY_REQUEST_ERR: Raised if node is of a type that does * not allow children of the type of the childToAppend node, or * if the node to append is one of node's ancestors or the * rootNode of node's document. * * NOT_SUPPORTED_ERR: Raised if the childToInsert is the rootNode * of another document or if node is a rootNode. * * OK: otherwise * * Side effects: * Alters the involved document(s). * *---------------------------------------------------------------------- */ domException domAppendChild ( domNode *node, domNode *childToAppend ) { domNode *n; if (node->nodeType != ELEMENT_NODE) { return HIERARCHY_REQUEST_ERR; } /* check, whether childToAppend is node or one of node's ancestors */ n = node; while (n) { if (n == childToAppend) { return HIERARCHY_REQUEST_ERR; } n = n->parentNode; } if (childToAppend == childToAppend->ownerDocument->rootNode) { if (childToAppend == node->ownerDocument->rootNode) { return HIERARCHY_REQUEST_ERR; } else { return NOT_SUPPORTED_ERR; } } /* unlink childToAppend */ if (childToAppend->previousSibling) { childToAppend->previousSibling->nextSibling = childToAppend->nextSibling; } else { if (childToAppend->parentNode) { childToAppend->parentNode->firstChild = childToAppend->nextSibling; } else { /* childToAppend is either out of the fragment list or a child of the rootNode of its document */ if (childToAppend->ownerDocument->fragments == childToAppend) { childToAppend->ownerDocument->fragments = childToAppend->nextSibling; } else { childToAppend->ownerDocument->rootNode->firstChild = childToAppend->nextSibling; } } } if (childToAppend->nextSibling) { childToAppend->nextSibling->previousSibling = childToAppend->previousSibling; } else { if (childToAppend->parentNode) { childToAppend->parentNode->lastChild = childToAppend->previousSibling; } else { if (childToAppend->ownerDocument->rootNode->lastChild == childToAppend) { childToAppend->ownerDocument->rootNode->lastChild = childToAppend->previousSibling; } } } if (node->lastChild) { node->lastChild->nextSibling = childToAppend; childToAppend->previousSibling = node->lastChild; } else { node->firstChild = childToAppend; childToAppend->previousSibling = NULL; } node->lastChild = childToAppend; childToAppend->nextSibling = NULL; if (!childToAppend->parentNode && (childToAppend->ownerDocument->documentElement == childToAppend)) { childToAppend->ownerDocument->documentElement = childToAppend->ownerDocument->rootNode->firstChild; } if (node == node->ownerDocument->rootNode) { childToAppend->parentNode = NULL; } else { childToAppend->parentNode = node; } if ((node->ownerDocument != childToAppend->ownerDocument) || node->ownerDocument->nsptr || childToAppend->ownerDocument->baseURIs->numEntries) { domSetDocument (childToAppend, node->ownerDocument); } node->ownerDocument->nodeFlags |= NEEDS_RENUMBERING; MutationEvent(); return OK; } /* *---------------------------------------------------------------------- * * domInsertBefore -- * * This procedure implements the dom method insertBefore. * It inserts the node childToInsert before the existing child * node referenceChild. If referenceChild is null, insert * childToInsert at the end of the list of children of node. The * arguments node and childToInsert must be non NULL. The * childToInsert is unlinked from its previous place (fragment * list or tree). * * Results: * Returns a domException: * * HIERARCHY_REQUEST_ERR: Raised if node is of a type that does * not allow children of the type of the childToInsert node, or * if the node to insert is node or one of node's ancestors or the * rootNode of node's document. * * NOT_FOUND_ERR: Raised if refChild is not a child of this node. * * NOT_SUPPORTED_ERR: Raised if the childToInsert is the rootNode * of another document or if node is a rootNode. * * OK: otherwise * * Side effects: * Alters the involved document(s). * *---------------------------------------------------------------------- */ domException domInsertBefore ( domNode *node, domNode *childToInsert, domNode *referenceChild ) { domNode *n; if (node->nodeType != ELEMENT_NODE) { return HIERARCHY_REQUEST_ERR; } /* check, if node is in deed the parent of referenceChild */ if (referenceChild) { if (referenceChild->parentNode != node) { /* If node is the root node of a document and referenceChild is in deed a child of this node, then referenceChild->parentNode will be NULL. In this case, we loop throu the children of node, to see, if the referenceChild is valid. */ if (node->ownerDocument->rootNode == node) { n = node->firstChild; while (n) { if (n == referenceChild) { /* referenceChild is in deed a child of node */ break; } n = n->nextSibling; } if (!n) { return NOT_FOUND_ERR; } } else { return NOT_FOUND_ERR; } } } if (childToInsert == referenceChild) { return OK; } /* check, whether childToInsert is one of node's ancestors */ n = node; while (n) { if (n == childToInsert) { return HIERARCHY_REQUEST_ERR; } n = n->parentNode; } if (childToInsert == childToInsert->ownerDocument->rootNode) { if (childToInsert == node->ownerDocument->rootNode) { return HIERARCHY_REQUEST_ERR; } else { /* For now, we simply don't allow the rootNode of another element as childToInsert. The way to go may be simply to treat the rootNode as DocumentFragment and to insert all children of that rootNode before the referenceChild. This would result in a document without documentElement, which then should be handled right by other methods. This is planned, but not carefully considered, yet. */ return NOT_SUPPORTED_ERR; } } /* unlink childToInsert */ if (childToInsert->previousSibling) { childToInsert->previousSibling->nextSibling = childToInsert->nextSibling; } else { if (childToInsert->parentNode) { childToInsert->parentNode->firstChild = childToInsert->nextSibling; } else { /* childToInsert is either out of the fragment list or a child of the rootNode of its document */ if (childToInsert->ownerDocument->fragments == childToInsert) { childToInsert->ownerDocument->fragments = childToInsert->nextSibling; } else { childToInsert->ownerDocument->rootNode->firstChild = childToInsert->nextSibling; } } } if (childToInsert->nextSibling) { childToInsert->nextSibling->previousSibling = childToInsert->previousSibling; } else { if (childToInsert->parentNode) { childToInsert->parentNode->lastChild = childToInsert->previousSibling; } else { if (childToInsert->ownerDocument->rootNode->lastChild == childToInsert) { childToInsert->ownerDocument->rootNode->lastChild = childToInsert->previousSibling; } } } childToInsert->nextSibling = referenceChild; if (referenceChild) { if (referenceChild->previousSibling) { childToInsert->previousSibling = referenceChild->previousSibling; referenceChild->previousSibling->nextSibling = childToInsert; } else { node->firstChild = childToInsert; childToInsert->previousSibling = NULL; } referenceChild->previousSibling = childToInsert; } else { if (node->lastChild) { node->lastChild->nextSibling = childToInsert; childToInsert->previousSibling = node->lastChild; } else { node->firstChild = childToInsert; childToInsert->previousSibling = NULL; } node->lastChild = childToInsert; } if (!childToInsert->parentNode && (childToInsert->ownerDocument->documentElement == childToInsert)) { childToInsert->ownerDocument->documentElement = childToInsert->ownerDocument->rootNode->firstChild; } if (node == node->ownerDocument->rootNode) { childToInsert->parentNode = NULL; } else { childToInsert->parentNode = node; } if (node->ownerDocument != childToInsert->ownerDocument || node->ownerDocument->nsptr || childToInsert->ownerDocument->baseURIs->numEntries) { domSetDocument (childToInsert, node->ownerDocument); } node->ownerDocument->nodeFlags |= NEEDS_RENUMBERING; MutationEvent3(DOMNodeInsert, childToInsert, node); MutationEvent2(DOMSubtreeModified, node); return OK; } /* *---------------------------------------------------------------------- * * domReplaceChild -- * * This procedure implements the dom method replaceChild. * Replaces the child node oldChild with newChild in the list of * children of node 'node'. * * Results: * Returns a domException: * * HIERARCHY_REQUEST_ERR: Raised if node is of a type that does * not allow children of the type of the newChild node, or * if newChild is node or one of node's ancestors or the * rootNode of node's document. * * NOT_FOUND_ERR: Raised if oldChild is not a child of node. * * NOT_SUPPORTED_ERR: Raised if the newChild is the rootNode * of another document. * * OK: otherwise * * Side effects: * Alters the involved document(s). * *---------------------------------------------------------------------- */ domException domReplaceChild ( domNode *node, domNode *newChild, domNode *oldChild ) { domNode *n; if (node->nodeType != ELEMENT_NODE) { return HIERARCHY_REQUEST_ERR; } /* check, if node is in deed the parent of oldChild */ if (oldChild->parentNode != node) { /* If node is the root node of a document and oldChild is in deed a child of this node, then oldChild->parentNode will be NULL. In this case, we loop throu the children of node, to see, if the oldChild is valid. */ if (node->ownerDocument->rootNode == node) { n = node->firstChild; while (n) { if (n == oldChild) { /* oldChild is in deed a child of node */ break; } n = n->nextSibling; } if (!n) { return NOT_FOUND_ERR; } } else { return NOT_FOUND_ERR; } } if (oldChild == newChild) { return OK; } /* check, whether newChild is node or one of node's ancestors */ n = node; while (n) { if (n == newChild) { return HIERARCHY_REQUEST_ERR; } n = n->parentNode; } if (newChild == newChild->ownerDocument->rootNode) { if (newChild == node->ownerDocument->rootNode) { return HIERARCHY_REQUEST_ERR; } else { return NOT_SUPPORTED_ERR; } } /* unlink newChild */ if (newChild->previousSibling) { newChild->previousSibling->nextSibling = newChild->nextSibling; } else { if (newChild->parentNode) { newChild->parentNode->firstChild = newChild->nextSibling; } else { /* newChild is either out of the fragment list or a child of the rootNode of its document */ if (newChild->ownerDocument->fragments == newChild) { newChild->ownerDocument->fragments = newChild->nextSibling; } else { newChild->ownerDocument->rootNode->firstChild = newChild->nextSibling; } } } if (newChild->nextSibling) { newChild->nextSibling->previousSibling = newChild->previousSibling; } else { if (newChild->parentNode) { newChild->parentNode->lastChild = newChild->previousSibling; } else { if (newChild->ownerDocument->rootNode->lastChild == newChild) { newChild->ownerDocument->rootNode->lastChild = newChild->previousSibling; } } } newChild->nextSibling = oldChild->nextSibling; newChild->previousSibling = oldChild->previousSibling; if (!newChild->parentNode && (newChild->ownerDocument->documentElement == newChild)) { newChild->ownerDocument->documentElement = newChild->ownerDocument->rootNode->firstChild; } if (node == node->ownerDocument->rootNode) { newChild->parentNode = NULL; } else { newChild->parentNode = node; } if (oldChild->previousSibling) { oldChild->previousSibling->nextSibling = newChild; } else { node->firstChild = newChild; } if (oldChild->nextSibling) { oldChild->nextSibling->previousSibling = newChild; } else { node->lastChild = newChild; } if (node->ownerDocument != newChild->ownerDocument || node->ownerDocument->nsptr || newChild->ownerDocument->baseURIs->numEntries) { domSetDocument (newChild, node->ownerDocument); } /* add old child into his fragment list */ if (oldChild->ownerDocument->fragments) { oldChild->nextSibling = oldChild->ownerDocument->fragments; oldChild->ownerDocument->fragments->previousSibling = oldChild; oldChild->ownerDocument->fragments = oldChild; } else { oldChild->ownerDocument->fragments = oldChild; oldChild->nextSibling = oldChild->previousSibling = NULL; } oldChild->parentNode = NULL; node->ownerDocument->nodeFlags |= NEEDS_RENUMBERING; MutationEvent(); return OK; } /*--------------------------------------------------------------------------- | domNewTextNode | \--------------------------------------------------------------------------*/ domTextNode * domNewTextNode( domDocument *doc, const char *value, domLength length, domNodeType nodeType ) { domTextNode *node; node = (domTextNode*) domAlloc(sizeof(domTextNode)); memset(node, 0, sizeof(domTextNode)); node->nodeType = nodeType; node->nodeNumber = NODE_NO(doc); node->ownerDocument = doc; node->valueLength = length; node->nodeValue = (char*)MALLOC(length); memmove(node->nodeValue, value, length); if (doc->fragments) { node->nextSibling = doc->fragments; doc->fragments->previousSibling = (domNode*)node; doc->fragments = (domNode*)node; } else { doc->fragments = (domNode*)node; } return node; } void domEscapeCData ( char *value, domLength length, Tcl_DString *escapedData ) { domLength i, start = 0; char *pc; Tcl_DStringInit (escapedData); pc = value; for (i = 0; i < length; i++) { if (*pc == '&') { Tcl_DStringAppend (escapedData, &value[start], i - start); Tcl_DStringAppend (escapedData, "&", 5); start = i+1; } else if (*pc == '<') { Tcl_DStringAppend (escapedData, &value[start], i - start); Tcl_DStringAppend (escapedData, "<", 4); start = i+1; } else if (*pc == '>') { Tcl_DStringAppend (escapedData, &value[start], i - start); Tcl_DStringAppend (escapedData, ">", 4); start = i+1; } pc++; } if (start) { Tcl_DStringAppend (escapedData, &value[start], length - start); } } /*--------------------------------------------------------------------------- | domAppendNewTextNode | \--------------------------------------------------------------------------*/ domTextNode * domAppendNewTextNode( domNode *parent, char *value, domLength length, domNodeType nodeType, int disableOutputEscaping ) { domTextNode *node; if (!length && (nodeType == TEXT_NODE)) { return NULL; } if (parent->lastChild && parent->lastChild->nodeType == TEXT_NODE && nodeType == TEXT_NODE ) { /*------------------------------------------------------------------ | append to already existing text node \-----------------------------------------------------------------*/ domAppendData ((domTextNode *) (parent->lastChild), value, length, disableOutputEscaping); MutationEvent(); return (domTextNode*)parent->lastChild; } node = (domTextNode*) domAlloc(sizeof(domTextNode)); memset(node, 0, sizeof(domTextNode)); node->nodeType = nodeType; if (disableOutputEscaping) { node->nodeFlags |= DISABLE_OUTPUT_ESCAPING; } node->nodeNumber = NODE_NO(parent->ownerDocument); node->ownerDocument = parent->ownerDocument; node->valueLength = length; node->nodeValue = (char*)MALLOC(length); memmove(node->nodeValue, value, length); if (parent->lastChild) { parent->lastChild->nextSibling = (domNode*)node; node->previousSibling = parent->lastChild; } else { parent->firstChild = (domNode*)node; node->previousSibling = NULL; } parent->lastChild = (domNode*)node; node->nextSibling = NULL; if (parent != parent->ownerDocument->rootNode) { node->parentNode = parent; } MutationEvent(); return node; } /*--------------------------------------------------------------------------- | domAppendNewElementNode | \--------------------------------------------------------------------------*/ domNode * domAppendNewElementNode( domNode *parent, const char *tagName, const char *uri ) { Tcl_HashEntry *h; domNode *node; domNS *ns; domAttrNode *NSattr; int hnew; char prefix[MAX_PREFIX_LEN]; const char *localname; Tcl_DString dStr; if (parent == NULL) { DBG(fprintf(stderr, "dom.c: Error parent == NULL!\n");) return NULL; } h = Tcl_CreateHashEntry(&HASHTAB(parent->ownerDocument,tdom_tagNames), tagName, &hnew); node = (domNode*) domAlloc(sizeof(domNode)); memset(node, 0, sizeof(domNode)); node->nodeType = ELEMENT_NODE; node->nodeNumber = NODE_NO(parent->ownerDocument); node->ownerDocument = parent->ownerDocument; node->nodeName = (char *)&(h->key); if (parent->lastChild) { parent->lastChild->nextSibling = node; node->previousSibling = parent->lastChild; } else { parent->firstChild = node; node->previousSibling = NULL; } parent->lastChild = node; node->nextSibling = NULL; if (parent != parent->ownerDocument->rootNode) { node->parentNode = parent; } /*-------------------------------------------------------- | reuse existing namespace or create a new one \-------------------------------------------------------*/ if (uri) { domSplitQName (tagName, prefix, &localname); DBG(fprintf(stderr, "tag '%s' has prefix='%s' \n", tagName, prefix);) ns = domLookupPrefix (node, prefix); if (!ns || (strcmp (uri, ns->uri)!=0)) { ns = domNewNamespace(node->ownerDocument, prefix, uri); if (prefix[0] == '\0') { domSetAttributeNS (node, "xmlns", uri, NULL, 1); } else { Tcl_DStringInit (&dStr); Tcl_DStringAppend (&dStr, "xmlns:", 6); Tcl_DStringAppend (&dStr, prefix, -1); domSetAttributeNS (node, Tcl_DStringValue (&dStr), uri, NULL, 1); } } node->namespace = ns->index; } else { ns = domLookupPrefix (node, ""); if (ns) { if (strcmp (ns->uri, "")!=0) { NSattr = domSetAttributeNS (node, "xmlns", "", NULL, 1); if (NSattr) { node->namespace = NSattr->namespace; } } else { node->namespace = ns->index; } } } MutationEvent(); return node; } /* *---------------------------------------------------------------------- * * domAppendData -- * * This procedure implements the dom method appendData. It is * also used by domNormalize and domAppendNewTextNode. * * Results: * A domException; currently always OK. * * Side effects: * Appends the data to node. * *---------------------------------------------------------------------- */ domException domAppendData ( domTextNode *node, /* The node, to append value to. Must be a TEXT_NODE, COMMENT_NODE or CDATA_SECTION_NODE*/ char *value, /* The data to append */ domLength length, /* The length of value in byte */ int disableOutputEscaping /* If true, disable output escaping on the node */ ) { Tcl_DString escData; if (node->nodeFlags & DISABLE_OUTPUT_ESCAPING) { if (disableOutputEscaping) { node->nodeValue = REALLOC (node->nodeValue, node->valueLength + length); memmove (node->nodeValue + node->valueLength, value, length); node->valueLength += length; } else { domEscapeCData (value, length, &escData); if (Tcl_DStringLength (&escData)) { node->nodeValue = REALLOC (node->nodeValue, node->valueLength + Tcl_DStringLength (&escData)); memmove (node->nodeValue + node->valueLength, Tcl_DStringValue (&escData), Tcl_DStringLength (&escData)); node->valueLength += Tcl_DStringLength (&escData); } else { node->nodeValue = REALLOC (node->nodeValue, node->valueLength+length); memmove (node->nodeValue + node->valueLength, value, length); node->valueLength += length; } Tcl_DStringFree (&escData); } } else { if (disableOutputEscaping) { node->nodeFlags |= DISABLE_OUTPUT_ESCAPING; domEscapeCData (node->nodeValue, node->valueLength, &escData); if (Tcl_DStringLength (&escData)) { FREE (node->nodeValue); node->nodeValue = MALLOC (Tcl_DStringLength (&escData) + length); memmove (node->nodeValue, Tcl_DStringValue (&escData), Tcl_DStringLength (&escData)); node->valueLength = Tcl_DStringLength (&escData); } else { node->nodeValue = REALLOC (node->nodeValue, node->valueLength+length); } Tcl_DStringFree (&escData); } else { node->nodeValue = REALLOC (node->nodeValue, node->valueLength + length); } memmove (node->nodeValue + node->valueLength, value, length); node->valueLength += length; } return OK; } /* *---------------------------------------------------------------------- * * domNormalize -- * * This procedure implements the dom method normalize. Puts all * Text nodes in the full depth of the sub-tree underneath node, * including attribute nodes, into a "normal" form where only * structure (e.g., elements, comments, processing instructions, * CDATA sections, and entity references) separates Text nodes, * i.e., there are neither adjacent Text nodes nor empty Text * nodes. If the flag forXPath is true, then CDATASection nodes * are treated as if they are text nodes (and merged with * circumjacent text nodes). Node must be an ELEMENT_NODE. * * Results: * None. * * Side effects: * May alter the tree. * *---------------------------------------------------------------------- */ void domNormalize ( domNode *node, /* root of the sub-tree to normalize */ int forXPath, /* if true, treat CDATA_SECTION_NODEs as if they where TEXT_NODEs */ domFreeCallback freeCB, /* Function to call, if a node must be freed */ void *clientData /* ClientData, to provide to the freeCB */ ) { domNode *child, *nextChild; int merge = 0; if (node->nodeType != ELEMENT_NODE) return; child = node->firstChild; while (child) { merge = 0; switch (child->nodeType) { case ELEMENT_NODE: domNormalize (child, forXPath, freeCB, clientData); break; case TEXT_NODE: if (child->previousSibling && child->previousSibling->nodeType == TEXT_NODE) { merge = 1; } else { if (((domTextNode *)child)->valueLength == 0) { nextChild = child->nextSibling; domDeleteNode (child, freeCB, clientData); child = nextChild; continue; } } break; case CDATA_SECTION_NODE: if (forXPath) { if (child->previousSibling && child->previousSibling->nodeType == TEXT_NODE) { merge = 1; } else { if (((domTextNode *)child)->valueLength == 0) { nextChild = child->nextSibling; domDeleteNode (child, freeCB, clientData); child = nextChild; continue; } child->nodeType = TEXT_NODE; } } break; default: break; } if (merge) { domAppendData ( (domTextNode *)(child->previousSibling), ((domTextNode *)child)->nodeValue, ((domTextNode *)child)->valueLength, (child->nodeFlags & DISABLE_OUTPUT_ESCAPING) ); nextChild = child->nextSibling; domDeleteNode (child, freeCB, clientData); child = nextChild; } else { child = child->nextSibling; } } } /*--------------------------------------------------------------------------- | domAddNSToNode | \--------------------------------------------------------------------------*/ domNS * domAddNSToNode ( domNode *node, domNS *nsToAdd ) { domAttrNode *attr, *lastNSAttr; domNS *ns, noNS; Tcl_HashEntry *h; int hnew; Tcl_DString dStr; if (!nsToAdd) { noNS.uri = ""; noNS.prefix = ""; noNS.index = 0; nsToAdd = &noNS; } DBG(fprintf (stderr, "domAddNSToNode to node '%s': prefix: %s, uri: %s\n", node->nodeName, nsToAdd->prefix, nsToAdd->uri);) ns = domLookupPrefix (node, nsToAdd->prefix); if (ns) { if (strcmp (ns->uri, nsToAdd->uri)==0) { /* namespace already in scope, we're done. */ return ns; } } else { /* If the NS to set was no NS and there isn't a default NS we're done */ if (nsToAdd->prefix[0] == '\0' && nsToAdd->uri[0] == '\0') return NULL; } ns = domNewNamespace (node->ownerDocument, nsToAdd->prefix, nsToAdd->uri); Tcl_DStringInit (&dStr); if (nsToAdd->prefix[0] == '\0') { Tcl_DStringAppend (&dStr, "xmlns", 5); } else { Tcl_DStringAppend (&dStr, "xmlns:", 6); Tcl_DStringAppend (&dStr, nsToAdd->prefix, -1); } /* Add new namespace attribute */ attr = (domAttrNode*) domAlloc(sizeof(domAttrNode)); memset(attr, 0, sizeof(domAttrNode)); h = Tcl_CreateHashEntry(&HASHTAB(node->ownerDocument,tdom_attrNames), Tcl_DStringValue(&dStr), &hnew); attr->nodeType = ATTRIBUTE_NODE; attr->nodeFlags = IS_NS_NODE; attr->namespace = ns->index; attr->nodeName = (char *)&(h->key); attr->parentNode = node; attr->valueLength = (domLength)strlen(nsToAdd->uri); attr->nodeValue = (char*)MALLOC(attr->valueLength+1); strcpy(attr->nodeValue, nsToAdd->uri); lastNSAttr = NULL; if (node->firstAttr && (node->firstAttr->nodeFlags & IS_NS_NODE)) { lastNSAttr = node->firstAttr; while (lastNSAttr->nextSibling && (lastNSAttr->nextSibling->nodeFlags & IS_NS_NODE)) { lastNSAttr = lastNSAttr->nextSibling; } } if (lastNSAttr) { attr->nextSibling = lastNSAttr->nextSibling; lastNSAttr->nextSibling = attr; } else { attr->nextSibling = node->firstAttr; node->firstAttr = attr; } Tcl_DStringFree (&dStr); return ns; } /*--------------------------------------------------------------------------- | domAppendLiteralNode | \--------------------------------------------------------------------------*/ domNode * domAppendLiteralNode( domNode *parent, domNode *literalNode ) { Tcl_HashEntry *h; domNode *node; int hnew; if (parent == NULL) { DBG(fprintf(stderr, "dom.c: Error parent == NULL!\n");) return NULL; } h = Tcl_CreateHashEntry(&HASHTAB(parent->ownerDocument, tdom_tagNames), literalNode->nodeName, &hnew); node = (domNode*) domAlloc(sizeof(domNode)); memset(node, 0, sizeof(domNode)); node->nodeType = ELEMENT_NODE; node->nodeNumber = NODE_NO(parent->ownerDocument); node->ownerDocument = parent->ownerDocument; node->nodeName = (char *)&(h->key); if (parent->lastChild) { parent->lastChild->nextSibling = node; node->previousSibling = parent->lastChild; } else { parent->firstChild = node; node->previousSibling = NULL; } parent->lastChild = node; node->nextSibling = NULL; if (parent != parent->ownerDocument->rootNode) { node->parentNode = parent; } MutationEvent(); return node; } /*--------------------------------------------------------------------------- | domNewProcessingInstructionNode | \--------------------------------------------------------------------------*/ domProcessingInstructionNode * domNewProcessingInstructionNode( domDocument *doc, const char *targetValue, domLength targetLength, const char *dataValue, domLength dataLength ) { domProcessingInstructionNode *node; node = (domProcessingInstructionNode*) domAlloc(sizeof(domProcessingInstructionNode)); memset(node, 0, sizeof(domProcessingInstructionNode)); node->nodeType = PROCESSING_INSTRUCTION_NODE; node->nodeNumber = NODE_NO(doc); node->ownerDocument = doc; node->targetLength = targetLength; node->targetValue = (char*)MALLOC(targetLength); memmove(node->targetValue, targetValue, targetLength); node->dataLength = dataLength; node->dataValue = (char*)MALLOC(dataLength); memmove(node->dataValue, dataValue, dataLength); if (doc->fragments) { node->nextSibling = doc->fragments; doc->fragments->previousSibling = (domNode*)node; doc->fragments = (domNode*)node; } else { doc->fragments = (domNode*)node; } MutationEvent(); return node; } /*--------------------------------------------------------------------------- | domNewElementNode | \--------------------------------------------------------------------------*/ domNode * domNewElementNode( domDocument *doc, const char *tagName ) { domNode *node; Tcl_HashEntry *h; int hnew; h = Tcl_CreateHashEntry(&HASHTAB(doc, tdom_tagNames), tagName, &hnew); node = (domNode*) domAlloc(sizeof(domNode)); memset(node, 0, sizeof(domNode)); node->nodeType = ELEMENT_NODE; node->nodeNumber = NODE_NO(doc); node->ownerDocument = doc; node->nodeName = (char *)&(h->key); if (doc->fragments) { node->nextSibling = doc->fragments; doc->fragments->previousSibling = node; doc->fragments = node; } else { doc->fragments = node; } return node; } /*--------------------------------------------------------------------------- | domNewElementNodeNS | \--------------------------------------------------------------------------*/ domNode * domNewElementNodeNS ( domDocument *doc, const char *tagName, const char *uri ) { domNode *node; Tcl_HashEntry *h; int hnew; char prefix[MAX_PREFIX_LEN]; const char *localname; domNS *ns; domSplitQName (tagName, prefix, &localname); if (prefix[0] == '\0' && uri[0] == '\0') { return NULL; } h = Tcl_CreateHashEntry(&HASHTAB(doc, tdom_tagNames), tagName, &hnew); node = (domNode*) domAlloc(sizeof(domNode)); memset(node, 0, sizeof(domNode)); node->nodeType = ELEMENT_NODE; node->nodeNumber = NODE_NO(doc); node->ownerDocument = doc; node->nodeName = (char *)&(h->key); ns = domNewNamespace(doc, prefix, uri); node->namespace = ns->index; if (doc->fragments) { node->nextSibling = doc->fragments; doc->fragments->previousSibling = node; doc->fragments = node; } else { doc->fragments = node; } return node; } /*--------------------------------------------------------------------------- | domCloneNode | \--------------------------------------------------------------------------*/ domNode * domCloneNode ( domNode *node, int deep ) { domAttrNode *attr, *nattr; domNode *n, *child, *newChild; /*------------------------------------------------------------------ | create new node \-----------------------------------------------------------------*/ if (node->nodeType == PROCESSING_INSTRUCTION_NODE) { domProcessingInstructionNode *pinode = (domProcessingInstructionNode*)node; return (domNode*) domNewProcessingInstructionNode( pinode->ownerDocument, pinode->targetValue, pinode->targetLength, pinode->dataValue, pinode->dataLength); } if (node->nodeType != ELEMENT_NODE) { domTextNode *t1node, *tnode = (domTextNode*)node; t1node = domNewTextNode(tnode->ownerDocument, tnode->nodeValue, tnode->valueLength, tnode->nodeType); t1node->info = tnode->info; t1node->nodeFlags = tnode->nodeFlags; return (domNode*) t1node; } n = domNewElementNode(node->ownerDocument, node->nodeName); n->namespace = node->namespace; n->info = node->info; /*------------------------------------------------------------------ | copy attributes (if any) \-----------------------------------------------------------------*/ attr = node->firstAttr; while (attr != NULL) { nattr = domSetAttribute (n, attr->nodeName, attr->nodeValue ); nattr->namespace = attr->namespace; nattr->nodeFlags = attr->nodeFlags; attr = attr->nextSibling; } if (deep) { child = node->firstChild; while (child) { newChild = domCloneNode(child, deep); /* append new (cloned)child to cloned node, its new parent. Don't use domAppendChild for this, because that would mess around with the namespaces */ if (n->ownerDocument->fragments->nextSibling) { n->ownerDocument->fragments = n->ownerDocument->fragments->nextSibling; n->ownerDocument->fragments->previousSibling = NULL; newChild->nextSibling = NULL; } else { n->ownerDocument->fragments = NULL; } if (n->firstChild) { newChild->previousSibling = n->lastChild; n->lastChild->nextSibling = newChild; } else { n->firstChild = newChild; } n->lastChild = newChild; newChild->parentNode = n; /* clone next child */ child = child->nextSibling; } } return n; } /*---------------------------------------------------------------------------- | domCopyNS | \---------------------------------------------------------------------------*/ void domCopyNS ( domNode *from, domNode *to ) { domNode *n, *n1; domNS *ns, *ns1; domAttrNode *attr, *attr1; int skip; n = from; while (n) { attr = n->firstAttr; while (attr && (attr->nodeFlags & IS_NS_NODE)) { ns = n->ownerDocument->namespaces[attr->namespace-1]; skip = 0; n1 = from; while (n1 != n) { attr1 = n1->firstAttr; while (attr1 && (attr1->nodeFlags & IS_NS_NODE)) { ns1 = n1->ownerDocument->namespaces[attr1->namespace-1]; if ((ns1->prefix == NULL && ns->prefix == NULL) || (strcmp (ns1->prefix, ns->prefix)==0)) { skip = 1; break; } attr1 = attr1->nextSibling; } if (skip) break; n1 = n1->parentNode; } if (!skip) { /* Add this prefix/uri combination only to the destination, if it isn't already in scope */ ns1 = domLookupPrefix (to, ns->prefix); if (!ns1 || (strcmp (ns->uri, ns1->uri)!=0)) { domAddNSToNode (to, ns); } } attr = attr->nextSibling; } n = n->parentNode; } } /*--------------------------------------------------------------------------- | domCopyTo | \--------------------------------------------------------------------------*/ void domCopyTo ( domNode *node, domNode *parent, int copyNS ) { domAttrNode *attr, *nattr; domNode *n, *child; domNS *ns, *ns1; /*------------------------------------------------------------------ | create new node \-----------------------------------------------------------------*/ if (node->nodeType == PROCESSING_INSTRUCTION_NODE) { domProcessingInstructionNode *pinode = (domProcessingInstructionNode*)node; n = (domNode*) domNewProcessingInstructionNode( parent->ownerDocument, pinode->targetValue, pinode->targetLength, pinode->dataValue, pinode->dataLength); domAppendChild (parent, n); return; } if (node->nodeType != ELEMENT_NODE) { domTextNode *tnode = (domTextNode*)node; n = (domNode*) domNewTextNode(parent->ownerDocument, tnode->nodeValue, tnode->valueLength, tnode->nodeType); domAppendChild (parent, n); return; } n = domAppendLiteralNode (parent, node); if (copyNS) { domCopyNS (node, n); } /*------------------------------------------------------------------ | copy attributes (if any) \-----------------------------------------------------------------*/ attr = node->firstAttr; while (attr != NULL) { if (attr->nodeFlags & IS_NS_NODE) { if (copyNS) { /* If copyNS is true, then all namespaces in scope * (including the one declared with the node to copy) * are already copied over. */ attr = attr->nextSibling; continue; } ns = node->ownerDocument->namespaces[attr->namespace-1]; ns1 = domLookupPrefix (n, ns->prefix); if (ns1 && strcmp (ns->uri, ns1->uri)==0) { /* This namespace is already in scope, so we don't copy the namespace attribute over */ attr = attr->nextSibling; continue; } nattr = domSetAttribute (n, attr->nodeName, attr->nodeValue ); nattr->nodeFlags = attr->nodeFlags; ns1 = domNewNamespace (n->ownerDocument, ns->prefix, ns->uri); nattr->namespace = ns1->index; } else { nattr = domSetAttribute (n, attr->nodeName, attr->nodeValue ); nattr->nodeFlags = attr->nodeFlags; if (attr->namespace) { ns = node->ownerDocument->namespaces[attr->namespace-1]; ns1 = domLookupPrefix (n, ns->prefix); if (ns1) { nattr->namespace = ns1->index; } } } attr = attr->nextSibling; } /* We have to set the node namespace index after copying the attribute nodes over, because the node may be in a namespace, which is declared just at the node. */ if (node->namespace) { ns = node->ownerDocument->namespaces[node->namespace-1]; ns1 = domLookupPrefix (n, ns->prefix); n->namespace = ns1->index; } child = node->firstChild; while (child) { domCopyTo(child, n, 0); child = child->nextSibling; } } /*--------------------------------------------------------------------------- | domXPointerChild | \--------------------------------------------------------------------------*/ int domXPointerChild ( domNode * node, int all, int instance, domNodeType type, char * element, char * attrName, char * attrValue, domLength attrLen, domAddCallback addCallback, void * clientData ) { domNode *child; domAttrNode *attr; int i=0, result; if (node->nodeType != ELEMENT_NODE) { return 0; } if (instance<0) { child = node->lastChild; } else { child = node->firstChild; } while (child) { if ((type == ALL_NODES) || (child->nodeType == type)) { if ((element == NULL) || ((child->nodeType == ELEMENT_NODE) && (strcmp(child->nodeName,element)==0)) ) { if (attrName == NULL) { i = (instance<0) ? i-1 : i+1; if (all || (i == instance)) { result = addCallback (child, clientData); if (result) { return result; } } } else { attr = child->firstAttr; while (attr) { if ((strcmp(attr->nodeName,attrName)==0) && ( (strcmp(attrValue,"*")==0) || ( (attr->valueLength == attrLen) && (strcmp(attr->nodeValue,attrValue)==0) ) ) ) { i = (instance<0) ? i-1 : i+1; if (all || (i == instance)) { result = addCallback (child, clientData); if (result) { return result; } } } attr = attr->nextSibling; } } } } if (instance<0) { child = child->previousSibling; } else { child = child->nextSibling; } } return 0; } /*--------------------------------------------------------------------------- | domXPointerXSibling | \--------------------------------------------------------------------------*/ int domXPointerXSibling ( domNode * node, int forward_mode, int all, int instance, domNodeType type, char * element, char * attrName, char * attrValue, domLength attrLen, domAddCallback addCallback, void * clientData ) { domNode *sibling, *endSibling; domAttrNode *attr; int i=0, result; if (forward_mode) { if (instance<0) { endSibling = node; sibling = node; if (node->parentNode) { sibling = node->parentNode->lastChild; } } else { sibling = node->nextSibling; endSibling = NULL; } } else { if (instance<0) { endSibling = node; sibling = node; if (node->parentNode) { sibling = node->parentNode->firstChild; } } else { sibling = node->previousSibling; endSibling = NULL; } instance = -1 * instance; } while (sibling != endSibling) { if ((type == ALL_NODES) || (sibling->nodeType == type)) { if ((element == NULL) || ((sibling->nodeType == ELEMENT_NODE) && (strcmp(sibling->nodeName,element)==0)) ) { if (attrName == NULL) { i = (instance<0) ? i-1 : i+1; if (all || (i == instance)) { result = addCallback (sibling, clientData); if (result) { return result; } } } else { attr = sibling->firstAttr; while (attr) { if ((strcmp(attr->nodeName,attrName)==0) && ( (strcmp(attrValue,"*")==0) || ( (attr->valueLength == attrLen) && (strcmp(attr->nodeValue,attrValue)==0) ) ) ) { i = (instance<0) ? i-1 : i+1; if (all || (i == instance)) { result = addCallback (sibling, clientData); if (result) { return result; } } } attr = attr->nextSibling; } } } } if (instance<0) { sibling = sibling->previousSibling; } else { sibling = sibling->nextSibling; } } return 0; } /*--------------------------------------------------------------------------- | domXPointerDescendant | \--------------------------------------------------------------------------*/ int domXPointerDescendant ( domNode * node, int all, int instance, int * i, domNodeType type, char * element, char * attrName, char * attrValue, domLength attrLen, domAddCallback addCallback, void * clientData ) { domNode *child; domAttrNode *attr; int found=0, result; if (node->nodeType != ELEMENT_NODE) { return 0; } if (instance<0) { child = node->lastChild; } else { child = node->firstChild; } while (child) { found = 0; if ((type == ALL_NODES) || (child->nodeType == type)) { if ((element == NULL) || ((child->nodeType == ELEMENT_NODE) && (strcmp(child->nodeName,element)==0)) ) { if (attrName == NULL) { *i = (instance<0) ? (*i)-1 : (*i)+1; if (all || (*i == instance)) { result = addCallback (child, clientData); if (result) { return result; } found = 1; } } else { attr = child->firstAttr; while (attr) { if ((strcmp(attr->nodeName,attrName)==0) && ( (strcmp(attrValue,"*")==0) || ( (attr->valueLength == attrLen) && (strcmp(attr->nodeValue,attrValue)==0) ) ) ) { *i = (instance<0) ? (*i)-1 : (*i)+1; if (all || (*i == instance)) { result = addCallback (child, clientData); if (result) { return result; } found = 1; } } attr = attr->nextSibling; } } } } if (!found) { /* recurs into children */ result = domXPointerDescendant (child, all, instance, i, type, element, attrName, attrValue, attrLen, addCallback, clientData); if (result) { return result; } } if (instance<0) { child = child->previousSibling; } else { child = child->nextSibling; } } return 0; } /*--------------------------------------------------------------------------- | domXPointerAncestor | \--------------------------------------------------------------------------*/ int domXPointerAncestor ( domNode * node, int all, int instance, int * i, domNodeType type, char * element, char * attrName, char * attrValue, domLength attrLen, domAddCallback addCallback, void * clientData ) { domNode *ancestor; domAttrNode *attr; int result; ancestor = node->parentNode; if (ancestor) { if ((type == ALL_NODES) || (ancestor->nodeType == type)) { if ((element == NULL) || ((ancestor->nodeType == ELEMENT_NODE) && (strcmp(ancestor->nodeName,element)==0)) ) { if (attrName == NULL) { *i = (instance<0) ? (*i)-1 : (*i)+1; if (all || (*i == instance)) { result = addCallback (ancestor, clientData); if (result) { return result; } } } else { attr = ancestor->firstAttr; while (attr) { if ((strcmp(attr->nodeName,attrName)==0) && ( (strcmp(attrValue,"*")==0) || ( (attr->valueLength == attrLen) && (strcmp(attr->nodeValue,attrValue)==0) ) ) ) { *i = (instance<0) ? (*i)-1 : (*i)+1; if (all || (*i == instance)) { result = addCallback (ancestor, clientData); if (result) { return result; } } } attr = attr->nextSibling; } } } } /* go up */ result = domXPointerAncestor (ancestor, all, instance, i, type, element, attrName, attrValue, attrLen, addCallback, clientData); if (result) { return result; } } return 0; } /*--------------------------------------------------------------------------- | type tdomCmdReadInfo | \--------------------------------------------------------------------------*/ /* The struct members until the tdom cmd specific elements must be the * same as for domReadInfo. */ typedef struct _tdomCmdReadInfo { XML_Parser parser; domDocument *document; domNode *currentNode; int depth; int ignoreWhiteSpaces; int cdataSection; Tcl_DString *cdata; int storeLineColumn; domLength textStartLine; domLength textStartColumn; domLength textStartByteIndex; int ignorexmlns; int feedbackAfter; Tcl_Obj *feedbackCmd; XML_Index nextFeedbackPosition; Tcl_Interp *interp; int activeNSsize; int activeNSpos; domActiveNS *activeNS; int baseURIstackSize; int baseURIstackPos; domActiveBaseURI *baseURIstack; int insideDTD; #ifndef TDOM_NO_SCHEMA SchemaData *sdata; #endif int status; /* Now the tdom cmd specific elements */ int tdomStatus; Tcl_Obj *extResolver; TclGenExpatInfo *expatinfo; /* Use read-only ! */ } tdomCmdReadInfo; int tcldom_returnDocumentObj (Tcl_Interp *interp, domDocument *document, Tcl_Obj *var_name, int trace, int forOwnerDocument); void tdom_freeProc ( Tcl_Interp *UNUSED(interp), void *userData ) { tdomCmdReadInfo *info = (tdomCmdReadInfo *) userData; if (info->document) { domFreeDocument (info->document, NULL, NULL); } if (info->activeNS) { FREE (info->activeNS); } if (info->baseURIstack) { FREE (info->baseURIstack); } Tcl_DStringFree (info->cdata); FREE (info->cdata); if (info->extResolver) { Tcl_DecrRefCount (info->extResolver); } FREE (info); } void tdom_parserResetProc ( XML_Parser parser, void *userData ) { tdomCmdReadInfo *info = (tdomCmdReadInfo *) userData; info->parser = parser; } void tdom_resetProc ( Tcl_Interp *interp, void *userData ) { tdomCmdReadInfo *info = (tdomCmdReadInfo *) userData; if (!info->tdomStatus) return; if (info->document) { domFreeDocument (info->document, NULL, NULL); } info->document = NULL; info->currentNode = NULL; info->depth = 0; info->feedbackAfter = 0; info->ignorexmlns = 0; Tcl_DStringSetLength (info->cdata, 0); info->textStartLine = 0; info->nextFeedbackPosition = info->feedbackAfter; info->interp = interp; info->activeNSpos = -1; info->insideDTD = 0; info->baseURIstackPos = 0; info->tdomStatus = 0; } void tdom_initParseProc ( Tcl_Interp *UNUSED(interp), void *userData ) { tdomCmdReadInfo *info = (tdomCmdReadInfo *) userData; info->document = domCreateDoc(XML_GetBase (info->parser), info->storeLineColumn); if (info->extResolver) { info->document->extResolver = tdomstrdup (Tcl_GetString (info->extResolver)); } info->baseURIstack[0].baseURI = XML_GetBase (info->parser); info->baseURIstack[0].depth = 0; info->tdomStatus = 2; info->status = 0; info->expatinfo->cdataStartLine = 0; } static void tdom_charDataHandler ( void *userData, const char *s, domLength len ) { tdomCmdReadInfo *info = (tdomCmdReadInfo *) userData; Tcl_DStringAppend (info->cdata, s, len); if (info->storeLineColumn) { if (!info->textStartLine) { info->textStartLine = info->expatinfo->cdataStartLine; info->textStartColumn = info->expatinfo->cdataStartColumn; info->textStartByteIndex = info->expatinfo->cdataStartByteIndex; } } DispatchPCDATA ((domReadInfo*) info); return; } static void tdom_startCDATA ( void *userData ) { tdomCmdReadInfo *info = (tdomCmdReadInfo *) userData; DispatchPCDATA ((domReadInfo*) info); info->cdataSection = 1; if (info->storeLineColumn) { info->textStartLine = (domLength)XML_GetCurrentLineNumber (info->parser); info->textStartColumn = (domLength)XML_GetCurrentColumnNumber (info->parser); info->textStartByteIndex = (domLength)XML_GetCurrentByteIndex (info->parser); } } int TclTdomObjCmd ( ClientData UNUSED(dummy), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { CHandlerSet *handlerSet; int methodIndex, result, bool; tdomCmdReadInfo *info; TclGenExpatInfo *expat; Tcl_Obj *newObjName = NULL; static const char *tdomMethods[] = { "enable", "getdoc", "setStoreLineColumn", "setExternalEntityResolver", "keepEmpties", "remove", "ignorexmlns", "keepCDATA", "keepTextStart", NULL }; enum tdomMethod { m_enable, m_getdoc, m_setStoreLineColumn, m_setExternalEntityResolver, m_keepEmpties, m_remove, m_ignorexmlns, m_keepCDATA, m_keepTextStart }; if (objc < 3 || objc > 4) { Tcl_WrongNumArgs (interp, 1, objv, tdom_usage); return TCL_ERROR; } if (!CheckExpatParserObj (interp, objv[1])) { Tcl_SetResult (interp, "First argument has to be a expat parser object", NULL); return TCL_ERROR; } if (Tcl_GetIndexFromObj (interp, objv[2], tdomMethods, "method", 0, &methodIndex) != TCL_OK) { Tcl_SetResult (interp, tdom_usage, NULL); return TCL_ERROR; } switch ((enum tdomMethod) methodIndex) { default: Tcl_SetResult (interp, "unknown method", NULL); return TCL_ERROR; case m_enable: expat = GetExpatInfo (interp, objv[1]); if (expat->parsingState != 0) { Tcl_SetResult (interp, "Parser is not in init or reset state.", NULL); return TCL_ERROR; } handlerSet = CHandlerSetCreate ("tdom"); handlerSet->ignoreWhiteCDATAs = 1; handlerSet->resetProc = tdom_resetProc; handlerSet->freeProc = tdom_freeProc; handlerSet->parserResetProc = tdom_parserResetProc; handlerSet->initParseProc = tdom_initParseProc; handlerSet->elementstartcommand = startElement; handlerSet->elementendcommand = endElement; handlerSet->datacommand = tdom_charDataHandler; handlerSet->commentCommand = commentHandler; handlerSet->picommand = processingInstructionHandler; handlerSet->entityDeclCommand = entityDeclHandler; handlerSet->startDoctypeDeclCommand = startDoctypeDeclHandler; handlerSet->endDoctypeDeclCommand = endDoctypeDeclHandler; info = (tdomCmdReadInfo *) MALLOC (sizeof (tdomCmdReadInfo)); memset(info, 0, sizeof(tdomCmdReadInfo)); info->parser = expat->parser; info->ignoreWhiteSpaces = 1; info->cdata = (Tcl_DString*) MALLOC (sizeof (Tcl_DString)); Tcl_DStringInit (info->cdata); info->interp = interp; info->activeNSpos = -1; info->activeNSsize = 8; info->activeNS = (domActiveNS*) MALLOC(sizeof(domActiveNS) * info->activeNSsize); info->baseURIstackSize = INITIAL_BASEURISTACK_SIZE; info->baseURIstack = (domActiveBaseURI*) MALLOC (sizeof(domActiveBaseURI) * info->baseURIstackSize); info->expatinfo = expat; handlerSet->userData = info; CHandlerSetInstall (interp, objv[1], handlerSet); break; case m_getdoc: info = CHandlerSetGetUserData (interp, objv[1], "tdom"); if (!info) { Tcl_SetResult (interp, "parser object isn't tdom enabled.", NULL); return TCL_ERROR; } expat = GetExpatInfo (interp, objv[1]); if (info->tdomStatus != 2 || !expat->finished) { Tcl_SetResult (interp, "No DOM tree available.", NULL); return TCL_ERROR; } domSetDocumentElement (info->document); result = tcldom_returnDocumentObj (interp, info->document, newObjName, 0, 0); info->document = NULL; return result; case m_setStoreLineColumn: info = CHandlerSetGetUserData (interp, objv[1], "tdom"); if (!info) { Tcl_SetResult (interp, "parser object isn't tdom enabled.", NULL); return TCL_ERROR; } Tcl_SetIntObj (Tcl_GetObjResult (interp), info->storeLineColumn); if (objc == 4) { if (Tcl_GetBooleanFromObj (interp, objv[3], &bool) != TCL_OK) { return TCL_ERROR; } info->storeLineColumn = bool; } info->tdomStatus = 1; break; case m_remove: result = CHandlerSetRemove (interp, objv[1], "tdom"); if (result == 2) { Tcl_SetResult (interp, "expat parser obj hasn't a C handler set named \"tdom\"", NULL); return TCL_ERROR; } break; case m_setExternalEntityResolver: if (objc != 4) { Tcl_SetResult (interp, "You must name a Tcl command as external entity resolver for setExternalEntityResolver.", NULL); return TCL_ERROR; } info = CHandlerSetGetUserData (interp, objv[1], "tdom"); if (!info) { Tcl_SetResult (interp, "parser object isn't tdom enabled.", NULL); return TCL_ERROR; } if (info->extResolver) { Tcl_DecrRefCount (info->extResolver); } if (strcmp (Tcl_GetString (objv[3]), "") == 0) { info->extResolver = NULL; } else { info->extResolver = objv[3]; Tcl_IncrRefCount (info->extResolver); } info->tdomStatus = 1; break; case m_keepEmpties: if (objc != 4) { Tcl_SetResult (interp, "wrong # of args for method keepEmpties.", NULL); return TCL_ERROR; } handlerSet = CHandlerSetGet (interp, objv[1], "tdom"); if (!handlerSet) { Tcl_SetResult (interp, "parser object isn't tdom enabled.", NULL); return TCL_ERROR; } info = handlerSet->userData; if (!info) { Tcl_SetResult (interp, "parser object isn't tdom enabled.", NULL); return TCL_ERROR; } Tcl_SetIntObj (Tcl_GetObjResult (interp), info->ignoreWhiteSpaces); if (Tcl_GetBooleanFromObj (interp, objv[3], &bool) != TCL_OK) { return TCL_ERROR; } info->ignoreWhiteSpaces = !bool; handlerSet->ignoreWhiteCDATAs = !bool; info->tdomStatus = 1; break; case m_keepCDATA: if (objc != 4) { Tcl_SetResult (interp, "wrong # of args for method keepCDATA.", NULL); return TCL_ERROR; } handlerSet = CHandlerSetGet (interp, objv[1], "tdom"); if (!handlerSet) { Tcl_SetResult (interp, "parser object isn't tdom enabled.", NULL); return TCL_ERROR; } info = handlerSet->userData; if (!info) { Tcl_SetResult (interp, "parser object isn't tdom enabled.", NULL); return TCL_ERROR; } if (Tcl_GetBooleanFromObj (interp, objv[3], &bool) != TCL_OK) { return TCL_ERROR; } if (bool) { handlerSet->startCdataSectionCommand = tdom_startCDATA; handlerSet->endCdataSectionCommand = endCDATA; } else { handlerSet->startCdataSectionCommand = NULL; handlerSet->endCdataSectionCommand = NULL; } info->tdomStatus = 1; break; case m_keepTextStart: if (objc != 4) { Tcl_SetResult (interp, "wrong # of args for method keepCDATA.", NULL); return TCL_ERROR; } handlerSet = CHandlerSetGet (interp, objv[1], "tdom"); if (!handlerSet) { Tcl_SetResult (interp, "parser object isn't tdom enabled.", NULL); return TCL_ERROR; } info = handlerSet->userData; if (!info) { Tcl_SetResult (interp, "parser object isn't tdom enabled.", NULL); return TCL_ERROR; } if (Tcl_GetBooleanFromObj (interp, objv[3], &bool) != TCL_OK) { return TCL_ERROR; } expat = GetExpatInfo (interp, objv[1]); expat->keepTextStart = bool; expat->cdataStartLine = 0; break; case m_ignorexmlns: info = CHandlerSetGetUserData (interp, objv[1], "tdom"); if (!info) { Tcl_SetResult (interp, "parser object isn't tdom enabled.", NULL); return TCL_ERROR; } Tcl_SetIntObj (Tcl_GetObjResult (interp), info->ignorexmlns); if (objc == 4) { if (Tcl_GetBooleanFromObj (interp, objv[3], &bool) != TCL_OK) { return TCL_ERROR; } info->ignorexmlns = bool; } info->tdomStatus = 1; break; } return TCL_OK; } tdom-0.9.5-src/generic/domxpath.h0000644000175000017500000002026714703531020015356 0ustar rolfrolf/*---------------------------------------------------------------------------- | Copyright (c) 1999 Jochen Loewer (loewerj@hotmail.com) |----------------------------------------------------------------------------- | | A (partial) XPath implementation (lexer/parser/evaluator) for tDOM, | the DOM implementation for Tcl. | Based on the August 13 working draft of the W3C | (http://www.w3.org/1999/08/WD-xpath-19990813.html) | | | The contents of this file are subject to the Mozilla Public License | Version 2.0 (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) 1998, 1999 | Jochen Loewer. All Rights Reserved. | | Contributor(s): | | | | written by Jochen Loewer | July, 1999 | \---------------------------------------------------------------------------*/ #ifndef __DOMXPATH_H__ #define __DOMXPATH_H__ #include #include /*---------------------------------------------------------------------------- | Macros | \---------------------------------------------------------------------------*/ #define XPATH_OK 0 #define XPATH_LEX_ERR -1 #define XPATH_SYNTAX_ERR -2 #define XPATH_EVAL_ERR -3 #define XPATH_VAR_NOT_FOUND -4 #define XPATH_I18N_ERR -5 /* * Macros for testing floating-point values for certain special cases. Test * for not-a-number by comparing a value against itself; test for infinity * by comparing against the largest floating-point value. */ #define IS_NAN(v) ((v) != (v)) #ifdef DBL_MAX # define IS_INF(v) ((v) > DBL_MAX ? 1 : ((v) < -DBL_MAX ? -1 : 0)) #else # define IS_INF(v) 0 #endif #if TCL_MAJOR_VERSION > 8 # define dom_minl domLength #else # define dom_minl long #endif /*---------------------------------------------------------------------------- | Types for abstract syntax trees | \---------------------------------------------------------------------------*/ typedef enum { Int, Real, Mult, Div, Mod, UnaryMinus, IsNSElement, IsNode, IsComment, IsText, IsPI, IsSpecificPI, IsElement, IsFQElement, GetVar, GetFQVar, Literal, ExecFunction, Pred, EvalSteps, SelectRoot, CombineSets, Add, Subtract, Less, LessOrEq, Greater, GreaterOrEq, Equal, NotEqual, And, Or, IsNSAttr, IsAttr, AxisAncestor, AxisAncestorOrSelf, AxisAttribute, AxisChild, AxisDescendant, AxisDescendantOrSelf, AxisFollowing, AxisFollowingSibling, AxisNamespace, AxisParent, AxisPreceding, AxisPrecedingSibling, AxisSelf, GetContextNode, GetParentNode, AxisDescendantOrSelfLit, AxisDescendantLit, SlashSlash, CombinePath, IsRoot, ToParent, ToAncestors, FillNodeList, FillWithCurrentNode, ExecIdKey } astType; typedef struct astElem { astType type; struct astElem *child; struct astElem *next; char *strvalue; dom_minl intvalue; double realvalue; } astElem; typedef astElem *ast; /*---------------------------------------------------------------------------- | Types for XPath result set | \---------------------------------------------------------------------------*/ typedef enum { UnknownResult = 0, EmptyResult, BoolResult, IntResult, RealResult, StringResult, xNodeSetResult, NaNResult, InfResult, NInfResult, NodesResult, AttrnodesResult, MixedResult } xpathResultType; typedef struct xpathResultSet { xpathResultType type; char *string; domLength string_len; dom_minl intvalue; double realvalue; domNode **nodes; domLength nr_nodes; domLength allocated; } xpathResultSet; typedef xpathResultSet *xpathResultSets; typedef int (*xpathFuncCallback) (void *clientData, char *functionName, domNode *ctxNode, domLength position, xpathResultSet *nodeList, domNode *exprContext, int argc, xpathResultSets *args, xpathResultSet *result, char **errMsg); typedef int (*xpathVarCallback) (void *clientData, char *variableName, char *varURI, xpathResultSet *result, char **errMsg); typedef struct xpathCBs { /* all xpath callbacks + clientData */ xpathVarCallback varCB; void * varClientData; xpathFuncCallback funcCB; void * funcClientData; } xpathCBs; typedef char * (*xpathParseVarCallback) (void *clientData, char *strToParse, domLength *offset, char **errMsg); typedef struct xpathParseVarCB { xpathParseVarCallback parseVarCB; void * parseVarClientData; } xpathParseVarCB; /* XPath expr/pattern types */ typedef enum { XPATH_EXPR, XPATH_FORMAT_PATTERN, XPATH_TEMPMATCH_PATTERN, XPATH_KEY_USE_EXPR, XPATH_KEY_MATCH_PATTERN } xpathExprType; /*---------------------------------------------------------------------------- | Prototypes | \---------------------------------------------------------------------------*/ int xpathParse (char *xpath, domNode *exprContext, xpathExprType type, char **prefixMappings, xpathParseVarCB *varParseCB, ast *t, char **errMsg); void xpathFreeAst (ast t); double xpathGetPrio (ast t); int xpathEval (domNode *node, domNode *exprContext, char *xpath, char **prefixMappings, xpathCBs *cbs, xpathParseVarCB *parseVarCB, Tcl_HashTable *catch, char **errMsg, xpathResultSet *rs); int xpathEvalAst (ast t, xpathResultSet *nodeList, domNode *node, xpathCBs *cbs, xpathResultSet *rs, char **errMsg); int xpathMatches (ast steps, domNode * exprContext, domNode *nodeToMatch, xpathCBs *cbs, char **errMsg ); int xpathEvalSteps (ast steps, xpathResultSet *nodeList, domNode *currentNode, domNode *exprContext, domLength currentPos, int *docOrder, xpathCBs *cbs, xpathResultSet *result, char **errMsg); #define xpathRSInit(x) (x)->type = EmptyResult; \ (x)->intvalue = 0; \ (x)->nr_nodes = 0; void xpathRSFree (xpathResultSet *rs); void xpathRSReset (xpathResultSet *rs, domNode *ode); int xpathFuncBoolean (xpathResultSet *rs); double xpathFuncNumber (xpathResultSet *rs, int *NaN); char * xpathFuncString (xpathResultSet *rs); char * xpathFuncStringForNode (domNode *node); domLength xpathRound (double r); char * xpathGetStringValue (domNode *node, domLength *strLen); char * xpathNodeToXPath (domNode *node, int legacy); void rsSetBool ( xpathResultSet *rs, dom_minl i ); void rsSetLong ( xpathResultSet *rs, dom_minl i ); void rsSetReal ( xpathResultSet *rs, double d ); void rsSetReal2 ( xpathResultSet *rs, double d ); void rsSetString ( xpathResultSet *rs, const char *s ); void rsAddNode ( xpathResultSet *rs, domNode *node ); void rsAddNodeFast ( xpathResultSet *rs, domNode *node ); void rsCopy ( xpathResultSet *to, xpathResultSet *from ); /* This function is only used for debugging code */ void rsPrint ( xpathResultSet *rs ); const char * xpathResultType2string (xpathResultType type); /* This function is used (outside of tcldom.c) only by schema.c. It * has to have a prototype somewhere. */ int tcldom_xpathFuncCallBack ( void *clientData, char *functionName, domNode *ctxNode, domLength position, xpathResultSet *nodeList, domNode *exprContext, int argc, xpathResultSets *args, xpathResultSet *result, char **errMsg ); #endif tdom-0.9.5-src/generic/HTML5ent.inc0000644000175000017500000033437014703531020015417 0ustar rolfrolfcase 9: AE(" "); break; /* \t */ case 10: AE(" "); break; /* \n */ case 33: AE("!"); break; /* ! */ /* quot aka QUOT */ case 34: AE("""); break; /* " */ case 35: AE("#"); break; /* # */ case 36: AE("$"); break; /* $ */ case 37: AE("%"); break; /* % */ /* amp aka AMP */ case 38: AE("&"); break; /* & */ case 39: AE("'"); break; /* ' */ case 40: AE("("); break; /* ( */ case 41: AE(")"); break; /* ) */ /* ast aka midast */ case 42: AE("*"); break; /* * */ case 43: AE("+"); break; /* + */ case 44: AE(","); break; /* , */ case 46: AE("."); break; /* . */ case 47: AE("/"); break; /* / */ case 58: AE(":"); break; /* : */ case 59: AE(";"); break; /* ; */ case 60: TWOCPE; if (clen2 && uniChar2 == 8402) { AE("<⃒"); MCP; /* <⃒ */ } else { /* lt aka LT */ AE("<"); /* < */ }; break; case 61: TWOCPE; if (clen2 && uniChar2 == 8421) { AE("=⃥"); MCP; /* =⃥ */ } else { AE("="); /* = */ }; break; case 62: TWOCPE; if (clen2 && uniChar2 == 8402) { AE(">⃒"); MCP; /* >⃒ */ } else { /* gt aka GT */ AE(">"); /* > */ }; break; case 63: AE("?"); break; /* ? */ case 64: AE("@"); break; /* @ */ /* lsqb aka lbrack */ case 91: AE("["); break; /* [ */ case 92: AE("\"); break; /* \ */ /* rsqb aka rbrack */ case 93: AE("]"); break; /* ] */ case 94: AE("^"); break; /* ^ */ /* lowbar aka UnderBar */ case 95: AE("_"); break; /* _ */ /* grave aka DiacriticalGrave */ case 96: AE("`"); break; /* ` */ case 102: TWOCPE; if (uniChar2 == 106) { AE("fj"); MCP; /* fj */ } else {charDone = 0;}; break; /* lcub aka lbrace */ case 123: AE("{"); break; /* { */ /* vert aka VerticalLine or verbar */ case 124: AE("|"); break; /* | */ /* rcub aka rbrace */ case 125: AE("}"); break; /* } */ /* nbsp aka NonBreakingSpace */ case 160: AE(" "); break; /*   */ case 161: AE("¡"); break; /* ¡ */ case 162: AE("¢"); break; /* ¢ */ case 163: AE("£"); break; /* £ */ case 164: AE("¤"); break; /* ¤ */ case 165: AE("¥"); break; /* ¥ */ case 166: AE("¦"); break; /* ¦ */ case 167: AE("§"); break; /* § */ /* die aka Dot or DoubleDot or uml */ case 168: AE("¨"); break; /* ¨ */ /* copy aka COPY */ case 169: AE("©"); break; /* © */ case 170: AE("ª"); break; /* ª */ case 171: AE("«"); break; /* « */ case 172: AE("¬"); break; /* ¬ */ case 173: AE("­"); break; /* ­ */ /* reg aka REG or circledR */ case 174: AE("®"); break; /* ® */ /* macr aka strns */ case 175: AE("¯"); break; /* ¯ */ case 176: AE("°"); break; /* ° */ /* pm aka PlusMinus or plusmn */ case 177: AE("±"); break; /* ± */ case 178: AE("²"); break; /* ² */ case 179: AE("³"); break; /* ³ */ /* acute aka DiacriticalAcute */ case 180: AE("´"); break; /* ´ */ case 181: AE("µ"); break; /* µ */ case 182: AE("¶"); break; /* ¶ */ /* middot aka CenterDot or centerdot */ case 183: AE("·"); break; /* · */ /* cedil aka Cedilla */ case 184: AE("¸"); break; /* ¸ */ case 185: AE("¹"); break; /* ¹ */ case 186: AE("º"); break; /* º */ case 187: AE("»"); break; /* » */ case 188: AE("¼"); break; /* ¼ */ /* half aka frac12 */ case 189: AE("½"); break; /* ½ */ case 190: AE("¾"); break; /* ¾ */ case 191: AE("¿"); break; /* ¿ */ case 192: AE("À"); break; /* À */ case 193: AE("Á"); break; /* Á */ case 194: AE("Â"); break; /*  */ case 195: AE("Ã"); break; /* à */ case 196: AE("Ä"); break; /* Ä */ /* angst aka Aring */ case 197: AE("Å"); break; /* Å */ case 198: AE("Æ"); break; /* Æ */ case 199: AE("Ç"); break; /* Ç */ case 200: AE("È"); break; /* È */ case 201: AE("É"); break; /* É */ case 202: AE("Ê"); break; /* Ê */ case 203: AE("Ë"); break; /* Ë */ case 204: AE("Ì"); break; /* Ì */ case 205: AE("Í"); break; /* Í */ case 206: AE("Î"); break; /* Î */ case 207: AE("Ï"); break; /* Ï */ case 208: AE("Ð"); break; /* Ð */ case 209: AE("Ñ"); break; /* Ñ */ case 210: AE("Ò"); break; /* Ò */ case 211: AE("Ó"); break; /* Ó */ case 212: AE("Ô"); break; /* Ô */ case 213: AE("Õ"); break; /* Õ */ case 214: AE("Ö"); break; /* Ö */ case 215: AE("×"); break; /* × */ case 216: AE("Ø"); break; /* Ø */ case 217: AE("Ù"); break; /* Ù */ case 218: AE("Ú"); break; /* Ú */ case 219: AE("Û"); break; /* Û */ case 220: AE("Ü"); break; /* Ü */ case 221: AE("Ý"); break; /* Ý */ case 222: AE("Þ"); break; /* Þ */ case 223: AE("ß"); break; /* ß */ case 224: AE("à"); break; /* à */ case 225: AE("á"); break; /* á */ case 226: AE("â"); break; /* â */ case 227: AE("ã"); break; /* ã */ case 228: AE("ä"); break; /* ä */ case 229: AE("å"); break; /* å */ case 230: AE("æ"); break; /* æ */ case 231: AE("ç"); break; /* ç */ case 232: AE("è"); break; /* è */ case 233: AE("é"); break; /* é */ case 234: AE("ê"); break; /* ê */ case 235: AE("ë"); break; /* ë */ case 236: AE("ì"); break; /* ì */ case 237: AE("í"); break; /* í */ case 238: AE("î"); break; /* î */ case 239: AE("ï"); break; /* ï */ case 240: AE("ð"); break; /* ð */ case 241: AE("ñ"); break; /* ñ */ case 242: AE("ò"); break; /* ò */ case 243: AE("ó"); break; /* ó */ case 244: AE("ô"); break; /* ô */ case 245: AE("õ"); break; /* õ */ case 246: AE("ö"); break; /* ö */ /* div aka divide */ case 247: AE("÷"); break; /* ÷ */ case 248: AE("ø"); break; /* ø */ case 249: AE("ù"); break; /* ù */ case 250: AE("ú"); break; /* ú */ case 251: AE("û"); break; /* û */ case 252: AE("ü"); break; /* ü */ case 253: AE("ý"); break; /* ý */ case 254: AE("þ"); break; /* þ */ case 255: AE("ÿ"); break; /* ÿ */ case 256: AE("Ā"); break; /* Ā */ case 257: AE("ā"); break; /* ā */ case 258: AE("Ă"); break; /* Ă */ case 259: AE("ă"); break; /* ă */ case 260: AE("Ą"); break; /* Ą */ case 261: AE("ą"); break; /* ą */ case 262: AE("Ć"); break; /* Ć */ case 263: AE("ć"); break; /* ć */ case 264: AE("Ĉ"); break; /* Ĉ */ case 265: AE("ĉ"); break; /* ĉ */ case 266: AE("Ċ"); break; /* Ċ */ case 267: AE("ċ"); break; /* ċ */ case 268: AE("Č"); break; /* Č */ case 269: AE("č"); break; /* č */ case 270: AE("Ď"); break; /* Ď */ case 271: AE("ď"); break; /* ď */ case 272: AE("Đ"); break; /* Đ */ case 273: AE("đ"); break; /* đ */ case 274: AE("Ē"); break; /* Ē */ case 275: AE("ē"); break; /* ē */ case 278: AE("Ė"); break; /* Ė */ case 279: AE("ė"); break; /* ė */ case 280: AE("Ę"); break; /* Ę */ case 281: AE("ę"); break; /* ę */ case 282: AE("Ě"); break; /* Ě */ case 283: AE("ě"); break; /* ě */ case 284: AE("Ĝ"); break; /* Ĝ */ case 285: AE("ĝ"); break; /* ĝ */ case 286: AE("Ğ"); break; /* Ğ */ case 287: AE("ğ"); break; /* ğ */ case 288: AE("Ġ"); break; /* Ġ */ case 289: AE("ġ"); break; /* ġ */ case 290: AE("Ģ"); break; /* Ģ */ case 292: AE("Ĥ"); break; /* Ĥ */ case 293: AE("ĥ"); break; /* ĥ */ case 294: AE("Ħ"); break; /* Ħ */ case 295: AE("ħ"); break; /* ħ */ case 296: AE("Ĩ"); break; /* Ĩ */ case 297: AE("ĩ"); break; /* ĩ */ case 298: AE("Ī"); break; /* Ī */ case 299: AE("ī"); break; /* ī */ case 302: AE("Į"); break; /* Į */ case 303: AE("į"); break; /* į */ case 304: AE("İ"); break; /* İ */ /* imath aka inodot */ case 305: AE("ı"); break; /* ı */ case 306: AE("IJ"); break; /* IJ */ case 307: AE("ij"); break; /* ij */ case 308: AE("Ĵ"); break; /* Ĵ */ case 309: AE("ĵ"); break; /* ĵ */ case 310: AE("Ķ"); break; /* Ķ */ case 311: AE("ķ"); break; /* ķ */ case 312: AE("ĸ"); break; /* ĸ */ case 313: AE("Ĺ"); break; /* Ĺ */ case 314: AE("ĺ"); break; /* ĺ */ case 315: AE("Ļ"); break; /* Ļ */ case 316: AE("ļ"); break; /* ļ */ case 317: AE("Ľ"); break; /* Ľ */ case 318: AE("ľ"); break; /* ľ */ case 319: AE("Ŀ"); break; /* Ŀ */ case 320: AE("ŀ"); break; /* ŀ */ case 321: AE("Ł"); break; /* Ł */ case 322: AE("ł"); break; /* ł */ case 323: AE("Ń"); break; /* Ń */ case 324: AE("ń"); break; /* ń */ case 325: AE("Ņ"); break; /* Ņ */ case 326: AE("ņ"); break; /* ņ */ case 327: AE("Ň"); break; /* Ň */ case 328: AE("ň"); break; /* ň */ case 329: AE("ʼn"); break; /* ʼn */ case 330: AE("Ŋ"); break; /* Ŋ */ case 331: AE("ŋ"); break; /* ŋ */ case 332: AE("Ō"); break; /* Ō */ case 333: AE("ō"); break; /* ō */ case 336: AE("Ő"); break; /* Ő */ case 337: AE("ő"); break; /* ő */ case 338: AE("Œ"); break; /* Œ */ case 339: AE("œ"); break; /* œ */ case 340: AE("Ŕ"); break; /* Ŕ */ case 341: AE("ŕ"); break; /* ŕ */ case 342: AE("Ŗ"); break; /* Ŗ */ case 343: AE("ŗ"); break; /* ŗ */ case 344: AE("Ř"); break; /* Ř */ case 345: AE("ř"); break; /* ř */ case 346: AE("Ś"); break; /* Ś */ case 347: AE("ś"); break; /* ś */ case 348: AE("Ŝ"); break; /* Ŝ */ case 349: AE("ŝ"); break; /* ŝ */ case 350: AE("Ş"); break; /* Ş */ case 351: AE("ş"); break; /* ş */ case 352: AE("Š"); break; /* Š */ case 353: AE("š"); break; /* š */ case 354: AE("Ţ"); break; /* Ţ */ case 355: AE("ţ"); break; /* ţ */ case 356: AE("Ť"); break; /* Ť */ case 357: AE("ť"); break; /* ť */ case 358: AE("Ŧ"); break; /* Ŧ */ case 359: AE("ŧ"); break; /* ŧ */ case 360: AE("Ũ"); break; /* Ũ */ case 361: AE("ũ"); break; /* ũ */ case 362: AE("Ū"); break; /* Ū */ case 363: AE("ū"); break; /* ū */ case 364: AE("Ŭ"); break; /* Ŭ */ case 365: AE("ŭ"); break; /* ŭ */ case 366: AE("Ů"); break; /* Ů */ case 367: AE("ů"); break; /* ů */ case 368: AE("Ű"); break; /* Ű */ case 369: AE("ű"); break; /* ű */ case 370: AE("Ų"); break; /* Ų */ case 371: AE("ų"); break; /* ų */ case 372: AE("Ŵ"); break; /* Ŵ */ case 373: AE("ŵ"); break; /* ŵ */ case 374: AE("Ŷ"); break; /* Ŷ */ case 375: AE("ŷ"); break; /* ŷ */ case 376: AE("Ÿ"); break; /* Ÿ */ case 377: AE("Ź"); break; /* Ź */ case 378: AE("ź"); break; /* ź */ case 379: AE("Ż"); break; /* Ż */ case 380: AE("ż"); break; /* ż */ case 381: AE("Ž"); break; /* Ž */ case 382: AE("ž"); break; /* ž */ case 402: AE("ƒ"); break; /* ƒ */ case 437: AE("Ƶ"); break; /* Ƶ */ case 501: AE("ǵ"); break; /* ǵ */ case 567: AE("ȷ"); break; /* ȷ */ case 710: AE("ˆ"); break; /* ˆ */ /* caron aka Hacek */ case 711: AE("ˇ"); break; /* ˇ */ /* breve aka Breve */ case 728: AE("˘"); break; /* ˘ */ /* dot aka DiacriticalDot */ case 729: AE("˙"); break; /* ˙ */ case 730: AE("˚"); break; /* ˚ */ case 731: AE("˛"); break; /* ˛ */ /* tilde aka DiacriticalTilde */ case 732: AE("˜"); break; /* ˜ */ /* dblac aka DiacriticalDoubleAcute */ case 733: AE("˝"); break; /* ˝ */ case 785: AE("̑"); break; /* ̑ */ case 913: AE("Α"); break; /* Α */ case 914: AE("Β"); break; /* Β */ case 915: AE("Γ"); break; /* Γ */ case 916: AE("Δ"); break; /* Δ */ case 917: AE("Ε"); break; /* Ε */ case 918: AE("Ζ"); break; /* Ζ */ case 919: AE("Η"); break; /* Η */ case 920: AE("Θ"); break; /* Θ */ case 921: AE("Ι"); break; /* Ι */ case 922: AE("Κ"); break; /* Κ */ case 923: AE("Λ"); break; /* Λ */ case 924: AE("Μ"); break; /* Μ */ case 925: AE("Ν"); break; /* Ν */ case 926: AE("Ξ"); break; /* Ξ */ case 927: AE("Ο"); break; /* Ο */ case 928: AE("Π"); break; /* Π */ case 929: AE("Ρ"); break; /* Ρ */ case 931: AE("Σ"); break; /* Σ */ case 932: AE("Τ"); break; /* Τ */ case 933: AE("Υ"); break; /* Υ */ case 934: AE("Φ"); break; /* Φ */ case 935: AE("Χ"); break; /* Χ */ case 936: AE("Ψ"); break; /* Ψ */ /* ohm aka Omega */ case 937: AE("Ω"); break; /* Ω */ case 945: AE("α"); break; /* α */ case 946: AE("β"); break; /* β */ case 947: AE("γ"); break; /* γ */ case 948: AE("δ"); break; /* δ */ /* epsi aka epsilon */ case 949: AE("ε"); break; /* ε */ case 950: AE("ζ"); break; /* ζ */ case 951: AE("η"); break; /* η */ case 952: AE("θ"); break; /* θ */ case 953: AE("ι"); break; /* ι */ case 954: AE("κ"); break; /* κ */ case 955: AE("λ"); break; /* λ */ case 956: AE("μ"); break; /* μ */ case 957: AE("ν"); break; /* ν */ case 958: AE("ξ"); break; /* ξ */ case 959: AE("ο"); break; /* ο */ case 960: AE("π"); break; /* π */ case 961: AE("ρ"); break; /* ρ */ /* sigmaf aka sigmav or varsigma */ case 962: AE("ς"); break; /* ς */ case 963: AE("σ"); break; /* σ */ case 964: AE("τ"); break; /* τ */ /* upsi aka upsilon */ case 965: AE("υ"); break; /* υ */ case 966: AE("φ"); break; /* φ */ case 967: AE("χ"); break; /* χ */ case 968: AE("ψ"); break; /* ψ */ case 969: AE("ω"); break; /* ω */ /* thetav aka thetasym or vartheta */ case 977: AE("ϑ"); break; /* ϑ */ /* Upsi aka upsih */ case 978: AE("ϒ"); break; /* ϒ */ /* phiv aka straightphi or varphi */ case 981: AE("ϕ"); break; /* ϕ */ /* piv aka varpi */ case 982: AE("ϖ"); break; /* ϖ */ case 988: AE("Ϝ"); break; /* Ϝ */ /* gammad aka digamma */ case 989: AE("ϝ"); break; /* ϝ */ /* kappav aka varkappa */ case 1008: AE("ϰ"); break; /* ϰ */ /* rhov aka varrho */ case 1009: AE("ϱ"); break; /* ϱ */ /* epsiv aka straightepsilon or varepsilon */ case 1013: AE("ϵ"); break; /* ϵ */ /* bepsi aka backepsilon */ case 1014: AE("϶"); break; /* ϶ */ case 1025: AE("Ё"); break; /* Ё */ case 1026: AE("Ђ"); break; /* Ђ */ case 1027: AE("Ѓ"); break; /* Ѓ */ case 1028: AE("Є"); break; /* Є */ case 1029: AE("Ѕ"); break; /* Ѕ */ case 1030: AE("І"); break; /* І */ case 1031: AE("Ї"); break; /* Ї */ case 1032: AE("Ј"); break; /* Ј */ case 1033: AE("Љ"); break; /* Љ */ case 1034: AE("Њ"); break; /* Њ */ case 1035: AE("Ћ"); break; /* Ћ */ case 1036: AE("Ќ"); break; /* Ќ */ case 1038: AE("Ў"); break; /* Ў */ case 1039: AE("Џ"); break; /* Џ */ case 1040: AE("А"); break; /* А */ case 1041: AE("Б"); break; /* Б */ case 1042: AE("В"); break; /* В */ case 1043: AE("Г"); break; /* Г */ case 1044: AE("Д"); break; /* Д */ case 1045: AE("Е"); break; /* Е */ case 1046: AE("Ж"); break; /* Ж */ case 1047: AE("З"); break; /* З */ case 1048: AE("И"); break; /* И */ case 1049: AE("Й"); break; /* Й */ case 1050: AE("К"); break; /* К */ case 1051: AE("Л"); break; /* Л */ case 1052: AE("М"); break; /* М */ case 1053: AE("Н"); break; /* Н */ case 1054: AE("О"); break; /* О */ case 1055: AE("П"); break; /* П */ case 1056: AE("Р"); break; /* Р */ case 1057: AE("С"); break; /* С */ case 1058: AE("Т"); break; /* Т */ case 1059: AE("У"); break; /* У */ case 1060: AE("Ф"); break; /* Ф */ case 1061: AE("Х"); break; /* Х */ case 1062: AE("Ц"); break; /* Ц */ case 1063: AE("Ч"); break; /* Ч */ case 1064: AE("Ш"); break; /* Ш */ case 1065: AE("Щ"); break; /* Щ */ case 1066: AE("Ъ"); break; /* Ъ */ case 1067: AE("Ы"); break; /* Ы */ case 1068: AE("Ь"); break; /* Ь */ case 1069: AE("Э"); break; /* Э */ case 1070: AE("Ю"); break; /* Ю */ case 1071: AE("Я"); break; /* Я */ case 1072: AE("а"); break; /* а */ case 1073: AE("б"); break; /* б */ case 1074: AE("в"); break; /* в */ case 1075: AE("г"); break; /* г */ case 1076: AE("д"); break; /* д */ case 1077: AE("е"); break; /* е */ case 1078: AE("ж"); break; /* ж */ case 1079: AE("з"); break; /* з */ case 1080: AE("и"); break; /* и */ case 1081: AE("й"); break; /* й */ case 1082: AE("к"); break; /* к */ case 1083: AE("л"); break; /* л */ case 1084: AE("м"); break; /* м */ case 1085: AE("н"); break; /* н */ case 1086: AE("о"); break; /* о */ case 1087: AE("п"); break; /* п */ case 1088: AE("р"); break; /* р */ case 1089: AE("с"); break; /* с */ case 1090: AE("т"); break; /* т */ case 1091: AE("у"); break; /* у */ case 1092: AE("ф"); break; /* ф */ case 1093: AE("х"); break; /* х */ case 1094: AE("ц"); break; /* ц */ case 1095: AE("ч"); break; /* ч */ case 1096: AE("ш"); break; /* ш */ case 1097: AE("щ"); break; /* щ */ case 1098: AE("ъ"); break; /* ъ */ case 1099: AE("ы"); break; /* ы */ case 1100: AE("ь"); break; /* ь */ case 1101: AE("э"); break; /* э */ case 1102: AE("ю"); break; /* ю */ case 1103: AE("я"); break; /* я */ case 1105: AE("ё"); break; /* ё */ case 1106: AE("ђ"); break; /* ђ */ case 1107: AE("ѓ"); break; /* ѓ */ case 1108: AE("є"); break; /* є */ case 1109: AE("ѕ"); break; /* ѕ */ case 1110: AE("і"); break; /* і */ case 1111: AE("ї"); break; /* ї */ case 1112: AE("ј"); break; /* ј */ case 1113: AE("љ"); break; /* љ */ case 1114: AE("њ"); break; /* њ */ case 1115: AE("ћ"); break; /* ћ */ case 1116: AE("ќ"); break; /* ќ */ case 1118: AE("ў"); break; /* ў */ case 1119: AE("џ"); break; /* џ */ case 8194: AE(" "); break; /*   */ case 8195: AE(" "); break; /*   */ case 8196: AE(" "); break; /*   */ case 8197: AE(" "); break; /*   */ case 8199: AE(" "); break; /*   */ case 8200: AE(" "); break; /*   */ /* thinsp aka ThinSpace */ case 8201: AE(" "); break; /*   */ /* hairsp aka VeryThinSpace */ case 8202: AE(" "); break; /*   */ /* ZeroWidthSpace aka NegativeMediumSpace or NegativeThickSpace or NegativeThinSpace or NegativeVeryThinSpace */ case 8203: AE("​"); break; /* ​ */ case 8204: AE("‌"); break; /* ‌ */ case 8205: AE("‍"); break; /* ‍ */ case 8206: AE("‎"); break; /* ‎ */ case 8207: AE("‏"); break; /* ‏ */ /* dash aka hyphen */ case 8208: AE("‐"); break; /* ‐ */ case 8211: AE("–"); break; /* – */ case 8212: AE("—"); break; /* — */ case 8213: AE("―"); break; /* ― */ /* Vert aka Verbar */ case 8214: AE("‖"); break; /* ‖ */ /* lsquo aka OpenCurlyQuote */ case 8216: AE("‘"); break; /* ‘ */ /* rsquo aka CloseCurlyQuote or rsquor */ case 8217: AE("’"); break; /* ’ */ /* sbquo aka lsquor */ case 8218: AE("‚"); break; /* ‚ */ /* ldquo aka OpenCurlyDoubleQuote */ case 8220: AE("“"); break; /* “ */ /* rdquo aka CloseCurlyDoubleQuote or rdquor */ case 8221: AE("”"); break; /* ” */ /* bdquo aka ldquor */ case 8222: AE("„"); break; /* „ */ case 8224: AE("†"); break; /* † */ /* Dagger aka ddagger */ case 8225: AE("‡"); break; /* ‡ */ /* bull aka bullet */ case 8226: AE("•"); break; /* • */ case 8229: AE("‥"); break; /* ‥ */ /* mldr aka hellip */ case 8230: AE("…"); break; /* … */ case 8240: AE("‰"); break; /* ‰ */ case 8241: AE("‱"); break; /* ‱ */ case 8242: AE("′"); break; /* ′ */ case 8243: AE("″"); break; /* ″ */ case 8244: AE("‴"); break; /* ‴ */ /* bprime aka backprime */ case 8245: AE("‵"); break; /* ‵ */ case 8249: AE("‹"); break; /* ‹ */ case 8250: AE("›"); break; /* › */ /* oline aka OverBar */ case 8254: AE("‾"); break; /* ‾ */ case 8257: AE("⁁"); break; /* ⁁ */ case 8259: AE("⁃"); break; /* ⁃ */ case 8260: AE("⁄"); break; /* ⁄ */ case 8271: AE("⁏"); break; /* ⁏ */ case 8279: AE("⁗"); break; /* ⁗ */ case 8287: TWOCPE; if (clen2 && uniChar2 == 8202) { AE("  "); MCP; /*    */ } else { AE(" "); /*   */ }; break; case 8288: AE("⁠"); break; /* ⁠ */ /* af aka ApplyFunction */ case 8289: AE("⁡"); break; /* ⁡ */ /* it aka InvisibleTimes */ case 8290: AE("⁢"); break; /* ⁢ */ /* ic aka InvisibleComma */ case 8291: AE("⁣"); break; /* ⁣ */ case 8364: AE("€"); break; /* € */ /* tdot aka TripleDot */ case 8411: AE("⃛"); break; /* ⃛ */ case 8412: AE("⃜"); break; /* ⃜ */ /* Copf aka complexes */ case 8450: AE("ℂ"); break; /* ℂ */ case 8453: AE("℅"); break; /* ℅ */ case 8458: AE("ℊ"); break; /* ℊ */ /* Hscr aka HilbertSpace or hamilt */ case 8459: AE("ℋ"); break; /* ℋ */ /* Hfr aka Poincareplane */ case 8460: AE("ℌ"); break; /* ℌ */ /* Hopf aka quaternions */ case 8461: AE("ℍ"); break; /* ℍ */ case 8462: AE("ℎ"); break; /* ℎ */ /* hbar aka hslash or planck or plankv */ case 8463: AE("ℏ"); break; /* ℏ */ /* Iscr aka imagline */ case 8464: AE("ℐ"); break; /* ℐ */ /* Im aka Ifr or image or imagpart */ case 8465: AE("ℑ"); break; /* ℑ */ /* Lscr aka Laplacetrf or lagran */ case 8466: AE("ℒ"); break; /* ℒ */ case 8467: AE("ℓ"); break; /* ℓ */ /* Nopf aka naturals */ case 8469: AE("ℕ"); break; /* ℕ */ case 8470: AE("№"); break; /* № */ case 8471: AE("℗"); break; /* ℗ */ /* wp aka weierp */ case 8472: AE("℘"); break; /* ℘ */ /* Popf aka primes */ case 8473: AE("ℙ"); break; /* ℙ */ /* Qopf aka rationals */ case 8474: AE("ℚ"); break; /* ℚ */ /* Rscr aka realine */ case 8475: AE("ℛ"); break; /* ℛ */ /* Re aka Rfr or real or realpart */ case 8476: AE("ℜ"); break; /* ℜ */ /* Ropf aka reals */ case 8477: AE("ℝ"); break; /* ℝ */ case 8478: AE("℞"); break; /* ℞ */ /* trade aka TRADE */ case 8482: AE("™"); break; /* ™ */ /* Zopf aka integers */ case 8484: AE("ℤ"); break; /* ℤ */ case 8487: AE("℧"); break; /* ℧ */ /* Zfr aka zeetrf */ case 8488: AE("ℨ"); break; /* ℨ */ case 8489: AE("℩"); break; /* ℩ */ /* Bscr aka Bernoullis or bernou */ case 8492: AE("ℬ"); break; /* ℬ */ /* Cfr aka Cayleys */ case 8493: AE("ℭ"); break; /* ℭ */ case 8495: AE("ℯ"); break; /* ℯ */ /* Escr aka expectation */ case 8496: AE("ℰ"); break; /* ℰ */ /* Fscr aka Fouriertrf */ case 8497: AE("ℱ"); break; /* ℱ */ /* Mscr aka Mellintrf or phmmat */ case 8499: AE("ℳ"); break; /* ℳ */ /* oscr aka order or orderof */ case 8500: AE("ℴ"); break; /* ℴ */ /* aleph aka alefsym */ case 8501: AE("ℵ"); break; /* ℵ */ case 8502: AE("ℶ"); break; /* ℶ */ case 8503: AE("ℷ"); break; /* ℷ */ case 8504: AE("ℸ"); break; /* ℸ */ /* DD aka CapitalDifferentialD */ case 8517: AE("ⅅ"); break; /* ⅅ */ /* dd aka DifferentialD */ case 8518: AE("ⅆ"); break; /* ⅆ */ /* ee aka ExponentialE or exponentiale */ case 8519: AE("ⅇ"); break; /* ⅇ */ /* ii aka ImaginaryI */ case 8520: AE("ⅈ"); break; /* ⅈ */ case 8531: AE("⅓"); break; /* ⅓ */ case 8532: AE("⅔"); break; /* ⅔ */ case 8533: AE("⅕"); break; /* ⅕ */ case 8534: AE("⅖"); break; /* ⅖ */ case 8535: AE("⅗"); break; /* ⅗ */ case 8536: AE("⅘"); break; /* ⅘ */ case 8537: AE("⅙"); break; /* ⅙ */ case 8538: AE("⅚"); break; /* ⅚ */ case 8539: AE("⅛"); break; /* ⅛ */ case 8540: AE("⅜"); break; /* ⅜ */ case 8541: AE("⅝"); break; /* ⅝ */ case 8542: AE("⅞"); break; /* ⅞ */ /* larr aka LeftArrow or ShortLeftArrow or leftarrow or slarr */ case 8592: AE("←"); break; /* ← */ /* uarr aka ShortUpArrow or UpArrow or uparrow */ case 8593: AE("↑"); break; /* ↑ */ /* rarr aka RightArrow or ShortRightArrow or rightarrow or srarr */ case 8594: AE("→"); break; /* → */ /* darr aka DownArrow or ShortDownArrow or downarrow */ case 8595: AE("↓"); break; /* ↓ */ /* harr aka LeftRightArrow or leftrightarrow */ case 8596: AE("↔"); break; /* ↔ */ /* varr aka UpDownArrow or updownarrow */ case 8597: AE("↕"); break; /* ↕ */ /* nwarr aka UpperLeftArrow or nwarrow */ case 8598: AE("↖"); break; /* ↖ */ /* nearr aka UpperRightArrow or nearrow */ case 8599: AE("↗"); break; /* ↗ */ /* searr aka LowerRightArrow or searrow */ case 8600: AE("↘"); break; /* ↘ */ /* swarr aka LowerLeftArrow or swarrow */ case 8601: AE("↙"); break; /* ↙ */ /* nlarr aka nleftarrow */ case 8602: AE("↚"); break; /* ↚ */ /* nrarr aka nrightarrow */ case 8603: AE("↛"); break; /* ↛ */ case 8605: TWOCPE; if (clen2 && uniChar2 == 824) { AE("↝̸"); MCP; /* ↝̸ */ } else { /* rarrw aka rightsquigarrow */ AE("↝"); /* ↝ */ }; break; /* Larr aka twoheadleftarrow */ case 8606: AE("↞"); break; /* ↞ */ case 8607: AE("↟"); break; /* ↟ */ /* Rarr aka twoheadrightarrow */ case 8608: AE("↠"); break; /* ↠ */ case 8609: AE("↡"); break; /* ↡ */ /* larrtl aka leftarrowtail */ case 8610: AE("↢"); break; /* ↢ */ /* rarrtl aka rightarrowtail */ case 8611: AE("↣"); break; /* ↣ */ /* mapstoleft aka LeftTeeArrow */ case 8612: AE("↤"); break; /* ↤ */ /* mapstoup aka UpTeeArrow */ case 8613: AE("↥"); break; /* ↥ */ /* map aka RightTeeArrow or mapsto */ case 8614: AE("↦"); break; /* ↦ */ /* mapstodown aka DownTeeArrow */ case 8615: AE("↧"); break; /* ↧ */ /* larrhk aka hookleftarrow */ case 8617: AE("↩"); break; /* ↩ */ /* rarrhk aka hookrightarrow */ case 8618: AE("↪"); break; /* ↪ */ /* larrlp aka looparrowleft */ case 8619: AE("↫"); break; /* ↫ */ /* rarrlp aka looparrowright */ case 8620: AE("↬"); break; /* ↬ */ /* harrw aka leftrightsquigarrow */ case 8621: AE("↭"); break; /* ↭ */ /* nharr aka nleftrightarrow */ case 8622: AE("↮"); break; /* ↮ */ /* lsh aka Lsh */ case 8624: AE("↰"); break; /* ↰ */ /* rsh aka Rsh */ case 8625: AE("↱"); break; /* ↱ */ case 8626: AE("↲"); break; /* ↲ */ case 8627: AE("↳"); break; /* ↳ */ case 8629: AE("↵"); break; /* ↵ */ /* cularr aka curvearrowleft */ case 8630: AE("↶"); break; /* ↶ */ /* curarr aka curvearrowright */ case 8631: AE("↷"); break; /* ↷ */ /* olarr aka circlearrowleft */ case 8634: AE("↺"); break; /* ↺ */ /* orarr aka circlearrowright */ case 8635: AE("↻"); break; /* ↻ */ /* lharu aka LeftVector or leftharpoonup */ case 8636: AE("↼"); break; /* ↼ */ /* lhard aka DownLeftVector or leftharpoondown */ case 8637: AE("↽"); break; /* ↽ */ /* uharr aka RightUpVector or upharpoonright */ case 8638: AE("↾"); break; /* ↾ */ /* uharl aka LeftUpVector or upharpoonleft */ case 8639: AE("↿"); break; /* ↿ */ /* rharu aka RightVector or rightharpoonup */ case 8640: AE("⇀"); break; /* ⇀ */ /* rhard aka DownRightVector or rightharpoondown */ case 8641: AE("⇁"); break; /* ⇁ */ /* dharr aka RightDownVector or downharpoonright */ case 8642: AE("⇂"); break; /* ⇂ */ /* dharl aka LeftDownVector or downharpoonleft */ case 8643: AE("⇃"); break; /* ⇃ */ /* rlarr aka RightArrowLeftArrow or rightleftarrows */ case 8644: AE("⇄"); break; /* ⇄ */ /* udarr aka UpArrowDownArrow */ case 8645: AE("⇅"); break; /* ⇅ */ /* lrarr aka LeftArrowRightArrow or leftrightarrows */ case 8646: AE("⇆"); break; /* ⇆ */ /* llarr aka leftleftarrows */ case 8647: AE("⇇"); break; /* ⇇ */ /* uuarr aka upuparrows */ case 8648: AE("⇈"); break; /* ⇈ */ /* rrarr aka rightrightarrows */ case 8649: AE("⇉"); break; /* ⇉ */ /* ddarr aka downdownarrows */ case 8650: AE("⇊"); break; /* ⇊ */ /* lrhar aka ReverseEquilibrium or leftrightharpoons */ case 8651: AE("⇋"); break; /* ⇋ */ /* rlhar aka Equilibrium or rightleftharpoons */ case 8652: AE("⇌"); break; /* ⇌ */ /* nlArr aka nLeftarrow */ case 8653: AE("⇍"); break; /* ⇍ */ /* nhArr aka nLeftrightarrow */ case 8654: AE("⇎"); break; /* ⇎ */ /* nrArr aka nRightarrow */ case 8655: AE("⇏"); break; /* ⇏ */ /* lArr aka DoubleLeftArrow or Leftarrow */ case 8656: AE("⇐"); break; /* ⇐ */ /* uArr aka DoubleUpArrow or Uparrow */ case 8657: AE("⇑"); break; /* ⇑ */ /* rArr aka DoubleRightArrow or Implies or Rightarrow */ case 8658: AE("⇒"); break; /* ⇒ */ /* dArr aka DoubleDownArrow or Downarrow */ case 8659: AE("⇓"); break; /* ⇓ */ /* iff aka DoubleLeftRightArrow or Leftrightarrow or hArr */ case 8660: AE("⇔"); break; /* ⇔ */ /* vArr aka DoubleUpDownArrow or Updownarrow */ case 8661: AE("⇕"); break; /* ⇕ */ case 8662: AE("⇖"); break; /* ⇖ */ case 8663: AE("⇗"); break; /* ⇗ */ case 8664: AE("⇘"); break; /* ⇘ */ case 8665: AE("⇙"); break; /* ⇙ */ /* lAarr aka Lleftarrow */ case 8666: AE("⇚"); break; /* ⇚ */ /* rAarr aka Rrightarrow */ case 8667: AE("⇛"); break; /* ⇛ */ case 8669: AE("⇝"); break; /* ⇝ */ /* larrb aka LeftArrowBar */ case 8676: AE("⇤"); break; /* ⇤ */ /* rarrb aka RightArrowBar */ case 8677: AE("⇥"); break; /* ⇥ */ /* duarr aka DownArrowUpArrow */ case 8693: AE("⇵"); break; /* ⇵ */ case 8701: AE("⇽"); break; /* ⇽ */ case 8702: AE("⇾"); break; /* ⇾ */ case 8703: AE("⇿"); break; /* ⇿ */ /* forall aka ForAll */ case 8704: AE("∀"); break; /* ∀ */ /* comp aka complement */ case 8705: AE("∁"); break; /* ∁ */ case 8706: TWOCPE; if (clen2 && uniChar2 == 824) { AE("∂̸"); MCP; /* ∂̸ */ } else { /* part aka PartialD */ AE("∂"); /* ∂ */ }; break; /* exist aka Exists */ case 8707: AE("∃"); break; /* ∃ */ /* nexist aka NotExists or nexists */ case 8708: AE("∄"); break; /* ∄ */ /* empty aka emptyset or emptyv or varnothing */ case 8709: AE("∅"); break; /* ∅ */ /* Del aka nabla */ case 8711: AE("∇"); break; /* ∇ */ /* in aka Element or isin or isinv */ case 8712: AE("∈"); break; /* ∈ */ /* notin aka NotElement or notinva */ case 8713: AE("∉"); break; /* ∉ */ /* ni aka ReverseElement or SuchThat or niv */ case 8715: AE("∋"); break; /* ∋ */ /* notni aka NotReverseElement or notniva */ case 8716: AE("∌"); break; /* ∌ */ /* prod aka Product */ case 8719: AE("∏"); break; /* ∏ */ /* coprod aka Coproduct */ case 8720: AE("∐"); break; /* ∐ */ /* sum aka Sum */ case 8721: AE("∑"); break; /* ∑ */ case 8722: AE("−"); break; /* − */ /* mp aka MinusPlus or mnplus */ case 8723: AE("∓"); break; /* ∓ */ /* plusdo aka dotplus */ case 8724: AE("∔"); break; /* ∔ */ /* setmn aka Backslash or setminus or smallsetminus or ssetmn */ case 8726: AE("∖"); break; /* ∖ */ case 8727: AE("∗"); break; /* ∗ */ /* compfn aka SmallCircle */ case 8728: AE("∘"); break; /* ∘ */ /* Sqrt aka radic */ case 8730: AE("√"); break; /* √ */ /* prop aka Proportional or propto or varpropto or vprop */ case 8733: AE("∝"); break; /* ∝ */ case 8734: AE("∞"); break; /* ∞ */ case 8735: AE("∟"); break; /* ∟ */ case 8736: TWOCPE; if (clen2 && uniChar2 == 8402) { AE("∠⃒"); MCP; /* ∠⃒ */ } else { /* ang aka angle */ AE("∠"); /* ∠ */ }; break; /* angmsd aka measuredangle */ case 8737: AE("∡"); break; /* ∡ */ case 8738: AE("∢"); break; /* ∢ */ /* mid aka VerticalBar or shortmid or smid */ case 8739: AE("∣"); break; /* ∣ */ /* nmid aka NotVerticalBar or nshortmid or nsmid */ case 8740: AE("∤"); break; /* ∤ */ /* par aka DoubleVerticalBar or parallel or shortparallel or spar */ case 8741: AE("∥"); break; /* ∥ */ /* npar aka NotDoubleVerticalBar or nparallel or nshortparallel or nspar */ case 8742: AE("∦"); break; /* ∦ */ /* and aka wedge */ case 8743: AE("∧"); break; /* ∧ */ /* or aka vee */ case 8744: AE("∨"); break; /* ∨ */ case 8745: TWOCPE; if (clen2 && uniChar2 == 65024) { AE("∩︀"); MCP; /* ∩︀ */ } else { AE("∩"); /* ∩ */ }; break; case 8746: TWOCPE; if (clen2 && uniChar2 == 65024) { AE("∪︀"); MCP; /* ∪︀ */ } else { AE("∪"); /* ∪ */ }; break; /* int aka Integral */ case 8747: AE("∫"); break; /* ∫ */ case 8748: AE("∬"); break; /* ∬ */ /* tint aka iiint */ case 8749: AE("∭"); break; /* ∭ */ /* oint aka ContourIntegral or conint */ case 8750: AE("∮"); break; /* ∮ */ /* Conint aka DoubleContourIntegral */ case 8751: AE("∯"); break; /* ∯ */ case 8752: AE("∰"); break; /* ∰ */ case 8753: AE("∱"); break; /* ∱ */ /* cwconint aka ClockwiseContourIntegral */ case 8754: AE("∲"); break; /* ∲ */ /* awconint aka CounterClockwiseContourIntegral */ case 8755: AE("∳"); break; /* ∳ */ /* there4 aka Therefore or therefore */ case 8756: AE("∴"); break; /* ∴ */ /* becaus aka Because or because */ case 8757: AE("∵"); break; /* ∵ */ case 8758: AE("∶"); break; /* ∶ */ /* Colon aka Proportion */ case 8759: AE("∷"); break; /* ∷ */ /* minusd aka dotminus */ case 8760: AE("∸"); break; /* ∸ */ case 8762: AE("∺"); break; /* ∺ */ case 8763: AE("∻"); break; /* ∻ */ case 8764: TWOCPE; if (clen2 && uniChar2 == 8402) { AE("∼⃒"); MCP; /* ∼⃒ */ } else { /* sim aka Tilde or thicksim or thksim */ AE("∼"); /* ∼ */ }; break; case 8765: TWOCPE; if (clen2 && uniChar2 == 817) { AE("∽̱"); MCP; /* ∽̱ */ } else { /* bsim aka backsim */ AE("∽"); /* ∽ */ }; break; case 8766: TWOCPE; if (clen2 && uniChar2 == 819) { AE("∾̳"); MCP; /* ∾̳ */ } else { /* ac aka mstpos */ AE("∾"); /* ∾ */ }; break; case 8767: AE("∿"); break; /* ∿ */ /* wr aka VerticalTilde or wreath */ case 8768: AE("≀"); break; /* ≀ */ /* nsim aka NotTilde */ case 8769: AE("≁"); break; /* ≁ */ case 8770: TWOCPE; if (clen2 && uniChar2 == 824) { /* esim aka NotEqualTilde */ AE("≂̸"); MCP; /* ≂̸ */ } else { /* esim aka EqualTilde or eqsim */ AE("≂"); /* ≂ */ }; break; /* sime aka TildeEqual or simeq */ case 8771: AE("≃"); break; /* ≃ */ /* nsime aka NotTildeEqual or nsimeq */ case 8772: AE("≄"); break; /* ≄ */ /* cong aka TildeFullEqual */ case 8773: AE("≅"); break; /* ≅ */ case 8774: AE("≆"); break; /* ≆ */ /* ncong aka NotTildeFullEqual */ case 8775: AE("≇"); break; /* ≇ */ /* ap aka TildeTilde or approx or asymp or thickapprox or thkap */ case 8776: AE("≈"); break; /* ≈ */ /* nap aka NotTildeTilde or napprox */ case 8777: AE("≉"); break; /* ≉ */ /* ape aka approxeq */ case 8778: AE("≊"); break; /* ≊ */ case 8779: TWOCPE; if (clen2 && uniChar2 == 824) { AE("≋̸"); MCP; /* ≋̸ */ } else { AE("≋"); /* ≋ */ }; break; /* bcong aka backcong */ case 8780: AE("≌"); break; /* ≌ */ case 8781: TWOCPE; if (clen2 && uniChar2 == 8402) { AE("≍⃒"); MCP; /* ≍⃒ */ } else { /* CupCap aka asympeq */ AE("≍"); /* ≍ */ }; break; case 8782: TWOCPE; if (clen2 && uniChar2 == 824) { /* bump aka NotHumpDownHump */ AE("≎̸"); MCP; /* ≎̸ */ } else { /* bump aka Bumpeq or HumpDownHump */ AE("≎"); /* ≎ */ }; break; case 8783: TWOCPE; if (clen2 && uniChar2 == 824) { /* bumpe aka NotHumpEqual */ AE("≏̸"); MCP; /* ≏̸ */ } else { /* bumpe aka HumpEqual or bumpeq */ AE("≏"); /* ≏ */ }; break; case 8784: TWOCPE; if (clen2 && uniChar2 == 824) { AE("≐̸"); MCP; /* ≐̸ */ } else { /* doteq aka DotEqual or esdot */ AE("≐"); /* ≐ */ }; break; /* eDot aka doteqdot */ case 8785: AE("≑"); break; /* ≑ */ /* efDot aka fallingdotseq */ case 8786: AE("≒"); break; /* ≒ */ /* erDot aka risingdotseq */ case 8787: AE("≓"); break; /* ≓ */ /* Assign aka colone or coloneq */ case 8788: AE("≔"); break; /* ≔ */ /* ecolon aka eqcolon */ case 8789: AE("≕"); break; /* ≕ */ /* ecir aka eqcirc */ case 8790: AE("≖"); break; /* ≖ */ /* cire aka circeq */ case 8791: AE("≗"); break; /* ≗ */ case 8793: AE("≙"); break; /* ≙ */ case 8794: AE("≚"); break; /* ≚ */ /* trie aka triangleq */ case 8796: AE("≜"); break; /* ≜ */ /* equest aka questeq */ case 8799: AE("≟"); break; /* ≟ */ /* ne aka NotEqual */ case 8800: AE("≠"); break; /* ≠ */ case 8801: TWOCPE; if (clen2 && uniChar2 == 8421) { AE("≡⃥"); MCP; /* ≡⃥ */ } else { /* equiv aka Congruent */ AE("≡"); /* ≡ */ }; break; /* nequiv aka NotCongruent */ case 8802: AE("≢"); break; /* ≢ */ case 8804: TWOCPE; if (clen2 && uniChar2 == 8402) { AE("≤⃒"); MCP; /* ≤⃒ */ } else { /* le aka leq */ AE("≤"); /* ≤ */ }; break; case 8805: TWOCPE; if (clen2 && uniChar2 == 8402) { AE("≥⃒"); MCP; /* ≥⃒ */ } else { /* ge aka GreaterEqual or geq */ AE("≥"); /* ≥ */ }; break; case 8806: TWOCPE; if (clen2 && uniChar2 == 824) { /* lE aka nleqq */ AE("≦̸"); MCP; /* ≦̸ */ } else { /* lE aka LessFullEqual or leqq */ AE("≦"); /* ≦ */ }; break; case 8807: TWOCPE; if (clen2 && uniChar2 == 824) { /* gE aka NotGreaterFullEqual or ngeqq */ AE("≧̸"); MCP; /* ≧̸ */ } else { /* gE aka GreaterFullEqual or geqq */ AE("≧"); /* ≧ */ }; break; case 8808: TWOCPE; if (clen2 && uniChar2 == 65024) { /* lnE aka lvertneqq */ AE("≨︀"); MCP; /* ≨︀ */ } else { /* lnE aka lneqq */ AE("≨"); /* ≨ */ }; break; case 8809: TWOCPE; if (clen2 && uniChar2 == 65024) { /* gnE aka gvertneqq */ AE("≩︀"); MCP; /* ≩︀ */ } else { /* gnE aka gneqq */ AE("≩"); /* ≩ */ }; break; case 8810: TWOCPE; if (clen2 && uniChar2 == 824) { /* nLtv aka NotLessLess */ AE("≪̸"); MCP; /* ≪̸ */ } else if (clen2 && uniChar2 == 8402) { AE("≪⃒"); MCP; /* ≪⃒ */ } else { /* ll aka Lt or NestedLessLess */ AE("≪"); /* ≪ */ }; break; case 8811: TWOCPE; if (clen2 && uniChar2 == 824) { /* nGtv aka NotGreaterGreater */ AE("≫̸"); MCP; /* ≫̸ */ } else if (clen2 && uniChar2 == 8402) { AE("≫⃒"); MCP; /* ≫⃒ */ } else { /* gg aka Gt or NestedGreaterGreater */ AE("≫"); /* ≫ */ }; break; /* twixt aka between */ case 8812: AE("≬"); break; /* ≬ */ case 8813: AE("≭"); break; /* ≭ */ /* nlt aka NotLess or nless */ case 8814: AE("≮"); break; /* ≮ */ /* ngt aka NotGreater or ngtr */ case 8815: AE("≯"); break; /* ≯ */ /* nle aka NotLessEqual or nleq */ case 8816: AE("≰"); break; /* ≰ */ /* nge aka NotGreaterEqual or ngeq */ case 8817: AE("≱"); break; /* ≱ */ /* lsim aka LessTilde or lesssim */ case 8818: AE("≲"); break; /* ≲ */ /* gsim aka GreaterTilde or gtrsim */ case 8819: AE("≳"); break; /* ≳ */ /* nlsim aka NotLessTilde */ case 8820: AE("≴"); break; /* ≴ */ /* ngsim aka NotGreaterTilde */ case 8821: AE("≵"); break; /* ≵ */ /* lg aka LessGreater or lessgtr */ case 8822: AE("≶"); break; /* ≶ */ /* gl aka GreaterLess or gtrless */ case 8823: AE("≷"); break; /* ≷ */ /* ntlg aka NotLessGreater */ case 8824: AE("≸"); break; /* ≸ */ /* ntgl aka NotGreaterLess */ case 8825: AE("≹"); break; /* ≹ */ /* pr aka Precedes or prec */ case 8826: AE("≺"); break; /* ≺ */ /* sc aka Succeeds or succ */ case 8827: AE("≻"); break; /* ≻ */ /* prcue aka PrecedesSlantEqual or preccurlyeq */ case 8828: AE("≼"); break; /* ≼ */ /* sccue aka SucceedsSlantEqual or succcurlyeq */ case 8829: AE("≽"); break; /* ≽ */ /* prsim aka PrecedesTilde or precsim */ case 8830: AE("≾"); break; /* ≾ */ case 8831: TWOCPE; if (clen2 && uniChar2 == 824) { AE("≿̸"); MCP; /* ≿̸ */ } else { /* scsim aka SucceedsTilde or succsim */ AE("≿"); /* ≿ */ }; break; /* npr aka NotPrecedes or nprec */ case 8832: AE("⊀"); break; /* ⊀ */ /* nsc aka NotSucceeds or nsucc */ case 8833: AE("⊁"); break; /* ⊁ */ case 8834: TWOCPE; if (clen2 && uniChar2 == 8402) { /* sub aka NotSubset or nsubset */ AE("⊂⃒"); MCP; /* ⊂⃒ */ } else { /* sub aka subset */ AE("⊂"); /* ⊂ */ }; break; case 8835: TWOCPE; if (clen2 && uniChar2 == 8402) { /* sup aka NotSuperset or nsupset */ AE("⊃⃒"); MCP; /* ⊃⃒ */ } else { /* sup aka Superset or supset */ AE("⊃"); /* ⊃ */ }; break; case 8836: AE("⊄"); break; /* ⊄ */ case 8837: AE("⊅"); break; /* ⊅ */ /* sube aka SubsetEqual or subseteq */ case 8838: AE("⊆"); break; /* ⊆ */ /* supe aka SupersetEqual or supseteq */ case 8839: AE("⊇"); break; /* ⊇ */ /* nsube aka NotSubsetEqual or nsubseteq */ case 8840: AE("⊈"); break; /* ⊈ */ /* nsupe aka NotSupersetEqual or nsupseteq */ case 8841: AE("⊉"); break; /* ⊉ */ case 8842: TWOCPE; if (clen2 && uniChar2 == 65024) { /* subne aka varsubsetneq */ AE("⊊︀"); MCP; /* ⊊︀ */ } else { /* subne aka subsetneq */ AE("⊊"); /* ⊊ */ }; break; case 8843: TWOCPE; if (clen2 && uniChar2 == 65024) { /* supne aka varsupsetneq */ AE("⊋︀"); MCP; /* ⊋︀ */ } else { /* supne aka supsetneq */ AE("⊋"); /* ⊋ */ }; break; case 8845: AE("⊍"); break; /* ⊍ */ /* uplus aka UnionPlus */ case 8846: AE("⊎"); break; /* ⊎ */ case 8847: TWOCPE; if (clen2 && uniChar2 == 824) { AE("⊏̸"); MCP; /* ⊏̸ */ } else { /* sqsub aka SquareSubset or sqsubset */ AE("⊏"); /* ⊏ */ }; break; case 8848: TWOCPE; if (clen2 && uniChar2 == 824) { AE("⊐̸"); MCP; /* ⊐̸ */ } else { /* sqsup aka SquareSuperset or sqsupset */ AE("⊐"); /* ⊐ */ }; break; /* sqsube aka SquareSubsetEqual or sqsubseteq */ case 8849: AE("⊑"); break; /* ⊑ */ /* sqsupe aka SquareSupersetEqual or sqsupseteq */ case 8850: AE("⊒"); break; /* ⊒ */ case 8851: TWOCPE; if (clen2 && uniChar2 == 65024) { AE("⊓︀"); MCP; /* ⊓︀ */ } else { /* sqcap aka SquareIntersection */ AE("⊓"); /* ⊓ */ }; break; case 8852: TWOCPE; if (clen2 && uniChar2 == 65024) { AE("⊔︀"); MCP; /* ⊔︀ */ } else { /* sqcup aka SquareUnion */ AE("⊔"); /* ⊔ */ }; break; /* oplus aka CirclePlus */ case 8853: AE("⊕"); break; /* ⊕ */ /* ominus aka CircleMinus */ case 8854: AE("⊖"); break; /* ⊖ */ /* otimes aka CircleTimes */ case 8855: AE("⊗"); break; /* ⊗ */ case 8856: AE("⊘"); break; /* ⊘ */ /* odot aka CircleDot */ case 8857: AE("⊙"); break; /* ⊙ */ /* ocir aka circledcirc */ case 8858: AE("⊚"); break; /* ⊚ */ /* oast aka circledast */ case 8859: AE("⊛"); break; /* ⊛ */ /* odash aka circleddash */ case 8861: AE("⊝"); break; /* ⊝ */ /* plusb aka boxplus */ case 8862: AE("⊞"); break; /* ⊞ */ /* minusb aka boxminus */ case 8863: AE("⊟"); break; /* ⊟ */ /* timesb aka boxtimes */ case 8864: AE("⊠"); break; /* ⊠ */ /* sdotb aka dotsquare */ case 8865: AE("⊡"); break; /* ⊡ */ /* vdash aka RightTee */ case 8866: AE("⊢"); break; /* ⊢ */ /* dashv aka LeftTee */ case 8867: AE("⊣"); break; /* ⊣ */ /* top aka DownTee */ case 8868: AE("⊤"); break; /* ⊤ */ /* bot aka UpTee or bottom or perp */ case 8869: AE("⊥"); break; /* ⊥ */ case 8871: AE("⊧"); break; /* ⊧ */ /* vDash aka DoubleRightTee */ case 8872: AE("⊨"); break; /* ⊨ */ case 8873: AE("⊩"); break; /* ⊩ */ case 8874: AE("⊪"); break; /* ⊪ */ case 8875: AE("⊫"); break; /* ⊫ */ case 8876: AE("⊬"); break; /* ⊬ */ case 8877: AE("⊭"); break; /* ⊭ */ case 8878: AE("⊮"); break; /* ⊮ */ case 8879: AE("⊯"); break; /* ⊯ */ case 8880: AE("⊰"); break; /* ⊰ */ /* vltri aka LeftTriangle or vartriangleleft */ case 8882: AE("⊲"); break; /* ⊲ */ /* vrtri aka RightTriangle or vartriangleright */ case 8883: AE("⊳"); break; /* ⊳ */ case 8884: TWOCPE; if (clen2 && uniChar2 == 8402) { AE("⊴⃒"); MCP; /* ⊴⃒ */ } else { /* ltrie aka LeftTriangleEqual or trianglelefteq */ AE("⊴"); /* ⊴ */ }; break; case 8885: TWOCPE; if (clen2 && uniChar2 == 8402) { AE("⊵⃒"); MCP; /* ⊵⃒ */ } else { /* rtrie aka RightTriangleEqual or trianglerighteq */ AE("⊵"); /* ⊵ */ }; break; case 8886: AE("⊶"); break; /* ⊶ */ case 8887: AE("⊷"); break; /* ⊷ */ /* mumap aka multimap */ case 8888: AE("⊸"); break; /* ⊸ */ case 8889: AE("⊹"); break; /* ⊹ */ /* intcal aka intercal */ case 8890: AE("⊺"); break; /* ⊺ */ case 8891: AE("⊻"); break; /* ⊻ */ case 8893: AE("⊽"); break; /* ⊽ */ case 8894: AE("⊾"); break; /* ⊾ */ case 8895: AE("⊿"); break; /* ⊿ */ /* Wedge aka bigwedge or xwedge */ case 8896: AE("⋀"); break; /* ⋀ */ /* Vee aka bigvee or xvee */ case 8897: AE("⋁"); break; /* ⋁ */ /* xcap aka Intersection or bigcap */ case 8898: AE("⋂"); break; /* ⋂ */ /* xcup aka Union or bigcup */ case 8899: AE("⋃"); break; /* ⋃ */ /* diam aka Diamond or diamond */ case 8900: AE("⋄"); break; /* ⋄ */ case 8901: AE("⋅"); break; /* ⋅ */ /* Star aka sstarf */ case 8902: AE("⋆"); break; /* ⋆ */ /* divonx aka divideontimes */ case 8903: AE("⋇"); break; /* ⋇ */ case 8904: AE("⋈"); break; /* ⋈ */ case 8905: AE("⋉"); break; /* ⋉ */ case 8906: AE("⋊"); break; /* ⋊ */ /* lthree aka leftthreetimes */ case 8907: AE("⋋"); break; /* ⋋ */ /* rthree aka rightthreetimes */ case 8908: AE("⋌"); break; /* ⋌ */ /* bsime aka backsimeq */ case 8909: AE("⋍"); break; /* ⋍ */ /* cuvee aka curlyvee */ case 8910: AE("⋎"); break; /* ⋎ */ /* cuwed aka curlywedge */ case 8911: AE("⋏"); break; /* ⋏ */ /* Sub aka Subset */ case 8912: AE("⋐"); break; /* ⋐ */ /* Sup aka Supset */ case 8913: AE("⋑"); break; /* ⋑ */ case 8914: AE("⋒"); break; /* ⋒ */ case 8915: AE("⋓"); break; /* ⋓ */ /* fork aka pitchfork */ case 8916: AE("⋔"); break; /* ⋔ */ case 8917: AE("⋕"); break; /* ⋕ */ /* ltdot aka lessdot */ case 8918: AE("⋖"); break; /* ⋖ */ /* gtdot aka gtrdot */ case 8919: AE("⋗"); break; /* ⋗ */ case 8920: TWOCPE; if (clen2 && uniChar2 == 824) { AE("⋘̸"); MCP; /* ⋘̸ */ } else { AE("⋘"); /* ⋘ */ }; break; case 8921: TWOCPE; if (clen2 && uniChar2 == 824) { AE("⋙̸"); MCP; /* ⋙̸ */ } else { /* Gg aka ggg */ AE("⋙"); /* ⋙ */ }; break; case 8922: TWOCPE; if (clen2 && uniChar2 == 65024) { AE("⋚︀"); MCP; /* ⋚︀ */ } else { /* leg aka LessEqualGreater or lesseqgtr */ AE("⋚"); /* ⋚ */ }; break; case 8923: TWOCPE; if (clen2 && uniChar2 == 65024) { AE("⋛︀"); MCP; /* ⋛︀ */ } else { /* gel aka GreaterEqualLess or gtreqless */ AE("⋛"); /* ⋛ */ }; break; /* cuepr aka curlyeqprec */ case 8926: AE("⋞"); break; /* ⋞ */ /* cuesc aka curlyeqsucc */ case 8927: AE("⋟"); break; /* ⋟ */ /* nprcue aka NotPrecedesSlantEqual */ case 8928: AE("⋠"); break; /* ⋠ */ /* nsccue aka NotSucceedsSlantEqual */ case 8929: AE("⋡"); break; /* ⋡ */ /* nsqsube aka NotSquareSubsetEqual */ case 8930: AE("⋢"); break; /* ⋢ */ /* nsqsupe aka NotSquareSupersetEqual */ case 8931: AE("⋣"); break; /* ⋣ */ case 8934: AE("⋦"); break; /* ⋦ */ case 8935: AE("⋧"); break; /* ⋧ */ /* prnsim aka precnsim */ case 8936: AE("⋨"); break; /* ⋨ */ /* scnsim aka succnsim */ case 8937: AE("⋩"); break; /* ⋩ */ /* nltri aka NotLeftTriangle or ntriangleleft */ case 8938: AE("⋪"); break; /* ⋪ */ /* nrtri aka NotRightTriangle or ntriangleright */ case 8939: AE("⋫"); break; /* ⋫ */ /* nltrie aka NotLeftTriangleEqual or ntrianglelefteq */ case 8940: AE("⋬"); break; /* ⋬ */ /* nrtrie aka NotRightTriangleEqual or ntrianglerighteq */ case 8941: AE("⋭"); break; /* ⋭ */ case 8942: AE("⋮"); break; /* ⋮ */ case 8943: AE("⋯"); break; /* ⋯ */ case 8944: AE("⋰"); break; /* ⋰ */ case 8945: AE("⋱"); break; /* ⋱ */ case 8946: AE("⋲"); break; /* ⋲ */ case 8947: AE("⋳"); break; /* ⋳ */ case 8948: AE("⋴"); break; /* ⋴ */ case 8949: TWOCPE; if (clen2 && uniChar2 == 824) { AE("⋵̸"); MCP; /* ⋵̸ */ } else { AE("⋵"); /* ⋵ */ }; break; case 8950: AE("⋶"); break; /* ⋶ */ case 8951: AE("⋷"); break; /* ⋷ */ case 8953: TWOCPE; if (clen2 && uniChar2 == 824) { AE("⋹̸"); MCP; /* ⋹̸ */ } else { AE("⋹"); /* ⋹ */ }; break; case 8954: AE("⋺"); break; /* ⋺ */ case 8955: AE("⋻"); break; /* ⋻ */ case 8956: AE("⋼"); break; /* ⋼ */ case 8957: AE("⋽"); break; /* ⋽ */ case 8958: AE("⋾"); break; /* ⋾ */ /* barwed aka barwedge */ case 8965: AE("⌅"); break; /* ⌅ */ /* Barwed aka doublebarwedge */ case 8966: AE("⌆"); break; /* ⌆ */ /* lceil aka LeftCeiling */ case 8968: AE("⌈"); break; /* ⌈ */ /* rceil aka RightCeiling */ case 8969: AE("⌉"); break; /* ⌉ */ /* lfloor aka LeftFloor */ case 8970: AE("⌊"); break; /* ⌊ */ /* rfloor aka RightFloor */ case 8971: AE("⌋"); break; /* ⌋ */ case 8972: AE("⌌"); break; /* ⌌ */ case 8973: AE("⌍"); break; /* ⌍ */ case 8974: AE("⌎"); break; /* ⌎ */ case 8975: AE("⌏"); break; /* ⌏ */ case 8976: AE("⌐"); break; /* ⌐ */ case 8978: AE("⌒"); break; /* ⌒ */ case 8979: AE("⌓"); break; /* ⌓ */ case 8981: AE("⌕"); break; /* ⌕ */ case 8982: AE("⌖"); break; /* ⌖ */ /* ulcorn aka ulcorner */ case 8988: AE("⌜"); break; /* ⌜ */ /* urcorn aka urcorner */ case 8989: AE("⌝"); break; /* ⌝ */ /* dlcorn aka llcorner */ case 8990: AE("⌞"); break; /* ⌞ */ /* drcorn aka lrcorner */ case 8991: AE("⌟"); break; /* ⌟ */ /* frown aka sfrown */ case 8994: AE("⌢"); break; /* ⌢ */ /* smile aka ssmile */ case 8995: AE("⌣"); break; /* ⌣ */ case 9005: AE("⌭"); break; /* ⌭ */ case 9006: AE("⌮"); break; /* ⌮ */ case 9014: AE("⌶"); break; /* ⌶ */ case 9021: AE("⌽"); break; /* ⌽ */ case 9023: AE("⌿"); break; /* ⌿ */ case 9084: AE("⍼"); break; /* ⍼ */ /* lmoust aka lmoustache */ case 9136: AE("⎰"); break; /* ⎰ */ /* rmoust aka rmoustache */ case 9137: AE("⎱"); break; /* ⎱ */ /* tbrk aka OverBracket */ case 9140: AE("⎴"); break; /* ⎴ */ /* bbrk aka UnderBracket */ case 9141: AE("⎵"); break; /* ⎵ */ case 9142: AE("⎶"); break; /* ⎶ */ case 9180: AE("⏜"); break; /* ⏜ */ case 9181: AE("⏝"); break; /* ⏝ */ case 9182: AE("⏞"); break; /* ⏞ */ case 9183: AE("⏟"); break; /* ⏟ */ case 9186: AE("⏢"); break; /* ⏢ */ case 9191: AE("⏧"); break; /* ⏧ */ case 9251: AE("␣"); break; /* ␣ */ /* oS aka circledS */ case 9416: AE("Ⓢ"); break; /* Ⓢ */ /* boxh aka HorizontalLine */ case 9472: AE("─"); break; /* ─ */ case 9474: AE("│"); break; /* │ */ case 9484: AE("┌"); break; /* ┌ */ case 9488: AE("┐"); break; /* ┐ */ case 9492: AE("└"); break; /* └ */ case 9496: AE("┘"); break; /* ┘ */ case 9500: AE("├"); break; /* ├ */ case 9508: AE("┤"); break; /* ┤ */ case 9516: AE("┬"); break; /* ┬ */ case 9524: AE("┴"); break; /* ┴ */ case 9532: AE("┼"); break; /* ┼ */ case 9552: AE("═"); break; /* ═ */ case 9553: AE("║"); break; /* ║ */ case 9554: AE("╒"); break; /* ╒ */ case 9555: AE("╓"); break; /* ╓ */ case 9556: AE("╔"); break; /* ╔ */ case 9557: AE("╕"); break; /* ╕ */ case 9558: AE("╖"); break; /* ╖ */ case 9559: AE("╗"); break; /* ╗ */ case 9560: AE("╘"); break; /* ╘ */ case 9561: AE("╙"); break; /* ╙ */ case 9562: AE("╚"); break; /* ╚ */ case 9563: AE("╛"); break; /* ╛ */ case 9564: AE("╜"); break; /* ╜ */ case 9565: AE("╝"); break; /* ╝ */ case 9566: AE("╞"); break; /* ╞ */ case 9567: AE("╟"); break; /* ╟ */ case 9568: AE("╠"); break; /* ╠ */ case 9569: AE("╡"); break; /* ╡ */ case 9570: AE("╢"); break; /* ╢ */ case 9571: AE("╣"); break; /* ╣ */ case 9572: AE("╤"); break; /* ╤ */ case 9573: AE("╥"); break; /* ╥ */ case 9574: AE("╦"); break; /* ╦ */ case 9575: AE("╧"); break; /* ╧ */ case 9576: AE("╨"); break; /* ╨ */ case 9577: AE("╩"); break; /* ╩ */ case 9578: AE("╪"); break; /* ╪ */ case 9579: AE("╫"); break; /* ╫ */ case 9580: AE("╬"); break; /* ╬ */ case 9600: AE("▀"); break; /* ▀ */ case 9604: AE("▄"); break; /* ▄ */ case 9608: AE("█"); break; /* █ */ case 9617: AE("░"); break; /* ░ */ case 9618: AE("▒"); break; /* ▒ */ case 9619: AE("▓"); break; /* ▓ */ /* squ aka Square or square */ case 9633: AE("□"); break; /* □ */ /* squf aka FilledVerySmallSquare or blacksquare or squarf */ case 9642: AE("▪"); break; /* ▪ */ case 9643: AE("▫"); break; /* ▫ */ case 9645: AE("▭"); break; /* ▭ */ case 9646: AE("▮"); break; /* ▮ */ case 9649: AE("▱"); break; /* ▱ */ /* xutri aka bigtriangleup */ case 9651: AE("△"); break; /* △ */ /* utrif aka blacktriangle */ case 9652: AE("▴"); break; /* ▴ */ /* utri aka triangle */ case 9653: AE("▵"); break; /* ▵ */ /* rtrif aka blacktriangleright */ case 9656: AE("▸"); break; /* ▸ */ /* rtri aka triangleright */ case 9657: AE("▹"); break; /* ▹ */ /* xdtri aka bigtriangledown */ case 9661: AE("▽"); break; /* ▽ */ /* dtrif aka blacktriangledown */ case 9662: AE("▾"); break; /* ▾ */ /* dtri aka triangledown */ case 9663: AE("▿"); break; /* ▿ */ /* ltrif aka blacktriangleleft */ case 9666: AE("◂"); break; /* ◂ */ /* ltri aka triangleleft */ case 9667: AE("◃"); break; /* ◃ */ /* loz aka lozenge */ case 9674: AE("◊"); break; /* ◊ */ case 9675: AE("○"); break; /* ○ */ case 9708: AE("◬"); break; /* ◬ */ /* xcirc aka bigcirc */ case 9711: AE("◯"); break; /* ◯ */ case 9720: AE("◸"); break; /* ◸ */ case 9721: AE("◹"); break; /* ◹ */ case 9722: AE("◺"); break; /* ◺ */ case 9723: AE("◻"); break; /* ◻ */ case 9724: AE("◼"); break; /* ◼ */ /* starf aka bigstar */ case 9733: AE("★"); break; /* ★ */ case 9734: AE("☆"); break; /* ☆ */ case 9742: AE("☎"); break; /* ☎ */ case 9792: AE("♀"); break; /* ♀ */ case 9794: AE("♂"); break; /* ♂ */ /* spades aka spadesuit */ case 9824: AE("♠"); break; /* ♠ */ /* clubs aka clubsuit */ case 9827: AE("♣"); break; /* ♣ */ /* hearts aka heartsuit */ case 9829: AE("♥"); break; /* ♥ */ /* diams aka diamondsuit */ case 9830: AE("♦"); break; /* ♦ */ case 9834: AE("♪"); break; /* ♪ */ case 9837: AE("♭"); break; /* ♭ */ /* natur aka natural */ case 9838: AE("♮"); break; /* ♮ */ case 9839: AE("♯"); break; /* ♯ */ /* check aka checkmark */ case 10003: AE("✓"); break; /* ✓ */ case 10007: AE("✗"); break; /* ✗ */ /* malt aka maltese */ case 10016: AE("✠"); break; /* ✠ */ case 10038: AE("✶"); break; /* ✶ */ case 10072: AE("❘"); break; /* ❘ */ case 10098: AE("❲"); break; /* ❲ */ case 10099: AE("❳"); break; /* ❳ */ case 10184: AE("⟈"); break; /* ⟈ */ case 10185: AE("⟉"); break; /* ⟉ */ /* lobrk aka LeftDoubleBracket */ case 10214: AE("⟦"); break; /* ⟦ */ /* robrk aka RightDoubleBracket */ case 10215: AE("⟧"); break; /* ⟧ */ /* lang aka LeftAngleBracket or langle */ case 10216: AE("⟨"); break; /* ⟨ */ /* rang aka RightAngleBracket or rangle */ case 10217: AE("⟩"); break; /* ⟩ */ case 10218: AE("⟪"); break; /* ⟪ */ case 10219: AE("⟫"); break; /* ⟫ */ case 10220: AE("⟬"); break; /* ⟬ */ case 10221: AE("⟭"); break; /* ⟭ */ /* xlarr aka LongLeftArrow or longleftarrow */ case 10229: AE("⟵"); break; /* ⟵ */ /* xrarr aka LongRightArrow or longrightarrow */ case 10230: AE("⟶"); break; /* ⟶ */ /* xharr aka LongLeftRightArrow or longleftrightarrow */ case 10231: AE("⟷"); break; /* ⟷ */ /* xlArr aka DoubleLongLeftArrow or Longleftarrow */ case 10232: AE("⟸"); break; /* ⟸ */ /* xrArr aka DoubleLongRightArrow or Longrightarrow */ case 10233: AE("⟹"); break; /* ⟹ */ /* xhArr aka DoubleLongLeftRightArrow or Longleftrightarrow */ case 10234: AE("⟺"); break; /* ⟺ */ /* xmap aka longmapsto */ case 10236: AE("⟼"); break; /* ⟼ */ case 10239: AE("⟿"); break; /* ⟿ */ case 10498: AE("⤂"); break; /* ⤂ */ case 10499: AE("⤃"); break; /* ⤃ */ case 10500: AE("⤄"); break; /* ⤄ */ case 10501: AE("⤅"); break; /* ⤅ */ case 10508: AE("⤌"); break; /* ⤌ */ /* rbarr aka bkarow */ case 10509: AE("⤍"); break; /* ⤍ */ case 10510: AE("⤎"); break; /* ⤎ */ /* rBarr aka dbkarow */ case 10511: AE("⤏"); break; /* ⤏ */ /* RBarr aka drbkarow */ case 10512: AE("⤐"); break; /* ⤐ */ case 10513: AE("⤑"); break; /* ⤑ */ case 10514: AE("⤒"); break; /* ⤒ */ case 10515: AE("⤓"); break; /* ⤓ */ case 10518: AE("⤖"); break; /* ⤖ */ case 10521: AE("⤙"); break; /* ⤙ */ case 10522: AE("⤚"); break; /* ⤚ */ case 10523: AE("⤛"); break; /* ⤛ */ case 10524: AE("⤜"); break; /* ⤜ */ case 10525: AE("⤝"); break; /* ⤝ */ case 10526: AE("⤞"); break; /* ⤞ */ case 10527: AE("⤟"); break; /* ⤟ */ case 10528: AE("⤠"); break; /* ⤠ */ case 10531: AE("⤣"); break; /* ⤣ */ case 10532: AE("⤤"); break; /* ⤤ */ /* searhk aka hksearow */ case 10533: AE("⤥"); break; /* ⤥ */ /* swarhk aka hkswarow */ case 10534: AE("⤦"); break; /* ⤦ */ case 10535: AE("⤧"); break; /* ⤧ */ /* toea aka nesear */ case 10536: AE("⤨"); break; /* ⤨ */ /* tosa aka seswar */ case 10537: AE("⤩"); break; /* ⤩ */ case 10538: AE("⤪"); break; /* ⤪ */ case 10547: TWOCPE; if (clen2 && uniChar2 == 824) { AE("⤳̸"); MCP; /* ⤳̸ */ } else { AE("⤳"); /* ⤳ */ }; break; case 10549: AE("⤵"); break; /* ⤵ */ case 10550: AE("⤶"); break; /* ⤶ */ case 10551: AE("⤷"); break; /* ⤷ */ case 10552: AE("⤸"); break; /* ⤸ */ case 10553: AE("⤹"); break; /* ⤹ */ case 10556: AE("⤼"); break; /* ⤼ */ case 10557: AE("⤽"); break; /* ⤽ */ case 10565: AE("⥅"); break; /* ⥅ */ case 10568: AE("⥈"); break; /* ⥈ */ case 10569: AE("⥉"); break; /* ⥉ */ case 10570: AE("⥊"); break; /* ⥊ */ case 10571: AE("⥋"); break; /* ⥋ */ case 10574: AE("⥎"); break; /* ⥎ */ case 10575: AE("⥏"); break; /* ⥏ */ case 10576: AE("⥐"); break; /* ⥐ */ case 10577: AE("⥑"); break; /* ⥑ */ case 10578: AE("⥒"); break; /* ⥒ */ case 10579: AE("⥓"); break; /* ⥓ */ case 10580: AE("⥔"); break; /* ⥔ */ case 10581: AE("⥕"); break; /* ⥕ */ case 10582: AE("⥖"); break; /* ⥖ */ case 10583: AE("⥗"); break; /* ⥗ */ case 10584: AE("⥘"); break; /* ⥘ */ case 10585: AE("⥙"); break; /* ⥙ */ case 10586: AE("⥚"); break; /* ⥚ */ case 10587: AE("⥛"); break; /* ⥛ */ case 10588: AE("⥜"); break; /* ⥜ */ case 10589: AE("⥝"); break; /* ⥝ */ case 10590: AE("⥞"); break; /* ⥞ */ case 10591: AE("⥟"); break; /* ⥟ */ case 10592: AE("⥠"); break; /* ⥠ */ case 10593: AE("⥡"); break; /* ⥡ */ case 10594: AE("⥢"); break; /* ⥢ */ case 10595: AE("⥣"); break; /* ⥣ */ case 10596: AE("⥤"); break; /* ⥤ */ case 10597: AE("⥥"); break; /* ⥥ */ case 10598: AE("⥦"); break; /* ⥦ */ case 10599: AE("⥧"); break; /* ⥧ */ case 10600: AE("⥨"); break; /* ⥨ */ case 10601: AE("⥩"); break; /* ⥩ */ case 10602: AE("⥪"); break; /* ⥪ */ case 10603: AE("⥫"); break; /* ⥫ */ case 10604: AE("⥬"); break; /* ⥬ */ case 10605: AE("⥭"); break; /* ⥭ */ /* udhar aka UpEquilibrium */ case 10606: AE("⥮"); break; /* ⥮ */ /* duhar aka ReverseUpEquilibrium */ case 10607: AE("⥯"); break; /* ⥯ */ case 10608: AE("⥰"); break; /* ⥰ */ case 10609: AE("⥱"); break; /* ⥱ */ case 10610: AE("⥲"); break; /* ⥲ */ case 10611: AE("⥳"); break; /* ⥳ */ case 10612: AE("⥴"); break; /* ⥴ */ case 10613: AE("⥵"); break; /* ⥵ */ case 10614: AE("⥶"); break; /* ⥶ */ case 10616: AE("⥸"); break; /* ⥸ */ case 10617: AE("⥹"); break; /* ⥹ */ case 10619: AE("⥻"); break; /* ⥻ */ case 10620: AE("⥼"); break; /* ⥼ */ case 10621: AE("⥽"); break; /* ⥽ */ case 10622: AE("⥾"); break; /* ⥾ */ case 10623: AE("⥿"); break; /* ⥿ */ case 10629: AE("⦅"); break; /* ⦅ */ case 10630: AE("⦆"); break; /* ⦆ */ case 10635: AE("⦋"); break; /* ⦋ */ case 10636: AE("⦌"); break; /* ⦌ */ case 10637: AE("⦍"); break; /* ⦍ */ case 10638: AE("⦎"); break; /* ⦎ */ case 10639: AE("⦏"); break; /* ⦏ */ case 10640: AE("⦐"); break; /* ⦐ */ case 10641: AE("⦑"); break; /* ⦑ */ case 10642: AE("⦒"); break; /* ⦒ */ case 10643: AE("⦓"); break; /* ⦓ */ case 10644: AE("⦔"); break; /* ⦔ */ case 10645: AE("⦕"); break; /* ⦕ */ case 10646: AE("⦖"); break; /* ⦖ */ case 10650: AE("⦚"); break; /* ⦚ */ case 10652: AE("⦜"); break; /* ⦜ */ case 10653: AE("⦝"); break; /* ⦝ */ case 10660: AE("⦤"); break; /* ⦤ */ case 10661: AE("⦥"); break; /* ⦥ */ case 10662: AE("⦦"); break; /* ⦦ */ case 10663: AE("⦧"); break; /* ⦧ */ case 10664: AE("⦨"); break; /* ⦨ */ case 10665: AE("⦩"); break; /* ⦩ */ case 10666: AE("⦪"); break; /* ⦪ */ case 10667: AE("⦫"); break; /* ⦫ */ case 10668: AE("⦬"); break; /* ⦬ */ case 10669: AE("⦭"); break; /* ⦭ */ case 10670: AE("⦮"); break; /* ⦮ */ case 10671: AE("⦯"); break; /* ⦯ */ case 10672: AE("⦰"); break; /* ⦰ */ case 10673: AE("⦱"); break; /* ⦱ */ case 10674: AE("⦲"); break; /* ⦲ */ case 10675: AE("⦳"); break; /* ⦳ */ case 10676: AE("⦴"); break; /* ⦴ */ case 10677: AE("⦵"); break; /* ⦵ */ case 10678: AE("⦶"); break; /* ⦶ */ case 10679: AE("⦷"); break; /* ⦷ */ case 10681: AE("⦹"); break; /* ⦹ */ case 10683: AE("⦻"); break; /* ⦻ */ case 10684: AE("⦼"); break; /* ⦼ */ case 10686: AE("⦾"); break; /* ⦾ */ case 10687: AE("⦿"); break; /* ⦿ */ case 10688: AE("⧀"); break; /* ⧀ */ case 10689: AE("⧁"); break; /* ⧁ */ case 10690: AE("⧂"); break; /* ⧂ */ case 10691: AE("⧃"); break; /* ⧃ */ case 10692: AE("⧄"); break; /* ⧄ */ case 10693: AE("⧅"); break; /* ⧅ */ case 10697: AE("⧉"); break; /* ⧉ */ case 10701: AE("⧍"); break; /* ⧍ */ case 10702: AE("⧎"); break; /* ⧎ */ case 10703: TWOCPE; if (clen2 && uniChar2 == 824) { AE("⧏̸"); MCP; /* ⧏̸ */ } else { AE("⧏"); /* ⧏ */ }; break; case 10704: TWOCPE; if (clen2 && uniChar2 == 824) { AE("⧐̸"); MCP; /* ⧐̸ */ } else { AE("⧐"); /* ⧐ */ }; break; case 10716: AE("⧜"); break; /* ⧜ */ case 10717: AE("⧝"); break; /* ⧝ */ case 10718: AE("⧞"); break; /* ⧞ */ case 10723: AE("⧣"); break; /* ⧣ */ case 10724: AE("⧤"); break; /* ⧤ */ case 10725: AE("⧥"); break; /* ⧥ */ /* lozf aka blacklozenge */ case 10731: AE("⧫"); break; /* ⧫ */ case 10740: AE("⧴"); break; /* ⧴ */ case 10742: AE("⧶"); break; /* ⧶ */ /* xodot aka bigodot */ case 10752: AE("⨀"); break; /* ⨀ */ /* xoplus aka bigoplus */ case 10753: AE("⨁"); break; /* ⨁ */ /* xotime aka bigotimes */ case 10754: AE("⨂"); break; /* ⨂ */ /* xuplus aka biguplus */ case 10756: AE("⨄"); break; /* ⨄ */ /* xsqcup aka bigsqcup */ case 10758: AE("⨆"); break; /* ⨆ */ /* qint aka iiiint */ case 10764: AE("⨌"); break; /* ⨌ */ case 10765: AE("⨍"); break; /* ⨍ */ case 10768: AE("⨐"); break; /* ⨐ */ case 10769: AE("⨑"); break; /* ⨑ */ case 10770: AE("⨒"); break; /* ⨒ */ case 10771: AE("⨓"); break; /* ⨓ */ case 10772: AE("⨔"); break; /* ⨔ */ case 10773: AE("⨕"); break; /* ⨕ */ case 10774: AE("⨖"); break; /* ⨖ */ case 10775: AE("⨗"); break; /* ⨗ */ case 10786: AE("⨢"); break; /* ⨢ */ case 10787: AE("⨣"); break; /* ⨣ */ case 10788: AE("⨤"); break; /* ⨤ */ case 10789: AE("⨥"); break; /* ⨥ */ case 10790: AE("⨦"); break; /* ⨦ */ case 10791: AE("⨧"); break; /* ⨧ */ case 10793: AE("⨩"); break; /* ⨩ */ case 10794: AE("⨪"); break; /* ⨪ */ case 10797: AE("⨭"); break; /* ⨭ */ case 10798: AE("⨮"); break; /* ⨮ */ case 10799: AE("⨯"); break; /* ⨯ */ case 10800: AE("⨰"); break; /* ⨰ */ case 10801: AE("⨱"); break; /* ⨱ */ case 10803: AE("⨳"); break; /* ⨳ */ case 10804: AE("⨴"); break; /* ⨴ */ case 10805: AE("⨵"); break; /* ⨵ */ case 10806: AE("⨶"); break; /* ⨶ */ case 10807: AE("⨷"); break; /* ⨷ */ case 10808: AE("⨸"); break; /* ⨸ */ case 10809: AE("⨹"); break; /* ⨹ */ case 10810: AE("⨺"); break; /* ⨺ */ case 10811: AE("⨻"); break; /* ⨻ */ /* iprod aka intprod */ case 10812: AE("⨼"); break; /* ⨼ */ case 10815: AE("⨿"); break; /* ⨿ */ case 10816: AE("⩀"); break; /* ⩀ */ case 10818: AE("⩂"); break; /* ⩂ */ case 10819: AE("⩃"); break; /* ⩃ */ case 10820: AE("⩄"); break; /* ⩄ */ case 10821: AE("⩅"); break; /* ⩅ */ case 10822: AE("⩆"); break; /* ⩆ */ case 10823: AE("⩇"); break; /* ⩇ */ case 10824: AE("⩈"); break; /* ⩈ */ case 10825: AE("⩉"); break; /* ⩉ */ case 10826: AE("⩊"); break; /* ⩊ */ case 10827: AE("⩋"); break; /* ⩋ */ case 10828: AE("⩌"); break; /* ⩌ */ case 10829: AE("⩍"); break; /* ⩍ */ case 10832: AE("⩐"); break; /* ⩐ */ case 10835: AE("⩓"); break; /* ⩓ */ case 10836: AE("⩔"); break; /* ⩔ */ case 10837: AE("⩕"); break; /* ⩕ */ case 10838: AE("⩖"); break; /* ⩖ */ case 10839: AE("⩗"); break; /* ⩗ */ case 10840: AE("⩘"); break; /* ⩘ */ case 10842: AE("⩚"); break; /* ⩚ */ case 10843: AE("⩛"); break; /* ⩛ */ case 10844: AE("⩜"); break; /* ⩜ */ case 10845: AE("⩝"); break; /* ⩝ */ case 10847: AE("⩟"); break; /* ⩟ */ case 10854: AE("⩦"); break; /* ⩦ */ case 10858: AE("⩪"); break; /* ⩪ */ case 10861: TWOCPE; if (clen2 && uniChar2 == 824) { AE("⩭̸"); MCP; /* ⩭̸ */ } else { AE("⩭"); /* ⩭ */ }; break; case 10862: AE("⩮"); break; /* ⩮ */ case 10863: AE("⩯"); break; /* ⩯ */ case 10864: TWOCPE; if (clen2 && uniChar2 == 824) { AE("⩰̸"); MCP; /* ⩰̸ */ } else { AE("⩰"); /* ⩰ */ }; break; case 10865: AE("⩱"); break; /* ⩱ */ case 10866: AE("⩲"); break; /* ⩲ */ case 10867: AE("⩳"); break; /* ⩳ */ case 10868: AE("⩴"); break; /* ⩴ */ case 10869: AE("⩵"); break; /* ⩵ */ /* eDDot aka ddotseq */ case 10871: AE("⩷"); break; /* ⩷ */ case 10872: AE("⩸"); break; /* ⩸ */ case 10873: AE("⩹"); break; /* ⩹ */ case 10874: AE("⩺"); break; /* ⩺ */ case 10875: AE("⩻"); break; /* ⩻ */ case 10876: AE("⩼"); break; /* ⩼ */ case 10877: TWOCPE; if (clen2 && uniChar2 == 824) { /* les aka NotLessSlantEqual or nleqslant */ AE("⩽̸"); MCP; /* ⩽̸ */ } else { /* les aka LessSlantEqual or leqslant */ AE("⩽"); /* ⩽ */ }; break; case 10878: TWOCPE; if (clen2 && uniChar2 == 824) { /* ges aka NotGreaterSlantEqual or ngeqslant */ AE("⩾̸"); MCP; /* ⩾̸ */ } else { /* ges aka GreaterSlantEqual or geqslant */ AE("⩾"); /* ⩾ */ }; break; case 10879: AE("⩿"); break; /* ⩿ */ case 10880: AE("⪀"); break; /* ⪀ */ case 10881: AE("⪁"); break; /* ⪁ */ case 10882: AE("⪂"); break; /* ⪂ */ case 10883: AE("⪃"); break; /* ⪃ */ case 10884: AE("⪄"); break; /* ⪄ */ /* lap aka lessapprox */ case 10885: AE("⪅"); break; /* ⪅ */ /* gap aka gtrapprox */ case 10886: AE("⪆"); break; /* ⪆ */ /* lne aka lneq */ case 10887: AE("⪇"); break; /* ⪇ */ /* gne aka gneq */ case 10888: AE("⪈"); break; /* ⪈ */ /* lnap aka lnapprox */ case 10889: AE("⪉"); break; /* ⪉ */ /* gnap aka gnapprox */ case 10890: AE("⪊"); break; /* ⪊ */ /* lEg aka lesseqqgtr */ case 10891: AE("⪋"); break; /* ⪋ */ /* gEl aka gtreqqless */ case 10892: AE("⪌"); break; /* ⪌ */ case 10893: AE("⪍"); break; /* ⪍ */ case 10894: AE("⪎"); break; /* ⪎ */ case 10895: AE("⪏"); break; /* ⪏ */ case 10896: AE("⪐"); break; /* ⪐ */ case 10897: AE("⪑"); break; /* ⪑ */ case 10898: AE("⪒"); break; /* ⪒ */ case 10899: AE("⪓"); break; /* ⪓ */ case 10900: AE("⪔"); break; /* ⪔ */ /* els aka eqslantless */ case 10901: AE("⪕"); break; /* ⪕ */ /* egs aka eqslantgtr */ case 10902: AE("⪖"); break; /* ⪖ */ case 10903: AE("⪗"); break; /* ⪗ */ case 10904: AE("⪘"); break; /* ⪘ */ case 10905: AE("⪙"); break; /* ⪙ */ case 10906: AE("⪚"); break; /* ⪚ */ case 10909: AE("⪝"); break; /* ⪝ */ case 10910: AE("⪞"); break; /* ⪞ */ case 10911: AE("⪟"); break; /* ⪟ */ case 10912: AE("⪠"); break; /* ⪠ */ case 10913: TWOCPE; if (clen2 && uniChar2 == 824) { AE("⪡̸"); MCP; /* ⪡̸ */ } else { AE("⪡"); /* ⪡ */ }; break; case 10914: TWOCPE; if (clen2 && uniChar2 == 824) { AE("⪢̸"); MCP; /* ⪢̸ */ } else { AE("⪢"); /* ⪢ */ }; break; case 10916: AE("⪤"); break; /* ⪤ */ case 10917: AE("⪥"); break; /* ⪥ */ case 10918: AE("⪦"); break; /* ⪦ */ case 10919: AE("⪧"); break; /* ⪧ */ case 10920: AE("⪨"); break; /* ⪨ */ case 10921: AE("⪩"); break; /* ⪩ */ case 10922: AE("⪪"); break; /* ⪪ */ case 10923: AE("⪫"); break; /* ⪫ */ case 10924: TWOCPE; if (clen2 && uniChar2 == 65024) { AE("⪬︀"); MCP; /* ⪬︀ */ } else { AE("⪬"); /* ⪬ */ }; break; case 10925: TWOCPE; if (clen2 && uniChar2 == 65024) { AE("⪭︀"); MCP; /* ⪭︀ */ } else { AE("⪭"); /* ⪭ */ }; break; case 10926: AE("⪮"); break; /* ⪮ */ case 10927: TWOCPE; if (clen2 && uniChar2 == 824) { /* pre aka NotPrecedesEqual or npreceq */ AE("⪯̸"); MCP; /* ⪯̸ */ } else { /* pre aka PrecedesEqual or preceq */ AE("⪯"); /* ⪯ */ }; break; case 10928: TWOCPE; if (clen2 && uniChar2 == 824) { /* sce aka NotSucceedsEqual or nsucceq */ AE("⪰̸"); MCP; /* ⪰̸ */ } else { /* sce aka SucceedsEqual or succeq */ AE("⪰"); /* ⪰ */ }; break; case 10931: AE("⪳"); break; /* ⪳ */ case 10932: AE("⪴"); break; /* ⪴ */ /* prnE aka precneqq */ case 10933: AE("⪵"); break; /* ⪵ */ /* scnE aka succneqq */ case 10934: AE("⪶"); break; /* ⪶ */ /* prap aka precapprox */ case 10935: AE("⪷"); break; /* ⪷ */ /* scap aka succapprox */ case 10936: AE("⪸"); break; /* ⪸ */ /* prnap aka precnapprox */ case 10937: AE("⪹"); break; /* ⪹ */ /* scnap aka succnapprox */ case 10938: AE("⪺"); break; /* ⪺ */ case 10939: AE("⪻"); break; /* ⪻ */ case 10940: AE("⪼"); break; /* ⪼ */ case 10941: AE("⪽"); break; /* ⪽ */ case 10942: AE("⪾"); break; /* ⪾ */ case 10943: AE("⪿"); break; /* ⪿ */ case 10944: AE("⫀"); break; /* ⫀ */ case 10945: AE("⫁"); break; /* ⫁ */ case 10946: AE("⫂"); break; /* ⫂ */ case 10947: AE("⫃"); break; /* ⫃ */ case 10948: AE("⫄"); break; /* ⫄ */ case 10949: TWOCPE; if (clen2 && uniChar2 == 824) { /* subE aka nsubseteqq */ AE("⫅̸"); MCP; /* ⫅̸ */ } else { /* subE aka subseteqq */ AE("⫅"); /* ⫅ */ }; break; case 10950: TWOCPE; if (clen2 && uniChar2 == 824) { /* supE aka nsupseteqq */ AE("⫆̸"); MCP; /* ⫆̸ */ } else { /* supE aka supseteqq */ AE("⫆"); /* ⫆ */ }; break; case 10951: AE("⫇"); break; /* ⫇ */ case 10952: AE("⫈"); break; /* ⫈ */ case 10955: TWOCPE; if (clen2 && uniChar2 == 65024) { /* subnE aka varsubsetneqq */ AE("⫋︀"); MCP; /* ⫋︀ */ } else { /* subnE aka subsetneqq */ AE("⫋"); /* ⫋ */ }; break; case 10956: TWOCPE; if (clen2 && uniChar2 == 65024) { /* supnE aka varsupsetneqq */ AE("⫌︀"); MCP; /* ⫌︀ */ } else { /* supnE aka supsetneqq */ AE("⫌"); /* ⫌ */ }; break; case 10959: AE("⫏"); break; /* ⫏ */ case 10960: AE("⫐"); break; /* ⫐ */ case 10961: AE("⫑"); break; /* ⫑ */ case 10962: AE("⫒"); break; /* ⫒ */ case 10963: AE("⫓"); break; /* ⫓ */ case 10964: AE("⫔"); break; /* ⫔ */ case 10965: AE("⫕"); break; /* ⫕ */ case 10966: AE("⫖"); break; /* ⫖ */ case 10967: AE("⫗"); break; /* ⫗ */ case 10968: AE("⫘"); break; /* ⫘ */ case 10969: AE("⫙"); break; /* ⫙ */ case 10970: AE("⫚"); break; /* ⫚ */ case 10971: AE("⫛"); break; /* ⫛ */ /* Dashv aka DoubleLeftTee */ case 10980: AE("⫤"); break; /* ⫤ */ case 10982: AE("⫦"); break; /* ⫦ */ case 10983: AE("⫧"); break; /* ⫧ */ case 10984: AE("⫨"); break; /* ⫨ */ case 10985: AE("⫩"); break; /* ⫩ */ case 10987: AE("⫫"); break; /* ⫫ */ case 10988: AE("⫬"); break; /* ⫬ */ case 10989: AE("⫭"); break; /* ⫭ */ case 10990: AE("⫮"); break; /* ⫮ */ case 10991: AE("⫯"); break; /* ⫯ */ case 10992: AE("⫰"); break; /* ⫰ */ case 10993: AE("⫱"); break; /* ⫱ */ case 10994: AE("⫲"); break; /* ⫲ */ case 10995: AE("⫳"); break; /* ⫳ */ case 11005: TWOCPE; if (clen2 && uniChar2 == 8421) { AE("⫽⃥"); MCP; /* ⫽⃥ */ } else { AE("⫽"); /* ⫽ */ }; break; case 64256: AE("ff"); break; /* ff */ case 64257: AE("fi"); break; /* fi */ case 64258: AE("fl"); break; /* fl */ case 64259: AE("ffi"); break; /* ffi */ case 64260: AE("ffl"); break; /* ffl */ case 119964: AE("𝒜"); break; /* 𝒜 */ case 119966: AE("𝒞"); break; /* 𝒞 */ case 119967: AE("𝒟"); break; /* 𝒟 */ case 119970: AE("𝒢"); break; /* 𝒢 */ case 119973: AE("𝒥"); break; /* 𝒥 */ case 119974: AE("𝒦"); break; /* 𝒦 */ case 119977: AE("𝒩"); break; /* 𝒩 */ case 119978: AE("𝒪"); break; /* 𝒪 */ case 119979: AE("𝒫"); break; /* 𝒫 */ case 119980: AE("𝒬"); break; /* 𝒬 */ case 119982: AE("𝒮"); break; /* 𝒮 */ case 119983: AE("𝒯"); break; /* 𝒯 */ case 119984: AE("𝒰"); break; /* 𝒰 */ case 119985: AE("𝒱"); break; /* 𝒱 */ case 119986: AE("𝒲"); break; /* 𝒲 */ case 119987: AE("𝒳"); break; /* 𝒳 */ case 119988: AE("𝒴"); break; /* 𝒴 */ case 119989: AE("𝒵"); break; /* 𝒵 */ case 119990: AE("𝒶"); break; /* 𝒶 */ case 119991: AE("𝒷"); break; /* 𝒷 */ case 119992: AE("𝒸"); break; /* 𝒸 */ case 119993: AE("𝒹"); break; /* 𝒹 */ case 119995: AE("𝒻"); break; /* 𝒻 */ case 119997: AE("𝒽"); break; /* 𝒽 */ case 119998: AE("𝒾"); break; /* 𝒾 */ case 119999: AE("𝒿"); break; /* 𝒿 */ case 120000: AE("𝓀"); break; /* 𝓀 */ case 120001: AE("𝓁"); break; /* 𝓁 */ case 120002: AE("𝓂"); break; /* 𝓂 */ case 120003: AE("𝓃"); break; /* 𝓃 */ case 120005: AE("𝓅"); break; /* 𝓅 */ case 120006: AE("𝓆"); break; /* 𝓆 */ case 120007: AE("𝓇"); break; /* 𝓇 */ case 120008: AE("𝓈"); break; /* 𝓈 */ case 120009: AE("𝓉"); break; /* 𝓉 */ case 120010: AE("𝓊"); break; /* 𝓊 */ case 120011: AE("𝓋"); break; /* 𝓋 */ case 120012: AE("𝓌"); break; /* 𝓌 */ case 120013: AE("𝓍"); break; /* 𝓍 */ case 120014: AE("𝓎"); break; /* 𝓎 */ case 120015: AE("𝓏"); break; /* 𝓏 */ case 120068: AE("𝔄"); break; /* 𝔄 */ case 120069: AE("𝔅"); break; /* 𝔅 */ case 120071: AE("𝔇"); break; /* 𝔇 */ case 120072: AE("𝔈"); break; /* 𝔈 */ case 120073: AE("𝔉"); break; /* 𝔉 */ case 120074: AE("𝔊"); break; /* 𝔊 */ case 120077: AE("𝔍"); break; /* 𝔍 */ case 120078: AE("𝔎"); break; /* 𝔎 */ case 120079: AE("𝔏"); break; /* 𝔏 */ case 120080: AE("𝔐"); break; /* 𝔐 */ case 120081: AE("𝔑"); break; /* 𝔑 */ case 120082: AE("𝔒"); break; /* 𝔒 */ case 120083: AE("𝔓"); break; /* 𝔓 */ case 120084: AE("𝔔"); break; /* 𝔔 */ case 120086: AE("𝔖"); break; /* 𝔖 */ case 120087: AE("𝔗"); break; /* 𝔗 */ case 120088: AE("𝔘"); break; /* 𝔘 */ case 120089: AE("𝔙"); break; /* 𝔙 */ case 120090: AE("𝔚"); break; /* 𝔚 */ case 120091: AE("𝔛"); break; /* 𝔛 */ case 120092: AE("𝔜"); break; /* 𝔜 */ case 120094: AE("𝔞"); break; /* 𝔞 */ case 120095: AE("𝔟"); break; /* 𝔟 */ case 120096: AE("𝔠"); break; /* 𝔠 */ case 120097: AE("𝔡"); break; /* 𝔡 */ case 120098: AE("𝔢"); break; /* 𝔢 */ case 120099: AE("𝔣"); break; /* 𝔣 */ case 120100: AE("𝔤"); break; /* 𝔤 */ case 120101: AE("𝔥"); break; /* 𝔥 */ case 120102: AE("𝔦"); break; /* 𝔦 */ case 120103: AE("𝔧"); break; /* 𝔧 */ case 120104: AE("𝔨"); break; /* 𝔨 */ case 120105: AE("𝔩"); break; /* 𝔩 */ case 120106: AE("𝔪"); break; /* 𝔪 */ case 120107: AE("𝔫"); break; /* 𝔫 */ case 120108: AE("𝔬"); break; /* 𝔬 */ case 120109: AE("𝔭"); break; /* 𝔭 */ case 120110: AE("𝔮"); break; /* 𝔮 */ case 120111: AE("𝔯"); break; /* 𝔯 */ case 120112: AE("𝔰"); break; /* 𝔰 */ case 120113: AE("𝔱"); break; /* 𝔱 */ case 120114: AE("𝔲"); break; /* 𝔲 */ case 120115: AE("𝔳"); break; /* 𝔳 */ case 120116: AE("𝔴"); break; /* 𝔴 */ case 120117: AE("𝔵"); break; /* 𝔵 */ case 120118: AE("𝔶"); break; /* 𝔶 */ case 120119: AE("𝔷"); break; /* 𝔷 */ case 120120: AE("𝔸"); break; /* 𝔸 */ case 120121: AE("𝔹"); break; /* 𝔹 */ case 120123: AE("𝔻"); break; /* 𝔻 */ case 120124: AE("𝔼"); break; /* 𝔼 */ case 120125: AE("𝔽"); break; /* 𝔽 */ case 120126: AE("𝔾"); break; /* 𝔾 */ case 120128: AE("𝕀"); break; /* 𝕀 */ case 120129: AE("𝕁"); break; /* 𝕁 */ case 120130: AE("𝕂"); break; /* 𝕂 */ case 120131: AE("𝕃"); break; /* 𝕃 */ case 120132: AE("𝕄"); break; /* 𝕄 */ case 120134: AE("𝕆"); break; /* 𝕆 */ case 120138: AE("𝕊"); break; /* 𝕊 */ case 120139: AE("𝕋"); break; /* 𝕋 */ case 120140: AE("𝕌"); break; /* 𝕌 */ case 120141: AE("𝕍"); break; /* 𝕍 */ case 120142: AE("𝕎"); break; /* 𝕎 */ case 120143: AE("𝕏"); break; /* 𝕏 */ case 120144: AE("𝕐"); break; /* 𝕐 */ case 120146: AE("𝕒"); break; /* 𝕒 */ case 120147: AE("𝕓"); break; /* 𝕓 */ case 120148: AE("𝕔"); break; /* 𝕔 */ case 120149: AE("𝕕"); break; /* 𝕕 */ case 120150: AE("𝕖"); break; /* 𝕖 */ case 120151: AE("𝕗"); break; /* 𝕗 */ case 120152: AE("𝕘"); break; /* 𝕘 */ case 120153: AE("𝕙"); break; /* 𝕙 */ case 120154: AE("𝕚"); break; /* 𝕚 */ case 120155: AE("𝕛"); break; /* 𝕛 */ case 120156: AE("𝕜"); break; /* 𝕜 */ case 120157: AE("𝕝"); break; /* 𝕝 */ case 120158: AE("𝕞"); break; /* 𝕞 */ case 120159: AE("𝕟"); break; /* 𝕟 */ case 120160: AE("𝕠"); break; /* 𝕠 */ case 120161: AE("𝕡"); break; /* 𝕡 */ case 120162: AE("𝕢"); break; /* 𝕢 */ case 120163: AE("𝕣"); break; /* 𝕣 */ case 120164: AE("𝕤"); break; /* 𝕤 */ case 120165: AE("𝕥"); break; /* 𝕥 */ case 120166: AE("𝕦"); break; /* 𝕦 */ case 120167: AE("𝕧"); break; /* 𝕧 */ case 120168: AE("𝕨"); break; /* 𝕨 */ case 120169: AE("𝕩"); break; /* 𝕩 */ case 120170: AE("𝕪"); break; /* 𝕪 */ case 120171: AE("𝕫"); break; /* 𝕫 */ tdom-0.9.5-src/generic/domjson.h0000644000175000017500000000154414703531020015200 0ustar rolfrolf #ifndef JSON_MAX_NESTING # define JSON_MAX_NESTING 2000 #endif #ifndef JSON_OBJECT_CONTAINER # define JSON_OBJECT_CONTAINER "objectcontainer" #endif #ifndef JSON_ARRAY_CONTAINER # define JSON_ARRAY_CONTAINER "arraycontainer" #endif typedef enum { JSON_START, JSON_WITHIN_ARRAY, JSON_WITHIN_OBJECT } JSONWithin; #define JSON_ARRAY 1 #define JSON_OBJECT 2 #define JSON_NULL 3 #define JSON_TRUE 4 #define JSON_FALSE 5 #define JSON_STRING 6 #define JSON_NUMBER 7 domDocument * JSON_Parse ( char *json, /* Complete text of the json string being parsed */ char *documentElement, /* name of the root element, may be NULL */ int maxnesting, char **errStr, domLength *byteIndex ); domDocument * TypedList2DOM ( Tcl_Interp *interp, Tcl_Obj *typedList ); int isJSONNumber ( char *num, domLength numlen ); tdom-0.9.5-src/generic/domxslt.h0000644000175000017500000000675114703531020015226 0ustar rolfrolf/*---------------------------------------------------------------------------- | Copyright (c) 2000 Jochen Loewer (loewerj@hotmail.com) |----------------------------------------------------------------------------- | | A XSLT implementation for tDOM, according to the W3C | recommendation (16 Nov 1999, | http://www.w3.org/TR/1999/REC-xslt-19991116). | | | The contents of this file are subject to the Mozilla Public License | Version 2.0 (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) 1998, 1999 | Jochen Loewer. All Rights Reserved. | | Contributor(s): | | | $Log$ | Revision 1.6 2004/08/14 14:42:27 rolf | Use 'Id' cvs keyword (instead of 'Header') in the file heads. | | Revision 1.5 2003/01/11 00:19:02 rolf | Added conversion of XSLT stylesheet DOM trees to 'cached' xslt cmds | (new domDoc method toXSLTcmd). Works for non threaded tcl; needs | additional work for multi-threaded tcl and documentation. | | Revision 1.4 2002/12/27 23:40:10 rolf | The xslt method now understands also the options | -ignoreUndeclaredParameters and -xsltmessagecmd. | | Revision 1.3 2002/06/02 06:36:24 zoran | Added thread safety with capability of sharing DOM trees between | threads and ability to read/write-lock DOM documents | | Revision 1.2 2002/04/08 02:11:12 rolf | Added -parameters option to domNode xslt method, to enable setting of | top level parameters from tcl level. | | Revision 1.1.1.1 2002/02/22 01:05:35 rolf | tDOM0.7test with Jochens first set of patches | | Revision 1.1 2002/02/04 08:08:19 jolo | Initial revision | | | | written by Jochen Loewer | June, 2000 | \---------------------------------------------------------------------------*/ #ifndef __DOMXSLT_H__ #define __DOMXSLT_H__ #include #include typedef int (*xsltMsgCB) (void *clientData, char *str, domLength length, int terminate); /*---------------------------------------------------------------------------- | Prototypes | \---------------------------------------------------------------------------*/ int xsltProcess (domDocument * xsltDoc, domNode * xmlNode, void * xsltCmdData, char ** parameters, int ignoreUndeclaredParameters, int maxApplyDepth, xpathFuncCallback funcCB, void * xpathFuncClientData, xsltMsgCB xsltMsgCB, void * xsltMsgClientData, char ** errMsg, domDocument ** resultDoc ); void * xsltCompileStylesheet ( domDocument * xsltDoc, xpathFuncCallback funcCB, void * xpathFuncClientData, int guardXSLTTree, char ** errMsg ); void xsltFreeStateWrapper (void *clientData); void sortByDocOrder (xpathResultSet *rs); #endif tdom-0.9.5-src/generic/schema.c0000644000175000017500000071671314703531020014775 0ustar rolfrolf/*---------------------------------------------------------------------------- | Copyright (c) 2018 - 2022 Rolf Ade (rolf@pointsman.de) |----------------------------------------------------------------------------- | | | The contents of this file are subject to the Mozilla Public License | Version 2.0 (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. | | Contributor(s): | | | written by Rolf Ade | 2018-2022 | \---------------------------------------------------------------------------*/ #include #include #include #include #include #include #ifndef TDOM_NO_SCHEMA #include #include #ifdef _MSC_VER #include #else #include #endif #define SetResult(str) Tcl_ResetResult(interp); \ Tcl_SetStringObj(Tcl_GetObjResult(interp), (str), -1) /* #define DEBUG */ /* #define DDEBUG */ /*---------------------------------------------------------------------------- | Debug Macros | \---------------------------------------------------------------------------*/ #ifdef DEBUG # define DBG(x) x #else # define DBG(x) #endif #if defined(DEBUG) || defined(DDEBUG) # define DDBG(x) x #else # define DDBG(x) #endif /*---------------------------------------------------------------------------- | Choice/attribute handling method threshold | \---------------------------------------------------------------------------*/ #ifndef TDOM_CHOICE_HASH_THRESHOLD # define TDOM_CHOICE_HASH_THRESHOLD 5 #endif #ifndef TDOM_ATTRIBUTE_HASH_THRESHOLD # define TDOM_ATTRIBUTE_HASH_THRESHOLD 5 #endif #ifndef TDOM_EXPAT_READ_SIZE # define TDOM_EXPAT_READ_SIZE (1024*8) #endif /*---------------------------------------------------------------------------- | Initial buffer sizes | \---------------------------------------------------------------------------*/ #ifndef CONTENT_ARRAY_SIZE_INIT # define CONTENT_ARRAY_SIZE_INIT 20 #endif #ifndef ANON_PATTERN_ARRAY_SIZE_INIT # define ANON_PATTERN_ARRAY_SIZE_INIT 256 #endif #ifndef URI_BUFFER_LEN_INIT # define URI_BUFFER_LEN_INIT 128 #endif #ifndef ATTR_ARRAY_INIT # define ATTR_ARRAY_INIT 4 #endif /*---------------------------------------------------------------------------- | Local defines | \---------------------------------------------------------------------------*/ #ifndef O_BINARY # ifdef _O_BINARY # define O_BINARY _O_BINARY # else # define O_BINARY 0 # endif #endif #ifndef TCL_MATCH_NOCASE # define TCL_MATCH_NOCASE 1 #endif /*---------------------------------------------------------------------------- | Local typedefs | \---------------------------------------------------------------------------*/ typedef struct { SchemaData *sdata; Tcl_Interp *interp; XML_Parser parser; Tcl_DString *cdata; int onlyWhiteSpace; char *uri; int maxUriLen; Tcl_Obj *externalentitycommandObj; } ValidateMethodData; static const char *ValidationAction2str[] = { "NOT_USED", "MATCH_GLOBAL", "MATCH_ELEMENT_START", "MATCH_ELEMENT_END", "MATCH_TEXT", "MATCH_ATTRIBUTE_TEXT", "MATCH_DOM_KEYCONSTRAINT", "MATCH_DOM_XPATH_BOOLEAN" }; typedef enum { DOM_KEYCONSTRAINT, DOM_XPATH_BOOLEAN, MISSING_ATTRIBUTE, MISSING_ELEMENT, UNEXPECTED_TEXT, MISSING_TEXT, UNEXPECTED_ROOT_ELEMENT, UNEXPECTED_ELEMENT, UNKNOWN_ATTRIBUTE, INVALID_KEYREF, UNKNOWN_ROOT_ELEMENT, UNKNOWN_GLOBAL_ID, UNKNOWN_ID, INVALID_ATTRIBUTE_VALUE, INVALID_VALUE, INVALID_JSON_TYPE, } ValidationErrorType; static const char *ValidationErrorType2str[] = { "DOM_KEYCONSTRAINT", "DOM_XPATH_BOOLEAN", "MISSING_ATTRIBUTE", "MISSING_ELEMENT", "UNEXPECTED_TEXT", "MISSING_TEXT", "UNEXPECTED_ROOT_ELEMENT", "UNEXPECTED_ELEMENT", "UNKNOWN_ATTRIBUTE", "INVALID_KEYREF", "UNKNOWN_ROOT_ELEMENT", "UNKNOWN_GLOBAL_ID", "UNKNOWN_ID", "INVALID_ATTRIBUTE_VALUE", "INVALID_VALUE", "INVALID_JSON_TYPE" }; typedef enum { VALIDATE_STRING, VALIDATE_FILENAME, VALIDATE_CHANNEL } ValidationInput; static const char *jsonStructTypes[] = { "NONE", "OBJECT", "ARRAY", NULL }; typedef enum { jt_none, jt_object, jt_array } jsonStructType; /*---------------------------------------------------------------------------- | Recovering related flags | \---------------------------------------------------------------------------*/ #define RECOVER_FLAG_REWIND 1 #define RECOVER_FLAG_DONT_REPORT 2 #define RECOVER_FLAG_IGNORE 4 #define RECOVER_FLAG_MATCH_END_CONTINUE 8 /*---------------------------------------------------------------------------- | [schemacmd info expected] related flags | \---------------------------------------------------------------------------*/ #define EXPECTED_IGNORE_MATCHED 1 #define EXPECTED_ONLY_MANDATORY 2 #define EXPECTED_PROBE_MAYSKIP 4 /*---------------------------------------------------------------------------- | domKeyConstraint related flags | \---------------------------------------------------------------------------*/ #define DKC_FLAG_IGNORE_EMPTY_FIELD_SET 1 #define DKC_FLAG_BOOLEAN 2 /*---------------------------------------------------------------------------- | Macros | \---------------------------------------------------------------------------*/ #define SetResultV(str) if (!sdata->evalError) { \ Tcl_ResetResult(interp); \ Tcl_SetStringObj(Tcl_GetObjResult(interp), (str), -1); \ } #define SetResult3(str1,str2,str3) Tcl_ResetResult(interp); \ Tcl_AppendResult(interp, (str1), (str2), (str3), NULL) #define SetResult3V(str1,str2,str3) if (!sdata->evalError) { \ Tcl_ResetResult(interp); \ Tcl_AppendResult(interp, (str1), (str2), (str3), NULL); \ } #define SetIntResult(i) Tcl_ResetResult(interp); \ Tcl_SetDomLengthObj(Tcl_GetObjResult(interp), (i)) #define SetLongResult(i) Tcl_ResetResult(interp); \ Tcl_SetLongObj(Tcl_GetObjResult(interp), (i)) #define SetBooleanResult(i) Tcl_ResetResult(interp); \ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), (i)) #define checkNrArgs(l,h,err) if (objc < l || objc > h) { \ SetResult (err); \ return TCL_ERROR; \ } #if defined(DEBUG) || defined(DDEBUG) static const char *Schema_CP_Type2str[] = { "ANY", "NAME", "CHOICE", "INTERLEAVE", "PATTERN", "TEXT", "VIRTUAL", "KEYSPACE_START", "KEYSPACE_END", "JSON_STRUCT_TYPE" }; static const char *Schema_Quant_Type2str[] = { "ONE", "OPT", "REP", "PLUS", "NM", "ERROR" }; #endif #define CHECK_SI \ if (!sdata) { \ SetResult ("Command called outside of schema context"); \ return TCL_ERROR; \ } \ if (sdata->isTextConstraint) { \ SetResult ("Command called in invalid schema context"); \ return TCL_ERROR; \ } #define CHECK_TOPLEVEL \ if (sdata->defineToplevel) { \ SetResult("Command not allowed at top level " \ "in schema define evaluation"); \ return TCL_ERROR; \ } #define CHECK_RECURSIVE_CALL \ if (clientData != NULL) { \ savedsdata = GETASI; \ if (savedsdata == sdata) { \ SetResult ("This recursive call is not allowed"); \ return TCL_ERROR; \ } \ } else if (!sdata->defineToplevel) { \ SetResult ("Command only allowed at lop level"); \ return TCL_ERROR; \ } #define CHECK_EVAL \ if (sdata->currentEvals) { \ SetResult ("This method is not allowed in nested evaluation"); \ return TCL_ERROR; \ } #define CHECK_REWIND \ if (sdata->recoverFlags & RECOVER_FLAG_REWIND) { \ rewindStack (sdata); \ sdata->recoverFlags &= ~RECOVER_FLAG_REWIND; \ } \ #define maxOne(quant) \ ((quant) == SCHEMA_CQUANT_ONE || (quant) == SCHEMA_CQUANT_OPT) ? 1 : 0 #define minOne(quant) \ ((quant) == SCHEMA_CQUANT_ONE || (quant) == SCHEMA_CQUANT_PLUS) ? 1 : 0 #define mayRepeat(quant) \ ((quant) == SCHEMA_CQUANT_REP || (quant) == SCHEMA_CQUANT_PLUS) ? 1 : 0 #define mayMiss(quant) \ ((quant) == SCHEMA_CQUANT_REP || (quant) == SCHEMA_CQUANT_OPT) ? 1 : 0 #define hasMatched(quant,hm) \ (hm) == 0 ? mayMiss(quant) : 1 #define mustMatch(quant,hm) \ (hm) == 0 ? minOne(quant) : 0 #define getContext(cp, ac, hm) \ cp = se->pattern; \ ac = se->activeChild; \ hm = se->hasMatched; \ if (hm && maxOne (cp->quants[ac])) { \ ac += + 1; \ hm = 0; \ } \ #define updateStack(sdata,se,ac) \ if (!(sdata->recoverFlags & RECOVER_FLAG_REWIND)) { \ se->activeChild = ac; \ se->hasMatched = 1; \ } \ static const char *unknownNS = "type = type; switch (type) { case SCHEMA_CTYPE_NAME: pattern->flags |= CONSTRAINT_TEXT_CHILD; /* Fall through. */ case SCHEMA_CTYPE_PATTERN: pattern->namespace = (char *)namespace; pattern->name = name; /* Fall through. */ case SCHEMA_CTYPE_CHOICE: case SCHEMA_CTYPE_INTERLEAVE: pattern->content = (SchemaCP**) MALLOC ( sizeof(SchemaCP*) * CONTENT_ARRAY_SIZE_INIT ); pattern->quants = (SchemaQuant*) MALLOC ( sizeof (SchemaQuant) * CONTENT_ARRAY_SIZE_INIT ); break; case SCHEMA_CTYPE_TEXT: /* content/quant will be allocated, if the cp in fact has * constraints */ break; case SCHEMA_CTYPE_KEYSPACE_END: case SCHEMA_CTYPE_KEYSPACE: pattern->name = name; break; case SCHEMA_CTYPE_ANY: pattern->namespace = namespace; break; case SCHEMA_CTYPE_VIRTUAL: case SCHEMA_CTYPE_JSON_STRUCT: /* Do nothing */ break; } return pattern; } DDBG( static void serializeCP ( SchemaCP *pattern ) { fprintf (stderr, "CP %p type: %s\n", pattern, Schema_CP_Type2str[pattern->type]); switch (pattern->type) { case SCHEMA_CTYPE_KEYSPACE_END: case SCHEMA_CTYPE_KEYSPACE: fprintf (stderr, "\tName: '%s'\n", pattern->name); break; case SCHEMA_CTYPE_NAME: case SCHEMA_CTYPE_PATTERN: fprintf (stderr, "\tName: '%s' Namespace: '%s'\n", pattern->name, pattern->namespace); if (pattern->flags & FORWARD_PATTERN_DEF) { fprintf (stderr, "\tAnonymously defined NAME\n"); } if (pattern->flags & PLACEHOLDER_PATTERN_DEF) { fprintf (stderr, "\tAs placeholder defined NAME\n"); } if (pattern->flags & LOCAL_DEFINED_ELEMENT) { fprintf (stderr, "\tLocal defined NAME\n"); } if (pattern->flags & ELEMENTTYPE_DEF) { fprintf (stderr, "\tElementtype '%s'\n", pattern->name); } if (pattern->flags & TYPED_ELEMENT) { fprintf (stderr, "\tTyped element - type '%s'\n", pattern->typeptr->name); } /* Fall through. */ case SCHEMA_CTYPE_CHOICE: case SCHEMA_CTYPE_INTERLEAVE: fprintf (stderr, "\t%d children\n", pattern->nc); break; case SCHEMA_CTYPE_ANY: if (pattern->namespace) { fprintf (stderr, "\tNamespace: '%s'\n", pattern->namespace); } if (pattern->typedata) { fprintf (stderr, "\t%d namespaces\n", ((Tcl_HashTable*)pattern->typedata)->numEntries); } break; case SCHEMA_CTYPE_TEXT: case SCHEMA_CTYPE_VIRTUAL: case SCHEMA_CTYPE_JSON_STRUCT: /* Do nothing */ break; } } static void serializeQuant ( SchemaQuant quant ) { fprintf (stderr, "Quant type: %s\n", Schema_Quant_Type2str[quant]); } static int getDeep ( SchemaValidationStack *se ) { int i = 0; while (se) { if (se->pattern->type == SCHEMA_CTYPE_NAME) i++; se = se->down; } return i; } static void serializeStack ( SchemaData *sdata ) { SchemaValidationStack *se; fprintf (stderr, "++++ Current validation stack:\n"); se = sdata->stack; while (se) { serializeCP (se->pattern); fprintf (stderr, "\tdeep: %d ac: %d hm: %d\n", getDeep (se), se->activeChild, se->hasMatched); se = se->down; } fprintf (stderr, "++++ Stack bottom\n"); } ) /* DBG end */ static void freedomKeyConstraints ( domKeyConstraint *kc ) { domKeyConstraint *knext; int i; while (kc) { knext = kc->next; if (kc->name) FREE (kc->name); if (kc->emptyFieldSetValue) FREE (kc->emptyFieldSetValue); xpathFreeAst (kc->selector); for (i = 0; i < kc->nrFields; i++) { xpathFreeAst (kc->fields[i]); } FREE (kc->fields); FREE (kc); kc = knext; } } static void freeSchemaCP ( SchemaCP *pattern ) { unsigned int i; SchemaConstraint *sc; switch (pattern->type) { case SCHEMA_CTYPE_ANY: if (pattern->typedata) { Tcl_DeleteHashTable ((Tcl_HashTable *) pattern->typedata); FREE (pattern->typedata); } break; case SCHEMA_CTYPE_VIRTUAL: for (i = 0; i < pattern->nc; i++) { Tcl_DecrRefCount ((Tcl_Obj *)pattern->content[i]); } FREE (pattern->content); break; case SCHEMA_CTYPE_TEXT: for (i = 0; i < pattern->nc; i++) { sc = (SchemaConstraint *) pattern->content[i]; if (sc->freeData) { (sc->freeData) (sc->constraintData); } FREE (pattern->content[i]); } /* fall through */ default: if (pattern->flags & TYPED_ELEMENT) break; FREE (pattern->content); FREE (pattern->quants); if (pattern->attrs) { for (i = 0; i < pattern->numAttr; i++) { FREE (pattern->attrs[i]); } FREE (pattern->attrs); } freedomKeyConstraints (pattern->domKeys); if (pattern->type != SCHEMA_CTYPE_JSON_STRUCT && pattern->typedata) { Tcl_DeleteHashTable ((Tcl_HashTable *) pattern->typedata); FREE (pattern->typedata); } break; } if (pattern->defScript) { Tcl_DecrRefCount (pattern->defScript); } if (pattern->associated) { Tcl_DecrRefCount (pattern->associated); } FREE (pattern); } static SchemaData* initSchemaData ( Tcl_Obj *cmdNameObj) { SchemaData *sdata; domLength len; char *name; sdata = TMALLOC (SchemaData); memset (sdata, 0, sizeof(SchemaData)); name = Tcl_GetStringFromObj (cmdNameObj, &len); sdata->self = Tcl_NewStringObj (name, len); Tcl_IncrRefCount (sdata->self); Tcl_InitHashTable (&sdata->element, TCL_STRING_KEYS); Tcl_InitHashTable (&sdata->elementType, TCL_STRING_KEYS); Tcl_InitHashTable (&sdata->elementTypeInstance, TCL_ONE_WORD_KEYS); Tcl_InitHashTable (&sdata->prefix, TCL_STRING_KEYS); Tcl_InitHashTable (&sdata->pattern, TCL_STRING_KEYS); Tcl_InitHashTable (&sdata->attrNames, TCL_STRING_KEYS); Tcl_InitHashTable (&sdata->namespace, TCL_STRING_KEYS); Tcl_InitHashTable (&sdata->textDef, TCL_STRING_KEYS); sdata->patternList = (SchemaCP **) MALLOC ( sizeof (SchemaCP*) * ANON_PATTERN_ARRAY_SIZE_INIT); sdata->patternListSize = ANON_PATTERN_ARRAY_SIZE_INIT; /* evalStub initialization */ sdata->evalStub = (Tcl_Obj **) MALLOC (sizeof (Tcl_Obj*) * 4); sdata->evalStub[0] = Tcl_NewStringObj("::namespace", 11); Tcl_IncrRefCount (sdata->evalStub[0]); sdata->evalStub[1] = Tcl_NewStringObj("eval", 4); Tcl_IncrRefCount (sdata->evalStub[1]); sdata->evalStub[2] = Tcl_NewStringObj("::tdom::schema", 14); Tcl_IncrRefCount (sdata->evalStub[2]); /* textStub initialization */ sdata->textStub = (Tcl_Obj **) MALLOC (sizeof (Tcl_Obj*) * 4); sdata->textStub[0] = Tcl_NewStringObj("::namespace", 11); Tcl_IncrRefCount (sdata->textStub[0]); sdata->textStub[1] = Tcl_NewStringObj("eval", 4); Tcl_IncrRefCount (sdata->textStub[1]); sdata->textStub[2] = Tcl_NewStringObj("::tdom::schema::text", 20); Tcl_IncrRefCount (sdata->textStub[2]); sdata->cdata = TMALLOC (Tcl_DString); Tcl_DStringInit (sdata->cdata); Tcl_InitHashTable (&sdata->ids, TCL_STRING_KEYS); sdata->unknownIDrefs = 0; Tcl_InitHashTable (&sdata->idTables, TCL_STRING_KEYS); Tcl_InitHashTable (&sdata->keySpaces, TCL_STRING_KEYS); sdata->choiceHashThreshold = TDOM_CHOICE_HASH_THRESHOLD; sdata->attributeHashThreshold = TDOM_ATTRIBUTE_HASH_THRESHOLD; return sdata; } static void schemaInstanceDelete ( ClientData clientData ) { SchemaData *sdata = (SchemaData *) clientData; unsigned int i; SchemaValidationStack *down; Tcl_HashEntry *h; Tcl_HashSearch search; SchemaDocKey *dk; SchemaKeySpace *ks; /* Protect the clientData to be freed inside (even nested) * Tcl_Eval*() calls to avoid invalid mem access and postpone the * cleanup until the Tcl_Eval*() calls are finished (done in * tDOM_schemaInstanceCmd()). */ if (sdata->currentEvals || sdata->inuse > 0) { sdata->cleanupAfterUse = 1; return; } Tcl_DecrRefCount (sdata->self); if (sdata->start) FREE (sdata->start); if (sdata->prefixns) { i = 0; while (sdata->prefixns[i]) { FREE (sdata->prefixns[i]); i++; } FREE (sdata->prefixns); } Tcl_DeleteHashTable (&sdata->namespace); Tcl_DeleteHashTable (&sdata->element); Tcl_DeleteHashTable (&sdata->elementType); Tcl_DeleteHashTable (&sdata->elementTypeInstance); Tcl_DeleteHashTable (&sdata->prefix); Tcl_DeleteHashTable (&sdata->pattern); Tcl_DeleteHashTable (&sdata->attrNames); Tcl_DeleteHashTable (&sdata->textDef); for (i = 0; i < sdata->numPatternList; i++) { freeSchemaCP (sdata->patternList[i]); } FREE (sdata->patternList); FREE (sdata->quants); while (sdata->stack) { down = sdata->stack->down; if (sdata->stack->interleaveState) FREE (sdata->stack->interleaveState); FREE (sdata->stack); sdata->stack = down; } while (sdata->lastMatchse) { down = sdata->lastMatchse->down; if (sdata->lastMatchse->interleaveState) FREE (sdata->lastMatchse->interleaveState); FREE (sdata->lastMatchse); sdata->lastMatchse = down; } while (sdata->stackPool) { down = sdata->stackPool->down; /* interleaveState always got cleaned up at putting se back to * pool */ FREE (sdata->stackPool); sdata->stackPool = down; } Tcl_DecrRefCount (sdata->evalStub[0]); Tcl_DecrRefCount (sdata->evalStub[1]); Tcl_DecrRefCount (sdata->evalStub[2]); FREE (sdata->evalStub); Tcl_DecrRefCount (sdata->textStub[0]); Tcl_DecrRefCount (sdata->textStub[1]); Tcl_DecrRefCount (sdata->textStub[2]); FREE (sdata->textStub); Tcl_DStringFree (sdata->cdata); FREE (sdata->cdata); if (sdata->reportCmd) { Tcl_DecrRefCount (sdata->reportCmd); } Tcl_DeleteHashTable (&sdata->ids); for (h = Tcl_FirstHashEntry (&sdata->idTables, &search); h != NULL; h = Tcl_NextHashEntry (&search)) { dk = Tcl_GetHashValue (h); Tcl_DeleteHashTable (&dk->ids); FREE (dk); } Tcl_DeleteHashTable (&sdata->idTables); for (h = Tcl_FirstHashEntry (&sdata->keySpaces, &search); h != NULL; h = Tcl_NextHashEntry (&search)) { ks = Tcl_GetHashValue (h); if (ks->active) { Tcl_DeleteHashTable (&ks->ids); } FREE (ks); } Tcl_DeleteHashTable (&sdata->keySpaces); if (sdata->wsbufLen) { FREE (sdata->wsbuf); } FREE (sdata); } static void cleanupLastPattern ( SchemaData *sdata, unsigned int from ) { unsigned int i, j, k, freed, isElement; char *name; Tcl_HashTable *hashTable; Tcl_HashEntry *h, *h1; SchemaCP *this, *previous, *current, *typePattern, *this1; for (i = from; i < sdata->numPatternList; i++) { this = sdata->patternList[i]; hashTable = NULL; isElement = 0; name = this->name; if (this->type == SCHEMA_CTYPE_NAME) { /* Local defined elements aren't saved under their local * name bucket in the sdata->element hash table. */ if (this->flags & LOCAL_DEFINED_ELEMENT) { freeSchemaCP (sdata->patternList[i]); continue; } if (this->flags & ELEMENTTYPE_DEF) { hashTable = &sdata->elementType; } else if (this->flags & TYPED_ELEMENT) { hashTable = &sdata->elementTypeInstance; if (this->flags & HASH_ENTRY_DELETED) { freeSchemaCP (sdata->patternList[i]); continue; } } else { hashTable = &sdata->element; isElement = 1; } } else if (this->type == SCHEMA_CTYPE_PATTERN) { hashTable = &sdata->pattern; } if (name && hashTable) { if (this->flags & FORWARD_PATTERN_DEF) { sdata->forwardPatternDefs--; } h = Tcl_FindHashEntry (hashTable, name); if (h) { previous = NULL; current = Tcl_GetHashValue (h); while (current != NULL && current != this) { previous = current; current = current->next; } if (current) { if (previous) { if (current->next) { previous->next = current->next; } else { previous->next = NULL; } } else { if (current->next) { Tcl_SetHashValue (h, current->next); } else { if (isElement) { /* Typed elements with the same name * use the pointer to the key string * of the below deleted hash entry in * the name element of the pattern * structure. Additionally the pointer * to the key string is used as key in * the elementTypeInstance hash table. * We mark every element instance * pattern stored in * elementTypeInstance under this key * and delete the entry. */ h1 = Tcl_FindHashEntry ( &sdata->elementTypeInstance, name ); if (h1) { this1 = (SchemaCP *) Tcl_GetHashValue (h1); while (this1) { this1->flags |= HASH_ENTRY_DELETED; this1 = this1->next; } Tcl_DeleteHashEntry (h1); } } Tcl_DeleteHashEntry (h); } } } } if (this->flags & TYPED_ELEMENT) { /* If the type of the element is forward defined, then * the pointer to the below freed cp is noted in the * forward type definition. Clean that up. */ /* First step: Check, if the typePtr is still valid. */ freed = 0; for (j = from; j < i; j++) { if (this->typeptr == sdata->patternList[j]) { freed = 1; break; } } if (!freed) { typePattern = this->typeptr; if (typePattern->flags & FORWARD_PATTERN_DEF) { for (k = 0; k < typePattern->nc; k++) { if (this == typePattern->content[k]) { /* Later noted pattern are allocated * later than this and will be freed * later on in this cleanupLastPattern * call, so this is safe and * efficient. */ typePattern->nc = k; break; } } } } } } freeSchemaCP (sdata->patternList[i]); } sdata->numPatternList = from; } static void addToContent ( SchemaData *sdata, SchemaCP *pattern, SchemaQuant quant, int n, int m ) { SchemaCP *wrapperCP; SchemaCP *savedCP = NULL; unsigned int savedContenSize; if (sdata->cp->type == SCHEMA_CTYPE_NAME && sdata->cp->flags & CONSTRAINT_TEXT_CHILD && (pattern->type != SCHEMA_CTYPE_TEXT || pattern->nc == 0)) { sdata->cp->flags &= ~CONSTRAINT_TEXT_CHILD; } if (sdata->cp->type == SCHEMA_CTYPE_CHOICE || sdata->cp->type == SCHEMA_CTYPE_INTERLEAVE) { if (pattern->type == SCHEMA_CTYPE_CHOICE) { if (pattern->flags & MIXED_CONTENT) { sdata->cp->flags |= MIXED_CONTENT; } wrapperCP = initSchemaCP (SCHEMA_CTYPE_PATTERN, NULL, NULL); REMEMBER_PATTERN (wrapperCP); wrapperCP->content[0] = pattern; wrapperCP->quants[0] = SCHEMA_CQUANT_ONE; wrapperCP->nc = 1; pattern = wrapperCP; } if (sdata->cp->type == SCHEMA_CTYPE_CHOICE && quant != SCHEMA_CQUANT_ONE) { wrapperCP = initSchemaCP (SCHEMA_CTYPE_PATTERN, NULL, NULL); REMEMBER_PATTERN (wrapperCP); if (sdata->cp->nc == sdata->contentSize) { sdata->cp->content = REALLOC (sdata->cp->content, 2 * sdata->contentSize * sizeof (SchemaCP*)); sdata->cp->quants = REALLOC (sdata->cp->quants, 2 * sdata->contentSize * sizeof (SchemaQuant)); sdata->contentSize *= 2; } sdata->cp->content[sdata->cp->nc] = wrapperCP; sdata->cp->quants[sdata->cp->nc] = SCHEMA_CQUANT_ONE; sdata->cp->nc++; savedCP = sdata->cp; savedContenSize = sdata->contentSize; sdata->cp = wrapperCP; sdata->contentSize = CONTENT_ARRAY_SIZE_INIT; } } if (quant == SCHEMA_CQUANT_NM) { int i, newChilds, thisquant; if (m == -1) { m = n + 1; newChilds = m; thisquant = SCHEMA_CQUANT_REP; } else { newChilds = (n >= m) ? n : m; thisquant = SCHEMA_CQUANT_OPT; } while (sdata->cp->nc + newChilds >= sdata->contentSize) { sdata->cp->content = REALLOC (sdata->cp->content, 2 * sdata->contentSize * sizeof (SchemaCP*)); sdata->cp->quants = REALLOC (sdata->cp->quants, 2 * sdata->contentSize * sizeof (SchemaQuant)); sdata->contentSize *= 2; } for (i = 0; i < n; i++) { sdata->cp->content[sdata->cp->nc+i] = pattern; sdata->cp->quants[sdata->cp->nc+i] = SCHEMA_CQUANT_ONE; } for (i = n; i < m; i++) { sdata->cp->content[sdata->cp->nc+i] = pattern; sdata->cp->quants[sdata->cp->nc+i] = thisquant; } sdata->cp->nc = sdata->cp->nc + newChilds; } else { if (sdata->cp->nc == sdata->contentSize) { sdata->cp->content = REALLOC (sdata->cp->content, 2 * sdata->contentSize * sizeof (SchemaCP*)); sdata->cp->quants = REALLOC (sdata->cp->quants, 2 * sdata->contentSize * sizeof (SchemaQuant)); sdata->contentSize *= 2; } sdata->cp->content[sdata->cp->nc] = pattern; sdata->cp->quants[sdata->cp->nc] = quant; sdata->cp->nc++; } if (savedCP) { sdata->cp = savedCP; sdata->contentSize = savedContenSize; } } static SchemaValidationStack * getStackElement ( SchemaData *sdata, SchemaCP *pattern ) { SchemaValidationStack *stackElm; if (sdata->stackPool) { stackElm = sdata->stackPool; sdata->stackPool = stackElm->down; } else { stackElm = TMALLOC (SchemaValidationStack); } memset (stackElm, 0, sizeof (SchemaValidationStack)); stackElm->pattern = pattern; return stackElm; } static void repoolStackElement ( SchemaData *sdata, SchemaValidationStack *se ) { if (se->interleaveState) { FREE (se->interleaveState); se->interleaveState = NULL; } se->down = sdata->stackPool; sdata->stackPool = se; } static void pushToStack ( SchemaData *sdata, SchemaCP *pattern ) { SchemaValidationStack *se, *nextse; DBG(fprintf(stderr, "push to Stack:\n");serializeCP(pattern)); if (pattern->type == SCHEMA_CTYPE_NAME && sdata->lastMatchse) { se = sdata->lastMatchse; while (se) { nextse = se->down; repoolStackElement (sdata, se); se = nextse; } sdata->lastMatchse = NULL; } se = getStackElement (sdata, pattern); se->down = sdata->stack; if (pattern->type == SCHEMA_CTYPE_INTERLEAVE) { se->interleaveState = MALLOC (sizeof (int) * pattern->nc); memset (se->interleaveState, 0, sizeof (int) * pattern->nc); } sdata->stack = se; } static void popFromStack ( SchemaData *sdata, SchemaValidationStack **stack ) { SchemaValidationStack *se; DBG(fprintf(stderr, "popFromStack:\n"); serializeCP((*stack)->pattern)); se = (*stack)->down; repoolStackElement (sdata, *stack); *stack = se; } static void popStack ( SchemaData *sdata ) { SchemaValidationStack *se, *nextse; DBG(fprintf(stderr, "popStack:\n"); serializeCP(sdata->stack->pattern)); if (sdata->stack->pattern->type == SCHEMA_CTYPE_NAME) { se = sdata->lastMatchse; while (se) { nextse = se->down; repoolStackElement (sdata, se); se = nextse; } sdata->lastMatchse = NULL; se = sdata->stack->down; repoolStackElement (sdata, sdata->stack); sdata->stack = se; } else { if (sdata->stack->hasMatched) { se = sdata->stack->down; sdata->stack->down = sdata->lastMatchse; sdata->lastMatchse = sdata->stack; sdata->stack = se; } else { se = sdata->stack->down; repoolStackElement (sdata, sdata->stack); sdata->stack = se; } } } static void finalizeElement ( SchemaData *sdata, int ac ) { SchemaValidationStack *se; SchemaCP *cp, *cp1; unsigned int i; se = sdata->stack; cp = se->pattern; if (cp->type == SCHEMA_CTYPE_NAME || cp->type == SCHEMA_CTYPE_PATTERN) { for (i = ac; i < cp->nc; i++) { cp1 = cp->content[ac]; if (cp1->type == SCHEMA_CTYPE_KEYSPACE) { if (!cp1->keySpace->active) { Tcl_InitHashTable (&cp1->keySpace->ids, TCL_STRING_KEYS); cp1->keySpace->active = 1; cp1->keySpace->unknownIDrefs = 0; } else { cp1->keySpace->active++; } } else if (cp->content[ac]->type == SCHEMA_CTYPE_KEYSPACE_END) { cp1->keySpace->active--; if (!cp1->keySpace->active) { cp1->keySpace->unknownIDrefs = 0; Tcl_DeleteHashTable (&cp1->keySpace->ids); } } } } popStack (sdata); /* cp is still the pattern from stack top before the popStack */ if (cp->type != SCHEMA_CTYPE_NAME) { finalizeElement (sdata, sdata->stack->activeChild + 1); } } static void rewindStack ( SchemaData *sdata ) { SchemaValidationStack *se; while (sdata->lastMatchse) { se = sdata->lastMatchse; sdata->lastMatchse = se->down; se->down = sdata->stack; sdata->stack = se; } } static int recover ( Tcl_Interp *interp, SchemaData *sdata, ValidationErrorType errorType, ValidationAction action, const char *name, const char *ns, char *text, int ac ) { Tcl_Obj *cmdPtr; int rc; SchemaValidationStack *se; if (!sdata->reportCmd || sdata->evalError) return 0; if (sdata->recoverFlags & RECOVER_FLAG_DONT_REPORT) return 1; /* If non SCHEMA_CTYPE_NAME and the pattern hasn't already matched * that's a pattern pushed on stack to look for (probe) if it * matches (or allows empty match). Even if the pattern fail it * may be optional; recovering is done at the caller level in case * the pattern isn't optional. */ if (sdata->stack && sdata->stack->pattern->type != SCHEMA_CTYPE_NAME && sdata->stack->activeChild == 0 && sdata->stack->hasMatched == 0) return 0; cmdPtr = Tcl_DuplicateObj (sdata->reportCmd); Tcl_IncrRefCount(cmdPtr); Tcl_ListObjAppendElement (interp, cmdPtr, sdata->self); Tcl_ListObjAppendElement ( interp, cmdPtr, Tcl_NewStringObj (ValidationErrorType2str[errorType], -1) ); /* In case of unknown element the name/ns arguments of recover() * are NULL, but sdata->vname/sdata->vns are already * pre-filled. */ if (name) sdata->vname = name; if (ns) sdata->vns = ns; sdata->vtext = text; sdata->vaction = action; switch (errorType) { case INVALID_JSON_TYPE: case MISSING_TEXT: case INVALID_KEYREF: case INVALID_VALUE: if (sdata->stack) { se = sdata->stack; while (se->pattern->type != SCHEMA_CTYPE_NAME) { se = se->down; } sdata->vname = se->pattern->name; sdata->vns = se->pattern->namespace; } break; case MISSING_ELEMENT: if (action == MATCH_ELEMENT_END) { if (sdata->stack) { se = sdata->stack; while (se->pattern->type != SCHEMA_CTYPE_NAME) { se = se->down; } sdata->vname = se->pattern->name; sdata->vns = se->pattern->namespace; } } break; default: break; } sdata->currentEvals++; rc = Tcl_EvalObjEx (interp, cmdPtr, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); sdata->currentEvals--; sdata->vaction = 0; if (name) sdata->vname = name; if (ns) sdata->vns = ns; sdata->vtext = NULL; Tcl_DecrRefCount (cmdPtr); if (rc != TCL_OK) { sdata->evalError = 1; return 0; } switch (errorType) { case MISSING_ELEMENT: if (action == MATCH_ELEMENT_START) { if (strcmp (Tcl_GetStringResult (interp), "ignore") == 0) { sdata->recoverFlags |= RECOVER_FLAG_IGNORE; return 1; } else if (strcmp (Tcl_GetStringResult (interp), "vanish") == 0) { sdata->recoverFlags |= RECOVER_FLAG_REWIND; sdata->skipDeep = 1; return 1; } else { /* Rewind stack to last match and ignore the just opened * Element. */ finalizeElement (sdata, ac+1); sdata->skipDeep = 2; } } else if (action == MATCH_ELEMENT_END) { if (strcmp (Tcl_GetStringResult (interp), "ignore") == 0) { sdata->recoverFlags |= RECOVER_FLAG_MATCH_END_CONTINUE; } else { sdata->recoverFlags |= RECOVER_FLAG_DONT_REPORT; } } break; case MISSING_TEXT: if (action == MATCH_ELEMENT_END) { if (strcmp (Tcl_GetStringResult (interp), "ignore") == 0) { sdata->recoverFlags |= RECOVER_FLAG_MATCH_END_CONTINUE; } else { sdata->recoverFlags |= RECOVER_FLAG_DONT_REPORT; } } break; case UNEXPECTED_ELEMENT: if (strcmp (Tcl_GetStringResult (interp), "vanish") == 0) { sdata->recoverFlags |= RECOVER_FLAG_REWIND; sdata->skipDeep = 1; return 1; } else { finalizeElement (sdata, ac+1); sdata->skipDeep = 2; } break; case UNEXPECTED_TEXT: sdata->recoverFlags |= RECOVER_FLAG_REWIND; break; default: break; } return 1; } /* The cp argument must be type SCHEMA_CTYPE_TEXT */ int tDOM_checkText ( Tcl_Interp *interp, void *clientData, char *text ) { unsigned int i; SchemaCP *cp = (SchemaCP *) clientData; SchemaConstraint *sc; /* Look also at oneOfImpl */ for (i = 0; i < cp->nc; i++) { sc = (SchemaConstraint *) cp->content[i]; if (!(sc->constraint) (interp, sc->constraintData, text)) { return 0; } } return 1; } /* The argument ac points to the child of the current top-most stack * element pattern which is to evaluate. */ static int evalVirtual ( Tcl_Interp *interp, SchemaData *sdata, int ac ) { int rc; SchemaCP *cp; cp = sdata->stack->pattern->content[ac]; sdata->currentEvals++; rc = Tcl_EvalObjv (interp, cp->nc, (Tcl_Obj **) cp->content, TCL_EVAL_GLOBAL); sdata->currentEvals--; if (rc != TCL_OK) { sdata->evalError = 1; return 0; } return 1; } /* Check, if the pattern to probe does not call itself (even * indirectly) without a match inbetween.*/ static TDOM_INLINE int recursivePattern ( SchemaValidationStack *se, SchemaCP *pattern ) { int rc = 0; while (se && se->pattern->type != SCHEMA_CTYPE_NAME) { if (!se->hasMatched && se->pattern == pattern) { rc = 1; break; } se = se->down; } return rc; } static int checkJsonStructType ( Tcl_Interp *interp, SchemaData *sdata, SchemaCP *cp, ValidationErrorType errorType, ValidationAction action, int ac ) { jsonStructType jsonType; char *str; Tcl_Obj *strObj; if (!sdata->insideNode) return 1; jsonType = (intptr_t) cp->typedata; switch (jsonType) { case jt_none: if (sdata->insideNode->info > 0 && sdata->insideNode->info < 8) goto error; break; case jt_object: if (sdata->insideNode->info != JSON_OBJECT) goto error; break; case jt_array: if (sdata->insideNode->info != JSON_ARRAY) goto error; break; default: SetResult ("Internal error: invalid JSON structure type!"); sdata->evalError = 1; return 0; } return 1; error: if (!recover (interp, sdata, errorType, action, sdata->insideNode->nodeName, domNamespaceURI(sdata->insideNode), NULL, ac)) { str = xpathNodeToXPath (sdata->insideNode, 0); strObj = Tcl_NewStringObj (str, -1); Tcl_AppendStringsToObj (strObj, ": Wrong JSON type", NULL); Tcl_SetObjResult (interp, strObj); FREE (str); sdata->evalError = 2; return 0; } return 1; } static int matchingAny ( char *namespace, SchemaCP *candidate ) { Tcl_HashEntry *h; if (candidate->flags & ANY_NOT) { if (candidate->namespace || candidate->typedata) { /* The any wildcard is limited to one or several * namespaces (the empty namespace may be one of * them). */ if (namespace) { if (candidate->typedata) { h = Tcl_FindHashEntry ( (Tcl_HashTable *)candidate->typedata, namespace); if (h) return 0; } else { if (candidate->namespace == namespace) { return 0; } } } else { if (candidate->namespace == emptyStr) { return 0; } } } return 1; } else { if (candidate->namespace || candidate->typedata) { /* The any wildcard is limited to one or several * namespaces (the empty namespace may be one of * them). */ if (namespace) { if (candidate->typedata) { h = Tcl_FindHashEntry ( (Tcl_HashTable *)candidate->typedata, namespace); if (!h) return 0; } else { if (candidate->namespace != namespace) { return 0; } } } else { if (candidate->namespace != emptyStr) { return 0; } } } return 1; } } static int matchElementStart ( Tcl_Interp *interp, SchemaData *sdata, char *name, char *namespace ) { SchemaCP *cp, *candidate, *icp; int hm, mayskip, thismayskip, rc, isName = 0; unsigned int ac, i; SchemaValidationStack *se; Tcl_HashEntry *h; if (!sdata->stack) return 0; se = sdata->stack; getContext (cp, ac, hm); switch (cp->type) { case SCHEMA_CTYPE_NAME: isName = 1; /* fall through */ case SCHEMA_CTYPE_PATTERN: while (ac < cp->nc) { candidate = cp->content[ac]; mayskip = 0; switch (candidate->type) { case SCHEMA_CTYPE_TEXT: if (candidate->nc) { if (!checkText (interp, candidate, "")) { if (recover (interp, sdata, MISSING_TEXT, MATCH_ELEMENT_START, name, namespace, NULL, ac)) { mayskip = 1; break; } return 0; } } break; case SCHEMA_CTYPE_ANY: if (!matchingAny (namespace, candidate)) break; updateStack (sdata, se, ac); sdata->skipDeep = 1; /* See comment in tDOM_probeElement: sdata->vname and * sdata->vns may be pre-filled. We reset it here.*/ sdata->vname = NULL; sdata->vns = NULL; return 1; case SCHEMA_CTYPE_NAME: DBG(fprintf (stderr, "name: %s ns: %s candidate name: %s " "candidate ns: %s\n", name, namespace, candidate->name, candidate->namespace)); if (candidate->name == name && candidate->namespace == namespace) { pushToStack (sdata, candidate); updateStack (sdata, se, ac); return 1; } break; case SCHEMA_CTYPE_CHOICE: if (candidate->typedata) { h = Tcl_FindHashEntry ((Tcl_HashTable *)candidate->typedata, name); if (h) { icp = Tcl_GetHashValue (h); if (icp->namespace == namespace) { pushToStack (sdata, icp); updateStack (sdata, se, ac); return 1; } } /* TODO: Short-cut in case of no match (looking * for empty match, recovering). For now fall * throu to simple, serial approach. */ } for (i = 0; i < candidate->nc; i++) { icp = candidate->content[i]; switch (icp->type) { case SCHEMA_CTYPE_TEXT: break; case SCHEMA_CTYPE_ANY: if (!matchingAny (namespace, icp)) break; updateStack (sdata, se, ac); sdata->skipDeep = 1; /* See comment in tDOM_probeElement: sdata->vname * and sdata->vns may be pre-filled. We reset it * here.*/ sdata->vname = NULL; sdata->vns = NULL; return 1; case SCHEMA_CTYPE_NAME: if (icp->name == name && icp->namespace == namespace) { pushToStack (sdata, icp); updateStack (sdata, se, ac); return 1; } break; case SCHEMA_CTYPE_CHOICE: SetResult ("MIXED or CHOICE child of MIXED or CHOICE"); sdata->evalError = 1; return 0; case SCHEMA_CTYPE_PATTERN: if (recursivePattern (se, icp)) { mayskip = 1; continue; } /* fall through */ case SCHEMA_CTYPE_INTERLEAVE: pushToStack (sdata, icp); rc = matchElementStart (interp, sdata, name, namespace); if (rc == 1) { updateStack (sdata, se, ac); return 1; } popStack (sdata); if (rc == -1) mayskip = 1; break; case SCHEMA_CTYPE_VIRTUAL: SetResult ("Virtual constrain in MIXED or CHOICE"); sdata->evalError = 1; return 0; case SCHEMA_CTYPE_KEYSPACE_END: case SCHEMA_CTYPE_KEYSPACE: SetResult ("Keyspace constrain in MIXED or CHOICE"); sdata->evalError = 1; return 0; case SCHEMA_CTYPE_JSON_STRUCT: SetResult ("JSON structure constrain in MIXED or CHOICE"); sdata->evalError = 2; return 0; } if (!mayskip && mayMiss (candidate->quants[i])) mayskip = 1; } break; case SCHEMA_CTYPE_VIRTUAL: if (evalVirtual (interp, sdata, ac)) { hm = 1; break; } else return 0; case SCHEMA_CTYPE_JSON_STRUCT: if (!checkJsonStructType ( interp, sdata, candidate, INVALID_JSON_TYPE, MATCH_ELEMENT_START, ac) ) { return 0; }; ac++; hm = 0; continue; case SCHEMA_CTYPE_PATTERN: if (recursivePattern (se, candidate)) { mayskip = 1; break; } /* fall through */ case SCHEMA_CTYPE_INTERLEAVE: pushToStack (sdata, candidate); rc = matchElementStart (interp, sdata, name, namespace); if (rc == 1) { updateStack (sdata, se, ac); return 1; } popStack (sdata); if (rc == -1) mayskip = 1; break; case SCHEMA_CTYPE_KEYSPACE_END: candidate->keySpace->active--; if (!candidate->keySpace->active) { if (candidate->keySpace->unknownIDrefs) { if (!recover (interp, sdata, INVALID_KEYREF, MATCH_ELEMENT_START, name, namespace, NULL, ac)) { SetResultV ("Invalid key ref."); sdata->evalError = 2; return 0; } candidate->keySpace->unknownIDrefs = 0; } Tcl_DeleteHashTable (&candidate->keySpace->ids); } ac++; hm = 0; continue; case SCHEMA_CTYPE_KEYSPACE: if (!candidate->keySpace->active) { Tcl_InitHashTable (&candidate->keySpace->ids, TCL_STRING_KEYS); candidate->keySpace->active = 1; candidate->keySpace->unknownIDrefs = 0; } else { candidate->keySpace->active++; } ac++; hm = 0; continue; } if (!mayskip && mustMatch (cp->quants[ac], hm)) { if (recover (interp, sdata, MISSING_ELEMENT, MATCH_ELEMENT_START, name, namespace, NULL, ac)) { if (sdata->recoverFlags & RECOVER_FLAG_IGNORE) { /* We pretend the ac content particle had * matched. */ updateStack (sdata, se, ac); } return 1; } return 0; } ac++; hm = 0; } if (isName) { if (recover (interp, sdata, UNEXPECTED_ELEMENT, MATCH_ELEMENT_START, name, namespace, NULL, 0)) { return 1; } return 0; } return -1; case SCHEMA_CTYPE_KEYSPACE: case SCHEMA_CTYPE_KEYSPACE_END: case SCHEMA_CTYPE_VIRTUAL: case SCHEMA_CTYPE_CHOICE: case SCHEMA_CTYPE_TEXT: case SCHEMA_CTYPE_ANY: case SCHEMA_CTYPE_JSON_STRUCT: /* Never pushed onto stack */ SetResult ("Invalid CTYPE onto the validation stack!"); sdata->evalError = 1; return 0; case SCHEMA_CTYPE_INTERLEAVE: mayskip = 1; for (i = 0; i < cp->nc; i++) { thismayskip = 0; if (se->interleaveState[i]) { if (maxOne (cp->quants[i])) continue; } icp = cp->content[i]; switch (icp->type) { case SCHEMA_CTYPE_TEXT: if (icp->nc) { if (checkText (interp, icp, "")) { thismayskip = 1; } } else { thismayskip = 1; } break; case SCHEMA_CTYPE_ANY: if (!matchingAny (namespace, icp)) break; sdata->skipDeep = 1; se->hasMatched = 1; se->interleaveState[i] = 1; /* See comment in tDOM_probeElement: sdata->vname and * sdata->vns may be pre-filled. We reset it here.*/ sdata->vname = NULL; sdata->vns = NULL; return 1; case SCHEMA_CTYPE_NAME: if (icp->name == name && icp->namespace == namespace) { pushToStack (sdata, icp); se->hasMatched = 1; se->interleaveState[i] = 1; return 1; } break; case SCHEMA_CTYPE_CHOICE: SetResult ("MIXED or CHOICE child of INTERLEAVE"); sdata->evalError = 1; return 0; case SCHEMA_CTYPE_PATTERN: if (recursivePattern (se, icp)) { thismayskip = 1; break; } /* fall through */ case SCHEMA_CTYPE_INTERLEAVE: pushToStack (sdata, icp); rc = matchElementStart (interp, sdata, name, namespace); if (rc == 1) { if (!(sdata->recoverFlags & RECOVER_FLAG_REWIND)) { se->hasMatched = 1; se->interleaveState[i] = 1; } return 1; } popStack (sdata); if (rc == -1) thismayskip = 1; break; case SCHEMA_CTYPE_VIRTUAL: SetResult ("Virtual constraint child of INTERLEAVE"); sdata->evalError = 1; return 0; case SCHEMA_CTYPE_KEYSPACE_END: case SCHEMA_CTYPE_KEYSPACE: SetResult ("Keyspace constraint child of INTERLEAVE"); sdata->evalError = 1; return 0; case SCHEMA_CTYPE_JSON_STRUCT: SetResult ("JSON structure constraint child of INTERLEAVE"); sdata->evalError = 1; return 0; } if (!thismayskip && minOne (cp->quants[i])) mayskip = 0; } if (mayskip) break; if (recover (interp, sdata, MISSING_ELEMENT, MATCH_ELEMENT_START, name, namespace, NULL, cp->nc)) { if (sdata->recoverFlags & RECOVER_FLAG_IGNORE) { /* We mark the first so far not matched mandatory * interleave child cp as matched */ for (i = 0; i < cp->nc; i++) { if (!se->interleaveState[i]) { if (minOne (cp->quants[i])) { se->interleaveState[i] = 1; break; } } } } return 1; } return 0; } return -1; } static void * getNamespacePtr ( SchemaData *sdata, char *ns ) { Tcl_HashEntry *h; int hnew; if (!ns) return NULL; if (ns[0] == '\0') return NULL; h = Tcl_FindHashEntry (&sdata->prefix, ns); if (h) { return Tcl_GetHashValue (h); } h = Tcl_CreateHashEntry (&sdata->namespace, ns, &hnew); return Tcl_GetHashKey (&sdata->namespace, h); } int tDOM_probeElement ( Tcl_Interp *interp, SchemaData *sdata, const char *name, void *namespace ) { Tcl_HashEntry *h; void *namespacePtr, *namePtr; SchemaCP *pattern; int rc = 1, reportError; if (sdata->skipDeep) { sdata->skipDeep++; return TCL_OK; } if (sdata->validationState == VALIDATION_FINISHED) { SetResult ("Validation finished."); return TCL_ERROR; } DBG( fprintf (stderr, "tDOM_probeElement: look if '%s' in ns '%s' match\n", name, (char *)namespace); ); if (namespace) { h = Tcl_FindHashEntry (&sdata->namespace, namespace); } else { h = NULL; } if (h) { namespacePtr = Tcl_GetHashKey (&sdata->namespace, h); } else { if (namespace) { /* This namespace isn't known at all by the schema; this * element may only match an any condition. If it does we * know only later. So we use namePtr and namespacePtr * both NULL that match nothing else in the schema and * will be able to look if there is such a possible any * match in the schema. */ rc = 0; /* If there isn't a matching any cp this is a validation * error. To have the node name/namespace information * available in case of recovering we prefill the sdata * struct here.*/ sdata->vname = name; sdata->vns = namespace; namespacePtr = (void *) unknownNS; } else { namespacePtr = NULL; } } if (!rc) { /* Already the provided namespace isn't known to the schema, * so the name in that namespace of course also. */ namePtr = NULL; } else { h = Tcl_FindHashEntry (&sdata->element, name); if (h) { namePtr = Tcl_GetHashKey (&sdata->element, h); } else { namePtr = NULL; /* Prefill in case of validation error. See above. */ sdata->vname = name; } } if (sdata->validationState == VALIDATION_READY) { /* The root of the tree to check. */ if (sdata->start) { if (strcmp (name, sdata->start) != 0) { if (recover (interp, sdata, UNEXPECTED_ROOT_ELEMENT, MATCH_ELEMENT_START, name, namespace, NULL, 0)) { sdata->validationState = VALIDATION_FINISHED; return TCL_OK; } SetResult ("Root element doesn't match"); return TCL_ERROR; } if (namespace) { if (!sdata->startNamespace|| strcmp (namespace, sdata->startNamespace) != 0) { if (recover (interp, sdata, UNEXPECTED_ROOT_ELEMENT, MATCH_ELEMENT_START, name, namespace, NULL, 0)) { sdata->validationState = VALIDATION_FINISHED; return TCL_OK; } SetResult ("Root element namespace doesn't match"); return TCL_ERROR; } } else { if (sdata->startNamespace) { if (recover (interp, sdata, UNEXPECTED_ROOT_ELEMENT, MATCH_ELEMENT_START, name, namespace, NULL, 0)) { sdata->validationState = VALIDATION_FINISHED; return TCL_OK; } SetResult ("Root element namespace doesn't match"); return TCL_ERROR; } } } reportError = 0; if (h) { pattern = (SchemaCP *) Tcl_GetHashValue (h); while (pattern) { if (pattern->namespace == namespacePtr) { if (pattern->flags & PLACEHOLDER_PATTERN_DEF || pattern->flags & FORWARD_PATTERN_DEF) { reportError = 1; } break; } pattern = pattern->next; } } else { pattern = NULL; } sdata->validationState = VALIDATION_STARTED; if (reportError || pattern == NULL) { if (recover (interp, sdata, UNKNOWN_ROOT_ELEMENT, MATCH_ELEMENT_START, name, namespace, NULL, 0)) { sdata->skipDeep = 1; return TCL_OK; } SetResult ("Unknown element"); return TCL_ERROR; } pushToStack (sdata, pattern); return TCL_OK; } /* The normal case: we're inside the tree */ /* In case of recovering and if the user wants a required cp to be * treated as matched (or in other words: that the validation * engine should ignore the mandatory state of the cp) we unwind * the call stack to have updated stack elements, to be able to * pretend, we have seen the mandatory cp. Now try to match the * open element from this stack state. */ while (1) { rc = matchElementStart (interp, sdata, (char *) namePtr, namespacePtr); while (rc == -1) { popStack (sdata); rc = matchElementStart (interp, sdata, (char *) namePtr, namespacePtr); }; if (rc) { DBG( fprintf (stderr, "tDOM_probeElement: element '%s' match\n", name); serializeStack (sdata); fprintf (stderr, "\n"); ); if (sdata->recoverFlags & RECOVER_FLAG_IGNORE) { sdata->recoverFlags &= ~RECOVER_FLAG_IGNORE; continue; } CHECK_REWIND; return TCL_OK; } break; } DBG( fprintf (stderr, "element '%s' DOESN'T match\n", name); serializeStack (sdata); fprintf (stderr, "\n"); ); if (!sdata->evalError) { SetResult ("Element \""); if (namespacePtr) { Tcl_AppendResult (interp, namespacePtr, ":", NULL); } Tcl_AppendResult (interp, name, "\" doesn't match", NULL); } return TCL_ERROR; } int probeAttribute ( Tcl_Interp *interp, SchemaData *sdata, const char *name, const char *ns, char *value, int *isrequired ) { unsigned int i; SchemaCP *cp; Tcl_HashTable *t; Tcl_HashEntry *h; SchemaAttr *attr; cp = sdata->stack->pattern; *isrequired = 0; if (cp->typedata) { t = (Tcl_HashTable *) cp->typedata; h = Tcl_FindHashEntry (t, name); if (!h) return 0; attr = (SchemaAttr *) Tcl_GetHashValue (h); while (attr && attr->namespace != ns) { attr = attr->next; } if (!attr) return 0; if (attr->cp) { if (!checkText (interp, attr->cp, value)) { if (!recover (interp, sdata, INVALID_ATTRIBUTE_VALUE, MATCH_ELEMENT_START, name, ns, value, 0)) { SetResult3V ("Attribute value doesn't match for " "attribute '", name , "'"); sdata->evalError = 2; return 0; } } } if (attr->required) *isrequired = 1; return 1; } for (i = 0; i < cp->numAttr; i++) { if (cp->attrs[i]->namespace == ns && cp->attrs[i]->name == name) { if (cp->attrs[i]->cp) { if (!checkText (interp, cp->attrs[i]->cp, value)) { if (!recover (interp, sdata, INVALID_ATTRIBUTE_VALUE, MATCH_ATTRIBUTE_TEXT, name, ns, value, i)) { SetResult3V ("Attribute value doesn't match for " "attribute '", name , "'"); sdata->evalError = 2; return 0; } } } if (cp->attrs[i]->required) *isrequired = 1; return 1; } } return 0; } int tDOM_probeAttributes ( Tcl_Interp *interp, SchemaData *sdata, const char **attr ) { char **atPtr, *ln, *namespace, *ns; int j, found, nsatt, req; unsigned int i, reqAttr = 0; SchemaCP *cp; Tcl_HashEntry *h; cp = sdata->stack->pattern; for (atPtr = (char **) attr; atPtr[0] && atPtr[1]; atPtr += 2) { found = 0; ln = atPtr[0]; j = 0; while (*ln && *ln != '\xFF') { j++, ln++; } if (*ln == '\xFF') { namespace = atPtr[0]; namespace[j] = '\0'; ln++; nsatt = 1; } else { namespace = NULL; ln = atPtr[0]; nsatt = 0; } h = Tcl_FindHashEntry (&sdata->attrNames, ln); if (!h) goto unknowncleanup; ln = Tcl_GetHashKey (&sdata->attrNames, h); ns = NULL; if (namespace) { h = Tcl_FindHashEntry (&sdata->namespace, namespace); if (!h) goto unknowncleanup; ns = Tcl_GetHashKey (&sdata->namespace, h); } found = probeAttribute (interp, sdata, ln, ns, atPtr[1], &req); if (sdata->evalError) { return TCL_ERROR; } reqAttr += req; unknowncleanup: if (!found) { if (!recover (interp, sdata, UNKNOWN_ATTRIBUTE, MATCH_ELEMENT_START, ln, namespace, NULL, 0)) { if (!sdata->evalError) { if (nsatt) { SetResult ("Unknown attribute \""); Tcl_AppendResult (interp, namespace, ":", ln, "\"", NULL); } else { SetResult3 ("Unknown attribute \"", ln, "\""); } } if (nsatt) namespace[j] = '\xFF'; return TCL_ERROR; } } if (nsatt) namespace[j] = '\xFF'; } if (reqAttr != cp->numReqAttr) { /* Lookup the missing attribute(s) */ if (!sdata->evalError) { SetResult ("Missing mandatory attribute(s):"); } for (i = 0; i < cp->numAttr; i++) { if (!cp->attrs[i]->required) continue; found = 0; for (atPtr = (char **) attr; atPtr[0] && atPtr[1]; atPtr += 2) { ln = atPtr[0]; if (cp->attrs[i]->namespace) { j = 0; while (*ln && *ln != '\xFF') { j++, ln++; } if (*ln == '\xFF') { namespace = atPtr[0]; namespace[j] = '\0'; ln++; nsatt = 1; } else { continue; } if (strcmp (cp->attrs[i]->namespace, namespace) != 0) { if (nsatt) namespace[j] = '\xFF'; continue; } if (nsatt) namespace[j] = '\xFF'; } if (strcmp (ln, cp->attrs[i]->name) == 0) { found = 1; break; } } if (!found) { if (!recover (interp, sdata, MISSING_ATTRIBUTE, MATCH_ELEMENT_START, cp->attrs[i]->name, cp->attrs[i]->namespace, NULL, i)) { if (cp->attrs[i]->namespace) { Tcl_AppendResult (interp, " ", cp->attrs[i]->namespace, ":", cp->attrs[i]->name, NULL); } else { Tcl_AppendResult (interp, " ", cp->attrs[i]->name, NULL); } } } } if (!sdata->reportCmd) { return TCL_ERROR; } } return TCL_OK; } int tDOM_probeDomAttributes ( Tcl_Interp *interp, SchemaData *sdata, domAttrNode *attr ) { domAttrNode *atPtr; int found, req; unsigned int i, reqAttr = 0; const char *ns, *ln; SchemaCP *cp; Tcl_HashEntry *h; cp = sdata->stack->pattern; atPtr = attr; while (atPtr) { if (atPtr->nodeFlags & IS_NS_NODE) goto nextAttr; found = 0; if (atPtr->namespace) { ns = domNamespaceURI ((domNode *)atPtr); /* A namespaced attribute must always have a prefix */ ln = atPtr->nodeName; while (*ln) { if (*ln == ':') { ln++; break; } ln++; } } else { ns = NULL; ln = atPtr->nodeName; } h = Tcl_FindHashEntry (&sdata->attrNames, ln); if (!h) goto unknown; ln = Tcl_GetHashKey (&sdata->attrNames, h); if (ns) { h = Tcl_FindHashEntry (&sdata->namespace, ns); if (!h) goto unknown; ns = Tcl_GetHashKey (&sdata->namespace, h); } else { ns = NULL; } found = probeAttribute (interp, sdata, ln, ns, atPtr->nodeValue, &req); reqAttr += req; unknown: if (!found) { if (!recover (interp, sdata, UNKNOWN_ATTRIBUTE, MATCH_ELEMENT_START, ln, ns, NULL, 0)) { if (!sdata->evalError) { if (ns) { SetResult ("Unknown attribute \""); Tcl_AppendResult (interp, ns, ":", atPtr->nodeName, "\"", NULL); } else { SetResult3 ("Unknown attribute \"", atPtr->nodeName, "\""); } sdata->validationState = VALIDATION_ERROR; } return TCL_ERROR; } } nextAttr: atPtr = atPtr->nextSibling; } if (reqAttr != cp->numReqAttr) { /* Lookup the missing attribute(s) */ if (!sdata->evalError) { SetResult ("Missing mandatory attribute(s):"); } for (i = 0; i < cp->numAttr; i++) { if (!cp->attrs[i]->required) continue; found = 0; atPtr = attr; while (atPtr) { if (cp->attrs[i]->namespace) { if (!atPtr->namespace) goto nextAttr2; ns = domNamespaceURI ((domNode *)atPtr); if (strcmp (ns, cp->attrs[i]->namespace) != 0) { goto nextAttr2; } ln = atPtr->nodeName; while (*ln) { if (*ln == ':') { ln++; break; } ln++; } } else { if (atPtr->namespace) goto nextAttr2; ln = atPtr->nodeName; } if (strcmp (ln, cp->attrs[i]->name) == 0) { found = 1; break; } nextAttr2: atPtr = atPtr->nextSibling; } if (!found) { if (!recover (interp, sdata, MISSING_ATTRIBUTE, MATCH_ELEMENT_START, cp->attrs[i]->name, cp->attrs[i]->namespace, NULL, i)) { if (!sdata->evalError) { if (cp->attrs[i]->namespace) { Tcl_AppendResult (interp, " ", cp->attrs[i]->namespace, ":", cp->attrs[i]->name, NULL); } else { Tcl_AppendResult (interp, " ", cp->attrs[i]->name, NULL); } } } } } if (!sdata->reportCmd) { sdata->validationState = VALIDATION_ERROR; return TCL_ERROR; } } return TCL_OK; } static int probeEventAttribute ( Tcl_Interp *interp, SchemaData *sdata, Tcl_Obj *attr, domLength len ) { int found, req; domLength i; unsigned int reqAttr = 0; char *name, *ns; SchemaCP *cp; Tcl_HashEntry *h; Tcl_Obj *attname, *attns, *attvalue; cp = sdata->stack->pattern; for (i = 0; i < len; i += 2) { found = 0; ns = NULL; name = NULL; attns = NULL; Tcl_ListObjIndex (interp, attr, i, &attname); Tcl_ListObjIndex (interp, attr, i+1, &attvalue); if (Tcl_ListObjLength (interp, attname, &len) == TCL_OK) { if (len == 2) { Tcl_ListObjIndex (interp, attname, 1, &attns); Tcl_ListObjIndex (interp, attname, 0, &attname); } } h = Tcl_FindHashEntry (&sdata->attrNames, Tcl_GetString (attname)); if (!h) goto unknown; name = Tcl_GetHashKey (&sdata->attrNames, h); if (attns) { h = Tcl_FindHashEntry (&sdata->namespace, Tcl_GetString (attns)); if (!h) goto unknown; ns = Tcl_GetHashKey (&sdata->namespace, h); } found = probeAttribute (interp, sdata, name, ns, Tcl_GetString (attvalue), &req); reqAttr += req; unknown: if (!found) { if (!recover (interp, sdata, UNKNOWN_ATTRIBUTE, MATCH_ELEMENT_START, Tcl_GetString (attname), Tcl_GetString (attns), NULL, 0)) { if (ns) { SetResult ("Unknown attribute \""); Tcl_AppendResult (interp, ns, ":", name, "\"", NULL); } else { SetResult3 ("Unknown attribute \"", name, "\""); } sdata->validationState = VALIDATION_ERROR; return TCL_ERROR; } } } if (reqAttr != cp->numReqAttr) { SetResult ("Missing mandatory attribute(s)"); return TCL_ERROR; } return TCL_OK; } /* Returns either -1, 0, 1, 2 -1 means a pattern or an interleave ended without error, look further at parents next sibling. 0 means rewind with validation error. 1 means element content may end here. 2 means recovering requested further error reporting about missing children in the current element. To be able to answer a [info expected] on the occasion of the next error, we update the stack in this case and let tDOM_probeElementEnd restart checkElementEnd again with this stack state. */ static int checkElementEnd ( Tcl_Interp *interp, SchemaData *sdata ) { SchemaValidationStack *se; SchemaCP *cp, *ic; int hm, thismayskip, mayskip = 0, rc; unsigned int ac, i; int isName = 0; DBG(fprintf (stderr, "checkElementEnd:\n"); serializeStack(sdata);); se = sdata->stack; getContext (cp, ac, hm); if (cp->type == SCHEMA_CTYPE_INTERLEAVE) { ac = 0; hm = 0; mayskip = 1; } switch (cp->type) { case SCHEMA_CTYPE_NAME: isName = 1; /* Fall through */ case SCHEMA_CTYPE_INTERLEAVE: case SCHEMA_CTYPE_PATTERN: if (ac < cp->nc && (hasMatched (cp->quants[ac], hm))) { DBG(fprintf (stderr, "ac %d has matched, skipping to next ac\n", ac)); ac++; hm = 0; } while (ac < cp->nc) { DBG(fprintf (stderr, "ac %d hm %d mayMiss: %d\n", ac, hm, mayMiss (cp->quants[ac]))); if (se->interleaveState && se->interleaveState[ac]) { ac++; continue; } if (mayMiss (cp->quants[ac])) { ac++; continue; } switch (cp->content[ac]->type) { case SCHEMA_CTYPE_KEYSPACE_END: /* Don't happen as INTERLEAVE child */ cp->content[ac]->keySpace->active--; if (!cp->content[ac]->keySpace->active) { if (cp->content[ac]->keySpace->unknownIDrefs) { if (!recover (interp, sdata, INVALID_KEYREF, MATCH_ELEMENT_END, NULL, NULL, cp->content[ac]->keySpace->name, 0)) { SetResultV ("Invalid key ref."); sdata->evalError = 2; return 0; } cp->content[ac]->keySpace->unknownIDrefs = 0; } Tcl_DeleteHashTable (&cp->content[ac]->keySpace->ids); } break; case SCHEMA_CTYPE_KEYSPACE: /* Don't happen as INTERLEAVE child */ if (!cp->content[ac]->keySpace->active) { Tcl_InitHashTable (&cp->content[ac]->keySpace->ids, TCL_STRING_KEYS); cp->content[ac]->keySpace->active = 1; cp->content[ac]->keySpace->unknownIDrefs = 0; } else { cp->content[ac]->keySpace->active++; } break; case SCHEMA_CTYPE_TEXT: if (cp->content[ac]->nc) { if (!checkText (interp, cp->content[ac], "")) { if (recover (interp, sdata, MISSING_TEXT, MATCH_ELEMENT_END, NULL, NULL, NULL, ac)) { break; } return 0; } } break; case SCHEMA_CTYPE_CHOICE: /* Don't happen as INTERLEAVE child */ thismayskip = 0; for (i = 0; i < cp->content[ac]->nc; i++) { if (mayMiss (cp->content[ac]->quants[i])) { thismayskip = 1; break; } ic = cp->content[ac]->content[i]; switch (ic->type) { case SCHEMA_CTYPE_TEXT: if (ic->nc) { if (!checkText (interp, ic, "")) { continue; } } thismayskip = 1; break; case SCHEMA_CTYPE_NAME: case SCHEMA_CTYPE_ANY: continue; case SCHEMA_CTYPE_PATTERN: if (recursivePattern (se, ic)) { thismayskip = 1; break; } /* fall through */ case SCHEMA_CTYPE_INTERLEAVE: pushToStack (sdata, ic); if (checkElementEnd (interp, sdata) == -1) { thismayskip = 1; } popStack (sdata); break; case SCHEMA_CTYPE_KEYSPACE_END: case SCHEMA_CTYPE_KEYSPACE: case SCHEMA_CTYPE_VIRTUAL: case SCHEMA_CTYPE_JSON_STRUCT: case SCHEMA_CTYPE_CHOICE: SetResult ("Invalid CTYPE in MIXED or CHOICE"); sdata->evalError = 1; return 0; } if (thismayskip) break; } if (thismayskip) break; if (!recover (interp, sdata, MISSING_ELEMENT, MATCH_ELEMENT_END, NULL, NULL, NULL, 0)) { return 0; } if (sdata->recoverFlags & RECOVER_FLAG_MATCH_END_CONTINUE) { updateStack (sdata, se, ac); return 2; } break; case SCHEMA_CTYPE_VIRTUAL: if (evalVirtual (interp, sdata, ac)) break; else return 0; case SCHEMA_CTYPE_JSON_STRUCT: if (!checkJsonStructType (interp, sdata, cp->content[ac], INVALID_JSON_TYPE, MATCH_ELEMENT_END, ac)) { return 0; } break; case SCHEMA_CTYPE_PATTERN: if (recursivePattern (se, cp->content[ac])) { break; } /* fall through */ case SCHEMA_CTYPE_INTERLEAVE: pushToStack (sdata, cp->content[ac]); rc = checkElementEnd (interp, sdata); if (rc == 0) { popStack (sdata); if (sdata->stack->pattern->type == SCHEMA_CTYPE_NAME || sdata->stack->activeChild || sdata->stack->hasMatched) { if (recover (interp, sdata, MISSING_ELEMENT, MATCH_ELEMENT_END, NULL, NULL, NULL, 0)) { if (sdata->recoverFlags & RECOVER_FLAG_MATCH_END_CONTINUE) { updateStack (sdata, se, ac); return 2; } break; } } return 0; } if (rc == 2) { updateStack (sdata, se, ac); return 2; } popStack (sdata); break; case SCHEMA_CTYPE_ANY: case SCHEMA_CTYPE_NAME: if (recover (interp, sdata, MISSING_ELEMENT, MATCH_ELEMENT_END, NULL, NULL, NULL, 0)) { if (sdata->recoverFlags & RECOVER_FLAG_MATCH_END_CONTINUE) { updateStack (sdata, se, ac); return 2; } break; } return 0; } ac++; } if (se->interleaveState) { if (!mayskip) return 0; } if (isName) return 1; return -1; case SCHEMA_CTYPE_KEYSPACE_END: case SCHEMA_CTYPE_KEYSPACE: case SCHEMA_CTYPE_VIRTUAL: case SCHEMA_CTYPE_CHOICE: case SCHEMA_CTYPE_TEXT: case SCHEMA_CTYPE_ANY: case SCHEMA_CTYPE_JSON_STRUCT: /* Never pushed onto stack */ SetResult ("Invalid CTYPE onto the validation stack!"); sdata->evalError = 1; return 0; } /* Not reached */ return 0; } static int checkDocKeys ( Tcl_Interp *interp, SchemaData *sdata ) { Tcl_HashEntry *h, *h1; Tcl_HashSearch search, search1; int haveErrMsg = 0; SchemaDocKey *dk; if (sdata->evalError) return 0; if (sdata->unknownIDrefs) { if (!recover (interp, sdata, UNKNOWN_ID, MATCH_GLOBAL, NULL, NULL, NULL, 0)) { haveErrMsg = 1; SetResult ("References to unknown IDs:"); for (h = Tcl_FirstHashEntry (&sdata->ids, &search); h != NULL; h = Tcl_NextHashEntry (&search)) { if (Tcl_GetHashValue (h) == 0) { Tcl_AppendResult (interp, " '", Tcl_GetHashKey (&sdata->ids, h), "'", NULL); } } } } if (sdata->idTables.numEntries) { for (h = Tcl_FirstHashEntry (&sdata->idTables, &search); h != NULL; h = Tcl_NextHashEntry (&search)) { dk = Tcl_GetHashValue (h); if (dk->unknownIDrefs) { if (!recover (interp, sdata, UNKNOWN_GLOBAL_ID, MATCH_GLOBAL, NULL, NULL, NULL, 0)) { if (haveErrMsg) { Tcl_AppendResult (interp, "\n", NULL); } else { haveErrMsg = 1; } Tcl_AppendResult (interp, "References to unknown IDs in ID space '", Tcl_GetHashKey (&sdata->idTables, h), "':", NULL); for (h1 = Tcl_FirstHashEntry (&dk->ids, &search1); h1 != NULL; h1 = Tcl_NextHashEntry (&search1)) { if (Tcl_GetHashValue (h1) == 0) { Tcl_AppendResult (interp, " '", Tcl_GetHashKey (&dk->ids, h1), "'", NULL); } } } } } } if (haveErrMsg) { sdata->validationState = VALIDATION_ERROR; return 0; } return 1; } int tDOM_probeElementEnd ( Tcl_Interp *interp, SchemaData *sdata ) { int rc; DBG(if (sdata->stack) { fprintf (stderr, "tDOM_probeElementEnd: look if current stack top can " " end name: '%s' deep: %d\n", sdata->stack->pattern->name, getDeep (sdata->stack)); } else {fprintf (stderr, "stack is NULL\n");} ); if (sdata->skipDeep) { sdata->skipDeep--; return TCL_OK; } if (sdata->validationState == VALIDATION_FINISHED) { SetResult ("Validation finished"); return TCL_ERROR; } if (sdata->validationState == VALIDATION_READY) { SetResult ("No validation started"); return TCL_ERROR; } if (sdata->validationState == VALIDATION_ERROR) { return TCL_ERROR; } while (1) { rc = checkElementEnd (interp, sdata); while (rc == -1) { popStack (sdata); rc = checkElementEnd (interp, sdata); } sdata->recoverFlags &= ~RECOVER_FLAG_DONT_REPORT; if (rc == 2) { sdata->recoverFlags &= ~RECOVER_FLAG_MATCH_END_CONTINUE; continue; } if (rc == 1) { popStack (sdata); if (sdata->stack == NULL) { /* End of the first pattern (the tree root) without error. */ /* Check for unknown ID references */ if (!checkDocKeys (interp, sdata)) { return TCL_ERROR; } /* We have successfully finished validation */ sdata->validationState = VALIDATION_FINISHED; } DBG( fprintf(stderr, "tDOM_probeElementEnd: _CAN_ end here.\n"); serializeStack (sdata); ); return TCL_OK; } break; } SetResultV ("Missing mandatory content"); sdata->validationState = VALIDATION_ERROR; DBG( fprintf(stderr, "tDOM_probeElementEnd: CAN'T end here.\n"); serializeStack (sdata); ); return TCL_ERROR; } static int matchText ( Tcl_Interp *interp, SchemaData *sdata, char *text ) { SchemaCP *cp, *candidate, *ic; SchemaValidationStack *se; int hm, isName = 0, mayskip; unsigned int ac, i; DBG(fprintf (stderr, "matchText called with text '%s'\n", text)); se = sdata->stack; getContext (cp, ac, hm); while (1) { switch (cp->type) { case SCHEMA_CTYPE_NAME: isName = 1; /* fall through */ case SCHEMA_CTYPE_PATTERN: while (ac < cp->nc) { candidate = cp->content[ac]; switch (candidate->type) { case SCHEMA_CTYPE_TEXT: if (checkText (interp, candidate, text)) { updateStack (sdata, se, ac); return 1; } if (sdata->evalError) return 0; if (recover (interp, sdata, INVALID_VALUE, MATCH_TEXT, NULL, NULL, text, ac)) { updateStack (sdata, se, ac); return 1; } SetResult ("Invalid text content"); return 0; case SCHEMA_CTYPE_CHOICE: if (candidate->flags & MIXED_CONTENT) { updateStack (sdata, se, ac); return 1; } for (i = 0; i < candidate->nc; i++) { ic = candidate->content[i]; switch (ic->type) { case SCHEMA_CTYPE_TEXT: if (checkText (interp, ic, text)) { updateStack (sdata, se, ac); return 1; } break; case SCHEMA_CTYPE_NAME: case SCHEMA_CTYPE_ANY: break; case SCHEMA_CTYPE_PATTERN: if (recursivePattern (se, ic)) { break; } /* fall through */ case SCHEMA_CTYPE_INTERLEAVE: pushToStack (sdata, ic); if (matchText (interp, sdata, text)) { updateStack (sdata, se, ac); return 1; } popStack (sdata); break; case SCHEMA_CTYPE_VIRTUAL: SetResult ("Virtual constrain in MIXED or" " CHOICE"); sdata->evalError = 1; return 0; case SCHEMA_CTYPE_CHOICE: SetResult ("MIXED or CHOICE child of MIXED or" " CHOICE"); sdata->evalError = 1; return 0; case SCHEMA_CTYPE_KEYSPACE_END: case SCHEMA_CTYPE_KEYSPACE: SetResult ("Keyspace constrain in MIXED or" " CHOICE"); sdata->evalError = 1; return 0; case SCHEMA_CTYPE_JSON_STRUCT: SetResult ("JSON structure constrain in MIXED or" " CHOICE"); sdata->evalError = 1; return 0; } } if (mustMatch (cp->quants[ac], hm)) { if (recover (interp, sdata, UNEXPECTED_TEXT, MATCH_TEXT, NULL, NULL, text, 0)) { return 1; } SetResultV ("Unexpected text content"); return 0; } break; case SCHEMA_CTYPE_PATTERN: if (recursivePattern (se, candidate)) { break; } /* fall through */ case SCHEMA_CTYPE_INTERLEAVE: pushToStack (sdata, candidate); if (matchText (interp, sdata, text)) { updateStack (sdata, se, ac); return 1; } popStack (sdata); if (mustMatch (cp->quants[ac], hm)) { if (recover (interp, sdata, UNEXPECTED_TEXT, MATCH_TEXT, NULL, NULL, text, 0)) { return 1; } SetResultV ("Unexpected text content"); return 0; } break; case SCHEMA_CTYPE_VIRTUAL: if (!evalVirtual (interp, sdata, ac)) return 0; break; case SCHEMA_CTYPE_JSON_STRUCT: if (checkJsonStructType (interp, sdata, candidate, INVALID_JSON_TYPE, MATCH_TEXT, ac)) { ac++; continue; } return 0; case SCHEMA_CTYPE_KEYSPACE: if (!cp->content[ac]->keySpace->active) { Tcl_InitHashTable (&cp->content[ac]->keySpace->ids, TCL_STRING_KEYS); cp->content[ac]->keySpace->active = 1; cp->content[ac]->keySpace->unknownIDrefs = 0; } else { cp->content[ac]->keySpace->active++; } break; case SCHEMA_CTYPE_KEYSPACE_END: cp->content[ac]->keySpace->active--; if (!cp->content[ac]->keySpace->active) { if (cp->content[ac]->keySpace->unknownIDrefs) { if (!recover (interp, sdata, INVALID_KEYREF, MATCH_TEXT, NULL, NULL, text, ac)) { return 0; SetResultV ("Invalid key ref."); sdata->evalError = 2; } cp->content[ac]->keySpace->unknownIDrefs = 0; } Tcl_DeleteHashTable (&cp->content[ac]->keySpace->ids); } break; case SCHEMA_CTYPE_NAME: case SCHEMA_CTYPE_ANY: if (mustMatch (cp->quants[ac], hm)) { if (recover (interp, sdata, UNEXPECTED_TEXT, MATCH_TEXT, NULL, NULL, text, ac)) { return 1; } SetResultV ("Unexpected text content"); return 0; } break; } ac++; } if (isName) { if (recover (interp, sdata, UNEXPECTED_TEXT, MATCH_TEXT, NULL, NULL, text, 0)) { return 1; } SetResultV ("Unexpected text content"); return 0; } popStack (sdata); se = sdata->stack; getContext (cp, ac, hm); ac++; continue; case SCHEMA_CTYPE_KEYSPACE: case SCHEMA_CTYPE_KEYSPACE_END: case SCHEMA_CTYPE_VIRTUAL: case SCHEMA_CTYPE_JSON_STRUCT: case SCHEMA_CTYPE_CHOICE: case SCHEMA_CTYPE_TEXT: case SCHEMA_CTYPE_ANY: /* Never pushed onto stack */ SetResult ("Invalid CTYPE onto the validation stack!"); sdata->evalError = 1; return 0; case SCHEMA_CTYPE_INTERLEAVE: mayskip = 1; for (i = 0; i < cp->nc; i++) { if (se->interleaveState[i]) { if (maxOne (cp->quants[i])) continue; } else { if (minOne (cp->quants[i])) mayskip = 0; } ic = cp->content[i]; switch (ic->type) { case SCHEMA_CTYPE_TEXT: if (checkText (interp, ic, text)) { if (!(sdata->recoverFlags & RECOVER_FLAG_REWIND)) { se->hasMatched = 1; se->interleaveState[i] = 1; } return 1; } break; case SCHEMA_CTYPE_NAME: case SCHEMA_CTYPE_ANY: break; case SCHEMA_CTYPE_PATTERN: if (recursivePattern (se, ic)) { break; } /* fall through */ case SCHEMA_CTYPE_INTERLEAVE: pushToStack (sdata, ic); if (matchText (interp, sdata, text)) { updateStack (sdata, se, ac); return 1; } popStack (sdata); break; case SCHEMA_CTYPE_CHOICE: SetResult ("MIXED or CHOICE child of INTERLEAVE"); sdata->evalError = 1; return 0; case SCHEMA_CTYPE_KEYSPACE_END: case SCHEMA_CTYPE_KEYSPACE: SetResult ("Keyspace child of INTERLEAVE"); sdata->evalError = 1; return 0; case SCHEMA_CTYPE_VIRTUAL: break; case SCHEMA_CTYPE_JSON_STRUCT: SetResult ("JSON structure constraint child of" "INTERLEAVE"); sdata->evalError = 1; return 0; } } if (!mayskip) { if (recover (interp, sdata, UNEXPECTED_TEXT, MATCH_TEXT, NULL, NULL, text, ac)) { return 1; } SetResultV ("Unexpected text content"); return 0; } popStack (sdata); se = sdata->stack; getContext (cp, ac, hm); ac++; continue; } /* Not reached, but this is inside a while (1) {} loop ...*/ break; } /* Not reached, but at least makes the compiler happy. */ return 0; } int tDOM_probeText ( Tcl_Interp *interp, SchemaData *sdata, char *text, int *only_whites ) { int myonly_whites; char *pc; DBG(fprintf (stderr, "tDOM_probeText started, text: '%s'\n", text);) if (sdata->skipDeep) { return TCL_OK; } if (sdata->validationState == VALIDATION_FINISHED) { SetResult ("Validation finished"); return TCL_ERROR; } if (sdata->validationState == VALIDATION_READY) { SetResult ("No validation started"); return TCL_ERROR; } if (sdata->stack->pattern->flags & CONSTRAINT_TEXT_CHILD) { if (!*text && sdata->stack->pattern->nc == 0) { return TCL_OK; } if (matchText (interp, sdata, text)) { CHECK_REWIND; return TCL_OK; } } else { if (only_whites) { myonly_whites = *only_whites; } else { myonly_whites = 1; pc = text; while (SPACE (*pc)) pc++; if (*pc) myonly_whites = 0; } if (myonly_whites) return TCL_OK; if (matchText (interp, sdata, text)) { CHECK_REWIND; return TCL_OK; } } if (!sdata->evalError) { SetResult ("Text content doesn't match"); } return TCL_ERROR; } static void startElement( void *userData, const char *name, const char **atts ) { ValidateMethodData *vdata = (ValidateMethodData *) userData; SchemaData *sdata; char *namespace; const char *s; int i = 0; DBG(fprintf (stderr, "startElement: '%s'\n", name);) sdata = vdata->sdata; if (!sdata->skipDeep && sdata->stack && Tcl_DStringLength (vdata->cdata)) { if (tDOM_probeText (vdata->interp, sdata, Tcl_DStringValue (vdata->cdata), NULL) != TCL_OK) { 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') { s++; if (i) { if (i >= vdata->maxUriLen - 1) { vdata->uri = (char *) REALLOC (vdata->uri, vdata->maxUriLen * 2); vdata->maxUriLen *= 2; } memcpy (vdata->uri, name, i); vdata->uri[i] = '\0'; namespace = vdata->uri; } } else { s = name; } if (tDOM_probeElement (vdata->interp, sdata, s, namespace) != TCL_OK) { sdata->validationState = VALIDATION_ERROR; XML_StopParser (vdata->parser, 0); return; } if (sdata->skipDeep == 0 && (atts[0] || (sdata->stack && sdata->stack->pattern->attrs))) { if (tDOM_probeAttributes (vdata->interp, sdata, atts) != TCL_OK) { sdata->validationState = VALIDATION_ERROR; XML_StopParser (vdata->parser, 0); } } } static void endElement ( void *userData, const char *UNUSED(name) ) { ValidateMethodData *vdata = (ValidateMethodData *) userData; SchemaData *sdata; DBG(fprintf (stderr, "endElement: '%s'\n", name);) sdata = vdata->sdata; if (sdata->validationState == VALIDATION_ERROR) { return; } if (!sdata->skipDeep && sdata->stack && Tcl_DStringLength (vdata->cdata)) { if (tDOM_probeText (vdata->interp, sdata, Tcl_DStringValue (vdata->cdata), NULL) != TCL_OK) { sdata->validationState = VALIDATION_ERROR; XML_StopParser (vdata->parser, 0); Tcl_DStringSetLength (vdata->cdata, 0); vdata->onlyWhiteSpace = 1; return; } } if (Tcl_DStringLength (vdata->cdata)) { Tcl_DStringSetLength (vdata->cdata, 0); vdata->onlyWhiteSpace = 1; } if (tDOM_probeElementEnd (vdata->interp, sdata) != TCL_OK) { sdata->validationState = VALIDATION_ERROR; XML_StopParser (vdata->parser, 0); } } static void 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 void schemaxpathRSFree ( xpathResultSet *rs ) { if (rs->type == StringResult) FREE (rs->string); FREE (rs->nodes); } static int checkdomKeyConstraints ( Tcl_Interp *interp, SchemaData *sdata, domNode *node ) { xpathResultSet nodeList, rs, frs; domKeyConstraint *kc; domNode *n; domAttrNode *attr; int rc, i, j, hnew, skip, first; domLength len; char *errMsg = NULL, *keystr, *efsv; Tcl_HashTable htable; Tcl_DString dStr; xpathCBs cbs; kc = sdata->stack->pattern->domKeys; memset (&nodeList, 0, sizeof (xpathResultSet)); nodeList.type = EmptyResult; memset (&rs, 0, sizeof (xpathResultSet)); rs.type = EmptyResult; memset (&frs, 0, sizeof (xpathResultSet)); frs.type = EmptyResult; Tcl_DStringInit (&dStr); xpathRSReset (&nodeList, node); cbs.funcCB = tcldom_xpathFuncCallBack; cbs.funcClientData = interp; cbs.varCB = NULL; cbs.varClientData = NULL; while (kc) { xpathRSReset (&rs, NULL); rc = xpathEvalAst (kc->selector, &nodeList, node, &cbs, &rs, &errMsg); if (rc) { SetResult (errMsg); goto booleanErrorCleanup; } if (kc->flags & DKC_FLAG_BOOLEAN) { i = xpathFuncBoolean (&rs); if (!i) { if (!recover (interp, sdata, DOM_XPATH_BOOLEAN, MATCH_DOM_KEYCONSTRAINT, kc->name, NULL, NULL, 0)) { SetResultV ("INVALID_DOM_XPATH_BOOLEAN"); goto booleanErrorCleanup; } } kc = kc->next; continue; } if (rs.type == EmptyResult) goto nextConstraint; if (rs.type != xNodeSetResult) { SetResult ("INVALID_DOM_KEYCONSTRAINT"); goto errorCleanup; } Tcl_InitHashTable (&htable, TCL_STRING_KEYS); for (i = 0; i < rs.nr_nodes; i++) { n = rs.nodes[i]; if (n->nodeType != ELEMENT_NODE) { SetResult ("INVALID_DOM_KEYCONSTRAINT"); goto errorCleanup; } xpathRSReset (&nodeList, n); if (kc->nrFields == 1) { xpathRSReset (&frs, NULL); rc = xpathEvalAst (kc->fields[0], &nodeList, n, &cbs, &frs, &errMsg); if (rc) { SetResult (errMsg); goto errorCleanup; } if (frs.type != xNodeSetResult && frs.type != EmptyResult) { SetResult ("INVALID_DOM_KEYCONSTRAINT"); goto errorCleanup; } if (frs.type == EmptyResult || frs.nr_nodes == 0) { if (kc->flags & DKC_FLAG_IGNORE_EMPTY_FIELD_SET) { continue; } efsv = ""; if (kc->emptyFieldSetValue) { efsv = kc->emptyFieldSetValue; } Tcl_CreateHashEntry (&htable, efsv, &hnew); if (!hnew) { if (recover (interp, sdata, DOM_KEYCONSTRAINT, MATCH_DOM_KEYCONSTRAINT, kc->name, NULL, efsv, 0)) { break; } SetResultV ("DOM_KEYCONSTRAINT"); goto errorCleanup; } continue; } if (frs.nr_nodes != 1) { if (recover (interp, sdata, DOM_KEYCONSTRAINT, MATCH_DOM_KEYCONSTRAINT, kc->name, NULL, NULL, 0)) { break; } SetResultV ("DOM_KEYCONSTRAINT"); goto errorCleanup; } if (frs.nodes[0]->nodeType != ELEMENT_NODE && frs.nodes[0]->nodeType != ATTRIBUTE_NODE) { SetResult ("INVALID_DOM_KEYCONSTRAINT"); goto errorCleanup; } if (frs.nodes[0]->nodeType == ATTRIBUTE_NODE) { attr = (domAttrNode *) frs.nodes[0]; Tcl_CreateHashEntry (&htable, attr->nodeValue, &hnew); if (!hnew) { if (recover (interp, sdata, DOM_KEYCONSTRAINT, MATCH_DOM_KEYCONSTRAINT, kc->name, NULL, attr->nodeValue, 0)) { break; } SetResultV ("DOM_KEYCONSTRAINT"); goto errorCleanup; } } else { keystr = xpathGetStringValue (frs.nodes[0], &len); Tcl_CreateHashEntry (&htable, keystr, &hnew); if (!hnew) { if (recover (interp, sdata, DOM_KEYCONSTRAINT, MATCH_DOM_KEYCONSTRAINT, kc->name, NULL, keystr, 0)) { FREE(keystr); break; } FREE(keystr); SetResultV ("DOM_KEYCONSTRAINT"); goto errorCleanup; } FREE(keystr); } } else { Tcl_DStringSetLength (&dStr, 0); skip = 0; first = 1; for (j = 0; j < kc->nrFields; j++) { xpathRSReset (&frs, NULL); rc = xpathEvalAst (kc->fields[j], &nodeList, n, &cbs, &frs, &errMsg); if (rc) { SetResult (errMsg); goto errorCleanup; } if (frs.type != xNodeSetResult && frs.type != EmptyResult) { SetResult ("INVALID_DOM_KEYCONSTRAINT"); goto errorCleanup; } if (frs.type == EmptyResult || frs.nr_nodes == 0) { if (kc->flags & DKC_FLAG_IGNORE_EMPTY_FIELD_SET) { continue; } if (kc->emptyFieldSetValue) { if (first) first = 0; else Tcl_DStringAppend (&dStr, ":", 1); Tcl_DStringAppend (&dStr, kc->emptyFieldSetValue, (domLength)kc->efsv_len); } else { if (first) first = 0; else Tcl_DStringAppend (&dStr, ":", 1); } continue; } if (frs.nr_nodes != 1) { if (recover (interp, sdata, DOM_KEYCONSTRAINT, MATCH_DOM_KEYCONSTRAINT, kc->name, NULL, NULL, 0)) { skip = 1; break; } SetResultV ("DOM_KEYCONSTRAINT"); goto errorCleanup; } if (frs.nodes[0]->nodeType != ELEMENT_NODE && frs.nodes[0]->nodeType != ATTRIBUTE_NODE) { SetResult ("INVALID_DOM_KEYCONSTRAINT"); goto errorCleanup; } if (first) first = 0; else Tcl_DStringAppend (&dStr, ":", 1); if (frs.nodes[0]->nodeType == ATTRIBUTE_NODE) { attr = (domAttrNode *) frs.nodes[0]; Tcl_DStringAppend (&dStr, attr->nodeValue, attr->valueLength); } else { keystr = xpathGetStringValue (frs.nodes[0], &len); Tcl_DStringAppend (&dStr, keystr, len); FREE (keystr); } } if (skip) break; Tcl_CreateHashEntry (&htable, Tcl_DStringValue (&dStr), &hnew); if (!hnew) { if (recover (interp, sdata, DOM_KEYCONSTRAINT, MATCH_DOM_KEYCONSTRAINT, kc->name, NULL, Tcl_DStringValue (&dStr),0)) { break; } SetResultV ("DOM_KEYCONSTRAINT"); goto errorCleanup; } } } Tcl_DeleteHashTable (&htable); nextConstraint: kc = kc->next; } schemaxpathRSFree (&frs); schemaxpathRSFree (&rs); schemaxpathRSFree (&nodeList); return TCL_OK; errorCleanup: Tcl_DeleteHashTable (&htable); booleanErrorCleanup: schemaxpathRSFree (&frs); schemaxpathRSFree (&rs); schemaxpathRSFree (&nodeList); return TCL_ERROR; } static void validateDOMerrorReport ( Tcl_Interp *interp, SchemaData *sdata, domNode *node ) { char *str; Tcl_Obj *strObj; if (node) { str = xpathNodeToXPath (node, 0); strObj = Tcl_NewStringObj (str, -1); Tcl_AppendStringsToObj (strObj, ": ", Tcl_GetStringResult (interp), NULL); Tcl_SetObjResult (interp, strObj); FREE (str); } sdata->evalError = 2; } static int validateDOM ( Tcl_Interp *interp, SchemaData *sdata, domNode *node ) { char *ln; domNode *savednode, *savedinsideNode; Tcl_Obj *str; int rc; if (node->namespace) { if (node->ownerDocument->namespaces[node->namespace-1]->prefix[0] == '\0') { ln = node->nodeName; } else { ln = node->nodeName; while (*ln && (*ln != ':')) { ln++; } if (*ln == ':') { ln++; } else { /* Ups? */ ln = node->nodeName; } } } else { ln = node->nodeName; } savednode = sdata->node; sdata->node = node; if (tDOM_probeElement (interp, sdata, ln, node->namespace ? node->ownerDocument->namespaces[node->namespace-1]->uri : NULL) != TCL_OK) { validateDOMerrorReport (interp, sdata, node); return TCL_ERROR; } /* In case of UNKNOWN_ROOT_ELEMENT and reportCmd is set * sdata->stack is NULL. */ if (!sdata->stack) return TCL_OK; if (sdata->skipDeep == 0) { if (node->firstAttr) { if (tDOM_probeDomAttributes (interp, sdata, node->firstAttr) != TCL_OK) { validateDOMerrorReport (interp, sdata, node); return TCL_ERROR; } } else { if (sdata->stack->pattern->numReqAttr) { /* tDOM_probeDomAttributes fills interp result with a * msg which required attributes are missing in case * of no reportCmd. In case of reportCmd * tDOM_probeDomAttributes() returns only error in the * case of error in called scripts. */ if (tDOM_probeDomAttributes (interp, sdata, NULL) != TCL_OK) { validateDOMerrorReport (interp, sdata, node); return TCL_ERROR; } } } } if (sdata->stack->pattern->domKeys) { if (checkdomKeyConstraints (interp, sdata, node) != TCL_OK) { validateDOMerrorReport (interp, sdata, node); return TCL_ERROR; } } savedinsideNode = sdata->insideNode; sdata->insideNode = node; node = node->firstChild; while (node) { switch (node->nodeType) { case ELEMENT_NODE: if (Tcl_DStringLength (sdata->cdata)) { if (tDOM_probeText (interp, sdata, Tcl_DStringValue (sdata->cdata), NULL) != TCL_OK) { validateDOMerrorReport (interp, sdata, node); return TCL_ERROR; } Tcl_DStringSetLength (sdata->cdata, 0); } if (validateDOM (interp, sdata, node) != TCL_OK) { return TCL_ERROR; } break; case TEXT_NODE: case CDATA_SECTION_NODE: str = Tcl_NewStringObj (((domTextNode *) node)->nodeValue, ((domTextNode *) node)->valueLength); sdata->textNode = (domTextNode *)node; rc = tDOM_probeText (interp, sdata, Tcl_GetString (str), NULL); Tcl_DecrRefCount (str); sdata->textNode = NULL; if (rc != TCL_OK) { validateDOMerrorReport (interp, sdata, node); return TCL_ERROR; } break; case COMMENT_NODE: case PROCESSING_INSTRUCTION_NODE: /* They are just ignored by validation. */ break; default: SetResult ("Unexpected node type in validateDOM!"); validateDOMerrorReport (interp, sdata, node); return TCL_ERROR; } node = node->nextSibling; } if (tDOM_probeElementEnd (interp, sdata) != TCL_OK) { validateDOMerrorReport (interp, sdata, node); return TCL_ERROR; } sdata->node = savednode; sdata->insideNode = savedinsideNode; return TCL_OK; } static void schemaReset ( SchemaData *sdata ) { Tcl_HashEntry *h; Tcl_HashSearch search; SchemaDocKey *dk; SchemaKeySpace *ks; while (sdata->stack) popStack (sdata); while (sdata->lastMatchse) popFromStack (sdata, &sdata->lastMatchse); sdata->recoverFlags = 0; sdata->validationState = VALIDATION_READY; sdata->skipDeep = 0; sdata->evalError = 0; sdata->vaction = 0; sdata->vname = NULL; sdata->vns = NULL; sdata->vtext = NULL; Tcl_DStringSetLength (sdata->cdata, 0); if (sdata->ids.numEntries) { Tcl_DeleteHashTable (&sdata->ids); Tcl_InitHashTable (&sdata->ids, TCL_STRING_KEYS); sdata->unknownIDrefs = 0; } if (sdata->idTables.numEntries) { for (h = Tcl_FirstHashEntry (&sdata->idTables, &search); h != NULL; h = Tcl_NextHashEntry (&search)) { dk = Tcl_GetHashValue (h); if ((&dk->ids)->numEntries) { Tcl_DeleteHashTable (&dk->ids); Tcl_InitHashTable (&dk->ids, TCL_STRING_KEYS); dk->unknownIDrefs = 0; } } } if (sdata->keySpaces.numEntries) { for (h = Tcl_FirstHashEntry (&sdata->keySpaces, &search); h != NULL; h = Tcl_NextHashEntry (&search)) { ks = Tcl_GetHashValue (h); if (ks->active && ks->ids.numEntries) { Tcl_DeleteHashTable (&ks->ids); Tcl_InitHashTable (&ks->ids, TCL_STRING_KEYS); } ks->unknownIDrefs = 0; ks->active = 0; } } sdata->parser = NULL; sdata->node = NULL; sdata->insideNode = NULL; sdata->textNode = NULL; } void tDOM_schemaReset ( SchemaData *sdata ) { if (sdata->cleanupAfterUse && sdata->inuse == 0 && sdata->currentEvals == 0) { schemaInstanceDelete (sdata); return; } schemaReset (sdata); } int tDOM_evalConstraints ( Tcl_Interp *interp, SchemaData *sdata, SchemaCP *cp, Tcl_Obj *script ) { int result, savedIsTextConstraint; SchemaCP *savedCP; unsigned int savedContenSize; /* Save some state of sdata .. */ savedCP = sdata->cp; savedContenSize = sdata->contentSize; savedIsTextConstraint = sdata->isTextConstraint; /* ... and prepare sdata for definition evaluation. */ sdata->cp = cp; sdata->contentSize = CONTENT_ARRAY_SIZE_INIT; sdata->isTextConstraint = 1; sdata->textStub[3] = script; sdata->currentEvals++; result = Tcl_EvalObjv (interp, 4, sdata->textStub, TCL_EVAL_GLOBAL); sdata->currentEvals--; /* ... and restore the previously saved sdata states */ sdata->isTextConstraint = savedIsTextConstraint; sdata->cp = savedCP; sdata->contentSize = savedContenSize; return result; } /* cp must be of type SCHEMA_CTYPE_NAME for useful results */ static Tcl_Obj* serializeElementName ( Tcl_Interp *interp, SchemaCP *cp ) { Tcl_Obj *rObj; rObj = Tcl_NewObj(); Tcl_ListObjAppendElement (interp, rObj, Tcl_NewStringObj (cp->name, -1)); if (cp->namespace) { Tcl_ListObjAppendElement (interp, rObj, Tcl_NewStringObj (cp->namespace, -1)); } return rObj; } static Tcl_Obj* serializeElementTypeName ( Tcl_Interp *interp, SchemaCP *cp ) { Tcl_Obj *rObj; rObj = Tcl_NewObj(); Tcl_ListObjAppendElement (interp, rObj, Tcl_NewStringObj (cp->name, -1)); if (cp->namespace) { Tcl_ListObjAppendElement (interp, rObj, Tcl_NewStringObj (cp->namespace, -1)); } return rObj; } /* cp must be of type SCHEMA_CTYPE_ANY for useful results */ static Tcl_Obj* serializeAnyCP ( Tcl_Interp *interp, SchemaCP *cp ) { Tcl_Obj *rObj, *nslistLObj; Tcl_HashTable *t; Tcl_HashEntry *h; Tcl_HashSearch search; rObj = Tcl_NewObj(); Tcl_ListObjAppendElement (interp, rObj, Tcl_NewStringObj ("", 5)); if (cp->namespace || cp->typedata) { nslistLObj = Tcl_NewObj(); if (cp->namespace) { Tcl_ListObjAppendElement (interp, nslistLObj, Tcl_NewStringObj (cp->namespace, -1)); } if (cp->typedata) { t = (Tcl_HashTable *)cp->typedata; for (h = Tcl_FirstHashEntry (t, &search); h != NULL; h = Tcl_NextHashEntry (&search)) { Tcl_ListObjAppendElement ( interp, nslistLObj, Tcl_NewStringObj (Tcl_GetHashKey (t, h), -1) ); } } Tcl_ListObjAppendElement (interp, rObj, nslistLObj); } else { Tcl_ListObjAppendElement (interp, rObj, Tcl_NewObj()); } return rObj; } /* The cp argument may be NULL. If it isn't NULL cp must be of type * SCHEMA_CTYPE_TEXT for useful results */ static Tcl_Obj* serializeTextCP ( Tcl_Interp *interp ) { Tcl_Obj *rObj; rObj = Tcl_NewObj(); Tcl_ListObjAppendElement (interp, rObj, Tcl_NewStringObj ("#text", 5)); Tcl_ListObjAppendElement (interp, rObj, Tcl_NewObj()); return rObj; } static Tcl_Obj* serializeElementEnd ( Tcl_Interp *interp ) { Tcl_Obj *rObj; rObj = Tcl_NewObj(); Tcl_ListObjAppendElement (interp, rObj, Tcl_NewStringObj ("", 12)); Tcl_ListObjAppendElement (interp, rObj, Tcl_NewObj()); return rObj; } static void definedElements ( Tcl_HashTable *htable, Tcl_Interp *interp ) { Tcl_Obj *rObj, *elmObj; Tcl_HashEntry *h; Tcl_HashSearch search; SchemaCP *cp; rObj = Tcl_GetObjResult (interp); for (h = Tcl_FirstHashEntry (htable, &search); h != NULL; h = Tcl_NextHashEntry (&search)) { cp = (SchemaCP *) Tcl_GetHashValue (h); while (cp) { if (cp->flags & FORWARD_PATTERN_DEF || cp->flags & PLACEHOLDER_PATTERN_DEF) { cp = cp->next; continue; } elmObj = serializeElementName (interp, cp); Tcl_ListObjAppendElement (interp, rObj, elmObj); cp = cp->next; } } } static void definedElementtypes ( SchemaData *sdata, Tcl_Interp *interp ) { Tcl_Obj *rObj, *elmObj; Tcl_HashEntry *h; Tcl_HashSearch search; SchemaCP *cp; rObj = Tcl_GetObjResult (interp); for (h = Tcl_FirstHashEntry (&sdata->elementType, &search); h != NULL; h = Tcl_NextHashEntry (&search)) { cp = (SchemaCP *) Tcl_GetHashValue (h); while (cp) { if (cp->flags & FORWARD_PATTERN_DEF || cp->flags & PLACEHOLDER_PATTERN_DEF) { cp = cp->next; continue; } if (cp->flags & FORWARD_PATTERN_DEF || cp->flags & PLACEHOLDER_PATTERN_DEF) continue; elmObj = serializeElementTypeName (interp, cp); Tcl_ListObjAppendElement (interp, rObj, elmObj); cp = cp->next; } } } static int getNextExpectedWorker ( SchemaData *sdata, SchemaValidationStack *se, Tcl_Interp *interp, Tcl_HashTable *seenCPs, Tcl_Obj *rObj, int expectedFlags ) { int hm, hnew, mustMatch, mayskip, rc = 1, probeMayskip = 0; unsigned int ac, i; SchemaCP *cp, *ic, *jc; SchemaValidationStack *se1; if (expectedFlags & EXPECTED_PROBE_MAYSKIP) { probeMayskip = 1; } getContext (cp, ac, hm); if ((expectedFlags & EXPECTED_IGNORE_MATCHED || expectedFlags & EXPECTED_ONLY_MANDATORY) && hm) { ac++; hm = 0; } else { if (hm && maxOne(cp->quants[ac])) { ac++; hm = 0; } } switch (cp->type) { case SCHEMA_CTYPE_INTERLEAVE: ac = 0; mustMatch = 0; /* fall through */ case SCHEMA_CTYPE_NAME: case SCHEMA_CTYPE_PATTERN: while (ac < cp->nc) { if (se->interleaveState && se->interleaveState[ac] && maxOne (cp->quants[ac])) { ac++; hm = 0; continue; } if (expectedFlags & EXPECTED_ONLY_MANDATORY && !(mustMatch (cp->quants[ac], hm))) { ac++; hm = 0; continue; } ic = cp->content[ac]; mayskip = 0; switch (ic->type) { case SCHEMA_CTYPE_NAME: if (probeMayskip) break; Tcl_ListObjAppendElement (interp, rObj, serializeElementName (interp, ic)); break; case SCHEMA_CTYPE_PATTERN: if (recursivePattern (se, ic)) { break; } /* fall through */ case SCHEMA_CTYPE_INTERLEAVE: if (expectedFlags & EXPECTED_ONLY_MANDATORY && !se->hasMatched) { expectedFlags |= EXPECTED_PROBE_MAYSKIP; se1 = getStackElement (sdata, ic); mayskip = getNextExpectedWorker (sdata, se1, interp, seenCPs, rObj, expectedFlags); repoolStackElement (sdata, se1); if (!probeMayskip) { expectedFlags &= ~EXPECTED_PROBE_MAYSKIP; } if (mayskip) break; } if (probeMayskip) break; Tcl_CreateHashEntry (seenCPs, (char *)ic, &hnew); if (hnew) { se1 = getStackElement (sdata, ic); mayskip = getNextExpectedWorker (sdata, se1, interp, seenCPs, rObj, expectedFlags); repoolStackElement (sdata, se1); } break; case SCHEMA_CTYPE_ANY: if (probeMayskip) break; if (!(expectedFlags & EXPECTED_ONLY_MANDATORY) || minOne (cp->quants[ac])) { Tcl_ListObjAppendElement (interp, rObj, serializeAnyCP (interp, ic)); } break; case SCHEMA_CTYPE_TEXT: if (ic->nc == 0 || checkText (interp, ic, "")) { mayskip = 1; } if (probeMayskip) break; if (!(expectedFlags & EXPECTED_ONLY_MANDATORY) || mayskip == 0) { Tcl_ListObjAppendElement (interp, rObj, serializeTextCP (interp)); } break; case SCHEMA_CTYPE_CHOICE: if (probeMayskip) { for (i = 0; i < ic->nc; i++) { if (mayMiss (ic->quants[i])) { mayskip = 1; break; } jc = ic->content[i]; switch (jc->type) { case SCHEMA_CTYPE_PATTERN: if (recursivePattern (se, ic)) { mayskip = 1; break; } /* fall through */ case SCHEMA_CTYPE_INTERLEAVE: se1 = getStackElement (sdata, ic); mayskip = getNextExpectedWorker ( sdata, se1, interp, seenCPs, rObj, expectedFlags ); repoolStackElement (sdata, se1); break; case SCHEMA_CTYPE_TEXT: if (ic->nc == 0 || checkText (interp, ic, "")) { mayskip = 1; } break; default: break; } if (mayskip) break; } break; } if (ic->flags & MIXED_CONTENT) { if (!(expectedFlags & EXPECTED_ONLY_MANDATORY)) { Tcl_ListObjAppendElement ( interp, rObj, serializeTextCP (interp)); } } for (i = 0; i < ic->nc; i++) { jc = ic->content[i]; switch (jc->type) { case SCHEMA_CTYPE_NAME: if (!(expectedFlags & EXPECTED_ONLY_MANDATORY) || minOne (cp->quants[i])) { Tcl_ListObjAppendElement ( interp, rObj, serializeElementName (interp, jc) ); } break; case SCHEMA_CTYPE_PATTERN: if (recursivePattern (se, jc)) { break; } /* fall through */ case SCHEMA_CTYPE_INTERLEAVE: Tcl_CreateHashEntry (seenCPs, (char *)jc, &hnew); if (hnew) { se1 = getStackElement (sdata, jc); mayskip = getNextExpectedWorker ( sdata, se1, interp, seenCPs, rObj, expectedFlags ); repoolStackElement (sdata, se1); } break; case SCHEMA_CTYPE_ANY: if (!(expectedFlags & EXPECTED_ONLY_MANDATORY) || minOne (cp->quants[i])) { Tcl_ListObjAppendElement ( interp, rObj, serializeAnyCP (interp, jc) ); } break; case SCHEMA_CTYPE_TEXT: if (!(expectedFlags & EXPECTED_ONLY_MANDATORY) || minOne (cp->quants[i])) { Tcl_ListObjAppendElement ( interp, rObj, serializeTextCP (interp) ); } break; case SCHEMA_CTYPE_CHOICE: SetResult ("MIXED or CHOICE child of MIXED or CHOICE"); sdata->evalError = 1; return 0; case SCHEMA_CTYPE_VIRTUAL: case SCHEMA_CTYPE_JSON_STRUCT: case SCHEMA_CTYPE_KEYSPACE: case SCHEMA_CTYPE_KEYSPACE_END: break; } } break; case SCHEMA_CTYPE_VIRTUAL: case SCHEMA_CTYPE_JSON_STRUCT: case SCHEMA_CTYPE_KEYSPACE: case SCHEMA_CTYPE_KEYSPACE_END: mayskip = 1; break; } if (cp->type == SCHEMA_CTYPE_INTERLEAVE) { if (!mustMatch && minOne(cp->quants[ac])) mustMatch = 1; } else { if (!mayskip && !hm && minOne (cp->quants[ac])) break; } ac++; hm = 0; } if (cp->type == SCHEMA_CTYPE_NAME) { if (ac == cp->nc) { /* The currently open element can end here, no * mandatory elements missing. * The element end is always mandatory.*/ Tcl_ListObjAppendElement ( interp, rObj, serializeElementEnd (interp) ); } rc = 0; } else if (cp->type == SCHEMA_CTYPE_INTERLEAVE) { if (mustMatch) rc = 0; } else { /* SCHEMA_CTYPE_PATTERN */ if (ac < cp->nc) rc = 0; } break; case SCHEMA_CTYPE_ANY: case SCHEMA_CTYPE_CHOICE: case SCHEMA_CTYPE_TEXT: case SCHEMA_CTYPE_VIRTUAL: case SCHEMA_CTYPE_JSON_STRUCT: case SCHEMA_CTYPE_KEYSPACE: case SCHEMA_CTYPE_KEYSPACE_END: SetResult ("Invalid CTYPE onto the validation stack!"); sdata->evalError = 1; return 0; } return rc; } static Tcl_Obj * unifyMatchList ( Tcl_Interp *interp, Tcl_HashTable *htable, Tcl_Obj *list ) { domLength len, i; int hnew; Tcl_HashEntry *h; Tcl_Obj *rObj, *thisObj; Tcl_HashSearch search; rObj = Tcl_NewObj(); Tcl_ListObjLength (interp, list, &len); if (len == 0) return rObj; if (len == 1) { Tcl_ListObjIndex (interp, list, 0, &thisObj); Tcl_ListObjAppendElement (interp, rObj, thisObj); return rObj; } Tcl_InitHashTable (htable, TCL_STRING_KEYS); for (i = 0; i < len; i++) { Tcl_ListObjIndex (interp, list, i, &thisObj); h = Tcl_CreateHashEntry (htable, Tcl_GetString (thisObj), &hnew); if (hnew) { Tcl_SetHashValue (h, thisObj); } } for (h = Tcl_FirstHashEntry (htable, &search); h != NULL; h = Tcl_NextHashEntry (&search)) { Tcl_ListObjAppendElement (interp, rObj, Tcl_GetHashValue (h)); } Tcl_DeleteHashTable (htable); return rObj; } static void getNextExpected ( SchemaData *sdata, Tcl_Interp *interp, int expectedFlags ) { int remainingLastMatch, count, rc; Tcl_Obj *rObj; Tcl_HashTable localHash; SchemaValidationStack *se; rObj = Tcl_NewObj(); Tcl_InitHashTable (&localHash, TCL_ONE_WORD_KEYS); remainingLastMatch = 0; if (sdata->lastMatchse) { se = sdata->lastMatchse; while (se->down) { remainingLastMatch++; se = se->down; } while (se && getNextExpectedWorker (sdata, se, interp, &localHash, rObj, expectedFlags)) { if (remainingLastMatch) { count = 1; se = sdata->lastMatchse; while (count < remainingLastMatch) { se = se->down; count++; } remainingLastMatch--; } else break; } } se = sdata->stack; while (se) { if (!se->hasMatched && se->pattern->type != SCHEMA_CTYPE_NAME) { se = se->down; continue; } rc = getNextExpectedWorker (sdata, se, interp, &localHash, rObj, expectedFlags); if (se->pattern->type == SCHEMA_CTYPE_NAME) break; se = se->down; if (!rc) break; } Tcl_DeleteHashTable (&localHash); Tcl_SetObjResult (interp, unifyMatchList (interp, &localHash, rObj)); Tcl_DecrRefCount (rObj); } static int schemaInstanceInfoCmd ( SchemaData *sdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { int methodIndex, expectedFlags; XML_Size line, column; XML_Index byteIndex; Tcl_HashEntry *h; SchemaCP *cp; SchemaValidationStack *se; void *ns; Tcl_Obj *rObj; static const char *schemaInstanceInfoMethods[] = { "validationstate", "vstate", "definedElements", "stack", "toplevel", "expected", "definition", "validationaction", "vaction", "line", "column", "byteIndex", "domNode", "nrForwardDefinitions", "typedefinition", "definedElementtypes", "patterndefinition", "definedPatterns", NULL }; enum schemaInstanceInfoMethod { m_validationstate, m_vstate, m_definedElements, m_stack, m_toplevel, m_expected, m_definition, m_validationaction, m_vaction, m_line, m_column, m_byteIndex, m_domNode, m_nrForwardDefinitions, m_typedefinition, m_definedElementtypes, m_patterndefinition, m_definedPatterns }; static const char *schemaInstanceInfoStackMethods[] = { "top", "inside", "associated", NULL }; enum schemaInstanceInfoStackMethod { m_top, m_inside, m_associated }; static const char *schemaInstanceInfoVactionMethods[] = { "name", "namespace", "text", NULL }; enum schemaInstanceInfoVactionMethod { m_name, m_namespace, m_text }; static const char *schemaInstanceInfoExpectedOptions[] = { "-ignorematched", "-onlymandatory", NULL }; enum schemaInstanceInfoExpectedOption { o_ignorematched, o_onlymandatory }; if (objc < 2) { Tcl_WrongNumArgs (interp, 1, objv, "subcommand ?arguments?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj (interp, objv[1], schemaInstanceInfoMethods, "method", 0, &methodIndex) != TCL_OK) { return TCL_ERROR; } Tcl_ResetResult (interp); switch ((enum schemaInstanceInfoMethod) methodIndex) { case m_validationstate: case m_vstate: switch (sdata->validationState) { case VALIDATION_READY: SetResult ("READY"); break; case VALIDATION_STARTED: SetResult ("VALIDATING"); break; case VALIDATION_FINISHED: SetResult ("FINISHED"); break; default: SetResult ("Internal error: Invalid validation state"); return TCL_ERROR; } break; case m_definedElements: if (objc != 2) { Tcl_WrongNumArgs (interp, 1, objv, "definedElements"); return TCL_ERROR; } definedElements (&sdata->element, interp); break; case m_definedPatterns: if (objc != 2) { Tcl_WrongNumArgs (interp, 1, objv, "definedPatterns"); return TCL_ERROR; } definedElements (&sdata->pattern, interp); break; case m_definedElementtypes: if (objc != 2) { Tcl_WrongNumArgs (interp, 1, objv, "definedElementtypes"); return TCL_ERROR; } definedElementtypes (sdata, interp); break; case m_stack: if (objc != 3) { Tcl_WrongNumArgs (interp, 2, objv, "top|inside"); return TCL_ERROR; } if (Tcl_GetIndexFromObj (interp, objv[2], schemaInstanceInfoStackMethods, "method", 0, &methodIndex) != TCL_OK) { return TCL_ERROR; } if (!sdata->stack) { return TCL_OK; } se = sdata->stack; switch ((enum schemaInstanceInfoStackMethod) methodIndex) { case m_inside: rObj = Tcl_NewObj(); while (se) { if (se->pattern->type == SCHEMA_CTYPE_NAME) { Tcl_ListObjAppendElement (interp, rObj, serializeElementName (interp, se->pattern)); } se = se->down; } Tcl_SetObjResult (interp, rObj); return TCL_OK; case m_top: while (se->pattern->type != SCHEMA_CTYPE_NAME) { se = se->down; } rObj = serializeElementName (interp, se->pattern); Tcl_SetObjResult (interp, rObj); return TCL_OK; case m_associated: if (!se->pattern->associated) { return TCL_OK; } Tcl_SetObjResult (interp, se->pattern->associated); return TCL_OK; } break; case m_toplevel: if (objc != 2) { Tcl_WrongNumArgs (interp, 2, objv, ""); return TCL_ERROR; } if (!sdata->currentEvals) { SetResult ("not called while schema evaluation"); return TCL_ERROR; } if (!sdata->defineToplevel && sdata->currentEvals > 1) { SetBooleanResult (0); } else { SetBooleanResult (1); } return TCL_OK; case m_expected: if (objc < 2 || objc > 4) { Tcl_WrongNumArgs (interp, 2, objv, "?-ignorematched? ?-onlymandatory?"); return TCL_ERROR; } if (sdata->validationState == VALIDATION_ERROR || sdata->validationState == VALIDATION_FINISHED) { return TCL_OK; } expectedFlags = 0; while (objc > 2) { if (Tcl_GetIndexFromObj (interp, objv[2], schemaInstanceInfoExpectedOptions, "option", 0, &methodIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum schemaInstanceInfoExpectedOption) methodIndex) { case o_ignorematched: expectedFlags |= EXPECTED_IGNORE_MATCHED; break; case o_onlymandatory: expectedFlags |= EXPECTED_ONLY_MANDATORY; break; } objv++; objc--; } if (!sdata->stack) { if (sdata->start) { Tcl_AppendElement (interp, sdata->start); if (sdata->startNamespace) { Tcl_AppendElement (interp, sdata->startNamespace); } } else { definedElements (&sdata->element, interp); } } else { getNextExpected (sdata, interp, expectedFlags); } break; case m_definition: if (objc < 3 || objc > 4) { Tcl_WrongNumArgs (interp, 1, objv, "name ?namespace?"); return TCL_ERROR; } h = Tcl_FindHashEntry (&sdata->element, Tcl_GetString (objv[2])); if (!h) { SetResult ("Unknown element definition"); return TCL_ERROR; } cp = Tcl_GetHashValue (h); ns = NULL; if (objc == 4) { ns = getNamespacePtr (sdata, Tcl_GetString (objv[3])); } while (cp && cp->namespace != ns) { cp = cp->next; } if (!cp || cp->flags & LOCAL_DEFINED_ELEMENT || cp->flags & PLACEHOLDER_PATTERN_DEF) { SetResult ("Unknown element definition"); return TCL_ERROR; } Tcl_AppendElement (interp, "defelement"); Tcl_AppendElement (interp, cp->name); if (cp->namespace) { Tcl_AppendElement (interp, cp->namespace); } if (cp->defScript) { Tcl_AppendElement (interp, Tcl_GetString (cp->defScript)); } break; case m_patterndefinition: if (objc < 3 || objc > 4) { Tcl_WrongNumArgs (interp, 1, objv, "name ?namespace?"); return TCL_ERROR; } h = Tcl_FindHashEntry (&sdata->pattern, Tcl_GetString (objv[2])); if (!h) { SetResult ("Unknown pattern definition"); return TCL_ERROR; } cp = Tcl_GetHashValue (h); ns = NULL; if (objc == 4) { ns = getNamespacePtr (sdata, Tcl_GetString (objv[3])); } while (cp && cp->namespace != ns) { cp = cp->next; } if (!cp || cp->flags & PLACEHOLDER_PATTERN_DEF) { SetResult ("Unknown pattern definition"); return TCL_ERROR; } Tcl_AppendElement (interp, "defpattern"); Tcl_AppendElement (interp, cp->name); if (cp->namespace) { Tcl_AppendElement (interp, cp->namespace); } if (cp->defScript) { Tcl_AppendElement (interp, Tcl_GetString (cp->defScript)); } break; case m_typedefinition: if (objc < 3 || objc > 4) { Tcl_WrongNumArgs (interp, 2, objv, "name ?namespace?"); return TCL_ERROR; } h = Tcl_FindHashEntry (&sdata->elementType, Tcl_GetString (objv[2])); if (!h) { SetResult ("Unknown elementtype definition"); return TCL_ERROR; } cp = Tcl_GetHashValue (h); ns = NULL; if (objc == 4) { ns = getNamespacePtr (sdata, Tcl_GetString (objv[3])); } while (cp && cp->namespace != ns) { cp = cp->next; } if (!cp || cp->flags & PLACEHOLDER_PATTERN_DEF) { SetResult ("Unknown elementtype definition"); return TCL_ERROR; } Tcl_AppendElement (interp, "defelementtype"); Tcl_AppendElement (interp, cp->name); if (cp->namespace) { Tcl_AppendElement (interp, cp->namespace); } if (cp->defScript) { Tcl_AppendElement (interp, Tcl_GetString (cp->defScript)); } break; case m_vaction: case m_validationaction: if (sdata->validationState != VALIDATION_STARTED || sdata->currentEvals == 0) { SetResult ("NONE"); break; } if (objc == 2) { SetResult (ValidationAction2str[sdata->vaction]); break; } if (objc != 3) { Tcl_WrongNumArgs (interp, 2, objv, "?name|namespace|text?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj (interp, objv[2], schemaInstanceInfoVactionMethods, "method", 0, &methodIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum schemaInstanceInfoVactionMethod) methodIndex) { case m_name: SetResult (sdata->vname); break; case m_namespace: SetResult (sdata->vns); break; case m_text: SetResult (sdata->vtext); break; } break; case m_line: if (!sdata->parser && !sdata->node) break; if (sdata->parser) { SetLongResult ((domLength)XML_GetCurrentLineNumber (sdata->parser)); break; } if (domGetLineColumn(sdata->node, &line, &column, &byteIndex) < 0) break; SetLongResult ((domLength)line); break; case m_column: if (!sdata->parser && !sdata->node) break; if (sdata->parser) { SetLongResult ((domLength)XML_GetCurrentColumnNumber (sdata->parser)); break; } if (domGetLineColumn(sdata->node, &line, &column, &byteIndex) < 0) break; SetLongResult ((domLength)column); break; case m_byteIndex: if (!sdata->parser && !sdata->node) break; if (sdata->parser) { SetLongResult ((domLength)XML_GetCurrentByteIndex (sdata->parser)); break; } if (domGetLineColumn(sdata->node, &line, &column, &byteIndex) < 0) break; SetLongResult ((domLength)byteIndex); break; case m_domNode: if (!sdata->node) break; /* We distinguish between calls from reportCmd and others * (from scripts called with the tcl cmd). */ if (sdata->vaction) { /* This is the case: called from reportCmd. */ return tcldom_setInterpAndReturnVar (interp, sdata->node, NULL); } else { /* This is the case: called from a with tcl called script. */ return tcldom_setInterpAndReturnVar (interp, sdata->insideNode, NULL); } break; case m_nrForwardDefinitions: if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } SetIntResult(sdata->forwardPatternDefs); break; } return TCL_OK; } static void attributeLookupPreparation ( SchemaData *sdata, SchemaCP *cp ) { Tcl_HashTable *t; unsigned int i; int hnew; Tcl_HashEntry *h; SchemaAttr *attr; if (cp->numAttr <= sdata->attributeHashThreshold) return; t = TMALLOC (Tcl_HashTable); Tcl_InitHashTable (t, TCL_STRING_KEYS); for (i = 0; i < cp->numAttr; i++) { h = Tcl_CreateHashEntry (t, cp->attrs[i]->name, &hnew); if (hnew) { Tcl_SetHashValue (h, cp->attrs[i]); } else { attr = (SchemaAttr *) Tcl_GetHashValue (h); cp->attrs[i]->next = attr->next; attr->next = cp->attrs[i]; } } cp->typedata = (void *)t; } static void validateReportError ( Tcl_Interp *interp, SchemaData *sdata, XML_Parser parser ) { Tcl_Obj *resultObj; char sl[50], sc[50]; resultObj = Tcl_NewObj (); sprintf(sl, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentLineNumber(parser)); sprintf(sc, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentColumnNumber(parser)); if (sdata->validationState == VALIDATION_ERROR) { Tcl_AppendStringsToObj (resultObj, "error \"", Tcl_GetStringResult (interp), "\" at line ", sl, " character ", sc, NULL); } else { Tcl_AppendStringsToObj (resultObj, "error \"", XML_ErrorString(XML_GetErrorCode(parser)), "\" at line ", sl, " character ", sc, NULL); } Tcl_SetObjResult (interp, resultObj); } static int externalEntityRefHandler ( XML_Parser parser, const char *openEntityNames, const char *base, const char *systemId, const char *publicId ) { ValidateMethodData *vdata; Tcl_Obj *cmdPtr, *resultObj, *resultTypeObj, *extbaseObj, *xmlstringObj; Tcl_Obj *channelIdObj; int result, mode, done, keepresult = 0; domLength len, tclLen; XML_Parser extparser, oldparser = NULL; char buf[4096], *resultType, *extbase, *xmlstring, *xmlstringstart, *channelId, s[50]; Tcl_Channel chan = (Tcl_Channel) NULL; enum XML_Status status; const char *interpResult; vdata = (ValidateMethodData *) XML_GetUserData (parser); if (vdata->externalentitycommandObj == NULL) { Tcl_AppendResult (vdata->interp, "Can't read external entity \"", systemId, "\": No -externalentitycommand given", NULL); return 0; } cmdPtr = Tcl_NewStringObj(Tcl_GetString(vdata->externalentitycommandObj), -1); Tcl_IncrRefCount(cmdPtr); if (base) { Tcl_ListObjAppendElement(vdata->interp, cmdPtr, Tcl_NewStringObj(base, (domLength)strlen(base))); } else { Tcl_ListObjAppendElement(vdata->interp, cmdPtr, Tcl_NewObj()); } /* For a document with doctype declaration, the systemId is always != NULL. But if the document doesn't have a doctype declaration and the user uses -useForeignDTD 1, the externalEntityRefHandler will be called with a systemId (and publicId and openEntityNames) == NULL. */ if (systemId) { Tcl_ListObjAppendElement(vdata->interp, cmdPtr, Tcl_NewStringObj(systemId, (domLength)strlen(systemId))); } else { Tcl_ListObjAppendElement(vdata->interp, cmdPtr, Tcl_NewObj()); } if (publicId) { Tcl_ListObjAppendElement(vdata->interp, cmdPtr, Tcl_NewStringObj(publicId, (domLength)strlen(publicId))); } else { Tcl_ListObjAppendElement(vdata->interp, cmdPtr, Tcl_NewObj()); } result = Tcl_EvalObjEx (vdata->interp, cmdPtr, TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL); Tcl_DecrRefCount(cmdPtr); if (result != TCL_OK) { vdata->sdata->evalError = 1; return 0; } extparser = XML_ExternalEntityParserCreate (parser, openEntityNames, 0); resultObj = Tcl_GetObjResult (vdata->interp); Tcl_IncrRefCount (resultObj); result = Tcl_ListObjLength (vdata->interp, resultObj, &tclLen); if ((result != TCL_OK) || (tclLen != 3)) { goto wrongScriptResult; } result = Tcl_ListObjIndex (vdata->interp, resultObj, 0, &resultTypeObj); if (result != TCL_OK) { goto wrongScriptResult; } resultType = Tcl_GetString(resultTypeObj); if (strcmp (resultType, "string") == 0) { result = Tcl_ListObjIndex (vdata->interp, resultObj, 2, &xmlstringObj); xmlstring = Tcl_GetStringFromObj (xmlstringObj, &len); } else if (strcmp (resultType, "channel") == 0) { xmlstring = NULL; len = 0; result = Tcl_ListObjIndex (vdata->interp, resultObj, 2, &channelIdObj); channelId = Tcl_GetString(channelIdObj); chan = Tcl_GetChannel (vdata->interp, channelId, &mode); if (chan == (Tcl_Channel) NULL) { goto wrongScriptResult; } if ((mode & TCL_READABLE) == 0) { return 0; } } else if (strcmp (resultType, "filename") == 0) { /* result type "filename" not yet implemented */ return 0; } else { goto wrongScriptResult; } result = Tcl_ListObjIndex (vdata->interp, resultObj, 1, &extbaseObj); if (result != TCL_OK) { goto wrongScriptResult; } extbase = Tcl_GetString(extbaseObj); /* TODO: what to do, if this document was already parsed before ? */ if (!extparser) { Tcl_DecrRefCount (resultObj); Tcl_SetResult (vdata->interp, "unable to create expat external entity parser", NULL); return 0; } oldparser = vdata->parser; vdata->parser = extparser; XML_SetBase (extparser, extbase); Tcl_ResetResult (vdata->interp); result = 1; xmlstringstart = xmlstring; if (chan == NULL) { do { done = (len < TDOM_PCS); status = XML_Parse (extparser, xmlstring, (int)(done ? len : TDOM_PCS), done); if (!done) { xmlstring += TDOM_PCS; len -= TDOM_PCS; } } while (!done && status == XML_STATUS_OK); switch (status) { case XML_STATUS_ERROR: interpResult = Tcl_GetStringResult(vdata->interp); if (interpResult[0] == '\0') { tcldom_reportErrorLocation ( vdata->interp, 20, 40, XML_GetCurrentLineNumber(extparser), XML_GetCurrentColumnNumber(extparser), xmlstringstart, systemId, XML_GetCurrentByteIndex(extparser), XML_ErrorString(XML_GetErrorCode(extparser))); } else { sprintf(s, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentLineNumber(extparser)); Tcl_AppendResult(vdata->interp, ", referenced in entity \"", systemId, "\" at line ", s, " character ", NULL); sprintf(s, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentColumnNumber(extparser)); Tcl_AppendResult(vdata->interp, s, NULL); } keepresult = 1; result = 0; break; case XML_STATUS_SUSPENDED: XML_StopParser (oldparser, 1); keepresult = 1; break; default: break; } } else { do { len = Tcl_Read (chan, buf, sizeof(buf)); done = len < sizeof(buf); status = XML_Parse (extparser, buf, (int)len, done); switch (status) { case XML_STATUS_ERROR: interpResult = Tcl_GetStringResult(vdata->interp); sprintf(s, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentLineNumber(extparser)); if (interpResult[0] == '\0') { Tcl_ResetResult (vdata->interp); Tcl_AppendResult( vdata->interp, "error \"", XML_ErrorString(XML_GetErrorCode(extparser)), "\" in entity \"", systemId, "\" at line ", s, " character ", NULL ); sprintf(s, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentColumnNumber(extparser)); Tcl_AppendResult(vdata->interp, s, NULL); } else { Tcl_AppendResult( vdata->interp, ", referenced in entity \"", systemId, "\" at line ", s, " character ", NULL ); sprintf(s, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentColumnNumber(extparser)); Tcl_AppendResult(vdata->interp, s, NULL); } result = 0; keepresult = 1; done = 1; break; case XML_STATUS_SUSPENDED: XML_StopParser (oldparser, 1); keepresult = 1; done = 1; break; default: break; } } while (!done); } if (!keepresult) { Tcl_ResetResult (vdata->interp); } XML_ParserFree (extparser); vdata->parser = oldparser; Tcl_DecrRefCount (resultObj); return result; wrongScriptResult: Tcl_DecrRefCount (resultObj); Tcl_ResetResult (vdata->interp); XML_ParserFree (extparser); if (oldparser) { vdata->parser = oldparser; } vdata->sdata->evalError = 1; Tcl_AppendResult (vdata->interp, "The -externalentitycommand script " "has to return a Tcl list with 3 elements.\n" "Syntax: {string|channel|filename }\n", NULL); return 0; } static int validateSource ( ValidationInput source, SchemaData *sdata, ValidateMethodData *vdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { XML_Parser parser; char sep = '\xFF'; Tcl_DString cdata; Tcl_Obj *bufObj; char *xmlstr, *filename, *str, *baseurl = NULL; int result, fd, mode, done, rc, value, useForeignDTD = 0; domLength len, tclLen; int forest = 0; int paramEntityParsing = XML_PARAM_ENTITY_PARSING_ALWAYS; Tcl_DString translatedFilename; int optionIndex; Tcl_Channel channel; static const char *validateOptions[] = { "-baseurl", "-externalentitycommand", "-paramentityparsing", "-useForeignDTD", "-forest", NULL }; enum validateOption { o_baseurl, o_externalentitycommand, o_paramentityparsing, o_useForeignDTD, o_forest }; static const char *paramEntityParsingValues[] = { "always", "never", "notstandalone", (char *) NULL }; enum paramEntityParsingValue { EXPAT_PARAMENTITYPARSINGALWAYS, EXPAT_PARAMENTITYPARSINGNEVER, EXPAT_PARAMENTITYPARSINGNOTSTANDALONE }; if (objc < 3) { Tcl_WrongNumArgs (interp, 2, objv, "?-baseurl ? " "?-externalentitycommand ? " "?-paramentityparsing (always|never|standalone? " " ?resultVarName?"); return TCL_ERROR; } if (sdata->validationState != VALIDATION_READY) { SetResult ("The schema command is busy"); return TCL_ERROR; } objc -= 2; objv += 2; memset (vdata, 0, sizeof (ValidateMethodData)); vdata->externalentitycommandObj = Tcl_NewStringObj ("::tdom::extRefHandler", 21); Tcl_IncrRefCount (vdata->externalentitycommandObj); while (objc > 2) { if (Tcl_GetIndexFromObj (interp, objv[0], validateOptions, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum validateOption) optionIndex) { case o_baseurl: baseurl = Tcl_GetString (objv[1]); break; case o_externalentitycommand: if (vdata->externalentitycommandObj) Tcl_DecrRefCount (vdata->externalentitycommandObj); Tcl_GetStringFromObj (objv[1], &len); if (len) { vdata->externalentitycommandObj = objv[1]; Tcl_IncrRefCount (objv[1]); } else { vdata->externalentitycommandObj = NULL; } break; case o_paramentityparsing: if (Tcl_GetIndexFromObj(interp, objv[1], paramEntityParsingValues, "value", 0, &value) != TCL_OK) { Tcl_DecrRefCount (vdata->externalentitycommandObj); return TCL_ERROR; } switch ((enum paramEntityParsingValue) value) { case EXPAT_PARAMENTITYPARSINGALWAYS: paramEntityParsing = XML_PARAM_ENTITY_PARSING_ALWAYS; break; case EXPAT_PARAMENTITYPARSINGNEVER: paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER; break; case EXPAT_PARAMENTITYPARSINGNOTSTANDALONE: paramEntityParsing = XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE; break; } break; case o_useForeignDTD: if (Tcl_GetBooleanFromObj(interp, objv[1], &useForeignDTD) != TCL_OK) { return TCL_ERROR; } break; case o_forest: if (Tcl_GetBooleanFromObj(interp, objv[1], &forest) != TCL_OK) { return TCL_ERROR; } break; } objc -= 2; objv += 2; } parser = XML_ParserCreate_MM (NULL, MEM_SUITE, &sep); vdata->interp = interp; vdata->sdata = sdata; vdata->parser = parser; sdata->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_SetBase (parser, baseurl); XML_SetElementHandler (parser, startElement, endElement); XML_SetCharacterDataHandler (parser, characterDataHandler); if (vdata->externalentitycommandObj) { XML_SetExternalEntityRefHandler (parser, externalEntityRefHandler); } XML_UseForeignDTD (parser, (unsigned char) useForeignDTD); XML_SetParamEntityParsing (parser, paramEntityParsing); switch (source) { case VALIDATE_STRING: xmlstr = Tcl_GetStringFromObj (objv[0], &len); result = TCL_OK; do { done = (len < TDOM_PCS); if (XML_Parse (parser, xmlstr, (int)(done ? len : TDOM_PCS), done) != XML_STATUS_OK || sdata->validationState == VALIDATION_ERROR) { validateReportError (interp, sdata, parser); result = TCL_ERROR; break; } if (!done) { xmlstr += TDOM_PCS; len -= TDOM_PCS; } } while (!done); break; case VALIDATE_FILENAME: filename = Tcl_TranslateFileName (interp, Tcl_GetString (objv[0]), &translatedFilename); if (filename == NULL) { result = TCL_ERROR; goto cleanup; } fd = open(filename, O_BINARY|O_RDONLY); if (fd < 0) { Tcl_ResetResult (interp); Tcl_AppendResult (interp, "error opening file \"", filename, "\"", (char *) NULL); result = TCL_ERROR; goto cleanup; } for (;;) { domLength nread; char *fbuf = XML_GetBuffer (parser, TDOM_EXPAT_READ_SIZE); if (!fbuf) { close (fd); Tcl_ResetResult (interp); Tcl_SetResult (interp, "Out of memory\n", NULL); result = TCL_ERROR; goto cleanup; } nread = read(fd, fbuf, TDOM_EXPAT_READ_SIZE); if (nread < 0) { close (fd); Tcl_ResetResult (interp); Tcl_AppendResult (interp, "error reading from file \"", filename, "\"", (char *) NULL); result = TCL_ERROR; goto cleanup; } result = XML_ParseBuffer (parser, (int)nread, nread == 0); if (result != XML_STATUS_OK || !nread || sdata->validationState == VALIDATION_ERROR) { close (fd); break; } } if (result != XML_STATUS_OK || sdata->validationState == VALIDATION_ERROR) { validateReportError (interp, sdata, parser); result = TCL_ERROR; } else { result = TCL_OK; } cleanup: Tcl_DStringFree (&translatedFilename); break; case VALIDATE_CHANNEL: channel = Tcl_GetChannel(interp, Tcl_GetString (objv[0]), &mode); if (channel == NULL) { SetResult ("The channel argument isn't a tcl channel"); result = TCL_ERROR; break; } bufObj = Tcl_NewObj(); Tcl_SetObjLength (bufObj, 6144); result = TCL_OK; do { len = Tcl_ReadChars (channel, bufObj, 1024, 0); done = (len < 1024); str = Tcl_GetStringFromObj(bufObj, &tclLen); rc = XML_Parse (parser, str, (int)tclLen, done); if (rc != XML_STATUS_OK || sdata->validationState == VALIDATION_ERROR) { validateReportError (interp, sdata, parser); result = TCL_ERROR; break; } } while (!done); Tcl_DecrRefCount (bufObj); break; } XML_ParserFree (parser); sdata->parser = NULL; FREE (vdata->uri); Tcl_DStringFree (&cdata); Tcl_DecrRefCount (vdata->externalentitycommandObj); /* sdata->evalError == 1 means Tcl evaluation error in called * script. sdata->evalError == 2 is used to signal "abort but * leave interp result alone, it is set". */ if (sdata->evalError == 1) { result = TCL_ERROR; } else { if (result == TCL_OK) { SetBooleanResult (1); } else { if (objc == 2) { Tcl_SetVar (interp, Tcl_GetString (objv[1]), Tcl_GetStringResult (interp), 0); } result = TCL_OK; SetBooleanResult (0); } } schemaReset (sdata); return result; } /* This implements the script interface to the created schema commands. Since validation may call out to Tcl scripts those scripts may delete the schema command (which just validates input by calling out to a Tcl script). This is handled by Tcl evaluation level counting and postponing the schema data deletion until back on top. After any code by this function that may have called out to a Tcl script it is important not to return locally but to signal the return value with the result variable and ensure to reach the code at the end of tDOM_schemaInstanceCmd. */ int tDOM_schemaInstanceCmd ( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { int methodIndex, keywordIndex, hnew, patternIndex; int result = TCL_OK, forwardDef = 0, j, k = 0; int savedDefineToplevel, type, n; domLength len; unsigned int i, savedNumPatternList, nrTypeInstances, typeInstancesLen; SchemaData *savedsdata = NULL, *sdata = (SchemaData *) clientData; Tcl_HashTable *hashTable; Tcl_HashEntry *h, *h1; SchemaCP *pattern, *current = NULL; void *namespacePtr, *savedNamespacePtr; char *errMsg; domDocument *doc; domNode *node; Tcl_Obj *attData; SchemaCP **typeInstances; ValidateMethodData vdata; static const char *schemaInstanceMethods[] = { "defelement", "defpattern", "start", "event", "delete", "reset", "define", "validate", "domvalidate", "deftexttype", "info", "reportcmd", "prefixns", "validatefile", "validatechannel", "defelementtype", "set", NULL }; enum schemaInstanceMethod { m_defelement, m_defpattern, m_start, m_event, m_delete, m_reset, m_define, m_validate, m_domvalidate, m_deftexttype, m_info, m_reportcmd, m_prefixns, m_validatefile, m_validatechannel, m_defelementtype, m_set }; static const char *eventKeywords[] = { "start", "end", "text", NULL }; enum eventKeyword { k_elementstart, k_elementend, k_text }; static const char *setKeywords[] = { "choiceHashThreshold", "attributeHashThreshold", NULL }; enum setKeyword { s_choiceHashThreshold, s_attributeHashThreshold }; if (sdata == NULL) { /* Inline defined defelement, defelementtype, defpattern, * deftexttype, start or prefixns */ sdata = GETASI; CHECK_SI; if (!sdata->defineToplevel && sdata->currentEvals > 1) { SetResult ("Command not allowed in nested schema define script"); return TCL_ERROR; } k = 1; } if (objc + k < 2) { Tcl_WrongNumArgs (interp, 1, objv, "subcommand ?arguments?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj (interp, objv[1-k], schemaInstanceMethods, "method", 0, &methodIndex) != TCL_OK) { return TCL_ERROR; } Tcl_ResetResult (interp); switch ((enum schemaInstanceMethod) methodIndex) { case m_defelement: case m_defpattern: CHECK_RECURSIVE_CALL if (objc != 4-k && objc != 5-k) { Tcl_WrongNumArgs (interp, 2-k, objv, "" " ?? pattern"); return TCL_ERROR; } if ((enum schemaInstanceMethod) methodIndex == m_defelement) { hashTable = &sdata->element; type = SCHEMA_CTYPE_NAME; } else { hashTable = &sdata->pattern; type = SCHEMA_CTYPE_PATTERN; } savedNumPatternList = sdata->numPatternList; namespacePtr = NULL; patternIndex = 3-k; if (objc == 5-k) { patternIndex = 4-k; namespacePtr = getNamespacePtr (sdata, Tcl_GetString (objv[3-k])); } h = Tcl_CreateHashEntry (hashTable, Tcl_GetString (objv[2-k]), &hnew); pattern = NULL; if (!hnew) { pattern = (SchemaCP *) Tcl_GetHashValue (h); while (pattern) { if (pattern->namespace == namespacePtr) { if (pattern->flags & FORWARD_PATTERN_DEF || pattern->flags & PLACEHOLDER_PATTERN_DEF) { forwardDef = 1; break; } if ((enum schemaInstanceMethod) methodIndex == m_defelement) { SetResult ("Element already defined " "in this namespace"); } else { SetResult ("Pattern already defined " "in this namespace"); } return TCL_ERROR; } pattern = pattern->next; } } if (pattern == NULL) { pattern = initSchemaCP (type, namespacePtr, Tcl_GetHashKey (hashTable, h)); if (!hnew) { current = (SchemaCP *) Tcl_GetHashValue (h); pattern->next = current; } REMEMBER_PATTERN (pattern); Tcl_SetHashValue (h, pattern); } SETASI(sdata); savedDefineToplevel = sdata->defineToplevel; savedNamespacePtr = sdata->currentNamespace; sdata->defineToplevel = 0; sdata->currentNamespace = namespacePtr; sdata->cp = pattern; sdata->numAttr = 0; sdata->numReqAttr = 0; sdata->currentAttrs = NULL; sdata->contentSize = CONTENT_ARRAY_SIZE_INIT; sdata->evalStub[3] = objv[patternIndex]; sdata->currentEvals++; result = Tcl_EvalObjv (interp, 4, sdata->evalStub, TCL_EVAL_GLOBAL); sdata->currentEvals--; sdata->currentNamespace = NULL; pattern->attrs = sdata->currentAttrs; pattern->numAttr = sdata->numAttr; pattern->numReqAttr = sdata->numReqAttr; if (result == TCL_OK) { if (pattern->numAttr) { attributeLookupPreparation (sdata, pattern); } if (forwardDef) { if (pattern->flags & FORWARD_PATTERN_DEF) { sdata->forwardPatternDefs--; pattern->flags &= ~FORWARD_PATTERN_DEF; } pattern->flags &= ~PLACEHOLDER_PATTERN_DEF; } pattern->defScript = objv[patternIndex]; Tcl_IncrRefCount (pattern->defScript); } else { if (forwardDef) { pattern->nc = 0; } cleanupLastPattern (sdata, savedNumPatternList); } sdata->defineToplevel = savedDefineToplevel; sdata->currentNamespace = savedNamespacePtr; if (!savedDefineToplevel) { SETASI(savedsdata); } break; case m_define: CHECK_EVAL if (objc != 3) { Tcl_WrongNumArgs (interp, 2, objv, ""); return TCL_ERROR; } if (clientData) { savedsdata = GETASI; if (savedsdata == sdata) { SetResult ("Recursive call of schema command is not allowed"); return TCL_ERROR; } } SETASI(sdata); savedNumPatternList = sdata->numPatternList; sdata->currentNamespace = 0; sdata->cp = NULL; sdata->contentSize = 0; sdata->defineToplevel = 1; sdata->evalStub[3] = objv[2]; sdata->currentEvals++; result = Tcl_EvalObjv (interp, 4, sdata->evalStub, TCL_EVAL_GLOBAL); sdata->currentEvals--; if (result != TCL_OK) { cleanupLastPattern (sdata, savedNumPatternList); } sdata->defineToplevel = 0; SETASI(savedsdata); break; case m_deftexttype: CHECK_RECURSIVE_CALL if (objc != 4-k) { Tcl_WrongNumArgs (interp, 2-k, objv, "" " "); return TCL_ERROR; } h = Tcl_CreateHashEntry (&sdata->textDef, Tcl_GetString (objv[2-k]), &hnew); if (!hnew) { pattern = Tcl_GetHashValue (h); if (pattern->flags & FORWARD_PATTERN_DEF) { forwardDef = 1; } else { SetResult ("There is already a text type definition with " "this name"); return TCL_ERROR; } } else { pattern = initSchemaCP (SCHEMA_CTYPE_CHOICE, NULL, NULL); pattern->type = SCHEMA_CTYPE_TEXT; REMEMBER_PATTERN (pattern); } SETASI(sdata); savedDefineToplevel = sdata->defineToplevel; result = evalConstraints (interp, sdata, pattern, objv[3-k]); sdata->defineToplevel = savedDefineToplevel; if (!savedDefineToplevel) { SETASI(savedsdata); } if (result == TCL_OK) { if (forwardDef) { pattern->flags &= ~FORWARD_PATTERN_DEF; sdata->forwardPatternDefs--; } else { Tcl_SetHashValue (h, pattern); } } else { if (!forwardDef) { Tcl_DeleteHashEntry (h); } } break; case m_start: CHECK_RECURSIVE_CALL if (objc < 3-k || objc > 4-k) { Tcl_WrongNumArgs (interp, 2-k, objv, "" " ??"); return TCL_ERROR; } if (sdata->start) { FREE (sdata->start); } if (objc == 3-k && strcmp (Tcl_GetString (objv[2-k]), "") == 0) { sdata->startNamespace = NULL; sdata->start = NULL; break; } sdata->start = tdomstrdup (Tcl_GetString (objv[2-k])); if (objc == 4-k) { sdata->startNamespace = getNamespacePtr (sdata, Tcl_GetString (objv[3-k])); } break; case m_event: CHECK_EVAL if (objc < 3) { Tcl_WrongNumArgs (interp, 2, objv, "" " ??"); return TCL_ERROR; } if (Tcl_GetIndexFromObj (interp, objv[2], eventKeywords, "keyword", 0, &keywordIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum eventKeyword) keywordIndex) { case k_elementstart: if (objc < 4 || objc > 6) { Tcl_WrongNumArgs (interp, 3, objv, "" "?? ??"); return TCL_ERROR; } namespacePtr = NULL; len = 0; attData = NULL; if (objc == 6) { namespacePtr = getNamespacePtr (sdata, Tcl_GetString (objv[5])); } if (objc >= 5) { if (Tcl_ListObjLength (interp, objv[4], &len) != TCL_OK) { if (objc == 6) { SetResult ("Invalid attribute information"); return TCL_ERROR; } else { namespacePtr = getNamespacePtr (sdata, Tcl_GetString (objv[4])); len = 0; } } else { if (len == 1) { namespacePtr = getNamespacePtr (sdata, Tcl_GetString (objv[4])); len = 0; } else if (len % 2 != 0) { SetResult ("Invalid attribute information"); return TCL_ERROR; } else { attData = objv[4]; } } } result = tDOM_probeElement (interp, sdata, Tcl_GetString (objv[3]), namespacePtr); /* In case of UNKNOWN_ROOT_ELEMENT and reportCmd is set * sdata->stack is NULL. */ if (!sdata->stack) break; if (sdata->skipDeep == 0 && result == TCL_OK) { result = probeEventAttribute (interp, sdata, attData, len); } break; case k_elementend: if (objc != 3) { Tcl_WrongNumArgs (interp, 3, objv, "No arguments expected."); return TCL_ERROR; } result = tDOM_probeElementEnd (interp, sdata); break; case k_text: if (objc != 4) { Tcl_WrongNumArgs (interp, 3, objv, ""); return TCL_ERROR; } result = tDOM_probeText (interp, sdata, Tcl_GetString (objv[3]), NULL); break; } break; case m_delete: if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } Tcl_DeleteCommand(interp, Tcl_GetString(objv[0])); /* We return immediately here to avoid clashes with postponed sdata cleanup at the end of the function. */ return TCL_OK; case m_reset: CHECK_EVAL schemaReset (sdata); break; case m_validate: result = validateSource (VALIDATE_STRING, sdata, &vdata, interp, objc, objv); break; case m_validatefile: result = validateSource (VALIDATE_FILENAME, sdata, &vdata, interp, objc, objv); break; case m_validatechannel: result = validateSource (VALIDATE_CHANNEL, sdata, &vdata, interp, objc, objv); break; case m_domvalidate: CHECK_EVAL if (objc < 3 || objc > 4) { Tcl_WrongNumArgs (interp, 2, objv, " ?resultVarName?"); return TCL_ERROR; } doc = tcldom_getDocumentFromName (interp, Tcl_GetString (objv[2]), &errMsg); if (doc) { node = doc->documentElement; } else { node = tcldom_getNodeFromObj (interp, objv[2]); if (!node) { SetResult ("The second argument must be either a " "document or a element node"); return TCL_ERROR; } } if (validateDOM (interp, sdata, node) == TCL_OK) { SetBooleanResult (1); if (objc == 4) { Tcl_SetVar (interp, Tcl_GetString (objv[3]), "", 0); } } else { if (objc == 4) { Tcl_SetVar (interp, Tcl_GetString (objv[3]), Tcl_GetStringResult (interp), 0); } SetBooleanResult (0); } schemaReset (sdata); break; case m_info: objv++; objc--; result = schemaInstanceInfoCmd (sdata, interp, objc, objv); break; case m_reportcmd: if (objc == 2) { if (sdata->reportCmd) { Tcl_SetObjResult (interp, sdata->reportCmd); } else { Tcl_SetObjResult (interp, Tcl_NewObj()); } break; } if (objc != 3) { Tcl_WrongNumArgs (interp, 2, objv, ""); return TCL_ERROR; } if (sdata->reportCmd) { Tcl_DecrRefCount (sdata->reportCmd); } if (strlen (Tcl_GetString (objv[2])) == 0) { sdata->reportCmd = NULL; } else { sdata->reportCmd = objv[2]; Tcl_IncrRefCount (sdata->reportCmd); } break; case m_prefixns: CHECK_RECURSIVE_CALL if (objc != 2-k && objc != 3-k) { Tcl_WrongNumArgs (interp, 2-k, objv, "?prefixUriList?"); return TCL_ERROR; } if (!k) {objc--; objv++;} result = tcldom_prefixNSlist (&sdata->prefixns, interp, objc, objv, "prefixns"); if (sdata->prefix.numEntries) { Tcl_DeleteHashTable (&sdata->prefix); Tcl_InitHashTable (&sdata->prefix, TCL_STRING_KEYS); } if (result == TCL_OK && sdata->prefixns) { j = 0; while (sdata->prefixns[j]) { h1 = Tcl_CreateHashEntry (&sdata->prefix, sdata->prefixns[j], &hnew); /* This means: First prefix mapping wins */ if (hnew) { h = Tcl_CreateHashEntry (&sdata->namespace, sdata->prefixns[j+1], &hnew); Tcl_SetHashValue (h1, Tcl_GetHashKey (&sdata->namespace, h)); } j += 2; } } break; case m_defelementtype: CHECK_RECURSIVE_CALL if (objc != 4-k && objc != 5-k) { Tcl_WrongNumArgs (interp, 2-k, objv, " " " ?? pattern"); return TCL_ERROR; } savedNumPatternList = sdata->numPatternList; namespacePtr = NULL; patternIndex = 3-k; if (objc == 5-k) { namespacePtr = getNamespacePtr (sdata, Tcl_GetString (objv[3-k])); patternIndex = 4-k; } h = Tcl_CreateHashEntry (&sdata->elementType , Tcl_GetString (objv[2-k]), &hnew); pattern = NULL; if (!hnew) { pattern = (SchemaCP *) Tcl_GetHashValue (h); while (pattern) { if (pattern->namespace == namespacePtr) { if (pattern->flags & FORWARD_PATTERN_DEF) { forwardDef = 1; break; } SetResult ("Element type already defined in this " "namespace"); return TCL_ERROR; } pattern = pattern->next; } } if (pattern == NULL) { pattern = initSchemaCP (SCHEMA_CTYPE_NAME, namespacePtr, Tcl_GetHashKey (&sdata->elementType, h)); pattern->flags |= ELEMENTTYPE_DEF; if (!hnew) { current = (SchemaCP *) Tcl_GetHashValue (h); pattern->next = current; } REMEMBER_PATTERN (pattern); Tcl_SetHashValue (h, pattern); } if (forwardDef) { /* The type was already forward defined. Save the with the forward defined pattern stored instance elements to be able to set the actual content of the instance pattern after the type content is eventually defined below. */ typeInstances = pattern->content; nrTypeInstances = pattern->nc; typeInstancesLen = pattern->numAttr; pattern->content = (SchemaCP**) MALLOC ( sizeof(SchemaCP*) * CONTENT_ARRAY_SIZE_INIT ); pattern->numAttr = 0; pattern->nc = 0; } SETASI(sdata); savedDefineToplevel = sdata->defineToplevel; savedNamespacePtr = sdata->currentNamespace; sdata->defineToplevel = 0; sdata->currentNamespace = namespacePtr; sdata->cp = pattern; sdata->numAttr = 0; sdata->numReqAttr = 0; sdata->currentAttrs = NULL; sdata->contentSize = CONTENT_ARRAY_SIZE_INIT; sdata->evalStub[3] = objv[patternIndex]; sdata->currentEvals++; result = Tcl_EvalObjv (interp, 4, sdata->evalStub, TCL_EVAL_GLOBAL); sdata->currentEvals--; sdata->currentNamespace = NULL; pattern->attrs = sdata->currentAttrs; pattern->numAttr = sdata->numAttr; pattern->numReqAttr = sdata->numReqAttr; if (result == TCL_OK) { if (pattern->numAttr) { attributeLookupPreparation (sdata, pattern); } if (forwardDef) { sdata->forwardPatternDefs--; pattern->flags &= ~FORWARD_PATTERN_DEF; for (i = 0; i < nrTypeInstances; i++) { typeInstances[i]->content = pattern->content; typeInstances[i]->quants = pattern->quants; typeInstances[i]->nc = pattern->nc; typeInstances[i]->typedata = pattern->typedata; typeInstances[i]->attrs = pattern->attrs; typeInstances[i]->numAttr = pattern->numAttr; typeInstances[i]->numReqAttr = pattern->numReqAttr; typeInstances[i]->domKeys = pattern->domKeys; typeInstances[i]->keySpace = pattern->keySpace; /* TODO: decide what to do with associated */ } FREE (typeInstances); } pattern->defScript = objv[patternIndex]; Tcl_IncrRefCount (pattern->defScript); } else { if (forwardDef) { FREE (pattern->content); pattern->content = typeInstances; pattern->nc = nrTypeInstances; pattern->numAttr = typeInstancesLen; } cleanupLastPattern (sdata, savedNumPatternList); } sdata->defineToplevel = savedDefineToplevel; sdata->currentNamespace = savedNamespacePtr; if (!savedDefineToplevel) { SETASI(savedsdata); } break; case m_set: if (objc < 3 || objc > 4) { Tcl_WrongNumArgs (interp, 2, objv, "setting ?value?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj (interp, objv[2], setKeywords, "setting", 0, &keywordIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum setKeyword) keywordIndex) { case s_choiceHashThreshold: if (objc == 4) { if (Tcl_GetIntFromObj (interp, objv[3], &n) != TCL_OK) { SetResult ("Invalid threshold value"); return TCL_ERROR; } if (n < 0) { SetResult ("Invalid threshold value"); return TCL_ERROR; } sdata->choiceHashThreshold = n; } SetIntResult (sdata->choiceHashThreshold); break; case s_attributeHashThreshold: if (objc == 4) { if (Tcl_GetIntFromObj (interp, objv[3], &n) != TCL_OK) { SetResult ("Invalid threshold value"); return TCL_ERROR; } if (n < 0) { SetResult ("Invalid threshold value"); return TCL_ERROR; } sdata->attributeHashThreshold = n; } SetIntResult (sdata->attributeHashThreshold); break; } break; default: Tcl_SetResult (interp, "unknown method", NULL); result = TCL_ERROR; break; } if (sdata->cleanupAfterUse && sdata->currentEvals == 0 && !(sdata->inuse > 0)) { schemaInstanceDelete (sdata); } return result; } /* *---------------------------------------------------------------------------- * * tDOM_SchemaObjCmd -- * * This procedure is invoked to process the "schema" command. * See the user documentation for what it does. * * Results: * A standard Tcl result. * * Side effects: * * *---------------------------------------------------------------------------- */ int tDOM_SchemaObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { int methodIndex, ind, result = TCL_OK; SchemaData *sdata; static const char *schemaMethods[] = { "create", NULL }; enum schemaMethod { m_create }; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs (interp, 1, objv, "subcommand ?argument?"); return TCL_ERROR; } if (objc == 2) { methodIndex = m_create; ind = 1; } else { if (Tcl_GetIndexFromObj (interp, objv[1], schemaMethods, "method", 0, &methodIndex) != TCL_OK) { return TCL_ERROR; } ind = 2; } Tcl_ResetResult (interp); switch ((enum schemaMethod) methodIndex) { case m_create: sdata = initSchemaData (objv[ind]); Tcl_CreateObjCommand (interp, Tcl_GetString(objv[ind]), tDOM_schemaInstanceCmd, (ClientData) sdata, schemaInstanceDelete); Tcl_SetObjResult (interp, objv[ind]); break; default: Tcl_SetResult (interp, "unknown method", NULL); result = TCL_ERROR; break; } return result; } static SchemaQuant getQuant ( Tcl_Interp *interp, Tcl_Obj *quantObj, int *n, int *m ) { char *quantStr; domLength len; Tcl_Obj *thisObj; *n = 0; *m = 0; if (!quantObj) { return SCHEMA_CQUANT_ONE; } quantStr = Tcl_GetStringFromObj (quantObj, &len); if (len == 1) { switch (quantStr[0]) { case '!': return SCHEMA_CQUANT_ONE; case '*': return SCHEMA_CQUANT_REP; case '?': return SCHEMA_CQUANT_OPT; case '+': return SCHEMA_CQUANT_PLUS; } } if (Tcl_ListObjLength (interp, quantObj, &len) != TCL_OK) { SetResult ("Invalid quant specifier"); return SCHEMA_CQUANT_ERROR; } if (len != 1 && len != 2) { SetResult ("Invalid quant specifier"); return SCHEMA_CQUANT_ERROR; } if (len == 1) { if (Tcl_GetIntFromObj (interp, quantObj, n) != TCL_OK) { SetResult ("Invalid quant specifier"); return SCHEMA_CQUANT_ERROR; } if (*n < 1) { SetResult ("Invalid quant specifier"); return SCHEMA_CQUANT_ERROR; } if (*n == 1) { return SCHEMA_CQUANT_ONE; *n = 0; } return SCHEMA_CQUANT_NM; } /* The "list-ness" of the quantObj is already checked by the * Tcl_ListObjLength() call above, no need to check result. */ Tcl_ListObjIndex (interp, quantObj, 0, &thisObj); if (Tcl_GetIntFromObj (interp, thisObj, n) != TCL_OK) { SetResult ("Invalid quant specifier"); return SCHEMA_CQUANT_ERROR; } if (*n < 0) { SetResult ("Invalid quant specifier"); return SCHEMA_CQUANT_ERROR; } Tcl_ListObjIndex (interp, quantObj, 1, &thisObj); if (Tcl_GetIntFromObj (interp, thisObj, m) == TCL_OK) { if (*n > *m) { SetResult ("Invalid quant specifier"); return SCHEMA_CQUANT_ERROR; } if (*n == 0 && *m == 1) { return SCHEMA_CQUANT_OPT; } if (*n == 1 && *m == 1) { return SCHEMA_CQUANT_ONE; } return SCHEMA_CQUANT_NM; } else { quantStr = Tcl_GetStringFromObj (thisObj, &len); if (len == 1 && quantStr[0] == '*') { if (*n == 0) { return SCHEMA_CQUANT_REP; } *m = -1; return SCHEMA_CQUANT_NM; } else { SetResult ("Invalid quant specifier"); return SCHEMA_CQUANT_ERROR; } } } /* Implements the schema definition command "any" */ static int AnyPatternObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaCP *pattern; SchemaQuant quant; char *ns = NULL, *ns1; int n, m, hnew, revert, optionIndex; domLength nrns, i; Tcl_Obj *nsObj; Tcl_HashTable *t = NULL; static const char *anyOptions[] = { "-not", "--", NULL }; enum anyOption { o_not, o_Last }; CHECK_SI CHECK_TOPLEVEL revert = 0; while (objc > 1) { if (Tcl_GetIndexFromObj(interp, objv[1], anyOptions, "option", 0, &optionIndex) != TCL_OK) { break; } switch ((enum anyOption) optionIndex) { case o_not: revert = 1; objv++; objc--; continue; case o_Last: objv++; objc--; break; } if ((enum anyOption) optionIndex == o_Last) break; } checkNrArgs (1,3,"(options? ?namespace list? ?quant?"); quant = SCHEMA_CQUANT_ONE; if (objc == 1) { n = 0; m = 0; goto createpattern; } else if (objc == 2) { quant = getQuant (interp, objv[1], &n, &m); if (quant != SCHEMA_CQUANT_ERROR) { goto createpattern; } quant = SCHEMA_CQUANT_ONE; } else { quant = getQuant (interp, objv[2], &n, &m); if (quant == SCHEMA_CQUANT_ERROR) { return TCL_ERROR; } } if (Tcl_ListObjLength (interp, objv[1], &nrns) != TCL_OK) { SetResult ("The argument must be a valid tcl list"); return TCL_ERROR; } if (nrns == 1) { Tcl_ListObjIndex (interp, objv[1], 0, &nsObj); ns1 = Tcl_GetString (nsObj); if (ns1[0] == '\0') { ns = emptyStr; } else { ns = getNamespacePtr (sdata, Tcl_GetString (nsObj)); } } else { t = TMALLOC (Tcl_HashTable); Tcl_InitHashTable (t, TCL_ONE_WORD_KEYS); for (i = 0; i < nrns; i++) { Tcl_ListObjIndex (interp, objv[1], i, &nsObj); ns1 = Tcl_GetString (nsObj); if (ns1[0] == '\0') { ns = emptyStr; } else { ns1 = getNamespacePtr (sdata, Tcl_GetString (nsObj)); Tcl_CreateHashEntry (t, ns1, &hnew); } } } createpattern: pattern = initSchemaCP (SCHEMA_CTYPE_ANY, ns, NULL); if (t) pattern->typedata = (void*)t; if (revert) pattern->flags |= ANY_NOT; REMEMBER_PATTERN (pattern) addToContent(sdata, pattern, quant, n, m); return TCL_OK; } static int evalDefinition ( Tcl_Interp *interp, SchemaData *sdata, Tcl_Obj *definition, SchemaCP *pattern, SchemaQuant quant, int n, int m ) { SchemaCP *savedCP; SchemaAttr **savedCurrentAttrs; unsigned int savedContenSize, i; unsigned int savedAttrSize, savedNumAttr, savedNumReqAttr; int result, onlyName, hnew; Tcl_HashEntry *h; Tcl_HashTable *t; /* Save some state of sdata .. */ savedCP = sdata->cp; savedContenSize = sdata->contentSize; savedNumAttr = sdata->numAttr; savedNumReqAttr = sdata->numReqAttr; savedAttrSize = sdata->attrSize; savedCurrentAttrs = sdata->currentAttrs; /* ... and prepare sdata for definition evaluation. */ sdata->cp = pattern; sdata->contentSize = CONTENT_ARRAY_SIZE_INIT; sdata->numAttr = 0; sdata->numReqAttr = 0; sdata->currentAttrs = NULL; sdata->attrSize = 0; sdata->currentEvals++; result = Tcl_EvalObjEx (interp, definition, TCL_EVAL_DIRECT); sdata->currentEvals--; pattern->attrs = sdata->currentAttrs; pattern->numAttr = sdata->numAttr; pattern->numReqAttr = sdata->numReqAttr; /* ... and restore the previously saved sdata states */ sdata->cp = savedCP; sdata->contentSize = savedContenSize; sdata->numAttr = savedNumAttr; sdata->numReqAttr = savedNumReqAttr; sdata->currentAttrs = savedCurrentAttrs; sdata->attrSize = savedAttrSize; if (result != TCL_OK) { freeSchemaCP (pattern); return result; } REMEMBER_PATTERN (pattern); if (pattern->numAttr) { attributeLookupPreparation (sdata, pattern); } if (pattern->type == SCHEMA_CTYPE_CHOICE) { onlyName = 1; for (i = 0; i < pattern->nc; i++) { if (pattern->content[i]->type != SCHEMA_CTYPE_NAME && pattern->content[i]->type != SCHEMA_CTYPE_TEXT) { onlyName = 0; break; } } if (onlyName && pattern->nc > sdata->choiceHashThreshold) { t = TMALLOC (Tcl_HashTable); Tcl_InitHashTable (t, TCL_ONE_WORD_KEYS); hnew = 1; for (i = 0; i < pattern->nc; i++) { if (pattern->content[i]->type != SCHEMA_CTYPE_NAME) { continue; } h = Tcl_CreateHashEntry (t, pattern->content[i]->name, &hnew); if (!hnew) { break; } Tcl_SetHashValue (h, pattern->content[i]); } if (hnew) { pattern->typedata = (void *)t; } else { /* No simple lookup possible because of more than one * element with the same local name belong to the * choices. Rewind. */ Tcl_DeleteHashTable (t); FREE (t); } } } addToContent (sdata, pattern, quant, n, m); return TCL_OK; } /* Implements the schema definition commands "element" */ static int ElementPatternObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; Tcl_HashEntry *h; SchemaCP *pattern = NULL, *typePattern = NULL, *current; SchemaQuant quant; int hnew, n, m, typed = 0, ind = 3, localdef = 0; char *namePtr; CHECK_SI CHECK_TOPLEVEL checkNrArgs (2,5,"Expected: elementName ?quant? ?(pattern|\"type\" " "typename)?"); quant = getQuant (interp, objc == 2 ? NULL : objv[2], &n, &m); if (quant == SCHEMA_CQUANT_ERROR) { /* May be default quant with local definition or type. */ if (objc != 3 && objc != 4) { SetResult("Expected: elementName ?quant? ?(pattern|\"type\" " "typename)?"); return TCL_ERROR; } quant = SCHEMA_CQUANT_ONE; if (objc == 4) { /* Reference to type */ typed = 1; } else { ind = 2; localdef = 1; } } else { if (objc == 5) { typed = 1; ind = 4; } else if (objc == 4) { localdef = 1; } } if (typed) { if (strcmp (Tcl_GetString (objv[ind-1]), "type") != 0) { SetResult("Expected: elementName ?quant? ?(pattern|\"type\" " "typename)?"); return TCL_ERROR; } } h = Tcl_CreateHashEntry (&sdata->element, Tcl_GetString(objv[1]), &hnew); namePtr = Tcl_GetHashKey (&sdata->element, h); if (hnew) { pattern = initSchemaCP( SCHEMA_CTYPE_NAME, sdata->currentNamespace, namePtr); if (typed || localdef) { pattern->flags |= PLACEHOLDER_PATTERN_DEF; } else { pattern->flags |= FORWARD_PATTERN_DEF; sdata->forwardPatternDefs++; } Tcl_SetHashValue (h, pattern); REMEMBER_PATTERN (pattern); } if (typed) { pattern = NULL; h = Tcl_CreateHashEntry (&sdata->elementType, Tcl_GetString (objv[ind]), &hnew); if (!hnew) { typePattern = (SchemaCP *) Tcl_GetHashValue (h); while (typePattern) { if (typePattern->namespace == sdata->currentNamespace) { break; } typePattern = typePattern->next; } } if (!typePattern) { typePattern = initSchemaCP ( SCHEMA_CTYPE_NAME, sdata->currentNamespace, Tcl_GetHashKey (&sdata->elementType, h)); typePattern->flags |= (ELEMENTTYPE_DEF | FORWARD_PATTERN_DEF); sdata->forwardPatternDefs++; REMEMBER_PATTERN (typePattern); /* We (ab)use the numAttr for the allocated content length * for forward defined types, to be able to store the * instance pattern until the type pattern is eventually * defined. */ typePattern->numAttr = CONTENT_ARRAY_SIZE_INIT; if (!hnew) { current = (SchemaCP *) Tcl_GetHashValue (h); typePattern->next = current; } Tcl_SetHashValue (h, typePattern); } h = Tcl_CreateHashEntry (&sdata->elementTypeInstance, namePtr, &hnew); if (!hnew) { pattern = (SchemaCP *) Tcl_GetHashValue (h); while (pattern) { if (pattern->namespace == sdata->currentNamespace && pattern->typeptr == typePattern) { break; } pattern = pattern->next; } } if (!pattern) { pattern = TMALLOC (SchemaCP); memset (pattern, 0, sizeof(SchemaCP)); pattern->type = SCHEMA_CTYPE_NAME; pattern->namespace = sdata->currentNamespace; pattern->name = namePtr; pattern->flags |= TYPED_ELEMENT; REMEMBER_PATTERN (pattern); if (!hnew) { current = (SchemaCP *) Tcl_GetHashValue (h); pattern->next = current; } Tcl_SetHashValue (h, pattern); pattern->typeptr = typePattern; } if (typePattern->flags & FORWARD_PATTERN_DEF) { /* Remember the instance pattern with the type pattern * (a bit misusing struct members) to be able to set * the instance pattern to the actual content if the * type pattern is eventually defined. */ if (typePattern->nc == typePattern->numAttr) { typePattern->content = REALLOC (typePattern->content, 2 * typePattern->numAttr * sizeof (SchemaCP*)); typePattern->numAttr *= 2; } typePattern->content[typePattern->nc] = pattern; typePattern->nc++; } else { pattern->content = typePattern->content; pattern->quants = typePattern->quants; pattern->nc = typePattern->nc; pattern->typedata = typePattern->typedata; pattern->attrs = typePattern->attrs; pattern->numAttr = typePattern->numAttr; pattern->numReqAttr = typePattern->numReqAttr; pattern->domKeys = typePattern->domKeys; pattern->keySpace = typePattern->keySpace; /* TODO: decide what to do with associated */ } addToContent (sdata, pattern, quant, n, m); } else if (localdef) { pattern = initSchemaCP (SCHEMA_CTYPE_NAME, sdata->currentNamespace, namePtr); pattern->flags |= LOCAL_DEFINED_ELEMENT; return evalDefinition (interp, sdata, objv[ind], pattern, quant, n, m); } else { /* Reference to an element. */ if (!hnew) { pattern = (SchemaCP *) Tcl_GetHashValue (h); while (pattern) { if (pattern->namespace == sdata->currentNamespace) { break; } pattern = pattern->next; } if (!pattern) { pattern = initSchemaCP (SCHEMA_CTYPE_NAME, sdata->currentNamespace, namePtr); pattern->flags |= FORWARD_PATTERN_DEF; sdata->forwardPatternDefs++; if (!hnew) { current = (SchemaCP *) Tcl_GetHashValue (h); pattern->next = current; } REMEMBER_PATTERN (pattern); Tcl_SetHashValue (h, pattern); } } addToContent (sdata, pattern, quant, n, m); } return TCL_OK; } /* Implements the schema definition commands "ref" */ static int RefPatternObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; Tcl_HashEntry *h; SchemaCP *pattern = NULL, *current; SchemaQuant quant; int hnew, n, m; CHECK_SI CHECK_TOPLEVEL checkNrArgs (2,3,"Expected: patternName ?quant?"); quant = getQuant (interp, objc == 2 ? NULL : objv[2], &n, &m); if (quant == SCHEMA_CQUANT_ERROR) { return TCL_ERROR; } h = Tcl_CreateHashEntry (&sdata->pattern, Tcl_GetString(objv[1]), &hnew); if (!hnew) { pattern = (SchemaCP *) Tcl_GetHashValue (h); while (pattern) { if (pattern->namespace == sdata->currentNamespace) { break; } pattern = pattern->next; } } if (!pattern) { pattern = initSchemaCP ( SCHEMA_CTYPE_PATTERN, sdata->currentNamespace, Tcl_GetHashKey (&sdata->pattern, h) ); pattern->flags |= FORWARD_PATTERN_DEF; sdata->forwardPatternDefs++; if (!hnew) { current = (SchemaCP *) Tcl_GetHashValue (h); pattern->next = current; } REMEMBER_PATTERN (pattern); Tcl_SetHashValue (h, pattern); } addToContent (sdata, pattern, quant, n, m); return TCL_OK; } /* Implements the schema definition commands "choice", "group", * "interleave" and "mixed" */ static int AnonPatternObjCmd ( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; Schema_CP_Type patternType; SchemaQuant quant; SchemaCP *pattern; int n, m; CHECK_SI CHECK_TOPLEVEL checkNrArgs (2,3,"Expected: ?quant? definition"); quant = getQuant (interp, objc == 2 ? NULL : objv[1], &n, &m); if (quant == SCHEMA_CQUANT_ERROR) { return TCL_ERROR; } if (clientData == 0) { patternType = SCHEMA_CTYPE_CHOICE; } else if (clientData == (ClientData) 1) { patternType = SCHEMA_CTYPE_CHOICE; /* Default quant for mixed is * */ if (objc == 2) { quant = SCHEMA_CQUANT_REP; } } else if (clientData == (ClientData) 2) { patternType = SCHEMA_CTYPE_INTERLEAVE; } else { patternType = SCHEMA_CTYPE_PATTERN; } pattern = initSchemaCP (patternType, NULL, NULL); if (clientData == (ClientData) 1) { pattern->flags |= MIXED_CONTENT; } return evalDefinition (interp, sdata, objc == 2 ? objv[1] : objv[2], pattern, quant, n, m); } static int maybeAddAttr ( Tcl_Interp *interp, SchemaData *sdata, Tcl_Obj *nameObj, Tcl_Obj *namespaceObj, Tcl_Obj *scriptObj, int required, SchemaCP *type ) { Tcl_HashEntry *h; int hnew, result = TCL_OK; unsigned int i; char *name, *namespace = NULL; SchemaAttr *attr; SchemaCP *cp; if (namespaceObj) { namespace = getNamespacePtr (sdata, Tcl_GetString (namespaceObj)); } h = Tcl_CreateHashEntry (&sdata->attrNames, Tcl_GetString (nameObj), &hnew); name = Tcl_GetHashKey (&sdata->attrNames, h); if (!hnew) { /* Check, if there is already an attribute with this name and namespace */ for (i = 0; i < sdata->numAttr; i++) { if (sdata->currentAttrs[i]->name == name && sdata->currentAttrs[i]->namespace == namespace) { /* Ignore the later attribute declaration */ return TCL_OK; } } } attr = TMALLOC (SchemaAttr); attr->namespace = namespace; attr->name = name; attr->next = NULL; attr->required = required; if (scriptObj) { cp = initSchemaCP (SCHEMA_CTYPE_CHOICE, NULL, NULL); cp->type = SCHEMA_CTYPE_TEXT; REMEMBER_PATTERN (cp) sdata->isAttributeConstraint = 1; result = evalConstraints (interp, sdata, cp, scriptObj); sdata->isAttributeConstraint = 0; attr->cp = cp; } else if (type) { attr->cp = type; } else { attr->cp = NULL; } if (!sdata->currentAttrs) { sdata->currentAttrs = MALLOC (sizeof(SchemaAttr*) * ATTR_ARRAY_INIT); sdata->attrSize = ATTR_ARRAY_INIT; } else if (sdata->numAttr == sdata->attrSize) { sdata->currentAttrs = REALLOC (sdata->currentAttrs, 2 * sdata->attrSize * sizeof (SchemaAttr)); sdata->attrSize *= 2; } sdata->currentAttrs[sdata->numAttr] = attr; sdata->numAttr++; if (required) { sdata->numReqAttr++; } return result; } static int AttributePatternObjCmd ( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; char *str; int required = 1; domLength len; Tcl_Obj *nsObj, *nameObj; Tcl_HashEntry *h; SchemaCP *type; CHECK_SI CHECK_TOPLEVEL if (sdata->cp->type != SCHEMA_CTYPE_NAME) { SetResult ("The commands attribute and nsattribute are only allowed " "toplevel in element definition scripts"); return TCL_ERROR; } if (clientData) { checkNrArgs (3,6,"Expected:" " name namespace" " | name namespace attquant" " | name namespace ?attquant? " " | name namespace ?attquant? \"type\" typename"); nsObj = objv[2]; } else { checkNrArgs (2,5,"Expected:" " name" " | name attquant" " | name ?attquant? " " | name ?attquant? \"type\" typename"); nsObj = NULL; } nameObj = objv[1]; if (clientData) { objv++; objc--; } if (objc == 2) { return maybeAddAttr (interp, sdata, nameObj, nsObj, NULL, 1, NULL); } str = Tcl_GetStringFromObj (objv[2], &len); if (len == 1) { if (str[0] == '?') { required = 0; } else if (str[0] != '!') { SetResult ("Invalid attribute quant"); return TCL_ERROR; } if (objc == 3) { return maybeAddAttr (interp, sdata, nameObj, nsObj, NULL, required, NULL); } objv++; objc--; str = Tcl_GetStringFromObj (objv[2], &len); } if (objc == 4) { if (len != 4 || strcmp("type", str) != 0) { if (clientData) { SetResult ("Expected:" " name namespace" " | name namespace attquant" " | name namespace ?attquant? " " | name namespace ?attquant? \"type\" typename"); } else { SetResult ("Expected:" " name" " | name attquant" " | name ?attquant? " " | name ?attquant? \"type\" typename"); } return TCL_ERROR; } h = Tcl_FindHashEntry (&sdata->textDef, Tcl_GetString (objv[3])); if (!h) { SetResult3 ("Unknown text type \"", Tcl_GetString (objv[3]), "\""); return TCL_ERROR; } type = (SchemaCP *) Tcl_GetHashValue (h); return maybeAddAttr (interp, sdata, nameObj, nsObj, NULL, required, type); } else { return maybeAddAttr (interp, sdata, nameObj, nsObj, objv[2], required, NULL); } } static int NamespacePatternObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; char *currentNamespace; int result; CHECK_SI CHECK_TOPLEVEL checkNrArgs (3,3,"Expected: namespace pattern"); currentNamespace = sdata->currentNamespace; sdata->currentNamespace = getNamespacePtr (sdata, Tcl_GetString(objv[1])); sdata->currentEvals++; result = Tcl_EvalObjEx (interp, objv[2], TCL_EVAL_DIRECT); sdata->currentEvals--; sdata->currentNamespace = currentNamespace; return result; } static int TextPatternObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaQuant quant = SCHEMA_CQUANT_OPT; SchemaCP *pattern; Tcl_HashEntry *h; int hnew, result = TCL_OK; CHECK_SI CHECK_TOPLEVEL checkNrArgs (1,3,"?? | type "); if (objc == 1) { pattern = initSchemaCP (SCHEMA_CTYPE_TEXT, NULL, NULL); } else if (objc == 2) { quant = SCHEMA_CQUANT_ONE; pattern = initSchemaCP (SCHEMA_CTYPE_CHOICE, NULL, NULL); pattern->type = SCHEMA_CTYPE_TEXT; } else { if (strcmp("type", Tcl_GetString (objv[1])) != 0) { SetResult ("Expected: ?? | type "); return TCL_ERROR; } h = Tcl_CreateHashEntry (&sdata->textDef, Tcl_GetString (objv[2]), &hnew); if (hnew) { pattern = initSchemaCP (SCHEMA_CTYPE_CHOICE, NULL, NULL); pattern->type = SCHEMA_CTYPE_TEXT; REMEMBER_PATTERN (pattern) pattern->flags |= FORWARD_PATTERN_DEF; sdata->forwardPatternDefs++; Tcl_SetHashValue (h, pattern); } quant = SCHEMA_CQUANT_ONE; pattern = (SchemaCP *) Tcl_GetHashValue (h); } if (objc == 2) { result = evalConstraints (interp, sdata, pattern, objv[1]); } if (result == TCL_OK) { if (objc < 3) { REMEMBER_PATTERN (pattern) } addToContent (sdata, pattern, quant, 0, 0); } else { freeSchemaCP (pattern); } return result; } static int VirtualPatternObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaCP *pattern; int i; CHECK_SI CHECK_TOPLEVEL if (objc < 2) { SetResult ("Expected: ?arg? ?arg? ..."); return TCL_ERROR; } if (sdata->cp->type != SCHEMA_CTYPE_NAME && sdata->cp->type != SCHEMA_CTYPE_PATTERN) { SetResult ("The \"tcl\" schema definition command is only " "allowed in sequential context (defelement, " "element, group or defpattern)"); return TCL_ERROR; } pattern = initSchemaCP (SCHEMA_CTYPE_VIRTUAL, NULL, NULL); REMEMBER_PATTERN (pattern) pattern->content = MALLOC (sizeof (Tcl_Obj*) * (objc-1)); for (i = 0; i < objc-1; i++) { pattern->content[i] = (SchemaCP *) objv[i+1]; Tcl_IncrRefCount (objv[i+1]); } pattern->nc = objc-1; addToContent (sdata, pattern, SCHEMA_CQUANT_ONE, 0, 0); return TCL_OK; } static int SelfObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const UNUSED(objv[]) ) { SchemaData *sdata = GETASI; CHECK_SI CHECK_TOPLEVEL if (objc != 1) { SetResult ("No argument expected"); return TCL_ERROR; } Tcl_SetObjResult (interp, Tcl_DuplicateObj (sdata->self)); return TCL_OK; } static int domuniquePatternObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; ast t; char *errMsg = NULL; domKeyConstraint *kc, *kc1; domLength i, nrFields; int flags = 0; Tcl_Obj *elm; CHECK_SI CHECK_TOPLEVEL checkNrArgs (3, 6, "Expected: ?? ?\"IGNORE_EMPTY_FIELD_SET\"|(?\"EMPTY_FIELD_SET_VALUE\" cp->type != SCHEMA_CTYPE_NAME) { SetResult ("The domunique schema definition command is only " "allowed as direct child of an element."); } if (Tcl_ListObjLength (interp, objv[2], &nrFields) != TCL_OK) { SetResult ("The argument must be a valid tcl list"); return TCL_ERROR; } if (nrFields == 0) { SetResult ("Non empty fieldlist argument expected."); return TCL_ERROR; } if (objc == 5) { if (strcmp (Tcl_GetString (objv[4]), "IGNORE_EMPTY_FIELD_SET") != 0) { SetResult3 ("Unknown flag '", Tcl_GetString (objv[4]), "'"); return TCL_ERROR; } flags |= DKC_FLAG_IGNORE_EMPTY_FIELD_SET; } if (objc == 6) { if (strcmp (Tcl_GetString (objv[4]), "EMPTY_FIELD_SET_VALUE") != 0) { SetResult3 ("Unknown flag '", Tcl_GetString (objv[4]), "'"); return TCL_ERROR; } } if (xpathParse (Tcl_GetString (objv[1]), NULL, XPATH_EXPR, sdata->prefixns, NULL, &t, &errMsg) < 0) { SetResult3 ("Error in selector xpath: '", errMsg, ""); FREE (errMsg); return TCL_ERROR; } kc = TMALLOC (domKeyConstraint); memset (kc, 0, sizeof (domKeyConstraint)); kc->fields = MALLOC (sizeof (ast) * nrFields); memset (kc->fields, 0, sizeof (ast) * nrFields); kc->nrFields = nrFields; kc->selector = t; kc->flags = flags; for (i = 0; i < nrFields; i++) { Tcl_ListObjIndex (interp, objv[2], i, &elm); if (xpathParse (Tcl_GetString (elm), NULL, XPATH_EXPR, sdata->prefixns, NULL, &t, &errMsg) < 0) { SetResult3 ("Error in field xpath: '", errMsg, ""); FREE (errMsg); xpathFreeAst (t); freedomKeyConstraints (kc); return TCL_ERROR; } kc->fields[i] = t; } if (objc >= 4) { kc->name = tdomstrdup (Tcl_GetString (objv[3])); } if (objc == 6) { kc->emptyFieldSetValue = tdomstrdup (Tcl_GetString (objv[5])); kc->efsv_len = strlen (kc->emptyFieldSetValue); } /* Append to end so that the constraints are checked in * definition order */ if (sdata->cp->domKeys) { kc1 = sdata->cp->domKeys; while (1) { if (kc1->next) kc1 = kc1->next; else break; } kc1->next = kc; } else { sdata->cp->domKeys = kc; } return TCL_OK; } static int domxpathbooleanPatternObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; ast t; char *errMsg = NULL; domKeyConstraint *kc, *kc1; CHECK_SI CHECK_TOPLEVEL checkNrArgs (2, 3, "Expected: ??"); if (sdata->cp->type != SCHEMA_CTYPE_NAME) { SetResult ("The domxpathboolean schema definition command is only " "allowed as direct child of an element."); } if (xpathParse (Tcl_GetString (objv[1]), NULL, XPATH_EXPR, sdata->prefixns, NULL, &t, &errMsg) < 0) { SetResult3 ("Error in selector xpath: '", errMsg, ""); FREE (errMsg); return TCL_ERROR; } kc = TMALLOC (domKeyConstraint); memset (kc, 0, sizeof (domKeyConstraint)); kc->selector = t; kc->flags |= DKC_FLAG_BOOLEAN; if (objc == 3) { kc->name = tdomstrdup (Tcl_GetString (objv[2])); } /* Append to end so that the constraints are checked in * definition order */ if (sdata->cp->domKeys) { kc1 = sdata->cp->domKeys; while (1) { if (kc1->next) kc1 = kc1->next; else break; } kc1->next = kc; } else { sdata->cp->domKeys = kc; } return TCL_OK; } static int jsontypePatternObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; int jsonType; SchemaCP *pattern; CHECK_SI CHECK_TOPLEVEL if (sdata->cp->type != SCHEMA_CTYPE_NAME) { SetResult ("The command jsontype is only allowed toplevel in element " "definition scripts"); return TCL_ERROR; } checkNrArgs (2,2,"Expected: "); if (Tcl_GetIndexFromObj (interp, objv[1], jsonStructTypes, "jsonType", 1, &jsonType) != TCL_OK) { return TCL_ERROR; } pattern = initSchemaCP (SCHEMA_CTYPE_JSON_STRUCT, NULL, NULL); pattern->typedata = (void *) (intptr_t) jsonType; REMEMBER_PATTERN (pattern); addToContent (sdata, pattern, SCHEMA_CQUANT_ONE, 0, 0); return TCL_OK; } static int keyspacePatternObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; SchemaCP *pattern; domLength nrKeyspaces, i; int hnew; Tcl_Obj *ksObj; SchemaKeySpace *ks; Tcl_HashEntry *h; CHECK_SI CHECK_TOPLEVEL checkNrArgs (3, 3, "Expected: pattern"); if (sdata->cp->type != SCHEMA_CTYPE_NAME && sdata->cp->type != SCHEMA_CTYPE_PATTERN) { SetResult ("The keyspace schema definition command is only " "allowed in sequential context (defelement, " "element or defpattern)"); return TCL_ERROR; } if (Tcl_ListObjLength (interp, objv[1], &nrKeyspaces) != TCL_OK) { SetResult ("The argument must be a valid tcl " "list"); return TCL_ERROR; } for (i = 0; i < nrKeyspaces; i++) { Tcl_ListObjIndex (interp, objv[1], i, &ksObj); h = Tcl_CreateHashEntry (&sdata->keySpaces, Tcl_GetString (ksObj), &hnew); if (hnew) { ks = TMALLOC (SchemaKeySpace); ks->name = Tcl_GetHashKey (&sdata->keySpaces, h); ks->active = 0; ks->unknownIDrefs = 0; Tcl_SetHashValue (h, ks); } else { ks = Tcl_GetHashValue (h); } pattern = initSchemaCP (SCHEMA_CTYPE_KEYSPACE, Tcl_GetString (ksObj), NULL); pattern->keySpace = ks; REMEMBER_PATTERN (pattern); addToContent (sdata, pattern, SCHEMA_CQUANT_ONE, 0, 0); } sdata->currentEvals++; if (Tcl_EvalObjEx (interp, objv[2], TCL_EVAL_DIRECT) != TCL_OK) { return TCL_ERROR; } sdata->currentEvals--; for (i = 0; i < nrKeyspaces; i++) { Tcl_ListObjIndex (interp, objv[1], i, &ksObj); h = Tcl_FindHashEntry (&sdata->keySpaces, Tcl_GetString(ksObj)); pattern = initSchemaCP (SCHEMA_CTYPE_KEYSPACE_END, Tcl_GetString (ksObj), NULL); REMEMBER_PATTERN (pattern); pattern->keySpace = Tcl_GetHashValue (h); addToContent (sdata, pattern, SCHEMA_CQUANT_ONE, 0, 0); } return TCL_OK; } static int associatePatternObjCmd ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { SchemaData *sdata = GETASI; CHECK_SI CHECK_TOPLEVEL checkNrArgs (2, 2, "Expected: data"); switch (sdata->cp->type) { case SCHEMA_CTYPE_NAME: case SCHEMA_CTYPE_PATTERN: case SCHEMA_CTYPE_INTERLEAVE: break; default: SetResult ("The associate schema definition command is only " "allowed inside of global or local element, pattern or " "interleval context"); return TCL_ERROR; } if (sdata->cp->associated) { Tcl_DecrRefCount (sdata->cp->associated); } sdata->cp->associated = objv[1]; Tcl_IncrRefCount (sdata->cp->associated); return TCL_OK; } void tDOM_SchemaInit ( Tcl_Interp *interp ) { Tcl_CreateObjCommand (interp, "tdom::schema", tDOM_SchemaObjCmd, NULL, NULL); /* Inline definition commands. */ Tcl_CreateObjCommand (interp, "tdom::schema::defelement", tDOM_schemaInstanceCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::defelementtype", tDOM_schemaInstanceCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::defpattern", tDOM_schemaInstanceCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::deftexttype", tDOM_schemaInstanceCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::start", tDOM_schemaInstanceCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::prefixns", tDOM_schemaInstanceCmd, NULL, NULL); /* The "any" definition command. */ Tcl_CreateObjCommand (interp, "tdom::schema::any", AnyPatternObjCmd, NULL, NULL); /* The named pattern commands "element" and "ref". */ Tcl_CreateObjCommand (interp, "tdom::schema::element", ElementPatternObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::ref", RefPatternObjCmd, NULL, NULL); /* The anonymous pattern commands "choice", "mixed", "interleave" * and "group". */ Tcl_CreateObjCommand (interp, "tdom::schema::choice", AnonPatternObjCmd, (ClientData) 0, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::mixed", AnonPatternObjCmd, (ClientData) 1, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::interleave", AnonPatternObjCmd, (ClientData) 2, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::group", AnonPatternObjCmd, (ClientData) 3, NULL); /* The "attribute", "nsattribute", "namespace" and "text" * definition commands. */ Tcl_CreateObjCommand (interp, "tdom::schema::attribute", AttributePatternObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::nsattribute", AttributePatternObjCmd, (ClientData) 1, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::namespace", NamespacePatternObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::text", TextPatternObjCmd, NULL, NULL); /* The 'virtual' "tcl" and the "self" definition command */ Tcl_CreateObjCommand (interp, "tdom::schema::tcl", VirtualPatternObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp, "tdom::schema::self", SelfObjCmd, NULL, NULL); /* XPath constraints for DOM validation */ Tcl_CreateObjCommand (interp,"tdom::schema::domunique", domuniquePatternObjCmd, NULL, NULL); Tcl_CreateObjCommand (interp,"tdom::schema::domxpathboolean", domxpathbooleanPatternObjCmd, NULL, NULL); /* JSON structure types for DOM validation */ Tcl_CreateObjCommand (interp,"tdom::schema::jsontype", jsontypePatternObjCmd, NULL, NULL); /* Local key constraints */ Tcl_CreateObjCommand (interp, "tdom::schema::keyspace", keyspacePatternObjCmd, NULL, NULL); /* The associate command */ Tcl_CreateObjCommand (interp,"tdom::schema::associate", associatePatternObjCmd, NULL, NULL); tDOM_DatatypesInit (interp); } #else /* #ifndef TDOM_NO_SCHEMA */ SchemaData * tdomGetSchemadata (Tcl_Interp *interp) { return 0; } #endif /* #ifndef TDOM_NO_SCHEMA */ tdom-0.9.5-src/generic/domhtml.c0000644000175000017500000063542114703531020015175 0ustar rolfrolf/*---------------------------------------------------------------------------- | Copyright (c) 2000 Jochen Loewer (loewerj@hotmail.com) |----------------------------------------------------------------------------- | | | !! EXPERIMENTAL / pre alpha !! | A simple (hopefully fast) HTML parser to build up a DOM structure | in memory. | Based on xmlsimple.c. | !! EXPERIMENTAL / pre alpha !! | | | The contents of this file are subject to the Mozilla Public License | Version 2.0 (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) 1998, 1999 | Jochen Loewer. All Rights Reserved. | | Contributor(s): | | | written by Jochen Loewer | October 2000 | | ------------------------------------------------------------------------ | | Partly based on a parser for XML (for TMML by R.Hipp 1998). | This source code is released into the public domain by the author. | on 2002, December 17. | \---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- | Includes | \---------------------------------------------------------------------------*/ #include #include #include #include /*---------------------------------------------------------------------------- | Defines | \---------------------------------------------------------------------------*/ #define DBG(x) #define RetError(m,p) *errStr = tdomstrdup(m); *pos = p; return TCL_ERROR; #define IsLetter(c) ( ((c)>='A' && (c)<='Z') || ((c)>='a' && (c)<='z') || ((c) >= '0' && (c) <= '9') ) #define TU(c) toupper((unsigned char)c) /*---------------------------------------------------------------------------- | Begin Character Entity Translator | | | The next section of code implements routines used to translate | character entity references into their corresponding strings. | | Examples: | | & "&" | < "<" | > ">" |   " " | \---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- | Each entity reference is recorded as an instance of the following | structure \---------------------------------------------------------------------------*/ typedef struct Er Er; struct Er { const char *zName; /* The name of this entity reference. ex: "amp" */ const char *zValue; /* The value for this entity. ex: "&" */ Er *pNext; /* Next entity with the same hash on zName */ }; /*---------------------------------------------------------------------------- | The size of the hash table. For best results this should | be a prime number which is about the same size as the number of | character entity references known to the system. | \---------------------------------------------------------------------------*/ #define ER_HASH_SIZE 2129 /*---------------------------------------------------------------------------- | The following flag is TRUE if entity reference hash table needs | to be initialized. | \---------------------------------------------------------------------------*/ static int bErNeedsInit = 1; TDomThreaded(static Tcl_Mutex initMutex;) /*---------------------------------------------------------------------------- | The hash table | | If the name of an entity reference hashes to the value H, then | apErHash[H] will point to a linked list of Er structures, one of | which will be the Er structure for that entity reference | \---------------------------------------------------------------------------*/ static Er *apErHash[ER_HASH_SIZE]; /*---------------------------------------------------------------------------- | ErHash -- | | Hash an entity reference name. The value returned is an | integer between 0 and Er_HASH_SIZE-1, inclusive. | \---------------------------------------------------------------------------*/ static int ErHash( const char *zName ) { int h = 0; /* The hash value to be returned */ char c; /* The next character in the name being hashed */ while( (c=*zName)!=0 ){ h = h<<5 ^ h ^ c; zName++; } if( h<0 ) h = -h; return h % ER_HASH_SIZE; } /* ErHash */ /*---------------------------------------------------------------------------- | The following is a table of all entity references. To create | new character entities, add entries to this table. | | Note: For the decoder to work, the name of the entity reference | (including the leading & and closing ;) must not be shorter than | the value. | \---------------------------------------------------------------------------*/ /* This is a temporary hack to work around a bug of the gcc build chain * on RiscV. * see https://tdom.org/index.html/tktview?name=faa62e0934 */ #ifdef __riscv #pragma GCC push_options #pragma GCC optimize ("O0") #endif static Er er_sequences[] = { { "AElig", "\xC3\x86", 0 }, { "AMP", "\x26", 0 }, { "Aacute", "\xC3\x81", 0 }, { "Abreve", "\xC4\x82", 0 }, { "Acirc", "\xC3\x82", 0 }, { "Acy", "\xD0\x90", 0 }, { "Afr", "\xF0\x9D\x94\x84", 0 }, { "Agrave", "\xC3\x80", 0 }, { "Alpha", "\xCE\x91", 0 }, { "Amacr", "\xC4\x80", 0 }, { "And", "\xE2\xA9\x93", 0 }, { "Aogon", "\xC4\x84", 0 }, { "Aopf", "\xF0\x9D\x94\xB8", 0 }, { "ApplyFunction", "\xE2\x81\xA1", 0 }, { "Aring", "\xC3\x85", 0 }, { "Ascr", "\xF0\x9D\x92\x9C", 0 }, { "Assign", "\xE2\x89\x94", 0 }, { "Atilde", "\xC3\x83", 0 }, { "Auml", "\xC3\x84", 0 }, { "Backslash", "\xE2\x88\x96", 0 }, { "Barv", "\xE2\xAB\xA7", 0 }, { "Barwed", "\xE2\x8C\x86", 0 }, { "Bcy", "\xD0\x91", 0 }, { "Because", "\xE2\x88\xB5", 0 }, { "Bernoullis", "\xE2\x84\xAC", 0 }, { "Beta", "\xCE\x92", 0 }, { "Bfr", "\xF0\x9D\x94\x85", 0 }, { "Bopf", "\xF0\x9D\x94\xB9", 0 }, { "Breve", "\xCB\x98", 0 }, { "Bscr", "\xE2\x84\xAC", 0 }, { "Bumpeq", "\xE2\x89\x8E", 0 }, { "CHcy", "\xD0\xA7", 0 }, { "COPY", "\xC2\xA9", 0 }, { "Cacute", "\xC4\x86", 0 }, { "Cap", "\xE2\x8B\x92", 0 }, { "CapitalDifferentialD", "\xE2\x85\x85", 0 }, { "Cayleys", "\xE2\x84\xAD", 0 }, { "Ccaron", "\xC4\x8C", 0 }, { "Ccedil", "\xC3\x87", 0 }, { "Ccirc", "\xC4\x88", 0 }, { "Cconint", "\xE2\x88\xB0", 0 }, { "Cdot", "\xC4\x8A", 0 }, { "Cedilla", "\xC2\xB8", 0 }, { "CenterDot", "\xC2\xB7", 0 }, { "Cfr", "\xE2\x84\xAD", 0 }, { "Chi", "\xCE\xA7", 0 }, { "CircleDot", "\xE2\x8A\x99", 0 }, { "CircleMinus", "\xE2\x8A\x96", 0 }, { "CirclePlus", "\xE2\x8A\x95", 0 }, { "CircleTimes", "\xE2\x8A\x97", 0 }, { "ClockwiseContourIntegral", "\xE2\x88\xB2", 0 }, { "CloseCurlyDoubleQuote", "\xE2\x80\x9D", 0 }, { "CloseCurlyQuote", "\xE2\x80\x99", 0 }, { "Colon", "\xE2\x88\xB7", 0 }, { "Colone", "\xE2\xA9\xB4", 0 }, { "Congruent", "\xE2\x89\xA1", 0 }, { "Conint", "\xE2\x88\xAF", 0 }, { "ContourIntegral", "\xE2\x88\xAE", 0 }, { "Copf", "\xE2\x84\x82", 0 }, { "Coproduct", "\xE2\x88\x90", 0 }, { "CounterClockwiseContourIntegral", "\xE2\x88\xB3", 0 }, { "Cross", "\xE2\xA8\xAF", 0 }, { "Cscr", "\xF0\x9D\x92\x9E", 0 }, { "Cup", "\xE2\x8B\x93", 0 }, { "CupCap", "\xE2\x89\x8D", 0 }, { "DD", "\xE2\x85\x85", 0 }, { "DDotrahd", "\xE2\xA4\x91", 0 }, { "DJcy", "\xD0\x82", 0 }, { "DScy", "\xD0\x85", 0 }, { "DZcy", "\xD0\x8F", 0 }, { "Dagger", "\xE2\x80\xA1", 0 }, { "Darr", "\xE2\x86\xA1", 0 }, { "Dashv", "\xE2\xAB\xA4", 0 }, { "Dcaron", "\xC4\x8E", 0 }, { "Dcy", "\xD0\x94", 0 }, { "Del", "\xE2\x88\x87", 0 }, { "Delta", "\xCE\x94", 0 }, { "Dfr", "\xF0\x9D\x94\x87", 0 }, { "DiacriticalAcute", "\xC2\xB4", 0 }, { "DiacriticalDot", "\xCB\x99", 0 }, { "DiacriticalDoubleAcute", "\xCB\x9D", 0 }, { "DiacriticalGrave", "\x60", 0 }, { "DiacriticalTilde", "\xCB\x9C", 0 }, { "Diamond", "\xE2\x8B\x84", 0 }, { "DifferentialD", "\xE2\x85\x86", 0 }, { "Dopf", "\xF0\x9D\x94\xBB", 0 }, { "Dot", "\xC2\xA8", 0 }, { "DotDot", "\xE2\x83\x9C", 0 }, { "DotEqual", "\xE2\x89\x90", 0 }, { "DoubleContourIntegral", "\xE2\x88\xAF", 0 }, { "DoubleDot", "\xC2\xA8", 0 }, { "DoubleDownArrow", "\xE2\x87\x93", 0 }, { "DoubleLeftArrow", "\xE2\x87\x90", 0 }, { "DoubleLeftRightArrow", "\xE2\x87\x94", 0 }, { "DoubleLeftTee", "\xE2\xAB\xA4", 0 }, { "DoubleLongLeftArrow", "\xE2\x9F\xB8", 0 }, { "DoubleLongLeftRightArrow", "\xE2\x9F\xBA", 0 }, { "DoubleLongRightArrow", "\xE2\x9F\xB9", 0 }, { "DoubleRightArrow", "\xE2\x87\x92", 0 }, { "DoubleRightTee", "\xE2\x8A\xA8", 0 }, { "DoubleUpArrow", "\xE2\x87\x91", 0 }, { "DoubleUpDownArrow", "\xE2\x87\x95", 0 }, { "DoubleVerticalBar", "\xE2\x88\xA5", 0 }, { "DownArrow", "\xE2\x86\x93", 0 }, { "DownArrowBar", "\xE2\xA4\x93", 0 }, { "DownArrowUpArrow", "\xE2\x87\xB5", 0 }, { "DownBreve", "\xCC\x91", 0 }, { "DownLeftRightVector", "\xE2\xA5\x90", 0 }, { "DownLeftTeeVector", "\xE2\xA5\x9E", 0 }, { "DownLeftVector", "\xE2\x86\xBD", 0 }, { "DownLeftVectorBar", "\xE2\xA5\x96", 0 }, { "DownRightTeeVector", "\xE2\xA5\x9F", 0 }, { "DownRightVector", "\xE2\x87\x81", 0 }, { "DownRightVectorBar", "\xE2\xA5\x97", 0 }, { "DownTee", "\xE2\x8A\xA4", 0 }, { "DownTeeArrow", "\xE2\x86\xA7", 0 }, { "Downarrow", "\xE2\x87\x93", 0 }, { "Dscr", "\xF0\x9D\x92\x9F", 0 }, { "Dstrok", "\xC4\x90", 0 }, { "ENG", "\xC5\x8A", 0 }, { "ETH", "\xC3\x90", 0 }, { "Eacute", "\xC3\x89", 0 }, { "Ecaron", "\xC4\x9A", 0 }, { "Ecirc", "\xC3\x8A", 0 }, { "Ecy", "\xD0\xAD", 0 }, { "Edot", "\xC4\x96", 0 }, { "Efr", "\xF0\x9D\x94\x88", 0 }, { "Egrave", "\xC3\x88", 0 }, { "Element", "\xE2\x88\x88", 0 }, { "Emacr", "\xC4\x92", 0 }, { "EmptySmallSquare", "\xE2\x97\xBB", 0 }, { "EmptyVerySmallSquare", "\xE2\x96\xAB", 0 }, { "Eogon", "\xC4\x98", 0 }, { "Eopf", "\xF0\x9D\x94\xBC", 0 }, { "Epsilon", "\xCE\x95", 0 }, { "Equal", "\xE2\xA9\xB5", 0 }, { "EqualTilde", "\xE2\x89\x82", 0 }, { "Equilibrium", "\xE2\x87\x8C", 0 }, { "Escr", "\xE2\x84\xB0", 0 }, { "Esim", "\xE2\xA9\xB3", 0 }, { "Eta", "\xCE\x97", 0 }, { "Euml", "\xC3\x8B", 0 }, { "Exists", "\xE2\x88\x83", 0 }, { "ExponentialE", "\xE2\x85\x87", 0 }, { "Fcy", "\xD0\xA4", 0 }, { "Ffr", "\xF0\x9D\x94\x89", 0 }, { "FilledSmallSquare", "\xE2\x97\xBC", 0 }, { "FilledVerySmallSquare", "\xE2\x96\xAA", 0 }, { "Fopf", "\xF0\x9D\x94\xBD", 0 }, { "ForAll", "\xE2\x88\x80", 0 }, { "Fouriertrf", "\xE2\x84\xB1", 0 }, { "Fscr", "\xE2\x84\xB1", 0 }, { "GJcy", "\xD0\x83", 0 }, { "GT", "\x3E", 0 }, { "Gamma", "\xCE\x93", 0 }, { "Gammad", "\xCF\x9C", 0 }, { "Gbreve", "\xC4\x9E", 0 }, { "Gcedil", "\xC4\xA2", 0 }, { "Gcirc", "\xC4\x9C", 0 }, { "Gcy", "\xD0\x93", 0 }, { "Gdot", "\xC4\xA0", 0 }, { "Gfr", "\xF0\x9D\x94\x8A", 0 }, { "Gg", "\xE2\x8B\x99", 0 }, { "Gopf", "\xF0\x9D\x94\xBE", 0 }, { "GreaterEqual", "\xE2\x89\xA5", 0 }, { "GreaterEqualLess", "\xE2\x8B\x9B", 0 }, { "GreaterFullEqual", "\xE2\x89\xA7", 0 }, { "GreaterGreater", "\xE2\xAA\xA2", 0 }, { "GreaterLess", "\xE2\x89\xB7", 0 }, { "GreaterSlantEqual", "\xE2\xA9\xBE", 0 }, { "GreaterTilde", "\xE2\x89\xB3", 0 }, { "Gscr", "\xF0\x9D\x92\xA2", 0 }, { "Gt", "\xE2\x89\xAB", 0 }, { "HARDcy", "\xD0\xAA", 0 }, { "Hacek", "\xCB\x87", 0 }, { "Hat", "\x5E", 0 }, { "Hcirc", "\xC4\xA4", 0 }, { "Hfr", "\xE2\x84\x8C", 0 }, { "HilbertSpace", "\xE2\x84\x8B", 0 }, { "Hopf", "\xE2\x84\x8D", 0 }, { "HorizontalLine", "\xE2\x94\x80", 0 }, { "Hscr", "\xE2\x84\x8B", 0 }, { "Hstrok", "\xC4\xA6", 0 }, { "HumpDownHump", "\xE2\x89\x8E", 0 }, { "HumpEqual", "\xE2\x89\x8F", 0 }, { "IEcy", "\xD0\x95", 0 }, { "IJlig", "\xC4\xB2", 0 }, { "IOcy", "\xD0\x81", 0 }, { "Iacute", "\xC3\x8D", 0 }, { "Icirc", "\xC3\x8E", 0 }, { "Icy", "\xD0\x98", 0 }, { "Idot", "\xC4\xB0", 0 }, { "Ifr", "\xE2\x84\x91", 0 }, { "Igrave", "\xC3\x8C", 0 }, { "Im", "\xE2\x84\x91", 0 }, { "Imacr", "\xC4\xAA", 0 }, { "ImaginaryI", "\xE2\x85\x88", 0 }, { "Implies", "\xE2\x87\x92", 0 }, { "Int", "\xE2\x88\xAC", 0 }, { "Integral", "\xE2\x88\xAB", 0 }, { "Intersection", "\xE2\x8B\x82", 0 }, { "InvisibleComma", "\xE2\x81\xA3", 0 }, { "InvisibleTimes", "\xE2\x81\xA2", 0 }, { "Iogon", "\xC4\xAE", 0 }, { "Iopf", "\xF0\x9D\x95\x80", 0 }, { "Iota", "\xCE\x99", 0 }, { "Iscr", "\xE2\x84\x90", 0 }, { "Itilde", "\xC4\xA8", 0 }, { "Iukcy", "\xD0\x86", 0 }, { "Iuml", "\xC3\x8F", 0 }, { "Jcirc", "\xC4\xB4", 0 }, { "Jcy", "\xD0\x99", 0 }, { "Jfr", "\xF0\x9D\x94\x8D", 0 }, { "Jopf", "\xF0\x9D\x95\x81", 0 }, { "Jscr", "\xF0\x9D\x92\xA5", 0 }, { "Jsercy", "\xD0\x88", 0 }, { "Jukcy", "\xD0\x84", 0 }, { "KHcy", "\xD0\xA5", 0 }, { "KJcy", "\xD0\x8C", 0 }, { "Kappa", "\xCE\x9A", 0 }, { "Kcedil", "\xC4\xB6", 0 }, { "Kcy", "\xD0\x9A", 0 }, { "Kfr", "\xF0\x9D\x94\x8E", 0 }, { "Kopf", "\xF0\x9D\x95\x82", 0 }, { "Kscr", "\xF0\x9D\x92\xA6", 0 }, { "LJcy", "\xD0\x89", 0 }, { "LT", "\x3C", 0 }, { "Lacute", "\xC4\xB9", 0 }, { "Lambda", "\xCE\x9B", 0 }, { "Lang", "\xE2\x9F\xAA", 0 }, { "Laplacetrf", "\xE2\x84\x92", 0 }, { "Larr", "\xE2\x86\x9E", 0 }, { "Lcaron", "\xC4\xBD", 0 }, { "Lcedil", "\xC4\xBB", 0 }, { "Lcy", "\xD0\x9B", 0 }, { "LeftAngleBracket", "\xE2\x9F\xA8", 0 }, { "LeftArrow", "\xE2\x86\x90", 0 }, { "LeftArrowBar", "\xE2\x87\xA4", 0 }, { "LeftArrowRightArrow", "\xE2\x87\x86", 0 }, { "LeftCeiling", "\xE2\x8C\x88", 0 }, { "LeftDoubleBracket", "\xE2\x9F\xA6", 0 }, { "LeftDownTeeVector", "\xE2\xA5\xA1", 0 }, { "LeftDownVector", "\xE2\x87\x83", 0 }, { "LeftDownVectorBar", "\xE2\xA5\x99", 0 }, { "LeftFloor", "\xE2\x8C\x8A", 0 }, { "LeftRightArrow", "\xE2\x86\x94", 0 }, { "LeftRightVector", "\xE2\xA5\x8E", 0 }, { "LeftTee", "\xE2\x8A\xA3", 0 }, { "LeftTeeArrow", "\xE2\x86\xA4", 0 }, { "LeftTeeVector", "\xE2\xA5\x9A", 0 }, { "LeftTriangle", "\xE2\x8A\xB2", 0 }, { "LeftTriangleBar", "\xE2\xA7\x8F", 0 }, { "LeftTriangleEqual", "\xE2\x8A\xB4", 0 }, { "LeftUpDownVector", "\xE2\xA5\x91", 0 }, { "LeftUpTeeVector", "\xE2\xA5\xA0", 0 }, { "LeftUpVector", "\xE2\x86\xBF", 0 }, { "LeftUpVectorBar", "\xE2\xA5\x98", 0 }, { "LeftVector", "\xE2\x86\xBC", 0 }, { "LeftVectorBar", "\xE2\xA5\x92", 0 }, { "Leftarrow", "\xE2\x87\x90", 0 }, { "Leftrightarrow", "\xE2\x87\x94", 0 }, { "LessEqualGreater", "\xE2\x8B\x9A", 0 }, { "LessFullEqual", "\xE2\x89\xA6", 0 }, { "LessGreater", "\xE2\x89\xB6", 0 }, { "LessLess", "\xE2\xAA\xA1", 0 }, { "LessSlantEqual", "\xE2\xA9\xBD", 0 }, { "LessTilde", "\xE2\x89\xB2", 0 }, { "Lfr", "\xF0\x9D\x94\x8F", 0 }, { "Ll", "\xE2\x8B\x98", 0 }, { "Lleftarrow", "\xE2\x87\x9A", 0 }, { "Lmidot", "\xC4\xBF", 0 }, { "LongLeftArrow", "\xE2\x9F\xB5", 0 }, { "LongLeftRightArrow", "\xE2\x9F\xB7", 0 }, { "LongRightArrow", "\xE2\x9F\xB6", 0 }, { "Longleftarrow", "\xE2\x9F\xB8", 0 }, { "Longleftrightarrow", "\xE2\x9F\xBA", 0 }, { "Longrightarrow", "\xE2\x9F\xB9", 0 }, { "Lopf", "\xF0\x9D\x95\x83", 0 }, { "LowerLeftArrow", "\xE2\x86\x99", 0 }, { "LowerRightArrow", "\xE2\x86\x98", 0 }, { "Lscr", "\xE2\x84\x92", 0 }, { "Lsh", "\xE2\x86\xB0", 0 }, { "Lstrok", "\xC5\x81", 0 }, { "Lt", "\xE2\x89\xAA", 0 }, { "Map", "\xE2\xA4\x85", 0 }, { "Mcy", "\xD0\x9C", 0 }, { "MediumSpace", "\xE2\x81\x9F", 0 }, { "Mellintrf", "\xE2\x84\xB3", 0 }, { "Mfr", "\xF0\x9D\x94\x90", 0 }, { "MinusPlus", "\xE2\x88\x93", 0 }, { "Mopf", "\xF0\x9D\x95\x84", 0 }, { "Mscr", "\xE2\x84\xB3", 0 }, { "Mu", "\xCE\x9C", 0 }, { "NJcy", "\xD0\x8A", 0 }, { "Nacute", "\xC5\x83", 0 }, { "Ncaron", "\xC5\x87", 0 }, { "Ncedil", "\xC5\x85", 0 }, { "Ncy", "\xD0\x9D", 0 }, { "NegativeMediumSpace", "\xE2\x80\x8B", 0 }, { "NegativeThickSpace", "\xE2\x80\x8B", 0 }, { "NegativeThinSpace", "\xE2\x80\x8B", 0 }, { "NegativeVeryThinSpace", "\xE2\x80\x8B", 0 }, { "NestedGreaterGreater", "\xE2\x89\xAB", 0 }, { "NestedLessLess", "\xE2\x89\xAA", 0 }, { "NewLine", "\x0A", 0 }, { "Nfr", "\xF0\x9D\x94\x91", 0 }, { "NoBreak", "\xE2\x81\xA0", 0 }, { "NonBreakingSpace", "\xC2\xA0", 0 }, { "Nopf", "\xE2\x84\x95", 0 }, { "Not", "\xE2\xAB\xAC", 0 }, { "NotCongruent", "\xE2\x89\xA2", 0 }, { "NotCupCap", "\xE2\x89\xAD", 0 }, { "NotDoubleVerticalBar", "\xE2\x88\xA6", 0 }, { "NotElement", "\xE2\x88\x89", 0 }, { "NotEqual", "\xE2\x89\xA0", 0 }, { "NotEqualTilde", "\xE2\x89\x82\xCC\xB8", 0 }, { "NotExists", "\xE2\x88\x84", 0 }, { "NotGreater", "\xE2\x89\xAF", 0 }, { "NotGreaterEqual", "\xE2\x89\xB1", 0 }, { "NotGreaterFullEqual", "\xE2\x89\xA7\xCC\xB8", 0 }, { "NotGreaterGreater", "\xE2\x89\xAB\xCC\xB8", 0 }, { "NotGreaterLess", "\xE2\x89\xB9", 0 }, { "NotGreaterSlantEqual", "\xE2\xA9\xBE\xCC\xB8", 0 }, { "NotGreaterTilde", "\xE2\x89\xB5", 0 }, { "NotHumpDownHump", "\xE2\x89\x8E\xCC\xB8", 0 }, { "NotHumpEqual", "\xE2\x89\x8F\xCC\xB8", 0 }, { "NotLeftTriangle", "\xE2\x8B\xAA", 0 }, { "NotLeftTriangleBar", "\xE2\xA7\x8F\xCC\xB8", 0 }, { "NotLeftTriangleEqual", "\xE2\x8B\xAC", 0 }, { "NotLess", "\xE2\x89\xAE", 0 }, { "NotLessEqual", "\xE2\x89\xB0", 0 }, { "NotLessGreater", "\xE2\x89\xB8", 0 }, { "NotLessLess", "\xE2\x89\xAA\xCC\xB8", 0 }, { "NotLessSlantEqual", "\xE2\xA9\xBD\xCC\xB8", 0 }, { "NotLessTilde", "\xE2\x89\xB4", 0 }, { "NotNestedGreaterGreater", "\xE2\xAA\xA2\xCC\xB8", 0 }, { "NotNestedLessLess", "\xE2\xAA\xA1\xCC\xB8", 0 }, { "NotPrecedes", "\xE2\x8A\x80", 0 }, { "NotPrecedesEqual", "\xE2\xAA\xAF\xCC\xB8", 0 }, { "NotPrecedesSlantEqual", "\xE2\x8B\xA0", 0 }, { "NotReverseElement", "\xE2\x88\x8C", 0 }, { "NotRightTriangle", "\xE2\x8B\xAB", 0 }, { "NotRightTriangleBar", "\xE2\xA7\x90\xCC\xB8", 0 }, { "NotRightTriangleEqual", "\xE2\x8B\xAD", 0 }, { "NotSquareSubset", "\xE2\x8A\x8F\xCC\xB8", 0 }, { "NotSquareSubsetEqual", "\xE2\x8B\xA2", 0 }, { "NotSquareSuperset", "\xE2\x8A\x90\xCC\xB8", 0 }, { "NotSquareSupersetEqual", "\xE2\x8B\xA3", 0 }, { "NotSubset", "\xE2\x8A\x82\xE2\x83\x92", 0 }, { "NotSubsetEqual", "\xE2\x8A\x88", 0 }, { "NotSucceeds", "\xE2\x8A\x81", 0 }, { "NotSucceedsEqual", "\xE2\xAA\xB0\xCC\xB8", 0 }, { "NotSucceedsSlantEqual", "\xE2\x8B\xA1", 0 }, { "NotSucceedsTilde", "\xE2\x89\xBF\xCC\xB8", 0 }, { "NotSuperset", "\xE2\x8A\x83\xE2\x83\x92", 0 }, { "NotSupersetEqual", "\xE2\x8A\x89", 0 }, { "NotTilde", "\xE2\x89\x81", 0 }, { "NotTildeEqual", "\xE2\x89\x84", 0 }, { "NotTildeFullEqual", "\xE2\x89\x87", 0 }, { "NotTildeTilde", "\xE2\x89\x89", 0 }, { "NotVerticalBar", "\xE2\x88\xA4", 0 }, { "Nscr", "\xF0\x9D\x92\xA9", 0 }, { "Ntilde", "\xC3\x91", 0 }, { "Nu", "\xCE\x9D", 0 }, { "OElig", "\xC5\x92", 0 }, { "Oacute", "\xC3\x93", 0 }, { "Ocirc", "\xC3\x94", 0 }, { "Ocy", "\xD0\x9E", 0 }, { "Odblac", "\xC5\x90", 0 }, { "Ofr", "\xF0\x9D\x94\x92", 0 }, { "Ograve", "\xC3\x92", 0 }, { "Omacr", "\xC5\x8C", 0 }, { "Omega", "\xCE\xA9", 0 }, { "Omicron", "\xCE\x9F", 0 }, { "Oopf", "\xF0\x9D\x95\x86", 0 }, { "OpenCurlyDoubleQuote", "\xE2\x80\x9C", 0 }, { "OpenCurlyQuote", "\xE2\x80\x98", 0 }, { "Or", "\xE2\xA9\x94", 0 }, { "Oscr", "\xF0\x9D\x92\xAA", 0 }, { "Oslash", "\xC3\x98", 0 }, { "Otilde", "\xC3\x95", 0 }, { "Otimes", "\xE2\xA8\xB7", 0 }, { "Ouml", "\xC3\x96", 0 }, { "OverBar", "\xE2\x80\xBE", 0 }, { "OverBrace", "\xE2\x8F\x9E", 0 }, { "OverBracket", "\xE2\x8E\xB4", 0 }, { "OverParenthesis", "\xE2\x8F\x9C", 0 }, { "PartialD", "\xE2\x88\x82", 0 }, { "Pcy", "\xD0\x9F", 0 }, { "Pfr", "\xF0\x9D\x94\x93", 0 }, { "Phi", "\xCE\xA6", 0 }, { "Pi", "\xCE\xA0", 0 }, { "PlusMinus", "\xC2\xB1", 0 }, { "Poincareplane", "\xE2\x84\x8C", 0 }, { "Popf", "\xE2\x84\x99", 0 }, { "Pr", "\xE2\xAA\xBB", 0 }, { "Precedes", "\xE2\x89\xBA", 0 }, { "PrecedesEqual", "\xE2\xAA\xAF", 0 }, { "PrecedesSlantEqual", "\xE2\x89\xBC", 0 }, { "PrecedesTilde", "\xE2\x89\xBE", 0 }, { "Prime", "\xE2\x80\xB3", 0 }, { "Product", "\xE2\x88\x8F", 0 }, { "Proportion", "\xE2\x88\xB7", 0 }, { "Proportional", "\xE2\x88\x9D", 0 }, { "Pscr", "\xF0\x9D\x92\xAB", 0 }, { "Psi", "\xCE\xA8", 0 }, { "QUOT", "\x22", 0 }, { "Qfr", "\xF0\x9D\x94\x94", 0 }, { "Qopf", "\xE2\x84\x9A", 0 }, { "Qscr", "\xF0\x9D\x92\xAC", 0 }, { "RBarr", "\xE2\xA4\x90", 0 }, { "REG", "\xC2\xAE", 0 }, { "Racute", "\xC5\x94", 0 }, { "Rang", "\xE2\x9F\xAB", 0 }, { "Rarr", "\xE2\x86\xA0", 0 }, { "Rarrtl", "\xE2\xA4\x96", 0 }, { "Rcaron", "\xC5\x98", 0 }, { "Rcedil", "\xC5\x96", 0 }, { "Rcy", "\xD0\xA0", 0 }, { "Re", "\xE2\x84\x9C", 0 }, { "ReverseElement", "\xE2\x88\x8B", 0 }, { "ReverseEquilibrium", "\xE2\x87\x8B", 0 }, { "ReverseUpEquilibrium", "\xE2\xA5\xAF", 0 }, { "Rfr", "\xE2\x84\x9C", 0 }, { "Rho", "\xCE\xA1", 0 }, { "RightAngleBracket", "\xE2\x9F\xA9", 0 }, { "RightArrow", "\xE2\x86\x92", 0 }, { "RightArrowBar", "\xE2\x87\xA5", 0 }, { "RightArrowLeftArrow", "\xE2\x87\x84", 0 }, { "RightCeiling", "\xE2\x8C\x89", 0 }, { "RightDoubleBracket", "\xE2\x9F\xA7", 0 }, { "RightDownTeeVector", "\xE2\xA5\x9D", 0 }, { "RightDownVector", "\xE2\x87\x82", 0 }, { "RightDownVectorBar", "\xE2\xA5\x95", 0 }, { "RightFloor", "\xE2\x8C\x8B", 0 }, { "RightTee", "\xE2\x8A\xA2", 0 }, { "RightTeeArrow", "\xE2\x86\xA6", 0 }, { "RightTeeVector", "\xE2\xA5\x9B", 0 }, { "RightTriangle", "\xE2\x8A\xB3", 0 }, { "RightTriangleBar", "\xE2\xA7\x90", 0 }, { "RightTriangleEqual", "\xE2\x8A\xB5", 0 }, { "RightUpDownVector", "\xE2\xA5\x8F", 0 }, { "RightUpTeeVector", "\xE2\xA5\x9C", 0 }, { "RightUpVector", "\xE2\x86\xBE", 0 }, { "RightUpVectorBar", "\xE2\xA5\x94", 0 }, { "RightVector", "\xE2\x87\x80", 0 }, { "RightVectorBar", "\xE2\xA5\x93", 0 }, { "Rightarrow", "\xE2\x87\x92", 0 }, { "Ropf", "\xE2\x84\x9D", 0 }, { "RoundImplies", "\xE2\xA5\xB0", 0 }, { "Rrightarrow", "\xE2\x87\x9B", 0 }, { "Rscr", "\xE2\x84\x9B", 0 }, { "Rsh", "\xE2\x86\xB1", 0 }, { "RuleDelayed", "\xE2\xA7\xB4", 0 }, { "SHCHcy", "\xD0\xA9", 0 }, { "SHcy", "\xD0\xA8", 0 }, { "SOFTcy", "\xD0\xAC", 0 }, { "Sacute", "\xC5\x9A", 0 }, { "Sc", "\xE2\xAA\xBC", 0 }, { "Scaron", "\xC5\xA0", 0 }, { "Scedil", "\xC5\x9E", 0 }, { "Scirc", "\xC5\x9C", 0 }, { "Scy", "\xD0\xA1", 0 }, { "Sfr", "\xF0\x9D\x94\x96", 0 }, { "ShortDownArrow", "\xE2\x86\x93", 0 }, { "ShortLeftArrow", "\xE2\x86\x90", 0 }, { "ShortRightArrow", "\xE2\x86\x92", 0 }, { "ShortUpArrow", "\xE2\x86\x91", 0 }, { "Sigma", "\xCE\xA3", 0 }, { "SmallCircle", "\xE2\x88\x98", 0 }, { "Sopf", "\xF0\x9D\x95\x8A", 0 }, { "Sqrt", "\xE2\x88\x9A", 0 }, { "Square", "\xE2\x96\xA1", 0 }, { "SquareIntersection", "\xE2\x8A\x93", 0 }, { "SquareSubset", "\xE2\x8A\x8F", 0 }, { "SquareSubsetEqual", "\xE2\x8A\x91", 0 }, { "SquareSuperset", "\xE2\x8A\x90", 0 }, { "SquareSupersetEqual", "\xE2\x8A\x92", 0 }, { "SquareUnion", "\xE2\x8A\x94", 0 }, { "Sscr", "\xF0\x9D\x92\xAE", 0 }, { "Star", "\xE2\x8B\x86", 0 }, { "Sub", "\xE2\x8B\x90", 0 }, { "Subset", "\xE2\x8B\x90", 0 }, { "SubsetEqual", "\xE2\x8A\x86", 0 }, { "Succeeds", "\xE2\x89\xBB", 0 }, { "SucceedsEqual", "\xE2\xAA\xB0", 0 }, { "SucceedsSlantEqual", "\xE2\x89\xBD", 0 }, { "SucceedsTilde", "\xE2\x89\xBF", 0 }, { "SuchThat", "\xE2\x88\x8B", 0 }, { "Sum", "\xE2\x88\x91", 0 }, { "Sup", "\xE2\x8B\x91", 0 }, { "Superset", "\xE2\x8A\x83", 0 }, { "SupersetEqual", "\xE2\x8A\x87", 0 }, { "Supset", "\xE2\x8B\x91", 0 }, { "THORN", "\xC3\x9E", 0 }, { "TRADE", "\xE2\x84\xA2", 0 }, { "TSHcy", "\xD0\x8B", 0 }, { "TScy", "\xD0\xA6", 0 }, { "Tab", "\x09", 0 }, { "Tau", "\xCE\xA4", 0 }, { "Tcaron", "\xC5\xA4", 0 }, { "Tcedil", "\xC5\xA2", 0 }, { "Tcy", "\xD0\xA2", 0 }, { "Tfr", "\xF0\x9D\x94\x97", 0 }, { "Therefore", "\xE2\x88\xB4", 0 }, { "Theta", "\xCE\x98", 0 }, { "ThickSpace", "\xE2\x81\x9F\xE2\x80\x8A", 0 }, { "ThinSpace", "\xE2\x80\x89", 0 }, { "Tilde", "\xE2\x88\xBC", 0 }, { "TildeEqual", "\xE2\x89\x83", 0 }, { "TildeFullEqual", "\xE2\x89\x85", 0 }, { "TildeTilde", "\xE2\x89\x88", 0 }, { "Topf", "\xF0\x9D\x95\x8B", 0 }, { "TripleDot", "\xE2\x83\x9B", 0 }, { "Tscr", "\xF0\x9D\x92\xAF", 0 }, { "Tstrok", "\xC5\xA6", 0 }, { "Uacute", "\xC3\x9A", 0 }, { "Uarr", "\xE2\x86\x9F", 0 }, { "Uarrocir", "\xE2\xA5\x89", 0 }, { "Ubrcy", "\xD0\x8E", 0 }, { "Ubreve", "\xC5\xAC", 0 }, { "Ucirc", "\xC3\x9B", 0 }, { "Ucy", "\xD0\xA3", 0 }, { "Udblac", "\xC5\xB0", 0 }, { "Ufr", "\xF0\x9D\x94\x98", 0 }, { "Ugrave", "\xC3\x99", 0 }, { "Umacr", "\xC5\xAA", 0 }, { "UnderBar", "\x5F", 0 }, { "UnderBrace", "\xE2\x8F\x9F", 0 }, { "UnderBracket", "\xE2\x8E\xB5", 0 }, { "UnderParenthesis", "\xE2\x8F\x9D", 0 }, { "Union", "\xE2\x8B\x83", 0 }, { "UnionPlus", "\xE2\x8A\x8E", 0 }, { "Uogon", "\xC5\xB2", 0 }, { "Uopf", "\xF0\x9D\x95\x8C", 0 }, { "UpArrow", "\xE2\x86\x91", 0 }, { "UpArrowBar", "\xE2\xA4\x92", 0 }, { "UpArrowDownArrow", "\xE2\x87\x85", 0 }, { "UpDownArrow", "\xE2\x86\x95", 0 }, { "UpEquilibrium", "\xE2\xA5\xAE", 0 }, { "UpTee", "\xE2\x8A\xA5", 0 }, { "UpTeeArrow", "\xE2\x86\xA5", 0 }, { "Uparrow", "\xE2\x87\x91", 0 }, { "Updownarrow", "\xE2\x87\x95", 0 }, { "UpperLeftArrow", "\xE2\x86\x96", 0 }, { "UpperRightArrow", "\xE2\x86\x97", 0 }, { "Upsi", "\xCF\x92", 0 }, { "Upsilon", "\xCE\xA5", 0 }, { "Uring", "\xC5\xAE", 0 }, { "Uscr", "\xF0\x9D\x92\xB0", 0 }, { "Utilde", "\xC5\xA8", 0 }, { "Uuml", "\xC3\x9C", 0 }, { "VDash", "\xE2\x8A\xAB", 0 }, { "Vbar", "\xE2\xAB\xAB", 0 }, { "Vcy", "\xD0\x92", 0 }, { "Vdash", "\xE2\x8A\xA9", 0 }, { "Vdashl", "\xE2\xAB\xA6", 0 }, { "Vee", "\xE2\x8B\x81", 0 }, { "Verbar", "\xE2\x80\x96", 0 }, { "Vert", "\xE2\x80\x96", 0 }, { "VerticalBar", "\xE2\x88\xA3", 0 }, { "VerticalLine", "\x7C", 0 }, { "VerticalSeparator", "\xE2\x9D\x98", 0 }, { "VerticalTilde", "\xE2\x89\x80", 0 }, { "VeryThinSpace", "\xE2\x80\x8A", 0 }, { "Vfr", "\xF0\x9D\x94\x99", 0 }, { "Vopf", "\xF0\x9D\x95\x8D", 0 }, { "Vscr", "\xF0\x9D\x92\xB1", 0 }, { "Vvdash", "\xE2\x8A\xAA", 0 }, { "Wcirc", "\xC5\xB4", 0 }, { "Wedge", "\xE2\x8B\x80", 0 }, { "Wfr", "\xF0\x9D\x94\x9A", 0 }, { "Wopf", "\xF0\x9D\x95\x8E", 0 }, { "Wscr", "\xF0\x9D\x92\xB2", 0 }, { "Xfr", "\xF0\x9D\x94\x9B", 0 }, { "Xi", "\xCE\x9E", 0 }, { "Xopf", "\xF0\x9D\x95\x8F", 0 }, { "Xscr", "\xF0\x9D\x92\xB3", 0 }, { "YAcy", "\xD0\xAF", 0 }, { "YIcy", "\xD0\x87", 0 }, { "YUcy", "\xD0\xAE", 0 }, { "Yacute", "\xC3\x9D", 0 }, { "Ycirc", "\xC5\xB6", 0 }, { "Ycy", "\xD0\xAB", 0 }, { "Yfr", "\xF0\x9D\x94\x9C", 0 }, { "Yopf", "\xF0\x9D\x95\x90", 0 }, { "Yscr", "\xF0\x9D\x92\xB4", 0 }, { "Yuml", "\xC5\xB8", 0 }, { "ZHcy", "\xD0\x96", 0 }, { "Zacute", "\xC5\xB9", 0 }, { "Zcaron", "\xC5\xBD", 0 }, { "Zcy", "\xD0\x97", 0 }, { "Zdot", "\xC5\xBB", 0 }, { "ZeroWidthSpace", "\xE2\x80\x8B", 0 }, { "Zeta", "\xCE\x96", 0 }, { "Zfr", "\xE2\x84\xA8", 0 }, { "Zopf", "\xE2\x84\xA4", 0 }, { "Zscr", "\xF0\x9D\x92\xB5", 0 }, { "aacute", "\xC3\xA1", 0 }, { "abreve", "\xC4\x83", 0 }, { "ac", "\xE2\x88\xBE", 0 }, { "acE", "\xE2\x88\xBE\xCC\xB3", 0 }, { "acd", "\xE2\x88\xBF", 0 }, { "acirc", "\xC3\xA2", 0 }, { "acute", "\xC2\xB4", 0 }, { "acy", "\xD0\xB0", 0 }, { "aelig", "\xC3\xA6", 0 }, { "af", "\xE2\x81\xA1", 0 }, { "afr", "\xF0\x9D\x94\x9E", 0 }, { "agrave", "\xC3\xA0", 0 }, { "alefsym", "\xE2\x84\xB5", 0 }, { "aleph", "\xE2\x84\xB5", 0 }, { "alpha", "\xCE\xB1", 0 }, { "amacr", "\xC4\x81", 0 }, { "amalg", "\xE2\xA8\xBF", 0 }, { "amp", "\x26", 0 }, { "and", "\xE2\x88\xA7", 0 }, { "andand", "\xE2\xA9\x95", 0 }, { "andd", "\xE2\xA9\x9C", 0 }, { "andslope", "\xE2\xA9\x98", 0 }, { "andv", "\xE2\xA9\x9A", 0 }, { "ang", "\xE2\x88\xA0", 0 }, { "ange", "\xE2\xA6\xA4", 0 }, { "angle", "\xE2\x88\xA0", 0 }, { "angmsd", "\xE2\x88\xA1", 0 }, { "angmsdaa", "\xE2\xA6\xA8", 0 }, { "angmsdab", "\xE2\xA6\xA9", 0 }, { "angmsdac", "\xE2\xA6\xAA", 0 }, { "angmsdad", "\xE2\xA6\xAB", 0 }, { "angmsdae", "\xE2\xA6\xAC", 0 }, { "angmsdaf", "\xE2\xA6\xAD", 0 }, { "angmsdag", "\xE2\xA6\xAE", 0 }, { "angmsdah", "\xE2\xA6\xAF", 0 }, { "angrt", "\xE2\x88\x9F", 0 }, { "angrtvb", "\xE2\x8A\xBE", 0 }, { "angrtvbd", "\xE2\xA6\x9D", 0 }, { "angsph", "\xE2\x88\xA2", 0 }, { "angst", "\xC3\x85", 0 }, { "angzarr", "\xE2\x8D\xBC", 0 }, { "aogon", "\xC4\x85", 0 }, { "aopf", "\xF0\x9D\x95\x92", 0 }, { "ap", "\xE2\x89\x88", 0 }, { "apE", "\xE2\xA9\xB0", 0 }, { "apacir", "\xE2\xA9\xAF", 0 }, { "ape", "\xE2\x89\x8A", 0 }, { "apid", "\xE2\x89\x8B", 0 }, { "apos", "\x27", 0 }, { "approx", "\xE2\x89\x88", 0 }, { "approxeq", "\xE2\x89\x8A", 0 }, { "aring", "\xC3\xA5", 0 }, { "ascr", "\xF0\x9D\x92\xB6", 0 }, { "ast", "\x2A", 0 }, { "asymp", "\xE2\x89\x88", 0 }, { "asympeq", "\xE2\x89\x8D", 0 }, { "atilde", "\xC3\xA3", 0 }, { "auml", "\xC3\xA4", 0 }, { "awconint", "\xE2\x88\xB3", 0 }, { "awint", "\xE2\xA8\x91", 0 }, { "bNot", "\xE2\xAB\xAD", 0 }, { "backcong", "\xE2\x89\x8C", 0 }, { "backepsilon", "\xCF\xB6", 0 }, { "backprime", "\xE2\x80\xB5", 0 }, { "backsim", "\xE2\x88\xBD", 0 }, { "backsimeq", "\xE2\x8B\x8D", 0 }, { "barvee", "\xE2\x8A\xBD", 0 }, { "barwed", "\xE2\x8C\x85", 0 }, { "barwedge", "\xE2\x8C\x85", 0 }, { "bbrk", "\xE2\x8E\xB5", 0 }, { "bbrktbrk", "\xE2\x8E\xB6", 0 }, { "bcong", "\xE2\x89\x8C", 0 }, { "bcy", "\xD0\xB1", 0 }, { "bdquo", "\xE2\x80\x9E", 0 }, { "becaus", "\xE2\x88\xB5", 0 }, { "because", "\xE2\x88\xB5", 0 }, { "bemptyv", "\xE2\xA6\xB0", 0 }, { "bepsi", "\xCF\xB6", 0 }, { "bernou", "\xE2\x84\xAC", 0 }, { "beta", "\xCE\xB2", 0 }, { "beth", "\xE2\x84\xB6", 0 }, { "between", "\xE2\x89\xAC", 0 }, { "bfr", "\xF0\x9D\x94\x9F", 0 }, { "bigcap", "\xE2\x8B\x82", 0 }, { "bigcirc", "\xE2\x97\xAF", 0 }, { "bigcup", "\xE2\x8B\x83", 0 }, { "bigodot", "\xE2\xA8\x80", 0 }, { "bigoplus", "\xE2\xA8\x81", 0 }, { "bigotimes", "\xE2\xA8\x82", 0 }, { "bigsqcup", "\xE2\xA8\x86", 0 }, { "bigstar", "\xE2\x98\x85", 0 }, { "bigtriangledown", "\xE2\x96\xBD", 0 }, { "bigtriangleup", "\xE2\x96\xB3", 0 }, { "biguplus", "\xE2\xA8\x84", 0 }, { "bigvee", "\xE2\x8B\x81", 0 }, { "bigwedge", "\xE2\x8B\x80", 0 }, { "bkarow", "\xE2\xA4\x8D", 0 }, { "blacklozenge", "\xE2\xA7\xAB", 0 }, { "blacksquare", "\xE2\x96\xAA", 0 }, { "blacktriangle", "\xE2\x96\xB4", 0 }, { "blacktriangledown", "\xE2\x96\xBE", 0 }, { "blacktriangleleft", "\xE2\x97\x82", 0 }, { "blacktriangleright", "\xE2\x96\xB8", 0 }, { "blank", "\xE2\x90\xA3", 0 }, { "blk12", "\xE2\x96\x92", 0 }, { "blk14", "\xE2\x96\x91", 0 }, { "blk34", "\xE2\x96\x93", 0 }, { "block", "\xE2\x96\x88", 0 }, { "bne", "\x3D\xE2\x83\xA5", 0 }, { "bnequiv", "\xE2\x89\xA1\xE2\x83\xA5", 0 }, { "bnot", "\xE2\x8C\x90", 0 }, { "bopf", "\xF0\x9D\x95\x93", 0 }, { "bot", "\xE2\x8A\xA5", 0 }, { "bottom", "\xE2\x8A\xA5", 0 }, { "bowtie", "\xE2\x8B\x88", 0 }, { "boxDL", "\xE2\x95\x97", 0 }, { "boxDR", "\xE2\x95\x94", 0 }, { "boxDl", "\xE2\x95\x96", 0 }, { "boxDr", "\xE2\x95\x93", 0 }, { "boxH", "\xE2\x95\x90", 0 }, { "boxHD", "\xE2\x95\xA6", 0 }, { "boxHU", "\xE2\x95\xA9", 0 }, { "boxHd", "\xE2\x95\xA4", 0 }, { "boxHu", "\xE2\x95\xA7", 0 }, { "boxUL", "\xE2\x95\x9D", 0 }, { "boxUR", "\xE2\x95\x9A", 0 }, { "boxUl", "\xE2\x95\x9C", 0 }, { "boxUr", "\xE2\x95\x99", 0 }, { "boxV", "\xE2\x95\x91", 0 }, { "boxVH", "\xE2\x95\xAC", 0 }, { "boxVL", "\xE2\x95\xA3", 0 }, { "boxVR", "\xE2\x95\xA0", 0 }, { "boxVh", "\xE2\x95\xAB", 0 }, { "boxVl", "\xE2\x95\xA2", 0 }, { "boxVr", "\xE2\x95\x9F", 0 }, { "boxbox", "\xE2\xA7\x89", 0 }, { "boxdL", "\xE2\x95\x95", 0 }, { "boxdR", "\xE2\x95\x92", 0 }, { "boxdl", "\xE2\x94\x90", 0 }, { "boxdr", "\xE2\x94\x8C", 0 }, { "boxh", "\xE2\x94\x80", 0 }, { "boxhD", "\xE2\x95\xA5", 0 }, { "boxhU", "\xE2\x95\xA8", 0 }, { "boxhd", "\xE2\x94\xAC", 0 }, { "boxhu", "\xE2\x94\xB4", 0 }, { "boxminus", "\xE2\x8A\x9F", 0 }, { "boxplus", "\xE2\x8A\x9E", 0 }, { "boxtimes", "\xE2\x8A\xA0", 0 }, { "boxuL", "\xE2\x95\x9B", 0 }, { "boxuR", "\xE2\x95\x98", 0 }, { "boxul", "\xE2\x94\x98", 0 }, { "boxur", "\xE2\x94\x94", 0 }, { "boxv", "\xE2\x94\x82", 0 }, { "boxvH", "\xE2\x95\xAA", 0 }, { "boxvL", "\xE2\x95\xA1", 0 }, { "boxvR", "\xE2\x95\x9E", 0 }, { "boxvh", "\xE2\x94\xBC", 0 }, { "boxvl", "\xE2\x94\xA4", 0 }, { "boxvr", "\xE2\x94\x9C", 0 }, { "bprime", "\xE2\x80\xB5", 0 }, { "breve", "\xCB\x98", 0 }, { "brvbar", "\xC2\xA6", 0 }, { "bscr", "\xF0\x9D\x92\xB7", 0 }, { "bsemi", "\xE2\x81\x8F", 0 }, { "bsim", "\xE2\x88\xBD", 0 }, { "bsime", "\xE2\x8B\x8D", 0 }, { "bsol", "\x5C", 0 }, { "bsolb", "\xE2\xA7\x85", 0 }, { "bsolhsub", "\xE2\x9F\x88", 0 }, { "bull", "\xE2\x80\xA2", 0 }, { "bullet", "\xE2\x80\xA2", 0 }, { "bump", "\xE2\x89\x8E", 0 }, { "bumpE", "\xE2\xAA\xAE", 0 }, { "bumpe", "\xE2\x89\x8F", 0 }, { "bumpeq", "\xE2\x89\x8F", 0 }, { "cacute", "\xC4\x87", 0 }, { "cap", "\xE2\x88\xA9", 0 }, { "capand", "\xE2\xA9\x84", 0 }, { "capbrcup", "\xE2\xA9\x89", 0 }, { "capcap", "\xE2\xA9\x8B", 0 }, { "capcup", "\xE2\xA9\x87", 0 }, { "capdot", "\xE2\xA9\x80", 0 }, { "caps", "\xE2\x88\xA9\xEF\xB8\x80", 0 }, { "caret", "\xE2\x81\x81", 0 }, { "caron", "\xCB\x87", 0 }, { "ccaps", "\xE2\xA9\x8D", 0 }, { "ccaron", "\xC4\x8D", 0 }, { "ccedil", "\xC3\xA7", 0 }, { "ccirc", "\xC4\x89", 0 }, { "ccups", "\xE2\xA9\x8C", 0 }, { "ccupssm", "\xE2\xA9\x90", 0 }, { "cdot", "\xC4\x8B", 0 }, { "cedil", "\xC2\xB8", 0 }, { "cemptyv", "\xE2\xA6\xB2", 0 }, { "cent", "\xC2\xA2", 0 }, { "centerdot", "\xC2\xB7", 0 }, { "cfr", "\xF0\x9D\x94\xA0", 0 }, { "chcy", "\xD1\x87", 0 }, { "check", "\xE2\x9C\x93", 0 }, { "checkmark", "\xE2\x9C\x93", 0 }, { "chi", "\xCF\x87", 0 }, { "cir", "\xE2\x97\x8B", 0 }, { "cirE", "\xE2\xA7\x83", 0 }, { "circ", "\xCB\x86", 0 }, { "circeq", "\xE2\x89\x97", 0 }, { "circlearrowleft", "\xE2\x86\xBA", 0 }, { "circlearrowright", "\xE2\x86\xBB", 0 }, { "circledR", "\xC2\xAE", 0 }, { "circledS", "\xE2\x93\x88", 0 }, { "circledast", "\xE2\x8A\x9B", 0 }, { "circledcirc", "\xE2\x8A\x9A", 0 }, { "circleddash", "\xE2\x8A\x9D", 0 }, { "cire", "\xE2\x89\x97", 0 }, { "cirfnint", "\xE2\xA8\x90", 0 }, { "cirmid", "\xE2\xAB\xAF", 0 }, { "cirscir", "\xE2\xA7\x82", 0 }, { "clubs", "\xE2\x99\xA3", 0 }, { "clubsuit", "\xE2\x99\xA3", 0 }, { "colon", "\x3A", 0 }, { "colone", "\xE2\x89\x94", 0 }, { "coloneq", "\xE2\x89\x94", 0 }, { "comma", "\x2C", 0 }, { "commat", "\x40", 0 }, { "comp", "\xE2\x88\x81", 0 }, { "compfn", "\xE2\x88\x98", 0 }, { "complement", "\xE2\x88\x81", 0 }, { "complexes", "\xE2\x84\x82", 0 }, { "cong", "\xE2\x89\x85", 0 }, { "congdot", "\xE2\xA9\xAD", 0 }, { "conint", "\xE2\x88\xAE", 0 }, { "copf", "\xF0\x9D\x95\x94", 0 }, { "coprod", "\xE2\x88\x90", 0 }, { "copy", "\xC2\xA9", 0 }, { "copysr", "\xE2\x84\x97", 0 }, { "crarr", "\xE2\x86\xB5", 0 }, { "cross", "\xE2\x9C\x97", 0 }, { "cscr", "\xF0\x9D\x92\xB8", 0 }, { "csub", "\xE2\xAB\x8F", 0 }, { "csube", "\xE2\xAB\x91", 0 }, { "csup", "\xE2\xAB\x90", 0 }, { "csupe", "\xE2\xAB\x92", 0 }, { "ctdot", "\xE2\x8B\xAF", 0 }, { "cudarrl", "\xE2\xA4\xB8", 0 }, { "cudarrr", "\xE2\xA4\xB5", 0 }, { "cuepr", "\xE2\x8B\x9E", 0 }, { "cuesc", "\xE2\x8B\x9F", 0 }, { "cularr", "\xE2\x86\xB6", 0 }, { "cularrp", "\xE2\xA4\xBD", 0 }, { "cup", "\xE2\x88\xAA", 0 }, { "cupbrcap", "\xE2\xA9\x88", 0 }, { "cupcap", "\xE2\xA9\x86", 0 }, { "cupcup", "\xE2\xA9\x8A", 0 }, { "cupdot", "\xE2\x8A\x8D", 0 }, { "cupor", "\xE2\xA9\x85", 0 }, { "cups", "\xE2\x88\xAA\xEF\xB8\x80", 0 }, { "curarr", "\xE2\x86\xB7", 0 }, { "curarrm", "\xE2\xA4\xBC", 0 }, { "curlyeqprec", "\xE2\x8B\x9E", 0 }, { "curlyeqsucc", "\xE2\x8B\x9F", 0 }, { "curlyvee", "\xE2\x8B\x8E", 0 }, { "curlywedge", "\xE2\x8B\x8F", 0 }, { "curren", "\xC2\xA4", 0 }, { "curvearrowleft", "\xE2\x86\xB6", 0 }, { "curvearrowright", "\xE2\x86\xB7", 0 }, { "cuvee", "\xE2\x8B\x8E", 0 }, { "cuwed", "\xE2\x8B\x8F", 0 }, { "cwconint", "\xE2\x88\xB2", 0 }, { "cwint", "\xE2\x88\xB1", 0 }, { "cylcty", "\xE2\x8C\xAD", 0 }, { "dArr", "\xE2\x87\x93", 0 }, { "dHar", "\xE2\xA5\xA5", 0 }, { "dagger", "\xE2\x80\xA0", 0 }, { "daleth", "\xE2\x84\xB8", 0 }, { "darr", "\xE2\x86\x93", 0 }, { "dash", "\xE2\x80\x90", 0 }, { "dashv", "\xE2\x8A\xA3", 0 }, { "dbkarow", "\xE2\xA4\x8F", 0 }, { "dblac", "\xCB\x9D", 0 }, { "dcaron", "\xC4\x8F", 0 }, { "dcy", "\xD0\xB4", 0 }, { "dd", "\xE2\x85\x86", 0 }, { "ddagger", "\xE2\x80\xA1", 0 }, { "ddarr", "\xE2\x87\x8A", 0 }, { "ddotseq", "\xE2\xA9\xB7", 0 }, { "deg", "\xC2\xB0", 0 }, { "delta", "\xCE\xB4", 0 }, { "demptyv", "\xE2\xA6\xB1", 0 }, { "dfisht", "\xE2\xA5\xBF", 0 }, { "dfr", "\xF0\x9D\x94\xA1", 0 }, { "dharl", "\xE2\x87\x83", 0 }, { "dharr", "\xE2\x87\x82", 0 }, { "diam", "\xE2\x8B\x84", 0 }, { "diamond", "\xE2\x8B\x84", 0 }, { "diamondsuit", "\xE2\x99\xA6", 0 }, { "diams", "\xE2\x99\xA6", 0 }, { "die", "\xC2\xA8", 0 }, { "digamma", "\xCF\x9D", 0 }, { "disin", "\xE2\x8B\xB2", 0 }, { "div", "\xC3\xB7", 0 }, { "divide", "\xC3\xB7", 0 }, { "divideontimes", "\xE2\x8B\x87", 0 }, { "divonx", "\xE2\x8B\x87", 0 }, { "djcy", "\xD1\x92", 0 }, { "dlcorn", "\xE2\x8C\x9E", 0 }, { "dlcrop", "\xE2\x8C\x8D", 0 }, { "dollar", "\x24", 0 }, { "dopf", "\xF0\x9D\x95\x95", 0 }, { "dot", "\xCB\x99", 0 }, { "doteq", "\xE2\x89\x90", 0 }, { "doteqdot", "\xE2\x89\x91", 0 }, { "dotminus", "\xE2\x88\xB8", 0 }, { "dotplus", "\xE2\x88\x94", 0 }, { "dotsquare", "\xE2\x8A\xA1", 0 }, { "doublebarwedge", "\xE2\x8C\x86", 0 }, { "downarrow", "\xE2\x86\x93", 0 }, { "downdownarrows", "\xE2\x87\x8A", 0 }, { "downharpoonleft", "\xE2\x87\x83", 0 }, { "downharpoonright", "\xE2\x87\x82", 0 }, { "drbkarow", "\xE2\xA4\x90", 0 }, { "drcorn", "\xE2\x8C\x9F", 0 }, { "drcrop", "\xE2\x8C\x8C", 0 }, { "dscr", "\xF0\x9D\x92\xB9", 0 }, { "dscy", "\xD1\x95", 0 }, { "dsol", "\xE2\xA7\xB6", 0 }, { "dstrok", "\xC4\x91", 0 }, { "dtdot", "\xE2\x8B\xB1", 0 }, { "dtri", "\xE2\x96\xBF", 0 }, { "dtrif", "\xE2\x96\xBE", 0 }, { "duarr", "\xE2\x87\xB5", 0 }, { "duhar", "\xE2\xA5\xAF", 0 }, { "dwangle", "\xE2\xA6\xA6", 0 }, { "dzcy", "\xD1\x9F", 0 }, { "dzigrarr", "\xE2\x9F\xBF", 0 }, { "eDDot", "\xE2\xA9\xB7", 0 }, { "eDot", "\xE2\x89\x91", 0 }, { "eacute", "\xC3\xA9", 0 }, { "easter", "\xE2\xA9\xAE", 0 }, { "ecaron", "\xC4\x9B", 0 }, { "ecir", "\xE2\x89\x96", 0 }, { "ecirc", "\xC3\xAA", 0 }, { "ecolon", "\xE2\x89\x95", 0 }, { "ecy", "\xD1\x8D", 0 }, { "edot", "\xC4\x97", 0 }, { "ee", "\xE2\x85\x87", 0 }, { "efDot", "\xE2\x89\x92", 0 }, { "efr", "\xF0\x9D\x94\xA2", 0 }, { "eg", "\xE2\xAA\x9A", 0 }, { "egrave", "\xC3\xA8", 0 }, { "egs", "\xE2\xAA\x96", 0 }, { "egsdot", "\xE2\xAA\x98", 0 }, { "el", "\xE2\xAA\x99", 0 }, { "elinters", "\xE2\x8F\xA7", 0 }, { "ell", "\xE2\x84\x93", 0 }, { "els", "\xE2\xAA\x95", 0 }, { "elsdot", "\xE2\xAA\x97", 0 }, { "emacr", "\xC4\x93", 0 }, { "empty", "\xE2\x88\x85", 0 }, { "emptyset", "\xE2\x88\x85", 0 }, { "emptyv", "\xE2\x88\x85", 0 }, { "emsp", "\xE2\x80\x83", 0 }, { "emsp13", "\xE2\x80\x84", 0 }, { "emsp14", "\xE2\x80\x85", 0 }, { "eng", "\xC5\x8B", 0 }, { "ensp", "\xE2\x80\x82", 0 }, { "eogon", "\xC4\x99", 0 }, { "eopf", "\xF0\x9D\x95\x96", 0 }, { "epar", "\xE2\x8B\x95", 0 }, { "eparsl", "\xE2\xA7\xA3", 0 }, { "eplus", "\xE2\xA9\xB1", 0 }, { "epsi", "\xCE\xB5", 0 }, { "epsilon", "\xCE\xB5", 0 }, { "epsiv", "\xCF\xB5", 0 }, { "eqcirc", "\xE2\x89\x96", 0 }, { "eqcolon", "\xE2\x89\x95", 0 }, { "eqsim", "\xE2\x89\x82", 0 }, { "eqslantgtr", "\xE2\xAA\x96", 0 }, { "eqslantless", "\xE2\xAA\x95", 0 }, { "equals", "\x3D", 0 }, { "equest", "\xE2\x89\x9F", 0 }, { "equiv", "\xE2\x89\xA1", 0 }, { "equivDD", "\xE2\xA9\xB8", 0 }, { "eqvparsl", "\xE2\xA7\xA5", 0 }, { "erDot", "\xE2\x89\x93", 0 }, { "erarr", "\xE2\xA5\xB1", 0 }, { "escr", "\xE2\x84\xAF", 0 }, { "esdot", "\xE2\x89\x90", 0 }, { "esim", "\xE2\x89\x82", 0 }, { "eta", "\xCE\xB7", 0 }, { "eth", "\xC3\xB0", 0 }, { "euml", "\xC3\xAB", 0 }, { "euro", "\xE2\x82\xAC", 0 }, { "excl", "\x21", 0 }, { "exist", "\xE2\x88\x83", 0 }, { "expectation", "\xE2\x84\xB0", 0 }, { "exponentiale", "\xE2\x85\x87", 0 }, { "fallingdotseq", "\xE2\x89\x92", 0 }, { "fcy", "\xD1\x84", 0 }, { "female", "\xE2\x99\x80", 0 }, { "ffilig", "\xEF\xAC\x83", 0 }, { "fflig", "\xEF\xAC\x80", 0 }, { "ffllig", "\xEF\xAC\x84", 0 }, { "ffr", "\xF0\x9D\x94\xA3", 0 }, { "filig", "\xEF\xAC\x81", 0 }, { "fjlig", "\x66\x6A", 0 }, { "flat", "\xE2\x99\xAD", 0 }, { "fllig", "\xEF\xAC\x82", 0 }, { "fltns", "\xE2\x96\xB1", 0 }, { "fnof", "\xC6\x92", 0 }, { "fopf", "\xF0\x9D\x95\x97", 0 }, { "forall", "\xE2\x88\x80", 0 }, { "fork", "\xE2\x8B\x94", 0 }, { "forkv", "\xE2\xAB\x99", 0 }, { "fpartint", "\xE2\xA8\x8D", 0 }, { "frac12", "\xC2\xBD", 0 }, { "frac13", "\xE2\x85\x93", 0 }, { "frac14", "\xC2\xBC", 0 }, { "frac15", "\xE2\x85\x95", 0 }, { "frac16", "\xE2\x85\x99", 0 }, { "frac18", "\xE2\x85\x9B", 0 }, { "frac23", "\xE2\x85\x94", 0 }, { "frac25", "\xE2\x85\x96", 0 }, { "frac34", "\xC2\xBE", 0 }, { "frac35", "\xE2\x85\x97", 0 }, { "frac38", "\xE2\x85\x9C", 0 }, { "frac45", "\xE2\x85\x98", 0 }, { "frac56", "\xE2\x85\x9A", 0 }, { "frac58", "\xE2\x85\x9D", 0 }, { "frac78", "\xE2\x85\x9E", 0 }, { "frasl", "\xE2\x81\x84", 0 }, { "frown", "\xE2\x8C\xA2", 0 }, { "fscr", "\xF0\x9D\x92\xBB", 0 }, { "gE", "\xE2\x89\xA7", 0 }, { "gEl", "\xE2\xAA\x8C", 0 }, { "gacute", "\xC7\xB5", 0 }, { "gamma", "\xCE\xB3", 0 }, { "gammad", "\xCF\x9D", 0 }, { "gap", "\xE2\xAA\x86", 0 }, { "gbreve", "\xC4\x9F", 0 }, { "gcirc", "\xC4\x9D", 0 }, { "gcy", "\xD0\xB3", 0 }, { "gdot", "\xC4\xA1", 0 }, { "ge", "\xE2\x89\xA5", 0 }, { "gel", "\xE2\x8B\x9B", 0 }, { "geq", "\xE2\x89\xA5", 0 }, { "geqq", "\xE2\x89\xA7", 0 }, { "geqslant", "\xE2\xA9\xBE", 0 }, { "ges", "\xE2\xA9\xBE", 0 }, { "gescc", "\xE2\xAA\xA9", 0 }, { "gesdot", "\xE2\xAA\x80", 0 }, { "gesdoto", "\xE2\xAA\x82", 0 }, { "gesdotol", "\xE2\xAA\x84", 0 }, { "gesl", "\xE2\x8B\x9B\xEF\xB8\x80", 0 }, { "gesles", "\xE2\xAA\x94", 0 }, { "gfr", "\xF0\x9D\x94\xA4", 0 }, { "gg", "\xE2\x89\xAB", 0 }, { "ggg", "\xE2\x8B\x99", 0 }, { "gimel", "\xE2\x84\xB7", 0 }, { "gjcy", "\xD1\x93", 0 }, { "gl", "\xE2\x89\xB7", 0 }, { "glE", "\xE2\xAA\x92", 0 }, { "gla", "\xE2\xAA\xA5", 0 }, { "glj", "\xE2\xAA\xA4", 0 }, { "gnE", "\xE2\x89\xA9", 0 }, { "gnap", "\xE2\xAA\x8A", 0 }, { "gnapprox", "\xE2\xAA\x8A", 0 }, { "gne", "\xE2\xAA\x88", 0 }, { "gneq", "\xE2\xAA\x88", 0 }, { "gneqq", "\xE2\x89\xA9", 0 }, { "gnsim", "\xE2\x8B\xA7", 0 }, { "gopf", "\xF0\x9D\x95\x98", 0 }, { "grave", "\x60", 0 }, { "gscr", "\xE2\x84\x8A", 0 }, { "gsim", "\xE2\x89\xB3", 0 }, { "gsime", "\xE2\xAA\x8E", 0 }, { "gsiml", "\xE2\xAA\x90", 0 }, { "gt", "\x3E", 0 }, { "gtcc", "\xE2\xAA\xA7", 0 }, { "gtcir", "\xE2\xA9\xBA", 0 }, { "gtdot", "\xE2\x8B\x97", 0 }, { "gtlPar", "\xE2\xA6\x95", 0 }, { "gtquest", "\xE2\xA9\xBC", 0 }, { "gtrapprox", "\xE2\xAA\x86", 0 }, { "gtrarr", "\xE2\xA5\xB8", 0 }, { "gtrdot", "\xE2\x8B\x97", 0 }, { "gtreqless", "\xE2\x8B\x9B", 0 }, { "gtreqqless", "\xE2\xAA\x8C", 0 }, { "gtrless", "\xE2\x89\xB7", 0 }, { "gtrsim", "\xE2\x89\xB3", 0 }, { "gvertneqq", "\xE2\x89\xA9\xEF\xB8\x80", 0 }, { "gvnE", "\xE2\x89\xA9\xEF\xB8\x80", 0 }, { "hArr", "\xE2\x87\x94", 0 }, { "hairsp", "\xE2\x80\x8A", 0 }, { "half", "\xC2\xBD", 0 }, { "hamilt", "\xE2\x84\x8B", 0 }, { "hardcy", "\xD1\x8A", 0 }, { "harr", "\xE2\x86\x94", 0 }, { "harrcir", "\xE2\xA5\x88", 0 }, { "harrw", "\xE2\x86\xAD", 0 }, { "hbar", "\xE2\x84\x8F", 0 }, { "hcirc", "\xC4\xA5", 0 }, { "hearts", "\xE2\x99\xA5", 0 }, { "heartsuit", "\xE2\x99\xA5", 0 }, { "hellip", "\xE2\x80\xA6", 0 }, { "hercon", "\xE2\x8A\xB9", 0 }, { "hfr", "\xF0\x9D\x94\xA5", 0 }, { "hksearow", "\xE2\xA4\xA5", 0 }, { "hkswarow", "\xE2\xA4\xA6", 0 }, { "hoarr", "\xE2\x87\xBF", 0 }, { "homtht", "\xE2\x88\xBB", 0 }, { "hookleftarrow", "\xE2\x86\xA9", 0 }, { "hookrightarrow", "\xE2\x86\xAA", 0 }, { "hopf", "\xF0\x9D\x95\x99", 0 }, { "horbar", "\xE2\x80\x95", 0 }, { "hscr", "\xF0\x9D\x92\xBD", 0 }, { "hslash", "\xE2\x84\x8F", 0 }, { "hstrok", "\xC4\xA7", 0 }, { "hybull", "\xE2\x81\x83", 0 }, { "hyphen", "\xE2\x80\x90", 0 }, { "iacute", "\xC3\xAD", 0 }, { "ic", "\xE2\x81\xA3", 0 }, { "icirc", "\xC3\xAE", 0 }, { "icy", "\xD0\xB8", 0 }, { "iecy", "\xD0\xB5", 0 }, { "iexcl", "\xC2\xA1", 0 }, { "iff", "\xE2\x87\x94", 0 }, { "ifr", "\xF0\x9D\x94\xA6", 0 }, { "igrave", "\xC3\xAC", 0 }, { "ii", "\xE2\x85\x88", 0 }, { "iiiint", "\xE2\xA8\x8C", 0 }, { "iiint", "\xE2\x88\xAD", 0 }, { "iinfin", "\xE2\xA7\x9C", 0 }, { "iiota", "\xE2\x84\xA9", 0 }, { "ijlig", "\xC4\xB3", 0 }, { "imacr", "\xC4\xAB", 0 }, { "image", "\xE2\x84\x91", 0 }, { "imagline", "\xE2\x84\x90", 0 }, { "imagpart", "\xE2\x84\x91", 0 }, { "imath", "\xC4\xB1", 0 }, { "imof", "\xE2\x8A\xB7", 0 }, { "imped", "\xC6\xB5", 0 }, { "in", "\xE2\x88\x88", 0 }, { "incare", "\xE2\x84\x85", 0 }, { "infin", "\xE2\x88\x9E", 0 }, { "infintie", "\xE2\xA7\x9D", 0 }, { "inodot", "\xC4\xB1", 0 }, { "int", "\xE2\x88\xAB", 0 }, { "intcal", "\xE2\x8A\xBA", 0 }, { "integers", "\xE2\x84\xA4", 0 }, { "intercal", "\xE2\x8A\xBA", 0 }, { "intlarhk", "\xE2\xA8\x97", 0 }, { "intprod", "\xE2\xA8\xBC", 0 }, { "iocy", "\xD1\x91", 0 }, { "iogon", "\xC4\xAF", 0 }, { "iopf", "\xF0\x9D\x95\x9A", 0 }, { "iota", "\xCE\xB9", 0 }, { "iprod", "\xE2\xA8\xBC", 0 }, { "iquest", "\xC2\xBF", 0 }, { "iscr", "\xF0\x9D\x92\xBE", 0 }, { "isin", "\xE2\x88\x88", 0 }, { "isinE", "\xE2\x8B\xB9", 0 }, { "isindot", "\xE2\x8B\xB5", 0 }, { "isins", "\xE2\x8B\xB4", 0 }, { "isinsv", "\xE2\x8B\xB3", 0 }, { "isinv", "\xE2\x88\x88", 0 }, { "it", "\xE2\x81\xA2", 0 }, { "itilde", "\xC4\xA9", 0 }, { "iukcy", "\xD1\x96", 0 }, { "iuml", "\xC3\xAF", 0 }, { "jcirc", "\xC4\xB5", 0 }, { "jcy", "\xD0\xB9", 0 }, { "jfr", "\xF0\x9D\x94\xA7", 0 }, { "jmath", "\xC8\xB7", 0 }, { "jopf", "\xF0\x9D\x95\x9B", 0 }, { "jscr", "\xF0\x9D\x92\xBF", 0 }, { "jsercy", "\xD1\x98", 0 }, { "jukcy", "\xD1\x94", 0 }, { "kappa", "\xCE\xBA", 0 }, { "kappav", "\xCF\xB0", 0 }, { "kcedil", "\xC4\xB7", 0 }, { "kcy", "\xD0\xBA", 0 }, { "kfr", "\xF0\x9D\x94\xA8", 0 }, { "kgreen", "\xC4\xB8", 0 }, { "khcy", "\xD1\x85", 0 }, { "kjcy", "\xD1\x9C", 0 }, { "kopf", "\xF0\x9D\x95\x9C", 0 }, { "kscr", "\xF0\x9D\x93\x80", 0 }, { "lAarr", "\xE2\x87\x9A", 0 }, { "lArr", "\xE2\x87\x90", 0 }, { "lAtail", "\xE2\xA4\x9B", 0 }, { "lBarr", "\xE2\xA4\x8E", 0 }, { "lE", "\xE2\x89\xA6", 0 }, { "lEg", "\xE2\xAA\x8B", 0 }, { "lHar", "\xE2\xA5\xA2", 0 }, { "lacute", "\xC4\xBA", 0 }, { "laemptyv", "\xE2\xA6\xB4", 0 }, { "lagran", "\xE2\x84\x92", 0 }, { "lambda", "\xCE\xBB", 0 }, { "lang", "\xE2\x9F\xA8", 0 }, { "langd", "\xE2\xA6\x91", 0 }, { "langle", "\xE2\x9F\xA8", 0 }, { "lap", "\xE2\xAA\x85", 0 }, { "laquo", "\xC2\xAB", 0 }, { "larr", "\xE2\x86\x90", 0 }, { "larrb", "\xE2\x87\xA4", 0 }, { "larrbfs", "\xE2\xA4\x9F", 0 }, { "larrfs", "\xE2\xA4\x9D", 0 }, { "larrhk", "\xE2\x86\xA9", 0 }, { "larrlp", "\xE2\x86\xAB", 0 }, { "larrpl", "\xE2\xA4\xB9", 0 }, { "larrsim", "\xE2\xA5\xB3", 0 }, { "larrtl", "\xE2\x86\xA2", 0 }, { "lat", "\xE2\xAA\xAB", 0 }, { "latail", "\xE2\xA4\x99", 0 }, { "late", "\xE2\xAA\xAD", 0 }, { "lates", "\xE2\xAA\xAD\xEF\xB8\x80", 0 }, { "lbarr", "\xE2\xA4\x8C", 0 }, { "lbbrk", "\xE2\x9D\xB2", 0 }, { "lbrace", "\x7B", 0 }, { "lbrack", "\x5B", 0 }, { "lbrke", "\xE2\xA6\x8B", 0 }, { "lbrksld", "\xE2\xA6\x8F", 0 }, { "lbrkslu", "\xE2\xA6\x8D", 0 }, { "lcaron", "\xC4\xBE", 0 }, { "lcedil", "\xC4\xBC", 0 }, { "lceil", "\xE2\x8C\x88", 0 }, { "lcub", "\x7B", 0 }, { "lcy", "\xD0\xBB", 0 }, { "ldca", "\xE2\xA4\xB6", 0 }, { "ldquo", "\xE2\x80\x9C", 0 }, { "ldquor", "\xE2\x80\x9E", 0 }, { "ldrdhar", "\xE2\xA5\xA7", 0 }, { "ldrushar", "\xE2\xA5\x8B", 0 }, { "ldsh", "\xE2\x86\xB2", 0 }, { "le", "\xE2\x89\xA4", 0 }, { "leftarrow", "\xE2\x86\x90", 0 }, { "leftarrowtail", "\xE2\x86\xA2", 0 }, { "leftharpoondown", "\xE2\x86\xBD", 0 }, { "leftharpoonup", "\xE2\x86\xBC", 0 }, { "leftleftarrows", "\xE2\x87\x87", 0 }, { "leftrightarrow", "\xE2\x86\x94", 0 }, { "leftrightarrows", "\xE2\x87\x86", 0 }, { "leftrightharpoons", "\xE2\x87\x8B", 0 }, { "leftrightsquigarrow", "\xE2\x86\xAD", 0 }, { "leftthreetimes", "\xE2\x8B\x8B", 0 }, { "leg", "\xE2\x8B\x9A", 0 }, { "leq", "\xE2\x89\xA4", 0 }, { "leqq", "\xE2\x89\xA6", 0 }, { "leqslant", "\xE2\xA9\xBD", 0 }, { "les", "\xE2\xA9\xBD", 0 }, { "lescc", "\xE2\xAA\xA8", 0 }, { "lesdot", "\xE2\xA9\xBF", 0 }, { "lesdoto", "\xE2\xAA\x81", 0 }, { "lesdotor", "\xE2\xAA\x83", 0 }, { "lesg", "\xE2\x8B\x9A\xEF\xB8\x80", 0 }, { "lesges", "\xE2\xAA\x93", 0 }, { "lessapprox", "\xE2\xAA\x85", 0 }, { "lessdot", "\xE2\x8B\x96", 0 }, { "lesseqgtr", "\xE2\x8B\x9A", 0 }, { "lesseqqgtr", "\xE2\xAA\x8B", 0 }, { "lessgtr", "\xE2\x89\xB6", 0 }, { "lesssim", "\xE2\x89\xB2", 0 }, { "lfisht", "\xE2\xA5\xBC", 0 }, { "lfloor", "\xE2\x8C\x8A", 0 }, { "lfr", "\xF0\x9D\x94\xA9", 0 }, { "lg", "\xE2\x89\xB6", 0 }, { "lgE", "\xE2\xAA\x91", 0 }, { "lhard", "\xE2\x86\xBD", 0 }, { "lharu", "\xE2\x86\xBC", 0 }, { "lharul", "\xE2\xA5\xAA", 0 }, { "lhblk", "\xE2\x96\x84", 0 }, { "ljcy", "\xD1\x99", 0 }, { "ll", "\xE2\x89\xAA", 0 }, { "llarr", "\xE2\x87\x87", 0 }, { "llcorner", "\xE2\x8C\x9E", 0 }, { "llhard", "\xE2\xA5\xAB", 0 }, { "lltri", "\xE2\x97\xBA", 0 }, { "lmidot", "\xC5\x80", 0 }, { "lmoust", "\xE2\x8E\xB0", 0 }, { "lmoustache", "\xE2\x8E\xB0", 0 }, { "lnE", "\xE2\x89\xA8", 0 }, { "lnap", "\xE2\xAA\x89", 0 }, { "lnapprox", "\xE2\xAA\x89", 0 }, { "lne", "\xE2\xAA\x87", 0 }, { "lneq", "\xE2\xAA\x87", 0 }, { "lneqq", "\xE2\x89\xA8", 0 }, { "lnsim", "\xE2\x8B\xA6", 0 }, { "loang", "\xE2\x9F\xAC", 0 }, { "loarr", "\xE2\x87\xBD", 0 }, { "lobrk", "\xE2\x9F\xA6", 0 }, { "longleftarrow", "\xE2\x9F\xB5", 0 }, { "longleftrightarrow", "\xE2\x9F\xB7", 0 }, { "longmapsto", "\xE2\x9F\xBC", 0 }, { "longrightarrow", "\xE2\x9F\xB6", 0 }, { "looparrowleft", "\xE2\x86\xAB", 0 }, { "looparrowright", "\xE2\x86\xAC", 0 }, { "lopar", "\xE2\xA6\x85", 0 }, { "lopf", "\xF0\x9D\x95\x9D", 0 }, { "loplus", "\xE2\xA8\xAD", 0 }, { "lotimes", "\xE2\xA8\xB4", 0 }, { "lowast", "\xE2\x88\x97", 0 }, { "lowbar", "\x5F", 0 }, { "loz", "\xE2\x97\x8A", 0 }, { "lozenge", "\xE2\x97\x8A", 0 }, { "lozf", "\xE2\xA7\xAB", 0 }, { "lpar", "\x28", 0 }, { "lparlt", "\xE2\xA6\x93", 0 }, { "lrarr", "\xE2\x87\x86", 0 }, { "lrcorner", "\xE2\x8C\x9F", 0 }, { "lrhar", "\xE2\x87\x8B", 0 }, { "lrhard", "\xE2\xA5\xAD", 0 }, { "lrm", "\xE2\x80\x8E", 0 }, { "lrtri", "\xE2\x8A\xBF", 0 }, { "lsaquo", "\xE2\x80\xB9", 0 }, { "lscr", "\xF0\x9D\x93\x81", 0 }, { "lsh", "\xE2\x86\xB0", 0 }, { "lsim", "\xE2\x89\xB2", 0 }, { "lsime", "\xE2\xAA\x8D", 0 }, { "lsimg", "\xE2\xAA\x8F", 0 }, { "lsqb", "\x5B", 0 }, { "lsquo", "\xE2\x80\x98", 0 }, { "lsquor", "\xE2\x80\x9A", 0 }, { "lstrok", "\xC5\x82", 0 }, { "lt", "\x3C", 0 }, { "ltcc", "\xE2\xAA\xA6", 0 }, { "ltcir", "\xE2\xA9\xB9", 0 }, { "ltdot", "\xE2\x8B\x96", 0 }, { "lthree", "\xE2\x8B\x8B", 0 }, { "ltimes", "\xE2\x8B\x89", 0 }, { "ltlarr", "\xE2\xA5\xB6", 0 }, { "ltquest", "\xE2\xA9\xBB", 0 }, { "ltrPar", "\xE2\xA6\x96", 0 }, { "ltri", "\xE2\x97\x83", 0 }, { "ltrie", "\xE2\x8A\xB4", 0 }, { "ltrif", "\xE2\x97\x82", 0 }, { "lurdshar", "\xE2\xA5\x8A", 0 }, { "luruhar", "\xE2\xA5\xA6", 0 }, { "lvertneqq", "\xE2\x89\xA8\xEF\xB8\x80", 0 }, { "lvnE", "\xE2\x89\xA8\xEF\xB8\x80", 0 }, { "mDDot", "\xE2\x88\xBA", 0 }, { "macr", "\xC2\xAF", 0 }, { "male", "\xE2\x99\x82", 0 }, { "malt", "\xE2\x9C\xA0", 0 }, { "maltese", "\xE2\x9C\xA0", 0 }, { "map", "\xE2\x86\xA6", 0 }, { "mapsto", "\xE2\x86\xA6", 0 }, { "mapstodown", "\xE2\x86\xA7", 0 }, { "mapstoleft", "\xE2\x86\xA4", 0 }, { "mapstoup", "\xE2\x86\xA5", 0 }, { "marker", "\xE2\x96\xAE", 0 }, { "mcomma", "\xE2\xA8\xA9", 0 }, { "mcy", "\xD0\xBC", 0 }, { "mdash", "\xE2\x80\x94", 0 }, { "measuredangle", "\xE2\x88\xA1", 0 }, { "mfr", "\xF0\x9D\x94\xAA", 0 }, { "mho", "\xE2\x84\xA7", 0 }, { "micro", "\xC2\xB5", 0 }, { "mid", "\xE2\x88\xA3", 0 }, { "midast", "\x2A", 0 }, { "midcir", "\xE2\xAB\xB0", 0 }, { "middot", "\xC2\xB7", 0 }, { "minus", "\xE2\x88\x92", 0 }, { "minusb", "\xE2\x8A\x9F", 0 }, { "minusd", "\xE2\x88\xB8", 0 }, { "minusdu", "\xE2\xA8\xAA", 0 }, { "mlcp", "\xE2\xAB\x9B", 0 }, { "mldr", "\xE2\x80\xA6", 0 }, { "mnplus", "\xE2\x88\x93", 0 }, { "models", "\xE2\x8A\xA7", 0 }, { "mopf", "\xF0\x9D\x95\x9E", 0 }, { "mp", "\xE2\x88\x93", 0 }, { "mscr", "\xF0\x9D\x93\x82", 0 }, { "mstpos", "\xE2\x88\xBE", 0 }, { "mu", "\xCE\xBC", 0 }, { "multimap", "\xE2\x8A\xB8", 0 }, { "mumap", "\xE2\x8A\xB8", 0 }, { "nGg", "\xE2\x8B\x99\xCC\xB8", 0 }, { "nGtv", "\xE2\x89\xAB\xCC\xB8", 0 }, { "nLeftarrow", "\xE2\x87\x8D", 0 }, { "nLeftrightarrow", "\xE2\x87\x8E", 0 }, { "nLl", "\xE2\x8B\x98\xCC\xB8", 0 }, { "nLtv", "\xE2\x89\xAA\xCC\xB8", 0 }, { "nRightarrow", "\xE2\x87\x8F", 0 }, { "nVDash", "\xE2\x8A\xAF", 0 }, { "nVdash", "\xE2\x8A\xAE", 0 }, { "nabla", "\xE2\x88\x87", 0 }, { "nacute", "\xC5\x84", 0 }, { "nang", "\xE2\x88\xA0\xE2\x83\x92", 0 }, { "nap", "\xE2\x89\x89", 0 }, { "napE", "\xE2\xA9\xB0\xCC\xB8", 0 }, { "napid", "\xE2\x89\x8B\xCC\xB8", 0 }, { "napos", "\xC5\x89", 0 }, { "napprox", "\xE2\x89\x89", 0 }, { "natur", "\xE2\x99\xAE", 0 }, { "natural", "\xE2\x99\xAE", 0 }, { "naturals", "\xE2\x84\x95", 0 }, { "nbsp", "\xC2\xA0", 0 }, { "nbump", "\xE2\x89\x8E\xCC\xB8", 0 }, { "nbumpe", "\xE2\x89\x8F\xCC\xB8", 0 }, { "ncap", "\xE2\xA9\x83", 0 }, { "ncaron", "\xC5\x88", 0 }, { "ncedil", "\xC5\x86", 0 }, { "ncong", "\xE2\x89\x87", 0 }, { "ncongdot", "\xE2\xA9\xAD\xCC\xB8", 0 }, { "ncup", "\xE2\xA9\x82", 0 }, { "ncy", "\xD0\xBD", 0 }, { "ndash", "\xE2\x80\x93", 0 }, { "ne", "\xE2\x89\xA0", 0 }, { "neArr", "\xE2\x87\x97", 0 }, { "nearhk", "\xE2\xA4\xA4", 0 }, { "nearr", "\xE2\x86\x97", 0 }, { "nearrow", "\xE2\x86\x97", 0 }, { "nedot", "\xE2\x89\x90\xCC\xB8", 0 }, { "nequiv", "\xE2\x89\xA2", 0 }, { "nesear", "\xE2\xA4\xA8", 0 }, { "nesim", "\xE2\x89\x82\xCC\xB8", 0 }, { "nexist", "\xE2\x88\x84", 0 }, { "nexists", "\xE2\x88\x84", 0 }, { "nfr", "\xF0\x9D\x94\xAB", 0 }, { "ngE", "\xE2\x89\xA7\xCC\xB8", 0 }, { "nge", "\xE2\x89\xB1", 0 }, { "ngeq", "\xE2\x89\xB1", 0 }, { "ngeqq", "\xE2\x89\xA7\xCC\xB8", 0 }, { "ngeqslant", "\xE2\xA9\xBE\xCC\xB8", 0 }, { "nges", "\xE2\xA9\xBE\xCC\xB8", 0 }, { "ngsim", "\xE2\x89\xB5", 0 }, { "ngt", "\xE2\x89\xAF", 0 }, { "ngtr", "\xE2\x89\xAF", 0 }, { "nhArr", "\xE2\x87\x8E", 0 }, { "nharr", "\xE2\x86\xAE", 0 }, { "nhpar", "\xE2\xAB\xB2", 0 }, { "ni", "\xE2\x88\x8B", 0 }, { "nis", "\xE2\x8B\xBC", 0 }, { "nisd", "\xE2\x8B\xBA", 0 }, { "niv", "\xE2\x88\x8B", 0 }, { "njcy", "\xD1\x9A", 0 }, { "nlArr", "\xE2\x87\x8D", 0 }, { "nlE", "\xE2\x89\xA6\xCC\xB8", 0 }, { "nlarr", "\xE2\x86\x9A", 0 }, { "nldr", "\xE2\x80\xA5", 0 }, { "nle", "\xE2\x89\xB0", 0 }, { "nleftarrow", "\xE2\x86\x9A", 0 }, { "nleftrightarrow", "\xE2\x86\xAE", 0 }, { "nleq", "\xE2\x89\xB0", 0 }, { "nleqq", "\xE2\x89\xA6\xCC\xB8", 0 }, { "nleqslant", "\xE2\xA9\xBD\xCC\xB8", 0 }, { "nles", "\xE2\xA9\xBD\xCC\xB8", 0 }, { "nless", "\xE2\x89\xAE", 0 }, { "nlsim", "\xE2\x89\xB4", 0 }, { "nlt", "\xE2\x89\xAE", 0 }, { "nltri", "\xE2\x8B\xAA", 0 }, { "nltrie", "\xE2\x8B\xAC", 0 }, { "nmid", "\xE2\x88\xA4", 0 }, { "nopf", "\xF0\x9D\x95\x9F", 0 }, { "not", "\xC2\xAC", 0 }, { "notin", "\xE2\x88\x89", 0 }, { "notinE", "\xE2\x8B\xB9\xCC\xB8", 0 }, { "notindot", "\xE2\x8B\xB5\xCC\xB8", 0 }, { "notinva", "\xE2\x88\x89", 0 }, { "notinvb", "\xE2\x8B\xB7", 0 }, { "notinvc", "\xE2\x8B\xB6", 0 }, { "notni", "\xE2\x88\x8C", 0 }, { "notniva", "\xE2\x88\x8C", 0 }, { "notnivb", "\xE2\x8B\xBE", 0 }, { "notnivc", "\xE2\x8B\xBD", 0 }, { "npar", "\xE2\x88\xA6", 0 }, { "nparallel", "\xE2\x88\xA6", 0 }, { "nparsl", "\xE2\xAB\xBD\xE2\x83\xA5", 0 }, { "npart", "\xE2\x88\x82\xCC\xB8", 0 }, { "npolint", "\xE2\xA8\x94", 0 }, { "npr", "\xE2\x8A\x80", 0 }, { "nprcue", "\xE2\x8B\xA0", 0 }, { "npre", "\xE2\xAA\xAF\xCC\xB8", 0 }, { "nprec", "\xE2\x8A\x80", 0 }, { "npreceq", "\xE2\xAA\xAF\xCC\xB8", 0 }, { "nrArr", "\xE2\x87\x8F", 0 }, { "nrarr", "\xE2\x86\x9B", 0 }, { "nrarrc", "\xE2\xA4\xB3\xCC\xB8", 0 }, { "nrarrw", "\xE2\x86\x9D\xCC\xB8", 0 }, { "nrightarrow", "\xE2\x86\x9B", 0 }, { "nrtri", "\xE2\x8B\xAB", 0 }, { "nrtrie", "\xE2\x8B\xAD", 0 }, { "nsc", "\xE2\x8A\x81", 0 }, { "nsccue", "\xE2\x8B\xA1", 0 }, { "nsce", "\xE2\xAA\xB0\xCC\xB8", 0 }, { "nscr", "\xF0\x9D\x93\x83", 0 }, { "nshortmid", "\xE2\x88\xA4", 0 }, { "nshortparallel", "\xE2\x88\xA6", 0 }, { "nsim", "\xE2\x89\x81", 0 }, { "nsime", "\xE2\x89\x84", 0 }, { "nsimeq", "\xE2\x89\x84", 0 }, { "nsmid", "\xE2\x88\xA4", 0 }, { "nspar", "\xE2\x88\xA6", 0 }, { "nsqsube", "\xE2\x8B\xA2", 0 }, { "nsqsupe", "\xE2\x8B\xA3", 0 }, { "nsub", "\xE2\x8A\x84", 0 }, { "nsubE", "\xE2\xAB\x85\xCC\xB8", 0 }, { "nsube", "\xE2\x8A\x88", 0 }, { "nsubset", "\xE2\x8A\x82\xE2\x83\x92", 0 }, { "nsubseteq", "\xE2\x8A\x88", 0 }, { "nsubseteqq", "\xE2\xAB\x85\xCC\xB8", 0 }, { "nsucc", "\xE2\x8A\x81", 0 }, { "nsucceq", "\xE2\xAA\xB0\xCC\xB8", 0 }, { "nsup", "\xE2\x8A\x85", 0 }, { "nsupE", "\xE2\xAB\x86\xCC\xB8", 0 }, { "nsupe", "\xE2\x8A\x89", 0 }, { "nsupset", "\xE2\x8A\x83\xE2\x83\x92", 0 }, { "nsupseteq", "\xE2\x8A\x89", 0 }, { "nsupseteqq", "\xE2\xAB\x86\xCC\xB8", 0 }, { "ntgl", "\xE2\x89\xB9", 0 }, { "ntilde", "\xC3\xB1", 0 }, { "ntlg", "\xE2\x89\xB8", 0 }, { "ntriangleleft", "\xE2\x8B\xAA", 0 }, { "ntrianglelefteq", "\xE2\x8B\xAC", 0 }, { "ntriangleright", "\xE2\x8B\xAB", 0 }, { "ntrianglerighteq", "\xE2\x8B\xAD", 0 }, { "nu", "\xCE\xBD", 0 }, { "num", "\x23", 0 }, { "numero", "\xE2\x84\x96", 0 }, { "numsp", "\xE2\x80\x87", 0 }, { "nvDash", "\xE2\x8A\xAD", 0 }, { "nvHarr", "\xE2\xA4\x84", 0 }, { "nvap", "\xE2\x89\x8D\xE2\x83\x92", 0 }, { "nvdash", "\xE2\x8A\xAC", 0 }, { "nvge", "\xE2\x89\xA5\xE2\x83\x92", 0 }, { "nvgt", "\x3E\xE2\x83\x92", 0 }, { "nvinfin", "\xE2\xA7\x9E", 0 }, { "nvlArr", "\xE2\xA4\x82", 0 }, { "nvle", "\xE2\x89\xA4\xE2\x83\x92", 0 }, { "nvlt", "\x3C\xE2\x83\x92", 0 }, { "nvltrie", "\xE2\x8A\xB4\xE2\x83\x92", 0 }, { "nvrArr", "\xE2\xA4\x83", 0 }, { "nvrtrie", "\xE2\x8A\xB5\xE2\x83\x92", 0 }, { "nvsim", "\xE2\x88\xBC\xE2\x83\x92", 0 }, { "nwArr", "\xE2\x87\x96", 0 }, { "nwarhk", "\xE2\xA4\xA3", 0 }, { "nwarr", "\xE2\x86\x96", 0 }, { "nwarrow", "\xE2\x86\x96", 0 }, { "nwnear", "\xE2\xA4\xA7", 0 }, { "oS", "\xE2\x93\x88", 0 }, { "oacute", "\xC3\xB3", 0 }, { "oast", "\xE2\x8A\x9B", 0 }, { "ocir", "\xE2\x8A\x9A", 0 }, { "ocirc", "\xC3\xB4", 0 }, { "ocy", "\xD0\xBE", 0 }, { "odash", "\xE2\x8A\x9D", 0 }, { "odblac", "\xC5\x91", 0 }, { "odiv", "\xE2\xA8\xB8", 0 }, { "odot", "\xE2\x8A\x99", 0 }, { "odsold", "\xE2\xA6\xBC", 0 }, { "oelig", "\xC5\x93", 0 }, { "ofcir", "\xE2\xA6\xBF", 0 }, { "ofr", "\xF0\x9D\x94\xAC", 0 }, { "ogon", "\xCB\x9B", 0 }, { "ograve", "\xC3\xB2", 0 }, { "ogt", "\xE2\xA7\x81", 0 }, { "ohbar", "\xE2\xA6\xB5", 0 }, { "ohm", "\xCE\xA9", 0 }, { "oint", "\xE2\x88\xAE", 0 }, { "olarr", "\xE2\x86\xBA", 0 }, { "olcir", "\xE2\xA6\xBE", 0 }, { "olcross", "\xE2\xA6\xBB", 0 }, { "oline", "\xE2\x80\xBE", 0 }, { "olt", "\xE2\xA7\x80", 0 }, { "omacr", "\xC5\x8D", 0 }, { "omega", "\xCF\x89", 0 }, { "omicron", "\xCE\xBF", 0 }, { "omid", "\xE2\xA6\xB6", 0 }, { "ominus", "\xE2\x8A\x96", 0 }, { "oopf", "\xF0\x9D\x95\xA0", 0 }, { "opar", "\xE2\xA6\xB7", 0 }, { "operp", "\xE2\xA6\xB9", 0 }, { "oplus", "\xE2\x8A\x95", 0 }, { "or", "\xE2\x88\xA8", 0 }, { "orarr", "\xE2\x86\xBB", 0 }, { "ord", "\xE2\xA9\x9D", 0 }, { "order", "\xE2\x84\xB4", 0 }, { "orderof", "\xE2\x84\xB4", 0 }, { "ordf", "\xC2\xAA", 0 }, { "ordm", "\xC2\xBA", 0 }, { "origof", "\xE2\x8A\xB6", 0 }, { "oror", "\xE2\xA9\x96", 0 }, { "orslope", "\xE2\xA9\x97", 0 }, { "orv", "\xE2\xA9\x9B", 0 }, { "oscr", "\xE2\x84\xB4", 0 }, { "oslash", "\xC3\xB8", 0 }, { "osol", "\xE2\x8A\x98", 0 }, { "otilde", "\xC3\xB5", 0 }, { "otimes", "\xE2\x8A\x97", 0 }, { "otimesas", "\xE2\xA8\xB6", 0 }, { "ouml", "\xC3\xB6", 0 }, { "ovbar", "\xE2\x8C\xBD", 0 }, { "par", "\xE2\x88\xA5", 0 }, { "para", "\xC2\xB6", 0 }, { "parallel", "\xE2\x88\xA5", 0 }, { "parsim", "\xE2\xAB\xB3", 0 }, { "parsl", "\xE2\xAB\xBD", 0 }, { "part", "\xE2\x88\x82", 0 }, { "pcy", "\xD0\xBF", 0 }, { "percnt", "\x25", 0 }, { "period", "\x2E", 0 }, { "permil", "\xE2\x80\xB0", 0 }, { "perp", "\xE2\x8A\xA5", 0 }, { "pertenk", "\xE2\x80\xB1", 0 }, { "pfr", "\xF0\x9D\x94\xAD", 0 }, { "phi", "\xCF\x86", 0 }, { "phiv", "\xCF\x95", 0 }, { "phmmat", "\xE2\x84\xB3", 0 }, { "phone", "\xE2\x98\x8E", 0 }, { "pi", "\xCF\x80", 0 }, { "pitchfork", "\xE2\x8B\x94", 0 }, { "piv", "\xCF\x96", 0 }, { "planck", "\xE2\x84\x8F", 0 }, { "planckh", "\xE2\x84\x8E", 0 }, { "plankv", "\xE2\x84\x8F", 0 }, { "plus", "\x2B", 0 }, { "plusacir", "\xE2\xA8\xA3", 0 }, { "plusb", "\xE2\x8A\x9E", 0 }, { "pluscir", "\xE2\xA8\xA2", 0 }, { "plusdo", "\xE2\x88\x94", 0 }, { "plusdu", "\xE2\xA8\xA5", 0 }, { "pluse", "\xE2\xA9\xB2", 0 }, { "plusmn", "\xC2\xB1", 0 }, { "plussim", "\xE2\xA8\xA6", 0 }, { "plustwo", "\xE2\xA8\xA7", 0 }, { "pm", "\xC2\xB1", 0 }, { "pointint", "\xE2\xA8\x95", 0 }, { "popf", "\xF0\x9D\x95\xA1", 0 }, { "pound", "\xC2\xA3", 0 }, { "pr", "\xE2\x89\xBA", 0 }, { "prE", "\xE2\xAA\xB3", 0 }, { "prap", "\xE2\xAA\xB7", 0 }, { "prcue", "\xE2\x89\xBC", 0 }, { "pre", "\xE2\xAA\xAF", 0 }, { "prec", "\xE2\x89\xBA", 0 }, { "precapprox", "\xE2\xAA\xB7", 0 }, { "preccurlyeq", "\xE2\x89\xBC", 0 }, { "preceq", "\xE2\xAA\xAF", 0 }, { "precnapprox", "\xE2\xAA\xB9", 0 }, { "precneqq", "\xE2\xAA\xB5", 0 }, { "precnsim", "\xE2\x8B\xA8", 0 }, { "precsim", "\xE2\x89\xBE", 0 }, { "prime", "\xE2\x80\xB2", 0 }, { "primes", "\xE2\x84\x99", 0 }, { "prnE", "\xE2\xAA\xB5", 0 }, { "prnap", "\xE2\xAA\xB9", 0 }, { "prnsim", "\xE2\x8B\xA8", 0 }, { "prod", "\xE2\x88\x8F", 0 }, { "profalar", "\xE2\x8C\xAE", 0 }, { "profline", "\xE2\x8C\x92", 0 }, { "profsurf", "\xE2\x8C\x93", 0 }, { "prop", "\xE2\x88\x9D", 0 }, { "propto", "\xE2\x88\x9D", 0 }, { "prsim", "\xE2\x89\xBE", 0 }, { "prurel", "\xE2\x8A\xB0", 0 }, { "pscr", "\xF0\x9D\x93\x85", 0 }, { "psi", "\xCF\x88", 0 }, { "puncsp", "\xE2\x80\x88", 0 }, { "qfr", "\xF0\x9D\x94\xAE", 0 }, { "qint", "\xE2\xA8\x8C", 0 }, { "qopf", "\xF0\x9D\x95\xA2", 0 }, { "qprime", "\xE2\x81\x97", 0 }, { "qscr", "\xF0\x9D\x93\x86", 0 }, { "quaternions", "\xE2\x84\x8D", 0 }, { "quatint", "\xE2\xA8\x96", 0 }, { "quest", "\x3F", 0 }, { "questeq", "\xE2\x89\x9F", 0 }, { "quot", "\x22", 0 }, { "rAarr", "\xE2\x87\x9B", 0 }, { "rArr", "\xE2\x87\x92", 0 }, { "rAtail", "\xE2\xA4\x9C", 0 }, { "rBarr", "\xE2\xA4\x8F", 0 }, { "rHar", "\xE2\xA5\xA4", 0 }, { "race", "\xE2\x88\xBD\xCC\xB1", 0 }, { "racute", "\xC5\x95", 0 }, { "radic", "\xE2\x88\x9A", 0 }, { "raemptyv", "\xE2\xA6\xB3", 0 }, { "rang", "\xE2\x9F\xA9", 0 }, { "rangd", "\xE2\xA6\x92", 0 }, { "range", "\xE2\xA6\xA5", 0 }, { "rangle", "\xE2\x9F\xA9", 0 }, { "raquo", "\xC2\xBB", 0 }, { "rarr", "\xE2\x86\x92", 0 }, { "rarrap", "\xE2\xA5\xB5", 0 }, { "rarrb", "\xE2\x87\xA5", 0 }, { "rarrbfs", "\xE2\xA4\xA0", 0 }, { "rarrc", "\xE2\xA4\xB3", 0 }, { "rarrfs", "\xE2\xA4\x9E", 0 }, { "rarrhk", "\xE2\x86\xAA", 0 }, { "rarrlp", "\xE2\x86\xAC", 0 }, { "rarrpl", "\xE2\xA5\x85", 0 }, { "rarrsim", "\xE2\xA5\xB4", 0 }, { "rarrtl", "\xE2\x86\xA3", 0 }, { "rarrw", "\xE2\x86\x9D", 0 }, { "ratail", "\xE2\xA4\x9A", 0 }, { "ratio", "\xE2\x88\xB6", 0 }, { "rationals", "\xE2\x84\x9A", 0 }, { "rbarr", "\xE2\xA4\x8D", 0 }, { "rbbrk", "\xE2\x9D\xB3", 0 }, { "rbrace", "\x7D", 0 }, { "rbrack", "\x5D", 0 }, { "rbrke", "\xE2\xA6\x8C", 0 }, { "rbrksld", "\xE2\xA6\x8E", 0 }, { "rbrkslu", "\xE2\xA6\x90", 0 }, { "rcaron", "\xC5\x99", 0 }, { "rcedil", "\xC5\x97", 0 }, { "rceil", "\xE2\x8C\x89", 0 }, { "rcub", "\x7D", 0 }, { "rcy", "\xD1\x80", 0 }, { "rdca", "\xE2\xA4\xB7", 0 }, { "rdldhar", "\xE2\xA5\xA9", 0 }, { "rdquo", "\xE2\x80\x9D", 0 }, { "rdquor", "\xE2\x80\x9D", 0 }, { "rdsh", "\xE2\x86\xB3", 0 }, { "real", "\xE2\x84\x9C", 0 }, { "realine", "\xE2\x84\x9B", 0 }, { "realpart", "\xE2\x84\x9C", 0 }, { "reals", "\xE2\x84\x9D", 0 }, { "rect", "\xE2\x96\xAD", 0 }, { "reg", "\xC2\xAE", 0 }, { "rfisht", "\xE2\xA5\xBD", 0 }, { "rfloor", "\xE2\x8C\x8B", 0 }, { "rfr", "\xF0\x9D\x94\xAF", 0 }, { "rhard", "\xE2\x87\x81", 0 }, { "rharu", "\xE2\x87\x80", 0 }, { "rharul", "\xE2\xA5\xAC", 0 }, { "rho", "\xCF\x81", 0 }, { "rhov", "\xCF\xB1", 0 }, { "rightarrow", "\xE2\x86\x92", 0 }, { "rightarrowtail", "\xE2\x86\xA3", 0 }, { "rightharpoondown", "\xE2\x87\x81", 0 }, { "rightharpoonup", "\xE2\x87\x80", 0 }, { "rightleftarrows", "\xE2\x87\x84", 0 }, { "rightleftharpoons", "\xE2\x87\x8C", 0 }, { "rightrightarrows", "\xE2\x87\x89", 0 }, { "rightsquigarrow", "\xE2\x86\x9D", 0 }, { "rightthreetimes", "\xE2\x8B\x8C", 0 }, { "ring", "\xCB\x9A", 0 }, { "risingdotseq", "\xE2\x89\x93", 0 }, { "rlarr", "\xE2\x87\x84", 0 }, { "rlhar", "\xE2\x87\x8C", 0 }, { "rlm", "\xE2\x80\x8F", 0 }, { "rmoust", "\xE2\x8E\xB1", 0 }, { "rmoustache", "\xE2\x8E\xB1", 0 }, { "rnmid", "\xE2\xAB\xAE", 0 }, { "roang", "\xE2\x9F\xAD", 0 }, { "roarr", "\xE2\x87\xBE", 0 }, { "robrk", "\xE2\x9F\xA7", 0 }, { "ropar", "\xE2\xA6\x86", 0 }, { "ropf", "\xF0\x9D\x95\xA3", 0 }, { "roplus", "\xE2\xA8\xAE", 0 }, { "rotimes", "\xE2\xA8\xB5", 0 }, { "rpar", "\x29", 0 }, { "rpargt", "\xE2\xA6\x94", 0 }, { "rppolint", "\xE2\xA8\x92", 0 }, { "rrarr", "\xE2\x87\x89", 0 }, { "rsaquo", "\xE2\x80\xBA", 0 }, { "rscr", "\xF0\x9D\x93\x87", 0 }, { "rsh", "\xE2\x86\xB1", 0 }, { "rsqb", "\x5D", 0 }, { "rsquo", "\xE2\x80\x99", 0 }, { "rsquor", "\xE2\x80\x99", 0 }, { "rthree", "\xE2\x8B\x8C", 0 }, { "rtimes", "\xE2\x8B\x8A", 0 }, { "rtri", "\xE2\x96\xB9", 0 }, { "rtrie", "\xE2\x8A\xB5", 0 }, { "rtrif", "\xE2\x96\xB8", 0 }, { "rtriltri", "\xE2\xA7\x8E", 0 }, { "ruluhar", "\xE2\xA5\xA8", 0 }, { "rx", "\xE2\x84\x9E", 0 }, { "sacute", "\xC5\x9B", 0 }, { "sbquo", "\xE2\x80\x9A", 0 }, { "sc", "\xE2\x89\xBB", 0 }, { "scE", "\xE2\xAA\xB4", 0 }, { "scap", "\xE2\xAA\xB8", 0 }, { "scaron", "\xC5\xA1", 0 }, { "sccue", "\xE2\x89\xBD", 0 }, { "sce", "\xE2\xAA\xB0", 0 }, { "scedil", "\xC5\x9F", 0 }, { "scirc", "\xC5\x9D", 0 }, { "scnE", "\xE2\xAA\xB6", 0 }, { "scnap", "\xE2\xAA\xBA", 0 }, { "scnsim", "\xE2\x8B\xA9", 0 }, { "scpolint", "\xE2\xA8\x93", 0 }, { "scsim", "\xE2\x89\xBF", 0 }, { "scy", "\xD1\x81", 0 }, { "sdot", "\xE2\x8B\x85", 0 }, { "sdotb", "\xE2\x8A\xA1", 0 }, { "sdote", "\xE2\xA9\xA6", 0 }, { "seArr", "\xE2\x87\x98", 0 }, { "searhk", "\xE2\xA4\xA5", 0 }, { "searr", "\xE2\x86\x98", 0 }, { "searrow", "\xE2\x86\x98", 0 }, { "sect", "\xC2\xA7", 0 }, { "semi", "\x3B", 0 }, { "seswar", "\xE2\xA4\xA9", 0 }, { "setminus", "\xE2\x88\x96", 0 }, { "setmn", "\xE2\x88\x96", 0 }, { "sext", "\xE2\x9C\xB6", 0 }, { "sfr", "\xF0\x9D\x94\xB0", 0 }, { "sfrown", "\xE2\x8C\xA2", 0 }, { "sharp", "\xE2\x99\xAF", 0 }, { "shchcy", "\xD1\x89", 0 }, { "shcy", "\xD1\x88", 0 }, { "shortmid", "\xE2\x88\xA3", 0 }, { "shortparallel", "\xE2\x88\xA5", 0 }, { "shy", "\xC2\xAD", 0 }, { "sigma", "\xCF\x83", 0 }, { "sigmaf", "\xCF\x82", 0 }, { "sigmav", "\xCF\x82", 0 }, { "sim", "\xE2\x88\xBC", 0 }, { "simdot", "\xE2\xA9\xAA", 0 }, { "sime", "\xE2\x89\x83", 0 }, { "simeq", "\xE2\x89\x83", 0 }, { "simg", "\xE2\xAA\x9E", 0 }, { "simgE", "\xE2\xAA\xA0", 0 }, { "siml", "\xE2\xAA\x9D", 0 }, { "simlE", "\xE2\xAA\x9F", 0 }, { "simne", "\xE2\x89\x86", 0 }, { "simplus", "\xE2\xA8\xA4", 0 }, { "simrarr", "\xE2\xA5\xB2", 0 }, { "slarr", "\xE2\x86\x90", 0 }, { "smallsetminus", "\xE2\x88\x96", 0 }, { "smashp", "\xE2\xA8\xB3", 0 }, { "smeparsl", "\xE2\xA7\xA4", 0 }, { "smid", "\xE2\x88\xA3", 0 }, { "smile", "\xE2\x8C\xA3", 0 }, { "smt", "\xE2\xAA\xAA", 0 }, { "smte", "\xE2\xAA\xAC", 0 }, { "smtes", "\xE2\xAA\xAC\xEF\xB8\x80", 0 }, { "softcy", "\xD1\x8C", 0 }, { "sol", "\x2F", 0 }, { "solb", "\xE2\xA7\x84", 0 }, { "solbar", "\xE2\x8C\xBF", 0 }, { "sopf", "\xF0\x9D\x95\xA4", 0 }, { "spades", "\xE2\x99\xA0", 0 }, { "spadesuit", "\xE2\x99\xA0", 0 }, { "spar", "\xE2\x88\xA5", 0 }, { "sqcap", "\xE2\x8A\x93", 0 }, { "sqcaps", "\xE2\x8A\x93\xEF\xB8\x80", 0 }, { "sqcup", "\xE2\x8A\x94", 0 }, { "sqcups", "\xE2\x8A\x94\xEF\xB8\x80", 0 }, { "sqsub", "\xE2\x8A\x8F", 0 }, { "sqsube", "\xE2\x8A\x91", 0 }, { "sqsubset", "\xE2\x8A\x8F", 0 }, { "sqsubseteq", "\xE2\x8A\x91", 0 }, { "sqsup", "\xE2\x8A\x90", 0 }, { "sqsupe", "\xE2\x8A\x92", 0 }, { "sqsupset", "\xE2\x8A\x90", 0 }, { "sqsupseteq", "\xE2\x8A\x92", 0 }, { "squ", "\xE2\x96\xA1", 0 }, { "square", "\xE2\x96\xA1", 0 }, { "squarf", "\xE2\x96\xAA", 0 }, { "squf", "\xE2\x96\xAA", 0 }, { "srarr", "\xE2\x86\x92", 0 }, { "sscr", "\xF0\x9D\x93\x88", 0 }, { "ssetmn", "\xE2\x88\x96", 0 }, { "ssmile", "\xE2\x8C\xA3", 0 }, { "sstarf", "\xE2\x8B\x86", 0 }, { "star", "\xE2\x98\x86", 0 }, { "starf", "\xE2\x98\x85", 0 }, { "straightepsilon", "\xCF\xB5", 0 }, { "straightphi", "\xCF\x95", 0 }, { "strns", "\xC2\xAF", 0 }, { "sub", "\xE2\x8A\x82", 0 }, { "subE", "\xE2\xAB\x85", 0 }, { "subdot", "\xE2\xAA\xBD", 0 }, { "sube", "\xE2\x8A\x86", 0 }, { "subedot", "\xE2\xAB\x83", 0 }, { "submult", "\xE2\xAB\x81", 0 }, { "subnE", "\xE2\xAB\x8B", 0 }, { "subne", "\xE2\x8A\x8A", 0 }, { "subplus", "\xE2\xAA\xBF", 0 }, { "subrarr", "\xE2\xA5\xB9", 0 }, { "subset", "\xE2\x8A\x82", 0 }, { "subseteq", "\xE2\x8A\x86", 0 }, { "subseteqq", "\xE2\xAB\x85", 0 }, { "subsetneq", "\xE2\x8A\x8A", 0 }, { "subsetneqq", "\xE2\xAB\x8B", 0 }, { "subsim", "\xE2\xAB\x87", 0 }, { "subsub", "\xE2\xAB\x95", 0 }, { "subsup", "\xE2\xAB\x93", 0 }, { "succ", "\xE2\x89\xBB", 0 }, { "succapprox", "\xE2\xAA\xB8", 0 }, { "succcurlyeq", "\xE2\x89\xBD", 0 }, { "succeq", "\xE2\xAA\xB0", 0 }, { "succnapprox", "\xE2\xAA\xBA", 0 }, { "succneqq", "\xE2\xAA\xB6", 0 }, { "succnsim", "\xE2\x8B\xA9", 0 }, { "succsim", "\xE2\x89\xBF", 0 }, { "sum", "\xE2\x88\x91", 0 }, { "sung", "\xE2\x99\xAA", 0 }, { "sup", "\xE2\x8A\x83", 0 }, { "sup1", "\xC2\xB9", 0 }, { "sup2", "\xC2\xB2", 0 }, { "sup3", "\xC2\xB3", 0 }, { "supE", "\xE2\xAB\x86", 0 }, { "supdot", "\xE2\xAA\xBE", 0 }, { "supdsub", "\xE2\xAB\x98", 0 }, { "supe", "\xE2\x8A\x87", 0 }, { "supedot", "\xE2\xAB\x84", 0 }, { "suphsol", "\xE2\x9F\x89", 0 }, { "suphsub", "\xE2\xAB\x97", 0 }, { "suplarr", "\xE2\xA5\xBB", 0 }, { "supmult", "\xE2\xAB\x82", 0 }, { "supnE", "\xE2\xAB\x8C", 0 }, { "supne", "\xE2\x8A\x8B", 0 }, { "supplus", "\xE2\xAB\x80", 0 }, { "supset", "\xE2\x8A\x83", 0 }, { "supseteq", "\xE2\x8A\x87", 0 }, { "supseteqq", "\xE2\xAB\x86", 0 }, { "supsetneq", "\xE2\x8A\x8B", 0 }, { "supsetneqq", "\xE2\xAB\x8C", 0 }, { "supsim", "\xE2\xAB\x88", 0 }, { "supsub", "\xE2\xAB\x94", 0 }, { "supsup", "\xE2\xAB\x96", 0 }, { "swArr", "\xE2\x87\x99", 0 }, { "swarhk", "\xE2\xA4\xA6", 0 }, { "swarr", "\xE2\x86\x99", 0 }, { "swarrow", "\xE2\x86\x99", 0 }, { "swnwar", "\xE2\xA4\xAA", 0 }, { "szlig", "\xC3\x9F", 0 }, { "target", "\xE2\x8C\x96", 0 }, { "tau", "\xCF\x84", 0 }, { "tbrk", "\xE2\x8E\xB4", 0 }, { "tcaron", "\xC5\xA5", 0 }, { "tcedil", "\xC5\xA3", 0 }, { "tcy", "\xD1\x82", 0 }, { "tdot", "\xE2\x83\x9B", 0 }, { "telrec", "\xE2\x8C\x95", 0 }, { "tfr", "\xF0\x9D\x94\xB1", 0 }, { "there4", "\xE2\x88\xB4", 0 }, { "therefore", "\xE2\x88\xB4", 0 }, { "theta", "\xCE\xB8", 0 }, { "thetasym", "\xCF\x91", 0 }, { "thetav", "\xCF\x91", 0 }, { "thickapprox", "\xE2\x89\x88", 0 }, { "thicksim", "\xE2\x88\xBC", 0 }, { "thinsp", "\xE2\x80\x89", 0 }, { "thkap", "\xE2\x89\x88", 0 }, { "thksim", "\xE2\x88\xBC", 0 }, { "thorn", "\xC3\xBE", 0 }, { "tilde", "\xCB\x9C", 0 }, { "times", "\xC3\x97", 0 }, { "timesb", "\xE2\x8A\xA0", 0 }, { "timesbar", "\xE2\xA8\xB1", 0 }, { "timesd", "\xE2\xA8\xB0", 0 }, { "tint", "\xE2\x88\xAD", 0 }, { "toea", "\xE2\xA4\xA8", 0 }, { "top", "\xE2\x8A\xA4", 0 }, { "topbot", "\xE2\x8C\xB6", 0 }, { "topcir", "\xE2\xAB\xB1", 0 }, { "topf", "\xF0\x9D\x95\xA5", 0 }, { "topfork", "\xE2\xAB\x9A", 0 }, { "tosa", "\xE2\xA4\xA9", 0 }, { "tprime", "\xE2\x80\xB4", 0 }, { "trade", "\xE2\x84\xA2", 0 }, { "triangle", "\xE2\x96\xB5", 0 }, { "triangledown", "\xE2\x96\xBF", 0 }, { "triangleleft", "\xE2\x97\x83", 0 }, { "trianglelefteq", "\xE2\x8A\xB4", 0 }, { "triangleq", "\xE2\x89\x9C", 0 }, { "triangleright", "\xE2\x96\xB9", 0 }, { "trianglerighteq", "\xE2\x8A\xB5", 0 }, { "tridot", "\xE2\x97\xAC", 0 }, { "trie", "\xE2\x89\x9C", 0 }, { "triminus", "\xE2\xA8\xBA", 0 }, { "triplus", "\xE2\xA8\xB9", 0 }, { "trisb", "\xE2\xA7\x8D", 0 }, { "tritime", "\xE2\xA8\xBB", 0 }, { "trpezium", "\xE2\x8F\xA2", 0 }, { "tscr", "\xF0\x9D\x93\x89", 0 }, { "tscy", "\xD1\x86", 0 }, { "tshcy", "\xD1\x9B", 0 }, { "tstrok", "\xC5\xA7", 0 }, { "twixt", "\xE2\x89\xAC", 0 }, { "twoheadleftarrow", "\xE2\x86\x9E", 0 }, { "twoheadrightarrow", "\xE2\x86\xA0", 0 }, { "uArr", "\xE2\x87\x91", 0 }, { "uHar", "\xE2\xA5\xA3", 0 }, { "uacute", "\xC3\xBA", 0 }, { "uarr", "\xE2\x86\x91", 0 }, { "ubrcy", "\xD1\x9E", 0 }, { "ubreve", "\xC5\xAD", 0 }, { "ucirc", "\xC3\xBB", 0 }, { "ucy", "\xD1\x83", 0 }, { "udarr", "\xE2\x87\x85", 0 }, { "udblac", "\xC5\xB1", 0 }, { "udhar", "\xE2\xA5\xAE", 0 }, { "ufisht", "\xE2\xA5\xBE", 0 }, { "ufr", "\xF0\x9D\x94\xB2", 0 }, { "ugrave", "\xC3\xB9", 0 }, { "uharl", "\xE2\x86\xBF", 0 }, { "uharr", "\xE2\x86\xBE", 0 }, { "uhblk", "\xE2\x96\x80", 0 }, { "ulcorn", "\xE2\x8C\x9C", 0 }, { "ulcorner", "\xE2\x8C\x9C", 0 }, { "ulcrop", "\xE2\x8C\x8F", 0 }, { "ultri", "\xE2\x97\xB8", 0 }, { "umacr", "\xC5\xAB", 0 }, { "uml", "\xC2\xA8", 0 }, { "uogon", "\xC5\xB3", 0 }, { "uopf", "\xF0\x9D\x95\xA6", 0 }, { "uparrow", "\xE2\x86\x91", 0 }, { "updownarrow", "\xE2\x86\x95", 0 }, { "upharpoonleft", "\xE2\x86\xBF", 0 }, { "upharpoonright", "\xE2\x86\xBE", 0 }, { "uplus", "\xE2\x8A\x8E", 0 }, { "upsi", "\xCF\x85", 0 }, { "upsih", "\xCF\x92", 0 }, { "upsilon", "\xCF\x85", 0 }, { "upuparrows", "\xE2\x87\x88", 0 }, { "urcorn", "\xE2\x8C\x9D", 0 }, { "urcorner", "\xE2\x8C\x9D", 0 }, { "urcrop", "\xE2\x8C\x8E", 0 }, { "uring", "\xC5\xAF", 0 }, { "urtri", "\xE2\x97\xB9", 0 }, { "uscr", "\xF0\x9D\x93\x8A", 0 }, { "utdot", "\xE2\x8B\xB0", 0 }, { "utilde", "\xC5\xA9", 0 }, { "utri", "\xE2\x96\xB5", 0 }, { "utrif", "\xE2\x96\xB4", 0 }, { "uuarr", "\xE2\x87\x88", 0 }, { "uuml", "\xC3\xBC", 0 }, { "uwangle", "\xE2\xA6\xA7", 0 }, { "vArr", "\xE2\x87\x95", 0 }, { "vBar", "\xE2\xAB\xA8", 0 }, { "vBarv", "\xE2\xAB\xA9", 0 }, { "vDash", "\xE2\x8A\xA8", 0 }, { "vangrt", "\xE2\xA6\x9C", 0 }, { "varepsilon", "\xCF\xB5", 0 }, { "varkappa", "\xCF\xB0", 0 }, { "varnothing", "\xE2\x88\x85", 0 }, { "varphi", "\xCF\x95", 0 }, { "varpi", "\xCF\x96", 0 }, { "varpropto", "\xE2\x88\x9D", 0 }, { "varr", "\xE2\x86\x95", 0 }, { "varrho", "\xCF\xB1", 0 }, { "varsigma", "\xCF\x82", 0 }, { "varsubsetneq", "\xE2\x8A\x8A\xEF\xB8\x80", 0 }, { "varsubsetneqq", "\xE2\xAB\x8B\xEF\xB8\x80", 0 }, { "varsupsetneq", "\xE2\x8A\x8B\xEF\xB8\x80", 0 }, { "varsupsetneqq", "\xE2\xAB\x8C\xEF\xB8\x80", 0 }, { "vartheta", "\xCF\x91", 0 }, { "vartriangleleft", "\xE2\x8A\xB2", 0 }, { "vartriangleright", "\xE2\x8A\xB3", 0 }, { "vcy", "\xD0\xB2", 0 }, { "vdash", "\xE2\x8A\xA2", 0 }, { "vee", "\xE2\x88\xA8", 0 }, { "veebar", "\xE2\x8A\xBB", 0 }, { "veeeq", "\xE2\x89\x9A", 0 }, { "vellip", "\xE2\x8B\xAE", 0 }, { "verbar", "\x7C", 0 }, { "vert", "\x7C", 0 }, { "vfr", "\xF0\x9D\x94\xB3", 0 }, { "vltri", "\xE2\x8A\xB2", 0 }, { "vnsub", "\xE2\x8A\x82\xE2\x83\x92", 0 }, { "vnsup", "\xE2\x8A\x83\xE2\x83\x92", 0 }, { "vopf", "\xF0\x9D\x95\xA7", 0 }, { "vprop", "\xE2\x88\x9D", 0 }, { "vrtri", "\xE2\x8A\xB3", 0 }, { "vscr", "\xF0\x9D\x93\x8B", 0 }, { "vsubnE", "\xE2\xAB\x8B\xEF\xB8\x80", 0 }, { "vsubne", "\xE2\x8A\x8A\xEF\xB8\x80", 0 }, { "vsupnE", "\xE2\xAB\x8C\xEF\xB8\x80", 0 }, { "vsupne", "\xE2\x8A\x8B\xEF\xB8\x80", 0 }, { "vzigzag", "\xE2\xA6\x9A", 0 }, { "wcirc", "\xC5\xB5", 0 }, { "wedbar", "\xE2\xA9\x9F", 0 }, { "wedge", "\xE2\x88\xA7", 0 }, { "wedgeq", "\xE2\x89\x99", 0 }, { "weierp", "\xE2\x84\x98", 0 }, { "wfr", "\xF0\x9D\x94\xB4", 0 }, { "wopf", "\xF0\x9D\x95\xA8", 0 }, { "wp", "\xE2\x84\x98", 0 }, { "wr", "\xE2\x89\x80", 0 }, { "wreath", "\xE2\x89\x80", 0 }, { "wscr", "\xF0\x9D\x93\x8C", 0 }, { "xcap", "\xE2\x8B\x82", 0 }, { "xcirc", "\xE2\x97\xAF", 0 }, { "xcup", "\xE2\x8B\x83", 0 }, { "xdtri", "\xE2\x96\xBD", 0 }, { "xfr", "\xF0\x9D\x94\xB5", 0 }, { "xhArr", "\xE2\x9F\xBA", 0 }, { "xharr", "\xE2\x9F\xB7", 0 }, { "xi", "\xCE\xBE", 0 }, { "xlArr", "\xE2\x9F\xB8", 0 }, { "xlarr", "\xE2\x9F\xB5", 0 }, { "xmap", "\xE2\x9F\xBC", 0 }, { "xnis", "\xE2\x8B\xBB", 0 }, { "xodot", "\xE2\xA8\x80", 0 }, { "xopf", "\xF0\x9D\x95\xA9", 0 }, { "xoplus", "\xE2\xA8\x81", 0 }, { "xotime", "\xE2\xA8\x82", 0 }, { "xrArr", "\xE2\x9F\xB9", 0 }, { "xrarr", "\xE2\x9F\xB6", 0 }, { "xscr", "\xF0\x9D\x93\x8D", 0 }, { "xsqcup", "\xE2\xA8\x86", 0 }, { "xuplus", "\xE2\xA8\x84", 0 }, { "xutri", "\xE2\x96\xB3", 0 }, { "xvee", "\xE2\x8B\x81", 0 }, { "xwedge", "\xE2\x8B\x80", 0 }, { "yacute", "\xC3\xBD", 0 }, { "yacy", "\xD1\x8F", 0 }, { "ycirc", "\xC5\xB7", 0 }, { "ycy", "\xD1\x8B", 0 }, { "yen", "\xC2\xA5", 0 }, { "yfr", "\xF0\x9D\x94\xB6", 0 }, { "yicy", "\xD1\x97", 0 }, { "yopf", "\xF0\x9D\x95\xAA", 0 }, { "yscr", "\xF0\x9D\x93\x8E", 0 }, { "yucy", "\xD1\x8E", 0 }, { "yuml", "\xC3\xBF", 0 }, { "zacute", "\xC5\xBA", 0 }, { "zcaron", "\xC5\xBE", 0 }, { "zcy", "\xD0\xB7", 0 }, { "zdot", "\xC5\xBC", 0 }, { "zeetrf", "\xE2\x84\xA8", 0 }, { "zeta", "\xCE\xB6", 0 }, { "zfr", "\xF0\x9D\x94\xB7", 0 }, { "zhcy", "\xD0\xB6", 0 }, { "zigrarr", "\xE2\x87\x9D", 0 }, { "zopf", "\xF0\x9D\x95\xAB", 0 }, { "zscr", "\xF0\x9D\x93\x8F", 0 }, { "zwj", "\xE2\x80\x8D", 0 }, { "zwnj", "\xE2\x80\x8C", 0 }, }; /* End of temporary hack for RiskV */ #ifdef __riscv #pragma GCC pop_options #endif /*---------------------------------------------------------------------------- | ErInit -- | | Initialize the entity reference hash table | \---------------------------------------------------------------------------*/ static void ErInit (void) { size_t i; /* For looping through the list of entity references */ int h; /* The hash on a entity */ for(i=0; inodeType == ATTRIBUTE_NODE) { z = ((domAttrNode*)textOrAtt)->nodeValue; zlen = ((domAttrNode*)textOrAtt)->valueLength; } else { z = textOrAtt->nodeValue; zlen = textOrAtt->valueLength; } from = to = 0; if (bErNeedsInit) { TDomThreaded(Tcl_MutexLock(&initMutex);) if (bErNeedsInit) { ErInit(); bErNeedsInit = 0; } TDomThreaded(Tcl_MutexUnlock(&initMutex);) } while (z[from]) { if (z[from]=='&') { int isInvalid = 0; int i = from+1; int c; if (z[i] == '#') { /*--------------------------------------------- | convert character reference \--------------------------------------------*/ value = 0; if (z[++i] == 'x') { i++; while ((c=z[i]) && (c!=';')) { value = value * 16; if ((c>='0') && (c<='9')) { value += c-'0'; } else if ((c>='A') && (c<='F')) { value += c-'A' + 10; } else if ((c>='a') && (c<='f')) { value += c-'a' + 10; } else { /* error */ isInvalid = 1; break; } if (value > 2097152) { /* error */ isInvalid = 1; break; } i++; } } else { while ((c=z[i]) && (c!=';')) { value = value * 10; if ((c>='0') && (c<='9')) { value += c-'0'; } else { /* error */ isInvalid = 1; break; } if (value > 2097152) { /* error */ isInvalid = 1; break; } i++; } } if (z[i]!=';') { /* error */ isInvalid = 1; } if (isInvalid) { /* * In case the character reference was invalid * it was a false alaram, no valid character * reference, just copy the source chars; */ int j; for (j = from; j < i; j++) { z[to++] = z[j]; } from = i; } else { if (value < 0x80) { z[to++] = value; } else if (value <= 0x7FF) { z[to++] = (char) ((value >> 6) | 0xC0); z[to++] = (char) ((value | 0x80) & 0xBF); } else if (value <= 0xFFFF) { z[to++] = (char) ((value >> 12) | 0xE0); z[to++] = (char) (((value >> 6) | 0x80) & 0xBF); z[to++] = (char) ((value | 0x80) & 0xBF); } else { z[to++] = (char) ((value >> 18) | 0xf0); z[to++] = (char) (((value >> 12) & 0x3f) | 0x80); z[to++] = (char) (((value >> 6) & 0x3f) | 0x80); z[to++] = (char) ((value & 0x3f) | 0x80); } from = i+1; } } else { while (z[i] && isalnum((unsigned char)z[i])) { i++; } c = z[i]; z[i] = 0; h = ErHash(&z[from+1]); p = apErHash[h]; while (p && strcmp(p->zName,&z[from+1])!=0 ) { p = p->pNext; } ole = NULL; if (!p && c == ';') { /* Entity name not found. It may be one of the few * entities with a referenced UTF-8 byte sequence * which is longer than the reference. */ if (strcmp("nGt",&z[from+1]) == 0) { ole = "\xE2\x89\xAB\xE2\x83\x92\x00"; overlen = 1; } else if (strcmp("nLt",&z[from+1]) == 0) { ole = "\xE2\x89\xAA\xE2\x83\x92\x00"; overlen = 1; } } z[i] = c; if (p) { zVal = p->zValue; while (*zVal) { z[to++] = *(zVal++); } from = i; if (c==';') from++; } else { if (ole) { /* Over-long entity reference */ from = i; newNodeValue = MALLOC(zlen + 1 + overlen); memmove(newNodeValue,z,to); while (*ole) { newNodeValue[to++] = *(ole++); } memmove(newNodeValue + to, z + from + 1 , zlen - from); z = newNodeValue; zlen = zlen + overlen; if (textOrAtt->nodeType == ATTRIBUTE_NODE) { FREE (((domAttrNode*)textOrAtt)->nodeValue); ((domAttrNode*)textOrAtt)->nodeValue = z; ((domAttrNode*)textOrAtt)->valueLength = zlen; } else { FREE (textOrAtt->nodeValue); textOrAtt->nodeValue = z; textOrAtt->valueLength = zlen; } from = to; } else { z[to++] = z[from++]; } } } } else { z[to++] = z[from++]; } } z[to] = 0; if (textOrAtt->nodeType == ATTRIBUTE_NODE) { ((domAttrNode*)textOrAtt)->valueLength = to; } else { textOrAtt->valueLength = to; } } /*---------------------------------------------------------------------------- | End Of Character Entity Translator \---------------------------------------------------------------------------*/ DBG( /*---------------------------------------------------------------------------- | getDeep | \---------------------------------------------------------------------------*/ static int getDeep (domNode *n) { int d; d = 0; while (n->parentNode != NULL) { d++; n = n->parentNode; } return d; } ) /*---------------------------------------------------------------------------- | HTML_SimpleParse (non recursive) | | Parses the HTML string starting at 'pos' and continuing to the | first encountered error. | \---------------------------------------------------------------------------*/ static int HTML_SimpleParse ( char *html, /* HTML string */ domLength *pos, /* Index of next unparsed character in xml */ domDocument *doc, domNode *parent, int ignoreWhiteSpaces, int forest, char **errStr ) { register int c; /* Next character of the input file */ register char *pn, *e; register char *x, *start, *piSep; char savedChar; int hasContent; domNode *pnode; domNode *node = NULL, *parent_node = parent; domTextNode *tnode; domAttrNode *attrnode, *lastAttr; int ampersandSeen = 0; int only_whites = 0; int hnew, autoclose, ignore, maybeCustomName, rc; char tmp[250], *y = NULL; Tcl_HashEntry *h; domProcessingInstructionNode *pinode; x = &(html[*pos]); while ( (c=*x)!=0 ) { start = x; if ((c!='<') || ((c=='<') && (x[1]!='!') && (x[2]!='-') && (x[3]!='-') && (x[1]!='/') && !IsLetter(x[1])) ) { /*---------------------------------------------------------------- | read text between tags | \---------------------------------------------------------------*/ readText: ampersandSeen = 0; only_whites = 1; if (c=='<') x++; while ( (c=*x)!=0 && c!='<' ) { if (c=='&') ampersandSeen = 1; if ( !SPACE(c) ) only_whites = 0; x++; } if (!(only_whites && ignoreWhiteSpaces) && parent_node) { /*-------------------------------------------------------- | allocate new TEXT node \-------------------------------------------------------*/ tnode = (domTextNode*) domAlloc(sizeof(domTextNode)); memset(tnode, 0, sizeof(domTextNode)); tnode->nodeType = TEXT_NODE; tnode->ownerDocument = doc; tnode->nodeNumber = NODE_NO(doc); tnode->valueLength = (domLength)(x - start); tnode->nodeValue = (char*)MALLOC((x - start)+1); memmove(tnode->nodeValue, start, (x - start)); *(tnode->nodeValue + (x - start)) = 0; DBG(fprintf(stderr, "New text node: '%s'\n", tnode->nodeValue);) if (ampersandSeen) { TranslateEntityRefs (tnode); } tnode->parentNode = parent_node; if (parent_node->firstChild) { parent_node->lastChild->nextSibling = (domNode*)tnode; tnode->previousSibling = parent_node->lastChild; parent_node->lastChild = (domNode*)tnode; } else { parent_node->firstChild = parent_node->lastChild = (domNode*)tnode; } node = (domNode*)tnode; } } else if (x[1]=='/') { /*------------------------------------------------------------ | read and check closing tag \-----------------------------------------------------------*/ x += 2; while ((c=*x)!=0 && c!='>' && c!='<' && !SPACE(c) ) { *x = tolower(c); x++; } if (c==0) { RetError("Missing \">\"",(domLength)(start-html) ); } if ( (x-start)==2) { RetError("Null markup name",(domLength)(start-html) ); } *x = '\0'; /* temporarily terminate the string */ /*---------------------------------------------------------------------- | check for tags which could optional be close | like \---------------------------------------------------------------------*/ ignore = 0; pnode = NULL; if (parent_node) { if (parent_node->lastChild && (parent_node->lastChild->nodeType == ELEMENT_NODE)) { pnode = parent_node->lastChild; } else if (parent_node->lastChild && parent_node->lastChild->previousSibling && (parent_node->lastChild->previousSibling->nodeType == ELEMENT_NODE)) { pnode = parent_node->lastChild->previousSibling; } } if (pnode) { DBG(fprintf(stderr, "'%s' closing with last empty tag '%s' ?\n", start+2, pnode->nodeName);) if (strcmp(start+2,pnode->nodeName)==0) { switch (*(start+2)) { case 'o': if (!strcmp(start+2,"option")) ignore = 1; break; } } } if (!ignore) { /*---------------------------------------------------------------------- | look for a corresponding opening tag the way up the tag hierarchy \---------------------------------------------------------------------*/ pnode = parent_node; while (pnode != NULL) { DBG(fprintf(stderr, "checking '%s' to top hierarchy: '%s' \n", start+2,pnode->nodeName);) if (!strcmp(start+2,pnode->nodeName)) break; pnode = pnode->parentNode; } if (pnode == NULL) { /* beginning tag was not found the way up the tag hierarchy -> ignore the tag */ DBG(fprintf(stderr,"ignoring closing '%s' \n", start+2);) ignore = 1; } } if (!ignore) { pn = (char*)parent_node->nodeName; while (1) { DBG(fprintf(stderr, "comparing '%s' with pn='%s' \n", start+2, pn);) if (strcmp(start+2,pn)!=0) { /*---------------------------------------------------------- | check for parent tags which allow closing of sub tags | which belong to the parent tag \---------------------------------------------------------*/ ignore = 0; if (!strcmp(pn,"table") && (!strcmp(start+2,"tr") || !strcmp(start+2,"td")) ) { ignore = 1; } if (ignore) { parent_node = node->parentNode; break; } /*--------------------------------------------------------------- | check for tags for which end tag can be omitted \--------------------------------------------------------------*/ autoclose = 0; switch (pn[0]) { case 'a': if (!strcmp(pn,"a")) {autoclose = 1;} break; case 'b': if (!strcmp(pn,"b")) {autoclose = 1;} break; case 'c': if (!strcmp(pn,"colgroup")) {autoclose = 1;} break; case 'd': if (!strcmp(pn,"dd") || !strcmp(pn,"dt") || (!strcmp(start+2,"form") && !strcmp(pn,"div")) ) {autoclose = 1;} break; case 'h': if (!strcmp(pn,"head") || !strcmp(pn,"html")) {autoclose = 1;} break; case 'f': if (!strcmp(pn,"font")|| !strcmp(pn,"form")) {autoclose = 1;} break; case 'i': if (!strcmp(pn,"i")) {autoclose = 1;} break; case 'l': if (!strcmp(pn,"li")) {autoclose = 1;} break; case 'n': if (!strcmp(pn,"noscript")) {autoclose = 1;} break; case 'o': if (!strcmp(pn,"option")) {autoclose = 1;} break; case 'p': if (!strcmp(pn,"p")) {autoclose = 1;} break; case 's': if (!strcmp(pn,"span")) {autoclose = 1;} break; case 't': if (!strcmp(pn,"tbody") || !strcmp(pn,"td") || !strcmp(pn,"tfoot") || !strcmp(pn,"thead") || !strcmp(pn,"th") || !strcmp(pn,"tr") || !strcmp(pn,"tt")) {autoclose = 1;} break; case 'u': if (!strcmp(pn,"ul")) {autoclose = 1;} break; /* ext */ } /*--------------------------------------------------------------- | check for tags for close inner tags \--------------------------------------------------------------*/ switch (start[2]) { case 'b': if (!strcmp(start+2,"body")) autoclose = 1; break; } if (autoclose) { DBG(fprintf(stderr, "autoclose '%s' with '%s' \n", pn, start+2);) if (parent_node != NULL) { node = parent_node; parent_node = node->parentNode; pn = (char*)node->nodeName; break; } } sprintf(tmp, "Unterminated element '%s' (within '%s')", start+2, pn); *x = c; /* remove temporarily termination */ RetError(tmp,(domLength)(x - html)); } break; } /* move up */ node = parent_node; parent_node = NULL; if (node) parent_node = node->parentNode; } *x = c; /* remove temporarily termination */ while (SPACE(*x)) { x++; } if (*x=='>') { x++; } else { if (*x == '<') { /* start of new tag, ends closing tag */ } else { RetError("Missing \">\"",(domLength)(x - html)-1); } } if (parent_node == NULL) { /* we return to main node and so finished parsing */ return TCL_OK; } continue; } else { x++; if (*x=='!') { if (x[1]=='-' && x[2]=='-') { /*-------------------------------------------------------- | read over a comment \-------------------------------------------------------*/ x += 3; while ( (c=*x)!=0 && (c!='-' || x[1]!='-' || x[2]!='>')) { x++; } if (*x) { /*---------------------------------------------------- | allocate new COMMENT node for comments \---------------------------------------------------*/ tnode = (domTextNode*) domAlloc(sizeof(domTextNode)); memset(tnode, 0, sizeof(domTextNode)); tnode->nodeType = COMMENT_NODE; tnode->ownerDocument = doc; tnode->nodeNumber = NODE_NO(doc); tnode->parentNode = parent_node; tnode->valueLength = (domLength)(x - start - 4); tnode->nodeValue = (char*)MALLOC(tnode->valueLength+1); memmove(tnode->nodeValue, start+4, tnode->valueLength); *(tnode->nodeValue + tnode->valueLength) = 0; if (parent_node == NULL) { if (doc->rootNode->lastChild) { tnode->previousSibling = doc->rootNode->lastChild; doc->rootNode->lastChild->nextSibling = (domNode *) tnode; } else { doc->rootNode->firstChild = (domNode*) tnode; } doc->rootNode->lastChild = (domNode*) tnode; } else { if (parent_node->firstChild) { parent_node->lastChild->nextSibling = (domNode*)tnode; tnode->previousSibling = parent_node->lastChild; parent_node->lastChild = (domNode*)tnode; } else { parent_node->firstChild = parent_node->lastChild = (domNode*)tnode; } } x += 3; } else { RetError("Unterminated comment",(domLength)(start-html)); } continue; } else if (TU(x[1])=='D' && TU(x[2])=='O' && TU(x[3])=='C' && TU(x[4])=='T' && TU(x[5])=='Y' && TU(x[6])=='P' && TU(x[7])=='E' ) { /*-------------------------------------------------------- | read over a DOCTYPE definition \-------------------------------------------------------*/ x += 8; start = x; while (*x!=0) { if (*x=='[') { x++; while ((*x!=0) && (*x!=']')) x++; } else if (*x=='>') { break; } else { x++; } } if (*x) { x++; } else { RetError("Unterminated DOCTYPE definition",(domLength)(start-html)); } continue; } else if (x[1]=='[' && x[2]=='C' && x[3]=='D' && x[4]=='A' && x[5]=='T' && x[6]=='A' && x[7]=='[' ) { /*-------------------------------------------------------- | read over a '))) { x++; } if (*x) { if (parent_node) { /*---------------------------------------------------- | allocate new TEXT node for CDATA section data \---------------------------------------------------*/ tnode = (domTextNode*) domAlloc(sizeof(domTextNode)); memset(tnode, 0, sizeof(domTextNode)); tnode->nodeType = TEXT_NODE; tnode->ownerDocument = doc; tnode->nodeNumber = NODE_NO(doc); tnode->parentNode = parent_node; tnode->valueLength = (domLength)(x - start); tnode->nodeValue = (char*)MALLOC((x - start)+1); memmove(tnode->nodeValue, start, (x - start)); *(tnode->nodeValue + (x - start)) = 0; if (parent_node->firstChild) { parent_node->lastChild->nextSibling = (domNode*)tnode; tnode->previousSibling = parent_node->lastChild; parent_node->lastChild = (domNode*)tnode; } else { parent_node->firstChild = parent_node->lastChild = (domNode*)tnode; } } x += 3; } else { RetError("Unterminated CDATA definition",(domLength)(start-html) ); } continue; } else { RetError("Incorrect ')) { x++; } if (*x) { /*------------------------------------------------------------ | allocate new PI node for processing instruction section \-----------------------------------------------------------*/ pinode = (domProcessingInstructionNode*) MALLOC(sizeof(domProcessingInstructionNode)); memset(pinode, 0, sizeof(domProcessingInstructionNode)); pinode->nodeType = PROCESSING_INSTRUCTION_NODE; pinode->ownerDocument = doc; pinode->nodeNumber = NODE_NO(doc); pinode->parentNode = parent_node; /*------------------------------------------------- | extract PI target \------------------------------------------------*/ piSep = start; while ( (c=*piSep)!=0 && !SPACE(c) && (c!='?' || piSep[1]!='>')) { piSep++; } *piSep = '\0'; /* temporarily terminate the string */ pinode->targetLength = (domLength)strlen(start); pinode->targetValue = (char*)MALLOC(pinode->targetLength); memmove(pinode->targetValue, start, pinode->targetLength); *piSep = c; /* remove temporarily termination */ /*------------------------------------------------- | extract PI data \------------------------------------------------*/ while (SPACE(*piSep)) { piSep++; } pinode->dataLength = (domLength)(x - piSep); pinode->dataValue = (char*)MALLOC(pinode->dataLength); memmove(pinode->dataValue, piSep, pinode->dataLength); if (parent_node == NULL) { if (doc->rootNode->lastChild) { pinode->previousSibling = doc->rootNode->lastChild; doc->rootNode->lastChild->nextSibling = (domNode*) pinode; } else { doc->rootNode->firstChild = (domNode*) pinode; } doc->rootNode->lastChild = (domNode*) pinode; } else { if (parent_node->firstChild) { parent_node->lastChild->nextSibling = (domNode*)pinode; pinode->previousSibling = parent_node->lastChild; parent_node->lastChild = (domNode*)pinode; } else { parent_node->firstChild = parent_node->lastChild = (domNode*)pinode; } } x += 2; } else { RetError("Unterminated processing instruction(PI)",(domLength)(start-html)); } continue; } /*---------------------------------------------------------------- | new tag/element | \---------------------------------------------------------------*/ maybeCustomName = 0; while ((c=*x)!=0 && c!='/' && c!='>' && c!='<' && !SPACE(c) ) { if (!maybeCustomName && !isalnum(c)) maybeCustomName = 1; x++; } if (!maybeCustomName) { c = *x; *x = '\0'; /* temporarily terminate the string */ x = start + 1; while (*x) { *x = tolower(*x); x++; } *x = c; } else { c = *x; *x = '\0'; /* temporarily terminate the string */ rc = domIsHTML5CustomName (start+1); *x = c; if (!rc) { goto readText; } } hasContent = 1; if (c==0) { RetError("Missing \">\"",(domLength)(start-html)); } if ( (x-start)==1) { RetError("Null markup name",(domLength)(start-html)); } DBG(fprintf(stderr, "\nnew tag '%70.70s...' \n", start);) *x = '\0'; /* temporarily terminate the string */ /*----------------------------------------------------------- | check, whether new starting element close another | currently open one \----------------------------------------------------------*/ e = start+1; pn = ""; if (parent_node) { pn = (char*)parent_node->nodeName; } autoclose = 0; switch (*e) { case 'a': if(!strcmp(e,"a")&&!strcmp(pn,"a")) autoclose=1; break; case 'b': if(!strcmp(e,"b")&&!strcmp(pn,"b")) autoclose=1; break; case 'o': if (!strcmp(e,"option")&&!strcmp(pn,"option")) autoclose = 1; break; case 'p': if((!strcmp(e,"pre")&&!strcmp(pn,"pre")) ||(!strcmp(e,"p")&&!strcmp(pn,"p"))) autoclose=1; break; } if (autoclose) { DBG(fprintf(stderr, "autoclose '%s' because of new '%s' \n", pn, e);) node = parent_node; parent_node = node->parentNode; } /*----------------------------------------------------------- | create new DOM element node \----------------------------------------------------------*/ if (!parent_node && (strcmp(e,"html")!=0)) { // Insert missing html tag h = Tcl_CreateHashEntry(&HASHTAB(doc,tdom_tagNames), "html", &hnew); node = (domNode*) domAlloc(sizeof(domNode)); memset(node, 0, sizeof(domNode)); node->nodeType = ELEMENT_NODE; node->nodeName = (char *)&(h->key); node->ownerDocument = doc; node->nodeNumber = NODE_NO(doc); if (doc->rootNode->lastChild) { node->previousSibling = doc->rootNode->lastChild; doc->rootNode->lastChild->nextSibling = node; } else { doc->rootNode->firstChild = node; } doc->rootNode->lastChild = node; parent_node = node; DBG(fprintf(stderr, "%d: Inserted missing tag '%s' hasContent=%d nodeNumber=%d\n", getDeep(node), node->nodeName, hasContent, node->nodeNumber);) } h = Tcl_CreateHashEntry(&HASHTAB(doc,tdom_tagNames), e, &hnew); node = (domNode*) domAlloc(sizeof(domNode)); memset(node, 0, sizeof(domNode)); node->nodeType = ELEMENT_NODE; node->nodeName = (char *)&(h->key); node->ownerDocument = doc; node->nodeNumber = NODE_NO(doc); if (parent_node == NULL) { if (doc->rootNode->lastChild) { node->previousSibling = doc->rootNode->lastChild; doc->rootNode->lastChild->nextSibling = node; } else { doc->rootNode->firstChild = node; } doc->rootNode->lastChild = node; } else { node->parentNode = parent_node; if (parent_node->firstChild) { parent_node->lastChild->nextSibling = node; node->previousSibling = parent_node->lastChild; parent_node->lastChild = node; } else { parent_node->firstChild = parent_node->lastChild = node; } } *x = c; /* remove temporarily termination */ while (SPACE(*x) ) { x++; } /*----------------------------------------------------------- | read attribute name-value pairs \----------------------------------------------------------*/ lastAttr = NULL; while ( (c=*x) && (c!='/') && (c!='>') && (c!='<') ) { char *ArgName = x; domLength nArgName; char *ArgVal = NULL; domLength nArgVal = 0; while ((c=*x)!=0 && c!='=' && c!='>' && !SPACE(c) ) { *x = tolower(c); x++; } nArgName = (domLength)(x - ArgName); while (SPACE(*x)) { x++; } if (*x == '=') { /* attribute with value, like width="1234" */ x++; while (SPACE(*x)) { x++; } savedChar = *(ArgName + nArgName); *(ArgName + nArgName) = '\0'; /* terminate arg name */ if (*x=='>' || *x==0) { ArgVal = ArgName; nArgVal = nArgName; } else if ((c=*x)=='\"' || c=='\'') { register int cDelim = c; x++; ArgVal = x; ampersandSeen = 0; while ((c=*x)!=0 && c!=cDelim) { if (c=='&') ampersandSeen = 1; x++; } nArgVal = (domLength)(x - ArgVal); if (c==0) { RetError("Unterminated string",(domLength)(ArgVal - html - 1)); } else { x++; } } else if (c!=0 && c!='>') { ArgVal = x; while ((c=*x)!=0 && c!='>' && !SPACE(c)) { if (c=='&') ampersandSeen = 1; x++; } if (c==0) { RetError("Missing \">\"",(domLength)(start-html)); } nArgVal = (domLength)(x - ArgVal); } } else { /* attribute without value, like 'nowrap' */ savedChar = *(ArgName + nArgName); *(ArgName + nArgName) = '\0'; /* terminate arg name */ ArgVal = ArgName; nArgVal = nArgName; } /*-------------------------------------------------- | allocate new attribute node \--------------------------------------------------*/ h = Tcl_CreateHashEntry(&HASHTAB(doc,tdom_attrNames), ArgName, &hnew); attrnode = (domAttrNode*) domAlloc(sizeof(domAttrNode)); memset(attrnode, 0, sizeof(domAttrNode)); attrnode->parentNode = node; attrnode->nodeName = (char *)&(h->key); attrnode->nodeType = ATTRIBUTE_NODE; attrnode->nodeValue = (char*)MALLOC(nArgVal+1); attrnode->valueLength = nArgVal; memmove(attrnode->nodeValue, ArgVal, nArgVal); *(attrnode->nodeValue + nArgVal) = 0; if (ampersandSeen) { TranslateEntityRefs ((domTextNode*)attrnode); } if (!strcmp(ArgName, "id")) { if (!doc->ids) { doc->ids = (Tcl_HashTable *) MALLOC (sizeof (Tcl_HashTable)); Tcl_InitHashTable (doc->ids, TCL_STRING_KEYS); } h = Tcl_CreateHashEntry (doc->ids, attrnode->nodeValue, &hnew); /* How to resolve in case of duplicates? We follow, what the core dom building code does: the first value in document order wins. */ if (hnew) { Tcl_SetHashValue (h, node); attrnode->nodeFlags |= IS_ID_ATTRIBUTE; } } if (node->firstAttr) { lastAttr->nextSibling = attrnode; } else { node->firstAttr = attrnode; } lastAttr = attrnode; *(ArgName + nArgName) = savedChar; while (SPACE(*x)) { x++; } } /*----------------------------------------------------------- | check for empty HTML tags \----------------------------------------------------------*/ switch (node->nodeName[0]) { case 'a': if (!strcmp(node->nodeName,"area")) {hasContent = 0;} break; case 'b': if (!strcmp(node->nodeName,"br") || !strcmp(node->nodeName,"base") || !strcmp(node->nodeName,"basefont")) {hasContent = 0;} break; case 'c': if (!strcmp(node->nodeName,"col")) {hasContent = 0;} break; case 'e': if (!strcmp(node->nodeName,"embed")) {hasContent = 0;} break; case 'f': if (!strcmp(node->nodeName,"frame")) {hasContent = 0;} break; case 'h': if (!strcmp(node->nodeName,"hr")) {hasContent = 0;} break; case 'i': if (!strcmp(node->nodeName,"img") || !strcmp(node->nodeName,"input") || !strcmp(node->nodeName,"isindex")) {hasContent = 0;} break; case 'l': if (!strcmp(node->nodeName,"link")) {hasContent = 0;} break; case 'm': if (!strcmp(node->nodeName,"meta")) {hasContent = 0;} break; case 'p': if (!strcmp(node->nodeName,"param")) {hasContent = 0;} break; case 's': if (!strcmp(node->nodeName,"spacer") || !strcmp(node->nodeName,"source")) {hasContent = 0;} break; /*html5*/ } if (*x=='/') { hasContent = 0; x++; if (*x!='>') { RetError("Syntax Error",(domLength)(x - html - 1)); } } if (*x=='>') { x++; } DBG(fprintf(stderr, "%d: new node '%s' hasContent=%d \n", getDeep(node), node->nodeName, hasContent);) if ((strcmp(node->nodeName,"style" )==0) || (strcmp(node->nodeName,"script")==0) ) { /*----------------------------------------------------------- | read over any data within a 'style' or 'script' tag \----------------------------------------------------------*/ hasContent = 1; start = x; while (1) { while ( (*x!=0) && ((*x!='<') || (x[1]!='/'))) { x++; } if (!*x) break; y = x + 2; while (*y!=0 && SPACE(*y)) y++; if (TU(y[0]) == 'S' && TU(y[1]) == 'C' && TU(y[2]) == 'R' && TU(y[3]) == 'I' && TU(y[4]) == 'P' && TU(y[5]) == 'T' ) break; if (TU(y[0]) == 'S' && TU(y[1]) == 'T' && TU(y[2]) == 'Y' && TU(y[3]) == 'L' && TU(y[4]) == 'E' ) break; x++; } if (*x) { /*---------------------------------------------------- | allocate new TEXT node for style/script data \---------------------------------------------------*/ tnode = (domTextNode*) domAlloc(sizeof(domTextNode)); memset(tnode, 0, sizeof(domTextNode)); tnode->nodeType = TEXT_NODE; tnode->ownerDocument = doc; tnode->nodeNumber = NODE_NO(doc); tnode->parentNode = node; tnode->valueLength = (domLength)(x - start); tnode->nodeValue = (char*)MALLOC((x - start)+1); memmove(tnode->nodeValue, start, (x - start)); *(tnode->nodeValue + (x - start)) = 0; if (node->firstChild) { node->lastChild->nextSibling = (domNode*)tnode; tnode->previousSibling = node->lastChild; node->lastChild = (domNode*)tnode; } else { node->firstChild = node->lastChild = (domNode*)tnode; } } } if (hasContent) { /*------------------------------------------------------------ | recurs to read child tags/texts \-----------------------------------------------------------*/ parent_node = node; } DBG(fprintf(stderr, "%d: after node '%s' \n", getDeep(node), node->nodeName);) } } while (parent_node != NULL && node->parentNode) { pn = (char*)node->parentNode->nodeName; DBG(fprintf(stderr, "final autoclose '%s'? \n", pn);) /*--------------------------------------------------------------- | check for tags for which end tag can be omitted \--------------------------------------------------------------*/ autoclose = 0; switch (pn[0]) { case 'b': if (!strcmp(pn,"body")) {autoclose = 1;} break; case 'c': if (!strcmp(pn,"colgroup")) {autoclose = 1;} break; case 'd': if (!strcmp(pn,"dd") || !strcmp(pn,"dt")) {autoclose = 1;} break; case 'h': if (!strcmp(pn,"head") || !strcmp(pn,"html")) {autoclose = 1;} break; case 'l': if (!strcmp(pn,"li")) {autoclose = 1;} break; case 'o': if (!strcmp(pn,"option")) {autoclose = 1;} break; case 'p': if (!strcmp(pn,"p")) {autoclose = 1;} break; case 't': if (!strcmp(pn,"tbody") || !strcmp(pn,"td") || !strcmp(pn,"tfoot") || !strcmp(pn,"thead") || !strcmp(pn,"th") || !strcmp(pn,"tr")) {autoclose = 1;} break; case 'u': if (!strcmp(pn,"ul")) {autoclose = 1;} break; /* ext */ } if (!autoclose) break; DBG(fprintf(stderr, "final autoclosed '%s'! \n", pn);) node = node->parentNode; parent_node = node->parentNode; } if (parent_node == NULL) { /* we return to main node and so finished parsing */ return TCL_OK; } if (forest && parent_node == parent) { return TCL_OK; } RetError("Unexpected end",(domLength)(x - html)); } /* HTML_SimpleParse */ /*---------------------------------------------------------------------------- | HTML_SimpleParseDocument | | Create a document, parses the HTML string starting at 'pos' and | continuing to the first encountered error. | \---------------------------------------------------------------------------*/ domDocument * HTML_SimpleParseDocument ( char *html, /* Complete text of the file being parsed */ int ignoreWhiteSpaces, int forest, domLength *pos, char **errStr ) { domDocument *doc = domCreateDoc(NULL, 0); domNode *save, *node = NULL; Tcl_HashEntry *h; int hnew; if (forest) { // Create umbrella tag h = Tcl_CreateHashEntry(&HASHTAB(doc,tdom_tagNames), "forestroot", &hnew); node = (domNode*) domAlloc(sizeof(domNode)); memset(node, 0, sizeof(domNode)); node->nodeType = ELEMENT_NODE; node->nodeName = (char *)&(h->key); node->ownerDocument = doc; doc->rootNode->firstChild = node; doc->rootNode->lastChild = node; } *pos = 0; HTML_SimpleParse (html, pos, doc, node, ignoreWhiteSpaces, forest, errStr); if (forest) { doc->rootNode->firstChild = node->firstChild; doc->rootNode->lastChild = node->lastChild; save = node; for (node = doc->rootNode->firstChild; node != NULL; node = node->nextSibling) { node->parentNode = NULL; } domFree ((void*)save); } domSetDocumentElement (doc); return doc; } /* HTML_SimpleParseDocument */ tdom-0.9.5-src/generic/tdom.h0000644000175000017500000000037114703531020014467 0ustar rolfrolf #define __TDOM_H #include "tcl.h" #include #include #undef TCL_STORAGE_CLASS #ifdef BUILD_tdom # define TCL_STORAGE_CLASS DLLEXPORT #else # define TCL_STORAGE_CLASS DLLIMPORT #endif #include "dom.h" #include "tdomDecls.h" tdom-0.9.5-src/generic/tcldom.h0000644000175000017500000000677014703531020015017 0ustar rolfrolf/*---------------------------------------------------------------------------- | Copyright (c) 1999 Jochen Loewer (loewerj@hotmail.com) +----------------------------------------------------------------------------- | | A DOM implementation for Tcl using James Clark's expat XML parser | | | The contents of this file are subject to the Mozilla Public License | Version 2.0 (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) 1998, 1999 | Jochen Loewer. All Rights Reserved. | | Contributor(s): | | | written by Jochen Loewer | April, 1999 | \---------------------------------------------------------------------------*/ #ifndef __TCLDOM_H_INCLUDE__ #define __TCLDOM_H_INCLUDE__ #include #ifdef __cplusplus extern "C" { #endif /* The following procs are defined in tcldom.c - since they are used * in nodecmd.c these need a prototype somewhere. The prototypes can * live here for now. */ int tcldom_textCheck(Tcl_Interp *interp, char *text, char *errText); int tcldom_commentCheck(Tcl_Interp *interp, char *text); int tcldom_CDATACheck(Tcl_Interp *interp, char *text); int tcldom_PIValueCheck(Tcl_Interp *interp, char *text); int tcldom_PINameCheck(Tcl_Interp *interp, char *name); int tcldom_nameCheck(Tcl_Interp *interp, char *name, char *nameType, int isFQName); void tcldom_createNodeObj(Tcl_Interp * interp, domNode *node, char *objCmdName); domNode * tcldom_getNodeFromObj(Tcl_Interp *interp, Tcl_Obj *nodeObj); #ifndef __TDOM_H domDocument * tcldom_getDocumentFromName(Tcl_Interp *interp, char *docName, char **errMsg); #endif int tcldom_prefixNSlist (char ***prefixnsPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], const char *methodName); int tcldom_setInterpAndReturnVar (Tcl_Interp *interp, domNode *node, Tcl_Obj *var_name); void tcldom_initialize(void); void tcldom_deleteDoc (Tcl_Interp *interp, domDocument *doc); Tcl_ObjCmdProc tcldom_DomObjCmd; Tcl_ObjCmdProc tcldom_DocObjCmd; Tcl_ObjCmdProc tcldom_NodeObjCmd; Tcl_ObjCmdProc tcldom_unknownCmd; Tcl_ObjCmdProc TclTdomObjCmd; int tDOM_fsnewNodeCmd (ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *const objv[]); int tDOM_fsinsertNodeCmd (ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj *const objv[]); void tcldom_reportErrorLocation ( Tcl_Interp *interp, int before, int after, XML_Size line, XML_Size column, char *xmlstring, const char *entity, XML_Index byteIndex, const char *errStr ); #ifdef __cplusplus } #endif #if defined(_MSC_VER) || defined(__MINGW32__) # undef TCL_STORAGE_CLASS # define TCL_STORAGE_CLASS DLLEXPORT #endif #define STR_TDOM_VERSION(v) (VERSION) EXTERN int Tdom_Init (Tcl_Interp *interp); EXTERN int Tdom_SafeInit (Tcl_Interp *interp); #endif tdom-0.9.5-src/generic/expat_config.h0000644000175000017500000000005014703531020016164 0ustar rolfrolf/* an empty/fake config.h for expat */ tdom-0.9.5-src/generic/domhtml.h0000644000175000017500000000032114703531020015163 0ustar rolfrolf domDocument * HTML_SimpleParseDocument ( char *html, int ignoreWhiteSpaces, int forrest, domLength *pos, char **errStr ); tdom-0.9.5-src/generic/domxpath.c0000644000175000017500000063456114703531020015361 0ustar rolfrolf/*---------------------------------------------------------------------------- | Copyright (c) 1999-2001 Jochen Loewer (loewerj@hotmail.com) |----------------------------------------------------------------------------- | | 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 2.0 (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, several optimizations and bug | fixes. | | written by Jochen Loewer | July, 1999 | \---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- | Includes | \---------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include /*---------------------------------------------------------------------------- | 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 const 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; dom_minl intvalue; double realvalue; domLength pos; } XPathToken; typedef XPathToken *XPathTokens; /*---------------------------------------------------------------------------- | Types for abstract syntax trees | \---------------------------------------------------------------------------*/ static const 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", "Subtract", "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" }; static const char *xpathResultTypes[] = { "unknown", "empty", "bool", "number", "number", "string", "xNodeSet", "number", "number", "number", "nodes", "attrnodes", "mixed", NULL }; /*---------------------------------------------------------------------------- | 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_laststring, 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, domLength 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); /*---------------------------------------------------------------------------- | xpathResultType2string | \---------------------------------------------------------------------------*/ const char * xpathResultType2string ( xpathResultType type ) { return xpathResultTypes[type]; } /*---------------------------------------------------------------------------- | 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 xpathRSReset ( xpathResultSet *rs, domNode *node ) { if (rs->type == StringResult) FREE(rs->string); if (node) { if (!rs->nodes) { rs->nodes = (domNode**)MALLOC( INITIAL_SIZE*sizeof(domNode*)); rs->allocated = INITIAL_SIZE; } rs->nodes[0] = node; rs->nr_nodes = 1; rs->type = xNodeSetResult; } else { rs->nr_nodes = 0; if (rs->nodes) rs->type = xNodeSetResult; else rs->type = EmptyResult; } } void rsPrint ( xpathResultSet *rs ) { domLength i = 0,l; char tmp[80]; switch (rs->type) { case EmptyResult: fprintf(stderr, "empty result \n"); break; case BoolResult: #if TCL_MAJOR_VERSION > 8 fprintf(stderr, "boolean result: %" TCL_SIZE_MODIFIER "d \n", #else fprintf(stderr, "boolean result: %ld \n", #endif rs->intvalue); break; case IntResult: #if TCL_MAJOR_VERSION > 8 fprintf(stderr, "boolean result: %" TCL_SIZE_MODIFIER "d \n", #else fprintf(stderr, "boolean result: %ld \n", #endif rs->intvalue); break; case RealResult: fprintf(stderr, "real result: %f \n", rs->realvalue); break; case StringResult: fprintf(stderr, "string result: -%80s-\n", rs->string); break; case xNodeSetResult: if (!i) fprintf(stderr,"nodeSet result (len " domLengthConversion "):\n", rs->nr_nodes); for (i=0; inr_nodes; i++) { if (rs->nodes[i]->nodeType == ELEMENT_NODE) { fprintf(stderr, "%2" TCL_SIZE_MODIFIER "i domNode%p %s ", i, (void *)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, "%2" TCL_SIZE_MODIFIER "i domNode%p text:'%s' \n", i, (void *)rs->nodes[i], tmp); } else if (rs->nodes[i]->nodeType == COMMENT_NODE) { l = ((domTextNode*)rs->nodes[i])->valueLength; memcpy (tmp, "", 3); tmp[7+l] = '\0'; fprintf(stderr, "%2" TCL_SIZE_MODIFIER "i domNode%p text:'%s' \n", i, (void *)rs->nodes[i], tmp); } else if (rs->nodes[i]->nodeType == ATTRIBUTE_NODE) { fprintf(stderr, "%2" TCL_SIZE_MODIFIER "i Attr %s='%80s'\n", i, ((domAttrNode*)rs->nodes[i])->nodeName, ((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 rsSetReal2 ( xpathResultSet *rs, double d) { if (d <= (double)LONG_MIN || d >= (double)LONG_MAX || d != (long)d) { rs->type = RealResult; rs->realvalue = d; } else { rs->type = IntResult; rs->intvalue = (long)d; } } void rsSetNaN ( xpathResultSet *rs ) { rs->type = NaNResult; } void rsSetInf ( xpathResultSet *rs ) { rs->type = InfResult; } void rsSetNInf ( xpathResultSet *rs ) { rs->type = NInfResult; } void rsSetLong ( xpathResultSet *rs, dom_minl i) { rs->type = IntResult; rs->intvalue = i; } void rsSetBool ( xpathResultSet *rs, dom_minl i) { rs->type = BoolResult; rs->intvalue = (i ? 1 : 0); } void rsSetString ( xpathResultSet *rs, const char *s) { rs->type = StringResult; if (s) { rs->string = tdomstrdup(s); rs->string_len = (domLength)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 { domLength insertIndex, 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)) { 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 { 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 ) { domLength 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; inr_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( dom_minl 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; itype]); switch (t->type) { case Int : #if TCL_MAJOR_VERSION > 8 fprintf(stderr, "%" TCL_SIZE_MODIFIER "d", t->intvalue); break; #else fprintf(stderr, "%ld", t->intvalue); break; #endif 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 ) { domLength l, allocated, 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) { *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 (!varParseCB) { *errMsg = tdomstrdup ("Unexpected char '%'"); return tokens; } ps = (varParseCB->parseVarCB) ( varParseCB->parseVarClientData, &xpath[i], &offset, errMsg ); if (ps) { token = WCARDNAME; tokens[l].strvalue = tdomstrdup (ps); /* We kind of misuse the (in case of * WCARDNAME token otherwise not used) * intvalue to mark this WCARDNAME token * to be meant as literal - this is to * distinguish between '*' as wildcard and * as literal element name. */ tokens[l].intvalue = 1; i += offset - 1; } else { 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, i.e. a REAL. Handled by default. */ /* fall through */ 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 %" TCL_SIZE_MODIFIER "i", 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) { errno = 0; 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 %" TCL_SIZE_MODIFIER "i", i); *errMsg = tdomstrdup (tmpErr); return tokens; } } else { sprintf (tmpErr, "Unexpected character '%c' at " "position %" TCL_SIZE_MODIFIER "i", 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); a->intvalue = INTVAL; } 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; break; case 'l': if (strcmp (funcName, "lang")==0) return f_lang; else if (strcmp (funcName, "last")==0) return f_last; else if (strcmp (funcName, "laststring")==0) return f_laststring; 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 a; 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(RelativeLocationPath); if (!b) return a; if (b->type == AxisChild) { b->type = AxisDescendant; } else { Append(a, New( AxisDescendantOrSelf ) ); } Append(a, b ); } } else { if ( (LA==SLASH) || (LA==SLASHSLASH)) { return Recurse(AbsoluteLocationPath); } else { return Recurse(RelativeLocationPath); } } EndProduction /*----------------------------------------------------------------- | UnionExpr production | \----------------------------------------------------------------*/ Production(UnionExpr) a = Recurse(PathExpr); while (LA==PIPE) { Consume(PIPE); a = New2( CombineSets, a, Recurse(PathExpr)); } EndProduction /*----------------------------------------------------------------- | UnaryExpr production | \----------------------------------------------------------------*/ Production(UnaryExpr) if (LA==MINUS) { Consume(MINUS); a = Recurse(UnionExpr); if (!a) { if (*errMsg == NULL) { ErrExpected("UnionExpr"); } return NULL; } if ((a->type == Int) && (a->next == NULL)) { a->intvalue = a->intvalue * -1; } else if ((a->type == Real) && (a->next == NULL)) { a->realvalue = a->realvalue * -1; } else { a = New1( UnaryMinus, a); } } else { a = Recurse(UnionExpr); } EndProduction /*----------------------------------------------------------------- | MultiplicativeExpr production | \----------------------------------------------------------------*/ Production(MultiplicativeExpr) a = Recurse(UnaryExpr); while ( (LA==MULTIPLY) ||(LA==DIV) ||(LA==MOD) ) { if (LA==MULTIPLY) { Consume(MULTIPLY); a = New2( Mult, a, Recurse(UnaryExpr)); } else if (LA==DIV) { Consume(DIV); a = New2( Div, a, Recurse(UnaryExpr)); } else { Consume(MOD); a = New2( Mod, a, Recurse(UnaryExpr)); } } EndProduction /*----------------------------------------------------------------- | AdditiveExpr production | \----------------------------------------------------------------*/ Production(AdditiveExpr) a = Recurse(MultiplicativeExpr); while ( (LA==PLUS) ||(LA==MINUS) ) { if (LA==PLUS) { Consume(PLUS); a = New2( Add, a, Recurse(MultiplicativeExpr)); } else { Consume(MINUS); a = New2( Subtract, a, Recurse(MultiplicativeExpr)); } } EndProduction /*----------------------------------------------------------------- | RelationalExpr production | \----------------------------------------------------------------*/ Production(RelationalExpr) a = Recurse(AdditiveExpr); while ( (LA==LT) ||(LA==LTE) ||(LA==GT) ||(LA==GTE) ) { if (LA==LT) { Consume(LT); a = New2( Less, a, Recurse(AdditiveExpr)); } else if (LA==LTE) { Consume(LTE); a = New2( LessOrEq, a, Recurse(AdditiveExpr)); } else if (LA==GT) { Consume(GT); a = New2( Greater, a, Recurse(AdditiveExpr)); } else { Consume(GTE); a = New2( GreaterOrEq, a, Recurse(AdditiveExpr)); } } EndProduction /*----------------------------------------------------------------- | EqualityExpr production | \----------------------------------------------------------------*/ Production(EqualityExpr) a = Recurse(RelationalExpr); while ( (LA==EQUAL) ||(LA==NOTEQ) ) { if (LA==EQUAL) { Consume(EQUAL); a = New2( Equal, a, Recurse(RelationalExpr)); } else { Consume(NOTEQ); a = New2( NotEqual, a, Recurse(RelationalExpr)); } } EndProduction /*----------------------------------------------------------------- | AndExpr production | \----------------------------------------------------------------*/ Production(AndExpr) a = Recurse(EqualityExpr); while (LA==AND) { Consume(AND); a = New2( And, a, Recurse(EqualityExpr)); } EndProduction /*----------------------------------------------------------------- | OrExpr production | \----------------------------------------------------------------*/ Production(OrExpr) a = Recurse(AndExpr); while (LA==OR) { Consume(OR); a = New2( Or, a, Recurse(AndExpr)); } EndProduction /*----------------------------------------------------------------- | Predicate production | \----------------------------------------------------------------*/ Production(Predicate) Consume(LBRACKET); a = Recurse(OrExpr); Consume(RBRACKET); EndProduction /*----------------------------------------------------------------- | Basis production | \----------------------------------------------------------------*/ Production(Basis) if (LA==AXISNAME) { astType t; Consume(AXISNAME); if (IS_STR('c',"child")) { t = AxisChild; } else if (IS_STR('d',"descendant")) { t = AxisDescendantLit; } else if (IS_STR('d',"descendant-or-self")) { t = AxisDescendantOrSelfLit; } else if (IS_STR('s',"self")) { t = AxisSelf; } else if (IS_STR('a',"attribute")) { t = AxisAttribute; } else if (IS_STR('a',"ancestor")) { t = AxisAncestor; } else if (IS_STR('a',"ancestor-or-self")) { t = AxisAncestorOrSelf; } else if (IS_STR('f',"following")) { t = AxisFollowing; } else if (IS_STR('f',"following-sibling")) { t = AxisFollowingSibling; } else if (IS_STR('n',"namespace")) { t = AxisNamespace; } else if (IS_STR('p',"parent")) { t = AxisParent; } else if (IS_STR('p',"preceding")) { t = AxisPreceding; } else if (IS_STR('p',"preceding-sibling")) { t = AxisPrecedingSibling; } else { ErrExpected("correct axis name"); } a = New( t ); Consume(COLONCOLON); AddChild( a, Recurse(NodeTest)); } else { a = Recurse(AbbreviatedBasis); } EndProduction /*----------------------------------------------------------------- | Step production | \----------------------------------------------------------------*/ static dom_minl IsStepPredOptimizable (ast a) { ast b; dom_minl left; /* Must be called with a != NULL */ DBG ( fprintf (stderr, "IsStepPredOptimizable:\n"); printAst (0,a); ) switch (a->type) { case Int: return a->intvalue; case Less: case LessOrEq: b = a->child; if (!b) return 0; if (b->type != ExecFunction || b->intvalue != f_position) return 0; b = b->next; if (!b) return 0; if (b->type != Int) return 0; if (a->type == Less) return b->intvalue; else return b->intvalue + 1; case Greater: case GreaterOrEq: b = a->child; if (!b) return 0; if (b->type != Int) return 0; left = b->intvalue; b = b->next; if (!b) return 0; if (b->type != ExecFunction || b->intvalue != f_position) return 0; if (a->type == Greater) return left; else return left + 1; case Equal: b = a->child; if (!b) return 0; if (b->type == Int && b->next && b->next->type == ExecFunction && b->next->intvalue == f_position) return b->intvalue; if (b->type == ExecFunction && b->intvalue == f_position && b->next && b->next->type == Int) return b->next->intvalue; return 0; default: return 0; } } Production(Step) if (LA==DOT) { Consume(DOT); a = New( GetContextNode ); /* a = New1( AxisSelf, New (IsNode)); */ } else if (LA==DOTDOT) { Consume(DOTDOT); a = New( GetParentNode ); /* a = New1( AxisParent, New (IsNode)); */ } else { ast b; int isFirst = 1; a = Recurse(Basis); if (LA==LBRACKET && !a) { if (*errMsg == NULL) { ErrExpected("Step"); } return NULL; } while (LA==LBRACKET) { b = Recurse (Predicate); if (!b) return a; if (isFirst) { a->intvalue = IsStepPredOptimizable (b); DBG (fprintf (stderr, "step type %s, intvalue: %d\n", astType2str[a->type], a->intvalue);) isFirst = 0; } Append( a, New1WithEvalSteps( Pred, b)); } } EndProduction /*----------------------------------------------------------------- | RelativeLocationPath production | \----------------------------------------------------------------*/ Production(RelativeLocationPath) a = Recurse(Step); if (!a) return NULL; while ((LA==SLASH) || (LA==SLASHSLASH)) { if (LA==SLASH) { Consume(SLASH); Append(a, Recurse(Step)); } else { ast b; Consume(SLASHSLASH); b = Recurse(Step); if (!b) return a; if (b->type == AxisChild) { b->type = AxisDescendant; } else { Append(a, New( AxisDescendantOrSelf ) ); } Append(a, b ); } } EndProduction /*----------------------------------------------------------------- | AbsoluteLocationPath production | \----------------------------------------------------------------*/ Production(AbsoluteLocationPath) if (LA==SLASH) { ast b; Consume(SLASH); a = New(SelectRoot); if ( (LA==AXISNAME) ||(LA==WCARDNAME) ||(LA==NSPREFIX) ||(LA==NSWC) ||(LA==NODE) ||(LA==TEXT) ||(LA==COMMENT) ||(LA==PINSTR) ||(LA==DOT) ||(LA==DOTDOT) ||(LA==ATTRIBUTE) ||(LA==ATTRIBUTEPREFIX) ) { b = Recurse(RelativeLocationPath); Append(a, b); } } else if (LA==SLASHSLASH) { ast b; Consume(SLASHSLASH); a = New(SelectRoot); b = Recurse(RelativeLocationPath); if (!b) { freeAst (a); return NULL; } if (b->type == AxisChild) { b->type = AxisDescendant; } else { Append(a, New( AxisDescendantOrSelf ) ); } Append(a, b ); } else { ErrExpected("/ or //"); } EndProduction /*----------------------------------------------------------------- | XSLT StepPattern production | \----------------------------------------------------------------*/ static int usesPositionInformation ( ast a) { while (a) { if (a->type == ExecFunction && (a->intvalue == f_position || a->intvalue == f_last || a->intvalue == f_laststring || a->intvalue == f_unknown)) { return 1; } if (a->child) { if (usesPositionInformation (a->child)) return 1; } a = a->next; } return 0; } /* Must be called with a != NULL */ static int checkStepPatternPredOptimizability ( ast a , dom_minl *max) { ast b; switch (a->type) { case Literal: case AxisAncestor: case AxisAncestorOrSelf: case AxisChild: case AxisAttribute: case AxisDescendant: case AxisDescendantLit: case AxisDescendantOrSelf: case AxisDescendantOrSelfLit: case AxisFollowing: case AxisFollowingSibling: case AxisNamespace: case AxisParent: case AxisPreceding: case AxisPrecedingSibling: case AxisSelf: case IsNode: case IsComment: case IsText: case IsPI: case IsSpecificPI: case IsElement: case GetContextNode: case GetParentNode: break; case And: case Or: if (usesPositionInformation(a->child)) return 0; return 1; case Less: case LessOrEq: b = a->child; if (b && b->type == ExecFunction && b->intvalue == f_position && b->next && b->next->type == Int) { if (a->type == Less) *max = b->next->intvalue; else *max = b->next->intvalue + 1; return 0; } if (usesPositionInformation(a->child)) return 0; return 1; case Greater: case GreaterOrEq: b = a->child; if (b && b->type == Int && b->next && b->next->type == ExecFunction && b->next->intvalue == f_position) { if (a->type == Greater) *max = b->intvalue; else *max = b->intvalue + 1; return 0; } if (usesPositionInformation(a->child)) return 0; return 1; case Equal: b = a->child; if (b && b->type == Int && b->next && b->next->type == ExecFunction && b->next->intvalue == f_position) { *max = b->intvalue; return 0; } if (b && b->type == ExecFunction && b->intvalue == f_position && b->next && b->next->type == Int) { *max = b->next->intvalue; return 0; } if (usesPositionInformation(a->child)) return 0; return 1; case NotEqual: if (usesPositionInformation(a->child)) return 0; return 1; case Int: *max = a->intvalue; return 0; case ExecFunction: return !usesPositionInformation(a); default: return 0; } return 1; } /* Must be called with a != NULL */ static long IsStepPatternPredOptimizable ( ast a, dom_minl *max ) { long f; *max = 0; f = checkStepPatternPredOptimizability(a, max); DBG( if (f) { fprintf(stderr, "\nStepPattern Pred is optimizable:\n"); } else { fprintf(stderr, "\nStepPattern Pred is not optimizable, max = %d:\n", *max); } printAst(0,a); ) return f; } /*----------------------------------------------------------------- | XSLT StepPattern production | \----------------------------------------------------------------*/ Production(StepPattern) if (LA==AXISNAME) { astType t; Consume(AXISNAME); if (IS_STR('c',"child")) { t = AxisChild; } else if (IS_STR('a',"attribute")) { t = AxisAttribute; } else { ErrExpected("correct axis name (child/attribute)"); } Consume(COLONCOLON); a = New1( t, Recurse(NodeTest)); } else 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 = Recurse(NodeTest); } if (!a) { if (*errMsg == NULL) { ErrExpected("StepPattern") }; return NULL; } { ast b = NULL, c = NULL, aCopy = NULL; int stepIsOptimizable = 1, isFirst = 1; dom_minl max, savedmax; while (LA==LBRACKET) { b = Recurse (Predicate); if (!b) return a; if (stepIsOptimizable) { if (!IsStepPatternPredOptimizable(b, &max)) stepIsOptimizable = 0; } if (isFirst) { savedmax = max; c = New1WithEvalSteps( Pred, b); isFirst = 0; } else { Append (c, New1WithEvalSteps( Pred, b)); } } if (!isFirst) { if (stepIsOptimizable) { Append (a, New (FillWithCurrentNode)); } else { /* copy the step before the Predicate */ aCopy = NEWCONS; aCopy->type = a->type; aCopy->next = NULL; if (a->strvalue) aCopy->strvalue = tdomstrdup(a->strvalue); else aCopy->strvalue = NULL; aCopy->intvalue = a->intvalue; aCopy->realvalue = a->realvalue; aCopy->child = NULL; if (a->child) { ast aCopyChild = NEWCONS; aCopyChild->type = a->child->type; aCopyChild->next = NULL; aCopyChild->child = NULL; if (a->child->strvalue) { aCopyChild->strvalue = tdomstrdup(a->child->strvalue); } else { aCopyChild->strvalue = NULL; } aCopyChild->intvalue = a->child->intvalue; aCopyChild->realvalue = a->child->realvalue; aCopy->child = aCopyChild; } b = New1( FillNodeList, aCopy); b->intvalue = savedmax; Append( a, b); } Append (a, c); } } EndProduction /*----------------------------------------------------------------- | XSLT RelativePathPattern production | \----------------------------------------------------------------*/ Production(RelativePathPattern) a = Recurse(StepPattern); while ((LA==SLASH) || (LA==SLASHSLASH)) { ast b; if (LA==SLASH) { Consume(SLASH); b = Recurse(StepPattern); if (b) { Append(b, New(ToParent) ); Append(b, a); a = b; } } else { Consume(SLASHSLASH); b = Recurse(StepPattern); if (b) { Append(b, New(ToAncestors) ); Append(b, a); a = b; } } } EndProduction /*----------------------------------------------------------------- | XSLT IdKeyPattern production | \----------------------------------------------------------------*/ Production(IdKeyPattern) Consume(FUNCTION); if (strcmp(STRVAL, "id" )==0) { ast b; /* id */ a = NewStr( ExecIdKey, STRVAL); a->intvalue = f_id; Consume(LPAR); Consume(LITERAL); b = NewStr( Literal, STRVAL); AddChild (a, b); Consume(RPAR); } else { ast b; /* key */ a = NewStr( ExecIdKey, STRVAL); Consume(LPAR); Consume(LITERAL); b = NewStr( Literal, STRVAL); AddChild (a, b); Consume(COMMA); Consume(LITERAL); b = NewStr( Literal, STRVAL); AddChild (a, b); Consume(RPAR); } EndProduction /*----------------------------------------------------------------- | XSLT LocationPathPattern production | \----------------------------------------------------------------*/ Production(LocationPathPattern) if (LA==SLASH) { Consume(SLASH); if (LA==EOS || LA==PIPE) { a = New(IsRoot); } else { a = Recurse(RelativePathPattern); if (a) { Append( a, New(ToParent) ); Append( a, New(IsRoot) ); } } } else if ((LA==FUNCTION) && ( (strcmp(tokens[*l].strvalue, "id" )==0) ||(strcmp(tokens[*l].strvalue, "key")==0) ) ) { ast b; b = Recurse(IdKeyPattern); if (LA==SLASH) { Consume(SLASH); a = Recurse(RelativePathPattern); if (a) { Append( a, New(ToParent) ); } } else if (LA==SLASHSLASH) { Consume(SLASHSLASH); a = Recurse(RelativePathPattern); if (a) { Append( a, New(ToAncestors) ); } } if (!a) { a = b; } else { Append( a, b); } } else { if (LA==SLASHSLASH) { Consume(SLASHSLASH); a = Recurse(RelativePathPattern); if (a) { Append( a, New(ToAncestors) ); Append( a, New(IsRoot) ); } } else { a = Recurse(RelativePathPattern); } } EndProduction /*----------------------------------------------------------------- | XSLT Pattern production | \----------------------------------------------------------------*/ Production(Pattern) a = Recurse(LocationPathPattern); while (LA==PIPE) { Consume(PIPE); a = New2( CombinePath, New1(EvalSteps, a), New1(EvalSteps, Recurse(LocationPathPattern) ) ); } EndProduction /*---------------------------------------------------------------------------- | xpathFreeTokens | \---------------------------------------------------------------------------*/ static int xpathFreeTokens ( XPathTokens tokens ) { int i; for (i=0; tokens[i].token != EOS; i++) { if (tokens[i].strvalue) { FREE(tokens[i].strvalue); } } FREE((char*)tokens); return 0; } /*---------------------------------------------------------------------------- | xpathParsePostProcess | \---------------------------------------------------------------------------*/ static int xpathParsePostProcess ( ast t, xpathExprType type, domNode *exprContext, char **prefixMappings, char **errMsg ) { const char *uri; DBG( fprintf(stderr, "xpathParsePostProcess start:\n"); printAst (0, t); ) while (t) { DBG(printAst (4, t);) if (t->type == AxisNamespace) { if (t->child->type == IsElement && t->child->strvalue[0] != '*' && t->child->intvalue == 0) { uri = domLookupPrefixWithMappings (exprContext, t->child->strvalue, prefixMappings); if (!uri) { *errMsg = tdomstrdup ("Prefix doesn't resolve"); return 0; } FREE (t->child->strvalue); t->child->strvalue = tdomstrdup (uri); } } if (type != XPATH_EXPR) { if (type != XPATH_KEY_USE_EXPR) { /* 12.4: "It is an error to use the current function in a pattern." */ if (t->type == ExecFunction && t->intvalue == f_unknown && (strcmp (t->strvalue, "current")==0)) { *errMsg = tdomstrdup( "The 'current' function is not allowed in Pattern." ); return 0; } } if (type == XPATH_KEY_MATCH_PATTERN || type == XPATH_KEY_USE_EXPR) { /* 12.2: "It is an error for the value of either the use attribute or the match attribute to contain a VariableReference, or a call to the key function." */ if (t->type == ExecFunction && t->intvalue == f_unknown && (strcmp (t->strvalue, "key")==0)) { *errMsg = tdomstrdup("The 'key' function is not allowed " "in the use and match attribute " "pattern of xsl:key."); return 0; } if (t->type == GetVar || t->type == GetFQVar) { *errMsg = tdomstrdup("Variable references are not allowed " "in the use and match attribute of " "xsl:key."); return 0; } } if (type == XPATH_TEMPMATCH_PATTERN) { /* 5.3: "It is an error for the value of the match attribute to contain a VariableReference." */ if (t->type == GetVar || t->type == GetFQVar) { *errMsg = tdomstrdup("Variable references are not allowed " "in the match attribute of " "xsl:template." ); return 0; } } } if (t->child) { if (!xpathParsePostProcess (t->child, type, exprContext, prefixMappings, errMsg)) return 0; } t = t->next; } return 1; } /*---------------------------------------------------------------------------- | xpathParse | \---------------------------------------------------------------------------*/ int xpathParse ( char *xpath, domNode *exprContext, xpathExprType type, char **prefixMappings, xpathParseVarCB *varParseCB, ast *t, char **errMsg ) { XPathTokens tokens; int i, l; size_t len, newlen, slen; int useNamespaceAxis = 0; char tmp[200]; DDBG(fprintf(stderr, "\nLex output following tokens for '%s':\n", xpath);) *errMsg = NULL; tokens = xpathLexer(xpath, exprContext, prefixMappings, &useNamespaceAxis, 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 %5ld %s\n", i, token2str[tokens[i].token-LPAR], tokens[i].intvalue, tokens[i].realvalue, tokens[i].pos, tokens[i].strvalue ); } ) l = 0; *t = NULL; if (type == XPATH_EXPR || type == XPATH_KEY_USE_EXPR) { *t = OrExpr (&l, tokens, errMsg); } else { *t = Pattern (&l, tokens, errMsg); } if ((*errMsg == NULL) && (tokens[l].token != EOS)) { *errMsg = tdomstrdup("Unexpected tokens (beyond end)!"); } if (*errMsg == NULL && ((type != XPATH_EXPR) || useNamespaceAxis)) { xpathParsePostProcess (*t, type, exprContext, prefixMappings, errMsg); } if (*errMsg) { len = strlen(*errMsg); 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++) { #if TCL_MAJOR_VERSION > 8 sprintf(tmp, "%s\n%3s%3d %-12s %5" TCL_SIZE_MODIFIER "d %09.3g %5" TCL_SIZE_MODIFIER "d ", #else sprintf(tmp, "%s\n%3s%3d %-12s %5ld %09.3g %5d ", #endif (i==0) ? "\n\nParsed symbols:" : "", (i==l) ? "-->" : " ", i, token2str[tokens[i].token-LPAR], tokens[i].intvalue, tokens[i].realvalue, tokens[i].pos ); len = strlen(*errMsg); newlen = strlen(tmp); slen = 0; if (tokens[i].strvalue) { slen = strlen(tokens[i].strvalue); } *errMsg = (char*)REALLOC(*errMsg, len+newlen+slen+1); memmove(*errMsg + len, tmp, newlen); memmove(*errMsg + len + newlen, tokens[i].strvalue, slen); (*errMsg)[len + newlen + slen] = '\0'; } } DBG( if (type) { fprintf(stderr, "\nPattern AST for '%s': \n", xpath); printAst (0, *t); } else { fprintf(stderr, "AST (xpathParse):\n"); printAst (0, *t); } ) xpathFreeTokens (tokens); if (*errMsg!=NULL) { if (*t) freeAst (*t); return XPATH_SYNTAX_ERR; } return 0; } /* xpathParse */ /*---------------------------------------------------------------------------- | xpathNodeTest | \---------------------------------------------------------------------------*/ int xpathNodeTest ( domNode *node, ast step ) { const char *localName, *nodeUri; if (!(step->child)) return 1; if (step->child->type == IsElement) { if (node->nodeType == ELEMENT_NODE) { if ((step->child->strvalue[0] == '*') && (step->child->strvalue[1] == '\0') && (node->ownerDocument->rootNode != node) && (step->child->intvalue == 0)) return 1; if (node->namespace && (node->ownerDocument->namespaces[node->namespace-1]->prefix[0] != '\0' || node->ownerDocument->namespaces[node->namespace-1]->uri[0] != '\0') ) return 0; return (strcmp(node->nodeName, step->child->strvalue)==0); } return 0; } else if (step->child->type == IsAttr) { if (node->nodeType == ATTRIBUTE_NODE) { if (node->nodeFlags & IS_NS_NODE) return 0; if ( (step->child->strvalue[0] == '*') &&(step->child->strvalue[1] == '\0') ) { return 1; } return (strcmp( ((domAttrNode*)node)->nodeName, step->child->strvalue)==0); } return 0; } else if (step->child->type == IsFQElement) { if (node->nodeType != ELEMENT_NODE || node->namespace == 0) return 0; nodeUri = domNamespaceURI (node); if (!nodeUri) return 0; if (strcmp (step->child->strvalue, nodeUri) != 0) return 0; localName = domGetLocalName (node->nodeName); if (strcmp (step->child->child->strvalue, localName)==0) return 1; return 0; } else if (step->child->type == IsNSElement) { nodeUri = domNamespaceURI (node); if (!nodeUri) return 0; if (nodeUri && (strcmp (step->child->strvalue, nodeUri)==0)) return 1; return 0; } else if (step->child->type == IsNSAttr) { if (node->nodeType != ATTRIBUTE_NODE || node->nodeFlags & IS_NS_NODE) return 0; nodeUri = domNamespaceURI (node); if (!nodeUri) return 0; if (strcmp (step->child->strvalue, nodeUri) != 0) return 0; if (strcmp (step->child->child->strvalue, "*")==0) return 1; localName = domGetLocalName (((domAttrNode *) node)->nodeName); if (strcmp (step->child->child->strvalue, localName)==0) return 1; return 0; } else if (step->child->type == IsNode) { DBG(fprintf(stderr, "nodeTest: nodeType=%d \n", node->nodeType);) return 1; } else if (step->child->type == IsText) { DBG(fprintf(stderr, "nodeTest: nodeType=%d == %d?? \n", node->nodeType, TEXT_NODE);) return (node->nodeType == TEXT_NODE); } else if (step->child->type == IsPI) { return (node->nodeType == PROCESSING_INSTRUCTION_NODE); } else if (step->child->type == IsSpecificPI) { return (node->nodeType == PROCESSING_INSTRUCTION_NODE && strncmp (((domProcessingInstructionNode*)node)->targetValue, step->child->strvalue, ((domProcessingInstructionNode*)node)->targetLength) == 0); } else if (step->child->type == IsComment) { return (node->nodeType == COMMENT_NODE); } return 1; } /*---------------------------------------------------------------------------- | xpathFuncBoolean | \---------------------------------------------------------------------------*/ int xpathFuncBoolean ( xpathResultSet *rs ) { switch (rs->type) { case BoolResult: return ( rs->intvalue ? 1 : 0 ); case IntResult: return ( rs->intvalue ? 1 : 0 ); case RealResult: return ((rs->realvalue != 0.0 ) && !IS_NAN (rs->realvalue)); case StringResult: return ( rs->string_len > 0 ); case xNodeSetResult: return ( rs->nr_nodes > 0 ); case InfResult: case NInfResult: return 1; /* NaNResult and EmptyResult are 'false' */ default: return 0; } } static double xpathStringToNumber ( char *str, int *NaN ) { int dotseen = 0; double d; char *pc, *tailptr; /* Just to use strtod() isn't sufficient for a few reasons: - strtod() accepts a leading - or +, but XPath allows only a leading - - strtod() accepts the string representation of a hexadecimal number, but XPath does not - strtod() accepts an optional exponent but XPath does not - strtod() accepts leading whitespace including \f and \v, but XPath doesn't allow this characters. Since this two characters are not legal XML characters, they can not be part of a DOM tree and therefore there isn't a problem with XPath expressions on DOM trees or in XSLT. But on Tcl level it's possible, to feed that characters literal into the XPath engine. */ *NaN = 0; pc = str; while (*pc && IS_XML_WHITESPACE(*pc)) pc++; if (!*pc) goto returnNaN; if (*pc == '-') { pc++; if (!*pc) goto returnNaN; } else if (*pc == '.') { dotseen = 1; pc++; if (!*pc) goto returnNaN; } if (!isdigit((unsigned char)*pc)) goto returnNaN; while (*pc) { if (isdigit((unsigned char)*pc)) { pc++; continue; } if (*pc == '.' && !dotseen) { dotseen = 1; pc++; continue; } break; } while (*pc && IS_XML_WHITESPACE(*pc)) pc++; if (*pc) goto returnNaN; /* If we are here str is a number string, as XPath expects it. Now we just use strtod(), to get the number */ d = strtod (str, &tailptr); if (d == 0.0 && tailptr == str) goto returnNaN; else if (IS_NAN(d)) goto returnNaN; return d; returnNaN: *NaN = 2; return strtod ("nan", &tailptr); } /*---------------------------------------------------------------------------- | xpathFuncNumber | \---------------------------------------------------------------------------*/ double xpathFuncNumber ( xpathResultSet *rs, int *NaN ) { double d; char *pc, *tailptr; *NaN = 0; switch (rs->type) { case BoolResult: return (rs->intvalue? 1.0 : 0.0); case IntResult: return (double)rs->intvalue; case RealResult: if (IS_NAN(rs->realvalue)) *NaN = 2; else if (IS_INF(rs->realvalue)!=0) *NaN = IS_INF(rs->realvalue); return rs->realvalue; case NaNResult: *NaN = 2; return 0.0; case InfResult: *NaN = 1; #ifdef INFINITY return INFINITY; #else # ifdef DBL_MAX return DBL_MAX; # else /* well, what? */ return 0.0 # endif #endif case NInfResult: *NaN = -1; #ifdef INFINITY return -INFINITY; #else # ifdef DBL_MAX return -DBL_MAX; # else /* well, what? */ return 0.0 # endif #endif case StringResult: return xpathStringToNumber(rs->string, NaN); case xNodeSetResult: pc = xpathFuncString(rs); d = xpathStringToNumber(pc, NaN); FREE(pc); return d; default: DBG(fprintf(stderr, "funcNumber: default: 0.0\n");) d = strtod ("nan", &tailptr); *NaN = 2; return d; } } /*---------------------------------------------------------------------------- | xpathGetStringValue | \---------------------------------------------------------------------------*/ static char * xpathGetStringValueForElement ( domNode *node, domLength *len ) { char *pc, *t; domLength l; domNode *child; if (node->nodeType == ELEMENT_NODE) { DBG(fprintf(stderr,"GetTextValue: tag='%s' \n", node->nodeName);) pc = MALLOC(1); *pc = '\0'; *len = 0; child = node->firstChild; while (child) { t = xpathGetStringValueForElement(child, &l); pc = (char*)REALLOC(pc, 1 + *len + l); memmove(pc + *len, t, l ); *len += l; pc[*len] = '\0'; FREE((char*)t); child = child->nextSibling; } } else if (node->nodeType == TEXT_NODE) { *len = ((domTextNode*)node)->valueLength; pc = (char*)MALLOC(1+*len); memmove(pc, ((domTextNode*)node)->nodeValue, *len); pc[*len] = '\0'; DBG(fprintf(stderr,"GetTextValue: text='%s' \n", pc);) } else { pc = tdomstrdup (""); *len = 0; } return pc; } char * xpathGetStringValue ( domNode *node, domLength *len ) { char *pc, *t; domLength l; domNode *child; domAttrNode *attr; if (node->nodeType == ELEMENT_NODE) { DBG(fprintf(stderr,"GetTextValue: tag='%s' \n", node->nodeName);) pc = MALLOC(1); *pc = '\0'; *len = 0; child = node->firstChild; while (child) { t = xpathGetStringValueForElement(child, &l); pc = (char*)REALLOC(pc, 1 + *len + l); memmove(pc + *len, t, l ); *len += l; pc[*len] = '\0'; FREE((char*)t); child = child->nextSibling; } } else if ((node->nodeType == TEXT_NODE) || (node->nodeType == CDATA_SECTION_NODE) || (node->nodeType == COMMENT_NODE) ) { *len = ((domTextNode*)node)->valueLength; pc = (char*)MALLOC(1+*len); memmove(pc, ((domTextNode*)node)->nodeValue, *len); pc[*len] = '\0'; DBG(fprintf(stderr,"GetTextValue: text='%s' \n", pc);) } else if (node->nodeType == PROCESSING_INSTRUCTION_NODE) { *len = ((domProcessingInstructionNode*)node)->dataLength; pc = (char*)MALLOC(1+*len); memmove(pc, ((domProcessingInstructionNode*)node)->dataValue, *len); pc[*len] = '\0'; } else if (node->nodeType == ATTRIBUTE_NODE) { attr = (domAttrNode*)node; DBG(fprintf(stderr,"GetTextValue: attr='%s' \n", attr->nodeName);) pc = MALLOC(attr->valueLength +1); memmove(pc, attr->nodeValue, attr->valueLength); *(pc + attr->valueLength) = '\0'; *len = attr->valueLength; } else { pc = tdomstrdup (""); *len = 0; } return pc; } /*---------------------------------------------------------------------------- | xpathFuncString | \---------------------------------------------------------------------------*/ char * xpathFuncString ( xpathResultSet *rs ) { char tmp[80], *pc; domLength len; switch (rs->type) { case BoolResult: if (rs->intvalue) return (tdomstrdup("true")); else return (tdomstrdup("false")); case IntResult: #if TCL_MAJOR_VERSION > 8 sprintf(tmp, "%" TCL_SIZE_MODIFIER "d", rs->intvalue); #else sprintf(tmp, "%ld", rs->intvalue); #endif return (tdomstrdup(tmp)); 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 = (domLength)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: return tdomstrdup ("NaN"); case InfResult: return tdomstrdup ("Infinity"); case NInfResult: return tdomstrdup ("-Infinity"); case StringResult: pc = MALLOC(rs->string_len +1); memmove(pc, rs->string, rs->string_len); *(pc + rs->string_len) = '\0'; return pc; case xNodeSetResult: if (rs->nr_nodes == 0) { pc = tdomstrdup (""); } else { pc = xpathGetStringValue (rs->nodes[0], &len); } return pc; default: return (tdomstrdup ("")); } } /*---------------------------------------------------------------------------- | xpathFuncStringForNode | \---------------------------------------------------------------------------*/ char * xpathFuncStringForNode ( domNode *node ) { domLength len; return xpathGetStringValue (node, &len); } /*---------------------------------------------------------------------------- | xpathArity | \---------------------------------------------------------------------------*/ static int xpathArity ( ast step ) { int parms = 0; step = step->child; while (step) { parms++; step = step->next; } return parms; } /*---------------------------------------------------------------------------- | xpathArityCheck | \---------------------------------------------------------------------------*/ static int xpathArityCheck ( ast step, int arity, char **errMsg ) { int parms = 0; step = step->child; while (step) { parms++; step = step->next; } if (arity!=parms) { *errMsg = tdomstrdup("wrong number of parameters!"); return 1; } return 0; } #define XPATH_ARITYCHECK(s,a,m) if (xpathArityCheck(s,a,m)) return XPATH_EVAL_ERR /*---------------------------------------------------------------------------- | xpathRound | \---------------------------------------------------------------------------*/ domLength xpathRound (double r) { if (r < 0.0) { return (domLength)floor (r + 0.5); } else { return (domLength)(r + 0.5); } } /*---------------------------------------------------------------------------- | idSplitAndAdd | \---------------------------------------------------------------------------*/ static void idSplitAndAdd ( char *idStr, Tcl_HashTable *ids, xpathResultSet *result ) { int pwhite; char *pfrom, *pto; Tcl_HashEntry *entryPtr; domNode *node; pwhite = 0; pfrom = pto = idStr; while (*pto) { switch (*pto) { case ' ' : case '\n': case '\r': case '\t': if (pwhite) { pto++; continue; } *pto = '\0'; entryPtr = Tcl_FindHashEntry (ids, pfrom); if (entryPtr) { node = (domNode*) Tcl_GetHashValue (entryPtr); /* Don't report nodes out of the fragment list */ if (node->parentNode != NULL || (node == node->ownerDocument->documentElement)) { rsAddNode (result, node); } } pwhite = 1; pto++; continue; default: if (pwhite) { pfrom = pto; pwhite = 0; } pto++; } } if (!pwhite) { entryPtr = Tcl_FindHashEntry (ids, pfrom); if (entryPtr) { node = (domNode*) Tcl_GetHashValue (entryPtr); /* Don't report nodes out of the fragment list */ if (node->parentNode != NULL || (node == node->ownerDocument->documentElement)) { rsAddNode (result, node); } } } } /*---------------------------------------------------------------------------- | xpathEvalFunction | \---------------------------------------------------------------------------*/ static int xpathEvalFunction ( ast step, domNode *ctxNode, domNode *exprContext, domLength position, xpathResultSet *nodeList, xpathCBs *cbs, xpathResultSet *result, int *docOrder, char **errMsg ) { xpathResultSet leftResult, rightResult, replaceResult; int rc, pwhite, NaN, attrcount, argc, savedDocOrder, found, utfCharLen, untilEnd, left = 0; domLength len, lenstr, fromlen, i, j, from; char *replaceStr, *pfrom, *pto, tmp[80], tmp1[80], *leftStr = NULL, *rightStr = NULL, utfBuf[TCL_UTF_MAX]; domNode *node; domAttrNode *attr; double leftReal, dRight = 0.0; ast nextStep; xpathResultSets *args; xpathResultSet *arg; Tcl_HashTable *ids; Tcl_HashEntry *entryPtr; const char *str; Tcl_DString dStr, tstr, tfrom, tto, tresult; Tcl_UniChar *ufStr, *upfrom, unichar; switch (step->intvalue) { case f_position: XPATH_ARITYCHECK(step,0,errMsg); if (*docOrder) { rsSetLong (result, position+1); } else { rsSetLong (result, nodeList->nr_nodes - position); } break; case f_last: XPATH_ARITYCHECK(step,0,errMsg); rsSetLong (result, nodeList->nr_nodes); break; case f_number: xpathRSInit (&leftResult); if (xpathArity(step) == 0) { /* no parameter, the context node is the nodeset to * operate with */ rsAddNodeFast( &leftResult, ctxNode); } else { XPATH_ARITYCHECK(step,1,errMsg); xpathRSInit (&leftResult); rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); if (rc) { xpathRSFree( &leftResult ); return rc; } } leftReal = xpathFuncNumber(&leftResult, &NaN); if (NaN) { if (NaN == 2) rsSetNaN (result); else if (NaN == 1) rsSetInf (result); else rsSetNInf (result); } else { rsSetReal (result, leftReal); } xpathRSFree( &leftResult ); break; case f_floor: case f_ceiling: case f_round: XPATH_ARITYCHECK(step,1,errMsg); xpathRSInit (&leftResult); rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); if (rc) { xpathRSFree( &leftResult ); return rc; } leftReal = xpathFuncNumber(&leftResult, &NaN); if (NaN) { if (NaN == 2) rsSetNaN (result); else if (NaN == 1) rsSetInf (result); else rsSetNInf (result); } else { if (step->intvalue == f_floor) leftReal = floor(leftReal); else if (step->intvalue == f_ceiling) leftReal = ceil(leftReal); else leftReal = (double)xpathRound(leftReal); rsSetReal2 (result, leftReal); } xpathRSFree( &leftResult ); break; case f_boolean: XPATH_ARITYCHECK(step,1,errMsg); xpathRSInit (&leftResult); rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); if (rc) { xpathRSFree( &leftResult ); return rc; } left = xpathFuncBoolean(&leftResult); rsSetBool (result, left); xpathRSFree( &leftResult ); break; case f_string: case f_normalizeSpace: case f_stringLength: case f_laststring: xpathRSInit (&leftResult); if (step->child == NULL) { /* no parameter, the context node is the nodeset to * operate with */ rsAddNodeFast( &leftResult, ctxNode); } else { XPATH_ARITYCHECK(step,1,errMsg); xpathRSInit (&leftResult); rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); if (rc) { xpathRSFree( &leftResult ); return rc; } DBG(fprintf(stderr, "normalize-space: \n"); rsPrint(&leftResult); ) } if (step->intvalue == f_laststring) { if (leftResult.type == xNodeSetResult) { if (leftResult.nr_nodes == 0) { leftStr = tdomstrdup (""); } else { leftStr = xpathGetStringValue ( leftResult.nodes[leftResult.nr_nodes-1], &len); } } else { leftStr = xpathFuncString (&leftResult ); } } else { leftStr = xpathFuncString (&leftResult ); } xpathRSFree( &leftResult ); DBG(fprintf(stderr, "leftStr='%s'\n", leftStr);) if (step->intvalue == f_string) rsSetString (result, leftStr); else if (step->intvalue == f_stringLength) { pto = leftStr; len = 0; while (*pto) { len++; i = UTF8_CHAR_LEN (*pto); if (!i) { FREE (leftStr); *errMsg = tdomstrdup("Can only handle UTF-8 chars up " "to 4 bytes length"); return XPATH_I18N_ERR; } pto += i; } rsSetLong (result, len); } else { pwhite = 1; pfrom = pto = leftStr; while (*pfrom) { switch (*pfrom) { case ' ' : case '\n': case '\r': case '\t': if (!pwhite) { *pto++ = ' '; pwhite = 1; } break; default: *pto++ = *pfrom; pwhite = 0; break; } pfrom++; } if ((pto > leftStr) && (*(pto-1) == ' ')) { pto--; /* cut last empty space */ } *pto = '\0'; rsSetString (result, leftStr); } FREE(leftStr); break; case f_not: XPATH_ARITYCHECK(step,1,errMsg); xpathRSInit (&leftResult); rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); if (rc) { xpathRSFree (&leftResult); return rc; } left = xpathFuncBoolean(&leftResult); xpathRSFree (&leftResult); rsSetBool (result, !left); break; case f_true: XPATH_ARITYCHECK(step,0,errMsg); rsSetBool (result, 1); break; case f_false: XPATH_ARITYCHECK(step,0,errMsg); rsSetBool (result, 0); break; case f_id: XPATH_ARITYCHECK(step,1,errMsg); if (ctxNode->nodeType == ATTRIBUTE_NODE) { ids = ((domAttrNode*)ctxNode)->parentNode->ownerDocument->ids; } else { ids = ctxNode->ownerDocument->ids; } if (!ids) { break; } xpathRSInit (&leftResult); rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); if (rc) { xpathRSFree( &leftResult ); return rc; } DBG(fprintf(stderr, "id: \n"); rsPrint(&leftResult); ) if (leftResult.type == EmptyResult) { xpathRSFree (&leftResult); return XPATH_OK; } if (leftResult.type == xNodeSetResult) { for (i=0; i < leftResult.nr_nodes; i++) { leftStr = xpathFuncStringForNode (leftResult.nodes[i]); idSplitAndAdd (leftStr, ids, result); FREE(leftStr); } } else { leftStr = xpathFuncString (&leftResult); idSplitAndAdd (leftStr, ids, result); FREE(leftStr); } sortByDocOrder (result); xpathRSFree (&leftResult); break; case f_sum: XPATH_ARITYCHECK(step,1,errMsg); xpathRSInit (&leftResult); rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); if (rc) { xpathRSFree( &leftResult ); return rc; } if (leftResult.type != xNodeSetResult) { if (leftResult.type == EmptyResult) { rsSetLong (result, 0); return XPATH_OK; } else { xpathRSFree( &leftResult ); *errMsg = tdomstrdup("sum() requires a node set!"); xpathRSFree( &leftResult ); return XPATH_EVAL_ERR; } } xpathRSInit(&rightResult); rightResult.nr_nodes = 1; rightResult.type = leftResult.type; leftReal = 0.0; for (i=0; ichild, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); if (rc) { xpathRSFree (&leftResult); return rc; } leftStr = xpathFuncString (&leftResult); if (ctxNode->nodeType != ELEMENT_NODE) { if (ctxNode->nodeType == ATTRIBUTE_NODE) { node = ((domAttrNode*)ctxNode)->parentNode; } else { node = ctxNode->parentNode; } } else { node = ctxNode; } while (node) { attr = node->firstAttr; while (attr) { if (strcmp (attr->nodeName, "xml:lang")!=0) { attr = attr->nextSibling; continue; } tcldom_tolower (attr->nodeValue, tmp, 80); tcldom_tolower (leftStr, tmp1, 80); if (strcmp (tmp, tmp1)==0) { rsSetBool (result, 1); FREE(leftStr); xpathRSFree (&leftResult); return XPATH_OK; } else { pfrom = tmp; i = 0; while (*pfrom && i < 79) { if (*pfrom == '-') { *pfrom = '\0'; break; } pfrom++; i++; } if (strcmp (tmp, tmp1)==0) { rsSetBool (result, 1); FREE(leftStr); xpathRSFree (&leftResult); return XPATH_OK; } else { rsSetBool (result, 0); FREE(leftStr); xpathRSFree (&leftResult); return XPATH_OK; } } } node = node->parentNode; } rsSetBool (result, 0); FREE(leftStr); xpathRSFree (&leftResult); break; case f_startsWith: case f_contains: case f_substringBefore: case f_substringAfter: XPATH_ARITYCHECK(step,2,errMsg); xpathRSInit (&leftResult); xpathRSInit (&rightResult); savedDocOrder = *docOrder; rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); CHECK_RC; *docOrder = savedDocOrder; rc = xpathEvalStep( step->child->next, ctxNode, exprContext, position, nodeList, cbs, &rightResult, docOrder, errMsg); CHECK_RC; *docOrder = savedDocOrder; DBG(fprintf(stderr, "\nsubstring-* left,right:\n"); rsPrint(&leftResult); rsPrint(&rightResult); ) leftStr = xpathFuncString( &leftResult ); rightStr = xpathFuncString( &rightResult ); DBG(fprintf(stderr, "substring-* '%s' '%s' \n", leftStr, rightStr);) if (step->intvalue == f_contains) { if (strstr(leftStr, rightStr) != NULL) { rsSetBool (result, 1); } else { rsSetBool (result, 0); } } else if (step->intvalue == f_substringBefore) { pfrom = strstr(leftStr, rightStr); if (pfrom != NULL) { DBG(fprintf(stderr, "substring-before '%s' '%s' : ", leftStr, rightStr);) *pfrom = '\0'; DBG(fprintf(stderr, "'%s' \n", leftStr);) rsSetString (result, leftStr); } else { rsSetString (result, ""); } } else if (step->intvalue == f_substringAfter) { pfrom = strstr(leftStr, rightStr); if (pfrom != NULL) { rsSetString (result, pfrom + strlen (rightStr)); } else { rsSetString (result, ""); } } else { /* starts-with */ i = (domLength)strlen(rightStr); if(strncmp(leftStr, rightStr, i)==0) { rsSetBool (result, 1); } else { rsSetBool (result, 0); } } xpathRSFree (&leftResult); xpathRSFree (&rightResult); FREE(rightStr); FREE(leftStr); break; case f_concat: if (xpathArity(step) < 2) { *errMsg = tdomstrdup("wrong number of parameters!"); return XPATH_EVAL_ERR; } nextStep = step->child; pto = MALLOC(1); *pto = '\0'; len = 0; while (nextStep) { xpathRSInit (&leftResult); savedDocOrder = *docOrder; rc = xpathEvalStep( nextStep, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); if (rc) { FREE (pto); return rc; } *docOrder = savedDocOrder; leftStr = xpathFuncString( &leftResult ); pto = (char*)REALLOC(pto, 1+len+strlen(leftStr)); memmove(pto + len, leftStr, strlen(leftStr)); len += (domLength)strlen(leftStr); *(pto + len) = '\0'; xpathRSFree( &leftResult ); FREE(leftStr); nextStep = nextStep->next; } rsSetString (result, pto); FREE(pto); break; case f_substring: i = xpathArity(step); if (i != 2 && i != 3) { *errMsg = tdomstrdup("wrong number of parameters!"); return XPATH_EVAL_ERR; } xpathRSInit (&leftResult); savedDocOrder = *docOrder; rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); CHECK_RC; *docOrder = savedDocOrder; xpathRSInit (&rightResult); rc = xpathEvalStep( step->child->next, ctxNode, exprContext, position, nodeList, cbs, &rightResult, docOrder, errMsg); CHECK_RC; *docOrder = savedDocOrder; leftStr = xpathFuncString( &leftResult ); xpathRSFree (&leftResult); from = xpathRound(xpathFuncNumber(&rightResult, &NaN))-1; xpathRSFree( &rightResult ); if (NaN) { FREE(leftStr); rsSetString (result, ""); return XPATH_OK; } if (step->child->next->next) { untilEnd = 0; xpathRSInit (&rightResult); savedDocOrder = *docOrder; rc = xpathEvalStep( step->child->next->next, ctxNode, exprContext, position, nodeList, cbs, &rightResult, docOrder, errMsg); CHECK_RC; *docOrder = savedDocOrder; dRight = xpathFuncNumber (&rightResult, &NaN); len = xpathRound(dRight); xpathRSFree (&rightResult); if (NaN) { if (NaN == 1) { untilEnd = 1; } else { FREE(leftStr); rsSetString (result, ""); return XPATH_OK; } } xpathRSFree (&rightResult); if (from < 0) { len = len + from; if (len <= 0) { FREE(leftStr); rsSetString (result, ""); return XPATH_OK; } from = 0; } } else { if (from < 0) from = 0; untilEnd = 1; } pfrom = leftStr; while (*pfrom && (from > 0)) { i = UTF8_CHAR_LEN (*pfrom); if (!i) { FREE (leftStr); *errMsg = tdomstrdup("Can only handle UTF-8 chars up " "to 4 bytes length"); return XPATH_I18N_ERR; } pfrom += i; from--; } if (!untilEnd) { pto = pfrom; while (*pto && (len > 0)) { i = UTF8_CHAR_LEN (*pto); if (!i) { FREE (leftStr); *errMsg = tdomstrdup("Can only handle UTF-8 chars up " "to 4 bytes length"); return XPATH_I18N_ERR; } pto += i; len--; } *pto = '\0'; } rsSetString (result, pfrom); FREE(leftStr); break; case f_translate: XPATH_ARITYCHECK(step,3,errMsg); xpathRSInit (&leftResult); savedDocOrder = *docOrder; rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); CHECK_RC; *docOrder = savedDocOrder; xpathRSInit (&rightResult); rc = xpathEvalStep( step->child->next, ctxNode, exprContext, position, nodeList, cbs, &rightResult, docOrder, errMsg); CHECK_RC; *docOrder = savedDocOrder; xpathRSInit (&replaceResult); rc = xpathEvalStep( step->child->next->next, ctxNode, exprContext, position, nodeList, cbs, &replaceResult, docOrder, errMsg); CHECK_RC; *docOrder = savedDocOrder; leftStr = xpathFuncString( &leftResult ); rightStr = xpathFuncString( &rightResult ); replaceStr = xpathFuncString( &replaceResult ); Tcl_DStringInit (&tstr); Tcl_DStringInit (&tfrom); Tcl_DStringInit (&tto); Tcl_DStringInit (&tresult); Tcl_UtfToUniCharDString (leftStr, -1, &tstr); Tcl_UtfToUniCharDString (rightStr, -1, &tfrom); Tcl_UtfToUniCharDString (replaceStr, -1, &tto); lenstr = Tcl_DStringLength (&tstr) / sizeof (Tcl_UniChar); fromlen = Tcl_DStringLength (&tfrom) / sizeof (Tcl_UniChar); len = Tcl_DStringLength (&tto) / sizeof (Tcl_UniChar); upfrom = (Tcl_UniChar *)Tcl_DStringValue (&tstr); for (i = 0; i < lenstr; i++) { found = 0; ufStr = (Tcl_UniChar *)Tcl_DStringValue (&tfrom); for (j = 0; j < fromlen; j++) { if (*ufStr == *upfrom) { found = 1; break; } ufStr++; } if (found) { if (j < len) { unichar = Tcl_UniCharAtIndex (replaceStr, j); utfCharLen = (int)Tcl_UniCharToUtf (unichar, utfBuf); Tcl_DStringAppend (&tresult, utfBuf, utfCharLen); } } else { utfCharLen = (int)Tcl_UniCharToUtf (*upfrom, utfBuf); Tcl_DStringAppend (&tresult, utfBuf, utfCharLen); } upfrom++; } rsSetString (result, Tcl_DStringValue (&tresult)); Tcl_DStringFree (&tstr); Tcl_DStringFree (&tfrom); Tcl_DStringFree (&tto); Tcl_DStringFree (&tresult); xpathRSFree( &replaceResult ); xpathRSFree( &rightResult ); xpathRSFree( &leftResult ); FREE(leftStr); FREE(rightStr); FREE(replaceStr); break; case f_count: XPATH_ARITYCHECK(step,1,errMsg); xpathRSInit (&leftResult); rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); if (rc) { xpathRSFree( &leftResult ); return rc; } if (leftResult.type == EmptyResult) { rsSetLong (result, 0); return XPATH_OK; } if (leftResult.type != xNodeSetResult) { *errMsg = tdomstrdup("count() requires a node set!"); xpathRSFree( &leftResult ); return XPATH_EVAL_ERR; } rsSetLong (result, leftResult.nr_nodes); xpathRSFree (&leftResult); break; case f_unparsedEntityUri: XPATH_ARITYCHECK(step,1,errMsg); if (!ctxNode->ownerDocument->unparsedEntities) { break; } xpathRSInit (&leftResult); rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); if (rc) { xpathRSFree( &leftResult ); return rc; } leftStr = xpathFuncString (&leftResult); entryPtr = Tcl_FindHashEntry (ctxNode->ownerDocument->unparsedEntities, leftStr); if (entryPtr) { rsSetString (result, (char *)Tcl_GetHashValue (entryPtr)); } else { rsSetString (result, ""); } FREE(leftStr); xpathRSFree (&leftResult); break; case f_localName: case f_name: case f_namespaceUri: case f_generateId: xpathRSInit (&leftResult); if (step->child == NULL) { /* no parameter, the context node is the nodeset to * operate with */ rsAddNodeFast( &leftResult, ctxNode); } else { XPATH_ARITYCHECK(step,1,errMsg); xpathRSInit (&leftResult); rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); if (rc) { xpathRSFree( &leftResult ); return rc; } } if (leftResult.type == EmptyResult) { rsSetString (result, ""); return XPATH_OK; } if (step->intvalue == f_generateId) { if (leftResult.type != xNodeSetResult) { *errMsg = tdomstrdup("generate-id() requires a nodeset or no argument!"); xpathRSFree (&leftResult); return XPATH_EVAL_ERR; } if (leftResult.nodes[0]->nodeType == ATTRIBUTE_NODE) { node = ((domAttrNode*)leftResult.nodes[0])->parentNode; attrcount = 0; attr = node->firstAttr; while (attr) { if ((domNode*)attr == leftResult.nodes[0]) break; attr = attr->nextSibling; attrcount++; } sprintf(tmp,"id%p-%d", (void *)node, attrcount); } else { sprintf(tmp,"id%p", (void *)leftResult.nodes[0]); } rsSetString (result, tmp); } else if (step->intvalue == f_namespaceUri) { if (leftResult.type != xNodeSetResult) { *errMsg = tdomstrdup("namespace-uri() requires a node set!"); xpathRSFree( &leftResult ); return XPATH_EVAL_ERR; } if ( (leftResult.nr_nodes <= 0) || ( leftResult.nodes[0]->nodeType != ELEMENT_NODE && leftResult.nodes[0]->nodeType != ATTRIBUTE_NODE ) ) { rsSetString (result, ""); } else { rsSetString (result, domNamespaceURI(leftResult.nodes[0])); } } else if (step->intvalue == f_localName) { if (leftResult.type != xNodeSetResult) { *errMsg = tdomstrdup("local-name() requires a node set!"); xpathRSFree( &leftResult ); return XPATH_EVAL_ERR; } if (leftResult.nodes[0]->nodeType == ELEMENT_NODE) { if (leftResult.nodes[0] == leftResult.nodes[0]->ownerDocument->rootNode) { rsSetString (result, ""); } else { rsSetString (result, domGetLocalName(leftResult.nodes[0]->nodeName)); } } else if (leftResult.nodes[0]->nodeType == ATTRIBUTE_NODE) { str = domGetLocalName(((domAttrNode*)leftResult.nodes[0])->nodeName); if (str[0] == 'x' && strcmp(str, "xmlns")==0) { rsSetString (result, ""); } else { rsSetString (result, str); } } else if (leftResult.nodes[0]->nodeType == PROCESSING_INSTRUCTION_NODE) { if (((domProcessingInstructionNode*)leftResult.nodes[0])->targetLength > 79) { memmove(tmp, ((domProcessingInstructionNode*)leftResult.nodes[0])->targetValue, 79); tmp[79]= '\0'; } else { memmove(tmp, ((domProcessingInstructionNode*)leftResult.nodes[0])->targetValue, ((domProcessingInstructionNode*)leftResult.nodes[0])->targetLength); tmp[((domProcessingInstructionNode*)leftResult.nodes[0])->targetLength] = '\0'; } rsSetString (result, tmp); } else { rsSetString (result, ""); } } else if (step->intvalue == f_name) { if ( leftResult.type != xNodeSetResult ) { *errMsg = tdomstrdup("name() requires a node set!"); xpathRSFree( &leftResult ); return XPATH_EVAL_ERR; } if (leftResult.nodes[0]->nodeType == ELEMENT_NODE) { if (leftResult.nodes[0] == leftResult.nodes[0]->ownerDocument->rootNode) { rsSetString (result, ""); } else { rsSetString (result, leftResult.nodes[0]->nodeName); } } else if (leftResult.nodes[0]->nodeType == ATTRIBUTE_NODE) { if (leftResult.nodes[0]->nodeFlags & IS_NS_NODE) { if (((domAttrNode *)leftResult.nodes[0])->nodeName[5] == '\0') { rsSetString (result, ""); } else { rsSetString (result, &((domAttrNode*)leftResult.nodes[0])->nodeName[6]); } } else { rsSetString (result, ((domAttrNode*)leftResult.nodes[0])->nodeName ); } } else if (leftResult.nodes[0]->nodeType == PROCESSING_INSTRUCTION_NODE) { if (((domProcessingInstructionNode*)leftResult.nodes[0])->targetLength > 79) { memmove(tmp, ((domProcessingInstructionNode*)leftResult.nodes[0])->targetValue, 79); tmp[79]= '\0'; } else { memmove(tmp, ((domProcessingInstructionNode*)leftResult.nodes[0])->targetValue, ((domProcessingInstructionNode*)leftResult.nodes[0])->targetLength); tmp[((domProcessingInstructionNode*)leftResult.nodes[0])->targetLength] = '\0'; } rsSetString (result, tmp); } else { rsSetString (result, ""); } } xpathRSFree( &leftResult ); break; case f_fqfunction: Tcl_DStringInit (&dStr); if (cbs->funcCB == NULL) { Tcl_DStringAppend (&dStr, "Unknown function ", -1); } Tcl_DStringAppend (&dStr, step->strvalue, -1); Tcl_DStringAppend (&dStr, "::", 2); nextStep = step->child; Tcl_DStringAppend (&dStr, nextStep->strvalue, -1); if (cbs->funcCB == NULL) { *errMsg = tdomstrdup (Tcl_DStringValue (&dStr)); Tcl_DStringFree (&dStr); return XPATH_EVAL_ERR; } /* fall through */ default: if (cbs->funcCB == NULL) { if (strlen(step->strvalue)>50) *(step->strvalue + 50) = '\0'; sprintf(tmp, "Unknown function '%s'!", step->strvalue); *errMsg = tdomstrdup(tmp); return XPATH_EVAL_ERR; } /* count number of arguments (to be able to allocate later) */ argc = 0; if (step->intvalue == f_fqfunction) { nextStep = step->child->next; } else { nextStep = step->child; } while (nextStep) { argc++; nextStep = nextStep->next; } args = (xpathResultSets*)MALLOC((argc+1) * sizeof(xpathResultSets)); args[0] = NULL; argc = 0; if (step->intvalue == f_fqfunction) { nextStep = step->child->next; } else { nextStep = step->child; } savedDocOrder = *docOrder; while (nextStep) { arg = (xpathResultSet*)MALLOC(sizeof(xpathResultSet)); args[argc++] = arg; args[argc] = NULL; xpathRSInit (arg); rc = xpathEvalStep( nextStep, ctxNode, exprContext, position, nodeList, cbs, arg, docOrder, errMsg); if (rc) goto unknownfunccleanup; *docOrder = savedDocOrder; nextStep = nextStep->next; } if (step->intvalue == f_fqfunction) { rc = (cbs->funcCB) (cbs->funcClientData, Tcl_DStringValue (&dStr), ctxNode, position, nodeList, exprContext, argc, args, result, errMsg); } else { rc = (cbs->funcCB) (cbs->funcClientData, step->strvalue, ctxNode, position, nodeList, exprContext, argc, args, result, errMsg); } unknownfunccleanup: argc = 0; while ( args[argc] != NULL) { xpathRSFree( args[argc] ); FREE((char*)args[argc++]); } FREE((char*)args); if (step->intvalue == f_fqfunction) { Tcl_DStringFree (&dStr); } return rc; } return XPATH_OK; } /*---------------------------------------------------------------------------- | xpathEvalStep | \---------------------------------------------------------------------------*/ static int xpathEvalStep ( ast step, domNode *ctxNode, domNode *exprContext, domLength position, xpathResultSet *nodeList, xpathCBs *cbs, xpathResultSet *result, int *docOrder, char **errMsg ) { xpathResultSet leftResult, rightResult; xpathResultSet *pleftResult, *prightResult, tResult; int rc, res, NaN, NaN1, switchResult; domLength i, j, k, count = 0; domNode *node, *child, *startingNode, *ancestor; domAttrNode *attr; int savedDocOrder, predLimit; int left = 0, right = 0, useFastAdd; double dLeft = 0.0, dRight = 0.0, dTmp; char *leftStr = NULL, *rightStr = NULL; astType savedAstType; if (result->type == EmptyResult) useFastAdd = 1; else useFastAdd = 0; switch (step->type) { case AxisChild: DBG(fprintf(stderr, "AxisChild ctxNode->nodeType = %d \n", ctxNode->nodeType);) *docOrder = 1; if (ctxNode->nodeType != ELEMENT_NODE) return XPATH_OK; DBG(fprintf(stderr, "AxisChild: scanning \n");) child = ctxNode->firstChild; if (step->intvalue) { while (child && (count < step->intvalue)) { DBG(fprintf(stderr, "AxisChild: child '%s' domNode%p \n", child->nodeName, child);) if (xpathNodeTest(child, step)) { DBG(fprintf(stderr, "AxisChild: after node taking child '%s' domNode%p \n", child->nodeName, child);) checkRsAddNode( result, child); count++; } child = child->nextSibling; } } else { while (child) { DBG(fprintf(stderr, "AxisChild: child '%s' domNode%p \n", child->nodeName, child);) if (xpathNodeTest(child, step)) { DBG(fprintf(stderr, "AxisChild: after node taking child '%s' domNode%p \n", child->nodeName, child);) checkRsAddNode( result, child); } child = child->nextSibling; } } DBG( fprintf(stderr,"AxisChild result:\n"); rsPrint(result); ) break; case SlashSlash: xpathRSInit (&tResult); node = ctxNode->firstChild; while (node) { if (node->nodeType == ELEMENT_NODE) { rc = xpathEvalStep (step, node, exprContext, position, nodeList, cbs, result, docOrder, errMsg); if (rc) { xpathRSFree (&tResult); return rc; } } if (xpathNodeTest(node, step)) { rsAddNodeFast( &tResult, node); } node = node->nextSibling; } rc = xpathEvalPredicate (step->next, exprContext, result, &tResult, cbs, docOrder, errMsg); xpathRSFree (&tResult); CHECK_RC; break; case AxisDescendant: case AxisDescendantOrSelf: if (step->next && step->next->type == Pred) { *docOrder = 1; if (ctxNode->nodeType == ATTRIBUTE_NODE && step->type == AxisDescendantOrSelf) { if (xpathNodeTest(ctxNode, step)) { checkRsAddNode( result, ctxNode); } break; } if (ctxNode->nodeType != ELEMENT_NODE) return XPATH_OK; if (step->type == AxisDescendantOrSelf) { if (xpathNodeTest(ctxNode, step)) { xpathRSInit (&tResult); rsAddNodeFast( &tResult, ctxNode); rc = xpathEvalPredicate (step->next, exprContext, result, &tResult, cbs, docOrder, errMsg); xpathRSFree (&tResult); CHECK_RC; } } savedAstType = step->type; step->type = SlashSlash; rc = xpathEvalStep (step, ctxNode, exprContext, position, nodeList, cbs, result, docOrder, errMsg); step->type = savedAstType; CHECK_RC; break; } /* without following Pred step, // is the same as AxisDescendantOrSelf */ /* fall through */ case AxisDescendantLit: case AxisDescendantOrSelfLit: *docOrder = 1; if (step->intvalue && (step->type == AxisDescendantLit || step->type == AxisDescendantOrSelfLit)) predLimit = 1; else predLimit = 0; if (ctxNode->nodeType == ATTRIBUTE_NODE && (step->type == AxisDescendantOrSelf || step->type == AxisDescendantOrSelfLit)) { if (xpathNodeTest(ctxNode, step)) { checkRsAddNode( result, ctxNode); } break; } if (ctxNode->nodeType != ELEMENT_NODE) return XPATH_OK; if (step->type == AxisDescendantOrSelf || step->type == AxisDescendantOrSelfLit) { if (xpathNodeTest(ctxNode, step)) { checkRsAddNode( result, ctxNode); if (predLimit) { count++; } } } startingNode = ctxNode; node = ctxNode->firstChild; while (node && node != startingNode) { if (xpathNodeTest(node, step)) { checkRsAddNode( result, node); if (predLimit) { count++; if (count >= step->intvalue) break; } } if ((node->nodeType == ELEMENT_NODE) && (node->firstChild)) { node = node->firstChild; continue; } if (node->nextSibling) { node = node->nextSibling; continue; } while ( node->parentNode && (node->parentNode != startingNode) && (node->parentNode->nextSibling == NULL) ) { node = node->parentNode; } if ((node != startingNode) && (node->parentNode) && (node->parentNode != startingNode) ) { node = node->parentNode->nextSibling; } else { break; } } break; case AxisSelf: *docOrder = 1; DBG(fprintf(stderr, "AxisSelf :: \n");) if (xpathNodeTest(ctxNode, step)) { rsAddNode( result, ctxNode); } break; case GetContextNode: rsAddNode( result, ctxNode); break; case AxisAttribute: *docOrder = 1; DBG(fprintf(stderr, "AxisAttribute %s \n", step->child->strvalue);) if (ctxNode->nodeType != ELEMENT_NODE) return XPATH_OK; if (step->child->type == IsElement) { step->child->type = IsAttr; } if (step->child->type == IsAttr) { if (strcmp(step->child->strvalue, "*")==0) { attr = ctxNode->firstAttr; while (attr) { if (!(attr->nodeFlags & IS_NS_NODE)) { checkRsAddNode (result, (domNode *)attr); } attr = attr->nextSibling; } } else { attr = ctxNode->firstAttr; while (attr && (attr->nodeFlags & IS_NS_NODE)) attr = attr->nextSibling; while (attr) { if (xpathNodeTest( (domNode*)attr, step)) { checkRsAddNode (result, (domNode *)attr); } attr = attr->nextSibling; } } } else if (step->child->type == IsNSAttr) { attr = ctxNode->firstAttr; while (attr && (attr->nodeFlags & IS_NS_NODE)) attr = attr->nextSibling; while (attr) { if (xpathNodeTest ( (domNode*)attr, step)) { checkRsAddNode (result, (domNode *)attr); } attr = attr->nextSibling; } } break; case AxisParent: *docOrder = 1; if (ctxNode->nodeType == ATTRIBUTE_NODE) { if (xpathNodeTest(((domAttrNode *)ctxNode)->parentNode, step)) { rsAddNode(result,((domAttrNode *)ctxNode)->parentNode); } } else { if (ctxNode->parentNode) { if (xpathNodeTest(ctxNode->parentNode, step)) { rsAddNode(result,ctxNode->parentNode); } } else { if (ctxNode->ownerDocument->rootNode != ctxNode && xpathNodeTest (ctxNode->ownerDocument->rootNode, step)) { rsAddNode (result, ctxNode->ownerDocument->rootNode); } } } break; case GetParentNode: if (ctxNode->nodeType == ATTRIBUTE_NODE) { rsAddNode(result,((domAttrNode*)ctxNode)->parentNode); } else { if (ctxNode->parentNode) { rsAddNode(result,ctxNode->parentNode); } else { if (ctxNode != ctxNode->ownerDocument->rootNode) { rsAddNode (result, ctxNode->ownerDocument->rootNode); } } } break; case AxisAncestor: case AxisAncestorOrSelf: *docOrder = 0; xpathRSInit (&tResult); if (step->type == AxisAncestorOrSelf) { if (xpathNodeTest(ctxNode, step)) { rsAddNodeFast(&tResult, ctxNode); } } if (ctxNode->nodeType == ATTRIBUTE_NODE) { ctxNode = ((domAttrNode *)ctxNode)->parentNode; if (xpathNodeTest(ctxNode, step)) { rsAddNodeFast(&tResult, ctxNode); } } startingNode = ctxNode; while (ctxNode->parentNode) { ctxNode = ctxNode->parentNode; if (xpathNodeTest(ctxNode, step)) { rsAddNodeFast(&tResult, ctxNode); } } if (startingNode != ctxNode->ownerDocument->rootNode) { if (xpathNodeTest (ctxNode->ownerDocument->rootNode, step)) { rsAddNodeFast (&tResult, ctxNode->ownerDocument->rootNode); } } for (i = tResult.nr_nodes - 1; i >= 0; i--) { checkRsAddNode (result, tResult.nodes[i]); } xpathRSFree (&tResult); break; case AxisFollowingSibling: *docOrder = 1; if (ctxNode->nodeType == ATTRIBUTE_NODE) { return XPATH_OK; } if (step->intvalue) { while (ctxNode->nextSibling && (count < step->intvalue)) { ctxNode = ctxNode->nextSibling; if (xpathNodeTest(ctxNode, step)) { checkRsAddNode(result, ctxNode); count++; } } } else { while (ctxNode->nextSibling) { ctxNode = ctxNode->nextSibling; if (xpathNodeTest(ctxNode, step)) { checkRsAddNode(result, ctxNode); } } } break; case AxisPrecedingSibling: *docOrder = 0; if (ctxNode->nodeType == ATTRIBUTE_NODE) { return XPATH_OK; } if (step->intvalue) { node = ctxNode->previousSibling; xpathRSInit (&tResult); while (node && (count < step->intvalue)) { if (xpathNodeTest (node, step)) { rsAddNodeFast (&tResult, node); count++; } node = node->previousSibling; } for (i = tResult.nr_nodes -1; i >= 0; i--) { checkRsAddNode (result, tResult.nodes[i]); } xpathRSFree (&tResult); } else { startingNode = ctxNode; if (startingNode->parentNode) { node = (startingNode->parentNode)->firstChild; } else { if (ctxNode == ctxNode->ownerDocument->rootNode) return XPATH_OK; node = startingNode->ownerDocument->rootNode->firstChild; } while (node && (node != startingNode)) { if (xpathNodeTest(node, step)) { checkRsAddNode(result, node); } node = node->nextSibling; } } break; case AxisFollowing: *docOrder = 1; if (ctxNode->nodeType == ATTRIBUTE_NODE) { node = ((domAttrNode *)ctxNode)->parentNode->firstChild; } else { node = ctxNode; if (node->nextSibling) { node = node->nextSibling; } else { while (node->parentNode) { node = node->parentNode; if (node->nextSibling) break; } if (!node->nextSibling) return XPATH_OK; else node = node->nextSibling; } } while (1) { if (xpathNodeTest (node, step)) { checkRsAddNode (result, node); if (step->intvalue) { count++; if (count >= step->intvalue) break; } } if (node->nodeType == ELEMENT_NODE && node->firstChild) { node = node->firstChild; } else if (node->nextSibling) { node = node->nextSibling; } else { while (node->parentNode) { node = node->parentNode; if (node->nextSibling) break; } if (!node->nextSibling) break; node = node->nextSibling; } } break; case AxisPreceding: *docOrder = 0; if (ctxNode->nodeType == ATTRIBUTE_NODE) { ancestor = node = ((domAttrNode *)ctxNode)->parentNode; } else { ancestor = node = ctxNode; } i = 0; while (node->parentNode) { ancestor = node; node = node->parentNode; i++; } startingNode = node->firstChild; for (; i > 0; i--) { if (!startingNode) continue; if (startingNode->nodeType == ELEMENT_NODE) { node = startingNode->firstChild; } else { node = NULL; } while (startingNode != ancestor) { if (xpathNodeTest(startingNode, step)) { checkRsAddNode(result, startingNode); } while ((node) && (node != startingNode)) { if (xpathNodeTest(node, step)) { checkRsAddNode(result, node); } if ((node->nodeType == ELEMENT_NODE) && (node->firstChild)) { node = node->firstChild; continue; } if (node->nextSibling) { node = node->nextSibling; continue; } while ((node->parentNode != startingNode) && (node->parentNode->nextSibling == NULL)) { node = node->parentNode; } if (node->parentNode != startingNode) { node = node->parentNode->nextSibling; } else { break; } } startingNode = startingNode->nextSibling; if (startingNode->nodeType == ELEMENT_NODE) { node = startingNode->firstChild; } else { node = NULL; } } if (ctxNode->nodeType == ATTRIBUTE_NODE) { node = ((domAttrNode *)ctxNode)->parentNode; } else { node = ctxNode; } for (j = 0; j < i - 1 ; j++) { ancestor = node; node = node->parentNode; } if (node->nodeType == ELEMENT_NODE) { startingNode = node->firstChild; } else { startingNode = NULL; } } break; case AxisNamespace: *docOrder = 1; /* XPath rec 2.2: "the namespace axis contains the namespace * nodes of the context node; the axis will be empty unless * the context node is an element */ if (ctxNode->nodeType != ELEMENT_NODE) { return XPATH_OK; } node = ctxNode; while (node) { attr = node->firstAttr; while (attr && (attr->nodeFlags & IS_NS_NODE)) { if (step->child->type == IsElement) { if ((step->child->strvalue[0] != '*')) { if (strcmp(attr->nodeValue, step->child->strvalue)!=0) { attr = attr->nextSibling; continue; } } } rc = 0; for (i = 0; i < result->nr_nodes; i++) { if (strcmp (attr->nodeName, ((domAttrNode*)result->nodes[i])->nodeName)==0) { rc = 1; break; } } if (rc) {attr = attr->nextSibling; continue;} checkRsAddNode (result, (domNode *)attr); attr = attr->nextSibling; } if (node == node->ownerDocument->documentElement) { if (ctxNode != ctxNode->ownerDocument->rootNode) { node = ctxNode->ownerDocument->rootNode; } else { node = NULL; } } else { node = node->parentNode; } } break; case GetFQVar: case GetVar: if (cbs->varCB) { if (step->type == GetFQVar) { leftStr = step->child->strvalue; rightStr = step->strvalue; } else { leftStr = step->strvalue; rightStr = NULL; } rc = (cbs->varCB)(cbs->varClientData, leftStr, rightStr, result, errMsg); CHECK_RC; } break; case Literal: rsSetString (result, step->strvalue); break; case Int: rsSetLong (result, step->intvalue); break; case Real: rsSetReal (result, step->realvalue); break; case Add: case Subtract: case Mult: case Div: case Mod: xpathRSInit (&leftResult); xpathRSInit (&rightResult); savedDocOrder = *docOrder; rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); CHECK_RC; DBG( fprintf(stderr,"left:\n"); rsPrint(&leftResult); ) *docOrder = savedDocOrder; rc = xpathEvalStep( step->child->next, ctxNode, exprContext, position, nodeList, cbs, &rightResult, docOrder, errMsg); CHECK_RC; *docOrder = savedDocOrder; DBG( fprintf(stderr,"right:\n"); rsPrint(&rightResult); ) if ((&leftResult)->type == RealResult) { dLeft = (&leftResult)->realvalue; NaN = 0; if (IS_NAN(dLeft)) NaN = 2; else if (IS_INF(dLeft)!=0) NaN = IS_INF(dLeft); } else { dLeft = xpathFuncNumber(&leftResult, &NaN); } if ((&rightResult)->type == RealResult) { dRight = (&rightResult)->realvalue; NaN1 = 0; if (IS_NAN(dRight)) NaN1= 2; else if (IS_INF(dRight) !=0) NaN1 = IS_INF(dRight); } else { dRight = xpathFuncNumber(&rightResult, &NaN1); } if (NaN || NaN1) { if ((NaN == 2) || (NaN1 == 2)) { rsSetNaN (result); } else { switch (step->type) { case Subtract: NaN1 = -1 * NaN1; /* fall through */ case Add: if (NaN == NaN1) { if (NaN == 1) rsSetInf (result); else rsSetNInf (result); } else if ((rc = NaN + NaN1) != 0) { if (rc == 1) rsSetInf (result); else rsSetNInf (result); } else { rsSetNaN (result); } break; case Mult: if ((dLeft == 0.0) || (dRight == 0.0)) rsSetNaN (result); else if (NaN && NaN1) { rc = NaN * NaN1; if (rc == 1) rsSetInf (result); else rsSetNInf (result); } else { if (NaN) dTmp = NaN * dRight; else dTmp = NaN1 * dLeft; if (dTmp > 0.0) rsSetInf (result); else rsSetNInf (result); } break; case Div: if (NaN && NaN1) rsSetNaN (result); else if (NaN1) rsSetLong (result, 0); else { if (dRight == 0.0) dTmp = NaN; else dTmp = NaN * dRight; if (dTmp > 0.0) rsSetInf (result); else rsSetNInf (result); } break; case Mod: rsSetNaN (result); break; default: break; } } xpathRSFree (&rightResult); xpathRSFree (&leftResult); return XPATH_OK; } switch (step->type) { case Add: rsSetReal (result, dLeft + dRight); break; case Subtract: rsSetReal (result, dLeft - dRight); break; case Mult: rsSetReal (result, dLeft * dRight); break; case Div: if (dRight == 0.0) { if (dLeft == 0.0) { rsSetNaN (result); } else { if (dLeft > 0) { rsSetInf (result); } else { rsSetNInf (result); } } } else { rsSetReal (result, dLeft / dRight); } break; case Mod: if ((int)dRight == 0) { rsSetNaN (result); } else { if (dRight < (double)LONG_MIN - 0.1 || dRight > (double)LONG_MAX + 0.1 || dLeft < (double)LONG_MIN - 0.1 || dLeft > (double)LONG_MAX + 0.1) { rsSetNaN (result); } else { rsSetLong (result, ((long)dLeft) % ((long)dRight)); } } break; default: break; } xpathRSFree (&rightResult); xpathRSFree (&leftResult); return XPATH_OK; case CombineSets: xpathRSInit (&leftResult); xpathRSInit (&rightResult); savedDocOrder = *docOrder; rc = xpathEvalStep (step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); CHECK_RC; DBG( fprintf(stderr,"left:\n"); rsPrint(&leftResult); ) *docOrder = savedDocOrder; rc = xpathEvalStep( step->child->next, ctxNode, exprContext, position, nodeList, cbs, &rightResult, docOrder, errMsg); CHECK_RC; *docOrder = savedDocOrder; DBG( fprintf(stderr,"right:\n"); rsPrint(&rightResult); ) if (((leftResult.type != xNodeSetResult) && (leftResult.type != EmptyResult)) || ((rightResult.type != xNodeSetResult) && (rightResult.type != EmptyResult))) { *errMsg = tdomstrdup("| requires node sets!"); xpathRSFree (&rightResult); xpathRSFree (&leftResult); return XPATH_EVAL_ERR; } if (leftResult.type == EmptyResult) { rsCopy (result, &rightResult); goto combineSetCleanup; } if (rightResult.type == EmptyResult) { rsCopy (result, &leftResult); goto combineSetCleanup; } *docOrder = 1; j = k = 0; for (i=0; i<(leftResult.nr_nodes+rightResult.nr_nodes); i++) { if (leftResult.nodes[j] == rightResult.nodes[k]) { rsAddNodeFast (result, leftResult.nodes[j]); j++; k++; if (j == leftResult.nr_nodes) break; if (k == rightResult.nr_nodes) break; i++; continue; } if (domPrecedes (leftResult.nodes[j], rightResult.nodes[k])) { rsAddNodeFast (result, leftResult.nodes[j]); j++; if (j == leftResult.nr_nodes) break; } else { rsAddNodeFast (result, rightResult.nodes[k]); k++; if (k == rightResult.nr_nodes) break; } } if (j < leftResult.nr_nodes) { for (i=j; i< leftResult.nr_nodes; i++) { rsAddNodeFast ( result, leftResult.nodes[i]); } } else { for (i=k; i< rightResult.nr_nodes; i++) { rsAddNodeFast ( result, rightResult.nodes[i]); } } combineSetCleanup: xpathRSFree (&rightResult); xpathRSFree (&leftResult); return XPATH_OK; case And: case Or: case Equal: case NotEqual: xpathRSInit (&leftResult); xpathRSInit (&rightResult); savedDocOrder = *docOrder; rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); CHECK_RC; *docOrder = savedDocOrder; DBG( fprintf(stderr,"left:\n"); rsPrint(&leftResult); ) /*---------------------------------------------- | short circuit evaluation for AND/OR \---------------------------------------------*/ if (step->type == And) { left = xpathFuncBoolean(&leftResult); if (!left) { /* left result is false, so AND result is also false */ rsSetBool (result, left); xpathRSFree (&leftResult); return XPATH_OK; } } if (step->type == Or) { left = xpathFuncBoolean(&leftResult); if (left) { /* left result is true, so OR result is also true */ rsSetBool (result, left); xpathRSFree (&leftResult); return XPATH_OK; } } rc = xpathEvalStep( step->child->next, ctxNode, exprContext, position, nodeList, cbs, &rightResult, docOrder, errMsg); CHECK_RC; *docOrder = savedDocOrder; DBG( fprintf(stderr,"right:\n"); rsPrint(&rightResult); ) res = 0; if ((step->type == And) || (step->type == Or)) { right = xpathFuncBoolean(&rightResult); if (step->type == And) res = (left && right); if (step->type == Or) res = (left || right); rsSetBool (result, res); xpathRSFree (&rightResult); xpathRSFree (&leftResult); return XPATH_OK; } if ( leftResult.type == xNodeSetResult || rightResult.type == xNodeSetResult) { if (leftResult.type == xNodeSetResult) { pleftResult = &leftResult; prightResult = &rightResult; } else { pleftResult = &rightResult; prightResult = &leftResult; } switch (prightResult->type) { case EmptyResult: res = 0; break; case xNodeSetResult: JDBG( fprintf(stderr,"\nleft+right result:\n"); rsPrint(pleftResult); rsPrint(prightResult); ) for (i=0; i < pleftResult->nr_nodes; i++) { leftStr = xpathFuncStringForNode (pleftResult->nodes[i]); for (j=0; j < prightResult->nr_nodes; j++) { rightStr = xpathFuncStringForNode (prightResult->nodes[j]); JDBG(fprintf(stderr, "leftStr='%s' rightStr='%s'\n", leftStr, rightStr);) res = strcmp (leftStr, rightStr); if (step->type == Equal) res = (res==0); else if (step->type == NotEqual) res = (res!=0); FREE(rightStr); if (res) break; } FREE(leftStr); if (res) break; } break; case BoolResult: if (step->type == Equal) res = (prightResult->intvalue != 0); else res = (prightResult->intvalue == 0); break; case IntResult: case RealResult: dRight = xpathFuncNumber (prightResult, &NaN); if (NaN) { /* The real value of a node could never be inf/-inf */ /* And NaN is always != NaN (and != everything else) */ if (step->type == Equal) res = 0; else res = 1; break; } for (i=0; i < pleftResult->nr_nodes; i++) { leftStr = xpathFuncStringForNode (pleftResult->nodes[i]); dLeft = xpathStringToNumber (leftStr, &NaN); FREE(leftStr); if (NaN) continue; if (step->type == Equal) res = (dLeft == dRight); else res = (dLeft != dRight); if (res) break; } break; case NaNResult: case InfResult: case NInfResult: res = 0; break; case StringResult: rightStr = xpathFuncString (prightResult); for (i=0; i < pleftResult->nr_nodes; i++) { leftStr = xpathFuncStringForNode (pleftResult->nodes[i]); res = strcmp (leftStr, rightStr); if (step->type == Equal) res = (res == 0); else res = (res != 0); FREE(leftStr); if (res) break; } FREE(rightStr); break; default: Tcl_Panic("Invalid xpathResultType %s in xpathEvalStep!", xpathResultType2string(prightResult->type)); break; } } else if (leftResult.type == BoolResult || rightResult.type == BoolResult) { left = xpathFuncBoolean (&leftResult); right = xpathFuncBoolean (&rightResult); if (step->type == Equal) res = (left == right); else res = (left != right); } else if ( leftResult.type == IntResult || leftResult.type == RealResult || rightResult.type == IntResult || rightResult.type == RealResult || rightResult.type == NaNResult || rightResult.type == InfResult || rightResult.type == NInfResult || leftResult.type == NaNResult || leftResult.type == InfResult || leftResult.type == NInfResult ) { if ( leftResult.type == EmptyResult || rightResult.type == EmptyResult) { res = 0; } else { dLeft = xpathFuncNumber (&leftResult, &NaN); dRight = xpathFuncNumber (&rightResult, &NaN1); if (NaN || NaN1) { if (NaN == NaN1) { if (NaN != 2) { if (step->type == Equal) res = 1; } else { if (step->type == NotEqual) res = 1; } } else { if (step->type == NotEqual) res = 1; } } else { if (step->type == Equal) res = (dLeft == dRight); else res = (dLeft != dRight); } } } else { if ( leftResult.type == EmptyResult || rightResult.type == EmptyResult) { res = 0; } else { leftStr = xpathFuncString (&leftResult); rightStr = xpathFuncString (&rightResult); res = strcmp (leftStr, rightStr); if (step->type == Equal) res = (res == 0); else res = (res != 0); FREE(leftStr); FREE(rightStr); } } rsSetBool (result, res); xpathRSFree (&rightResult); xpathRSFree (&leftResult); return XPATH_OK; case Less: case LessOrEq: case Greater: case GreaterOrEq: xpathRSInit (&leftResult); xpathRSInit (&rightResult); savedDocOrder = *docOrder; rc = xpathEvalStep( step->child, ctxNode, exprContext, position, nodeList, cbs, &leftResult, docOrder, errMsg); CHECK_RC; *docOrder = savedDocOrder; DBG( fprintf(stderr,"left:\n"); rsPrint(&leftResult); ) rc = xpathEvalStep( step->child->next, ctxNode, exprContext, position, nodeList, cbs, &rightResult, docOrder, errMsg); CHECK_RC; *docOrder = savedDocOrder; DBG( fprintf(stderr,"right:\n"); rsPrint(&rightResult); ) res = 0; if ( leftResult.type == xNodeSetResult || rightResult.type == xNodeSetResult) { if (leftResult.type == xNodeSetResult) { pleftResult = &leftResult; prightResult = &rightResult; switchResult = 0; } else { pleftResult = &rightResult; prightResult = &leftResult; switchResult = 1; } switch (prightResult->type) { case EmptyResult: res = 0; break; case xNodeSetResult: JDBG( fprintf(stderr,"\nleft+right result:\n"); rsPrint(pleftResult); rsPrint(prightResult); ) for (i=0; i < pleftResult->nr_nodes; i++) { leftStr = xpathFuncStringForNode (pleftResult->nodes[i]); dLeft = xpathStringToNumber (leftStr, &NaN); FREE(leftStr); if (NaN) continue; for (j=0; j < prightResult->nr_nodes; j++) { rightStr = xpathFuncStringForNode (prightResult->nodes[j]); dRight = xpathStringToNumber (rightStr, &NaN); FREE(rightStr); if (NaN) continue; if (switchResult) { dTmp = dLeft; dLeft = dRight; dRight = dTmp; } if (step->type == Less) res = (dLeft < dRight); else if (step->type == LessOrEq) res = (dLeft <= dRight); else if (step->type == Greater) res = (dLeft > dRight); else res = (dLeft >= dRight); if (res) break; } if (res) break; } break; case BoolResult: /* pleftResult is a nonempty nodeset, therefore: */ dLeft = 1.0; dRight = xpathFuncNumber (prightResult, &NaN); if (NaN) break; if (step->type == Less) res = (dLeft < dRight); else if (step->type == LessOrEq) res = (dLeft <= dRight); else if (step->type == Greater) res = (dLeft > dRight); else res = (dLeft >= dRight); if (switchResult) { res = !res; } break; case NaNResult: break; case InfResult: case NInfResult: case IntResult: case RealResult: case StringResult: dRight = xpathFuncNumber (prightResult, &NaN); if (NaN) { if (NaN == 2) break; #ifdef DBL_MAX if (NaN == 1) dRight = DBL_MAX; else dRight = -DBL_MAX; #endif } for (i=0; i < pleftResult->nr_nodes; i++) { leftStr = xpathFuncStringForNode (pleftResult->nodes[i]); dLeft = xpathStringToNumber (leftStr, &NaN); FREE (leftStr); if (NaN) continue; if (switchResult) { dTmp = dLeft; dLeft = dRight; dRight = dTmp; } if (step->type == Less) res = (dLeft < dRight); else if (step->type == LessOrEq) res = (dLeft <= dRight); else if (step->type == Greater) res = (dLeft > dRight); else res = (dLeft >= dRight); if (res) break; } break; default: Tcl_Panic("Invalid xpathResultType %s in xpathEvalStep!", xpathResultType2string(prightResult->type)); break; } } else { if ( leftResult.type == EmptyResult || rightResult.type == EmptyResult) { res = 0; } else { dLeft = xpathFuncNumber (&leftResult, &NaN); if (NaN) { if (NaN == 2) goto compareFinish; #ifdef DBL_MAX if (NaN == 1) dLeft = DBL_MAX; else dLeft = -DBL_MAX; #endif } dRight = xpathFuncNumber (&rightResult, &NaN); if (NaN) { if (NaN == 2) goto compareFinish; #ifdef DBL_MAX if (NaN == 1) dRight = DBL_MAX; else dRight = -DBL_MAX; #endif } if (step->type == Less) res = (dLeft < dRight); else if (step->type == LessOrEq) res = (dLeft <= dRight); else if (step->type == Greater) res = (dLeft > dRight); else res = (dLeft >= dRight); } } compareFinish: rsSetBool (result, res); xpathRSFree (&rightResult); xpathRSFree (&leftResult); return XPATH_OK; case SelectRoot: if (ctxNode->nodeType == ATTRIBUTE_NODE) { node = ((domAttrNode *)ctxNode)->parentNode; checkRsAddNode(result, node->ownerDocument->rootNode); } else { checkRsAddNode(result, ctxNode->ownerDocument->rootNode); } break; case UnaryMinus: xpathRSInit (&leftResult); rc = xpathEvalSteps (step->child, nodeList, ctxNode, exprContext, position, docOrder,cbs, &leftResult, errMsg); CHECK_RC; dLeft = xpathFuncNumber (&leftResult, &NaN); if (NaN) { if (NaN == 2) rsSetNaN (result); else if (NaN == 1) rsSetNInf (result); else rsSetInf (result); } else rsSetReal (result , -1 * dLeft); xpathRSFree (&leftResult); break; case EvalSteps: rc = xpathEvalSteps (step->child, nodeList, ctxNode, exprContext, position, docOrder,cbs, &leftResult, errMsg); CHECK_RC; if ((result->type != EmptyResult) && (leftResult.type != result->type)) { DBG( fprintf (stderr, "EvalSteps:\nresult:\n"); rsPrint (result); fprintf (stderr, "leftResult:\n"); rsPrint (&leftResult); ) *errMsg = tdomstrdup("can not merge different result types!"); return XPATH_EVAL_ERR; } switch (leftResult.type) { case xNodeSetResult: for (i=0; itype]); return XPATH_EVAL_ERR; } return XPATH_OK; } /* xpathEvalStep */ /*---------------------------------------------------------------------------- | xpathEvalPredicate | \---------------------------------------------------------------------------*/ static int xpathEvalPredicate ( ast step, domNode *exprContext, xpathResultSet *result, xpathResultSet *stepResult, xpathCBs *cbs, int *docOrder, char **errMsg ) { xpathResultSet predResult, tmpResult; int rc, savedDocOrder, useFastAdd; domLength i; if (result->nr_nodes == 0) useFastAdd = 1; else useFastAdd = 0; savedDocOrder = *docOrder; while (step && step->type == Pred) { xpathRSInit (&tmpResult); if (step->child->type == Int) { if (stepResult->nr_nodes >= step->child->intvalue && step->child->intvalue > 0) { if (*docOrder) { rsAddNode (&tmpResult, stepResult->nodes[step->child->intvalue - 1]); } else { rsAddNode (&tmpResult, stepResult->nodes[stepResult->nr_nodes - step->child->intvalue]); } } goto nextPred; } for (i=0; inr_nodes; i++) { xpathRSInit (&predResult); rc = xpathEvalStep( step->child, stepResult->nodes[i], exprContext, i, stepResult, cbs, &predResult, docOrder, errMsg); CHECK_RC; *docOrder = savedDocOrder; DBG( fprintf(stderr, "after eval for Predicate: \n"); ) DBG( rsPrint( &predResult); ) if (predResult.type == RealResult) { predResult.type = IntResult; predResult.intvalue = xpathRound(predResult.realvalue); } if (predResult.type == IntResult) { if (predResult.intvalue < 0) { predResult.intvalue = stepResult->nr_nodes + predResult.intvalue; } if (savedDocOrder) { if (predResult.intvalue == (i+1)) { rsAddNodeFast (&tmpResult, stepResult->nodes[i]); } } else { if (predResult.intvalue == (stepResult->nr_nodes - i)){ rsAddNodeFast (&tmpResult, stepResult->nodes[i]); } } } else if (xpathFuncBoolean(&predResult)) { rsAddNodeFast (&tmpResult, stepResult->nodes[i]); } xpathRSFree (&predResult); } nextPred: DBG( fprintf(stderr, "result after Predicate: \n"); ) DBG( rsPrint( &tmpResult); ) xpathRSFree( stepResult ); *stepResult = tmpResult; step = step->next; } /* add remaining result set to overall result set */ for (i=0; inr_nodes; i++) { checkRsAddNode (result, stepResult->nodes[i]); } return 0; } /*---------------------------------------------------------------------------- | xpathEvalStepAndPredicates | \---------------------------------------------------------------------------*/ static int xpathEvalStepAndPredicates ( ast steps, xpathResultSet *nodeList, domNode *currentNode, domNode *exprContext, domLength currentPos, int *docOrder, xpathCBs *cbs, xpathResultSet *result, char **errMsg ) { xpathResultSet stepResult; int rc; /* For AxisDescendantOrSelf/AxisDescendant, the predicate filtering is already done 'inlined' during xpathEvalStep, to do the filtering "with respect to the child axis" (XPath rec. 3.3) in an efficienter way, then up to now. */ if ( steps->next && steps->next->type == Pred && steps->type != AxisDescendantOrSelf && steps->type != AxisDescendant) { xpathRSInit (&stepResult); rc = xpathEvalStep( steps, currentNode, exprContext, currentPos, nodeList, cbs, &stepResult, docOrder, errMsg); if (rc) { xpathRSFree (&stepResult); return rc; } rc = xpathEvalPredicate (steps->next, exprContext, result, &stepResult, cbs, docOrder, errMsg); xpathRSFree (&stepResult); CHECK_RC; } else { /* for steps not followed by a predicate immediately add to the final result set */ rc = xpathEvalStep( steps, currentNode, exprContext, currentPos, nodeList, cbs, result, docOrder, errMsg); CHECK_RC; DBG( rsPrint( result); ) } return 0; } /*---------------------------------------------------------------------------- | xpathEvalSteps | \---------------------------------------------------------------------------*/ int xpathEvalSteps ( ast steps, xpathResultSet *nodeList, domNode *currentNode, domNode *exprContext, domLength currentPos, int *docOrder, xpathCBs *cbs, xpathResultSet *result, char **errMsg ) { int rc, first = 1; domLength i; xpathResultSet savedContext; DBG (fprintf (stderr, "xpathEvalSteps start\n");) savedContext = *nodeList; xpathRSInit (result); while (steps) { DBG (fprintf (stderr, "xpathEvalSteps: eval step '%s'\n", astType2str[steps->type]);) if (steps->type == Pred) { *errMsg = "Pred step not expected now!"; return XPATH_EVAL_ERR; } if (first) { rc = xpathEvalStepAndPredicates (steps, nodeList, currentNode, exprContext, currentPos, docOrder, cbs, result, errMsg); CHECK_RC; first = 0; } else { DBG( fprintf(stderr, "doing location step nodeList->nr_nodes=%ld \n", nodeList->nr_nodes); ) if (result->type != xNodeSetResult) { xpathRSFree (result); xpathRSInit (result); *nodeList = savedContext; return 0; } *nodeList = *result; xpathRSInit (result); for (i=0; inr_nodes; i++) { rc = xpathEvalStepAndPredicates (steps, nodeList, nodeList->nodes[i], exprContext, i, docOrder, cbs, result, errMsg); if (rc) { xpathRSFree (result); xpathRSFree (nodeList); return rc; } } xpathRSFree (nodeList); } DBG( fprintf(stderr, "result after location step: \n"); ) DBG( rsPrint( result); ) steps = steps->next; /* skip the already processed Predicate parts */ while (steps && steps->type == Pred) steps = steps->next; *docOrder = 1; } *nodeList = savedContext; return 0; } /*---------------------------------------------------------------------------- | xpathEval | \---------------------------------------------------------------------------*/ int xpathEval ( domNode * node, domNode * exprContext, char * xpath, char ** prefixMappings, xpathCBs * cbs, xpathParseVarCB * parseVarCB, Tcl_HashTable * cache, char ** errMsg, xpathResultSet * result ) { xpathResultSet nodeList; int rc, hnew = 1, docOrder = 1; ast t; Tcl_HashEntry *h = NULL; *errMsg = NULL; if (cache) { h = Tcl_CreateHashEntry (cache, xpath, &hnew); } if (hnew) { rc = xpathParse(xpath, exprContext, XPATH_EXPR, prefixMappings, parseVarCB, &t, errMsg); if (rc) { if (h != NULL) { Tcl_DeleteHashEntry(h); } return rc; } if (cache) { Tcl_SetHashValue(h, t); } } else { t = (ast)Tcl_GetHashValue(h); } xpathRSInit( &nodeList); rsAddNodeFast( &nodeList, node); rc = xpathEvalSteps( t, &nodeList, node, exprContext, 0, &docOrder, cbs, result, errMsg); if (!cache) { freeAst(t); } xpathRSFree( &nodeList ); CHECK_RC; DBG(rsPrint( result );) return 0; } /* xpathEval */ int xpathEvalAst ( ast t, xpathResultSet *nodeList, domNode *node, xpathCBs * cbs, xpathResultSet *rs, char **errMsg ) { int rc, first = 1, docOrder = 1; domLength i; xpathResultSet savedContext; savedContext = *nodeList; while (t) { DBG (fprintf (stderr, "xpathEvalAst: eval step '%s'\n", astType2str[t->type]);) if (t->type == Pred) { *errMsg = "Pred step not expected now!"; return XPATH_EVAL_ERR; } if (first) { rc = xpathEvalStepAndPredicates (t, nodeList, node, node, 0, &docOrder, cbs, rs, errMsg); CHECK_RC; first = 0; } else { DBG( fprintf(stderr, "doing location step nodeList->nr_nodes=%ld \n", nodeList->nr_nodes); ) if (rs->type != xNodeSetResult) { *nodeList = savedContext; return 0; } *nodeList = *rs; xpathRSReset (rs, NULL); for (i=0; i < nodeList->nr_nodes; i++) { rc = xpathEvalStepAndPredicates (t, nodeList, nodeList->nodes[i], node, i, &docOrder, NULL, rs, errMsg); if (rc) { *nodeList = savedContext; return rc; } } } DBG( fprintf(stderr, "result after location step: \n"); ) DBG( rsPrint( result); ) t = t->next; /* skip the already processed Predicate parts */ while (t && t->type == Pred) t = t->next; docOrder = 1; } *nodeList = savedContext; return 0; } /*---------------------------------------------------------------------------- | xpathMatches | \---------------------------------------------------------------------------*/ int xpathMatches ( ast step, domNode * exprContext, domNode * nodeToMatch, xpathCBs * cbs, char ** errMsg ) { xpathResultSet stepResult, nodeList, newNodeList; ast childSteps; int rc, nodeMatches, docOrder = 1; domLength currentPos = 0, i, j; int useFastAdd; const char *localName = NULL, *nodeUri; domAttrNode *attr; domNode *child; DBG(printAst(3,step)); xpathRSInit (&nodeList); while (step) { TRACE1("xpathMatches type=%d \n", step->type); if (nodeList.nr_nodes == 0) useFastAdd = 1; else useFastAdd = 0; switch (step->type) { case AxisAttribute: if (step->child->type != IsAttr && step->child->type != IsNSAttr) { if (step->child->type == IsElement) { step->child->type = IsAttr; } else { DBG(fprintf(stderr, "strange: AxisAttribute with no IsAttr below!\n");) xpathRSFree (&nodeList); return 0; } } attr = NULL; if (nodeToMatch->nodeType == ATTRIBUTE_NODE) { rc = xpathMatches (step->child, exprContext, nodeToMatch, cbs, errMsg); DBG(fprintf(stderr, "rc=%d attribute match\n", rc); ) if (rc != 1) { xpathRSFree (&nodeList); return 0; } attr = (domAttrNode*) nodeToMatch; } else { xpathRSFree (&nodeList); return 0; } if (attr == NULL) { xpathRSFree (&nodeList); return 0; } break; case AxisChild: if (step->child->type == IsElement) { if (nodeToMatch->nodeType != ELEMENT_NODE) { xpathRSFree (&nodeList); return 0; } if (nodeToMatch == nodeToMatch->ownerDocument->rootNode) { xpathRSFree (&nodeList); return 0; } if ((step->child->strvalue[0] != '*') || (step->child->strvalue[1] != '\0') || (step->child->intvalue != 0)) { if (nodeToMatch->namespace) return 0; if (strcmp(nodeToMatch->nodeName, step->child->strvalue)!=0) { xpathRSFree (&nodeList); return 0; } } break; } if (step->child->type == IsFQElement) { if (nodeToMatch->nodeType != ELEMENT_NODE) { xpathRSFree (&nodeList); return 0; } nodeUri = domNamespaceURI (nodeToMatch); if (!nodeUri) { xpathRSFree (&nodeList); return 0; } if (strcmp (step->child->strvalue, nodeUri) != 0) { xpathRSFree (&nodeList); return 0; } localName = domGetLocalName (nodeToMatch->nodeName); if (!localName) { xpathRSFree (&nodeList); return 0; } if (strcmp (step->child->child->strvalue, localName)!=0) { xpathRSFree (&nodeList); return 0; } break; } if (step->child->type == IsNSElement) { nodeUri = domNamespaceURI (nodeToMatch); if (!nodeUri) { xpathRSFree (&nodeList); return 0; } if (strcmp (step->child->strvalue, nodeUri)!=0) { xpathRSFree (&nodeList); return 0; } break; } DBG(fprintf(stderr, "strange: AxisChild with no IsElement, IsFQElement or IsNSElement below!\n");) return 0; case IsElement: if (nodeToMatch->nodeType != ELEMENT_NODE) { xpathRSFree (&nodeList); return 0; } if (nodeToMatch == nodeToMatch->ownerDocument->rootNode) { xpathRSFree (&nodeList); return 0; } if ((step->strvalue[0] != '*') || (step->strvalue[1] != '\0') || (step->intvalue != 0)) { if (nodeToMatch->namespace) return 0; if (strcmp(nodeToMatch->nodeName, step->strvalue)!=0) { xpathRSFree (&nodeList); return 0; } } break; case IsFQElement: if (nodeToMatch->nodeType != ELEMENT_NODE) { xpathRSFree (&nodeList); return 0; } nodeUri = domNamespaceURI (nodeToMatch); if (!nodeUri) { xpathRSFree (&nodeList); return 0; } if (strcmp (step->strvalue, nodeUri) != 0) { xpathRSFree (&nodeList); return 0; } localName = domGetLocalName (nodeToMatch->nodeName); if (!localName) { xpathRSFree (&nodeList); return 0; } if (strcmp (step->child->strvalue, localName)!=0) { xpathRSFree (&nodeList); return 0; } break; case IsNSElement: nodeUri = domNamespaceURI (nodeToMatch); if (!nodeUri) { xpathRSFree (&nodeList); return 0; } if (strcmp (step->strvalue, nodeUri)!=0) { xpathRSFree (&nodeList); return 0; } break; case IsAttr: if ((nodeToMatch->nodeType != ATTRIBUTE_NODE) || (nodeToMatch->nodeFlags & IS_NS_NODE)) { xpathRSFree (&nodeList); return 0; } if (!((step->strvalue[0] == '*') && (step->strvalue[1] == '\0'))) { if (strcmp( ((domAttrNode*)nodeToMatch)->nodeName, step->strvalue)!=0) { xpathRSFree (&nodeList); return 0; } } break; case IsNSAttr: if ((nodeToMatch->nodeType != ATTRIBUTE_NODE) || (nodeToMatch->nodeFlags & IS_NS_NODE)) { xpathRSFree (&nodeList); return 0; } nodeUri = domNamespaceURI (nodeToMatch); if (!nodeUri) { xpathRSFree (&nodeList); return 0; } if (strcmp (step->strvalue, nodeUri) != 0) { xpathRSFree (&nodeList); return 0; } if (strcmp (step->child->strvalue, "*")==0) break; localName = domGetLocalName (((domAttrNode *)nodeToMatch)->nodeName); if (!localName) { xpathRSFree (&nodeList); return 0; } if (strcmp (step->child->strvalue, localName)!=0) { xpathRSFree (&nodeList); return 0; } break; case IsNode: DBG(fprintf(stderr, "IsNode: nodeTpye=%d \n", nodeToMatch->nodeType);) if (nodeToMatch->nodeType == ATTRIBUTE_NODE) { xpathRSFree (&nodeList); return 0; } if ((nodeToMatch->nodeType == ELEMENT_NODE) && (nodeToMatch->ownerDocument->rootNode == nodeToMatch)) { xpathRSFree (&nodeList); return 0; } break; case IsText: if (nodeToMatch->nodeType != TEXT_NODE) { xpathRSFree (&nodeList); return 0; } break; case IsPI: if (nodeToMatch->nodeType != PROCESSING_INSTRUCTION_NODE) { xpathRSFree (&nodeList); return 0; } break; case IsSpecificPI: if (nodeToMatch->nodeType != PROCESSING_INSTRUCTION_NODE) { xpathRSFree (&nodeList); return 0; } if (strncmp(((domProcessingInstructionNode*)nodeToMatch)->targetValue, step->strvalue, ((domProcessingInstructionNode*)nodeToMatch)->targetLength) != 0) { xpathRSFree (&nodeList); return 0; } break; case IsComment: if (nodeToMatch->nodeType != COMMENT_NODE) { xpathRSFree (&nodeList); return 0; } break; case IsRoot: if (nodeToMatch->nodeType == ATTRIBUTE_NODE) { xpathRSFree (&nodeList); return 0; } if (nodeToMatch != nodeToMatch->ownerDocument->rootNode) { xpathRSFree (&nodeList); return 0; } break; case ToParent: if (nodeToMatch->nodeType == ATTRIBUTE_NODE) { nodeToMatch = ((domAttrNode *)nodeToMatch)->parentNode; break; } if (nodeToMatch == nodeToMatch->ownerDocument->rootNode) { xpathRSFree (&nodeList); return 0; } if (nodeToMatch->parentNode) { nodeToMatch = nodeToMatch->parentNode; } else { nodeToMatch = nodeToMatch->ownerDocument->rootNode; } break; case ToAncestors: if (step->next == NULL) { xpathRSFree (&nodeList); return 1;} while (1) { if (nodeToMatch->nodeType == ATTRIBUTE_NODE) { nodeToMatch = ((domAttrNode *)nodeToMatch)->parentNode; } else { if (nodeToMatch == nodeToMatch->ownerDocument->rootNode) { xpathRSFree (&nodeList); return 0; } if (nodeToMatch->parentNode) { nodeToMatch = nodeToMatch->parentNode; } else { nodeToMatch = nodeToMatch->ownerDocument->rootNode; } } if (step->next == NULL) { xpathRSFree (&nodeList); return 0; } rc = xpathMatches (step->next, exprContext, nodeToMatch, cbs, errMsg); if (rc == 1) break; } break; case FillWithCurrentNode: checkRsAddNode( &nodeList, nodeToMatch); currentPos = 0; DBG( fprintf(stderr, "FillWithCurrentNode:\n"); rsPrint(&nodeList); ) break; case FillNodeList: if (nodeToMatch->nodeType == ATTRIBUTE_NODE) { child = (domNode*) ((domAttrNode*)nodeToMatch)->parentNode->firstAttr; DBG(fprintf(stderr, "FillNodeList all attribute\n");) } else { if (nodeToMatch->ownerDocument->rootNode == nodeToMatch) { xpathRSFree (&nodeList); return 0; } DBG(if (nodeToMatch->parentNode) { fprintf(stderr, "FillNodeList on %s/%s...\n", nodeToMatch->parentNode->nodeName,nodeToMatch->nodeName); } else { fprintf(stderr, "FillNodeList on (null)/%s...\n", nodeToMatch->nodeName); } fprintf (stderr, "Current nodeList is:\n"); rsPrint (&nodeList); ) if (nodeToMatch->parentNode == NULL) { child = nodeToMatch->ownerDocument->rootNode->firstChild; } else { child = nodeToMatch->parentNode->firstChild; } } currentPos = -1; i = 0; while (child) { rc = xpathMatches (step->child, exprContext, child, cbs, errMsg); if (rc == 1) { checkRsAddNode( &nodeList, child); if (child == nodeToMatch) currentPos = i; i++; if (step->intvalue && i >= step->intvalue) break; } if (child->nodeType == ATTRIBUTE_NODE) { child = (domNode*) ((domAttrNode*)child)->nextSibling; } else { child = child->nextSibling; } } DBG( rsPrint(&nodeList); fprintf(stderr, "currentPos = %d \n", currentPos); ) break; case Pred: xpathRSInit (&stepResult); DBG(fprintf(stderr, "Before Pred inner EvalStep. currentPos = %d\n", currentPos);) rc = xpathEvalStep (step->child, nodeToMatch, exprContext, currentPos, &nodeList, cbs, &stepResult, &docOrder, errMsg); CHECK_RC; DBG( fprintf(stderr, "Pred inner EvalStep returned\n"); rsPrint(&stepResult); ) nodeMatches = 0; if (stepResult.type == RealResult) { stepResult.type = IntResult; stepResult.intvalue = xpathRound(stepResult.realvalue); } if (stepResult.type == IntResult) { if (stepResult.intvalue < 0) { stepResult.intvalue = nodeList.nr_nodes + stepResult.intvalue; } if ((stepResult.intvalue > 0 ) && (stepResult.intvalue <= nodeList.nr_nodes) && (stepResult.intvalue == (currentPos+1)) ) { nodeMatches = 1; } } else if (xpathFuncBoolean(&stepResult)) { nodeMatches = 1; } xpathRSFree (&stepResult); /* if nodeMatches == false we don't have to continue to filter */ if (!nodeMatches) { xpathRSFree (&nodeList); return 0; } /* if the nr_nodes of nodeList is > 1 (i.e. we filter a FillNodeList step, not only a FillWithCurrentNode step), build the resulting nodeList context after this predicate */ if (nodeList.nr_nodes > 1) { xpathRSInit (&newNodeList); currentPos = -1; j = 0; for (i = 0; i < nodeList.nr_nodes; i++) { xpathRSInit (&stepResult); docOrder = 1; rc = xpathEvalStep (step->child, nodeList.nodes[i], exprContext, i, &nodeList, cbs, &stepResult, &docOrder, errMsg); if (rc) { xpathRSFree (&stepResult); xpathRSFree (&nodeList); return rc; } nodeMatches = 0; if (stepResult.type == RealResult) { stepResult.type = IntResult; stepResult.intvalue = xpathRound(stepResult.realvalue); } if (stepResult.type == IntResult) { if (stepResult.intvalue < 0) { stepResult.intvalue = nodeList.nr_nodes + stepResult.intvalue; } if ((stepResult.intvalue > 0 ) && (stepResult.intvalue <= nodeList.nr_nodes) && (stepResult.intvalue == (currentPos+1)) ) { nodeMatches = 1; } } else if (xpathFuncBoolean(&stepResult)) { nodeMatches = 1; } if (nodeMatches) { checkRsAddNode (&newNodeList, nodeList.nodes[i]); if (nodeList.nodes[i] == nodeToMatch) { currentPos = j; } j++; } xpathRSFree (&stepResult); } xpathRSFree (&nodeList); nodeList = newNodeList; } break; case CombinePath: childSteps = step->child; while (childSteps) { rc = xpathMatches (childSteps->child, exprContext, nodeToMatch, cbs, errMsg); if (rc == 1) break; childSteps = childSteps->next; } if (childSteps == NULL) { xpathRSFree (&nodeList); return 0; } break; case ExecIdKey: xpathRSInit (&stepResult); rc = xpathEvalStep (step, nodeToMatch, exprContext, currentPos, &nodeList, cbs, &stepResult, &docOrder, errMsg); CHECK_RC; if (stepResult.type != xNodeSetResult) { xpathRSFree (&stepResult); xpathRSFree (&nodeList); return 0; } nodeMatches = 0; for (i = 0; i < stepResult.nr_nodes; i++) { if (nodeToMatch == stepResult.nodes[i]) { nodeMatches = 1; break; } } xpathRSFree (&stepResult); if (!nodeMatches) { xpathRSFree (&nodeList); return 0; } break; default: DBG( fprintf(stderr, "wrong type %d for xpathMatches \n", step->type); fprintf(stderr, "AST:\n"); ) printAst (0, step); xpathRSFree (&nodeList); return 0; break; } step = step->next; } xpathRSFree (&nodeList); return 1; } /*---------------------------------------------------------------------------- | xpathGetPrio | \---------------------------------------------------------------------------*/ double xpathGetPrio ( ast steps ) { if (!steps) return 0.0; DBG(printAst(0, steps);) if (steps->next == NULL) { if (steps->type == IsElement) { if (strcmp(steps->strvalue, "*")==0 && steps->intvalue==0) { return -0.5; } else { return 0.0; } } else if (steps->type == IsFQElement) { return 0.0; } else if (steps->type == IsNSElement) { return -0.25; } else if (steps->type == IsAttr) { if (strcmp(steps->strvalue, "*")==0) { return -0.5; } else { return 0.0; } } else if (steps->type == IsNSAttr) { if (strcmp(steps->child->strvalue, "*")==0) { return -0.25; } else { return 0.0; } } else if (steps->type == IsSpecificPI) { return 0.0; } else if ( steps->type == IsNode || steps->type == IsText || steps->type == IsPI || steps->type == IsComment ) { return -0.5; } else if ( steps->type == AxisChild || steps->type == AxisAttribute || steps->type == EvalSteps ) { return (xpathGetPrio (steps->child)); } } return 0.5; } /* xpathGetPrio */ /*---------------------------------------------------------------------------- | nodeToXPath - returns a XPath addressing exactly the given node | \---------------------------------------------------------------------------*/ static void nodeToXPath ( domNode * node, char ** xpath, domLength * xpathLen, domLength * xpathAllocated, int legacy ) { domNode *parent, *child; char step[200], *nTest; domLength len; int sameNodes, nodeIndex; parent = node->parentNode; if (parent == NULL) { parent = node->ownerDocument->rootNode; } else { nodeToXPath (parent, xpath, xpathLen, xpathAllocated, legacy); } step[0] = '\0'; switch (node->nodeType) { case ELEMENT_NODE: nodeIndex = 0; sameNodes = 0; child = parent->firstChild; if (node->namespace && !legacy) { while (child) { if (child->nodeType == ELEMENT_NODE) { sameNodes++; if (node == child) { nodeIndex = sameNodes; if (sameNodes > 1) break; } } child = child->nextSibling; } if (sameNodes == 1) { sprintf(step, "/*"); } else { sprintf(step, "/*[%d]", nodeIndex); } } else { while (child) { if (strcmp(child->nodeName, node->nodeName)==0) { sameNodes++; if (node == child) nodeIndex = sameNodes; if ((nodeIndex != 0) && (sameNodes > 2)) break; } child = child->nextSibling; } if (sameNodes == 1) { sprintf(step, "/%s", node->nodeName); } else { sprintf(step, "/%s[%d]", node->nodeName, nodeIndex); } } break; case TEXT_NODE: case COMMENT_NODE: case PROCESSING_INSTRUCTION_NODE: nodeIndex = 0; sameNodes = 0; child = parent->firstChild; while (child) { if (child->nodeType == node->nodeType) { sameNodes++; if (node == child) nodeIndex = sameNodes; if ((nodeIndex != 0) && (sameNodes > 2)) break; } child = child->nextSibling; } switch (node->nodeType) { case TEXT_NODE: nTest = "text()"; break; case COMMENT_NODE: nTest = "comment()"; break; case PROCESSING_INSTRUCTION_NODE: nTest = "processing-instruction()"; break; default: nTest = "unknownNodeType()"; } if (sameNodes == 1) { sprintf(step, "/%s", nTest); } else { sprintf(step, "/%s[%d]", nTest, nodeIndex); } break; default: break; } len = (domLength)strlen(step); if ( (len + *xpathLen) > *xpathAllocated ) { *xpathAllocated = *xpathAllocated * 2; *xpath = REALLOC(*xpath, *xpathAllocated + 1); } strcpy( *xpath + *xpathLen, step); *xpathLen += len; } /* nodeToXPath */ /*---------------------------------------------------------------------------- | xpathNodeToXPath | \---------------------------------------------------------------------------*/ char * xpathNodeToXPath ( domNode *node, int legacy ) { char * xpath; domLength xpathLen, xpathAllocated; xpathAllocated = 100; xpathLen = 0; xpath = MALLOC(xpathAllocated + 1); nodeToXPath (node, &xpath, &xpathLen, &xpathAllocated, legacy); return xpath; } /* xpathNodeToXPath */ tdom-0.9.5-src/generic/tdom.decls0000644000175000017500000000445714703531020015343 0ustar rolfrolf# tdom.decls -- # # This file contains the declarations for all supported public # functions that are exported by the tDOM library via the stubs table. # # Copyright (c) 2002 Rolf Ade. library tdom interface tdom #hooks {} declare 0 generic { int TclExpatObjCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) } declare 1 generic { int CheckExpatParserObj (Tcl_Interp *interp, Tcl_Obj *const nameObj) } declare 2 generic { int CHandlerSetInstall (Tcl_Interp *interp, Tcl_Obj *const expatObj, CHandlerSet *handlerSet) } declare 3 generic { int CHandlerSetRemove (Tcl_Interp *interp, Tcl_Obj *const expatObj, char *handlerSetName) } declare 4 generic { CHandlerSet * CHandlerSetCreate (const char *name) } declare 5 generic { CHandlerSet * CHandlerSetGet (Tcl_Interp *interp, Tcl_Obj *const expatObj, char *handlerSetName) } declare 6 generic { void * CHandlerSetGetUserData (Tcl_Interp *interp, Tcl_Obj *const expatObj, char *handlerSetName) } declare 7 generic { TclGenExpatInfo * GetExpatInfo (Tcl_Interp *interp, Tcl_Obj *const expatObj) } declare 8 generic { XML_Size XML_GetCurrentLineNumber(XML_Parser parser) } declare 9 generic { XML_Size XML_GetCurrentColumnNumber(XML_Parser parser) } declare 10 generic { XML_Index XML_GetCurrentByteIndex(XML_Parser parser) } declare 11 generic { int XML_GetCurrentByteCount(XML_Parser parser) } declare 12 generic { enum XML_Status XML_SetBase(XML_Parser parser, const XML_Char *base) } declare 13 generic { const XML_Char * XML_GetBase(XML_Parser parser) } declare 14 generic { int XML_GetSpecifiedAttributeCount(XML_Parser parser) } declare 15 generic { int XML_GetIdAttributeIndex(XML_Parser parser) } declare 16 generic { domNode * tcldom_getNodeFromName(Tcl_Interp *interp, char *nodeName, char **errMsg) } declare 17 generic { domDocument * tcldom_getDocumentFromName (Tcl_Interp *interp, char *docName, char **errMsg) } declare 18 generic { SchemaData * tdomGetSchemadata (void) } tdom-0.9.5-src/generic/domalloc.c0000644000175000017500000005006414703531020015315 0ustar rolfrolf/*--------------------------------------------------------------------------- | Copyright (C) 1999-2000 Jochen C. Loewer (loewerj@hotmail.com) +---------------------------------------------------------------------------- | | A special memory allocator, which uses preallocated / bit masked | based administration of memory blocks with fixed sizes, like | DOM nodes. This will hopefully save some memory. | | | The contents of this file are subject to the Mozilla Public License | Version 2.0 (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) 1998, 1999 | Jochen Loewer. All Rights Reserved. | | Contributor(s): | | | written by Jochen Loewer | October, 2000 | \--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- | Includes | \--------------------------------------------------------------------------*/ #include #include #include #include /*--------------------------------------------------------------------------- | Defines | \--------------------------------------------------------------------------*/ #define DBG(x) #define MAX_BINS 256 #define BIN_HASH_SIZE 512 #define BIN_HASH_MASK 0x01FF #define CACHE_SIZE 4 #define BLOCK_DATA_SIZE 31000 #define BLOCK_SIZE_BITS 16 /*--------------------------------------------------------------------------- | Typedefs | \--------------------------------------------------------------------------*/ typedef struct domAllocBlock { struct domAllocBin * bin; void * end; struct domAllocBlock * prev; struct domAllocBlock * next; int hashIndex1; struct domAllocBlock * hashNext1; int hashIndex2; struct domAllocBlock * hashNext2; int slots; int freeSlots; int bitmaps; int freePos; int freeBit; unsigned int freeMask; } domAllocBlock; typedef struct domAllocBin { int size; int nrSlots; int freeSlots; int nrBlocks; domAllocBlock * freeBlocks; domAllocBlock * usedBlocks; } domAllocBin; typedef struct domAllocBins { struct domAllocBin * bin[MAX_BINS]; struct domAllocBlock * hashedBlocks[BIN_HASH_SIZE]; struct domAllocBlock * blockCache[CACHE_SIZE]; } domAllocBins; /*--------------------------------------------------------------------------- | Globals. This is a "single-threaded" allocator. | \--------------------------------------------------------------------------*/ static domAllocBins bins; #ifdef TCL_THREADS # define TDomThreaded(x) x static Tcl_Mutex binMutex; #else # define TDomThreaded(x) #endif /*--------------------------------------------------------------------------- | domAllocInit | \--------------------------------------------------------------------------*/ void domAllocInit() { int i; DBG(fprintf(stderr, "domAllocInit...\n");) for (i=0; i < MAX_BINS; i++) bins.bin[i] = NULL; for (i=0; i < CACHE_SIZE; i++) bins.blockCache[i] = NULL; for (i=0; i < BIN_HASH_SIZE; i++) bins.hashedBlocks[i] = NULL; } /*-------------------------------------------------------------------------- | fillHashTable | \--------------------------------------------------------------------------*/ static void fillHashTable ( domAllocBlock * block, void * mem ) { domAllocBlock * hashedBlock; unsigned int i; i = ( (unsigned int)mem >> BLOCK_SIZE_BITS) & BIN_HASH_MASK; hashedBlock = bins.hashedBlocks[i]; while (hashedBlock != NULL) { if (hashedBlock == block) { /* all is fine, block is already in hash table */ return; } if (hashedBlock->hashIndex1 == (int)i) hashedBlock = hashedBlock->hashNext1; else if (hashedBlock->hashIndex2 == (int)i) hashedBlock = hashedBlock->hashNext2; else hashedBlock = NULL; } /* add block in hash table */ if (block->hashIndex1 == -1) { block->hashIndex1 = i; block->hashNext1 = bins.hashedBlocks[i]; } else if (block->hashIndex2 == -1) { block->hashIndex2 = i; block->hashNext2 = bins.hashedBlocks[i]; } else { DBG( fprintf(stderr, "\ntoo many hash entries for %x %x->%d %d,%d!\n", (unsigned int)block, (unsigned int)mem, i, block->hashIndex1, block->hashIndex2);) } bins.hashedBlocks[i] = block; } /*-------------------------------------------------------------------------- | domAlloc | \--------------------------------------------------------------------------*/ void * domAlloc ( int size ) { domAllocBin * bin; domAllocBlock * block; domAllocBlock * hashedBlock; int i, j, slots, bitmaps, blockSize; unsigned int mask; char * mem; unsigned int * usedBitmap; DBG(fprintf(stderr, "\ndomAlloc %d \n", size);) if (size >= MAX_BINS) { DBG(fprintf(stderr, "\nSize too large as used for bin!\n");) return NULL; } /*------------------------------------------------- | FIXME | | Rewrite with TSD-based bins to avoid mutex | contention. Threads are going to step on | each other toes here which is not what we | would like to have, don't we ? (zv) \------------------------------------------------*/ TDomThreaded(Tcl_MutexLock(&binMutex);) /* LOCK !*/ if (bins.bin[size] == NULL) { /*------------------------------------------------- | create new bin \------------------------------------------------*/ bin = (domAllocBin *)malloc(sizeof(domAllocBin)); bin->size = size; bin->nrSlots = 0; bin->freeSlots = 0; bin->nrBlocks = 0; bin->freeBlocks = NULL; bin->usedBlocks = NULL; bins.bin[size] = bin; } else { bin = bins.bin[size]; } if (bin->freeSlots == 0) { DBG(fprintf(stderr, "allocating new block ... \n");) /*---------------------------------------------------------------- | allocate and initialize a new block | \---------------------------------------------------------------*/ bitmaps = (BLOCK_DATA_SIZE / size) / 32; slots = bitmaps * 32; blockSize = sizeof(domAllocBlock) + bitmaps*4 + slots*size; block = (domAllocBlock *)malloc( blockSize ); block->bin = bin; block->end = (char*)block + blockSize; block->slots = slots; block->freeSlots = slots; block->bitmaps = bitmaps; block->freePos = 0; block->freeBit = 0; block->freeMask = 0x80000000; block->hashIndex1 = -1; block->hashNext1 = NULL; block->hashIndex2 = -1; block->hashNext2 = NULL; usedBitmap = (unsigned int *) ((char*)block + sizeof(domAllocBlock)); memset(usedBitmap, 0, bitmaps * 4); bin->nrSlots += slots; bin->freeSlots += slots; bin->nrBlocks++; block->prev = NULL; /* prepend this new block to free list */ block->next = bin->freeBlocks; bin->freeBlocks = block; /*--------------------------------------------------------- | enter block in 'hash' table: | first and last memory location could have different | hash entries due to different upper address bits \--------------------------------------------------------*/ mem = (char*)usedBitmap + bitmaps * 4; fillHashTable (block, mem); mem += (slots-1) * size; fillHashTable (block, mem); } else { block = bin->freeBlocks; } /*------------------------------------------------------------------------ | find free slot in (partial) free block | \-----------------------------------------------------------------------*/ usedBitmap = (unsigned int *) ((char*)block + sizeof(domAllocBlock)); i = block->freePos; /* start at old pos to quickly find a free slot */ j = block->freeBit; mask = block->freeMask; do { DBG(fprintf(stderr, "looking %d slot i=%d j=%d %x mask %x\n", size, i, j, usedBitmap[i], mask); ) if (usedBitmap[i] != 0xFFFFFFFF) { do { if ((usedBitmap[i] & mask)==0) { DBG(fprintf(stderr, "found free slot i=%d j=%d %x mask %x\n", i, j, usedBitmap[i], mask); ) mem = ((char*)usedBitmap) + (4*block->bitmaps) + ((i*32)+j) * size; usedBitmap[i] |= mask; block->freeSlots--; bin->freeSlots--; if (block->freeSlots == 0) { DBG(fprintf(stderr, "freeSlots == 0\n");) if (block->prev == NULL) { /* remove block from free list */ bin->freeBlocks = block->next; } else { block->prev->next = block->next; } if (block->next) block->next->prev = block->prev; block->next = bin->usedBlocks; /* add block to used list */ if (block->next) block->next->prev = block; block->prev = NULL; bin->usedBlocks = block; /* check consistency */ hashedBlock = block->bin->freeBlocks; while (hashedBlock) { if (hashedBlock == block) { DBG(fprintf(stderr, "strange block still in free list \n");) } hashedBlock = hashedBlock->next; } } /* keep found free position for later, * so that next slots can be found quickly */ block->freePos = i; j++; mask = mask >> 1; if (j >= 32) { j = 0; mask = 0x80000000; } block->freeBit = j; block->freeMask = mask; TDomThreaded(Tcl_MutexUnlock(&binMutex);) /* UNLOCK !*/ return mem; } j++; mask = mask >> 1; if (j >= 32) { j = 0; mask = 0x80000000; } } while (j != block->freeBit); } i++; if (i >= block->bitmaps) i = 0; } while (i != block->freePos); /* TDomThreaded(Tcl_MutexUnlock(&binMutex);) */ DBG(fprintf(stderr, "\ndomAlloc: can't happen! \n");) *((char*)0) = 0; /* Use Tcl_Panic() for this ? */ return NULL; } /*--------------------------------------------------------------------------- | domFree | \--------------------------------------------------------------------------*/ void domFree ( void * mem ) { domAllocBlock * block; domAllocBlock * hashedBlock; domAllocBlock * prevBlock; domLength slotNr, i, foundInCache; unsigned int * usedBitmap; unsigned int mask; DBG(fprintf(stderr, "domFree...\n");) if (mem == NULL) return; /*------------------------------------------------- | FIXME (see domAlloc comments) | \------------------------------------------------*/ TDomThreaded(Tcl_MutexLock(&binMutex);) /*------------------------------------------------------------------- | Find the block, which corresponds to the given memory location | | - First try to look in the memory range cache. | \------------------------------------------------------------------*/ block = NULL; foundInCache = 0; for (i=0; i < CACHE_SIZE; i++) { if ((bins.blockCache[i] != NULL) && (mem > (void*)(bins.blockCache[i])) && (mem < (void*)(bins.blockCache[i]->end))) { block = bins.blockCache[i]; foundInCache = 1; break; } } /*------------------------------------------------------------------- | - Otherwise try to lookup corresponding block in hashtable | \------------------------------------------------------------------*/ if (!foundInCache) { i = ( (unsigned int)mem >> BLOCK_SIZE_BITS) & BIN_HASH_MASK; block = bins.hashedBlocks[i]; while (block != NULL) { if ((mem > (void*)block) && (mem < (void*)(block->end))) break; if (block->hashIndex1 == i) block = block->hashNext1; else if (block->hashIndex2 == i) block = block->hashNext2; else block = NULL; } } if (block == NULL) { DBG(fprintf(stderr, "\n unable to free mem %x !\n", (unsigned int)mem);) TDomThreaded(Tcl_MutexUnlock(&binMutex);) return; } /*------------------------------------------------------------------- | clear the allocation bit \------------------------------------------------------------------*/ usedBitmap = (unsigned int *) ((char*)block + sizeof(domAllocBlock)); slotNr = ( (char*)mem - (char*)usedBitmap - block->bitmaps*4 ) / block->bin->size; DBG( if (slotNr >= block->slots) { fprintf(stderr, "assertion failed: slotNr = %d \n", slotNr); }) i = slotNr >> 5 ; /* slotNr / 32 */ mask = 0x80000000 >> (slotNr % 32); usedBitmap[i] &= ~mask; block->freeSlots++; block->bin->freeSlots++; DBG( if ((block->freeSlots < 1) || (block->freeSlots > block->slots)) { fprintf(stderr, "assertion failed: freeSlots = %d \n", block->freeSlots); }) /*------------------------------------------------------------------- | update free/used lists \------------------------------------------------------------------*/ if (block->freeSlots == 1) { if (block->prev == NULL) { /* remove block from used list */ block->bin->usedBlocks = block->next; } else { block->prev->next = block->next; } if (block->next) block->next->prev = block->prev; block->next = block->bin->freeBlocks; /* add block to free list */ if (block->next) block->next->prev = block; block->prev = NULL; block->bin->freeBlocks = block; DBG( /* check consistency */ hashedBlock = block->bin->usedBlocks; while (hashedBlock) { if (hashedBlock == block) { fprintf(stderr, "strange block still in used list \n"); } hashedBlock = hashedBlock->next; } ) } /*------------------------------------------------------------------- | free the whole block, when all slots are freed \------------------------------------------------------------------*/ if (block->freeSlots == block->slots) { DBG(fprintf(stderr, "block completely freed %x\n", (unsigned int)block);) if (block->prev == NULL) { /* remove block from free list */ block->bin->freeBlocks = block->next; } else { block->prev->next = block->next; } if (block->next) block->next->prev = block->prev; block->bin->nrSlots -= block->slots; block->bin->freeSlots -= block->slots; block->bin->nrBlocks--; /*-------------------------------------------------------------------- | remove block from (two) hash lists \-------------------------------------------------------------------*/ i = block->hashIndex1; if (i != -1) { DBG(fprintf(stderr, "remove from hash list %d \n", i);) prevBlock = NULL; hashedBlock = bins.hashedBlocks[i]; while (hashedBlock) { if (hashedBlock == block) break; prevBlock = hashedBlock; if (hashedBlock->hashIndex1 == i) hashedBlock = hashedBlock->hashNext1; else if (hashedBlock->hashIndex2 == i) hashedBlock = hashedBlock->hashNext2; else hashedBlock = NULL; } if (prevBlock == NULL) { bins.hashedBlocks[i] = block->hashNext1; } else { if (prevBlock->hashIndex1 == i) prevBlock->hashNext1 = block->hashNext1; else if (prevBlock->hashIndex2 == i) prevBlock->hashNext2 = block->hashNext1; } } i = block->hashIndex2; if (i != -1) { DBG(fprintf(stderr, "remove from hash list %d \n", i);) prevBlock = NULL; hashedBlock = bins.hashedBlocks[i]; while (hashedBlock) { if (hashedBlock == block) break; prevBlock = hashedBlock; if (hashedBlock->hashIndex1 == i) hashedBlock = hashedBlock->hashNext1; else if (hashedBlock->hashIndex2 == i) hashedBlock = hashedBlock->hashNext2; else hashedBlock = NULL; } if (prevBlock == NULL) { bins.hashedBlocks[i] = block->hashNext2; } else { if (prevBlock->hashIndex1 == i) prevBlock->hashNext1 = block->hashNext2; else if (prevBlock->hashIndex2 == i) prevBlock->hashNext2 = block->hashNext2; } } /*------------------------------------------------------ | remove block from cache, if found \-----------------------------------------------------*/ for (i=0; i < CACHE_SIZE; i++) { if (bins.blockCache[i] == block) { bins.blockCache[i] = NULL; } } DBG( /* check consistency */ for (i=0; i < block->bitmaps; i++) { if (usedBitmap[i] != 0) { fprintf(stderr, "strange bitmap %d is %x \n", i, usedBitmap[i]); } } for (i=0; i < BIN_HASH_SIZE; i++) { hashedBlock = bins.hashedBlocks[i]; while (hashedBlock) { if (hashedBlock == block) { fprintf(stderr, "strange block %d still in hash table \n", i); } if (hashedBlock->hashIndex1 == i) hashedBlock = hashedBlock->hashNext1; else if (hashedBlock->hashIndex2 == i) hashedBlock = hashedBlock->hashNext2; else hashedBlock = NULL; } } hashedBlock = block->bin->freeBlocks; while (hashedBlock) { if (hashedBlock == block) { fprintf(stderr, "strange block still in free list \n"); } hashedBlock = hashedBlock->next; } hashedBlock = block->bin->usedBlocks; while (hashedBlock) { if (hashedBlock == block) { fprintf(stderr, "strange block still in used list \n"); } hashedBlock = hashedBlock->next; } ) free((char*)block); } else { /*----------------------------------------------------------- | update cache \----------------------------------------------------------*/ if (!foundInCache) { /* remove oldest entry and add this block */ for (i=1; i < CACHE_SIZE; i++) { bins.blockCache[i-1] = bins.blockCache[i]; } bins.blockCache[CACHE_SIZE-1] = block; } } TDomThreaded(Tcl_MutexUnlock(&binMutex);) /* UNLOCK !*/ } tdom-0.9.5-src/generic/tcldom.c0000644000175000017500000106701114703531020015006 0ustar rolfrolf/*---------------------------------------------------------------------------- | Copyright (c) 1999 Jochen Loewer (loewerj@hotmail.com) +----------------------------------------------------------------------------- | | A DOM implementation for Tcl using James Clark's expat XML parser | | | The contents of this file are subject to the Mozilla Public License | Version 2.0 (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) 1998, 1999 | Jochen Loewer. All Rights Reserved. | | Contributor(s): | Sept99 Carsten Zerbst Added comment and processing instructions | nodes. | June00 Zoran Vasiljevic Made thread-safe. | July00 Zoran Vasiljevic Added "domNode appendFromScript" | | | written by Jochen Loewer | April, 1999 | \---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- | Includes | \---------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include #include /* #define DEBUG */ /*---------------------------------------------------------------------------- | Debug Macros | \---------------------------------------------------------------------------*/ #ifdef DEBUG # define DBG(x) x #else # define DBG(x) #endif #ifndef C14N_ATTR_SORT_SIZE_INIT # define C14N_ATTR_SORT_SIZE_INIT 8 #endif /*---------------------------------------------------------------------------- | Macros | \---------------------------------------------------------------------------*/ #define XP_CHILD 0 #define XP_DESCENDANT 1 #define XP_ANCESTOR 2 #define XP_FSIBLING 3 #define XP_PSIBLING 4 #define MAX_REWRITE_ARGS 50 #define MAX_XSLT_APPLY_DEPTH 3000 #define SetResult(str) Tcl_ResetResult(interp); \ Tcl_SetStringObj(Tcl_GetObjResult(interp), (str), -1) #define SetResult3(str1,str2,str3) Tcl_ResetResult(interp); \ Tcl_AppendResult(interp, (str1), (str2), (str3), NULL) #define SetIntResult(i) Tcl_ResetResult(interp); \ Tcl_SetDomLengthObj(Tcl_GetObjResult(interp), (i)) #define SetLongResult(i) Tcl_ResetResult(interp); \ Tcl_SetLongObj(Tcl_GetObjResult(interp), (i)) #define SetDoubleResult(d) Tcl_ResetResult(interp); \ Tcl_SetDoubleObj(Tcl_GetObjResult(interp), (d)) #define SetBooleanResult(i) Tcl_ResetResult(interp); \ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), (i)) #define AppendResult(str) {Tcl_Obj *o = Tcl_GetObjResult(interp); \ if (Tcl_IsShared(o)) { \ o = Tcl_DuplicateObj(o); \ Tcl_SetObjResult(interp, o); \ } \ Tcl_AppendToObj(o, (str), -1);} #define CheckArgs(min,max,n,msg) \ if ((objc < min) || (objc >max)) { \ Tcl_WrongNumArgs(interp, n, objv, msg); \ return TCL_ERROR; \ } #define CheckName(interp, name, errText, isFQ) \ if (!TcldomDATA(dontCheckName)) { \ if (!tcldom_nameCheck(interp, name, errText, isFQ)) {\ return TCL_ERROR; \ } \ } #define CheckPIName(interp, name) \ if (!TcldomDATA(dontCheckName)) { \ if (!tcldom_PINameCheck(interp, name)) {\ return TCL_ERROR; \ } \ } #define CheckText(interp, text, errText) \ if (!TcldomDATA(dontCheckCharData)) { \ if (!tcldom_textCheck(interp, text, errText)) {\ return TCL_ERROR; \ } \ } #define CheckComment(interp, text) \ if (!TcldomDATA(dontCheckCharData)) { \ if (!tcldom_commentCheck(interp, text)) {\ return TCL_ERROR; \ } \ } #define CheckCDATA(interp, text) \ if (!TcldomDATA(dontCheckCharData)) { \ if (!tcldom_CDATACheck(interp, text)) {\ return TCL_ERROR; \ } \ } #define CheckPIValue(interp, text) \ if (!TcldomDATA(dontCheckCharData)) { \ if (!tcldom_PIValueCheck(interp, text)) {\ return TCL_ERROR; \ } \ } #define writeChars(var,chan,buf,len) (chan) ? \ ((void)Tcl_WriteChars ((chan), (buf), (len) )) : \ (Tcl_AppendToObj ((var), (buf), (len) )); #define DOM_CREATECMDMODE_AUTO 0 #define DOM_CREATECMDMODE_CMDS 1 #define DOM_CREATECMDMODE_TOKENS 2 #define SERIALIZE_XML_DECLARATION 1 #define SERIALIZE_DOCTYPE_DECLARATION 2 #define SERIALIZE_FOR_ATTR 4 #define SERIALIZE_ESCAPE_NON_ASCII 8 #define SERIALIZE_HTML_ENTITIES 16 #define SERIALIZE_ESCAPE_ALL_QUOT 32 #define SERIALIZE_NO_GT_ESCAPE 64 #define SERIALIZE_NO_EMPTY_ELEMENT_TAG 128 #define SERIALIZE_INDENT_WITH_TAB 256 #define SERIALIZE_INDENT_ATTR_WITH_TAB 512 #define SERIALIZE_ESCAPE_CR 1024 #define SERIALIZE_ESCAPE_TAB 2048 /*---------------------------------------------------------------------------- | Module Globals | \---------------------------------------------------------------------------*/ typedef struct TcldomData { int storeLineColumn; int dontCreateObjCommands; int dontCheckCharData; int dontCheckName; int domCreateCmdMode; } TcldomData; #define TcldomDATA(x) tdPtr->x #define GetTcldomDATA TcldomData *tdPtr = tcldom_getdata(interp) #ifdef TCL_THREADS static Tcl_HashTable sharedDocs; static Tcl_Mutex tableMutex; static int tcldomInitialized; #endif /* TCL_THREADS */ static const char *jsonTypes[] = { "NONE", "ARRAY", "OBJECT", "NULL", "TRUE", "FALSE", "STRING", "NUMBER", NULL }; /*---------------------------------------------------------------------------- | Types | \---------------------------------------------------------------------------*/ typedef struct XsltMsgCBInfo { Tcl_Interp * interp; Tcl_Obj * msgcmd; } XsltMsgCBInfo; static void UpdateStringOfTdomNode(Tcl_Obj *objPtr); static int SetTdomNodeFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); Tcl_ObjType tdomNodeType = { "tdom-node", NULL, NULL, UpdateStringOfTdomNode, SetTdomNodeFromAny }; /*---------------------------------------------------------------------------- | Prototypes for procedures defined later in this file: | \---------------------------------------------------------------------------*/ static Tcl_VarTraceProc tcldom_docTrace; static Tcl_CmdDeleteProc tcldom_docCmdDeleteProc; static void tcldom_treeAsJSON(Tcl_Obj *jstring, domNode *node, Tcl_Channel channel, int indent, int outputFlags, int level, int inside); #ifdef TCL_THREADS static int tcldom_EvalLocked(Tcl_Interp* interp, Tcl_Obj** objv, domDocument* doc, int flag); static int tcldom_RegisterDocShared(domDocument* doc); static int tcldom_CheckDocShared(domDocument* doc); static int tcldom_UnregisterDocShared(Tcl_Interp* interp, domDocument* doc); /*---------------------------------------------------------------------------- | tcldom_Finalize | | Activated in application exit handler to delete shared document table | Table entries are deleted by the object command deletion callbacks, | so at this time, table should be empty. If not, we will leave some | memory leaks. This is not fatal, though: we're exiting the app anyway. | This is a private function to this file. \---------------------------------------------------------------------------*/ static void tcldom_Finalize( ClientData UNUSED(unused) ) { DBG(fprintf(stderr, "--> tcldom_Finalize\n")); Tcl_MutexLock(&tableMutex); Tcl_DeleteHashTable(&sharedDocs); tcldomInitialized = 0; Tcl_MutexUnlock(&tableMutex); } /*---------------------------------------------------------------------------- | tcldom_initialize | Activated at module load to initialize shared document table. | This is exported since we need it in tdominit.c. \---------------------------------------------------------------------------*/ void tcldom_initialize(void) { if (!tcldomInitialized) { DBG(fprintf(stderr, "--> tcldom_initialize\n")); Tcl_MutexLock(&tableMutex); Tcl_InitHashTable(&sharedDocs, TCL_ONE_WORD_KEYS); Tcl_CreateExitHandler(tcldom_Finalize, NULL); tcldomInitialized = 1; Tcl_MutexUnlock(&tableMutex); } } #endif /* TCL_THREADS */ /*---------------------------------------------------------------------------- | tcldom_findata and tcldom_getdata | Some interpreter global information is managed in an assoc data struct. \---------------------------------------------------------------------------*/ static void tcldom_findata( ClientData clientData, Tcl_Interp *UNUSED(interp) ) { ckfree((char *) clientData); } static TDOM_INLINE TcldomData * tcldom_getdata( Tcl_Interp * interp ) { TcldomData *tdPtr = (TcldomData *) Tcl_GetAssocData(interp, "tdom_data", NULL); if (tdPtr == NULL) { tdPtr = (TcldomData *) ckalloc(sizeof(TcldomData)); memset(tdPtr, 0, sizeof(TcldomData)); Tcl_SetAssocData(interp, "tdom_data", tcldom_findata, (ClientData) tdPtr); } return tdPtr; } /*---------------------------------------------------------------------------- | tcldom_deleteNode | \---------------------------------------------------------------------------*/ static void tcldom_deleteNode ( domNode * node, void * clientData ) { Tcl_Interp *interp = clientData; char objCmdName[80]; /* Try to delete the node object commands, ignore errors */ if (node->nodeFlags & VISIBLE_IN_TCL) { NODE_CMD(objCmdName, node); Tcl_DeleteCommand(interp, objCmdName); node->nodeFlags &= ~VISIBLE_IN_TCL; } } /*---------------------------------------------------------------------------- | tcldom_deleteDoc | \---------------------------------------------------------------------------*/ void tcldom_deleteDoc ( Tcl_Interp * interp, domDocument * doc ) { int deleted = 1; if (doc->nodeFlags & INSIDE_FROM_SCRIPT) { doc->nodeFlags |= DELETE_AFTER_FROM_SCRIPT; return; } TDomThreaded(deleted = tcldom_UnregisterDocShared(interp, doc)); if (deleted) { domFreeDocument(doc, tcldom_deleteNode, interp); } } /*---------------------------------------------------------------------------- | tcldom_docCmdDeleteProc | \---------------------------------------------------------------------------*/ static void tcldom_docCmdDeleteProc( ClientData clientData ) { domDeleteInfo *dinfo = (domDeleteInfo *)clientData; domDocument *doc = dinfo->document; int hasTrace = dinfo->document->nodeFlags & VAR_TRACE; DBG(fprintf(stderr, "--> tcldom_docCmdDeleteProc doc %p\n", doc)); tcldom_deleteDoc(dinfo->interp, doc); if (hasTrace) { dinfo->document = NULL; } else { FREE((void*)dinfo); } } /*---------------------------------------------------------------------------- | tcldom_docTrace | \---------------------------------------------------------------------------*/ static char * tcldom_docTrace ( ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags ) { domDeleteInfo *dinfo = (domDeleteInfo*) clientData; domDocument *doc = dinfo->document; char objCmdName[80]; DBG(fprintf(stderr, "--> tcldom_docTrace %x %p\n", flags, doc)); if (doc == NULL) { if (!Tcl_InterpDeleted (interp)) { Tcl_UntraceVar(dinfo->interp, dinfo->traceVarName, TCL_TRACE_WRITES|TCL_TRACE_UNSETS, tcldom_docTrace, clientData); } FREE (dinfo->traceVarName); FREE (dinfo); return NULL; } if (flags & TCL_TRACE_WRITES) { DOC_CMD(objCmdName, doc); Tcl_SetVar2 (interp, name1, name2, objCmdName, TCL_LEAVE_ERR_MSG); return "var is read-only"; } if (flags & TCL_TRACE_UNSETS) { DOC_CMD(objCmdName, doc); DBG(fprintf(stderr, "--> tcldom_docTrace delete doc %p\n", doc)); Tcl_DeleteCommand(interp, objCmdName); FREE (dinfo->traceVarName); FREE (dinfo); } return NULL; } /*---------------------------------------------------------------------------- | UpdateStringOfTdomNode | \---------------------------------------------------------------------------*/ static void UpdateStringOfTdomNode( Tcl_Obj *objPtr) { char nodeName[80]; domLength len; NODE_CMD(nodeName, objPtr->internalRep.otherValuePtr); len = (domLength)strlen(nodeName); objPtr->bytes = (ckalloc((unsigned char) len+1)); memcpy(objPtr->bytes, nodeName, len+1); objPtr->length = len; } /*---------------------------------------------------------------------------- | SetTdomNodeFromAny | \---------------------------------------------------------------------------*/ static int SetTdomNodeFromAny( Tcl_Interp *interp, /* Tcl interpreter or NULL */ Tcl_Obj *objPtr) /* Pointer to the object to parse */ { Tcl_CmdInfo cmdInfo; domNode *node = NULL; char *nodeName; char eolcheck; if (objPtr->typePtr == &tdomNodeType) { return TCL_OK; } nodeName = Tcl_GetString(objPtr); if (strncmp(nodeName, "domNode", 7)) { if (interp) { SetResult3("Parameter \"", nodeName, "\" is not a domNode."); return TCL_ERROR; } } if (sscanf(&nodeName[7], "%p%1c", (void **)&node, &eolcheck) != 1) { if (!Tcl_GetCommandInfo(interp, nodeName, &cmdInfo)) { if (interp) { SetResult3("Parameter \"", nodeName, "\" is not a domNode."); return TCL_ERROR; } } if ( (cmdInfo.isNativeObjectProc == 0) || (cmdInfo.objProc != (Tcl_ObjCmdProc*)tcldom_NodeObjCmd)) { if (interp) { SetResult3("Parameter \"", nodeName, "\" is not a domNode" " object command"); return TCL_ERROR; } } node = (domNode*)cmdInfo.objClientData; } if (objPtr->typePtr && objPtr->typePtr->freeIntRepProc) { objPtr->typePtr->freeIntRepProc(objPtr); } objPtr->internalRep.otherValuePtr = node; objPtr->typePtr = &tdomNodeType; return TCL_OK; } /*---------------------------------------------------------------------------- | tcldom_createNodeObj | \---------------------------------------------------------------------------*/ void tcldom_createNodeObj ( Tcl_Interp * interp, domNode * node, char * objCmdName ) { GetTcldomDATA; NODE_CMD(objCmdName, node); if (TcldomDATA(dontCreateObjCommands) == 0) { DBG(fprintf(stderr,"--> creating node %s\n", objCmdName)); Tcl_CreateObjCommand(interp, objCmdName, (Tcl_ObjCmdProc *) tcldom_NodeObjCmd, (ClientData) node, (Tcl_CmdDeleteProc*)NULL); node->nodeFlags |= VISIBLE_IN_TCL; } } /*---------------------------------------------------------------------------- | tcldom_setInterpAndReturnVar | \---------------------------------------------------------------------------*/ int tcldom_setInterpAndReturnVar ( Tcl_Interp *interp, domNode *node, Tcl_Obj *var_name ) { char objCmdName[80]; Tcl_Obj *resultObj; GetTcldomDATA; if (node == NULL) { if (var_name) { if (!Tcl_ObjSetVar2 (interp, var_name, NULL, Tcl_NewStringObj("",0), TCL_LEAVE_ERR_MSG)) { return TCL_ERROR; } } SetResult(""); return TCL_OK; } resultObj = Tcl_NewObj(); resultObj->bytes = NULL; resultObj->length = 0; resultObj->internalRep.otherValuePtr = node; resultObj->typePtr = &tdomNodeType; Tcl_SetObjResult (interp, resultObj); if (TcldomDATA(dontCreateObjCommands) == 0) { tcldom_createNodeObj(interp, node, objCmdName); } if (var_name) { if (!Tcl_ObjSetVar2 (interp, var_name, NULL, resultObj, TCL_LEAVE_ERR_MSG)) { return TCL_ERROR; } } return TCL_OK; } /*---------------------------------------------------------------------------- | tcldom_returnNodeObj | \---------------------------------------------------------------------------*/ static Tcl_Obj *tcldom_returnNodeObj ( Tcl_Interp *interp, domNode *node) { char objCmdName[80]; Tcl_Obj *resultObj; GetTcldomDATA; resultObj = Tcl_NewObj(); if (node == NULL) { return resultObj; } if (TcldomDATA(dontCreateObjCommands) == 0) { tcldom_createNodeObj(interp, node, objCmdName); } resultObj->bytes = NULL; resultObj->length = 0; resultObj->internalRep.otherValuePtr = node; resultObj->typePtr = &tdomNodeType; return resultObj; } /*---------------------------------------------------------------------------- | tcldom_returnDocumentObj | \---------------------------------------------------------------------------*/ int tcldom_returnDocumentObj ( Tcl_Interp *interp, domDocument *document, Tcl_Obj *var_name, int trace, int forOwnerDocument ) { char objCmdName[80], *objVar; domDeleteInfo *dinfo; Tcl_CmdInfo cmd_info; GetTcldomDATA; if (document == NULL) { if (var_name) { objVar = Tcl_GetString(var_name); Tcl_UnsetVar(interp, objVar, 0); Tcl_SetVar (interp, objVar, "", 0); } SetResult(""); return TCL_OK; } DOC_CMD(objCmdName, document); if (TcldomDATA(dontCreateObjCommands)) { if (var_name) { objVar = Tcl_GetString(var_name); Tcl_SetVar(interp, objVar, objCmdName, 0); } } else { if (!Tcl_GetCommandInfo(interp, objCmdName, &cmd_info)) { dinfo = (domDeleteInfo*)MALLOC(sizeof(domDeleteInfo)); dinfo->interp = interp; dinfo->document = document; document->nodeFlags |= DOCUMENT_CMD; dinfo->traceVarName = NULL; Tcl_CreateObjCommand(interp, objCmdName, (Tcl_ObjCmdProc *) tcldom_DocObjCmd, (ClientData) dinfo, (Tcl_CmdDeleteProc*)tcldom_docCmdDeleteProc); } else { dinfo = (domDeleteInfo*)cmd_info.objClientData; } if (var_name) { objVar = Tcl_GetString(var_name); Tcl_UnsetVar(interp, objVar, 0); Tcl_SetVar (interp, objVar, objCmdName, 0); if (trace) { document->nodeFlags |= VAR_TRACE; dinfo->traceVarName = tdomstrdup(objVar); Tcl_TraceVar(interp,objVar,TCL_TRACE_WRITES|TCL_TRACE_UNSETS, (Tcl_VarTraceProc*)tcldom_docTrace, (ClientData)dinfo); } } } if (!forOwnerDocument) { TDomThreaded(tcldom_RegisterDocShared(document)); } SetResult(objCmdName); return TCL_OK; } /*---------------------------------------------------------------------------- | tcldom_getElementsByTagName | \---------------------------------------------------------------------------*/ static int tcldom_getElementsByTagName ( Tcl_Interp *interp, char *namePattern, domNode *node, int nsIndex, const char *uri ) { int result; domNode *child; char prefix[MAX_PREFIX_LEN]; const char *localName; Tcl_Obj *namePtr, *resultPtr; /* nsIndex == -1 ==> DOM 1 no NS i.e getElementsByTagName nsIndex != -1 are the NS aware cases nsIndex == -2 ==> more than one namespace in the document with the requested namespace, we have to strcmp the URI with the namespace uri of every node nsIndex == -3 ==> NS wildcard '*' nsIndex == -4 ==> special handled case uri == "", i.e. all nodes not in a namespace */ while (node) { if (node->nodeType != ELEMENT_NODE) { node = node->nextSibling; continue; } if ( (nsIndex == -1) || (nsIndex == (int)node->namespace) || (nsIndex == -3) || (nsIndex == -2 && node->namespace && strcmp(uri, domNamespaceURI (node)) == 0) || (nsIndex == -4 && (!node->namespace || strcmp ("", domNamespaceURI (node))==0)) ) { if (nsIndex == -1) { localName = node->nodeName; } else { domSplitQName(node->nodeName, prefix, &localName); } if (Tcl_StringMatch(localName, namePattern)) { resultPtr = Tcl_GetObjResult(interp); namePtr = tcldom_returnNodeObj(interp, node); result = Tcl_ListObjAppendElement(interp, resultPtr, namePtr); if (result != TCL_OK) { Tcl_DecrRefCount(namePtr); return result; } } } /* recurs to the child nodes */ child = node->firstChild; result = tcldom_getElementsByTagName(interp, namePattern, child, nsIndex, uri); if (result != TCL_OK) { return result; } node = node->nextSibling; } return TCL_OK; } /*---------------------------------------------------------------------------- | tcldom_find | \---------------------------------------------------------------------------*/ static domNode * tcldom_find ( domNode *node, char *attrName, char *attrVal, domLength length ) { domNode *child, *result; domAttrNode *attrs; if (node->nodeType != ELEMENT_NODE) return NULL; attrs = node->firstAttr; while (attrs) { if ((strcmp(attrs->nodeName, attrName)==0) && (length == attrs->valueLength) && (strncmp(attrs->nodeValue, attrVal, length)==0)) { return node; } attrs = attrs->nextSibling; } child = node->firstChild; while (child != NULL) { result = tcldom_find(child, attrName, attrVal, length); if (result != NULL) { return result; } child = child->nextSibling; } return NULL; } /*---------------------------------------------------------------------------- | tcldom_xpointerAddCallback | \---------------------------------------------------------------------------*/ static int tcldom_xpointerAddCallback ( domNode * node, void * clientData ) { Tcl_Interp * interp = (Tcl_Interp*)clientData; Tcl_Obj * resultPtr = Tcl_GetObjResult(interp); Tcl_Obj * namePtr; int result; namePtr = tcldom_returnNodeObj(interp, node); result = Tcl_ListObjAppendElement(interp, resultPtr, namePtr); if (result != TCL_OK) { Tcl_DecrRefCount(namePtr); } return result; } /*---------------------------------------------------------------------------- | tcldom_xpointerSearch | \---------------------------------------------------------------------------*/ static int tcldom_xpointerSearch ( Tcl_Interp * interp, int mode, domNode * node, int objc, Tcl_Obj * const objv[] ) { char *str; int i = 0; int result = 0; int all = 0; int instance = 0; int type = ELEMENT_NODE; char *element = NULL; char *attrName = NULL; char *attrValue = NULL; domLength attrLen; str = Tcl_GetString(objv[2]); if (strcmp(str, "all")==0) { all = 1; } else { if (Tcl_GetIntFromObj(interp, objv[2], &instance) != TCL_OK) { SetResult( "instance must be integer or 'all'"); return TCL_ERROR; } } if (objc > 3) { str = Tcl_GetString(objv[3]); if (*str == '#') { if (strcmp(str,"#text")==0) { type = TEXT_NODE; } else if (strcmp(str,"#cdata")==0) { type = CDATA_SECTION_NODE; } else if (strcmp(str,"#all")==0) { type = ALL_NODES; } else if (strcmp(str,"#element")==0) { type = ELEMENT_NODE; } else { SetResult( "wrong node type"); return TCL_ERROR; } } else { element = str; } } if (objc >= 5) { if ((type != ELEMENT_NODE) && (type != ALL_NODES)) { SetResult( "Attribute search only for element nodes"); return TCL_ERROR; } attrName = Tcl_GetString(objv[4]); if (objc == 6) { attrValue = Tcl_GetStringFromObj(objv[5], &attrLen); } else { attrValue = "*"; attrLen = 1; } } Tcl_ResetResult(interp); switch (mode) { case XP_CHILD: result = domXPointerChild (node, all, instance, type, element, attrName, attrValue, attrLen, tcldom_xpointerAddCallback, interp); break; case XP_DESCENDANT: result = domXPointerDescendant (node, all, instance, &i, type, element, attrName, attrValue, attrLen, tcldom_xpointerAddCallback, interp); break; case XP_ANCESTOR: result = domXPointerAncestor (node, all, instance, &i, type, element, attrName, attrValue, attrLen, tcldom_xpointerAddCallback, interp); break; case XP_FSIBLING: result = domXPointerXSibling (node, 1, all, instance, type, element, attrName, attrValue, attrLen, tcldom_xpointerAddCallback, interp); break; case XP_PSIBLING: result = domXPointerXSibling (node, 0, all, instance, type, element, attrName, attrValue, attrLen, tcldom_xpointerAddCallback, interp); break; } if (result != 0) { return TCL_ERROR; } return TCL_OK; } /*---------------------------------------------------------------------------- | tcldom_getNodeFromObj | \---------------------------------------------------------------------------*/ domNode * tcldom_getNodeFromObj ( Tcl_Interp *interp, Tcl_Obj *nodeObj ) { Tcl_CmdInfo cmdInfo; domNode *node = NULL; char *nodeName; char eolcheck; GetTcldomDATA; if (nodeObj->typePtr == &tdomNodeType) { return (domNode*)nodeObj->internalRep.otherValuePtr; } if (TcldomDATA(dontCreateObjCommands)) { if (SetTdomNodeFromAny (interp, nodeObj) == TCL_OK) { return (domNode*)nodeObj->internalRep.otherValuePtr; } return NULL; } nodeName = Tcl_GetString(nodeObj); if (strncmp(nodeName, "domNode", 7)) { SetResult3("Parameter \"", nodeName, "\" is not a domNode."); return NULL; } if (sscanf(&nodeName[7], "%p%1c", (void **)&node, &eolcheck) != 1) { if (!Tcl_GetCommandInfo(interp, nodeName, &cmdInfo)) { SetResult3("Parameter \"", nodeName, "\" is not a domNode."); return NULL; } if ( (cmdInfo.isNativeObjectProc == 0) || (cmdInfo.objProc != (Tcl_ObjCmdProc*)tcldom_NodeObjCmd)) { SetResult3("Parameter \"", nodeName, "\" is not a domNode" " object command."); return NULL; } node = (domNode*)cmdInfo.objClientData; } return node; } /*---------------------------------------------------------------------------- | tcldom_getNodeFromName | \---------------------------------------------------------------------------*/ domNode * tcldom_getNodeFromName ( Tcl_Interp *interp, char *nodeName, char **errMsg ) { Tcl_CmdInfo cmdInfo; domNode *node = NULL; char eolcheck; if (strncmp(nodeName, "domNode", 7)) { *errMsg = "parameter not a domNode!"; return NULL; } if (sscanf(&nodeName[7], "%p%1c", (void **)&node, &eolcheck) != 1) { if (!Tcl_GetCommandInfo(interp, nodeName, &cmdInfo)) { *errMsg = "parameter not a domNode!"; return NULL; } if ( (cmdInfo.isNativeObjectProc == 0) || (cmdInfo.objProc != (Tcl_ObjCmdProc*)tcldom_NodeObjCmd)) { *errMsg = "parameter not a domNode object command!"; return NULL; } node = (domNode*)cmdInfo.objClientData; } return node; } /*---------------------------------------------------------------------------- | tcldom_getDocumentFromName | \---------------------------------------------------------------------------*/ domDocument * tcldom_getDocumentFromName ( Tcl_Interp *interp, char *docName, char **errMsg ) { Tcl_CmdInfo cmdInfo; domDocument *doc = NULL; int shared = 1; char eolcheck; if (strncmp(docName, "domDoc", 6)) { *errMsg = "parameter not a domDoc!"; return NULL; } if (sscanf(&docName[6], "%p%1c", (void **)&doc, &eolcheck) != 1) { if (!Tcl_GetCommandInfo(interp, docName, &cmdInfo)) { *errMsg = "parameter not a domDoc!"; return NULL; } if ( (cmdInfo.isNativeObjectProc == 0) || (cmdInfo.objProc != (Tcl_ObjCmdProc*)tcldom_DocObjCmd)) { *errMsg = "parameter not a domDoc object command!"; return NULL; } doc = ((domDeleteInfo*)cmdInfo.objClientData)->document; } TDomThreaded(shared = tcldom_CheckDocShared(doc)); if (!shared) { *errMsg = "parameter not a shared domDoc!"; return NULL; } return doc; } /*---------------------------------------------------------------------------- | tcldom_appendXML | \---------------------------------------------------------------------------*/ int tcldom_appendXML ( Tcl_Interp *interp, domNode *node, Tcl_Obj *obj ) { char *xml_string; Tcl_Obj *extResolver = NULL; domLength xml_string_len; int resultcode = 0; int ignorexmlns = 0; domDocument *doc; domNode *nodeToAppend; XML_Parser parser; domParseForestErrorData forestError; GetTcldomDATA; xml_string = Tcl_GetStringFromObj(obj, &xml_string_len); #ifdef TDOM_NO_EXPAT SetResult("tDOM was compiled without Expat!"); return TCL_ERROR; #else parser = XML_ParserCreate_MM(NULL, MEM_SUITE, NULL); if (node->ownerDocument->extResolver) { extResolver = Tcl_NewStringObj(node->ownerDocument->extResolver, -1); Tcl_IncrRefCount (extResolver); } if (node->ownerDocument->nodeFlags & IGNORE_XMLNS) { ignorexmlns = 1; } doc = domReadDocument(parser, xml_string, xml_string_len, 1, 0, TcldomDATA(storeLineColumn), ignorexmlns, 0, NULL, NULL, NULL, extResolver, 0, 0, (int) XML_PARAM_ENTITY_PARSING_ALWAYS, #ifndef TDOM_NO_SCHEMA NULL, #endif interp, &forestError, &resultcode); if (extResolver) { Tcl_DecrRefCount(extResolver); } if (doc == NULL) { tcldom_reportErrorLocation ( interp, 20, 40, XML_GetCurrentLineNumber(parser), XML_GetCurrentColumnNumber(parser), xml_string, NULL, XML_GetCurrentByteIndex(parser), XML_ErrorString(XML_GetErrorCode(parser))); XML_ParserFree(parser); return TCL_ERROR; } XML_ParserFree(parser); nodeToAppend = doc->rootNode->firstChild; while (nodeToAppend) { domAppendChild(node, nodeToAppend); nodeToAppend = nodeToAppend->nextSibling; } domFreeDocument(doc, NULL, NULL); return tcldom_setInterpAndReturnVar(interp, node, NULL); #endif } /*---------------------------------------------------------------------------- | tcldom_xpathResultSet | \---------------------------------------------------------------------------*/ static int tcldom_xpathResultSet ( Tcl_Interp *interp, xpathResultSet *rs, xpathResultType *type, Tcl_Obj *value ) { int rc, i; Tcl_Obj *namePtr, *objv[2]; domAttrNode *attr; domNodeType startType; int mixedNodeSet; switch (rs->type) { case EmptyResult: *type = EmptyResult; Tcl_SetStringObj(value, "", -1); break; case BoolResult: *type = BoolResult; Tcl_SetIntObj(value, rs->intvalue); break; case IntResult: *type = IntResult; Tcl_SetLongObj(value, rs->intvalue); break; case RealResult: *type = RealResult; Tcl_SetDoubleObj(value, rs->realvalue); break; case NaNResult: *type = NaNResult; Tcl_SetStringObj(value, "NaN", -1); break; case InfResult: *type = InfResult; Tcl_SetStringObj(value, "Infinity", -1); break; case NInfResult: *type = NInfResult; Tcl_SetStringObj(value, "-Infinity", -1); break; case StringResult: *type = StringResult; Tcl_SetStringObj(value, rs->string, rs->string_len); break; case xNodeSetResult: startType = rs->nodes[0]->nodeType; mixedNodeSet = 0; for (i=0; inr_nodes; i++) { if (rs->nodes[i]->nodeType != startType) mixedNodeSet = 1; if (rs->nodes[i]->nodeType == ATTRIBUTE_NODE) { attr = (domAttrNode*)rs->nodes[i]; objv[0] = Tcl_NewStringObj(attr->nodeName, -1); objv[1] = Tcl_NewStringObj(attr->nodeValue, attr->valueLength); namePtr = Tcl_NewListObj(2, objv); } else { namePtr = tcldom_returnNodeObj(interp, rs->nodes[i]); } rc = Tcl_ListObjAppendElement(interp, value, namePtr); if (rc != TCL_OK) { Tcl_DecrRefCount(namePtr); return rc; } } if (mixedNodeSet) { *type = MixedResult; } else { if (startType == ATTRIBUTE_NODE) *type = AttrnodesResult; else *type = NodesResult; } break; default: Tcl_Panic("Invalid xpathResultType %s in tcldom_xpathResultSet!", xpathResultType2string(rs->type)); break; } return TCL_OK; } /*---------------------------------------------------------------------------- | tcldom_xpathFuncCallBack | \---------------------------------------------------------------------------*/ int tcldom_xpathFuncCallBack ( void *clientData, char *functionName, domNode *ctxNode, domLength position, xpathResultSet *nodeList, domNode *UNUSED(exprContext), int argc, xpathResultSets *args, xpathResultSet *result, char **errMsg ) { Tcl_Interp *interp = (Tcl_Interp*) clientData; char tclxpathFuncName[220], objCmdName[80]; char *errStr, *typeStr; Tcl_Obj *resultPtr, *objv[MAX_REWRITE_ARGS], *type, *value, *nodeObj, *tmpObj; Tcl_CmdInfo cmdInfo; int objc, rc, res, boolValue; domLength errStrLen, listLen, i, longValue; xpathResultType rstype; double doubleValue; domNode *node; DBG(fprintf(stderr, "tcldom_xpathFuncCallBack functionName=%s " "position=%d argc=%d\n", functionName, position, argc);) if (strlen(functionName) > 200) { *errMsg = (char*)MALLOC (80 + strlen (functionName)); strcpy (*errMsg, "Unreasonable long XPath function name: \""); strcat (*errMsg, functionName); strcat (*errMsg, "\"!"); return XPATH_EVAL_ERR; } sprintf (tclxpathFuncName, "::dom::xpathFunc::%s", functionName); DBG(fprintf(stderr, "testing %s\n", tclxpathFuncName);) rc = Tcl_GetCommandInfo (interp, tclxpathFuncName, &cmdInfo); if (!rc) { *errMsg = (char*)MALLOC (80 + strlen (functionName)); strcpy (*errMsg, "Unknown XPath function: \""); strcat (*errMsg, functionName); strcat (*errMsg, "\"!"); return XPATH_EVAL_ERR; } if (!cmdInfo.isNativeObjectProc) { *errMsg = (char*)tdomstrdup("can't access Tcl level method!"); return XPATH_EVAL_ERR; } if ( (5+(2*argc)) >= MAX_REWRITE_ARGS) { *errMsg = (char*)tdomstrdup("too many args for Tcl level method!"); return XPATH_EVAL_ERR; } objc = 0; objv[objc] = Tcl_NewStringObj(tclxpathFuncName, -1); Tcl_IncrRefCount(objv[objc++]); if (ctxNode->nodeType == ATTRIBUTE_NODE) { tcldom_createNodeObj(interp, ((domAttrNode*)ctxNode)->parentNode, objCmdName); tmpObj = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(interp, tmpObj, Tcl_NewStringObj(objCmdName, -1)); Tcl_ListObjAppendElement( interp, tmpObj, Tcl_NewStringObj(((domAttrNode*)ctxNode)->nodeName, -1)); } else { tmpObj = tcldom_returnNodeObj(interp, ctxNode); } objv[objc] = tmpObj; Tcl_IncrRefCount(objv[objc++]); objv[objc] = Tcl_NewIntObj(position); Tcl_IncrRefCount(objv[objc++]); value = Tcl_NewObj(); tcldom_xpathResultSet(interp, nodeList, &rstype, value); objv[objc] = Tcl_NewStringObj(xpathResultType2string(rstype), -1); Tcl_IncrRefCount(objv[objc++]); objv[objc] = value; Tcl_IncrRefCount(objv[objc++]); for (i=0; i returning XPATH_EVAL_ERR \n");) res = XPATH_EVAL_ERR; goto funcCallCleanup; } Tcl_ResetResult(interp); res = XPATH_OK; } else { errStr = Tcl_GetStringFromObj( Tcl_GetObjResult(interp), &errStrLen); *errMsg = (char*)MALLOC(120+strlen(functionName) + errStrLen); strcpy(*errMsg, "Tcl error while executing XPath extension function '"); strcat(*errMsg, functionName ); strcat(*errMsg, "':\n" ); strcat(*errMsg, errStr); Tcl_ResetResult(interp); DBG(fprintf(stderr, "returning XPATH_EVAL_ERR \n");) res = XPATH_EVAL_ERR; } funcCallCleanup: for (i = 0; i < objc; i++) { Tcl_DecrRefCount(objv[i]); } return res; } /*---------------------------------------------------------------------------- | tcldom_xsltMsgCB | \---------------------------------------------------------------------------*/ static int tcldom_xsltMsgCB ( void *clientData, char *str, domLength length, int terminate ) { XsltMsgCBInfo *msgCBInfo = (XsltMsgCBInfo *)clientData; Tcl_Obj *cmdPtr; int rc; if (msgCBInfo->msgcmd == NULL) { return 0; } cmdPtr = Tcl_DuplicateObj(msgCBInfo->msgcmd); Tcl_IncrRefCount(cmdPtr); if (Tcl_ListObjAppendElement(msgCBInfo->interp, cmdPtr, Tcl_NewStringObj(str, length)) != TCL_OK) { Tcl_DecrRefCount(cmdPtr); return 1; } if (terminate) { Tcl_ListObjAppendElement(msgCBInfo->interp, cmdPtr, Tcl_NewBooleanObj(1)); } else { Tcl_ListObjAppendElement(msgCBInfo->interp, cmdPtr, Tcl_NewBooleanObj(0)); } rc = Tcl_GlobalEvalObj(msgCBInfo->interp, cmdPtr); Tcl_DecrRefCount(cmdPtr); switch (rc) { case TCL_OK: return 0; case TCL_BREAK: return 3; default: return rc; } } /*---------------------------------------------------------------------------- | tcldom_xpathResolveVar | \---------------------------------------------------------------------------*/ static char * tcldom_xpathResolveVar ( void *clientData, char *strToParse, domLength *offset, char **errMsg ) { const char *varValue; const char *termPtr; Tcl_Interp *interp = (Tcl_Interp *) clientData; *offset = 0; varValue = Tcl_ParseVar(interp, strToParse, &termPtr); if (varValue) { *offset = (domLength)(termPtr - strToParse); /* If strToParse start with a single '$' without a following * var name (according to Tcl var name rules), Tcl_ParseVar() * doesn't report a parsing error but returns just a pointer * to a static string "$". */ if (*offset == 1) { *errMsg = tdomstrdup ("Missing var name after '$'."); varValue = NULL; } } else { *errMsg = tdomstrdup (Tcl_GetStringResult(interp)); } Tcl_ResetResult (interp); return (char*)varValue; } static int selectNodesQueryList ( Tcl_Interp * interp, domNode * node, Tcl_Obj * queryList, ast tt, domLength queryListInd, domLength queryListLen, char ** prefixMappings, xpathCBs * cbs, xpathParseVarCB * parseVarCB, Tcl_HashTable * cache, Tcl_Obj * result, xpathResultType * type ) { Tcl_Obj *queryObj, *thisResult; char *query, *errMsg = NULL; xpathResultSet nodeList, rs; int rc, hnew = 1, docOrder = 1, i; ast t; Tcl_HashEntry *h = NULL; xpathResultType rstype; xpathRSInit( &nodeList); rsAddNodeFast( &nodeList, node); xpathRSInit(&rs); rc = xpathEvalSteps( tt, &nodeList, node, node, 0, &docOrder, cbs, &rs, &errMsg); xpathRSFree( &nodeList ); if (rc) { Tcl_ResetResult (interp); Tcl_AppendResult (interp, "invalid XPath query: '", errMsg, "'", NULL); if (errMsg) { FREE(errMsg); } xpathRSFree( &rs ); return TCL_ERROR; } queryListInd++; if (queryListInd < queryListLen) { if (rs.type != xNodeSetResult && rs.type != EmptyResult) { Tcl_ResetResult (interp); Tcl_AppendResult (interp, "only the last XPath query in the query " "list is allowed to select something else then " "nodes", NULL); xpathRSFree( &rs ); return TCL_ERROR; } if (rs.type == EmptyResult) { if (*type) { if (*type != EmptyResult) { *type = MixedResult; } } else { *type = EmptyResult; } return TCL_OK; } Tcl_ListObjIndex(interp, queryList, queryListInd, &queryObj); query = Tcl_GetString (queryObj); if (cache) { h = Tcl_CreateHashEntry (cache, query, &hnew); } if (hnew) { rc = xpathParse(query, node, XPATH_EXPR, prefixMappings, parseVarCB, &t, &errMsg); if (rc) { if (h != NULL) { Tcl_DeleteHashEntry(h); } Tcl_ResetResult (interp); Tcl_AppendResult (interp, "invalid XPath query '", query, "': ", errMsg, NULL); FREE (errMsg); xpathRSFree( &rs ); return TCL_ERROR; } if (cache) { Tcl_SetHashValue(h, t); } } else { t = (ast)Tcl_GetHashValue(h); } rc = TCL_OK; for (i=0; i < rs.nr_nodes; i++) { rc = selectNodesQueryList (interp, rs.nodes[i], queryList, t, queryListInd, queryListLen, prefixMappings, cbs, parseVarCB, cache, result, type); if (rc != TCL_OK) { break; } } if (!cache) { xpathFreeAst(t); } if (rc != TCL_OK) { xpathRSFree (&rs); return TCL_ERROR; } } else { thisResult = Tcl_NewListObj (0, NULL); Tcl_IncrRefCount (thisResult); tcldom_xpathResultSet(interp, &rs, &rstype, thisResult); Tcl_ListObjAppendElement (interp, result, thisResult); if (*type) { if (*type != rstype) { *type = MixedResult; } } else { *type = rstype; } Tcl_DecrRefCount (thisResult); } xpathRSFree (&rs); return TCL_OK; } /*---------------------------------------------------------------------------- | tcldom_selectNodes | \---------------------------------------------------------------------------*/ static int tcldom_selectNodes ( Tcl_Interp *interp, domNode *node, int objc, Tcl_Obj *const objv[] ) { char *xpathQuery, *typeVar, *option, *query; char *errMsg = NULL, **mappings = NULL; int rc, optionIndex, localmapping = 0, cache = 0; int list = 0, hnew; domLength i, len, xpathListLen, mappingListObjLen = 0; xpathResultSet rs; Tcl_Obj *objPtr, *objPtr1, *mappingListObj = NULL; Tcl_Obj *queryObj, *result; xpathCBs cbs; xpathParseVarCB parseVarCB; Tcl_HashTable *xpathCache = NULL; Tcl_HashEntry *h = NULL; ast t; xpathResultType rstype; static const char *selectNodesOptions[] = { "-namespaces", "-cache", "-list", NULL }; enum selectNodesOption { o_namespaces, o_cache, o_list }; if (objc < 2) { SetResult("Wrong # of arguments."); return TCL_ERROR; } while (objc > 2) { option = Tcl_GetString (objv[1]); if (option[0] != '-') { break; } if (Tcl_GetIndexFromObj (NULL, objv[1], selectNodesOptions, "option", 0, &optionIndex) != TCL_OK) { break; } switch ((enum selectNodesOption) optionIndex) { case o_namespaces: rc = Tcl_ListObjLength (interp, objv[2], &len); if (rc != TCL_OK || (len % 2) != 0) { SetResult ("The \"-namespaces\" option requires a 'prefix" " namespace' pairs list as argument"); rc = TCL_ERROR; goto cleanup; } if (mappings) { for (i = 0; i < mappingListObjLen; i++) { Tcl_ListObjIndex (interp, mappingListObj, i, &objPtr1); Tcl_DecrRefCount (objPtr1); } Tcl_DecrRefCount (mappingListObj); FREE (mappings); } mappings = MALLOC (sizeof (char *) * (len + 1)); localmapping = 1; for (i = 0; i < len; i++) { Tcl_ListObjIndex (interp, objv[2], i, &objPtr); Tcl_IncrRefCount (objPtr); mappings[i] = Tcl_GetString (objPtr); } mappings[len] = NULL; mappingListObj = objv[2]; Tcl_IncrRefCount (mappingListObj); mappingListObjLen = len; objc -= 2; objv += 2; break; case o_cache: if (Tcl_GetBooleanFromObj (interp, objv[2], &cache) != TCL_OK) { return TCL_ERROR; } objc -= 2; objv += 2; break; case o_list: list = 1; objc--; objv++; break; default: Tcl_ResetResult (interp); Tcl_AppendResult (interp, "bad option \"", Tcl_GetString (objv[1]), "\"; must be " "-namespaces, -cache or -list", NULL); return TCL_ERROR; } } if (objc != 2 && objc != 3) { SetResult("Wrong # of arguments."); rc = TCL_ERROR; goto cleanup; } xpathQuery = Tcl_GetString(objv[1]); xpathRSInit(&rs); cbs.funcCB = tcldom_xpathFuncCallBack; cbs.funcClientData = interp; cbs.varCB = NULL; cbs.varClientData = NULL; parseVarCB.parseVarCB = tcldom_xpathResolveVar; parseVarCB.parseVarClientData = interp; if (mappings == NULL) { mappings = node->ownerDocument->prefixNSMappings; } typeVar = NULL; if (objc > 2) { typeVar = Tcl_GetString(objv[2]); } if (cache) { if (!node->ownerDocument->xpathCache) { node->ownerDocument->xpathCache = MALLOC (sizeof (Tcl_HashTable)); Tcl_InitHashTable (node->ownerDocument->xpathCache, TCL_STRING_KEYS); } xpathCache = node->ownerDocument->xpathCache; } if (list) { if (Tcl_ListObjLength (interp, objv[1], &xpathListLen) != TCL_OK) { SetResult ("If the -list option is given the xpathQuery argument " "must be a valid Tcl list of XPath expressions."); return TCL_ERROR; } if (xpathListLen == 0) { Tcl_ResetResult (interp); return TCL_OK; } Tcl_ListObjIndex(interp, objv[1], 0, &queryObj); query = Tcl_GetString (queryObj); if (cache) { h = Tcl_CreateHashEntry (xpathCache, query, &hnew); } else { hnew = 1; } if (hnew) { rc = xpathParse(query, node, XPATH_EXPR, mappings, &parseVarCB, &t, &errMsg); if (rc) { if (h != NULL) { Tcl_DeleteHashEntry(h); } Tcl_ResetResult (interp); Tcl_AppendResult (interp, "invalid XPath query '", query, "': ", errMsg, NULL); FREE (errMsg); return TCL_ERROR; } if (cache) { Tcl_SetHashValue(h, t); } } else { t = (ast)Tcl_GetHashValue(h); } result = Tcl_NewListObj (0, NULL); rstype = UnknownResult; rc = selectNodesQueryList (interp, node, objv[1], t, 0, xpathListLen, mappings, &cbs, &parseVarCB, xpathCache, result, &rstype); if (!xpathCache) { xpathFreeAst (t); } if (rc != TCL_OK) { Tcl_DecrRefCount (result); return TCL_ERROR; } if (typeVar) { Tcl_SetVar(interp, typeVar, xpathResultType2string(rstype), 0); } Tcl_SetObjResult (interp, result); return TCL_OK; } rc = xpathEval (node, node, xpathQuery, mappings, &cbs, &parseVarCB, xpathCache, &errMsg, &rs); if (rc != XPATH_OK) { xpathRSFree(&rs); SetResult(errMsg); DBG(fprintf(stderr, "errMsg = %s \n", errMsg);) if (errMsg) { FREE(errMsg); } rc = TCL_ERROR; goto cleanup; } if (errMsg) { fprintf (stderr, "Why this: '%s'\n", errMsg); FREE(errMsg); } DBG(fprintf(stderr, "before tcldom_xpathResultSet \n");) tcldom_xpathResultSet(interp, &rs, &rstype, Tcl_GetObjResult(interp)); DBG(fprintf(stderr, "after tcldom_xpathResultSet \n");) if (typeVar) { Tcl_SetVar(interp, typeVar, xpathResultType2string(rstype), 0); } rc = TCL_OK; xpathRSFree( &rs ); cleanup: if (localmapping) { for (i = 0; i < mappingListObjLen; i++) { Tcl_ListObjIndex (interp, mappingListObj, i, &objPtr1); Tcl_DecrRefCount (objPtr1); } Tcl_DecrRefCount (mappingListObj); FREE (mappings); } return rc; } /*---------------------------------------------------------------------------- | tcldom_nameCheck | \---------------------------------------------------------------------------*/ int tcldom_nameCheck ( Tcl_Interp *interp, char *name, char *nameType, int isFQName ) { int result; if (isFQName) { result = domIsQNAME (name); } else { result = domIsNAME (name); } if (!result) { Tcl_ResetResult (interp); Tcl_AppendResult (interp, "Invalid ", nameType, " name '", name, "'", (char *) NULL); return 0; } return 1; } /*---------------------------------------------------------------------------- | tcldom_PINameCheck | \---------------------------------------------------------------------------*/ int tcldom_PINameCheck ( Tcl_Interp *interp, char *name ) { /* XML rec, production 17 */ if (!domIsPINAME (name)) { Tcl_ResetResult (interp); Tcl_AppendResult (interp, "Invalid processing instruction name '", name, "'", NULL); return 0; } return 1; } /*---------------------------------------------------------------------------- | tcldom_textCheck | \---------------------------------------------------------------------------*/ int tcldom_textCheck ( Tcl_Interp *interp, char *text, char *errText ) { if (!domIsChar (text)) { Tcl_ResetResult (interp); Tcl_AppendResult (interp, "Invalid ", errText, " value '", text, "'", (char *) NULL); return 0; } return 1; } /*---------------------------------------------------------------------------- | tcldom_commentCheck | \---------------------------------------------------------------------------*/ int tcldom_commentCheck ( Tcl_Interp *interp, char *text ) { if (!domIsComment (text)) { Tcl_ResetResult (interp); Tcl_AppendResult (interp, "Invalid comment value '", text, "'", (char *) NULL); return 0; } return 1; } /*---------------------------------------------------------------------------- | tcldom_CDATACheck | \---------------------------------------------------------------------------*/ int tcldom_CDATACheck ( Tcl_Interp *interp, char *text ) { if (!domIsCDATA (text)) { Tcl_ResetResult (interp); Tcl_AppendResult (interp, "Invalid CDATA section value '", text, "'", (char *) NULL); return 0; } return 1; } /*---------------------------------------------------------------------------- | tcldom_PIValueCheck | \---------------------------------------------------------------------------*/ int tcldom_PIValueCheck ( Tcl_Interp *interp, char *text ) { if (!domIsPIValue (text)) { Tcl_ResetResult (interp); Tcl_AppendResult (interp, "Invalid processing instruction value '", text, "'", (char *) NULL); return 0; } return 1; } /*---------------------------------------------------------------------------- | tcldom_appendFromTclList | \---------------------------------------------------------------------------*/ static int tcldom_appendFromTclList ( Tcl_Interp *interp, domNode *node, Tcl_Obj *obj ) { int i, rc; domLength valueLength, length, attrLength, attrValueLength; domLength childListLength; Tcl_Obj *lnode, *tagNameObj, *piNameObj, *valueObj, *attrListObj, *attrObj, *childListObj, *childObj; char *tag_name, *pi_name, *value, *attrName, *attrValue; domNode *newnode; GetTcldomDATA; /*------------------------------------------------------------------------ | check format of Tcl list node \-----------------------------------------------------------------------*/ lnode = obj; if ((rc = Tcl_ListObjLength(interp, lnode, &length)) != TCL_OK) { return rc; } if ((length != 3) && (length != 2)) { SetResult( "invalid node list format!"); return TCL_ERROR; } /*------------------------------------------------------------------------ | create node \-----------------------------------------------------------------------*/ if ((rc = Tcl_ListObjIndex(interp, lnode, 0, &tagNameObj)) != TCL_OK) { return rc; } tag_name = Tcl_GetString(tagNameObj); if ( (strcmp(tag_name,"#cdata")==0) || (strcmp(tag_name,"#text")==0) || (strcmp(tag_name,"#comment")==0) ) { if (length != 2) { SetResult( "invalid text or comment node list format!"); return TCL_ERROR; } /*-------------------------------------------------------------------- | create text node \-------------------------------------------------------------------*/ if ((rc = Tcl_ListObjIndex(interp, lnode, 1, &valueObj)) != TCL_OK) { return rc; } value = Tcl_GetStringFromObj(valueObj, &valueLength); if (strcmp(tag_name, "#text")==0) { CheckText (interp, value, "text"); newnode = (domNode*)domNewTextNode(node->ownerDocument, value, valueLength, TEXT_NODE); } else if (strcmp(tag_name, "#comment")==0) { CheckComment (interp, value); newnode = (domNode*)domNewTextNode(node->ownerDocument, value, valueLength, COMMENT_NODE); } else { CheckCDATA (interp, value); newnode = (domNode*)domNewTextNode(node->ownerDocument, value, valueLength, CDATA_SECTION_NODE); } domAppendChild(node, newnode); return TCL_OK; } if (strcmp(tag_name,"#pi")==0) { if (length != 3) { SetResult( "invalid PI node list format!"); return TCL_ERROR; } /*-------------------------------------------------------------------- | create processing instruction node \-------------------------------------------------------------------*/ if ((rc = Tcl_ListObjIndex(interp, lnode, 1, &piNameObj)) != TCL_OK) { return rc; } if ((rc = Tcl_ListObjIndex(interp, lnode, 2, &valueObj)) != TCL_OK) { return rc; } pi_name = Tcl_GetStringFromObj(piNameObj, &length); CheckPIName (interp, pi_name); value = Tcl_GetStringFromObj(valueObj, &valueLength); CheckPIValue (interp, value); newnode = (domNode*)domNewProcessingInstructionNode (node->ownerDocument, pi_name, length, value, valueLength); domAppendChild(node, newnode); return TCL_OK; } /*------------------------------------------------------------------------ | create element node \-----------------------------------------------------------------------*/ if (length != 3) { SetResult("invalid element node list format!"); return TCL_ERROR; } CheckName (interp, tag_name, "tag", 0); newnode = domNewElementNode(node->ownerDocument, tag_name); domAppendChild(node, newnode); /*------------------------------------------------------------------------ | create attributes \-----------------------------------------------------------------------*/ if ((rc = Tcl_ListObjIndex(interp, lnode, 1, &attrListObj)) != TCL_OK) { return rc; } if ((rc = Tcl_ListObjLength(interp, attrListObj, &attrLength)) != TCL_OK) { return rc; } if (attrLength % 2) { SetResult("invalid attributes list format!"); return TCL_ERROR; } for (i=0; inodeType == TEXT_NODE) || (node->nodeType == CDATA_SECTION_NODE)) { value = Tcl_NewStringObj(((domTextNode*)node)->nodeValue, ((domTextNode*)node)->valueLength); objv[0] = Tcl_NewStringObj("#text", -1); objv[1] = value; return Tcl_NewListObj(2, objv); } if (node->nodeType == COMMENT_NODE) { value = Tcl_NewStringObj(((domTextNode*)node)->nodeValue, ((domTextNode*)node)->valueLength); objv[0] = Tcl_NewStringObj("#comment", -1); objv[1] = value; return Tcl_NewListObj(2, objv); } if (node->nodeType == PROCESSING_INSTRUCTION_NODE) { domProcessingInstructionNode *dpn; dpn = (domProcessingInstructionNode *)node; name = Tcl_NewStringObj(dpn->targetValue, dpn->targetLength); value = Tcl_NewStringObj(dpn->dataValue, dpn->dataLength); objv[0] = Tcl_NewStringObj("#pi", -1); objv[1] = name; objv[2] = value; return Tcl_NewListObj(3, objv); } name = Tcl_NewStringObj(node->nodeName, -1); attrsList = Tcl_NewListObj(0, NULL); attrs = node->firstAttr; while (attrs) { attrName = Tcl_NewStringObj(attrs->nodeName, -1); attrValue = Tcl_NewStringObj(attrs->nodeValue, attrs->valueLength); Tcl_ListObjAppendElement(interp, attrsList, attrName); Tcl_ListObjAppendElement(interp, attrsList, attrValue); attrs = attrs->nextSibling; } childList = Tcl_NewListObj(0, NULL); if (node->nodeType == ELEMENT_NODE) { child = node->firstChild; while (child != NULL) { result = Tcl_ListObjAppendElement (interp, childList, tcldom_treeAsTclList(interp, child)); if (result != TCL_OK) { return NULL; } child = child->nextSibling; } } objv[0] = name; objv[1] = attrsList; objv[2] = childList; return Tcl_NewListObj(3, objv); } #if TCL_MAJOR_VERSION < 9 static int tcldom_UtfToUniChar ( const char *src, int *uniChar ) { int clen; Tcl_UniChar uni16; clen = UTF8_CHAR_LEN(*src); if (clen && clen < 4) { clen = Tcl_UtfToUniChar (src, &uni16); *uniChar = uni16; return clen; } else if (clen == 4) { /* This resembles exactly what Tcl 9 does */ if (((src[1] & 0xC0) == 0x80) && ((src[2] & 0xC0) == 0x80) && ((src[3] & 0xC0) == 0x80)) { /* * Four-byte-character lead byte followed by three trail bytes. */ *uniChar = (((src[0] & 0x07) << 18) | ((src[1] & 0x3F) << 12) | ((src[2] & 0x3F) << 6) | (src[3] & 0x3F)); if ((unsigned)(*uniChar - 0x10000) <= 0xFFFFF) { return 4; } } } *uniChar = src[0]; return 1; } #else # define tcldom_UtfToUniChar Tcl_UtfToUniChar #endif /*---------------------------------------------------------------------------- | tcldom_AppendEscaped | \---------------------------------------------------------------------------*/ static void tcldom_AppendEscaped ( Tcl_Obj *xmlString, Tcl_Channel chan, char *value, domLength value_length, int outputFlags ) { #define APESC_BUF_SIZE 512 #define AP(c) *b++ = c; #define AE(s) pc1 = s; while(*pc1) *b++ = *pc1++; #define TWOCPE clen2 = UTF8_CHAR_LEN(*(pc+clen)); \ if (clen) tcldom_UtfToUniChar(pc+clen, &uniChar2); #define MCP pc += clen; clen = clen2; char buf[APESC_BUF_SIZE+80], *b, *bLimit, *pc, *pc1, *pEnd, charRef[10]; int charDone, i; int clen = 0, clen2 = 0; int unicode; int uniChar, uniChar2; b = buf; bLimit = b + APESC_BUF_SIZE; pc = pEnd = value; if (value_length != -1) { pEnd = pc + value_length; } while ( (value_length == -1 && *pc) || (value_length != -1 && pc != pEnd) ) { if ((*pc == '"') && (outputFlags & SERIALIZE_FOR_ATTR || outputFlags & SERIALIZE_ESCAPE_ALL_QUOT)) { AP('&') AP('q') AP('u') AP('o') AP('t') AP(';') } else if (*pc == '&') { AP('&') AP('a') AP('m') AP('p') AP(';') } else if (*pc == '<') { AP('&') AP('l') AP('t') AP(';') } else if (*pc == '>' && !(outputFlags & SERIALIZE_NO_GT_ESCAPE)) { AP('&') AP('g') AP('t') AP(';') } else if ((*pc == '\n') && outputFlags & SERIALIZE_FOR_ATTR) { AP('&') AP('#') AP('x') AP('A') AP(';') } else if ((*pc == '\r') && outputFlags & SERIALIZE_ESCAPE_CR) { AP('&') AP('#') AP('x') AP('D') AP(';') } else if ((*pc == '\t') && outputFlags & SERIALIZE_ESCAPE_TAB) { AP('&') AP('#') AP('x') AP('9') AP(';') } else { charDone = 0; clen = UTF8_CHAR_LEN(*pc); if (outputFlags & SERIALIZE_HTML_ENTITIES) { charDone = 1; tcldom_UtfToUniChar(pc, &uniChar); switch (uniChar) { #include "HTML5ent.inc" default: charDone = 0; } if (charDone) { pc += (clen - 1); } } if (!charDone) { if ((unsigned char)*pc > 127) { if (!clen) { domPanic("tcldom_AppendEscaped: can only handle " "UTF-8 chars up to 4 bytes length"); } if (clen == 4 || outputFlags & SERIALIZE_ESCAPE_NON_ASCII) { if (clen == 4) { unicode = ((pc[0] & 0x07) << 18) + ((pc[1] & 0x3F) << 12) + ((pc[2] & 0x3F) << 6) + (pc[3] & 0x3F); } else if (clen == 3) { unicode = ((pc[0] & 0x0F) << 12) + ((pc[1] & 0x3F) << 6) + (pc[2] & 0x3F); } else { unicode = ((pc[0] & 0x1F) << 6) + (pc[1] & 0x3F); } AP('&') AP('#') sprintf(charRef, "%d", unicode); for (i = 0; i < (int)strlen(charRef); i++) { AP(charRef[i]); } AP(';') pc += (clen - 1); } else { for (i = 0; i < clen; i++) { AP(*pc); pc++; } pc--; } } else { AP(*pc); } } } if (b >= bLimit) { writeChars(xmlString, chan, buf, (domLength)(b - buf)); b = buf; } pc++; } if (b > buf) { writeChars(xmlString, chan, buf, (domLength)(b - buf)); } } /*---------------------------------------------------------------------------- | tcldom_tolower | \---------------------------------------------------------------------------*/ void tcldom_tolower ( const char *str, char *str_out, int len ) { char *p; int i; len--; i = 0; p = str_out; while (*str && (i < len)) { *p++ = tolower((unsigned char)*str++); i++; } *p++ = '\0'; } /*---------------------------------------------------------------------------- | tcldom_treeAsHTML | \---------------------------------------------------------------------------*/ static void tcldom_treeAsHTML ( Tcl_Obj *htmlString, domNode *node, Tcl_Channel chan, int escapeNonASCII, int htmlEntities, int doctypeDeclaration, int noEscaping, int onlyContents, int breakLines ) { int empty, scriptTag, outputFlags = 0; domNode *child; domAttrNode *attrs; domDocument *doc; char tag[80], attrName[80]; if (escapeNonASCII) outputFlags = SERIALIZE_ESCAPE_NON_ASCII; if (htmlEntities) outputFlags |= SERIALIZE_HTML_ENTITIES; if (node->nodeType == DOCUMENT_NODE) { doc = (domDocument*) node; if (doctypeDeclaration && doc->documentElement) { writeChars(htmlString, chan, "documentElement->nodeName, -1); if ( doc->doctype && doc->doctype->systemId && doc->doctype->systemId[0] != '\0') { if ( doc->doctype->publicId && doc->doctype->publicId[0] != '\0') { writeChars(htmlString, chan, " PUBLIC \"", 9); writeChars(htmlString, chan, doc->doctype->publicId, -1); writeChars(htmlString, chan, "\" \"", 3); writeChars(htmlString, chan, doc->doctype->systemId, -1); writeChars(htmlString, chan, "\"", 1); } else { writeChars(htmlString, chan, " SYSTEM \"", 9); writeChars(htmlString, chan, doc->doctype->systemId, -1); writeChars(htmlString, chan, "\"", 1); } } if (doc->doctype && doc->doctype->internalSubset) { writeChars(htmlString, chan, " [", 2); writeChars(htmlString, chan, doc->doctype->internalSubset, -1); writeChars(htmlString, chan, "]", 1); } writeChars(htmlString, chan, ">\n", 2); } child = doc->rootNode->firstChild; while (child) { tcldom_treeAsHTML(htmlString, child, chan, escapeNonASCII, htmlEntities, doctypeDeclaration, 0, 0, breakLines); child = child->nextSibling; } return; } if (node->nodeType == PROCESSING_INSTRUCTION_NODE) { domProcessingInstructionNode *dpn; dpn = (domProcessingInstructionNode *)node; writeChars(htmlString, chan, "targetValue, dpn->targetLength); writeChars(htmlString, chan, " ", 1); writeChars(htmlString, chan, dpn->dataValue, dpn->dataLength); writeChars(htmlString, chan, ">", 1); return; } if (node->nodeType == TEXT_NODE) { if ((node->nodeFlags & DISABLE_OUTPUT_ESCAPING) || noEscaping) { writeChars(htmlString, chan, ((domTextNode*)node)->nodeValue, ((domTextNode*)node)->valueLength); } else { tcldom_AppendEscaped(htmlString, chan, ((domTextNode*)node)->nodeValue, ((domTextNode*)node)->valueLength, outputFlags); } return; } if (node->nodeType == CDATA_SECTION_NODE) { if (noEscaping) { writeChars(htmlString, chan, ((domTextNode*)node)->nodeValue, ((domTextNode*)node)->valueLength); } else { tcldom_AppendEscaped(htmlString, chan, ((domTextNode*)node)->nodeValue, ((domTextNode*)node)->valueLength, outputFlags); } return; } if (node->nodeType == COMMENT_NODE) { writeChars(htmlString, chan, "", 3); return; } tcldom_tolower(node->nodeName, tag, 80); /*----------------------------------------------------------- | check for HTML tags, that must be handled special: | empty tags and script tags (todo: HTML tags with | URI attributes, to do escaping of Non-ASCII chars | in the URI). \----------------------------------------------------------*/ empty = 0; scriptTag = 0; switch (tag[0]) { case 'a': if (!strcmp(tag,"area")) {empty = 1;} break; case 'b': if (!strcmp(tag,"br") || !strcmp(tag,"base") || !strcmp(tag,"basefont")) {empty = 1;} break; case 'c': if (!strcmp(tag,"col")) {empty = 1;} break; case 'f': if (!strcmp(tag,"frame")) {empty = 1;} break; case 'h': if (!strcmp(tag,"hr")) {empty = 1;} break; case 'i': if (!strcmp(tag,"img") || !strcmp(tag,"input") || !strcmp(tag,"isindex")) {empty = 1;} break; case 'l': if (!strcmp(tag,"link")) {empty = 1;} break; case 'm': if (!strcmp(tag,"meta")) {empty = 1;} break; case 'p': if (!strcmp(tag,"param")) {empty = 1;} break; case 's': if (!strcmp(tag,"script") || !strcmp(tag,"style")) {scriptTag = 1;} break; } if (!onlyContents) { writeChars(htmlString, chan, "<", 1); writeChars(htmlString, chan, tag, -1); attrs = node->firstAttr; while (attrs) { tcldom_tolower(attrs->nodeName, attrName, 80); writeChars(htmlString, chan, " ", 1); writeChars (htmlString, chan, attrName, -1); writeChars(htmlString, chan, "=\"", 2); tcldom_AppendEscaped(htmlString, chan, attrs->nodeValue, -1, outputFlags | SERIALIZE_FOR_ATTR); writeChars(htmlString, chan, "\"", 1); attrs = attrs->nextSibling; } if (breakLines) { writeChars(htmlString, chan, "\n>", 2); } else { writeChars(htmlString, chan, ">", 1); } } if (empty) { /* strange ! should not happen ! */ child = node->firstChild; while (child != NULL) { tcldom_treeAsHTML(htmlString, child, chan, escapeNonASCII, htmlEntities, doctypeDeclaration, scriptTag, 0, breakLines); child = child->nextSibling; } return; } if (node->nodeType == ELEMENT_NODE) { child = node->firstChild; if ((child != NULL) && (child != node->lastChild) && (child->nodeType != TEXT_NODE)) { writeChars(htmlString, chan, "\n", 1); } while (child != NULL) { tcldom_treeAsHTML(htmlString, child, chan, escapeNonASCII, htmlEntities, doctypeDeclaration, scriptTag, 0, breakLines); child = child->nextSibling; } if ((node->firstChild != NULL) && (node->firstChild != node->lastChild) && (node->lastChild->nodeType != TEXT_NODE)) { writeChars(htmlString, chan, "\n", 1); } } if (!onlyContents) { writeChars(htmlString, chan, "", 1); } } /*---------------------------------------------------------------------------- | tcldom_treeAsXML | \---------------------------------------------------------------------------*/ static void tcldom_treeAsXML ( Tcl_Obj *xmlString, domNode *node, int indent, int level, int doIndent, Tcl_Channel chan, Tcl_Obj *encString, int cdataChild, int outputFlags, int indentAttrs ) { domAttrNode *attrs; domNode *child; domDocument *doc; int first, hasElements, i; char prefix[MAX_PREFIX_LEN], *start, *p; const char *localName; Tcl_HashEntry *h; Tcl_DString dStr; if (outputFlags & SERIALIZE_XML_DECLARATION) { outputFlags &= ~SERIALIZE_XML_DECLARATION; writeChars(xmlString, chan, "nodeType == DOCUMENT_NODE && ((domDocument*) node)->doctype && ((domDocument*) node)->doctype->encoding) { writeChars(xmlString, chan, " encoding=\"", 11); writeChars(xmlString, chan, ((domDocument*) node)->doctype->encoding, -1); writeChars(xmlString, chan, "\"", 1); } writeChars(xmlString, chan, "?>\n", 3); } if (node->nodeType == DOCUMENT_NODE) { doc = (domDocument*) node; if (outputFlags & SERIALIZE_DOCTYPE_DECLARATION && doc->documentElement) { writeChars(xmlString, chan, "documentElement->nodeName, -1); if ( doc->doctype && doc->doctype->systemId && (doc->doctype->systemId[0] != '\0')) { if ( doc->doctype->publicId && doc->doctype->publicId[0] != '\0') { writeChars(xmlString, chan, " PUBLIC \"", 9); writeChars(xmlString, chan, doc->doctype->publicId, -1); writeChars(xmlString, chan, "\" \"", 3); writeChars(xmlString, chan, doc->doctype->systemId, -1); writeChars(xmlString, chan, "\"", 1); } else { writeChars(xmlString, chan, " SYSTEM \"", 9); writeChars(xmlString, chan, doc->doctype->systemId, -1); writeChars(xmlString, chan, "\"", 1); } if (doc->doctype->internalSubset) { writeChars(xmlString, chan, " [", 2); writeChars(xmlString, chan, doc->doctype->internalSubset, -1); writeChars(xmlString, chan, "]", 1); } } writeChars(xmlString, chan, ">\n", 2); } child = doc->rootNode->firstChild; while (child) { tcldom_treeAsXML(xmlString, child, indent, level, doIndent, chan, NULL, 0, outputFlags, indentAttrs); child = child->nextSibling; } return; } if (node->nodeType == TEXT_NODE) { if (cdataChild) { writeChars(xmlString, chan, "nodeValue; while (i < ((domTextNode*)node)->valueLength) { if (*p == ']') { p++; i++; if (i >= ((domTextNode*)node)->valueLength) break; if (*p == ']') { p++; i++; if (i >= ((domTextNode*)node)->valueLength) break; if (*p == '>') { writeChars(xmlString, chan, start, (domLength)(p-start)); writeChars(xmlString, chan, "]]>", 13); start = p+1; } } } p++; i++; } writeChars(xmlString, chan, start, (domLength)(p-start)); writeChars(xmlString, chan, "]]>", 3); } else { if (node->nodeFlags & DISABLE_OUTPUT_ESCAPING) { writeChars(xmlString, chan, ((domTextNode*)node)->nodeValue, ((domTextNode*)node)->valueLength); } else { tcldom_AppendEscaped(xmlString, chan, ((domTextNode*)node)->nodeValue, ((domTextNode*)node)->valueLength, outputFlags); } } return; } if (node->nodeType == CDATA_SECTION_NODE) { writeChars(xmlString, chan, "nodeValue, ((domTextNode*)node)->valueLength); writeChars(xmlString, chan, "]]>", 3); return; } if ((indent != -1) && doIndent) { if (outputFlags & SERIALIZE_INDENT_WITH_TAB) { for(i=0; inodeType == COMMENT_NODE) { writeChars(xmlString, chan, "", 3); if (indent != -1) writeChars (xmlString, chan, "\n", 1); return; } if (node->nodeType == PROCESSING_INSTRUCTION_NODE) { writeChars(xmlString, chan, "targetValue, ((domProcessingInstructionNode*)node)->targetLength); writeChars(xmlString, chan, " ", 1); writeChars(xmlString, chan, ((domProcessingInstructionNode*)node)->dataValue, ((domProcessingInstructionNode*)node)->dataLength); writeChars(xmlString, chan, "?>", 2); if (indent != -1) writeChars (xmlString, chan, "\n", 1); return; } writeChars(xmlString, chan, "<", 1); writeChars(xmlString, chan, node->nodeName, -1); attrs = node->firstAttr; while (attrs) { if (indentAttrs > -1) { writeChars(xmlString, chan, "\n", 1); if ((indent != -1) && doIndent) { if (outputFlags & SERIALIZE_INDENT_WITH_TAB) { for(i=0; inodeName, -1); writeChars(xmlString, chan, "=\"", 2); tcldom_AppendEscaped(xmlString, chan, attrs->nodeValue, attrs->valueLength, outputFlags | SERIALIZE_FOR_ATTR); writeChars(xmlString, chan, "\"", 1); attrs = attrs->nextSibling; } hasElements = 0; first = 1; doIndent = 1; if (node->nodeType == ELEMENT_NODE) { cdataChild = 0; if (node->ownerDocument->doctype && node->ownerDocument->doctype->cdataSectionElements) { if (node->namespace) { Tcl_DStringInit (&dStr); Tcl_DStringAppend (&dStr, domNamespaceURI(node), -1); Tcl_DStringAppend (&dStr, ":", 1); domSplitQName (node->nodeName, prefix, &localName); Tcl_DStringAppend (&dStr, localName, -1); h = Tcl_FindHashEntry ( node->ownerDocument->doctype->cdataSectionElements, Tcl_DStringValue (&dStr)); Tcl_DStringFree (&dStr); } else { h = Tcl_FindHashEntry ( node->ownerDocument->doctype->cdataSectionElements, node->nodeName); } if (h) { cdataChild = 1; } } child = node->firstChild; while (child != NULL) { if ( (child->nodeType == ELEMENT_NODE) ||(child->nodeType == PROCESSING_INSTRUCTION_NODE) ||(child->nodeType == COMMENT_NODE) ) { hasElements = 1; } if (first) { writeChars(xmlString, chan, ">", 1); if ((indent != -1) && hasElements) { writeChars(xmlString, chan, "\n", 1); } } first = 0; tcldom_treeAsXML(xmlString, child, indent, level+1, doIndent, chan, NULL, cdataChild, outputFlags, indentAttrs); doIndent = 0; if ( (child->nodeType == ELEMENT_NODE) ||(child->nodeType == PROCESSING_INSTRUCTION_NODE) ||(child->nodeType == COMMENT_NODE) ) { doIndent = 1; } child = child->nextSibling; } } if (first) { if (indent != -1) { if (outputFlags & SERIALIZE_NO_EMPTY_ELEMENT_TAG) { writeChars (xmlString, chan, ">nodeName, -1); writeChars(xmlString, chan, ">\n", 2); } else { writeChars(xmlString, chan, "/>\n", 3); } } else { if (outputFlags & SERIALIZE_NO_EMPTY_ELEMENT_TAG) { writeChars (xmlString, chan, ">nodeName, -1); writeChars(xmlString, chan, ">", 1); } else { writeChars(xmlString, chan, "/>", 2); } } } else { if ((indent != -1) && hasElements) { if (outputFlags & SERIALIZE_INDENT_WITH_TAB) { for(i=0; inodeName, -1); if (indent != -1) { writeChars(xmlString, chan, ">\n", 2); } else { writeChars(xmlString, chan, ">", 1); } } } /*---------------------------------------------------------------------------- | tcldom_AppendEscapedJSON | \---------------------------------------------------------------------------*/ static void tcldom_AppendEscapedJSON ( Tcl_Obj *jstring, Tcl_Channel chan, char *value, domLength value_length ) { char buf[APESC_BUF_SIZE+80], *b, *bLimit, *pc, *pEnd; int i; int clen = 0; b = buf; bLimit = b + APESC_BUF_SIZE; pc = pEnd = value; if (value_length != -1) { pEnd = pc + value_length; } AP('"'); while ( (value_length == -1 && *pc) || (value_length != -1 && pc != pEnd) ) { clen = UTF8_CHAR_LEN(*pc); if (!clen) { /* This would be invalid utf-8 encoding. */ clen = 1; } if (clen == 1) { if (*pc == '\\') { AP('\\'); AP('\\'); } else if (*pc == '"') { AP('\\'); AP('"'); } else if (*pc == '\b') { AP('\\'); AP('b'); } else if (*pc == '\f') { AP('\\'); AP('f'); } else if (*pc == '\n') { AP('\\'); AP('n'); } else if (*pc == '\r') { AP('\\'); AP('r'); } else if (*pc == '\t') { AP('\\'); AP('t'); } else if ((unsigned char)*pc < 0x20) { AP('\\'); AP('u'); AP('0'); AP('0'); AP('0' + (*pc>>4)); AP("0123456789abcdef"[*pc&0xf]); } else { AP(*pc); } pc++; } else { if ((unsigned char)*pc == 0xC0 && (unsigned char)*(pc+1) == 0x80) { AP('\\');AP('u');AP('0');AP('0');AP('0');AP('0'); pc++;pc++; } else { for (i = 0; i < clen; i++) { AP(*pc); pc++; } } } if (b >= bLimit) { writeChars(jstring, chan, buf, (domLength)(b - buf)); b = buf; } } AP('"'); writeChars(jstring, chan, buf, (domLength)(b - buf)); } static void tcldom_childrenAsJSON ( Tcl_Obj *jstring, domNode *node, /* Must be an ELEMENT_NODE */ Tcl_Channel channel, int indent, int outputFlags, int level, int inside ) { domNode *child, *nextChild; int i, effectivParentType = 0; int first = 1; child = node->firstChild; while (child && child->nodeType != TEXT_NODE && child->nodeType != ELEMENT_NODE) { child = child->nextSibling; } if (node->info == JSON_ARRAY || node->info == JSON_OBJECT) { effectivParentType = node->info; } else if (child == NULL) { /* Need 'heuristic rule' to decide, what to do. */ switch (inside) { case JSON_OBJECT: /* The children to serialize are the value of an object member. */ /* No content at all. This could be an empty string, * an empty object or an empty array. We default to * empty string. */ writeChars(jstring, channel, "\"\"",2); return; case JSON_START: case JSON_ARRAY: /* The children we are serializing are the value of an * array element. The node is a container for either a * (nested, in case of JSON_ARRAY) array or an object. */ /* Look, if the name of the container gives a hint.*/ if (strcmp (node->nodeName, JSON_ARRAY_CONTAINER)==0) { effectivParentType = JSON_ARRAY; break; } /* If we here, heuristics didn't helped. We have to * default to something. Let's say ... */ effectivParentType = JSON_OBJECT; break; } } else { if (child->nodeType == ELEMENT_NODE) { /* The first 'relevant' child node is ELEMENT_NODE */ effectivParentType = JSON_OBJECT; if (inside == JSON_ARRAY) { /* Though, if we inside of an array and the node name * of the first 'relevant' child is the array * container element, we assume an array (with a * nested array as first value of that array. */ if (strcmp (child->nodeName, JSON_ARRAY_CONTAINER)) effectivParentType = JSON_ARRAY; } } else { /* If we are here, the first 'relevant' child is a * text node. If there is any other 'relevant' child, * we assume the value to be an array. Otherwise (only * single 'relevant' child is a text node), this is * any of string, true, false null. Child may have a * type hint. */ nextChild = child->nextSibling; while (nextChild && nextChild->nodeType != TEXT_NODE && nextChild->nodeType != ELEMENT_NODE) { nextChild = nextChild->nextSibling; } if (nextChild) { effectivParentType = JSON_ARRAY; } else { /* Exactly one 'relevant' child node, a text node; * serialize it as simple token value. */ tcldom_treeAsJSON (jstring, child, channel, indent, outputFlags, level, JSON_ARRAY); return; } } } switch (effectivParentType) { case JSON_ARRAY: writeChars(jstring, channel, "[",1); while (child) { if (first) { first = 0; level++; } else { writeChars(jstring, channel, ",", 1); } if (indent > -1) { writeChars(jstring, channel, "\n", 1); if (outputFlags & SERIALIZE_INDENT_WITH_TAB) { for (i = 0; i < level; i++) { writeChars(jstring, channel, "\t", 1); } } else { for (i = 0; i < level; i++) { writeChars(jstring, channel, " ", indent); } } } tcldom_treeAsJSON (jstring, child, channel, indent, outputFlags, level, JSON_ARRAY); child = child->nextSibling; while (child && child->nodeType != TEXT_NODE && child->nodeType != ELEMENT_NODE) { child = child->nextSibling; } } if (indent > -1 && first == 0) { writeChars(jstring, channel, "\n", 1); level--; if (outputFlags & SERIALIZE_INDENT_WITH_TAB) { for (i = 0; i < level; i++) { writeChars(jstring, channel, "\t", 1); } } else { for (i = 0; i < level; i++) { writeChars(jstring, channel, " ", indent); } } } writeChars(jstring, channel, "]",1); break; case JSON_OBJECT: writeChars(jstring, channel, "{",1); while (child) { if (first) { first = 0; level++; } else { writeChars(jstring, channel, ",", 1); } if (indent > -1) { writeChars(jstring, channel, "\n", 1); if (outputFlags & SERIALIZE_INDENT_WITH_TAB) { for (i = 0; i < level; i++) { writeChars(jstring, channel, "\t", 1); } } else { for (i = 0; i < level; i++) { writeChars(jstring, channel, " ", indent); } } } tcldom_treeAsJSON (jstring, child, channel, indent, outputFlags, level, JSON_OBJECT); child = child->nextSibling; /* Inside of a JSON_OBJECT, only element children make * semantically sense. */ while (child && child->nodeType != ELEMENT_NODE) { child = child->nextSibling; } } if (indent > -1 && first == 0) { writeChars(jstring, channel, "\n", 1); level--; if (outputFlags & SERIALIZE_INDENT_WITH_TAB) { for (i = 0; i < level; i++) { writeChars(jstring, channel, "\t", 1); } } else { for (i = 0; i < level; i++) { writeChars(jstring, channel, " ", indent); } } } writeChars(jstring, channel, "}",1); break; default: break; } } /*---------------------------------------------------------------------------- | tcldom_treeAsJSON | \---------------------------------------------------------------------------*/ static void tcldom_treeAsJSON ( Tcl_Obj *jstring, domNode *node, /* Must not be NULL */ Tcl_Channel channel, int indent, int outputFlags, int level, int inside ) { domTextNode *textNode; switch (node->nodeType) { case TEXT_NODE: if (inside == JSON_OBJECT) { /* We're inside a JSON object. A text node can not be * meaningful interpreted as member of an object. Ignore * the node */ return; } textNode = (domTextNode *) node; switch (node->info) { case JSON_NUMBER: /* Check, if the text value is a JSON number and fall back * to string token, if not. This is to ensure, the * serialization is always a valid JSON string. */ if (isJSONNumber (textNode->nodeValue, textNode->valueLength)) { writeChars(jstring, channel, textNode->nodeValue, textNode->valueLength); } else { tcldom_AppendEscapedJSON (jstring, channel, textNode->nodeValue, textNode->valueLength); } break; case JSON_NULL: writeChars(jstring, channel, "null",4); break; case JSON_TRUE: writeChars(jstring, channel, "true",4); break; case JSON_FALSE: writeChars(jstring, channel, "false",5); break; case JSON_STRING: /* Fall through */ default: tcldom_AppendEscapedJSON (jstring, channel, textNode->nodeValue, textNode->valueLength); break; }; return; case ELEMENT_NODE: switch (inside) { case JSON_OBJECT: /* Write the member name and recurse to the children for * the value. */ tcldom_AppendEscapedJSON (jstring, channel, node->nodeName, -1); writeChars (jstring, channel, ":", 1); if (indent > -1 || outputFlags & SERIALIZE_INDENT_WITH_TAB) { writeChars (jstring, channel, " ", 1); } tcldom_childrenAsJSON (jstring, node, channel, indent, outputFlags, level, inside); break; case JSON_ARRAY: /* Since we're already inside of an array, the element can only be interpreted as a container for a nested JSON object or array. */ tcldom_childrenAsJSON (jstring, node, channel, indent, outputFlags, level, inside); break; case JSON_START: tcldom_childrenAsJSON (jstring, node, channel, indent, outputFlags, level, inside); break; } return; default: /* Any other node types (COMMENT_NODE, CDATA_SECTION_NODE, PROCESSING_INSTRUCTION_NODE) are ignored. */ return; } } /*---------------------------------------------------------------------------- | tcldom_treeAsTclValueWorker | \---------------------------------------------------------------------------*/ static Tcl_Obj * tcldom_treeAsTclValueWorker ( Tcl_Interp *interp, domNode *node, int parentType ) { domNode *this; domTextNode *textNode; Tcl_Obj *resultObj, *nameObj, *valueObj; this = node->firstChild; switch (node->info) { case JSON_ARRAY: resultObj = Tcl_NewListObj (0, NULL); while (this) { if (this->nodeType != ELEMENT_NODE && this->nodeType != TEXT_NODE) { this = this->nextSibling; continue; } if (this->nodeType == TEXT_NODE) { textNode = (domTextNode *)this; valueObj = Tcl_NewStringObj (textNode->nodeValue, textNode->valueLength); } else { valueObj = tcldom_treeAsTclValueWorker (interp, this, JSON_ARRAY); } Tcl_ListObjAppendElement (interp, resultObj, valueObj); this = this->nextSibling; } break; case JSON_OBJECT: resultObj = Tcl_NewDictObj (); while (this) { if (this->nodeType != ELEMENT_NODE) { /* There are no valid TEXT_NODE elements as children * of a JSON_OBJECT. */ this = this->nextSibling; continue; } valueObj = tcldom_treeAsTclValueWorker (interp, this, JSON_OBJECT); nameObj = Tcl_NewStringObj (this->nodeName, -1); Tcl_IncrRefCount (nameObj); Tcl_DictObjPut (interp, resultObj, nameObj, valueObj); Tcl_DecrRefCount (nameObj); this = this->nextSibling; } break; case 0: while (this) { if (this->nodeType != TEXT_NODE) { this = this->nextSibling; continue; } /* We take the first text child */ break; } if (this) { textNode = (domTextNode *)this; resultObj = Tcl_NewStringObj (textNode->nodeValue, textNode->valueLength); } else { resultObj = Tcl_NewObj (); } break; default: DBG (fprintf (stderr, "tcldom_treeAsTclValueWorker: Should not reach that!")); resultObj = Tcl_NewObj (); break; } return resultObj; } /*---------------------------------------------------------------------------- | tcldom_treeAsTclValue | \---------------------------------------------------------------------------*/ static int tcldom_treeAsTclValue ( Tcl_Interp *interp, domNode *node, Tcl_Obj *var_name ) { char *type; int typelen; Tcl_Obj *resultObj; domTextNode *textnode; if (var_name) { if (node->nodeType == ELEMENT_NODE) { if (node->info == JSON_OBJECT) { type = "dict"; typelen = 4; } else if (node->info == JSON_ARRAY) { type = "list"; typelen = 4; } else { type = "string"; typelen = 6; } } else { type = "string"; typelen = 6; } if (!Tcl_ObjSetVar2 (interp, var_name, NULL, Tcl_NewStringObj (type, typelen), TCL_LEAVE_ERR_MSG)) { return TCL_ERROR; } } if (node->nodeType == ELEMENT_NODE) { resultObj = tcldom_treeAsTclValueWorker (interp, node, node->info); } else if (node->nodeType == TEXT_NODE) { textnode = (domTextNode*)node; resultObj = Tcl_NewStringObj (textnode->nodeValue, textnode->valueLength); } else { resultObj = Tcl_NewObj (); } Tcl_SetObjResult (interp, resultObj); return TCL_OK; } typedef struct { Tcl_Obj *object; Tcl_Obj *array; Tcl_Obj *null; Tcl_Obj *true; Tcl_Obj *false; Tcl_Obj *number; Tcl_Obj *string; } asTypedListTypes; /*---------------------------------------------------------------------------- | tcldom_treeAsTypedList | \---------------------------------------------------------------------------*/ static Tcl_Obj* tcldom_treeAsTypedListWorker ( domNode *node, /* Must be ELEMENT_NODE or TEXT_NODE */ const asTypedListTypes *c /* c for string constants */ ) { Tcl_Obj *listObj, *resultObj = Tcl_NewListObj (0, NULL); domNode *child, *childchild; domTextNode *textNode; if (node->nodeType == ELEMENT_NODE) { switch (node->info) { case JSON_ARRAY: listObj = Tcl_NewListObj (0, NULL); child = node->firstChild; while (child) { if (child->nodeType == ELEMENT_NODE || child->nodeType == TEXT_NODE) { Tcl_ListObjAppendElement ( NULL, listObj, tcldom_treeAsTypedListWorker (child, c) ); } child = child->nextSibling; } Tcl_ListObjAppendElement(NULL, resultObj, c->array); Tcl_ListObjAppendElement(NULL, resultObj, listObj); break; case JSON_OBJECT: listObj = Tcl_NewListObj (0, NULL); child = node->firstChild; while (child) { Tcl_ListObjAppendElement(NULL, listObj, Tcl_NewStringObj(child->nodeName, -1)); if (child->nodeType == ELEMENT_NODE) { if (child->info == 0) { childchild = child->firstChild; while (childchild) { if (childchild->nodeType == TEXT_NODE) { Tcl_ListObjAppendElement( NULL, listObj, tcldom_treeAsTypedListWorker ( childchild, c)); break; } childchild = childchild->nextSibling; } } else { Tcl_ListObjAppendElement(NULL, listObj, tcldom_treeAsTypedListWorker ( child, c)); } } child = child->nextSibling; } Tcl_ListObjAppendElement(NULL, resultObj, c->object); Tcl_ListObjAppendElement(NULL, resultObj, listObj); break; } } else { /* Text node */ switch (node->info) { case JSON_NULL: Tcl_ListObjAppendElement (NULL, resultObj, c->null); break; case JSON_TRUE: Tcl_ListObjAppendElement (NULL, resultObj, c->true); break; case JSON_FALSE: Tcl_ListObjAppendElement (NULL, resultObj, c->false); break; case JSON_NUMBER: textNode = (domTextNode *)node; if (isJSONNumber (textNode->nodeValue, textNode->valueLength)) { Tcl_ListObjAppendElement(NULL, resultObj, c->number); Tcl_ListObjAppendElement( NULL, resultObj, Tcl_NewStringObj(textNode->nodeValue, textNode->valueLength)); break; } /* fall through */ case JSON_STRING: default: textNode = (domTextNode *)node; Tcl_ListObjAppendElement(NULL, resultObj, c->string); Tcl_ListObjAppendElement( NULL, resultObj, Tcl_NewStringObj(textNode->nodeValue, textNode->valueLength)); break; } } return resultObj; } static void tcldom_treeAsTypedList ( Tcl_Interp *interp, domNode *node ) { asTypedListTypes c; if (node->nodeType != ELEMENT_NODE && node->nodeType != TEXT_NODE) { Tcl_ResetResult (interp); return; } c.object = Tcl_NewStringObj ("OBJECT", 6); c.array = Tcl_NewStringObj ("ARRAY", 5); c.null = Tcl_NewStringObj ("NULL", 4); c.true = Tcl_NewStringObj ("TRUE", 4); c.false = Tcl_NewStringObj ("FALSE", 5); c.number = Tcl_NewStringObj ("NUMBER", 6); c.string = Tcl_NewStringObj ("STRING", 6); Tcl_IncrRefCount (c.object); Tcl_IncrRefCount (c.array); Tcl_IncrRefCount (c.null); Tcl_IncrRefCount (c.true); Tcl_IncrRefCount (c.false); Tcl_IncrRefCount (c.number); Tcl_IncrRefCount (c.string); if (node->nodeType == ELEMENT_NODE && node->info == 0 && node->firstChild->nodeType == TEXT_NODE) { /* Either a value only json document or a OBJECT propertiy * element node.*/ node = node->firstChild; } Tcl_SetObjResult (interp, tcldom_treeAsTypedListWorker (node, &c)); Tcl_DecrRefCount (c.object); Tcl_DecrRefCount (c.array); Tcl_DecrRefCount (c.null); Tcl_DecrRefCount (c.true); Tcl_DecrRefCount (c.false); Tcl_DecrRefCount (c.number); Tcl_DecrRefCount (c.string); } /*---------------------------------------------------------------------------- | findBaseURI | \---------------------------------------------------------------------------*/ const char *findBaseURI ( domNode *node ) { const char *baseURI = NULL; Tcl_HashEntry *entryPtr; domNode *orgNode; orgNode = node; do { if (node->nodeFlags & HAS_BASEURI) { entryPtr = Tcl_FindHashEntry(node->ownerDocument->baseURIs, (char*)node); baseURI = (const char *)Tcl_GetHashValue(entryPtr); break; } else { node = node->parentNode; } } while (node); if (!baseURI) { node = orgNode->ownerDocument->rootNode; if (node->nodeFlags & HAS_BASEURI) { entryPtr = Tcl_FindHashEntry(node->ownerDocument->baseURIs, (char*)node); baseURI = (const char *)Tcl_GetHashValue(entryPtr); } } return baseURI; } /*---------------------------------------------------------------------------- | serializeAsXML | \---------------------------------------------------------------------------*/ static int serializeAsXML ( domNode *node, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { char *channelId, prefix[MAX_PREFIX_LEN]; const char *localName; int indent, mode, bool; int outputFlags = 0; int optionIndex, cdataChild; Tcl_Obj *resultPtr, *encString = NULL; Tcl_Channel chan = (Tcl_Channel) NULL; Tcl_HashEntry *h; Tcl_DString dStr; int indentAttrs = -1; static const char *asXMLOptions[] = { "-indent", "-channel", "-escapeNonASCII", "-doctypeDeclaration", "-xmlDeclaration", "-encString", "-escapeAllQuot", "-indentAttrs", "-nogtescape", "-noEmptyElementTag", "-escapeCR", "-escapeTab", NULL }; enum asXMLOption { m_indent, m_channel, m_escapeNonASCII, m_doctypeDeclaration, m_xmlDeclaration, m_encString, m_escapeAllQuot, m_indentAttrs, m_nogtescape, m_noEmptyElementTag, m_escapeCR, m_escapeTab }; indent = 4; while (objc > 2) { if (Tcl_GetIndexFromObj(interp, objv[2], asXMLOptions, "option", 0, &optionIndex) != TCL_OK) { goto cleanup; } switch ((enum asXMLOption) optionIndex) { case m_indent: if (objc < 4) { SetResult("-indent must have an argument " "(0..8 or 'no'/'none'/'tabs')"); goto cleanup; } if (strcmp("none", Tcl_GetString(objv[3]))==0) { indent = -1; } else if (strcmp("no", Tcl_GetString(objv[3]))==0) { indent = -1; } else if (strcmp("tabs", Tcl_GetString(objv[3]))==0) { outputFlags |= SERIALIZE_INDENT_WITH_TAB; } else if (Tcl_GetIntFromObj(interp, objv[3], &indent) != TCL_OK) { SetResult( "indent must be an integer (0..8) or " "'no'/'none'/'tabs'"); goto cleanup; } objc -= 2; objv += 2; break; case m_indentAttrs: if (objc < 4) { SetResult("-indentAttrs must have an argument " "(0..8 or 'no'/'none'/'tabs')"); goto cleanup; } if (strcmp("none", Tcl_GetString(objv[3]))==0) { indentAttrs = -1; } else if (strcmp("no", Tcl_GetString(objv[3]))==0) { indentAttrs = -1; } else if (strcmp("tabs", Tcl_GetString(objv[3]))==0) { outputFlags |= SERIALIZE_INDENT_ATTR_WITH_TAB; } else if (Tcl_GetIntFromObj(interp, objv[3], &indentAttrs) != TCL_OK) { SetResult( "indentAttrs must be an integer (0..8) or " "'no'/'none'/'tabs'"); goto cleanup; } if (indentAttrs > 8) indentAttrs = 8; if (indentAttrs < 0) indentAttrs = 0; objc -= 2; objv += 2; break; case m_channel: if (objc < 4) { SetResult("-channel must have a channeldID as argument"); goto cleanup; } channelId = Tcl_GetString(objv[3]); chan = Tcl_GetChannel(interp, channelId, &mode); if (chan == (Tcl_Channel) NULL) { SetResult("-channel must have a channeldID as argument"); goto cleanup; } if ((mode & TCL_WRITABLE) == 0) { Tcl_AppendResult(interp, "channel \"", channelId, "\" is not opened for writing", (char*)NULL); goto cleanup; } objc -= 2; objv += 2; break; case m_escapeNonASCII: outputFlags |= SERIALIZE_ESCAPE_NON_ASCII; objc--; objv++; break; case m_doctypeDeclaration: if (node->nodeType != DOCUMENT_NODE) { SetResult("-doctypeDeclaration as flag to the method " "'asXML' is only allowed for domDocCmds"); goto cleanup; } if (objc < 4) { SetResult("-doctypeDeclaration must have a boolean value " "as argument"); goto cleanup; } if (Tcl_GetBooleanFromObj(interp, objv[3], &bool) != TCL_OK) { goto cleanup; } if (bool) outputFlags |= SERIALIZE_DOCTYPE_DECLARATION; objc -= 2; objv += 2; break; case m_xmlDeclaration: if (objc < 4) { SetResult("-xmlDeclaration must have a boolean value " "as argument"); goto cleanup; } if (Tcl_GetBooleanFromObj(interp, objv[3], &bool) != TCL_OK) { goto cleanup; } if (bool) outputFlags |= SERIALIZE_XML_DECLARATION; objc -= 2; objv += 2; break; case m_encString: if (objc < 4) { SetResult("-encString must have a string " "as argument"); goto cleanup; } if (encString) { Tcl_DecrRefCount(encString); } encString = objv[3]; Tcl_IncrRefCount(encString); objc -= 2; objv += 2; break; case m_escapeAllQuot: outputFlags |= SERIALIZE_ESCAPE_ALL_QUOT; objc -= 1; objv += 1; break; case m_nogtescape: outputFlags |= SERIALIZE_NO_GT_ESCAPE; objc -= 1; objv += 1; break; case m_noEmptyElementTag: outputFlags |= SERIALIZE_NO_EMPTY_ELEMENT_TAG; objc -= 1; objv += 1; break; case m_escapeCR: outputFlags |= SERIALIZE_ESCAPE_CR; objc -= 1; objv += 1; break; case m_escapeTab: outputFlags |= SERIALIZE_ESCAPE_TAB; objc -= 1; objv += 1; break; } } if (indent > 8) indent = 8; if (indent < -1) indent = -1; resultPtr = Tcl_NewStringObj("", 0); cdataChild = 0; if (node->nodeType == ELEMENT_NODE && node->ownerDocument->doctype && node->ownerDocument->doctype->cdataSectionElements) { if (node->namespace) { Tcl_DStringInit (&dStr); Tcl_DStringAppend (&dStr, domNamespaceURI(node), -1); Tcl_DStringAppend (&dStr, ":", 1); domSplitQName (node->nodeName, prefix, &localName); Tcl_DStringAppend (&dStr, localName, -1); h = Tcl_FindHashEntry ( node->ownerDocument->doctype->cdataSectionElements, Tcl_DStringValue (&dStr)); Tcl_DStringFree (&dStr); } else { h = Tcl_FindHashEntry ( node->ownerDocument->doctype->cdataSectionElements, node->nodeName); } if (h) { cdataChild = 1; } } tcldom_treeAsXML(resultPtr, node, indent, 0, 1, chan, encString, cdataChild, outputFlags, indentAttrs); Tcl_SetObjResult(interp, resultPtr); if (encString) { Tcl_DecrRefCount(encString); } return TCL_OK; cleanup: if (encString) { Tcl_DecrRefCount(encString); } return TCL_ERROR; } static int compareNSAtts ( domAttrNode *a, domAttrNode *b ) { if (strcmp (a->nodeName, "xmlns") == 0) { return -1; } else if (strcmp (b->nodeName, "xmlns") == 0) { return 1; } return (strcmp (&a->nodeName[6], &b->nodeName[6])); } static int compareAtts ( domAttrNode *a, domAttrNode *b ) { domNS *ans, *bns; domDocument *doc; const char *alocalname, *blocalname; int res; if (a->nodeFlags & IS_NS_NODE) { if (b->nodeFlags & IS_NS_NODE) { return compareNSAtts (a, b); } else { return -1; } } else { if (a->nodeFlags & IS_NS_NODE) { return 1; } } if (a->namespace) { if (b->namespace) { doc = a->parentNode->ownerDocument; ans = domGetNamespaceByIndex (doc, a->namespace); bns = domGetNamespaceByIndex (doc, b->namespace); res = strcmp (ans->uri, bns->uri); if (res == 0) { alocalname = domGetLocalName (a->nodeName); blocalname = domGetLocalName (b->nodeName); return strcmp (alocalname, blocalname); } else { return res; } } else { return 1; } } else { if (b->namespace) { return -1; } else { alocalname = domGetLocalName (a->nodeName); blocalname = domGetLocalName (b->nodeName); return strcmp (alocalname, blocalname); } } } static domAttrNode* mergeAtt ( domAttrNode *a, int len_a, domAttrNode *b, int len_b ) { domAttrNode *start, *head; int pos_a = 0; int pos_b = 0; if (!len_a) { return b; } if (!len_b) { return a; } if (compareAtts (a, b) < 0) { pos_a++; start = a; a = a->nextSibling; } else { pos_b++; start = b; b = b->nextSibling; } head = start; while (pos_a < len_a && pos_b < len_b) { if (compareAtts (a, b) < 0) { pos_a++; head->nextSibling = a; head = a; a = a->nextSibling; } else { pos_b++; head->nextSibling = b; head = b; b = b->nextSibling; } } while (pos_a < len_a) { pos_a++; head->nextSibling = a; head = a; a = a->nextSibling; } while (pos_b < len_b) { pos_b++; head->nextSibling = b; head = b; b = b->nextSibling; } head->nextSibling = NULL; return start; } static domAttrNode* mergeSortAtt ( domAttrNode *attr, int len ) { domAttrNode *attr_a, *attr_b; int half, count = 1; if (len <= 1) { return attr; } half = len/2; attr_b = attr->nextSibling; while (count < half) { attr_b = attr_b->nextSibling; count++; } attr_a = attr; return mergeAtt (mergeSortAtt (attr_a, half), half, mergeSortAtt (attr_b, len - half), len - half); } static void treeAsCanonicalXML ( Tcl_Obj *xmlString, domNode *node, Tcl_Channel chan, int comments, domAttrNode **attOrderArray, int *lengthAttOrderArray ) { domAttrNode *attr, *thisAtt = NULL, *previousAtt, *attOrder; domNode *child; domDocument *doc; domNS *ns, *ns1; int outputFlags = SERIALIZE_ESCAPE_CR, attNr = 0; switch (node->nodeType) { case ELEMENT_NODE: writeChars(xmlString, chan, "<", 1); writeChars(xmlString, chan, node->nodeName, -1); restartAttOrder: attOrder = *attOrderArray; attr = node->firstAttr; if (attr) { doc = node->ownerDocument; /* Attribute sort: It would be possible to sort the * attributes linked list in place, but this would mean * that two asXML serializations with an asCanonicalXML * serialization inbetween may be different, which would * be surprsing. */ while (attr) { if(attr->nodeFlags & IS_NS_NODE) { ns = domGetNamespaceByIndex(doc, attr->namespace); ns1 = domLookupPrefix (node->parentNode, ns->prefix); if (ns1) { if (strcmp (ns->uri, ns1->uri) == 0) { /* Namespace declaration already in scope, * suppress it */ attr = attr->nextSibling; continue; } } else { if (ns->uri[0] == '\0') { /* This is a superfluous unsetting of the * default namespace because there isn't * default namespace in scope. */ attr = attr->nextSibling; continue; } } } if (attNr >= *lengthAttOrderArray) { FREE (*attOrderArray); *attOrderArray = MALLOC (sizeof (domAttrNode) * *lengthAttOrderArray * 2); *lengthAttOrderArray *= 2; attNr = 0; goto restartAttOrder; } thisAtt = memcpy (&attOrder[attNr], attr, sizeof (domAttrNode)); if (attNr) { previousAtt = &attOrder[attNr-1]; previousAtt->nextSibling = thisAtt; } attNr++; attr = attr->nextSibling; } if (attNr && thisAtt) { thisAtt->nextSibling = NULL; } attr = mergeSortAtt (attOrderArray[0], attNr) ; while (attr) { writeChars(xmlString, chan, " ", 1); writeChars(xmlString, chan, attr->nodeName, -1); writeChars(xmlString, chan, "=\"", 2); tcldom_AppendEscaped(xmlString, chan, attr->nodeValue, attr->valueLength, outputFlags | SERIALIZE_FOR_ATTR | SERIALIZE_NO_GT_ESCAPE | SERIALIZE_ESCAPE_TAB); writeChars(xmlString, chan, "\"", 1); attr = attr->nextSibling; } } writeChars(xmlString, chan, ">", 1); child = node->firstChild; while (child != NULL) { treeAsCanonicalXML (xmlString, child, chan, comments, attOrderArray, lengthAttOrderArray); child = child->nextSibling; } writeChars(xmlString, chan, "nodeName, -1); writeChars(xmlString, chan, ">", 1); break; case TEXT_NODE: case CDATA_SECTION_NODE: tcldom_AppendEscaped(xmlString, chan, ((domTextNode*)node)->nodeValue, ((domTextNode*)node)->valueLength, outputFlags); break; case COMMENT_NODE: if (comments) { writeChars(xmlString, chan, "", 3); } break; case PROCESSING_INSTRUCTION_NODE: writeChars(xmlString, chan, "targetValue, ((domProcessingInstructionNode*)node)->targetLength); if (((domProcessingInstructionNode*)node)->dataLength) { writeChars(xmlString, chan, " ", 1); writeChars(xmlString, chan, ((domProcessingInstructionNode*)node)->dataValue, ((domProcessingInstructionNode*)node)->dataLength); } writeChars(xmlString, chan, "?>", 2); break; default: /* Nothing to output */ break; } return; } /*---------------------------------------------------------------------------- | serializeAsCanonicalXML | \---------------------------------------------------------------------------*/ static int serializeAsCanonicalXML ( domNode *node, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { int optionIndex, mode, comments = 0, first= 1; int lengthAttOrderArray = C14N_ATTR_SORT_SIZE_INIT; Tcl_Channel chan = NULL; domNode *docChild; Tcl_Obj *resultObj; domAttrNode *attOrderArray; static const char *asCanonicalXMLOptions[] = { "-channel", "-comments", NULL }; enum asCanonicalXMLOption { m_channel, m_comments }; while (objc > 3) { if (Tcl_GetIndexFromObj(interp, objv[2], asCanonicalXMLOptions, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum asCanonicalXMLOption) optionIndex) { case m_channel: chan = Tcl_GetChannel (interp, Tcl_GetString (objv[3]), &mode); if (chan == NULL) { SetResult("the -channel option must have a Tcl channel" " argument"); return TCL_ERROR; } if ((mode & TCL_WRITABLE) == 0) { SetResult ("channel is not opened for writing"); return TCL_ERROR; } objc -= 2; objv += 2; break; case m_comments: if (Tcl_GetBooleanFromObj(interp, objv[3], &comments) != TCL_OK) { return TCL_ERROR; } objc -= 2; objv += 2; break; } } if (objc > 2) { SetResult ("unexpected argument(s) after options"); return TCL_ERROR; } attOrderArray = (domAttrNode *) MALLOC (sizeof (domAttrNode) * C14N_ATTR_SORT_SIZE_INIT); if (node->nodeType == DOCUMENT_NODE) { docChild = ((domDocument*)node)->rootNode->firstChild; resultObj = Tcl_GetObjResult (interp); while (docChild) { if (first) { first = 0; } else { if ((docChild->nodeType != COMMENT_NODE) || comments) { writeChars(resultObj, chan, "\n", 1); } } treeAsCanonicalXML(resultObj, docChild, chan, comments, &attOrderArray, &lengthAttOrderArray); docChild = docChild->nextSibling; } } else { treeAsCanonicalXML(Tcl_GetObjResult (interp), node, chan, comments, &attOrderArray, &lengthAttOrderArray); } FREE (attOrderArray); return TCL_OK; } /*---------------------------------------------------------------------------- | serializeAsHTML | \---------------------------------------------------------------------------*/ static int serializeAsHTML ( domNode *node, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { char *channelId; int optionIndex, mode, escapeNonASCII = 0, htmlEntities = 0; int doctypeDeclaration = 0, onlyContents = 0, breakLines = 0; Tcl_Obj *resultPtr; Tcl_Channel chan = (Tcl_Channel) NULL; static const char *asHTMLOptions[] = { "-channel", "-escapeNonASCII", "-htmlEntities", "-doctypeDeclaration", "-onlyContents", "-breakLines", NULL }; enum asHTMLOption { m_channel, m_escapeNonASCII, m_htmlEntities, m_doctypeDeclaration, m_onlyContents, m_breakLines }; if (objc > 10) { Tcl_WrongNumArgs(interp, 2, objv, "?-channel ? ?-escapeNonASCII? " "?-htmlEntities? ?-doctypeDeclaration ? " "?-onlyContents? ?-breakLines?"); return TCL_ERROR; } while (objc > 2) { if (Tcl_GetIndexFromObj(interp, objv[2], asHTMLOptions, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum asHTMLOption) optionIndex) { case m_channel: if (objc < 4) { SetResult("-channel must have a channeldID as argument"); return TCL_ERROR; } channelId = Tcl_GetString(objv[3]); chan = Tcl_GetChannel(interp, channelId, &mode); if (chan == (Tcl_Channel) NULL) { SetResult("-channel must have a channeldID as argument"); return TCL_ERROR; } if ((mode & TCL_WRITABLE) == 0) { Tcl_AppendResult(interp, "channel \"", channelId, "\" wasn't opened for writing", (char*)NULL); return TCL_ERROR; } objc -= 2; objv += 2; break; case m_escapeNonASCII: escapeNonASCII = 1; objc--; objv++; break; case m_htmlEntities: htmlEntities = 1; objc--; objv++; break; case m_doctypeDeclaration: if (node->nodeType != DOCUMENT_NODE) { SetResult("-doctypeDeclaration as flag to the method " "'asHTML' is only allowed for domDocCmds"); return TCL_ERROR; } if (objc < 4) { SetResult("-doctypeDeclaration must have a boolean value " "as argument"); return TCL_ERROR; } if (Tcl_GetBooleanFromObj(interp, objv[3], &doctypeDeclaration) != TCL_OK) { return TCL_ERROR; } objc -= 2; objv += 2; break; case m_onlyContents: onlyContents = 1; objc--; objv++; break; case m_breakLines: breakLines = 1; objc--; objv++; break; } } resultPtr = Tcl_NewStringObj("", 0); tcldom_treeAsHTML(resultPtr, node, chan, escapeNonASCII, htmlEntities, doctypeDeclaration, 0, onlyContents, breakLines); Tcl_AppendResult(interp, Tcl_GetString(resultPtr), NULL); Tcl_DecrRefCount(resultPtr); return TCL_OK; } /*---------------------------------------------------------------------------- | serializeAsJSON | \---------------------------------------------------------------------------*/ static int serializeAsJSON ( domNode *node, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { char *channelId; int optionIndex, mode, outputFlags = 0, indent = -1; Tcl_Obj *resultPtr; Tcl_Channel chan = (Tcl_Channel) NULL; static const char *asJSONOptions[] = { "-channel", "-indent", NULL }; enum asJSONOption { m_channel, m_indent }; if (node->nodeType != ELEMENT_NODE) { SetResult("Not an element node.\n"); return TCL_ERROR; } if (objc > 5) { Tcl_WrongNumArgs(interp, 2, objv, "?-channel ? " "?-indent ?"); return TCL_ERROR; } while (objc > 2) { if (Tcl_GetIndexFromObj(interp, objv[2], asJSONOptions, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum asJSONOption) optionIndex) { case m_channel: if (objc < 4) { SetResult("-channel must have a channeldID as argument"); return TCL_ERROR; } channelId = Tcl_GetString(objv[3]); chan = Tcl_GetChannel(interp, channelId, &mode); if (chan == (Tcl_Channel) NULL) { SetResult("-channel must have a channeldID as argument"); return TCL_ERROR; } if ((mode & TCL_WRITABLE) == 0) { Tcl_AppendResult(interp, "channel \"", channelId, "\" wasn't opened for writing", (char*)NULL); return TCL_ERROR; } objc -= 2; objv += 2; break; case m_indent: if (objc < 4) { SetResult("-indent must have an argument " "(0..8 or 'no'/'none')"); return TCL_ERROR; } if (strcmp("none", Tcl_GetString(objv[3]))==0) { indent = -1; } else if (strcmp("no", Tcl_GetString(objv[3]))==0) { indent = -1; } else if (strcmp("tabs", Tcl_GetString(objv[3]))==0) { /* User wants indentation */ indent = 0; outputFlags |= SERIALIZE_INDENT_WITH_TAB; } else if (Tcl_GetIntFromObj(interp, objv[3], &indent) != TCL_OK) { SetResult( "indent must be an integer (0..8) or 'no'/'none'"); return TCL_ERROR; } else if (indent < 0 || indent > 8) { SetResult( "indent must be an integer (0..8) or 'no'/'none'"); return TCL_ERROR; } objc -= 2; objv += 2; break; } } resultPtr = Tcl_NewStringObj("", 0); tcldom_treeAsJSON(resultPtr, node, chan, indent, outputFlags, 0, JSON_START); Tcl_AppendResult(interp, Tcl_GetString(resultPtr), NULL); Tcl_DecrRefCount(resultPtr); return TCL_OK; } /*---------------------------------------------------------------------------- | cdataSectionElements | \---------------------------------------------------------------------------*/ static int cdataSectionElements ( domDocument *doc, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { int result, hnew; Tcl_Obj *resultPtr,*namePtr; Tcl_HashEntry *h; Tcl_HashSearch search; CheckArgs (3,4,0, " cdataSectionElements ?URI:?localname " "?boolean?"); if (objc == 3) { if (Tcl_GetString(objv[2])[0] == '*' && Tcl_GetString(objv[2])[1] == '\0') { Tcl_ResetResult (interp); if (doc->doctype && doc->doctype->cdataSectionElements) { resultPtr = Tcl_GetObjResult (interp); for (h = Tcl_FirstHashEntry ( doc->doctype->cdataSectionElements, &search); h != NULL; h = Tcl_NextHashEntry(&search)) { namePtr = Tcl_NewStringObj ( Tcl_GetHashKey (doc->doctype->cdataSectionElements, h), -1); result = Tcl_ListObjAppendElement (interp, resultPtr, namePtr); if (result != TCL_OK) { Tcl_DecrRefCount(namePtr); return result; } } } return TCL_OK; } if (!doc->doctype || !doc->doctype->cdataSectionElements) { SetBooleanResult (0); } else { if (Tcl_FindHashEntry (doc->doctype->cdataSectionElements, Tcl_GetString (objv[2]))) { SetBooleanResult (1); } else { SetBooleanResult (0); } } } else { if (Tcl_GetBooleanFromObj (interp, objv[3], &result) != TCL_OK) { return TCL_ERROR; } if (result) { if (!doc->doctype) { doc->doctype = (domDocInfo *)MALLOC(sizeof(domDocInfo)); memset(doc->doctype, 0,(sizeof(domDocInfo))); } if (!doc->doctype->cdataSectionElements) { doc->doctype->cdataSectionElements = (Tcl_HashTable *)MALLOC(sizeof(Tcl_HashTable)); Tcl_InitHashTable (doc->doctype->cdataSectionElements, TCL_STRING_KEYS); } Tcl_CreateHashEntry (doc->doctype->cdataSectionElements, Tcl_GetString (objv[2]), &hnew); } else { if (doc->doctype && doc->doctype->cdataSectionElements) { h = Tcl_FindHashEntry (doc->doctype->cdataSectionElements, Tcl_GetString (objv[2])); if (h) { Tcl_DeleteHashEntry (h); if (!doc->doctype->cdataSectionElements->numEntries) { Tcl_DeleteHashTable ( doc->doctype->cdataSectionElements ); FREE (doc->doctype->cdataSectionElements); doc->doctype->cdataSectionElements = NULL; } } } } SetBooleanResult(result); } return TCL_OK; } /*---------------------------------------------------------------------------- | selectNodesNamespaces | \---------------------------------------------------------------------------*/ int tcldom_prefixNSlist ( char ***prefixnsPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], const char *methodName ) { char **prefixns = *prefixnsPtr; domLength len, i; int result; Tcl_Obj *objPtr, *listPtr; i = 0; if (objc == 1) { if (!prefixns) return TCL_OK; listPtr = Tcl_NewListObj (0, NULL); i = 0; while (prefixns[i]) { Tcl_ListObjAppendElement ( interp, listPtr, Tcl_NewStringObj (prefixns[i], -1) ); i++; } Tcl_SetObjResult (interp, listPtr); return TCL_OK; } result = Tcl_ListObjLength (interp, objv[1], &len); if (result != TCL_OK || (len % 2) != 0) { SetResult3 ("The optional argument to ", methodName, " must be a 'prefix namespace' pairs list"); return TCL_ERROR; } if (prefixns) { while (prefixns[i]) { FREE (prefixns[i]); i++; } } if (len == 0) { FREE (prefixns); *prefixnsPtr = NULL; return TCL_OK; } if (i < len + 1) { if (prefixns) FREE (prefixns); prefixns = MALLOC (sizeof (char*) * (len+1)); *prefixnsPtr = prefixns; } for (i = 0; i < len; i++) { Tcl_ListObjIndex (interp, objv[1], i, &objPtr); prefixns[i] = tdomstrdup (Tcl_GetString (objPtr)); } prefixns[len] = NULL; Tcl_SetObjResult (interp, objv[1]); return TCL_OK; } /*---------------------------------------------------------------------------- | renameNodes | \---------------------------------------------------------------------------*/ static int renameNodes ( domDocument *doc, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { domLength len, i; int hnew; Tcl_HashEntry *h; Tcl_Obj *objPtr; domNode *node; CheckArgs (4,4,0, " renameNode nodeList name"); if (Tcl_ListObjLength (interp, objv[2], &len) != TCL_OK) { SetResult ("The first argument to the renameNode method" " must be a list of element nodes."); return TCL_ERROR; } h = Tcl_CreateHashEntry(&HASHTAB(doc,tdom_tagNames), Tcl_GetString(objv[3]), &hnew); for (i = 0; i < len; i++) { Tcl_ListObjIndex (interp, objv[2], i, &objPtr); node = tcldom_getNodeFromObj (interp, objPtr); if (node == NULL) { return TCL_ERROR; } node->nodeName = (char *)&(h->key); } return TCL_OK; } /*---------------------------------------------------------------------------- | deleteXPathCache | \---------------------------------------------------------------------------*/ static int deleteXPathCache ( domDocument *doc, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { Tcl_HashEntry *h; Tcl_HashSearch search; CheckArgs (2,3,0, " deleteXPathCache ?xpathQuery?"); if (objc == 3) { if (!doc->xpathCache) { return TCL_OK; } h = Tcl_FindHashEntry (doc->xpathCache, Tcl_GetString(objv[2])); if (h) { xpathFreeAst((ast)Tcl_GetHashValue (h)); Tcl_DeleteHashEntry (h); } return TCL_OK; } if (!doc->xpathCache) { return TCL_OK; } h = Tcl_FirstHashEntry (doc->xpathCache, &search); while (h) { xpathFreeAst((ast)Tcl_GetHashValue (h)); h = Tcl_NextHashEntry (&search); } Tcl_DeleteHashTable (doc->xpathCache); FREE (doc->xpathCache); doc->xpathCache = NULL; return TCL_OK; } /*---------------------------------------------------------------------------- | applyXSLT | \---------------------------------------------------------------------------*/ static int applyXSLT ( domNode *node, Tcl_Interp *interp, void *clientData, int objc, Tcl_Obj *const objv[] ) { char *usage, **parameters = NULL, *errMsg, *option; Tcl_Obj *objPtr, *localListPtr = (Tcl_Obj *)NULL; int result, optionIndex, ignoreUndeclaredParameters = 0; int maxApplyDepth = MAX_XSLT_APPLY_DEPTH; domLength i, length; domDocument *xsltDoc, *xmlDoc, *resultDoc = NULL; XsltMsgCBInfo xsltMsgInfo; static char *method_usage = "wrong # args: should be \"nodeObj xslt ?-parameters parameterList? " "?-ignoreUndeclaredParameters? ?-maxApplyDepth int? " "?-xsltmessagecmd cmd? xsltDocNode ?varname?\""; static char *cmd_usage = "wrong # args: should be \"?-parameters parameterList? " "?-ignoreUndeclaredParameters? ?-maxApplyDepth int? " "?-xsltmessagecmd cmd? ?objVar?\""; static const char *xsltOptions[] = { "-parameters", "-ignoreUndeclaredParameters", "-maxApplyDepth", "-xsltmessagecmd", NULL }; enum xsltOption { m_parameters, m_ignoreUndeclaredParameters, m_maxApplyDepth, m_xsltmessagecmd }; xsltMsgInfo.interp = interp; xsltMsgInfo.msgcmd = NULL; if (node) usage = method_usage; else usage = cmd_usage; while (objc > 1) { option = Tcl_GetString(objv[0]); if (option[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[0], xsltOptions, "option", 0, &optionIndex) != TCL_OK) { goto applyXSLTCleanUP; } switch ((enum xsltOption) optionIndex) { case m_parameters: if (objc < 3) {SetResult(usage); goto applyXSLTCleanUP;} if (Tcl_ListObjLength(interp, objv[1], &length) != TCL_OK) { SetResult("ill-formed parameters list: the -parameters " "option needs a list of parameter name and " "parameter value pairs"); goto applyXSLTCleanUP; } if (length % 2) { SetResult("parameter value missing: the -parameters " "option needs a list of parameter name and " "parameter value pairs"); goto applyXSLTCleanUP; } if (parameters) { SetResult("only one -parameters option allowed"); goto applyXSLTCleanUP; } localListPtr = Tcl_DuplicateObj(objv[1]); Tcl_IncrRefCount(localListPtr); parameters = (char **)MALLOC(sizeof(char *)*(length+1)); for (i = 0; i < length; i ++) { Tcl_ListObjIndex(interp, localListPtr, i, &objPtr); parameters[i] = Tcl_GetString(objPtr); } parameters[length] = NULL; objc -= 2; objv += 2; break; case m_maxApplyDepth: if (objc < 3) {SetResult(usage); goto applyXSLTCleanUP;} if (Tcl_GetIntFromObj(interp, objv[1], &maxApplyDepth) != TCL_OK) { SetResult("-maxApplyDepth requires a positive integer " "as argument"); goto applyXSLTCleanUP; } if (maxApplyDepth < 1) { SetResult("-maxApplyDepth requires a positive integer " "as argument"); goto applyXSLTCleanUP; } objc -= 2; objv += 2; break; case m_ignoreUndeclaredParameters: if (objc < 2) {SetResult(usage); goto applyXSLTCleanUP;} ignoreUndeclaredParameters = 1; objc--; objv++; break; case m_xsltmessagecmd: if (objc < 3) {SetResult(usage); goto applyXSLTCleanUP;} if (xsltMsgInfo.msgcmd) { Tcl_DecrRefCount(xsltMsgInfo.msgcmd); } xsltMsgInfo.msgcmd = objv[1]; Tcl_IncrRefCount(xsltMsgInfo.msgcmd); objc -= 2; objv += 2; break; } } if (objc > 2 || objc < 1) {SetResult(usage); goto applyXSLTCleanUP;} if (node) { xsltDoc = tcldom_getDocumentFromName(interp, Tcl_GetString(objv[0]), &errMsg); if (xsltDoc == NULL) { SetResult( errMsg ); goto applyXSLTCleanUP; } } else { xmlDoc = tcldom_getDocumentFromName(interp,Tcl_GetString(objv[0]), &errMsg); if (xmlDoc == NULL) { SetResult( errMsg ); goto applyXSLTCleanUP; } node = (domNode *) xmlDoc; xsltDoc = NULL; } result = xsltProcess(xsltDoc, node, clientData, parameters, ignoreUndeclaredParameters, maxApplyDepth, tcldom_xpathFuncCallBack, interp, tcldom_xsltMsgCB, &xsltMsgInfo, &errMsg, &resultDoc); if (result < 0) { SetResult( errMsg ); FREE(errMsg); if (objc == 2) { Tcl_SetVar (interp, Tcl_GetString(objv[1]), "", 0); } goto applyXSLTCleanUP; } if (parameters) { Tcl_DecrRefCount(localListPtr); FREE((char *) parameters); } if (xsltMsgInfo.msgcmd) { Tcl_DecrRefCount(xsltMsgInfo.msgcmd); } return tcldom_returnDocumentObj(interp, resultDoc, (objc == 2) ? objv[1] : NULL, 1, 0); applyXSLTCleanUP: if (localListPtr) { Tcl_DecrRefCount(localListPtr); FREE((char *) parameters); } if (xsltMsgInfo.msgcmd) { Tcl_DecrRefCount(xsltMsgInfo.msgcmd); } return TCL_ERROR; } /*---------------------------------------------------------------------------- | tcldom_XSLTObjCmd | \---------------------------------------------------------------------------*/ static int tcldom_XSLTObjCmd ( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { int index; char *errMsg = NULL; static const char *options[] = { "transform", "delete", NULL }; enum option { m_transform, m_delete }; /* Longest possible call currently is: xsltCmd transform -parameters parameterList \ -ignoreUndeclaredParameters -xsltmessagecmd cmd objVar */ CheckArgs(2,9,1,"option ?arg ...?"); /* This is not optimal, because we do the tcldom_getDocumentFromName call here and again in applyXSLT. This is only transitional, until will be deprecated */ if ((tcldom_getDocumentFromName (interp, Tcl_GetString(objv[1]), &errMsg) != NULL) || (Tcl_GetString (objv[1])[0] == '-')) { /* Method obmitted, may default to "transform", try this */ objv++; objc--; return applyXSLT(NULL, interp, (void *) clientData, objc, objv); } if (Tcl_GetIndexFromObj (interp, objv[1], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum option) index) { case m_transform: objv++;objv++; objc--;objc--; return applyXSLT(NULL, interp, (void *) clientData, objc, objv); case m_delete: if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } Tcl_DeleteCommand(interp, Tcl_GetString(objv[0])); } return TCL_OK; } /*---------------------------------------------------------------------------- | convertToXSLTCmd | \---------------------------------------------------------------------------*/ static int convertToXSLTCmd ( domDocument *doc, Tcl_Interp *interp, Tcl_Obj *var_name ) { char *errMsg, *objVar, objCmdName[80]; ClientData *clientData; doc->nodeFlags |= DONT_FREE; clientData = (ClientData *) xsltCompileStylesheet(doc, tcldom_xpathFuncCallBack, interp, 0, &errMsg); if (!clientData) { doc->nodeFlags &= ~DONT_FREE; SetResult(errMsg); if (var_name) { objVar = Tcl_GetString(var_name); Tcl_UnsetVar(interp, objVar, 0); Tcl_SetVar (interp, objVar, "", 0); } FREE(errMsg); return TCL_ERROR; } DOC_CMD(objCmdName, doc); Tcl_DeleteCommand( interp, objCmdName ); XSLT_CMD(objCmdName, doc); Tcl_CreateObjCommand(interp, objCmdName, tcldom_XSLTObjCmd, clientData, xsltFreeStateWrapper); if (var_name) { objVar = Tcl_GetString(var_name); Tcl_UnsetVar (interp, objVar, 0); Tcl_SetVar (interp, objVar, objCmdName, 0); } SetResult(objCmdName); return TCL_OK; } /*---------------------------------------------------------------------------- | tcldom_NodeObjCmd | \---------------------------------------------------------------------------*/ int tcldom_NodeObjCmd ( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { GetTcldomDATA; domNode *node, *child, *refChild, *oldChild, *refNode; domNS *ns; domAttrNode *attrs; domException exception; char tmp[200], prefix[MAX_PREFIX_LEN], *method, *nodeName, *str, *attr_name, *attr_val, *filter; const char *localName, *uri, *nsStr; int result, methodIndex, i; domLength length; XML_Size line, column; XML_Index byteIndex; int nsIndex, bool, hnew, legacy, jsonType; Tcl_Obj *namePtr, *resultPtr; Tcl_Obj *mobjv[MAX_REWRITE_ARGS], *storedErrMsg; Tcl_CmdInfo cmdInfo; Tcl_HashEntry *h; static const char *nodeMethods[] = { "firstChild", "nextSibling", "getAttribute", "nodeName", "nodeValue", "nodeType", "attributes", "asList", "find", "setAttribute", "removeAttribute", "parentNode", "previousSibling", "lastChild", "appendChild", "removeChild", "hasChildNodes", "localName", "childNodes", "ownerDocument", "insertBefore", "replaceChild", "getLine", "getColumn", "asXML", "appendFromList", "child", "fsibling", "psibling", "descendant", "ancestor", "text", "root", "hasAttribute", "cloneNode", "appendXML", "target", "data", "selectNodes", "namespaceURI", "getAttributeNS", "setAttributeNS", "hasAttributeNS", "removeAttributeNS", "asHTML", "prefix", "getBaseURI", "appendFromScript", "xslt", "toXPath", "delete", "getElementById", "getElementsByTagName", "getElementsByTagNameNS", "disableOutputEscaping", "precedes", "asText", "insertBeforeFromScript", "normalize", "baseURI", "asJSON", "asTclValue", "asTypedList", "jsonType", "attributeNames", "asCanonicalXML", "getByteIndex", #ifdef TCL_THREADS "readlock", "writelock", #endif NULL }; enum nodeMethod { m_firstChild, m_nextSibling, m_getAttribute, m_nodeName, m_nodeValue, m_nodeType, m_attributes, m_asList, m_find, m_setAttribute, m_removeAttribute, m_parentNode, m_previousSibling, m_lastChild, m_appendChild, m_removeChild, m_hasChildNodes, m_localName, m_childNodes, m_ownerDocument, m_insertBefore, m_replaceChild, m_getLine, m_getColumn, m_asXML, m_appendFromList, m_child, m_fsibling, m_psibling, m_descendant, m_ancestor, m_text, m_root, m_hasAttribute, m_cloneNode, m_appendXML, m_target, m_data, m_selectNodes, m_namespaceURI, m_getAttributeNS, m_setAttributeNS, m_hasAttributeNS, m_removeAttributeNS, m_asHTML, m_prefix, m_getBaseURI, m_appendFromScript, m_xslt, m_toXPath, m_delete, m_getElementById, m_getElementsByTagName, m_getElementsByTagNameNS, m_disableOutputEscaping, m_precedes, m_asText, m_insertBeforeFromScript, m_normalize, m_baseURI, m_asJSON, m_asTclValue, m_asTypedList, m_jsonType, m_attributeNames, m_asCanonicalXML, m_getByteIndex #ifdef TCL_THREADS ,m_readlock, m_writelock #endif }; node = (domNode*) clientData; if (TcldomDATA(domCreateCmdMode) == DOM_CREATECMDMODE_AUTO) { TcldomDATA(dontCreateObjCommands) = 0; } if (node == NULL) { if (objc < 3) { Tcl_WrongNumArgs (interp, 1, objv, "nodetoken subcommand ?arg ...?"); return TCL_ERROR; } if (TcldomDATA(domCreateCmdMode) == DOM_CREATECMDMODE_AUTO) { TcldomDATA(dontCreateObjCommands) = 1; } node = tcldom_getNodeFromObj(interp, objv[1]); if (node == NULL) { return TCL_ERROR; } objc--; objv++; } if (objc < 2) { Tcl_WrongNumArgs (interp, 1, objv, "subcommand ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], nodeMethods, "method", 0, &methodIndex) != TCL_OK) { method = Tcl_GetString(objv[1]); if (*method != '@') { /*-------------------------------------------------------- | not a getAttribute short cut: | try to find method implemented as normal Tcl proc \-------------------------------------------------------*/ result = 0; storedErrMsg = Tcl_GetObjResult (interp); Tcl_IncrRefCount (storedErrMsg); if (node->nodeType == ELEMENT_NODE) { /*---------------------------------------------------- | try to find Tcl level node specific method proc | | ::dom::domNode:::: | \---------------------------------------------------*/ sprintf(tmp, "::dom::domNode::%s::%s", (char*)node->nodeName, method); DBG(fprintf(stderr, "testing %s\n", tmp)); result = Tcl_GetCommandInfo(interp, tmp, &cmdInfo); } if (!result) { /*---------------------------------------------------- | try to find Tcl level general method proc | | ::dom::domNode:: | \---------------------------------------------------*/ sprintf(tmp, "::dom::domNode::%s", method); DBG(fprintf(stderr, "testing %s\n", tmp)); result = Tcl_GetCommandInfo(interp, tmp, &cmdInfo); } if (!result) { SetResult(Tcl_GetString (storedErrMsg)); Tcl_DecrRefCount (storedErrMsg); return TCL_ERROR; } Tcl_DecrRefCount (storedErrMsg); if (!cmdInfo.isNativeObjectProc) { SetResult("can't access Tcl level method!"); return TCL_ERROR; } if (objc >= MAX_REWRITE_ARGS) { SetResult("too many args to call Tcl level method!"); return TCL_ERROR; } mobjv[0] = objv[1]; mobjv[1] = objv[0]; for (i=2; i: try to look up attribute \-------------------------------------------------------*/ Tcl_ResetResult(interp); CheckArgs(2,3,1,"@ ?defaultvalue?"); if (node->nodeType != ELEMENT_NODE) { SetResult("NOT_AN_ELEMENT : there are no attributes"); return TCL_ERROR; } attrs = node->firstAttr; while (attrs && strcmp(attrs->nodeName, &(method[1]))) { attrs = attrs->nextSibling; } if (attrs) { SetResult(attrs->nodeValue); } else { if (objc == 3) { SetResult(Tcl_GetString(objv[2])); } else { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "Attribute \"", &(method[1]), "\" not found!", NULL); return TCL_ERROR; } } return TCL_OK; } /*---------------------------------------------------------------------- | node may have been deleted in the meantime by some other | thread operating on the tree, so check this fact before. | \---------------------------------------------------------------------*/ if (node->nodeFlags & IS_DELETED) { SetResult("node has been deleted"); return TCL_ERROR; } /*---------------------------------------------------------------------- | dispatch the node object method | \---------------------------------------------------------------------*/ switch ((enum nodeMethod)methodIndex) { case m_toXPath: CheckArgs(2,3,2,"?-legacy?"); legacy = 0; if (objc == 3) { if (!strcmp(Tcl_GetString(objv[2]), "-legacy")) { legacy = 1; } else { SetResult("unknown option! Options: ?-legacy?"); return TCL_ERROR; } } str = xpathNodeToXPath(node, legacy); SetResult (str); FREE (str); return TCL_OK; case m_xslt: CheckArgs(3,9,2, "?-parameters parameterList? " "?-ignoreUndeclaredParameters? ?-xsltmessagecmd cmd? " " ?objVar?"); objv += 2; objc -= 2; return applyXSLT(node, interp, NULL, objc, objv); case m_selectNodes: return tcldom_selectNodes (interp, node, --objc, ++objv); case m_find: CheckArgs(4,5,2,"attrName attrVal ?nodeObjVar?"); attr_name = Tcl_GetStringFromObj(objv[2], NULL); attr_val = Tcl_GetStringFromObj(objv[3], &length); return tcldom_setInterpAndReturnVar (interp, tcldom_find(node, attr_name, attr_val, length), (objc == 5) ? objv[4] : NULL); case m_child: CheckArgs(3,6,2,"instance|all ?type? ?attr value?"); return tcldom_xpointerSearch(interp, XP_CHILD, node, objc, objv); case m_descendant: CheckArgs(3,6,2,"instance|all ?type? ?attr value?"); return tcldom_xpointerSearch(interp, XP_DESCENDANT,node,objc,objv); case m_ancestor: CheckArgs(3,6,2,"instance|all ?type? ?attr value?"); return tcldom_xpointerSearch(interp, XP_ANCESTOR, node,objc,objv); case m_fsibling: CheckArgs(3,6,2,"instance|all ?type? ?attr value?"); return tcldom_xpointerSearch(interp, XP_FSIBLING, node,objc,objv); case m_psibling: CheckArgs(3,6,2,"instance|all ?type? ?attr value?"); return tcldom_xpointerSearch(interp, XP_PSIBLING, node,objc,objv); case m_root: CheckArgs(2,3,2,"?nodeObjVar?"); while (node->parentNode) { node = node->parentNode; } return tcldom_setInterpAndReturnVar(interp, node, (objc == 3) ? objv[2] : NULL); case m_text: CheckArgs(2,2,2,""); if (node->nodeType != ELEMENT_NODE) { SetResult("NOT_AN_ELEMENT"); return TCL_ERROR; } Tcl_ResetResult(interp); child = node->firstChild; while (child) { if ((child->nodeType == TEXT_NODE) || (child->nodeType == CDATA_SECTION_NODE)) { Tcl_AppendToObj(Tcl_GetObjResult(interp), ((domTextNode*)child)->nodeValue, ((domTextNode*)child)->valueLength); } child = child->nextSibling; } return TCL_OK; case m_attributes: CheckArgs(2,3,2,"?nameFilter?"); if (node->nodeType != ELEMENT_NODE) { SetResult(""); return TCL_OK; } filter = NULL; if (objc == 3) { filter = Tcl_GetString(objv[2]); } Tcl_ResetResult(interp); resultPtr = Tcl_GetObjResult(interp); attrs = node->firstAttr; while (attrs != NULL) { if (!filter || Tcl_StringMatch((char*)attrs->nodeName, filter)) { if (attrs->namespace == 0) { namePtr = Tcl_NewStringObj((char*)attrs->nodeName, -1); } else { domSplitQName((char*)attrs->nodeName, prefix, &localName); mobjv[0] = Tcl_NewStringObj((char*)localName, -1); mobjv[1] = Tcl_NewStringObj( domNamespacePrefix((domNode*)attrs), -1 ); mobjv[2] = Tcl_NewStringObj( domNamespaceURI((domNode*)attrs), -1 ); namePtr = Tcl_NewListObj(3, mobjv); } result = Tcl_ListObjAppendElement(interp, resultPtr, namePtr); if (result != TCL_OK) { Tcl_DecrRefCount(namePtr); return result; } } attrs = attrs->nextSibling; } break; case m_attributeNames: CheckArgs(2,3,2,"?nameFilter?"); if (node->nodeType != ELEMENT_NODE) { SetResult(""); return TCL_OK; } filter = NULL; if (objc == 3) { filter = Tcl_GetString(objv[2]); } resultPtr = Tcl_GetObjResult(interp); attrs = node->firstAttr; while (attrs != NULL) { if (!filter || Tcl_StringMatch((char*)attrs->nodeName, filter)) { namePtr = Tcl_NewStringObj((char*)attrs->nodeName, -1); result = Tcl_ListObjAppendElement(interp, resultPtr, namePtr); if (result != TCL_OK) { Tcl_DecrRefCount(namePtr); return result; } } attrs = attrs->nextSibling; } break; case m_asList: CheckArgs(2,2,2,""); Tcl_SetObjResult(interp, tcldom_treeAsTclList(interp, node)); break; case m_asXML: Tcl_ResetResult(interp); if (serializeAsXML(node, interp, objc, objv) != TCL_OK) { return TCL_ERROR; } break; case m_asCanonicalXML: Tcl_ResetResult(interp); if (serializeAsCanonicalXML(node, interp, objc, objv) != TCL_OK) { return TCL_ERROR; } break; case m_asHTML: Tcl_ResetResult(interp); if (serializeAsHTML(node, interp, objc, objv) != TCL_OK) { return TCL_ERROR; } break; case m_asJSON: if (serializeAsJSON(node, interp, objc, objv) != TCL_OK) { return TCL_ERROR; } break; case m_asTclValue: CheckArgs(2,3,2,"?typeVar?"); if (tcldom_treeAsTclValue (interp, node, (objc == 3) ? objv[2] : NULL) != TCL_OK) { return TCL_ERROR; } break; case m_asTypedList: CheckArgs(2,2,2,""); tcldom_treeAsTypedList (interp, node); break; case m_getAttribute: CheckArgs(3,4,2,"attrName ?defaultValue?"); if (node->nodeType != ELEMENT_NODE) { SetResult("NOT_AN_ELEMENT : there are no attributes"); return TCL_ERROR; } attr_name = Tcl_GetString(objv[2]); attrs = node->firstAttr; while(attrs && strcmp(attrs->nodeName, attr_name)) { attrs = attrs->nextSibling; } if (attrs) { SetResult(attrs->nodeValue); return TCL_OK; } if (objc == 4) { SetResult(Tcl_GetString(objv[3])); return TCL_OK; } else { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "Attribute \"", attr_name, "\" not found!", NULL); return TCL_ERROR; } break; case m_getAttributeNS: CheckArgs(4,5,2,"uri localName ?defaultValue?"); if (node->nodeType != ELEMENT_NODE) { SetResult("NOT_AN_ELEMENT : there are no attributes"); return TCL_ERROR; } uri = Tcl_GetString(objv[2]); localName = Tcl_GetString(objv[3]); attrs = domGetAttributeNodeNS(node, uri, localName); if (attrs) { SetResult(attrs->nodeValue); return TCL_OK; } if (objc == 5) { SetResult(Tcl_GetString(objv[4])); return TCL_OK; } Tcl_ResetResult (interp); Tcl_AppendResult (interp, "Attribute \"", localName, "\" in " "namespace \"", uri, "\" not found!", NULL); return TCL_ERROR; case m_setAttribute: if (node->nodeType != ELEMENT_NODE) { SetResult("NOT_AN_ELEMENT : there are no attributes"); return TCL_ERROR; } if ((objc < 4) || ((objc % 2)!=0)) { SetResult("attrName value pairs expected"); return TCL_ERROR; } for ( i = 2; i < objc; ) { attr_name = Tcl_GetString(objv[i++]); CheckName (interp, attr_name, "attribute", 0); attr_val = Tcl_GetString(objv[i++]); CheckText (interp, attr_val, "attribute"); domSetAttribute(node, attr_name, attr_val); } return tcldom_setInterpAndReturnVar(interp, node, NULL); case m_setAttributeNS: if (node->nodeType != ELEMENT_NODE) { SetResult("NOT_AN_ELEMENT : there are no attributes"); return TCL_ERROR; } if ((objc < 5) || (((objc - 2) % 3) != 0)) { SetResult("uri attrName value triples expected"); return TCL_ERROR; } for (i = 2; i < objc;) { uri = Tcl_GetString(objv[i++]); attr_name = Tcl_GetString(objv[i++]); CheckName (interp, attr_name, "full qualified attribute", 1); attr_val = Tcl_GetString(objv[i++]); CheckText (interp, attr_val, "attribute"); attrs = domSetAttributeNS(node, attr_name, attr_val, uri, 0); if (!attrs) { if (uri[0]) { SetResult("An attribute in a namespace " "must have a prefix"); } else { SetResult("For all prefixed attributes with prefixes " "other than 'xml' or 'xmlns' " "you have to provide a namespace URI"); } return TCL_ERROR; } } return tcldom_setInterpAndReturnVar(interp, node, NULL); case m_hasAttribute: CheckArgs(3,3,2,"attrName"); if (node->nodeType != ELEMENT_NODE) { SetResult("NOT_AN_ELEMENT : there are no attributes"); return TCL_ERROR; } attr_name = Tcl_GetString(objv[2]); attrs = node->firstAttr; while (attrs && strcmp(attrs->nodeName, attr_name)) { attrs = attrs->nextSibling; } if (attrs) { SetResult("1"); return TCL_OK; } SetResult("0"); return TCL_OK; case m_hasAttributeNS: CheckArgs(4,4,2,"uri localName"); if (node->nodeType != ELEMENT_NODE) { SetResult("NOT_AN_ELEMENT : there are no attributes"); return TCL_ERROR; } uri = Tcl_GetString(objv[2]); localName = Tcl_GetString(objv[3]); attrs = node->firstAttr; while (attrs) { domSplitQName(attrs->nodeName, prefix, &nsStr); if (!strcmp(localName,nsStr)) { ns = domGetNamespaceByIndex(node->ownerDocument, attrs->namespace); if (ns && !strcmp(ns->uri, uri)) { SetResult("1"); return TCL_OK; } } attrs = attrs->nextSibling; } SetResult("0"); return TCL_OK; case m_removeAttribute: CheckArgs(3,3,2,"attrName"); if (node->nodeType != ELEMENT_NODE) { SetResult("NOT_AN_ELEMENT : there are no attributes"); return TCL_ERROR; } attr_name = Tcl_GetString(objv[2]); result = domRemoveAttribute(node, attr_name); if (result) { SetResult("can't remove attribute '"); AppendResult(attr_name); AppendResult("'"); return TCL_ERROR; } return tcldom_setInterpAndReturnVar(interp, node, NULL); case m_removeAttributeNS: CheckArgs(4,4,2,"uri attrName"); if (node->nodeType != ELEMENT_NODE) { SetResult("NOT_AN_ELEMENT : there are no attributes"); return TCL_ERROR; } uri = Tcl_GetString(objv[2]); localName = Tcl_GetString(objv[3]); result = domRemoveAttributeNS(node, uri, localName); if (result < 0) { SetResult("can't remove attribute with localName '"); AppendResult(localName); AppendResult("'"); return TCL_ERROR; } return tcldom_setInterpAndReturnVar(interp, node, NULL); case m_nextSibling: CheckArgs(2,3,2,"?nodeObjVar?"); return tcldom_setInterpAndReturnVar(interp, node->nextSibling, (objc == 3) ? objv[2] : NULL); case m_previousSibling: CheckArgs(2,3,2,"?nodeObjVar?"); return tcldom_setInterpAndReturnVar(interp, node->previousSibling, (objc == 3) ? objv[2] : NULL); case m_firstChild: CheckArgs(2,3,2,"?nodeObjVar?"); if (node->nodeType == ELEMENT_NODE) { return tcldom_setInterpAndReturnVar(interp, node->firstChild, (objc == 3) ? objv[2] : NULL); } return tcldom_setInterpAndReturnVar(interp, NULL, (objc == 3) ? objv[2] : NULL); case m_lastChild: CheckArgs(2,3,2,"?nodeObjVar?"); if (node->nodeType == ELEMENT_NODE) { return tcldom_setInterpAndReturnVar(interp, node->lastChild, (objc == 3) ? objv[2] : NULL); } return tcldom_setInterpAndReturnVar(interp, NULL, (objc == 3) ? objv[2] : NULL); case m_parentNode: CheckArgs(2,3,2,"?nodeObjVar?"); return tcldom_setInterpAndReturnVar(interp, node->parentNode, (objc == 3) ? objv[2] : NULL); case m_appendFromList: CheckArgs(3,3,2,"list"); return tcldom_appendFromTclList(interp, node, objv[2]); case m_appendFromScript: CheckArgs(3,3,2,"script"); result = nodecmd_appendFromScript(interp, node, objv[2]); if (result == TCL_BREAK) { SetResult(""); return TCL_OK; } if (result != TCL_OK) { return TCL_ERROR; } return tcldom_setInterpAndReturnVar(interp, node, NULL); case m_insertBeforeFromScript: CheckArgs(4,4,2, "script refChild"); if (objv[3]->typePtr == &tdomNodeType) { refChild = objv[3]->internalRep.otherValuePtr; } else { nodeName = Tcl_GetString (objv[3]); if (nodeName[0] == '\0') { refChild = NULL; } else { refChild = tcldom_getNodeFromObj (interp, objv[3]); if (refChild == NULL) { return TCL_ERROR; } } } result = nodecmd_insertBeforeFromScript(interp, node, objv[2], refChild); if (result == TCL_BREAK) { SetResult(""); return TCL_OK; } if (result != TCL_OK) { return TCL_ERROR; } return tcldom_setInterpAndReturnVar (interp, node, NULL); case m_appendXML: CheckArgs(3,3,2,"xmlString"); return tcldom_appendXML(interp, node, objv[2]); case m_appendChild: CheckArgs(3,3,2,"nodeToAppend"); child = tcldom_getNodeFromObj(interp, objv[2]); if (child == NULL) { return TCL_ERROR; } exception = domAppendChild (node, child); if (exception != OK) { SetResult(domException2String(exception)); return TCL_ERROR; } return tcldom_setInterpAndReturnVar(interp, child, NULL); case m_cloneNode: CheckArgs(2,3,2,"?-deep?"); if (objc == 3) { if (!strcmp(Tcl_GetString(objv[2]), "-deep")) { return tcldom_setInterpAndReturnVar( interp, domCloneNode(node, 1), NULL ); } SetResult("unknown option! Options: ?-deep? "); return TCL_ERROR; } return tcldom_setInterpAndReturnVar( interp, domCloneNode(node, 0), NULL ); case m_removeChild: CheckArgs(3,3,2,"childToRemove"); child = tcldom_getNodeFromObj(interp, objv[2]); if (child == NULL) { return TCL_ERROR; } exception = domRemoveChild (node, child); if (exception != OK) { SetResult (domException2String (exception)); return TCL_ERROR; } return tcldom_setInterpAndReturnVar(interp, child, NULL); case m_insertBefore: CheckArgs(4,4,2,"childToInsert refChild"); child = tcldom_getNodeFromObj(interp, objv[2]); if (child == NULL) { return TCL_ERROR; } if (objv[3]->typePtr == &tdomNodeType) { refChild = objv[3]->internalRep.otherValuePtr; } else { nodeName = Tcl_GetString (objv[3]); if (nodeName[0] == '\0') { refChild = NULL; } else { refChild = tcldom_getNodeFromObj (interp, objv[3]); if (refChild == NULL) { return TCL_ERROR; } } } exception = domInsertBefore(node, child, refChild); if (exception != OK) { SetResult(domException2String(exception)); return TCL_ERROR; } return tcldom_setInterpAndReturnVar(interp, child, NULL); case m_replaceChild: CheckArgs(4,4,2,"new old"); child = tcldom_getNodeFromObj(interp, objv[2]); if (child == NULL) { return TCL_ERROR; } oldChild = tcldom_getNodeFromObj(interp, objv[3]); if (oldChild == NULL) { return TCL_ERROR; } exception = domReplaceChild(node, child, oldChild); if (exception != OK) { SetResult(domException2String(exception)); return TCL_ERROR; } return tcldom_setInterpAndReturnVar(interp, oldChild, NULL); case m_hasChildNodes: CheckArgs(2,2,2,""); if (node->nodeType == ELEMENT_NODE) { SetIntResult(node->firstChild ? 1 : 0); } else { SetIntResult(0); } break; case m_childNodes: CheckArgs(2,2,2,""); resultPtr = Tcl_GetObjResult(interp); if (node->nodeType == ELEMENT_NODE) { child = node->firstChild; while (child != NULL) { namePtr = tcldom_returnNodeObj(interp, child); result = Tcl_ListObjAppendElement(interp, resultPtr, namePtr); if (result != TCL_OK) { Tcl_DecrRefCount(namePtr); return result; } child = child->nextSibling; } } break; case m_getElementsByTagName: CheckArgs(3,3,2,"elementName"); if (node->nodeType != ELEMENT_NODE) { SetResult("Node must be an element node."); return TCL_ERROR; } Tcl_ResetResult(interp); return tcldom_getElementsByTagName(interp, Tcl_GetString(objv[2]), node->firstChild, -1, NULL); case m_getElementsByTagNameNS: CheckArgs(4,4,2,"uri localname"); if (node->nodeType != ELEMENT_NODE) { SetResult("Node must be an element node."); return TCL_ERROR; } uri = Tcl_GetString(objv[2]); str = Tcl_GetString(objv[3]); nsIndex = -1; if (uri[0] == '*' && uri[1] == '\0') { nsIndex = -3; } else if (uri[0] == '\0') { /* all elements not in a namespace */ nsIndex = -4; } else { for (i = 0; i <= node->ownerDocument->nsptr; i++) { if (strcmp (node->ownerDocument->namespaces[i]->uri, uri)==0) { if (nsIndex != -1) { /* OK, this is one of the 'degenerated' (though legal) documents, which bind the same URI to different prefixes. */ nsIndex = -2; break; } nsIndex = node->ownerDocument->namespaces[i]->index; } } } if (nsIndex == -1) { /* There isn't such a namespace declared in this document. Since getElementsByTagNameNS doesn't raise an exception short cut: return empty result */ Tcl_ResetResult(interp); return TCL_OK; } return tcldom_getElementsByTagName(interp, str, node->firstChild, nsIndex, uri); case m_getElementById: CheckArgs(3,3,2,"id"); if (node->ownerDocument->ids) { str = Tcl_GetString(objv[2]); h = Tcl_FindHashEntry(node->ownerDocument->ids, str); if (h) { domNode *node = Tcl_GetHashValue(h); return tcldom_setInterpAndReturnVar(interp, node, NULL); } } SetResult(""); return TCL_OK; case m_nodeName: CheckArgs(2,2,2,""); if (node->nodeType == ELEMENT_NODE) { SetResult((char*)node->nodeName); } else if (node->nodeType == TEXT_NODE) { SetResult("#text"); } else if (node->nodeType == PROCESSING_INSTRUCTION_NODE) { domProcessingInstructionNode *dpn; dpn = (domProcessingInstructionNode *)node; Tcl_SetStringObj(Tcl_GetObjResult(interp), dpn->targetValue, dpn->targetLength); } else if (node->nodeType == COMMENT_NODE) { SetResult("#comment"); } else if (node->nodeType == CDATA_SECTION_NODE) { SetResult("#cdata-section"); } else { SetResult(""); } break; case m_nodeValue: CheckArgs(2,3,2,"?newValue?"); if (node->nodeType == ELEMENT_NODE) { Tcl_SetStringObj(Tcl_GetObjResult(interp), "", 0); } else if (node->nodeType == PROCESSING_INSTRUCTION_NODE) { domProcessingInstructionNode *dpn; dpn = (domProcessingInstructionNode *)node; Tcl_SetStringObj(Tcl_GetObjResult(interp), dpn->dataValue, dpn->dataLength); } else { domTextNode *dtn; dtn = (domTextNode*)node; Tcl_SetStringObj(Tcl_GetObjResult(interp), dtn->nodeValue, dtn->valueLength); } if (objc == 3) { str = Tcl_GetStringFromObj(objv[2], &length); switch (node->nodeType) { case TEXT_NODE: CheckText (interp, str, "text"); break; case COMMENT_NODE: CheckComment (interp, str); break; case CDATA_SECTION_NODE: CheckCDATA (interp, str); break; default: break; /* Do nothing */ } exception = domSetNodeValue(node, str, length); if (exception != OK) { SetResult(domException2String(exception)); return TCL_ERROR; } } break; case m_nodeType: CheckArgs(2,2,2,""); switch (node->nodeType) { case ELEMENT_NODE: SetResult("ELEMENT_NODE"); break; case ATTRIBUTE_NODE: SetResult("ATTRIBUTE_NODE"); break; case TEXT_NODE: SetResult("TEXT_NODE"); break; case CDATA_SECTION_NODE: SetResult("CDATA_SECTION_NODE"); break; case COMMENT_NODE: SetResult("COMMENT_NODE"); break; case PROCESSING_INSTRUCTION_NODE: SetResult("PROCESSING_INSTRUCTION_NODE"); break; default: SetResult("unknown nodeType!"); return TCL_ERROR; } break; case m_prefix: CheckArgs(2,2,2,""); nsStr = domNamespacePrefix(node); if (nsStr) { SetResult(nsStr); } else { SetResult(""); } return TCL_OK; case m_namespaceURI: CheckArgs(2,2,2,""); nsStr = domNamespaceURI(node); if (nsStr) { SetResult(nsStr); } else { SetResult(""); } return TCL_OK; case m_localName: CheckArgs(2,2,2,""); if (node->nodeType == ELEMENT_NODE) { if (node->namespace != 0) { SetResult(domGetLocalName((char*)node->nodeName)); break; } } SetResult(""); break; case m_ownerDocument: CheckArgs(2,3,2,"?docObjVar?"); return tcldom_returnDocumentObj(interp, node->ownerDocument, (objc == 3) ? objv[2] : NULL, 0, 1); case m_target: CheckArgs(2,2,2,""); if (node->nodeType != PROCESSING_INSTRUCTION_NODE) { SetResult("not a PROCESSING_INSTRUCTION_NODE!"); return TCL_ERROR; } else { domProcessingInstructionNode *dpn; dpn = (domProcessingInstructionNode *)node; Tcl_SetStringObj(Tcl_GetObjResult(interp), dpn->targetValue, dpn->targetLength); } break; case m_delete: CheckArgs(2,2,2,""); domDeleteNode(node, tcldom_deleteNode, interp); break; case m_data: CheckArgs(2,2,2,""); if (node->nodeType == PROCESSING_INSTRUCTION_NODE) { domProcessingInstructionNode *dpn; dpn = (domProcessingInstructionNode*)node; Tcl_SetStringObj(Tcl_GetObjResult(interp), dpn->dataValue, dpn->dataLength); } else if ( node->nodeType == TEXT_NODE || node->nodeType == CDATA_SECTION_NODE || node->nodeType == COMMENT_NODE) { domTextNode *dtn; dtn = (domTextNode*)node; Tcl_SetStringObj(Tcl_GetObjResult(interp), dtn->nodeValue, dtn->valueLength); } else { SetResult("not a " "TEXT_NODE / " "CDATA_SECTION_NODE / " "COMMENT_NODE / " "PROCESSING_INSTRUCTION_NODE !"); return TCL_ERROR; } break; case m_getLine: CheckArgs(2,2,2,""); if (domGetLineColumn(node, &line, &column, &byteIndex) < 0) { SetResult("no line/column information available!"); return TCL_ERROR; } SetLongResult((domLength)line); break; case m_getColumn: CheckArgs(2,2,2,""); if (domGetLineColumn (node, &line, &column, &byteIndex) < 0) { SetResult("no line/column information available!"); return TCL_ERROR; } SetLongResult((domLength)column); break; case m_getByteIndex: CheckArgs(2,2,2,""); if (domGetLineColumn (node, &line, &column, &byteIndex) < 0) { SetResult("no position information available!"); return TCL_ERROR; } SetLongResult((domLength)byteIndex); break; case m_getBaseURI: CheckArgs(2,2,2,""); /* fall through */ case m_baseURI: CheckArgs(2,3,2,"?URI?"); if (objc == 3) { h = Tcl_CreateHashEntry (node->ownerDocument->baseURIs, (char *) node, &hnew); if (!hnew) { FREE (Tcl_GetHashValue (h)); } Tcl_SetHashValue (h, tdomstrdup (Tcl_GetString (objv[2]))); node->nodeFlags |= HAS_BASEURI; SetResult (Tcl_GetString (objv[2])); } else { nsStr = findBaseURI(node); if (!nsStr) { SetResult(""); } else { SetResult(nsStr); } } break; case m_disableOutputEscaping: CheckArgs(2,3,2,"?boolean?"); if (node->nodeType != TEXT_NODE) { SetResult("not a TEXT_NODE!"); return TCL_ERROR; } SetIntResult( (((node->nodeFlags & DISABLE_OUTPUT_ESCAPING) == 0) ? 0 : 1)); if (objc == 3) { if (Tcl_GetBooleanFromObj(interp, objv[2], &bool) != TCL_OK) { return TCL_ERROR; } if (bool) { node->nodeFlags |= DISABLE_OUTPUT_ESCAPING; } else { node->nodeFlags &= (~DISABLE_OUTPUT_ESCAPING); } } break; case m_precedes: CheckArgs(3,3,2, "node"); refNode = tcldom_getNodeFromObj(interp, objv[2]); if (refNode == NULL) { return TCL_ERROR; } if (node->ownerDocument != refNode->ownerDocument) { SetResult("Cannot compare the relative order of nodes " "out of different documents."); return TCL_ERROR; } if (((node->parentNode == NULL) && (node != node->ownerDocument->documentElement) && (node != node->ownerDocument->rootNode)) || ((refNode->parentNode == NULL) && (refNode != refNode->ownerDocument->documentElement) && (refNode != refNode->ownerDocument->rootNode))) { SetResult("Cannot compare the relative order of a node " "with a node out of the fragment list."); return TCL_ERROR; } SetBooleanResult (domPrecedes (node, refNode)); break; case m_asText: CheckArgs (2,2,2, ""); str = xpathGetStringValue(node, &length); Tcl_SetStringObj(Tcl_GetObjResult(interp), str, length); FREE (str); return TCL_OK; case m_normalize: CheckArgs (2,3,2, "?-forXPath?"); bool = 0; if (objc == 3) { if (strcmp (Tcl_GetString(objv[2]), "-forXPath") == 0) { bool = 1; } else { SetResult("unknown option! Options: ?-forXPath?"); return TCL_ERROR; } } domNormalize (node, bool, tcldom_deleteNode, interp); return TCL_OK; case m_jsonType: CheckArgs (2,3,2, "?jsonType?"); if (node->nodeType != ELEMENT_NODE && node->nodeType != TEXT_NODE) { SetResult("Only element and text nodes may have a JSON type."); return TCL_ERROR; } if (objc == 3) { if (Tcl_GetIndexFromObj (interp, objv[2], jsonTypes, "jsonType", 0, &jsonType) != TCL_OK) { return TCL_ERROR; } if (node->nodeType == ELEMENT_NODE) { if (jsonType > 2) { SetResult("For an element node the jsonType argument " "must be one out of this list: ARRAY OBJECT NONE."); return TCL_ERROR; } } else { /* Text nodes */ if (jsonType < 3 && jsonType > 0) { SetResult("For a text node the jsonType argument must be " "one out of this list: TRUE FALSE NULL NUMBER " "STRING NONE"); return TCL_ERROR; } } node->info = jsonType; SetIntResult(jsonType); return TCL_OK; } if (node->info > 7) { SetResult(jsonTypes[0]); } else { SetResult(jsonTypes[node->info]); } return TCL_OK; TDomThreaded( case m_writelock: CheckArgs(3,3,2,"script"); return tcldom_EvalLocked(interp, (Tcl_Obj**)objv, node->ownerDocument, LOCK_WRITE); case m_readlock: CheckArgs(3,3,2,"script"); return tcldom_EvalLocked(interp, (Tcl_Obj**)objv, node->ownerDocument, LOCK_READ); ) } return TCL_OK;} /*---------------------------------------------------------------------------- | tcldom_DocObjCmd | \---------------------------------------------------------------------------*/ int tcldom_DocObjCmd ( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { GetTcldomDATA; domDeleteInfo * dinfo; domDocument * doc; char * method, *tag, *data, *target, *uri, tmp[100]; char * str, *docName, *errMsg; int methodIndex, result, i, nsIndex, forXPath, bool; int setDocumentElement = 0, restoreDomCreateCmdMode = 0; domLength data_length, target_length; domNode * n; Tcl_CmdInfo cmdInfo; Tcl_Obj * mobjv[MAX_REWRITE_ARGS], *storedErrMsg; static const char *docMethods[] = { "documentElement", "getElementsByTagName", "delete", "createElement", "createCDATASection", "createTextNode", "createComment", "createProcessingInstruction", "createElementNS", "getDefaultOutputMethod", "asXML", "asHTML", "getElementsByTagNameNS", "xslt", "publicId", "systemId", "internalSubset", "toXSLTcmd", "asText", "normalize", "indent", "omit-xml-declaration", "encoding", "standalone", "mediaType", "nodeType", "cdataSectionElements", "selectNodesNamespaces", "renameNode", "deleteXPathCache", "asCanonicalXML", /* The following methods will be dispatched to tcldom_NodeObjCmd */ "getElementById", "firstChild", "lastChild", "appendChild", "removeChild", "hasChildNodes", "childNodes", "ownerDocument", "insertBefore", "replaceChild", "appendFromList", "appendXML", "selectNodes", "baseURI", "appendFromScript", "insertBeforeFromScript", "asJSON", "jsonType", "asTclValue", "asTypedList", #ifdef TCL_THREADS "readlock", "writelock", "renumber", #endif NULL }; enum docMethod { m_documentElement, m_getElementsByTagName, m_delete, m_createElement, m_createCDATASection, m_createTextNode, m_createComment, m_createProcessingInstruction, m_createElementNS, m_getdefaultoutputmethod, m_asXML, m_asHTML, m_getElementsByTagNameNS, m_xslt, m_publicId, m_systemId, m_internalSubset, m_toXSLTcmd, m_asText, m_normalize, m_indent, m_omitXMLDeclaration, m_encoding, m_standalone, m_mediaType, m_nodeType, m_cdataSectionElements, m_selectNodesNamespaces, m_renameNode, m_deleteXPathCache, m_asCanonicalXML, /* The following methods will be dispatched to tcldom_NodeObjCmd */ m_getElementById, m_firstChild, m_lastChild, m_appendChild, m_removeChild, m_hasChildNodes, m_childNodes, m_ownerDocument, m_insertBefore, m_replaceChild, m_appendFromList, m_appendXML, m_selectNodes, m_baseURI, m_appendFromScript, m_insertBeforeFromScript, m_asJSON, m_jsonType, m_asTclValue, m_asTypedList #ifdef TCL_THREADS ,m_readlock, m_writelock, m_renumber #endif }; dinfo = (domDeleteInfo*)clientData; if (TcldomDATA(domCreateCmdMode) == DOM_CREATECMDMODE_AUTO) { TcldomDATA(dontCreateObjCommands) = 0; } if (dinfo == NULL) { if (objc < 3) { Tcl_WrongNumArgs (interp, 1, objv, "doctoken subcommand ?arg ...?"); return TCL_ERROR; } if (TcldomDATA(domCreateCmdMode) == DOM_CREATECMDMODE_AUTO) { TcldomDATA(dontCreateObjCommands) = 1; } docName = Tcl_GetString(objv[1]); doc = tcldom_getDocumentFromName(interp, docName, &errMsg); if (doc == NULL) { SetResult(errMsg); return TCL_ERROR; } objc--; objv++; } else { doc = dinfo->document; } if (objc < 2) { Tcl_WrongNumArgs (interp, 1, objv, "subcommand ?arg ...?"); return TCL_ERROR; } method = Tcl_GetString(objv[1]); if (Tcl_GetIndexFromObj(interp, objv[1], docMethods, "method", 0, &methodIndex) != TCL_OK) { /*-------------------------------------------------------- | try to find method implemented as normal Tcl proc \-------------------------------------------------------*/ sprintf(tmp, "::dom::domDoc::%s", method); DBG(fprintf(stderr, "testing %s\n", tmp)); storedErrMsg = Tcl_GetObjResult (interp); Tcl_IncrRefCount (storedErrMsg); result = Tcl_GetCommandInfo(interp, tmp, &cmdInfo); if (!result) { SetResult(Tcl_GetString (storedErrMsg)); Tcl_DecrRefCount (storedErrMsg); return TCL_ERROR; } Tcl_DecrRefCount (storedErrMsg); if (!cmdInfo.isNativeObjectProc) { SetResult( "can't access Tcl level method!"); return TCL_ERROR; } if (objc >= MAX_REWRITE_ARGS) { SetResult("too many args to call Tcl level method!"); return TCL_ERROR; } mobjv[0] = objv[1]; mobjv[1] = objv[0]; for (i = 2; i < objc; i++) { mobjv[i] = objv[i]; } return cmdInfo.objProc(cmdInfo.objClientData, interp, objc, mobjv); } CheckArgs (2,20,1,"Too many arguments."); Tcl_ResetResult (interp); /*---------------------------------------------------------------------- | dispatch the doc object method | \---------------------------------------------------------------------*/ switch ((enum docMethod) methodIndex ) { case m_documentElement: CheckArgs(2,3,2,""); return tcldom_setInterpAndReturnVar(interp, doc->documentElement, (objc == 3) ? objv[2] : NULL); case m_getElementsByTagName: CheckArgs(3,3,2,"elementName"); return tcldom_getElementsByTagName(interp, Tcl_GetString(objv[2]), doc->documentElement, -1, NULL); case m_getElementsByTagNameNS: CheckArgs(4,4,2,"uri localname"); uri = Tcl_GetString(objv[2]); str = Tcl_GetString(objv[3]); nsIndex = -1; if (uri[0] == '*' && uri[1] == '\0') { nsIndex = -3; } else if (uri[0] == '\0') { /* all elements not in a namespace i.e. */ nsIndex = -4; } else { for (i = 0; i <= doc->nsptr; i++) { if (strcmp(doc->namespaces[i]->uri, uri)==0) { if (nsIndex != -1) { /* OK, this is one of the 'degenerated' (though legal) documents, which bind the same URI to different prefixes. */ nsIndex = -2; break; } nsIndex = doc->namespaces[i]->index; } } } if (nsIndex == -1) { /* There isn't such a namespace declared in this document. Since getElementsByTagNameNS doesn't raise an exception short cut: return empty result */ return TCL_OK; } return tcldom_getElementsByTagName(interp, str, doc->documentElement, nsIndex, uri); case m_createElement: CheckArgs(3,4,2,"elementName ?newObjVar?"); tag = Tcl_GetString(objv[2]); CheckName (interp, tag, "tag", 0); n = domNewElementNode(doc, tag); return tcldom_setInterpAndReturnVar(interp, n, (objc == 4) ? objv[3] : NULL); case m_createElementNS: CheckArgs(4,5,2,"elementName uri ?newObjVar?"); uri = Tcl_GetString(objv[2]); tag = Tcl_GetString(objv[3]); CheckName (interp, tag, "full qualified tag", 1); n = domNewElementNodeNS(doc, tag, uri); if (n == NULL) { SetResult("Missing URI in Namespace declaration"); return TCL_ERROR; } return tcldom_setInterpAndReturnVar(interp, n, (objc == 5) ? objv[4] : NULL); case m_createTextNode: CheckArgs(3,4,2,"data ?newObjVar?"); data = Tcl_GetStringFromObj(objv[2], &data_length); CheckText (interp, data, "text"); n = (domNode*)domNewTextNode(doc, data, data_length, TEXT_NODE); return tcldom_setInterpAndReturnVar(interp, n, (objc == 4) ? objv[3] : NULL); case m_createCDATASection: CheckArgs(3,4,2,"data ?newObjVar?"); data = Tcl_GetStringFromObj(objv[2], &data_length); CheckCDATA (interp, data); n = (domNode*)domNewTextNode(doc, data, data_length, CDATA_SECTION_NODE); return tcldom_setInterpAndReturnVar(interp, n, (objc == 4) ? objv[3] : NULL); case m_createComment: CheckArgs(3,4,2,"data ?newObjVar?"); data = Tcl_GetStringFromObj(objv[2], &data_length); CheckComment(interp, data); n = (domNode*)domNewTextNode(doc, data, data_length, COMMENT_NODE); return tcldom_setInterpAndReturnVar(interp, n, (objc == 4) ? objv[3] : NULL); case m_createProcessingInstruction: CheckArgs(4,5,2,"target data ?newObjVar?"); target = Tcl_GetStringFromObj(objv[2], &target_length); CheckPIName (interp, target); data = Tcl_GetStringFromObj(objv[3], &data_length); CheckPIValue (interp, data); n = (domNode*)domNewProcessingInstructionNode(doc, target, target_length, data, data_length); return tcldom_setInterpAndReturnVar(interp, n, (objc == 5) ? objv[4] : NULL); case m_delete: CheckArgs(2,2,2,""); if (clientData != NULL || doc->nodeFlags & DOCUMENT_CMD) { Tcl_DeleteCommand(interp, Tcl_GetString (objv[0])); } else { tcldom_deleteDoc(interp, doc); } SetResult(""); return TCL_OK; case m_getdefaultoutputmethod: CheckArgs(2,2,2,""); if (doc->doctype && doc->doctype->method) { SetResult (doc->doctype->method); } else { SetResult("xml"); } return TCL_OK; case m_asXML: if (serializeAsXML((domNode*)doc, interp, objc, objv) != TCL_OK) { return TCL_ERROR; } return TCL_OK; case m_asCanonicalXML: if (serializeAsCanonicalXML((domNode*)doc, interp, objc, objv) != TCL_OK) { return TCL_ERROR; } return TCL_OK; case m_asHTML: if (serializeAsHTML((domNode*)doc, interp, objc, objv) != TCL_OK) { return TCL_ERROR; } return TCL_OK; case m_xslt: CheckArgs(3,9,2, "?-parameters parameterList? " "?-ignoreUndeclaredParameters? " "?-xsltmessagecmd cmd? ?objVar?"); objv += 2; objc -= 2; return applyXSLT((domNode *) doc, interp, NULL, objc, objv); case m_toXSLTcmd: CheckArgs(2,3,2, "?objVar?"); return convertToXSLTCmd(doc, interp, (objc == 3) ? objv[2] : NULL); case m_publicId: CheckArgs(2,3,2, "?publicID?"); if (doc->doctype && doc->doctype->publicId) { SetResult(doc->doctype->publicId); } else { SetResult(""); } if (objc == 3) { if (!doc->doctype) { doc->doctype = (domDocInfo *)MALLOC(sizeof(domDocInfo)); memset(doc->doctype, 0,(sizeof(domDocInfo))); } else if (doc->doctype->publicId) { FREE(doc->doctype->publicId); } doc->doctype->publicId = tdomstrdup(Tcl_GetString(objv[2])); } return TCL_OK; case m_systemId: CheckArgs(2,3,2, "?systemID?"); if (doc->doctype && doc->doctype->systemId) { SetResult(doc->doctype->systemId); } else { SetResult(""); } if (objc == 3) { if (!doc->doctype) { doc->doctype = (domDocInfo *)MALLOC(sizeof(domDocInfo)); memset(doc->doctype, 0,(sizeof(domDocInfo))); } else if (doc->doctype->systemId) { FREE(doc->doctype->systemId); } doc->doctype->systemId = tdomstrdup(Tcl_GetString(objv[2])); } return TCL_OK; case m_internalSubset: CheckArgs(2,3,2, "?internalSubset?"); if (doc->doctype && doc->doctype->internalSubset) { SetResult(doc->doctype->internalSubset); } else { SetResult(""); } if (objc == 3) { if (!doc->doctype) { doc->doctype = (domDocInfo *)MALLOC(sizeof(domDocInfo)); memset(doc->doctype, 0,(sizeof(domDocInfo))); } else if (doc->doctype->systemId) { FREE(doc->doctype->systemId); } doc->doctype->internalSubset = tdomstrdup(Tcl_GetString(objv[2])); } return TCL_OK; case m_indent: CheckArgs(2,3,2, "?boolean?"); if (doc->nodeFlags & OUTPUT_DEFAULT_INDENT) { SetBooleanResult (1); } else { SetBooleanResult(0); } if (objc == 3) { if (Tcl_GetBooleanFromObj (interp, objv[2], &bool) != TCL_OK) { return TCL_ERROR; } if (bool) { doc->nodeFlags |= OUTPUT_DEFAULT_INDENT; } else { doc->nodeFlags &= ~OUTPUT_DEFAULT_INDENT; } } return TCL_OK; case m_omitXMLDeclaration: CheckArgs(2,3,2, "?boolean?"); if (doc->doctype) { SetBooleanResult (doc->doctype->omitXMLDeclaration); } else { SetBooleanResult (1); } if (objc == 3) { if (!doc->doctype) { doc->doctype = (domDocInfo *)MALLOC(sizeof(domDocInfo)); memset(doc->doctype, 0,(sizeof(domDocInfo))); } if (Tcl_GetBooleanFromObj ( interp, objv[2], &(doc->doctype->omitXMLDeclaration) ) != TCL_OK) { return TCL_ERROR; } } return TCL_OK; case m_encoding: CheckArgs(2,3,2, "?value?"); if (doc->doctype && doc->doctype->encoding) { SetResult (doc->doctype->encoding); } else { SetResult (""); } if (objc == 3) { if (!doc->doctype) { doc->doctype = (domDocInfo *)MALLOC(sizeof(domDocInfo)); memset(doc->doctype, 0,(sizeof(domDocInfo))); } else { if (doc->doctype->encoding) FREE (doc->doctype->encoding); } doc->doctype->encoding = tdomstrdup (Tcl_GetString (objv[2])); } return TCL_OK; case m_standalone: CheckArgs(2,3,2, "?boolean?"); if (doc->doctype) { SetBooleanResult (doc->doctype->standalone); } else { SetBooleanResult (0); } if (objc == 3) { if (!doc->doctype) { doc->doctype = (domDocInfo *)MALLOC(sizeof(domDocInfo)); memset(doc->doctype, 0,(sizeof(domDocInfo))); } if (Tcl_GetBooleanFromObj ( interp, objv[2], &(doc->doctype->standalone) ) != TCL_OK) { return TCL_ERROR; } } return TCL_OK; case m_mediaType: CheckArgs(2,3,2, "?value?"); if (doc->doctype && doc->doctype->mediaType) { SetResult (doc->doctype->mediaType); } else { SetResult (""); } if (objc == 3) { if (!doc->doctype) { doc->doctype = (domDocInfo *)MALLOC(sizeof(domDocInfo)); memset(doc->doctype, 0,(sizeof(domDocInfo))); } else { if (doc->doctype->mediaType) FREE(doc->doctype->mediaType); } doc->doctype->mediaType = tdomstrdup (Tcl_GetString (objv[2])); } return TCL_OK; case m_asText: CheckArgs (2,2,2,""); data = xpathGetStringValue (doc->rootNode, &data_length); Tcl_SetStringObj (Tcl_GetObjResult (interp), data, data_length); FREE (data); return TCL_OK; case m_normalize: CheckArgs (2,3,2, "?-forXPath?"); forXPath = 0; if (objc == 3) { if (strcmp (Tcl_GetString (objv[2]), "-forXPath") == 0) { forXPath = 1; } else { SetResult("unknown option! Options: ?-forXPath?"); return TCL_ERROR; } } domNormalize(doc->rootNode, forXPath, tcldom_deleteNode, interp); return TCL_OK; case m_nodeType: CheckArgs (2,2,2, ""); SetResult("DOCUMENT_NODE"); return TCL_OK; case m_cdataSectionElements: return cdataSectionElements (doc, interp, objc, objv); case m_selectNodesNamespaces: CheckArgs (2,3,2, "?prefixUriList?"); return tcldom_prefixNSlist (&(doc->prefixNSMappings), interp, --objc, ++objv, "selectNodesNamespaces"); case m_renameNode: return renameNodes (doc, interp, objc, objv); case m_deleteXPathCache: return deleteXPathCache (doc, interp, objc, objv); case m_appendChild: case m_removeChild: case m_insertBefore: case m_replaceChild: case m_appendFromList: case m_appendXML: case m_appendFromScript: case m_insertBeforeFromScript: setDocumentElement = 1; /* fall through */ case m_firstChild: case m_lastChild: case m_hasChildNodes: case m_childNodes: case m_ownerDocument: case m_selectNodes: case m_baseURI: case m_asJSON: case m_asTclValue: case m_asTypedList: case m_jsonType: case m_getElementById: /* We dispatch the method call to tcldom_NodeObjCmd */ if (TcldomDATA(domCreateCmdMode) == DOM_CREATECMDMODE_AUTO) { if (dinfo == NULL) { /* tcldom_DocObjCmd was called with a doc token. Since the domCreateCmdMode is 'automatic' and we call tcldom_DocObjCmd with the root node as 'clientData', we temporarily set domCreateCmdMode to 'token', to get token results from that call and later to set it back. */ TcldomDATA(domCreateCmdMode) = DOM_CREATECMDMODE_TOKENS; restoreDomCreateCmdMode = 1; } } if (tcldom_NodeObjCmd (doc->rootNode, interp, objc, objv) != TCL_OK) { if (restoreDomCreateCmdMode) { TcldomDATA(domCreateCmdMode) = DOM_CREATECMDMODE_AUTO; TcldomDATA(dontCreateObjCommands) = 0; } return TCL_ERROR; } if (setDocumentElement) { /* The method call may have altered the documentElement. */ /* There may be even no node anymore */ domSetDocumentElement (doc); } if (restoreDomCreateCmdMode) { TcldomDATA(domCreateCmdMode) = DOM_CREATECMDMODE_AUTO; TcldomDATA(dontCreateObjCommands) = 0; } return TCL_OK; TDomThreaded( case m_writelock: CheckArgs(3,3,2,"script"); return tcldom_EvalLocked(interp, (Tcl_Obj**)objv, doc, LOCK_WRITE); case m_readlock: CheckArgs(3,3,2,"script"); return tcldom_EvalLocked(interp, (Tcl_Obj**)objv, doc, LOCK_READ); case m_renumber: CheckArgs(2,2,2,""); if (doc->nodeFlags & NEEDS_RENUMBERING) { domRenumberTree (doc->rootNode); doc->nodeFlags &= ~NEEDS_RENUMBERING; } return TCL_OK; ) } /* Not reached */ return TCL_ERROR; } /*---------------------------------------------------------------------------- | tDOM_fsnewNodeCmd | \---------------------------------------------------------------------------*/ int tDOM_fsnewNodeCmd ( ClientData UNUSED(clientData), Tcl_Interp * interp, int objc, Tcl_Obj *const objv[] ) { domNode *parent, *newNode = NULL; int index, jsonType, haveJsonType = 0, type, ret; int checkName, checkCharData; domLength len; Tcl_Obj *cmdObj; char *namespace = NULL, *option, *tag; GetTcldomDATA; static const char *options[] = { "-jsonType", "-namespace", "--", NULL }; enum option { o_jsonType, o_namespace, o_Last }; static const char *jsonTypes[] = { "NONE", "ARRAY", "OBJECT", "NULL", "TRUE", "FALSE", "STRING", "NUMBER" }; Tcl_ResetResult (interp); /*------------------------------------------------------------------------ | Need parent node to get the owner document and to append new | child tag to it. The current parent node is stored on the stack. | \-----------------------------------------------------------------------*/ parent = nodecmd_currentNode(interp); if (parent == NULL) { Tcl_AppendResult(interp, "called outside domNode context", NULL); return TCL_ERROR; } if (objc < 2) { Tcl_AppendResult(interp, "::tdom::fsnewNode \n" "\t?-jsonType ?\n" "\t?-namespace ?\n" " tagName ?attributes? ?script?", NULL); return TCL_ERROR; } while (objc > 2) { option = Tcl_GetString (objv[1]); if (option[0] != '-') { break; } if (Tcl_GetIndexFromObj (interp, objv[1], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum option) index) { case o_jsonType: if (Tcl_GetIndexFromObj (interp, objv[2], jsonTypes, "jsonType", 1, &jsonType) != TCL_OK) { return TCL_ERROR; } haveJsonType = 1; objc -= 2; objv += 2; break; case o_namespace: namespace = Tcl_GetString (objv[2]); objc -= 2; objv += 2; break; case o_Last: objv++; objc--; break; } } if (objc < 2) { Tcl_AppendResult(interp, "::tdom::fsnewNode \n" "\t?-jsonType ?\n" "\t?-namespace ?\n" " tagName ?attributes? ?script?", NULL); return TCL_ERROR; } tag = Tcl_GetStringFromObj(objv[1], &len); objv++; objc--; newNode = domAppendNewElementNode (parent, tag, namespace); if (haveJsonType) { newNode->info = jsonType; } cmdObj = NULL; checkName = !TcldomDATA(dontCheckName); checkCharData = !TcldomDATA(dontCheckCharData); if (objc > 1) { if (haveJsonType) { type = ELEMENT_NODE; } else { if (checkName && checkCharData) { type = ELEMENT_NODE_CHK; } else if (checkName) { type = ELEMENT_NODE_ANAME_CHK; } else if (checkCharData) { type = ELEMENT_NODE_AVALUE_CHK; } else { type = ELEMENT_NODE; } } if (nodecmd_processAttributes (interp, newNode, type, objc, objv, &cmdObj) != TCL_OK) { return TCL_ERROR; } if (cmdObj) { ret = nodecmd_appendFromScript(interp, newNode, cmdObj); if (ret == TCL_OK) { parent->ownerDocument->nodeFlags |= NEEDS_RENUMBERING; } return ret; } } return TCL_OK; } /*---------------------------------------------------------------------------- | tDOM_fsinsertNodeCmd | \---------------------------------------------------------------------------*/ int tDOM_fsinsertNodeCmd ( ClientData UNUSED(clientData), Tcl_Interp * interp, int objc, Tcl_Obj *const objv[] ) { domNode *parent, *newNode = NULL; domException exception; Tcl_ResetResult (interp); if (objc != 2) { Tcl_AppendResult (interp, "::tdom::fsinsertNode ", NULL); return TCL_ERROR; } /*------------------------------------------------------------------------ | Need parent node to get the owner document and to append new | child tag to it. The current parent node is stored on the stack. | \-----------------------------------------------------------------------*/ parent = nodecmd_currentNode(interp); if (parent == NULL) { Tcl_AppendResult(interp, "called outside domNode context", NULL); return TCL_ERROR; } newNode = tcldom_getNodeFromObj (interp, objv[1]); if (!newNode) { return TCL_ERROR; } exception = domAppendChild (parent, newNode); if (exception != OK) { Tcl_AppendResult (interp, domException2String(exception), NULL); return TCL_ERROR; } tcldom_setInterpAndReturnVar (interp, newNode, NULL); return TCL_OK; } /*---------------------------------------------------------------------------- | tcldom_createDocument | \---------------------------------------------------------------------------*/ static int tcldom_createDocument ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj * const objv[] ) { domDocument *doc; Tcl_Obj *newObjName = NULL; GetTcldomDATA; CheckArgs(2,3,1,"docElemName ?newObjVar?"); if (objc == 3) { newObjName = objv[2]; } CheckName(interp, Tcl_GetString(objv[1]), "root element", 0); doc = domCreateDocument(NULL, Tcl_GetString(objv[1])); return tcldom_returnDocumentObj(interp, doc, newObjName, 1, 0); } /*---------------------------------------------------------------------------- | tcldom_createDocumentNode | \---------------------------------------------------------------------------*/ static int tcldom_createDocumentNode ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj * const objv[] ) { int jsonType = 0, index; domDocument *doc; Tcl_Obj *newObjName = NULL; static const char *options[] = {"-jsonType", NULL}; CheckArgs(1,4,1,"?-jsonType jsonType? ?newObjVar?"); if (objc == 2) { newObjName = objv[1]; } if (objc > 2) { if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } Tcl_ResetResult(interp); if (Tcl_GetIndexFromObj(interp, objv[2], jsonTypes, "jsonType", 0, &jsonType) != TCL_OK) { return TCL_ERROR; } if (objc == 4) { newObjName = objv[3]; } } doc = domCreateDoc(NULL, 0); doc->rootNode->info = jsonType; return tcldom_returnDocumentObj(interp, doc, newObjName, 1, 0); } /*---------------------------------------------------------------------------- | tcldom_createDocumentNS | \---------------------------------------------------------------------------*/ static int tcldom_createDocumentNS ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj * const objv[] ) { domLength len; char *uri; domDocument *doc; Tcl_Obj *newObjName = NULL; GetTcldomDATA; CheckArgs(3,4,1,"uri docElemName ?newObjVar?"); if (objc == 4) { newObjName = objv[3]; } CheckName(interp, Tcl_GetString(objv[2]), "root element", 1); uri = Tcl_GetStringFromObj (objv[1], &len); if (len == 0) { if (!TcldomDATA(dontCheckName)) { if (!domIsNCNAME (Tcl_GetString(objv[2]))) { SetResult ("Missing URI in Namespace declaration"); return TCL_ERROR; } } doc = domCreateDocument (NULL, Tcl_GetString(objv[2])); } else { doc = domCreateDocument (uri, Tcl_GetString(objv[2])); } return tcldom_returnDocumentObj (interp, doc, newObjName, 1, 0); } /*---------------------------------------------------------------------------- | tcldom_createFromTypedList | \---------------------------------------------------------------------------*/ static int tcldom_createFromTypedList ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj * const objv[] ) { domDocument *doc; Tcl_Obj *newObjName = NULL; CheckArgs(2,3,1,"typedList ?newObjVar?"); if (objc == 3) { newObjName = objv[2]; } doc = TypedList2DOM (interp, objv[1]); if (doc == NULL) { return TCL_ERROR; } return tcldom_returnDocumentObj(interp, doc, newObjName, 1, 0); } /* Helper function to build up the error string message in a central * place. Caller must provide byteIndex; line is expected to be > 0 if * line/column information is given. */ void tcldom_reportErrorLocation ( Tcl_Interp *interp, int before, int after, XML_Size line, XML_Size column, char *xmlstring, const char *entity, XML_Index byteIndex, const char *errStr ) { char s[200], sb[25], sl[25], sc[25]; char *d = NULL, *buf; domLength i, ind; if (before > 197 || after > 197) { d = MALLOC (sizeof (char) * ((before > after ? before + 3 : after + 1))); buf = d; } else { buf = s; } Tcl_ResetResult(interp); Tcl_AppendResult (interp, "error \"", errStr, "\"", NULL); if (entity) { Tcl_AppendResult (interp, " in entity \"", entity, "\"", NULL); } if (line) { sprintf(sl, "%" TDOM_LS_MODIFIER "d", line); sprintf(sc, "%" TDOM_LS_MODIFIER "d", column); Tcl_AppendResult (interp, " at line ", sl, " character ", sc, NULL); } else { sprintf(sb, "%" TDOM_LS_MODIFIER "d", byteIndex); Tcl_AppendResult (interp, " at position ", sb, NULL); } if (xmlstring) { Tcl_AppendResult (interp, "\n\"", NULL); ind = 0; buf[0] = '\0'; for (i = (byteIndex < before ? 0 : (domLength)(byteIndex - before)); i <= byteIndex; i++) { buf[ind] = xmlstring[i]; ind++; } buf[ind] = '\0'; Tcl_AppendResult(interp, buf, " <--Error-- ", NULL); ind = 0; buf[0] = '\0'; if (xmlstring[byteIndex]) { for (i = (domLength)(byteIndex + 1); i < (domLength)(byteIndex + after); i++) { if (!xmlstring[i]) { break; } buf[ind] = xmlstring[i]; ind++; } buf[ind] = '\0'; Tcl_AppendResult(interp, buf, NULL); } Tcl_AppendResult(interp, "\"",NULL); } if (d) { FREE (d); } } /*---------------------------------------------------------------------------- | tcldom_parse | \---------------------------------------------------------------------------*/ static int tcldom_parse ( ClientData UNUSED(clientData), Tcl_Interp *interp, int objc, Tcl_Obj * const objv[] ) { GetTcldomDATA; char *xml_string, *option, *errStr, *channelId, *baseURI = NULL; char *jsonRoot = NULL; Tcl_Obj *extResolver = NULL; Tcl_Obj *feedbackCmd = NULL; const char *interpResult; int optionIndex, value, mode; domLength xml_string_len; int jsonmaxnesting = JSON_MAX_NESTING; int ignoreWhiteSpaces = 1; int takeJSONParser = 0; int takeSimpleParser = 0; int takeHTMLParser = 0; int takeGUMBOParser = 0; int ignorexmlns = 0; int feedbackAfter = 0; int useForeignDTD = 0; int paramEntityParsing = (int)XML_PARAM_ENTITY_PARSING_ALWAYS; int keepCDATA = 0; int forest = 0; int status = 0; double maximumAmplification = 0.0; long activationThreshold = 0; domParseForestErrorData forestError; domDocument *doc; Tcl_Obj *newObjName = NULL; XML_Parser parser; Tcl_Channel chan = (Tcl_Channel) NULL; Tcl_CmdInfo cmdInfo; #ifndef TDOM_NO_SCHEMA SchemaData *sdata = NULL; #endif static const char *parseOptions[] = { "-keepEmpties", "-simple", "-html", "-feedbackAfter", "-channel", "-baseurl", "-externalentitycommand", "-useForeignDTD", "-paramentityparsing", "-feedbackcmd", "-json", "-jsonroot", #ifdef TDOM_HAVE_GUMBO "-html5", #endif #ifndef TDOM_NO_SCHEMA "-validateCmd", #endif "-jsonmaxnesting", "-ignorexmlns", "--", "-keepCDATA", "-billionLaughsAttackProtectionMaximumAmplification", "-billionLaughsAttackProtectionActivationThreshold", "-forest", NULL }; enum parseOption { o_keepEmpties, o_simple, o_html, o_feedbackAfter, o_channel, o_baseurl, o_externalentitycommand, o_useForeignDTD, o_paramentityparsing, o_feedbackcmd, o_json, o_jsonroot, #ifdef TDOM_HAVE_GUMBO o_htmlfive, #endif #ifndef TDOM_NO_SCHEMA o_validateCmd, #endif o_jsonmaxnesting, o_ignorexmlns, o_LAST, o_keepCDATA, o_billionLaughsAttackProtectionMaximumAmplification, o_billionLaughsAttackProtectionActivationThreshold, o_forest }; static const char *paramEntityParsingValues[] = { "always", "never", "notstandalone", (char *) NULL }; enum paramEntityParsingValue { EXPAT_PARAMENTITYPARSINGALWAYS, EXPAT_PARAMENTITYPARSINGNEVER, EXPAT_PARAMENTITYPARSINGNOTSTANDALONE }; while (objc > 1) { option = Tcl_GetString(objv[1]); if (option[0] != '-') { break; } if (Tcl_GetIndexFromObj(interp, objv[1], parseOptions, "option", 0, &optionIndex) != TCL_OK) { if (chan == NULL && (takeJSONParser || objc <= 3)) { /* A string starting with '-' may be a valid JSON document. */ break; } return TCL_ERROR; } switch ((enum parseOption) optionIndex) { case o_keepEmpties: ignoreWhiteSpaces = 0; objv++; objc--; continue; case o_json: if (takeGUMBOParser || takeHTMLParser) { SetResult("The options -html, -html5 and -json are " "mutually exclusive."); return TCL_ERROR; } takeJSONParser = 1; objv++; objc--; continue; case o_jsonroot: objv++; objc--; if (objc > 1) { jsonRoot = Tcl_GetString(objv[1]); } else { SetResult("The \"dom parse\" option \"-jsonroot\" " "expects the document element name of the " "DOM tree to create as argument."); return TCL_ERROR; } objv++; objc--; continue; case o_simple: takeSimpleParser = 1; objv++; objc--; continue; case o_html: if (takeGUMBOParser || takeJSONParser) { SetResult("The options -html, -html5 and -json are " "mutually exclusive."); return TCL_ERROR; } takeSimpleParser = 1; takeHTMLParser = 1; objv++; objc--; continue; #ifdef TDOM_HAVE_GUMBO case o_htmlfive: if (takeHTMLParser || takeJSONParser) { SetResult("The options -html, -html5 and -json are " "mutually exclusive."); return TCL_ERROR; } takeGUMBOParser = 1; objv++; objc--; continue; #endif case o_feedbackAfter: objv++; objc--; if (objc > 1) { if (Tcl_GetIntFromObj(interp, objv[1], &feedbackAfter) != TCL_OK) { SetResult("-feedbackAfter must have an integer argument"); return TCL_ERROR; } } else { SetResult("The \"dom parse\" option \"-feedbackAfter\" requires" " a positive integer as argument."); return TCL_ERROR; } if (feedbackAfter <= 0) { SetResult("The \"dom parse\" option \"-feedbackAfter\" requires" " a positive integer as argument."); return TCL_ERROR; } objv++; objc--; continue; case o_channel: objv++; objc--; if (objc > 1) { channelId = Tcl_GetString(objv[1]); } else { SetResult("The \"dom parse\" option \"-channel\" " "requires a Tcl channel as argument."); return TCL_ERROR; } chan = Tcl_GetChannel(interp, channelId, &mode); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } if ((mode & TCL_READABLE) == 0) { Tcl_AppendResult(interp, "channel \"", channelId, "\" wasn't opened for reading", (char *) NULL); return TCL_ERROR; } objv++; objc--; continue; case o_baseurl: objv++; objc--; if (objc > 1) { baseURI = Tcl_GetString(objv[1]); } else { SetResult("The \"dom parse\" option \"-baseurl\" " "requires the base URL of the document " "to parse as argument."); return TCL_ERROR; } objv++; objc--; continue; case o_externalentitycommand: objv++; objc--; if (objc > 1) { extResolver = objv[1]; } else { SetResult("The \"dom parse\" option \"-externalentitycommand\" " "requires a script as argument."); return TCL_ERROR; } objv++; objc--; continue; case o_useForeignDTD: objv++; objc--; if (objc > 1) { if (Tcl_GetBooleanFromObj(interp, objv[1], &useForeignDTD) != TCL_OK) { return TCL_ERROR; } } else { SetResult("The \"dom parse\" option \"-useForeignDTD\" " "requires a boolean as argument."); return TCL_ERROR; } objv++; objc--; continue; case o_paramentityparsing: if (objc > 2) { if (Tcl_GetIndexFromObj(interp, objv[2], paramEntityParsingValues, "value", 0, &value) != TCL_OK) { return TCL_ERROR; } switch ((enum paramEntityParsingValue) value) { case EXPAT_PARAMENTITYPARSINGALWAYS: paramEntityParsing = (int) XML_PARAM_ENTITY_PARSING_ALWAYS; break; case EXPAT_PARAMENTITYPARSINGNEVER: paramEntityParsing = (int) XML_PARAM_ENTITY_PARSING_NEVER; break; case EXPAT_PARAMENTITYPARSINGNOTSTANDALONE: paramEntityParsing = (int) XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE; break; } } else { SetResult("-paramEntityParsing requires 'always', 'never' " "or 'notstandalone' as argument"); return TCL_ERROR; } objv++; objc--; objv++; objc--; continue; case o_feedbackcmd: objv++; objc--; if (objc > 1) { feedbackCmd = objv[1]; } else { SetResult("The \"dom parse\" option \"-feedbackcmd\" " "requires a script as argument."); return TCL_ERROR; } objv++; objc--; continue; case o_ignorexmlns: ignorexmlns = 1; objv++; objc--; continue; case o_jsonmaxnesting: objv++; objc--; if (objc < 2) { SetResult("The \"dom parse\" option \"-jsonmaxnesting\" " "requires an integer as argument."); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[1], &jsonmaxnesting) != TCL_OK) { SetResult("-jsonmaxnesting must have an integer argument"); return TCL_ERROR; } if (jsonmaxnesting < 0) { SetResult("The value of -jsonmaxnesting cannot be negative"); return TCL_ERROR; } objv++; objc--; continue; case o_LAST: objv++; objc--; break; case o_keepCDATA: keepCDATA = 1; objv++; objc--; continue; case o_billionLaughsAttackProtectionMaximumAmplification: objv++; objc--; if (objc < 2) { SetResult("The \"dom parse\" option \"" "-billionLaughsAttackProtectionMaximumAmplification" "\" requires a float >= 1.0 as argument."); return TCL_ERROR; } if (Tcl_GetDoubleFromObj (interp, objv[1], &maximumAmplification) != TCL_OK) { SetResult("The \"dom parse\" option \"" "-billionLaughsAttackProtectionMaximumAmplification" "\" requires a float >= 1.0 as argument."); return TCL_ERROR; } if (maximumAmplification > (double)FLT_MAX || maximumAmplification < 1.0) { SetResult("The \"dom parse\" option \"" "-billionLaughsAttackProtectionMaximumAmplification" "\" requires a float >= 1.0 as argument."); return TCL_ERROR; } objv++; objc--; continue; case o_billionLaughsAttackProtectionActivationThreshold: objv++; objc--; if (objc < 2) { SetResult("The \"dom parse\" option \"" "-billionLaughsAttackProtectionActivationThreshold" "\" requires a long > 0 as argument."); return TCL_ERROR; } if (Tcl_GetLongFromObj (interp, objv[1], &activationThreshold) != TCL_OK) { SetResult("The \"dom parse\" option \"" "-billionLaughsAttackProtectionActivationThreshold" "\" requires a long > 0 as argument."); return TCL_ERROR; } if (activationThreshold < 1) { SetResult("The \"dom parse\" option \"" "-billionLaughsAttackProtectionActivationThreshold" "\" requires a long > 0 as argument."); return TCL_ERROR; } objv++; objc--; continue; #ifndef TDOM_NO_SCHEMA case o_validateCmd: objv++; objc--; if (objc < 2) { SetResult("The \"dom parse\" option \"-validateCmd\" " "requires a tDOM validation command as argument."); return TCL_ERROR; } if (!Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo)) { SetResult3("The \"-validateCmd\" argument \"", Tcl_GetString(objv[1]), "\" is not a tDOM validation command."); return TCL_ERROR; } if (cmdInfo.objProc != tDOM_schemaInstanceCmd) { SetResult3("The \"-validateCmd\" argument \"", Tcl_GetString(objv[1]), "\" is not a tDOM validation command."); return TCL_ERROR; } sdata = (SchemaData *) cmdInfo.objClientData; objv++; objc--; continue; #endif case o_forest: forest = 1; forestError.errorLine = 0; forestError.errorColumn = 0; forestError.byteIndex = 0; forestError.errorCode = 0; objv++; objc--; continue; } if ((enum parseOption) optionIndex == o_LAST) break; } if (feedbackAfter && !feedbackCmd) { if (!Tcl_GetCommandInfo(interp, "::dom::domParseFeedback", &cmdInfo)) { SetResult("If -feedbackAfter is used, " "-feedbackcmd must also be used."); return TCL_ERROR; } } if (chan == NULL) { if (objc < 2) { Tcl_WrongNumArgs (interp, 1, objv, "?options? ?data? ?objvar?"); return TCL_ERROR; } xml_string = Tcl_GetStringFromObj( objv[1], &xml_string_len); if (objc == 3) { newObjName = objv[2]; } } else { if (objc > 2) { SetResult("Too much arguments."); return TCL_ERROR; } xml_string = NULL; xml_string_len = 0; if (takeSimpleParser || takeHTMLParser || takeJSONParser #ifdef TDOM_HAVE_GUMBO || takeGUMBOParser #endif ) { Tcl_AppendResult(interp, "simple, JSON and HTML parser " " don't support channel reading", NULL); return TCL_ERROR; } if (objc == 2) { newObjName = objv[1]; } } #ifdef TDOM_HAVE_GUMBO if (takeGUMBOParser) { if (xml_string_len > UINT_MAX) { SetResult ("The Gumbo library doesn't support strings longer than" " 4 gigabytes."); return TCL_ERROR; } doc = HTML_GumboParseDocument(xml_string, ignoreWhiteSpaces, ignorexmlns); return tcldom_returnDocumentObj (interp, doc, newObjName, 1, 0); } #endif if (takeJSONParser) { domLength byteIndex; errStr = NULL; doc = JSON_Parse (xml_string, jsonRoot, jsonmaxnesting, &errStr, &byteIndex); if (doc) { return tcldom_returnDocumentObj (interp, doc, newObjName, 1, 0); } else { tcldom_reportErrorLocation(interp, 20, 20, 0, 0, xml_string, NULL, byteIndex, errStr); return TCL_ERROR; } } if (takeSimpleParser) { domLength byteIndex; errStr = NULL; if (takeHTMLParser) { doc = HTML_SimpleParseDocument(xml_string, ignoreWhiteSpaces, forest, &byteIndex, &errStr); } else { doc = XML_SimpleParseDocument(xml_string, ignoreWhiteSpaces, keepCDATA, forest, baseURI, extResolver, &byteIndex, &errStr); } if (errStr != NULL) { domFreeDocument (doc, NULL, interp); tcldom_reportErrorLocation(interp, 80, 80, 0, 0, xml_string, NULL, byteIndex, errStr); if (takeHTMLParser) { FREE(errStr); } return TCL_ERROR; } return tcldom_returnDocumentObj (interp, doc, newObjName, 1, 0); } #ifdef TDOM_NO_EXPAT Tcl_AppendResult(interp, "tDOM was compiled without Expat!", NULL); return TCL_ERROR; #else parser = XML_ParserCreate_MM(NULL, MEM_SUITE, NULL); #ifndef TDOM_NO_SCHEMA if (sdata) { if (sdata->validationState != VALIDATION_READY) { XML_ParserFree(parser); SetResult ("The configured schema command is busy"); return TCL_ERROR; } sdata->inuse++; sdata->parser = parser; } #endif #ifdef XML_DTD if (maximumAmplification >= 1.0f) { if (XML_SetBillionLaughsAttackProtectionMaximumAmplification ( parser, (float)maximumAmplification) == XML_FALSE) { SetResult("The \"dom parse\" option \"" "-billionLaughsAttackProtectionMaximumAmplification" "\" requires a float >= 1.0 as argument."); XML_ParserFree(parser); return TCL_ERROR; } } if (activationThreshold > 0) { if (XML_SetBillionLaughsAttackProtectionActivationThreshold ( parser, activationThreshold) == XML_FALSE) { XML_ParserFree(parser); SetResult("The \"dom parse\" option \"" "-billionLaughsAttackProtectionActivationThreshold" "\" requires a long > 0 as argument."); return TCL_ERROR; } } #endif Tcl_ResetResult(interp); doc = domReadDocument(parser, xml_string, xml_string_len, ignoreWhiteSpaces, keepCDATA, TcldomDATA(storeLineColumn), ignorexmlns, feedbackAfter, feedbackCmd, chan, baseURI, extResolver, useForeignDTD, forest, paramEntityParsing, #ifndef TDOM_NO_SCHEMA sdata, #endif interp, &forestError, &status); #ifndef TDOM_NO_SCHEMA if (sdata) { sdata->inuse--; tDOM_schemaReset (sdata); } #endif if (doc == NULL) { char sl[50]; char sc[50]; switch (status) { case TCL_BREAK: /* Abort of parsing by the application */ Tcl_ResetResult(interp); XML_ParserFree(parser); return TCL_OK; default: interpResult = Tcl_GetStringResult(interp); if (interpResult[0] == '\0') { /* If the interp result isn't empty, then there was an error in an external entity and the interp result has already the error msg. If we don't got a document, but interp result is empty, the error occurred in the main document and we build the error msg as follows. */ tcldom_reportErrorLocation ( interp, 20, 40, (forest ? forestError.errorLine : XML_GetCurrentLineNumber(parser)), (forest ? forestError.errorColumn : XML_GetCurrentColumnNumber(parser)), xml_string, NULL, (forest ? forestError.byteIndex : XML_GetCurrentByteIndex(parser)), XML_ErrorString((forest ? forestError.errorCode : XML_GetErrorCode(parser)))); } else { if (status == TCL_OK) { /* For Tcl errors (in -externalentitycommand or * feedback callback) we leave the error msg in * the interpreter alone. If there wasn't a Tcl * error, there was a parsing error. Because the * interp has already an error msg, that parsing * error was in an external entity. Therefore, we * just add the place of the referencing entity in * the main document.*/ sprintf(sl, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentLineNumber(parser)); Tcl_AppendResult(interp, ", referenced at line ", sl, NULL); sprintf(sc, "%" TDOM_LS_MODIFIER "d", XML_GetCurrentColumnNumber(parser)); Tcl_AppendResult(interp, " character ", sc, NULL); } } XML_ParserFree(parser); return TCL_ERROR; } } XML_ParserFree(parser); return tcldom_returnDocumentObj (interp, doc, newObjName, 1, 0); #endif } /*---------------------------------------------------------------------------- | tcldom_featureinfo | \---------------------------------------------------------------------------*/ static int tcldom_featureinfo ( ClientData UNUSED(clientData), Tcl_Interp *interp, int UNUSED(objc), Tcl_Obj * const objv[] ) { int featureIndex, result; static const char *features[] = { "expatversion", "expatmajorversion", "expatminorversion", "expatmicroversion", "dtd", "ns", "unknown", "tdomalloc", "lessns", "html5", "jsonmaxnesting", "versionhash", "pullparser", "TCL_UTF_MAX", "schema", NULL }; enum feature { o_expatversion, o_expatmajorversion, o_expatminorversion, o_expatmicroversion, o_dtd, o_ns, o_unknown, o_tdomalloc, o_lessns, o_html5, o_jsonmaxnesting, o_versionhash, o_pullparser, o_TCL_UTF_MAX, o_schema }; /* objc is already checked by caller */ if (Tcl_GetIndexFromObj(interp, objv[1], features, "feature", 0, &featureIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum feature) featureIndex) { case o_expatversion: SetResult(XML_ExpatVersion()); break; case o_expatmajorversion: SetIntResult(XML_MAJOR_VERSION); break; case o_expatminorversion: SetIntResult(XML_MINOR_VERSION); break; case o_expatmicroversion: SetIntResult(XML_MICRO_VERSION); break; case o_dtd: #ifdef XML_DTD result = 1; #else result = 0; #endif SetBooleanResult(result); break; case o_ns: #ifdef XML_NS result = 1; #else result = 0; #endif SetBooleanResult(result); break; case o_unknown: #ifdef TDOM_NO_UNKNOWN_CMD result = 0; #else result = 1; #endif SetBooleanResult(result); break; case o_tdomalloc: #ifdef USE_NORMAL_ALLOCATOR result = 0; #else result = 1; #endif SetBooleanResult(result); break; case o_lessns: #ifdef TDOM_LESS_NS result = 1; #else result = 0; #endif SetBooleanResult(result); break; case o_html5: #ifdef TDOM_HAVE_GUMBO result = 1; #else result = 0; #endif SetBooleanResult(result); break; case o_jsonmaxnesting: SetIntResult(JSON_MAX_NESTING); break; case o_versionhash: SetResult(FOSSIL_HASH); break; case o_pullparser: #ifndef TDOM_NO_PULL result = 1; #else result = 0; #endif SetBooleanResult(result); break; case o_schema: #ifndef TDOM_NO_SCHEMA result = 1; #else result = 0; #endif SetBooleanResult(result); break; case o_TCL_UTF_MAX: SetIntResult(TCL_UTF_MAX); break; } return TCL_OK; } /*---------------------------------------------------------------------------- | tcldom_DomObjCmd | \---------------------------------------------------------------------------*/ int tcldom_DomObjCmd ( ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj * const objv[] ) { GetTcldomDATA; char * method, tmp[300], *string, *option, *replacement; int methodIndex, result, i, bool, changed; domLength repllen; Tcl_CmdInfo cmdInfo; Tcl_Obj * mobjv[MAX_REWRITE_ARGS], *newObj, *storedErrMsg; Tcl_DString cleardString; static const char *domMethods[] = { "createDocument", "createDocumentNS", "createNodeCmd", "createFromTypedList", "parse", "setStoreLineColumn", "isCharData", "isName", "isPIName", "isQName", "isComment", "isCDATA", "isPIValue", "isNCName", "createDocumentNode", "setNameCheck", "setTextCheck", "setObjectCommands", "featureinfo", "isBMPCharData", "clearString", "isHTML5CustomName", #ifdef TCL_THREADS "attachDocument", "detachDocument", #endif NULL }; enum domMethod { m_createDocument, m_createDocumentNS, m_createNodeCmd, m_createFromTypedList, m_parse, m_setStoreLineColumn, m_isCharData, m_isName, m_isPIName, m_isQName, m_isComment, m_isCDATA, m_isPIValue, m_isNCName, m_createDocumentNode, m_setNameCheck, m_setTextCheck, m_setObjectCommands, m_featureinfo, m_isBMPCharData, m_clearString, m_isHTML5CustomName #ifdef TCL_THREADS ,m_attachDocument, m_detachDocument #endif }; static const char *nodeModeValues[] = { "automatic", "command", "token", NULL }; enum nodeModeValue { v_automatic, v_command, v_token }; static const char *clearStringOptions[] = { "-replace", NULL }; enum clearStringOption { o_replace }; if (objc < 2) { Tcl_WrongNumArgs (interp, 1, objv, "subcommand ?arg ...?"); return TCL_ERROR; } if (TcldomDATA(domCreateCmdMode) == DOM_CREATECMDMODE_AUTO) { TcldomDATA(dontCreateObjCommands) = 0; } method = Tcl_GetString(objv[1]); if (Tcl_GetIndexFromObj(interp, objv[1], domMethods, "method", 0, &methodIndex) != TCL_OK) { /*-------------------------------------------------------- | try to find method implemented as normal Tcl proc \-------------------------------------------------------*/ if ((strlen(method)-1) >= 270) { SetResult("method name too long!"); return TCL_ERROR; } sprintf(tmp, "::dom::DOMImplementation::%s", method); DBG(fprintf(stderr, "testing %s\n", tmp)); storedErrMsg = Tcl_GetObjResult (interp); Tcl_IncrRefCount (storedErrMsg); result = Tcl_GetCommandInfo(interp, tmp, &cmdInfo); if (!result) { SetResult(Tcl_GetString (storedErrMsg)); Tcl_DecrRefCount (storedErrMsg); return TCL_ERROR; } Tcl_DecrRefCount (storedErrMsg); if (!cmdInfo.isNativeObjectProc) { SetResult("can't access Tcl level method!"); return TCL_ERROR; } if (objc >= MAX_REWRITE_ARGS) { SetResult("too many args to call Tcl level method!"); return TCL_ERROR; } mobjv[0] = objv[1]; mobjv[1] = objv[0]; for (i=2; i= 4) { option = Tcl_GetString (objv[2]); if (option[0] == '-' && option[1] == 'r') { if (Tcl_GetIndexFromObj (interp, objv[2], clearStringOptions, "option", 0, &i) != TCL_OK) { return TCL_ERROR; } } else { SetResult("expected: clearString ?-replace ?replacement?" " string"); return TCL_ERROR; } objc--; objv++; if (objc == 4) { replacement = Tcl_GetStringFromObj (objv[2], &repllen); objc--; objv++; } else { replacement = "\xEF\xBF\xBD\0"; repllen = 3; } } else { replacement = NULL; repllen = 0; } string = Tcl_GetString (objv[2]); domClearString (string, replacement, repllen, &cleardString, &changed); if (changed) { newObj = Tcl_NewStringObj ( Tcl_DStringValue (&cleardString), Tcl_DStringLength (&cleardString)); Tcl_DStringFree (&cleardString); Tcl_SetObjResult (interp, newObj); } else { Tcl_SetObjResult (interp, objv[2]); } return TCL_OK; } return TCL_ERROR; } #ifdef TCL_THREADS /*---------------------------------------------------------------------------- | tcldom_EvalLocked | \---------------------------------------------------------------------------*/ static int tcldom_EvalLocked ( Tcl_Interp * interp, Tcl_Obj ** objv, domDocument * doc, int flag ) { int ret; domlock *dl = doc->lock; domLocksLock(dl, flag); Tcl_AllowExceptions(interp); ret = Tcl_EvalObjEx(interp, objv[2], 0); if (ret == TCL_ERROR) { char msg[64 + TCL_INTEGER_SPACE]; sprintf(msg, "\n (\"%s %s\" body line %d)", Tcl_GetString(objv[0]), Tcl_GetString(objv[1]), Tcl_GetErrorLine(interp)); Tcl_AddErrorInfo(interp, msg); } domLocksUnlock(dl); return (ret == TCL_BREAK) ? TCL_OK : ret; } /*---------------------------------------------------------------------------- | tcldom_RegisterDocShared | \---------------------------------------------------------------------------*/ static int tcldom_RegisterDocShared ( domDocument * doc ) { Tcl_HashEntry *entryPtr; int newEntry = 0; #ifdef DEBUG int refCount; #endif Tcl_MutexLock(&tableMutex); #ifdef DEBUG refCount = ++doc->refCount; #else ++doc->refCount; #endif entryPtr = Tcl_CreateHashEntry(&sharedDocs, (char*)doc, &newEntry); if (newEntry) { Tcl_SetHashValue(entryPtr, (ClientData)doc); } Tcl_MutexUnlock(&tableMutex); DBG(fprintf(stderr, "--> tcldom_RegisterDocShared: doc %p %s " "shared table now with refcount of %d\n", doc, newEntry ? "entered into" : "already in", refCount)); return 0; } /*---------------------------------------------------------------------------- | tcldom_UnregisterDocShared | \---------------------------------------------------------------------------*/ static int tcldom_UnregisterDocShared ( Tcl_Interp * interp, domDocument * doc ) { int deleted; Tcl_MutexLock(&tableMutex); if (doc->refCount > 1) { tcldom_deleteNode(doc->rootNode, interp); domFreeNode(doc->rootNode, tcldom_deleteNode, interp, 1); doc->refCount--; deleted = 0; } else { if (tcldomInitialized) { Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&sharedDocs, (char*)doc); if (entryPtr) { Tcl_DeleteHashEntry(entryPtr); deleted = 1; } else { deleted = 0; } } else { deleted = 0; } } Tcl_MutexUnlock(&tableMutex); DBG(fprintf(stderr, "--> tcldom_UnregisterDocShared: doc %p %s " "shared table\n", doc, deleted ? "deleted from" : "left in")); return deleted; } /*---------------------------------------------------------------------------- | tcldom_CheckDocShared | \---------------------------------------------------------------------------*/ static int tcldom_CheckDocShared ( domDocument * doc ) { Tcl_HashEntry *entryPtr; domDocument *tabDoc = NULL; int found = 0; Tcl_MutexLock(&tableMutex); if (tcldomInitialized) { entryPtr = Tcl_FindHashEntry(&sharedDocs, (char*)doc); if (entryPtr == NULL) { found = 0; } else { tabDoc = (domDocument*)Tcl_GetHashValue(entryPtr); found = tabDoc ? 1 : 0; } } Tcl_MutexUnlock(&tableMutex); if (found && doc != tabDoc) { Tcl_Panic("document mismatch; doc=%p, in table=%p\n", (void *)doc, (void *)tabDoc); } return found; } #endif /* TCL_THREADS */ #ifndef TDOM_NO_UNKNOWN_CMD /*---------------------------------------------------------------------------- | tcldom_unknownCmd | \---------------------------------------------------------------------------*/ int tcldom_unknownCmd ( ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj * const objv[] ) { int i, rc, openedParen, count, args; domLength len; char *cmd, *dot, *paren, *arg[MAX_REWRITE_ARGS], *object, *method; Tcl_DString callString; Tcl_CmdInfo cmdInfo; Tcl_Obj *vector[2+MAX_REWRITE_ARGS]; Tcl_Obj **objvCall; cmd = Tcl_GetStringFromObj(objv[1], &len); DBG(fprintf(stderr, "tcldom_unknownCmd: cmd=-%s- \n", cmd)); dot = strchr(cmd,'.'); if ((dot != NULL) && (dot != cmd)) { object = cmd; cmd = dot+1; *dot = '\0'; dot = strchr(cmd,'.'); while (dot != NULL) { method = cmd; paren = strchr(cmd,'('); args = 0; if (paren && (paren < dot)) { *paren = '\0'; paren++; arg[args] = paren; openedParen = 1; while (*paren) { if (*paren == '\\') { (void) Tcl_Backslash(paren, &count); paren += count; } else if (*paren == ')') { openedParen--; if (openedParen==0) { *paren = '\0'; args++; break; } } else if (*paren == '(') { openedParen++; paren++; } else if (*paren == ',') { *paren = '\0'; arg[++args] = paren+1; if (args >= MAX_REWRITE_ARGS) { SetResult( "too many args"); return TCL_ERROR; } paren++; } else { paren++; } } if (openedParen!=0) { SetResult( "mismatched ("); return TCL_ERROR; } } cmd = dot+1; *dot = '\0'; DBG(fprintf(stderr, "method=-%s- \n", method); fprintf(stderr, "rest=-%s- \n", cmd); for(i=0; i= 0; i--) { Tcl_DecrRefCount(vector[i]); } } else { Tcl_DStringInit(&callString); Tcl_DStringAppendElement(&callString, object); Tcl_DStringAppendElement(&callString, method); for(i=0; i= MAX_REWRITE_ARGS) { SetResult( "too many args"); return TCL_ERROR; } paren++; } else { paren++; } } if (openedParen!=0) { SetResult( "mismatched ("); return TCL_ERROR; } } DBG(fprintf(stderr, "method=-%s- \n", method); fprintf(stderr, "rest=-%s- \n", cmd); for(i=0; i= 0; i--) { Tcl_DecrRefCount(objvCall[i]); } FREE((void*)objvCall); } else { Tcl_DStringInit(&callString); Tcl_DStringAppendElement(&callString, object); Tcl_DStringAppendElement(&callString, method); for(i=2; i #include #include #include #include #include #ifdef _MSC_VER #include #else #include #endif /* Used internal als status, like TCL_OK, TCL_ERROR etc. As a consequence, application specific error codes must be at least greater than 5 */ #define ERROR_IN_EXTREFHANDLER 5 #ifndef TDOM_EXPAT_READ_SIZE # define TDOM_EXPAT_READ_SIZE (1024*8) #endif #ifndef O_BINARY #ifdef _O_BINARY #define O_BINARY _O_BINARY #else #define O_BINARY 0 #endif #endif /*---------------------------------------------------------------------------- | Macros | \---------------------------------------------------------------------------*/ #define DBG(x) #define SetResult(interp,str) \ (Tcl_SetStringObj (Tcl_GetObjResult (interp), (str), -1)) #define SetIntResult(interp,i) \ (Tcl_SetDomLengthObj (Tcl_GetObjResult (interp), (i) )) #define AppendResult(interp,str) \ (Tcl_AppendToObj (Tcl_GetObjResult (interp), (str), -1)) #define CheckArgs(min,max,n,msg) \ if ((objc < min) || (objc >max)) { \ Tcl_WrongNumArgs(interp, n, objv, msg); \ return TCL_ERROR; \ } #define CheckDefaultTclHandlerSet \ if (!activeTclHandlerSet) { \ activeTclHandlerSet = CreateTclHandlerSet("default");\ tmpTclHandlerSet = expat->firstTclHandlerSet; \ expat->firstTclHandlerSet = activeTclHandlerSet; \ activeTclHandlerSet->nextHandlerSet = tmpTclHandlerSet; \ } #define SetResult3(str1,str2,str3) Tcl_ResetResult(interp); \ Tcl_AppendResult(interp, (str1), (str2), (str3), NULL) /*---------------------------------------------------------------------------- | typedefs | \---------------------------------------------------------------------------*/ typedef enum { EXPAT_INPUT_STRING, EXPAT_INPUT_CHANNEL, EXPAT_INPUT_FILENAME } TclExpat_InputType; /*---------------------------------------------------------------------------- | local globals | \---------------------------------------------------------------------------*/ static int uniqueCounter = 0; /* Counter to generate unique command names */ TDomThreaded(static Tcl_Mutex counterMutex;) /* Protect the counter (zv) */ /*---------------------------------------------------------------------------- | Prototypes for procedures defined later in this file: | \---------------------------------------------------------------------------*/ int TclExpatObjCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int TclExpatInstanceCmd (ClientData dummy, Tcl_Interp *interp, int objc, struct Tcl_Obj *const objv[]); static void TclExpatDeleteCmd (ClientData clientData); static Tcl_Obj* FindUniqueCmdName (Tcl_Interp *interp); static int TclExpatCheckWhiteData (char *pc, domLength len); static int TclExpatInitializeParser (Tcl_Interp *interp, TclGenExpatInfo *expat, int resetOptions ); static void TclExpatFreeParser (TclGenExpatInfo *expat); static int TclExpatParse (Tcl_Interp *interp, TclGenExpatInfo *expat, char *data, domLength len, TclExpat_InputType type); static int TclExpatConfigure (Tcl_Interp *interp, TclGenExpatInfo *expat, int objc, Tcl_Obj *const objv[]); static int TclExpatCget (Tcl_Interp *interp, TclGenExpatInfo *expat, int objc, Tcl_Obj *const objv[]); static int TclExpatGet (Tcl_Interp *interp, TclGenExpatInfo *expat, int objc, Tcl_Obj *const objv[]); static void TclExpatDispatchPCDATA (TclGenExpatInfo *expat); static void TclGenExpatElementStartHandler (void *userdata, const XML_Char *name, const XML_Char **atts); static void TclGenExpatElementEndHandler (void *userData, const XML_Char *name); static void TclGenExpatCharacterDataHandler (void *userData, const XML_Char *s, int len); static void TclGenExpatProcessingInstructionHandler ( void *userData, const XML_Char *target, const XML_Char *data); static int TclGenExpatExternalEntityRefHandler ( XML_Parser parser, const XML_Char *openEntityNames, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId); static void TclGenExpatDefaultHandler (void *userData, const XML_Char *s, int len); static void TclGenExpatNotationDeclHandler (void *userData, const XML_Char *notationName, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId); static int TclGenExpatUnknownEncodingHandler ( void *encodingHandlerData, const XML_Char *name, XML_Encoding *info); static void TclGenExpatStartNamespaceDeclHandler (void *userdata, const XML_Char *prefix, const XML_Char *uri); static void TclGenExpatEndNamespaceDeclHandler (void *userData, const XML_Char *prefix); /* Following added by ericm@scriptics, 1999.6.25 */ /* Prototype definition for the TclExpat comment handler */ static void TclGenExpatCommentHandler (void *userData, const XML_Char *data); /* Prototype for TclExpat Not Standalone Handler */ static int TclGenExpatNotStandaloneHandler (void *userData); /* Prototype for TclExpat {Start|End}CdataSectionHandler */ static void TclGenExpatStartCdataSectionHandler (void *userData); static void TclGenExpatEndCdataSectionHandler (void *userData); /* Added by ericm@scriptics.com, 1999.09.13 */ /* Prototype for TclExpat (Element|Attlist) Declaration Handlers */ static void TclGenExpatElementDeclHandler (void *userData, const XML_Char *name, XML_Content *model); static void TclGenExpatAttlistDeclHandler (void *userData, const XML_Char *elname, const XML_Char *name, const XML_Char *type, const XML_Char *dflt, int isrequired); /* Prototypes for the TclExpat Doctype Decl handlers */ static void TclGenExpatStartDoctypeDeclHandler ( void *userData, const XML_Char *doctypeName, const XML_Char *sysid, const XML_Char *pubid, int has_internal_subset); static void TclGenExpatEndDoctypeDeclHandler (void *userData); static void TclGenExpatXmlDeclHandler (void *userData, const XML_Char *version, const XML_Char *encoding, int standalone); static void TclGenExpatEntityDeclHandler (void *userData, const XML_Char *entityname, int is_param, const XML_Char *value, int length, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char *notationName); /* *---------------------------------------------------------------------------- * * CreateTclHandlerSet -- * * Malloc's and initializes a tclHandlerSet. * * Results: * None. * * Side effects: * Mallocs memory for the structure and the 'name' field, sets all * handler scripts to NULL and inits some other fields. * *---------------------------------------------------------------------------- */ static TclHandlerSet* CreateTclHandlerSet ( char *name ) { TclHandlerSet *handlerSet; handlerSet = (TclHandlerSet*) MALLOC (sizeof (TclHandlerSet)); \ handlerSet->name = tdomstrdup (name); handlerSet->ignoreWhiteCDATAs = 0; handlerSet->status = TCL_OK; handlerSet->continueCount = 0; handlerSet->nextHandlerSet = NULL; handlerSet->fastCall = 0; handlerSet->elementstartcommand = NULL; handlerSet->elementendcommand = NULL; handlerSet->startnsdeclcommand = NULL; handlerSet->endnsdeclcommand = NULL; handlerSet->datacommand = NULL; handlerSet->picommand = NULL; handlerSet->defaultcommand = NULL; handlerSet->notationcommand = NULL; handlerSet->externalentitycommand = NULL; handlerSet->unknownencodingcommand = NULL; handlerSet->commentCommand = NULL; handlerSet->notStandaloneCommand = NULL; handlerSet->startCdataSectionCommand = NULL; handlerSet->endCdataSectionCommand = NULL; handlerSet->elementDeclCommand = NULL; handlerSet->attlistDeclCommand = NULL; handlerSet->startDoctypeDeclCommand = NULL; handlerSet->endDoctypeDeclCommand = NULL; handlerSet->xmlDeclCommand = NULL; handlerSet->entityDeclCommand = NULL; return handlerSet; } /* *---------------------------------------------------------------------------- * * CHandlerSetCreate -- * * Initializes a CHandlerSet. * * Results: * None. * * Side effects: * Mallocs memory for the 'name' of the structure, sets all * handler functions to NULL and inits some other fields. * *---------------------------------------------------------------------------- */ CHandlerSet* CHandlerSetCreate ( char *name ) { CHandlerSet *handlerSet; handlerSet = (CHandlerSet *) MALLOC (sizeof (CHandlerSet)); handlerSet->name = tdomstrdup (name); handlerSet->ignoreWhiteCDATAs = 0; handlerSet->nextHandlerSet = NULL; handlerSet->userData = NULL; handlerSet->resetProc = NULL; handlerSet->freeProc = NULL; handlerSet->initParseProc = NULL; handlerSet->parserResetProc = NULL; handlerSet->elementstartcommand = NULL; handlerSet->elementendcommand = NULL; handlerSet->startnsdeclcommand = NULL; handlerSet->endnsdeclcommand = NULL; handlerSet->datacommand = NULL; handlerSet->picommand = NULL; handlerSet->defaultcommand = NULL; handlerSet->notationcommand = NULL; handlerSet->externalentitycommand = NULL; handlerSet->unknownencodingcommand = NULL; handlerSet->commentCommand = NULL; handlerSet->notStandaloneCommand = NULL; handlerSet->startCdataSectionCommand = NULL; handlerSet->endCdataSectionCommand = NULL; handlerSet->elementDeclCommand = NULL; handlerSet->attlistDeclCommand = NULL; handlerSet->startDoctypeDeclCommand = NULL; handlerSet->endDoctypeDeclCommand = NULL; handlerSet->xmlDeclCommand = NULL; handlerSet->entityDeclCommand = NULL; return handlerSet; } /* *---------------------------------------------------------------------------- * * TclExpatObjCmd -- * * Creation command for expat class. * * Results: * The name of the newly created parser instance. * * Side effects: * This creates an expat parser. * *---------------------------------------------------------------------------- */ int TclExpatObjCmd( ClientData UNUSED(dummy), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { TclGenExpatInfo *genexpat; /* * Create the data structures for this parser. */ if (!(genexpat = (TclGenExpatInfo *) MALLOC(sizeof(TclGenExpatInfo)))) { FREE( (char*) genexpat); Tcl_SetResult(interp, "unable to create parser", NULL); return TCL_ERROR; } memset (genexpat, 0, sizeof (TclGenExpatInfo)); genexpat->interp = interp; genexpat->final = 1; /* * Find unique command name */ if (objc < 2) { genexpat->name = FindUniqueCmdName(interp); } else { genexpat->name = objv[1]; if (*(Tcl_GetString(genexpat->name)) != '-') { Tcl_IncrRefCount(genexpat->name); objv++; objc--; } else { genexpat->name = FindUniqueCmdName(interp); } } genexpat->paramentityparsing = XML_PARAM_ENTITY_PARSING_NEVER; genexpat->nsSeparator = ':'; genexpat->maximumAmplification = 0.0; genexpat->activationThreshold = 0; if (objc > 0) { /* * Handle configuration options */ if (TclExpatConfigure(interp, genexpat, objc - 1, objv + 1) != TCL_OK) { TclExpatDeleteCmd (genexpat); return TCL_ERROR; } } if (TclExpatInitializeParser(interp, genexpat, 0) != TCL_OK) { TclExpatDeleteCmd (genexpat); return TCL_ERROR; } /* * Register a Tcl command for this parser instance. */ Tcl_CreateObjCommand(interp, Tcl_GetString(genexpat->name), TclExpatInstanceCmd, (ClientData) genexpat, TclExpatDeleteCmd); Tcl_SetObjResult(interp, genexpat->name); return TCL_OK; } /* *---------------------------------------------------------------------------- * * FindUniqueCmdName -- * * Generate new command name in caller's namespace. * * Results: * Returns newly allocated Tcl object containing name. * * Side effects: * Allocates Tcl object. * *---------------------------------------------------------------------------- */ static Tcl_Obj * FindUniqueCmdName( Tcl_Interp *interp ) { Tcl_Obj *name; Tcl_CmdInfo info; char s[20]; name = Tcl_NewStringObj("", 0); Tcl_IncrRefCount(name); do { TDomThreaded(Tcl_MutexLock(&counterMutex);) sprintf(s, "xmlparser%d", uniqueCounter++); TDomThreaded(Tcl_MutexUnlock(&counterMutex);) Tcl_SetStringObj(name, s, -1); } while (Tcl_GetCommandInfo(interp, Tcl_GetString(name), &info)); return name; } /* *---------------------------------------------------------------------------- * * TclExpatInitializeParser -- * * Create or re-initializes (if it already exists) the expat * parser and initialize (some of) the TclExpatInfo structure. * * Note that callback commands are not affected by this routine, * to allow a reset to leave these intact. * * Results: * A flag, signaling success or error. * * Side effects: * Creates or reset an expat parser. * Modifies TclExpatInfo fields. * *---------------------------------------------------------------------------- */ static int TclExpatInitializeParser( Tcl_Interp *interp, TclGenExpatInfo *expat, int resetOptions ) { CHandlerSet *activeCHandlerSet; ExpatElemContent *eContent, *eContentSave; if (expat->parser) { XML_ParserReset (expat->parser, NULL); activeCHandlerSet = expat->firstCHandlerSet; while (activeCHandlerSet) { if (activeCHandlerSet->resetProc) { activeCHandlerSet->resetProc (expat->interp, activeCHandlerSet->userData); } activeCHandlerSet = activeCHandlerSet->nextHandlerSet; } } else { if (expat->ns_mode) { if (!(expat->parser = XML_ParserCreate_MM(NULL, MEM_SUITE, &expat->nsSeparator))) { Tcl_SetResult(interp, "unable to create expat parserNs", NULL); return TCL_ERROR; } } else { if (!(expat->parser = XML_ParserCreate_MM(NULL, MEM_SUITE, NULL))) { Tcl_SetResult(interp, "unable to create expat parser", NULL); return TCL_ERROR; } } #ifdef XML_DTD if (expat->maximumAmplification >= 1.0f) { if (XML_SetBillionLaughsAttackProtectionMaximumAmplification ( expat->parser, expat->maximumAmplification) == XML_FALSE) { XML_ParserFree(expat->parser); Tcl_SetResult(interp, "The option \"" "-billionLaughsAttackProtectionMaximumAmplification" "\" requires a float >= 1.0 as argument.", NULL); return TCL_ERROR; } } if (expat->activationThreshold > 0) { if (XML_SetBillionLaughsAttackProtectionActivationThreshold ( expat->parser, expat->activationThreshold) == XML_FALSE) { XML_ParserFree(expat->parser); Tcl_SetResult(interp, "The \"" "-billionLaughsAttackProtectionActivationThreshold" "\" requires a long > 0 as argument.", NULL); return TCL_ERROR; } } #endif } expat->status = TCL_OK; if (expat->result) { Tcl_DecrRefCount (expat->result); expat->result = NULL; } if (expat->cdata) { Tcl_DecrRefCount (expat->cdata); } expat->cdata = NULL; eContent = expat->eContents; while (eContent) { XML_FreeContentModel (expat->parser, eContent->content); eContentSave = eContent; eContent = eContent->next; FREE((char *) eContentSave); } expat->eContents = NULL; expat->finished = 0; expat->parsingState = 0; #ifndef TDOM_NO_SCHEMA if (expat->sdata) { tDOM_schemaReset (expat->sdata); } #endif if (resetOptions) { expat->final = 1; expat->needWSCheck = 0; expat->noexpand = 0; expat->useForeignDTD = 0; expat->paramentityparsing = XML_PARAM_ENTITY_PARSING_NEVER; if (expat->baseURI) { Tcl_DecrRefCount (expat->baseURI); expat->baseURI = NULL; } } if (expat->baseURI) { XML_SetBase (expat->parser, Tcl_GetString (expat->baseURI)); Tcl_DecrRefCount (expat->baseURI); expat->baseURI = NULL; } XML_SetParamEntityParsing(expat->parser, expat->paramentityparsing); XML_UseForeignDTD (expat->parser, (unsigned char)expat->useForeignDTD); /* * Set handlers for the parser to routines in this module. */ XML_SetElementHandler(expat->parser, TclGenExpatElementStartHandler, TclGenExpatElementEndHandler); XML_SetNamespaceDeclHandler(expat->parser, TclGenExpatStartNamespaceDeclHandler, TclGenExpatEndNamespaceDeclHandler); XML_SetCharacterDataHandler(expat->parser, TclGenExpatCharacterDataHandler); XML_SetProcessingInstructionHandler(expat->parser, TclGenExpatProcessingInstructionHandler); XML_SetDefaultHandlerExpand(expat->parser, TclGenExpatDefaultHandler); XML_SetNotationDeclHandler(expat->parser, TclGenExpatNotationDeclHandler); XML_SetExternalEntityRefHandler(expat->parser, TclGenExpatExternalEntityRefHandler); XML_SetUnknownEncodingHandler(expat->parser, TclGenExpatUnknownEncodingHandler, (void *) expat); XML_SetCommentHandler(expat->parser, TclGenExpatCommentHandler); XML_SetNotStandaloneHandler(expat->parser, TclGenExpatNotStandaloneHandler); XML_SetCdataSectionHandler(expat->parser, TclGenExpatStartCdataSectionHandler, TclGenExpatEndCdataSectionHandler); XML_SetElementDeclHandler(expat->parser, TclGenExpatElementDeclHandler); XML_SetAttlistDeclHandler(expat->parser, TclGenExpatAttlistDeclHandler); XML_SetDoctypeDeclHandler(expat->parser, TclGenExpatStartDoctypeDeclHandler, TclGenExpatEndDoctypeDeclHandler); XML_SetXmlDeclHandler (expat->parser, TclGenExpatXmlDeclHandler); XML_SetEntityDeclHandler (expat->parser, TclGenExpatEntityDeclHandler); if (expat->noexpand) { XML_SetDefaultHandler(expat->parser, TclGenExpatDefaultHandler); } else { XML_SetDefaultHandlerExpand(expat->parser, TclGenExpatDefaultHandler); } XML_SetUserData(expat->parser, (void *) expat); return TCL_OK; } /* *---------------------------------------------------------------------------- * * TclExpatFreeParser -- * * Destroy the expat parser structure and frees the stored content models, * if there one. * * Results: * None. * * Side effects: * Frees any memory allocated for the XML parser and (if still present) * the stored content models. * *---------------------------------------------------------------------------- */ static void TclExpatFreeParser( TclGenExpatInfo *expat ) { ExpatElemContent *eContent, *eContentSave; eContent = expat->eContents; while (eContent) { XML_FreeContentModel (expat->parser, eContent->content); eContentSave = eContent; eContent = eContent->next; FREE((char *) eContentSave); } expat->eContents = NULL; XML_ParserFree(expat->parser); expat->parser = NULL; } /* *---------------------------------------------------------------------------- * * CurrentmarkupCommand -- * * Set as defaultHandler prior to XML_Currentmarkup() call. * * Results: * None. * * Side effects: * Stores the markup context in expat->currentmarkup. * *---------------------------------------------------------------------------- */ static void CurrentmarkupCommand ( void *userData, const char *s, int len ) { TclGenExpatInfo *expat = (TclGenExpatInfo *) userData; if (expat->status != TCL_OK) { return; } if (expat->cdata) { /* TclGenExpatCharacterDataHandler() was called and * initialized expat->cdata, but expat->cdata isn't reset by * TclExpatDispatchPCDATA(), so we're called from * -characterdatacommand and return the empty string by * definition. */ expat->currentmarkup = NULL; expat->currentmarkuplen = 0; return; } expat->currentmarkup = s; expat->currentmarkuplen = len; return; } /* *---------------------------------------------------------------------------- * * TclExpatInstanceCmd -- * * Implements instance command for expat class objects. * * Results: * Depends on the method. * * Side effects: * Depends on the method. * *---------------------------------------------------------------------------- */ static int TclExpatInstanceCmd ( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { TclGenExpatInfo *expat = (TclGenExpatInfo *) clientData; char *data; int optionIndex, result = TCL_OK; domLength len = 0; #ifndef TDOM_NO_SCHEMA int resetsdata = 0; #endif static const char *options[] = { "configure", "cget", "currentmarkup", "free", "get", "parse", "parsechannel", "parsefile", "reset", "delete", NULL }; enum options { EXPAT_CONFIGURE, EXPAT_CGET, EXPAT_CURRENTMARKUP, EXPAT_FREE, EXPAT_GET, EXPAT_PARSE, EXPAT_PARSECHANNEL, EXPAT_PARSEFILE, EXPAT_RESET, EXPAT_DELETE }; if (objc < 2) { Tcl_SetResult (interp, "wrong # args: should be \"parserCmd method ?arg ...?\"", TCL_STATIC); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum options) optionIndex) { case EXPAT_CONFIGURE: if (objc < 3) { Tcl_SetResult (interp, "wrong # args: should be " "\"parserCmd configure
    textmore text
    } test tnc-1.1 {tnc enable} { set parser [expat] tnc $parser enable $parser free set result "" } {} test tnc-1.2 {tnc enable} { expat parser tnc parser enable parser free set result "" } {} test tnc-1.3 {try to enable tnc for an already tnc enabled parser} { set parser [expat] tnc $parser enable set result [catch {tnc $parser enable}] $parser free set result } {1} test tnc-1.4 {tnc - first arg isn't a parser} { set errMsg "" set result [catch {tnc foo enable} errMsg] list $result $errMsg } {1 {First argument has to be a expat parser object}} test tnc-1.5 {tnc - wrong method name (second arg)} { set parser [expat] set errMsg "" set result [catch {tnc $parser foobaz} errMsg] $parser free list $result $errMsg } {1 {bad method "foobaz": must be enable, remove, or getValidateCmd}} test tnc-2.1 {parse with tnc enabled} { set parser [expat] tnc $parser enable set result [catch {$parser parse $xml}] $parser free set result } {0} test tnc-2.2 {parse with tnc enabled} { set parser [expat] tnc $parser enable set result [catch {$parser parse $xml}] $parser free set result } {0} test tnc-2.3 {parse with tnc enabled} { set parser [expat] tnc $parser enable set result [catch {$parser parse $xml}] $parser free set result } {0} # This is like $xml, only with wrong root element set xmlWrong { ]> texttextmore text } test tnc-2.4 {parse with tnc enable - wrong document element} { set parser [expat] tnc $parser enable set errMsg "" set result [catch {$parser parse $xmlWrong} errMsg] $parser free lappend result $errMsg } {1 {Validation error at line 6, character 0: No declaration for this element.}} test tnc-2.5 {invalid DTD} { set parser [expat] tnc $parser enable set result [catch {$parser parse { ]> texttextmore text }}] $parser free set result } {1} test tnc-2.6 {invalid document} { set parser [expat] tnc $parser enable set errMsg "" set result [catch {$parser parse { ]> }} errMsg] $parser free set result } {1} test tnc-2.7 {not valid document} { set parser [expat] tnc $parser enable set result [catch {$parser parse { ]> text}} errMsg] $parser free set errMsg } {Validation error at line 6, character 17: Element can not end here (required element(s) missing).} proc 2.8-resolver {base systemId publicId} { switch $publicId { "-//W3C//DTD Specification V2.0//EN" { set fd [open [file join [file dir [info script]] \ ../../../tests/data/xmlspec-v20.dtd]] set xmlspec [read $fd] close $fd return [list "string" "" $xmlspec] } default { puts stderr "Unexpected systemId '$systemId'" return "" } } } test tnc-2.8 {Validate REC-xslt-19991116.xml} { set ::tdom::extRefHandlerDebug 1 set parser [expat -externalentitycommand 2.8-resolver \ -paramentityparsing always] tnc $parser enable $parser parsefile [file join [file dir [info script]] \ ../../../tests/data/REC-xslt-19991116.xml] $parser free } {} test tnc-2.8.1 {Validate REC-xslt-19991116-mod.xml} { set ::tDOM::extRefHandlerDebug 1 set parser [expat -externalentitycommand 2.8-resolver \ -paramentityparsing always] tnc $parser enable set result [catch { $parser parsefile [file join [file dir [info script]] \ ../../../tests/data/REC-xslt-19991116-mod.xml] }] $parser free set result } 1 test tnc-2.9 {check #PCDATA only element} { set parser [expat] tnc $parser enable set result [catch {$parser parse { ]> texttext}} errMsg] $parser free set errMsg } {Validation error at line 6, character 13: Element is not allowed here.} test tnc-3.1 {validate cmd} { set parser [expat] tnc $parser enable set result [catch {$parser parse $xml}] set validator [tnc $parser getValidateCmd] rename $validator {} $parser free set result } {0} test tnc-3.2 {validate cmd} { set parser [expat] tnc $parser enable set result [catch {$parser parse $xml}] set validator [tnc $parser getValidateCmd] $parser free rename $validator {} set result } {0} test tnc-3.3 {validate cmd} { set parser [expat] tnc $parser enable set result [catch {$parser parse $xml}] set validator [tnc $parser getValidateCmd] $parser reset lappend result [catch {$parser parse $xml}] rename $validator {} $parser free set result } {0 0} test tnc-3.4 {validate cmd} { set parser [expat] tnc $parser enable tdom $parser enable $parser parse $xml set validator [tnc $parser getValidateCmd] set doc [tdom $parser getdoc] $parser free set result [catch {$validator validateTree [$doc documentElement]} errMsg] rename $validator {} $doc delete if {$result} { set errMsg } else { set result } } {0} test tnc-3.5 {validate cmd} { set parser [expat] tnc $parser enable tdom $parser enable $parser parse $xml set validator [tnc $parser getValidateCmd] tnc $parser remove $parser reset $parser parse $xml set doc [tdom $parser getdoc] $parser free set result [catch {$validator validateTree [$doc documentElement]} errMsg] rename $validator {} $doc delete if {$result} { set errMsg } else { set result } } {0} test tnc-3.6 {validate cmd} { set parser [expat] tnc $parser enable tdom $parser enable $parser parse $xml set validator [tnc $parser getValidateCmd] tnc $parser remove $parser reset $parser parse $xml set doc [tdom $parser getdoc] $parser free set root [$doc documentElement] set result [catch {$validator validateTree $root}] foreach child [$root childNodes] { if {[$child nodeType] == "ELEMENT_NODE"} { lappend result [catch {$validator validateTree $child}] } } rename $validator {} $doc delete set result } {0 0 0} test tnc-3.7 {validate cmd} { set parser [expat] tnc $parser enable set result [catch {$parser parse $xmlWrong}] set validator [tnc $parser getValidateCmd] $parser free set doc [dom parse $xml] set root [$doc documentElement] lappend result [catch {$validator validateTree $root}] lappend result [catch {$validator validateDocument $doc}] $validator delete $doc delete set result } {1 0 0} test tnc-3.8 {validator cmd generated from not-wellformed document with well-formed DTD} { set parser [expat] tnc $parser enable set errMsg "" catch {$parser parse { ]> }} tnc $parser getValidateCmd validator set doc [dom parse $xml] set result [validator validateDocument $doc] $parser free validator delete $doc delete set result } {1} test tnc-3.9 {validator cmd - validation error info} { set parser [expat] tnc $parser enable $parser parse $xml tnc $parser getValidateCmd validator $parser free set doc [dom parse $xml] set result [validator validateDocument $doc errInfo] validator delete $doc delete set result lappend result $errInfo } {1 {}} test tnc-3.10 {validator cmd - validation error info} { set parser [expat] tnc $parser enable $parser parse $xml tnc $parser getValidateCmd validator $parser free set doc [dom parse $xml] set errInfo "something" set result [validator validateDocument $doc errInfo] validator delete $doc delete set result lappend result $errInfo } {1 {}} test tnc-3.11 {validator cmd - validation error info} { set parser [expat] tnc $parser enable $parser parse $xml tnc $parser getValidateCmd validator $parser free set doc [dom parse $xmlWrong] set result [validator validateDocument $doc errInfo] validator delete $doc delete set result lappend result $errInfo } {0 {Root element doesn't match DOCTYPE name.}} test tnc-3.12 {validator cmd - validation error info} { set parser [expat] tnc $parser enable $parser parse $xml tnc $parser getValidateCmd validator $parser free set doc [dom parse $xml] set root [$doc documentElement] $root appendChild [$doc createElement wrong] set result [validator validateDocument $doc errInfo] lappend result $errInfo lappend result [validator validateTree $root errInfo] lappend result $errInfo validator delete $doc delete set result } {0 {No declaration for this element.} 0 {No declaration for this element.}} set xmlID { ]> } test tnc-3.13 {validator cmd - validateDocument with ID's} { set parser [expat] tnc $parser enable tdom $parser enable $parser parse $xmlID set validator [tnc $parser getValidateCmd] set doc [tdom $parser getdoc] $parser free set result [$validator validateDocument $doc errInfo] lappend result $errInfo set root [$doc documentElement] $root setAttribute id "id1" lappend result [$validator validateTree $root errInfo] lappend result $errInfo lappend result [$validator validateDocument $doc errInfo] lappend result $errInfo $doc delete $validator delete set result } {1 {} 0 {ID attribute values must be unique within the document.} 0 {ID attribute values must be unique within the document.}} test tnc-3.14 {validator cmd - validateAttributes} { set parser [expat] tnc $parser enable tdom $parser enable $parser parse $xmlID set validator [tnc $parser getValidateCmd] set doc [tdom $parser getdoc] $parser free set root [$doc documentElement] $root setAttribute wrongAtt "id1" set result [$validator validateAttributes $root errInfo] lappend result $errInfo $doc delete $validator delete set result } {0 {Unknown attribute for this element.}} proc extrefhandler-4.1 {base systemId publicId} { if {$systemId == ""} { return [list "string" $base { }] } else { error "error in tnc-4.1" } } test tnc-4.1 {document has no DTD, DTD provided via -useForeignDTD} { set parser [expat -externalentitycommand extrefhandler-4.1 \ -paramentityparsing always \ -useForeignDTD 1] tnc $parser enable $parser parse { texttextmore text } $parser free set result 1 } {1} proc extrefhandler-4.2 {base systemId publicId} { global parser if {$systemId == ""} { tnc $parser remove return [list string $base ""] } else { error "error in tnc-4.2" } } test tnc-4.2 {remove tnc from parser in extrefhandler} { set parser [expat -externalentitycommand extrefhandler-4.2 \ -paramentityparsing always \ -useForeignDTD 1] tnc $parser enable $parser parse $parser free set result 1 } {1} # cleanup ::tcltest::cleanupTests return tdom-0.9.5-src/extensions/tnc/tests/loadtnc.tcl0000644000175000017500000000133014703531020020210 0ustar rolfrolfcatch {load ../../../unix/libtdom0.9.2.so} catch {load ../libtnc0.3.0.so} catch {load ../../unix/libtdom0.9.2.so} catch {load libtnc0.3.0.so} # loadtnc.tcl -- # # This file is [source]d by all.tcl and all test files, to ensure, that # the tcltest package and the lastest tnc build is present. if {[lsearch [namespace children] ::tcltest] == -1} { if {$tcl_version < 8.2} { puts stderr "sourcing def.tcl" source [file join [file dir [info script]] defs.tcl] set auto_path [pwd] } else { package require tcltest namespace import ::tcltest::* } } if {[catch {package present tdom}]} { package require tdom } if {[catch {package require tnc}]} { package require tnc } tdom-0.9.5-src/extensions/tnc/tests/all.tcl0000644000175000017500000000453014703531020017341 0ustar rolfrolf# all.tcl -- # # This file contains a top-level script to run all of the Tcl # tests. Execute it by invoking "tclsh all.test". # # Copyright (c) 1998-1999 by Scriptics Corporation. # All rights reserved. # # RCS: @(#) $Id$ # source [file join [file dir [info script]] loadtnc.tcl] if {$tcl_version >= 8.1} { if {[lsearch [info proc ::tcltest::testConstraint] \ ::tcltest::testConstraint] == -1} { set ::tcltest::testConfig(need_i18n) 1 set ::tcltest::testConstraints(need_i18n) 1 } else { ::tcltest::testConstraint need_i18n 1 } } set timeCmd {clock format [clock seconds]} set ::tcltest::testSingleFile false puts stdout "Tcl $tcl_patchLevel tests running in interp: [info nameofexecutable]" if {$tcl_version < 8.2} { set TESTS_DIR [file join [pwd] [file dirname [info script]]] set currentDir [pwd] set globPattern [file join $TESTS_DIR *.test] foreach file [lsort [glob $globPattern]] { set tail [file tail $file] if {[string match l.*.test $tail]} { # This is an SCCS lockfile; ignore it continue } puts stdout $tail if {[catch {source $file} msg]} { puts stdout $msg } } } else { set ::tcltest::testsDirectory [file dir [info script]] puts stdout "Tests running in working dir: $::tcltest::testsDirectory" if {[llength $::tcltest::skip] > 0} { puts stdout "Skipping tests that match: $::tcltest::skip" } if {[llength $::tcltest::match] > 0} { puts stdout "Only running tests that match: $::tcltest::match" } if {[llength $::tcltest::skipFiles] > 0} { puts stdout "Skipping test files that match: $::tcltest::skipFiles" } if {[llength $::tcltest::matchFiles] > 0} { puts stdout "Only sourcing test files that match: $::tcltest::matchFiles" } puts stdout "Tests began at [eval $timeCmd]" # source each of the specified tests foreach file [lsort [::tcltest::getMatchingFiles]] { set tail [file tail $file] puts stdout $tail if {[catch {source $file} msg]} { puts stdout $msg } } } # cleanup puts stdout "\nTests ended at [eval $timeCmd]" ::tcltest::cleanupTests 1 # Just a dirty trick, to make life of mem leak debuggers a bit easier. # See http://mini.net/tcl/3248 proc exit args {} tdom-0.9.5-src/extensions/tnc/win/0000755000175000017500000000000014703531020015516 5ustar rolfrolftdom-0.9.5-src/extensions/tnc/win/rules.vc0000644000175000017500000017256014703531020017215 0ustar rolfrolf#------------------------------------------------------------- -*- makefile -*- # rules.vc -- # # Part of the nmake based build system for Tcl and its extensions. # This file does all the hard work in terms of parsing build options, # compiler switches, defining common targets and macros. The Tcl makefile # directly includes this. Extensions include it via "rules-ext.vc". # # See TIP 477 (https://core.tcl-lang.org/tips/doc/main/tip/477.md) for # detailed documentation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # Copyright (c) 2001-2003 David Gravereaux. # Copyright (c) 2003-2008 Patrick Thoyts # Copyright (c) 2017 Ashok P. Nadkarni #------------------------------------------------------------------------------ !ifndef _RULES_VC _RULES_VC = 1 # The following macros define the version of the rules.vc nmake build system # For modifications that are not backward-compatible, you *must* change # the major version. RULES_VERSION_MAJOR = 1 RULES_VERSION_MINOR = 10 # The PROJECT macro must be defined by parent makefile. !if "$(PROJECT)" == "" !error *** Error: Macro PROJECT not defined! Please define it before including rules.vc !endif !if "$(PRJ_PACKAGE_TCLNAME)" == "" PRJ_PACKAGE_TCLNAME = $(PROJECT) !endif # Also special case Tcl and Tk to save some typing later DOING_TCL = 0 DOING_TK = 0 !if "$(PROJECT)" == "tcl" DOING_TCL = 1 !elseif "$(PROJECT)" == "tk" DOING_TK = 1 !endif !ifndef NEED_TK # Backwards compatibility !ifdef PROJECT_REQUIRES_TK NEED_TK = $(PROJECT_REQUIRES_TK) !else NEED_TK = 0 !endif !endif !ifndef NEED_TCL_SOURCE NEED_TCL_SOURCE = 0 !endif !ifdef NEED_TK_SOURCE !if $(NEED_TK_SOURCE) NEED_TK = 1 !endif !else NEED_TK_SOURCE = 0 !endif ################################################################ # Nmake is a pretty weak environment in syntax and capabilities # so this file is necessarily verbose. It's broken down into # the following parts. # # 0. Sanity check that compiler environment is set up and initialize # any built-in settings from the parent makefile # 1. First define the external tools used for compiling, copying etc. # as this is independent of everything else. # 2. Figure out our build structure in terms of the directory, whether # we are building Tcl or an extension, etc. # 3. Determine the compiler and linker versions # 4. Build the nmakehlp helper application # 5. Determine the supported compiler options and features # 6. Parse the OPTS macro value for user-specified build configuration # 7. Parse the STATS macro value for statistics instrumentation # 8. Parse the CHECKS macro for additional compilation checks # 9. Extract Tcl, and possibly Tk, version numbers from the headers # 10. Based on this selected configuration, construct the output # directory and file paths # 11. Construct the paths where the package is to be installed # 12. Set up the actual options passed to compiler and linker based # on the information gathered above. # 13. Define some standard build targets and implicit rules. These may # be optionally disabled by the parent makefile. # 14. (For extensions only.) Compare the configuration of the target # Tcl and the extensions and warn against discrepancies. # # One final note about the macro names used. They are as they are # for historical reasons. We would like legacy extensions to # continue to work with this make include file so be wary of # changing them for consistency or clarity. # 0. Sanity check compiler environment # Check to see we are configured to build with MSVC (MSDEVDIR, MSVCDIR or # VCINSTALLDIR) or with the MS Platform SDK (MSSDK or WindowsSDKDir) !if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(VCINSTALLDIR) && !defined(MSSDK) && !defined(WINDOWSSDKDIR) MSG = ^ Visual C++ compiler environment not initialized. !error $(MSG) !endif # We need to run from the directory the parent makefile is located in. # nmake does not tell us what makefile was used to invoke it so parent # makefile has to set the MAKEFILEVC macro or we just make a guess and # warn if we think that is not the case. !if "$(MAKEFILEVC)" == "" !if exist("$(PROJECT).vc") MAKEFILEVC = $(PROJECT).vc !elseif exist("makefile.vc") MAKEFILEVC = makefile.vc !endif !endif # "$(MAKEFILEVC)" == "" !if !exist("$(MAKEFILEVC)") MSG = ^ You must run nmake from the directory containing the project makefile.^ If you are doing that and getting this message, set the MAKEFILEVC^ macro to the name of the project makefile. !message WARNING: $(MSG) !endif ################################################################ # 1. Define external programs being used #---------------------------------------------------------- # Set the proper copy method to avoid overwrite questions # to the user when copying files and selecting the right # "delete all" method. #---------------------------------------------------------- RMDIR = rmdir /S /Q CPY = xcopy /i /y >NUL CPYDIR = xcopy /e /i /y >NUL COPY = copy /y >NUL MKDIR = mkdir ###################################################################### # 2. Figure out our build environment in terms of what we're building. # # (a) Tcl itself # (b) Tk # (c) a Tcl extension using libraries/includes from an *installed* Tcl # (d) a Tcl extension using libraries/includes from Tcl source directory # # This last is needed because some extensions still need # some Tcl interfaces that are not publicly exposed. # # The fragment will set the following macros: # ROOT - root of this module sources # COMPATDIR - source directory that holds compatibility sources # DOCDIR - source directory containing documentation files # GENERICDIR - platform-independent source directory # WIN_DIR - Windows-specific source directory # TESTDIR - directory containing test files # TOOLSDIR - directory containing build tools # _TCLDIR - root of the Tcl installation OR the Tcl sources. Not set # when building Tcl itself. # _INSTALLDIR - native form of the installation path. For Tcl # this will be the root of the Tcl installation. For extensions # this will be the lib directory under the root. # TCLINSTALL - set to 1 if _TCLDIR refers to # headers and libraries from an installed Tcl, and 0 if built against # Tcl sources. Not set when building Tcl itself. Yes, not very well # named. # _TCL_H - native path to the tcl.h file # # If Tk is involved, also sets the following # _TKDIR - native form Tk installation OR Tk source. Not set if building # Tk itself. # TKINSTALL - set 1 if _TKDIR refers to installed Tk and 0 if Tk sources # _TK_H - native path to the tk.h file # Root directory for sources and assumed subdirectories ROOT = $(MAKEDIR)\.. # The following paths CANNOT have spaces in them as they appear on the # left side of implicit rules. !ifndef COMPATDIR COMPATDIR = $(ROOT)\compat !endif !ifndef DOCDIR DOCDIR = $(ROOT)\doc !endif !ifndef GENERICDIR GENERICDIR = $(ROOT)\generic !endif !ifndef TOOLSDIR TOOLSDIR = $(ROOT)\tools !endif !ifndef TESTDIR TESTDIR = $(ROOT)\tests !endif !ifndef LIBDIR !if exist("$(ROOT)\library") LIBDIR = $(ROOT)\library !else LIBDIR = $(ROOT)\lib !endif !endif !ifndef DEMODIR !if exist("$(LIBDIR)\demos") DEMODIR = $(LIBDIR)\demos !else DEMODIR = $(ROOT)\demos !endif !endif # ifndef DEMODIR # Do NOT use WINDIR because it is Windows internal environment # variable to point to c:\windows! WIN_DIR = $(ROOT)\win !ifndef RCDIR !if exist("$(WIN_DIR)\rc") RCDIR = $(WIN_DIR)\rc !else RCDIR = $(WIN_DIR) !endif !endif RCDIR = $(RCDIR:/=\) # The target directory where the built packages and binaries will be installed. # INSTALLDIR is the (optional) path specified by the user. # _INSTALLDIR is INSTALLDIR using the backslash separator syntax !ifdef INSTALLDIR ### Fix the path separators. _INSTALLDIR = $(INSTALLDIR:/=\) !else ### Assume the normal default. _INSTALLDIR = $(HOMEDRIVE)\Tcl !endif !if $(DOING_TCL) # BEGIN Case 2(a) - Building Tcl itself # Only need to define _TCL_H _TCL_H = ..\generic\tcl.h # END Case 2(a) - Building Tcl itself !elseif $(DOING_TK) # BEGIN Case 2(b) - Building Tk TCLINSTALL = 0 # Tk always builds against Tcl source, not an installed Tcl !if "$(TCLDIR)" == "" !if [echo TCLDIR = \> nmakehlp.out] \ || [nmakehlp -L generic\tcl.h >> nmakehlp.out] !error *** Could not locate Tcl source directory. !endif !include nmakehlp.out !endif # TCLDIR == "" _TCLDIR = $(TCLDIR:/=\) _TCL_H = $(_TCLDIR)\generic\tcl.h !if !exist("$(_TCL_H)") !error Could not locate tcl.h. Please set the TCLDIR macro to point to the Tcl *source* directory. !endif _TK_H = ..\generic\tk.h # END Case 2(b) - Building Tk !else # BEGIN Case 2(c) or (d) - Building an extension other than Tk # If command line has specified Tcl location through TCLDIR, use it # else default to the INSTALLDIR setting !if "$(TCLDIR)" != "" _TCLDIR = $(TCLDIR:/=\) !if exist("$(_TCLDIR)\include\tcl.h") # Case 2(c) with TCLDIR defined TCLINSTALL = 1 _TCL_H = $(_TCLDIR)\include\tcl.h !elseif exist("$(_TCLDIR)\generic\tcl.h") # Case 2(d) with TCLDIR defined TCLINSTALL = 0 _TCL_H = $(_TCLDIR)\generic\tcl.h !endif !else # # Case 2(c) for extensions with TCLDIR undefined # Need to locate Tcl depending on whether it needs Tcl source or not. # If we don't, check the INSTALLDIR for an installed Tcl first !if exist("$(_INSTALLDIR)\include\tcl.h") && !$(NEED_TCL_SOURCE) TCLINSTALL = 1 TCLDIR = $(_INSTALLDIR)\.. # NOTE: we will be resetting _INSTALLDIR to _INSTALLDIR/lib for extensions # later so the \.. accounts for the /lib _TCLDIR = $(_INSTALLDIR)\.. _TCL_H = $(_TCLDIR)\include\tcl.h !else # exist(...) && !$(NEED_TCL_SOURCE) !if [echo _TCLDIR = \> nmakehlp.out] \ || [nmakehlp -L generic\tcl.h >> nmakehlp.out] !error *** Could not locate Tcl source directory. !endif !include nmakehlp.out TCLINSTALL = 0 TCLDIR = $(_TCLDIR) _TCL_H = $(_TCLDIR)\generic\tcl.h !endif # exist(...) && !$(NEED_TCL_SOURCE) !endif # TCLDIR !ifndef _TCL_H MSG =^ Failed to find tcl.h. The TCLDIR macro is set incorrectly or is not set and default path does not contain tcl.h. !error $(MSG) !endif # Now do the same to locate Tk headers and libs if project requires Tk !if $(NEED_TK) !if "$(TKDIR)" != "" _TKDIR = $(TKDIR:/=\) !if exist("$(_TKDIR)\include\tk.h") TKINSTALL = 1 _TK_H = $(_TKDIR)\include\tk.h !elseif exist("$(_TKDIR)\generic\tk.h") TKINSTALL = 0 _TK_H = $(_TKDIR)\generic\tk.h !endif !else # TKDIR not defined # Need to locate Tcl depending on whether it needs Tcl source or not. # If we don't, check the INSTALLDIR for an installed Tcl first !if exist("$(_INSTALLDIR)\include\tk.h") && !$(NEED_TK_SOURCE) TKINSTALL = 1 # NOTE: we will be resetting _INSTALLDIR to _INSTALLDIR/lib for extensions # later so the \.. accounts for the /lib _TKDIR = $(_INSTALLDIR)\.. _TK_H = $(_TKDIR)\include\tk.h TKDIR = $(_TKDIR) !else # exist("$(_INSTALLDIR)\include\tk.h") && !$(NEED_TK_SOURCE) !if [echo _TKDIR = \> nmakehlp.out] \ || [nmakehlp -L generic\tk.h >> nmakehlp.out] !error *** Could not locate Tk source directory. !endif !include nmakehlp.out TKINSTALL = 0 TKDIR = $(_TKDIR) _TK_H = $(_TKDIR)\generic\tk.h !endif # exist("$(_INSTALLDIR)\include\tk.h") && !$(NEED_TK_SOURCE) !endif # TKDIR !ifndef _TK_H MSG =^ Failed to find tk.h. The TKDIR macro is set incorrectly or is not set and default path does not contain tk.h. !error $(MSG) !endif !endif # NEED_TK !if $(NEED_TCL_SOURCE) && $(TCLINSTALL) MSG = ^ *** Warning: This extension requires the source distribution of Tcl.^ *** Please set the TCLDIR macro to point to the Tcl sources. !error $(MSG) !endif !if $(NEED_TK_SOURCE) !if $(TKINSTALL) MSG = ^ *** Warning: This extension requires the source distribution of Tk.^ *** Please set the TKDIR macro to point to the Tk sources. !error $(MSG) !endif !endif # If INSTALLDIR set to Tcl installation root dir then reset to the # lib dir for installing extensions !if exist("$(_INSTALLDIR)\include\tcl.h") _INSTALLDIR=$(_INSTALLDIR)\lib !endif # END Case 2(c) or (d) - Building an extension !endif # if $(DOING_TCL) ################################################################ # 3. Determine compiler version and architecture # In this section, we figure out the compiler version and the # architecture for which we are building. This sets the # following macros: # VCVERSION - the internal compiler version as 1200, 1400, 1910 etc. # This is also printed by the compiler in dotted form 19.10 etc. # VCVER - the "marketing version", for example Visual C++ 6 for internal # compiler version 1200. This is kept only for legacy reasons as it # does not make sense for recent Microsoft compilers. Only used for # output directory names. # ARCH - set to IX86, ARM64 or AMD64 depending on 32- or 64-bit target # NATIVE_ARCH - set to IX86, ARM64 or AMD64 for the host machine # MACHINE - same as $(ARCH) - legacy # _VC_MANIFEST_EMBED_{DLL,EXE} - commands for embedding a manifest if needed cc32 = $(CC) # built-in default. link32 = link lib32 = lib rc32 = $(RC) # built-in default. #---------------------------------------------------------------- # Figure out the compiler architecture and version by writing # the C macros to a file, preprocessing them with the C # preprocessor and reading back the created file _HASH=^# _VC_MANIFEST_EMBED_EXE= _VC_MANIFEST_EMBED_DLL= VCVER=0 !if ![echo VCVERSION=_MSC_VER > vercl.x] \ && ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \ && ![echo ARCH=IX86 >> vercl.x] \ && ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \ && ![echo ARCH=AMD64 >> vercl.x] \ && ![echo $(_HASH)elif defined(_M_ARM64) >> vercl.x] \ && ![echo ARCH=ARM64 >> vercl.x] \ && ![echo $(_HASH)endif >> vercl.x] \ && ![$(cc32) -nologo -TC -P vercl.x 2>NUL] !include vercl.i !if $(VCVERSION) < 1900 !if ![echo VCVER= ^\> vercl.vc] \ && ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc] !include vercl.vc !endif !else # The simple calculation above does not apply to new Visual Studio releases # Keep the compiler version in its native form. VCVER = $(VCVERSION) !endif !endif !if ![del 2>NUL /q/f vercl.x vercl.i vercl.vc] !endif #---------------------------------------------------------------- # The MACHINE macro is used by legacy makefiles so set it as well !ifdef MACHINE !if "$(MACHINE)" == "x86" !undef MACHINE MACHINE = IX86 !elseif "$(MACHINE)" == "arm64" !undef MACHINE MACHINE = ARM64 !elseif "$(MACHINE)" == "x64" !undef MACHINE MACHINE = AMD64 !endif !if "$(MACHINE)" != "$(ARCH)" !error Specified MACHINE macro $(MACHINE) does not match detected target architecture $(ARCH). !endif !else MACHINE=$(ARCH) !endif #--------------------------------------------------------------- # The PLATFORM_IDENTIFY macro matches the values returned by # the Tcl platform::identify command !if "$(MACHINE)" == "AMD64" PLATFORM_IDENTIFY = win32-x86_64 !elseif "$(MACHINE)" == "ARM64" PLATFORM_IDENTIFY = win32-arm !else PLATFORM_IDENTIFY = win32-ix86 !endif # The MULTIPLATFORM macro controls whether binary extensions are installed # in platform-specific directories. Intended to be set/used by extensions. !ifndef MULTIPLATFORM_INSTALL MULTIPLATFORM_INSTALL = 0 !endif #------------------------------------------------------------ # Figure out the *host* architecture by reading the registry !if ![reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | findstr /i x86] NATIVE_ARCH=IX86 !elseif ![reg query HKLM\Hardware\Description\System\CentralProcessor\0 /v Identifier | findstr /i ARM | findstr /i 64-bit] NATIVE_ARCH=ARM64 !else NATIVE_ARCH=AMD64 !endif # Since MSVC8 we must deal with manifest resources. !if $(VCVERSION) >= 1400 _VC_MANIFEST_EMBED_EXE=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;1 _VC_MANIFEST_EMBED_DLL=if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2 !endif ################################################################ # 4. Build the nmakehlp program # This is a helper app we need to overcome nmake's limiting # environment. We will call out to it to get various bits of # information about supported compiler options etc. # # Tcl itself will always use the nmakehlp.c program which is # in its own source. It will be kept updated there. # # Extensions built against an installed Tcl will use the installed # copy of Tcl's nmakehlp.c if there is one and their own version # otherwise. In the latter case, they would also be using their own # rules.vc. Note that older versions of Tcl do not install nmakehlp.c # or rules.vc. # # Extensions built against Tcl sources will use the one from the Tcl source. # # When building an extension using a sufficiently new version of Tcl, # rules-ext.vc will define NMAKEHLPC appropriately to point to the # copy of nmakehlp.c to be used. !ifndef NMAKEHLPC # Default to the one in the current directory (the extension's own nmakehlp.c) NMAKEHLPC = nmakehlp.c !if !$(DOING_TCL) !if $(TCLINSTALL) !if exist("$(_TCLDIR)\lib\nmake\nmakehlp.c") NMAKEHLPC = $(_TCLDIR)\lib\nmake\nmakehlp.c !endif !else # !$(TCLINSTALL) !if exist("$(_TCLDIR)\win\nmakehlp.c") NMAKEHLPC = $(_TCLDIR)\win\nmakehlp.c !endif !endif # $(TCLINSTALL) !endif # !$(DOING_TCL) !endif # NMAKEHLPC # We always build nmakehlp even if it exists since we do not know # what source it was built from. !if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "$(NATIVE_ARCH)" !if [$(cc32) -nologo "$(NMAKEHLPC)" -link -subsystem:console > nul] !endif !else !if [copy $(NMAKEHLPC:nmakehlp.c=x86_64-w64-mingw32-nmakehlp.exe) nmakehlp.exe >NUL] !endif !endif ################################################################ # 5. Test for compiler features # Visual C++ compiler options have changed over the years. Check # which options are supported by the compiler in use. # # The following macros are set: # OPTIMIZATIONS - the compiler flags to be used for optimized builds # DEBUGFLAGS - the compiler flags to be used for debug builds # LINKERFLAGS - Flags passed to the linker # # Note that these are the compiler settings *available*, not those # that will be *used*. The latter depends on the OPTS macro settings # which we have not yet parsed. # # Also note that some of the flags in OPTIMIZATIONS are not really # related to optimization. They are placed there only for legacy reasons # as some extensions expect them to be included in that macro. # -Op improves float consistency. Note only needed for older compilers # Newer compilers do not need or support this option. !if [nmakehlp -c -Op] FPOPTS = -Op !endif # Strict floating point semantics - present in newer compilers in lieu of -Op !if [nmakehlp -c -fp:strict] FPOPTS = $(FPOPTS) -fp:strict !endif !if "$(MACHINE)" == "IX86" ### test for pentium errata !if [nmakehlp -c -QI0f] !message *** Compiler has 'Pentium 0x0f fix' FPOPTS = $(FPOPTS) -QI0f !else !message *** Compiler does not have 'Pentium 0x0f fix' !endif !endif ### test for optimizations # /O2 optimization includes /Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy as per # documentation. Note we do NOT want /Gs as that inserts a _chkstk # stack probe at *every* function entry, not just those with more than # a page of stack allocation resulting in a performance hit. However, # /O2 documentation is misleading as its stack probes are simply the # default page size locals allocation probes and not what is implied # by an explicit /Gs option. OPTIMIZATIONS = $(FPOPTS) !if [nmakehlp -c -O2] OPTIMIZING = 1 OPTIMIZATIONS = $(OPTIMIZATIONS) -O2 !else # Legacy, really. All modern compilers support this !message *** Compiler does not have 'Optimizations' OPTIMIZING = 0 !endif # Checks for buffer overflows in local arrays !if [nmakehlp -c -GS] OPTIMIZATIONS = $(OPTIMIZATIONS) -GS !endif # Link time optimization. Note that this option (potentially) makes # generated libraries only usable by the specific VC++ version that # created it. Requires /LTCG linker option !if [nmakehlp -c -GL] OPTIMIZATIONS = $(OPTIMIZATIONS) -GL CC_GL_OPT_ENABLED = 1 !else # In newer compilers -GL and -YX are incompatible. !if [nmakehlp -c -YX] OPTIMIZATIONS = $(OPTIMIZATIONS) -YX !endif !endif # [nmakehlp -c -GL] DEBUGFLAGS = $(FPOPTS) # Run time error checks. Not available or valid in a release, non-debug build # RTC is for modern compilers, -GZ is legacy !if [nmakehlp -c -RTC1] DEBUGFLAGS = $(DEBUGFLAGS) -RTC1 !elseif [nmakehlp -c -GZ] DEBUGFLAGS = $(DEBUGFLAGS) -GZ !endif #---------------------------------------------------------------- # Linker flags # LINKER_TESTFLAGS are for internal use when we call nmakehlp to test # if the linker supports a specific option. Without these flags link will # return "LNK1561: entry point must be defined" error compiling from VS-IDE: # They are not passed through to the actual application / extension # link rules. !ifndef LINKER_TESTFLAGS LINKER_TESTFLAGS = /DLL /NOENTRY /OUT:nmakehlp.out !endif LINKERFLAGS = # If compiler has enabled link time optimization, linker must too with -ltcg !ifdef CC_GL_OPT_ENABLED !if [nmakehlp -l -ltcg $(LINKER_TESTFLAGS)] LINKERFLAGS = $(LINKERFLAGS) -ltcg !endif !endif ################################################################ # 6. Extract various version numbers from headers # For Tcl and Tk, version numbers are extracted from tcl.h and tk.h # respectively. For extensions, versions are extracted from the # configure.in or configure.ac from the TEA configuration if it # exists, and unset otherwise. # Sets the following macros: # TCL_MAJOR_VERSION # TCL_MINOR_VERSION # TCL_RELEASE_SERIAL # TCL_PATCH_LEVEL # TCL_PATCH_LETTER # TCL_VERSION # TK_MAJOR_VERSION # TK_MINOR_VERSION # TK_RELEASE_SERIAL # TK_PATCH_LEVEL # TK_PATCH_LETTER # TK_VERSION # DOTVERSION - set as (for example) 2.5 # VERSION - set as (for example 25) #-------------------------------------------------------------- !if [echo REM = This file is generated from rules.vc > versions.vc] !endif !if [echo TCL_MAJOR_VERSION = \>> versions.vc] \ && [nmakehlp -V "$(_TCL_H)" TCL_MAJOR_VERSION >> versions.vc] !endif !if [echo TCL_MINOR_VERSION = \>> versions.vc] \ && [nmakehlp -V "$(_TCL_H)" TCL_MINOR_VERSION >> versions.vc] !endif !if [echo TCL_RELEASE_SERIAL = \>> versions.vc] \ && [nmakehlp -V "$(_TCL_H)" TCL_RELEASE_SERIAL >> versions.vc] !endif !if [echo TCL_PATCH_LEVEL = \>> versions.vc] \ && [nmakehlp -V "$(_TCL_H)" TCL_PATCH_LEVEL >> versions.vc] !endif !if defined(_TK_H) !if [echo TK_MAJOR_VERSION = \>> versions.vc] \ && [nmakehlp -V $(_TK_H) TK_MAJOR_VERSION >> versions.vc] !endif !if [echo TK_MINOR_VERSION = \>> versions.vc] \ && [nmakehlp -V $(_TK_H) TK_MINOR_VERSION >> versions.vc] !endif !if [echo TK_RELEASE_SERIAL = \>> versions.vc] \ && [nmakehlp -V "$(_TK_H)" TK_RELEASE_SERIAL >> versions.vc] !endif !if [echo TK_PATCH_LEVEL = \>> versions.vc] \ && [nmakehlp -V $(_TK_H) TK_PATCH_LEVEL >> versions.vc] !endif !endif # _TK_H !include versions.vc TCL_VERSION = $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION) TCL_DOTVERSION = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION) !if [nmakehlp -f $(TCL_PATCH_LEVEL) "a"] TCL_PATCH_LETTER = a !elseif [nmakehlp -f $(TCL_PATCH_LEVEL) "b"] TCL_PATCH_LETTER = b !else TCL_PATCH_LETTER = . !endif !if defined(_TK_H) TK_VERSION = $(TK_MAJOR_VERSION)$(TK_MINOR_VERSION) TK_DOTVERSION = $(TK_MAJOR_VERSION).$(TK_MINOR_VERSION) !if [nmakehlp -f $(TK_PATCH_LEVEL) "a"] TK_PATCH_LETTER = a !elseif [nmakehlp -f $(TK_PATCH_LEVEL) "b"] TK_PATCH_LETTER = b !else TK_PATCH_LETTER = . !endif !endif # Set DOTVERSION and VERSION !if $(DOING_TCL) DOTVERSION = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION) VERSION = $(TCL_VERSION) !elseif $(DOING_TK) DOTVERSION = $(TK_DOTVERSION) VERSION = $(TK_VERSION) !else # Doing a non-Tk extension # If parent makefile has not defined DOTVERSION, try to get it from TEA # first from a configure.in file, and then from configure.ac !ifndef DOTVERSION !if [echo DOTVERSION = \> versions.vc] \ || [nmakehlp -V $(ROOT)\configure.in ^[$(PROJECT)^] >> versions.vc] !if [echo DOTVERSION = \> versions.vc] \ || [nmakehlp -V $(ROOT)\configure.ac ^[$(PROJECT)^] >> versions.vc] !error *** Could not figure out extension version. Please define DOTVERSION in parent makefile before including rules.vc. !endif !endif !include versions.vc !endif # DOTVERSION VERSION = $(DOTVERSION:.=) !endif # $(DOING_TCL) ... etc. # Windows RC files have 3 version components. Ensure this irrespective # of how many components the package has specified. Basically, ensure # minimum 4 components by appending 4 0's and then pick out the first 4. # Also take care of the fact that DOTVERSION may have "a" or "b" instead # of "." separating the version components. DOTSEPARATED=$(DOTVERSION:a=.) DOTSEPARATED=$(DOTSEPARATED:b=.) !if [echo RCCOMMAVERSION = \> versions.vc] \ || [for /f "tokens=1,2,3,4,5* delims=." %a in ("$(DOTSEPARATED).0.0.0.0") do echo %a,%b,%c,%d >> versions.vc] !error *** Could not generate RCCOMMAVERSION *** !endif !include versions.vc ######################################################################## # 7. Parse the OPTS macro to work out the requested build configuration. # Based on this, we will construct the actual switches to be passed to the # compiler and linker using the macros defined in the previous section. # The following macros are defined by this section based on OPTS # STATIC_BUILD - 0 -> Tcl is to be built as a shared library # 1 -> build as a static library and shell # TCL_THREADS - legacy but always 1 on Windows since winsock requires it. # DEBUG - 1 -> debug build, 0 -> release builds # SYMBOLS - 1 -> generate PDB's, 0 -> no PDB's # PROFILE - 1 -> generate profiling info, 0 -> no profiling # PGO - 1 -> profile based optimization, 0 -> no # MSVCRT - 1 -> link to dynamic C runtime even when building static Tcl build # 0 -> link to static C runtime for static Tcl build. # Does not impact shared Tcl builds (STATIC_BUILD == 0) # Default: 1 for Tcl 8.7 and up, 0 otherwise. # TCL_USE_STATIC_PACKAGES - 1 -> statically link the registry and dde extensions # in the Tcl and Wish shell. 0 -> keep them as shared libraries. Does # not impact shared Tcl builds. Implied by STATIC_BUILD since Tcl 8.7. # USE_THREAD_ALLOC - 1 -> Use a shared global free pool for allocation. # 0 -> Use the non-thread allocator. # UNCHECKED - 1 -> when doing a debug build with symbols, use the release # C runtime, 0 -> use the debug C runtime. # USE_STUBS - 1 -> compile to use stubs interfaces, 0 -> direct linking # CONFIG_CHECK - 1 -> check current build configuration against Tcl # configuration (ignored for Tcl itself) # _USE_64BIT_TIME_T - forces a build using 64-bit time_t for 32-bit build # (CRT library should support this, not needed for Tcl 9.x) # TCL_UTF_MAX=3 - forces a build using UTF-16 internally (not recommended). # Further, LINKERFLAGS are modified based on above. # Default values for all the above STATIC_BUILD = 0 TCL_THREADS = 1 DEBUG = 0 SYMBOLS = 0 PROFILE = 0 PGO = 0 MSVCRT = 1 TCL_USE_STATIC_PACKAGES = 0 USE_THREAD_ALLOC = 1 UNCHECKED = 0 CONFIG_CHECK = 1 !if $(DOING_TCL) USE_STUBS = 0 !else USE_STUBS = 1 !endif # If OPTS is not empty AND does not contain "none" which turns off all OPTS # set the above macros based on OPTS content !if "$(OPTS)" != "" && ![nmakehlp -f "$(OPTS)" "none"] # OPTS are specified, parse them !if [nmakehlp -f $(OPTS) "static"] !message *** Doing static STATIC_BUILD = 1 !endif !if [nmakehlp -f $(OPTS) "nostubs"] !message *** Not using stubs USE_STUBS = 0 !endif !if [nmakehlp -f $(OPTS) "nomsvcrt"] !message *** Doing nomsvcrt MSVCRT = 0 !else !if [nmakehlp -f $(OPTS) "msvcrt"] !message *** Doing msvcrt !else !if $(TCL_MAJOR_VERSION) == 8 && $(TCL_MINOR_VERSION) < 7 && $(STATIC_BUILD) MSVCRT = 0 !endif !endif !endif # [nmakehlp -f $(OPTS) "nomsvcrt"] !if [nmakehlp -f $(OPTS) "staticpkg"] && $(STATIC_BUILD) !message *** Doing staticpkg TCL_USE_STATIC_PACKAGES = 1 !endif !if [nmakehlp -f $(OPTS) "nothreads"] !message *** Compile explicitly for non-threaded tcl TCL_THREADS = 0 USE_THREAD_ALLOC= 0 !endif !if $(TCL_MAJOR_VERSION) == 8 !if [nmakehlp -f $(OPTS) "time64bit"] !message *** Force 64-bit time_t _USE_64BIT_TIME_T = 1 !endif !if [nmakehlp -f $(OPTS) "utf16"] !message *** Force UTF-16 internally TCL_UTF_MAX = 3 !endif !endif # Yes, it's weird that the "symbols" option controls DEBUG and # the "pdbs" option controls SYMBOLS. That's historical. !if [nmakehlp -f $(OPTS) "symbols"] !message *** Doing symbols DEBUG = 1 !else DEBUG = 0 !endif !if [nmakehlp -f $(OPTS) "pdbs"] !message *** Doing pdbs SYMBOLS = 1 !else SYMBOLS = 0 !endif !if [nmakehlp -f $(OPTS) "profile"] !message *** Doing profile PROFILE = 1 !else PROFILE = 0 !endif !if [nmakehlp -f $(OPTS) "pgi"] !message *** Doing profile guided optimization instrumentation PGO = 1 !elseif [nmakehlp -f $(OPTS) "pgo"] !message *** Doing profile guided optimization PGO = 2 !else PGO = 0 !endif !if [nmakehlp -f $(OPTS) "loimpact"] !message *** Warning: ignoring option "loimpact" - deprecated on modern Windows. !endif # TBD - should get rid of this option !if [nmakehlp -f $(OPTS) "thrdalloc"] !message *** Doing thrdalloc USE_THREAD_ALLOC = 1 !endif !if [nmakehlp -f $(OPTS) "tclalloc"] USE_THREAD_ALLOC = 0 !endif !if [nmakehlp -f $(OPTS) "unchecked"] !message *** Doing unchecked UNCHECKED = 1 !else UNCHECKED = 0 !endif !if [nmakehlp -f $(OPTS) "noconfigcheck"] CONFIG_CHECK = 1 !else CONFIG_CHECK = 0 !endif !endif # "$(OPTS)" != "" && ... parsing of OPTS # Set linker flags based on above !if $(PGO) > 1 !if [nmakehlp -l -ltcg:pgoptimize $(LINKER_TESTFLAGS)] LINKERFLAGS = $(LINKERFLAGS:-ltcg=) -ltcg:pgoptimize !else MSG=^ This compiler does not support profile guided optimization. !error $(MSG) !endif !elseif $(PGO) > 0 !if [nmakehlp -l -ltcg:pginstrument $(LINKER_TESTFLAGS)] LINKERFLAGS = $(LINKERFLAGS:-ltcg=) -ltcg:pginstrument !else MSG=^ This compiler does not support profile guided optimization. !error $(MSG) !endif !endif ################################################################ # 8. Parse the STATS macro to configure code instrumentation # The following macros are set by this section: # TCL_MEM_DEBUG - 1 -> enables memory allocation instrumentation # 0 -> disables # TCL_COMPILE_DEBUG - 1 -> enables byte compiler logging # 0 -> disables # Default both are off TCL_MEM_DEBUG = 0 TCL_COMPILE_DEBUG = 0 !if "$(STATS)" != "" && ![nmakehlp -f "$(STATS)" "none"] !if [nmakehlp -f $(STATS) "memdbg"] !message *** Doing memdbg TCL_MEM_DEBUG = 1 !else TCL_MEM_DEBUG = 0 !endif !if [nmakehlp -f $(STATS) "compdbg"] !message *** Doing compdbg TCL_COMPILE_DEBUG = 1 !else TCL_COMPILE_DEBUG = 0 !endif !endif #################################################################### # 9. Parse the CHECKS macro to configure additional compiler checks # The following macros are set by this section: # WARNINGS - compiler switches that control the warnings level # TCL_NO_DEPRECATED - 1 -> disable support for deprecated functions # 0 -> enable deprecated functions # Defaults - Permit deprecated functions and warning level 3 TCL_NO_DEPRECATED = 0 WARNINGS = -W3 !if "$(CHECKS)" != "" && ![nmakehlp -f "$(CHECKS)" "none"] !if [nmakehlp -f $(CHECKS) "nodep"] !message *** Doing nodep check TCL_NO_DEPRECATED = 1 !endif !if [nmakehlp -f $(CHECKS) "fullwarn"] !message *** Doing full warnings check WARNINGS = -W4 !if [nmakehlp -l -warn:3 $(LINKER_TESTFLAGS)] LINKERFLAGS = $(LINKERFLAGS) -warn:3 !endif !endif !if [nmakehlp -f $(CHECKS) "64bit"] && [nmakehlp -c -Wp64] !message *** Doing 64bit portability warnings WARNINGS = $(WARNINGS) -Wp64 !endif !endif ################################################################ # 10. Construct output directory and file paths # Figure-out how to name our intermediate and output directories. # In order to avoid inadvertent mixing of object files built using # different compilers, build configurations etc., # # Naming convention (suffixes): # t = full thread support. (Not used for Tcl >= 8.7) # s = static library (as opposed to an import library) # g = linked to the debug enabled C run-time. # x = special static build when it links to the dynamic C run-time. # # The following macros are set in this section: # SUFX - the suffix to use for binaries based on above naming convention # BUILDDIRTOP - the toplevel default output directory # is of the form {Release,Debug}[_AMD64][_COMPILERVERSION] # TMP_DIR - directory where object files are created # OUT_DIR - directory where output executables are created # Both TMP_DIR and OUT_DIR are defaulted only if not defined by the # parent makefile (or command line). The default values are # based on BUILDDIRTOP. # STUBPREFIX - name of the stubs library for this project # PRJIMPLIB - output path of the generated project import library # PRJLIBNAME - name of generated project library # PRJLIB - output path of generated project library # PRJSTUBLIBNAME - name of the generated project stubs library # PRJSTUBLIB - output path of the generated project stubs library # RESFILE - output resource file (only if not static build) SUFX = tsgx !if $(DEBUG) BUILDDIRTOP = Debug !else BUILDDIRTOP = Release !endif !if "$(MACHINE)" != "IX86" BUILDDIRTOP =$(BUILDDIRTOP)_$(MACHINE) !endif !if $(VCVER) > 6 BUILDDIRTOP =$(BUILDDIRTOP)_VC$(VCVER) !endif !if !$(DEBUG) || $(TCL_VERSION) > 86 || $(DEBUG) && $(UNCHECKED) SUFX = $(SUFX:g=) !endif TMP_DIRFULL = .\$(BUILDDIRTOP)\$(PROJECT)_ThreadedDynamicStaticX !if !$(STATIC_BUILD) TMP_DIRFULL = $(TMP_DIRFULL:Static=) SUFX = $(SUFX:s=) EXT = dll TMP_DIRFULL = $(TMP_DIRFULL:X=) SUFX = $(SUFX:x=) !else TMP_DIRFULL = $(TMP_DIRFULL:Dynamic=) EXT = lib !if !$(MSVCRT) TMP_DIRFULL = $(TMP_DIRFULL:X=) SUFX = $(SUFX:x=) !endif !endif !if !$(TCL_THREADS) || $(TCL_VERSION) > 86 TMP_DIRFULL = $(TMP_DIRFULL:Threaded=) SUFX = $(SUFX:t=) !endif !ifndef TMP_DIR TMP_DIR = $(TMP_DIRFULL) !ifndef OUT_DIR OUT_DIR = .\$(BUILDDIRTOP) !endif !else !ifndef OUT_DIR OUT_DIR = $(TMP_DIR) !endif !endif # Relative paths -> absolute !if [echo OUT_DIR = \> nmakehlp.out] \ || [nmakehlp -Q "$(OUT_DIR)" >> nmakehlp.out] !error *** Could not fully qualify path OUT_DIR=$(OUT_DIR) !endif !if [echo TMP_DIR = \>> nmakehlp.out] \ || [nmakehlp -Q "$(TMP_DIR)" >> nmakehlp.out] !error *** Could not fully qualify path TMP_DIR=$(TMP_DIR) !endif !include nmakehlp.out # The name of the stubs library for the project being built STUBPREFIX = $(PROJECT)stub # # Set up paths to various Tcl executables and libraries needed by extensions # # TIP 430. Unused for 8.6 but no harm defining it to allow a common rules.vc TCLSCRIPTZIPNAME = libtcl$(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)$(TCL_PATCH_LETTER)$(TCL_RELEASE_SERIAL).zip TKSCRIPTZIPNAME = libtk$(TK_MAJOR_VERSION).$(TK_MINOR_VERSION)$(TK_PATCH_LETTER)$(TK_RELEASE_SERIAL).zip !if $(DOING_TCL) TCLSHNAME = $(PROJECT)sh$(VERSION)$(SUFX).exe TCLSH = $(OUT_DIR)\$(TCLSHNAME) TCLIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib TCLLIBNAME = $(PROJECT)$(VERSION)$(SUFX).$(EXT) TCLLIB = $(OUT_DIR)\$(TCLLIBNAME) TCLSCRIPTZIP = $(OUT_DIR)\$(TCLSCRIPTZIPNAME) TCLSTUBLIBNAME = $(STUBPREFIX)$(VERSION).lib TCLSTUBLIB = $(OUT_DIR)\$(TCLSTUBLIBNAME) TCL_INCLUDES = -I"$(WIN_DIR)" -I"$(GENERICDIR)" !else # !$(DOING_TCL) !if $(TCLINSTALL) # Building against an installed Tcl # When building extensions, we need to locate tclsh. Depending on version # of Tcl we are building against, this may or may not have a "t" suffix. # Try various possibilities in turn. TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX:t=).exe !if !exist("$(TCLSH)") TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX:t=).exe !endif TCLSTUBLIB = $(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX:t=).lib # When building extensions, may be linking against Tcl that does not add # "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility. !if !exist("$(TCLIMPLIB)") TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)t$(SUFX:t=).lib !endif TCL_LIBRARY = $(_TCLDIR)\lib TCLREGLIB = $(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib TCLDDELIB = $(_TCLDIR)\lib\tcldde14$(SUFX:t=).lib TCLSCRIPTZIP = $(_TCLDIR)\lib\$(TCLSCRIPTZIPNAME) TCLTOOLSDIR = \must\have\tcl\sources\to\build\this\target TCL_INCLUDES = -I"$(_TCLDIR)\include" !else # Building against Tcl sources TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX:t=).exe !if !exist($(TCLSH)) TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX:t=).exe !endif TCLSTUBLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX:t=).lib # When building extensions, may be linking against Tcl that does not add # "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility. !if !exist("$(TCLIMPLIB)") TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)t$(SUFX:t=).lib !endif TCL_LIBRARY = $(_TCLDIR)\library TCLREGLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib TCLDDELIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde14$(SUFX:t=).lib TCLSCRIPTZIP = $(_TCLDIR)\win\$(BUILDDIRTOP)\$(TCLSCRIPTZIPNAME) TCLTOOLSDIR = $(_TCLDIR)\tools TCL_INCLUDES = -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win" !endif # TCLINSTALL tcllibs = "$(TCLSTUBLIB)" "$(TCLIMPLIB)" !endif # $(DOING_TCL) # We need a tclsh that will run on the host machine as part of the build. # IX86 runs on all architectures. !ifndef TCLSH_NATIVE !if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "$(NATIVE_ARCH)" TCLSH_NATIVE = $(TCLSH) !else !error You must explicitly set TCLSH_NATIVE for cross-compilation !endif !endif # Do the same for Tk and Tk extensions that require the Tk libraries !if $(DOING_TK) || $(NEED_TK) WISHNAMEPREFIX = wish WISHNAME = $(WISHNAMEPREFIX)$(TK_VERSION)$(SUFX).exe TKLIBNAME8 = tk$(TK_VERSION)$(SUFX).$(EXT) TKLIBNAME9 = tcl9tk$(TK_VERSION)$(SUFX).$(EXT) !if $(TCL_MAJOR_VERSION) == 8 TKLIBNAME = tk$(TK_VERSION)$(SUFX).$(EXT) TKIMPLIBNAME = tk$(TK_VERSION)$(SUFX).lib !else TKLIBNAME = tcl9tk$(TK_VERSION)$(SUFX).$(EXT) TKIMPLIBNAME = tcl9tk$(TK_VERSION)$(SUFX).lib !endif TKSTUBLIBNAME = tkstub$(TK_VERSION).lib !if $(DOING_TK) WISH = $(OUT_DIR)\$(WISHNAME) TKSTUBLIB = $(OUT_DIR)\$(TKSTUBLIBNAME) TKIMPLIB = $(OUT_DIR)\$(TKIMPLIBNAME) TKLIB = $(OUT_DIR)\$(TKLIBNAME) TK_INCLUDES = -I"$(WIN_DIR)" -I"$(GENERICDIR)" TKSCRIPTZIP = $(OUT_DIR)\$(TKSCRIPTZIPNAME) !else # effectively NEED_TK !if $(TKINSTALL) # Building against installed Tk WISH = $(_TKDIR)\bin\$(WISHNAME) TKSTUBLIB = $(_TKDIR)\lib\$(TKSTUBLIBNAME) TKIMPLIB = $(_TKDIR)\lib\$(TKIMPLIBNAME) # When building extensions, may be linking against Tk that does not add # "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility. !if !exist("$(TKIMPLIB)") TKIMPLIBNAME = tk$(TK_VERSION)$(SUFX:t=).lib TKIMPLIB = $(_TKDIR)\lib\$(TKIMPLIBNAME) !endif TK_INCLUDES = -I"$(_TKDIR)\include" TKSCRIPTZIP = $(_TKDIR)\lib\$(TKSCRIPTZIPNAME) !else # Building against Tk sources WISH = $(_TKDIR)\win\$(BUILDDIRTOP)\$(WISHNAME) TKSTUBLIB = $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKSTUBLIBNAME) TKIMPLIB = $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKIMPLIBNAME) # When building extensions, may be linking against Tk that does not add # "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility. !if !exist("$(TKIMPLIB)") TKIMPLIBNAME = tk$(TK_VERSION)$(SUFX:t=).lib TKIMPLIB = $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKIMPLIBNAME) !endif TK_INCLUDES = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib" TKSCRIPTZIP = $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKSCRIPTZIPNAME) !endif # TKINSTALL tklibs = "$(TKSTUBLIB)" "$(TKIMPLIB)" !endif # $(DOING_TK) !endif # $(DOING_TK) || $(NEED_TK) # Various output paths PRJIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib PRJLIBNAME8 = $(PROJECT)$(VERSION)$(SUFX).$(EXT) PRJLIBNAME9 = tcl9$(PROJECT)$(VERSION)$(SUFX).$(EXT) !if $(TCL_MAJOR_VERSION) == 8 PRJLIBNAME = $(PRJLIBNAME8) !else PRJLIBNAME = $(PRJLIBNAME9) !endif PRJLIB = $(OUT_DIR)\$(PRJLIBNAME) PRJSTUBLIBNAME = $(STUBPREFIX)$(VERSION).lib PRJSTUBLIB = $(OUT_DIR)\$(PRJSTUBLIBNAME) # If extension parent makefile has not defined a resource definition file, # we will generate one from standard template. !if !$(DOING_TCL) && !$(DOING_TK) && !$(STATIC_BUILD) !ifdef RCFILE RESFILE = $(TMP_DIR)\$(RCFILE:.rc=.res) !else RESFILE = $(TMP_DIR)\$(PROJECT).res !endif !endif ################################################################### # 11. Construct the paths for the installation directories # The following macros get defined in this section: # LIB_INSTALL_DIR - where libraries should be installed # BIN_INSTALL_DIR - where the executables should be installed # DOC_INSTALL_DIR - where documentation should be installed # SCRIPT_INSTALL_DIR - where scripts should be installed # INCLUDE_INSTALL_DIR - where C include files should be installed # DEMO_INSTALL_DIR - where demos should be installed # PRJ_INSTALL_DIR - where package will be installed (not set for Tcl and Tk) !if $(DOING_TCL) || $(DOING_TK) LIB_INSTALL_DIR = $(_INSTALLDIR)\lib BIN_INSTALL_DIR = $(_INSTALLDIR)\bin DOC_INSTALL_DIR = $(_INSTALLDIR)\doc !if $(DOING_TCL) SCRIPT_INSTALL_DIR = $(_INSTALLDIR)\lib\$(PROJECT)$(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION) MODULE_INSTALL_DIR = $(_INSTALLDIR)\lib\tcl$(TCL_MAJOR_VERSION) !else # DOING_TK SCRIPT_INSTALL_DIR = $(_INSTALLDIR)\lib\$(PROJECT)$(TK_MAJOR_VERSION).$(TK_MINOR_VERSION) !endif DEMO_INSTALL_DIR = $(SCRIPT_INSTALL_DIR)\demos INCLUDE_INSTALL_DIR = $(_INSTALLDIR)\include !else # extension other than Tk PRJ_INSTALL_DIR = $(_INSTALLDIR)\$(PROJECT)$(DOTVERSION) !if $(MULTIPLATFORM_INSTALL) LIB_INSTALL_DIR = $(PRJ_INSTALL_DIR)\$(PLATFORM_IDENTIFY) BIN_INSTALL_DIR = $(PRJ_INSTALL_DIR)\$(PLATFORM_IDENTIFY) !else LIB_INSTALL_DIR = $(PRJ_INSTALL_DIR) BIN_INSTALL_DIR = $(PRJ_INSTALL_DIR) !endif DOC_INSTALL_DIR = $(PRJ_INSTALL_DIR) SCRIPT_INSTALL_DIR = $(PRJ_INSTALL_DIR) DEMO_INSTALL_DIR = $(PRJ_INSTALL_DIR)\demos INCLUDE_INSTALL_DIR = $(_INSTALLDIR)\..\include !endif ################################################################### # 12. Set up actual options to be passed to the compiler and linker # Now we have all the information we need, set up the actual flags and # options that we will pass to the compiler and linker. The main # makefile should use these in combination with whatever other flags # and switches are specific to it. # The following macros are defined, names are for historical compatibility: # OPTDEFINES - /Dxxx C macro flags based on user-specified OPTS # COMPILERFLAGS - /Dxxx C macro flags independent of any configuration opttions # crt - Compiler switch that selects the appropriate C runtime # cdebug - Compiler switches related to debug AND optimizations # cwarn - Compiler switches that set warning levels # cflags - complete compiler switches (subsumes cdebug and cwarn) # ldebug - Linker switches controlling debug information and optimization # lflags - complete linker switches (subsumes ldebug) except subsystem type # dlllflags - complete linker switches to build DLLs (subsumes lflags) # conlflags - complete linker switches for console program (subsumes lflags) # guilflags - complete linker switches for GUI program (subsumes lflags) # baselibs - minimum Windows libraries required. Parent makefile can # define PRJ_LIBS before including rules.rc if additional libs are needed OPTDEFINES = /DSTDC_HEADERS /DUSE_NMAKE=1 !if $(VCVERSION) > 1600 OPTDEFINES = $(OPTDEFINES) /DHAVE_STDINT_H=1 !else OPTDEFINES = $(OPTDEFINES) /DMP_NO_STDINT=1 !endif !if $(VCVERSION) >= 1800 OPTDEFINES = $(OPTDEFINES) /DHAVE_INTTYPES_H=1 /DHAVE_STDBOOL_H=1 !endif !if $(TCL_MEM_DEBUG) OPTDEFINES = $(OPTDEFINES) /DTCL_MEM_DEBUG !endif !if $(TCL_COMPILE_DEBUG) OPTDEFINES = $(OPTDEFINES) /DTCL_COMPILE_DEBUG /DTCL_COMPILE_STATS !endif !if $(TCL_THREADS) && $(TCL_VERSION) < 87 OPTDEFINES = $(OPTDEFINES) /DTCL_THREADS=1 !if $(USE_THREAD_ALLOC) && $(TCL_VERSION) < 87 OPTDEFINES = $(OPTDEFINES) /DUSE_THREAD_ALLOC=1 !endif !endif !if $(STATIC_BUILD) OPTDEFINES = $(OPTDEFINES) /DSTATIC_BUILD !elseif $(TCL_VERSION) > 86 OPTDEFINES = $(OPTDEFINES) /DTCL_WITH_EXTERNAL_TOMMATH !if "$(MACHINE)" == "AMD64" || "$(MACHINE)" == "ARM64" OPTDEFINES = $(OPTDEFINES) /DMP_64BIT !endif !endif !if $(TCL_NO_DEPRECATED) OPTDEFINES = $(OPTDEFINES) /DTCL_NO_DEPRECATED !endif !if $(USE_STUBS) # Note we do not define USE_TCL_STUBS even when building tk since some # test targets in tk do not use stubs !if !$(DOING_TCL) USE_STUBS_DEFS = /DUSE_TCL_STUBS /DUSE_TCLOO_STUBS !if $(NEED_TK) USE_STUBS_DEFS = $(USE_STUBS_DEFS) /DUSE_TK_STUBS !endif !endif !endif # USE_STUBS !if !$(DEBUG) OPTDEFINES = $(OPTDEFINES) /DNDEBUG !if $(OPTIMIZING) OPTDEFINES = $(OPTDEFINES) /DTCL_CFG_OPTIMIZED !endif !endif !if $(PROFILE) OPTDEFINES = $(OPTDEFINES) /DTCL_CFG_PROFILED !endif !if "$(MACHINE)" == "AMD64" || "$(MACHINE)" == "ARM64" OPTDEFINES = $(OPTDEFINES) /DTCL_CFG_DO64BIT !endif !if $(VCVERSION) < 1300 OPTDEFINES = $(OPTDEFINES) /DNO_STRTOI64=1 !endif !if "$(TCL_MAJOR_VERSION)" == "8" !if "$(_USE_64BIT_TIME_T)" == "1" OPTDEFINES = $(OPTDEFINES) /D_USE_64BIT_TIME_T=1 !endif # _ATL_XP_TARGETING - Newer SDK's need this to build for XP COMPILERFLAGS = /D_ATL_XP_TARGETING !endif !if "$(TCL_UTF_MAX)" == "3" OPTDEFINES = $(OPTDEFINES) /DTCL_UTF_MAX=3 !endif # Like the TEA system only set this non empty for non-Tk extensions # Note: some extensions use PACKAGE_NAME and others use PACKAGE_TCLNAME # so we pass both !if !$(DOING_TCL) && !$(DOING_TK) PKGNAMEFLAGS = /DPACKAGE_NAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \ /DPACKAGE_TCLNAME="\"$(PRJ_PACKAGE_TCLNAME)\"" \ /DPACKAGE_VERSION="\"$(DOTVERSION)\"" \ /DMODULE_SCOPE=extern !endif # crt picks the C run time based on selected OPTS !if $(MSVCRT) !if $(DEBUG) && !$(UNCHECKED) crt = -MDd !else crt = -MD !endif !else !if $(DEBUG) && !$(UNCHECKED) crt = -MTd !else crt = -MT !endif !endif # cdebug includes compiler options for debugging as well as optimization. !if $(DEBUG) # In debugging mode, optimizations need to be disabled cdebug = -Zi -Od $(DEBUGFLAGS) !else cdebug = $(OPTIMIZATIONS) !if $(SYMBOLS) cdebug = $(cdebug) -Zi !endif !endif # $(DEBUG) # cwarn includes default warning levels, also C4090 (buggy) and C4146 is useless. cwarn = $(WARNINGS) -wd4090 -wd4146 !if "$(MACHINE)" == "AMD64" || "$(MACHINE)" == "ARM64" # Disable pointer<->int warnings related to cast between different sizes # There are a gadzillion of these due to use of ClientData and # clutter up compiler # output increasing chance of a real warning getting lost. So disable them. # Eventually some day, Tcl will be 64-bit clean. cwarn = $(cwarn) -wd4311 -wd4312 !endif ### Common compiler options that are architecture specific !if "$(MACHINE)" == "ARM" carch = /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE !else carch = !endif # cpuid is only available on intel machines !if "$(MACHINE)" == "IX86" || "$(MACHINE)" == "AMD64" carch = $(carch) /DHAVE_CPUID=1 !endif !if $(DEBUG) # Turn warnings into errors cwarn = $(cwarn) -WX !endif INCLUDES = $(TCL_INCLUDES) $(TK_INCLUDES) $(PRJ_INCLUDES) !if !$(DOING_TCL) && !$(DOING_TK) INCLUDES = $(INCLUDES) -I"$(GENERICDIR)" -I"$(WIN_DIR)" -I"$(COMPATDIR)" !endif # These flags are defined roughly in the order of the pre-reform # rules.vc/makefile.vc to help visually compare that the pre- and # post-reform build logs # cflags contains generic flags used for building practically all object files cflags = -nologo -c $(COMPILERFLAGS) $(carch) $(cwarn) -Fp$(TMP_DIR)^\ $(cdebug) # appcflags contains $(cflags) and flags for building the application # object files (e.g. tclsh, or wish) pkgcflags contains $(cflags) plus # flags used for building shared object files The two differ in the # BUILD_$(PROJECT) macro which should be defined only for the shared # library *implementation* and not for its caller interface appcflags_nostubs = $(cflags) $(crt) $(INCLUDES) $(TCL_DEFINES) $(PRJ_DEFINES) $(OPTDEFINES) appcflags = $(appcflags_nostubs) $(USE_STUBS_DEFS) pkgcflags = $(appcflags) $(PKGNAMEFLAGS) /DBUILD_$(PROJECT) pkgcflags_nostubs = $(appcflags_nostubs) $(PKGNAMEFLAGS) /DBUILD_$(PROJECT) # stubscflags contains $(cflags) plus flags used for building a stubs # library for the package. Note: /DSTATIC_BUILD is defined in # $(OPTDEFINES) only if the OPTS configuration indicates a static # library. However the stubs library is ALWAYS static hence included # here irrespective of the OPTS setting. # # TBD - tclvfs has a comment that stubs libs should not be compiled with -GL # without stating why. Tcl itself compiled stubs libs with this flag. # so we do not remove it from cflags. -GL may prevent extensions # compiled with one VC version to fail to link against stubs library # compiled with another VC version. Check for this and fix accordingly. stubscflags = $(cflags) $(PKGNAMEFLAGS) $(PRJ_DEFINES) $(OPTDEFINES) /Zl /GL- /DSTATIC_BUILD $(INCLUDES) $(USE_STUBS_DEFS) # Link flags !if $(DEBUG) ldebug = -debug -debugtype:cv !else ldebug = -release -opt:ref -opt:icf,3 !if $(SYMBOLS) ldebug = $(ldebug) -debug -debugtype:cv !endif !endif # Note: Profiling is currently only possible with the Visual Studio Enterprise !if $(PROFILE) ldebug= $(ldebug) -profile !endif ### Declarations common to all linker versions lflags = -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug) !if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900 lflags = $(lflags) -nodefaultlib:libucrt.lib !endif dlllflags = $(lflags) -dll conlflags = $(lflags) -subsystem:console guilflags = $(lflags) -subsystem:windows # Libraries that are required for every image. # Extensions should define any additional libraries with $(PRJ_LIBS) winlibs = kernel32.lib advapi32.lib !if $(NEED_TK) winlibs = $(winlibs) gdi32.lib user32.lib uxtheme.lib !endif # Avoid 'unresolved external symbol __security_cookie' errors. # c.f. http://support.microsoft.com/?id=894573 !if "$(MACHINE)" == "AMD64" !if $(VCVERSION) > 1399 && $(VCVERSION) < 1500 winlibs = $(winlibs) bufferoverflowU.lib !endif !endif baselibs = $(winlibs) $(PRJ_LIBS) !if $(MSVCRT) && !($(DEBUG) && !$(UNCHECKED)) && $(VCVERSION) >= 1900 baselibs = $(baselibs) ucrt.lib !endif ################################################################ # 13. Define standard commands, common make targets and implicit rules CCPKGCMD = $(cc32) $(pkgcflags) -Fo$(TMP_DIR)^\ CCAPPCMD = $(cc32) $(appcflags) -Fo$(TMP_DIR)^\ CCSTUBSCMD = $(cc32) $(stubscflags) -Fo$(TMP_DIR)^\ LIBCMD = $(lib32) -nologo $(LINKERFLAGS) -out:$@ DLLCMD = $(link32) $(dlllflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs) CONEXECMD = $(link32) $(conlflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs) GUIEXECMD = $(link32) $(guilflags) -out:$@ $(baselibs) $(tcllibs) $(tklibs) RESCMD = $(rc32) -fo $@ -r -i "$(GENERICDIR)" -i "$(TMP_DIR)" \ $(TCL_INCLUDES) \ /DDEBUG=$(DEBUG) -d UNCHECKED=$(UNCHECKED) \ /DCOMMAVERSION=$(RCCOMMAVERSION) \ /DDOTVERSION=\"$(DOTVERSION)\" \ /DVERSION=\"$(VERSION)\" \ /DSUFX=\"$(SUFX)\" \ /DPROJECT=\"$(PROJECT)\" \ /DPRJLIBNAME=\"$(PRJLIBNAME)\" !ifndef DEFAULT_BUILD_TARGET DEFAULT_BUILD_TARGET = $(PROJECT) !endif default-target: $(DEFAULT_BUILD_TARGET) !if $(MULTIPLATFORM_INSTALL) default-pkgindex: @echo if {[package vsatisfies [package provide Tcl] 9.0-]} { > $(OUT_DIR)\pkgIndex.tcl @echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \ [list load [file join $$dir $(PLATFORM_IDENTIFY) $(PRJLIBNAME9)]] >> $(OUT_DIR)\pkgIndex.tcl @echo } else { >> $(OUT_DIR)\pkgIndex.tcl @echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \ [list load [file join $$dir $(PLATFORM_IDENTIFY) $(PRJLIBNAME8)]] >> $(OUT_DIR)\pkgIndex.tcl @echo } >> $(OUT_DIR)\pkgIndex.tcl !else default-pkgindex: @echo if {[package vsatisfies [package provide Tcl] 9.0-]} { > $(OUT_DIR)\pkgIndex.tcl @echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \ [list load [file join $$dir $(PRJLIBNAME9)]] >> $(OUT_DIR)\pkgIndex.tcl @echo } else { >> $(OUT_DIR)\pkgIndex.tcl @echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \ [list load [file join $$dir $(PRJLIBNAME8)]] >> $(OUT_DIR)\pkgIndex.tcl @echo } >> $(OUT_DIR)\pkgIndex.tcl !endif default-pkgindex-tea: @if exist $(ROOT)\pkgIndex.tcl.in nmakehlp -s << $(ROOT)\pkgIndex.tcl.in > $(OUT_DIR)\pkgIndex.tcl @PACKAGE_VERSION@ $(DOTVERSION) @PACKAGE_NAME@ $(PRJ_PACKAGE_TCLNAME) @PACKAGE_TCLNAME@ $(PRJ_PACKAGE_TCLNAME) @PKG_LIB_FILE@ $(PRJLIBNAME) @PKG_LIB_FILE8@ $(PRJLIBNAME8) @PKG_LIB_FILE9@ $(PRJLIBNAME9) << default-install: default-install-binaries default-install-libraries !if $(SYMBOLS) default-install: default-install-pdbs !endif # Again to deal with historical brokenness, there is some confusion # in terminlogy. For extensions, the "install-binaries" was used to # locate target directory for *binary shared libraries* and thus # the appropriate macro is LIB_INSTALL_DIR since BIN_INSTALL_DIR is # for executables (exes). On the other hand the "install-libraries" # target is for *scripts* and should have been called "install-scripts". default-install-binaries: $(PRJLIB) @echo Installing binaries to '$(LIB_INSTALL_DIR)' @if not exist "$(LIB_INSTALL_DIR)" mkdir "$(LIB_INSTALL_DIR)" @$(CPY) $(PRJLIB) "$(LIB_INSTALL_DIR)" >NUL # Alias for default-install-scripts default-install-libraries: default-install-scripts default-install-scripts: $(OUT_DIR)\pkgIndex.tcl @echo Installing libraries to '$(SCRIPT_INSTALL_DIR)' @if exist $(LIBDIR) $(CPY) $(LIBDIR)\*.tcl "$(SCRIPT_INSTALL_DIR)" @echo Installing package index in '$(SCRIPT_INSTALL_DIR)' @$(CPY) $(OUT_DIR)\pkgIndex.tcl $(SCRIPT_INSTALL_DIR) default-install-stubs: @echo Installing stubs library to '$(SCRIPT_INSTALL_DIR)' @if not exist "$(SCRIPT_INSTALL_DIR)" mkdir "$(SCRIPT_INSTALL_DIR)" @$(CPY) $(PRJSTUBLIB) "$(SCRIPT_INSTALL_DIR)" >NUL default-install-pdbs: @echo Installing PDBs to '$(LIB_INSTALL_DIR)' @if not exist "$(LIB_INSTALL_DIR)" mkdir "$(LIB_INSTALL_DIR)" @$(CPY) "$(OUT_DIR)\*.pdb" "$(LIB_INSTALL_DIR)\" # "emacs font-lock highlighting fix default-install-docs-html: @echo Installing documentation files to '$(DOC_INSTALL_DIR)' @if not exist "$(DOC_INSTALL_DIR)" mkdir "$(DOC_INSTALL_DIR)" @if exist $(DOCDIR) for %f in ("$(DOCDIR)\*.html" "$(DOCDIR)\*.css" "$(DOCDIR)\*.png") do @$(COPY) %f "$(DOC_INSTALL_DIR)" default-install-docs-n: @echo Installing documentation files to '$(DOC_INSTALL_DIR)' @if not exist "$(DOC_INSTALL_DIR)" mkdir "$(DOC_INSTALL_DIR)" @if exist $(DOCDIR) for %f in ("$(DOCDIR)\*.n") do @$(COPY) %f "$(DOC_INSTALL_DIR)" default-install-demos: @echo Installing demos to '$(DEMO_INSTALL_DIR)' @if not exist "$(DEMO_INSTALL_DIR)" mkdir "$(DEMO_INSTALL_DIR)" @if exist $(DEMODIR) $(CPYDIR) "$(DEMODIR)" "$(DEMO_INSTALL_DIR)" default-clean: @echo Cleaning $(TMP_DIR)\* ... @if exist $(TMP_DIR)\nul $(RMDIR) $(TMP_DIR) @echo Cleaning $(WIN_DIR)\nmakehlp.obj, nmakehlp.exe ... @if exist $(WIN_DIR)\nmakehlp.obj del $(WIN_DIR)\nmakehlp.obj @if exist $(WIN_DIR)\nmakehlp.exe del $(WIN_DIR)\nmakehlp.exe @if exist $(WIN_DIR)\nmakehlp.out del $(WIN_DIR)\nmakehlp.out @echo Cleaning $(WIN_DIR)\nmhlp-out.txt ... @if exist $(WIN_DIR)\nmhlp-out.txt del $(WIN_DIR)\nmhlp-out.txt @echo Cleaning $(WIN_DIR)\_junk.pch ... @if exist $(WIN_DIR)\_junk.pch del $(WIN_DIR)\_junk.pch @echo Cleaning $(WIN_DIR)\vercl.x, vercl.i ... @if exist $(WIN_DIR)\vercl.x del $(WIN_DIR)\vercl.x @if exist $(WIN_DIR)\vercl.i del $(WIN_DIR)\vercl.i @echo Cleaning $(WIN_DIR)\versions.vc, version.vc ... @if exist $(WIN_DIR)\versions.vc del $(WIN_DIR)\versions.vc @if exist $(WIN_DIR)\version.vc del $(WIN_DIR)\version.vc default-hose: default-clean @echo Hosing $(OUT_DIR)\* ... @if exist $(OUT_DIR)\nul $(RMDIR) $(OUT_DIR) # Only for backward compatibility default-distclean: default-hose default-setup: @if not exist $(OUT_DIR)\nul mkdir $(OUT_DIR) @if not exist $(TMP_DIR)\nul mkdir $(TMP_DIR) !if "$(TESTPAT)" != "" TESTFLAGS = $(TESTFLAGS) -file $(TESTPAT) !endif default-test: default-setup $(PROJECT) @set TCLLIBPATH=$(OUT_DIR:\=/) @if exist $(LIBDIR) for %f in ("$(LIBDIR)\*.tcl") do @$(COPY) %f "$(OUT_DIR)" cd "$(TESTDIR)" && $(DEBUGGER) $(TCLSH) all.tcl $(TESTFLAGS) default-shell: default-setup $(PROJECT) @set TCLLIBPATH=$(OUT_DIR:\=/) @if exist $(LIBDIR) for %f in ("$(LIBDIR)\*.tcl") do @$(COPY) %f "$(OUT_DIR)" $(DEBUGGER) $(TCLSH) # Generation of Windows version resource !ifdef RCFILE # Note: don't use $** in below rule because there may be other dependencies # and only the "main" rc must be passed to the resource compiler $(TMP_DIR)\$(PROJECT).res: $(RCDIR)\$(PROJECT).rc $(RESCMD) $(RCDIR)\$(PROJECT).rc !else # If parent makefile has not defined a resource definition file, # we will generate one from standard template. $(TMP_DIR)\$(PROJECT).res: $(TMP_DIR)\$(PROJECT).rc $(TMP_DIR)\$(PROJECT).rc: @$(COPY) << $(TMP_DIR)\$(PROJECT).rc #include VS_VERSION_INFO VERSIONINFO FILEVERSION COMMAVERSION PRODUCTVERSION COMMAVERSION FILEFLAGSMASK 0x3fL #ifdef DEBUG FILEFLAGS VS_FF_DEBUG #else FILEFLAGS 0x0L #endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "Tcl extension " PROJECT VALUE "OriginalFilename", PRJLIBNAME VALUE "FileVersion", DOTVERSION VALUE "ProductName", "Package " PROJECT " for Tcl" VALUE "ProductVersion", DOTVERSION END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END << !endif # ifdef RCFILE !ifndef DISABLE_IMPLICIT_RULES DISABLE_IMPLICIT_RULES = 0 !endif !if !$(DISABLE_IMPLICIT_RULES) # Implicit rule definitions - only for building library objects. For stubs and # main application, the makefile should define explicit rules. {$(ROOT)}.c{$(TMP_DIR)}.obj:: $(CCPKGCMD) @<< $< << {$(WIN_DIR)}.c{$(TMP_DIR)}.obj:: $(CCPKGCMD) @<< $< << {$(GENERICDIR)}.c{$(TMP_DIR)}.obj:: $(CCPKGCMD) @<< $< << {$(COMPATDIR)}.c{$(TMP_DIR)}.obj:: $(CCPKGCMD) @<< $< << {$(RCDIR)}.rc{$(TMP_DIR)}.res: $(RESCMD) $< {$(WIN_DIR)}.rc{$(TMP_DIR)}.res: $(RESCMD) $< {$(TMP_DIR)}.rc{$(TMP_DIR)}.res: $(RESCMD) $< .SUFFIXES: .SUFFIXES:.c .rc !endif ################################################################ # 14. Sanity check selected options against Tcl build options # When building an extension, certain configuration options should # match the ones used when Tcl was built. Here we check and # warn on a mismatch. !if !$(DOING_TCL) !if $(TCLINSTALL) # Building against an installed Tcl !if exist("$(_TCLDIR)\lib\nmake\tcl.nmake") TCLNMAKECONFIG = "$(_TCLDIR)\lib\nmake\tcl.nmake" !endif !else # !$(TCLINSTALL) - building against Tcl source !if exist("$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl.nmake") TCLNMAKECONFIG = "$(_TCLDIR)\win\$(BUILDDIRTOP)\tcl.nmake" !endif !endif # TCLINSTALL !if $(CONFIG_CHECK) !ifdef TCLNMAKECONFIG !include $(TCLNMAKECONFIG) !if defined(CORE_MACHINE) && "$(CORE_MACHINE)" != "$(MACHINE)" !error ERROR: Build target ($(MACHINE)) does not match the Tcl library architecture ($(CORE_MACHINE)). !endif !if $(TCL_VERSION) < 87 && defined(CORE_USE_THREAD_ALLOC) && $(CORE_USE_THREAD_ALLOC) != $(USE_THREAD_ALLOC) !message WARNING: Value of USE_THREAD_ALLOC ($(USE_THREAD_ALLOC)) does not match its Tcl core value ($(CORE_USE_THREAD_ALLOC)). !endif !if defined(CORE_DEBUG) && $(CORE_DEBUG) != $(DEBUG) !message WARNING: Value of DEBUG ($(DEBUG)) does not match its Tcl library configuration ($(DEBUG)). !endif !endif !endif # TCLNMAKECONFIG !endif # !$(DOING_TCL) #---------------------------------------------------------- # Display stats being used. #---------------------------------------------------------- !if !$(DOING_TCL) !message *** Building against Tcl at '$(_TCLDIR)' !endif !if !$(DOING_TK) && $(NEED_TK) !message *** Building against Tk at '$(_TKDIR)' !endif !message *** Intermediate directory will be '$(TMP_DIR)' !message *** Output directory will be '$(OUT_DIR)' !message *** Installation, if selected, will be in '$(_INSTALLDIR)' !message *** Suffix for binaries will be '$(SUFX)' !message *** Compiler version $(VCVER). Target $(MACHINE), host $(NATIVE_ARCH). !endif # ifdef _RULES_VC tdom-0.9.5-src/extensions/tnc/win/makefile.vc0000644000175000017500000000267114703531020017633 0ustar rolfrolf#------------------------------------------------------------- -*- makefile -*- # # Makefile for tnc # # Basic build, test and install # nmake /f makefile.vc INSTALLDIR=c:\tcl # nmake /f makefile.vc INSTALLDIR=c:\tcl test # nmake /f makefile.vc INSTALLDIR=c:\tcl install # # For other build options (debug, static etc.), # See TIP 477 (https://core.tcl.tk/tips/doc/trunk/tip/477.md) for # detailed documentation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # #------------------------------------------------------------------------------ PROJECT = tnc !include "rules-ext.vc" PRJ_OBJS = $(TMP_DIR)\tnc.obj !if [echo TDOM_DOTVERSION = \> versions.vc] \ || [nmakehlp -V ..\..\..\configure.ac ^[tdom^] >> versions.vc] !error *** Could not figure out tdom version. !endif !include versions.vc TDOMVER = $(TDOM_DOTVERSION:.=) # tdom root TDOMROOT = ..\..\.. PRJ_DEFINES = -D _CRT_SECURE_NO_DEPRECATE -D _CRT_NONSTDC_NO_DEPRECATE \ -DHAVE_MEMMOVE=1 -DXML_DTD=1 -DXML_NS=1 -DTDOM_NO_UNKNOWN_CMD=1 \ !if !$(STATIC_BUILD) -DUSE_TDOM_STUBS !endif TDOMLIBPATH = "$(TDOMROOT)\win\$(BUILDDIRTOP)" PRJ_INCLUDES = -I$(TDOMROOT)\generic -I$(TDOMROOT)\expat TNCDIR = $(TDOMROOT)\extensions\tnc !if !$(STATIC_BUILD) PRJ_LIBS = $(TDOMLIBPATH)\tdomstub$(TDOMVER).lib !endif !include "$(_RULESDIR)\targets.vc" pkgindex: default-pkgindex tdom-0.9.5-src/extensions/tnc/win/nmakehlp.c0000644000175000017500000005127514703531020017473 0ustar rolfrolf/* * ---------------------------------------------------------------------------- * nmakehlp.c -- * * This is used to fix limitations within nmake and the environment. * * Copyright (c) 2002 by David Gravereaux. * Copyright (c) 2006 by Pat Thoyts * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * ---------------------------------------------------------------------------- */ #define _CRT_SECURE_NO_DEPRECATE #include #define NO_SHLWAPI_GDI #define NO_SHLWAPI_STREAM #define NO_SHLWAPI_REG #include #pragma comment (lib, "user32.lib") #pragma comment (lib, "kernel32.lib") #pragma comment (lib, "shlwapi.lib") #include #include /* * This library is required for x64 builds with _some_ versions of MSVC */ #if defined(_M_IA64) || defined(_M_AMD64) #if _MSC_VER >= 1400 && _MSC_VER < 1500 #pragma comment(lib, "bufferoverflowU") #endif #endif /* ISO hack for dumb VC++ */ #ifdef _MSC_VER #define snprintf _snprintf #endif /* protos */ static int CheckForCompilerFeature(const char *option); static int CheckForLinkerFeature(const char **options, int count); static int IsIn(const char *string, const char *substring); static int SubstituteFile(const char *substs, const char *filename); static int QualifyPath(const char *path); static int LocateDependency(const char *keyfile); static const char *GetVersionFromFile(const char *filename, const char *match, int numdots); static DWORD WINAPI ReadFromPipe(LPVOID args); /* globals */ #define CHUNK 25 #define STATICBUFFERSIZE 1000 typedef struct { HANDLE pipe; char buffer[STATICBUFFERSIZE]; } pipeinfo; pipeinfo Out = {INVALID_HANDLE_VALUE, '\0'}; pipeinfo Err = {INVALID_HANDLE_VALUE, '\0'}; /* * exitcodes: 0 == no, 1 == yes, 2 == error */ int main( int argc, char *argv[]) { char msg[300]; DWORD dwWritten; int chars; char *s; /* * Make sure children (cl.exe and link.exe) are kept quiet. */ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); /* * Make sure the compiler and linker aren't effected by the outside world. */ SetEnvironmentVariable("CL", ""); SetEnvironmentVariable("LINK", ""); if (argc > 1 && *argv[1] == '-') { switch (*(argv[1]+1)) { case 'c': if (argc != 3) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -c \n" "Tests for whether cl.exe supports an option\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return CheckForCompilerFeature(argv[2]); case 'l': if (argc < 3) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -l ? ...?\n" "Tests for whether link.exe supports an option\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return CheckForLinkerFeature(&argv[2], argc-2); case 'f': if (argc == 2) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -f \n" "Find a substring within another\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } else if (argc == 3) { /* * If the string is blank, there is no match. */ return 0; } else { return IsIn(argv[2], argv[3]); } case 's': if (argc == 2) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -s \n" "Perform a set of string map type substutitions on a file\n" "exitcodes: 0\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return SubstituteFile(argv[2], argv[3]); case 'V': if (argc != 4) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -V filename matchstring\n" "Extract a version from a file:\n" "eg: pkgIndex.tcl \"package ifneeded http\"", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 0; } s = GetVersionFromFile(argv[2], argv[3], *(argv[1]+2) - '0'); if (s && *s) { printf("%s\n", s); return 0; } else return 1; /* Version not found. Return non-0 exit code */ case 'Q': if (argc != 3) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -Q path\n" "Emit the fully qualified path\n" "exitcodes: 0 == no, 1 == yes, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return QualifyPath(argv[2]); case 'L': if (argc != 3) { chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -L keypath\n" "Emit the fully qualified path of directory containing keypath\n" "exitcodes: 0 == success, 1 == not found, 2 == error\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } return LocateDependency(argv[2]); } } chars = snprintf(msg, sizeof(msg) - 1, "usage: %s -c|-f|-l|-Q|-s|-V ...\n" "This is a little helper app to equalize shell differences between WinNT and\n" "Win9x and get nmake.exe to accomplish its job.\n", argv[0]); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, chars, &dwWritten, NULL); return 2; } static int CheckForCompilerFeature( const char *option) { STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; DWORD threadID; char msg[300]; BOOL ok; HANDLE hProcess, h, pipeThreads[2]; char cmdline[100]; hProcess = GetCurrentProcess(); ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = INVALID_HANDLE_VALUE; ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = FALSE; /* * Create a non-inheritible pipe. */ CreatePipe(&Out.pipe, &h, &sa, 0); /* * Dupe the write side, make it inheritible, and close the original. */ DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); /* * Same as above, but for the error side. */ CreatePipe(&Err.pipe, &h, &sa, 0); DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); /* * Base command line. */ lstrcpy(cmdline, "cl.exe -nologo -c -TC -Zs -X -Fp.\\_junk.pch "); /* * Append our option for testing */ lstrcat(cmdline, option); /* * Filename to compile, which exists, but is nothing and empty. */ lstrcat(cmdline, " .\\nul"); ok = CreateProcess( NULL, /* Module name. */ cmdline, /* Command line. */ NULL, /* Process handle not inheritable. */ NULL, /* Thread handle not inheritable. */ TRUE, /* yes, inherit handles. */ DETACHED_PROCESS, /* No console for you. */ NULL, /* Use parent's environment block. */ NULL, /* Use parent's starting directory. */ &si, /* Pointer to STARTUPINFO structure. */ &pi); /* Pointer to PROCESS_INFORMATION structure. */ if (!ok) { DWORD err = GetLastError(); int chars = snprintf(msg, sizeof(msg) - 1, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars], (300-chars), 0); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL); return 2; } /* * Close our references to the write handles that have now been inherited. */ CloseHandle(si.hStdOutput); CloseHandle(si.hStdError); WaitForInputIdle(pi.hProcess, 5000); CloseHandle(pi.hThread); /* * Start the pipe reader threads. */ pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID); pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID); /* * Block waiting for the process to end. */ WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); /* * Wait for our pipe to get done reading, should it be a little slow. */ WaitForMultipleObjects(2, pipeThreads, TRUE, 500); CloseHandle(pipeThreads[0]); CloseHandle(pipeThreads[1]); /* * Look for the commandline warning code in both streams. * - in MSVC 6 & 7 we get D4002, in MSVC 8 we get D9002. */ return !(strstr(Out.buffer, "D4002") != NULL || strstr(Err.buffer, "D4002") != NULL || strstr(Out.buffer, "D9002") != NULL || strstr(Err.buffer, "D9002") != NULL || strstr(Out.buffer, "D2021") != NULL || strstr(Err.buffer, "D2021") != NULL); } static int CheckForLinkerFeature( const char **options, int count) { STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; DWORD threadID; char msg[300]; BOOL ok; HANDLE hProcess, h, pipeThreads[2]; int i; char cmdline[255]; hProcess = GetCurrentProcess(); ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = INVALID_HANDLE_VALUE; ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* * Create a non-inheritible pipe. */ CreatePipe(&Out.pipe, &h, &sa, 0); /* * Dupe the write side, make it inheritible, and close the original. */ DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); /* * Same as above, but for the error side. */ CreatePipe(&Err.pipe, &h, &sa, 0); DuplicateHandle(hProcess, h, hProcess, &si.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); /* * Base command line. */ lstrcpy(cmdline, "link.exe -nologo "); /* * Append our option for testing. */ for (i = 0; i < count; i++) { lstrcat(cmdline, " \""); lstrcat(cmdline, options[i]); lstrcat(cmdline, "\""); } ok = CreateProcess( NULL, /* Module name. */ cmdline, /* Command line. */ NULL, /* Process handle not inheritable. */ NULL, /* Thread handle not inheritable. */ TRUE, /* yes, inherit handles. */ DETACHED_PROCESS, /* No console for you. */ NULL, /* Use parent's environment block. */ NULL, /* Use parent's starting directory. */ &si, /* Pointer to STARTUPINFO structure. */ &pi); /* Pointer to PROCESS_INFORMATION structure. */ if (!ok) { DWORD err = GetLastError(); int chars = snprintf(msg, sizeof(msg) - 1, "Tried to launch: \"%s\", but got error [%u]: ", cmdline, err); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS| FORMAT_MESSAGE_MAX_WIDTH_MASK, 0L, err, 0, (LPVOID)&msg[chars], (300-chars), 0); WriteFile(GetStdHandle(STD_ERROR_HANDLE), msg, lstrlen(msg), &err,NULL); return 2; } /* * Close our references to the write handles that have now been inherited. */ CloseHandle(si.hStdOutput); CloseHandle(si.hStdError); WaitForInputIdle(pi.hProcess, 5000); CloseHandle(pi.hThread); /* * Start the pipe reader threads. */ pipeThreads[0] = CreateThread(NULL, 0, ReadFromPipe, &Out, 0, &threadID); pipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &Err, 0, &threadID); /* * Block waiting for the process to end. */ WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); /* * Wait for our pipe to get done reading, should it be a little slow. */ WaitForMultipleObjects(2, pipeThreads, TRUE, 500); CloseHandle(pipeThreads[0]); CloseHandle(pipeThreads[1]); /* * Look for the commandline warning code in the stderr stream. */ return !(strstr(Out.buffer, "LNK1117") != NULL || strstr(Err.buffer, "LNK1117") != NULL || strstr(Out.buffer, "LNK4044") != NULL || strstr(Err.buffer, "LNK4044") != NULL || strstr(Out.buffer, "LNK4224") != NULL || strstr(Err.buffer, "LNK4224") != NULL); } static DWORD WINAPI ReadFromPipe( LPVOID args) { pipeinfo *pi = (pipeinfo *) args; char *lastBuf = pi->buffer; DWORD dwRead; BOOL ok; again: if (lastBuf - pi->buffer + CHUNK > STATICBUFFERSIZE) { CloseHandle(pi->pipe); return (DWORD)-1; } ok = ReadFile(pi->pipe, lastBuf, CHUNK, &dwRead, 0L); if (!ok || dwRead == 0) { CloseHandle(pi->pipe); return 0; } lastBuf += dwRead; goto again; return 0; /* makes the compiler happy */ } static int IsIn( const char *string, const char *substring) { return (strstr(string, substring) != NULL); } /* * GetVersionFromFile -- * Looks for a match string in a file and then returns the version * following the match where a version is anything acceptable to * package provide or package ifneeded. */ static const char * GetVersionFromFile( const char *filename, const char *match, int numdots) { size_t cbBuffer = 100; static char szBuffer[100]; char *szResult = NULL; FILE *fp = fopen(filename, "rt"); if (fp != NULL) { /* * Read data until we see our match string. */ while (fgets(szBuffer, cbBuffer, fp) != NULL) { LPSTR p, q; p = strstr(szBuffer, match); if (p != NULL) { /* * Skip to first digit after the match. */ p += strlen(match); while (*p && !isdigit(*p)) { ++p; } /* * Find ending whitespace. */ q = p; while (*q && (strchr("0123456789.ab", *q)) && ((!strchr(".ab", *q) && (!strchr("ab", q[-1])) || --numdots))) { ++q; } memcpy(szBuffer, p, q - p); szBuffer[q-p] = 0; szResult = szBuffer; break; } } fclose(fp); } return szResult; } /* * List helpers for the SubstituteFile function */ typedef struct list_item_t { struct list_item_t *nextPtr; char * key; char * value; } list_item_t; /* insert a list item into the list (list may be null) */ static list_item_t * list_insert(list_item_t **listPtrPtr, const char *key, const char *value) { list_item_t *itemPtr = malloc(sizeof(list_item_t)); if (itemPtr) { itemPtr->key = strdup(key); itemPtr->value = strdup(value); itemPtr->nextPtr = NULL; while(*listPtrPtr) { listPtrPtr = &(*listPtrPtr)->nextPtr; } *listPtrPtr = itemPtr; } return itemPtr; } static void list_free(list_item_t **listPtrPtr) { list_item_t *tmpPtr, *listPtr = *listPtrPtr; while (listPtr) { tmpPtr = listPtr; listPtr = listPtr->nextPtr; free(tmpPtr->key); free(tmpPtr->value); free(tmpPtr); } } /* * SubstituteFile -- * As windows doesn't provide anything useful like sed and it's unreliable * to use the tclsh you are building against (consider x-platform builds - * eg compiling AMD64 target from IX86) we provide a simple substitution * option here to handle autoconf style substitutions. * The substitution file is whitespace and line delimited. The file should * consist of lines matching the regular expression: * \s*\S+\s+\S*$ * * Usage is something like: * nmakehlp -S << $** > $@ * @PACKAGE_NAME@ $(PACKAGE_NAME) * @PACKAGE_VERSION@ $(PACKAGE_VERSION) * << */ static int SubstituteFile( const char *substitutions, const char *filename) { size_t cbBuffer = 1024; static char szBuffer[1024], szCopy[1024]; char *szResult = NULL; list_item_t *substPtr = NULL; FILE *fp, *sp; fp = fopen(filename, "rt"); if (fp != NULL) { /* * Build a list of substutitions from the first filename */ sp = fopen(substitutions, "rt"); if (sp != NULL) { while (fgets(szBuffer, cbBuffer, sp) != NULL) { unsigned char *ks, *ke, *vs, *ve; ks = (unsigned char*)szBuffer; while (ks && *ks && isspace(*ks)) ++ks; ke = ks; while (ke && *ke && !isspace(*ke)) ++ke; vs = ke; while (vs && *vs && isspace(*vs)) ++vs; ve = vs; while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve; *ke = 0, *ve = 0; list_insert(&substPtr, (char*)ks, (char*)vs); } fclose(sp); } /* debug: dump the list */ #ifdef _DEBUG { int n = 0; list_item_t *p = NULL; for (p = substPtr; p != NULL; p = p->nextPtr, ++n) { fprintf(stderr, "% 3d '%s' => '%s'\n", n, p->key, p->value); } } #endif /* * Run the substitutions over each line of the input */ while (fgets(szBuffer, cbBuffer, fp) != NULL) { list_item_t *p = NULL; for (p = substPtr; p != NULL; p = p->nextPtr) { char *m = strstr(szBuffer, p->key); if (m) { char *cp, *op, *sp; cp = szCopy; op = szBuffer; while (op != m) *cp++ = *op++; sp = p->value; while (sp && *sp) *cp++ = *sp++; op += strlen(p->key); while (*op) *cp++ = *op++; *cp = 0; memcpy(szBuffer, szCopy, sizeof(szCopy)); } } printf(szBuffer); } list_free(&substPtr); } fclose(fp); return 0; } /* * QualifyPath -- * * This composes the current working directory with a provided path * and returns the fully qualified and normalized path. * Mostly needed to setup paths for testing. */ static int QualifyPath( const char *szPath) { char szCwd[MAX_PATH + 1]; char szTmp[MAX_PATH + 1]; char *p; GetCurrentDirectory(MAX_PATH, szCwd); while ((p = strchr(szPath, '/')) && *p) *p = '\\'; PathCombine(szTmp, szCwd, szPath); PathCanonicalize(szCwd, szTmp); printf("%s\n", szCwd); return 0; } /* * Implements LocateDependency for a single directory. See that command * for an explanation. * Returns 0 if found after printing the directory. * Returns 1 if not found but no errors. * Returns 2 on any kind of error * Basically, these are used as exit codes for the process. */ static int LocateDependencyHelper(const char *dir, const char *keypath) { HANDLE hSearch; char path[MAX_PATH+1]; int dirlen, keylen, ret; WIN32_FIND_DATA finfo; if (dir == NULL || keypath == NULL) return 2; /* Have no real error reporting mechanism into nmake */ dirlen = strlen(dir); if ((dirlen + 3) > sizeof(path)) return 2; strncpy(path, dir, dirlen); strncpy(path+dirlen, "\\*", 3); /* Including terminating \0 */ keylen = strlen(keypath); #if 0 /* This function is not available in Visual C++ 6 */ /* * Use numerics 0 -> FindExInfoStandard, * 1 -> FindExSearchLimitToDirectories, * as these are not defined in Visual C++ 6 */ hSearch = FindFirstFileEx(path, 0, &finfo, 1, NULL, 0); #else hSearch = FindFirstFile(path, &finfo); #endif if (hSearch == INVALID_HANDLE_VALUE) return 1; /* Not found */ /* Loop through all subdirs checking if the keypath is under there */ ret = 1; /* Assume not found */ do { int sublen; /* * We need to check it is a directory despite the * FindExSearchLimitToDirectories in the above call. See SDK docs */ if ((finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) continue; sublen = strlen(finfo.cFileName); if ((dirlen+1+sublen+1+keylen+1) > sizeof(path)) continue; /* Path does not fit, assume not matched */ strncpy(path+dirlen+1, finfo.cFileName, sublen); path[dirlen+1+sublen] = '\\'; strncpy(path+dirlen+1+sublen+1, keypath, keylen+1); if (PathFileExists(path)) { /* Found a match, print to stdout */ path[dirlen+1+sublen] = '\0'; QualifyPath(path); ret = 0; break; } } while (FindNextFile(hSearch, &finfo)); FindClose(hSearch); return ret; } /* * LocateDependency -- * * Locates a dependency for a package. * keypath - a relative path within the package directory * that is used to confirm it is the correct directory. * The search path for the package directory is currently only * the parent and grandparent of the current working directory. * If found, the command prints * name_DIRPATH= * and returns 0. If not found, does not print anything and returns 1. */ static int LocateDependency(const char *keypath) { int i, ret; static char *paths[] = {"..", "..\\..", "..\\..\\.."}; for (i = 0; i < (sizeof(paths)/sizeof(paths[0])); ++i) { ret = LocateDependencyHelper(paths[i], keypath); if (ret == 0) return ret; } return ret; } /* * Local variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * indent-tabs-mode: t * tab-width: 8 * End: */ tdom-0.9.5-src/extensions/tnc/win/targets.vc0000644000175000017500000000505614703531020017527 0ustar rolfrolf#------------------------------------------------------------- -*- makefile -*- # targets.vc -- # # Part of the nmake based build system for Tcl and its extensions. # This file defines some standard targets for the convenience of extensions # and can be optionally included by the extension makefile. # See TIP 477 (https://core.tcl-lang.org/tips/doc/main/tip/477.md) for docs. $(PROJECT): setup pkgindex $(PRJLIB) !ifdef PRJ_STUBOBJS $(PROJECT): $(PRJSTUBLIB) $(PRJSTUBLIB): $(PRJ_STUBOBJS) $(LIBCMD) $** $(PRJ_STUBOBJS): $(CCSTUBSCMD) %s !endif # PRJ_STUBOBJS !ifdef PRJ_MANIFEST $(PROJECT): $(PRJLIB).manifest $(PRJLIB).manifest: $(PRJ_MANIFEST) @nmakehlp -s << $** >$@ @MACHINE@ $(MACHINE:IX86=X86) << !endif !if "$(PROJECT)" != "tcl" && "$(PROJECT)" != "tk" $(PRJLIB): $(PRJ_OBJS) $(RESFILE) !if $(STATIC_BUILD) $(LIBCMD) $** !else $(DLLCMD) $** $(_VC_MANIFEST_EMBED_DLL) !endif -@del $*.exp !endif !if "$(PRJ_HEADERS)" != "" && "$(PRJ_OBJS)" != "" $(PRJ_OBJS): $(PRJ_HEADERS) !endif # If parent makefile has defined stub objects, add their installation # to the default install !if "$(PRJ_STUBOBJS)" != "" default-install: default-install-stubs !endif # Unlike the other default targets, these cannot be in rules.vc because # the executed command depends on existence of macro PRJ_HEADERS_PUBLIC # that the parent makefile will not define until after including rules-ext.vc !if "$(PRJ_HEADERS_PUBLIC)" != "" default-install: default-install-headers default-install-headers: @echo Installing headers to '$(INCLUDE_INSTALL_DIR)' @for %f in ($(PRJ_HEADERS_PUBLIC)) do @$(COPY) %f "$(INCLUDE_INSTALL_DIR)" !endif !if "$(DISABLE_STANDARD_TARGETS)" == "" DISABLE_STANDARD_TARGETS = 0 !endif !if "$(DISABLE_TARGET_setup)" == "" DISABLE_TARGET_setup = 0 !endif !if "$(DISABLE_TARGET_install)" == "" DISABLE_TARGET_install = 0 !endif !if "$(DISABLE_TARGET_clean)" == "" DISABLE_TARGET_clean = 0 !endif !if "$(DISABLE_TARGET_test)" == "" DISABLE_TARGET_test = 0 !endif !if "$(DISABLE_TARGET_shell)" == "" DISABLE_TARGET_shell = 0 !endif !if !$(DISABLE_STANDARD_TARGETS) !if !$(DISABLE_TARGET_setup) setup: default-setup !endif !if !$(DISABLE_TARGET_install) install: default-install !endif !if !$(DISABLE_TARGET_clean) clean: default-clean realclean: hose hose: default-hose distclean: realclean default-distclean !endif !if !$(DISABLE_TARGET_test) test: default-test !endif !if !$(DISABLE_TARGET_shell) shell: default-shell !endif !endif # DISABLE_STANDARD_TARGETS tdom-0.9.5-src/extensions/tnc/win/rules-ext.vc0000644000175000017500000000732414703531020020006 0ustar rolfrolf# This file should only be included in makefiles for Tcl extensions, # NOT in the makefile for Tcl itself. !ifndef _RULES_EXT_VC # We need to run from the directory the parent makefile is located in. # nmake does not tell us what makefile was used to invoke it so parent # makefile has to set the MAKEFILEVC macro or we just make a guess and # warn if we think that is not the case. !if "$(MAKEFILEVC)" == "" !if exist("$(PROJECT).vc") MAKEFILEVC = $(PROJECT).vc !elseif exist("makefile.vc") MAKEFILEVC = makefile.vc !endif !endif # "$(MAKEFILEVC)" == "" !if !exist("$(MAKEFILEVC)") MSG = ^ You must run nmake from the directory containing the project makefile.^ If you are doing that and getting this message, set the MAKEFILEVC^ macro to the name of the project makefile. !message WARNING: $(MSG) !endif !if "$(PROJECT)" == "tcl" !error The rules-ext.vc file is not intended for Tcl itself. !endif # We extract version numbers using the nmakehlp program. For now use # the local copy of nmakehlp. Once we locate Tcl, we will use that # one if it is newer. !if [$(CC) -nologo -DNDEBUG "nmakehlp.c" -link -subsystem:console > nul] !endif # First locate the Tcl directory that we are working with. !if "$(TCLDIR)" != "" _RULESDIR = $(TCLDIR:/=\) !else # If an installation path is specified, that is also the Tcl directory. # Also Tk never builds against an installed Tcl, it needs Tcl sources !if defined(INSTALLDIR) && "$(PROJECT)" != "tk" _RULESDIR=$(INSTALLDIR:/=\) !else # Locate Tcl sources !if [echo _RULESDIR = \> nmakehlp.out] \ || [nmakehlp -L generic\tcl.h >> nmakehlp.out] _RULESDIR = ..\..\tcl !else !include nmakehlp.out !endif !endif # defined(INSTALLDIR).... !endif # ifndef TCLDIR # Now look for the targets.vc file under the Tcl root. Note we check this # file and not rules.vc because the latter also exists on older systems. !if exist("$(_RULESDIR)\lib\nmake\targets.vc") # Building against installed Tcl _RULESDIR = $(_RULESDIR)\lib\nmake !elseif exist("$(_RULESDIR)\win\targets.vc") # Building against Tcl sources _RULESDIR = $(_RULESDIR)\win !else # If we have not located Tcl's targets file, most likely we are compiling # against an older version of Tcl and so must use our own support files. _RULESDIR = . !endif !if "$(_RULESDIR)" != "." # Potentially using Tcl's support files. If this extension has its own # nmake support files, need to compare the versions and pick newer. !if exist("rules.vc") # The extension has its own copy !if [echo TCL_RULES_MAJOR = \> versions.vc] \ && [nmakehlp -V "$(_RULESDIR)\rules.vc" RULES_VERSION_MAJOR >> versions.vc] !endif !if [echo TCL_RULES_MINOR = \>> versions.vc] \ && [nmakehlp -V "$(_RULESDIR)\rules.vc" RULES_VERSION_MINOR >> versions.vc] !endif !if [echo OUR_RULES_MAJOR = \>> versions.vc] \ && [nmakehlp -V "rules.vc" RULES_VERSION_MAJOR >> versions.vc] !endif !if [echo OUR_RULES_MINOR = \>> versions.vc] \ && [nmakehlp -V "rules.vc" RULES_VERSION_MINOR >> versions.vc] !endif !include versions.vc # We have a newer version of the support files, use them !if ($(TCL_RULES_MAJOR) != $(OUR_RULES_MAJOR)) || ($(TCL_RULES_MINOR) < $(OUR_RULES_MINOR)) _RULESDIR = . !endif !endif # if exist("rules.vc") !endif # if $(_RULESDIR) != "." # Let rules.vc know what copy of nmakehlp.c to use. NMAKEHLPC = $(_RULESDIR)\nmakehlp.c # Get rid of our internal defines before calling rules.vc !undef TCL_RULES_MAJOR !undef TCL_RULES_MINOR !undef OUR_RULES_MAJOR !undef OUR_RULES_MINOR !if exist("$(_RULESDIR)\rules.vc") !message *** Using $(_RULESDIR)\rules.vc !include "$(_RULESDIR)\rules.vc" !else !error *** Could not locate rules.vc in $(_RULESDIR) !endif !endif # _RULES_EXT_VCtdom-0.9.5-src/extensions/tnc/configure0000755000175000017500000101462214703531020016636 0ustar rolfrolf#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for tnc 0.3.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='tnc' PACKAGE_TARNAME='tnc' PACKAGE_VERSION='0.3.0' PACKAGE_STRING='tnc 0.3.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS TCLSH_PROG VC_MANIFEST_EMBED_EXE VC_MANIFEST_EMBED_DLL RANLIB_STUB PKG_STUB_LIB_FILE MAKE_STUB_LIB MAKE_STATIC_LIB MAKE_SHARED_LIB MAKE_LIB LDFLAGS_DEFAULT CFLAGS_DEFAULT LD_LIBRARY_PATH_VAR SHLIB_CFLAGS SHLIB_LD_LIBS SHLIB_LD STLIB_LD LDFLAGS_OPTIMIZE LDFLAGS_DEBUG CFLAGS_WARNING CFLAGS_OPTIMIZE CFLAGS_DEBUG LIBOBJS RC AR STUBS_BUILD SHARED_BUILD TCL_THREADS TCL_INCLUDES PKG_OBJECTS PKG_SOURCES TDOM_SRC_DIR TDOM_STUB_LIB_SPEC TDOM_VERSION EGREP GREP RANLIB SET_MAKE CPP TCL_SHLIB_LD_LIBS TCL_LD_FLAGS TCL_EXTRA_CFLAGS TCL_DEFS TCL_LIBS CLEANFILES OBJEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC TCL_STUB_LIB_SPEC TCL_STUB_LIB_FLAG TCL_STUB_LIB_FILE TCL_LIB_SPEC TCL_LIB_FLAG TCL_LIB_FILE TCL_SRC_DIR TCL_BIN_DIR TCL_PATCH_LEVEL TCL_VERSION INSTALL_LIBRARY INSTALL_SCRIPT INSTALL_PROGRAM INSTALL_DATA INSTALL_DATA_DIR INSTALL PKG_CFLAGS PKG_LIBS PKG_INCLUDES PKG_HEADERS PKG_TCL_SOURCES PKG_STUB_OBJECTS PKG_STUB_SOURCES PKG_LIB_FILE9 PKG_LIB_FILE8 PKG_LIB_FILE EXEEXT CYGPATH target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_tcl with_tcl8 with_tdom with_tclinclude enable_threads enable_shared enable_stubs enable_64bit enable_64bit_vis enable_rpath enable_symbols ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures tnc 0.3.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/tnc] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of tnc 0.3.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-threads build with threads (default: on) --enable-shared build and link with shared libraries (default: on) --enable-stubs build and link with stub libraries. Always true for shared builds (default: on) --enable-64bit enable 64bit support (default: off) --enable-64bit-vis enable 64bit Sparc VIS support (default: off) --disable-rpath disable rpath support (default: on) --enable-symbols build with debugging symbols (default: off) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-tcl directory containing tcl configuration (tclConfig.sh) --with-tcl8 Compile for Tcl8 in Tcl9 environment --with-tdom directory containing tDOM configuration (tdomConfig.sh) --with-tclinclude directory containing the public Tcl header files Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF tnc configure 0.3.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by tnc $as_me 0.3.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. #-------------------------------------------------------------------- TEA_VERSION="3.13" { $as_echo "$as_me:${as_lineno-$LINENO}: checking TEA configuration" >&5 $as_echo_n "checking TEA configuration... " >&6; } if test x"${PACKAGE_NAME}" = x ; then as_fn_error $? " The PACKAGE_NAME variable must be defined by your TEA configure.ac" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok (TEA ${TEA_VERSION})" >&5 $as_echo "ok (TEA ${TEA_VERSION})" >&6; } # If the user did not set CFLAGS, set it now to keep macros # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2". if test "${CFLAGS+set}" != "set" ; then CFLAGS="" fi case "`uname -s`" in *win32*|*WIN32*|*MINGW32_*|*MINGW64_*|*MSYS_*) # Extract the first word of "cygpath", so it can be a program name with args. set dummy cygpath; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CYGPATH+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CYGPATH"; then ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CYGPATH="cygpath -m" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" fi fi CYGPATH=$ac_cv_prog_CYGPATH if test -n "$CYGPATH"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 $as_echo "$CYGPATH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi EXEEXT=".exe" TEA_PLATFORM="windows" ;; *CYGWIN_*) EXEEXT=".exe" # CYGPATH and TEA_PLATFORM are determined later in LOAD_TCLCONFIG ;; *) CYGPATH=echo # Maybe we are cross-compiling.... case ${host_alias} in *mingw32*) EXEEXT=".exe" TEA_PLATFORM="windows" ;; *) EXEEXT="" TEA_PLATFORM="unix" ;; esac ;; esac # Check if exec_prefix is set. If not use fall back to prefix. # Note when adjusted, so that TEA_PREFIX can correct for this. # This is needed for recursive configures, since autoconf propagates # $prefix, but not $exec_prefix (doh!). if test x$exec_prefix = xNONE ; then exec_prefix_default=yes exec_prefix=$prefix fi { $as_echo "$as_me:${as_lineno-$LINENO}: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&5 $as_echo "$as_me: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&6;} # This package name must be replaced statically for AC_SUBST to work # We AC_SUBST these here to ensure they are subst'ed, # in case the user doesn't call TEA_ADD_... # Configure the installer. INSTALL='$(SHELL) $(srcdir)/tclconfig/install-sh -c' INSTALL_DATA_DIR='${INSTALL} -d -m 755' INSTALL_DATA='${INSTALL} -m 644' INSTALL_PROGRAM='${INSTALL} -m 755' INSTALL_SCRIPT='${INSTALL} -m 755' { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5 $as_echo_n "checking system version... " >&6; } if ${tcl_cv_sys_version+:} false; then : $as_echo_n "(cached) " >&6 else # TEA specific: if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 $as_echo "$as_me: WARNING: can't find uname command" >&2;} tcl_cv_sys_version=unknown else if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then tcl_cv_sys_version=NetBSD-Debian fi fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 $as_echo "$tcl_cv_sys_version" >&6; } system=$tcl_cv_sys_version case $system in HP-UX-*) INSTALL_LIBRARY='${INSTALL} -m 755' ;; *) INSTALL_LIBRARY='${INSTALL} -m 644' ;; esac ac_aux_dir= for ac_dir in ../../tclconfig "$srcdir"/../../tclconfig; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in ../../tclconfig \"$srcdir\"/../../tclconfig" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. #-------------------------------------------------------------------- # Load the tclConfig.sh file #-------------------------------------------------------------------- # # Ok, lets find the tcl configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tcl # if test x"${no_tcl}" = x ; then # we reset no_tcl in case something fails here no_tcl=true # Check whether --with-tcl was given. if test "${with_tcl+set}" = set; then : withval=$with_tcl; with_tclconfig="${withval}" fi # Check whether --with-tcl8 was given. if test "${with_tcl8+set}" = set; then : withval=$with_tcl8; with_tcl8="${withval}" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl configuration" >&5 $as_echo_n "checking for Tcl configuration... " >&6; } if ${ac_cv_c_tclconfig+:} false; then : $as_echo_n "(cached) " >&6 else # First check to see if --with-tcl was specified. if test x"${with_tclconfig}" != x ; then case "${with_tclconfig}" in */tclConfig.sh ) if test -f "${with_tclconfig}"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5 $as_echo "$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&2;} with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" fi ;; esac if test -f "${with_tclconfig}/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" else as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5 fi fi # then check for a private Tcl installation if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ../tcl \ `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \ ../../tcl \ `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \ ../../../tcl \ `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi # on Darwin, check in Framework installation locations if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ `ls -d /Library/Frameworks 2>/dev/null` \ `ls -d /Network/Library/Frameworks 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Network/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Tcl.framework 2>/dev/null` \ ; do if test -f "$i/Tcl.framework/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" break fi done fi # TEA specific: on Windows, check in common installation locations if test "${TEA_PLATFORM}" = "windows" \ -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d C:/Tcl/lib 2>/dev/null` \ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ `ls -d /usr/lib/tcl9.0 2>/dev/null` \ `ls -d /usr/lib/tcl8.7 2>/dev/null` \ `ls -d /usr/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl9.0 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.7 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl9.0 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.7 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ${srcdir}/../tcl \ `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi fi if test x"${ac_cv_c_tclconfig}" = x ; then TCL_BIN_DIR="# no Tcl configs found" as_fn_error $? "Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" "$LINENO" 5 else no_tcl= TCL_BIN_DIR="${ac_cv_c_tclconfig}" { $as_echo "$as_me:${as_lineno-$LINENO}: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5 $as_echo "found ${TCL_BIN_DIR}/tclConfig.sh" >&6; } fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5 $as_echo_n "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... " >&6; } if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5 $as_echo "loading" >&6; } . "${TCL_BIN_DIR}/tclConfig.sh" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5 $as_echo "could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6; } fi # If the TCL_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable TCL_LIB_SPEC will be set to the value # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC # instead of TCL_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. if test -f "${TCL_BIN_DIR}/Makefile" ; then TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" elif test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use the libraries # from the framework at the given location so that linking works # against Tcl.framework installed in an arbitrary location. case ${TCL_DEFS} in *TCL_FRAMEWORK*) if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" break fi done fi if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" fi ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking platform" >&5 $as_echo_n "checking platform... " >&6; } hold_cc=$CC; CC="$TCL_CC" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifdef _WIN32 #error win32 #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # first test we've already retrieved platform (cross-compile), fallback to unix otherwise: TEA_PLATFORM="${TEA_PLATFORM-unix}" CYGPATH=echo else TEA_PLATFORM="windows" # Extract the first word of "cygpath", so it can be a program name with args. set dummy cygpath; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CYGPATH+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CYGPATH"; then ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CYGPATH="cygpath -m" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" fi fi CYGPATH=$ac_cv_prog_CYGPATH if test -n "$CYGPATH"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 $as_echo "$CYGPATH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CC=$hold_cc { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TEA_PLATFORM" >&5 $as_echo "$TEA_PLATFORM" >&6; } # The BUILD_$pkg is to define the correct extern storage class # handling when making this package cat >>confdefs.h <<_ACEOF #define BUILD_${PACKAGE_NAME} /**/ _ACEOF # Do this here as we have fully defined TEA_PLATFORM now if test "${TEA_PLATFORM}" = "windows" ; then EXEEXT=".exe" CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" fi # TEA specific: #-------------------------------------------------------------------- # Load the tkConfig.sh file if necessary (Tk extension) #-------------------------------------------------------------------- #TEA_PATH_TKCONFIG #TEA_LOAD_TKCONFIG #----------------------------------------------------------------------- # Handle the --prefix=... option by defaulting to what Tcl gave. # Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. #----------------------------------------------------------------------- if test "${prefix}" = "NONE"; then prefix_default=yes if test x"${TCL_PREFIX}" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&5 $as_echo "$as_me: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&6;} prefix=${TCL_PREFIX} else { $as_echo "$as_me:${as_lineno-$LINENO}: --prefix defaulting to /usr/local" >&5 $as_echo "$as_me: --prefix defaulting to /usr/local" >&6;} prefix=/usr/local fi fi if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ -o x"${exec_prefix_default}" = x"yes" ; then if test x"${TCL_EXEC_PREFIX}" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&5 $as_echo "$as_me: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&6;} exec_prefix=${TCL_EXEC_PREFIX} else { $as_echo "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to ${prefix}" >&5 $as_echo "$as_me: --exec-prefix defaulting to ${prefix}" >&6;} exec_prefix=$prefix fi fi #----------------------------------------------------------------------- # Standard compiler checks. # This sets up CC by using the CC env var, or looks for gcc otherwise. # This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create # the basic setup necessary to compile executables. #----------------------------------------------------------------------- # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) # in this macro, they need to go into TEA_SETUP_COMPILER instead. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu #-------------------------------------------------------------------- # Checks to see if the make program sets the $MAKE variable. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi #-------------------------------------------------------------------- # Find ranlib #-------------------------------------------------------------------- if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi #-------------------------------------------------------------------- # Determines the correct binary file extension (.o, .obj, .exe etc.) #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. #------------------------------------------------------------------------ # If we're using GCC, see if the compiler understands -pipe. If so, use it. # It makes compiling go faster. (This is only a performance feature.) #------------------------------------------------------------------------ if test -z "$no_pipe" -a -n "$GCC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler understands -pipe" >&5 $as_echo_n "checking if the compiler understands -pipe... " >&6; } if ${tcl_cv_cc_pipe+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_cc_pipe=yes else tcl_cv_cc_pipe=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe" >&5 $as_echo "$tcl_cv_cc_pipe" >&6; } if test $tcl_cv_cc_pipe = yes; then CFLAGS="$CFLAGS -pipe" fi fi if test "${TCL_MAJOR_VERSION}" -lt 9 -a "${TCL_MINOR_VERSION}" -lt 7; then $as_echo "#define Tcl_Size int" >>confdefs.h fi #-------------------------------------------------------------------- # Common compiler flag setup #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes; then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no else ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 $as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) # ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac #-------------------------------------------------------------------- # Load the tdomConfig.sh file #-------------------------------------------------------------------- if test x"${no_tdom}" = x ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tDOM configuration" >&5 $as_echo_n "checking for tDOM configuration... " >&6; } # Check whether --with-tdom was given. if test "${with_tdom+set}" = set; then : withval=$with_tdom; with_tdomconfig=${withval} fi no_tdom=true if test "${TEA_PLATFORM}" = "windows" ; then tdom_bindir=win else tdom_bindir=unix fi if ${ac_cv_c_tdomconfig+:} false; then : $as_echo_n "(cached) " >&6 else # First check to see if --with-tdom was specified. if test x"${with_tdomconfig}" != x ; then if test -f "${with_tdomconfig}/tdomConfig.sh" ; then ac_cv_c_tdomconfig=`(cd ${with_tdomconfig}; pwd)` else as_fn_error $? "${with_tdomconfig} directory doesn't contain tdomConfig.sh" "$LINENO" 5 fi fi # Then check for a sibling installation if test x"${ac_cv_c_tdomconfig}" = x ; then for i in \ ../tdom `ls -dr ../tdom-* 2>/dev/null` \ ../../tdom `ls -dr ../../tdom-* 2>/dev/null` \ ../../../tdom `ls -dr ../../../tdom-* 2>/dev/null` ; do if test -f "$i/$tdom_bindir/tdomConfig.sh" ; then ac_cv_c_tdomconfig=`(cd $i/$tdom_bindir; pwd)` fi done fi # Then check if tnc/tdom are compilied in the source tree if test x"${ac_cv_c_tdomconfig}" = x ; then if test -f "../../$tdom_bindir/tdomConfig.sh" ; then ac_cv_c_tdomconfig=`(cd ../../$tdom_bindir; pwd)` fi fi # Check in a few common install locations if test x"${ac_cv_c_tdomconfig}" = x ; then for i in \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` ; do if test -f "$i/tdomConfig.sh" ; then ac_cv_c_tdomconfig=`(cd $i; pwd)` fi done fi # Check in a few other private locations if test x"${ac_cv_c_tdomconfig}" = x ; then for i in \ ${srcdir}/../tdom \ `ls -dr ${srcdir}/../tdom[0-9].[0-9]* 2>/dev/null` ; do if test -f "$i/$tdom_bindir/tdomConfig.sh" ; then ac_cv_c_tdomconfig=`(cd $i/$tdom_bindir; pwd)` fi done fi fi if test x"${ac_cv_c_tdomconfig}" = x ; then TDOM_BIN_DIR="# no tDOM configuration file found" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't find tDOM configuration definitions" >&5 $as_echo "$as_me: WARNING: Can't find tDOM configuration definitions" >&2;} exit 0 else no_tdom= TDOM_BIN_DIR=${ac_cv_c_tdomconfig} { $as_echo "$as_me:${as_lineno-$LINENO}: result: found $TDOM_BIN_DIR/tdomConfig.sh" >&5 $as_echo "found $TDOM_BIN_DIR/tdomConfig.sh" >&6; } fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of $TDOM_BIN_DIR/tdomConfig.sh" >&5 $as_echo_n "checking for existence of $TDOM_BIN_DIR/tdomConfig.sh... " >&6; } if test -f "$TDOM_BIN_DIR/tdomConfig.sh" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5 $as_echo "loading" >&6; } . $TDOM_BIN_DIR/tdomConfig.sh else { $as_echo "$as_me:${as_lineno-$LINENO}: result: file not found" >&5 $as_echo "file not found" >&6; } fi if test -f "${TDOM_BIN_DIR}/Makefile" ; then TDOM_STUB_LIB_SPEC=${TDOM_BUILD_STUB_LIB_SPEC} fi #----------------------------------------------------------------------- # __CHANGE__ # Specify the C source files to compile in TEA_ADD_SOURCES, # public headers that need to be installed in TEA_ADD_HEADERS, # stub library C source files to compile in TEA_ADD_STUB_SOURCES, # and runtime Tcl library files in TEA_ADD_TCL_SOURCES. # This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS # and PKG_TCL_SOURCES. #----------------------------------------------------------------------- vars="tnc.c" for i in $vars; do case $i in \$*) # allow $-var names PKG_SOURCES="$PKG_SOURCES $i" PKG_OBJECTS="$PKG_OBJECTS $i" ;; *) # check for existence - allows for generic/win/unix VPATH # To add more dirs here (like 'src'), you have to update VPATH # in Makefile.in as well if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ -a ! -f "${srcdir}/macosx/$i" \ ; then as_fn_error $? "could not find source file '$i'" "$LINENO" 5 fi PKG_SOURCES="$PKG_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" fi PKG_OBJECTS="$PKG_OBJECTS $j" ;; esac done vars="" for i in $vars; do # check for existence, be strict because it is installed if test ! -f "${srcdir}/$i" ; then as_fn_error $? "could not find header file '${srcdir}/$i'" "$LINENO" 5 fi PKG_HEADERS="$PKG_HEADERS $i" done vars="-I${srcdir}/../../generic -I${srcdir}/../../expat" for i in $vars; do PKG_INCLUDES="$PKG_INCLUDES $i" done vars="${TDOM_STUB_LIB_SPEC}" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([^-].*\)\.[lL][iI][bB]$/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done PKG_CFLAGS="$PKG_CFLAGS -DUSE_TDOM_STUBS=1" vars="" for i in $vars; do # check for existence - allows for generic/win/unix VPATH if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ -a ! -f "${srcdir}/macosx/$i" \ ; then as_fn_error $? "could not find stub source file '$i'" "$LINENO" 5 fi PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" fi PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j" done vars="" for i in $vars; do # check for existence, be strict because it is installed if test ! -f "${srcdir}/$i" ; then as_fn_error $? "could not find tcl source file '${srcdir}/$i'" "$LINENO" 5 fi PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" done #-------------------------------------------------------------------- # __CHANGE__ # A few miscellaneous platform-specific items: # # Define a special symbol for Windows (BUILD_sample in this case) so # that we create the export library with the dll. # # Windows creates a few extra files that need to be cleaned up. # You can add more files to clean if your extension creates any extra # files. # # TEA_ADD_* any platform specific compiler/build info here. #-------------------------------------------------------------------- if test "${TEA_PLATFORM}" = "windows" ; then #AC_DEFINE(BUILD_tnc, 1, [Build windows export dll]) CLEANFILES="*.lib *.dll *.exp *.ilk *.pdb vc*.pch" #TEA_ADD_SOURCES([win/winFile.c]) #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"]) else CLEANFILES="" #TEA_ADD_SOURCES([unix/unixFile.c]) #TEA_ADD_LIBS([-lsuperfly]) fi #-------------------------------------------------------------------- # __CHANGE__ # Choose which headers you need. Extension authors should try very # hard to only rely on the Tcl public header files. Internal headers # contain private data structures and are subject to change without # notice. # This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl public headers" >&5 $as_echo_n "checking for Tcl public headers... " >&6; } # Check whether --with-tclinclude was given. if test "${with_tclinclude+set}" = set; then : withval=$with_tclinclude; with_tclinclude=${withval} fi if ${ac_cv_c_tclh+:} false; then : $as_echo_n "(cached) " >&6 else # Use the value from --with-tclinclude, if it was given if test x"${with_tclinclude}" != x ; then if test -f "${with_tclinclude}/tcl.h" ; then ac_cv_c_tclh=${with_tclinclude} else as_fn_error $? "${with_tclinclude} directory does not contain tcl.h" "$LINENO" 5 fi else list="" if test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use # the framework's Headers directory case ${TCL_DEFS} in *TCL_FRAMEWORK*) list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`" ;; esac fi # Look in the source dir only if Tcl is not installed, # and in that situation, look there before installed locations. if test -f "${TCL_BIN_DIR}/Makefile" ; then list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`" fi # Check order: pkg --prefix location, Tcl's --prefix location, # relative to directory of tclConfig.sh. eval "temp_includedir=${includedir}" list="$list \ `ls -d ${temp_includedir} 2>/dev/null` \ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then list="$list /usr/local/include /usr/include" if test x"${TCL_INCLUDE_SPEC}" != x ; then d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'` list="$list `ls -d ${d} 2>/dev/null`" fi fi for i in $list ; do if test -f "$i/tcl.h" ; then ac_cv_c_tclh=$i break fi done fi fi # Print a message based on how we determined the include path if test x"${ac_cv_c_tclh}" = x ; then as_fn_error $? "tcl.h not found. Please specify its location with --with-tclinclude" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ac_cv_c_tclh}" >&5 $as_echo "${ac_cv_c_tclh}" >&6; } fi # Convert to a native path and substitute into the output files. INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" #TEA_PRIVATE_TCL_HEADERS #TEA_PUBLIC_TK_HEADERS #TEA_PRIVATE_TK_HEADERS #TEA_PATH_X #-------------------------------------------------------------------- # Check whether --enable-threads or --disable-threads was given. # This auto-enables if Tcl was compiled threaded. #-------------------------------------------------------------------- # Check whether --enable-threads was given. if test "${enable_threads+set}" = set; then : enableval=$enable_threads; tcl_ok=$enableval else tcl_ok=yes fi if test "${enable_threads+set}" = set; then enableval="$enable_threads" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then TCL_THREADS=1 if test "${TEA_PLATFORM}" != "windows" ; then # We are always OK on Windows, so check what this platform wants: # USE_THREAD_ALLOC tells us to try the special thread-based # allocator that significantly reduces lock contention $as_echo "#define USE_THREAD_ALLOC 1" >>confdefs.h $as_echo "#define _REENTRANT 1" >>confdefs.h if test "`uname -s`" = "SunOS" ; then $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h fi $as_echo "#define _THREAD_SAFE 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5 $as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; } if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (); int main () { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_pthread_mutex_init=yes else ac_cv_lib_pthread_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "no"; then # Check a little harder for __pthread_mutex_init in the same # library, as some systems hide it there until pthread.h is # defined. We could alternatively do an AC_TRY_COMPILE with # pthread.h, but that will work with libpthread really doesn't # exist, like AIX 4.2. [Bug: 4359] { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5 $as_echo_n "checking for __pthread_mutex_init in -lpthread... " >&6; } if ${ac_cv_lib_pthread___pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char __pthread_mutex_init (); int main () { return __pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread___pthread_mutex_init=yes else ac_cv_lib_pthread___pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_pthread___pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes; then : tcl_ok=yes else tcl_ok=no fi fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthread" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5 $as_echo_n "checking for pthread_mutex_init in -lpthreads... " >&6; } if ${ac_cv_lib_pthreads_pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthreads $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (); int main () { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthreads_pthread_mutex_init=yes else ac_cv_lib_pthreads_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthreads" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5 $as_echo_n "checking for pthread_mutex_init in -lc... " >&6; } if ${ac_cv_lib_c_pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (); int main () { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_pthread_mutex_init=yes else ac_cv_lib_c_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_c_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5 $as_echo_n "checking for pthread_mutex_init in -lc_r... " >&6; } if ${ac_cv_lib_c_r_pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc_r $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (); int main () { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_r_pthread_mutex_init=yes else ac_cv_lib_c_r_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_c_r_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_c_r_pthread_mutex_init" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -pthread" else TCL_THREADS=0 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&5 $as_echo "$as_me: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&2;} fi fi fi fi fi else TCL_THREADS=0 fi # Do checking message here to not mess up interleaved configure output { $as_echo "$as_me:${as_lineno-$LINENO}: checking for building with threads" >&5 $as_echo_n "checking for building with threads... " >&6; } if test "${TCL_THREADS}" = 1; then $as_echo "#define TCL_THREADS 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (default)" >&5 $as_echo "yes (default)" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # TCL_THREADS sanity checking. See if our request for building with # threads is the same as the way Tcl was built. If not, warn the user. case ${TCL_DEFS} in *THREADS=1*) if test "${TCL_THREADS}" = "0"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Building ${PACKAGE_NAME} without threads enabled, but building against Tcl that IS thread-enabled. It is recommended to use --enable-threads." >&5 $as_echo "$as_me: WARNING: Building ${PACKAGE_NAME} without threads enabled, but building against Tcl that IS thread-enabled. It is recommended to use --enable-threads." >&2;} fi ;; esac #-------------------------------------------------------------------- # The statement below defines a collection of symbols related to # building as a shared library instead of a static library. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5 $as_echo_n "checking how to build libraries... " >&6; } # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; shared_ok=$enableval else shared_ok=yes fi if test "${enable_shared+set}" = set; then enableval="$enable_shared" shared_ok=$enableval else shared_ok=yes fi # Check whether --enable-stubs was given. if test "${enable_stubs+set}" = set; then : enableval=$enable_stubs; stubs_ok=$enableval else stubs_ok=yes fi if test "${enable_stubs+set}" = set; then enableval="$enable_stubs" stubs_ok=$enableval else stubs_ok=yes fi # Stubs are always enabled for shared builds if test "$shared_ok" = "yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: shared" >&5 $as_echo "shared" >&6; } SHARED_BUILD=1 STUBS_BUILD=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5 $as_echo "static" >&6; } SHARED_BUILD=0 $as_echo "#define STATIC_BUILD 1" >>confdefs.h if test "$stubs_ok" = "yes" ; then STUBS_BUILD=1 else STUBS_BUILD=0 fi fi if test "${STUBS_BUILD}" = "1" ; then $as_echo "#define USE_TCL_STUBS 1" >>confdefs.h $as_echo "#define USE_TCLOO_STUBS 1" >>confdefs.h if test "${TEA_WINDOWINGSYSTEM}" != ""; then $as_echo "#define USE_TK_STUBS 1" >>confdefs.h fi fi #-------------------------------------------------------------------- # This macro figures out what flags to use with the compiler/linker # when building shared/static debug/optimized objects. This information # can be taken from the tclConfig.sh file, but this figures it all out. #-------------------------------------------------------------------- if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi # Step 0.a: Enable 64 bit support? { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5 $as_echo_n "checking if 64bit support is requested... " >&6; } # Check whether --enable-64bit was given. if test "${enable_64bit+set}" = set; then : enableval=$enable_64bit; do64bit=$enableval else do64bit=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5 $as_echo "$do64bit" >&6; } # Step 0.b: Enable Solaris 64 bit VIS support? { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit Sparc VIS support is requested" >&5 $as_echo_n "checking if 64bit Sparc VIS support is requested... " >&6; } # Check whether --enable-64bit-vis was given. if test "${enable_64bit_vis+set}" = set; then : enableval=$enable_64bit_vis; do64bitVIS=$enableval else do64bitVIS=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bitVIS" >&5 $as_echo "$do64bitVIS" >&6; } # Force 64bit on with VIS if test "$do64bitVIS" = "yes"; then : do64bit=yes fi # Step 0.c: Check if visibility support is available. Do this here so # that platform specific alternatives can be used below if this fails. { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports visibility \"hidden\"" >&5 $as_echo_n "checking if compiler supports visibility \"hidden\"... " >&6; } if ${tcl_cv_cc_visibility_hidden+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ extern __attribute__((__visibility__("hidden"))) void f(void); void f(void) {} int main () { f(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_cc_visibility_hidden=yes else tcl_cv_cc_visibility_hidden=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_visibility_hidden" >&5 $as_echo "$tcl_cv_cc_visibility_hidden" >&6; } if test $tcl_cv_cc_visibility_hidden = yes; then : $as_echo "#define MODULE_SCOPE extern __attribute__((__visibility__(\"hidden\")))" >>confdefs.h $as_echo "#define HAVE_HIDDEN 1" >>confdefs.h fi # Step 0.d: Disable -rpath support? { $as_echo "$as_me:${as_lineno-$LINENO}: checking if rpath support is requested" >&5 $as_echo_n "checking if rpath support is requested... " >&6; } # Check whether --enable-rpath was given. if test "${enable_rpath+set}" = set; then : enableval=$enable_rpath; doRpath=$enableval else doRpath=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doRpath" >&5 $as_echo "$doRpath" >&6; } # Set the variable "system" to hold the name and version number # for the system. { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5 $as_echo_n "checking system version... " >&6; } if ${tcl_cv_sys_version+:} false; then : $as_echo_n "(cached) " >&6 else # TEA specific: if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 $as_echo "$as_me: WARNING: can't find uname command" >&2;} tcl_cv_sys_version=unknown else if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then tcl_cv_sys_version=NetBSD-Debian fi fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 $as_echo "$tcl_cv_sys_version" >&6; } system=$tcl_cv_sys_version # Require ranlib early so we can override it in special cases below. # Set configuration options based on system name and version. # This is similar to Tcl's unix/tcl.m4 except that we've added a # "windows" case and removed some core-only vars. do64bit_ok=no # default to '{$LIBS}' and set to "" on per-platform necessary basis SHLIB_LD_LIBS='${LIBS}' # When ld needs options to work in 64-bit mode, put them in # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] # is disabled by the user. [Bug 1016796] LDFLAGS_ARCH="" UNSHARED_LIB_SUFFIX="" # TEA specific: use PACKAGE_VERSION instead of VERSION TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' ECHO_VERSION='`echo ${PACKAGE_VERSION}`' TCL_LIB_VERSIONS_OK=ok CFLAGS_DEBUG=-g if test "$GCC" = yes; then : CFLAGS_OPTIMIZE=-O2 CFLAGS_WARNING="-Wall" else CFLAGS_OPTIMIZE=-O CFLAGS_WARNING="" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="${ac_tool_prefix}ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_AR" = x; then AR="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi else AR="$ac_cv_prog_AR" fi STLIB_LD='${AR} cr' LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" if test "x$SHLIB_VERSION" = x; then : SHLIB_VERSION="" else SHLIB_VERSION=".$SHLIB_VERSION" fi case $system in # TEA specific: windows) MACHINE="X86" if test "$do64bit" != "no" ; then case "$do64bit" in amd64|x64|yes) MACHINE="AMD64" ; # default to AMD64 64-bit build ;; arm64|aarch64) MACHINE="ARM64" ;; ia64) MACHINE="IA64" ;; esac fi if test "$GCC" != "yes" ; then if test "${SHARED_BUILD}" = "0" ; then runtime=-MT else runtime=-MD fi case "x`echo \${VisualStudioVersion}`" in x1[4-9]*) lflags="${lflags} -nodefaultlib:libucrt.lib" vars="ucrt.lib" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([^-].*\)\.[lL][iI][bB]$/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done ;; *) ;; esac if test "$do64bit" != "no" ; then CC="cl.exe" RC="rc.exe" lflags="${lflags} -nologo -MACHINE:${MACHINE} " LINKBIN="link.exe" CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d" CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" # Avoid 'unresolved external symbol __security_cookie' # errors, c.f. http://support.microsoft.com/?id=894573 vars="bufferoverflowU.lib" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([^-].*\)\.[lL][iI][bB]$/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done else RC="rc" lflags="${lflags} -nologo" LINKBIN="link" CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" fi fi if test "$GCC" = "yes"; then # mingw gcc mode if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args. set dummy ${ac_tool_prefix}windres; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RC"; then ac_cv_prog_RC="$RC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RC="${ac_tool_prefix}windres" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RC=$ac_cv_prog_RC if test -n "$RC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RC" >&5 $as_echo "$RC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RC"; then ac_ct_RC=$RC # Extract the first word of "windres", so it can be a program name with args. set dummy windres; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RC"; then ac_cv_prog_ac_ct_RC="$ac_ct_RC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RC="windres" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RC=$ac_cv_prog_ac_ct_RC if test -n "$ac_ct_RC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RC" >&5 $as_echo "$ac_ct_RC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RC" = x; then RC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RC=$ac_ct_RC fi else RC="$ac_cv_prog_RC" fi CFLAGS_DEBUG="-g" CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" SHLIB_LD='${CC} -shared' UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cross-compile version of gcc" >&5 $as_echo_n "checking for cross-compile version of gcc... " >&6; } if ${ac_cv_cross+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef _WIN32 #error cross-compiler #endif int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_cross=yes else ac_cv_cross=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cross" >&5 $as_echo "$ac_cv_cross" >&6; } if test "$ac_cv_cross" = "yes"; then case "$do64bit" in amd64|x64|yes) CC="x86_64-w64-mingw32-${CC}" LD="x86_64-w64-mingw32-ld" AR="x86_64-w64-mingw32-ar" RANLIB="x86_64-w64-mingw32-ranlib" RC="x86_64-w64-mingw32-windres" ;; arm64|aarch64) CC="aarch64-w64-mingw32-clang" LD="aarch64-w64-mingw32-ld" AR="aarch64-w64-mingw32-ar" RANLIB="aarch64-w64-mingw32-ranlib" RC="aarch64-w64-mingw32-windres" ;; *) CC="i686-w64-mingw32-${CC}" LD="i686-w64-mingw32-ld" AR="i686-w64-mingw32-ar" RANLIB="i686-w64-mingw32-ranlib" RC="i686-w64-mingw32-windres" ;; esac fi else SHLIB_LD="${LINKBIN} -dll ${lflags}" # link -lib only works when -lib is the first arg STLIB_LD="${LINKBIN} -lib ${lflags}" UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib' PATHTYPE=-w # For information on what debugtype is most useful, see: # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp # and also # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx # This essentially turns it all on. LDFLAGS_DEBUG="-debug -debugtype:cv" LDFLAGS_OPTIMIZE="-release" LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" fi SHLIB_SUFFIX=".dll" SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' TCL_LIB_VERSIONS_OK=nodots ;; AIX-*) if test "$GCC" != "yes"; then : # AIX requires the _r compiler when gcc isn't being used case "${CC}" in *_r|*_r\ *) # ok ... ;; *) # Make sure only first arg gets _r CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'` ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads" >&5 $as_echo "Using $CC for compiling with threads" >&6; } fi LIBS="$LIBS -lc" SHLIB_CFLAGS="" SHLIB_SUFFIX=".so" LD_LIBRARY_PATH_VAR="LIBPATH" # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = yes; then : if test "$GCC" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} else do64bit_ok=yes CFLAGS="$CFLAGS -q64" LDFLAGS_ARCH="-q64" RANLIB="${RANLIB} -X64" AR="${AR} -X64" SHLIB_LD_FLAGS="-b64" fi fi if test "`uname -m`" = ia64; then : # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC SHLIB_LD="/usr/ccs/bin/ld -G -z text" if test "$GCC" = yes; then : CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' else CC_SEARCH_FLAGS='"-R${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' else if test "$GCC" = yes; then : SHLIB_LD='${CC} -shared -Wl,-bexpall' else SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" LDFLAGS="$LDFLAGS -brtl" fi SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" CC_SEARCH_FLAGS='"-L${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} fi ;; BeOS*) SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} -nostart' SHLIB_SUFFIX=".so" #----------------------------------------------------------- # Check for inet_ntoa in -lbind, for BeOS (which also needs # -lsocket, even if the network functions are in -lnet which # is always linked to, for compatibility. #----------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lbind" >&5 $as_echo_n "checking for inet_ntoa in -lbind... " >&6; } if ${ac_cv_lib_bind_inet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbind $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inet_ntoa (); int main () { return inet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bind_inet_ntoa=yes else ac_cv_lib_bind_inet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_inet_ntoa" >&5 $as_echo "$ac_cv_lib_bind_inet_ntoa" >&6; } if test "x$ac_cv_lib_bind_inet_ntoa" = xyes; then : LIBS="$LIBS -lbind -lsocket" fi ;; BSD/OS-2.1*|BSD/OS-3*) SHLIB_CFLAGS="" SHLIB_LD="shlicc -r" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; BSD/OS-4.*) SHLIB_CFLAGS="-export-dynamic -fPIC" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".so" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; CYGWIN_*) SHLIB_CFLAGS="" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".dll" SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$@.a" EXEEXT=".exe" do64bit_ok=yes CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; dgux*) SHLIB_CFLAGS="-K PIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; Haiku*) LDFLAGS="$LDFLAGS -Wl,--export-dynamic" SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnetwork" >&5 $as_echo_n "checking for inet_ntoa in -lnetwork... " >&6; } if ${ac_cv_lib_network_inet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnetwork $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inet_ntoa (); int main () { return inet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_network_inet_ntoa=yes else ac_cv_lib_network_inet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_inet_ntoa" >&5 $as_echo "$ac_cv_lib_network_inet_ntoa" >&6; } if test "x$ac_cv_lib_network_inet_ntoa" = xyes; then : LIBS="$LIBS -lnetwork" fi ;; HP-UX-*.11.*) # Use updated header definitions where possible $as_echo "#define _XOPEN_SOURCE_EXTENDED 1" >>confdefs.h # TEA specific: Needed by Tcl, but not most extensions #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) #LIBS="$LIBS -lxnet" # Use the XOPEN network library if test "`uname -m`" = ia64; then : SHLIB_SUFFIX=".so" else SHLIB_SUFFIX=".sl" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = yes; then : SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."' LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."' LD_LIBRARY_PATH_VAR="SHLIB_PATH" fi if test "$GCC" = yes; then : SHLIB_LD='${CC} -shared' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} else CFLAGS="$CFLAGS -z" fi # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = "yes"; then : if test "$GCC" = yes; then : case `${CC} -dumpmachine` in hppa64*) # 64-bit gcc in use. Fix flags for GNU ld. do64bit_ok=yes SHLIB_LD='${CC} -shared' if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} ;; esac else do64bit_ok=yes CFLAGS="$CFLAGS +DD64" LDFLAGS_ARCH="+DD64" fi fi ;; HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) SHLIB_SUFFIX=".sl" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : tcl_ok=yes else tcl_ok=no fi if test "$tcl_ok" = yes; then : SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS="" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."' LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."' LD_LIBRARY_PATH_VAR="SHLIB_PATH" fi ;; IRIX-5.*) SHLIB_CFLAGS="" SHLIB_LD="ld -shared -rdata_shared" SHLIB_SUFFIX=".so" case " $LIBOBJS " in *" mkstemp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext" ;; esac if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"' fi ;; IRIX-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"' fi if test "$GCC" = yes; then : CFLAGS="$CFLAGS -mabi=n32" LDFLAGS="$LDFLAGS -mabi=n32" else case $system in IRIX-6.3) # Use to build 6.2 compatible binaries on 6.3. CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" ;; *) CFLAGS="$CFLAGS -n32" ;; esac LDFLAGS="$LDFLAGS -n32" fi ;; IRIX64-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"' fi # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = yes; then : if test "$GCC" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported by gcc" >&2;} else do64bit_ok=yes SHLIB_LD="ld -64 -shared -rdata_shared" CFLAGS="$CFLAGS -64" LDFLAGS_ARCH="-64" fi fi ;; Linux*|GNU*|NetBSD-Debian|DragonFly-*|FreeBSD-*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" # TEA specific: CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS_DEFAULT} -shared' LDFLAGS="$LDFLAGS -Wl,--export-dynamic" case $system in DragonFly-*|FreeBSD-*) if test "${TCL_THREADS}" = "1"; then : # The -pthread needs to go in the LDFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $PTHREAD_LIBS" fi ;; esac if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} if test "`uname -m`" = "alpha"; then : CFLAGS="$CFLAGS -mieee" fi if test $do64bit = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -m64 flag" >&5 $as_echo_n "checking if compiler accepts -m64 flag... " >&6; } if ${tcl_cv_cc_m64+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS CFLAGS="$CFLAGS -m64" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_cc_m64=yes else tcl_cv_cc_m64=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_m64" >&5 $as_echo "$tcl_cv_cc_m64" >&6; } if test $tcl_cv_cc_m64 = yes; then : CFLAGS="$CFLAGS -m64" do64bit_ok=yes fi fi # The combo of gcc + glibc has a bug related to inlining of # functions like strtod(). The -fno-builtin flag should address # this problem but it does not work. The -fno-inline flag is kind # of overkill but it works. Disable inlining only when one of the # files in compat/*.c is being linked in. if test x"${USE_COMPAT}" != x; then : CFLAGS="$CFLAGS -fno-inline" fi ;; Lynx*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE=-02 SHLIB_LD='${CC} -shared' LD_FLAGS="-Wl,--export-dynamic" if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi ;; OpenBSD-*) arch=`arch -s` case "$arch" in alpha|sparc64) SHLIB_CFLAGS="-fPIC" ;; *) SHLIB_CFLAGS="-fpic" ;; esac SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}' LDFLAGS="$LDFLAGS -Wl,-export-dynamic" CFLAGS_OPTIMIZE="-O2" # On OpenBSD: Compile with -pthread # Don't link with -lpthread LIBS=`echo $LIBS | sed s/-lpthread//` CFLAGS="$CFLAGS -pthread" # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; NetBSD-*) # NetBSD has ELF and can use 'cc -shared' to build shared libs SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" LDFLAGS="$LDFLAGS -export-dynamic" if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} # The -pthread needs to go in the CFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" ;; Darwin-*) CFLAGS_OPTIMIZE="-Os" SHLIB_CFLAGS="-fno-common" # To avoid discrepancies between what headers configure sees during # preprocessing tests and compiling tests, move any -isysroot and # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if ($i~/^(isysroot|mmacosx-version-min)/) print "-"$i}'`" CFLAGS="`echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if (!($i~/^(isysroot|mmacosx-version-min)/)) print "-"$i}'`" if test $do64bit = yes; then : case `arch` in ppc) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch ppc64 flag" >&5 $as_echo_n "checking if compiler accepts -arch ppc64 flag... " >&6; } if ${tcl_cv_cc_arch_ppc64+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_cc_arch_ppc64=yes else tcl_cv_cc_arch_ppc64=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_ppc64" >&5 $as_echo "$tcl_cv_cc_arch_ppc64" >&6; } if test $tcl_cv_cc_arch_ppc64 = yes; then : CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" do64bit_ok=yes fi;; i386) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch x86_64 flag" >&5 $as_echo_n "checking if compiler accepts -arch x86_64 flag... " >&6; } if ${tcl_cv_cc_arch_x86_64+:} false; then : $as_echo_n "(cached) " >&6 else hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch x86_64" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_cc_arch_x86_64=yes else tcl_cv_cc_arch_x86_64=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_x86_64" >&5 $as_echo "$tcl_cv_cc_arch_x86_64" >&6; } if test $tcl_cv_cc_arch_x86_64 = yes; then : CFLAGS="$CFLAGS -arch x86_64" do64bit_ok=yes fi;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5 $as_echo "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};; esac else # Check for combined 32-bit and 64-bit fat build if echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '; then : fat_32_64=yes fi fi # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -single_module flag" >&5 $as_echo_n "checking if ld accepts -single_module flag... " >&6; } if ${tcl_cv_ld_single_module+:} false; then : $as_echo_n "(cached) " >&6 else hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { int i; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_ld_single_module=yes else tcl_cv_ld_single_module=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_single_module" >&5 $as_echo "$tcl_cv_ld_single_module" >&6; } if test $tcl_cv_ld_single_module = yes; then : SHLIB_LD="${SHLIB_LD} -Wl,-single_module" fi # TEA specific: link shlib with current and compatibility version flags vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([0-9]\{1,5\}\)\(\(\.[0-9]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" SHLIB_SUFFIX=".dylib" LDFLAGS="$LDFLAGS -headerpad_max_install_names" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag" >&5 $as_echo_n "checking if ld accepts -search_paths_first flag... " >&6; } if ${tcl_cv_ld_search_paths_first+:} false; then : $as_echo_n "(cached) " >&6 else hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-search_paths_first" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { int i; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_ld_search_paths_first=yes else tcl_cv_ld_search_paths_first=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_search_paths_first" >&5 $as_echo "$tcl_cv_ld_search_paths_first" >&6; } if test $tcl_cv_ld_search_paths_first = yes; then : LDFLAGS="$LDFLAGS -Wl,-search_paths_first" fi if test "$tcl_cv_cc_visibility_hidden" != yes; then : $as_echo "#define MODULE_SCOPE __private_extern__" >>confdefs.h tcl_cv_cc_visibility_hidden=yes fi CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" # TEA specific: for combined 32 & 64 bit fat builds of Tk # extensions, verify that 64-bit build is possible. if test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"; then : if test "${TEA_WINDOWINGSYSTEM}" = x11; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit X11" >&5 $as_echo_n "checking for 64-bit X11... " >&6; } if ${tcl_cv_lib_x11_64+:} false; then : $as_echo_n "(cached) " >&6 else for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { XrmInitialize(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_lib_x11_64=yes else tcl_cv_lib_x11_64=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_x11_64" >&5 $as_echo "$tcl_cv_lib_x11_64" >&6; } fi if test "${TEA_WINDOWINGSYSTEM}" = aqua; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit Tk" >&5 $as_echo_n "checking for 64-bit Tk... " >&6; } if ${tcl_cv_lib_tk_64+:} false; then : $as_echo_n "(cached) " >&6 else for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}" LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { Tk_InitStubs(NULL, "", 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_lib_tk_64=yes else tcl_cv_lib_tk_64=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_tk_64" >&5 $as_echo "$tcl_cv_lib_tk_64" >&6; } fi # remove 64-bit arch flags from CFLAGS et al. if configuration # does not support 64-bit. if test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no; then : { $as_echo "$as_me:${as_lineno-$LINENO}: Removing 64-bit architectures from compiler & linker flags" >&5 $as_echo "$as_me: Removing 64-bit architectures from compiler & linker flags" >&6;} for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' done fi fi ;; OS/390-*) CFLAGS_OPTIMIZE="" # Optimizer is buggy $as_echo "#define _OE_SOCKETS 1" >>confdefs.h ;; OSF1-V*) # Digital OSF/1 SHLIB_CFLAGS="" if test "$SHARED_BUILD" = 1; then : SHLIB_LD='ld -shared -expect_unresolved "*"' else SHLIB_LD='ld -non_shared -expect_unresolved "*"' fi SHLIB_SUFFIX=".so" if test $doRpath = yes; then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' fi if test "$GCC" = yes; then : CFLAGS="$CFLAGS -mieee" else CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee" fi # see pthread_intro(3) for pthread support on osf1, k.furukawa CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" LIBS=`echo $LIBS | sed s/-lpthreads//` if test "$GCC" = yes; then : LIBS="$LIBS -lpthread -lmach -lexc" else CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" fi ;; QNX-6*) # QNX RTP # This may work for all QNX, but it was only reported for v6. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SCO_SV-3.2*) if test "$GCC" = yes; then : SHLIB_CFLAGS="-fPIC -melf" LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" else SHLIB_CFLAGS="-Kpic -belf" LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" fi SHLIB_LD="ld -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SunOS-5.[0-6]) # Careful to not let 5.10+ fall into this case # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. $as_echo "#define _REENTRANT 1" >>confdefs.h $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h SHLIB_CFLAGS="-KPIC" SHLIB_SUFFIX=".so" if test "$GCC" = yes; then : SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} else SHLIB_LD="/usr/ccs/bin/ld -G -z text" CC_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} fi ;; SunOS-5*) # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. $as_echo "#define _REENTRANT 1" >>confdefs.h $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h SHLIB_CFLAGS="-KPIC" # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = yes; then : arch=`isainfo` if test "$arch" = "sparcv9 sparc"; then : if test "$GCC" = yes; then : if test "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;} else do64bit_ok=yes CFLAGS="$CFLAGS -m64 -mcpu=v9" LDFLAGS="$LDFLAGS -m64 -mcpu=v9" SHLIB_CFLAGS="-fPIC" fi else do64bit_ok=yes if test "$do64bitVIS" = yes; then : CFLAGS="$CFLAGS -xarch=v9a" LDFLAGS_ARCH="-xarch=v9a" else CFLAGS="$CFLAGS -xarch=v9" LDFLAGS_ARCH="-xarch=v9" fi # Solaris 64 uses this as well #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" fi else if test "$arch" = "amd64 i386"; then : if test "$GCC" = yes; then : case $system in SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) do64bit_ok=yes CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};; esac else do64bit_ok=yes case $system in SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) CFLAGS="$CFLAGS -xarch=amd64" LDFLAGS="$LDFLAGS -xarch=amd64";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported for $arch" >&5 $as_echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;} fi fi fi SHLIB_SUFFIX=".so" if test "$GCC" = yes; then : SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} if test "$do64bit_ok" = yes; then : if test "$arch" = "sparcv9 sparc"; then : # We need to specify -static-libgcc or we need to # add the path to the sparv9 libgcc. # JH: static-libgcc is necessary for core Tcl, but may # not be necessary for extensions. SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" # for finding sparcv9 libgcc, get the regular libgcc # path, remove so name and append 'sparcv9' #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" else if test "$arch" = "amd64 i386"; then : # JH: static-libgcc is necessary for core Tcl, but may # not be necessary for extensions. SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" fi fi fi else case $system in SunOS-5.[1-9][0-9]*) # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';; *) SHLIB_LD='/usr/ccs/bin/ld -G -z text';; esac CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' fi ;; UNIX_SV* | UnixWare-5*) SHLIB_CFLAGS="-KPIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers # that don't grok the -Bexport option. Test that it does. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld accepts -Bexport flag" >&5 $as_echo_n "checking for ld accepts -Bexport flag... " >&6; } if ${tcl_cv_ld_Bexport+:} false; then : $as_echo_n "(cached) " >&6 else hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-Bexport" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { int i; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : tcl_cv_ld_Bexport=yes else tcl_cv_ld_Bexport=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport" >&5 $as_echo "$tcl_cv_ld_Bexport" >&6; } if test $tcl_cv_ld_Bexport = yes; then : LDFLAGS="$LDFLAGS -Wl,-Bexport" fi CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; esac if test "$do64bit" = yes -a "$do64bit_ok" = no; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5 $as_echo "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;} fi # Add in the arch flags late to ensure it wasn't removed. # Not necessary in TEA, but this is aligned with core LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" # If we're running gcc, then change the C flags for compiling shared # libraries to the right flags for gcc, instead of those for the # standard manufacturer compiler. if test "$GCC" = yes; then : case $system in AIX-*) ;; BSD/OS*) ;; CYGWIN_*|MINGW32_*|MINGW64_*|MSYS_*) ;; IRIX*) ;; NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;; Darwin-*) ;; SCO_SV-3.2*) ;; windows) ;; *) SHLIB_CFLAGS="-fPIC" ;; esac fi if test "$tcl_cv_cc_visibility_hidden" != yes; then : $as_echo "#define MODULE_SCOPE extern" >>confdefs.h fi if test "$SHARED_LIB_SUFFIX" = ""; then : # TEA specific: use PACKAGE_VERSION instead of VERSION SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}' fi if test "$UNSHARED_LIB_SUFFIX" = ""; then : # TEA specific: use PACKAGE_VERSION instead of VERSION UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a' fi if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SEH support in compiler" >&5 $as_echo_n "checking for SEH support in compiler... " >&6; } if ${tcl_cv_seh+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : tcl_cv_seh=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main(int argc, char** argv) { int a, b = 0; __try { a = 666 / b; } __except (EXCEPTION_EXECUTE_HANDLER) { return 0; } return 1; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : tcl_cv_seh=yes else tcl_cv_seh=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_seh" >&5 $as_echo "$tcl_cv_seh" >&6; } if test "$tcl_cv_seh" = "no" ; then $as_echo "#define HAVE_NO_SEH 1" >>confdefs.h fi # # Check to see if the excpt.h include file provided contains the # definition for EXCEPTION_DISPOSITION; if not, which is the case # with Cygwin's version as of 2002-04-10, define it to be int, # sufficient for getting the current code to work. # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EXCEPTION_DISPOSITION support in include files" >&5 $as_echo_n "checking for EXCEPTION_DISPOSITION support in include files... " >&6; } if ${tcl_cv_eh_disposition+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # define WIN32_LEAN_AND_MEAN # include # undef WIN32_LEAN_AND_MEAN int main () { EXCEPTION_DISPOSITION x; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_eh_disposition=yes else tcl_cv_eh_disposition=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_eh_disposition" >&5 $as_echo "$tcl_cv_eh_disposition" >&6; } if test "$tcl_cv_eh_disposition" = "no" ; then $as_echo "#define EXCEPTION_DISPOSITION int" >>confdefs.h fi # Check to see if winnt.h defines CHAR, SHORT, and LONG # even if VOID has already been #defined. The win32api # used by mingw and cygwin is known to do this. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for winnt.h that ignores VOID define" >&5 $as_echo_n "checking for winnt.h that ignores VOID define... " >&6; } if ${tcl_cv_winnt_ignore_void+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define VOID void #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main () { CHAR c; SHORT s; LONG l; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_winnt_ignore_void=yes else tcl_cv_winnt_ignore_void=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_winnt_ignore_void" >&5 $as_echo "$tcl_cv_winnt_ignore_void" >&6; } if test "$tcl_cv_winnt_ignore_void" = "yes" ; then $as_echo "#define HAVE_WINNT_IGNORE_VOID 1" >>confdefs.h fi fi # See if the compiler supports casting to a union type. # This is used to stop gcc from printing a compiler # warning when initializing a union member. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5 $as_echo_n "checking for cast to union support... " >&6; } if ${tcl_cv_cast_to_union+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { union foo { int i; double d; }; union foo f = (union foo) (int) 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_cast_to_union=yes else tcl_cv_cast_to_union=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5 $as_echo "$tcl_cv_cast_to_union" >&6; } if test "$tcl_cv_cast_to_union" = "yes"; then $as_echo "#define HAVE_CAST_TO_UNION 1" >>confdefs.h fi ac_fn_c_check_header_mongrel "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default" if test "x$ac_cv_header_stdbool_h" = xyes; then : $as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h fi # These must be called after we do the basic CFLAGS checks and # verify any possible 64-bit or similar switches are necessary { $as_echo "$as_me:${as_lineno-$LINENO}: checking for required early compiler flags" >&5 $as_echo_n "checking for required early compiler flags... " >&6; } tcl_flags="" if ${tcl_cv_flag__isoc99_source+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { char *p = (char *)strtoll; char *q = (char *)strtoull; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_flag__isoc99_source=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _ISOC99_SOURCE 1 #include int main () { char *p = (char *)strtoll; char *q = (char *)strtoull; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_flag__isoc99_source=yes else tcl_cv_flag__isoc99_source=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "x${tcl_cv_flag__isoc99_source}" = "xyes" ; then $as_echo "#define _ISOC99_SOURCE 1" >>confdefs.h tcl_flags="$tcl_flags _ISOC99_SOURCE" fi if test "${TCL_MAJOR_VERSION}" -ne 8 ; then if ${tcl_cv_flag__file_offset_bits+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_flag__file_offset_bits=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include int main () { switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_flag__file_offset_bits=yes else tcl_cv_flag__file_offset_bits=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "x${tcl_cv_flag__file_offset_bits}" = "xyes" ; then $as_echo "#define _FILE_OFFSET_BITS 64" >>confdefs.h tcl_flags="$tcl_flags _FILE_OFFSET_BITS" fi fi if test "x${tcl_flags}" = "x" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}" >&5 $as_echo "${tcl_flags}" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit integer type" >&5 $as_echo_n "checking for 64-bit integer type... " >&6; } if ${tcl_cv_type_64bit+:} false; then : $as_echo_n "(cached) " >&6 else tcl_cv_type_64bit=none # See if the compiler knows natively about __int64 cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { __int64 value = (__int64) 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_type_64bit=__int64 else tcl_type_64bit="long long" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # See if we could use long anyway Note that we substitute in the # type that is our current guess for a 64-bit type inside this check # program, so it should be modified only carefully... cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { switch (0) { case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_type_64bit=${tcl_type_64bit} fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "${tcl_cv_type_64bit}" = none ; then $as_echo "#define TCL_WIDE_INT_IS_LONG 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } elif test "${tcl_cv_type_64bit}" = "__int64" \ -a "${TEA_PLATFORM}" = "windows" ; then # TEA specific: We actually want to use the default tcl.h checks in # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* { $as_echo "$as_me:${as_lineno-$LINENO}: result: using Tcl header defaults" >&5 $as_echo "using Tcl header defaults" >&6; } else cat >>confdefs.h <<_ACEOF #define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit} _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_cv_type_64bit}" >&5 $as_echo "${tcl_cv_type_64bit}" >&6; } # Now check for auxiliary declarations if test "${TCL_MAJOR_VERSION}" -ne 8 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit time_t" >&5 $as_echo_n "checking for 64-bit time_t... " >&6; } if ${tcl_cv_time_t_64+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;} ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_time_t_64=yes else tcl_cv_time_t_64=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_time_t_64" >&5 $as_echo "$tcl_cv_time_t_64" >&6; } if test "x${tcl_cv_time_t_64}" = "xno" ; then # Note that _TIME_BITS=64 requires _FILE_OFFSET_BITS=64 # which SC_TCL_EARLY_FLAGS has defined if necessary. { $as_echo "$as_me:${as_lineno-$LINENO}: checking if _TIME_BITS=64 enables 64-bit time_t" >&5 $as_echo_n "checking if _TIME_BITS=64 enables 64-bit time_t... " >&6; } if ${tcl_cv__time_bits+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _TIME_BITS 64 #include int main () { switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;} ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv__time_bits=yes else tcl_cv__time_bits=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv__time_bits" >&5 $as_echo "$tcl_cv__time_bits" >&6; } if test "x${tcl_cv__time_bits}" = "xyes" ; then $as_echo "#define _TIME_BITS 64" >>confdefs.h fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct dirent64" >&5 $as_echo_n "checking for struct dirent64... " >&6; } if ${tcl_cv_struct_dirent64+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct dirent64 p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_struct_dirent64=yes else tcl_cv_struct_dirent64=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64" >&5 $as_echo "$tcl_cv_struct_dirent64" >&6; } if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then $as_echo "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DIR64" >&5 $as_echo_n "checking for DIR64... " >&6; } if ${tcl_cv_DIR64+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct dirent64 *p; DIR64 d = opendir64("."); p = readdir64(d); rewinddir64(d); closedir64(d); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_DIR64=yes else tcl_cv_DIR64=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_DIR64" >&5 $as_echo "$tcl_cv_DIR64" >&6; } if test "x${tcl_cv_DIR64}" = "xyes" ; then $as_echo "#define HAVE_DIR64 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat64" >&5 $as_echo_n "checking for struct stat64... " >&6; } if ${tcl_cv_struct_stat64+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { struct stat64 p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_struct_stat64=yes else tcl_cv_struct_stat64=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_stat64" >&5 $as_echo "$tcl_cv_struct_stat64" >&6; } if test "x${tcl_cv_struct_stat64}" = "xyes" ; then $as_echo "#define HAVE_STRUCT_STAT64 1" >>confdefs.h fi for ac_func in open64 lseek64 do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for off64_t" >&5 $as_echo_n "checking for off64_t... " >&6; } if ${tcl_cv_type_off64_t+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { off64_t offset; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : tcl_cv_type_off64_t=yes else tcl_cv_type_off64_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "x${tcl_cv_type_off64_t}" = "xyes" && \ test "x${ac_cv_func_lseek64}" = "xyes" && \ test "x${ac_cv_func_open64}" = "xyes" ; then $as_echo "#define HAVE_TYPE_OFF64_T 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi #-------------------------------------------------------------------- # Set the default compiler switches based on the --enable-symbols option. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5 $as_echo_n "checking for build with symbols... " >&6; } # Check whether --enable-symbols was given. if test "${enable_symbols+set}" = set; then : enableval=$enable_symbols; tcl_ok=$enableval else tcl_ok=no fi if test "$tcl_ok" = "no"; then CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG" LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define TCL_CFG_OPTIMIZED 1" >>confdefs.h else CFLAGS_DEFAULT="${CFLAGS_DEBUG}" LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" if test "$tcl_ok" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)" >&5 $as_echo "yes (standard debugging)" >&6; } fi fi if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then $as_echo "#define TCL_MEM_DEBUG 1" >>confdefs.h fi if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then if test "$tcl_ok" = "all"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled symbols mem debugging" >&5 $as_echo "enabled symbols mem debugging" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5 $as_echo "enabled $tcl_ok debugging" >&6; } fi fi #-------------------------------------------------------------------- # Everyone should be linking against the Tcl stub library. If you # can't for some reason, remove this definition. If you aren't using # stubs, you also need to modify the SHLIB_LD_LIBS setting below to # link against the non-stubbed Tcl library. Add Tk too if necessary. #-------------------------------------------------------------------- $as_echo "#define USE_TCL_STUBS 1" >>confdefs.h #AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs]) #-------------------------------------------------------------------- # This macro generates a line to use when building a library. It # depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, # and TEA_LOAD_TCLCONFIG macros above. #-------------------------------------------------------------------- if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then MAKE_STATIC_LIB="\${STLIB_LD} -out:\$@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -out:\$@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined(_MSC_VER) && _MSC_VER >= 1400 print("manifest needed") #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "manifest needed" >/dev/null 2>&1; then : # Could do a CHECK_PROG for mt, but should always be with MSVC8+ VC_MANIFEST_EMBED_DLL="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;2 ; fi" VC_MANIFEST_EMBED_EXE="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;1 ; fi" MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" CLEANFILES="$CLEANFILES *.manifest" fi rm -f conftest* MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\$@ \$(PKG_STUB_OBJECTS)" else MAKE_STATIC_LIB="\${STLIB_LD} \$@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -o \$@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" MAKE_STUB_LIB="\${STLIB_LD} \$@ \$(PKG_STUB_OBJECTS)" fi if test "${SHARED_BUILD}" = "1" ; then MAKE_LIB="${MAKE_SHARED_LIB} " else MAKE_LIB="${MAKE_STATIC_LIB} " fi #-------------------------------------------------------------------- # Shared libraries and static libraries have different names. # Use the double eval to make sure any variables in the suffix is # substituted. (@@@ Might not be necessary anymore) #-------------------------------------------------------------------- PACKAGE_LIB_PREFIX8="${PACKAGE_LIB_PREFIX}" PACKAGE_LIB_PREFIX9="${PACKAGE_LIB_PREFIX}tcl9" if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX9}" else PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX8}" $as_echo "#define TCL_MAJOR_VERSION 8" >>confdefs.h fi if test "${TEA_PLATFORM}" = "windows" ; then if test "${SHARED_BUILD}" = "1" ; then # We force the unresolved linking of symbols that are really in # the private libraries of Tcl and Tk. if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" fi SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" if test "$GCC" = "yes"; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc" fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" else if test "$GCC" = "yes"; then PACKAGE_LIB_PREFIX=lib${PACKAGE_LIB_PREFIX} fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub.a" else eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" fi if test "$GCC" = "yes"; then PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} fi # These aren't needed on Windows (either MSVC or gcc) RANLIB=: RANLIB_STUB=: else RANLIB_STUB="${RANLIB}" if test "${SHARED_BUILD}" = "1" ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}" if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}" fi eval eval "PKG_LIB_FILE8=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=lib${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" RANLIB=: else eval eval "PKG_LIB_FILE8=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=lib${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" = x; then eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub.a" else eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" fi fi # These are escaped so that only CFLAGS is picked up at configure time. # The other values will be substituted at make time. CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}" if test "${SHARED_BUILD}" = "1" ; then CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}" fi # Substitute STUB_LIB_FILE in case package creates a stub library too. #-------------------------------------------------------------------- # Determine the name of the tclsh and/or wish executables in the # Tcl and Tk build directories or the location they were installed # into. These paths are used to support running test cases only, # the Makefile should not be making use of these paths to generate # a pkgIndex.tcl file or anything else at extension build time. #-------------------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5 $as_echo_n "checking for tclsh... " >&6; } if test -f "${TCL_BIN_DIR}/Makefile" ; then # tclConfig.sh is in Tcl build directory if test "${TEA_PLATFORM}" = "windows"; then if test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" fi else TCLSH_PROG="${TCL_BIN_DIR}/tclsh" fi else # tclConfig.sh is in install location if test "${TEA_PLATFORM}" = "windows"; then TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" else TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}" fi list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" for i in $list ; do if test -f "$i/${TCLSH_PROG}" ; then REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" break fi done TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${TCLSH_PROG}" >&5 $as_echo "${TCLSH_PROG}" >&6; } #TEA_PROG_WISH #-------------------------------------------------------------------- # Finally, substitute all of the various values into the Makefile. # You may alternatively have a special pkgIndex.tcl.in or other files # which require substituting th AC variables in. Include these here. #-------------------------------------------------------------------- ac_config_files="$ac_config_files Makefile pkgIndex.tcl" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS="" : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by tnc $as_me 0.3.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ tnc config.status 0.3.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "pkgIndex.tcl") CONFIG_FILES="$CONFIG_FILES pkgIndex.tcl" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi tdom-0.9.5-src/extensions/tnc/tnc.c0000644000175000017500000030716614703531020015666 0ustar rolfrolf/* This code implements a set of tDOM C Handlers that can be dynamically loaded into a tclsh with already loaded tDOM package. This parser extension does some tests according to the DTD against the data within an XML document. Copyright (c) 2001-2003 Rolf Ade */ #include #include #include #ifndef TCL_THREADS # define TDomThreaded(x) #else # define TDomThreaded(x) x #endif /* The initial stack sizes must be at least 1 */ #define TNC_INITCONTENTSTACKSIZE 512 /*---------------------------------------------------------------------------- | local globals | \---------------------------------------------------------------------------*/ /* Counter to generate unique validateCmd names */ static int uniqueCounter = 0; TDomThreaded(static Tcl_Mutex counterMutex;) /* Protect the counter */ /* To enable some debugging output at stdout use this. But beware: this debugging output isn't systematic and only understandable, if you know the internals of tnc. */ /* #define TNC_DEBUG */ /* The elements of TNC_Content carry exactly the same information as expats XML_Content. But the element is identified by his Tcl_HashEntry entry within the "tagNames" Hashtable (see TNC_Data) and not the element name. This should be much more efficient. */ typedef struct TNC_cp TNC_Content; typedef struct TNC_elemAttInfo TNC_ElemAttInfo; struct TNC_cp { enum XML_Content_Type type; enum XML_Content_Quant quant; Tcl_HashEntry *nameId; unsigned int numchildren; TNC_Content *children; TNC_ElemAttInfo *attInfo; }; typedef struct TNC_contentStack { TNC_Content *model; int activeChild; int deep; int alreadymatched; } TNC_ContentStack; typedef struct TNC_data { char *doctypeName; /* From DOCTYPE declaration */ int skipWhiteCDATAs; /* Flag: white space allowed in current content model? */ int ignorePCDATA; /* Flag: currently mixed content model? */ Tcl_HashTable *tagNames; /* Hash table of all ELEMENT declarations of the DTD. Element name is the key. While parsing, entry points to the XML_Content of that Element, after finishing of DTD parsing, entry holds a pointer to the TNC_Content of that element. */ TNC_ElemAttInfo *elemAttInfo; /* TncElementStartCommand stores the elemAttInfo pointer of the current element here for DOM validation, to avoid two element name lookups. */ int elemContentsRewriten; /* Signals, if the tagNames entries point to TNC_Contents */ int dtdstatus; /* While used with expat obj: 1 after successful parsed DTD, 0 otherwise. For validateCmd used for error report during validation: 0 OK, 1 validation error. */ int idCheck; /* Flag: check IDREF resolution*/ Tcl_HashTable *attDefsTables; /* Used to store ATTLIST declarations while parsing. Keys are the element names. */ Tcl_HashTable *entityDecls; /* Used to store ENTITY declarations. */ Tcl_HashTable *notationDecls; /* Used to store NOTATION declarations. */ Tcl_HashTable *ids; /* Used to track IDs */ Tcl_Interp *interp; Tcl_Obj *expatObj; /* If != NULL, points to the parserCmd structure. NULL for ValidateCmds. Used, to distinguish between SAX and DOM validation. */ int contentStackSize; /* Current size of the content stack */ int contentStackPtr; /* Points to the currently active content model on the stack */ TNC_ContentStack *contentStack; /* Stack for the currently nested open content models. */ } TNC_Data; typedef enum TNC_attType { TNC_ATTTYPE_CDATA, TNC_ATTTYPE_ID, TNC_ATTTYPE_IDREF, TNC_ATTTYPE_IDREFS, TNC_ATTTYPE_ENTITY, TNC_ATTTYPE_ENTITIES, TNC_ATTTYPE_NMTOKEN, TNC_ATTTYPE_NMTOKENS, TNC_ATTTYPE_NOTATION, TNC_ATTTYPE_ENUMERATION, } TNC_AttType; struct TNC_elemAttInfo { Tcl_HashTable *attributes; int nrOfreq; int nrOfIdAtts; }; typedef struct TNC_attDecl { TNC_AttType att_type; char *dflt; int isrequired; Tcl_HashTable *lookupTable; /* either NotationTypes or enum values */ } TNC_AttDecl; typedef struct TNC_entityInfo { int is_notation; char *notationName; } TNC_EntityInfo; typedef Tcl_HashEntry TNC_NameId; static char tnc_usage[] = "Usage tnc , where subCommand can be: \n" " enable \n" " remove \n" " getValidateCmd ?cmdName?\n" ; static char validateCmd_usage[] = "Usage validateCmd , where method can be: \n" " validateDocument \n" " validateTree \n" " validateAttributes \n" " delete \n" ; enum TNC_Error { TNC_ERROR_NONE, TNC_ERROR_DUPLICATE_ELEMENT_DECL, TNC_ERROR_DUPLICATE_MIXED_ELEMENT, TNC_ERROR_UNKNOWN_ELEMENT, TNC_ERROR_EMPTY_ELEMENT, TNC_ERROR_DISALLOWED_PCDATA, TNC_ERROR_DISALLOWED_CDATA, TNC_ERROR_NO_DOCTYPE_DECL, TNC_ERROR_WRONG_ROOT_ELEMENT, TNC_ERROR_NO_ATTRIBUTES, TNC_ERROR_UNKNOWN_ATTRIBUTE, TNC_ERROR_WRONG_FIXED_ATTVALUE, TNC_ERROR_MISSING_REQUIRED_ATTRIBUTE, TNC_ERROR_MORE_THAN_ONE_ID_ATT, TNC_ERROR_ID_ATT_DEFAULT, TNC_ERROR_DUPLICATE_ID_VALUE, TNC_ERROR_UNKNOWN_ID_REFERRED, TNC_ERROR_ENTITY_ATTRIBUTE, TNC_ERROR_ENTITIES_ATTRIBUTE, TNC_ERROR_ATT_ENTITY_DEFAULT_MUST_BE_DECLARED, TNC_ERROR_NOTATION_REQUIRED, TNC_ERROR_NOTATION_MUST_BE_DECLARED, TNC_ERROR_IMPOSSIBLE_DEFAULT, TNC_ERROR_ENUM_ATT_WRONG_VALUE, TNC_ERROR_NMTOKEN_REQUIRED, TNC_ERROR_NAME_REQUIRED, TNC_ERROR_NAMES_REQUIRED, TNC_ERROR_ELEMENT_NOT_ALLOWED_HERE, TNC_ERROR_ELEMENT_CAN_NOT_END_HERE, TNC_ERROR_ONLY_THREE_BYTE_UTF8, TNC_ERROR_UNKNOWN_NODE_TYPE }; const char * TNC_ErrorString (int code) { static const char *message[] = { "No error.", "Element declared more than once.", "The same name must not appear more than once in \n\tone mixed-content declaration.", "No declaration for this element.", "Element is declared to be empty, but isn't.", "PCDATA not allowed here.", "CDATA section not allowed here.", "No DOCTYPE declaration.", "Root element doesn't match DOCTYPE name.", "No attributes defined for this element.", "Unknown attribute for this element.", "Attribute value must match the FIXED default.", "Required attribute missing.", "Only one attribute with type ID allowed.", "No default value allowed for attribute type ID.", "ID attribute values must be unique within the document.", "Unknown ID referred.", "Attribute value has to be a unparsed entity.", "Attribute value has to be a sequence of unparsed entities.", "The defaults of attributes with type ENTITY or ENTITIES\nhas to be unparsed entities.", "Attribute value has to be one of the allowed notations.", "Every used NOTATION must be declared.", "Attribute default is not one of the allowed values", "Attribute hasn't one of the allowed values.", "Attribute value has to be a NMTOKEN.", "Attribute value has to be a Name.", "Attribute value has to match production Names.", "Element is not allowed here.", "Element can not end here (required element(s) missing).", "Can only handle UTF8 chars up to 3 bytes length." "Unknown or unexpected dom node type." }; /* if (code > 0 && code < sizeof(message)/sizeof(message[0])) */ return message[code]; return 0; } #define CHECK_UTF_CHARLEN(d) if (!(d)) { \ signalNotValid (userData, TNC_ERROR_ONLY_THREE_BYTE_UTF8);\ return;\ } #define CHECK_UTF_CHARLENR(d) if (!(d)) { \ signalNotValid (userData, TNC_ERROR_ONLY_THREE_BYTE_UTF8);\ return 0;\ } #define CHECK_UTF_CHARLEN_COPY(d) if (!(d)) { \ signalNotValid (userData, TNC_ERROR_ONLY_THREE_BYTE_UTF8);\ FREE (copy);\ return;\ } #define SetResult(str) Tcl_ResetResult(interp); \ Tcl_SetStringObj(Tcl_GetObjResult(interp), (str), -1) #define SetBooleanResult(i) Tcl_ResetResult(interp); \ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), (i)) extern char *Tdom_InitStubs (Tcl_Interp *interp, char *version, int exact); static void signalNotValid ( void *userData, int code ) { TNC_Data *tncdata = (TNC_Data *) userData; TclGenExpatInfo *expat; char s[1000]; if (tncdata->expatObj) { expat = GetExpatInfo (tncdata->interp, tncdata->expatObj); sprintf (s, "Validation error at line %ld, character %ld: %s", XML_GetCurrentLineNumber (expat->parser), XML_GetCurrentColumnNumber (expat->parser), TNC_ErrorString (code)); expat->status = TCL_ERROR; expat->result = Tcl_NewStringObj (s, -1); Tcl_IncrRefCount (expat->result); } else { tncdata->dtdstatus = 1; Tcl_SetResult (tncdata->interp, (char *)TNC_ErrorString (code), TCL_VOLATILE); } } /* *---------------------------------------------------------------------------- * * FindUniqueCmdName -- * * Generate new command name. Used for getValidateCmd. * * Results: * Returns newly allocated Tcl object containing name. * * Side effects: * Allocates Tcl object. * *---------------------------------------------------------------------------- */ static void FindUniqueCmdName( Tcl_Interp *interp, char *s ) { Tcl_CmdInfo info; TDomThreaded(Tcl_MutexLock(&counterMutex);) do { sprintf(s, "DTDvalidator%d", uniqueCounter++); } while (Tcl_GetCommandInfo(interp, s, &info)); TDomThreaded(Tcl_MutexUnlock(&counterMutex);) } /* *---------------------------------------------------------------------------- * * TncStartDoctypeDeclHandler -- * * This procedure is called for the start of the DOCTYPE * declaration. * * Results: * None. * * Side effects: * Stores the doctype Name in the TNC_data. * *---------------------------------------------------------------------------- */ void TncStartDoctypeDeclHandler ( void *userData, const char *doctypeName, const char *sysid, const char *pubid, int has_internal_subset ) { TNC_Data *tncdata = (TNC_Data *) userData; #ifdef TNC_DEBUG printf ("TncStartDoctypeDeclHandler start\n"); #endif tncdata->doctypeName = tdomstrdup (doctypeName); } /* *---------------------------------------------------------------------------- * * TncFreeTncModel -- * * This helper procedure frees recursively TNC_Contents. * * Results: * None. * * Side effects: * Frees memory. * *---------------------------------------------------------------------------- */ static void TncFreeTncModel ( TNC_Content *tmodel ) { unsigned int i; if (tmodel->children) { for (i = 0; i < tmodel->numchildren; i++) { TncFreeTncModel (&tmodel->children[i]); } FREE ((char *) tmodel->children); } } /* *---------------------------------------------------------------------------- * * TncRewriteModel -- * * This helper procedure creates recursively a TNC_Content from * an XML_Content. * * Results: * None. * * Side effects: * Allocates memory for the TNC_Content models. * *---------------------------------------------------------------------------- */ static void TncRewriteModel ( XML_Content *emodel, TNC_Content *tmodel, Tcl_HashTable *tagNames ) { Tcl_HashEntry *entryPtr; unsigned int i; tmodel->type = emodel->type; tmodel->quant = emodel->quant; tmodel->numchildren = emodel->numchildren; tmodel->children = NULL; tmodel->nameId = NULL; switch (emodel->type) { case XML_CTYPE_MIXED: if (emodel->quant == XML_CQUANT_REP) { tmodel->children = (TNC_Content *) MALLOC (sizeof (TNC_Content) * emodel->numchildren); for (i = 0; i < emodel->numchildren; i++) { TncRewriteModel (&emodel->children[i], &tmodel->children[i], tagNames); } } break; case XML_CTYPE_ANY: case XML_CTYPE_EMPTY: /* do nothing */ break; case XML_CTYPE_SEQ: case XML_CTYPE_CHOICE: tmodel->children = (TNC_Content *) MALLOC (sizeof (TNC_Content) * emodel->numchildren); for (i = 0; i < emodel->numchildren; i++) { TncRewriteModel (&emodel->children[i], &tmodel->children[i], tagNames); } break; case XML_CTYPE_NAME: entryPtr = Tcl_FindHashEntry (tagNames, emodel->name); /* Notice, that it is possible for entryPtr to be NULL. This means, a content model uses a not declared element. This is legal even in valid documents. (Of course, if the undeclared element actually shows up in the document that would make the document invalid.) See rec 3.2 QUESTION: Should there be a flag to enable a warning, when a declaration contains an element type for which no declaration is provided, as rec 3.2 metioned? This would be the appropriated place to omit the warning. */ tmodel->nameId = entryPtr; } } /* *---------------------------------------------------------------------------- * * TncEndDoctypeDeclHandler -- * * This procedure is called at the end of the DOCTYPE * declaration, after processing any external subset. * It rewrites the XML_Content models to TNC_Content * models and frees the XML_Content models. * * Results: * None. * * Side effects: * Rewrites the XML_Content models to TNC_Content * models. * *---------------------------------------------------------------------------- */ void TncEndDoctypeDeclHandler ( void *userData ) { TNC_Data *tncdata = (TNC_Data *) userData; Tcl_HashEntry *entryPtr, *ePtr1; Tcl_HashSearch search; XML_Content *emodel; TNC_Content *tmodel = NULL; char *elementName; entryPtr = Tcl_FirstHashEntry (tncdata->tagNames, &search); while (entryPtr != NULL) { #ifdef TNC_DEBUG printf ("name: %-20s nameId: %p\n", Tcl_GetHashKey (tncdata->tagNames, entryPtr), entryPtr); #endif emodel = (XML_Content*) Tcl_GetHashValue (entryPtr); tmodel = (TNC_Content*) MALLOC (sizeof (TNC_Content)); TncRewriteModel (emodel, tmodel, tncdata->tagNames); elementName = Tcl_GetHashKey (tncdata->tagNames, entryPtr); ePtr1 = Tcl_FindHashEntry (tncdata->attDefsTables, elementName); if (ePtr1) { tmodel->attInfo = (TNC_ElemAttInfo *) Tcl_GetHashValue (ePtr1); } else { tmodel->attInfo = NULL; } Tcl_SetHashValue (entryPtr, tmodel); entryPtr = Tcl_NextHashEntry (&search); } tncdata->elemContentsRewriten = 1; /* Checks, if every used notation name is in deed declared */ entryPtr = Tcl_FirstHashEntry (tncdata->notationDecls, &search); while (entryPtr != NULL) { #ifdef TNC_DEBUG printf ("check notation name %s\n", Tcl_GetHashKey (tncdata->notationDecls, entryPtr)); printf ("value %p\n", Tcl_GetHashValue (entryPtr)); #endif if (!Tcl_GetHashValue (entryPtr)) { signalNotValid (userData, TNC_ERROR_NOTATION_MUST_BE_DECLARED); return; } entryPtr = Tcl_NextHashEntry (&search); } /* Checks, if every used entity name is indeed declared */ entryPtr = Tcl_FirstHashEntry (tncdata->entityDecls, &search); while (entryPtr != NULL) { if (!Tcl_GetHashValue (entryPtr)) { signalNotValid (userData, TNC_ERROR_ATT_ENTITY_DEFAULT_MUST_BE_DECLARED); return; } entryPtr = Tcl_NextHashEntry (&search); } tncdata->dtdstatus = 1; } /* *---------------------------------------------------------------------------- * * TncEntityDeclHandler -- * * This procedure is called for every entity declaration. * * Results: * None. * * Side effects: * Stores either the name of the entity and * type information in a lookup table. * *---------------------------------------------------------------------------- */ void TncEntityDeclHandler ( void *userData, const char *entityName, int is_parameter_entity, const char *value, int value_length, const char *base, const char *systemId, const char *publicId, const char *notationName ) { TNC_Data *tncdata = (TNC_Data *) userData; Tcl_HashEntry *entryPtr; int newPtr; TNC_EntityInfo *entityInfo; /* expat collects entity definitions internaly by itself. So this is maybe superfluous, if it possible to access the expat internal representation. To study this is left to the reader. */ if (is_parameter_entity) return; entryPtr = Tcl_CreateHashEntry (tncdata->entityDecls, entityName, &newPtr); /* multiple declaration of the same entity are allowed; first definition wins (rec. 4.2) */ if (!newPtr) { /* Eventually, an attribute declaration with type ENTITY or ENTITIES has used this (up to the attribute declaration undeclared) ENTITY within his default value. In this case, the hash value has to be NULL and the entity must be a unparsed entity. */ if (!Tcl_GetHashValue (entryPtr)) { if (notationName == NULL) { signalNotValid (userData, TNC_ERROR_ATT_ENTITY_DEFAULT_MUST_BE_DECLARED); return; } newPtr = 1; } } if (newPtr) { entityInfo = (TNC_EntityInfo *) MALLOC (sizeof (TNC_EntityInfo)); if (notationName != NULL) { entityInfo->is_notation = 1; Tcl_CreateHashEntry (tncdata->notationDecls, notationName, &newPtr); entityInfo->notationName = tdomstrdup (notationName); } else { entityInfo->is_notation = 0; } Tcl_SetHashValue (entryPtr, entityInfo); } } /* *---------------------------------------------------------------------------- * * TncNotationDeclHandler -- * * This procedure is called for every notation declaration. * * Results: * None. * * Side effects: * Stores the notationName in the notationDecls table with value * one. * *---------------------------------------------------------------------------- */ void TncNotationDeclHandler ( void *userData, const char *notationName, const char *base, const char *systemId, const char *publicId ) { TNC_Data *tncdata = (TNC_Data *) userData; Tcl_HashEntry *entryPtr; int newPtr; entryPtr = Tcl_CreateHashEntry (tncdata->notationDecls, notationName, &newPtr); #ifdef TNC_DEBUG printf ("Notation %s declared\n", notationName); #endif Tcl_SetHashValue (entryPtr, (char *) 1); } /* *---------------------------------------------------------------------------- * * TncElementDeclCommand -- * * This procedure is called for every element declaration. * * Results: * None. * * Side effects: * Stores the tag name of the element in a lookup table. * *---------------------------------------------------------------------------- */ void TncElementDeclCommand ( void *userData, const char *name, XML_Content *model ) { TNC_Data *tncdata = (TNC_Data *) userData; Tcl_HashEntry *entryPtr; int newPtr; unsigned int i, j; entryPtr = Tcl_CreateHashEntry (tncdata->tagNames, name, &newPtr); /* "No element type may be declared more than once." (rec. 3.2) */ if (!newPtr) { signalNotValid (userData, TNC_ERROR_DUPLICATE_ELEMENT_DECL); return; } /* "The same name must not appear more than once in a single mixed-content declaration." (rec. 3.2.2) NOTE: OK, OK, doing it this way may not be optimal or even fast in some cases. Please step in with a more fancy solution, if you feel the need. */ if (model->type == XML_CTYPE_MIXED && model->quant == XML_CQUANT_REP) { for (i = 0; i < model->numchildren; i++) { for (j = i + 1; j < model->numchildren; j++) { if (strcmp ((&model->children[i])->name, (&model->children[j])->name) == 0) { signalNotValid (userData, TNC_ERROR_DUPLICATE_MIXED_ELEMENT); return; } } } } Tcl_SetHashValue (entryPtr, model); return; } /* *---------------------------------------------------------------------------- * * TncAttDeclCommand -- * * This procedure is called for *each* attribute in an XML * ATTLIST declaration. It stores the attribute definition in * an element specific hash table. * * Results: * None. * * Side effects: * Stores the tag name of the element in a lookup table. * *---------------------------------------------------------------------------- */ void TncAttDeclCommand ( void *userData, const char *elname, const char *attname, const char *att_type, const char *dflt, int isrequired ) { TNC_Data *tncdata = (TNC_Data *) userData; Tcl_HashEntry *entryPtr, *entryPtr1; Tcl_HashTable *elemAtts; TNC_ElemAttInfo *elemAttInfo; TNC_AttDecl *attDecl; TNC_EntityInfo *entityInfo; int newPtr, start, i, clen; char *copy; entryPtr = Tcl_CreateHashEntry (tncdata->attDefsTables, elname, &newPtr); if (newPtr) { elemAttInfo = (TNC_ElemAttInfo *) MALLOC (sizeof (TNC_ElemAttInfo)); elemAtts = (Tcl_HashTable *) MALLOC (sizeof (Tcl_HashTable)); Tcl_InitHashTable (elemAtts, TCL_STRING_KEYS); elemAttInfo->attributes = elemAtts; elemAttInfo->nrOfreq = 0; elemAttInfo->nrOfIdAtts = 0; Tcl_SetHashValue (entryPtr, elemAttInfo); } else { elemAttInfo = (TNC_ElemAttInfo *) Tcl_GetHashValue (entryPtr); elemAtts = elemAttInfo->attributes; } entryPtr = Tcl_CreateHashEntry (elemAtts, attname, &newPtr); /* Multiple Attribute declarations are allowed, but later declarations are ignored. See rec 3.3. */ if (newPtr) { attDecl = (TNC_AttDecl *) MALLOC (sizeof (TNC_AttDecl)); if (strcmp (att_type, "CDATA") == 0) { attDecl->att_type = TNC_ATTTYPE_CDATA; } else if (strcmp (att_type, "ID") == 0) { if (elemAttInfo->nrOfIdAtts) { signalNotValid (userData, TNC_ERROR_MORE_THAN_ONE_ID_ATT); return; } elemAttInfo->nrOfIdAtts++; if (dflt != NULL) { signalNotValid (userData, TNC_ERROR_ID_ATT_DEFAULT); return; } attDecl->att_type = TNC_ATTTYPE_ID; } else if (strcmp (att_type, "IDREF") == 0) { attDecl->att_type = TNC_ATTTYPE_IDREF; } else if (strcmp (att_type, "IDREFS") == 0) { attDecl->att_type = TNC_ATTTYPE_IDREFS; } else if (strcmp (att_type, "ENTITY") == 0) { attDecl->att_type = TNC_ATTTYPE_ENTITY; } else if (strcmp (att_type, "ENTITIES") == 0) { attDecl->att_type = TNC_ATTTYPE_ENTITIES; } else if (strcmp (att_type, "NMTOKEN") == 0) { attDecl->att_type = TNC_ATTTYPE_NMTOKEN; } else if (strcmp (att_type, "NMTOKENS") == 0) { attDecl->att_type = TNC_ATTTYPE_NMTOKENS; } else if (strncmp (att_type, "NOTATION(", 9) == 0) { /* This is a bit puzzling. expat returns something like as att_type "NOTATION(gif)". */ attDecl->att_type = TNC_ATTTYPE_NOTATION; attDecl->lookupTable = (Tcl_HashTable *) MALLOC (sizeof (Tcl_HashTable)); Tcl_InitHashTable (attDecl->lookupTable, TCL_STRING_KEYS); copy = tdomstrdup (att_type); start = i = 9; while (i) { if (copy[i] == ')') { copy[i] = '\0'; #ifdef TNC_DEBUG printf ("att type NOTATION: notation %s allowed\n", ©[start]); #endif Tcl_CreateHashEntry (attDecl->lookupTable, ©[start], &newPtr); entryPtr1 = Tcl_CreateHashEntry (tncdata->notationDecls, ©[start], &newPtr); #ifdef TNC_DEBUG if (newPtr) { printf ("up to now unknown NOTATION\n"); } else { printf ("NOTATION already known\n"); } #endif FREE (copy); break; } if (copy[i] == '|') { copy[i] = '\0'; #ifdef TNC_DEBUG printf ("att type NOTATION: notation %s allowed\n", ©[start]); #endif Tcl_CreateHashEntry (attDecl->lookupTable, ©[start], &newPtr); entryPtr1 = Tcl_CreateHashEntry (tncdata->notationDecls, ©[start], &newPtr); #ifdef TNC_DEBUG if (newPtr) { printf ("up to now unknown NOTATION\n"); } else { printf ("NOTATION already known\n"); } #endif start = ++i; continue; } clen = UTF8_CHAR_LEN (copy[i]); CHECK_UTF_CHARLEN_COPY (clen); if (!UTF8_GET_NAMING_NMTOKEN (©[i], clen)) { signalNotValid (userData, TNC_ERROR_NMTOKEN_REQUIRED); FREE (copy); return; } i += clen; } } else { /* expat returns something like as att_type "(numbered|bullets)", e.g. in some "non-official" normalized way. Makes things easier for us. */ attDecl->att_type = TNC_ATTTYPE_ENUMERATION; attDecl->lookupTable = (Tcl_HashTable *) MALLOC (sizeof (Tcl_HashTable)); Tcl_InitHashTable (attDecl->lookupTable, TCL_STRING_KEYS); copy = tdomstrdup (att_type); start = i = 1; while (1) { if (copy[i] == ')') { copy[i] = '\0'; Tcl_CreateHashEntry (attDecl->lookupTable, ©[start], &newPtr); FREE (copy); break; } if (copy[i] == '|') { copy[i] = '\0'; Tcl_CreateHashEntry (attDecl->lookupTable, ©[start], &newPtr); start = ++i; continue; } clen = UTF8_CHAR_LEN (copy[i]); CHECK_UTF_CHARLEN_COPY (clen); if (!UTF8_GET_NAMING_NMTOKEN (©[i], clen)) { signalNotValid (userData, TNC_ERROR_NMTOKEN_REQUIRED); FREE (copy); return; } i += clen; } } if (dflt != NULL) { switch (attDecl->att_type) { case TNC_ATTTYPE_ENTITY: case TNC_ATTTYPE_IDREF: clen = UTF8_CHAR_LEN (*dflt); CHECK_UTF_CHARLEN (clen); if (!UTF8_GET_NAME_START (dflt, clen)) { signalNotValid (userData, TNC_ERROR_NAME_REQUIRED); return; } i = clen; while (1) { if (dflt[i] == '\0') { break; } clen = UTF8_CHAR_LEN (dflt[i]); CHECK_UTF_CHARLEN (clen); if (!UTF8_GET_NAMING_NMTOKEN (&dflt[i], clen)) { signalNotValid (userData, TNC_ERROR_NAME_REQUIRED); return; } i += clen; } if (attDecl->att_type == TNC_ATTTYPE_ENTITY) { entryPtr1 = Tcl_CreateHashEntry (tncdata->entityDecls, dflt, &newPtr); if (!newPtr) { entityInfo = (TNC_EntityInfo *) Tcl_GetHashValue (entryPtr1); if (!entityInfo->is_notation) { signalNotValid (userData,TNC_ERROR_ATT_ENTITY_DEFAULT_MUST_BE_DECLARED); } } } break; case TNC_ATTTYPE_IDREFS: start = i = 0; while (1) { if (dflt[i] == '\0') { break; } if (dflt[i] == ' ') { start = ++i; } if (start == i) { clen = UTF8_CHAR_LEN (dflt[i]); CHECK_UTF_CHARLEN (clen); if (!UTF8_GET_NAME_START (&dflt[i], clen)) { signalNotValid (userData, TNC_ERROR_NAME_REQUIRED); return; } i += clen; } else { clen = UTF8_CHAR_LEN (dflt[i]); CHECK_UTF_CHARLEN (clen); if (!UTF8_GET_NAMING_NMTOKEN (&dflt[i], clen)) { signalNotValid (userData, TNC_ERROR_NAME_REQUIRED); return; } i += clen; } } break; case TNC_ATTTYPE_ENTITIES: copy = tdomstrdup (dflt); start = i = 0; while (1) { if (copy[i] == '\0') { FREE (copy); break; } if (copy[i] == ' ') { copy[i] = '\0'; entryPtr1 = Tcl_CreateHashEntry (tncdata->entityDecls, ©[start], &newPtr); if (!newPtr) { entityInfo = (TNC_EntityInfo *) Tcl_GetHashValue (entryPtr1); if (!entityInfo->is_notation) { signalNotValid (userData,TNC_ERROR_ATT_ENTITY_DEFAULT_MUST_BE_DECLARED); } } start = ++i; } if (start == i) { clen = UTF8_CHAR_LEN (copy[i]); CHECK_UTF_CHARLEN_COPY (clen); if (!UTF8_GET_NAME_START (©[i], clen)) { signalNotValid (userData, TNC_ERROR_NAME_REQUIRED); FREE (copy); return; } i += clen; } else { clen = UTF8_CHAR_LEN (copy[i]); CHECK_UTF_CHARLEN_COPY (clen); if (!UTF8_GET_NAMING_NMTOKEN (©[i], clen)) { signalNotValid (userData, TNC_ERROR_NAME_REQUIRED); FREE (copy); return; } i += clen; } } break; case TNC_ATTTYPE_NMTOKEN: i = 0; while (1) { if (dflt[i] == '\0') { break; } clen = UTF8_CHAR_LEN (dflt[i]); CHECK_UTF_CHARLEN (clen); if (!UTF8_GET_NAMING_NMTOKEN (&dflt[i], clen)) { signalNotValid (userData, TNC_ERROR_NMTOKEN_REQUIRED); return; } i += clen; } if (!i) signalNotValid (userData, TNC_ERROR_NMTOKEN_REQUIRED); break; case TNC_ATTTYPE_NMTOKENS: i = 0; while (1) { if (dflt[i] == '\0') { break; } if (dflt[i] == ' ') { i++; } clen = UTF8_CHAR_LEN (dflt[i]); CHECK_UTF_CHARLEN (clen); if (!UTF8_GET_NAMING_NMTOKEN (&dflt[i], clen)) { signalNotValid (userData, TNC_ERROR_NMTOKEN_REQUIRED); return; } i += clen; } if (!i) signalNotValid (userData, TNC_ERROR_NMTOKEN_REQUIRED); break; case TNC_ATTTYPE_NOTATION: if (!Tcl_FindHashEntry (attDecl->lookupTable, dflt)) { signalNotValid (userData, TNC_ERROR_IMPOSSIBLE_DEFAULT); return; } case TNC_ATTTYPE_ENUMERATION: if (!Tcl_FindHashEntry (attDecl->lookupTable, dflt)) { signalNotValid (userData, TNC_ERROR_IMPOSSIBLE_DEFAULT); return; } case TNC_ATTTYPE_CDATA: case TNC_ATTTYPE_ID: /* This both cases are only there, to pacify -Wall. CDATA may have any allowed characters (and everything else is detected by extpat). ID's not allowed to have defaults (handled above). */ ; } attDecl->dflt = tdomstrdup (dflt); } else { attDecl->dflt = NULL; } if (isrequired) { elemAttInfo->nrOfreq++; } attDecl->isrequired = isrequired; Tcl_SetHashValue (entryPtr, attDecl); } } #ifdef TNC_DEBUG void printNameIDs (TNC_Data *tncdata) { Tcl_HashEntry *entryPtr; Tcl_HashSearch search; for (entryPtr = Tcl_FirstHashEntry (tncdata->tagNames, &search); entryPtr != NULL; entryPtr = Tcl_NextHashEntry (&search)) { printf ("name: %-20s nameId: %p\n", Tcl_GetHashKey (tncdata->tagNames, entryPtr), entryPtr); } } void printStackElm (TNC_ContentStack *stackelm) { if (stackelm->model->type == XML_CTYPE_NAME) { printf ("\tmodel %p\tNAME: %p\n\tactiveChild %d\n\tdeep %d\n\talreadymatched %d\n", stackelm->model, stackelm->model->nameId, stackelm->activeChild, stackelm->deep, stackelm->alreadymatched); } else { printf ("\tmodel %p\n\tactiveChild %d\n\tdeep %d\n\talreadymatched %d\n", stackelm->model, stackelm->activeChild, stackelm->deep, stackelm->alreadymatched); } } void printTNC_Content (TNC_Content *model) { printf ("TNC_Content..\n\ttype %d\n\tquant %d\n\tnameId %p\n\tnumchildren %d\n\tchildren %p\n", model->type, model->quant, model->nameId, model->numchildren, model->children); } void printContentStack (TNC_Data *tncdata) { TNC_ContentStack stackelm; int i; printf ("Current contentStack state (used stack slots %d):\n", tncdata->contentStackPtr); for (i = 0; i < tncdata->contentStackPtr; i++) { stackelm = tncdata->contentStack[i]; printf ("%3d:\n", i); printStackElm (&stackelm); } } #endif /* TNC_DEBUG */ /* *---------------------------------------------------------------------------- * * TncProbeElement -- * * This function checks, if the element match the * topmost content model on the content stack. * * Results: * 1 if the element match, * 0 if not. * -1 if not, but this isn't a validation error * * Side effects: * Eventually pushes data to the contentStack (even in * recurive calls). * *---------------------------------------------------------------------------- */ static int TncProbeElement ( TNC_NameId *nameId, TNC_Data *tncdata ) { TNC_ContentStack *stackelm; TNC_Content *activeModel; int myStackPtr, zeroMatchPossible, result; unsigned int i, seqstartindex; #ifdef TNC_DEBUG printf ("TncProbeElement start\n"); printContentStack (tncdata); #endif myStackPtr = tncdata->contentStackPtr - 1; stackelm = &(tncdata->contentStack)[myStackPtr]; switch (stackelm->model->type) { case XML_CTYPE_MIXED: #ifdef TNC_DEBUG printf ("TncProbeElement XML_CTYPE_MIXED\n"); #endif for (i = 0; i < stackelm->model->numchildren; i++) { if ((&stackelm->model->children[i])->nameId == nameId) { return 1; } } return 0; case XML_CTYPE_ANY: #ifdef TNC_DEBUG printf ("TncProbeElement XML_CTYPE_ANY\n"); #endif return 1; case XML_CTYPE_EMPTY: #ifdef TNC_DEBUG printf ("TncProbeElement XML_CTYPE_EMPTY\n"); #endif return 0; case XML_CTYPE_CHOICE: #ifdef TNC_DEBUG printf ("TncProbeElement XML_CTYPE_CHOICE\n"); #endif if (stackelm->alreadymatched) { activeModel = &stackelm->model->children[stackelm->activeChild]; if (activeModel->type == XML_CTYPE_NAME) { /* so this stackelement must be the topmost */ if (activeModel->quant == XML_CQUANT_REP || activeModel->quant == XML_CQUANT_PLUS) { /* the last matched element is multiple, maybe it matches again */ if (nameId == activeModel->nameId) { #ifdef TNC_DEBUG printf ("-->matched! child Nr. %d\n", stackelm->activeChild); #endif /* stack and activeChild nr. are already OK, just report success. */ return 1; } } } /* The active child is a SEQ or CHOICE. */ if (stackelm->model->quant == XML_CQUANT_NONE || stackelm->model->quant == XML_CQUANT_OPT) { /*The child cp's type SEQ or CHOICE keep track by themselve about if they are repeated. Because we are here, they don't. Since the current cp has already matched and isn't multiple, the current cp as a whole is done. But no contradiction detected, so return "search further" */ return -1; } } /* If one of the alternatives within the CHOICE cp is quant REP or OPT, it isn't a contradition to the document structure, if the cp doesn't match, even if it is quant NONE or PLUS, because of the "zero time" match of this one alternative. We use zeroMatchPossible, to know about this.*/ zeroMatchPossible = 0; for (i = 0; i < stackelm->model->numchildren; i++) { if ((&stackelm->model->children[i])->type == XML_CTYPE_NAME) { #ifdef TNC_DEBUG printf ("child is type NAME\n"); #endif if ((&stackelm->model->children[i])->nameId == nameId) { #ifdef TNC_DEBUG printf ("-->matched! child Nr. %d\n",i); #endif (&tncdata->contentStack[myStackPtr])->activeChild = i; (&tncdata->contentStack[myStackPtr])->alreadymatched = 1; return 1; } else { /* If the name child is optional, we have a candidat for "zero match". */ if ((&stackelm->model->children[i])->quant == XML_CQUANT_OPT || (&stackelm->model->children[i])->quant == XML_CQUANT_REP) { #ifdef TNC_DEBUG printf ("zero match possible\n"); #endif zeroMatchPossible = 1; } } } else { #ifdef TNC_DEBUG printf ("complex child type\n"); #endif if (tncdata->contentStackPtr == tncdata->contentStackSize) { tncdata->contentStack = (TNC_ContentStack *) Tcl_Realloc ((char *)tncdata->contentStack, sizeof (TNC_Content *) * 2 * tncdata->contentStackSize); tncdata->contentStackSize *= 2; } (&tncdata->contentStack[tncdata->contentStackPtr])->model = &stackelm->model->children[i]; tncdata->contentStack[tncdata->contentStackPtr].activeChild = 0; tncdata->contentStack[tncdata->contentStackPtr].deep = stackelm->deep + 1; tncdata->contentStack[tncdata->contentStackPtr].alreadymatched = 0; tncdata->contentStackPtr++; result = TncProbeElement (nameId, tncdata); if (result == 1) { #ifdef TNC_DEBUG printf ("-->matched! child nr. %d\n",i); #endif (&tncdata->contentStack[myStackPtr])->activeChild = i; (&tncdata->contentStack[myStackPtr])->alreadymatched = 1; return 1; } /* The child cp says, it doesn't has matched, but says also, it's perfectly OK, if it doesn't at all. So we have a candidat for "zero match". */ if (result == -1) { zeroMatchPossible = 1; } tncdata->contentStackPtr--; } } /* OK, nobody has claimed a match. Question is: try further or is this a document structure error. */ if (zeroMatchPossible || stackelm->alreadymatched || stackelm->model->quant == XML_CQUANT_REP || stackelm->model->quant == XML_CQUANT_OPT) { return -1; } #ifdef TNC_DEBUG printf ("validation error\n"); #endif return 0; case XML_CTYPE_SEQ: #ifdef TNC_DEBUG printf ("TncProbeElement XML_CTYPE_SEQ\n"); #endif if (stackelm->alreadymatched) { activeModel = &stackelm->model->children[stackelm->activeChild]; if (activeModel->type == XML_CTYPE_NAME) { /* so this stackelement must be the topmost */ if (activeModel->quant == XML_CQUANT_REP || activeModel->quant == XML_CQUANT_PLUS) { /* the last matched element is multiple, maybe it matches again */ if (nameId == activeModel->nameId) { #ifdef TNC_DEBUG printf ("-->matched! child Nr. %d\n", stackelm->activeChild); #endif /* stack and activeChild nr. are already OK, just report success. */ return 1; } } } } if (stackelm->alreadymatched) { seqstartindex = stackelm->activeChild + 1; } else { seqstartindex = 0; } /* This time zeroMatchPossible flags, if every of the remaining children - that may every child, if !alreadymatched - doesn't must occur. We assume, the (outstanding children of, in case of alreadymatched) current stackelement model has only optional children, and set to false, if we find any non-optional child */ zeroMatchPossible = 1; for (i = seqstartindex; i < stackelm->model->numchildren; i++) { if ((&stackelm->model->children[i])->type == XML_CTYPE_NAME) { if ((&stackelm->model->children[i])->nameId == nameId) { #ifdef TNC_DEBUG printf ("-->matched! child Nr. %d\n",i); #endif (&tncdata->contentStack[myStackPtr])->activeChild = i; (&tncdata->contentStack[myStackPtr])->alreadymatched = 1; return 1; } else if ((&stackelm->model->children[i])->quant == XML_CQUANT_NONE || (&stackelm->model->children[i])->quant == XML_CQUANT_PLUS) { zeroMatchPossible = 0; break; } } else { if (tncdata->contentStackPtr == tncdata->contentStackSize) { tncdata->contentStack = (TNC_ContentStack *) Tcl_Realloc ((char *)tncdata->contentStack, sizeof (TNC_Content *) * 2 * tncdata->contentStackSize); tncdata->contentStackSize *= 2; } (&tncdata->contentStack[tncdata->contentStackPtr])->model = &stackelm->model->children[i]; tncdata->contentStack[tncdata->contentStackPtr].activeChild = 0; tncdata->contentStack[tncdata->contentStackPtr].deep = stackelm->deep + 1; tncdata->contentStack[tncdata->contentStackPtr].alreadymatched = 0; tncdata->contentStackPtr++; result = TncProbeElement (nameId, tncdata); if (result == 1) { (&tncdata->contentStack[myStackPtr])->activeChild = i; (&tncdata->contentStack[myStackPtr])->alreadymatched = 1; return 1; } tncdata->contentStackPtr--; if (result == 0) { zeroMatchPossible = 0; break; } } } if (!stackelm->alreadymatched) { if (zeroMatchPossible) { /* The stackelm hasn't matched, but don't have to after all. Return try further */ return -1; } else { /* No previous match, but at least one child is necessary. Return depends of the quant of the entire seq */ if (stackelm->model->quant == XML_CQUANT_NONE || stackelm->model->quant == XML_CQUANT_PLUS) { /* DTD claims, the seq as to be there, but isn't */ return 0; } else { /* The seq is optional */ return -1; } } } if (stackelm->alreadymatched) { if (!zeroMatchPossible) { /* Some child at the start of the seq has matched in the past, but since zeroMatchPossible has changed to zero, there must be a non-matching non-optional child later. Error in document structure. */ return 0; } else { /* OK, SEQ has matched before. But after the last match, there where no required (quant NONE or PLUS) children. */ if (stackelm->model->quant == XML_CQUANT_NONE || stackelm->model->quant == XML_CQUANT_OPT) { /* The entire seq isn't multiple. Just look further. */ return -1; } } } /* The last untreated case is alreadymatched true, zeroMatchPossible (of the rest of the seq children after the last match) true and the entire seq may be multiple. Therefore, start again with activeChild = 0, to see, if the current nameId starts a repeated match of the seq. By the way: zeroMatchPossible still has initial value 1, therefore, no second initialiation is needed */ for (i = 0; i < seqstartindex; i++) { if ((&stackelm->model->children[i])->type == XML_CTYPE_NAME) { if ((&stackelm->model->children[i])->nameId == nameId) { #ifdef TNC_DEBUG printf ("-->matched! child Nr. %d\n",i); #endif (&tncdata->contentStack[myStackPtr])->activeChild = i; (&tncdata->contentStack[myStackPtr])->alreadymatched = 1; return 1; } else if ((&stackelm->model->children[i])->quant == XML_CQUANT_NONE || (&stackelm->model->children[i])->quant == XML_CQUANT_PLUS) { zeroMatchPossible = 0; break; } } else { if (tncdata->contentStackPtr == tncdata->contentStackSize) { tncdata->contentStack = (TNC_ContentStack *) Tcl_Realloc ((char *)tncdata->contentStack, sizeof (TNC_Content *) * 2 * tncdata->contentStackSize); tncdata->contentStackSize *= 2; } (&tncdata->contentStack[tncdata->contentStackPtr])->model = &stackelm->model->children[i]; tncdata->contentStack[tncdata->contentStackPtr].activeChild = 0; tncdata->contentStack[tncdata->contentStackPtr].deep = stackelm->deep + 1; tncdata->contentStack[tncdata->contentStackPtr].alreadymatched = 0; tncdata->contentStackPtr++; result = TncProbeElement (nameId, tncdata); if (result) { (&tncdata->contentStack[myStackPtr])->activeChild = i; /* alreadymatched is already 1 */ return 1; } tncdata->contentStackPtr--; if (result == 0) { /* OK, the seq doesn't match again. But since it have already matched, this isn't return 0 but.. */ return -1; } } } /* seq doesn't match again and every seq child from the very first up to (not including) the last match aren't required. This last fact may be nice to know, but after all since the entire seq have matched already ... */ return -1; case XML_CTYPE_NAME: /* NAME type doesn't occur at top level of a content model and is handled in some "shotcut" way directly in the CHOICE and SEQ cases. It's only here to pacify gcc -Wall. */ printf ("error!!! - in TncProbeElement: XML_CTYPE_NAME shouldn't reached in any case.\n"); default: printf ("error!!! - in TncProbeElement: unknown content type: %d\n", stackelm->model->type); } /* not reached */ printf ("error!!! - in TncProbeElement: end of function reached.\n"); return 0; } /* *---------------------------------------------------------------------------- * * TncProbeAttribute -- * * This function checks, if the given attribute * and it's value are allowed for this element. * * Results: * 1 if the attribute name/value is OK, * 0 if not. * * Side effects: * Eventually increments the required attributes counter. * *---------------------------------------------------------------------------- */ static int TncProbeAttribute ( void *userData, Tcl_HashTable *elemAtts, char *attrName, char *attrValue, int *nrOfreq ) { TNC_Data *tncdata = (TNC_Data *) userData; Tcl_HashEntry *entryPtr; TNC_AttDecl *attDecl; char *pc, *copy, save; int clen, i, start, hnew; TNC_EntityInfo *entityInfo; entryPtr = Tcl_FindHashEntry (elemAtts, attrName); if (!entryPtr) { signalNotValid (userData, TNC_ERROR_UNKNOWN_ATTRIBUTE); return 0; } /* NOTE: attribute uniqueness per element is a wellformed constrain and therefore done by expat. */ attDecl = (TNC_AttDecl *) Tcl_GetHashValue (entryPtr); switch (attDecl->att_type) { case TNC_ATTTYPE_CDATA: if (attDecl->isrequired && attDecl->dflt) { if (strcmp (attDecl->dflt, attrValue) != 0) { signalNotValid (userData, TNC_ERROR_WRONG_FIXED_ATTVALUE); return 0; } } break; case TNC_ATTTYPE_ID: pc = (char*)attrValue; clen = UTF8_CHAR_LEN (*pc); CHECK_UTF_CHARLENR (clen); if (!UTF8_GET_NAME_START (pc, clen)) { signalNotValid (userData, TNC_ERROR_NAME_REQUIRED); } pc += clen; while (1) { if (*pc == '\0') { break; } clen = UTF8_CHAR_LEN (*pc); CHECK_UTF_CHARLENR (clen); if (!UTF8_GET_NAMING_NMTOKEN (pc, clen)) { signalNotValid (userData, TNC_ERROR_NAME_REQUIRED); return 0; } pc += clen; } entryPtr = Tcl_CreateHashEntry (tncdata->ids, attrValue, &hnew); if (!hnew) { if (Tcl_GetHashValue (entryPtr)) { signalNotValid (userData, TNC_ERROR_DUPLICATE_ID_VALUE); return 0; } } Tcl_SetHashValue (entryPtr, (char *) 1); break; case TNC_ATTTYPE_IDREF: /* Name type constraint "implicit" checked. If the referenced ID exists, the type must be OK, because the type of the ID's within the document are checked. If there isn't such an ID, it's an error anyway. */ if (attrValue[0] == '\0') { signalNotValid (userData, TNC_ERROR_NAME_REQUIRED); return 0; } entryPtr = Tcl_CreateHashEntry (tncdata->ids, attrValue, &hnew); break; case TNC_ATTTYPE_IDREFS: if (attrValue[0] == '\0') { signalNotValid (userData, TNC_ERROR_NAMES_REQUIRED); return 0; } /* Due to attribute value normalization (xml rec 3.3.3) this is a simple list "ref ref ref ..." without leading or trailing spaces and exact one space between the refs. */ start = i = 0; while (attrValue[i]) { if (attrValue[i] == ' ') { save = attrValue[i]; attrValue[i] = '\0'; entryPtr = Tcl_CreateHashEntry (tncdata->ids, &attrValue[start], &hnew); attrValue[i] = save; start = ++i; continue; } i++; } entryPtr = Tcl_CreateHashEntry (tncdata->ids, &attrValue[start], &hnew); break; case TNC_ATTTYPE_ENTITY: /* There is a validity constraint requesting entity attributes values to be type Name. But if there would be an entity declaration that doesn't fit this constraint, expat would have already complained about the definition. So we go the easy way and just look up the att value. If it's declared, type must be OK, if not, it's an error anyway. */ entryPtr = Tcl_FindHashEntry (tncdata->entityDecls, attrValue); if (!entryPtr) { signalNotValid (userData, TNC_ERROR_ENTITY_ATTRIBUTE); return 0; } entityInfo = (TNC_EntityInfo *) Tcl_GetHashValue (entryPtr); if (!entityInfo->is_notation) { signalNotValid (userData, TNC_ERROR_ENTITY_ATTRIBUTE); return 0; } break; case TNC_ATTTYPE_ENTITIES: /* Normalized by exapt; for type see comment to TNC_ATTTYPE_ENTITY */ copy = tdomstrdup (attrValue); start = i = 0; while (1) { if (copy[i] == '\0') { entryPtr = Tcl_FindHashEntry (tncdata->entityDecls, ©[start]); if (!entryPtr) { signalNotValid (userData, TNC_ERROR_ENTITIES_ATTRIBUTE); FREE (copy); return 0; } entityInfo = (TNC_EntityInfo *) Tcl_GetHashValue (entryPtr); if (!entityInfo->is_notation) { signalNotValid (userData, TNC_ERROR_ENTITIES_ATTRIBUTE); FREE (copy); return 0; } FREE (copy); break; } if (copy[i] == ' ') { copy[i] = '\0'; entryPtr = Tcl_FindHashEntry (tncdata->entityDecls, ©[start]); if (!entryPtr) { signalNotValid (userData, TNC_ERROR_ENTITIES_ATTRIBUTE); FREE (copy); return 0; } entityInfo = (TNC_EntityInfo *) Tcl_GetHashValue (entryPtr); if (!entityInfo->is_notation) { signalNotValid (userData, TNC_ERROR_ENTITIES_ATTRIBUTE); FREE (copy); return 0; } start = ++i; continue; } i++; } break; case TNC_ATTTYPE_NMTOKEN: /* We assume, that the UTF-8 representation of the value is valid (no partial chars, minimum encoding). This makes things a little more easy and faster. I guess (but haven't deeply checked - QUESTION -), expat would have already complained otherwise. */ pc = (char*)attrValue; clen = 0; while (1) { if (*pc == '\0') { break; } clen = UTF8_CHAR_LEN (*pc); CHECK_UTF_CHARLENR (clen); if (!UTF8_GET_NAMING_NMTOKEN (pc, clen)) { signalNotValid (userData, TNC_ERROR_NMTOKEN_REQUIRED); return 0; } pc += clen; } if (!clen) signalNotValid (userData, TNC_ERROR_NMTOKEN_REQUIRED); break; case TNC_ATTTYPE_NMTOKENS: pc = (char*)attrValue; clen = 0; while (1) { if (*pc == '\0') { break; } /* NMTOKENS are normalized by expat, so this should be secure. */ if (*pc == ' ') { pc++; } clen = UTF8_CHAR_LEN (*pc); CHECK_UTF_CHARLENR (clen); if (!UTF8_GET_NAMING_NMTOKEN (pc, clen)) { signalNotValid (userData, TNC_ERROR_NMTOKEN_REQUIRED); return 0; } pc += clen; } if (!clen) signalNotValid (userData, TNC_ERROR_NMTOKEN_REQUIRED); break; case TNC_ATTTYPE_NOTATION: entryPtr = Tcl_FindHashEntry (attDecl->lookupTable, attrValue); if (!entryPtr) { signalNotValid (userData, TNC_ERROR_NOTATION_REQUIRED); return 0; } break; case TNC_ATTTYPE_ENUMERATION: if (!Tcl_FindHashEntry (attDecl->lookupTable, attrValue)) { signalNotValid (userData, TNC_ERROR_ENUM_ATT_WRONG_VALUE); return 0; } break; } if (attDecl->isrequired) { (*nrOfreq)++; } return 1; } /* *---------------------------------------------------------------------------- * * TncElementStartCommand -- * * This procedure is called for every element start event * while parsing XML Data with a "tnc" enabled tclexpat * parser. Checks, if the element can occur here and if it * has an acceptable set of attributes. * * Results: * None. * * Side effects: * Eventually signals application error. * *---------------------------------------------------------------------------- */ void TncElementStartCommand ( void *userData, const char *name, const char **atts ) { TNC_Data *tncdata = (TNC_Data *) userData; Tcl_HashEntry *entryPtr; Tcl_HashTable *elemAtts; const char **atPtr; TNC_ElemAttInfo *elemAttInfo; TNC_Content *model; int result, nrOfreq, acceptNoDoctype = 0; #ifdef TNC_DEBUG printf ("TncElementStartCommand name: %s\n", name); #endif /* If the document doesn't have a doctype declaration, but the user have used the -useForeignDTD 1 feature, the collected data out of the provided DTD isn't postprocessed by TncElementStartCommand. We do this now. NOTE: Since there wasn't a doctype declaration, there is no information available which element is expected to be the document element. Eventually it would be desirable, to set this somehow. For now, this means, that every valid subtree of the given DTD information is accepted. */ if (!tncdata->contentStackPtr && !tncdata->elemContentsRewriten) { TncEndDoctypeDeclHandler (userData); acceptNoDoctype = 1; } entryPtr = Tcl_FindHashEntry (tncdata->tagNames, name); if (!entryPtr) { signalNotValid (userData, TNC_ERROR_UNKNOWN_ELEMENT); return; } model = (TNC_Content *) Tcl_GetHashValue (entryPtr); switch (model->type) { case XML_CTYPE_MIXED: case XML_CTYPE_ANY: tncdata->skipWhiteCDATAs = 1; tncdata->ignorePCDATA = 1; break; case XML_CTYPE_EMPTY: tncdata->skipWhiteCDATAs = 0; break; case XML_CTYPE_CHOICE: case XML_CTYPE_SEQ: tncdata->skipWhiteCDATAs = 1; tncdata->ignorePCDATA = 0; break; case XML_CTYPE_NAME: break; } if (tncdata->contentStackPtr) { /* This is the normal case, within some content, at least the root element content. */ while (1) { result = TncProbeElement (entryPtr, tncdata); if (result == -1) { if (tncdata->contentStack[tncdata->contentStackPtr - 1].deep == 0) { signalNotValid (userData, TNC_ERROR_ELEMENT_NOT_ALLOWED_HERE); return; } tncdata->contentStackPtr--; continue; } if (result) { break; } if (!result) { signalNotValid (userData, TNC_ERROR_ELEMENT_NOT_ALLOWED_HERE); return; } } if (tncdata->contentStackPtr == tncdata->contentStackSize) { tncdata->contentStackSize *= 2; tncdata->contentStack = (TNC_ContentStack *) Tcl_Realloc ((char *)tncdata->contentStack, sizeof (TNC_Content *)*tncdata->contentStackSize); } (&tncdata->contentStack[tncdata->contentStackPtr])->model = model; (&tncdata->contentStack[tncdata->contentStackPtr])->activeChild = 0; (&tncdata->contentStack[tncdata->contentStackPtr])->deep = 0; (&tncdata->contentStack[tncdata->contentStackPtr])->alreadymatched = 0; tncdata->contentStackPtr++; } else { /* This is only in case of the root element */ if (atts) { if (!tncdata->doctypeName) { if (!acceptNoDoctype) { signalNotValid (userData, TNC_ERROR_NO_DOCTYPE_DECL); return; } } else { if (strcmp (tncdata->doctypeName, name) != 0) { signalNotValid (userData, TNC_ERROR_WRONG_ROOT_ELEMENT); return; } } } (&(tncdata->contentStack)[0])->model = model; (&(tncdata->contentStack)[0])->activeChild = 0; (&(tncdata->contentStack)[0])->deep = 0; (&(tncdata->contentStack)[0])->alreadymatched = 0; tncdata->contentStackPtr++; } if (atts) { elemAttInfo = model->attInfo; if (!elemAttInfo) { if (atts[0] != NULL) { signalNotValid (userData, TNC_ERROR_NO_ATTRIBUTES); return; } } else { elemAtts = elemAttInfo->attributes; nrOfreq = 0; for (atPtr = atts; atPtr[0]; atPtr += 2) { if (!TncProbeAttribute (userData, elemAtts, (char *) atPtr[0], (char *) atPtr[1], &nrOfreq)) return; } if (nrOfreq != elemAttInfo->nrOfreq) { signalNotValid (userData, TNC_ERROR_MISSING_REQUIRED_ATTRIBUTE); return; } } } else { tncdata->elemAttInfo = model->attInfo; } #ifdef TNC_DEBUG printf ("TncElementStartCommand end\n"); #endif } /* *---------------------------------------------------------------------------- * * TncProbeElementEnd -- * * This procedure checks, if the current content allows the * the element to end here. * * Results: * 1 if element end is OK, * 0 if not. * * Side effects: * Let the contentStackPtr point to the last current content * model before the element had started. * *---------------------------------------------------------------------------- */ static int TncProbeElementEnd ( TNC_Data *tncdata ) { TNC_ContentStack stackelm; unsigned int i; int zeroMatchPossible, seqstartindex; stackelm = tncdata->contentStack[tncdata->contentStackPtr - 1]; switch (stackelm.model->type) { case XML_CTYPE_MIXED: case XML_CTYPE_ANY: case XML_CTYPE_EMPTY: return 1; case XML_CTYPE_CHOICE: if (stackelm.alreadymatched) { return 1; } if (stackelm.model->quant == XML_CQUANT_REP || stackelm.model->quant == XML_CQUANT_OPT) { return 1; } zeroMatchPossible = 0; for (i = 0; i < stackelm.model->numchildren; i++) { if ((&stackelm.model->children[i])->type == XML_CTYPE_NAME) { if ((&stackelm.model->children[i])->quant == XML_CQUANT_OPT || (&stackelm.model->children[i])->quant == XML_CQUANT_REP) { zeroMatchPossible = 1; break; } } else { if (tncdata->contentStackPtr == tncdata->contentStackSize) { tncdata->contentStack = (TNC_ContentStack *) Tcl_Realloc ((char *)tncdata->contentStack, sizeof (TNC_Content *) * 2 * tncdata->contentStackSize); tncdata->contentStackSize *= 2; } (&tncdata->contentStack[tncdata->contentStackPtr])->model = &stackelm.model->children[i]; tncdata->contentStack[tncdata->contentStackPtr].activeChild = 0; tncdata->contentStack[tncdata->contentStackPtr].deep = stackelm.deep + 1; tncdata->contentStack[tncdata->contentStackPtr].alreadymatched = 0; tncdata->contentStackPtr++; if (TncProbeElementEnd (tncdata)) { zeroMatchPossible = 1; tncdata->contentStackPtr--; break; } tncdata->contentStackPtr--; } } if (zeroMatchPossible) { return 1; } else { return 0; } case XML_CTYPE_SEQ: if (!stackelm.alreadymatched) { if (stackelm.model->quant == XML_CQUANT_REP || stackelm.model->quant == XML_CQUANT_OPT) { return 1; } } if (!stackelm.alreadymatched) { seqstartindex = 0; } else { seqstartindex = stackelm.activeChild + 1; } for (i = seqstartindex; i < stackelm.model->numchildren; i++) { if ((&stackelm.model->children[i])->type == XML_CTYPE_NAME) { if ((&stackelm.model->children[i])->quant == XML_CQUANT_OPT || (&stackelm.model->children[i])->quant == XML_CQUANT_REP) { continue; } else { return 0; } } else { if (tncdata->contentStackPtr == tncdata->contentStackSize) { tncdata->contentStack = (TNC_ContentStack *) Tcl_Realloc ((char *)tncdata->contentStack, sizeof (TNC_Content *) * 2 * tncdata->contentStackSize); tncdata->contentStackSize *= 2; } (&tncdata->contentStack[tncdata->contentStackPtr])->model = &stackelm.model->children[i]; tncdata->contentStack[tncdata->contentStackPtr].activeChild = 0; tncdata->contentStack[tncdata->contentStackPtr].deep = stackelm.deep + 1; tncdata->contentStack[tncdata->contentStackPtr].alreadymatched = 0; tncdata->contentStackPtr++; if (TncProbeElementEnd (tncdata)) { tncdata->contentStackPtr--; continue; } else { tncdata->contentStackPtr--; return 0; } } } return 1; case XML_CTYPE_NAME: /* NAME type doesn't occur at top level of a content model and is handled in some "shotcut" way directly in the CHOICE and SEQ cases. It's only here to pacify gcc -Wall. */ fprintf (stderr, "error!!! - in TncProbeElementEnd: XML_CTYPE_NAME " "shouldn't be reached in any case.\n"); default: fprintf (stderr, "error!!! - in TncProbeElementEnd: unknown content " "type: %d\n", stackelm.model->type); return 1; } } /* *---------------------------------------------------------------------------- * * TncElementEndCommand -- * * This procedure is called for every element end event * while parsing XML Data with a "tnc" enabled tclexpat * parser. Checks, if the content model allows the element * to end at this point. * * Results: * None. * * Side effects: * Eventually signals application error. * *---------------------------------------------------------------------------- */ void TncElementEndCommand ( void *userData, const char *name ) { TNC_Data *tncdata = (TNC_Data *) userData; Tcl_HashEntry *entryPtr; Tcl_HashSearch search; #ifdef TNC_DEBUG printf ("TncElementEndCommand start\n"); printContentStack (tncdata); #endif while (1) { if (!TncProbeElementEnd (tncdata)) { signalNotValid (userData, TNC_ERROR_ELEMENT_CAN_NOT_END_HERE); return; } if (tncdata->contentStack[tncdata->contentStackPtr - 1].deep == 0) { break; } tncdata->contentStackPtr--; } /* Remove the content model of the closed element from the stack */ tncdata->contentStackPtr--; #ifdef TNC_DEBUG printf ("after removing ended element from the stack\n"); printContentStack (tncdata); #endif if (tncdata->contentStackPtr) { switch ((&tncdata->contentStack[tncdata->contentStackPtr - 1])->model->type) { case XML_CTYPE_MIXED: case XML_CTYPE_ANY: tncdata->skipWhiteCDATAs = 1; tncdata->ignorePCDATA = 1; break; case XML_CTYPE_EMPTY: tncdata->skipWhiteCDATAs = 0; break; case XML_CTYPE_CHOICE: case XML_CTYPE_SEQ: case XML_CTYPE_NAME: tncdata->skipWhiteCDATAs = 1; tncdata->ignorePCDATA = 0; break; } } else { /* This means, the root element is closed, therefore, the place to check, if every IDREF points to an ID. */ if (tncdata->idCheck) { for (entryPtr = Tcl_FirstHashEntry (tncdata->ids, &search); entryPtr != NULL; entryPtr = Tcl_NextHashEntry (&search)) { #ifdef TNC_DEBUG printf ("check id value %s\n", Tcl_GetHashKey (tncdata->ids, entryPtr)); printf ("value %p\n", Tcl_GetHashValue (entryPtr)); #endif if (!Tcl_GetHashValue (entryPtr)) { signalNotValid (userData, TNC_ERROR_UNKNOWN_ID_REFERRED); return; } } } } } /* *---------------------------------------------------------------------------- * * TncCharacterdataCommand -- * * This procedure is called with a piece of CDATA found in * document. * * Results: * None. * * Side effects: * Eventually signals application error. * *---------------------------------------------------------------------------- */ void TncCharacterdataCommand ( void *userData, const char *data, domLength len ) { TNC_Data *tncdata = (TNC_Data *) userData; int i; char *pc; if (!tncdata->skipWhiteCDATAs && len > 0) { signalNotValid (userData, TNC_ERROR_EMPTY_ELEMENT); return; } if (!tncdata->ignorePCDATA) { for (i = 0, pc = (char*)data; i < len; i++, pc++) { if ( (*pc == ' ') || (*pc == '\n') || (*pc == '\r') || (*pc == '\t') ) { continue; } signalNotValid (userData, TNC_ERROR_DISALLOWED_PCDATA); return; } } } /* *---------------------------------------------------------------------------- * * TncStartCdataSectionHandler -- * * This procedure is called at the start of a CDATA section * within the document. * * Results: * None. * * Side effects: * Eventually signals application error. * *---------------------------------------------------------------------------- */ void TncStartCdataSectionHandler ( void *userData ) { TNC_Data *tncdata = (TNC_Data *) userData; if (!tncdata->ignorePCDATA) { signalNotValid (userData, TNC_ERROR_DISALLOWED_CDATA); } } /* *---------------------------------------------------------------------------- * * validateNodeAttributes -- * * Validates the attributes of the given domNode. The domNode must be * an ELEMENT_NODE. * * Results: * 1 if OK, 0 for validation error. * * Side effects: * None. * *---------------------------------------------------------------------------- */ static int validateNodeAttributes ( TNC_Data *tncdata, TNC_ElemAttInfo *elemAttInfo, domNode *node ) { int nrOfreq; domAttrNode *attr; if (!elemAttInfo) { if (node->firstAttr) { signalNotValid (tncdata, TNC_ERROR_NO_ATTRIBUTES); return 0; } } else { attr = node->firstAttr; nrOfreq = 0; while (attr) { if (!TncProbeAttribute (tncdata, elemAttInfo->attributes, attr->nodeName, attr->nodeValue, &nrOfreq)) return 0; attr = attr->nextSibling; } if (nrOfreq != elemAttInfo->nrOfreq) { signalNotValid (tncdata, TNC_ERROR_MISSING_REQUIRED_ATTRIBUTE); return 0; } } return 1; } /* *---------------------------------------------------------------------------- * * validateTree -- * * Validates a complete DOM (sub-)tree against the DTD information in * the given tncdata structure. The node argument acts as root of the * (sub-)tree. * * Results: * 1 if OK, 0 for validation error. * * Side effects: * May alter the context state part of the tnc clientData (and even * mallocs additional memory for them). * *---------------------------------------------------------------------------- */ static int validateTree ( TNC_Data *tncdata, domNode *node ) { domNode *child; switch (node->nodeType) { case ELEMENT_NODE: TncElementStartCommand (tncdata, node->nodeName, NULL); if (tncdata->dtdstatus) return 0; if (!validateNodeAttributes (tncdata, tncdata->elemAttInfo, node)) return 0; if (node->firstChild) { child = node->firstChild; while (child) { if (!validateTree (tncdata, child)) return 0; child = child->nextSibling; } } TncElementEndCommand (tncdata, node->nodeName); if (tncdata->dtdstatus) return 0; break; case TEXT_NODE: case CDATA_SECTION_NODE: TncCharacterdataCommand (tncdata, ((domTextNode*)node)->nodeValue, ((domTextNode*)node)->valueLength); if (tncdata->dtdstatus) return 0; break; case COMMENT_NODE: case PROCESSING_INSTRUCTION_NODE: break; default: signalNotValid (tncdata, TNC_ERROR_UNKNOWN_NODE_TYPE); return 0; } return 1; } /* *---------------------------------------------------------------------------- * * tnc_ValidateObjCmd * * Implements the validateObjCmds. See the user documentation * for details. * * Results: * A standard Tcl result. * * Side effects: * May alter some parts of the tnc_ValidateObjCmd clientData * structure. * *---------------------------------------------------------------------------- */ static int tnc_ValidateObjCmd ( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { TNC_Data *tncdata = (TNC_Data*) clientData; int methodIndex, result = 1; domNode *node; char *errMsg = NULL; Tcl_HashEntry *entryPtr; TNC_Content *model; static const char *validateMethods[] = { "validateTree", "validateDocument", "validateAttributes", "delete", NULL }; enum validateMethod { m_validateTree, m_validateDocument, m_validateAttributes, m_delete }; if (objc < 2 || objc > 4) { SetResult (validateCmd_usage); return TCL_ERROR; } if (Tcl_GetIndexFromObj (interp, objv[1], validateMethods, "method", 0, &methodIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum validateMethod) methodIndex) { case m_validateTree: if (objc < 3 || objc > 4) { SetResult (validateCmd_usage); return TCL_ERROR; } node = tcldom_getNodeFromName ( interp, Tcl_GetStringFromObj(objv[2], NULL), &errMsg ); if (!node || (node->nodeType != ELEMENT_NODE)) { SetResult ("The validateTree method needs a domNode as argument."); return TCL_ERROR; } tncdata->dtdstatus = 0; tncdata->idCheck = 0; if (tncdata->ids->numEntries) { Tcl_DeleteHashTable (tncdata->ids); Tcl_InitHashTable (tncdata->ids, TCL_STRING_KEYS); } tncdata->contentStackPtr = 0; Tcl_ResetResult (interp); result = validateTree (tncdata, node); if (objc == 4) { if (Tcl_ObjSetVar2(interp, objv[3], NULL, Tcl_GetObjResult(interp), 0) == NULL) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "couldn't save msg in variable", -1); return TCL_ERROR; } } if (result) { SetBooleanResult (1); } else { SetBooleanResult (0); } break; case m_validateDocument: if (objc < 3 || objc > 4) { SetResult (validateCmd_usage); return TCL_ERROR; } node = (domNode *) tcldom_getDocumentFromName ( interp, Tcl_GetStringFromObj (objv[2], NULL), &errMsg ); if (!node) { SetResult ("The validateDocument method needs a domDocument as argument."); return TCL_ERROR; } node = ((domDocument *) node)->documentElement; if (!tncdata->doctypeName) { signalNotValid (tncdata, TNC_ERROR_NO_DOCTYPE_DECL); if (objc == 4) { if (Tcl_ObjSetVar2(interp, objv[3], NULL, Tcl_GetObjResult(interp), 0) == NULL) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "couldn't save msg in variable", -1); return TCL_ERROR; } } SetBooleanResult (0); return TCL_OK; } if (strcmp (tncdata->doctypeName, node->nodeName) != 0) { signalNotValid (tncdata, TNC_ERROR_WRONG_ROOT_ELEMENT); if (objc == 4) { if (Tcl_ObjSetVar2(interp, objv[3], NULL, Tcl_GetObjResult(interp), 0) == NULL) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "couldn't save msg in variable", -1); return TCL_ERROR; } } SetBooleanResult (0); return TCL_OK; } tncdata->dtdstatus = 0; tncdata->idCheck = 1; if (tncdata->ids->numEntries) { Tcl_DeleteHashTable (tncdata->ids); Tcl_InitHashTable (tncdata->ids, TCL_STRING_KEYS); } tncdata->contentStackPtr = 0; Tcl_ResetResult (interp); result = validateTree (tncdata, node); if (objc == 4) { if (Tcl_ObjSetVar2(interp, objv[3], NULL, Tcl_GetObjResult(interp), 0) == NULL) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "couldn't save msg in variable", -1); return TCL_ERROR; } } if (result) { SetBooleanResult (1); } else { SetBooleanResult (0); } break; case m_validateAttributes: if (objc < 3 || objc > 4) { SetResult (validateCmd_usage); return TCL_ERROR; } node = tcldom_getNodeFromName ( interp, Tcl_GetStringFromObj(objv[2], NULL), &errMsg ); if (!node || (node->nodeType != ELEMENT_NODE)) { SetResult ("The validateAttributes method needs a domNode as argument."); return TCL_ERROR; } entryPtr = Tcl_FindHashEntry (tncdata->tagNames, node->nodeName); if (!entryPtr) { signalNotValid (tncdata, TNC_ERROR_UNKNOWN_ELEMENT); if (objc == 4) { if (Tcl_ObjSetVar2(interp, objv[3], NULL, Tcl_GetObjResult(interp), 0) == NULL) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "couldn't save msg in variable", -1); return TCL_ERROR; } } SetBooleanResult (0); return TCL_OK; } model = (TNC_Content *) Tcl_GetHashValue (entryPtr); tncdata->dtdstatus = 0; tncdata->idCheck = 0; if (tncdata->ids->numEntries) { Tcl_DeleteHashTable (tncdata->ids); Tcl_InitHashTable (tncdata->ids, TCL_STRING_KEYS); } Tcl_ResetResult (interp); result = validateNodeAttributes (tncdata, model->attInfo, node); if (objc == 4) { if (Tcl_ObjSetVar2(interp, objv[3], NULL, Tcl_GetObjResult(interp), 0) == NULL) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "couldn't save msg in variable", -1); return TCL_ERROR; } } if (result) { SetBooleanResult (1); } else { SetBooleanResult (0); } break; case m_delete: if (objc != 2) { SetResult (validateCmd_usage); return TCL_ERROR; } Tcl_DeleteCommand (interp, Tcl_GetStringFromObj (objv[0], NULL)); SetResult (""); break; } return TCL_OK; } /* *---------------------------------------------------------------------------- * * FreeTncData * * Helper proc, used from TncResetProc and TncFreeProc. Frees all * collected DTD data and the id table. * * Results: * None. * * Side effects: * Frees memory. * *---------------------------------------------------------------------------- */ static void FreeTncData ( TNC_Data *tncdata ) { Tcl_HashEntry *entryPtr, *attentryPtr; Tcl_HashSearch search, attsearch; TNC_Content *model; TNC_ElemAttInfo *elemAttInfo; TNC_EntityInfo *entityInfo; TNC_AttDecl *attDecl; if (tncdata->elemContentsRewriten) { entryPtr = Tcl_FirstHashEntry (tncdata->tagNames, &search); while (entryPtr) { model = Tcl_GetHashValue (entryPtr); if (model) { TncFreeTncModel (model); FREE ((char *) model); } entryPtr = Tcl_NextHashEntry (&search); } } Tcl_DeleteHashTable (tncdata->tagNames); entryPtr = Tcl_FirstHashEntry (tncdata->attDefsTables, &search); while (entryPtr) { elemAttInfo = Tcl_GetHashValue (entryPtr); if (!elemAttInfo) { entryPtr = Tcl_NextHashEntry (&search); continue; } attentryPtr = Tcl_FirstHashEntry (elemAttInfo->attributes, &attsearch); while (attentryPtr) { attDecl = Tcl_GetHashValue (attentryPtr); if (attDecl) { if (attDecl->att_type == TNC_ATTTYPE_NOTATION || attDecl->att_type == TNC_ATTTYPE_ENUMERATION) { Tcl_DeleteHashTable (attDecl->lookupTable); FREE ((char *) attDecl->lookupTable); } if (attDecl->dflt) { FREE (attDecl->dflt); } FREE ((char *) attDecl); } attentryPtr = Tcl_NextHashEntry (&attsearch); } Tcl_DeleteHashTable (elemAttInfo->attributes); FREE ((char *) elemAttInfo->attributes); FREE ((char *) elemAttInfo); entryPtr = Tcl_NextHashEntry (&search); } Tcl_DeleteHashTable (tncdata->attDefsTables); entryPtr = Tcl_FirstHashEntry (tncdata->entityDecls, &search); while (entryPtr) { entityInfo = Tcl_GetHashValue (entryPtr); if (entityInfo) { if (entityInfo->is_notation) { FREE (entityInfo->notationName); } FREE ((char *) entityInfo); } entryPtr = Tcl_NextHashEntry (&search); } Tcl_DeleteHashTable (tncdata->entityDecls); Tcl_DeleteHashTable (tncdata->notationDecls); Tcl_DeleteHashTable (tncdata->ids); if (tncdata->doctypeName) { FREE (tncdata->doctypeName); } } /* *---------------------------------------------------------------------------- * * TncResetProc * * Called for C handler set specific reset actions in case of * parser reset. * * Results: * None. * * Side effects: * Resets the "userData" of the C handler set parser extension. * *---------------------------------------------------------------------------- */ void TncResetProc ( Tcl_Interp *interp, void *userData ) { TNC_Data *tncdata = (TNC_Data *) userData; FreeTncData (tncdata); Tcl_InitHashTable (tncdata->tagNames, TCL_STRING_KEYS); tncdata->elemContentsRewriten = 0; tncdata->dtdstatus = 0; tncdata->idCheck = 1; Tcl_InitHashTable (tncdata->attDefsTables, TCL_STRING_KEYS); Tcl_InitHashTable (tncdata->entityDecls, TCL_STRING_KEYS); Tcl_InitHashTable (tncdata->notationDecls, TCL_STRING_KEYS); Tcl_InitHashTable (tncdata->ids, TCL_STRING_KEYS); tncdata->doctypeName = NULL; tncdata->skipWhiteCDATAs = 1; tncdata->ignorePCDATA = 0; tncdata->contentStackPtr = 0; } /* *---------------------------------------------------------------------------- * * createTncData -- * * Helper proc. Allocates a TNC_Data structure and initializes it. * * Results: * None. * * Side effects: * Memory allocation and initialization. * *---------------------------------------------------------------------------- */ static TNC_Data * createTncData ( Tcl_Interp *interp, Tcl_Obj *expatObj ) { TNC_Data *tncdata; tncdata = (TNC_Data *) MALLOC (sizeof (TNC_Data)); tncdata->tagNames = (Tcl_HashTable *) MALLOC (sizeof (Tcl_HashTable)); Tcl_InitHashTable (tncdata->tagNames, TCL_STRING_KEYS); tncdata->elemContentsRewriten = 0; tncdata->dtdstatus = 0; tncdata->idCheck = 1; tncdata->attDefsTables = (Tcl_HashTable *) MALLOC (sizeof (Tcl_HashTable)); Tcl_InitHashTable (tncdata->attDefsTables, TCL_STRING_KEYS); tncdata->entityDecls = (Tcl_HashTable *) MALLOC (sizeof (Tcl_HashTable)); Tcl_InitHashTable (tncdata->entityDecls, TCL_STRING_KEYS); tncdata->notationDecls = (Tcl_HashTable *) MALLOC (sizeof (Tcl_HashTable)); Tcl_InitHashTable (tncdata->notationDecls, TCL_STRING_KEYS); tncdata->ids = (Tcl_HashTable *) MALLOC (sizeof (Tcl_HashTable)); Tcl_InitHashTable (tncdata->ids, TCL_STRING_KEYS); tncdata->doctypeName = NULL; tncdata->interp = interp; tncdata->expatObj = expatObj; tncdata->skipWhiteCDATAs = 1; tncdata->ignorePCDATA = 0; tncdata->contentStack = (TNC_ContentStack *) MALLOC (sizeof (TNC_ContentStack) * TNC_INITCONTENTSTACKSIZE); tncdata->contentStackSize = TNC_INITCONTENTSTACKSIZE; tncdata->contentStackPtr = 0; return tncdata; } /* *---------------------------------------------------------------------------- * * TncFreeProc * * Called for C handler set specific cleanup in case of parser * delete. * * Results: * None. * * Side effects: * C handler set specific userData gets free'd. * *---------------------------------------------------------------------------- */ void TncFreeProc ( Tcl_Interp *interp, void *userData ) { TNC_Data *tncdata = (TNC_Data *) userData; FreeTncData (tncdata); FREE ((char *) tncdata->tagNames); FREE ((char *) tncdata->attDefsTables); FREE ((char *) tncdata->entityDecls); FREE ((char *) tncdata->notationDecls); FREE ((char *) tncdata->ids); FREE ((char *) tncdata->contentStack); FREE ((char *) tncdata); } /* *---------------------------------------------------------------------------- * * tnc_ValidateObjDeleteCmd * * Called when a validateObjCmd is deleted. It's infact nothing * but a wrapper for TncFreeProc. * * Results: * None. * * Side effects: * The clientData structure will be freed, during cleanup routine calls. * *---------------------------------------------------------------------------- */ static void tnc_ValidateObjDeleteCmd ( ClientData clientData ) { TNC_Data *tncdata = (TNC_Data*) clientData; TncFreeProc (tncdata->interp, tncdata); } /* *---------------------------------------------------------------------------- * * TclTncObjCmd -- * * This procedure is invoked to process the "tnc" command. * * Results: * A standard Tcl result. * * Side effects: * The expat parser object provided as argument is enhanced by * by the "tnc" handler set. * *---------------------------------------------------------------------------- */ int TclTncObjCmd(dummy, interp, objc, objv) ClientData dummy; Tcl_Interp *interp; int objc; Tcl_Obj *const objv[]; { char *cmdName, s[20]; CHandlerSet *handlerSet; int methodIndex, result; TNC_Data *tncdata; static const char *tncMethods[] = { "enable", "remove", "getValidateCmd", NULL }; enum tncMethod { m_enable, m_remove, m_getValidateCmd }; if (!CheckExpatParserObj (interp, objv[1])) { SetResult ("First argument has to be a expat parser object"); return TCL_ERROR; } if (Tcl_GetIndexFromObj (interp, objv[2], tncMethods, "method", 0, &methodIndex) != TCL_OK) { return TCL_ERROR; } switch ((enum tncMethod) methodIndex) { case m_enable: if (objc != 3) { Tcl_WrongNumArgs (interp, 1, objv, tnc_usage); return TCL_ERROR; } handlerSet = CHandlerSetCreate ("tnc"); handlerSet->userData = createTncData (interp, objv[1]); handlerSet->ignoreWhiteCDATAs = 0; handlerSet->resetProc = TncResetProc; handlerSet->freeProc = TncFreeProc; handlerSet->elementDeclCommand = TncElementDeclCommand; handlerSet->attlistDeclCommand = TncAttDeclCommand; handlerSet->entityDeclCommand = TncEntityDeclHandler; handlerSet->notationcommand = TncNotationDeclHandler; handlerSet->elementstartcommand = TncElementStartCommand; handlerSet->elementendcommand = TncElementEndCommand; handlerSet->datacommand = TncCharacterdataCommand; handlerSet->startCdataSectionCommand = TncStartCdataSectionHandler; handlerSet->startDoctypeDeclCommand = TncStartDoctypeDeclHandler; handlerSet->endDoctypeDeclCommand = TncEndDoctypeDeclHandler; result = CHandlerSetInstall (interp, objv[1], handlerSet); if (result != 0) { SetResult ("already have tnc C handler set"); TncFreeProc (interp, handlerSet->userData); FREE (handlerSet->name); FREE ((char *) handlerSet); return TCL_ERROR; } return TCL_OK; case m_remove: if (objc != 3) { Tcl_WrongNumArgs (interp, 1, objv, tnc_usage); return TCL_ERROR; } result = CHandlerSetRemove (interp, objv[1], "tnc"); if (result == 1) { /* This should not happen if CheckExpatParserObj() is used. */ SetResult ("argument has to be a expat parser object"); return TCL_ERROR; } if (result == 2) { SetResult("expat parser obj hasn't a C handler set named \"tnc\""); return TCL_ERROR; } return TCL_OK; case m_getValidateCmd: if (objc != 3 && objc != 4) { Tcl_WrongNumArgs (interp, 1, objv, tnc_usage); return TCL_ERROR; } handlerSet = CHandlerSetGet (interp, objv[1], "tnc"); if (!handlerSet) { SetResult("expat parser obj hasn't a C handler set named \"tnc\""); return TCL_ERROR; } tncdata = (TNC_Data *) handlerSet->userData; if (!tncdata->dtdstatus) { SetResult ("No complete and error free DTD data available."); return TCL_ERROR; } /* After we finished, the validator structure is its own command, there isn't a parser cmd anymore. */ tncdata->expatObj = NULL; tncdata->dtdstatus = 0; handlerSet->userData = createTncData (interp, objv[1]); if (objc == 4) { cmdName = Tcl_GetStringFromObj (objv[3], NULL); } else { FindUniqueCmdName (interp, s); cmdName = s; } Tcl_CreateObjCommand (interp, cmdName, tnc_ValidateObjCmd, tncdata, tnc_ValidateObjDeleteCmd); Tcl_SetResult (interp, cmdName, TCL_VOLATILE); return TCL_OK; default: Tcl_SetResult (interp, "unknown method", NULL); return TCL_ERROR; } } #ifdef BUILD_tnc # undef TCL_STORAGE_CLASS # define TCL_STORAGE_CLASS DLLEXPORT #endif /* *---------------------------------------------------------------------------- * * Tnc_Init -- * * Initialization routine for loadable module * * Results: * None. * * Side effects: * Defines "tnc" enhancement command for expat parser obj * *---------------------------------------------------------------------------- */ #if defined(_MSC_VER) || defined(__MINGW32__) # undef TCL_STORAGE_CLASS # define TCL_STORAGE_CLASS DLLEXPORT #endif #if TCL_MAJOR_VERSION == 8 # define STUB_VERSION "8.5" #else # define STUB_VERSION "9.0" #endif EXTERN int Tnc_Init (interp) Tcl_Interp *interp; { #ifdef USE_TCL_STUBS if (Tcl_InitStubs(interp, STUB_VERSION, 0) == NULL) { return TCL_ERROR; } #endif #ifdef USE_TDOM_STUBS if (Tdom_InitStubs(interp, "0.8", 0) == NULL) { return TCL_ERROR; } #endif Tcl_PkgRequire (interp, "tdom", NULL, 0); Tcl_CreateObjCommand (interp, "tnc", TclTncObjCmd, NULL, NULL ); Tcl_PkgProvide (interp, "tnc", PACKAGE_VERSION); return TCL_OK; } tdom-0.9.5-src/extensions/tnc/Makefile.in0000644000175000017500000003760014703531020016774 0ustar rolfrolf# Makefile.in -- # # This file is a Makefile for Sample TEA Extension. If it has the name # "Makefile.in" then it is a template for a Makefile; to generate the # actual Makefile, run "./configure", which is a configuration script # generated by the "autoconf" program (constructs like "@foo@" will get # replaced in the actual Makefile. # # Copyright (c) 1999 Scriptics Corporation. # Copyright (c) 2002-2005 ActiveState Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. #======================================================================== # Add additional lines to handle any additional AC_SUBST cases that # have been added in a customized configure script. #======================================================================== #SAMPLE_NEW_VAR = @SAMPLE_NEW_VAR@ #======================================================================== # Nothing of the variables below this line should need to be changed. # Please check the TARGETS section below to make sure the make targets # are correct. #======================================================================== #======================================================================== # The names of the source files is defined in the configure script. # The object files are used for linking into the final library. # This will be used when a dist target is added to the Makefile. # It is not important to specify the directory, as long as it is the # $(srcdir) or in the generic, win or unix subdirectory. #======================================================================== PKG_SOURCES = @PKG_SOURCES@ PKG_OBJECTS = @PKG_OBJECTS@ PKG_STUB_SOURCES = @PKG_STUB_SOURCES@ PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@ #======================================================================== # PKG_TCL_SOURCES identifies Tcl runtime files that are associated with # this package that need to be installed, if any. #======================================================================== PKG_TCL_SOURCES = @PKG_TCL_SOURCES@ #======================================================================== # This is a list of public header files to be installed, if any. #======================================================================== PKG_HEADERS = @PKG_HEADERS@ #======================================================================== # "PKG_LIB_FILE" refers to the library (dynamic or static as per # configuration options) composed of the named objects. #======================================================================== PKG_LIB_FILE = @PKG_LIB_FILE@ PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@ lib_BINARIES = $(PKG_LIB_FILE) BINARIES = $(lib_BINARIES) SHELL = @SHELL@ srcdir = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ includedir = @includedir@ datarootdir = @datarootdir@ datadir = @datadir@ mandir = @mandir@ DESTDIR = PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION) pkgdatadir = $(datadir)/$(PKG_DIR) pkglibdir = $(libdir)/$(PKG_DIR) pkgincludedir = $(includedir)/$(PKG_DIR) top_builddir = . INSTALL_OPTIONS = INSTALL = $(SHELL) $(srcdir)/../../tclconfig/install-sh -c ${INSTALL_OPTIONS} INSTALL_DATA_DIR = ${INSTALL} -d -m 755 INSTALL_PROGRAM = ${INSTALL} -m 555 INSTALL_DATA = ${INSTALL} -m 444 INSTALL_SCRIPT = ${INSTALL_PROGRAM} INSTALL_LIBRARY = ${INSTALL_DATA} PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ CC = @CC@ CFLAGS_DEFAULT = @CFLAGS_DEFAULT@ CFLAGS_WARNING = @CFLAGS_WARNING@ EXEEXT = @EXEEXT@ LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@ MAKE_LIB = @MAKE_LIB@ MAKE_SHARED_LIB = @MAKE_SHARED_LIB@ MAKE_STATIC_LIB = @MAKE_STATIC_LIB@ MAKE_STUB_LIB = @MAKE_STUB_LIB@ OBJEXT = @OBJEXT@ RANLIB = @RANLIB@ RANLIB_STUB = @RANLIB_STUB@ SHLIB_CFLAGS = @SHLIB_CFLAGS@ SHLIB_LD = @SHLIB_LD@ SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ STLIB_LD = @STLIB_LD@ #TCL_DEFS = @TCL_DEFS@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_SRC_DIR = @TCL_SRC_DIR@ #TK_BIN_DIR = @TK_BIN_DIR@ #TK_SRC_DIR = @TK_SRC_DIR@ # Not used, but retained for reference of what libs Tcl required #TCL_LIBS = @TCL_LIBS@ #======================================================================== # TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our # package without installing. The other environment variables allow us # to test against an uninstalled Tcl. Add special env vars that you # require for testing here (like TCLX_LIBRARY). #======================================================================== EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR) #EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR) TCLLIBPATH = $(top_builddir) TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` PKG_ENV = @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ PATH="$(EXTRA_PATH):$(PATH)" \ TCLLIBPATH="$(TCLLIBPATH)" TCLSH_PROG = @TCLSH_PROG@ TCLSH = $(PKG_ENV) $(TCLSH_ENV) $(TCLSH_PROG) #WISH_ENV = TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library` #WISH_PROG = @WISH_PROG@ #WISH = $(PKG_ENV) $(TCLSH_ENV) $(WISH_ENV) $(WISH_PROG) SHARED_BUILD = @SHARED_BUILD@ INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ #INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@ PKG_CFLAGS = @PKG_CFLAGS@ # TCL_DEFS is not strictly need here, but if you remove it, then you # must make sure that configure.in checks for the necessary components # that your library may use. TCL_DEFS can actually be a problem if # you do not compile with a similar machine setup as the Tcl core was # compiled with. #DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS) DEFS = @DEFS@ $(PKG_CFLAGS) # Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl CLEANFILES = @CLEANFILES@ CPPFLAGS = @CPPFLAGS@ LIBS = @PKG_LIBS@ @LIBS@ AR = @AR@ CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) .SUFFIXES: .c .$(OBJEXT) #======================================================================== # Start of user-definable TARGETS section #======================================================================== #======================================================================== # TEA TARGETS. Please note that the "libraries:" target refers to platform # independent files, and the "binaries:" target includes executable programs and # platform-dependent libraries. Modify these targets so that they install # the various pieces of your package. The make and install rules # for the BINARIES that you specified above have already been done. #======================================================================== all: binaries libraries #======================================================================== # The binaries target builds executable programs, Windows .dll's, unix # shared/static libraries, and any other platform-dependent files. # The list of targets to build for "binaries:" is specified at the top # of the Makefile, in the "BINARIES" variable. #======================================================================== binaries: $(BINARIES) libraries: #======================================================================== # Your doc target should differentiate from doc builds (by the developer) # and doc installs (see install-doc), which just install the docs on the # end user machine when building from source. #======================================================================== doc: install: all install-binaries install-libraries install-binaries: binaries install-lib-binaries install-bin-binaries #======================================================================== # This rule installs platform-independent files, such as header files. # The list=...; for p in $$list handles the empty list case x-platform. #======================================================================== install-libraries: libraries @$(INSTALL_DATA_DIR) $(DESTDIR)$(includedir) #======================================================================== # Install documentation. Unix manpages should go in the $(mandir) # directory. #======================================================================== install-doc: doc @$(INSTALL_DATA_DIR) $(DESTDIR)$(mandir)/mann @echo "Installing documentation in $(DESTDIR)$(mandir)" @list='$(srcdir)/doc/*.n'; for i in $$list; do \ echo "Installing $$i"; \ $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \ done test: binaries libraries $(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) shell: binaries libraries @$(TCLSH) $(SCRIPT) gdb: $(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT) VALGRINDARGS = --tool=memcheck --num-callers=8 --leak-resolution=high \ --leak-check=yes --show-reachable=yes -v valgrind: binaries libraries $(TCLSH_ENV) valgrind $(VALGRINDARGS) $(TCLSH_PROG) \ `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) valgrindshell: binaries libraries $(TCLSH_ENV) valgrind $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT) depend: #======================================================================== # $(PKG_LIB_FILE) should be listed as part of the BINARIES variable # mentioned above. That will ensure that this target is built when you # run "make binaries". # # The $(PKG_OBJECTS) objects are created and linked into the final # library. In most cases these object files will correspond to the # source files above. #======================================================================== $(PKG_LIB_FILE): $(PKG_OBJECTS) -rm -f $(PKG_LIB_FILE) ${MAKE_LIB} $(RANLIB) $(PKG_LIB_FILE) $(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS) -rm -f $(PKG_STUB_LIB_FILE) ${MAKE_STUB_LIB} $(RANLIB_STUB) $(PKG_STUB_LIB_FILE) #======================================================================== # We need to enumerate the list of .c to .o lines here. # # In the following lines, $(srcdir) refers to the toplevel directory # containing your extension. If your sources are in a subdirectory, # you will have to modify the paths to reflect this: # # sample.$(OBJEXT): $(srcdir)/generic/sample.c # $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@ # # Setting the VPATH variable to a list of paths will cause the makefile # to look into these paths when resolving .c to .obj dependencies. # As necessary, add $(srcdir):$(srcdir)/compat:.... #======================================================================== VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win:$(srcdir)/macosx .c.@OBJEXT@: $(COMPILE) -c `@CYGPATH@ $<` -o $@ #======================================================================== # Create the pkgIndex.tcl file. #======================================================================== pkgIndex.tcl-hand: @(echo 'package ifneeded $(PACKAGE_NAME) $(PACKAGE_VERSION) \ "package require tdom;\ load [list [file join $$dir $(PKG_LIB_FILE)]];"'\ ) > pkgIndex.tcl #======================================================================== # Distribution creation # You may need to tweak this target to make it work correctly. #======================================================================== #COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar COMPRESS = tar zcvf $(PKG_DIR).tar.gz $(PKG_DIR) DIST_ROOT = /tmp/dist DIST_DIR = $(DIST_ROOT)/$(PKG_DIR) dist-clean: rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.* dist: dist-clean mkdir -p $(DIST_DIR) cp -p $(srcdir)/ChangeLog $(srcdir)/README* $(srcdir)/license* \ $(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \ $(DIST_DIR)/ chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4 chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.in for i in $(srcdir)/*.[ch]; do \ if [ -f $$i ]; then \ cp -p $$i $(DIST_DIR)/ ; \ fi; \ done; mkdir $(DIST_DIR)/tclconfig cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \ $(DIST_DIR)/tclconfig/ chmod 664 $(DIST_DIR)/tclconfig/tcl.m4 chmod +x $(DIST_DIR)/tclconfig/install-sh list='demos doc generic library mac tests unix win'; \ for p in $$list; do \ if test -d $(srcdir)/$$p ; then \ mkdir $(DIST_DIR)/$$p; \ cp -p $(srcdir)/$$p/*.* $(DIST_DIR)/$$p/; \ fi; \ done (cd $(DIST_ROOT); $(COMPRESS);) #======================================================================== # End of user-definable section #======================================================================== #======================================================================== # Don't modify the file to clean here. Instead, set the "CLEANFILES" # variable in configure.in #======================================================================== clean: -test -z "$(BINARIES)" || rm -f $(BINARIES) -rm -f *.$(OBJEXT) core *.core -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean: clean -rm -f *.tab.c -rm -f $(CONFIG_CLEAN_FILES) -rm -f config.cache config.log config.status #======================================================================== # Install binary object libraries. On Windows this includes both .dll and # .lib files. Because the .lib files are not explicitly listed anywhere, # we need to deduce their existence from the .dll file of the same name. # Library files go into the lib directory. # In addition, this will generate the pkgIndex.tcl # file in the install location (assuming it can find a usable tclsh shell) # # You should not have to modify this target. #======================================================================== install-lib-binaries: binaries @$(INSTALL_DATA_DIR) $(DESTDIR)$(pkglibdir) @list='$(lib_BINARIES)'; for p in $$list; do \ if test -f $$p; then \ echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \ $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p; \ stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \ if test "x$$stub" = "xstub"; then \ echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \ $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \ else \ echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \ $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \ fi; \ ext=`echo $$p|sed -e "s/.*\.//"`; \ if test "x$$ext" = "xdll"; then \ lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \ if test -f $$lib; then \ echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \ $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \ fi; \ fi; \ fi; \ done @list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ if test -f $(srcdir)/$$p; then \ destp=`basename $$p`; \ echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \ $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \ fi; \ done @if test "x$(SHARED_BUILD)" = "x1"; then \ echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \ $(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \ fi #======================================================================== # Install binary executables (e.g. .exe files and dependent .dll files) # This is for files that must go in the bin directory (located next to # wish and tclsh), like dependent .dll files on Windows. # # You should not have to modify this target, except to define bin_BINARIES # above if necessary. #======================================================================== install-bin-binaries: binaries @$(INSTALL_DATA_DIR) $(DESTDIR)$(bindir) @list='$(bin_BINARIES)'; for p in $$list; do \ if test -f $$p; then \ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \ fi; \ done Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status uninstall-binaries: list='$(lib_BINARIES)'; for p in $$list; do \ rm -f $(DESTDIR)$(pkglibdir)/$$p; \ done list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ p=`basename $$p`; \ rm -f $(DESTDIR)$(pkglibdir)/$$p; \ done list='$(bin_BINARIES)'; for p in $$list; do \ rm -f $(DESTDIR)$(bindir)/$$p; \ done .PHONY: all binaries clean depend distclean doc install libraries test # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: tdom-0.9.5-src/extensions/tnc/install-sh0000755000175000017500000003305414703531020016732 0ustar rolfrolf#!/bin/sh # install - install a program, script, or datafile scriptversion=2011-04-20.01; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -S $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -S) stripcmd="$stripprog $2" shift;; -t) dst_arg=$2 shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names starting with `-'. case $src in -*) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # Protect names starting with `-'. case $dst in -*) dst=./$dst;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writeable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; -*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test -z "$d" && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: tdom-0.9.5-src/extensions/tnc/test.tcl0000644000175000017500000000120214703531020016377 0ustar rolfrolf if {[catch {package require tnc 0.3} errMsg]} { if {[catch {load ./libtnc0.3.0.so}]} { puts $errMsg exit 1 } } if {[lsearch [namespace children] ::tDOM] == -1} { # tcldomsh without the script library. Source the lib. source [file join [file dir [info script]] ../../lib tdom.tcl] } if {[llength $argv] != 1} { puts stderr "usage: $argv0 " exit 1 } set parser [expat \ -baseurl [tDOM::baseURL $argv] \ -externalentitycommand tDOM::extRefHandler \ -paramentityparsing notstandalone] tnc $parser enable $parser parsefile $argv tdom-0.9.5-src/extensions/tnc/pkgIndex.tcl.in0000644000175000017500000000056714703531020017613 0ustar rolfrolf# tnc Tcl package index file if {[package vsatisfies [package provide Tcl] 9.0-]} { package ifneeded tnc @PACKAGE_VERSION@ \ "package require tdom; \ [list load [file join $dir @PKG_LIB_FILE9@]]" } else { package ifneeded tnc @PACKAGE_VERSION@ \ "package require tdom; \ [list load [file join $dir @PKG_LIB_FILE8@]]" } tdom-0.9.5-src/extensions/tnc/configure.ac0000644000175000017500000001706414703531020017217 0ustar rolfrolf#!/bin/bash -norc dnl This file is an input file used by the GNU "autoconf" program to dnl generate the file "configure", which is run during Tcl installation dnl to configure the system for the local environment. #----------------------------------------------------------------------- # Sample configure.in for Tcl Extensions. The only places you should # need to modify this file are marked by the string __CHANGE__ #----------------------------------------------------------------------- #----------------------------------------------------------------------- # __CHANGE__ # Set your package name and version numbers here. # # This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION # set as provided. These will also be added as -D defs in your Makefile # so you can encode the package version directly into the source files. #----------------------------------------------------------------------- AC_INIT([tnc], [0.3.0]) #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. #-------------------------------------------------------------------- TEA_INIT() AC_CONFIG_AUX_DIR(../../tclconfig) #-------------------------------------------------------------------- # Load the tclConfig.sh file #-------------------------------------------------------------------- TEA_PATH_TCLCONFIG TEA_LOAD_TCLCONFIG #-------------------------------------------------------------------- # Load the tkConfig.sh file if necessary (Tk extension) #-------------------------------------------------------------------- #TEA_PATH_TKCONFIG #TEA_LOAD_TKCONFIG #----------------------------------------------------------------------- # Handle the --prefix=... option by defaulting to what Tcl gave. # Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. #----------------------------------------------------------------------- TEA_PREFIX #----------------------------------------------------------------------- # Standard compiler checks. # This sets up CC by using the CC env var, or looks for gcc otherwise. # This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create # the basic setup necessary to compile executables. #----------------------------------------------------------------------- TEA_SETUP_COMPILER #-------------------------------------------------------------------- # Load the tdomConfig.sh file #-------------------------------------------------------------------- TDOM_PATH_CONFIG TDOM_LOAD_CONFIG #----------------------------------------------------------------------- # __CHANGE__ # Specify the C source files to compile in TEA_ADD_SOURCES, # public headers that need to be installed in TEA_ADD_HEADERS, # stub library C source files to compile in TEA_ADD_STUB_SOURCES, # and runtime Tcl library files in TEA_ADD_TCL_SOURCES. # This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS # and PKG_TCL_SOURCES. #----------------------------------------------------------------------- TEA_ADD_SOURCES([tnc.c]) TEA_ADD_HEADERS([]) TEA_ADD_INCLUDES([-I${srcdir}/../../generic -I${srcdir}/../../expat]) TEA_ADD_LIBS([${TDOM_STUB_LIB_SPEC}]) TEA_ADD_CFLAGS([-DUSE_TDOM_STUBS=1]) TEA_ADD_STUB_SOURCES([]) TEA_ADD_TCL_SOURCES([]) #-------------------------------------------------------------------- # __CHANGE__ # A few miscellaneous platform-specific items: # # Define a special symbol for Windows (BUILD_sample in this case) so # that we create the export library with the dll. # # Windows creates a few extra files that need to be cleaned up. # You can add more files to clean if your extension creates any extra # files. # # TEA_ADD_* any platform specific compiler/build info here. #-------------------------------------------------------------------- if test "${TEA_PLATFORM}" = "windows" ; then #AC_DEFINE(BUILD_tnc, 1, [Build windows export dll]) CLEANFILES="*.lib *.dll *.exp *.ilk *.pdb vc*.pch" #TEA_ADD_SOURCES([win/winFile.c]) #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"]) else CLEANFILES="" #TEA_ADD_SOURCES([unix/unixFile.c]) #TEA_ADD_LIBS([-lsuperfly]) fi AC_SUBST(CLEANFILES) #-------------------------------------------------------------------- # __CHANGE__ # Choose which headers you need. Extension authors should try very # hard to only rely on the Tcl public header files. Internal headers # contain private data structures and are subject to change without # notice. # This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG #-------------------------------------------------------------------- TEA_PUBLIC_TCL_HEADERS #TEA_PRIVATE_TCL_HEADERS #TEA_PUBLIC_TK_HEADERS #TEA_PRIVATE_TK_HEADERS #TEA_PATH_X #-------------------------------------------------------------------- # Check whether --enable-threads or --disable-threads was given. # This auto-enables if Tcl was compiled threaded. #-------------------------------------------------------------------- TEA_ENABLE_THREADS #-------------------------------------------------------------------- # The statement below defines a collection of symbols related to # building as a shared library instead of a static library. #-------------------------------------------------------------------- TEA_ENABLE_SHARED #-------------------------------------------------------------------- # This macro figures out what flags to use with the compiler/linker # when building shared/static debug/optimized objects. This information # can be taken from the tclConfig.sh file, but this figures it all out. #-------------------------------------------------------------------- TEA_CONFIG_CFLAGS #-------------------------------------------------------------------- # Set the default compiler switches based on the --enable-symbols option. #-------------------------------------------------------------------- TEA_ENABLE_SYMBOLS #-------------------------------------------------------------------- # Everyone should be linking against the Tcl stub library. If you # can't for some reason, remove this definition. If you aren't using # stubs, you also need to modify the SHLIB_LD_LIBS setting below to # link against the non-stubbed Tcl library. Add Tk too if necessary. #-------------------------------------------------------------------- AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs]) #AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs]) #-------------------------------------------------------------------- # This macro generates a line to use when building a library. It # depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, # and TEA_LOAD_TCLCONFIG macros above. #-------------------------------------------------------------------- TEA_MAKE_LIB #-------------------------------------------------------------------- # Determine the name of the tclsh and/or wish executables in the # Tcl and Tk build directories or the location they were installed # into. These paths are used to support running test cases only, # the Makefile should not be making use of these paths to generate # a pkgIndex.tcl file or anything else at extension build time. #-------------------------------------------------------------------- TEA_PROG_TCLSH #TEA_PROG_WISH #-------------------------------------------------------------------- # Finally, substitute all of the various values into the Makefile. # You may alternatively have a special pkgIndex.tcl.in or other files # which require substituting th AC variables in. Include these here. #-------------------------------------------------------------------- AC_OUTPUT([Makefile pkgIndex.tcl]) tdom-0.9.5-src/lib/0000755000175000017500000000000014703531020012504 5ustar rolfrolftdom-0.9.5-src/lib/tdom.tcl0000644000175000017500000010352714703531020014163 0ustar rolfrolf#---------------------------------------------------------------------------- # Copyright (c) 1999 Jochen Loewer (loewerj@hotmail.com) #---------------------------------------------------------------------------- # # $Id$ # # # The higher level functions of tDOM written in plain Tcl. # # # The contents of this file are subject to the Mozilla Public License # Version 2.0 (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) 1998, 1999 # Jochen Loewer. All Rights Reserved. # # Contributor(s): # Rolf Ade (rolf@pointsman.de): 'fake' nodelists/live childNodes # # written by Jochen Loewer # April, 1999 # #---------------------------------------------------------------------------- package require tdom #---------------------------------------------------------------------------- # setup namespaces for additional Tcl level methods, etc. # #---------------------------------------------------------------------------- namespace eval ::dom { namespace eval domDoc { } namespace eval domNode { } namespace eval DOMImplementation { } namespace eval xpathFunc { } namespace eval xpathFuncHelper { } } namespace eval ::tdom { variable extRefHandlerDebug 0 variable useForeignDTD "" variable utf8bom 0 namespace export xmlOpenFile xmlReadFile xmlReadFileForSimple \ extRefHandler baseURL } #---------------------------------------------------------------------------- # hasFeature (DOMImplementation method) # # # @in url the URL, where to get the XML document # # @return document object # @exception XML parse errors, ... # #---------------------------------------------------------------------------- proc ::dom::DOMImplementation::hasFeature { dom feature {version ""} } { switch $feature { xml - XML { if {($version == "") || ($version == "1.0")} { return 1 } } } return 0 } #---------------------------------------------------------------------------- # load (DOMImplementation method) # # requests a XML document via http using the given URL and # builds up a DOM tree in memory returning the document object # # # @in url the URL, where to get the XML document # # @return document object # @exception XML parse errors, ... # #---------------------------------------------------------------------------- proc ::dom::DOMImplementation::load { dom url } { error "Sorry, load method not implemented yet!" } #---------------------------------------------------------------------------- # isa (docDoc method, for [incr tcl] compatibility) # # # @in className # # @return 1 iff inherits from the given class # #---------------------------------------------------------------------------- proc ::dom::domDoc::isa { doc className } { if {$className == "domDoc"} { return 1 } return 0 } #---------------------------------------------------------------------------- # info (domDoc method, for [incr tcl] compatibility) # # # @in subcommand # @in args # #---------------------------------------------------------------------------- proc ::dom::domDoc::info { doc subcommand args } { switch $subcommand { class { return "domDoc" } inherit { return "" } heritage { return "domDoc {}" } default { error "domDoc::info subcommand $subcommand not yet implemented!" } } } #---------------------------------------------------------------------------- # importNode (domDoc method) # # Document Object Model (Core) Level 2 method # # # @in subcommand # @in args # #---------------------------------------------------------------------------- proc ::dom::domDoc::importNode { doc importedNode deep } { if {$deep || ($deep == "-deep")} { set node [$importedNode cloneNode -deep] } else { set node [$importedNode cloneNode] } return $node } #---------------------------------------------------------------------------- # isa (domNode method, for [incr tcl] compatibility) # # # @in className # # @return 1 iff inherits from the given class # #---------------------------------------------------------------------------- proc ::dom::domNode::isa { doc className } { if {$className == "domNode"} { return 1 } return 0 } #---------------------------------------------------------------------------- # info (domNode method, for [incr tcl] compatibility) # # # @in subcommand # @in args # #---------------------------------------------------------------------------- proc ::dom::domNode::info { doc subcommand args } { switch $subcommand { class { return "domNode" } inherit { return "" } heritage { return "domNode {}" } default { error "domNode::info subcommand $subcommand not yet implemented!" } } } #---------------------------------------------------------------------------- # isWithin (domNode method) # # tests, whether a node object is nested below another tag # # # @in tagName the nodeName of an elment node # # @return 1 iff node is nested below a element with nodeName tagName # 0 otherwise # #---------------------------------------------------------------------------- proc ::dom::domNode::isWithin { node tagName } { while {[$node parentNode] != ""} { set node [$node parentNode] if {[$node nodeName] == $tagName} { return 1 } } return 0 } #---------------------------------------------------------------------------- # tagName (domNode method) # # same a nodeName for element interface # #---------------------------------------------------------------------------- proc ::dom::domNode::tagName { node } { if {[$node nodeType] == "ELEMENT_NODE"} { return [$node nodeName] } return -code error "NOT_SUPPORTED_ERR not an element!" } #---------------------------------------------------------------------------- # simpleTranslate (domNode method) # # applies simple translation rules similar to Cost's simple # translations to a node # # # @in output_var # @in trans_specs # #---------------------------------------------------------------------------- proc ::dom::domNode::simpleTranslate { node output_var trans_specs } { upvar $output_var output if {[$node nodeType] == "TEXT_NODE"} { append output [cgiQuote [$node nodeValue]] return } set found 0 foreach {match action} $trans_specs { if {[catch { if {!$found && ([$node selectNode self::$match] != "") } { set found 1 } } err]} { if {![string match "NodeSet expected for parent axis!" $err]} { error $err } } if {$found && ($action != "-")} { set stop 0 foreach {type value} $action { switch $type { prefix { append output [subst $value] } tag { append output <$value> } start { append output [eval $value] } stop { set stop 1 } } } if {!$stop} { foreach child [$node childNodes] { simpleTranslate $child output $trans_specs } } foreach {type value} $action { switch $type { suffix { append output [subst $value] } end { append output [eval $value] } tag { append output } } } return } } foreach child [$node childNodes] { simpleTranslate $child output $trans_specs } } #---------------------------------------------------------------------------- # a DOM conformant 'live' childNodes # # @return a 'nodelist' object (it is just the normal node) # #---------------------------------------------------------------------------- proc ::dom::domNode::childNodesLive { node } { return $node } #---------------------------------------------------------------------------- # item method on a 'nodelist' object # # @return a 'nodelist' object (it is just a normal # #---------------------------------------------------------------------------- proc ::dom::domNode::item { nodeListNode index } { return [lindex [$nodeListNode childNodes] $index] } #---------------------------------------------------------------------------- # length method on a 'nodelist' object # # @return a 'nodelist' object (it is just a normal # #---------------------------------------------------------------------------- proc ::dom::domNode::length { nodeListNode } { return [llength [$nodeListNode childNodes]] } #---------------------------------------------------------------------------- # appendData on a 'CharacterData' object # #---------------------------------------------------------------------------- proc ::dom::domNode::appendData { node arg } { set type [$node nodeType] if {($type != "TEXT_NODE") && ($type != "CDATA_SECTION_NODE") && ($type != "COMMENT_NODE") } { return -code error "NOT_SUPPORTED_ERR: node is not a cdata node" } set oldValue [$node nodeValue] $node nodeValue [append oldValue $arg] } #---------------------------------------------------------------------------- # deleteData on a 'CharacterData' object # #---------------------------------------------------------------------------- proc ::dom::domNode::deleteData { node offset count } { set type [$node nodeType] if {($type != "TEXT_NODE") && ($type != "CDATA_SECTION_NODE") && ($type != "COMMENT_NODE") } { return -code error "NOT_SUPPORTED_ERR: node is not a cdata node" } incr offset -1 set before [string range [$node nodeValue] 0 $offset] incr offset incr offset $count set after [string range [$node nodeValue] $offset end] $node nodeValue [append before $after] } #---------------------------------------------------------------------------- # insertData on a 'CharacterData' object # #---------------------------------------------------------------------------- proc ::dom::domNode::insertData { node offset arg } { set type [$node nodeType] if {($type != "TEXT_NODE") && ($type != "CDATA_SECTION_NODE") && ($type != "COMMENT_NODE") } { return -code error "NOT_SUPPORTED_ERR: node is not a cdata node" } incr offset -1 set before [string range [$node nodeValue] 0 $offset] incr offset set after [string range [$node nodeValue] $offset end] $node nodeValue [append before $arg $after] } #---------------------------------------------------------------------------- # replaceData on a 'CharacterData' object # #---------------------------------------------------------------------------- proc ::dom::domNode::replaceData { node offset count arg } { set type [$node nodeType] if {($type != "TEXT_NODE") && ($type != "CDATA_SECTION_NODE") && ($type != "COMMENT_NODE") } { return -code error "NOT_SUPPORTED_ERR: node is not a cdata node" } incr offset -1 set before [string range [$node nodeValue] 0 $offset] incr offset incr offset $count set after [string range [$node nodeValue] $offset end] $node nodeValue [append before $arg $after] } #---------------------------------------------------------------------------- # substringData on a 'CharacterData' object # # @return part of the node value (text) # #---------------------------------------------------------------------------- proc ::dom::domNode::substringData { node offset count } { set type [$node nodeType] if {($type != "TEXT_NODE") && ($type != "CDATA_SECTION_NODE") && ($type != "COMMENT_NODE") } { return -code error "NOT_SUPPORTED_ERR: node is not a cdata node" } set endOffset {[expr $offset + $count - 1]} return [string range [$node nodeValue] $offset $endOffset] } #---------------------------------------------------------------------------- # coerce2number # #---------------------------------------------------------------------------- proc ::dom::xpathFuncHelper::coerce2number { type value } { switch $type { empty { return 0 } number - string { return $value } attrvalues { return [lindex $value 0] } nodes { return [[lindex $value 0] selectNodes number()] } attrnodes { return [lindex $value 1] } } } #---------------------------------------------------------------------------- # coerce2string # #---------------------------------------------------------------------------- proc ::dom::xpathFuncHelper::coerce2string { type value } { switch $type { empty { return "" } number - string { return $value } attrvalues { return [lindex $value 0] } nodes { return [[lindex $value 0] selectNodes string()] } attrnodes { return [lindex $value 1] } } } #---------------------------------------------------------------------------- # function-available # #---------------------------------------------------------------------------- proc ::dom::xpathFunc::function-available { ctxNode pos nodeListType nodeList args} { if {[llength $args] != 2} { error "function-available(): wrong # of args!" } foreach { arg1Typ arg1Value } $args break set str [::dom::xpathFuncHelper::coerce2string $arg1Typ $arg1Value ] switch $str { boolean - ceiling - concat - contains - count - current - document - element-available - false - floor - format-number - generate-id - id - key - last - lang - local-name - name - namespace-uri - normalize-space - not - number - position - round - starts-with - string - string-length - substring - substring-after - substring-before - sum - translate - true - unparsed-entity-uri { return [list bool true] } default { set TclXpathFuncs [info procs ::dom::xpathFunc::*] if {[lsearch -exact $TclXpathFuncs $str] != -1} { return [list bool true] } else { return [list bool false] } } } } #---------------------------------------------------------------------------- # element-available # # This is not strictly correct. The XSLT namespace may be bound # to another prefix (and the prefix 'xsl' may be bound to another # namespace). Since the expression context isn't available at the # moment at tcl coded XPath functions, this couldn't be done better # than this "works in the 'normal' cases" version. #---------------------------------------------------------------------------- proc ::dom::xpathFunc::element-available { ctxNode pos nodeListType nodeList args} { if {[llength $args] != 2} { error "element-available(): wrong # of args!" } foreach { arg1Typ arg1Value } $args break set str [::dom::xpathFuncHelper::coerce2string $arg1Typ $arg1Value ] # The XSLT recommendation says: "The element-available # function returns true if and only if the expanded-name # is the name of an instruction." The following xsl # elements are not in the category instruction. # xsl:attribute-set # xsl:decimal-format # xsl:include # xsl:key # xsl:namespace-alias # xsl:output # xsl:param # xsl:strip-space # xsl:preserve-space # xsl:template # xsl:import # xsl:otherwise # xsl:sort # xsl:stylesheet # xsl:transform # xsl:with-param # xsl:when switch $str { xsl:apply-templates - xsl:apply-imports - xsl:call-template - xsl:element - xsl:attribute - xsl:text - xsl:processing-instruction - xsl:comment - xsl:copy - xsl:value-of - xsl:number - xsl:for-each - xsl:if - xsl:choose - xsl:variable - xsl:copy-of - xsl:message - xsl:fallback { return [list bool true] } default { return [list bool false] } } } #---------------------------------------------------------------------------- # system-property # # This is not strictly correct. The XSLT namespace may be bound # to another prefix (and the prefix 'xsl' may be bound to another # namespace). Since the expression context isn't available at the # moment at tcl coded XPath functions, this couldn't be done better # than this "works in the 'normal' cases" version. #---------------------------------------------------------------------------- proc ::dom::xpathFunc::system-property { ctxNode pos nodeListType nodeList args } { if {[llength $args] != 2} { error "system-property(): wrong # of args!" } foreach { arg1Typ arg1Value } $args break set str [::dom::xpathFuncHelper::coerce2string $arg1Typ $arg1Value ] switch $str { xsl:version { return [list number 1.0] } xsl:vendor { return [list string "Jochen Loewer (loewerj@hotmail.com), Rolf Ade (rolf@pointsman.de) et. al."] } xsl:vendor-url { return [list string "http://www.tdom.org"] } default { return [list string ""] } } } #---------------------------------------------------------------------------- # IANAEncoding2TclEncoding # #---------------------------------------------------------------------------- # As of version 8.3.4 tcl supports # cp860 cp861 cp862 cp863 tis-620 cp864 cp865 cp866 gb12345 cp949 # cp950 cp869 dingbats ksc5601 macCentEuro cp874 macUkraine jis0201 # gb2312 euc-cn euc-jp iso8859-10 macThai jis0208 iso2022-jp # macIceland iso2022 iso8859-13 iso8859-14 jis0212 iso8859-15 cp737 # iso8859-16 big5 euc-kr macRomania macTurkish gb1988 iso2022-kr # macGreek ascii cp437 macRoman iso8859-1 iso8859-2 iso8859-3 ebcdic # macCroatian koi8-r iso8859-4 iso8859-5 cp1250 macCyrillic iso8859-6 # cp1251 koi8-u macDingbats iso8859-7 cp1252 iso8859-8 cp1253 # iso8859-9 cp1254 cp1255 cp850 cp1256 cp932 identity cp1257 cp852 # macJapan cp1258 shiftjis utf-8 cp855 cp936 symbol cp775 unicode # cp857 # # Just add more mappings (and mail them to the tDOM mailing list, please). proc ::tdom::IANAEncoding2TclEncoding {IANAName} { # First the most widespread encodings with there # preferred MIME name, to speed lookup in this # usual cases. Later the official names and the # aliases. # # For "official names for character sets that may be # used in the Internet" see # http://www.iana.org/assignments/character-sets # (that's the source for the encoding names below) # # Matching is case-insensitive switch [string tolower $IANAName] { "us-ascii" {return ascii} "utf-8" {return utf-8} "utf-16" {return unicode} "iso-8859-1" {return iso8859-1} "iso-8859-2" {return iso8859-2} "iso-8859-3" {return iso8859-3} "iso-8859-4" {return iso8859-4} "iso-8859-5" {return iso8859-5} "iso-8859-6" {return iso8859-6} "iso-8859-7" {return iso8859-7} "iso-8859-8" {return iso8859-8} "iso-8859-9" {return iso8859-9} "iso-8859-10" {return iso8859-10} "iso-8859-13" {return iso8859-13} "iso-8859-14" {return iso8859-14} "iso-8859-15" {return iso8859-15} "iso-8859-16" {return iso8859-16} "iso-2022-kr" {return iso2022-kr} "euc-kr" {return euc-kr} "iso-2022-jp" {return iso2022-jp} "koi8-r" {return koi8-r} "shift_jis" {return shiftjis} "euc-jp" {return euc-jp} "gb2312" {return gb2312} "big5" {return big5} "cp866" {return cp866} "cp1250" {return cp1250} "cp1253" {return cp1253} "cp1254" {return cp1254} "cp1255" {return cp1255} "cp1256" {return cp1256} "cp1257" {return cp1257} "windows-1251" - "cp1251" {return cp1251} "windows-1252" - "cp1252" {return cp1252} "iso_8859-1:1987" - "iso-ir-100" - "iso_8859-1" - "latin1" - "l1" - "ibm819" - "cp819" - "csisolatin1" {return iso8859-1} "iso_8859-2:1987" - "iso-ir-101" - "iso_8859-2" - "iso-8859-2" - "latin2" - "l2" - "csisolatin2" {return iso8859-2} "iso_8859-5:1988" - "iso-ir-144" - "iso_8859-5" - "iso-8859-5" - "cyrillic" - "csisolatincyrillic" {return iso8859-5} "ms_kanji" - "csshiftjis" {return shiftjis} "csiso2022kr" {return iso2022-kr} "ibm866" - "csibm866" {return cp866} default { # There are much more encoding names out there # It's only laziness, that let me stop here. error "Unrecognized encoding name '$IANAName'" } } } #---------------------------------------------------------------------------- # xmlOpenFileWorker # #---------------------------------------------------------------------------- proc ::tdom::xmlOpenFileWorker {filename {encodingString {}} {forSimple 0} {forRead 0}} { variable utf8bom # This partly (mis-)use the encoding of a channel handed to [dom # parse -channel ..] as a marker: if the channel encoding is utf-8 # then behind the scene Tcl_Read() is used, otherwise # Tcl_ReadChars(). This is used for the encodings understood (and # checked) by the used expat implementation: utf-8 and utf-16 (in # either byte order). # # The -translation auto used used in the fconfigure commands which # set the encoding isn't strictly necessary in case the parser is # expat (because it handles that internally) but it is the right # thing for the simple parser. set fd [open $filename] if {$encodingString != {}} { upvar $encodingString encString } # The autodetection of the encoding follows # XML Recomendation, Appendix F fconfigure $fd -translation binary if {![binary scan [read $fd 4] "H8" firstBytes]} { # very short (< 4 Bytes) file, that means not a well-formed # XML at all (the shortes possible would be <[a-zA-Z]/>). # Don't report that here but let the parser do that. seek $fd 0 start set encString UTF-8 return $fd } # First check for BOM switch [string range $firstBytes 0 3] { "feff" { # feff: UTF-16, big-endian BOM if {$forSimple || $forRead} { if {[package vsatisfies [package provide Tcl] 9-]} { seek $fd 2 start fconfigure $fd -encoding utf-16be -translation auto } else { error "UTF-16be is not supported" } } else { seek $fd 0 start set encString UTF-16be fconfigure $fd -encoding utf-8 -translation auto } return $fd } "fffe" { # ffef: UTF-16, little-endian BOM set encString UTF-16le if {$forSimple || $forRead} { seek $fd 2 start if {[package vsatisfies [package provide Tcl] 9-]} { fconfigure $fd -encoding utf-16le -translation auto } else { fconfigure $fd -encoding unicode -translation auto } } else { seek $fd 0 start fconfigure $fd -encoding utf-8 -translation auto } return $fd } } if {$utf8bom} { # According to the Unicode standard # (http://www.unicode.org/versions/Unicode5.0.0/ch02.pdf) the # "[u]se of a BOM is neither required nor recommended for # UTF-8". Nevertheless such files exits. If the programmer # explcitely enables this by setting ::tdom::utf8bom to true # this is handled here. if {[string range $firstBytes 0 5] eq "efbbbf"} { set encString UTF-8 seek $fd 3 start fconfigure $fd -encoding utf-8 -translation auto return $fd } } # If the entity has a XML Declaration, the first four characters # must be "" $head] if {$closeIndex == -1} { error "Weird XML data or not XML data at all" } seek $fd 0 start set xmlDeclaration [read $fd [expr {$closeIndex + 5}]] # extract the encoding information set pattern {^[^>]+encoding=[\x20\x9\xd\xa]*["']([^ "']+)['"]} # emacs: " if {![regexp $pattern $head - encStr]} { # Probably something like . # Without encoding declaration this must be UTF-8 set encoding utf-8 set encString UTF-8 } else { set encoding [IANAEncoding2TclEncoding $encStr] set encString $encStr } } "0000003c" - "0000003c" - "3c000000" - "00003c00" { # UCS-4 error "UCS-4 not supported" } "003c003f" { # UTF-16, big-endian, no BOM if {$forSimple || $forRead} { if {[package vsatisfies [package provide Tcl] 9-]} { set encoding utf-16be } else { error "UTF-16be is not supported by the simple parser" } } else { set encoding utf-8 } seek $fd 0 start set encString UTF-16be } "3c003f00" { # UTF-16, little-endian, no BOM if {$forSimple || $forRead} { if {[package vsatisfies [package provide Tcl] 9-]} { set encoding utf-16le } else { set encoding unicode } } else { set encoding utf-8 } seek $fd 0 start set encString UTF-16le } "4c6fa794" { # EBCDIC in some flavor if {[package vsatisfies [package provide Tcl] 9-]} { seek $fd 0 start set encoding ebcdic } else { error "EBCDIC not supported" } } default { # UTF-8 without an encoding declaration seek $fd 0 start set encoding utf-8 set encString "UTF-8" } } fconfigure $fd -encoding $encoding -translation auto return $fd } #---------------------------------------------------------------------------- # xmlOpenFile # #---------------------------------------------------------------------------- proc ::tdom::xmlOpenFile {filename {encodingString {}}} { if {$encodingString != {}} { upvar $encodingString encString } set fd [xmlOpenFileWorker $filename encString] return $fd } #---------------------------------------------------------------------------- # xmlReadFile # #---------------------------------------------------------------------------- proc ::tdom::xmlReadFile {filename {encodingString {}}} { if {$encodingString != {}} { upvar $encodingString encString } set fd [xmlOpenFileWorker $filename encString 0 1] set data [read $fd [file size $filename]] close $fd return $data } #---------------------------------------------------------------------------- # xmlReadFileForSimple # #---------------------------------------------------------------------------- proc ::tdom::xmlReadFileForSimple {filename {encodingString {}}} { if {$encodingString != {}} { upvar $encodingString encString } set fd [xmlOpenFileWorker $filename encString 1] set data [read $fd [file size $filename]] close $fd return $data } #---------------------------------------------------------------------------- # extRefHandler # # A very simple external entity resolver, included for convenience. # Depends on the tcllib package uri and resolves only file URLs. # #---------------------------------------------------------------------------- if {![catch {package require uri}]} { proc ::tdom::extRefHandler {base systemId publicId} { variable extRefHandlerDebug variable useForeignDTD if {$extRefHandlerDebug} { puts stderr "::tdom::extRefHandler called with:" puts stderr "\tbase: '$base'" puts stderr "\tsystemId: '$systemId'" puts stderr "\tpublicId: '$publicId'" } if {$systemId == ""} { if {$useForeignDTD != ""} { set systemId $useForeignDTD } else { error "::tdom::useForeignDTD does\ not point to the foreign DTD" } } set absolutURI [uri::resolve $base $systemId] array set uriData [uri::split $absolutURI] switch $uriData(scheme) { file { if {$::tcl_platform(platform) eq "windows"} { # Strip leading / for drive based paths if {[string match /?:* $uriData(path)]} { set uriData(path) [string range $uriData(path) 1 end] } } # FIXME - path should be URL-decoded return [list string $absolutURI [xmlReadFile $uriData(path)]] } default { error "can only handle file URI's" } } } } #---------------------------------------------------------------------------- # baseURL # # A simple convenience proc which returns an absolute URL for a given # filename. # #---------------------------------------------------------------------------- proc ::tdom::baseURL {path} { # FIXME - path components need to be URL-encoded # Note [file join] will return path as is if it is already absolute. # Also on Windows, it will change \ -> /. This is necessary because # file URIs must always use /, never \. set path [file join [pwd] $path] if {$::tcl_platform(platform) ne "windows"} { return "file://$path" } else { if {[string match //* $path]} { # UNC path return "file:$path" } else { # Drive based path return "file:///$path" } } } namespace eval ::tdom::json { namespace export asDict } # The argument node may be an element node as well as a document node. proc ::tdom::json::asDict {node} { return [nodesAsDict [$node childNodes] [$node jsonType]] } proc ::tdom::json::nodesAsDict {nodes parentType} { set result "" foreach n $nodes { set children [$n childNodes] set jsonType [$n jsonType] set childrendValue [nodesAsDict $children $jsonType] switch $jsonType { OBJECT { if {[$n nodeName] ne "objectcontainer" || $parentType eq "OBJECT"} { lappend result [$n nodeName] } lappend result $childrendValue } NONE { lappend result [$n nodeName] $childrendValue } ARRAY { if {[$n nodeName] ne "arraycontainer" || $parentType eq "OBJECT"} { lappend result [$n nodeName] } lappend result $childrendValue } default { set op [expr {[llength $nodes] > 1 ? "lappend" : "set"} ] $op result [$n nodeValue] } } } return $result } namespace eval ::tDOM { variable extRefHandlerDebug 0 variable useForeignDTD "" namespace export xmlOpenFile xmlReadFile xmlReadFileForSimple \ extRefHandler baseURL } foreach ::tdom::cmd { xmlOpenFile xmlReadFile xmlReadFileForSimple extRefHandler baseURL IANAEncoding2TclEncoding } { interp alias {} ::tDOM::$::tdom::cmd {} ::tdom::$::tdom::cmd } # EOF tdom-0.9.5-src/configure.ac0000644000175000017500000002372014703531020014230 0ustar rolfrolf#!/bin/bash -norc dnl This file is an input file used by the GNU "autoconf" program to dnl generate the file "configure", which is run during Tcl installation dnl to configure the system for the local environment. #----------------------------------------------------------------------- # Sample configure.ac for Tcl Extensions. The only places you should # need to modify this file are marked by the string __CHANGE__ #----------------------------------------------------------------------- #----------------------------------------------------------------------- # __CHANGE__ # Set your package name and version numbers here. # # This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION # set as provided. These will also be added as -D defs in your Makefile # so you can encode the package version directly into the source files. # This will also define a special symbol for Windows (BUILD_ # so that we create the export library with the dll. #----------------------------------------------------------------------- AC_INIT([tdom],[0.9.5]) #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. #-------------------------------------------------------------------- TEA_INIT() AC_CONFIG_AUX_DIR(tclconfig) #-------------------------------------------------------------------- # Load the tclConfig.sh file #-------------------------------------------------------------------- TEA_PATH_TCLCONFIG TEA_LOAD_TCLCONFIG #-------------------------------------------------------------------- # Load the tkConfig.sh file if necessary (Tk extension) #-------------------------------------------------------------------- #TEA_PATH_TKCONFIG #TEA_LOAD_TKCONFIG #----------------------------------------------------------------------- # Handle the --prefix=... option by defaulting to what Tcl gave. # Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER. #----------------------------------------------------------------------- TEA_PREFIX #----------------------------------------------------------------------- # Standard compiler checks. # This sets up CC by using the CC env var, or looks for gcc otherwise. # This also calls AC_PROG_CC and a few others to create the basic setup # necessary to compile executables. #----------------------------------------------------------------------- TEA_SETUP_COMPILER #----------------------------------------------------------------------- # Those two are needed for compiling expat. #----------------------------------------------------------------------- AC_CHECK_FUNCS(memmove bcopy) #-------------------------------------------------------------------- # Add optional AOLserver includes #-------------------------------------------------------------------- TDOM_PATH_AOLSERVER #-------------------------------------------------------------------- # Add shared expat includes and expat entropy #-------------------------------------------------------------------- TDOM_PATH_EXPAT TDOM_EXPAT_ENTROPY #-------------------------------------------------------------------- # We need the UINT2PTR and PTR2UINT macros, so make sure that intptr_t # is defined. #-------------------------------------------------------------------- AC_CHECK_TYPE([uintptr_t], [ AC_DEFINE([HAVE_UINTPTR_T], 1, [Do we have the uintptr_t type?])], [ AC_CACHE_CHECK([for pointer-size unsigned integer type], tcl_cv_uintptr_t, [ for tcl_cv_uintptr_t in "unsigned int" "unsigned long" "unsigned long long" \ none; do if test "$tcl_cv_uintptr_t" != none; then AC_COMPILE_IFELSE([AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT], [[sizeof (void *) <= sizeof ($tcl_cv_uintptr_t)]])], [tcl_ok=yes], [tcl_ok=no]) test "$tcl_ok" = yes && break; fi done]) if test "$tcl_cv_uintptr_t" != none; then AC_DEFINE_UNQUOTED([uintptr_t], [$tcl_cv_uintptr_t], [Unsigned integer type wide enough to hold a pointer.]) fi ]) #-------------------------------------------------------------------- # Add HTML5 parsing support. #-------------------------------------------------------------------- TDOM_ENABLE_HTML5 #----------------------------------------------------------------------- # __CHANGE__ # Specify the C source files to compile in TEA_ADD_SOURCES, # public headers that need to be installed in TEA_ADD_HEADERS, # stub library C source files to compile in TEA_ADD_STUB_SOURCES, # and runtime Tcl library files in TEA_ADD_TCL_SOURCES. # This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS # and PKG_TCL_SOURCES. #----------------------------------------------------------------------- TEA_ADD_SOURCES([generic/xmlsimple.c \ generic/dom.c \ generic/domhtml.c \ generic/domhtml5.c \ generic/domjson.c \ generic/domxpath.c \ generic/domxslt.c \ generic/domlock.c \ generic/tcldom.c \ generic/nodecmd.c \ generic/tdominit.c \ generic/tclexpat.c \ generic/tclpull.c \ generic/schema.c \ generic/datatypes.c \ generic/tdomStubInit.c]) TEA_ADD_HEADERS([generic/tdom.h]) TEA_ADD_INCLUDES([-I${srcdir}/generic ${AOL_INCLUDES} ${HTML5_INCLUDES}]) TEA_ADD_LIBS([${AOL_LIBS} ${HTML5_LIBS}]) TEA_ADD_CFLAGS([]) TEA_ADD_STUB_SOURCES([generic/tdomStubLib.c]) TEA_ADD_TCL_SOURCES([lib/tdom.tcl]) #-------------------------------------------------------------------- # __CHANGE__ # # You can add more files to clean if your extension creates any extra # files by extending CLEANFILES. # Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure # and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var. # # A few miscellaneous platform-specific items: # TEA_ADD_* any platform specific compiler/build info here. #-------------------------------------------------------------------- #CLEANFILES="$CLEANFILES pkgIndex.tcl" if test "${TEA_PLATFORM}" = "windows" ; then # Ensure no empty if clauses : #TEA_ADD_SOURCES([win/winFile.c]) #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"]) CLEANFILES="$CLEANFILES *.ilk vc*.pch" else # Ensure no empty else clauses : #TEA_ADD_SOURCES([unix/unixFile.c]) #TEA_ADD_LIBS([-lsuperfly]) CLEANFILES="$CLEANFILES tdom.tcl tcldomsh" fi #-------------------------------------------------------------------- # __CHANGE__ # Choose which headers you need. Extension authors should try very # hard to only rely on the Tcl public header files. Internal headers # contain private data structures and are subject to change without # notice. # This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG #-------------------------------------------------------------------- TEA_PUBLIC_TCL_HEADERS #TEA_PRIVATE_TCL_HEADERS #TEA_PUBLIC_TK_HEADERS #TEA_PRIVATE_TK_HEADERS #TEA_PATH_X #-------------------------------------------------------------------- # Check whether --enable-threads or --disable-threads was given. # This auto-enables if Tcl was compiled threaded. #-------------------------------------------------------------------- TEA_ENABLE_THREADS #-------------------------------------------------------------------- # The statement below defines a collection of symbols related to # building as a shared library instead of a static library. #-------------------------------------------------------------------- TEA_ENABLE_SHARED #-------------------------------------------------------------------- # This macro figures out what flags to use with the compiler/linker # when building shared/static debug/optimized objects. This information # can be taken from the tclConfig.sh file, but this figures it all out. #-------------------------------------------------------------------- TEA_CONFIG_CFLAGS TDOM_LD_SEARCH_FLAGS=${LD_SEARCH_FLAGS} AC_SUBST(TDOM_LD_SEARCH_FLAGS) #-------------------------------------------------------------------- # Set the default compiler switches based on the --enable-symbols option. #-------------------------------------------------------------------- TEA_ENABLE_SYMBOLS #-------------------------------------------------------------------- # This macro generates a line to use when building a library. It # depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS, # and TEA_LOAD_TCLCONFIG macros above. #-------------------------------------------------------------------- TEA_MAKE_LIB #-------------------------------------------------------------------- # Determine the name of the tclsh and/or wish executables in the # Tcl and Tk build directories or the location they were installed # into. These paths are used to support running test cases only, # the Makefile should not be making use of these paths to generate # a pkgIndex.tcl file or anything else at extension build time. #-------------------------------------------------------------------- TEA_PROG_TCLSH #TEA_PROG_WISH #-------------------------------------------------------------------- # Add some private preprocessor options #-------------------------------------------------------------------- TDOM_ENABLE_DTD # If we expose XML_GetInputContext() at script level #TDOM_CONTEXT_BYTES AC_DEFINE(XML_CONTEXT_BYTES, 0) AC_DEFINE(XML_GE, 1) AC_DEFINE(XML_LARGE_SIZE, 1) TDOM_ENABLE_NS TDOM_ENABLE_UNKNOWN TDOM_ENABLE_TDOMALLOC TDOM_ENABLE_LESS_NS TDOM_ENABLE_SCHEMA TDOMSHELL=tcldomsh AC_SUBST(TDOMSHELL) TEA_EXPORT_CONFIG([tdom]) #-------------------------------------------------------------------- # Finally, substitute all of the various values into the Makefile. # You may alternatively have a special pkgIndex.tcl.in or other files # which require substituting the AC variables in. Include these here. #-------------------------------------------------------------------- AC_CONFIG_FILES([Makefile pkgIndex.tcl tdomConfig.sh]) AC_OUTPUT tdom-0.9.5-src/doc/0000755000175000017500000000000014703531020012503 5ustar rolfrolftdom-0.9.5-src/doc/keyword-index.html0000644000175000017500000001460514703531020016170 0ustar rolfrolf tDOM manual: Keyword Index

    tDOM manual: Keywords

    tdom-0.9.5-src/doc/expat.xml0000644000175000017500000010130214703531020014343 0ustar rolfrolf expat Creates an instance of an expat parser object package require tdom expat ?parsername? ?-namespace? ?arg arg .. xml::parser ?parsername? ?-namespace? ?arg arg ..
    DESCRIPTION

    The parser created with expat or xml::parser (which is just another name for the same command in an own namespace) are able to parse any kind of well-formed XML. The parsers are stream oriented XML parser. This means that you register handler scripts with the parser prior to starting the parse. These handler scripts are called when the parser discovers the associated structures in the document being parsed. A start tag is an example of the kind of structures for which you may register a handler script.

    The parsers always check for XML well-formedness of the input (and report error, if the input isn't well-formed). They parse the internal DTD and, at request, external DTD and external entities, if you resolve the identifier of the external entities with the -externalentitycommand script (see there). If you use the -validateCmd option (see there), the input is additionally validated.

    Additionly, the Tcl extension code that implements this command provides an API for adding C level coded handlers. Up to now, there exists the parser extension command "tdom". The handler set installed by this extension build an in memory "tDOM" DOM tree, while the parser is parsing the input.

    It is possible to register an arbitrary amount of different handler scripts and C level handlers for most of the events. If the event occurs, they are called in turn.

    COMMAND OPTIONS -namespace

    Enables namespace parsing. You must use this option while creating the parser with the expat or xml::parser command. You can't enable (nor disable) namespace parsing with <parserobj> configure ....

    -namespaceseparator char

    This option has only effect, if used together with the option -namespace. If given, this option determines the character inserted between namespace URI and the local name, while reporting an XML element name to a handler script. The default is the character ':'. The value must be a one-character string less or equal to \u00FF, preferably a 7-bit ASCII character or the empty string. If the value is the empty string (as well, as if the value is \x00) the namespace URI and the local name will be concatenated without any separator.

    -final boolean

    This option indicates whether the document data next presented to the parse method is the final part of the document. A value of "0" indicates that more data is expected. A value of "1" indicates that no more is expected. The default value is "1".

    If this option is set to "0" then the parser will not report certain errors if the XML data is not well-formed upon end of input, such as unclosed or unbalanced start or end tags. Instead some data may be saved by the parser until the next call to the parse method, thus delaying the reporting of some of the data.

    If this option is set to "1" then documents which are not well-formed upon end of input will generate an error.

    -validateCmd <tdom schema cmd>

    This option expects the name of a tDOM schema command. If this option is given, then the input is also validated. If the schema command hasn't set a reportcmd then the first validation error will stop further parsing (as a well-formedness error).

    -baseurl url

    Reports the base url of the document to the parser.

    -fastcall boolean

    By default this option is 0 (off). If this option is on then any handler installed by the options -elementstartcommand, -elementendcommand and -characterdatacommand from this moment on is installed in a way that calling it has lesser overhead as usual. This option may be switched between callback hander (re-)installion as desired.

    However this has some requirenments. The handler proc has to be defined before used as callback. If it is not then the callback is installed as ususal. And the handler proc must not be removed or re-defined as long as it is used as callback. If this is done the programm probably will crash but also may execute arbitrary code.

    The callback handler installed while this option is on will not be traced by executing them.

    -keepTextStart boolean

    By default this option is 0 (off). If this option is on then the position information of the start of a text or CDATA node is keeped over collecting the sometimes by expat delivered cdata pieces. With this option on the position information returned by the parser in a -characterdatacommand proc will be correct, otherwise not. Called in all other handler code the parser always return the correct position results, no matter what value this option have. It is off by default because it is rarely needed and saves a few cpu cyles this way.

    -elementstartcommand script

    Specifies a Tcl command to associate with the start tag of an element. The actual command consists of this option followed by at least two arguments: the element type name and the attribute list.

    The attribute list is a Tcl list consisting of name/value pairs, suitable for passing to the array set Tcl command.

    Example:

    proc HandleStart {name attlist} { puts stderr "Element start ==> $name has attributes $attlist" } $parser configure -elementstartcommand HandleStart $parser parse {<test id="123"></test>}

    This would result in the following command being invoked:

    HandleStart text {id 123}
    -elementendcommand script

    Specifies a Tcl command to associate with the end tag of an element. The actual command consists of this option followed by at least one argument: the element type name. In addition, if the -reportempty option is set then the command may be invoked with the -empty configuration option to indicate whether it is an empty element. See the description of the -reportempty option for an example.

    Example:

    proc HandleEnd {name} { puts stderr "Element end ==> $name" } $parser configure -elementendcommand HandleEnd $parser parse {<test id="123"></test>}

    This would result in the following command being invoked:

    HandleEnd test
    -characterdatacommand script

    Specifies a Tcl command to associate with character data in the document, ie. text. The actual command consists of this option followed by one argument: the text.

    Other than with the C API of the expat parser it is guaranteed that character data will be passed to the application in a single call to this command.

    Example:

    proc HandleText {data} { puts stderr "Character data ==> $data" } $parser configure -characterdatacommand HandleText $parser parse {<test>this is a test document</test>}

    This would result in the following command being invoked:

    HandleText {this is a test document}
    -processinginstructioncommand script

    Specifies a Tcl command to associate with processing instructions in the document. The actual command consists of this option followed by two arguments: the PI target and the PI data.

    Example:

    proc HandlePI {target data} { puts stderr "Processing instruction ==> $target $data" } $parser configure -processinginstructioncommand HandlePI $parser parse {<test><?special this is a processing instruction?></test>}

    This would result in the following command being invoked:

    HandlePI special {this is a processing instruction}
    -notationdeclcommand script

    Specifies a Tcl command to associate with notation declaration in the document. The actual command consists of this option followed by four arguments: the notation name, the base uri of the document (this means, whatever was set by the -baseurl option), the system identifier and the public identifier. The notation name is never empty, the other arguments may be.

    -externalentitycommand script

    Specifies a Tcl command to associate with references to external entities in the document. The actual command consists of this option followed by three arguments: the base uri, the system identifier of the entity and the public identifier of the entity. The base uri and the public identifier may be the empty list.

    This handler script has to return a tcl list consisting of three elements. The first element of this list signals, how the external entity is returned to the processor. At the moment, the three allowed types are "string", "channel" and "filename". The second element of the list has to be the (absolute) base URI of the external entity to be parsed. The third element of the list are data, either the already read data out of the external entity as string in the case of type "string", or the name of a tcl channel, in the case of type "channel", or the path to the external entity to be read in case of type "filename". Behind the scene, the external entity referenced by the returned Tcl channel, string or file name will be parsed with an expat external entity parser with the same handler sets as the main parser. If parsing of the external entity fails, the whole parsing is stopped with an error message. If a Tcl command registered as externalentitycommand isn't able to resolve an external entity it is allowed to return TCL_CONTINUE. In this case, the wrapper give the next registered externalentitycommand a try. If no externalentitycommand is able to handle the external entity parsing stops with an error.

    Example:

    proc externalEntityRefHandler {base systemId publicId} { if {![regexp {^[a-zA-Z]+:/} $systemId]} { regsub {^[a-zA-Z]+:} $base {} base set basedir [file dirname $base] set systemId "[set basedir]/[set systemId]" } else { regsub {^[a-zA-Z]+:} $systemId systemId } if {[catch {set fd [open $systemId]}]} { return -code error \ -errorinfo "Failed to open external entity $systemId" } return [list channel $systemId $fd] } set parser [expat -externalentitycommand externalEntityRefHandler \ -baseurl "file:///local/doc/doc.xml" \ -paramentityparsing notstandalone] $parser parse {<?xml version='1.0'?> <!DOCTYPE test SYSTEM "test.dtd"> <test/>}

    This would result in the following command being invoked:

    externalEntityRefHandler file:///local/doc/doc.xml test.dtd {}

    External entities are only tried to resolve via this handler script, if necessary. This means, external parameter entities triggers this handler only, if -paramentityparsing is used with argument "always" or if -paramentityparsing is used with argument "notstandalone" and the document isn't marked as standalone.

    -unknownencodingcommand script

    Not implemented at Tcl level.

    -startnamespacedeclcommand script

    Specifies a Tcl command to associate with start scope of namespace declarations in the document. The actual command consists of this option followed by two arguments: the namespace prefix and the namespace URI. For an xmlns attribute, prefix will be the empty list. For an xmlns="" attribute, uri will be the empty list. The call to the start and end element handlers occur between the calls to the start and end namespace declaration handlers.

    -endnamespacedeclcommand script

    Specifies a Tcl command to associate with end scope of namespace declarations in the document. The actual command consists of this option followed by the namespace prefix as argument. In case of an xmlns attribute, prefix will be the empty list. The call to the start and end element handlers occur between the calls to the start and end namespace declaration handlers.

    -commentcommand script

    Specifies a Tcl command to associate with comments in the document. The actual command consists of this option followed by one argument: the comment data.

    Example:

    proc HandleComment {data} { puts stderr "Comment ==> $data" } $parser configure -commentcommand HandleComment $parser parse {<test><!-- this is <obviously> a comment --></test>}

    This would result in the following command being invoked:

    HandleComment { this is <obviously> a comment }
    -notstandalonecommand script

    This Tcl command is called, if the document is not standalone (it has an external subset or a reference to a parameter entity, but does not have standalone="yes"). It is called with no additional arguments.

    -startcdatasectioncommand script

    Specifies a Tcl command to associate with the start of a CDATA section. It is called with no additional arguments.

    -endcdatasectioncommand script

    Specifies a Tcl command to associate with the end of a CDATA section. It is called with no additional arguments.

    -elementdeclcommand script

    Specifies a Tcl command to associate with element declarations. The actual command consists of this option followed by two arguments: the name of the element and the content model. The content model arg is a tcl list of four elements. The first list element specifies the type of the XML element; the six different possible types are reported as "MIXED", "NAME", "EMPTY", "CHOICE", "SEQ" or "ANY". The second list element reports the quantifier to the content model in XML Syntax ("?", "*" or "+") or is the empty list. If the type is "MIXED", then the quantifier will be "{}", indicating an PCDATA only element, or "*", with the allowed elements to intermix with PCDATA as tcl list as the fourth argument. If the type is "NAME", the name is the third arg; otherwise the third argument is the empty list. If the type is "CHOICE" or "SEQ" the fourth argument will contain a list of content models build like this one. The "EMPTY", "ANY", and "MIXED" types will only occur at top level.

    Examples:

    proc elDeclHandler {name content} { puts "$name $content" } set parser [expat -elementdeclcommand elDeclHandler] $parser parse {<?xml version='1.0'?> <!DOCTYPE test [ <!ELEMENT test (#PCDATA)> ]> <test>foo</test>}

    This would result in the following command being invoked:

    test {MIXED {} {} {}} $parser reset $parser parse {<?xml version='1.0'?> <!DOCTYPE test [ <!ELEMENT test (a|b)> ]> <test><a/></test>}

    This would result in the following command being invoked:

    elDeclHandler test {CHOICE {} {} {{NAME {} a {}} {NAME {} b {}}}}
    -attlistdeclcommand script

    Specifies a Tcl command to associate with attlist declarations. The actual command consists of this option followed by five arguments. The Attlist declaration handler is called for *each* attribute. So a single Attlist declaration with multiple attributes declared will generate multiple calls to this handler. The arguments are the element name this attribute belongs to, the name of the attribute, the type of the attribute, the default value (may be the empty list) and a required flag. If this flag is true and the default value is not the empty list, then this is a "#FIXED" default.

    Example:

    proc attlistHandler {elname name type default isRequired} { puts "$elname $name $type $default $isRequired" } set parser [expat -attlistdeclcommand attlistHandler] $parser parse {<?xml version='1.0'?> <!DOCTYPE test [ <!ELEMENT test EMPTY> <!ATTLIST test id ID #REQUIRED name CDATA #IMPLIED> ]> <test/>}

    This would result in the following commands being invoked:

    attlistHandler test id ID {} 1 attlistHandler test name CDATA {} 0
    -startdoctypedeclcommand script

    Specifies a Tcl command to associate with the start of the DOCTYPE declaration. This command is called before any DTD or internal subset is parsed. The actual command consists of this option followed by four arguments: the doctype name, the system identifier, the public identifier and a boolean, that shows if the DOCTYPE has an internal subset.

    -enddoctypedeclcommand script

    Specifies a Tcl command to associate with the end of the DOCTYPE declaration. This command is called after processing any external subset. It is called with no additional arguments.

    -paramentityparsing never|notstandalone|always

    "never" disables expansion of parameter entities, "always" expands always and "notstandalone" only, if the document isn't "standalone='no'". The default ist "never"

    -entitydeclcommand script

    Specifies a Tcl command to associate with any entity declaration. The actual command consists of this option followed by seven arguments: the entity name, a boolean identifying parameter entities, the value of the entity, the base uri, the system identifier, the public identifier and the notation name. According to the type of entity declaration some of this arguments may be the empty list.

    -ignorewhitecdata boolean

    If this flag is set, element content which contain only whitespaces isn't reported with the -characterdatacommand.

    -ignorewhitespace boolean Another name for -ignorewhitecdata; see there. -handlerset name

    This option sets the Tcl handler set scope for the configure options. Any option value pair following this option in the same call to the parser are modifying the named Tcl handler set. If you don't use this option, you are modifying the default Tcl handler set, named "default".

    -noexpand boolean

    Normally, the parser will try to expand references to entities defined in the internal subset. If this option is set to a true value this entities are not expanded, but reported literal via the default handler. Warning: If you set this option to true and doesn't install a default handler (with the -defaultcommand option) for every handler set of the parser all internal entities are silent lost for the handler sets without a default handler.

    -useForeignDTD <boolean> If <boolean> is true and the document does not have an external subset, the parser will call the -externalentitycommand script with empty values for the systemId and publicID arguments. This option must be set, before the first piece of data is parsed. Setting this option, after the parsing has started has no effect. The default is not to use a foreign DTD. The default is restored, after resetting the parser. Pleace notice, that a -paramentityparsing value of "never" (which is the default) suppresses any call to the -externalentitycommand script. Pleace notice, that, if the document also doesn't have an internal subset, the -startdoctypedeclcommand and enddoctypedeclcommand scripts, if set, are not called. -billionLaughsAttackProtectionMaximumAmplification <float> This option together with -billionLaughsAttackProtectionActivationThreshold gives control over the parser limits that protects against billion laugh attacks (https://en.wikipedia.org/wiki/Billion_laughs_attack). This option expects a float >= 1.0 as argument. You should never need to use this option, because the default value (100.0) should work for any real data. If you ever need to increase this value for non-attack payload, please report. -billionLaughsAttackProtectionActivationThreshold <long> This option together with -billionLaughsAttackProtectionMaximumAmplification gives control over the parser limits that protects against billion laugh attacks (https://en.wikipedia.org/wiki/Billion_laughs_attack). This option expects a positiv integer as argument. You should never need to use this option, because the default value (8388608) should work for any real data. If you ever need to increase this value for non-attack payload, please report.
    COMMAND METHODS parser configure option value ?option value?

    Sets configuration options for the parser. Every command option, except -namespace can be set or modified with this method.

    parser cget ?-handlerset name? option

    Return the current configuration value option for the parser.

    If the -handlerset option is used, the configuration for the named handler set is returned.

    parser currentmarkup

    Returns the current markup as found in the XML, if called from within one of its markup event handler script (-elementstartcommand, -elementendcommand, -commentcommand and -processinginstructioncommand). Otherwise it return the empty string.

    parser delete

    Deletes the parser and the parser command. A parser cannot be deleted from within one of its handler callbacks (neither directly nor indirectly) and will raise a tcl error in this case.

    parser free

    Another name to call the method delete, see there.

    parser get -specifiedattributecount|-idattributeindex|-currentbytecount|-currentlinenumber|-currentcolumnnumber|-currentbyteindex -specifiedattributecount

    Returns the number of the attribute/value pairs passed in last call to the elementstartcommand that were specified in the start-tag rather than defaulted. Each attribute/value pair counts as 2; thus this corresponds to an index into the attribute list passed to the elementstartcommand.

    -idattributeindex

    Returns the index of the ID attribute passed in the last call to XML_StartElementHandler, or -1 if there is no ID attribute. Each attribute/value pair counts as 2; thus this corresponds to an index into the attributes list passed to the elementstartcommand.

    -currentbytecount

    Return the number of bytes in the current event. Returns 0 if the event is in an internal entity.

    If you use this option consider if you may need the parser option -keepTextStart.

    -currentlinenumber

    Returns the line number of the current parse location.

    If you use this option consider if you may need the parser option -keepTextStart.

    -currentcolumnnumber

    Returns the column number of the current parse location.

    If you use this option consider if you may need the parser option -keepTextStart.

    -currentbyteindex

    Returns the byte index of the current parse location.

    If you use this option consider if you may need the parser option -keepTextStart.

    Only one value may be requested at a time.

    parser parse data

    Parses the XML string data. The event callback scripts will be called, as there triggering events happens. This method cannot be used from within a callback (neither directly nor indirectly) of the parser to be used and will raise an error in this case.

    parser parsechannel channelID

    Reads the XML data out of the tcl channel channelID (starting at the current access position, without any seek) up to the end of file condition and parses that data. The channel encoding is respected. Use the helper proc tDOM::xmlOpenFile out of the tDOM script library to open a file, if you want to use this method. This method cannot be used from within a callback (neither directly nor indirectly) of the parser to be used and will raise an error in this case.

    parser parsefile filename

    Reads the XML data directly out of the file with the filename filename and parses that data. This is done with low-level file operations. The XML data must be in US-ASCII, ISO-8859-1, UTF-8 or UTF-16 encoding. If applicable, this is the fastest way, to parse XML data. This method cannot be used from within a callback (neither directly nor indirectly) of the parser to be used and will raise an error in this case.

    parser reset

    Resets the parser in preparation for parsing another document. A parser cannot be reset from within one of its handler callbacks (neither directly nor indirectly) and will raise a tcl error in this cases.

    Callback Command Return Codes

    A script invoked for any of the parser callback commands, such as -elementstartcommand, -elementendcommand, etc, may return an error code other than "ok" or "error". All callbacks may in addition return "break" or "continue".

    If a callback script returns an "error" error code then processing of the document is terminated and the error is propagated in the usual fashion.

    If a callback script returns a "break" error code then all further processing of every handler script out of this Tcl handler set is suppressed for the further parsing. This does not influence any other handler set.

    If a callback script returns a "continue" error code then processing of the current element, and its children, ceases for every handler script out of this Tcl handler set and processing continues with the next (sibling) element. This does not influence any other handler set.

    If a callback script returns a "return" error code then parsing is canceled altogether, but no error is raised.

    expatapi tdom SAX push pushparser
    tdom-0.9.5-src/doc/pullparser.n0000644000175000017500000001675614703531020015072 0ustar rolfrolf'\" '\" Generated from pullparser.xml '\" '\" BEGIN man.macros .if t .wh -1.3i ^B .nr ^l \n(.l .ad b .de AP .ie !"\\$4"" .TP \\$4 .el \{\ . ie !"\\$2"" .TP \\n()Cu . el .TP 15 .\} .ta \\n()Au \\n()Bu .ie !"\\$3"" \{\ \&\\$1 \\fI\\$2\\fP (\\$3) .\".b .\} .el \{\ .br .ie !"\\$2"" \{\ \&\\$1 \\fI\\$2\\fP .\} .el \{\ \&\\fI\\$1\\fP .\} .\} .. .de AS .nr )A 10n .if !"\\$1"" .nr )A \\w'\\$1'u+3n .nr )B \\n()Au+15n .\" .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n .nr )C \\n()Bu+\\w'(in/out)'u+2n .. .AS Tcl_Interp Tcl_CreateInterp in/out .de BS .br .mk ^y .nr ^b 1u .if n .nf .if n .ti 0 .if n \l'\\n(.lu\(ul' .if n .fi .. .de BE .nf .ti 0 .mk ^t .ie n \l'\\n(^lu\(ul' .el \{\ .\" Draw four-sided box normally, but don't draw top of .\" box if the box started on an earlier page. .ie !\\n(^b-1 \{\ \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .el \}\ \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .\} .fi .br .nr ^b 0 .. .de VS .if !"\\$2"" .br .mk ^Y .ie n 'mc \s12\(br\s0 .el .nr ^v 1u .. .de VE .ie n 'mc .el \{\ .ev 2 .nf .ti 0 .mk ^t \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' .sp -1 .fi .ev .\} .nr ^v 0 .. .de ^B .ev 2 'ti 0 'nf .mk ^t .if \\n(^b \{\ .\" Draw three-sided box if this is the box's first page, .\" draw two sides but no top otherwise. .ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .\} .if \\n(^v \{\ .nr ^x \\n(^tu+1v-\\n(^Yu \kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c .\} .bp 'fi .ev .if \\n(^b \{\ .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. .de DS .RS .nf .sp .. .de DE .fi .RE .sp .. .de SO .SH "STANDARD OPTIONS" .LP .nf .ta 5.5c 11c .ft B .. .de SE .fi .ft R .LP See the \\fBoptions\\fR manual entry for details on the standard options. .. .de OP .LP .nf .ta 4c Command-Line Name: \\fB\\$1\\fR Database Name: \\fB\\$2\\fR Database Class: \\fB\\$3\\fR .fi .IP .. .de CS .RS .nf .ta .25i .5i .75i 1i .if t .ft C .. .de CE .fi .if t .ft R .RE .. .de UL \\$1\l'|0\(ul'\\$2 .. '\" END man.macros .TH pullparser n "" Tcl "" .BS .SH NAME tdom::pullparser \- Create an XML pull parser command .SH SYNOPSIS .nf package require tdom \fBtdom::pullparser\fP \fIcmdName\fR \fR?\fP -ignorewhitecdata \fR?\fP .fi .BE .SH "DESCRIPTION " .PP This command creates XML pull parser commands with a simple API, along the lines of a simple StAX parser. After creation, you've to set an input source, to do anything useful with the pull parser. For this see the methods \fIinput\fR, \fIinputchannel\fR and \fIinputfile\fR. .PP The parser has always a \fIstate\fR. You start parsing the XML data until some next state, do what has to be done and skip again to the next state. XML well-formedness errors along the way will be reported as TCL_ERROR with additional info in the error message. .PP The pull parsers don't follow external entities and are XML 1.0 only, they know nothing about XML Namespaces. You get the tags and attribute names as in the source. You aren't noticed about comments, processing instructions and external entities; they are silently ignored for you. CDATA Sections are handled as if their content would have been provided without using a CDATA Section. .PP On the brighter side is that character entity and attribute default declarations in the internal subset are respected (because of using expat as underlying parser). It is probably somewhat faster than a comperable implementation with the SAX interface. It's a nice programming model. It's a slim interface. .PP If the option \fI-ignorewhitecdata\fR is given, the created XML pull parser command will ignore any white space only (' ', \et, \&\en and \er) text content between START_TAG and START_TAG / END_TAG. The parser won't stop at such input and will create TEXT state events only for not white space only text. .PP Not all methods are valid in every state. The parser will raise TCL_ERROR if a method is called in a state the method isn't valid for. Valid methods of the created commands are: .TP \&\fB\fBstate\fP \&\fRThis method is valid in all parser states. The possible return values and their meanings are: .RS .IP "\(bu" \&\fIREADY\fR - The parser is created or reset, but no input is set. .IP "\(bu" \&\fISTART_DOCUMENT\fR - Input is set, parser is ready to start parsing. .IP "\(bu" \&\fISTART_TAG\fR - Parser has stopped parsing at a start tag. .IP "\(bu" \&\fIEND_TAG\fR - Parser has stopped parsing at an end tag .IP "\(bu" \&\fITEXT\fR - Parser has stopped parsing to report text between tags. .IP "\(bu" \&\fIEND_DOKUMENT\fR - Parser has finished parsing without error. .IP "\(bu" \&\fIPARSE_ERROR\fR - Parser stopped parsing at XML error in input. .RE .TP \&\fB\fBinput\fP \fIdata\fB \&\fRThis method is only valid in state \fIREADY\fR. It prepares the parser to use \fIdata\fR as XML input to parse and switches the parser into state START_DOCUMENT. .TP \&\fB\fBinputchannel\fP \fIchannel\fB \&\fRThis method is only valid in state \fIREADY\fR. It prepares the parser to read the XML input to parse out of \&\fIchannel\fR and switches the parser into state START_DOCUMENT. .TP \&\fB\fBinputfile\fP \fIfilename\fB \&\fRThis method is only valid in state \fIREADY\fR. It open \fIfilename\fR and prepares the parser to read the XML input to parse out of that file. The method returns TCL_ERROR, if the file could not be open in read mode. Otherwise it switches the parser into state START_DOCUMENT. .TP \&\fB\fBnext\fP \&\fRThis method is valid in state \fISTART_DOCUMENT\fR, \&\fISTART_TAG\fR, \fIEND_TAG\fR and \fITEXT\fR. It continues parsing of the XML input until the next event, which it will return. .TP \&\fB\fBtag\fP \&\fRThis method is only valid in states \fISTART_TAG\fR and \&\fIEND_TAG\fR. It returns the tag name of the current start or end tag. .TP \&\fB\fBattributes\fP \&\fRThis method is only valid in state \fISTART_TAG\fR. It returns all attributes of the element in a name value list. .TP \&\fB\fBtext\fP \&\fRThis method is only valid in state \fITEXT\fR. It returns the character data of the event. There will be always at most one TEXT event between START_TAG and the next START_TAG or END_TAG event. .TP \&\fB\fBskip\fP \&\fRThis method is only valid in state \fISTART_TAG\fR. It skips to the corresponding end tag and ignores all events (but not XML parsing errors) on the way and returns the new state END_TAG. .TP \&\fB\fBfind-element\fP \fR?\fP tagname | -names tagnames \fR?\fP \&\fRThis method is only valid in states \&\fISTART_DOCUMENT\fR, \fISTART_TAG\fR and \fIEND_TAG\fR. It skips forward until the next element start tag with tag name \&\fItagname\fR and returns the new state START_TAG. If a list of tagnames is provided with the \fI-names\fR option, any of the \fItagnames\fR match. If there isn't such an element the parser stops at the end of the input and returns END_DOCUMENT. .TP \&\fB\fBreset\fP \&\fRThis method is valid in all parser states. It resets the parser into READY state and returns that. .TP \&\fB\fBdelete\fP \&\fRThis method is valid in all parser states. It deletes the parser command. .PP Miscellaneous methods: .TP \&\fB\fBline\fP \&\fRThis method is valid in all parser states except READY and TEXT. It returns the line number of the parsing position. Line counting starts with 1. .TP \&\fB\fBcolumn\fP \&\fRThis method is valid in all parser states except READY and TEXT. It returns the offset, from the beginning of the current line, of the parsing position. Column counting starts with 0. .SH KEYWORDS XML, pull, parsing tdom-0.9.5-src/doc/tmml.schema0000644000175000017500000003530514703531020014644 0ustar rolfrolfstart manpage defelement manpage { attribute version ? attribute title attribute id attribute cat attribute package ? element head ? element namesection element synopsis ? element section * element seealso ? element keywords ? } defelement DEF { attribute cat ? attribute name attribute package ? attribute subpart ? attribute manpage ? } defelement INDEX { attribute package ? attribute standalone ? attribute title element head ? choice * { element MAN element DEF element KWD } } defelement KWD { attribute manpage ? attribute name } defelement MAN { attribute id attribute title } defelement argdef { attribute version ? element argtype element name element argmode ? element desc } defelement arglist { element argdef + } defelement argmode { text } defelement argtype { text } defelement b { attribute cat ? mixed { element emph element ref element url element samp element command element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class } } defelement br { } defelement categories { element category + } defelement category { attribute title ? attribute id } defelement class { text } defelement cmd { text } defelement command { mixed { element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class } } defelement commanddef { attribute version ? element command element desc } defelement commandlist { element commanddef + } defelement dbclass { text } defelement dbname { text } defelement dd { mixed { element emph element ref element url element samp element command element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class element p element ul element ol element dl element sl element xl element example element syntax element commandlist element optlist } } defelement desc { mixed { element emph element ref element url element samp element command element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class element p element ul element ol element dl element sl element xl element example element syntax element commandlist element optlist } } defelement division { element title choice { element division * choice * { element manpage element subdoc element extref } } } defelement dl { attribute cat ? attribute scope ? {enumeration {local global}} choice + { element dle group { element dt element dd } } } defelement dle { attribute version ? element dt + element dd } defelement dt { mixed { element emph element ref element url element samp element command element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class } } defelement emph { mixed { element emph element ref element url element samp element command element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class } } defelement example { mixed { element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class } } defelement extension { attribute gi attribute tmml } defelement extensions { choice * { element extension element xlh } } defelement extref { attribute title attribute href attribute type } defelement file { text } defelement fun { text } defelement head { choice * { element extensions element info element link element category } } defelement i { attribute cat ? mixed { element emph element ref element url element samp element command element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class } } defelement info { attribute key attribute value } defelement keyword { text } defelement keywords { element keyword + } defelement l { text } defelement li { attribute version ? mixed { element emph element ref element url element samp element command element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class element p element ul element ol element dl element sl element xl element example element syntax element commandlist element optlist } } defelement link { attribute href attribute rel } defelement m { text } defelement manual { attribute version ? attribute package element title element head ? choice { element division * choice * { element manpage element subdoc element extref } } } defelement method { text } defelement name { attribute cat ? attribute name ? text } defelement namesection { choice { element name + group { element title element name * } } element desc } defelement new { attribute version mixed { element emph element ref element url element samp element command element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class } } defelement o { mixed { element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class } } defelement ol { element li + } defelement optarg { text } defelement optdef { element optname element optarg ? element desc } defelement option { text } defelement optiondef { attribute version ? element name element dbname element dbclass element desc } defelement optionlist { attribute cat ? attribute scope ? {enumeration {local global}} element optiondef + } defelement optlist { element optdef + } defelement optname { text } defelement p { attribute version ? mixed { element emph element ref element url element samp element command element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class } } defelement package { text } defelement ref { attribute cat ? attribute href ? attribute refid ? mixed { element emph element ref element url element samp element command element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class } } defelement samp { mixed { element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class } } defelement section { attribute id ? attribute version ? element title choice * { element p element ul element ol element dl element sl element xl element example element syntax element commandlist element optlist element arglist element optionlist } element subsection * } defelement seealso { choice + { element ref element url } } defelement sl { attribute cols ? attribute cat ? element li + } defelement subdoc { attribute href } defelement subsection { attribute id ? attribute version ? element title choice * { element p element ul element ol element dl element sl element xl element example element syntax element commandlist element optlist element arglist element optionlist } } defelement synopsis { choice + { element syntax element example } } defelement syntax { attribute name ? attribute scope ? {enumeration {local global}} attribute cat ? mixed { element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class } } defelement syscmd { text } defelement term { attribute cat ? text } defelement title { text } defelement type { text } defelement ul { element li + } defelement url { text } defelement variable { text } defelement widget { text } defelement xh { mixed { element emph element ref element url element samp element command element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class } } defelement xl { element xlh ? element xle + } defelement xle { element xt + element desc ? } defelement xlh { attribute gi ? element xh + } defelement xt { mixed { element emph element ref element url element samp element command element new element m element l element o element i element b element br element term element cmd element variable element method element option element file element syscmd element fun element widget element package element type element class } } tdom-0.9.5-src/doc/index.html0000644000175000017500000000412414703531020014501 0ustar rolfrolf tDOM manual

    tDOM manual: Contents

    tdom-0.9.5-src/doc/dom.xml0000644000175000017500000011120414703531020014003 0ustar rolfrolf dom Create an in-memory DOM tree from XML package require tdom dom method ?arg arg ...?
    DESCRIPTION

    This command provides the creation of DOM trees in memory. In the usual case a string containing a XML information is parsed and converted into a DOM tree. Other possible parse input may be HTML or JSON. The method indicates a specific subcommand.

    The valid methods are:

    dom parse ?options? ?data? Parses the XML information and builds up the DOM tree in memory providing a Tcl object command to this DOM document object. Example: dom parse $xml doc $doc documentElement root

    parses the XML in the variable xml, creates the DOM tree in memory, make a reference to the document object, visible in Tcl as a document object command, and assigns this new object name to the variable doc. When doc gets freed, the DOM tree and the associated Tcl command object (document and all node objects) are freed automatically.

    set document [dom parse $xml] set root [$document documentElement]

    parses the XML in the variable xml, creates the DOM tree in memory, make a reference to the document object, visible in Tcl as a document object command, and returns this new object name, which is then stored in document. To free the underlying DOM tree and the associative Tcl object commands (document + nodes + fragment nodes) the document object command has to be explicitly deleted by:

    $document delete or rename $document ""

    The valid options are:

    -simple If -simple is specified, a simple but fast parser is used (conforms not fully to XML recommendation). That should double parsing and DOM generation speed. The encoding of the data is not transformed inside the parser. The simple parser does not respect any encoding information in the XML declaration. It skips over the internal DTD subset and ignores any information in it. Therefore, it doesn't include defaulted attribute values into the tree, even if the according attribute declaration is in the internal subset. It also doesn't expand internal or external entity references other than the predefined entities and character references -html If -html is specified, a fast HTML parser is used, which tries to even parse badly formed HTML into a DOM tree. If the HTML document given to parse does not have a single root element (as it was legal up to HTML 4.01) and the -forest option is not used then a html node will be inserted as document element, with the HTML input data top level elements as children. -html5 This option is only available if tDOM was build with --enable-html5. Use the featureinfo method if you need to know if this feature is build in. If -html5 is specified, the gumbo lib html5 parser (https://github.com/google/gumbo-parser) is used to build the DOM tree. This is, as far as it goes, XML namespace-aware (which means for example that all HTML elements are in the html5 namespace). Since this probably isn't wanted by a lot of users and adds only burden for no good in a lot of use cases -html5 can be combined with -ignorexmlns, in which case all nodes and attributes in the DOM tree are not in an XML namespace. All tag and attribute names in the DOM tree will be lower case, even for foreign elements not in the xhtml, svg or mathml namespace. The DOM tree may include nodes, that the parser inserted because they are implied by the context (as <head>, <tbody>, etc.). Input longer than 4 GByte byte length is not supported by the underlying gumbo parser. -json If -json is specified, the data is expected to be a valid JSON string (according to RFC 7159). The command returns an ordinary DOM document with nesting token inside the JSON data translated into tree hierarchy. If a JSON array value is itself an object or array then container element nodes named (in a default build) arraycontainer or objectcontainer, respectively, are inserted into the tree. The JSON serialization of this document (with the domDoc method asJSON) is the same JSON information as the data, preserving JSON datatypes, allowing non-unique member names of objects while preserving their order and the full range of JSON string values. JSON datatype handling is done with an additional property "sticking" at the doc and tree nodes. This property isn't contained in an XML serialization of the document. If you need to store the JSON data represented by a document, store the JSON serialization and parse it back from there. Apart from this JSON type information the returned doc command or handle is an ordinary DOM doc, which may be investigated or modified with the full range of the doc and node methods. Please note that the element node names and the text node values within the tree may be outside of what the appropriate XML productions allow. -jsonroot <document element name> If given makes the given element name the document element of the resulting doc. The parsed content of the JSON string will be the children of this document element node. -jsonmaxnesting integer This option only has effect if used together with the -json option. The current implementation uses a recursive descent JSON parser. In order to avoid using excess stack space, any JSON input that has more than a certain levels of nesting is considered invalid. The default maximum nesting is 2000. The option -jsonmaxnesting allows the user to adjust that. -- The option -- marks the end of options. To give this option isn't strictly necessary even in the case of JSON parsing, for which valid data may start with a "-". If parsing json and if the second to last or last argument start with a "-" and isn't a known option name it will be treated as JSON data. -keepEmpties If -keepEmpties is specified then text nodes which contain only whitespaces will be part of the resulting DOM tree. In default case (-keepEmpties not given) those empty text nodes are removed at parsing time. -keepCDATA If -keepCDATA is specified then CDATA sections aren't added to the tree as text nodes (and, if necessary, combined with sibling text nodes into one text node) as without this option but are added as CDATA_SECTION_NODEs to the tree. Please note that the resulting tree isn't prepared for XPath selects or to be the source or the stylesheet of an XSLT transformation. If not combined with -keepEmpties only not whitespace only CDATA sections will be added to the resulting DOM tree. -channel <channel-ID> If -channel <channel-ID> is specified, the input to be parsed is read from the specified channel. The encoding setting of the channel (via fconfigure -encoding) is respected, ie the data read from the channel are converted to UTF-8 according to the encoding settings before the data is parsed. -baseurl <baseURI> If -baseurl <baseURI> is specified, the baseURI is used as the base URI of the document. External entities references in the document are resolved relative to this base URI. This base URI is also stored within the DOM tree. -feedbackAfter <#bytes> If -feedbackAfter <#bytes> is specified, the Tcl command given by -feedbackcmd is evaluated at the first element start within the document (or an external entity) after the start of the document or external entity or the last such call after #bytes. For backward compatibility if no -feedbackcmd is given but there is a Tcl proc named ::dom::domParseFeedback this proc is used as -feedbackcmd. If there isn't such a proc and -feedbackAfter is used it is an error to not also use -feedbackcmd. If the called script raises error, then parsing will be aborted, the dom parse call returns error, with the script error msg as error msg. If the called script return -code break, the parsing will abort and the dom parse call will return the empty string. -feedbackcmd <script> If -feedbackcmd <script> is specified, the script script is evaluated at the first element start within the document (or an external entity) after the start of the document or external entity or the last such call after #bytes value given by the -feedbackAfter option. If -feedbackAfter isn't given, using this option doesn't has any effect. If the called script raises error, then parsing will be aborted, the dom parse call returns error, with the script error msg as error msg. If the called script return -code break, the parsing will abort and the dom parse call will return the empty string. -externalentitycommand <script> If -externalentitycommand <script> is specified, the specified Tcl script is called to resolve any external entities of the document. The actual evaluated command consists of this option followed by three arguments: the base uri, the system identifier of the entity and the public identifier of the entity. The base uri and the public identifier may be the empty list. The script has to return a Tcl list consisting of three elements. The first element of this list signals how the external entity is returned to the processor. Currently the two allowed types are "string" and "channel". The second element of the list has to be the (absolute) base URI of the external entity to be parsed. The third element of the list are data, either the already read data out of the external entity as string in the case of type "string", or the name of a Tcl channel, in the case of type "channel". Note that if the script returns a Tcl channel, it will not be closed by the processor. It must be closed separately if it is no longer needed. -useForeignDTD <boolean> If <boolean> is true and the document does not have an external subset, the parser will call the -externalentitycommand script with empty values for the systemId and publicID arguments. Please note that if the document also doesn't have an internal subset, the -startdoctypedeclcommand and -enddoctypedeclcommand scripts, if set, are not called. -paramentityparsing <always|never|notstandalone> The -paramentityparsing option controls, if the parser tries to resolve the external entities (including the external DTD subset) of the document while building the DOM tree. -paramentityparsing requires an argument, which must be either "always", "never", or "notstandalone". The value "always" means that the parser tries to resolves (recursively) all external entities of the XML source. This is the default in case -paramentityparsing is omitted. The value "never" means that only the given XML source is parsed and no external entity (including the external subset) will be resolved and parsed. The value "notstandalone" means, that all external entities will be resolved and parsed, with the exception of documents, which explicitly states standalone="yes" in their XML declaration. -forest If this option is given, there is no need for a single root; any sequence of well-formed, balanced subtrees will be parsed into a DOM tree. This works for the expat DOM builder, the simple xml parser enabled with -simple and the simple HTML parser enabled -with -html. If used together with -json or -html5 this option is ignored. -ignorexmlns It is recommended, that you only use this option with the -html5 option. If this option is given, no node within the created DOM tree will be internally marked as placed into an XML Namespace, even if there is a default namespace in scope for un-prefixed elements or even if the element has a defined namespace prefix. One consequence is that XPath node expressions on such a DOM tree doesn't work as may be expected. Prefixed element nodes can't be selected naively and element nodes without prefix will be seen by XPath expressions as if they are not in any namespace (no matter if they are in fact should be in a default namespace). If you need to inject prefixed node names into an XPath expression use the '%' syntax described in the documentation of the of the domNode command method >selectNodes. -billionLaughsAttackProtectionMaximumAmplification <float> This option together with -billionLaughsAttackProtectionActivationThreshold gives control over the parser limits that protects against billion laugh attacks (https://en.wikipedia.org/wiki/Billion_laughs_attack). This option expects a float >= 1.0 as argument. You should never need to use this option, because the default value (100.0) should work for any real data. If you ever need to increase this value for non-attack payload, please report. -billionLaughsAttackProtectionActivationThreshold <long> This option together with -billionLaughsAttackProtectionMaximumAmplification gives control over the parser limits that protects against billion laugh attacks (https://en.wikipedia.org/wiki/Billion_laughs_attack). This option expects a positiv integer as argument. You should never need to use this option, because the default value (8388608) should work for any real data. If you ever need to increase this value for non-attack payload, please report.

    dom createDocument docElemName ?objVar? Creates a new DOM document object with one element node with node name docElemName. The objVar controls the memory handling as explained above. dom createDocumentNS uri docElemName ?objVar? Creates a new DOM document object with one element node with node name docElemName. Uri gives the namespace of the document element to create. The objVar controls the memory handling as explained above. dom createDocumentNode ?-jsonType jsonType? ?objVar? Creates a new 'empty' DOM document object without any element node. objVar controls the memory handling as explained above. If the option -jsonType is given the created document node will be of the given JSON type. dom createFromTypedList typedList ?objVar?

    Creates a new DOM document from the argument typedList. The objVar argument controls the memory handling as explained above.

    The typedList argument must be a Tcl list and must follow the format of the output of the document command method asTypedList, see there.

    dom createNodeCmd ?-returnNodeCmd? ?-tagName name? ?-jsonType jsonType? ?-namespace URI? (element|comment|text|cdata|pi)Node commandName This method creates Tcl commands, which in turn create tDOM nodes. Tcl commands created by this command are only available inside a script given to the domNode methods appendFromScript or insertBeforeFromScript. If a command created with createNodeCmd is invoked in any other context, it will return error. The created command commandName replaces any existing command or procedure with that name. If the commandName includes any Tcl namespace qualifiers, it is created in the specified namespace. The -tagName option is only allowed for the elementNode type. The -jsonType option is only allowed for elementNode and textNode types.

    If such command is invoked inside a script given as argument to the domNode method appendFromScript or insertBeforeFromScript it creates a new node and appends this node at the end of the child list of the invoking element node. If the option -returnNodeCmd was given, the command returns the created node as Tcl command. If this option was omitted, the command returns nothing. Each command creates always the same type of node. Which type of node is created by the command is determined by the first argument to the createNodeCmd. The syntax of the created command depends on the type of the node it creates.

    If the command type to create is elementNode, the created command will create an element node, if called. Without the -tagName option the tag name of the created node is commandName without Tcl namespace qualifiers. If the -tagName option was given then the created elements will have the value of this option as tag name. If the -jsonType option was given then the created node elements will have the given JSON type. If the -namespace option is given the created element node will be XML namespaced and in the namespace given by the option. The element name will be literal as given either by the command name or the -tagname option, if that was given. An appropriate XML namespace declaration will be automatically added, to bind the prefix (if the element name has one) or the default namespace (if the element name hasn't a prefix) to the namespace if such a binding isn't in scope.

    The syntax of the created command is:

    elementNodeCmd ?attributeName attributeValue ...? ?script? elementNodeCmd ?-attributeName attributeValue ...? ?script? elementNodeCmd name_value_list script

    The command syntax allows three different ways to specify the attributes of the resulting element. These could be specified with attributeName attributeValue argument pairs, in an "option style" way with -attriubteName attributeValue argument pairs (the '-' character is only syntactical sugar and will be stripped off) or as a Tcl list with elements interpreted as attribute name and the corresponding attribute value. The attribute name elements in the list may have a leading '-' character, which will be stripped off.

    Every elementNodeCmd accepts an optional Tcl script as last argument. This script is evaluated as recursive appendFromScript script with the node created by the elementNodeCmd as parent of all nodes created by the script.

    If the first argument of the method is textNode, the command will create a text node. If the -jsonType option was given then the created text node will have that JSON type. The syntax of the created command is:

    textNodeCmd ?-disableOutputEscaping? ?data?

    If the json type of the created text node is NULL, TRUE or FALSE then the data argument is optional, otherwise it this argument must be given.

    If the optional flag -disableOutputEscaping is given, the escaping of the ampersand character (&) and the left angle bracket (<) inside the data is disabled. You should use this flag carefully.

    If the first argument of the method is commentNode or cdataNode the command will create an comment node or CDATA section node. The syntax of the created command is:

    nodeCmd data

    If the first argument of the method is piNode, the command will create a processing instruction node. The syntax of the created command is:

    piNodeCmd target data

    Beside the with dom createNodeCmd calls created node commands there are two more commands which automatically insert nodes into the tree inside an appendFromScript script.

    tdom::fsnewNode ?-jsonType <jsonType>? ?-namespace <namespace>? tagName ?attributes? ?script?

    If called inside a fromScript context this command creates a new node tagName in the XML namespace namespace if the -namespace option was given and with the JSON type jsonType if the -jsonType option was given and appends this node at the end of the child list of the invoking element node. The attributes and script arguments will be processed as if given to an element creating node command. If called outside a fromScript context this command will raise error.

    tdom::fsinsertNode node

    If called inside o fromScript context this comannd instead of creating a new node appends the as argument given node at the end of the child list of the invoking element node. The node is unlinked from its previous place. If called outside a fromScript context this command will raise error.

    dom setStoreLineColumn ?boolean? If switched on, the DOM nodes will contain line and column position information for the original XML document after parsing. The default is not to store line and column position information. dom setNameCheck ?boolean? If NameCheck is true, every method which expects an XML Name, a full qualified name or a processing instructing target will check, if the given string is valid according to its production rule. For commands created with the createNodeCmd method to be used in the context of appendFromScript the status of the flag at creation time decides. If NameCheck is true at creation time, the command will check its arguments, otherwise not. The setNameCheck set this flag. It returns the current NameCheck flag state. The default state for NameCheck is true. dom setTextCheck ?boolean? If TextCheck is true, every command which expects XML Chars, a comment, a CDATA section value or a processing instructing value will check, if the given string is valid according to its production rule. For commands created with the createNodeCmd method to be used in the context of appendFromScript the status of the flag at creation time decides. If TextCheck is true at creation time, the command will check its arguments, otherwise not.The setTextCheck method sets this flag. It returns the current TextCheck flag state. The default state for TextCheck is true. dom setObjectCommands ?(automatic|token|command)? Controls if documents and nodes are created as Tcl commands or as token to be used with the domNode and domDoc commands. If the mode is 'automatic', then methods used at Tcl commands will create Tcl commands and methods used at doc or node tokes will create tokens. If the mode is 'command' then always Tcl commands will be created. If the mode is 'token', then always token will be created. The method returns the current mode. This method is an experimental interface. dom isName name Returns 1 if name is a valid XML Name according to production 5 of the XML 1.0 recommendation. This means that name is a valid XML element or attribute name. Otherwise it returns 0. dom isPIName name Returns 1 if name is a valid XML processing instruction target according to production 17 of the XML 1.0 recommendation. Otherwise it returns 0. dom isNCName name Returns 1 if name is a valid NCName according to production 4 of the of the Namespaces in XML recommendation. Otherwise it returns 0. dom isQName name Returns 1 if name is a valid QName according to production 6 of the of the Namespaces in XML recommendation. Otherwise it returns 0. dom isCharData string Returns 1 if every character in string is a valid XML Char according to production 2 of the XML 1.0 recommendation. Otherwise it returns 0. dom isHTML5CustomName string Returns 1 if string is a HTML5 valid custom element name (according to https://html.spec.whatwg.org/#valid-custom-element-name at 26 June 2024, it's a living standard). Otherwise it returns 0. dom clearString ?-replace? string Returns the string given as argument cleared out from any characters not allowed as XML parsed character data. If the -replace option is given then instead of removing such characters are replaced with \uFFFD. dom isBMPCharData string Returns 1 if every character in string is a valid XML Char with a Unicode code point within the Basic Multilingual Plane (that means, that every character within the string is at most 3 bytes long). Otherwise it returns 0. dom isComment string Returns 1 if string is a valid comment according to production 15 of the XML 1.0 recommendation. Otherwise it returns 0. dom isCDATA string Returns 1 if string is valid according to production 20 of the XML 1.0 recommendation. Otherwise it returns 0. dom isPIValue string Returns 1 if string is valid according to production 16 of the XML 1.0 recommendation. Otherwise it returns 0. dom featureinfo feature This method provides information about the used build options and the expat version. The valid values for the feature argument are: expatversion Returns the version of the underlyling expat version as string, something like "exapt_2.1.0". This is what the expat API function XML_ExpatVersion() returns. expatmajorversion Returns the major version of the at build time used expat version as integer. expatminorversion Returns the minor version of the at build time used expat version as integer. expatmicroversion Returns the micro version of the at build time used expat version as integer. dtd Returns as boolean if build with --enable-dtd. ns Returns as boolean if build with --enable-ns. unknown Returns as boolean if build with --enable-unknown. tdomalloc Returns as boolean if build with --enable-tdomalloc. lessns Returns as boolean if build with --enable-lessns. TCL_UTF_MAX Returns the TCL_UTF_MAX value of the Tcl core, tDOM was build with as integer html5 Returns as boolean, if build with --enable-html5. versionhash Returns the fossil repository version hash. pullparser Returns as boolean if the pullparser command is build in. schema Returns as boolean if the tDOM schema features are build in.
    XML DOM document node parsing
    tdom-0.9.5-src/doc/expatapi.n0000644000175000017500000002512714703531020014504 0ustar rolfrolf'\" '\" Generated from expatapi.xml '\" '\" BEGIN man.macros .if t .wh -1.3i ^B .nr ^l \n(.l .ad b .de AP .ie !"\\$4"" .TP \\$4 .el \{\ . ie !"\\$2"" .TP \\n()Cu . el .TP 15 .\} .ta \\n()Au \\n()Bu .ie !"\\$3"" \{\ \&\\$1 \\fI\\$2\\fP (\\$3) .\".b .\} .el \{\ .br .ie !"\\$2"" \{\ \&\\$1 \\fI\\$2\\fP .\} .el \{\ \&\\fI\\$1\\fP .\} .\} .. .de AS .nr )A 10n .if !"\\$1"" .nr )A \\w'\\$1'u+3n .nr )B \\n()Au+15n .\" .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n .nr )C \\n()Bu+\\w'(in/out)'u+2n .. .AS Tcl_Interp Tcl_CreateInterp in/out .de BS .br .mk ^y .nr ^b 1u .if n .nf .if n .ti 0 .if n \l'\\n(.lu\(ul' .if n .fi .. .de BE .nf .ti 0 .mk ^t .ie n \l'\\n(^lu\(ul' .el \{\ .\" Draw four-sided box normally, but don't draw top of .\" box if the box started on an earlier page. .ie !\\n(^b-1 \{\ \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .el \}\ \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .\} .fi .br .nr ^b 0 .. .de VS .if !"\\$2"" .br .mk ^Y .ie n 'mc \s12\(br\s0 .el .nr ^v 1u .. .de VE .ie n 'mc .el \{\ .ev 2 .nf .ti 0 .mk ^t \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' .sp -1 .fi .ev .\} .nr ^v 0 .. .de ^B .ev 2 'ti 0 'nf .mk ^t .if \\n(^b \{\ .\" Draw three-sided box if this is the box's first page, .\" draw two sides but no top otherwise. .ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .\} .if \\n(^v \{\ .nr ^x \\n(^tu+1v-\\n(^Yu \kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c .\} .bp 'fi .ev .if \\n(^b \{\ .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. .de DS .RS .nf .sp .. .de DE .fi .RE .sp .. .de SO .SH "STANDARD OPTIONS" .LP .nf .ta 5.5c 11c .ft B .. .de SE .fi .ft R .LP See the \\fBoptions\\fR manual entry for details on the standard options. .. .de OP .LP .nf .ta 4c Command-Line Name: \\fB\\$1\\fR Database Name: \\fB\\$2\\fR Database Class: \\fB\\$3\\fR .fi .IP .. .de CS .RS .nf .ta .25i .5i .75i 1i .if t .ft C .. .de CE .fi .if t .ft R .RE .. .de UL \\$1\l'|0\(ul'\\$2 .. '\" END man.macros .TH expatapi 3 "" Tcl "" .BS .SH NAME CheckExpatParserObj, CHandlerSetInstall, CHandlerSetRemove, CHandlerSetCreate, CHandlerSetGetUserData, GetExpatInfo \- Functions to create, install and remove expat parser object extensions. .SH SYNOPSIS .nf #include int \&\fBCheckExpatParserObj\fP (\fIinterp\fR, \fInameObj\fR) int \&\fBCHandlerSetInstall\fP (\fIinterp\fR, \fIexpatObj\fR, \fIhandlerSet\fR) int \&\fBCHandlerSetRemove\fP (\fIinterp\fR, \fIexpatObj\fR, \fIhandlerSetName\fR) CHandlerSet* \&\fBCHandlerSetCreate\fP (\fIhandlerSetName\fR) CHandlerSet* \&\fBCHandlerSetGet\fP (\fIinterp\fR, \fIexpatObj\fR, \fIhandlerSetName\fR) void* \&\fBCHandlerSetGetUserData\fP (\fIinterp\fR, \fIexpatObj\fR, \fIhandlerSetName\fR) TclGenExpatInfo* \&\fBGetExpatInfo\fP (\fIinterp\fR, \fIexpatObj\fR) .fi .SH ARGUMENTS .AS "unsigned long" clientData .AP Tcl_Interp "*interp" in Interpreter with the expat parser object. .AP Tcl_Obj "*expatObj" in A Tcl Object containing the command name of the expat parser object to be queried or modified. .AP char "*handlerSetName" in Identifier of the handler set. .AP CHandlerSet "*handlerSet" in Pointer to a C handler set. .AP Tcl_Obj "*nameObj" "" A Tcl Object containing the name of a expat parser object .BE .SH DESCRIPTION .PP The functions described in this manual allows one to add C level coded event handler to an tDOM Tcl expat parser objects. A tDOM Tcl expat parser object is able to have several Tcl scripts and C functions associated with a specific event. If the event occurs, first the Tcl scripts then the C functions associated with the event are called in turn. .PP A tDOM Tcl expat parser extension is an ordinary Tcl extension and loaded like every other Tcl extension. It must install at least one new Tcl Level command, that manipulates a tDOM Tcl expat parser object. .PP A C level handler set is a data structure like this: .CS typedef struct CHandlerSet { struct CHandlerSet *nextHandlerSet; char *name; /* refname of the handler set */ int ignoreWhiteCDATAs; /* ignore 'white' CDATA sections */ void *userData; /* Handler set specific Data Structure; the C handler set extension has to malloc the needed structure in his init func and has to provide a cleanup func (to free it). */ CHandlerSet_userDataReset resetProc; CHandlerSet_userDataFree freeProc; /* C func for element start */ XML_StartElementHandler elementstartcommand; /* C func for element end */ XML_EndElementHandler elementendcommand; /* C func for character data */ XML_CharacterDataHandler datacommand; /* C func for namespace decl start */ XML_StartNamespaceDeclHandler startnsdeclcommand; /* C func for namespace decl end */ XML_EndNamespaceDeclHandler endnsdeclcommand; /* C func for processing instruction */ XML_ProcessingInstructionHandler picommand; /* C func for default data */ XML_DefaultHandler defaultcommand; /* C func for unparsed entity declaration */ XML_NotationDeclHandler notationcommand; /* C func for external entity */ XML_ExternalEntityRefHandler externalentitycommand; /* C func for unknown encoding */ XML_UnknownEncodingHandler unknownencodingcommand; /* C func for comments */ XML_CommentHandler commentCommand; /* C func for "not standalone" docs */ XML_NotStandaloneHandler notStandaloneCommand; /* C func for CDATA section start */ XML_StartCdataSectionHandler startCdataSectionCommand; /* C func for CDATA section end */ XML_EndCdataSectionHandler endCdataSectionCommand; /* C func for !ELEMENT decl's */ XML_ElementDeclHandler elementDeclCommand; /* C func for !ATTLIST decl's */ XML_AttlistDeclHandler attlistDeclCommand; /* C func for !DOCTYPE decl's */ XML_StartDoctypeDeclHandler startDoctypeDeclCommand; /* C func for !DOCTYPE decl ends */ XML_EndDoctypeDeclHandler endDoctypeDeclCommand; /* C func for !ENTITY decls's */ XML_EntityDeclHandler entityDeclCommand; } CHandlerSet; .CE .PP The types and the arguments of the event functions (XML_*) are exactly the same like the expat lib handler functions and described in detail in expat.h, see there. The extension has only to provided the handler functions needed; it's perfectly OK to leave unused handler slots as the are (they are initialized to NULL by CHandlerSetCreate). .PP The \fIname\fR of this structure is used to identify the handler set. .PP If the flag \fIignoreWhiteCDATAs\fR is set, element content which contain only whitespace isn't reported with the datacommand. .PP The \fIuserData\fR element points to the handler set specific data. The event handler functions are called with this pointer as userData argument. .PP \&\fIresetProc\fR and \fIfreeProc\fR must have arguments that match the type .CS void (Tcl_Interp *interp, void *userData) .CE .PP \&\fIresetProc\fR is called in case the parser is reset with \&\fB reset\fR and should do any necessary cleanup and reinitializing to prepare the C handler set for a new XML document. The \&\fIfreeProc\fR is called, if the parser is deleted and should do memory cleanup etc. .PP \&\fICHandlerSetCreate\fR create a C handler set, gives it the name \&\fIname\fR and initializes any other element with NULL. .PP \&\fICHandlerSetInstall\fR adds the \fIhandlerSet\fR to the parser \&\fIexpatObj\fR. The parser has to be a tDOM Tcl expat parser object in the interpreter \fIinterp\fR. The name of the C handler set has to be unique for the parser. Returns 0 in case of success. Returns 1 if \fIexpatObj\fR isn't a parser object in the interpreter \fIinterp\fR. Returns 2 if this parser has already a C handler set with the handlerSet name. .PP \&\fICHandlerSetRemove\fR removes the C handler set referenced by the \&\fIhandlerSetName\fR from the parser \fIexpatObj\fR. The parser has to be a tDOM Tcl expat parser object in the interpreter \&\fIinterp\fR. \fICHandlerSetRemove\fR calls the freeProc function of the C handler set structure, removes the handler set from the C handler set list and frees the handler structure. Returns 0 in case of success. Returns 1 if \&\fIexpatObj\fR isn't a parser object in the interpreter \fIinterp\fR. Returns 2 if this parser hasn't a C handler set named \fIhandlerSetName\fR. .PP \&\fICheckExpatParserObj\fR returns 1, if \fInameObj\fR is a tDOM Tcl expat parser object in the interpreter \fIinterp\fR, otherwise it returns 0. Example: .CS int TclExampleObjCmd(dummy, interp, objc, objv) ClientData dummy; Tcl_Interp *interp; int objc; Tcl_Obj *const objv[]; { char *method; CHandlerSet *handlerSet; int methodIndex, result; simpleCounter *counter; static char *exampleMethods[] = { "enable", "getresult", "remove", NULL }; enum exampleMethod { m_enable, m_getresult, m_remove }; if (objc != 3) { Tcl_WrongNumArgs (interp, 1, objv, example_usage); return TCL_ERROR; } if (!CheckExpatParserObj (interp, objv[1])) { Tcl_SetResult (interp, "First argument has to be a expat parser object", NULL); return TCL_ERROR; } /* ... */ .CE .PP \&\fICHandlerSetGet\fR returns a pointer to the C handler Set referenced by the name \fIhandlerSetName\fR of the parser object \&\fIexpatObj\fR. \fIexpatObj\fR has to be an expat parser object in the interpreter \fIinterp\fR. Returns NULL in case of error. .PP \&\fICHandlerSetGetUserData\fR returns a pointer to the userData of the C handler set referenced by the name \fIhandlerSetName\fR of the parser object \&\fIexpatObj\fR. \fIexpatObj\fR has to be an expat parser object in the interpreter \fIinterp\fR. Returns NULL in case of error. .PP \&\fIGetExpatInfo\fR Is a helper function that returns a pointer to the TclGenExpatInfo structure of the tDOM Tcl expat parser object \&\fIexpatObj\fR. The \fIexpatObj\fR has to be a tDOM Tcl expat parser object in the interpreter \fIinterp\fR. This is most useful, to set the application status of the parser object. .PP See the simple but full functionally example in the extensions/example dir or the more complex example tnc in the extensions/tnc dir (a simple DTD validation extension). .SH "SEE ALSO" expat .SH KEYWORDS C handler set tdom-0.9.5-src/doc/manpage.css0000644000175000017500000000726514703531020014637 0ustar rolfrolf/* * $Id: manpage.css,v 1.4 2002/06/20 00:44:17 jenglish Exp $ * Author: Joe English, * Created: 26 Jun 2000 * Description: CSS stylesheet for TCL man pages */ HTML { background: #FFFFFF; color: black; } BODY { background: #FFFFFF; color: black; } DIV.body { margin-left: 10%; margin-right: 10%; } DIV.header,DIV.footer { width: 100%; margin-left: 0%; margin-right: 0%; } DIV.body H1,DIV.body H2 { margin-left: -5%; } /* Navigation material: */ DIV.navbar { width: 100%; margin-top: 5pt; margin-bottom: 5pt; margin-left: 0%; margin-right: 0%; padding-top: 5pt; padding-bottom: 5pt; background: #DDDDDD; color: black; border: 1px solid black; text-align: center; font-size: small; font-family: sans-serif; } P.navaid { text-align: center; } .navaid { font-size: small; font-family: sans-serif; } A.navaid:link { color: green; background: transparent; } A.navaid:visited { color: green; background: transparent; } A.navaid:active { color: yellow; background: transparent; } /* For most anchors, we should leave colors up to the user's preferences. */ /*-- A:link { color: blue; background: transparent; } A:visited { color: purple; background: transparent; } A:active { color: red; background: transparent; } --*/ H1, H2, H3, H4 { margin-top: 1em; font-family: sans-serif; font-size: large; color: #005A9C; background: transparent; text-align: left; } H1.title { text-align: center; } UL,OL { margin-right: 0em; margin-top: 3pt; margin-bottom: 3pt; } UL LI { list-style: disc; } OL LI { list-style: decimal; } DT { padding-top: 1ex; } DL.toc { font: normal 12pt/16pt sans-serif; margin-left: 10%; } UL.toc,UL.toc UL, UL.toc UL UL { font: normal 12pt/14pt serif; list-style: none; } LI.tocentry,LI.tocheading { list-style: none; margin-left: 0em; text-indent: 0em; padding: 0em; } .tocheading { font-family: sans-serif; font-weight: bold; color: #005A9C; background: transparent; } PRE { display: block; font-family: monospace; white-space: pre; margin: 0%; padding-top: 0.5ex; padding-bottom: 0.5ex; padding-left: 1ex; padding-right: 1ex; width: 100%; } PRE.syntax { color: black; background: #80ffff; border: 1px solid black; font-family: serif; } PRE.example { color: black; background: #f5dcb3; border: 1px solid black; } DIV.arglist { border: 1px solid black; width: 100%; } TH, THEAD TR, TR.heading { color: #005A9C; background: #DDDDDD; text-align: center; font-family: sans-serif; font-weight: bold; } TR.syntax { color: black; background: #80ffff; } TR.desc { color: black; background: #f5dcb3; } /* TR.row[01] are used to get alternately colored table rows. * Could probably choose better colors here... */ TR.row0 { color: black; background: #efffef; } TR.row1 { color: black; background: #efefff; } /* Workaround for Netscape bugs: * Netscape doesn't seem to compute table widths properly. * unless they're wrapped inside a DIV. (Additionally, * it appears to require a non-zero border-width.) */ DIV.table { border-width: 1px; border-color: white; width: 100%; } DIV.menu { /* Wrapper for TABLE class="menu" */ margin-top: 10px; margin-bottom: 10px; border: thin solid #005A9C; width: 100%; margin-left: 5%; } VAR { font-style: italic; } /* For debugging: highlight unrecognized elements: */ .unrecognized { color: red; background: green; } /* EOF */ tdom-0.9.5-src/doc/README0000644000175000017500000000320214703531020013360 0ustar rolfrolf The documentation is written in TMML (developed by Joe English). See http://tmml.sourceforge.net/ for informations about TMML. The HTML files and man pages are created from the TMML sources. To process the TMML files you need: o tDOM tDOM must be already successfully installed. o TMML VERY IMPORTANT: Make sure, you have the current CVS HEAD of TMML. The latest TMML distribution dates from August 2000 and could not used for the steps, described below. Informations about how to get TMML CVS HEAD could be found at http://sourceforge.net/cvs/?group_id=16386 You only need to check out the actual version of TMML, no further installation or modification is needed. o tcllib The TMML tools uses a module out of tcllib. Any recent distribution should do. If you really don't have it already, it's worth to install it, regardless of this TMML stuff. Installation should be completely painless. Find it at http://sourceforge.net/project/showfiles.php?group_id=12883 If you have all requirements in place, just do: tclsh path/to/your/tmml/tools/tmml.tcl toman dom.xml ?domDoc.xml ...? This creates nroff man pages of the accordingly documentation in the sub dir man (which will be automatically created, if it doesn't exist.) The next command creates the HTML pages: tclsh path/to/your/tmml/tools/tmml.tcl tohtml dom.xml ?domDoc.xml ...? This creates the HTML pages in the html sub dir (also, will be created, if needed). And you may do tclsh path/to/your/tmml/tools/tmml.tcl navpages This will create an index.html, the category-index.html and the keyword-index.html for the HTML version of the documentation. tdom-0.9.5-src/doc/tnc.n0000644000175000017500000001466014703531020013455 0ustar rolfrolf'\" '\" Generated from tnc.xml '\" '\" BEGIN man.macros .if t .wh -1.3i ^B .nr ^l \n(.l .ad b .de AP .ie !"\\$4"" .TP \\$4 .el \{\ . ie !"\\$2"" .TP \\n()Cu . el .TP 15 .\} .ta \\n()Au \\n()Bu .ie !"\\$3"" \{\ \&\\$1 \\fI\\$2\\fP (\\$3) .\".b .\} .el \{\ .br .ie !"\\$2"" \{\ \&\\$1 \\fI\\$2\\fP .\} .el \{\ \&\\fI\\$1\\fP .\} .\} .. .de AS .nr )A 10n .if !"\\$1"" .nr )A \\w'\\$1'u+3n .nr )B \\n()Au+15n .\" .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n .nr )C \\n()Bu+\\w'(in/out)'u+2n .. .AS Tcl_Interp Tcl_CreateInterp in/out .de BS .br .mk ^y .nr ^b 1u .if n .nf .if n .ti 0 .if n \l'\\n(.lu\(ul' .if n .fi .. .de BE .nf .ti 0 .mk ^t .ie n \l'\\n(^lu\(ul' .el \{\ .\" Draw four-sided box normally, but don't draw top of .\" box if the box started on an earlier page. .ie !\\n(^b-1 \{\ \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .el \}\ \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .\} .fi .br .nr ^b 0 .. .de VS .if !"\\$2"" .br .mk ^Y .ie n 'mc \s12\(br\s0 .el .nr ^v 1u .. .de VE .ie n 'mc .el \{\ .ev 2 .nf .ti 0 .mk ^t \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' .sp -1 .fi .ev .\} .nr ^v 0 .. .de ^B .ev 2 'ti 0 'nf .mk ^t .if \\n(^b \{\ .\" Draw three-sided box if this is the box's first page, .\" draw two sides but no top otherwise. .ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .\} .if \\n(^v \{\ .nr ^x \\n(^tu+1v-\\n(^Yu \kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c .\} .bp 'fi .ev .if \\n(^b \{\ .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. .de DS .RS .nf .sp .. .de DE .fi .RE .sp .. .de SO .SH "STANDARD OPTIONS" .LP .nf .ta 5.5c 11c .ft B .. .de SE .fi .ft R .LP See the \\fBoptions\\fR manual entry for details on the standard options. .. .de OP .LP .nf .ta 4c Command-Line Name: \\fB\\$1\\fR Database Name: \\fB\\$2\\fR Database Class: \\fB\\$3\\fR .fi .IP .. .de CS .RS .nf .ta .25i .5i .75i 1i .if t .ft C .. .de CE .fi .if t .ft R .RE .. .de UL \\$1\l'|0\(ul'\\$2 .. '\" END man.macros .TH tnc n "" Tcl "" .BS .SH NAME tnc \- tnc is an expat parser object extension, that validates the XML stream against the document DTD while parsing. .SH SYNOPSIS .nf package require tdom package require tnc set parser [expat] tnc $parser enable .fi .BE .SH DESCRIPTION .PP \&\fItnc\fR adds the C handler set "tnc" to a tcl expat parser obj. This handler set is a simple DTD validator. If the validator detects a validation error, it sets the interp result, signals error and stops parsing. There isn't any validation error recovering. As a consequence, only valid documents are completely parsed. .PP This handler set has only three methods: .TP \&\fB\fBtnc\fP \fIparserObj\fB \fBenable\fP \&\fR .RS .PP Adds the tnc C handler set to a Tcl expat parser object. .RE .TP \&\fB\fBtnc\fP \fIparserObj\fB \fBremove\fP \&\fR .RS .PP Removes the tnc validatore from the parser \fIparserObj\fR and frees all information, stored by it. .RE .TP \&\fB\fBtnc\fP \fIparserObj\fB \fBgetValidateCmd\fP \fB?validateCmdName?\fP \&\fR .RS .PP Returns a new created validation command, if one is available from the parser command, otherwise it signals error. The name of the validation command is the \fIvalidateCmdName\fR, if this optional argument was given, or a random chosen name. A validation command is available in a parser command, if the parser with tnc enabled was previously used, to parse an XML document with a valid doctype declaration, a valid external subset, if one was given by the doctype declaration, and a valid internal subset. The further document doesn't need to be valid, to make the validation command available. The validation command can only get received one time from the parser command. The created validation command has this syntax: .CS \&\fBvalidationCmd\fP \fImethod\fR \fI?args?\fR .CE .PP The valid methods are: .TP \&\fB\fBvalidateDocument\fP \fIdomDocument\fB \fI?varName?\fB \&\fRChecks, if the given domDocument is valid against the DTD information represented by the validation command. Returns 1, if the document ist valid, 0 otherwise. If the \fIvarName\fR argument is given, then the variable it names is set to the detected reason for the validation error or to the empty string in case of a valid document. .TP \&\fB\fBvalidateTree\fP \fIelementNode\fB \fI?varName?\fB \&\fRChecks, if the given subtree with \fIdomNode\fR as root element is a possible valid subtree of a document conforming to the DTD information represented by the validation command. IDREF could not checked, while validating only a subtree, but it is checked, that every known ID attribute in the subtree is unique. Returns 1, if the subtree is OK, 0 otherwise. If the \&\fIvarName\fR argument is given, then the variable it names is set to the detected reason for the validation error or to the empty string in case of a valid subtree. .TP \&\fB\fBvalidateAttributes\fP \fIelementNode\fB \fI?varName?\fB \&\fRChecks, if there is an element declaration for the name of the \&\fIelementNode\fR in the DTD represented by the validation command and, if yes, if the attributes of the \fIelementNode\fR are conform to the ATTLIST declarations for that element in the DTD. Returns 1, if the attributes and there value types are OK, 0 otherwise. If the \fIvarName\fR argument is given, then the variable it names is set to the detected reason for the validation error or to the empty string in case the element has all its required attributes, only declared attributes and the values of the attributes matches there type. .TP \&\fB\fBdelete\fP \&\fRDeletes the validation command and frees the memory used by it. Returns the empty string. .RE .SH BUGS .PP The validation error reports could be much more informative and user-friendly. .PP The validator doesn't detect ambiguous content models (see XML recomendation Section 3.2.1 and Appendix E). Most Java validators also doesn't, but handle such content models right anyhow. Tnc does not; if your DTD has such ambiguous content models, tnc can not used to validate documents against such (not completely XML spec compliant) DTDs. .PP It isn't possible to validate XML documents with standalone="yes" in the XML Declaration .PP Violations of the validity constraints Proper Group/PE Nesting and Proper Conditional Section/PE Nesting are not detected. They could only happen inside a invalid DTD, not in the content of a document. .SH KEYWORDS Validation, DTD tdom-0.9.5-src/doc/schema.xml0000644000175000017500000022740214703531020014474 0ustar rolfrolf tdom::schema Creates a schema validation command package require tdom tdom::schema ?create? cmdName
    DESCRIPTION

    Every call of this command creates a new validation command. A validation command has methods to define a schema and is able to validate XML data or to post-validate a tDOM DOM tree (and to some degree other kind of hierarchical data) against this schema.

    Also, a validation command may be used as argument to the -validateCmd option of the dom parse and the expat commands to enable validation additionally to what they do otherwise.

    The methods of created commands are:

    prefixns ?prefixUriList? This method controls prefix (or abbreviation) to namespace URI mapping. Wherever a namespace argument is expected in the schema command methods the "prefix" could be used instead of the namespace URI. If the list maps the same prefix to different namespace URIs, the first one wins. If there is no such prefix, the namespace argument is used literally as namespace URI. If the method is called without argument, it returns the current prefixUriList. If the method is called with the empty string, any namespace URI arguments are used literally. This is the default. defelement name ?namespace? <definition script> This method defines the element name (optional in the namespace namespace) in the schema. The definition script is evaluated and defines the content model of the element. If the namespace argument is given, any element or ref references in the definition script not wrapped inside a namespace command are resolved in that namespace. If there is already a element definition for the name/namespace combination, the command raises error. defelementtype typename ?namespace? <definition script> This method defines the element type typename (optional in the namespace namespace) in the schema. If the element type is used in a definition script with the schema command element, the validation engine expects an element content according to content model definition script. Defining (and using) element types seems only sensible if you really have elements with the same name and namespace but different content models. The definition script is evaluated and defines the content model of the element it is assgned to. If the namespace argument is given, any element or ref references in the definition script not wrapped inside a namespace command are resolved in that namespace. If there is already an elementtype definition for the typename/namespace combination, the command raises error. The document element of any XML to validate cannot be a defelementtype defined element. defpattern name ?namespace? <definition script> This method defines a (maybe complex) content particle with the name (optional in the namespace namespace) in the schema, to be used in other definition scripts with the definition command ref. The definition script is evaluated and defines the content model of the content particle. If the namespace argument is given, any element or ref references in the definition script not wrapped inside a namespace command are resolved in that namespace. If there is already a pattern definition for the name/namespace combination, the command raises error. deftexttype name <constraint script> This method defines a bundle of text constraints that can be referred to by name while defining constraints on text element or attribute values. If there is already a text type definition with this name, the command raises error. A text type may be referred before it is defined in the schema. If a referred text type isn't defined anywhere in the schema then any text will match this type during validation. start documentElement ?namespace? This method defines the name and namespace of the root element of a tree to validate. If this method is used, the root element must match for validity. If start is not used, any element defined by defelement may be the root of a valid document. The start method may be used several times with varying arguments during the lifetime of a validation command. If the command is called with just the empty string (and no namespace argument), the validation constraint for the root element is removed and any defined element will be valid as root of a tree to validate. define <definition script> This method defines several elements or patterns or a whole schema with one call, by evaluating the definition script>. All schema command methods so far (prefixns, defelement, defelementtype, defpattern, deftexttype and start) are allowed top level in the definition script. The define method itself isn't allowed recursively. event (start|end|text) ?event specific data? This method enables validation of hierarchical data against the content constraints of the validation command. start name ?attributes? ?namespace? Checks if the current validation state allows the element name in the namespace to start here. It raises error if not. end Checks if the current innermost open element may end there in the current state without violation of validation constraints. It raises error if not. text text Checks if the current validation state allows the given text content. It raises error if not. validate ?options? <XML string> ?objVar?

    Returns true if the <XML string> is valid, or false, otherwise. If validation has failed and the optional objVar argument is given, the variable with that name is set to a validation error message. If the XML string is valid and the optional objVar argument is given, the variable will be untouched.

    The valid options are:

    -baseurl <baseURI> If -baseurl <baseURI> is specified, the baseURI is used as the base URI of the document. External entities references in the document are resolved relative to this base URI. This base URI is also stored within the DOM tree. -externalentitycommand <script> If -externalentitycommand <script> is specified, the specified Tcl script is called to resolve any external entities of the document. The default is "::tdom::extRefHandler", which is a simple file URL resolver defined by the script part of the package. Setting the option value to the empty string disables resolving of external entities. The actual evaluated command consists of this option followed by three arguments: the base uri, the system identifier of the entity and the public identifier of the entity. The base uri and the public identifier may be the empty list. The script has to return a Tcl list consisting of three elements. The first element of this list signals how the external entity is returned to the processor. Currently the two allowed types are "string" and "channel". The second element of the list has to be the (absolute) base URI of the external entity to be parsed. The third element of the list are data, either the already read data out of the external entity as string in the case of type "string", or the name of a Tcl channel, in the case of type "channel". Note that if the script returns a Tcl channel, it will not be closed by the processor. It must be closed separately if it is no longer needed. -paramentityparsing <always|never|notstandalone> The -paramentityparsing option controls, if the parser tries to resolve the external entities (including the external DTD subset) of the document while building the DOM tree. -paramentityparsing requires an argument, which must be either "always", "never", or "notstandalone". The value "always" means that the parser tries to resolves (recursively) all external entities of the XML source. This is the default in case -paramentityparsing is omitted. The value "never" means that only the given XML source is parsed and no external entity (including the external subset) will be resolved and parsed. The value "notstandalone" means, that all external entities will be resolved and parsed, with the exception of documents, which explicitly states standalone="yes" in their XML declaration. -useForeignDTD <boolean> If <boolean> is true and the document does not have an external subset, the parser will call the -externalentitycommand script with empty values for the systemId and publicID arguments. Please note that if the document also doesn't have an internal subset, the -startdoctypedeclcommand and -enddoctypedeclcommand scripts, if set, are not called.
    validatefile ?options? filename ?objVar? Returns true if the content of filename is valid, or false, otherwise. The given file is fed as binary stream to expat, therefore, only US-ASCII, ISO-8859-1, UTF-8 or UTF-16 encoded data will work with this method. If validation has failed and the optional objVar argument is given, the variable with that name is set to a validation error message. If the XML data is valid and the optional objVar argument is given, the variable will be untouched. The allowed options and their meaning are the same as for the validate method; see there for a description. validatechannel ?options? channel ?objVar? Returns true if the content read from the Tcl channel channel is valid, or false, otherwise. Since data read out of a Tcl channel is UTF-8 encoded, any misleading encoding declaration at the beginning of the data will lead to errors. If the validation fails and the optional objVar argument is given, the variable with that name is set to a validation error message. If the XML data is valid and the optional objVar argument is given, the variable will be untouched. The allowed options and their meaning are the same as for the validate method; see there for a description. domvalidate domNode ?objVar? Returns true if the first argument is a valid tree, or false, otherwise. If validation has failed and the optional objVar argument is given, the variable with that name is set to a validation error message. If the dom tree is valid and the optional objVar argument is given, the variable with that name is set to the empty string. reportcmd ?cmd? This method expects the name of a Tcl command to be called in case of validation error. The command will be called with two arguments appended: the schema command which raises the validation error, and a validation error code.

    The possible error codes are:

    MISSING_ELEMENT
    MISSING_TEXT
    UNEXPECTED_ELEMENT
    UNEXPECTED_ROOT_ELEMENT
    UNEXPECTED_TEXT
    UNKNOWN_ROOT_ELEMENT
    UNKNOWN_ATTRIBUTE
    MISSING_ATTRIBUTE
    INVALID_ATTRIBUTE_VALUE
    DOM_KEYCONSTRAINT
    DOM_XPATH_BOOLEAN
    INVALID_KEYREF
    INVALID_VALUE
    UNKNOWN_GLOBAL_ID
    UNKNOWN_ID

    For more detailed information see section Recovering.

    delete This method deletes the validation command. info ?args? This method bundles methods to query the state of and details about the schema command. validationstate This method returns the state of the validation command with respect to validation state. The possible return values and their meanings are:
    READY
    The validation command is ready to start validation
    VALIDATING
    The validation command is in the process of validating input.
    FINISHED
    The validation has finished, no further events are expected.
    vstate This method is a shorter alias for validationstate; see there. line If the schema command is currently validating, this method returns the line part of the parsing position information, and the empty string in all other cases. If the schema command is currently post-validating a DOM tree, there may be no position information stored at some or all nodes. The empty string is returned in these cases. column If the schema command is currently validating this method returns the column part of the parsing position information, and the empty string in all other cases. If the schema command is currently post-validating a DOM tree, there may be no position information stored at some or all nodes. The empty string is returned in these cases. byteIndex If the schema command is currently validating this method returns the byte position of the parsing position information, and the empty string in all other cases. If the schema command is currently post-validating a DOM tree, there may be no position information stored at some or all nodes. The empty string is returned in these cases. domNode If the schema command isn't currently post-validating a DOM tree this method returns the empty string. Otherwise, if the schema command waits for the reportcmd script to finish while recovering from a validation error it returns the node on which the validation engine is currently looking at in case the node is an ELEMENT_NODE or, if not, its parent node. It is recommended that you do not use this method. Or at least leave the DOM tree alone, use it read-only. nrForwardDefinitions Returns how many elements, element types and ref patterns are referenced that aren't defined so far (summed together). definedElements Returns in no particular order the defined elements in the grammar as list. If an element is namespaced, its list entry will be itself a list with two elements, with the name as first and the namespace as second element. definedElementtypes Returns in no particular order the defined element types in the grammar as list. If an element type is namespaced, its list entry will be itself a list with two elements, with the name as first and the namespace as second element. definedPatterns Returns in no particular order the defined named pattern in the grammar as list. If a named pattern is namespaced, its list entry will be itself a list with two elements, with the name as first and the namespace as second element. expected Returns in no particular order all possible next events (since the last successful event match, if there was one) as a list. If an element is namespaced its list entry will be itself a list with two elements, with the name as first and the namespace as second element. If text is a possible next event, the list entry will be a two elements list, with #text as first element and the empty string as second. If an any element constraint is possible. the list entry will be a two elements list, with <any> as first element and the empty string as second. If an any element in a certain namespace constraint is possible, the list entry will be a two elements list, with <any> as first element and the namespace as second. If element end is a possible event, the list entry will be a two elements list with <elementend> as first element and the empty string as second element. definition name ?namespace? Returns the code that defines the given element. The command raises error if there is no definition of that element. typedefinition name ?namespace? Returns the code that defines the given element type definition. The command raises error if there is no definition of that element. patterndefinition name ?namespace? Returns the code that defines the given pattern definition. The command raises error if there is no definition of a pattern with that name and, if given, namespace. vaction ?name|namespace|text?

    This method returns useful information only if the schema command waits for the reportcmd script to finish while recovering from a validation error. Otherwise it returns NONE.

    If the command is called without the optional argument the possible return values and their meanings are:

    NONE
    The schema command currently does not recover from a validation event.
    MATCH_ELEMENT_START
    Element start event, which includes looking for missing or unknown attributes.
    MATCH_ELEMENT_END
    Element end event.
    MATCH_TEXT
    Validating text between tags.
    MATCH_ATTRIBUTE_TEXT
    Attribute text value constraint check
    MATCH_GLOBAL
    Checking global IDs
    MATCH_DOM_KEYCONSTRAINT
    Checking domunique constraint
    MATCH_DOM_XPATH_BOOLEAN
    Checking domxpathboolean constant

    If called with one of the possible optional arguments, the command returns detail information depending on current action.

    name
    Returns the name of the element that has to match in case of MATCH_ELEMENT_START. Returns the name of the closed element in case of MATCH_ELEMENT_END. Returns the name of the attribute in case of MATCH_ATTRIBUTE_TEXT. Returns the name of the parent element in case of MATCH_TEXT.
    namespace
    Returns the namespace of the element that has to match in case of MATCH_ELEMENT_START. Returns the namespace of the closed element in case of MATCH_ELEMENT_END. Returns the namespace of the attribute in case of MATCH_ATTRIBUTE_TEXT. Returns the namespace of the parent element in case of MATCH_TEXT.
    text
    Returns the text to match in case of MATCH_TEXT. Returns the value of the attribute in case of MATCH_ATTRIBUTE_TEXT.
    stack top|inside|associated In Tcl scripts evaluated by validation this method provides information about the current validation stack. Called outside this context the method returns the empty string. top Returns the element whose content is currently checked (the open element tag at this moment). inside Returns all currently open elements as a list. associated Returns the data associated with the current top most stack content particle or the empty string if there isn't any.
    reset This method resets the validation command into state READY (while preserving the defined grammar).
    Schema definition scripts

    Schema definition scripts are ordinary Tcl scripts evaluated in the namespace tdom::schema. The schema definition commands listed below in this Tcl namespace allow the definition of a wide variety of document structures. Every schema definition command establishes a validation constraint on the content which has to match or must be optional to qualify the content as valid. It is a validation error if there is additional (not matched) content. White-space-only text (in the XML sense of white space) between any different tags is ignored, with the exception of text only elements (for which even white-space-only text will be considered as significant content).

    The schema definition commands are:

    element name ?quant? (?<definition script>|"type" typename)?

    If neither the optional argument definition script nor the string "type" and a typename is given this command refers to the element defined with defelement with the name name in the current context namespace.

    If the string "type" and a typename is given then the content of the element is described by the content model defined with defelementtype with the name typename in the current context namespace.

    If the defelement script argument is given, the validation constraint expects an element with the name name in the current namespace with content "locally" defined by the definition script. Forward references to so far not defined elements or patterns or other local definitions of the same name inside the definition script are allowed. If a forward referenced element is not defined until validation, only an empty element with name name and namespace namespace and no attributes matches.

    ref name ?quant? This command refers to the content particle defined with defpattern with the name name in the current context namespace. Forward references to a so far not defined pattern and recursive references are allowed. If a forward referenced pattern is not defined until validation no content whatsoever is expected ("empty match"). group ?quant? <definition script> This method group a sequence of content particles defined by the definition script>, which have to match in this sequence order. choice ?quant? <definition script> This schema constraint matches if one of the top level content particles defined by the definition script> matches. If one of this top level content particle is optional this constraint matches the "empty match". interleave ?quant? <definition script> This schema constraint matches after every of the required top level content particles defined by the definition script> have matched (and, optional, some or all other) in any arbitrary order. mixed ?quant? <definition script> This schema constraint matches for any text (including the empty one) and every top level content particle defined by the definition script> with default quantifier *. text ?<constraint script>|"type" typename? Without the optional constraint script this validation constraint matches every string (including the empty one). With constraint script or with a given text type argument a text matching this script or the text type is expected. any ?options? ?<namespace list>? ?quant? Without arguments the any command matches every element. If the <namespace list> argument is given, this matches any element in a namespace out of that list. The empty string means elements with no namespace. If additionally the option -not is given then this maches every element with a namespace not in the list. The only other recognized option is -- which signals the end of any options. Please note that in case of no namespace argument is given that means that the quantifier * and + will eat up any elements until the enclosing element ends. If you really have a namespace that looks like a valid tDOM schema quantifier you will have to spell out always both arguments. attribute name ?quant? (?<constraint script>|"type" typename?) The attribute command defines an attribute (in no namespace) to the enclosing element. The first definition of name inside an element definition wins; later definitions of the same name are silently ignored. After the name argument there may be one of the quantifiers ? or !. If there is, it will be used. Otherwise the attribute will be required (must be present in the XML source). If there is one argument more this argument is evaluated as constraint script, defining the value constraints of the attribute. Otherwise, if there are two more arguments and the first of them is the bare-word "type" the following argument is used as a text type name. This command is only allowed at top level in the definition script of a defelement/element script. nsattribute name namespace ?quant? (?<constraint script>|"type" typename?) This command does the same as the command attribute, for the attribute name in the namespace namespace. namespace URI <definition script> Evaluates the definition script with context namespace URI. Every element, element type or ref command name will be looked up in the namespace URI, and local defined elements will be in that namespace. An empty string as URI means no namespace. tcl tclcmd ?arg arg ...? Evaluates the Tcl script tclcmd arg arg ... . This validation command is only allowed in strict sequential context (not in choice, mixed and interleave). If the return code is something else than TCL_OK, this is an error (which is not caught and reported by reportcmd). self Returns the schema command. associate data This command is only allowed top-level inside definition scripts of the element, elementtype, pattern or interleave content particles. Associates the data given as argument with the currently defined content particle and may be requested in scripts evaluated while validating the content of that particle with the schema command method call info stack associated. domunique selector fieldlist ?name? ?"IGNORE_EMPTY_FIELD_SET"|("EMPTY_FIELD_SET_VALUE" emptyFieldSetValue)? If not postvalidating a DOM tree with domvalidate this constraint always matches. If postvalidating this constraint resembles the xsd key/keyref mechanism. The selector argument may be any valid XPath expression (without the xsd limits). Several domunique commands within one element definition are allowed. They are checked in definition order. The argument name is available in the recovering script per info vaction name. If the fieldlist does not select something for a node of the result set of the selector the key value will be the empty string by default. If the arguments EMPTY_FIELD_SET_VALUE <value> are given an empty node set will have the key value value. If instead the flag IGNORE_EMPTY_FIELD_SET flag is given an empty node set result will not have any key value. domxpathboolean XPath_expr ?name?

    If not postvalidating a DOM tree with domvalidate this constraint always matches. If postvalidating the XPath_expr argument is evaluated (with the node matching the schema parent of the domxpathboolean command as context node). The constraint maches if the result of this XPath expression, converted to boolean by XPath rules, is true. Several domxpathboolean commands within one element definition are allowed. They are checked in definition order.

    This enables checks depending on more than one element. Consider

    tdom::schema s s define { defelement doc { element a ! text element b ! text element c ! text domxpathboolean "a * b * c >= 20000" volume domxpathboolean "a > b and b > c" sequence } }
    jsontype JSON structure type

    If not postvalidating a DOM tree with domvalidate this constraint always matches. If postvalidating the constraint matches if the enclosing element has the JSON type given as argument to the structure constraint. The possible JSON structure types are NONE, OBJECT and ARRAY. This constraint is only allowed as direct child of a defelement, defelementtype or local element definition.

    prefixns ?prefixUriList? This defines a prefix to namespace URI mapping exactly as a schemacmd prefixns would. It is meant as top-level command of a schemacmd define script. This command is not allowed nested in another definition script command and will raise error, if you call it there. defelement name ?namespace? <definition script> This defines an element exactly as a schemacmd defelement call would. It is meant as top-level command of a schemacmd define script. This command is not allowed nested in another definition script command and will raise error, if you call it there. defelementtype typename ?namespace? <definition script> This defines an elementtype exactly as a schemacmd defelementtype call would. It is meant as top-level command of a schemacmd define script. This command is not allowed nested in another definition script command and will raise error, if you call it there. defpattern name ?namespace? <definition script> This defines a named pattern exactly as a schemacmd defpattern call would. It is meant as top-level command of a schemacmd define script. This command is not allowed nested in another definition script command and will raise error, if you call it there. deftexttype name <constraint script> This defines a named bundle of text constraints exactly as a schemacmd deftexttype call would. It is meant as top-level command of a schemacmd define script. This command is not allowed nested in another definition script command and will raise error, if you call it there. start name ?namespace? This command works exactly as a schemacmd start call would. It is meant as top-level command of a schemacmd define script. This command is not allowed nested in another definition script command and will raise error, if you call it there.
    Quantity specifier

    Several schema definition commands expect a quantifier as one of their arguments which determines how often the content particle specified by the command is expected. The valid values for a quant argument are:

    ! The content particle has to occur exactly once in valid documents. ? The content particle may not occur more than once in valid documents - the particle is optional. * The content particle may occur zero or more times in a row in valid documents. + The content particle may occur one or more times in a row in valid documents. n The content particle must occur n times in a row in valid documents. The quantifier must be an integer greater zero. {n m} The content particle must occur at least n and at most m times in a row in valid documents. The quantifier must be a Tcl list with two elements. The first element of this list must be an integer with n >= 0. If the second list element is the character *, then there is no upper limit. Otherwise the second list element must be an integer with n < m.

    If an optional quantifier is not given, it defaults to * in case of the mixed command and to ! for all other commands.

    Text constraint scripts

    Text (parsed character data, as XML calls it) sometimes has to be of a certain kind or comply with certain rules to be valid. The text constraint script arguments to text, attribute, nsattribute and deftexttype commands are evaluated in the Tcl namespace tdom::schema::text namespace and allow the ensuing text constraint commands to check text for certain properties. The commands are defined in the Tcl namespace tdom::schema::text. They raise error in case they are called outside of a text constraint script.

    A few of the ensuing text type commands are exposed as general Tcl commands. They are defined in the namespace tdom::type and are called as documented below with the text to check appended to the argument list. They return a logical value. Please note that the commands may not accept starting or ending white space. If a command is available in the tdom::type namespace is recorded in its documentation.

    The tcl text constraint command

    The tcl text constraint command dispatches the check to an arbitrary Tcl command, thus enable any programmable decision rules.

    tcl tclcmd ?arg arg ...? Evaluates the Tcl script tclcmd arg arg ... and the text to validate appended to the argument list. The return value of the Tcl command is interpreted as a boolean.
    Basic XML types name This text constraint matches if the text value matches the XML name production https://www.w3.org/TR/xml/#NT-Name. This means that the text value must start with a letter, underscore (_), or colon (:), and may contain only letters, digits, underscores (_), colons (:), hyphens (-), and periods (.). ncname This text constraint matches if the text value matches the XML ncname production https://www.w3.org/TR/xml-names/#NT-NCName. This means that the text value must start with a letter or underscore (_), and may contain only letters, digits, underscores (_), hyphens (-), and periods (.) (The only difference to the name constraint is that colons are not permitted.) qname This text constraint matches if the text value matches the XML qname production https://www.w3.org/TR/xml-names/#NT-QName. This means that the text value is either a ncname or two ncnames joined by a colon (:). nmtoken This text constraint matches if the text value matches the XML nmtoken production https://www.w3.org/TR/xml/#NT-Nmtoken nmtokens This text constraint matches if the text value matches the XML nmtokens production https://www.w3.org/TR/xml/#NT-Nmtokens Basic type tests

    integer ?(xsd|tcl)? This text constraint matches if the text value could be parsed as an integer. If the optional argument to the command is tcl, everything that returns TCL_OK if fed into Tcl_GetInt() matches. If the optional argument to the command is xsd, the constraint matches if the value is a valid xsd:integer. Without argument xsd is the default. negativeInteger ?(xsd|tcl)? This text constraint matches the same text values as the integer text constraint (see there), with the additional constraint, that the value must be < zero. nonNegativeInteger ?(xsd|tcl)? This text constraint matches the same text values as the integer text constraint (see there), with the additional constraint, that the value must be >= zero. nonPositiveInteger ?(xsd|tcl)? This text constraint matches the same text values as the integer text constraint (see there), with the additional constraint, that the value must be <= zero. positiveInteger ?(xsd|tcl)? This text constraint matches the same text values as the integer text constraint (see there), with the additional constraint, that the value must be > zero. number ?(xsd|tcl)? This text constraint matches if the text value could be parsed as a number. If the optional argument to the command is tcl, everything that returns TCL_OK if fed into Tcl_GetDouble() matches. If the optional argument to the command is xsd, the constraint matches if the value is a valid xsd:decimal. Without argument xsd is the default. boolean ?(xsd|tcl)? This text constraint matches if the text value could be parsed as a boolean. If the optional argument to the command is tcl, everything that returns TCL_OK if fed into Tcl_GetBoolean() matches. If the optional argument to the command is xsd, the constraint matches if the value is a valid xsd:boolean. Without argument xsd is the default. date This text constraint matches if the text value is a xsd:date, which is basically like an ISO 8601 date of the form YYYY-MM-DD, with optional time zone part (either the letter Z or plus (+) or minus (-) followed by hh:mm and with maximum allowed positive or negative time zone 14:00). It follows the date rules of the Gregorian calendar for all dates. A preceding minus sign for bce dates is allowed. There is no year 0. The year may have more than 4 digits, but only if needed (no extra leading zeros). This is available as common Tcl command tdom::type::date. time This text constraint matches if the text value is a xsd:time, which is basically like an ISO 8601 time of the form hh:mm:ss with optional time zone part. The time zone part follow the rules of the date command; see there. All three parts of the time value (hours, minutes, seconds) must be spelled out with 2 digits. Additional fractional seconds (with a point ('.') as separator) are allowed, but not just a dangling point. The time value 24:00:00 (without fractional part) is allowed. This is available as common Tcl command tdom::type::time. dateTime This text constraint matches if the text value is a xsd:dateTime, which is basically like an ISO 8601 date time of the form YYYY-MM-DDThh:mm:ss with optional time zone part. The date and time zone parts follows the rules of the date and time command; see there. The time part (including the signaling 'T' character) is mandatory. This is available as common Tcl command tdom::type::dateTime. duration This text constraint matches if the text value is a xsd:duration, which is basically like an ISO 8601 duration of the form PnYnMnDTnHnMnS. All parts other than the starting P and - if one of H, M or S is given - T are optional. In case the following sign letter is S, n may be a decimal (with at least one digit before and after the dot), otherwise it must be a (positive) integer. This is available as common Tcl command tdom::type::duration. base64 This text constraint matches if text is valid according to RFC 4648. hexBinary This text constraint matches if text is a sequence of binary octets in hexadecimal encoding, where each binary octet is a two-character hexadecimal number. Lowercase and uppercase letters A through F are permitted. unsignedByte This text constraint matches if the text value is a xsd:unsignedByte. This is an integer between 0 and 255, both included, optionally preceded by a + sign and leading zeros. unsignedShort This text constraint matches if the text value is a xsd:unsignedShort. This is an integer between 0 and 65535, both included, optionally preceded by a + sign and leading zeros. unsignedInt This text constraint matches if the text value is a xsd:unsignedInt. This is an integer between 0 and 4294967295, both included, optionally preceded by a + sign and leading zeros. unsignedLong This text constraint matches if the text value is a xsd:unsignedLong. This is an integer between 0 and 18446744073709551615, both included, optionally preceded by a + sign and leading zeros. byte This text constraint matches if the text value is a xsd:byte. This is an integer between -128 and 127, both included, optionally preceded by a + or a - sign and leading zeros. short This text constraint matches if the text value is a xsd:short. This is an integer between -32768 and 32767, both included, optionally preceded by a + or a - sign and leading zeros. int This text constraint matches if the text value is a xsd:int. This is an integer between -2147483648 and 2147483647, both included, optionally preceded by a + or a - sign and leading zeros. long This text constraint matches if the text value is a xsd:long. This is an integer between -9223372036854775808 and 9223372036854775807, both included, optionally preceded by a + or a - sign and leading zeros.
    Logical constructs oneOf <constraint script> This text constraint matches if one of the text constraints defined in the argument constraint script matches the text. It stops after the first matches and probes the text constraints in the order of definition. allOf <constraint script> This text constraint matches if all of the text constraints defined in the argument constraint script matches the text. It stops after the first match failure and probes the text constraints in the order of definition. Since the schema definition command text also expects all text constraints to match the text constraint, allOf is useful mostly in connection with the oneOf text constraint command. not <constraint script> This text constraint matches if none of the text constraints defined in the argument constraint script matches the text. It stops after the first matching constraint in the constraint script and reports validation error. The text constraints in the constraint script are probed in the order of definition. type text type name This text constraint matches if the text type given as argument matches. Constraints on processed text value whitespace (preserve|replace|collapse) <constraint script> This text constraint command does white-space (#x20 (space, ' '), #x9 (tab, \t), #xA (linefeed, \n), and #xD (carriage return, \r) normalization to the text value and checks the resulting text with the text constraints of the constraint script argument. The normalization method preserve keeps everything as it is; this is another way to say allOf. The replace normalization method replaces any single white-space character (as above) to a space. The collapse normalization method removes all leading and trailing white-space, and all the other sequences of contiguous white-space are replaced by a single space. split ?type ?args??<constraint script>

    This text constraint command splits the text to test into a list of values and tests all elements of that list for the text constraints in the evaluated constraint script>.

    The available types are:

    whitespace
    The text to split is stripped of all white space at start and end and split into a list at any successive white space.
    tcl tclcmd ?arg ...?
    The text to split is handed to the tclcmd, which is evaluated on global level, appended with every given arg and the text to split as last argument. This call must return a valid Tcl list whose elements are tested.

    The default in case no split type argument is given is whitespace.

    strip <constraint script> This text constraint command tests all text constraints in the evaluated constraint script> with the text to test stripped of all white space at start and end.
    Various other string properties fixed value The text constraint only matches if the text value is string equal to the given value. enumeration list This text constraint matches if the text value is equal to one element (respecting case and any white-space) of the argument list, which has to be a valid Tcl list. match ?-nocase? glob_style_match_pattern> This text constraint matches if the text value matches the glob style pattern given as argument. It follows the rules of the Tcl [string match] command, see https://www.tcl.tk/man/tcl8.6/TclCmd/string.htm#M35. regexp expression This text constraint matches if the text value matches the regular expression given as argument. https://www.tcl.tk/man/tcl8.6/TclCmd/re_syntax.htm describes the regular expression syntax length length This text constraint matches if the length of the text value (in characters, not bytes) is length. The length argument must be a positive integer or zero. maxLength length This text constraint matches if the length of the text value (in characters, not bytes) is at most length. The length argument must be an integer greater zero. minLength length This text constraint matches if the length of the text value (in characters, not bytes) is at least length. The length argument must be an integer greater zero. id ?keySpace? This text constraint command marks the text as a document wide ID (to be referenced by an idref). Every ID value within a document must be unique. It isn't an error if the ID isn't actually referenced within the document. The optional argument keySpace does all this for a named key space. The key space "" (the empty sting) is another key space then the id command without keySpace argument. idref ?keySpace? This text constraint command expects the text to be a reference to an ID within the document. The referenced ID may appear later in the document, that the reference. Several references within the document to one ID are possible. jsontype <JSON text type> If not postvalidating a DOM tree with domvalidate this constraint always matches. If postvalidating the current TEXT_NODE to check must have the JSON text type given as argument to the text constraint command. The possible types are NULL, TRUE, FALSE, STRING and NUMBER.
    Local key constraints

    Document wide uniqueness and foreign key constraints are available with the text constraint commands id and idref. Keyspaces allow for sub-tree local uniqueness and foreign key constraints.

    keyspace <names list> <constraint script> Any number of keyspaces are possible. A keyspace is either active or not. An inside a constraint script called keyspace with the same name does nothing.

    This text constraint commands work with keyspaces:

    key <name> If the keyspace with the name <name> is not active the constraint always matches. If the keyspace is active, reports error if there is already a key with the value. Otherwise it stores the value as key in this keyspace and matches. keyref <name> If the keyspace with the name <name> is not active always matches. If the keyspace is active then reports error if there is still no key as the value at the end of the keyspace <name>. Otherwise, it matches.
    Recovering

    By default the validation engine stops at the first detected validation violation and reports that finding. It does so by return false (and sets, if given, the result variable with an error message) in case the schema command itself is used to validate input. If the schema command is used by a SAX parser or the DOM parser, it does so by throwing error.

    If a reportcmd is set this command is called on global level appended with the schema command and an error type as arguments in case a validation violation is detected. Then the validation recovers from the error and continues. For some validation errors the recover strategy can be determined with the script result of the reportcmd.

    With a reportcmd (as long as the reportcmd does not throw error while called) the validation engine will never report validation failure to its caller. The validation engine recovers, continues, and reports the next error (if occurring) and so on until the end of the input. The schema command will return true and the SAX parser and DOM builder will process normally until the end of the input, as if there had not been a validation error.

    Please note that this happens only for validation errors. It is not possible to recover from well-formedness errors. If the input is not well-formed, the schema command returns false and sets (if given) the result variable with an error message about the well-formedness error.

    If the reportcmd throws error while called by the validation engine then validation stops and the schema command throws error with the error message of the script.

    While validating basically three events can happen: an element start tag has to match, a piece of text has to match or an element end tag has to match. The method info vaction called in the recovering script or any script code called from there returns, which event has triggered the error report (MATCH_ELEMENT_START, MATCH_TEXT, MATCH_ELEMENT_END, respectively). While the command walks throu the schema looking whether the event matches other, data driven events (as, for example checking, if any keyref within a keyspace exists) may happen.

    Several of the validation error codes, appended as second argument to the reportcmd calls, may happen at more than one kind of validation event. The info vaction method and its subcommands provide information about the current validation event, if called from the report command.

    If a structural validation error happens, the default recovering strategy is to ignore any following (or missing) content within the current subtree and to continue with the element end event of the subtree.

    Returning "ignore" from the recovering script in case of error type MISSING_ELEMENT recovers by ignoring the failed constraint and continues to match the event further against the schema.

    Returning "vanish" from the recover script in case of the error types MISSING_ELEMENT and UNEXPECTED_ELEMENT recovers by ignoring the event.

    Examples

    The XML Schema Part 0: Primer Second Edition (https://www.w3.org/TR/xmlschema-0/) starts with this example schema:

    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:annotation> <xsd:documentation xml:lang="en"> Purchase order schema for Example.com. Copyright 2000 Example.com. All rights reserved. </xsd:documentation> </xsd:annotation> <xsd:element name="purchaseOrder" type="PurchaseOrderType"/> <xsd:element name="comment" type="xsd:string"/> <xsd:complexType name="PurchaseOrderType"> <xsd:sequence> <xsd:element name="shipTo" type="USAddress"/> <xsd:element name="billTo" type="USAddress"/> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="items" type="Items"/> </xsd:sequence> <xsd:attribute name="orderDate" type="xsd:date"/> </xsd:complexType> <xsd:complexType name="USAddress"> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> <xsd:element name="street" type="xsd:string"/> <xsd:element name="city" type="xsd:string"/> <xsd:element name="state" type="xsd:string"/> <xsd:element name="zip" type="xsd:decimal"/> </xsd:sequence> <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/> </xsd:complexType> <xsd:complexType name="Items"> <xsd:sequence> <xsd:element name="item" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="productName" type="xsd:string"/> <xsd:element name="quantity"> <xsd:simpleType> <xsd:restriction base="xsd:positiveInteger"> <xsd:maxExclusive value="100"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="USPrice" type="xsd:decimal"/> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/> </xsd:sequence> <xsd:attribute name="partNum" type="SKU" use="required"/> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> <!-- Stock Keeping Unit, a code for identifying products --> <xsd:simpleType name="SKU"> <xsd:restriction base="xsd:string"> <xsd:pattern value="\d{3}-[A-Z]{2}"/> </xsd:restriction> </xsd:simpleType> </xsd:schema>

    A simple one-to-one translation of that into a tDOM schema definition script would be:

    tdom::schema schema schema define { # Purchase order schema for Example.com. # Copyright 2000 Example.com. All rights reserved. defelement purchaseOrder {ref PurchaseOrderType} foreach elm {comment name street city state product} { defelement $elm text } defpattern PurchaseOrderType { element shipTo ! {ref USAddress} element billTo ! {ref USAddress} element comment ? element items attribute orderDate date } defpattern USAddress { element name element street element city element state element zip ! {text number} attribute country {fixed "US"} } defelement items { element item * { element product element quantity ! {text positiveInteger} element USPrice ! {text number} element comment element shipDate ? {text date} attribute partNum {regexp "^\d{3}-[A-Z]{2}$"} } } }

    The RELAX NG Tutorial (http://relaxng.org/tutorial-20011203.html) starts with this example:

    Consider a simple XML representation of an email address book: <addressBook> <card> <name>John Smith</name> <email>js@example.com</email> </card> <card> <name>Fred Bloggs</name> <email>fb@example.net</email> </card> </addressBook> The DTD would be as follows: <!DOCTYPE addressBook [ <!ELEMENT addressBook (card*)> <!ELEMENT card (name, email)> <!ELEMENT name (#PCDATA)> <!ELEMENT email (#PCDATA)> ]> A RELAX NG pattern for this could be written as follows: <element name="addressBook" xmlns="http://relaxng.org/ns/structure/1.0"> <zeroOrMore> <element name="card"> <element name="name"> <text/> </element> <element name="email"> <text/> </element> </element> </zeroOrMore> </element>

    This schema definition script will do the same:

    tdom::schema schema schema define { defelement addressBook { element card * } defelement card { element name element email } foreach e {name email} { defelement $e text } }
    Validation Postvalidation DOM SAX
    tdom-0.9.5-src/doc/domDoc.n0000644000175000017500000007275314703531020014105 0ustar rolfrolf'\" '\" Generated from domDoc.xml '\" '\" BEGIN man.macros .if t .wh -1.3i ^B .nr ^l \n(.l .ad b .de AP .ie !"\\$4"" .TP \\$4 .el \{\ . ie !"\\$2"" .TP \\n()Cu . el .TP 15 .\} .ta \\n()Au \\n()Bu .ie !"\\$3"" \{\ \&\\$1 \\fI\\$2\\fP (\\$3) .\".b .\} .el \{\ .br .ie !"\\$2"" \{\ \&\\$1 \\fI\\$2\\fP .\} .el \{\ \&\\fI\\$1\\fP .\} .\} .. .de AS .nr )A 10n .if !"\\$1"" .nr )A \\w'\\$1'u+3n .nr )B \\n()Au+15n .\" .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n .nr )C \\n()Bu+\\w'(in/out)'u+2n .. .AS Tcl_Interp Tcl_CreateInterp in/out .de BS .br .mk ^y .nr ^b 1u .if n .nf .if n .ti 0 .if n \l'\\n(.lu\(ul' .if n .fi .. .de BE .nf .ti 0 .mk ^t .ie n \l'\\n(^lu\(ul' .el \{\ .\" Draw four-sided box normally, but don't draw top of .\" box if the box started on an earlier page. .ie !\\n(^b-1 \{\ \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .el \}\ \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .\} .fi .br .nr ^b 0 .. .de VS .if !"\\$2"" .br .mk ^Y .ie n 'mc \s12\(br\s0 .el .nr ^v 1u .. .de VE .ie n 'mc .el \{\ .ev 2 .nf .ti 0 .mk ^t \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' .sp -1 .fi .ev .\} .nr ^v 0 .. .de ^B .ev 2 'ti 0 'nf .mk ^t .if \\n(^b \{\ .\" Draw three-sided box if this is the box's first page, .\" draw two sides but no top otherwise. .ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .\} .if \\n(^v \{\ .nr ^x \\n(^tu+1v-\\n(^Yu \kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c .\} .bp 'fi .ev .if \\n(^b \{\ .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. .de DS .RS .nf .sp .. .de DE .fi .RE .sp .. .de SO .SH "STANDARD OPTIONS" .LP .nf .ta 5.5c 11c .ft B .. .de SE .fi .ft R .LP See the \\fBoptions\\fR manual entry for details on the standard options. .. .de OP .LP .nf .ta 4c Command-Line Name: \\fB\\$1\\fR Database Name: \\fB\\$2\\fR Database Class: \\fB\\$3\\fR .fi .IP .. .de CS .RS .nf .ta .25i .5i .75i 1i .if t .ft C .. .de CE .fi .if t .ft R .RE .. .de UL \\$1\l'|0\(ul'\\$2 .. '\" END man.macros .TH domDoc n "" Tcl "" .BS .SH NAME domDoc \- Manipulates an instance of a DOM document object .SH SYNOPSIS .nf domDocObjCmd \fImethod\fR ?\fIarg arg ...\fR? .fi .BE .SH "DESCRIPTION " .PP This command manipulates one particular instance of a document object. \fImethod\fR indicates a specific method of the document class. These methods should closely conform to the W3C recommendation "Document Object Model (Core) Level 1" (http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html). Look at these documents for a deeper understanding of the functionality. .PP The valid methods are: .TP \&\fB\fBdocumentElement\fP ?\fIobjVar\fB? \&\fRReturns the top most element in the document (the root element). .TP \&\fB\fBgetElementsByTagName\fP \fIname\fB \&\fRReturns a list of all elements in the document matching (glob style) \fIname\fR. .TP \&\fB\fBgetElementsByTagNameNS\fP \fIuri\fB \fIlocalname\fB \&\fR Returns a list of all elements in the subtree matching (glob style) \fIlocalname\fR and having the given namespace \&\fIuri\fR. .TP \&\fB\fBcreateElement\fP \fItagName\fB ?\fIobjVar\fB? \&\fRCreates (allocates) a new element node with node name \&\fItagName\fR, append it to the hidden fragment list in the document object and returns the node object. If \fIobjVar\fR is given the new node object is stored in this variable. .TP \&\fB\fBcreateElementNS\fP \fIurl\fB \fItagName\fB ?\fIobjVar\fB? \&\fRCreates (allocates) a new element node within a namespace having \fIuri\fR as the URI and node name \fItagName\fR, which could include the namespace prefix, append it to the hidden fragment list in the document object and returns the node object. If \fIobjVar\fR is given the new node object is stored in this variable. .TP \&\fB\fBcreateTextNode\fP \fItext\fB ?\fIobjVar\fB? \&\fRCreates (allocates) a new text node with node value \&\fItext\fR, appends it to the hidden fragment list in the document object and returns the node object. If \fIobjVar\fR is given, the new node object is stored in this variable. .TP \&\fB\fBcreateComment\fP \fItext\fB ?\fIobjVar\fB? \&\fRCreates (allocates) a new comment node with value \&\fItext\fR, appends it to the hidden fragment list in the document object and returns the node object. If \fIobjVar\fR is given, the new comment node object is stored in this variable. .TP \&\fB\fBcreateCDATASection\fP \fIdata\fB ?\fIobjVar\fB? \&\fRCreates (allocates) a new CDATA node with node value \&\fIdata\fR, appends it to the hidden fragment list in the document object and returns the node object. If \fIobjVar\fR is given, the new node object is stored in this variable. .TP \&\fB\fBcreateProcessingInstruction\fP \fItarget\fB \fIdata\fB ?\fIobjVar\fB? \&\fRCreates a process instruction, appends it to the hidden fragment list in the document object and returns the node object. If \&\fIobjVar\fR is given, the new node object is stored in this variable. .TP \&\fB\fBdelete\fP \&\fRExplicitly deletes the document, including the associated Tcl object commands (for nodes, fragment/new nodes, the document object itself) and the underlying DOM tree. .TP \&\fB\fBgetDefaultOutputMethod\fP \&\fRReturns the default output method of the document. This is usually a result of a XSLT transformation. .TP \&\fB\fBasXML\fP \fB?-indent none/tabs/1..8?\fP \fB?-channel channelId?\fP \fB?-escapeNonASCII?\fP \fB?-doctypeDeclaration ?\fP \fB-xmlDeclaration ?\fP \fB-encString \fP \fB?-escapeAllQuot?\fP \fB?-indentAttrs?\fP \fB?-nogtescape?\fP \fB?-noEmptyElementTag?\fP \fB?-escapeCR?\fP \fB?-escapeTab?\fP \&\fR .RS .PP Returns the DOM tree as an (optional indented) XML string or sends the output directly to the given channelId. .PP The -indent option requires "no", "none", "tabs" or a natural number betwenn 0 and 8, both included, as value. With the values "no" or "none" no additional white space outside of markup will be added to the serialization. I. Otherwise, it's a "pretty-print" serialization, due to inserting white space between end and the next start tag according to the nesting level. The level indentation wide is given with the number. If the value is "tabs", then indentation is done with tabs, one tab per level. .PP If the option \fI-escapeNonASCII\fR is given, every non 7 bit ASCII character in attribute values or element PCDATA content will be escaped as character reference in decimal representation. .PP The flag \fI-doctypeDeclaration\fR determines whether there will be a DOCTYPE declaration emitted before the first node of the document. The default is not to emit it. The DOCTYPE name will always be the element name of the document element. An external entity declaration of the external subset is only emitted if the document has a system identifier. .PP The flag \fI-xmlDeclaration\fR determines whether there will be an XML Declaration and a newline emitted before anything else. The default is not to emit one. If this flag is given with a true argument then .PP \&\fI-encString\fR sets the encoding value in the XML Declaration. Otherwise this option is ignored. Please note that this option just enhances the string representation of the generated XML Declaration with an encoding information string, nothing more. It's up to the user to handle encoding in case of writing to a channel or reparsing. .PP If the option \fI-escapeAllQuot\fR is given, quotation marks will be escaped with " even in text content of elements. .PP If the option \fI-indentAttrs\fR is given, then attributes will each be separated with newlines and indented to the same level as the parent node plus the value given as argument to \fI-indentAttrs\fR (0..8). .PP If the option \fI-nogtescape\fR is given then the character '>' won't get escaped in attribute values and text content of elements. The default is to escape this character. .PP If the option \fI-noEmptyElementTag\fR is given then no empty tag syntax will be used. Instead, if an element has empty content it will be serialized with an element start tag and an immediately following element end tag. .PP If the option \fI-escapeCR\fR is given then the character \&'\er' will be escaped as character reference in attribute values and text content of elements. The default is to not do this. .PP If the option \fI-escapeTab\fR is given then the character \&'\et' will be escaped as character reference in attribute values and text content of elements. The default is to not do this. .RE .TP \&\fB\fBasCanonicalXML\fP \fB?-channel channelId?\fP \fB?-comments ?\fP \&\fR .RS .PP Returns the DOM tree as canonical XML string according to the "Canonical XML Version 1.0 W3C Recommendation 15 March 2001" or sends the output directly to the given channelId. .PP If the goal is to get a canonical XML serialization of the XML file from which the DOM tree was parsed there are a few prerequisites. The XML data must be parsed with the \&\fI-keepEmpties\fR option. If the XML data includes a DTD which defines attribute defaults or external parsed entity references it is necessary to use the expat parser (not the \&\fI-simple\fR one). For any supported Tcl version lesser then 9.0 if the XML data includes characters outside the BMP a Tcl build with TCL_UTF_MAX defined to 6 (and a tDOM build with this Tcl) is necessary. .PP If the -channel option is given then the output is send directly to the Tcl channel given as argument. It is the up to the caller to ensure that the channel is correctly fconfigured. If this option is not given then the command returns the serialization as string. .PP If the option \fI-comments\fR is given with a true value then the serialization includes comments according to the rules of the recommendation. If the value is false or this option is omitted then comments are removed from the serialization. .RE .TP \&\fB\fBasHTML\fP \fB?-channel channelId?\fP \fB?-escapeNonASCII?\fP \fB?-htmlEntities?\fP \fB?-doctypeDeclaration ?\fP \fB?-breakLines?\fP \fB?-onlyContents?\fP \&\fR .RS .PP Returns the DOM tree serialized according to HTML rules (HTML elements are recognized regardless of case, without end tags for empty HTML elements etc.) as string or sends the output directly to the given channelId. .PP If the option \fI-escapeNonASCII\fR is given, every non 7 bit ASCII character in attribute values or element PCDATA content will be escaped as character reference in decimal representation. .PP If the option \fI-htmlEntities\fR is given, a character or a pair of characters is written using its HTML 5 character entity reference, if it has one. Some HTML 5 character entity references encode the same character or code points. From the possible entity names the shortest is choosen. If there are more than one shortest name and this names differ only in case then the lowercase alternative is choosen. Otherwise frist name in lexical ASCII order is choosen. There is one HTML5 entitiy (ThickSpace), which escapes two characters for which the first and the second character have an entity name by itself. If the two characters are to be serialized then the one two-characters entity ThickSpace will be choosen. .PP If the option \fI-breakLines\fR is given the serialization outputs "\en>" instead of ">" for the opening tags of elements. .PP If the option \fI-onlyContents\fR is given only all child nodes are serialized. This option is ignored by document nodes. .PP If the flag \fI-doctypeDeclaration\fR is given there will be a DOCTYPE declaration emitted before the first node of the document. The default is, to do not. The DOCTYPE name will always be the element name of the document element without case normalization. An external entity declaration of the external subset is only emitted, if the document has a system identifier. The doctype declaration will be written from the available information, without check, if this is a known (w3c) HTML version information or if the document confirms to the given HTML version. All nodes types other than document nodes ignore this option. .RE .TP \&\fB\fBasText\fP \&\fRThe asText method returns the tree by serializing the string-value of every text node in document order without any escaping. In effect, this is what the xslt output method "text" (XSLT 1.0 recommendation, section 16.3) does. .TP \&\fB\fBasJSON\fP \fB?-indent none/0..8?\fP \fB?-channel channelId?\fP \&\fR .RS .PP The asJSON method serializes the tree into a valid JSON data string. In general, this may be a lossy serialization. For this serialization all comment, character data sections and processing instruction nodes, all attributes and all XML namespaces are ignored. Only element and text nodes may be reflected in the generated JSON serialization. Appropriate JSON data type information of a node will be respected. .PP If an element node has the JSON type OBJECT, then every element node child of this element will be serialized as member of that object, with the node name of the child as the member name and the relevant children of that child as the value. Every other child nodes will be ignored. .PP If an element node has the JSON type ARRAY, then the text and element node children of that element node are serialized as the consecutive values of the array. Element node children of an ARRAY element will be container nodes for nested ARRAY or OBJECT values. .PP Text nodes with the JSON types TRUE, FALSE or NULL will be serialized to the corresponding JSON token without looking at the value of the text node. A text node without JSON type will always be serialized as a JSON string token. A text node with JSON type NUMBER will be serialized as JSON number token if the text node value is in fact a valid JSON number and as a JSON string if not. .PP If an element node doesn't has a JSON type then the serialization of its children is determined by the following rules: .PP Only text and element node child are relevant. If the element node to serialize is the member of a JSON object and there is no relevant child node the value of that member will be an empty JSON string. If the only relevant child node of this element node is a text node then the JSON value of that text node will be the value of the object member. If the element has more than one relevant child nodes and the first one is a text node then the relevant children will be serialized as JSON array. If the only relevant child node is an element node or the first relevant child is an element node and the node name of that only or first relevant child isn't equal to the array container node name all element node children will be serialized as the members of a JSON object (while ignoring any intermixed text nodes). If the only or first relevant child is an element node and the node name of this child is equal to the array container element name then all relevant children will be serialized as the values of a JSON array. .PP If the element to serialize is a value of a JSON array and the node name of this element isn't equal to the array container node name that element will be seen as a container node for a JSON object and all element node children will be serialized as the members of that array while ignoring any text node children. If the element to serialize is a value of a JSON array and the node name of this element is equal to the array container node name, all relevant children will be serialized as JSON array. .PP If the \fI-channel\fR option is given the serialization isn't returned as string but send directly to the channel, given as argument to the option. .PP If the \fI-indent\fR option is given and the argument given to this option isn't "none" then the returned JSON string is "pretty-printed". The numeric argument to this option defines the number of spaces for any indentation level. The default is to not emit any additional white space. .RE .TP \&\fB\fBasTclValue\fP \fB?typevariable?\fP \&\fR .RS .PP In case the DOM tree includes JSON type information this method returns the JSON data as nested Tcl data structure. .PP The returned value may be a Tcl dict, a Tcl list or a string. If the optional argument \fItypevariable\fR is given then the variable with that name is set to the value \&\fIdict\fR, \fIlist\fR or \fIstring\fR respectively to signal the type of the result. .PP A JSON object is returned as Tcl dict, a JSON array is returned as list and JSON strings and numbers as well as the symbolic JSON values null, true and false are returned as string (with the strings null, true and false for the respectively JSON symbol). The value of a member of a JSON object may be also a Tcl dict, or a Tcl list or a string and the elements of a JSON array list may be a Tcl dict or a Tcl list or a string. .RE .TP \&\fB\fBasTypedList\fP \&\fR .RS .PP In case the DOM tree includes JSON type information this method returns the JSON data as a nested Tcl list. .PP The first element of every of this lists describes the type of the value. The types are: OBJECT, ARRAY, STRING, NUMBER, TRUE, FALSE or NULL. .PP If the type is NUMBER or STRING, then the second (and last) element is the value. If the type is NULL, TRUE or FALSE the list does not have any other elements. .PP If the type is OBJECT the second value will be a Tcl list of property name and value pairs, which means the second element could be used as dict. The value will be a Tcl list build by the rules of the \fIasTypedList\fR method. .PP If the type is ARRAY the second value will be a Tcl list of the JSON array values, each one build by the rules of the \&\fIasTypedList\fR method. .RE .TP \&\fB\fBpublicId\fP \fI?publicId?\fB \&\fRReturns the public identifier of the doctype declaration of the document, if there is one, otherwise the empty string. If there is a value given to the method, the public identifier of the document is set to this value. .TP \&\fB\fBsystemId\fP \fI?systemId?\fB \&\fRReturns the system identifier of the doctype declaration of the document, if there is one, otherwise the empty string. If there is a value given to the method, the system identifier of the document is set to this value. .TP \&\fB\fBinternalSubset\fP \fI?internalSubset?\fB \&\fRReturns the internal subset of the doctype declaration of the document, if there is one, otherwise the empty string. If there is a value given to the method, the internal subset of the document is set to this value. Note that none of the parsing methods preserve the internal subset of a document; a freshly parsed document will always have an empty internal subset. Also note that the method doesn't do any syntactical check on a given internal subset. .TP \&\fB\fBcdataSectionElements\fP \fI(?URI:?localname|*) ??\fB \&\fRThis method allows one to control for which element nodes the text node children will be serialized as CDATA sections (this affects only serialization with the asXML method, no text node is altered in any way by this method). IF the method is called with an element name as first argument and a boolean with value true as second argument, every text node child of every element node in the document with the same name as the first argument will be serialized as CDATA section. If the second argument is a boolean with value false, all text nodes of all elements with the same name as the first argument will be serialized as usual. Namespaced element names have to be given in the form namespace_URI:localname, not in the otherwise usual prefix:localname form. With two arguments called, the method returns the used boolean value. If the method is called with only an element name, it will return a boolean value, indicating that the text node children of all elements with that name in the document will be serialized as CDATA section elements (return value 1) or not (return value 0). If the method is called with only one argument and that argument is an asterisk ('*'), then the method returns an unordered list of all element names of the document, for which the text node children will be serialized as CDATA section nodes. .TP \&\fB\fBselectNodesNamespaces\fP \fB?prefixUriList?\fP \&\fRThis method gives control to a document global prefix to namespace URI mapping, which will be used for selectNodes method calls (on document as well as on all nodes, which belongs to the document) if it is not overwritten by using the -namespaces option of the selectNodes method. Any namespace prefix within an xpath expression will be first resolved against this list. If the list binds the same prefix to different namespaces, then the first binding will win. If a prefix could not resolved against the document global prefix / namespaces list, then the namespace definitions in scope of the context node will be used to resolve the prefix, as usual. If the optional argument \fIprefixUriList\fR is given, then the global prefix / namespace list is set to this list and returns it. Without the optional argument the method returns the current list. The default is the empty list. .TP \&\fB\fBxslt\fP \fB?-parameters parameterList?\fP \fB?-ignoreUndeclaredParameters?\fP \fB?-maxApplyDepth int?\fP \fB?-xsltmessagecmd script?\fP \fIstylesheet\fB \fI?outputVar?\fB \&\fRApplies an XSLT transformation on the whole document of the node object using the XSLT \fIstylesheet\fR (given as domDoc). Returns a document object containing the result document of the transformation and stores that document object in the optional \fIoutputVar\fR, if that was given. .RS .PP The optional \fI-parameters\fR option sets top level to string values. The \fIparameterList\fR has to be a tcl list consisting of parameter name and value pairs. .PP If the option \fI-ignoreUndeclaredParameters\fR is given, then parameter names in the \fIparameterList\fR given to the \fI-parameters\fR options that are not declared as top-level parameters in the stylesheet are silently ignored. Without this option, an error is raised if the user tries to set a top-level parameter that is not declared in the stylesheet. .PP The option \fI-maxApplyDepth\fR expects a positiv integer as argument. By default, the XSLT engine allows XSLT templates to nest up to 3000 levels (and raises error if they nest deeper). This limit can be set by the \fI-maxApplyDepth\fR option. .PP The \fI-xsltmessagecmd\fR option sets a callback for xslt:message elements in the stylesheet. The actual command consists of the script, given as argument to the option, appended with the XML Fragment from instantiating the xsl:message element content as string (as if the XPath string() function would have been applied to the XML Fragment) and a flag, which indicates, if the xsl:message has an attribute "terminate" with the value "yes". If the called script returns anything else then TCL_OK then the XSLT transformation will be aborted, returning error. If the called script returns -code break, the error message is empty, otherwise the result code is reported. In case of terminated transformation, the outputVar, if given, is set to the empty string. .RE .TP \&\fB\fBtoXSLTcmd\fP ?\fIobjVar\fB? \&\fRIf the DOM tree represents a valid XSLT stylesheet, this method transforms the DOM tree into an XSLT command, otherwise it returns error. The created xsltCmd is returned and stored in the \fIobjVar\fR, if a var name was given. A successful transformation of the DOM tree to an xsltCmd removes the domDoc cmd and all nodeCmds of the document. .RS .PP The syntax of the created xsltCmd is: .CS \&\fBxsltCmd\fP \fBmethod\fP \fB?arg ...?\fP .CE .PP The valid methods are: .TP \&\fB\fBtransform\fP \fB?-parameters parameterList?\fP \fB?-ignoreUndeclaredParameters?\fP \fB?-maxApplyDepth int?\fP \fB?-xsltmessagecmd script?\fP \fIdomDoc\fB \fI?outputVar?\fB \&\fRApplies XSLT transformation on the document \&\fIdomDoc\fR. Returns a document object containing the result document of that transformation and stores it in the optional \&\fIoutputVar\fR. .RS .PP The optional \fI-parameters\fR option sets top level to string values. The \fIparameterList\fR has to be a tcl list consisting of parameter name and value pairs. .PP If the option \fI-ignoreUndeclaredParameters\fR is given, then parameter names in the \fIparameterList\fR given to the \fI-parameters\fR options that are not declared as top-level parameters in the stylesheet are silently ignored. Without this option, an error is raised if the user tries to set a top-level parameter, which is not declared in the stylesheet. .PP The option \fI-maxApplyDepth\fR expects a positiv integer as argument. By default, the XSLT engine allows XSLT templates to nest up to 3000 levels (and raises error if they nest deeper). This limit can be set by the \fI-maxApplyDepth\fR option. .PP The \fI-xsltmessagecmd\fR option sets a callback for xslt:message elements in the stylesheet. The actual command consists of the script, given as argument to the option, appended with the XML Fragment from instantiating the xsl:message element content as string (as if the XPath string() function would have been applied to the XML Fragment) and a flag, which indicates, if the xsl:message has an attribute "terminate" with the value "yes". .RE .TP \&\fB\fBdelete\fP \&\fRDeletes the xsltCmd and cleans up all used recourses .PP If the first argument to an xsltCmd is a domDoc or starts with a "-", then the command is processed in the same way as \&\fI transform\fR. .RE .TP \&\fB\fBnormalize\fP \fI?-forXPath?\fB \&\fRPuts all text nodes in the document into a "normal" form where only structure (e.g., elements, comments, processing instructions and CDATA sections) separates text nodes, i.e., there are neither adjacent text nodes nor empty text nodes. If the option \&\fI-forXPath\fR is given, all CDATA sections in the nodes are converted to text nodes, as a first step before the normalization. .TP \&\fB\fBnodeType\fP \&\fRReturns the node type of the document node. This is always DOCUMENT_NODE. .TP \&\fB\fBgetElementById\fP \fIid\fB \&\fRReturns the node having a id attribute with value \&\fIid\fR or the empty string, if no node has an id attribute with that value. .TP \&\fB\fBfirstChild\fP \fB?objVar?\fP \&\fRReturns the first top level node of the document. .TP \&\fB\fBlastChild\fP \fB?objVar?\fP \&\fRReturns the last top level node of the document. .TP \&\fB\fBappendChild\fP \fInewChild\fB \&\fRAppend \fInewChild\fR to the end of the list of top level nodes of the document. .TP \&\fB\fBremoveChild\fP \fIchild\fB \&\fRRemoves \fIchild\fR from the list of top level nodes of the document. \fIchild\fR will be part of the document fragment list after this operation. It is not physically deleted. .TP \&\fB\fBhasChildNodes\fP \&\fRReturns 1 if the document has any nodes in the tree. Otherwise 0 is returned. .TP \&\fB\fBchildNodes\fP \&\fRReturns a list of the top level nodes of the document. .TP \&\fB\fBownerDocument\fP \fB?domObjVar?\fP \&\fRReturns the document itself. .TP \&\fB\fBinsertBefore\fP \fInewChild\fB \fIrefChild\fB \&\fRInsert \fInewChild\fR before the \fIrefChild\fR into the list of top level nodes of the document. If \fIrefChild\fR is the empty string, inserts \&\fInewChild\fR at the end of the top level nodes. .TP \&\fB\fBreplaceChild\fP \fInewChild\fB \fIoldChild\fB \&\fRReplaces \fIoldChild\fR with \fInewChild\fR in the list of children of that node. The \fIoldChild\fR node will be part of the document fragment list after this operation. .TP \&\fB\fBappendFromList\fP \fIlist\fB \&\fRParses \fIlist\fR , creates an according DOM subtree and appends this subtree at the end of the current list of top level nodes of the document. .TP \&\fB\fBappendXML\fP \fIXMLstring\fB \&\fRParses \fIXMLstring\fR, creates an according DOM subtree and appends this subtree at the end of the current list of top level nodes of the document. .TP \&\fB\fBselectNodes\fP \fB?-namespaces prefixUriList?\fP \fB?-cache ?\fP \fB?-list?\fP \fIxpathQuery\fB \fB?typeVar?\fP \&\fR .RS .PP Returns the result of applying the XPath query \&\fIxpathQuery\fR to the document. The context node of the query is the root node in the sense of the XPath recommendation (not the document element). The result can be a string/value, a list of strings, a list of nodes or a list of attribute name / value pairs. If \fItypeVar\fR is given the result type name is stored into that variable (empty, bool, number, string, nodes, attrnodes or mixed). .PP See the documentation of the of the .TP \&\fBdomNode \&\fR command method \&\fBselectNodes\fP for a detailed description of the arguments. .RE .TP \&\fB\fBbaseURI\fP \fI?URI?\fB \&\fRReturns the present baseURI of the document. If the optional argument URI is given, sets the base URI of the document to the given URI. .TP \&\fB\fBappendFromScript\fP \fItclScript\fB \&\fRAppends the nodes created by the \fItclScript\fR by Tcl functions, which have been built using \fIdom createNodeCmd\fR, at the end of the current list of top level nodes of the document. .TP \&\fB\fBinsertBeforeFromScript\fP \fItclScript\fB \fIrefChild\fB \&\fRInserts the nodes created in the \fItclScript\fR by Tcl functions, which have been built using \fIdom createNodeCmd\fR, before the \fIrefChild\fR into to the list of top level nodes of the document. If \fIrefChild\fR is the empty string, the new nodes will be appended. .TP \&\fB\fBdeleteXPathCache\fP \fI?xpathQuery?\fB \&\fRIf called without the optional argument, all cached XPath expressions of the document are freed. If called with the optional argument \fIxpathQuery\fR, this single XPath query will be removed from the cache, if it is there. The method always returns an empty string. .PP Otherwise, if an unknown method name is given, the command with the same name as the given method within the namespace \fB::dom::domDoc\fR is tried to be executed. This allows quick method additions on Tcl level. .PP Newly created nodes are appended to a hidden fragment list. If they are not moved into the tree they are automatically deleted as soon as the whole document gets deleted. .SH "SEE ALSO" dom, domNode .SH KEYWORDS DOM node creation, document element tdom-0.9.5-src/doc/expatapi.xml0000644000175000017500000002320214703531020015037 0ustar rolfrolf CheckExpatParserObj, CHandlerSetInstall, CHandlerSetRemove, CHandlerSetCreate, CHandlerSetGetUserData, GetExpatInfo Functions to create, install and remove expat parser object extensions. #include <tclexpat.h> int CheckExpatParserObj (interp, nameObj) int CHandlerSetInstall (interp, expatObj, handlerSet) int CHandlerSetRemove (interp, expatObj, handlerSetName) CHandlerSet* CHandlerSetCreate (handlerSetName) CHandlerSet* CHandlerSetGet (interp, expatObj, handlerSetName) void* CHandlerSetGetUserData (interp, expatObj, handlerSetName) TclGenExpatInfo* GetExpatInfo (interp, expatObj)
    ARGUMENTS Tcl_Interp *interp in Interpreter with the expat parser object. Tcl_Obj *expatObj in A Tcl Object containing the command name of the expat parser object to be queried or modified. char *handlerSetName in Identifier of the handler set. CHandlerSet *handlerSet in Pointer to a C handler set. Tcl_Obj *nameObj A Tcl Object containing the name of a expat parser object
    DESCRIPTION

    The functions described in this manual allows one to add C level coded event handler to an tDOM Tcl expat parser objects. A tDOM Tcl expat parser object is able to have several Tcl scripts and C functions associated with a specific event. If the event occurs, first the Tcl scripts then the C functions associated with the event are called in turn.

    A tDOM Tcl expat parser extension is an ordinary Tcl extension and loaded like every other Tcl extension. It must install at least one new Tcl Level command, that manipulates a tDOM Tcl expat parser object.

    A C level handler set is a data structure like this:

    typedef struct CHandlerSet { struct CHandlerSet *nextHandlerSet; char *name; /* refname of the handler set */ int ignoreWhiteCDATAs; /* ignore 'white' CDATA sections */ void *userData; /* Handler set specific Data Structure; the C handler set extension has to malloc the needed structure in his init func and has to provide a cleanup func (to free it). */ CHandlerSet_userDataReset resetProc; CHandlerSet_userDataFree freeProc; /* C func for element start */ XML_StartElementHandler elementstartcommand; /* C func for element end */ XML_EndElementHandler elementendcommand; /* C func for character data */ XML_CharacterDataHandler datacommand; /* C func for namespace decl start */ XML_StartNamespaceDeclHandler startnsdeclcommand; /* C func for namespace decl end */ XML_EndNamespaceDeclHandler endnsdeclcommand; /* C func for processing instruction */ XML_ProcessingInstructionHandler picommand; /* C func for default data */ XML_DefaultHandler defaultcommand; /* C func for unparsed entity declaration */ XML_NotationDeclHandler notationcommand; /* C func for external entity */ XML_ExternalEntityRefHandler externalentitycommand; /* C func for unknown encoding */ XML_UnknownEncodingHandler unknownencodingcommand; /* C func for comments */ XML_CommentHandler commentCommand; /* C func for "not standalone" docs */ XML_NotStandaloneHandler notStandaloneCommand; /* C func for CDATA section start */ XML_StartCdataSectionHandler startCdataSectionCommand; /* C func for CDATA section end */ XML_EndCdataSectionHandler endCdataSectionCommand; /* C func for !ELEMENT decl's */ XML_ElementDeclHandler elementDeclCommand; /* C func for !ATTLIST decl's */ XML_AttlistDeclHandler attlistDeclCommand; /* C func for !DOCTYPE decl's */ XML_StartDoctypeDeclHandler startDoctypeDeclCommand; /* C func for !DOCTYPE decl ends */ XML_EndDoctypeDeclHandler endDoctypeDeclCommand; /* C func for !ENTITY decls's */ XML_EntityDeclHandler entityDeclCommand; } CHandlerSet;

    The types and the arguments of the event functions (XML_*) are exactly the same like the expat lib handler functions and described in detail in expat.h, see there. The extension has only to provided the handler functions needed; it's perfectly OK to leave unused handler slots as the are (they are initialized to NULL by CHandlerSetCreate).

    The name of this structure is used to identify the handler set.

    If the flag ignoreWhiteCDATAs is set, element content which contain only whitespace isn't reported with the datacommand.

    The userData element points to the handler set specific data. The event handler functions are called with this pointer as userData argument.

    resetProc and freeProc must have arguments that match the type

    void (Tcl_Interp *interp, void *userData)

    resetProc is called in case the parser is reset with <parserObj> reset and should do any necessary cleanup and reinitializing to prepare the C handler set for a new XML document. The freeProc is called, if the parser is deleted and should do memory cleanup etc.

    CHandlerSetCreate create a C handler set, gives it the name name and initializes any other element with NULL.

    CHandlerSetInstall adds the handlerSet to the parser expatObj. The parser has to be a tDOM Tcl expat parser object in the interpreter interp. The name of the C handler set has to be unique for the parser. Returns 0 in case of success. Returns 1 if expatObj isn't a parser object in the interpreter interp. Returns 2 if this parser has already a C handler set with the handlerSet name.

    CHandlerSetRemove removes the C handler set referenced by the handlerSetName from the parser expatObj. The parser has to be a tDOM Tcl expat parser object in the interpreter interp. CHandlerSetRemove calls the freeProc function of the C handler set structure, removes the handler set from the C handler set list and frees the handler structure. Returns 0 in case of success. Returns 1 if expatObj isn't a parser object in the interpreter interp. Returns 2 if this parser hasn't a C handler set named handlerSetName.

    CheckExpatParserObj returns 1, if nameObj is a tDOM Tcl expat parser object in the interpreter interp, otherwise it returns 0. Example:

    int TclExampleObjCmd(dummy, interp, objc, objv) ClientData dummy; Tcl_Interp *interp; int objc; Tcl_Obj *const objv[]; { char *method; CHandlerSet *handlerSet; int methodIndex, result; simpleCounter *counter; static char *exampleMethods[] = { "enable", "getresult", "remove", NULL }; enum exampleMethod { m_enable, m_getresult, m_remove }; if (objc != 3) { Tcl_WrongNumArgs (interp, 1, objv, example_usage); return TCL_ERROR; } if (!CheckExpatParserObj (interp, objv[1])) { Tcl_SetResult (interp, "First argument has to be a expat parser object", NULL); return TCL_ERROR; } /* ... */

    CHandlerSetGet returns a pointer to the C handler Set referenced by the name handlerSetName of the parser object expatObj. expatObj has to be an expat parser object in the interpreter interp. Returns NULL in case of error.

    CHandlerSetGetUserData returns a pointer to the userData of the C handler set referenced by the name handlerSetName of the parser object expatObj. expatObj has to be an expat parser object in the interpreter interp. Returns NULL in case of error.

    GetExpatInfo Is a helper function that returns a pointer to the TclGenExpatInfo structure of the tDOM Tcl expat parser object expatObj. The expatObj has to be a tDOM Tcl expat parser object in the interpreter interp. This is most useful, to set the application status of the parser object.

    See the simple but full functionally example in the extensions/example dir or the more complex example tnc in the extensions/tnc dir (a simple DTD validation extension).

    expat C handler set
    tdom-0.9.5-src/doc/domDoc.xml0000644000175000017500000010546614703531020014446 0ustar rolfrolf domDoc Manipulates an instance of a DOM document object domDocObjCmd method ?arg arg ...?
    DESCRIPTION

    This command manipulates one particular instance of a document object. method indicates a specific method of the document class. These methods should closely conform to the W3C recommendation "Document Object Model (Core) Level 1" (http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html). Look at these documents for a deeper understanding of the functionality.

    The valid methods are:

    documentElement ?objVar? Returns the top most element in the document (the root element). getElementsByTagName name Returns a list of all elements in the document matching (glob style) name. getElementsByTagNameNS uri localname Returns a list of all elements in the subtree matching (glob style) localname and having the given namespace uri. createElement tagName ?objVar? Creates (allocates) a new element node with node name tagName, append it to the hidden fragment list in the document object and returns the node object. If objVar is given the new node object is stored in this variable. createElementNS url tagName ?objVar? Creates (allocates) a new element node within a namespace having uri as the URI and node name tagName, which could include the namespace prefix, append it to the hidden fragment list in the document object and returns the node object. If objVar is given the new node object is stored in this variable. createTextNode text ?objVar? Creates (allocates) a new text node with node value text, appends it to the hidden fragment list in the document object and returns the node object. If objVar is given, the new node object is stored in this variable. createComment text ?objVar? Creates (allocates) a new comment node with value text, appends it to the hidden fragment list in the document object and returns the node object. If objVar is given, the new comment node object is stored in this variable. createCDATASection data ?objVar? Creates (allocates) a new CDATA node with node value data, appends it to the hidden fragment list in the document object and returns the node object. If objVar is given, the new node object is stored in this variable. createProcessingInstruction target data ?objVar? Creates a process instruction, appends it to the hidden fragment list in the document object and returns the node object. If objVar is given, the new node object is stored in this variable. delete Explicitly deletes the document, including the associated Tcl object commands (for nodes, fragment/new nodes, the document object itself) and the underlying DOM tree. getDefaultOutputMethod Returns the default output method of the document. This is usually a result of a XSLT transformation. asXML

    Returns the DOM tree as an (optional indented) XML string or sends the output directly to the given channelId.

    The -indent option requires "no", "none", "tabs" or a natural number betwenn 0 and 8, both included, as value. With the values "no" or "none" no additional white space outside of markup will be added to the serialization. I. Otherwise, it's a "pretty-print" serialization, due to inserting white space between end and the next start tag according to the nesting level. The level indentation wide is given with the number. If the value is "tabs", then indentation is done with tabs, one tab per level.

    If the option -escapeNonASCII is given, every non 7 bit ASCII character in attribute values or element PCDATA content will be escaped as character reference in decimal representation.

    The flag -doctypeDeclaration determines whether there will be a DOCTYPE declaration emitted before the first node of the document. The default is not to emit it. The DOCTYPE name will always be the element name of the document element. An external entity declaration of the external subset is only emitted if the document has a system identifier.

    The flag -xmlDeclaration determines whether there will be an XML Declaration and a newline emitted before anything else. The default is not to emit one. If this flag is given with a true argument then

    -encString sets the encoding value in the XML Declaration. Otherwise this option is ignored. Please note that this option just enhances the string representation of the generated XML Declaration with an encoding information string, nothing more. It's up to the user to handle encoding in case of writing to a channel or reparsing.

    If the option -escapeAllQuot is given, quotation marks will be escaped with &quot; even in text content of elements.

    If the option -indentAttrs is given, then attributes will each be separated with newlines and indented to the same level as the parent node plus the value given as argument to -indentAttrs (0..8).

    If the option -nogtescape is given then the character '>' won't get escaped in attribute values and text content of elements. The default is to escape this character.

    If the option -noEmptyElementTag is given then no empty tag syntax will be used. Instead, if an element has empty content it will be serialized with an element start tag and an immediately following element end tag.

    If the option -escapeCR is given then the character '\r' will be escaped as character reference in attribute values and text content of elements. The default is to not do this.

    If the option -escapeTab is given then the character '\t' will be escaped as character reference in attribute values and text content of elements. The default is to not do this.

    asCanonicalXML

    Returns the DOM tree as canonical XML string according to the "Canonical XML Version 1.0 W3C Recommendation 15 March 2001" or sends the output directly to the given channelId.

    If the goal is to get a canonical XML serialization of the XML file from which the DOM tree was parsed there are a few prerequisites. The XML data must be parsed with the -keepEmpties option. If the XML data includes a DTD which defines attribute defaults or external parsed entity references it is necessary to use the expat parser (not the -simple one). For any supported Tcl version lesser then 9.0 if the XML data includes characters outside the BMP a Tcl build with TCL_UTF_MAX defined to 6 (and a tDOM build with this Tcl) is necessary.

    If the -channel option is given then the output is send directly to the Tcl channel given as argument. It is the up to the caller to ensure that the channel is correctly fconfigured. If this option is not given then the command returns the serialization as string.

    If the option -comments is given with a true value then the serialization includes comments according to the rules of the recommendation. If the value is false or this option is omitted then comments are removed from the serialization.

    asHTML

    Returns the DOM tree serialized according to HTML rules (HTML elements are recognized regardless of case, without end tags for empty HTML elements etc.) as string or sends the output directly to the given channelId.

    If the option -escapeNonASCII is given, every non 7 bit ASCII character in attribute values or element PCDATA content will be escaped as character reference in decimal representation.

    If the option -htmlEntities is given, a character or a pair of characters is written using its HTML 5 character entity reference, if it has one. Some HTML 5 character entity references encode the same character or code points. From the possible entity names the shortest is choosen. If there are more than one shortest name and this names differ only in case then the lowercase alternative is choosen. Otherwise frist name in lexical ASCII order is choosen. There is one HTML5 entitiy (ThickSpace), which escapes two characters for which the first and the second character have an entity name by itself. If the two characters are to be serialized then the one two-characters entity ThickSpace will be choosen.

    If the option -breakLines is given the serialization outputs "\n>" instead of ">" for the opening tags of elements.

    If the option -onlyContents is given only all child nodes are serialized. This option is ignored by document nodes.

    If the flag -doctypeDeclaration is given there will be a DOCTYPE declaration emitted before the first node of the document. The default is, to do not. The DOCTYPE name will always be the element name of the document element without case normalization. An external entity declaration of the external subset is only emitted, if the document has a system identifier. The doctype declaration will be written from the available information, without check, if this is a known (w3c) HTML version information or if the document confirms to the given HTML version. All nodes types other than document nodes ignore this option.

    asText The asText method returns the tree by serializing the string-value of every text node in document order without any escaping. In effect, this is what the xslt output method "text" (XSLT 1.0 recommendation, section 16.3) does. asJSON

    The asJSON method serializes the tree into a valid JSON data string. In general, this may be a lossy serialization. For this serialization all comment, character data sections and processing instruction nodes, all attributes and all XML namespaces are ignored. Only element and text nodes may be reflected in the generated JSON serialization. Appropriate JSON data type information of a node will be respected.

    If an element node has the JSON type OBJECT, then every element node child of this element will be serialized as member of that object, with the node name of the child as the member name and the relevant children of that child as the value. Every other child nodes will be ignored.

    If an element node has the JSON type ARRAY, then the text and element node children of that element node are serialized as the consecutive values of the array. Element node children of an ARRAY element will be container nodes for nested ARRAY or OBJECT values.

    Text nodes with the JSON types TRUE, FALSE or NULL will be serialized to the corresponding JSON token without looking at the value of the text node. A text node without JSON type will always be serialized as a JSON string token. A text node with JSON type NUMBER will be serialized as JSON number token if the text node value is in fact a valid JSON number and as a JSON string if not.

    If an element node doesn't has a JSON type then the serialization of its children is determined by the following rules:

    Only text and element node child are relevant. If the element node to serialize is the member of a JSON object and there is no relevant child node the value of that member will be an empty JSON string. If the only relevant child node of this element node is a text node then the JSON value of that text node will be the value of the object member. If the element has more than one relevant child nodes and the first one is a text node then the relevant children will be serialized as JSON array. If the only relevant child node is an element node or the first relevant child is an element node and the node name of that only or first relevant child isn't equal to the array container node name all element node children will be serialized as the members of a JSON object (while ignoring any intermixed text nodes). If the only or first relevant child is an element node and the node name of this child is equal to the array container element name then all relevant children will be serialized as the values of a JSON array.

    If the element to serialize is a value of a JSON array and the node name of this element isn't equal to the array container node name that element will be seen as a container node for a JSON object and all element node children will be serialized as the members of that array while ignoring any text node children. If the element to serialize is a value of a JSON array and the node name of this element is equal to the array container node name, all relevant children will be serialized as JSON array.

    If the -channel option is given the serialization isn't returned as string but send directly to the channel, given as argument to the option.

    If the -indent option is given and the argument given to this option isn't "none" then the returned JSON string is "pretty-printed". The numeric argument to this option defines the number of spaces for any indentation level. The default is to not emit any additional white space.

    asTclValue

    In case the DOM tree includes JSON type information this method returns the JSON data as nested Tcl data structure.

    The returned value may be a Tcl dict, a Tcl list or a string. If the optional argument typevariable is given then the variable with that name is set to the value dict, list or string respectively to signal the type of the result.

    A JSON object is returned as Tcl dict, a JSON array is returned as list and JSON strings and numbers as well as the symbolic JSON values null, true and false are returned as string (with the strings null, true and false for the respectively JSON symbol). The value of a member of a JSON object may be also a Tcl dict, or a Tcl list or a string and the elements of a JSON array list may be a Tcl dict or a Tcl list or a string.

    asTypedList

    In case the DOM tree includes JSON type information this method returns the JSON data as a nested Tcl list.

    The first element of every of this lists describes the type of the value. The types are: OBJECT, ARRAY, STRING, NUMBER, TRUE, FALSE or NULL.

    If the type is NUMBER or STRING, then the second (and last) element is the value. If the type is NULL, TRUE or FALSE the list does not have any other elements.

    If the type is OBJECT the second value will be a Tcl list of property name and value pairs, which means the second element could be used as dict. The value will be a Tcl list build by the rules of the asTypedList method.

    If the type is ARRAY the second value will be a Tcl list of the JSON array values, each one build by the rules of the asTypedList method.

    publicId ?publicId? Returns the public identifier of the doctype declaration of the document, if there is one, otherwise the empty string. If there is a value given to the method, the public identifier of the document is set to this value. systemId ?systemId? Returns the system identifier of the doctype declaration of the document, if there is one, otherwise the empty string. If there is a value given to the method, the system identifier of the document is set to this value. internalSubset ?internalSubset? Returns the internal subset of the doctype declaration of the document, if there is one, otherwise the empty string. If there is a value given to the method, the internal subset of the document is set to this value. Note that none of the parsing methods preserve the internal subset of a document; a freshly parsed document will always have an empty internal subset. Also note that the method doesn't do any syntactical check on a given internal subset. cdataSectionElements (?URI:?localname|*) ?<boolean>? This method allows one to control for which element nodes the text node children will be serialized as CDATA sections (this affects only serialization with the asXML method, no text node is altered in any way by this method). IF the method is called with an element name as first argument and a boolean with value true as second argument, every text node child of every element node in the document with the same name as the first argument will be serialized as CDATA section. If the second argument is a boolean with value false, all text nodes of all elements with the same name as the first argument will be serialized as usual. Namespaced element names have to be given in the form namespace_URI:localname, not in the otherwise usual prefix:localname form. With two arguments called, the method returns the used boolean value. If the method is called with only an element name, it will return a boolean value, indicating that the text node children of all elements with that name in the document will be serialized as CDATA section elements (return value 1) or not (return value 0). If the method is called with only one argument and that argument is an asterisk ('*'), then the method returns an unordered list of all element names of the document, for which the text node children will be serialized as CDATA section nodes. selectNodesNamespaces This method gives control to a document global prefix to namespace URI mapping, which will be used for selectNodes method calls (on document as well as on all nodes, which belongs to the document) if it is not overwritten by using the -namespaces option of the selectNodes method. Any namespace prefix within an xpath expression will be first resolved against this list. If the list binds the same prefix to different namespaces, then the first binding will win. If a prefix could not resolved against the document global prefix / namespaces list, then the namespace definitions in scope of the context node will be used to resolve the prefix, as usual. If the optional argument prefixUriList is given, then the global prefix / namespace list is set to this list and returns it. Without the optional argument the method returns the current list. The default is the empty list. xslt stylesheet ?outputVar? Applies an XSLT transformation on the whole document of the node object using the XSLT stylesheet (given as domDoc). Returns a document object containing the result document of the transformation and stores that document object in the optional outputVar, if that was given.

    The optional -parameters option sets top level <xsl:param> to string values. The parameterList has to be a tcl list consisting of parameter name and value pairs.

    If the option -ignoreUndeclaredParameters is given, then parameter names in the parameterList given to the -parameters options that are not declared as top-level parameters in the stylesheet are silently ignored. Without this option, an error is raised if the user tries to set a top-level parameter that is not declared in the stylesheet.

    The option -maxApplyDepth expects a positiv integer as argument. By default, the XSLT engine allows XSLT templates to nest up to 3000 levels (and raises error if they nest deeper). This limit can be set by the -maxApplyDepth option.

    The -xsltmessagecmd option sets a callback for xslt:message elements in the stylesheet. The actual command consists of the script, given as argument to the option, appended with the XML Fragment from instantiating the xsl:message element content as string (as if the XPath string() function would have been applied to the XML Fragment) and a flag, which indicates, if the xsl:message has an attribute "terminate" with the value "yes". If the called script returns anything else then TCL_OK then the XSLT transformation will be aborted, returning error. If the called script returns -code break, the error message is empty, otherwise the result code is reported. In case of terminated transformation, the outputVar, if given, is set to the empty string.

    toXSLTcmd ?objVar? If the DOM tree represents a valid XSLT stylesheet, this method transforms the DOM tree into an XSLT command, otherwise it returns error. The created xsltCmd is returned and stored in the objVar, if a var name was given. A successful transformation of the DOM tree to an xsltCmd removes the domDoc cmd and all nodeCmds of the document.

    The syntax of the created xsltCmd is:

    xsltCmd

    The valid methods are:

    transform domDoc ?outputVar? Applies XSLT transformation on the document domDoc. Returns a document object containing the result document of that transformation and stores it in the optional outputVar.

    The optional -parameters option sets top level <xsl:param> to string values. The parameterList has to be a tcl list consisting of parameter name and value pairs.

    If the option -ignoreUndeclaredParameters is given, then parameter names in the parameterList given to the -parameters options that are not declared as top-level parameters in the stylesheet are silently ignored. Without this option, an error is raised if the user tries to set a top-level parameter, which is not declared in the stylesheet.

    The option -maxApplyDepth expects a positiv integer as argument. By default, the XSLT engine allows XSLT templates to nest up to 3000 levels (and raises error if they nest deeper). This limit can be set by the -maxApplyDepth option.

    The -xsltmessagecmd option sets a callback for xslt:message elements in the stylesheet. The actual command consists of the script, given as argument to the option, appended with the XML Fragment from instantiating the xsl:message element content as string (as if the XPath string() function would have been applied to the XML Fragment) and a flag, which indicates, if the xsl:message has an attribute "terminate" with the value "yes".

    delete Deletes the xsltCmd and cleans up all used recourses

    If the first argument to an xsltCmd is a domDoc or starts with a "-", then the command is processed in the same way as <xsltCmd> transform.

    normalize ?-forXPath? Puts all text nodes in the document into a "normal" form where only structure (e.g., elements, comments, processing instructions and CDATA sections) separates text nodes, i.e., there are neither adjacent text nodes nor empty text nodes. If the option -forXPath is given, all CDATA sections in the nodes are converted to text nodes, as a first step before the normalization. nodeType Returns the node type of the document node. This is always DOCUMENT_NODE. getElementById id Returns the node having a id attribute with value id or the empty string, if no node has an id attribute with that value. firstChild ?objVar? Returns the first top level node of the document. lastChild ?objVar? Returns the last top level node of the document. appendChild newChild Append newChild to the end of the list of top level nodes of the document. removeChild child Removes child from the list of top level nodes of the document. child will be part of the document fragment list after this operation. It is not physically deleted. hasChildNodes Returns 1 if the document has any nodes in the tree. Otherwise 0 is returned. childNodes Returns a list of the top level nodes of the document. ownerDocument ?domObjVar? Returns the document itself. insertBefore newChild refChild Insert newChild before the refChild into the list of top level nodes of the document. If refChild is the empty string, inserts newChild at the end of the top level nodes. replaceChild newChild oldChild Replaces oldChild with newChild in the list of children of that node. The oldChild node will be part of the document fragment list after this operation. appendFromList list Parses list , creates an according DOM subtree and appends this subtree at the end of the current list of top level nodes of the document. appendXML XMLstring Parses XMLstring, creates an according DOM subtree and appends this subtree at the end of the current list of top level nodes of the document. selectNodes xpathQuery

    Returns the result of applying the XPath query xpathQuery to the document. The context node of the query is the root node in the sense of the XPath recommendation (not the document element). The result can be a string/value, a list of strings, a list of nodes or a list of attribute name / value pairs. If typeVar is given the result type name is stored into that variable (empty, bool, number, string, nodes, attrnodes or mixed).

    See the documentation of the of the domNode command method selectNodes for a detailed description of the arguments.

    baseURI ?URI? Returns the present baseURI of the document. If the optional argument URI is given, sets the base URI of the document to the given URI. appendFromScript tclScript Appends the nodes created by the tclScript by Tcl functions, which have been built using dom createNodeCmd, at the end of the current list of top level nodes of the document. insertBeforeFromScript tclScript refChild Inserts the nodes created in the tclScript by Tcl functions, which have been built using dom createNodeCmd, before the refChild into to the list of top level nodes of the document. If refChild is the empty string, the new nodes will be appended. deleteXPathCache ?xpathQuery? If called without the optional argument, all cached XPath expressions of the document are freed. If called with the optional argument xpathQuery, this single XPath query will be removed from the cache, if it is there. The method always returns an empty string.

    Otherwise, if an unknown method name is given, the command with the same name as the given method within the namespace ::dom::domDoc is tried to be executed. This allows quick method additions on Tcl level.

    Newly created nodes are appended to a hidden fragment list. If they are not moved into the tree they are automatically deleted as soon as the whole document gets deleted.

    dom domNode DOM node creation document element
    tdom-0.9.5-src/doc/domDoc.html0000644000175000017500000010733014703531020014602 0ustar rolfrolf tDOM manual: domDoc

    NAME

    domDoc -
    Manipulates an instance of a DOM document object

    SYNOPSIS

    domDocObjCmd method ?arg arg ...?

    DESCRIPTION

    This command manipulates one particular instance of a document object. method indicates a specific method of the document class. These methods should closely conform to the W3C recommendation "Document Object Model (Core) Level 1" (http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html). Look at these documents for a deeper understanding of the functionality.

    The valid methods are:

    documentElement ?objVar?
    Returns the top most element in the document (the root element).
    getElementsByTagName name
    Returns a list of all elements in the document matching (glob style) name.
    getElementsByTagNameNS uri localname
    Returns a list of all elements in the subtree matching (glob style) localname and having the given namespace uri.
    createElement tagName ?objVar?
    Creates (allocates) a new element node with node name tagName, append it to the hidden fragment list in the document object and returns the node object. If objVar is given the new node object is stored in this variable.
    createElementNS url tagName ?objVar?
    Creates (allocates) a new element node within a namespace having uri as the URI and node name tagName, which could include the namespace prefix, append it to the hidden fragment list in the document object and returns the node object. If objVar is given the new node object is stored in this variable.
    createTextNode text ?objVar?
    Creates (allocates) a new text node with node value text, appends it to the hidden fragment list in the document object and returns the node object. If objVar is given, the new node object is stored in this variable.
    createComment text ?objVar?
    Creates (allocates) a new comment node with value text, appends it to the hidden fragment list in the document object and returns the node object. If objVar is given, the new comment node object is stored in this variable.
    createCDATASection data ?objVar?
    Creates (allocates) a new CDATA node with node value data, appends it to the hidden fragment list in the document object and returns the node object. If objVar is given, the new node object is stored in this variable.
    createProcessingInstruction target data ?objVar?
    Creates a process instruction, appends it to the hidden fragment list in the document object and returns the node object. If objVar is given, the new node object is stored in this variable.
    delete
    Explicitly deletes the document, including the associated Tcl object commands (for nodes, fragment/new nodes, the document object itself) and the underlying DOM tree.
    getDefaultOutputMethod
    Returns the default output method of the document. This is usually a result of a XSLT transformation.
    asXML ?-indent none/tabs/1..8? ?-channel channelId? ?-escapeNonASCII? ?-doctypeDeclaration <boolean>? -xmlDeclaration <boolean>? -encString <string> ?-escapeAllQuot? ?-indentAttrs? ?-nogtescape? ?-noEmptyElementTag? ?-escapeCR? ?-escapeTab?

    Returns the DOM tree as an (optional indented) XML string or sends the output directly to the given channelId.

    The -indent option requires "no", "none", "tabs" or a natural number betwenn 0 and 8, both included, as value. With the values "no" or "none" no additional white space outside of markup will be added to the serialization. I. Otherwise, it's a "pretty-print" serialization, due to inserting white space between end and the next start tag according to the nesting level. The level indentation wide is given with the number. If the value is "tabs", then indentation is done with tabs, one tab per level.

    If the option -escapeNonASCII is given, every non 7 bit ASCII character in attribute values or element PCDATA content will be escaped as character reference in decimal representation.

    The flag -doctypeDeclaration determines whether there will be a DOCTYPE declaration emitted before the first node of the document. The default is not to emit it. The DOCTYPE name will always be the element name of the document element. An external entity declaration of the external subset is only emitted if the document has a system identifier.

    The flag -xmlDeclaration determines whether there will be an XML Declaration and a newline emitted before anything else. The default is not to emit one. If this flag is given with a true argument then

    -encString sets the encoding value in the XML Declaration. Otherwise this option is ignored. Please note that this option just enhances the string representation of the generated XML Declaration with an encoding information string, nothing more. It's up to the user to handle encoding in case of writing to a channel or reparsing.

    If the option -escapeAllQuot is given, quotation marks will be escaped with &quot; even in text content of elements.

    If the option -indentAttrs is given, then attributes will each be separated with newlines and indented to the same level as the parent node plus the value given as argument to -indentAttrs (0..8).

    If the option -nogtescape is given then the character '>' won't get escaped in attribute values and text content of elements. The default is to escape this character.

    If the option -noEmptyElementTag is given then no empty tag syntax will be used. Instead, if an element has empty content it will be serialized with an element start tag and an immediately following element end tag.

    If the option -escapeCR is given then the character '\r' will be escaped as character reference in attribute values and text content of elements. The default is to not do this.

    If the option -escapeTab is given then the character '\t' will be escaped as character reference in attribute values and text content of elements. The default is to not do this.

    asCanonicalXML ?-channel channelId? ?-comments <boolean>?

    Returns the DOM tree as canonical XML string according to the "Canonical XML Version 1.0 W3C Recommendation 15 March 2001" or sends the output directly to the given channelId.

    If the goal is to get a canonical XML serialization of the XML file from which the DOM tree was parsed there are a few prerequisites. The XML data must be parsed with the -keepEmpties option. If the XML data includes a DTD which defines attribute defaults or external parsed entity references it is necessary to use the expat parser (not the -simple one). For any supported Tcl version lesser then 9.0 if the XML data includes characters outside the BMP a Tcl build with TCL_UTF_MAX defined to 6 (and a tDOM build with this Tcl) is necessary.

    If the -channel option is given then the output is send directly to the Tcl channel given as argument. It is the up to the caller to ensure that the channel is correctly fconfigured. If this option is not given then the command returns the serialization as string.

    If the option -comments is given with a true value then the serialization includes comments according to the rules of the recommendation. If the value is false or this option is omitted then comments are removed from the serialization.

    asHTML ?-channel channelId? ?-escapeNonASCII? ?-htmlEntities? ?-doctypeDeclaration <boolean>? ?-breakLines? ?-onlyContents?

    Returns the DOM tree serialized according to HTML rules (HTML elements are recognized regardless of case, without end tags for empty HTML elements etc.) as string or sends the output directly to the given channelId.

    If the option -escapeNonASCII is given, every non 7 bit ASCII character in attribute values or element PCDATA content will be escaped as character reference in decimal representation.

    If the option -htmlEntities is given, a character or a pair of characters is written using its HTML 5 character entity reference, if it has one. Some HTML 5 character entity references encode the same character or code points. From the possible entity names the shortest is choosen. If there are more than one shortest name and this names differ only in case then the lowercase alternative is choosen. Otherwise frist name in lexical ASCII order is choosen. There is one HTML5 entitiy (ThickSpace), which escapes two characters for which the first and the second character have an entity name by itself. If the two characters are to be serialized then the one two-characters entity ThickSpace will be choosen.

    If the option -breakLines is given the serialization outputs "\n>" instead of ">" for the opening tags of elements.

    If the option -onlyContents is given only all child nodes are serialized. This option is ignored by document nodes.

    If the flag -doctypeDeclaration is given there will be a DOCTYPE declaration emitted before the first node of the document. The default is, to do not. The DOCTYPE name will always be the element name of the document element without case normalization. An external entity declaration of the external subset is only emitted, if the document has a system identifier. The doctype declaration will be written from the available information, without check, if this is a known (w3c) HTML version information or if the document confirms to the given HTML version. All nodes types other than document nodes ignore this option.

    asText
    The asText method returns the tree by serializing the string-value of every text node in document order without any escaping. In effect, this is what the xslt output method "text" (XSLT 1.0 recommendation, section 16.3) does.
    asJSON ?-indent none/0..8? ?-channel channelId?

    The asJSON method serializes the tree into a valid JSON data string. In general, this may be a lossy serialization. For this serialization all comment, character data sections and processing instruction nodes, all attributes and all XML namespaces are ignored. Only element and text nodes may be reflected in the generated JSON serialization. Appropriate JSON data type information of a node will be respected.

    If an element node has the JSON type OBJECT, then every element node child of this element will be serialized as member of that object, with the node name of the child as the member name and the relevant children of that child as the value. Every other child nodes will be ignored.

    If an element node has the JSON type ARRAY, then the text and element node children of that element node are serialized as the consecutive values of the array. Element node children of an ARRAY element will be container nodes for nested ARRAY or OBJECT values.

    Text nodes with the JSON types TRUE, FALSE or NULL will be serialized to the corresponding JSON token without looking at the value of the text node. A text node without JSON type will always be serialized as a JSON string token. A text node with JSON type NUMBER will be serialized as JSON number token if the text node value is in fact a valid JSON number and as a JSON string if not.

    If an element node doesn't has a JSON type then the serialization of its children is determined by the following rules:

    Only text and element node child are relevant. If the element node to serialize is the member of a JSON object and there is no relevant child node the value of that member will be an empty JSON string. If the only relevant child node of this element node is a text node then the JSON value of that text node will be the value of the object member. If the element has more than one relevant child nodes and the first one is a text node then the relevant children will be serialized as JSON array. If the only relevant child node is an element node or the first relevant child is an element node and the node name of that only or first relevant child isn't equal to the array container node name all element node children will be serialized as the members of a JSON object (while ignoring any intermixed text nodes). If the only or first relevant child is an element node and the node name of this child is equal to the array container element name then all relevant children will be serialized as the values of a JSON array.

    If the element to serialize is a value of a JSON array and the node name of this element isn't equal to the array container node name that element will be seen as a container node for a JSON object and all element node children will be serialized as the members of that array while ignoring any text node children. If the element to serialize is a value of a JSON array and the node name of this element is equal to the array container node name, all relevant children will be serialized as JSON array.

    If the -channel option is given the serialization isn't returned as string but send directly to the channel, given as argument to the option.

    If the -indent option is given and the argument given to this option isn't "none" then the returned JSON string is "pretty-printed". The numeric argument to this option defines the number of spaces for any indentation level. The default is to not emit any additional white space.

    asTclValue ?typevariable?

    In case the DOM tree includes JSON type information this method returns the JSON data as nested Tcl data structure.

    The returned value may be a Tcl dict, a Tcl list or a string. If the optional argument typevariable is given then the variable with that name is set to the value dict, list or string respectively to signal the type of the result.

    A JSON object is returned as Tcl dict, a JSON array is returned as list and JSON strings and numbers as well as the symbolic JSON values null, true and false are returned as string (with the strings null, true and false for the respectively JSON symbol). The value of a member of a JSON object may be also a Tcl dict, or a Tcl list or a string and the elements of a JSON array list may be a Tcl dict or a Tcl list or a string.

    asTypedList

    In case the DOM tree includes JSON type information this method returns the JSON data as a nested Tcl list.

    The first element of every of this lists describes the type of the value. The types are: OBJECT, ARRAY, STRING, NUMBER, TRUE, FALSE or NULL.

    If the type is NUMBER or STRING, then the second (and last) element is the value. If the type is NULL, TRUE or FALSE the list does not have any other elements.

    If the type is OBJECT the second value will be a Tcl list of property name and value pairs, which means the second element could be used as dict. The value will be a Tcl list build by the rules of the asTypedList method.

    If the type is ARRAY the second value will be a Tcl list of the JSON array values, each one build by the rules of the asTypedList method.

    publicId ?publicId?
    Returns the public identifier of the doctype declaration of the document, if there is one, otherwise the empty string. If there is a value given to the method, the public identifier of the document is set to this value.
    systemId ?systemId?
    Returns the system identifier of the doctype declaration of the document, if there is one, otherwise the empty string. If there is a value given to the method, the system identifier of the document is set to this value.
    internalSubset ?internalSubset?
    Returns the internal subset of the doctype declaration of the document, if there is one, otherwise the empty string. If there is a value given to the method, the internal subset of the document is set to this value. Note that none of the parsing methods preserve the internal subset of a document; a freshly parsed document will always have an empty internal subset. Also note that the method doesn't do any syntactical check on a given internal subset.
    cdataSectionElements (?URI:?localname|*) ?<boolean>?
    This method allows one to control for which element nodes the text node children will be serialized as CDATA sections (this affects only serialization with the asXML method, no text node is altered in any way by this method). IF the method is called with an element name as first argument and a boolean with value true as second argument, every text node child of every element node in the document with the same name as the first argument will be serialized as CDATA section. If the second argument is a boolean with value false, all text nodes of all elements with the same name as the first argument will be serialized as usual. Namespaced element names have to be given in the form namespace_URI:localname, not in the otherwise usual prefix:localname form. With two arguments called, the method returns the used boolean value. If the method is called with only an element name, it will return a boolean value, indicating that the text node children of all elements with that name in the document will be serialized as CDATA section elements (return value 1) or not (return value 0). If the method is called with only one argument and that argument is an asterisk ('*'), then the method returns an unordered list of all element names of the document, for which the text node children will be serialized as CDATA section nodes.
    selectNodesNamespaces ?prefixUriList?
    This method gives control to a document global prefix to namespace URI mapping, which will be used for selectNodes method calls (on document as well as on all nodes, which belongs to the document) if it is not overwritten by using the -namespaces option of the selectNodes method. Any namespace prefix within an xpath expression will be first resolved against this list. If the list binds the same prefix to different namespaces, then the first binding will win. If a prefix could not resolved against the document global prefix / namespaces list, then the namespace definitions in scope of the context node will be used to resolve the prefix, as usual. If the optional argument prefixUriList is given, then the global prefix / namespace list is set to this list and returns it. Without the optional argument the method returns the current list. The default is the empty list.
    xslt ?-parameters parameterList? ?-ignoreUndeclaredParameters? ?-maxApplyDepth int? ?-xsltmessagecmd script? stylesheet ?outputVar?
    Applies an XSLT transformation on the whole document of the node object using the XSLT stylesheet (given as domDoc). Returns a document object containing the result document of the transformation and stores that document object in the optional outputVar, if that was given.

    The optional -parameters option sets top level <xsl:param> to string values. The parameterList has to be a tcl list consisting of parameter name and value pairs.

    If the option -ignoreUndeclaredParameters is given, then parameter names in the parameterList given to the -parameters options that are not declared as top-level parameters in the stylesheet are silently ignored. Without this option, an error is raised if the user tries to set a top-level parameter that is not declared in the stylesheet.

    The option -maxApplyDepth expects a positiv integer as argument. By default, the XSLT engine allows XSLT templates to nest up to 3000 levels (and raises error if they nest deeper). This limit can be set by the -maxApplyDepth option.

    The -xsltmessagecmd option sets a callback for xslt:message elements in the stylesheet. The actual command consists of the script, given as argument to the option, appended with the XML Fragment from instantiating the xsl:message element content as string (as if the XPath string() function would have been applied to the XML Fragment) and a flag, which indicates, if the xsl:message has an attribute "terminate" with the value "yes". If the called script returns anything else then TCL_OK then the XSLT transformation will be aborted, returning error. If the called script returns -code break, the error message is empty, otherwise the result code is reported. In case of terminated transformation, the outputVar, if given, is set to the empty string.

    toXSLTcmd ?objVar?
    If the DOM tree represents a valid XSLT stylesheet, this method transforms the DOM tree into an XSLT command, otherwise it returns error. The created xsltCmd is returned and stored in the objVar, if a var name was given. A successful transformation of the DOM tree to an xsltCmd removes the domDoc cmd and all nodeCmds of the document.

    The syntax of the created xsltCmd is:

    xsltCmd method ?arg ...?
    

    The valid methods are:

    transform ?-parameters parameterList? ?-ignoreUndeclaredParameters? ?-maxApplyDepth int? ?-xsltmessagecmd script? domDoc ?outputVar?
    Applies XSLT transformation on the document domDoc. Returns a document object containing the result document of that transformation and stores it in the optional outputVar.

    The optional -parameters option sets top level <xsl:param> to string values. The parameterList has to be a tcl list consisting of parameter name and value pairs.

    If the option -ignoreUndeclaredParameters is given, then parameter names in the parameterList given to the -parameters options that are not declared as top-level parameters in the stylesheet are silently ignored. Without this option, an error is raised if the user tries to set a top-level parameter, which is not declared in the stylesheet.

    The option -maxApplyDepth expects a positiv integer as argument. By default, the XSLT engine allows XSLT templates to nest up to 3000 levels (and raises error if they nest deeper). This limit can be set by the -maxApplyDepth option.

    The -xsltmessagecmd option sets a callback for xslt:message elements in the stylesheet. The actual command consists of the script, given as argument to the option, appended with the XML Fragment from instantiating the xsl:message element content as string (as if the XPath string() function would have been applied to the XML Fragment) and a flag, which indicates, if the xsl:message has an attribute "terminate" with the value "yes".

    delete
    Deletes the xsltCmd and cleans up all used recourses

    If the first argument to an xsltCmd is a domDoc or starts with a "-", then the command is processed in the same way as <xsltCmd> transform.

    normalize ?-forXPath?
    Puts all text nodes in the document into a "normal" form where only structure (e.g., elements, comments, processing instructions and CDATA sections) separates text nodes, i.e., there are neither adjacent text nodes nor empty text nodes. If the option -forXPath is given, all CDATA sections in the nodes are converted to text nodes, as a first step before the normalization.
    nodeType
    Returns the node type of the document node. This is always DOCUMENT_NODE.
    getElementById id
    Returns the node having a id attribute with value id or the empty string, if no node has an id attribute with that value.
    firstChild ?objVar?
    Returns the first top level node of the document.
    lastChild ?objVar?
    Returns the last top level node of the document.
    appendChild newChild
    Append newChild to the end of the list of top level nodes of the document.
    removeChild child
    Removes child from the list of top level nodes of the document. child will be part of the document fragment list after this operation. It is not physically deleted.
    hasChildNodes
    Returns 1 if the document has any nodes in the tree. Otherwise 0 is returned.
    childNodes
    Returns a list of the top level nodes of the document.
    ownerDocument ?domObjVar?
    Returns the document itself.
    insertBefore newChild refChild
    Insert newChild before the refChild into the list of top level nodes of the document. If refChild is the empty string, inserts newChild at the end of the top level nodes.
    replaceChild newChild oldChild
    Replaces oldChild with newChild in the list of children of that node. The oldChild node will be part of the document fragment list after this operation.
    appendFromList list
    Parses list , creates an according DOM subtree and appends this subtree at the end of the current list of top level nodes of the document.
    appendXML XMLstring
    Parses XMLstring, creates an according DOM subtree and appends this subtree at the end of the current list of top level nodes of the document.
    selectNodes ?-namespaces prefixUriList? ?-cache <boolean>? ?-list? xpathQuery ?typeVar?

    Returns the result of applying the XPath query xpathQuery to the document. The context node of the query is the root node in the sense of the XPath recommendation (not the document element). The result can be a string/value, a list of strings, a list of nodes or a list of attribute name / value pairs. If typeVar is given the result type name is stored into that variable (empty, bool, number, string, nodes, attrnodes or mixed).

    See the documentation of the of the domNode command method selectNodes for a detailed description of the arguments.

    baseURI ?URI?
    Returns the present baseURI of the document. If the optional argument URI is given, sets the base URI of the document to the given URI.
    appendFromScript tclScript
    Appends the nodes created by the tclScript by Tcl functions, which have been built using dom createNodeCmd, at the end of the current list of top level nodes of the document.
    insertBeforeFromScript tclScript refChild
    Inserts the nodes created in the tclScript by Tcl functions, which have been built using dom createNodeCmd, before the refChild into to the list of top level nodes of the document. If refChild is the empty string, the new nodes will be appended.
    deleteXPathCache ?xpathQuery?
    If called without the optional argument, all cached XPath expressions of the document are freed. If called with the optional argument xpathQuery, this single XPath query will be removed from the cache, if it is there. The method always returns an empty string.

    Otherwise, if an unknown method name is given, the command with the same name as the given method within the namespace ::dom::domDoc is tried to be executed. This allows quick method additions on Tcl level.

    Newly created nodes are appended to a hidden fragment list. If they are not moved into the tree they are automatically deleted as soon as the whole document gets deleted.

    SEE ALSO

    dom, domNode

    KEYWORDS

    DOM node creation, document element

    tdom-0.9.5-src/doc/expat.html0000644000175000017500000010102714703531020014513 0ustar rolfrolf tDOM manual: expat

    NAME

    expat -
    Creates an instance of an expat parser object

    SYNOPSIS

    package require tdom
    
    expat ?parsername? ?-namespace? ?arg arg ..
    
    xml::parser ?parsername? ?-namespace? ?arg arg ..
    

    DESCRIPTION

    The parser created with expat or xml::parser (which is just another name for the same command in an own namespace) are able to parse any kind of well-formed XML. The parsers are stream oriented XML parser. This means that you register handler scripts with the parser prior to starting the parse. These handler scripts are called when the parser discovers the associated structures in the document being parsed. A start tag is an example of the kind of structures for which you may register a handler script.

    The parsers always check for XML well-formedness of the input (and report error, if the input isn't well-formed). They parse the internal DTD and, at request, external DTD and external entities, if you resolve the identifier of the external entities with the -externalentitycommand script (see there). If you use the -validateCmd option (see there), the input is additionally validated.

    Additionly, the Tcl extension code that implements this command provides an API for adding C level coded handlers. Up to now, there exists the parser extension command "tdom". The handler set installed by this extension build an in memory "tDOM" DOM tree, while the parser is parsing the input.

    It is possible to register an arbitrary amount of different handler scripts and C level handlers for most of the events. If the event occurs, they are called in turn.

    COMMAND OPTIONS

    -namespace

    Enables namespace parsing. You must use this option while creating the parser with the expat or xml::parser command. You can't enable (nor disable) namespace parsing with <parserobj> configure ....

    -namespaceseparator char

    This option has only effect, if used together with the option -namespace. If given, this option determines the character inserted between namespace URI and the local name, while reporting an XML element name to a handler script. The default is the character ':'. The value must be a one-character string less or equal to \u00FF, preferably a 7-bit ASCII character or the empty string. If the value is the empty string (as well, as if the value is \x00) the namespace URI and the local name will be concatenated without any separator.

    -final boolean

    This option indicates whether the document data next presented to the parse method is the final part of the document. A value of "0" indicates that more data is expected. A value of "1" indicates that no more is expected. The default value is "1".

    If this option is set to "0" then the parser will not report certain errors if the XML data is not well-formed upon end of input, such as unclosed or unbalanced start or end tags. Instead some data may be saved by the parser until the next call to the parse method, thus delaying the reporting of some of the data.

    If this option is set to "1" then documents which are not well-formed upon end of input will generate an error.

    -validateCmd <tdom schema cmd>

    This option expects the name of a tDOM schema command. If this option is given, then the input is also validated. If the schema command hasn't set a reportcmd then the first validation error will stop further parsing (as a well-formedness error).

    -baseurl url

    Reports the base url of the document to the parser.

    -fastcall boolean

    By default this option is 0 (off). If this option is on then any handler installed by the options -elementstartcommand, -elementendcommand and -characterdatacommand from this moment on is installed in a way that calling it has lesser overhead as usual. This option may be switched between callback hander (re-)installion as desired.

    However this has some requirenments. The handler proc has to be defined before used as callback. If it is not then the callback is installed as ususal. And the handler proc must not be removed or re-defined as long as it is used as callback. If this is done the programm probably will crash but also may execute arbitrary code.

    The callback handler installed while this option is on will not be traced by executing them.

    -keepTextStart boolean

    By default this option is 0 (off). If this option is on then the position information of the start of a text or CDATA node is keeped over collecting the sometimes by expat delivered cdata pieces. With this option on the position information returned by the parser in a -characterdatacommand proc will be correct, otherwise not. Called in all other handler code the parser always return the correct position results, no matter what value this option have. It is off by default because it is rarely needed and saves a few cpu cyles this way.

    -elementstartcommand script

    Specifies a Tcl command to associate with the start tag of an element. The actual command consists of this option followed by at least two arguments: the element type name and the attribute list.

    The attribute list is a Tcl list consisting of name/value pairs, suitable for passing to the array set Tcl command.

    Example:

    proc HandleStart {name attlist} {
        puts stderr "Element start ==> $name has attributes $attlist"
    }
    
    $parser configure -elementstartcommand HandleStart
    
    $parser parse {<test id="123"></test>}
    

    This would result in the following command being invoked:

    HandleStart text {id 123}
    -elementendcommand script

    Specifies a Tcl command to associate with the end tag of an element. The actual command consists of this option followed by at least one argument: the element type name. In addition, if the -reportempty option is set then the command may be invoked with the -empty configuration option to indicate whether it is an empty element. See the description of the -reportempty option for an example.

    Example:

    proc HandleEnd {name} {
        puts stderr "Element end ==> $name"
    }
    
    $parser configure -elementendcommand HandleEnd
    
    $parser parse {<test id="123"></test>}
    

    This would result in the following command being invoked:

    HandleEnd test
    
    -characterdatacommand script

    Specifies a Tcl command to associate with character data in the document, ie. text. The actual command consists of this option followed by one argument: the text.

    Other than with the C API of the expat parser it is guaranteed that character data will be passed to the application in a single call to this command.

    Example:

    proc HandleText {data} {
        puts stderr "Character data ==> $data"
    }
    
    $parser configure -characterdatacommand HandleText
    
    $parser parse {<test>this is a test document</test>}
    

    This would result in the following command being invoked:

    HandleText {this is a test document}
    -processinginstructioncommand script

    Specifies a Tcl command to associate with processing instructions in the document. The actual command consists of this option followed by two arguments: the PI target and the PI data.

    Example:

    proc HandlePI {target data} {
        puts stderr "Processing instruction ==> $target $data"
    }
    
    $parser configure -processinginstructioncommand HandlePI
    
    $parser parse {<test><?special this is a processing instruction?></test>}
    

    This would result in the following command being invoked:

    HandlePI special {this is a processing instruction}
    
    -notationdeclcommand script

    Specifies a Tcl command to associate with notation declaration in the document. The actual command consists of this option followed by four arguments: the notation name, the base uri of the document (this means, whatever was set by the -baseurl option), the system identifier and the public identifier. The notation name is never empty, the other arguments may be.

    -externalentitycommand script

    Specifies a Tcl command to associate with references to external entities in the document. The actual command consists of this option followed by three arguments: the base uri, the system identifier of the entity and the public identifier of the entity. The base uri and the public identifier may be the empty list.

    This handler script has to return a tcl list consisting of three elements. The first element of this list signals, how the external entity is returned to the processor. At the moment, the three allowed types are "string", "channel" and "filename". The second element of the list has to be the (absolute) base URI of the external entity to be parsed. The third element of the list are data, either the already read data out of the external entity as string in the case of type "string", or the name of a tcl channel, in the case of type "channel", or the path to the external entity to be read in case of type "filename". Behind the scene, the external entity referenced by the returned Tcl channel, string or file name will be parsed with an expat external entity parser with the same handler sets as the main parser. If parsing of the external entity fails, the whole parsing is stopped with an error message. If a Tcl command registered as externalentitycommand isn't able to resolve an external entity it is allowed to return TCL_CONTINUE. In this case, the wrapper give the next registered externalentitycommand a try. If no externalentitycommand is able to handle the external entity parsing stops with an error.

    Example:

    proc externalEntityRefHandler {base systemId publicId} {
        if {![regexp {^[a-zA-Z]+:/} $systemId]}  {
            regsub {^[a-zA-Z]+:} $base {} base
            set basedir [file dirname $base]
            set systemId "[set basedir]/[set systemId]"
        } else {
            regsub {^[a-zA-Z]+:} $systemId systemId
        }
        if {[catch {set fd [open $systemId]}]} {
            return -code error \
                    -errorinfo "Failed to open external entity $systemId"
        }
        return [list channel $systemId $fd]
    }
    
    set parser [expat -externalentitycommand externalEntityRefHandler \
                      -baseurl "file:///local/doc/doc.xml" \
                      -paramentityparsing notstandalone]
    $parser parse {<?xml version='1.0'?>
    <!DOCTYPE test SYSTEM "test.dtd">
    <test/>}
    

    This would result in the following command being invoked:

    externalEntityRefHandler file:///local/doc/doc.xml test.dtd {}
    

    External entities are only tried to resolve via this handler script, if necessary. This means, external parameter entities triggers this handler only, if -paramentityparsing is used with argument "always" or if -paramentityparsing is used with argument "notstandalone" and the document isn't marked as standalone.

    -unknownencodingcommand script

    Not implemented at Tcl level.

    -startnamespacedeclcommand script

    Specifies a Tcl command to associate with start scope of namespace declarations in the document. The actual command consists of this option followed by two arguments: the namespace prefix and the namespace URI. For an xmlns attribute, prefix will be the empty list. For an xmlns="" attribute, uri will be the empty list. The call to the start and end element handlers occur between the calls to the start and end namespace declaration handlers.

    -endnamespacedeclcommand script

    Specifies a Tcl command to associate with end scope of namespace declarations in the document. The actual command consists of this option followed by the namespace prefix as argument. In case of an xmlns attribute, prefix will be the empty list. The call to the start and end element handlers occur between the calls to the start and end namespace declaration handlers.

    -commentcommand script

    Specifies a Tcl command to associate with comments in the document. The actual command consists of this option followed by one argument: the comment data.

    Example:

    proc HandleComment {data} {
        puts stderr "Comment ==> $data"
    }
    
    $parser configure -commentcommand HandleComment
    
    $parser parse {<test><!-- this is <obviously> a comment --></test>}
    

    This would result in the following command being invoked:

    HandleComment { this is <obviously> a comment }
    
    -notstandalonecommand script

    This Tcl command is called, if the document is not standalone (it has an external subset or a reference to a parameter entity, but does not have standalone="yes"). It is called with no additional arguments.

    -startcdatasectioncommand script

    Specifies a Tcl command to associate with the start of a CDATA section. It is called with no additional arguments.

    -endcdatasectioncommand script

    Specifies a Tcl command to associate with the end of a CDATA section. It is called with no additional arguments.

    -elementdeclcommand script

    Specifies a Tcl command to associate with element declarations. The actual command consists of this option followed by two arguments: the name of the element and the content model. The content model arg is a tcl list of four elements. The first list element specifies the type of the XML element; the six different possible types are reported as "MIXED", "NAME", "EMPTY", "CHOICE", "SEQ" or "ANY". The second list element reports the quantifier to the content model in XML Syntax ("?", "*" or "+") or is the empty list. If the type is "MIXED", then the quantifier will be "{}", indicating an PCDATA only element, or "*", with the allowed elements to intermix with PCDATA as tcl list as the fourth argument. If the type is "NAME", the name is the third arg; otherwise the third argument is the empty list. If the type is "CHOICE" or "SEQ" the fourth argument will contain a list of content models build like this one. The "EMPTY", "ANY", and "MIXED" types will only occur at top level.

    Examples:

    proc elDeclHandler {name content} {
         puts "$name $content"
    }
    
    set parser [expat -elementdeclcommand elDeclHandler]
    $parser parse {<?xml version='1.0'?>
    <!DOCTYPE test [
    <!ELEMENT test (#PCDATA)> 
    ]>
    <test>foo</test>}
    

    This would result in the following command being invoked:

    test {MIXED {} {} {}}
    
    $parser reset
    $parser parse {<?xml version='1.0'?>
    <!DOCTYPE test [
    <!ELEMENT test (a|b)>
    ]>
    <test><a/></test>}
    

    This would result in the following command being invoked:

    elDeclHandler test {CHOICE {} {} {{NAME {} a {}} {NAME {} b {}}}}
    
    -attlistdeclcommand script

    Specifies a Tcl command to associate with attlist declarations. The actual command consists of this option followed by five arguments. The Attlist declaration handler is called for *each* attribute. So a single Attlist declaration with multiple attributes declared will generate multiple calls to this handler. The arguments are the element name this attribute belongs to, the name of the attribute, the type of the attribute, the default value (may be the empty list) and a required flag. If this flag is true and the default value is not the empty list, then this is a "#FIXED" default.

    Example:

    proc attlistHandler {elname name type default isRequired} {
        puts "$elname $name $type $default $isRequired"
    }
    
    set parser [expat -attlistdeclcommand attlistHandler]
    $parser parse {<?xml version='1.0'?>
    <!DOCTYPE test [
    <!ELEMENT test EMPTY>
    <!ATTLIST test
              id      ID      #REQUIRED
              name    CDATA   #IMPLIED>
    ]>
    <test/>}
    

    This would result in the following commands being invoked:

    attlistHandler test id ID {} 1
    attlistHandler test name CDATA {} 0
    
    -startdoctypedeclcommand script

    Specifies a Tcl command to associate with the start of the DOCTYPE declaration. This command is called before any DTD or internal subset is parsed. The actual command consists of this option followed by four arguments: the doctype name, the system identifier, the public identifier and a boolean, that shows if the DOCTYPE has an internal subset.

    -enddoctypedeclcommand script

    Specifies a Tcl command to associate with the end of the DOCTYPE declaration. This command is called after processing any external subset. It is called with no additional arguments.

    -paramentityparsing never|notstandalone|always

    "never" disables expansion of parameter entities, "always" expands always and "notstandalone" only, if the document isn't "standalone='no'". The default ist "never"

    -entitydeclcommand script

    Specifies a Tcl command to associate with any entity declaration. The actual command consists of this option followed by seven arguments: the entity name, a boolean identifying parameter entities, the value of the entity, the base uri, the system identifier, the public identifier and the notation name. According to the type of entity declaration some of this arguments may be the empty list.

    -ignorewhitecdata boolean

    If this flag is set, element content which contain only whitespaces isn't reported with the -characterdatacommand.

    -ignorewhitespace boolean
    Another name for -ignorewhitecdata; see there.
    -handlerset name

    This option sets the Tcl handler set scope for the configure options. Any option value pair following this option in the same call to the parser are modifying the named Tcl handler set. If you don't use this option, you are modifying the default Tcl handler set, named "default".

    -noexpand boolean

    Normally, the parser will try to expand references to entities defined in the internal subset. If this option is set to a true value this entities are not expanded, but reported literal via the default handler. Warning: If you set this option to true and doesn't install a default handler (with the -defaultcommand option) for every handler set of the parser all internal entities are silent lost for the handler sets without a default handler.

    -useForeignDTD <boolean>
    If <boolean> is true and the document does not have an external subset, the parser will call the -externalentitycommand script with empty values for the systemId and publicID arguments. This option must be set, before the first piece of data is parsed. Setting this option, after the parsing has started has no effect. The default is not to use a foreign DTD. The default is restored, after resetting the parser. Pleace notice, that a -paramentityparsing value of "never" (which is the default) suppresses any call to the -externalentitycommand script. Pleace notice, that, if the document also doesn't have an internal subset, the -startdoctypedeclcommand and enddoctypedeclcommand scripts, if set, are not called.
    -billionLaughsAttackProtectionMaximumAmplification <float>
    This option together with -billionLaughsAttackProtectionActivationThreshold gives control over the parser limits that protects against billion laugh attacks (https://en.wikipedia.org/wiki/Billion_laughs_attack). This option expects a float >= 1.0 as argument. You should never need to use this option, because the default value (100.0) should work for any real data. If you ever need to increase this value for non-attack payload, please report.
    -billionLaughsAttackProtectionActivationThreshold <long>
    This option together with -billionLaughsAttackProtectionMaximumAmplification gives control over the parser limits that protects against billion laugh attacks (https://en.wikipedia.org/wiki/Billion_laughs_attack). This option expects a positiv integer as argument. You should never need to use this option, because the default value (8388608) should work for any real data. If you ever need to increase this value for non-attack payload, please report.

    COMMAND METHODS

    parser configure option value ?option value?

    Sets configuration options for the parser. Every command option, except -namespace can be set or modified with this method.

    parser cget ?-handlerset name? option

    Return the current configuration value option for the parser.

    If the -handlerset option is used, the configuration for the named handler set is returned.

    parser currentmarkup

    Returns the current markup as found in the XML, if called from within one of its markup event handler script (-elementstartcommand, -elementendcommand, -commentcommand and -processinginstructioncommand). Otherwise it return the empty string.

    parser delete

    Deletes the parser and the parser command. A parser cannot be deleted from within one of its handler callbacks (neither directly nor indirectly) and will raise a tcl error in this case.

    parser free

    Another name to call the method delete, see there.

    parser get -specifiedattributecount|-idattributeindex|-currentbytecount|-currentlinenumber|-currentcolumnnumber|-currentbyteindex
    -specifiedattributecount

    Returns the number of the attribute/value pairs passed in last call to the elementstartcommand that were specified in the start-tag rather than defaulted. Each attribute/value pair counts as 2; thus this corresponds to an index into the attribute list passed to the elementstartcommand.

    -idattributeindex

    Returns the index of the ID attribute passed in the last call to XML_StartElementHandler, or -1 if there is no ID attribute. Each attribute/value pair counts as 2; thus this corresponds to an index into the attributes list passed to the elementstartcommand.

    -currentbytecount

    Return the number of bytes in the current event. Returns 0 if the event is in an internal entity.

    If you use this option consider if you may need the parser option -keepTextStart.

    -currentlinenumber

    Returns the line number of the current parse location.

    If you use this option consider if you may need the parser option -keepTextStart.

    -currentcolumnnumber

    Returns the column number of the current parse location.

    If you use this option consider if you may need the parser option -keepTextStart.

    -currentbyteindex

    Returns the byte index of the current parse location.

    If you use this option consider if you may need the parser option -keepTextStart.

    Only one value may be requested at a time.

    parser parse data

    Parses the XML string data. The event callback scripts will be called, as there triggering events happens. This method cannot be used from within a callback (neither directly nor indirectly) of the parser to be used and will raise an error in this case.

    parser parsechannel channelID

    Reads the XML data out of the tcl channel channelID (starting at the current access position, without any seek) up to the end of file condition and parses that data. The channel encoding is respected. Use the helper proc tDOM::xmlOpenFile out of the tDOM script library to open a file, if you want to use this method. This method cannot be used from within a callback (neither directly nor indirectly) of the parser to be used and will raise an error in this case.

    parser parsefile filename

    Reads the XML data directly out of the file with the filename filename and parses that data. This is done with low-level file operations. The XML data must be in US-ASCII, ISO-8859-1, UTF-8 or UTF-16 encoding. If applicable, this is the fastest way, to parse XML data. This method cannot be used from within a callback (neither directly nor indirectly) of the parser to be used and will raise an error in this case.

    parser reset

    Resets the parser in preparation for parsing another document. A parser cannot be reset from within one of its handler callbacks (neither directly nor indirectly) and will raise a tcl error in this cases.

    Callback Command Return Codes

    A script invoked for any of the parser callback commands, such as -elementstartcommand, -elementendcommand, etc, may return an error code other than "ok" or "error". All callbacks may in addition return "break" or "continue".

    If a callback script returns an "error" error code then processing of the document is terminated and the error is propagated in the usual fashion.

    If a callback script returns a "break" error code then all further processing of every handler script out of this Tcl handler set is suppressed for the further parsing. This does not influence any other handler set.

    If a callback script returns a "continue" error code then processing of the current element, and its children, ceases for every handler script out of this Tcl handler set and processing continues with the next (sibling) element. This does not influence any other handler set.

    If a callback script returns a "return" error code then parsing is canceled altogether, but no error is raised.

    SEE ALSO

    expatapi, tdom

    KEYWORDS

    SAX, push, pushparser

    tdom-0.9.5-src/doc/tdomcmd.html0000644000175000017500000000676714703531020015040 0ustar rolfrolf tDOM manual: tdom

    NAME

    tdom -
    tdom is an expat parser object extension to create an in-memory DOM tree from the input while parsing.

    SYNOPSIS

    package require tdom
    
    set parser [expat]
    
    tdom $parser enable

    DESCRIPTION

    tdom adds the C handler set "tdom" to an tcl expat parser obj. This handler set builds an in-memory DOM tree out of the input, parsed by the parser. A DOM tree created this way behave exactly like a DOM tree created by the "dom" command (see there). In fact, tdom is only another interface to the same functionality; it uses the code behind the dom code for building the DOM tree.

    tdom parserObj enable

    Adds the tdom C handler set to a Tcl expat parser object. Next time, the parser parses input, the tdom C handler functions create an in-memory DOM tree.

    tdom parserObj getdoc

    Returns the DOM tree as domDoc (see there) object.

    tdom parserObj setStoreLineColumn ?boolean?

    See the method setStoreLineColumn of the dom command.

    tdom parserObj remove

    Removes the tdom C handler set from the parser object.

    tdom parserObj keepEmpties

    See the option -keepEmpties of the dom command.

    tdom parserObj setExternalEntityResolver script

    SEE ALSO

    dom, expat

    KEYWORDS

    DOM, SAX, C handler set

    tdom-0.9.5-src/doc/pullparser.xml0000644000175000017500000001666114703531020015430 0ustar rolfrolf tdom::pullparser Create an XML pull parser command package require tdom tdom::pullparser cmdName -ignorewhitecdata
    DESCRIPTION

    This command creates XML pull parser commands with a simple API, along the lines of a simple StAX parser. After creation, you've to set an input source, to do anything useful with the pull parser. For this see the methods input, inputchannel and inputfile.

    The parser has always a state. You start parsing the XML data until some next state, do what has to be done and skip again to the next state. XML well-formedness errors along the way will be reported as TCL_ERROR with additional info in the error message.

    The pull parsers don't follow external entities and are XML 1.0 only, they know nothing about XML Namespaces. You get the tags and attribute names as in the source. You aren't noticed about comments, processing instructions and external entities; they are silently ignored for you. CDATA Sections are handled as if their content would have been provided without using a CDATA Section.

    On the brighter side is that character entity and attribute default declarations in the internal subset are respected (because of using expat as underlying parser). It is probably somewhat faster than a comperable implementation with the SAX interface. It's a nice programming model. It's a slim interface.

    If the option -ignorewhitecdata is given, the created XML pull parser command will ignore any white space only (' ', \t, \n and \r) text content between START_TAG and START_TAG / END_TAG. The parser won't stop at such input and will create TEXT state events only for not white space only text.

    Not all methods are valid in every state. The parser will raise TCL_ERROR if a method is called in a state the method isn't valid for. Valid methods of the created commands are:

    state This method is valid in all parser states. The possible return values and their meanings are:
    • READY - The parser is created or reset, but no input is set.
    • START_DOCUMENT - Input is set, parser is ready to start parsing.
    • START_TAG - Parser has stopped parsing at a start tag.
    • END_TAG - Parser has stopped parsing at an end tag
    • TEXT - Parser has stopped parsing to report text between tags.
    • END_DOKUMENT - Parser has finished parsing without error.
    • PARSE_ERROR - Parser stopped parsing at XML error in input.
    input data This method is only valid in state READY. It prepares the parser to use data as XML input to parse and switches the parser into state START_DOCUMENT. inputchannel channel This method is only valid in state READY. It prepares the parser to read the XML input to parse out of channel and switches the parser into state START_DOCUMENT. inputfile filename This method is only valid in state READY. It open filename and prepares the parser to read the XML input to parse out of that file. The method returns TCL_ERROR, if the file could not be open in read mode. Otherwise it switches the parser into state START_DOCUMENT. next This method is valid in state START_DOCUMENT, START_TAG, END_TAG and TEXT. It continues parsing of the XML input until the next event, which it will return. tag This method is only valid in states START_TAG and END_TAG. It returns the tag name of the current start or end tag. attributes This method is only valid in state START_TAG. It returns all attributes of the element in a name value list. text This method is only valid in state TEXT. It returns the character data of the event. There will be always at most one TEXT event between START_TAG and the next START_TAG or END_TAG event. skip This method is only valid in state START_TAG. It skips to the corresponding end tag and ignores all events (but not XML parsing errors) on the way and returns the new state END_TAG. find-element tagname | -names tagnames This method is only valid in states START_DOCUMENT, START_TAG and END_TAG. It skips forward until the next element start tag with tag name tagname and returns the new state START_TAG. If a list of tagnames is provided with the -names option, any of the tagnames match. If there isn't such an element the parser stops at the end of the input and returns END_DOCUMENT. reset This method is valid in all parser states. It resets the parser into READY state and returns that. delete This method is valid in all parser states. It deletes the parser command.

    Miscellaneous methods:

    line This method is valid in all parser states except READY and TEXT. It returns the line number of the parsing position. Line counting starts with 1. column This method is valid in all parser states except READY and TEXT. It returns the offset, from the beginning of the current line, of the parsing position. Column counting starts with 0.
    XML pull parsing
    tdom-0.9.5-src/doc/tmml.options0000644000175000017500000000025214703531020015070 0ustar rolfrolfarray set Options { xsltProcessor tdom masterDocument "tDOM.xml" tomanOptions -soelim htmlDirectory . nroffDirectory . } tdom-0.9.5-src/doc/expatapi.html0000644000175000017500000003122014703531020015202 0ustar rolfrolf tDOM manual: expatapi

    NAME

    CheckExpatParserObj, CHandlerSetInstall, CHandlerSetRemove, CHandlerSetCreate, CHandlerSetGetUserData, GetExpatInfo -
    Functions to create, install and remove expat parser object extensions.

    SYNOPSIS

    #include <tclexpat.h>
    
    int 
    CheckExpatParserObj (interp, nameObj)  
    
    int
    CHandlerSetInstall (interp, expatObj, handlerSet)
    
    int 
    CHandlerSetRemove (interp, expatObj, handlerSetName)
    
    CHandlerSet*
    CHandlerSetCreate (handlerSetName)
    
    CHandlerSet*
    CHandlerSetGet (interp, expatObj, handlerSetName)
    
    void*
    CHandlerSetGetUserData (interp, expatObj, handlerSetName)
    
    TclGenExpatInfo*
    GetExpatInfo (interp, expatObj)
    

    ARGUMENTS

    TypeNameMode
    Tcl_Interp*interpin
     Interpreter with the expat parser object.
    Tcl_Obj*expatObjin
     A Tcl Object containing the command name of the expat parser object to be queried or modified.
    char*handlerSetNamein
     Identifier of the handler set.
    CHandlerSet*handlerSetin
     Pointer to a C handler set.
    Tcl_Obj*nameObj
     A Tcl Object containing the name of a expat parser object

    DESCRIPTION

    The functions described in this manual allows one to add C level coded event handler to an tDOM Tcl expat parser objects. A tDOM Tcl expat parser object is able to have several Tcl scripts and C functions associated with a specific event. If the event occurs, first the Tcl scripts then the C functions associated with the event are called in turn.

    A tDOM Tcl expat parser extension is an ordinary Tcl extension and loaded like every other Tcl extension. It must install at least one new Tcl Level command, that manipulates a tDOM Tcl expat parser object.

    A C level handler set is a data structure like this:

    typedef struct CHandlerSet {
        struct CHandlerSet *nextHandlerSet;
        char *name;                     /* refname of the handler set */
        int ignoreWhiteCDATAs;          /* ignore 'white' CDATA sections */
    
        void *userData;                 /* Handler set specific Data Structure;
                                           the C handler set extension has to
                                           malloc the needed structure in his
                                           init func and has to provide a
                                           cleanup func (to free it). */
    
        CHandlerSet_userDataReset        resetProc;
        CHandlerSet_userDataFree         freeProc;
    
        /* C func for element start */
        XML_StartElementHandler          elementstartcommand;
        /* C func for element end */
        XML_EndElementHandler            elementendcommand;
        /* C func for character data */
        XML_CharacterDataHandler         datacommand;
        /* C func for namespace decl start */
        XML_StartNamespaceDeclHandler    startnsdeclcommand;
        /* C func for namespace decl end */
        XML_EndNamespaceDeclHandler      endnsdeclcommand;
        /* C func for processing instruction */
        XML_ProcessingInstructionHandler picommand;
        /* C func for default data */
        XML_DefaultHandler               defaultcommand;
        /* C func for unparsed entity declaration */
        XML_NotationDeclHandler          notationcommand;
        /* C func for external entity */
        XML_ExternalEntityRefHandler     externalentitycommand;
        /* C func for unknown encoding */
        XML_UnknownEncodingHandler       unknownencodingcommand;
        /* C func for comments */
        XML_CommentHandler               commentCommand;
        /* C func for "not standalone" docs */
        XML_NotStandaloneHandler         notStandaloneCommand;
        /* C func for CDATA section start */
        XML_StartCdataSectionHandler     startCdataSectionCommand;
        /* C func for CDATA section end */
        XML_EndCdataSectionHandler       endCdataSectionCommand;
        /* C func for !ELEMENT decl's */
        XML_ElementDeclHandler           elementDeclCommand;
        /* C func for !ATTLIST decl's */
        XML_AttlistDeclHandler           attlistDeclCommand;
        /* C func for !DOCTYPE decl's */
        XML_StartDoctypeDeclHandler      startDoctypeDeclCommand;
        /* C func for !DOCTYPE decl ends */
        XML_EndDoctypeDeclHandler        endDoctypeDeclCommand;
        /* C func for !ENTITY decls's */
        XML_EntityDeclHandler            entityDeclCommand;
    } CHandlerSet;
    

    The types and the arguments of the event functions (XML_*) are exactly the same like the expat lib handler functions and described in detail in expat.h, see there. The extension has only to provided the handler functions needed; it's perfectly OK to leave unused handler slots as the are (they are initialized to NULL by CHandlerSetCreate).

    The name of this structure is used to identify the handler set.

    If the flag ignoreWhiteCDATAs is set, element content which contain only whitespace isn't reported with the datacommand.

    The userData element points to the handler set specific data. The event handler functions are called with this pointer as userData argument.

    resetProc and freeProc must have arguments that match the type

    void (Tcl_Interp *interp, void *userData)

    resetProc is called in case the parser is reset with <parserObj> reset and should do any necessary cleanup and reinitializing to prepare the C handler set for a new XML document. The freeProc is called, if the parser is deleted and should do memory cleanup etc.

    CHandlerSetCreate create a C handler set, gives it the name name and initializes any other element with NULL.

    CHandlerSetInstall adds the handlerSet to the parser expatObj. The parser has to be a tDOM Tcl expat parser object in the interpreter interp. The name of the C handler set has to be unique for the parser. Returns 0 in case of success. Returns 1 if expatObj isn't a parser object in the interpreter interp. Returns 2 if this parser has already a C handler set with the handlerSet name.

    CHandlerSetRemove removes the C handler set referenced by the handlerSetName from the parser expatObj. The parser has to be a tDOM Tcl expat parser object in the interpreter interp. CHandlerSetRemove calls the freeProc function of the C handler set structure, removes the handler set from the C handler set list and frees the handler structure. Returns 0 in case of success. Returns 1 if expatObj isn't a parser object in the interpreter interp. Returns 2 if this parser hasn't a C handler set named handlerSetName.

    CheckExpatParserObj returns 1, if nameObj is a tDOM Tcl expat parser object in the interpreter interp, otherwise it returns 0. Example:

    int
    TclExampleObjCmd(dummy, interp, objc, objv)
         ClientData dummy;
         Tcl_Interp *interp;
         int objc;
         Tcl_Obj *const objv[];
    {
        char          *method;
        CHandlerSet   *handlerSet;
        int            methodIndex, result;
        simpleCounter *counter;
        
    
        static char *exampleMethods[] = {
            "enable", "getresult", "remove",
            NULL
        };
        enum exampleMethod {
            m_enable, m_getresult, m_remove
        };
    
        if (objc != 3) {
            Tcl_WrongNumArgs (interp, 1, objv, example_usage);
            return TCL_ERROR;
        }
    
        if (!CheckExpatParserObj (interp, objv[1])) {
            Tcl_SetResult (interp, "First argument has to be a expat parser object", NULL);
            return TCL_ERROR;
        }
        /* ... */
    

    CHandlerSetGet returns a pointer to the C handler Set referenced by the name handlerSetName of the parser object expatObj. expatObj has to be an expat parser object in the interpreter interp. Returns NULL in case of error.

    CHandlerSetGetUserData returns a pointer to the userData of the C handler set referenced by the name handlerSetName of the parser object expatObj. expatObj has to be an expat parser object in the interpreter interp. Returns NULL in case of error.

    GetExpatInfo Is a helper function that returns a pointer to the TclGenExpatInfo structure of the tDOM Tcl expat parser object expatObj. The expatObj has to be a tDOM Tcl expat parser object in the interpreter interp. This is most useful, to set the application status of the parser object.

    See the simple but full functionally example in the extensions/example dir or the more complex example tnc in the extensions/tnc dir (a simple DTD validation extension).

    SEE ALSO

    expat

    KEYWORDS

    C handler set

    tdom-0.9.5-src/doc/tdomcmd.n0000644000175000017500000000721514703531020014316 0ustar rolfrolf'\" '\" Generated from tdomcmd.xml '\" '\" BEGIN man.macros .if t .wh -1.3i ^B .nr ^l \n(.l .ad b .de AP .ie !"\\$4"" .TP \\$4 .el \{\ . ie !"\\$2"" .TP \\n()Cu . el .TP 15 .\} .ta \\n()Au \\n()Bu .ie !"\\$3"" \{\ \&\\$1 \\fI\\$2\\fP (\\$3) .\".b .\} .el \{\ .br .ie !"\\$2"" \{\ \&\\$1 \\fI\\$2\\fP .\} .el \{\ \&\\fI\\$1\\fP .\} .\} .. .de AS .nr )A 10n .if !"\\$1"" .nr )A \\w'\\$1'u+3n .nr )B \\n()Au+15n .\" .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n .nr )C \\n()Bu+\\w'(in/out)'u+2n .. .AS Tcl_Interp Tcl_CreateInterp in/out .de BS .br .mk ^y .nr ^b 1u .if n .nf .if n .ti 0 .if n \l'\\n(.lu\(ul' .if n .fi .. .de BE .nf .ti 0 .mk ^t .ie n \l'\\n(^lu\(ul' .el \{\ .\" Draw four-sided box normally, but don't draw top of .\" box if the box started on an earlier page. .ie !\\n(^b-1 \{\ \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .el \}\ \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .\} .fi .br .nr ^b 0 .. .de VS .if !"\\$2"" .br .mk ^Y .ie n 'mc \s12\(br\s0 .el .nr ^v 1u .. .de VE .ie n 'mc .el \{\ .ev 2 .nf .ti 0 .mk ^t \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' .sp -1 .fi .ev .\} .nr ^v 0 .. .de ^B .ev 2 'ti 0 'nf .mk ^t .if \\n(^b \{\ .\" Draw three-sided box if this is the box's first page, .\" draw two sides but no top otherwise. .ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .\} .if \\n(^v \{\ .nr ^x \\n(^tu+1v-\\n(^Yu \kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c .\} .bp 'fi .ev .if \\n(^b \{\ .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. .de DS .RS .nf .sp .. .de DE .fi .RE .sp .. .de SO .SH "STANDARD OPTIONS" .LP .nf .ta 5.5c 11c .ft B .. .de SE .fi .ft R .LP See the \\fBoptions\\fR manual entry for details on the standard options. .. .de OP .LP .nf .ta 4c Command-Line Name: \\fB\\$1\\fR Database Name: \\fB\\$2\\fR Database Class: \\fB\\$3\\fR .fi .IP .. .de CS .RS .nf .ta .25i .5i .75i 1i .if t .ft C .. .de CE .fi .if t .ft R .RE .. .de UL \\$1\l'|0\(ul'\\$2 .. '\" END man.macros .TH tdom n "" Tcl "" .BS .SH NAME tdom \- tdom is an expat parser object extension to create an in-memory DOM tree from the input while parsing. .SH SYNOPSIS .nf package require tdom set parser [expat] tdom $parser enable .fi .BE .SH DESCRIPTION .PP \&\fItdom\fR adds the C handler set "tdom" to an tcl expat parser obj. This handler set builds an in-memory DOM tree out of the input, parsed by the parser. A DOM tree created this way behave exactly like a DOM tree created by the "dom" command (see there). In fact, tdom is only another interface to the same functionality; it uses the code behind the \&\fBdom\fR code for building the DOM tree. .TP \&\fB\fBtdom\fP \fIparserObj\fB \fBenable\fP \&\fR .RS .PP Adds the tdom C handler set to a Tcl expat parser object. Next time, the parser parses input, the tdom C handler functions create an in-memory DOM tree. .RE .TP \&\fB\fBtdom\fP \fIparserObj\fB \fBgetdoc\fP \&\fR .RS .PP Returns the DOM tree as domDoc (see there) object. .RE .TP \&\fB\fBtdom\fP \fIparserObj\fB \fBsetStoreLineColumn\fP ?\fIboolean\fB? \&\fR .RS .PP See the method \fBsetStoreLineColumn\fR of the \&\fBdom\fP command. .RE .TP \&\fB\fBtdom\fP \fIparserObj\fB \fBremove\fP \&\fR .RS .PP Removes the tdom C handler set from the parser object. .RE .TP \&\fB\fBtdom\fP \fIparserObj\fB \fBkeepEmpties\fP \&\fR .RS .PP See the option \fB-keepEmpties\fR of the \fBdom\fP command. .RE .TP \&\fB\fBtdom\fP \fIparserObj\fB \fBsetExternalEntityResolver\fP \fIscript\fB \&\fR .SH "SEE ALSO" dom, expat .SH KEYWORDS DOM, SAX, C handler set tdom-0.9.5-src/doc/pullparser.html0000644000175000017500000002054114703531020015564 0ustar rolfrolf tDOM manual: pullparser

    NAME

    tdom::pullparser -
    Create an XML pull parser command

    SYNOPSIS

    package require tdom
    
        tdom::pullparser cmdName  ? -ignorewhitecdata ? 
        

    DESCRIPTION

    This command creates XML pull parser commands with a simple API, along the lines of a simple StAX parser. After creation, you've to set an input source, to do anything useful with the pull parser. For this see the methods input, inputchannel and inputfile.

    The parser has always a state. You start parsing the XML data until some next state, do what has to be done and skip again to the next state. XML well-formedness errors along the way will be reported as TCL_ERROR with additional info in the error message.

    The pull parsers don't follow external entities and are XML 1.0 only, they know nothing about XML Namespaces. You get the tags and attribute names as in the source. You aren't noticed about comments, processing instructions and external entities; they are silently ignored for you. CDATA Sections are handled as if their content would have been provided without using a CDATA Section.

    On the brighter side is that character entity and attribute default declarations in the internal subset are respected (because of using expat as underlying parser). It is probably somewhat faster than a comperable implementation with the SAX interface. It's a nice programming model. It's a slim interface.

    If the option -ignorewhitecdata is given, the created XML pull parser command will ignore any white space only (' ', \t, \n and \r) text content between START_TAG and START_TAG / END_TAG. The parser won't stop at such input and will create TEXT state events only for not white space only text.

    Not all methods are valid in every state. The parser will raise TCL_ERROR if a method is called in a state the method isn't valid for. Valid methods of the created commands are:

    state
    This method is valid in all parser states. The possible return values and their meanings are:
    • READY - The parser is created or reset, but no input is set.
    • START_DOCUMENT - Input is set, parser is ready to start parsing.
    • START_TAG - Parser has stopped parsing at a start tag.
    • END_TAG - Parser has stopped parsing at an end tag
    • TEXT - Parser has stopped parsing to report text between tags.
    • END_DOKUMENT - Parser has finished parsing without error.
    • PARSE_ERROR - Parser stopped parsing at XML error in input.
    input data
    This method is only valid in state READY. It prepares the parser to use data as XML input to parse and switches the parser into state START_DOCUMENT.
    inputchannel channel
    This method is only valid in state READY. It prepares the parser to read the XML input to parse out of channel and switches the parser into state START_DOCUMENT.
    inputfile filename
    This method is only valid in state READY. It open filename and prepares the parser to read the XML input to parse out of that file. The method returns TCL_ERROR, if the file could not be open in read mode. Otherwise it switches the parser into state START_DOCUMENT.
    next
    This method is valid in state START_DOCUMENT, START_TAG, END_TAG and TEXT. It continues parsing of the XML input until the next event, which it will return.
    tag
    This method is only valid in states START_TAG and END_TAG. It returns the tag name of the current start or end tag.
    attributes
    This method is only valid in state START_TAG. It returns all attributes of the element in a name value list.
    text
    This method is only valid in state TEXT. It returns the character data of the event. There will be always at most one TEXT event between START_TAG and the next START_TAG or END_TAG event.
    skip
    This method is only valid in state START_TAG. It skips to the corresponding end tag and ignores all events (but not XML parsing errors) on the way and returns the new state END_TAG.
    find-element ? tagname | -names tagnames ?
    This method is only valid in states START_DOCUMENT, START_TAG and END_TAG. It skips forward until the next element start tag with tag name tagname and returns the new state START_TAG. If a list of tagnames is provided with the -names option, any of the tagnames match. If there isn't such an element the parser stops at the end of the input and returns END_DOCUMENT.
    reset
    This method is valid in all parser states. It resets the parser into READY state and returns that.
    delete
    This method is valid in all parser states. It deletes the parser command.

    Miscellaneous methods:

    line
    This method is valid in all parser states except READY and TEXT. It returns the line number of the parsing position. Line counting starts with 1.
    column
    This method is valid in all parser states except READY and TEXT. It returns the offset, from the beginning of the current line, of the parsing position. Column counting starts with 0.

    KEYWORDS

    XML, pull, parsing

    tdom-0.9.5-src/doc/tDOM.xml0000644000175000017500000000106114703531020014026 0ustar rolfrolf ]> tDOM manual &dom; &domDoc; &domNode; &expat; &expatapi; &pullparser; &schema; &tdomcmd; &tnc; tdom-0.9.5-src/doc/INDEX.MAP0000644000175000017500000000564414703531020013722 0ustar rolfrolf tdom-0.9.5-src/doc/dom.n0000644000175000017500000007032014703531020013443 0ustar rolfrolf'\" '\" Generated from dom.xml '\" '\" BEGIN man.macros .if t .wh -1.3i ^B .nr ^l \n(.l .ad b .de AP .ie !"\\$4"" .TP \\$4 .el \{\ . ie !"\\$2"" .TP \\n()Cu . el .TP 15 .\} .ta \\n()Au \\n()Bu .ie !"\\$3"" \{\ \&\\$1 \\fI\\$2\\fP (\\$3) .\".b .\} .el \{\ .br .ie !"\\$2"" \{\ \&\\$1 \\fI\\$2\\fP .\} .el \{\ \&\\fI\\$1\\fP .\} .\} .. .de AS .nr )A 10n .if !"\\$1"" .nr )A \\w'\\$1'u+3n .nr )B \\n()Au+15n .\" .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n .nr )C \\n()Bu+\\w'(in/out)'u+2n .. .AS Tcl_Interp Tcl_CreateInterp in/out .de BS .br .mk ^y .nr ^b 1u .if n .nf .if n .ti 0 .if n \l'\\n(.lu\(ul' .if n .fi .. .de BE .nf .ti 0 .mk ^t .ie n \l'\\n(^lu\(ul' .el \{\ .\" Draw four-sided box normally, but don't draw top of .\" box if the box started on an earlier page. .ie !\\n(^b-1 \{\ \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .el \}\ \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .\} .fi .br .nr ^b 0 .. .de VS .if !"\\$2"" .br .mk ^Y .ie n 'mc \s12\(br\s0 .el .nr ^v 1u .. .de VE .ie n 'mc .el \{\ .ev 2 .nf .ti 0 .mk ^t \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' .sp -1 .fi .ev .\} .nr ^v 0 .. .de ^B .ev 2 'ti 0 'nf .mk ^t .if \\n(^b \{\ .\" Draw three-sided box if this is the box's first page, .\" draw two sides but no top otherwise. .ie !\\n(^b-1 \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .el \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\h'|0u'\c .\} .if \\n(^v \{\ .nr ^x \\n(^tu+1v-\\n(^Yu \kx\h'-\\nxu'\h'|\\n(^lu+3n'\ky\L'-\\n(^xu'\v'\\n(^xu'\h'|0u'\c .\} .bp 'fi .ev .if \\n(^b \{\ .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. .de DS .RS .nf .sp .. .de DE .fi .RE .sp .. .de SO .SH "STANDARD OPTIONS" .LP .nf .ta 5.5c 11c .ft B .. .de SE .fi .ft R .LP See the \\fBoptions\\fR manual entry for details on the standard options. .. .de OP .LP .nf .ta 4c Command-Line Name: \\fB\\$1\\fR Database Name: \\fB\\$2\\fR Database Class: \\fB\\$3\\fR .fi .IP .. .de CS .RS .nf .ta .25i .5i .75i 1i .if t .ft C .. .de CE .fi .if t .ft R .RE .. .de UL \\$1\l'|0\(ul'\\$2 .. '\" END man.macros .TH dom n "" Tcl "" .BS .SH NAME dom \- Create an in-memory DOM tree from XML .SH SYNOPSIS .nf package require tdom \&\fBdom\fP \fImethod\fR ?\fIarg arg ...\fR? .fi .BE .SH "DESCRIPTION " .PP This command provides the creation of DOM trees in memory. In the usual case a string containing a XML information is parsed and converted into a DOM tree. Other possible parse input may be HTML or JSON. The \fImethod\fR indicates a specific subcommand. .PP The valid methods are: .TP \&\fB\fBdom\fP \fBparse\fP ?\fIoptions\fB? ?\fIdata\fB? \&\fRParses the XML information and builds up the DOM tree in memory providing a Tcl object command to this DOM document object. Example: .RS .CS dom parse $xml doc $doc documentElement root .CE .PP parses the XML in the variable xml, creates the DOM tree in memory, make a reference to the document object, visible in Tcl as a document object command, and assigns this new object name to the variable doc. When doc gets freed, the DOM tree and the associated Tcl command object (document and all node objects) are freed automatically. .CS set document [dom parse $xml] set root [$document documentElement] .CE .PP parses the XML in the variable xml, creates the DOM tree in memory, make a reference to the document object, visible in Tcl as a document object command, and returns this new object name, which is then stored in \&\fIdocument\fR. To free the underlying DOM tree and the associative Tcl object commands (document + nodes + fragment nodes) the document object command has to be explicitly deleted by: .CS $document delete .CE or .CS rename $document "" .CE .PP The valid options are: .IP "\fB-simple\fR" If \fI-simple\fR is specified, a simple but fast parser is used (conforms not fully to XML recommendation). That should double parsing and DOM generation speed. The encoding of the data is not transformed inside the parser. The simple parser does not respect any encoding information in the XML declaration. It skips over the internal DTD subset and ignores any information in it. Therefore, it doesn't include defaulted attribute values into the tree, even if the according attribute declaration is in the internal subset. It also doesn't expand internal or external entity references other than the predefined entities and character references .IP "\fB-html\fR" If \fI-html\fR is specified, a fast HTML parser is used, which tries to even parse badly formed HTML into a DOM tree. If the HTML document given to parse does not have a single root element (as it was legal up to HTML 4.01) and the -forest option is not used then a html node will be inserted as document element, with the HTML input data top level elements as children. .IP "\fB-html5\fR" This option is only available if tDOM was build with --enable-html5. Use the \fIfeatureinfo\fR method if you need to know if this feature is build in. If \&\fI-html5\fR is specified, the gumbo lib html5 parser (https://github.com/google/gumbo-parser) is used to build the DOM tree. This is, as far as it goes, XML namespace-aware (which means for example that all HTML elements are in the html5 namespace). Since this probably isn't wanted by a lot of users and adds only burden for no good in a lot of use cases \fI-html5\fR can be combined with \fI-ignorexmlns\fR, in which case all nodes and attributes in the DOM tree are not in an XML namespace. All tag and attribute names in the DOM tree will be lower case, even for foreign elements not in the xhtml, svg or mathml namespace. The DOM tree may include nodes, that the parser inserted because they are implied by the context (as , , etc.). Input longer than 4 GByte byte length is not supported by the underlying gumbo parser. .IP "\fB-json\fR" If \fI-json\fR is specified, the \fIdata\fR is expected to be a valid JSON string (according to RFC 7159). The command returns an ordinary DOM document with nesting token inside the JSON data translated into tree hierarchy. If a JSON array value is itself an object or array then container element nodes named (in a default build) arraycontainer or objectcontainer, respectively, are inserted into the tree. The JSON serialization of this document (with the domDoc method \fIasJSON\fR) is the same JSON information as the \fIdata\fR, preserving JSON datatypes, allowing non-unique member names of objects while preserving their order and the full range of JSON string values. JSON datatype handling is done with an additional property "sticking" at the doc and tree nodes. This property isn't contained in an XML serialization of the document. If you need to store the JSON data represented by a document, store the JSON serialization and parse it back from there. Apart from this JSON type information the returned doc command or handle is an ordinary DOM doc, which may be investigated or modified with the full range of the doc and node methods. Please note that the element node names and the text node values within the tree may be outside of what the appropriate XML productions allow. .IP "\fB-jsonroot \fR" If given makes the given element name the document element of the resulting doc. The parsed content of the JSON string will be the children of this document element node. .IP "\fB-jsonmaxnesting \fIinteger\fP\fR" This option only has effect if used together with the \fI-json\fR option. The current implementation uses a recursive descent JSON parser. In order to avoid using excess stack space, any JSON input that has more than a certain levels of nesting is considered invalid. The default maximum nesting is 2000. The option -jsonmaxnesting allows the user to adjust that. .IP "\fB--\fR" The option \fI--\fR marks the end of options. To give this option isn't strictly necessary even in the case of JSON parsing, for which valid data may start with a "-". If parsing json and if the second to last or last argument start with a "-" and isn't a known option name it will be treated as JSON data. .IP "\fB-keepEmpties\fR" If \fI-keepEmpties\fR is specified then text nodes which contain only whitespaces will be part of the resulting DOM tree. In default case (\fI-keepEmpties\fR not given) those empty text nodes are removed at parsing time. .IP "\fB-keepCDATA\fR" If \fI-keepCDATA\fR is specified then CDATA sections aren't added to the tree as text nodes (and, if necessary, combined with sibling text nodes into one text node) as without this option but are added as CDATA_SECTION_NODEs to the tree. Please note that the resulting tree isn't prepared for XPath selects or to be the source or the stylesheet of an XSLT transformation. If not combined with \fI-keepEmpties\fR only not whitespace only CDATA sections will be added to the resulting DOM tree. .IP "\fB-channel \fI\fP\fR" If \fI-channel \fR is specified, the input to be parsed is read from the specified channel. The encoding setting of the channel (via fconfigure -encoding) is respected, ie the data read from the channel are converted to UTF-8 according to the encoding settings before the data is parsed. .IP "\fB-baseurl \fI\fP\fR" If \fI-baseurl \fR is specified, the baseURI is used as the base URI of the document. External entities references in the document are resolved relative to this base URI. This base URI is also stored within the DOM tree. .IP "\fB-feedbackAfter \fI<#bytes>\fP\fR" If \fI-feedbackAfter <#bytes>\fR is specified, the Tcl command given by \&\fI-feedbackcmd\fR is evaluated at the first element start within the document (or an external entity) after the start of the document or external entity or the last such call after #bytes. For backward compatibility if no -feedbackcmd is given but there is a Tcl proc named ::dom::domParseFeedback this proc is used as -feedbackcmd. If there isn't such a proc and -feedbackAfter is used it is an error to not also use -feedbackcmd. If the called script raises error, then parsing will be aborted, the \fIdom parse\fR call returns error, with the script error msg as error msg. If the called script \fIreturn -code break\fR, the parsing will abort and the \fIdom parse\fR call will return the empty string. .IP "\fB-feedbackcmd \fI