blob: 21655374794b32002fb4d12df14927a5467e9e6c [file] [log] [blame]
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001/*
2 * valid.c : part of the code use to do the DTD handling and the validity
3 * checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel.Veillard@w3.org
8 */
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include "valid.h"
14#include "parser.h"
15
16/****************************************************************
17 * *
18 * Util functions for data allocation/deallocation *
19 * *
20 ****************************************************************/
21
22/**
23 * xmlNewElementContent:
24 * @name: the subelement name or NULL
25 * @type: the type of element content decl
26 *
27 * Allocate an element content structure.
28 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000029 * Returns NULL if not, othervise the new element content structure
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000030 */
31xmlElementContentPtr
32xmlNewElementContent(CHAR *name, int type) {
33 xmlElementContentPtr ret;
34
35 switch(type) {
36 case XML_ELEMENT_CONTENT_ELEMENT:
37 if (name == NULL) {
38 fprintf(stderr, "xmlNewElementContent : name == NULL !\n");
39 }
40 break;
41 case XML_ELEMENT_CONTENT_PCDATA:
42 case XML_ELEMENT_CONTENT_SEQ:
43 case XML_ELEMENT_CONTENT_OR:
44 if (name != NULL) {
45 fprintf(stderr, "xmlNewElementContent : name != NULL !\n");
46 }
47 break;
48 default:
49 fprintf(stderr, "xmlNewElementContent: unknown type %d\n", type);
50 exit(1);
51 }
52 ret = (xmlElementContentPtr) malloc(sizeof(xmlElementContent));
53 if (ret == NULL) {
54 fprintf(stderr, "xmlNewElementContent : out of memory!\n");
55 return(NULL);
56 }
57 ret->type = type;
58 ret->ocur = XML_ELEMENT_CONTENT_ONCE;
Daniel Veillard3b9def11999-01-31 22:15:06 +000059 if (name != NULL)
60 ret->name = xmlStrdup(name);
61 else
62 ret->name = NULL;
Daniel Veillard1e346af1999-02-22 10:33:01 +000063 ret->c1 = ret->c2 = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000064 return(ret);
65}
66
67/**
Daniel Veillard3b9def11999-01-31 22:15:06 +000068 * xmlCopyElementContent:
69 * @content: An element content pointer.
70 *
71 * Build a copy of an element content description.
72 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000073 * Returns the new xmlElementContentPtr or NULL in case of error.
Daniel Veillard3b9def11999-01-31 22:15:06 +000074 */
75xmlElementContentPtr
Daniel Veillard1e346af1999-02-22 10:33:01 +000076xmlCopyElementContent(xmlElementContentPtr cur) {
77 xmlElementContentPtr ret;
78
79 if (cur == NULL) return(NULL);
80 ret = xmlNewElementContent((CHAR *) cur->name, cur->type);
81 if (cur->c1 != NULL) cur->c1 = xmlCopyElementContent(cur->c1);
82 if (cur->c2 != NULL) cur->c2 = xmlCopyElementContent(cur->c2);
83 return(ret);
Daniel Veillard3b9def11999-01-31 22:15:06 +000084}
85
86/**
Daniel Veillard1899e851999-02-01 12:18:54 +000087 * xmlFreeElementContent:
88 * @cur: the element content tree to free
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000089 *
90 * Free an element content structure. This is a recursive call !
91 */
92void
93xmlFreeElementContent(xmlElementContentPtr cur) {
Daniel Veillard1e346af1999-02-22 10:33:01 +000094 if (cur == NULL) return;
95 if (cur->c1 != NULL) xmlFreeElementContent(cur->c1);
96 if (cur->c2 != NULL) xmlFreeElementContent(cur->c2);
97 if (cur->name != NULL) free((CHAR *) cur->name);
98 memset(cur, -1, sizeof(xmlElementContent));
99 free(cur);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000100}
101
Daniel Veillard1899e851999-02-01 12:18:54 +0000102/**
103 * xmlDumpElementContent:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000104 * @buf: An XML buffer
Daniel Veillard1899e851999-02-01 12:18:54 +0000105 * @content: An element table
106 * @glob: 1 if one must print the englobing parenthesis, 0 otherwise
107 *
108 * This will dump the content of the element table as an XML DTD definition
Daniel Veillard1899e851999-02-01 12:18:54 +0000109 */
110void
Daniel Veillard5099ae81999-04-21 20:12:07 +0000111xmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content, int glob) {
Daniel Veillard1899e851999-02-01 12:18:54 +0000112 if (content == NULL) return;
113
Daniel Veillard5099ae81999-04-21 20:12:07 +0000114 if (glob) xmlBufferWriteChar(buf, "(");
Daniel Veillard1899e851999-02-01 12:18:54 +0000115 switch (content->type) {
116 case XML_ELEMENT_CONTENT_PCDATA:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000117 xmlBufferWriteChar(buf, "#PCDATA");
Daniel Veillard1899e851999-02-01 12:18:54 +0000118 break;
119 case XML_ELEMENT_CONTENT_ELEMENT:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000120 xmlBufferWriteCHAR(buf, content->name);
Daniel Veillard1899e851999-02-01 12:18:54 +0000121 break;
122 case XML_ELEMENT_CONTENT_SEQ:
123 if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
124 (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
Daniel Veillard5099ae81999-04-21 20:12:07 +0000125 xmlDumpElementContent(buf, content->c1, 1);
Daniel Veillard1899e851999-02-01 12:18:54 +0000126 else
Daniel Veillard5099ae81999-04-21 20:12:07 +0000127 xmlDumpElementContent(buf, content->c1, 0);
128 xmlBufferWriteChar(buf, " , ");
Daniel Veillard1899e851999-02-01 12:18:54 +0000129 if (content->c2->type == XML_ELEMENT_CONTENT_OR)
Daniel Veillard5099ae81999-04-21 20:12:07 +0000130 xmlDumpElementContent(buf, content->c2, 1);
Daniel Veillard1899e851999-02-01 12:18:54 +0000131 else
Daniel Veillard5099ae81999-04-21 20:12:07 +0000132 xmlDumpElementContent(buf, content->c2, 0);
Daniel Veillard1899e851999-02-01 12:18:54 +0000133 break;
134 case XML_ELEMENT_CONTENT_OR:
135 if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
136 (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
Daniel Veillard5099ae81999-04-21 20:12:07 +0000137 xmlDumpElementContent(buf, content->c1, 1);
Daniel Veillard1899e851999-02-01 12:18:54 +0000138 else
Daniel Veillard5099ae81999-04-21 20:12:07 +0000139 xmlDumpElementContent(buf, content->c1, 0);
140 xmlBufferWriteChar(buf, " | ");
Daniel Veillard1899e851999-02-01 12:18:54 +0000141 if (content->c2->type == XML_ELEMENT_CONTENT_SEQ)
Daniel Veillard5099ae81999-04-21 20:12:07 +0000142 xmlDumpElementContent(buf, content->c2, 1);
Daniel Veillard1899e851999-02-01 12:18:54 +0000143 else
Daniel Veillard5099ae81999-04-21 20:12:07 +0000144 xmlDumpElementContent(buf, content->c2, 0);
Daniel Veillard1899e851999-02-01 12:18:54 +0000145 break;
146 default:
147 fprintf(stderr, "xmlDumpElementContent: unknown type %d\n",
148 content->type);
149 }
150 if (glob)
Daniel Veillard5099ae81999-04-21 20:12:07 +0000151 xmlBufferWriteChar(buf, ")");
Daniel Veillard1899e851999-02-01 12:18:54 +0000152 switch (content->ocur) {
153 case XML_ELEMENT_CONTENT_ONCE:
154 break;
155 case XML_ELEMENT_CONTENT_OPT:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000156 xmlBufferWriteChar(buf, "?");
Daniel Veillard1899e851999-02-01 12:18:54 +0000157 break;
158 case XML_ELEMENT_CONTENT_MULT:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000159 xmlBufferWriteChar(buf, "*");
Daniel Veillard1899e851999-02-01 12:18:54 +0000160 break;
161 case XML_ELEMENT_CONTENT_PLUS:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000162 xmlBufferWriteChar(buf, "+");
Daniel Veillard1899e851999-02-01 12:18:54 +0000163 break;
164 }
165}
166
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000167/****************************************************************
168 * *
169 * Registration of DTD declarations *
170 * *
171 ****************************************************************/
172
Daniel Veillard3b9def11999-01-31 22:15:06 +0000173/**
174 * xmlCreateElementTable:
175 *
176 * create and initialize an empty element hash table.
177 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000178 * Returns the xmlElementTablePtr just created or NULL in case of error.
Daniel Veillard3b9def11999-01-31 22:15:06 +0000179 */
180xmlElementTablePtr
181xmlCreateElementTable(void) {
182 xmlElementTablePtr ret;
183
184 ret = (xmlElementTablePtr)
185 malloc(sizeof(xmlElementTable));
186 if (ret == NULL) {
187 fprintf(stderr, "xmlCreateElementTable : malloc(%d) failed\n",
188 sizeof(xmlElementTable));
189 return(NULL);
190 }
Daniel Veillard1e346af1999-02-22 10:33:01 +0000191 ret->max_elements = XML_MIN_ELEMENT_TABLE;
Daniel Veillard3b9def11999-01-31 22:15:06 +0000192 ret->nb_elements = 0;
193 ret->table = (xmlElementPtr )
194 malloc(ret->max_elements * sizeof(xmlElement));
195 if (ret == NULL) {
196 fprintf(stderr, "xmlCreateElementTable : malloc(%d) failed\n",
197 ret->max_elements * sizeof(xmlElement));
198 free(ret);
199 return(NULL);
200 }
201 return(ret);
202}
203
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000204
205/**
206 * xmlAddElementDecl:
Daniel Veillard1e346af1999-02-22 10:33:01 +0000207 * @dtd: pointer to the DTD
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000208 * @name: the entity name
Daniel Veillard1e346af1999-02-22 10:33:01 +0000209 * @type: the element type
210 * @content: the element content tree or NULL
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000211 *
212 * Register a new element declaration
213 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000214 * Returns NULL if not, othervise the entity
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000215 */
216xmlElementPtr
Daniel Veillard517752b1999-04-05 12:20:10 +0000217xmlAddElementDecl(xmlDtdPtr dtd, const CHAR *name, int type,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000218 xmlElementContentPtr content) {
Daniel Veillard3b9def11999-01-31 22:15:06 +0000219 xmlElementPtr ret, cur;
220 xmlElementTablePtr table;
221 int i;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000222
223 if (dtd == NULL) {
224 fprintf(stderr, "xmlAddElementDecl: dtd == NULL\n");
225 return(NULL);
226 }
227 if (name == NULL) {
228 fprintf(stderr, "xmlAddElementDecl: name == NULL\n");
229 return(NULL);
230 }
231 switch (type) {
232 case XML_ELEMENT_TYPE_EMPTY:
233 if (content != NULL) {
234 fprintf(stderr,
235 "xmlAddElementDecl: content != NULL for EMPTY\n");
236 return(NULL);
237 }
238 break;
239 case XML_ELEMENT_TYPE_ANY:
240 if (content != NULL) {
241 fprintf(stderr,
242 "xmlAddElementDecl: content != NULL for ANY\n");
243 return(NULL);
244 }
245 break;
246 case XML_ELEMENT_TYPE_MIXED:
247 if (content == NULL) {
248 fprintf(stderr,
249 "xmlAddElementDecl: content == NULL for MIXED\n");
250 return(NULL);
251 }
252 break;
253 case XML_ELEMENT_TYPE_ELEMENT:
254 if (content == NULL) {
255 fprintf(stderr,
256 "xmlAddElementDecl: content == NULL for ELEMENT\n");
257 return(NULL);
258 }
259 break;
260 default:
261 fprintf(stderr, "xmlAddElementDecl: unknown type %d\n", type);
262 return(NULL);
263 }
264
265 /*
Daniel Veillard3b9def11999-01-31 22:15:06 +0000266 * Create the Element table if needed.
267 */
268 table = dtd->elements;
269 if (table == NULL)
270 table = dtd->elements = xmlCreateElementTable();
271 if (table == NULL) {
272 fprintf(stderr, "xmlAddElementDecl: Table creation failed!\n");
273 return(NULL);
274 }
275
276 /*
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000277 * Validity Check:
278 * Search the DTD for previous declarations of the ELEMENT
279 */
Daniel Veillard3b9def11999-01-31 22:15:06 +0000280 for (i = 0;i < table->nb_elements;i++) {
281 cur = &table->table[i];
282 if (!xmlStrcmp(cur->name, name)) {
283 /*
284 * The element is already defined in this Dtd.
285 */
286 fprintf(stderr,
287 "xmlAddElementDecl: %s already defined\n", name);
288 return(NULL);
289 }
290 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000291
292 /*
Daniel Veillard3b9def11999-01-31 22:15:06 +0000293 * Grow the table, if needed.
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000294 */
Daniel Veillard3b9def11999-01-31 22:15:06 +0000295 if (table->nb_elements >= table->max_elements) {
296 /*
297 * need more elements.
298 */
299 table->max_elements *= 2;
300 table->table = (xmlElementPtr)
301 realloc(table->table, table->max_elements * sizeof(xmlElement));
302 if (table->table) {
303 fprintf(stderr, "xmlAddElementDecl: out of memory\n");
304 return(NULL);
305 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000306 }
Daniel Veillard3b9def11999-01-31 22:15:06 +0000307 ret = &table->table[table->nb_elements];
308
309 /*
310 * fill the structure.
311 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000312 ret->type = type;
313 ret->name = xmlStrdup(name);
314 ret->content = content;
Daniel Veillard3b9def11999-01-31 22:15:06 +0000315 table->nb_elements++;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000316
317 return(ret);
318}
319
Daniel Veillard3b9def11999-01-31 22:15:06 +0000320/**
321 * xmlFreeElement:
322 * @elem: An element
323 *
324 * Deallocate the memory used by an element definition
325 */
326void
327xmlFreeElement(xmlElementPtr elem) {
328 if (elem == NULL) return;
329 xmlFreeElementContent(elem->content);
330 if (elem->name != NULL)
331 free((CHAR *) elem->name);
332 memset(elem, -1, sizeof(xmlElement));
Daniel Veillard3b9def11999-01-31 22:15:06 +0000333}
334
335/**
336 * xmlFreeElementTable:
337 * @table: An element table
338 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000339 * Deallocate the memory used by an element hash table.
Daniel Veillard3b9def11999-01-31 22:15:06 +0000340 */
341void
342xmlFreeElementTable(xmlElementTablePtr table) {
343 int i;
344
345 if (table == NULL) return;
346
347 for (i = 0;i < table->nb_elements;i++) {
348 xmlFreeElement(&table->table[i]);
349 }
350 free(table->table);
351 free(table);
352}
353
354/**
355 * xmlCopyElementTable:
356 * @table: An element table
357 *
358 * Build a copy of an element table.
359 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000360 * Returns the new xmlElementTablePtr or NULL in case of error.
Daniel Veillard3b9def11999-01-31 22:15:06 +0000361 */
362xmlElementTablePtr
363xmlCopyElementTable(xmlElementTablePtr table) {
364 xmlElementTablePtr ret;
365 xmlElementPtr cur, ent;
366 int i;
367
368 ret = (xmlElementTablePtr) malloc(sizeof(xmlElementTable));
369 if (ret == NULL) {
370 fprintf(stderr, "xmlCopyElementTable: out of memory !\n");
371 return(NULL);
372 }
373 ret->table = (xmlElementPtr) malloc(table->max_elements *
374 sizeof(xmlElement));
375 if (ret->table == NULL) {
376 fprintf(stderr, "xmlCopyElementTable: out of memory !\n");
377 free(ret);
378 return(NULL);
379 }
380 ret->max_elements = table->max_elements;
381 ret->nb_elements = table->nb_elements;
382 for (i = 0;i < ret->nb_elements;i++) {
383 cur = &ret->table[i];
384 ent = &table->table[i];
385 cur->type = ent->type;
386 if (ent->name != NULL)
387 cur->name = xmlStrdup(ent->name);
388 else
389 cur->name = NULL;
390 cur->content = xmlCopyElementContent(ent->content);
391 }
392 return(ret);
393}
394
395/**
396 * xmlDumpElementTable:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000397 * @buf: the XML buffer output
Daniel Veillard3b9def11999-01-31 22:15:06 +0000398 * @table: An element table
399 *
400 * This will dump the content of the element table as an XML DTD definition
Daniel Veillard3b9def11999-01-31 22:15:06 +0000401 */
402void
Daniel Veillard5099ae81999-04-21 20:12:07 +0000403xmlDumpElementTable(xmlBufferPtr buf, xmlElementTablePtr table) {
Daniel Veillard3b9def11999-01-31 22:15:06 +0000404 int i;
405 xmlElementPtr cur;
406
407 if (table == NULL) return;
408
409 for (i = 0;i < table->nb_elements;i++) {
410 cur = &table->table[i];
411 switch (cur->type) {
412 case XML_ELEMENT_TYPE_EMPTY:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000413 xmlBufferWriteChar(buf, "<!ELEMENT ");
414 xmlBufferWriteCHAR(buf, cur->name);
415 xmlBufferWriteChar(buf, " EMPTY>\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000416 break;
417 case XML_ELEMENT_TYPE_ANY:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000418 xmlBufferWriteChar(buf, "<!ELEMENT ");
419 xmlBufferWriteCHAR(buf, cur->name);
420 xmlBufferWriteChar(buf, " ANY>\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000421 break;
422 case XML_ELEMENT_TYPE_MIXED:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000423 xmlBufferWriteChar(buf, "<!ELEMENT ");
424 xmlBufferWriteCHAR(buf, cur->name);
425 xmlBufferWriteChar(buf, " ");
426 xmlDumpElementContent(buf, cur->content, 1);
427 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000428 break;
429 case XML_ELEMENT_TYPE_ELEMENT:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000430 xmlBufferWriteChar(buf, "<!ELEMENT ");
431 xmlBufferWriteCHAR(buf, cur->name);
432 xmlBufferWriteChar(buf, " ");
433 xmlDumpElementContent(buf, cur->content, 1);
434 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000435 break;
436 default:
437 fprintf(stderr,
438 "xmlDumpElementTable: internal: unknown type %d\n",
439 cur->type);
440 }
441 }
442}
Daniel Veillard1e346af1999-02-22 10:33:01 +0000443
444/**
445 * xmlCreateEnumeration:
446 * @name: the enumeration name or NULL
447 *
448 * create and initialize an enumeration attribute node.
449 *
450 * Returns the xmlEnumerationPtr just created or NULL in case
451 * of error.
452 */
453xmlEnumerationPtr
454xmlCreateEnumeration(CHAR *name) {
455 xmlEnumerationPtr ret;
456
457 ret = (xmlEnumerationPtr) malloc(sizeof(xmlEnumeration));
458 if (ret == NULL) {
459 fprintf(stderr, "xmlCreateEnumeration : malloc(%d) failed\n",
460 sizeof(xmlEnumeration));
461 return(NULL);
462 }
463
464 if (name != NULL)
465 ret->name = xmlStrdup(name);
466 else
467 ret->name = NULL;
468 ret->next = NULL;
469 return(ret);
470}
471
472/**
473 * xmlFreeEnumeration:
474 * @cur: the tree to free.
475 *
476 * free an enumeration attribute node (recursive).
477 */
478void
479xmlFreeEnumeration(xmlEnumerationPtr cur) {
480 if (cur == NULL) return;
481
482 if (cur->next != NULL) xmlFreeEnumeration(cur->next);
483
484 if (cur->name != NULL) free((CHAR *) cur->name);
485 memset(cur, -1, sizeof(xmlEnumeration));
486 free(cur);
487}
488
489/**
490 * xmlCopyEnumeration:
491 * @cur: the tree to copy.
492 *
493 * Copy an enumeration attribute node (recursive).
494 *
495 * Returns the xmlEnumerationPtr just created or NULL in case
496 * of error.
497 */
498xmlEnumerationPtr
499xmlCopyEnumeration(xmlEnumerationPtr cur) {
500 xmlEnumerationPtr ret;
501
502 if (cur == NULL) return(NULL);
503 ret = xmlCreateEnumeration((CHAR *) cur->name);
504
505 if (cur->next != NULL) ret->next = xmlCopyEnumeration(cur->next);
506 else ret->next = NULL;
507
508 return(ret);
509}
510
511/**
512 * xmlCreateAttributeTable:
513 *
514 * create and initialize an empty attribute hash table.
515 *
516 * Returns the xmlAttributeTablePtr just created or NULL in case
517 * of error.
518 */
519xmlAttributeTablePtr
520xmlCreateAttributeTable(void) {
521 xmlAttributeTablePtr ret;
522
523 ret = (xmlAttributeTablePtr)
524 malloc(sizeof(xmlAttributeTable));
525 if (ret == NULL) {
526 fprintf(stderr, "xmlCreateAttributeTable : malloc(%d) failed\n",
527 sizeof(xmlAttributeTable));
528 return(NULL);
529 }
530 ret->max_attributes = XML_MIN_ATTRIBUTE_TABLE;
531 ret->nb_attributes = 0;
532 ret->table = (xmlAttributePtr )
533 malloc(ret->max_attributes * sizeof(xmlAttribute));
534 if (ret == NULL) {
535 fprintf(stderr, "xmlCreateAttributeTable : malloc(%d) failed\n",
536 ret->max_attributes * sizeof(xmlAttribute));
537 free(ret);
538 return(NULL);
539 }
540 return(ret);
541}
542
543
544/**
545 * xmlAddAttributeDecl:
546 * @dtd: pointer to the DTD
547 * @elem: the element name
548 * @name: the attribute name
549 * @type: the attribute type
550 * @def: the attribute default type
551 * @defaultValue: the attribute default value
552 * @tree: if it's an enumeration, the associated list
553 *
554 * Register a new attribute declaration
555 *
556 * Returns NULL if not, othervise the entity
557 */
558xmlAttributePtr
Daniel Veillard517752b1999-04-05 12:20:10 +0000559xmlAddAttributeDecl(xmlDtdPtr dtd, const CHAR *elem, const CHAR *name,
560 int type, int def, const CHAR *defaultValue,
561 xmlEnumerationPtr tree) {
Daniel Veillard1e346af1999-02-22 10:33:01 +0000562 xmlAttributePtr ret, cur;
563 xmlAttributeTablePtr table;
564 int i;
565
566 if (dtd == NULL) {
567 fprintf(stderr, "xmlAddAttributeDecl: dtd == NULL\n");
568 return(NULL);
569 }
570 if (name == NULL) {
571 fprintf(stderr, "xmlAddAttributeDecl: name == NULL\n");
572 return(NULL);
573 }
574 if (elem == NULL) {
575 fprintf(stderr, "xmlAddAttributeDecl: elem == NULL\n");
576 return(NULL);
577 }
578 /* TODO: Lacks verifications !!! */
579 switch (type) {
580 case XML_ATTRIBUTE_CDATA:
581 break;
582 case XML_ATTRIBUTE_ID:
583 break;
584 case XML_ATTRIBUTE_IDREF:
585 break;
586 case XML_ATTRIBUTE_IDREFS:
587 break;
588 case XML_ATTRIBUTE_ENTITY:
589 break;
590 case XML_ATTRIBUTE_ENTITIES:
591 break;
592 case XML_ATTRIBUTE_NMTOKEN:
593 break;
594 case XML_ATTRIBUTE_NMTOKENS:
595 break;
596 case XML_ATTRIBUTE_ENUMERATION:
597 break;
598 case XML_ATTRIBUTE_NOTATION:
599 break;
600 default:
601 fprintf(stderr, "xmlAddAttributeDecl: unknown type %d\n", type);
602 return(NULL);
603 }
604
605 /*
606 * Create the Attribute table if needed.
607 */
608 table = dtd->attributes;
609 if (table == NULL)
610 table = dtd->attributes = xmlCreateAttributeTable();
611 if (table == NULL) {
612 fprintf(stderr, "xmlAddAttributeDecl: Table creation failed!\n");
613 return(NULL);
614 }
615
616 /*
617 * Validity Check:
618 * Search the DTD for previous declarations of the ATTLIST
619 */
620 for (i = 0;i < table->nb_attributes;i++) {
621 cur = &table->table[i];
622 if ((!xmlStrcmp(cur->name, name)) && (!xmlStrcmp(cur->elem, elem))) {
623 /*
624 * The attribute is already defined in this Dtd.
625 */
626 fprintf(stderr,
627 "xmlAddAttributeDecl: %s already defined\n", name);
628 }
629 }
630
631 /*
632 * Grow the table, if needed.
633 */
634 if (table->nb_attributes >= table->max_attributes) {
635 /*
636 * need more attributes.
637 */
638 table->max_attributes *= 2;
639 table->table = (xmlAttributePtr)
640 realloc(table->table, table->max_attributes * sizeof(xmlAttribute));
641 if (table->table) {
642 fprintf(stderr, "xmlAddAttributeDecl: out of memory\n");
643 return(NULL);
644 }
645 }
646 ret = &table->table[table->nb_attributes];
647
648 /*
649 * fill the structure.
650 */
651 ret->type = type;
652 ret->name = xmlStrdup(name);
653 ret->elem = xmlStrdup(elem);
654 ret->def = def;
655 ret->tree = tree;
656 if (defaultValue != NULL)
657 ret->defaultValue = xmlStrdup(defaultValue);
658 else
659 ret->defaultValue = NULL;
660 table->nb_attributes++;
661
662 return(ret);
663}
664
665/**
666 * xmlFreeAttribute:
667 * @elem: An attribute
668 *
669 * Deallocate the memory used by an attribute definition
670 */
671void
672xmlFreeAttribute(xmlAttributePtr attr) {
673 if (attr == NULL) return;
674 if (attr->tree != NULL)
675 xmlFreeEnumeration(attr->tree);
676 if (attr->elem != NULL)
677 free((CHAR *) attr->elem);
678 if (attr->name != NULL)
679 free((CHAR *) attr->name);
680 if (attr->defaultValue != NULL)
681 free((CHAR *) attr->defaultValue);
682 memset(attr, -1, sizeof(xmlAttribute));
683}
684
685/**
686 * xmlFreeAttributeTable:
687 * @table: An attribute table
688 *
689 * Deallocate the memory used by an entities hash table.
690 */
691void
692xmlFreeAttributeTable(xmlAttributeTablePtr table) {
693 int i;
694
695 if (table == NULL) return;
696
697 for (i = 0;i < table->nb_attributes;i++) {
698 xmlFreeAttribute(&table->table[i]);
699 }
700 free(table->table);
701 free(table);
702}
703
704/**
705 * xmlCopyAttributeTable:
706 * @table: An attribute table
707 *
708 * Build a copy of an attribute table.
709 *
710 * Returns the new xmlAttributeTablePtr or NULL in case of error.
711 */
712xmlAttributeTablePtr
713xmlCopyAttributeTable(xmlAttributeTablePtr table) {
714 xmlAttributeTablePtr ret;
715 xmlAttributePtr cur, attr;
716 int i;
717
718 ret = (xmlAttributeTablePtr) malloc(sizeof(xmlAttributeTable));
719 if (ret == NULL) {
720 fprintf(stderr, "xmlCopyAttributeTable: out of memory !\n");
721 return(NULL);
722 }
723 ret->table = (xmlAttributePtr) malloc(table->max_attributes *
724 sizeof(xmlAttribute));
725 if (ret->table == NULL) {
726 fprintf(stderr, "xmlCopyAttributeTable: out of memory !\n");
727 free(ret);
728 return(NULL);
729 }
730 ret->max_attributes = table->max_attributes;
731 ret->nb_attributes = table->nb_attributes;
732 for (i = 0;i < ret->nb_attributes;i++) {
733 cur = &ret->table[i];
734 attr = &table->table[i];
735 cur->type = attr->type;
736 cur->def = attr->def;
737 cur->tree = xmlCopyEnumeration(attr->tree);
738 if (attr->elem != NULL)
739 cur->elem = xmlStrdup(attr->elem);
740 else
741 cur->elem = NULL;
742 if (attr->name != NULL)
743 cur->name = xmlStrdup(attr->name);
744 else
745 cur->name = NULL;
746 if (attr->defaultValue != NULL)
747 cur->defaultValue = xmlStrdup(attr->defaultValue);
748 else
749 cur->defaultValue = NULL;
750 }
751 return(ret);
752}
753
754/**
755 * xmlDumpAttributeTable:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000756 * @buf: the XML buffer output
Daniel Veillard1e346af1999-02-22 10:33:01 +0000757 * @table: An attribute table
758 *
759 * This will dump the content of the attribute table as an XML DTD definition
Daniel Veillard1e346af1999-02-22 10:33:01 +0000760 */
761void
Daniel Veillard5099ae81999-04-21 20:12:07 +0000762xmlDumpAttributeTable(xmlBufferPtr buf, xmlAttributeTablePtr table) {
Daniel Veillard1e346af1999-02-22 10:33:01 +0000763 int i;
764 xmlAttributePtr cur;
765
766 if (table == NULL) return;
767
768 for (i = 0;i < table->nb_attributes;i++) {
769 cur = &table->table[i];
Daniel Veillard5099ae81999-04-21 20:12:07 +0000770 xmlBufferWriteChar(buf, "<!ATTLIST ");
771 xmlBufferWriteCHAR(buf, cur->elem);
772 xmlBufferWriteChar(buf, " ");
773 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000774 switch (cur->type) {
775 case XML_ATTRIBUTE_CDATA:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000776 xmlBufferWriteChar(buf, " CDATA");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000777 break;
778 case XML_ATTRIBUTE_ID:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000779 xmlBufferWriteChar(buf, " ID");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000780 break;
781 case XML_ATTRIBUTE_IDREF:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000782 xmlBufferWriteChar(buf, " IDREF");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000783 break;
784 case XML_ATTRIBUTE_IDREFS:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000785 xmlBufferWriteChar(buf, " IDREFS");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000786 break;
787 case XML_ATTRIBUTE_ENTITY:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000788 xmlBufferWriteChar(buf, " ENTITY");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000789 break;
790 case XML_ATTRIBUTE_ENTITIES:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000791 xmlBufferWriteChar(buf, " ENTITIES");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000792 break;
793 case XML_ATTRIBUTE_NMTOKEN:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000794 xmlBufferWriteChar(buf, " NMTOKEN");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000795 break;
796 case XML_ATTRIBUTE_NMTOKENS:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000797 xmlBufferWriteChar(buf, " NMTOKENS");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000798 break;
799 case XML_ATTRIBUTE_ENUMERATION:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000800 xmlBufferWriteChar(buf, " (pbm)");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000801 break;
802 case XML_ATTRIBUTE_NOTATION:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000803 xmlBufferWriteChar(buf, " NOTATION (pbm)");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000804 break;
805 default:
806 fprintf(stderr,
807 "xmlDumpAttributeTable: internal: unknown type %d\n",
808 cur->type);
809 }
810 switch (cur->def) {
811 case XML_ATTRIBUTE_NONE:
812 break;
813 case XML_ATTRIBUTE_REQUIRED:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000814 xmlBufferWriteChar(buf, " #REQUIRED");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000815 break;
816 case XML_ATTRIBUTE_IMPLIED:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000817 xmlBufferWriteChar(buf, " #IMPLIED");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000818 if (cur->defaultValue != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +0000819 xmlBufferWriteChar(buf, " ");
820 xmlBufferWriteQuotedString(buf, cur->defaultValue);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000821 }
822 break;
823 case XML_ATTRIBUTE_FIXED:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000824 xmlBufferWriteChar(buf, " #FIXED ");
825 xmlBufferWriteQuotedString(buf, cur->defaultValue);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000826 break;
827 default:
828 fprintf(stderr,
829 "xmlDumpAttributeTable: internal: unknown default %d\n",
830 cur->def);
831 }
Daniel Veillard5099ae81999-04-21 20:12:07 +0000832 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000833 }
834}
835
836/************************************************************************
837 * *
838 * NOTATIONs *
839 * *
840 ************************************************************************/
841/**
842 * xmlCreateNotationTable:
843 *
844 * create and initialize an empty notation hash table.
845 *
846 * Returns the xmlNotationTablePtr just created or NULL in case
847 * of error.
848 */
849xmlNotationTablePtr
850xmlCreateNotationTable(void) {
851 xmlNotationTablePtr ret;
852
853 ret = (xmlNotationTablePtr)
854 malloc(sizeof(xmlNotationTable));
855 if (ret == NULL) {
856 fprintf(stderr, "xmlCreateNotationTable : malloc(%d) failed\n",
857 sizeof(xmlNotationTable));
858 return(NULL);
859 }
860 ret->max_notations = XML_MIN_NOTATION_TABLE;
861 ret->nb_notations = 0;
862 ret->table = (xmlNotationPtr )
863 malloc(ret->max_notations * sizeof(xmlNotation));
864 if (ret == NULL) {
865 fprintf(stderr, "xmlCreateNotationTable : malloc(%d) failed\n",
866 ret->max_notations * sizeof(xmlNotation));
867 free(ret);
868 return(NULL);
869 }
870 return(ret);
871}
872
873
874/**
875 * xmlAddNotationDecl:
876 * @dtd: pointer to the DTD
877 * @name: the entity name
878 * @PublicID: the public identifier or NULL
879 * @SystemID: the system identifier or NULL
880 *
881 * Register a new notation declaration
882 *
883 * Returns NULL if not, othervise the entity
884 */
885xmlNotationPtr
Daniel Veillard517752b1999-04-05 12:20:10 +0000886xmlAddNotationDecl(xmlDtdPtr dtd, const CHAR *name, const CHAR *PublicID,
887 const CHAR *SystemID) {
Daniel Veillard1e346af1999-02-22 10:33:01 +0000888 xmlNotationPtr ret, cur;
889 xmlNotationTablePtr table;
890 int i;
891
892 if (dtd == NULL) {
893 fprintf(stderr, "xmlAddNotationDecl: dtd == NULL\n");
894 return(NULL);
895 }
896 if (name == NULL) {
897 fprintf(stderr, "xmlAddNotationDecl: name == NULL\n");
898 return(NULL);
899 }
900 if ((PublicID == NULL) && (SystemID == NULL)) {
901 fprintf(stderr, "xmlAddNotationDecl: no PUBLIC ID nor SYSTEM ID\n");
902 }
903
904 /*
905 * Create the Notation table if needed.
906 */
907 table = dtd->notations;
908 if (table == NULL)
909 table = dtd->notations = xmlCreateNotationTable();
910 if (table == NULL) {
911 fprintf(stderr, "xmlAddNotationDecl: Table creation failed!\n");
912 return(NULL);
913 }
914
915 /*
916 * Validity Check:
917 * Search the DTD for previous declarations of the ATTLIST
918 */
919 for (i = 0;i < table->nb_notations;i++) {
920 cur = &table->table[i];
921 if (!xmlStrcmp(cur->name, name)) {
922 /*
923 * The notation is already defined in this Dtd.
924 */
925 fprintf(stderr,
926 "xmlAddNotationDecl: %s already defined\n", name);
927 }
928 }
929
930 /*
931 * Grow the table, if needed.
932 */
933 if (table->nb_notations >= table->max_notations) {
934 /*
935 * need more notations.
936 */
937 table->max_notations *= 2;
938 table->table = (xmlNotationPtr)
939 realloc(table->table, table->max_notations * sizeof(xmlNotation));
940 if (table->table) {
941 fprintf(stderr, "xmlAddNotationDecl: out of memory\n");
942 return(NULL);
943 }
944 }
945 ret = &table->table[table->nb_notations];
946
947 /*
948 * fill the structure.
949 */
950 ret->name = xmlStrdup(name);
951 if (SystemID != NULL)
952 ret->SystemID = xmlStrdup(SystemID);
953 else
954 ret->SystemID = NULL;
955 if (PublicID != NULL)
956 ret->PublicID = xmlStrdup(PublicID);
957 else
958 ret->PublicID = NULL;
959 table->nb_notations++;
960
961 return(ret);
962}
963
964/**
965 * xmlFreeNotation:
966 * @not: A notation
967 *
968 * Deallocate the memory used by an notation definition
969 */
970void
971xmlFreeNotation(xmlNotationPtr nota) {
972 if (nota == NULL) return;
973 if (nota->name != NULL)
974 free((CHAR *) nota->name);
975 if (nota->PublicID != NULL)
976 free((CHAR *) nota->PublicID);
977 if (nota->SystemID != NULL)
978 free((CHAR *) nota->SystemID);
979 memset(nota, -1, sizeof(xmlNotation));
980}
981
982/**
983 * xmlFreeNotationTable:
984 * @table: An notation table
985 *
986 * Deallocate the memory used by an entities hash table.
987 */
988void
989xmlFreeNotationTable(xmlNotationTablePtr table) {
990 int i;
991
992 if (table == NULL) return;
993
994 for (i = 0;i < table->nb_notations;i++) {
995 xmlFreeNotation(&table->table[i]);
996 }
997 free(table->table);
998 free(table);
999}
1000
1001/**
1002 * xmlCopyNotationTable:
1003 * @table: A notation table
1004 *
1005 * Build a copy of a notation table.
1006 *
1007 * Returns the new xmlNotationTablePtr or NULL in case of error.
1008 */
1009xmlNotationTablePtr
1010xmlCopyNotationTable(xmlNotationTablePtr table) {
1011 xmlNotationTablePtr ret;
1012 xmlNotationPtr cur, nota;
1013 int i;
1014
1015 ret = (xmlNotationTablePtr) malloc(sizeof(xmlNotationTable));
1016 if (ret == NULL) {
1017 fprintf(stderr, "xmlCopyNotationTable: out of memory !\n");
1018 return(NULL);
1019 }
1020 ret->table = (xmlNotationPtr) malloc(table->max_notations *
1021 sizeof(xmlNotation));
1022 if (ret->table == NULL) {
1023 fprintf(stderr, "xmlCopyNotationTable: out of memory !\n");
1024 free(ret);
1025 return(NULL);
1026 }
1027 ret->max_notations = table->max_notations;
1028 ret->nb_notations = table->nb_notations;
1029 for (i = 0;i < ret->nb_notations;i++) {
1030 cur = &ret->table[i];
1031 nota = &table->table[i];
1032 if (nota->name != NULL)
1033 cur->name = xmlStrdup(nota->name);
1034 else
1035 cur->name = NULL;
1036 if (nota->PublicID != NULL)
1037 cur->PublicID = xmlStrdup(nota->PublicID);
1038 else
1039 cur->PublicID = NULL;
1040 if (nota->SystemID != NULL)
1041 cur->SystemID = xmlStrdup(nota->SystemID);
1042 else
1043 cur->SystemID = NULL;
1044 }
1045 return(ret);
1046}
1047
1048/**
1049 * xmlDumpNotationTable:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001050 * @buf: the XML buffer output
Daniel Veillard1e346af1999-02-22 10:33:01 +00001051 * @table: A notation table
1052 *
1053 * This will dump the content of the notation table as an XML DTD definition
Daniel Veillard1e346af1999-02-22 10:33:01 +00001054 */
1055void
Daniel Veillard5099ae81999-04-21 20:12:07 +00001056xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
Daniel Veillard1e346af1999-02-22 10:33:01 +00001057 int i;
1058 xmlNotationPtr cur;
1059
1060 if (table == NULL) return;
1061
1062 for (i = 0;i < table->nb_notations;i++) {
1063 cur = &table->table[i];
Daniel Veillard5099ae81999-04-21 20:12:07 +00001064 xmlBufferWriteChar(buf, "<!NOTATION ");
1065 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001066 if (cur->PublicID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00001067 xmlBufferWriteChar(buf, " PUBLIC ");
1068 xmlBufferWriteQuotedString(buf, cur->PublicID);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001069 if (cur->SystemID != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00001070 xmlBufferWriteChar(buf, " ");
1071 xmlBufferWriteCHAR(buf, cur->SystemID);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001072 }
1073 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00001074 xmlBufferWriteChar(buf, " SYSTEM ");
1075 xmlBufferWriteCHAR(buf, cur->SystemID);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001076 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00001077 xmlBufferWriteChar(buf, " >\n");
Daniel Veillard1e346af1999-02-22 10:33:01 +00001078 }
1079}