blob: 3cb6276ca96d8188ab1ac7443bd2600bd6d8f4cc [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:
104 * @content: An element table
105 * @glob: 1 if one must print the englobing parenthesis, 0 otherwise
106 *
107 * This will dump the content of the element table as an XML DTD definition
108 *
109 * NOTE: TODO an extra parameter allowing a reentant implementation will
110 * be added.
111 */
112void
113xmlDumpElementContent(xmlElementContentPtr content, int glob) {
114 if (content == NULL) return;
115
116 if (glob) xmlBufferWriteChar("(");
117 switch (content->type) {
118 case XML_ELEMENT_CONTENT_PCDATA:
119 xmlBufferWriteChar("#PCDATA");
120 break;
121 case XML_ELEMENT_CONTENT_ELEMENT:
122 xmlBufferWriteCHAR(content->name);
123 break;
124 case XML_ELEMENT_CONTENT_SEQ:
125 if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
126 (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
127 xmlDumpElementContent(content->c1, 1);
128 else
129 xmlDumpElementContent(content->c1, 0);
130 xmlBufferWriteChar(" , ");
131 if (content->c2->type == XML_ELEMENT_CONTENT_OR)
132 xmlDumpElementContent(content->c2, 1);
133 else
134 xmlDumpElementContent(content->c2, 0);
135 break;
136 case XML_ELEMENT_CONTENT_OR:
137 if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
138 (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
139 xmlDumpElementContent(content->c1, 1);
140 else
141 xmlDumpElementContent(content->c1, 0);
142 xmlBufferWriteChar(" | ");
143 if (content->c2->type == XML_ELEMENT_CONTENT_SEQ)
144 xmlDumpElementContent(content->c2, 1);
145 else
146 xmlDumpElementContent(content->c2, 0);
147 break;
148 default:
149 fprintf(stderr, "xmlDumpElementContent: unknown type %d\n",
150 content->type);
151 }
152 if (glob)
153 xmlBufferWriteChar(")");
154 switch (content->ocur) {
155 case XML_ELEMENT_CONTENT_ONCE:
156 break;
157 case XML_ELEMENT_CONTENT_OPT:
158 xmlBufferWriteChar("?");
159 break;
160 case XML_ELEMENT_CONTENT_MULT:
161 xmlBufferWriteChar("*");
162 break;
163 case XML_ELEMENT_CONTENT_PLUS:
164 xmlBufferWriteChar("+");
165 break;
166 }
167}
168
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000169/****************************************************************
170 * *
171 * Registration of DTD declarations *
172 * *
173 ****************************************************************/
174
Daniel Veillard3b9def11999-01-31 22:15:06 +0000175/**
176 * xmlCreateElementTable:
177 *
178 * create and initialize an empty element hash table.
179 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000180 * Returns the xmlElementTablePtr just created or NULL in case of error.
Daniel Veillard3b9def11999-01-31 22:15:06 +0000181 */
182xmlElementTablePtr
183xmlCreateElementTable(void) {
184 xmlElementTablePtr ret;
185
186 ret = (xmlElementTablePtr)
187 malloc(sizeof(xmlElementTable));
188 if (ret == NULL) {
189 fprintf(stderr, "xmlCreateElementTable : malloc(%d) failed\n",
190 sizeof(xmlElementTable));
191 return(NULL);
192 }
Daniel Veillard1e346af1999-02-22 10:33:01 +0000193 ret->max_elements = XML_MIN_ELEMENT_TABLE;
Daniel Veillard3b9def11999-01-31 22:15:06 +0000194 ret->nb_elements = 0;
195 ret->table = (xmlElementPtr )
196 malloc(ret->max_elements * sizeof(xmlElement));
197 if (ret == NULL) {
198 fprintf(stderr, "xmlCreateElementTable : malloc(%d) failed\n",
199 ret->max_elements * sizeof(xmlElement));
200 free(ret);
201 return(NULL);
202 }
203 return(ret);
204}
205
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000206
207/**
208 * xmlAddElementDecl:
Daniel Veillard1e346af1999-02-22 10:33:01 +0000209 * @dtd: pointer to the DTD
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000210 * @name: the entity name
Daniel Veillard1e346af1999-02-22 10:33:01 +0000211 * @type: the element type
212 * @content: the element content tree or NULL
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000213 *
214 * Register a new element declaration
215 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000216 * Returns NULL if not, othervise the entity
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000217 */
218xmlElementPtr
Daniel Veillard1e346af1999-02-22 10:33:01 +0000219xmlAddElementDecl(xmlDtdPtr dtd, CHAR *name, int type,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000220 xmlElementContentPtr content) {
Daniel Veillard3b9def11999-01-31 22:15:06 +0000221 xmlElementPtr ret, cur;
222 xmlElementTablePtr table;
223 int i;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000224
225 if (dtd == NULL) {
226 fprintf(stderr, "xmlAddElementDecl: dtd == NULL\n");
227 return(NULL);
228 }
229 if (name == NULL) {
230 fprintf(stderr, "xmlAddElementDecl: name == NULL\n");
231 return(NULL);
232 }
233 switch (type) {
234 case XML_ELEMENT_TYPE_EMPTY:
235 if (content != NULL) {
236 fprintf(stderr,
237 "xmlAddElementDecl: content != NULL for EMPTY\n");
238 return(NULL);
239 }
240 break;
241 case XML_ELEMENT_TYPE_ANY:
242 if (content != NULL) {
243 fprintf(stderr,
244 "xmlAddElementDecl: content != NULL for ANY\n");
245 return(NULL);
246 }
247 break;
248 case XML_ELEMENT_TYPE_MIXED:
249 if (content == NULL) {
250 fprintf(stderr,
251 "xmlAddElementDecl: content == NULL for MIXED\n");
252 return(NULL);
253 }
254 break;
255 case XML_ELEMENT_TYPE_ELEMENT:
256 if (content == NULL) {
257 fprintf(stderr,
258 "xmlAddElementDecl: content == NULL for ELEMENT\n");
259 return(NULL);
260 }
261 break;
262 default:
263 fprintf(stderr, "xmlAddElementDecl: unknown type %d\n", type);
264 return(NULL);
265 }
266
267 /*
Daniel Veillard3b9def11999-01-31 22:15:06 +0000268 * Create the Element table if needed.
269 */
270 table = dtd->elements;
271 if (table == NULL)
272 table = dtd->elements = xmlCreateElementTable();
273 if (table == NULL) {
274 fprintf(stderr, "xmlAddElementDecl: Table creation failed!\n");
275 return(NULL);
276 }
277
278 /*
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000279 * Validity Check:
280 * Search the DTD for previous declarations of the ELEMENT
281 */
Daniel Veillard3b9def11999-01-31 22:15:06 +0000282 for (i = 0;i < table->nb_elements;i++) {
283 cur = &table->table[i];
284 if (!xmlStrcmp(cur->name, name)) {
285 /*
286 * The element is already defined in this Dtd.
287 */
288 fprintf(stderr,
289 "xmlAddElementDecl: %s already defined\n", name);
290 return(NULL);
291 }
292 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000293
294 /*
Daniel Veillard3b9def11999-01-31 22:15:06 +0000295 * Grow the table, if needed.
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000296 */
Daniel Veillard3b9def11999-01-31 22:15:06 +0000297 if (table->nb_elements >= table->max_elements) {
298 /*
299 * need more elements.
300 */
301 table->max_elements *= 2;
302 table->table = (xmlElementPtr)
303 realloc(table->table, table->max_elements * sizeof(xmlElement));
304 if (table->table) {
305 fprintf(stderr, "xmlAddElementDecl: out of memory\n");
306 return(NULL);
307 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000308 }
Daniel Veillard3b9def11999-01-31 22:15:06 +0000309 ret = &table->table[table->nb_elements];
310
311 /*
312 * fill the structure.
313 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000314 ret->type = type;
315 ret->name = xmlStrdup(name);
316 ret->content = content;
Daniel Veillard3b9def11999-01-31 22:15:06 +0000317 table->nb_elements++;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000318
319 return(ret);
320}
321
Daniel Veillard3b9def11999-01-31 22:15:06 +0000322/**
323 * xmlFreeElement:
324 * @elem: An element
325 *
326 * Deallocate the memory used by an element definition
327 */
328void
329xmlFreeElement(xmlElementPtr elem) {
330 if (elem == NULL) return;
331 xmlFreeElementContent(elem->content);
332 if (elem->name != NULL)
333 free((CHAR *) elem->name);
334 memset(elem, -1, sizeof(xmlElement));
Daniel Veillard3b9def11999-01-31 22:15:06 +0000335}
336
337/**
338 * xmlFreeElementTable:
339 * @table: An element table
340 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000341 * Deallocate the memory used by an element hash table.
Daniel Veillard3b9def11999-01-31 22:15:06 +0000342 */
343void
344xmlFreeElementTable(xmlElementTablePtr table) {
345 int i;
346
347 if (table == NULL) return;
348
349 for (i = 0;i < table->nb_elements;i++) {
350 xmlFreeElement(&table->table[i]);
351 }
352 free(table->table);
353 free(table);
354}
355
356/**
357 * xmlCopyElementTable:
358 * @table: An element table
359 *
360 * Build a copy of an element table.
361 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000362 * Returns the new xmlElementTablePtr or NULL in case of error.
Daniel Veillard3b9def11999-01-31 22:15:06 +0000363 */
364xmlElementTablePtr
365xmlCopyElementTable(xmlElementTablePtr table) {
366 xmlElementTablePtr ret;
367 xmlElementPtr cur, ent;
368 int i;
369
370 ret = (xmlElementTablePtr) malloc(sizeof(xmlElementTable));
371 if (ret == NULL) {
372 fprintf(stderr, "xmlCopyElementTable: out of memory !\n");
373 return(NULL);
374 }
375 ret->table = (xmlElementPtr) malloc(table->max_elements *
376 sizeof(xmlElement));
377 if (ret->table == NULL) {
378 fprintf(stderr, "xmlCopyElementTable: out of memory !\n");
379 free(ret);
380 return(NULL);
381 }
382 ret->max_elements = table->max_elements;
383 ret->nb_elements = table->nb_elements;
384 for (i = 0;i < ret->nb_elements;i++) {
385 cur = &ret->table[i];
386 ent = &table->table[i];
387 cur->type = ent->type;
388 if (ent->name != NULL)
389 cur->name = xmlStrdup(ent->name);
390 else
391 cur->name = NULL;
392 cur->content = xmlCopyElementContent(ent->content);
393 }
394 return(ret);
395}
396
397/**
398 * xmlDumpElementTable:
399 * @table: An element table
400 *
401 * This will dump the content of the element table as an XML DTD definition
402 *
403 * NOTE: TODO an extra parameter allowing a reentant implementation will
404 * be added.
405 */
406void
407xmlDumpElementTable(xmlElementTablePtr table) {
408 int i;
409 xmlElementPtr cur;
410
411 if (table == NULL) return;
412
413 for (i = 0;i < table->nb_elements;i++) {
414 cur = &table->table[i];
415 switch (cur->type) {
416 case XML_ELEMENT_TYPE_EMPTY:
417 xmlBufferWriteChar("<!ELEMENT ");
418 xmlBufferWriteCHAR(cur->name);
Daniel Veillard1899e851999-02-01 12:18:54 +0000419 xmlBufferWriteChar(" EMPTY>\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000420 break;
421 case XML_ELEMENT_TYPE_ANY:
422 xmlBufferWriteChar("<!ELEMENT ");
423 xmlBufferWriteCHAR(cur->name);
Daniel Veillard1899e851999-02-01 12:18:54 +0000424 xmlBufferWriteChar(" ANY>\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000425 break;
426 case XML_ELEMENT_TYPE_MIXED:
Daniel Veillard1899e851999-02-01 12:18:54 +0000427 xmlBufferWriteChar("<!ELEMENT ");
428 xmlBufferWriteCHAR(cur->name);
429 xmlBufferWriteChar(" ");
430 xmlDumpElementContent(cur->content, 1);
431 xmlBufferWriteChar(">\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000432 break;
433 case XML_ELEMENT_TYPE_ELEMENT:
Daniel Veillard1899e851999-02-01 12:18:54 +0000434 xmlBufferWriteChar("<!ELEMENT ");
435 xmlBufferWriteCHAR(cur->name);
436 xmlBufferWriteChar(" ");
437 xmlDumpElementContent(cur->content, 1);
438 xmlBufferWriteChar(">\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000439 break;
440 default:
441 fprintf(stderr,
442 "xmlDumpElementTable: internal: unknown type %d\n",
443 cur->type);
444 }
445 }
446}
Daniel Veillard1e346af1999-02-22 10:33:01 +0000447
448/**
449 * xmlCreateEnumeration:
450 * @name: the enumeration name or NULL
451 *
452 * create and initialize an enumeration attribute node.
453 *
454 * Returns the xmlEnumerationPtr just created or NULL in case
455 * of error.
456 */
457xmlEnumerationPtr
458xmlCreateEnumeration(CHAR *name) {
459 xmlEnumerationPtr ret;
460
461 ret = (xmlEnumerationPtr) malloc(sizeof(xmlEnumeration));
462 if (ret == NULL) {
463 fprintf(stderr, "xmlCreateEnumeration : malloc(%d) failed\n",
464 sizeof(xmlEnumeration));
465 return(NULL);
466 }
467
468 if (name != NULL)
469 ret->name = xmlStrdup(name);
470 else
471 ret->name = NULL;
472 ret->next = NULL;
473 return(ret);
474}
475
476/**
477 * xmlFreeEnumeration:
478 * @cur: the tree to free.
479 *
480 * free an enumeration attribute node (recursive).
481 */
482void
483xmlFreeEnumeration(xmlEnumerationPtr cur) {
484 if (cur == NULL) return;
485
486 if (cur->next != NULL) xmlFreeEnumeration(cur->next);
487
488 if (cur->name != NULL) free((CHAR *) cur->name);
489 memset(cur, -1, sizeof(xmlEnumeration));
490 free(cur);
491}
492
493/**
494 * xmlCopyEnumeration:
495 * @cur: the tree to copy.
496 *
497 * Copy an enumeration attribute node (recursive).
498 *
499 * Returns the xmlEnumerationPtr just created or NULL in case
500 * of error.
501 */
502xmlEnumerationPtr
503xmlCopyEnumeration(xmlEnumerationPtr cur) {
504 xmlEnumerationPtr ret;
505
506 if (cur == NULL) return(NULL);
507 ret = xmlCreateEnumeration((CHAR *) cur->name);
508
509 if (cur->next != NULL) ret->next = xmlCopyEnumeration(cur->next);
510 else ret->next = NULL;
511
512 return(ret);
513}
514
515/**
516 * xmlCreateAttributeTable:
517 *
518 * create and initialize an empty attribute hash table.
519 *
520 * Returns the xmlAttributeTablePtr just created or NULL in case
521 * of error.
522 */
523xmlAttributeTablePtr
524xmlCreateAttributeTable(void) {
525 xmlAttributeTablePtr ret;
526
527 ret = (xmlAttributeTablePtr)
528 malloc(sizeof(xmlAttributeTable));
529 if (ret == NULL) {
530 fprintf(stderr, "xmlCreateAttributeTable : malloc(%d) failed\n",
531 sizeof(xmlAttributeTable));
532 return(NULL);
533 }
534 ret->max_attributes = XML_MIN_ATTRIBUTE_TABLE;
535 ret->nb_attributes = 0;
536 ret->table = (xmlAttributePtr )
537 malloc(ret->max_attributes * sizeof(xmlAttribute));
538 if (ret == NULL) {
539 fprintf(stderr, "xmlCreateAttributeTable : malloc(%d) failed\n",
540 ret->max_attributes * sizeof(xmlAttribute));
541 free(ret);
542 return(NULL);
543 }
544 return(ret);
545}
546
547
548/**
549 * xmlAddAttributeDecl:
550 * @dtd: pointer to the DTD
551 * @elem: the element name
552 * @name: the attribute name
553 * @type: the attribute type
554 * @def: the attribute default type
555 * @defaultValue: the attribute default value
556 * @tree: if it's an enumeration, the associated list
557 *
558 * Register a new attribute declaration
559 *
560 * Returns NULL if not, othervise the entity
561 */
562xmlAttributePtr
563xmlAddAttributeDecl(xmlDtdPtr dtd, CHAR *elem, CHAR *name, int type, int def,
564 CHAR *defaultValue, xmlEnumerationPtr tree) {
565 xmlAttributePtr ret, cur;
566 xmlAttributeTablePtr table;
567 int i;
568
569 if (dtd == NULL) {
570 fprintf(stderr, "xmlAddAttributeDecl: dtd == NULL\n");
571 return(NULL);
572 }
573 if (name == NULL) {
574 fprintf(stderr, "xmlAddAttributeDecl: name == NULL\n");
575 return(NULL);
576 }
577 if (elem == NULL) {
578 fprintf(stderr, "xmlAddAttributeDecl: elem == NULL\n");
579 return(NULL);
580 }
581 /* TODO: Lacks verifications !!! */
582 switch (type) {
583 case XML_ATTRIBUTE_CDATA:
584 break;
585 case XML_ATTRIBUTE_ID:
586 break;
587 case XML_ATTRIBUTE_IDREF:
588 break;
589 case XML_ATTRIBUTE_IDREFS:
590 break;
591 case XML_ATTRIBUTE_ENTITY:
592 break;
593 case XML_ATTRIBUTE_ENTITIES:
594 break;
595 case XML_ATTRIBUTE_NMTOKEN:
596 break;
597 case XML_ATTRIBUTE_NMTOKENS:
598 break;
599 case XML_ATTRIBUTE_ENUMERATION:
600 break;
601 case XML_ATTRIBUTE_NOTATION:
602 break;
603 default:
604 fprintf(stderr, "xmlAddAttributeDecl: unknown type %d\n", type);
605 return(NULL);
606 }
607
608 /*
609 * Create the Attribute table if needed.
610 */
611 table = dtd->attributes;
612 if (table == NULL)
613 table = dtd->attributes = xmlCreateAttributeTable();
614 if (table == NULL) {
615 fprintf(stderr, "xmlAddAttributeDecl: Table creation failed!\n");
616 return(NULL);
617 }
618
619 /*
620 * Validity Check:
621 * Search the DTD for previous declarations of the ATTLIST
622 */
623 for (i = 0;i < table->nb_attributes;i++) {
624 cur = &table->table[i];
625 if ((!xmlStrcmp(cur->name, name)) && (!xmlStrcmp(cur->elem, elem))) {
626 /*
627 * The attribute is already defined in this Dtd.
628 */
629 fprintf(stderr,
630 "xmlAddAttributeDecl: %s already defined\n", name);
631 }
632 }
633
634 /*
635 * Grow the table, if needed.
636 */
637 if (table->nb_attributes >= table->max_attributes) {
638 /*
639 * need more attributes.
640 */
641 table->max_attributes *= 2;
642 table->table = (xmlAttributePtr)
643 realloc(table->table, table->max_attributes * sizeof(xmlAttribute));
644 if (table->table) {
645 fprintf(stderr, "xmlAddAttributeDecl: out of memory\n");
646 return(NULL);
647 }
648 }
649 ret = &table->table[table->nb_attributes];
650
651 /*
652 * fill the structure.
653 */
654 ret->type = type;
655 ret->name = xmlStrdup(name);
656 ret->elem = xmlStrdup(elem);
657 ret->def = def;
658 ret->tree = tree;
659 if (defaultValue != NULL)
660 ret->defaultValue = xmlStrdup(defaultValue);
661 else
662 ret->defaultValue = NULL;
663 table->nb_attributes++;
664
665 return(ret);
666}
667
668/**
669 * xmlFreeAttribute:
670 * @elem: An attribute
671 *
672 * Deallocate the memory used by an attribute definition
673 */
674void
675xmlFreeAttribute(xmlAttributePtr attr) {
676 if (attr == NULL) return;
677 if (attr->tree != NULL)
678 xmlFreeEnumeration(attr->tree);
679 if (attr->elem != NULL)
680 free((CHAR *) attr->elem);
681 if (attr->name != NULL)
682 free((CHAR *) attr->name);
683 if (attr->defaultValue != NULL)
684 free((CHAR *) attr->defaultValue);
685 memset(attr, -1, sizeof(xmlAttribute));
686}
687
688/**
689 * xmlFreeAttributeTable:
690 * @table: An attribute table
691 *
692 * Deallocate the memory used by an entities hash table.
693 */
694void
695xmlFreeAttributeTable(xmlAttributeTablePtr table) {
696 int i;
697
698 if (table == NULL) return;
699
700 for (i = 0;i < table->nb_attributes;i++) {
701 xmlFreeAttribute(&table->table[i]);
702 }
703 free(table->table);
704 free(table);
705}
706
707/**
708 * xmlCopyAttributeTable:
709 * @table: An attribute table
710 *
711 * Build a copy of an attribute table.
712 *
713 * Returns the new xmlAttributeTablePtr or NULL in case of error.
714 */
715xmlAttributeTablePtr
716xmlCopyAttributeTable(xmlAttributeTablePtr table) {
717 xmlAttributeTablePtr ret;
718 xmlAttributePtr cur, attr;
719 int i;
720
721 ret = (xmlAttributeTablePtr) malloc(sizeof(xmlAttributeTable));
722 if (ret == NULL) {
723 fprintf(stderr, "xmlCopyAttributeTable: out of memory !\n");
724 return(NULL);
725 }
726 ret->table = (xmlAttributePtr) malloc(table->max_attributes *
727 sizeof(xmlAttribute));
728 if (ret->table == NULL) {
729 fprintf(stderr, "xmlCopyAttributeTable: out of memory !\n");
730 free(ret);
731 return(NULL);
732 }
733 ret->max_attributes = table->max_attributes;
734 ret->nb_attributes = table->nb_attributes;
735 for (i = 0;i < ret->nb_attributes;i++) {
736 cur = &ret->table[i];
737 attr = &table->table[i];
738 cur->type = attr->type;
739 cur->def = attr->def;
740 cur->tree = xmlCopyEnumeration(attr->tree);
741 if (attr->elem != NULL)
742 cur->elem = xmlStrdup(attr->elem);
743 else
744 cur->elem = NULL;
745 if (attr->name != NULL)
746 cur->name = xmlStrdup(attr->name);
747 else
748 cur->name = NULL;
749 if (attr->defaultValue != NULL)
750 cur->defaultValue = xmlStrdup(attr->defaultValue);
751 else
752 cur->defaultValue = NULL;
753 }
754 return(ret);
755}
756
757/**
758 * xmlDumpAttributeTable:
759 * @table: An attribute table
760 *
761 * This will dump the content of the attribute table as an XML DTD definition
762 *
763 * NOTE: TODO an extra parameter allowing a reentant implementation will
764 * be added.
765 */
766void
767xmlDumpAttributeTable(xmlAttributeTablePtr table) {
768 int i;
769 xmlAttributePtr cur;
770
771 if (table == NULL) return;
772
773 for (i = 0;i < table->nb_attributes;i++) {
774 cur = &table->table[i];
775 xmlBufferWriteChar("<!ATTLIST ");
776 xmlBufferWriteCHAR(cur->elem);
777 xmlBufferWriteChar(" ");
778 xmlBufferWriteCHAR(cur->name);
779 switch (cur->type) {
780 case XML_ATTRIBUTE_CDATA:
781 xmlBufferWriteChar(" CDATA");
782 break;
783 case XML_ATTRIBUTE_ID:
784 xmlBufferWriteChar(" ID");
785 break;
786 case XML_ATTRIBUTE_IDREF:
787 xmlBufferWriteChar(" IDREF");
788 break;
789 case XML_ATTRIBUTE_IDREFS:
790 xmlBufferWriteChar(" IDREFS");
791 break;
792 case XML_ATTRIBUTE_ENTITY:
793 xmlBufferWriteChar(" ENTITY");
794 break;
795 case XML_ATTRIBUTE_ENTITIES:
796 xmlBufferWriteChar(" ENTITIES");
797 break;
798 case XML_ATTRIBUTE_NMTOKEN:
799 xmlBufferWriteChar(" NMTOKEN");
800 break;
801 case XML_ATTRIBUTE_NMTOKENS:
802 xmlBufferWriteChar(" NMTOKENS");
803 break;
804 case XML_ATTRIBUTE_ENUMERATION:
805 xmlBufferWriteChar(" (pbm)");
806 break;
807 case XML_ATTRIBUTE_NOTATION:
808 xmlBufferWriteChar(" NOTATION (pbm)");
809 break;
810 default:
811 fprintf(stderr,
812 "xmlDumpAttributeTable: internal: unknown type %d\n",
813 cur->type);
814 }
815 switch (cur->def) {
816 case XML_ATTRIBUTE_NONE:
817 break;
818 case XML_ATTRIBUTE_REQUIRED:
819 xmlBufferWriteChar(" #REQUIRED");
820 break;
821 case XML_ATTRIBUTE_IMPLIED:
822 xmlBufferWriteChar(" #IMPLIED");
823 if (cur->defaultValue != NULL) {
824 xmlBufferWriteChar(" \"");
825 xmlBufferWriteCHAR(cur->defaultValue);
826 xmlBufferWriteChar("\"");
827 }
828 break;
829 case XML_ATTRIBUTE_FIXED:
830 xmlBufferWriteChar(" #FIXED \"");
831 xmlBufferWriteCHAR(cur->defaultValue);
832 xmlBufferWriteChar("\"");
833 break;
834 default:
835 fprintf(stderr,
836 "xmlDumpAttributeTable: internal: unknown default %d\n",
837 cur->def);
838 }
839 xmlBufferWriteChar(">\n");
840 }
841}
842
843/************************************************************************
844 * *
845 * NOTATIONs *
846 * *
847 ************************************************************************/
848/**
849 * xmlCreateNotationTable:
850 *
851 * create and initialize an empty notation hash table.
852 *
853 * Returns the xmlNotationTablePtr just created or NULL in case
854 * of error.
855 */
856xmlNotationTablePtr
857xmlCreateNotationTable(void) {
858 xmlNotationTablePtr ret;
859
860 ret = (xmlNotationTablePtr)
861 malloc(sizeof(xmlNotationTable));
862 if (ret == NULL) {
863 fprintf(stderr, "xmlCreateNotationTable : malloc(%d) failed\n",
864 sizeof(xmlNotationTable));
865 return(NULL);
866 }
867 ret->max_notations = XML_MIN_NOTATION_TABLE;
868 ret->nb_notations = 0;
869 ret->table = (xmlNotationPtr )
870 malloc(ret->max_notations * sizeof(xmlNotation));
871 if (ret == NULL) {
872 fprintf(stderr, "xmlCreateNotationTable : malloc(%d) failed\n",
873 ret->max_notations * sizeof(xmlNotation));
874 free(ret);
875 return(NULL);
876 }
877 return(ret);
878}
879
880
881/**
882 * xmlAddNotationDecl:
883 * @dtd: pointer to the DTD
884 * @name: the entity name
885 * @PublicID: the public identifier or NULL
886 * @SystemID: the system identifier or NULL
887 *
888 * Register a new notation declaration
889 *
890 * Returns NULL if not, othervise the entity
891 */
892xmlNotationPtr
893xmlAddNotationDecl(xmlDtdPtr dtd, CHAR *name, CHAR *PublicID, CHAR *SystemID) {
894 xmlNotationPtr ret, cur;
895 xmlNotationTablePtr table;
896 int i;
897
898 if (dtd == NULL) {
899 fprintf(stderr, "xmlAddNotationDecl: dtd == NULL\n");
900 return(NULL);
901 }
902 if (name == NULL) {
903 fprintf(stderr, "xmlAddNotationDecl: name == NULL\n");
904 return(NULL);
905 }
906 if ((PublicID == NULL) && (SystemID == NULL)) {
907 fprintf(stderr, "xmlAddNotationDecl: no PUBLIC ID nor SYSTEM ID\n");
908 }
909
910 /*
911 * Create the Notation table if needed.
912 */
913 table = dtd->notations;
914 if (table == NULL)
915 table = dtd->notations = xmlCreateNotationTable();
916 if (table == NULL) {
917 fprintf(stderr, "xmlAddNotationDecl: Table creation failed!\n");
918 return(NULL);
919 }
920
921 /*
922 * Validity Check:
923 * Search the DTD for previous declarations of the ATTLIST
924 */
925 for (i = 0;i < table->nb_notations;i++) {
926 cur = &table->table[i];
927 if (!xmlStrcmp(cur->name, name)) {
928 /*
929 * The notation is already defined in this Dtd.
930 */
931 fprintf(stderr,
932 "xmlAddNotationDecl: %s already defined\n", name);
933 }
934 }
935
936 /*
937 * Grow the table, if needed.
938 */
939 if (table->nb_notations >= table->max_notations) {
940 /*
941 * need more notations.
942 */
943 table->max_notations *= 2;
944 table->table = (xmlNotationPtr)
945 realloc(table->table, table->max_notations * sizeof(xmlNotation));
946 if (table->table) {
947 fprintf(stderr, "xmlAddNotationDecl: out of memory\n");
948 return(NULL);
949 }
950 }
951 ret = &table->table[table->nb_notations];
952
953 /*
954 * fill the structure.
955 */
956 ret->name = xmlStrdup(name);
957 if (SystemID != NULL)
958 ret->SystemID = xmlStrdup(SystemID);
959 else
960 ret->SystemID = NULL;
961 if (PublicID != NULL)
962 ret->PublicID = xmlStrdup(PublicID);
963 else
964 ret->PublicID = NULL;
965 table->nb_notations++;
966
967 return(ret);
968}
969
970/**
971 * xmlFreeNotation:
972 * @not: A notation
973 *
974 * Deallocate the memory used by an notation definition
975 */
976void
977xmlFreeNotation(xmlNotationPtr nota) {
978 if (nota == NULL) return;
979 if (nota->name != NULL)
980 free((CHAR *) nota->name);
981 if (nota->PublicID != NULL)
982 free((CHAR *) nota->PublicID);
983 if (nota->SystemID != NULL)
984 free((CHAR *) nota->SystemID);
985 memset(nota, -1, sizeof(xmlNotation));
986}
987
988/**
989 * xmlFreeNotationTable:
990 * @table: An notation table
991 *
992 * Deallocate the memory used by an entities hash table.
993 */
994void
995xmlFreeNotationTable(xmlNotationTablePtr table) {
996 int i;
997
998 if (table == NULL) return;
999
1000 for (i = 0;i < table->nb_notations;i++) {
1001 xmlFreeNotation(&table->table[i]);
1002 }
1003 free(table->table);
1004 free(table);
1005}
1006
1007/**
1008 * xmlCopyNotationTable:
1009 * @table: A notation table
1010 *
1011 * Build a copy of a notation table.
1012 *
1013 * Returns the new xmlNotationTablePtr or NULL in case of error.
1014 */
1015xmlNotationTablePtr
1016xmlCopyNotationTable(xmlNotationTablePtr table) {
1017 xmlNotationTablePtr ret;
1018 xmlNotationPtr cur, nota;
1019 int i;
1020
1021 ret = (xmlNotationTablePtr) malloc(sizeof(xmlNotationTable));
1022 if (ret == NULL) {
1023 fprintf(stderr, "xmlCopyNotationTable: out of memory !\n");
1024 return(NULL);
1025 }
1026 ret->table = (xmlNotationPtr) malloc(table->max_notations *
1027 sizeof(xmlNotation));
1028 if (ret->table == NULL) {
1029 fprintf(stderr, "xmlCopyNotationTable: out of memory !\n");
1030 free(ret);
1031 return(NULL);
1032 }
1033 ret->max_notations = table->max_notations;
1034 ret->nb_notations = table->nb_notations;
1035 for (i = 0;i < ret->nb_notations;i++) {
1036 cur = &ret->table[i];
1037 nota = &table->table[i];
1038 if (nota->name != NULL)
1039 cur->name = xmlStrdup(nota->name);
1040 else
1041 cur->name = NULL;
1042 if (nota->PublicID != NULL)
1043 cur->PublicID = xmlStrdup(nota->PublicID);
1044 else
1045 cur->PublicID = NULL;
1046 if (nota->SystemID != NULL)
1047 cur->SystemID = xmlStrdup(nota->SystemID);
1048 else
1049 cur->SystemID = NULL;
1050 }
1051 return(ret);
1052}
1053
1054/**
1055 * xmlDumpNotationTable:
1056 * @table: A notation table
1057 *
1058 * This will dump the content of the notation table as an XML DTD definition
1059 *
1060 * NOTE: TODO an extra parameter allowing a reentant implementation will
1061 * be added.
1062 */
1063void
1064xmlDumpNotationTable(xmlNotationTablePtr table) {
1065 int i;
1066 xmlNotationPtr cur;
1067
1068 if (table == NULL) return;
1069
1070 for (i = 0;i < table->nb_notations;i++) {
1071 cur = &table->table[i];
1072 xmlBufferWriteChar("<!NOTATION ");
1073 xmlBufferWriteCHAR(cur->name);
1074 if (cur->PublicID != NULL) {
1075 xmlBufferWriteChar(" PUBLIC \"");
1076 xmlBufferWriteCHAR(cur->PublicID);
1077 xmlBufferWriteChar("\"");
1078 if (cur->SystemID != NULL) {
1079 xmlBufferWriteChar(" ");
1080 xmlBufferWriteCHAR(cur->SystemID);
1081 }
1082 } else {
1083 xmlBufferWriteChar(" SYSTEM ");
1084 xmlBufferWriteCHAR(cur->SystemID);
1085 }
1086 xmlBufferWriteChar(" >\n");
1087 }
1088}