1 /*---------------------------------------------------------------------------
2 |   Copyright (C) 1999  Jochen C. Loewer (loewerj@hotmail.com)
3 +----------------------------------------------------------------------------
4 |
5 |   $Id$
6 |
7 |
8 |   A DOM interface upon the expat XML parser for the C language
9 |   according to the W3C recommendation REC-DOM-Level-1-19981001
10 |
11 |
12 |   The contents of this file are subject to the Mozilla Public License
13 |   Version 1.1 (the "License"); you may not use this file except in
14 |   compliance with the License. You may obtain a copy of the License at
15 |   http://www.mozilla.org/MPL/
16 |
17 |   Software distributed under the License is distributed on an "AS IS"
18 |   basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
19 |   License for the specific language governing rights and limitations
20 |   under the License.
21 |
22 |   The Original Code is tDOM.
23 |
24 |   The Initial Developer of the Original Code is Jochen Loewer
25 |   Portions created by Jochen Loewer are Copyright (C) 1998, 1999
26 |   Jochen Loewer. All Rights Reserved.
27 |
28 |   Contributor(s):
29 |
30 |
31 |   written by Jochen Loewer
32 |   April 5, 1999
33 |
34 \--------------------------------------------------------------------------*/
35 
36 #ifndef __DOM_H__
37 #define __DOM_H__
38 
39 #include <tcl.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <ctype.h>
43 #include <bsdxml.h>
44 
45 /*
46  * tDOM provides it's own memory allocator which is optimized for
47  * low heap usage. It uses the native Tcl allocator underneath,
48  * though, but it is not very MT-friendly. Therefore, you might
49  * use the (normal) Tcl allocator with USE_NORMAL_ALLOCATOR
50  * defined during compile time. Actually, the symbols name is
51  * a misnomer. It should have benn called "USE_TCL_ALLOCATOR"
52  * but I did not want to break any backward compatibility.
53  */
54 
55 #ifndef USE_NORMAL_ALLOCATOR
56 # define MALLOC             malloc
57 # define FREE               free
58 # define REALLOC            realloc
59 # define tdomstrdup         strdup
60 #else
61 # define domAllocInit()
62 # define domAlloc           MALLOC
63 # define domFree            FREE
64 # if defined(TCL_MEM_DEBUG) || defined(NS_AOLSERVER)
65 #  define MALLOC            Tcl_Alloc
66 #  define FREE(a)           Tcl_Free((char*)(a))
67 #  define REALLOC           Tcl_Realloc
68 #  define tdomstrdup(s)     (char*)strcpy(MALLOC(strlen((s))+1),(char*)s)
69 # else
70 #  define MALLOC            malloc
71 #  define FREE              free
72 #  define REALLOC           realloc
73 #  define tdomstrdup        strdup
74 # endif /* TCL_MEM_DEBUG */
75 #endif /* USE_NORMAL_ALLOCATOR */
76 
77 #if defined(TCL_MEM_DEBUG) || defined(NS_AOLSERVER)
my_malloc(size_t size)78    static void* my_malloc(size_t size){return Tcl_Alloc(size);}
my_free(void * ptr)79    static void  my_free(void *ptr){Tcl_Free((char*)ptr);}
my_realloc(void * ptr,size_t size)80    static void* my_realloc(void *ptr,size_t size){return Tcl_Realloc(ptr,size);}
81    static XML_Memory_Handling_Suite memsuite = {
82        my_malloc, my_realloc, my_free
83    };
84 #  define MEM_SUITE &memsuite
85 #else
86 #  define MEM_SUITE NULL
87 #endif
88 
89 /*
90  * Beginning with 8.6, interp->errorLine isn't public visible anymore
91  * (TIP 330)
92  */
93 #if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 6)
94 # define Tcl_GetErrorLine(interp) (interp)->errorLine
95 #endif
96 
97 /*
98  * Starting with Tcl 8.2 the Tcl_Panic() is defined properly
99  * over the stubs table.
100  * Also, we have a proper Tcl_GetString() shortcut afterwards.
101  */
102 #if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 2)
103 # define Tcl_Panic panic
104 # define Tcl_GetString(a) Tcl_GetStringFromObj((a), NULL)
105 #endif
106 
107 #define domPanic(msg) Tcl_Panic((msg));
108 
109 /*
110  * If compiled against threaded Tcl core, we must take
111  * some extra care about process-wide globals and the
112  * way we name Tcl object accessor commands.
113  */
114 #ifndef TCL_THREADS
115   extern unsigned long domUniqueNodeNr;
116   extern unsigned long domUniqueDocNr;
117   extern Tcl_HashTable tdom_tagNames;
118   extern Tcl_HashTable tdom_attrNames;
119 # define TDomNotThreaded(x) x
120 # define TDomThreaded(x)
121 # define HASHTAB(doc,tab)   tab
122 # define NODE_NO(doc)       ++domUniqueNodeNr
123 # define DOC_NO(doc)        ++domUniqueDocNr
124 #else
125 # define TDomNotThreaded(x)
126 # define TDomThreaded(x)    x
127 # define HASHTAB(doc,tab)   (doc)->tab
128 # define NODE_NO(doc)       ((doc)->nodeCounter)++
129 # define DOC_NO(doc)        (unsigned long)(doc)
130 #endif /* TCL_THREADS */
131 
132 #define DOC_CMD(s,doc)      sprintf((s), "domDoc%p", (void *)(doc))
133 #define NODE_CMD(s,node)    sprintf((s), "domNode%p", (void *)(node))
134 #define XSLT_CMD(s,doc)     sprintf((s), "XSLTcmd%p", (void *)(doc))
135 
136 #define XML_NAMESPACE "http://www.w3.org/XML/1998/namespace"
137 #define XMLNS_NAMESPACE "http://www.w3.org/2000/xmlns"
138 
139 #define UTF8_1BYTE_CHAR(c) ( 0    == ((c) & 0x80))
140 #define UTF8_2BYTE_CHAR(c) ( 0xC0 == ((c) & 0xE0))
141 #define UTF8_3BYTE_CHAR(c) ( 0xE0 == ((c) & 0xF0))
142 #define UTF8_4BYTE_CHAR(c) ( 0xF0 == ((c) & 0xF8))
143 
144 #define UTF8_CHAR_LEN(c) \
145   UTF8_1BYTE_CHAR((c)) ? 1 : \
146    (UTF8_2BYTE_CHAR((c)) ? 2 : \
147      (UTF8_3BYTE_CHAR((c)) ? 3 : \
148        (UTF8_4BYTE_CHAR((c)) ? 4 : 0)))
149 
150 /* The following 2 defines are out of the expat code */
151 
152 /* A 2 byte UTF-8 representation splits the characters 11 bits
153 between the bottom 5 and 6 bits of the bytes.
154 We need 8 bits to index into pages, 3 bits to add to that index and
155 5 bits to generate the mask. */
156 #define UTF8_GET_NAMING2(pages, byte) \
157     (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \
158                       + ((((byte)[0]) & 3) << 1) \
159                       + ((((byte)[1]) >> 5) & 1)] \
160          & (1 << (((byte)[1]) & 0x1F)))
161 
162 /* A 3 byte UTF-8 representation splits the characters 16 bits
163 between the bottom 4, 6 and 6 bits of the bytes.
164 We need 8 bits to index into pages, 3 bits to add to that index and
165 5 bits to generate the mask. */
166 #define UTF8_GET_NAMING3(pages, byte) \
167   (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \
168                              + ((((byte)[1]) >> 2) & 0xF)] \
169                        << 3) \
170                       + ((((byte)[1]) & 3) << 1) \
171                       + ((((byte)[2]) >> 5) & 1)] \
172          & (1 << (((byte)[2]) & 0x1F)))
173 
174 #define UTF8_GET_NAMING_NMTOKEN(p, n) \
175   ((n) == 1 \
176   ? nameChar7Bit[(int)(*(p))] \
177   : ((n) == 2 \
178     ? UTF8_GET_NAMING2(namePages, (const unsigned char *)(p)) \
179     : ((n) == 3 \
180       ? UTF8_GET_NAMING3(namePages, (const unsigned char *)(p)) \
181       : 0)))
182 
183 #define UTF8_GET_NAMING_NCNMTOKEN(p, n) \
184   ((n) == 1 \
185   ? NCnameChar7Bit[(int)(*(p))] \
186   : ((n) == 2 \
187     ? UTF8_GET_NAMING2(namePages, (const unsigned char *)(p)) \
188     : ((n) == 3 \
189       ? UTF8_GET_NAMING3(namePages, (const unsigned char *)(p)) \
190       : 0)))
191 
192 #define UTF8_GET_NAME_START(p, n) \
193   ((n) == 1 \
194   ? nameStart7Bit[(int)(*(p))] \
195   : ((n) == 2 \
196     ? UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)(p)) \
197     : ((n) == 3 \
198       ? UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)(p)) \
199       : 0)))
200 
201 #define UTF8_GET_NCNAME_START(p, n) \
202   ((n) == 1 \
203   ? NCnameStart7Bit[(int)(*(p))] \
204   : ((n) == 2 \
205     ? UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)(p)) \
206     : ((n) == 3 \
207       ? UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)(p)) \
208       : 0)))
209 
210 #define UTF8_XMLCHAR3(p) \
211   (*(p) == 0xED  \
212    ? ((p)[1] < 0xA0 ? 1 : 0) \
213    : (*(p) == 0xEF \
214       ? ((p)[1] == 0xBF \
215          ? ((p)[2] == 0xBE || (p)[2] == 0xBF ? 0 : 1) \
216          : 1) \
217       : 1)) \
218 
219 /* This definition is lax in the sense, that it accepts every 4 byte
220  * utf-8 character beyond #xFFFF as valid, no matter, if Unicode has
221  * (so far) defined a character for that encoding point. Additionally,
222  * this define does not care about the discouraged characters beyond
223  * #xFFFF (but after all, they are only discouraged, not
224  * forbidden). */
225 #define UTF8_XMLCHAR(p, n) \
226   ((n) == 1 \
227   ? CharBit[(int)(*(p))] \
228   : ((n) == 2 \
229     ? 1 \
230     : ((n) == 3 \
231       ? (UTF8_XMLCHAR3(p)) \
232       : ((n) == 4 \
233         ? 1 : 0))))
234 
235 #include "../expat/nametab.h"
236 
237 static const unsigned char nameChar7Bit[] = {
238 /* 0x00 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239 /* 0x08 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240 /* 0x10 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241 /* 0x18 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242 /* 0x20 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243 /* 0x28 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
244 /* 0x30 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
245 /* 0x38 */    0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
246 /* 0x40 */    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
247 /* 0x48 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
248 /* 0x50 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
249 /* 0x58 */    0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
250 /* 0x60 */    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
251 /* 0x68 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
252 /* 0x70 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
253 /* 0x78 */    0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
254 };
255 
256 static const unsigned char NCnameChar7Bit[] = {
257 /* 0x00 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
258 /* 0x08 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
259 /* 0x10 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
260 /* 0x18 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261 /* 0x20 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
262 /* 0x28 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
263 /* 0x30 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
264 /* 0x38 */    0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265 /* 0x40 */    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
266 /* 0x48 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
267 /* 0x50 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
268 /* 0x58 */    0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
269 /* 0x60 */    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
270 /* 0x68 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
271 /* 0x70 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
272 /* 0x78 */    0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
273 };
274 
275 
276 static const unsigned char nameStart7Bit[] = {
277 /* 0x00 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
278 /* 0x08 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
279 /* 0x10 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
280 /* 0x18 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
281 /* 0x20 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
282 /* 0x28 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
283 /* 0x30 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284 /* 0x38 */    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
285 /* 0x40 */    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
286 /* 0x48 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
287 /* 0x50 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
288 /* 0x58 */    0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
289 /* 0x60 */    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
290 /* 0x68 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
291 /* 0x70 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
292 /* 0x78 */    0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
293 };
294 
295 
296 static const unsigned char NCnameStart7Bit[] = {
297 /* 0x00 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 /* 0x08 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299 /* 0x10 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300 /* 0x18 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301 /* 0x20 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302 /* 0x28 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303 /* 0x30 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
304 /* 0x38 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
305 /* 0x40 */    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
306 /* 0x48 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
307 /* 0x50 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
308 /* 0x58 */    0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
309 /* 0x60 */    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
310 /* 0x68 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
311 /* 0x70 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
312 /* 0x78 */    0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
313 };
314 
315 static const unsigned char CharBit[] = {
316 /* 0x00 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317 /* 0x08 */    0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
318 /* 0x10 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319 /* 0x18 */    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320 /* 0x20 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
321 /* 0x28 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
322 /* 0x30 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
323 /* 0x38 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
324 /* 0x40 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
325 /* 0x48 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
326 /* 0x50 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
327 /* 0x58 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
328 /* 0x60 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
329 /* 0x68 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
330 /* 0x70 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
331 /* 0x78 */    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
332 };
333 
334 
335 #define isNameStart(x)   UTF8_GET_NAME_START((x),UTF8_CHAR_LEN(*(x)))
336 #define isNCNameStart(x) UTF8_GET_NCNAME_START((x),UTF8_CHAR_LEN(*(x)))
337 #define isNameChar(x)    UTF8_GET_NAMING_NMTOKEN((x),UTF8_CHAR_LEN(*(x)))
338 #define isNCNameChar(x)  UTF8_GET_NAMING_NCNMTOKEN((x),UTF8_CHAR_LEN(*(x)))
339 
340 #define IS_XML_WHITESPACE(c)  ((c)==' ' || (c)=='\n' || (c)=='\r' || (c)=='\t')
341 
342 /*--------------------------------------------------------------------------
343 |   DOMString
344 |
345 \-------------------------------------------------------------------------*/
346 typedef char* domString;   /* should 16-bit unicode character !!*/
347 
348 
349 /*--------------------------------------------------------------------------
350 |   domNodeType
351 |
352 \-------------------------------------------------------------------------*/
353 #if defined(_AIX)
354 #    define    ELEMENT_NODE                 1
355 #    define    ATTRIBUTE_NODE               2
356 #    define    TEXT_NODE                    3
357 #    define    CDATA_SECTION_NODE           4
358 #    define    ENTITY_REFERENCE_NODE        5
359 #    define    ENTITY_NODE                  6
360 #    define    PROCESSING_INSTRUCTION_NODE  7
361 #    define    COMMENT_NODE                 8
362 #    define    DOCUMENT_NODE                9
363 #    define    DOCUMENT_TYPE_NODE           10
364 #    define    DOCUMENT_FRAGMENT_NODE       11
365 #    define    NOTATION_NODE                12
366 #    define    ALL_NODES                    100
367 
368 #    define    domNodeType                  int
369 
370 #else
371 
372 typedef enum {
373 
374     ELEMENT_NODE                = 1,
375     ATTRIBUTE_NODE              = 2,
376     TEXT_NODE                   = 3,
377     CDATA_SECTION_NODE          = 4,
378     ENTITY_REFERENCE_NODE       = 5,
379     ENTITY_NODE                 = 6,
380     PROCESSING_INSTRUCTION_NODE = 7,
381     COMMENT_NODE                = 8,
382     DOCUMENT_NODE               = 9,
383     DOCUMENT_TYPE_NODE          = 10,
384     DOCUMENT_FRAGMENT_NODE      = 11,
385     NOTATION_NODE               = 12,
386     ALL_NODES                   = 100
387 } domNodeType;
388 
389 #endif
390 
391 /*--------------------------------------------------------------------------
392 |   flags   -  indicating some internal features about nodes
393 |
394 \-------------------------------------------------------------------------*/
395 typedef unsigned int domNodeFlags;
396 
397 #define HAS_LINE_COLUMN           1
398 #define VISIBLE_IN_TCL            2
399 #define IS_DELETED                4
400 #define HAS_BASEURI               8
401 #define DISABLE_OUTPUT_ESCAPING  16
402 
403 typedef unsigned int domAttrFlags;
404 
405 #define IS_ID_ATTRIBUTE           1
406 #define IS_NS_NODE                2
407 
408 typedef unsigned int domDocFlags;
409 
410 #define OUTPUT_DEFAULT_INDENT     1
411 #define NEEDS_RENUMBERING         2
412 #define DONT_FREE                 4
413 #define IGNORE_XMLNS              8
414 #define DOCUMENT_CMD             16
415 #define VAR_TRACE                32
416 
417 /*--------------------------------------------------------------------------
418 |   a index to the namespace records
419 |
420 \-------------------------------------------------------------------------*/
421 typedef unsigned int domNameSpaceIndex;
422 
423 
424 
425 /*--------------------------------------------------------------------------
426 |   domException
427 |
428 \-------------------------------------------------------------------------*/
429 typedef enum {
430 
431     OK                          = 0,
432     INDEX_SIZE_ERR              = 1,
433     DOMSTRING_SIZE_ERR          = 2,
434     HIERARCHY_REQUEST_ERR       = 3,
435     WRONG_DOCUMENT_ERR          = 4,
436     INVALID_CHARACTER_ERR       = 5,
437     NO_DATA_ALLOWED_ERR         = 6,
438     NO_MODIFICATION_ALLOWED_ERR = 7,
439     NOT_FOUND_ERR               = 8,
440     NOT_SUPPORTED_ERR           = 9,
441     INUSE_ATTRIBUTE_ERR         = 10
442 
443 } domException;
444 
445 /*--------------------------------------------------------------------------
446 |   domDocInfo
447 |
448 \-------------------------------------------------------------------------*/
449 typedef struct domDocInfo {
450 
451     /* 'name' is always the name of the documentElement, no struct element
452        needed for this */
453     domString      publicId;
454     domString      systemId;
455     domString      internalSubset;
456     /* Currently missing, according to DOM 2: 'entities' and 'notations'. */
457     /* The following struct elements describes additional 'requested'
458        facets of the document, following the xslt rec, section 16 */
459     float          version;
460     char          *encoding;
461     int            omitXMLDeclaration;
462     int            standalone;
463     Tcl_HashTable *cdataSectionElements;
464     domString      method;
465     domString      mediaType;
466 
467 } domDocInfo;
468 
469 /*--------------------------------------------------------------------------
470 |   domDocument
471 |
472 \-------------------------------------------------------------------------*/
473 typedef struct domDocument {
474 
475     domNodeType       nodeType  : 8;
476     domDocFlags       nodeFlags : 8;
477     domNameSpaceIndex dummy     : 16;
478     unsigned long     documentNumber;
479     struct domNode   *documentElement;
480     struct domNode   *fragments;
481 #ifdef TCL_THREADS
482     struct domNode   *deletedNodes;
483 #endif
484     struct domNS    **namespaces;
485     int               nsptr;
486     int               nslen;
487     char            **prefixNSMappings; /* Stores doc global prefix ns
488                                            mappings for resolving of
489                                            prefixes in seletNodes expr */
490 #ifdef TCL_THREADS
491     unsigned int      nodeCounter;
492 #endif
493     struct domNode   *rootNode;
494     Tcl_HashTable    *ids;
495     Tcl_HashTable    *unparsedEntities;
496     Tcl_HashTable    *baseURIs;
497     Tcl_HashTable    *xpathCache;
498     char             *extResolver;
499     domDocInfo       *doctype;
500     TDomThreaded (
501         Tcl_HashTable tdom_tagNames;   /* Names of tags found in doc */
502         Tcl_HashTable tdom_attrNames;  /* Names of tag attributes */
503         unsigned int  refCount;        /* # of object commands attached */
504         struct _domlock *lock;          /* Lock for this document */
505     )
506 } domDocument;
507 
508 /*--------------------------------------------------------------------------
509 |  domLock
510 |
511 \-------------------------------------------------------------------------*/
512 
513 #ifdef TCL_THREADS
514 typedef struct _domlock {
515     domDocument* doc;           /* The DOM document to be locked */
516     int numrd;	                /* # of readers waiting for lock */
517     int numwr;                  /* # of writers waiting for lock */
518     int lrcnt;                  /* Lock ref count, > 0: # of shared
519                                  * readers, -1: exclusive writer */
520     Tcl_Mutex mutex;            /* Mutex for serializing access */
521     Tcl_Condition rcond;        /* Condition var for reader locks */
522     Tcl_Condition wcond;        /* Condition var for writer locks */
523     struct _domlock *next;       /* Next doc lock in global list */
524 } domlock;
525 
526 #define LOCK_READ  0
527 #define LOCK_WRITE 1
528 
529 #endif
530 
531 
532 /*--------------------------------------------------------------------------
533 |   namespace
534 |
535 \-------------------------------------------------------------------------*/
536 typedef struct domNS {
537 
538    char   *uri;
539    char   *prefix;
540    int     index;
541 
542 } domNS;
543 
544 
545 #define MAX_PREFIX_LEN   80
546 
547 /*---------------------------------------------------------------------------
548 |   type domActiveNS
549 |
550 \--------------------------------------------------------------------------*/
551 typedef struct _domActiveNS {
552 
553     int    depth;
554     domNS *namespace;
555 
556 } domActiveNS;
557 
558 
559 /*--------------------------------------------------------------------------
560 |   domLineColumn
561 |
562 \-------------------------------------------------------------------------*/
563 typedef struct domLineColumn {
564 
565     int   line;
566     int   column;
567 
568 } domLineColumn;
569 
570 
571 /*--------------------------------------------------------------------------
572 |   domNode
573 |
574 \-------------------------------------------------------------------------*/
575 typedef struct domNode {
576 
577     domNodeType         nodeType  : 8;
578     domNodeFlags        nodeFlags : 8;
579 #ifdef TDOM_LESS_NS
580     domNameSpaceIndex   namespace : 8;
581     unsigned int        info      : 8;
582 #else
583     unsigned int        dummy     : 8;
584     unsigned int        info      : 8;
585 #endif
586     unsigned int        nodeNumber;
587     domDocument        *ownerDocument;
588     struct domNode     *parentNode;
589     struct domNode     *previousSibling;
590     struct domNode     *nextSibling;
591 
592     domString           nodeName;  /* now the element node specific fields */
593 #ifndef TDOM_LESS_NS
594     domNameSpaceIndex   namespace;
595 #endif
596     struct domNode     *firstChild;
597     struct domNode     *lastChild;
598     struct domAttrNode *firstAttr;
599 
600 } domNode;
601 
602 /*--------------------------------------------------------------------------
603 |   domDeleteInfo
604 |
605 \-------------------------------------------------------------------------*/
606 
607 typedef struct domDeleteInfo {
608     domDocument * document;
609     domNode     * node;
610     Tcl_Interp  * interp;
611     char        * traceVarName;
612 } domDeleteInfo;
613 
614 
615 /*--------------------------------------------------------------------------
616 |   domTextNode
617 |
618 \-------------------------------------------------------------------------*/
619 typedef struct domTextNode {
620 
621     domNodeType         nodeType  : 8;
622     domNodeFlags        nodeFlags : 8;
623 #ifdef TDOM_LESS_NS
624     domNameSpaceIndex   namespace : 8;
625     unsigned int        info      : 8;
626 #else
627     unsigned int        dummy     : 8;
628     unsigned int        info      : 8;
629 #endif
630     unsigned int        nodeNumber;
631     domDocument        *ownerDocument;
632     struct domNode     *parentNode;
633     struct domNode     *previousSibling;
634     struct domNode     *nextSibling;
635 
636     domString           nodeValue;   /* now the text node specific fields */
637     int                 valueLength;
638 
639 } domTextNode;
640 
641 
642 /*--------------------------------------------------------------------------
643 |   domProcessingInstructionNode
644 |
645 \-------------------------------------------------------------------------*/
646 typedef struct domProcessingInstructionNode {
647 
648     domNodeType         nodeType  : 8;
649     domNodeFlags        nodeFlags : 8;
650 #ifdef TDOM_LESS_NS
651     domNameSpaceIndex   namespace : 8;
652     unsigned int        info      : 8;
653 #else
654     unsigned int        dummy     : 8;
655     unsigned int        info      : 8;
656 #endif
657     unsigned int        nodeNumber;
658     domDocument        *ownerDocument;
659     struct domNode     *parentNode;
660     struct domNode     *previousSibling;
661     struct domNode     *nextSibling;
662 
663     domString           targetValue;   /* now the pi specific fields */
664     int                 targetLength;
665 #ifndef TDOM_LESS_NS
666     domNameSpaceIndex   namespace;
667 #endif
668     domString           dataValue;
669     int                 dataLength;
670 
671 } domProcessingInstructionNode;
672 
673 
674 /*--------------------------------------------------------------------------
675 |   domAttrNode
676 |
677 \-------------------------------------------------------------------------*/
678 typedef struct domAttrNode {
679 
680     domNodeType         nodeType  : 8;
681     domAttrFlags        nodeFlags : 8;
682 #ifdef TDOM_LESS_NS
683     domNameSpaceIndex   namespace : 8;
684     unsigned int        info      : 8;
685 #else
686     unsigned int        dummy     : 8;
687     unsigned int        info      : 8;
688     domNameSpaceIndex   namespace;
689 #endif
690     domString           nodeName;
691     domString           nodeValue;
692     int                 valueLength;
693     struct domNode     *parentNode;
694     struct domAttrNode *nextSibling;
695 
696 } domAttrNode;
697 
698 /*--------------------------------------------------------------------------
699 |   domAddCallback
700 |
701 \-------------------------------------------------------------------------*/
702 typedef int  (*domAddCallback)  (domNode * node, void * clientData);
703 typedef void (*domFreeCallback) (domNode * node, void * clientData);
704 
705 /*--------------------------------------------------------------------------
706 |   Function prototypes
707 |
708 \-------------------------------------------------------------------------*/
709 const char *   domException2String (domException exception);
710 
711 
712 void           domModuleInitialize (void);
713 domDocument *  domCreateDoc (const char *baseURI, int storeLineColumn);
714 domDocument *  domCreateDocument (const char *uri,
715                                   char *documentElementTagName);
716 void           domSetDocumentElement (domDocument *doc);
717 
718 domDocument *  domReadDocument   (XML_Parser parser,
719                                   char *xml,
720                                   int   length,
721                                   int   ignoreWhiteSpaces,
722                                   int   keepCDATA,
723                                   int   storeLineColumn,
724                                   int   ignoreXMLNS,
725                                   int   feedbackAfter,
726                                   Tcl_Obj *feedbackCmd,
727                                   Tcl_Channel channel,
728                                   const char *baseurl,
729                                   Tcl_Obj *extResolver,
730                                   int   useForeignDTD,
731                                   int   paramEntityParsing,
732                                   Tcl_Interp *interp,
733                                   int  *status);
734 
735 void           domFreeDocument   (domDocument *doc,
736                                   domFreeCallback freeCB,
737                                   void * clientData);
738 
739 void           domFreeNode       (domNode *node,
740                                   domFreeCallback freeCB,
741                                   void *clientData,
742                                   int dontfree);
743 
744 domTextNode *  domNewTextNode    (domDocument *doc,
745                                   const char  *value,
746                                   int          length,
747                                   domNodeType  nodeType);
748 
749 domNode *      domNewElementNode (domDocument *doc,
750                                   const char  *tagName);
751 
752 domNode *      domNewElementNodeNS (domDocument *doc,
753                                     const char  *tagName,
754                                     const char  *uri);
755 
756 domProcessingInstructionNode * domNewProcessingInstructionNode (
757                                   domDocument *doc,
758                                   const char  *targetValue,
759                                   int          targetLength,
760                                   const char  *dataValue,
761                                   int          dataLength);
762 
763 domAttrNode *  domSetAttribute (domNode *node, const char *attributeName,
764                                                const char *attributeValue);
765 
766 domAttrNode *  domSetAttributeNS (domNode *node, const char *attributeName,
767                                                  const char *attributeValue,
768                                                  const char *uri,
769                                                  int   createNSIfNeeded);
770 domAttrNode *  domGetAttributeNodeNS (domNode *node, const char *uri,
771                                                      const char *localname);
772 
773 int            domRemoveAttribute (domNode *node, const char *attributeName);
774 int            domRemoveAttributeNS (domNode *node, const char *uri,
775                                      const char *localName);
776 domNode *      domPreviousSibling (domNode *attr);
777 domException   domDeleteNode   (domNode *node, domFreeCallback freeCB, void *clientData);
778 domException   domRemoveChild  (domNode *node, domNode *childToRemove);
779 domException   domAppendChild  (domNode *node, domNode *childToAppend);
780 domException   domInsertBefore (domNode *node, domNode *childToInsert, domNode *refChild);
781 domException   domReplaceChild (domNode *node, domNode *newChild, domNode *oldChild);
782 domException   domSetNodeValue (domNode *node, const char *nodeValue,
783                                 int valueLen);
784 domNode *      domCloneNode (domNode *node, int deep);
785 
786 domTextNode *  domAppendNewTextNode (domNode *parent, char *value, int length, domNodeType nodeType, int disableOutputEscaping);
787 domNode *      domAppendNewElementNode (domNode *parent, const char *tagName,
788                                         const char *uri);
789 domNode *      domAppendLiteralNode (domNode *parent, domNode *node);
790 domNS *        domAddNSToNode (domNode *node, domNS *nsToAdd);
791 const char *   domNamespacePrefix (domNode *node);
792 const char *   domNamespaceURI    (domNode *node);
793 const char *   domGetLocalName    (const char *nodeName);
794 int            domSplitQName (const char *name, char *prefix,
795                               const char **localName);
796 domNS *        domLookupNamespace (domDocument *doc, const char *prefix,
797                                    const char *namespaceURI);
798 domNS *        domLookupPrefix  (domNode *node, const char *prefix);
799 int            domIsNamespaceInScope (domActiveNS *NSstack, int NSstackPos,
800                                       const char *prefix, const char *namespaceURI);
801 const char *   domLookupPrefixWithMappings (domNode *node, const char *prefix,
802                                             char **prefixMappings);
803 domNS *        domLookupURI     (domNode *node, char *uri);
804 domNS *        domGetNamespaceByIndex (domDocument *doc, int nsIndex);
805 domNS *        domNewNamespace (domDocument *doc, const char *prefix,
806                                 const char *namespaceURI);
807 int            domGetLineColumn (domNode *node, int *line, int *column);
808 
809 int            domXPointerChild (domNode * node, int all, int instance, domNodeType type,
810                                  char *element, char *attrName, char *attrValue,
811                                  int attrLen, domAddCallback addCallback,
812                                  void * clientData);
813 
814 int            domXPointerDescendant (domNode * node, int all, int instance,
815                                       int * i, domNodeType type, char *element,
816                                       char *attrName, char *attrValue, int attrLen,
817                                       domAddCallback addCallback, void * clientData);
818 
819 int            domXPointerAncestor (domNode * node, int all, int instance,
820                                     int * i, domNodeType type, char *element,
821                                     char *attrName, char *attrValue, int attrLen,
822                                     domAddCallback addCallback, void * clientData);
823 
824 int            domXPointerXSibling (domNode * node, int forward_mode, int all, int instance,
825                                     domNodeType type, char *element, char *attrName,
826                                     char *attrValue, int attrLen,
827                                     domAddCallback addCallback, void * clientData);
828 
829 const char *   findBaseURI (domNode *node);
830 
831 void           tcldom_tolower (const char *str, char *str_out, int  len);
832 int            domIsNAME (const char *name);
833 int            domIsPINAME (const char *name);
834 int            domIsQNAME (const char *name);
835 int            domIsNCNAME (const char *name);
836 int            domIsChar (const char *str);
837 int            domIsBMPChar (const char *str);
838 int            domIsComment (const char *str);
839 int            domIsCDATA (const char *str);
840 int            domIsPIValue (const char *str);
841 void           domCopyTo (domNode *node, domNode *parent, int copyNS);
842 void           domCopyNS (domNode *from, domNode *to);
843 domAttrNode *  domCreateXMLNamespaceNode (domNode *parent);
844 void           domRenumberTree (domNode *node);
845 int            domPrecedes (domNode *node, domNode *other);
846 void           domNormalize (domNode *node, int forXPath,
847                              domFreeCallback freeCB, void *clientData);
848 domException   domAppendData (domTextNode *node, char *value, int length,
849                               int disableOutputEscaping);
850 
851 #ifdef TCL_THREADS
852 void           domLocksLock(domlock *dl, int how);
853 void           domLocksUnlock(domlock *dl);
854 void           domLocksAttach(domDocument *doc);
855 void           domLocksDetach(domDocument *doc);
856 void           domLocksFinalize(ClientData dummy);
857 #endif
858 
859 /*---------------------------------------------------------------------------
860 |   coercion routines for calling from C++
861 |
862 \--------------------------------------------------------------------------*/
863 domAttrNode                  * coerceToAttrNode( domNode *n );
864 domTextNode                  * coerceToTextNode( domNode *n );
865 domProcessingInstructionNode * coerceToProcessingInstructionNode( domNode *n );
866 
867 
868 #endif
869 
870