blob: 409db5bd03b8fb9b6d1c0ab81d7db4a03c26e695 [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:
397 * @table: An element table
398 *
399 * This will dump the content of the element table as an XML DTD definition
400 *
401 * NOTE: TODO an extra parameter allowing a reentant implementation will
402 * be added.
403 */
404void
Daniel Veillard5099ae81999-04-21 20:12:07 +0000405xmlDumpElementTable(xmlBufferPtr buf, xmlElementTablePtr table) {
Daniel Veillard3b9def11999-01-31 22:15:06 +0000406 int i;
407 xmlElementPtr cur;
408
409 if (table == NULL) return;
410
411 for (i = 0;i < table->nb_elements;i++) {
412 cur = &table->table[i];
413 switch (cur->type) {
414 case XML_ELEMENT_TYPE_EMPTY:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000415 xmlBufferWriteChar(buf, "<!ELEMENT ");
416 xmlBufferWriteCHAR(buf, cur->name);
417 xmlBufferWriteChar(buf, " EMPTY>\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000418 break;
419 case XML_ELEMENT_TYPE_ANY:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000420 xmlBufferWriteChar(buf, "<!ELEMENT ");
421 xmlBufferWriteCHAR(buf, cur->name);
422 xmlBufferWriteChar(buf, " ANY>\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000423 break;
424 case XML_ELEMENT_TYPE_MIXED:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000425 xmlBufferWriteChar(buf, "<!ELEMENT ");
426 xmlBufferWriteCHAR(buf, cur->name);
427 xmlBufferWriteChar(buf, " ");
428 xmlDumpElementContent(buf, cur->content, 1);
429 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000430 break;
431 case XML_ELEMENT_TYPE_ELEMENT:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000432 xmlBufferWriteChar(buf, "<!ELEMENT ");
433 xmlBufferWriteCHAR(buf, cur->name);
434 xmlBufferWriteChar(buf, " ");
435 xmlDumpElementContent(buf, cur->content, 1);
436 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000437 break;
438 default:
439 fprintf(stderr,
440 "xmlDumpElementTable: internal: unknown type %d\n",
441 cur->type);
442 }
443 }
444}
Daniel Veillard1e346af1999-02-22 10:33:01 +0000445
446/**
447 * xmlCreateEnumeration:
448 * @name: the enumeration name or NULL
449 *
450 * create and initialize an enumeration attribute node.
451 *
452 * Returns the xmlEnumerationPtr just created or NULL in case
453 * of error.
454 */
455xmlEnumerationPtr
456xmlCreateEnumeration(CHAR *name) {
457 xmlEnumerationPtr ret;
458
459 ret = (xmlEnumerationPtr) malloc(sizeof(xmlEnumeration));
460 if (ret == NULL) {
461 fprintf(stderr, "xmlCreateEnumeration : malloc(%d) failed\n",
462 sizeof(xmlEnumeration));
463 return(NULL);
464 }
465
466 if (name != NULL)
467 ret->name = xmlStrdup(name);
468 else
469 ret->name = NULL;
470 ret->next = NULL;
471 return(ret);
472}
473
474/**
475 * xmlFreeEnumeration:
476 * @cur: the tree to free.
477 *
478 * free an enumeration attribute node (recursive).
479 */
480void
481xmlFreeEnumeration(xmlEnumerationPtr cur) {
482 if (cur == NULL) return;
483
484 if (cur->next != NULL) xmlFreeEnumeration(cur->next);
485
486 if (cur->name != NULL) free((CHAR *) cur->name);
487 memset(cur, -1, sizeof(xmlEnumeration));
488 free(cur);
489}
490
491/**
492 * xmlCopyEnumeration:
493 * @cur: the tree to copy.
494 *
495 * Copy an enumeration attribute node (recursive).
496 *
497 * Returns the xmlEnumerationPtr just created or NULL in case
498 * of error.
499 */
500xmlEnumerationPtr
501xmlCopyEnumeration(xmlEnumerationPtr cur) {
502 xmlEnumerationPtr ret;
503
504 if (cur == NULL) return(NULL);
505 ret = xmlCreateEnumeration((CHAR *) cur->name);
506
507 if (cur->next != NULL) ret->next = xmlCopyEnumeration(cur->next);
508 else ret->next = NULL;
509
510 return(ret);
511}
512
513/**
514 * xmlCreateAttributeTable:
515 *
516 * create and initialize an empty attribute hash table.
517 *
518 * Returns the xmlAttributeTablePtr just created or NULL in case
519 * of error.
520 */
521xmlAttributeTablePtr
522xmlCreateAttributeTable(void) {
523 xmlAttributeTablePtr ret;
524
525 ret = (xmlAttributeTablePtr)
526 malloc(sizeof(xmlAttributeTable));
527 if (ret == NULL) {
528 fprintf(stderr, "xmlCreateAttributeTable : malloc(%d) failed\n",
529 sizeof(xmlAttributeTable));
530 return(NULL);
531 }
532 ret->max_attributes = XML_MIN_ATTRIBUTE_TABLE;
533 ret->nb_attributes = 0;
534 ret->table = (xmlAttributePtr )
535 malloc(ret->max_attributes * sizeof(xmlAttribute));
536 if (ret == NULL) {
537 fprintf(stderr, "xmlCreateAttributeTable : malloc(%d) failed\n",
538 ret->max_attributes * sizeof(xmlAttribute));
539 free(ret);
540 return(NULL);
541 }
542 return(ret);
543}
544
545
546/**
547 * xmlAddAttributeDecl:
548 * @dtd: pointer to the DTD
549 * @elem: the element name
550 * @name: the attribute name
551 * @type: the attribute type
552 * @def: the attribute default type
553 * @defaultValue: the attribute default value
554 * @tree: if it's an enumeration, the associated list
555 *
556 * Register a new attribute declaration
557 *
558 * Returns NULL if not, othervise the entity
559 */
560xmlAttributePtr
Daniel Veillard517752b1999-04-05 12:20:10 +0000561xmlAddAttributeDecl(xmlDtdPtr dtd, const CHAR *elem, const CHAR *name,
562 int type, int def, const CHAR *defaultValue,
563 xmlEnumerationPtr tree) {
Daniel Veillard1e346af1999-02-22 10:33:01 +0000564 xmlAttributePtr ret, cur;
565 xmlAttributeTablePtr table;
566 int i;
567
568 if (dtd == NULL) {
569 fprintf(stderr, "xmlAddAttributeDecl: dtd == NULL\n");
570 return(NULL);
571 }
572 if (name == NULL) {
573 fprintf(stderr, "xmlAddAttributeDecl: name == NULL\n");
574 return(NULL);
575 }
576 if (elem == NULL) {
577 fprintf(stderr, "xmlAddAttributeDecl: elem == NULL\n");
578 return(NULL);
579 }
580 /* TODO: Lacks verifications !!! */
581 switch (type) {
582 case XML_ATTRIBUTE_CDATA:
583 break;
584 case XML_ATTRIBUTE_ID:
585 break;
586 case XML_ATTRIBUTE_IDREF:
587 break;
588 case XML_ATTRIBUTE_IDREFS:
589 break;
590 case XML_ATTRIBUTE_ENTITY:
591 break;
592 case XML_ATTRIBUTE_ENTITIES:
593 break;
594 case XML_ATTRIBUTE_NMTOKEN:
595 break;
596 case XML_ATTRIBUTE_NMTOKENS:
597 break;
598 case XML_ATTRIBUTE_ENUMERATION:
599 break;
600 case XML_ATTRIBUTE_NOTATION:
601 break;
602 default:
603 fprintf(stderr, "xmlAddAttributeDecl: unknown type %d\n", type);
604 return(NULL);
605 }
606
607 /*
608 * Create the Attribute table if needed.
609 */
610 table = dtd->attributes;
611 if (table == NULL)
612 table = dtd->attributes = xmlCreateAttributeTable();
613 if (table == NULL) {
614 fprintf(stderr, "xmlAddAttributeDecl: Table creation failed!\n");
615 return(NULL);
616 }
617
618 /*
619 * Validity Check:
620 * Search the DTD for previous declarations of the ATTLIST
621 */
622 for (i = 0;i < table->nb_attributes;i++) {
623 cur = &table->table[i];
624 if ((!xmlStrcmp(cur->name, name)) && (!xmlStrcmp(cur->elem, elem))) {
625 /*
626 * The attribute is already defined in this Dtd.
627 */
628 fprintf(stderr,
629 "xmlAddAttributeDecl: %s already defined\n", name);
630 }
631 }
632
633 /*
634 * Grow the table, if needed.
635 */
636 if (table->nb_attributes >= table->max_attributes) {
637 /*
638 * need more attributes.
639 */
640 table->max_attributes *= 2;
641 table->table = (xmlAttributePtr)
642 realloc(table->table, table->max_attributes * sizeof(xmlAttribute));
643 if (table->table) {
644 fprintf(stderr, "xmlAddAttributeDecl: out of memory\n");
645 return(NULL);
646 }
647 }
648 ret = &table->table[table->nb_attributes];
649
650 /*
651 * fill the structure.
652 */
653 ret->type = type;
654 ret->name = xmlStrdup(name);
655 ret->elem = xmlStrdup(elem);
656 ret->def = def;
657 ret->tree = tree;
658 if (defaultValue != NULL)
659 ret->defaultValue = xmlStrdup(defaultValue);
660 else
661 ret->defaultValue = NULL;
662 table->nb_attributes++;
663
664 return(ret);
665}
666
667/**
668 * xmlFreeAttribute:
669 * @elem: An attribute
670 *
671 * Deallocate the memory used by an attribute definition
672 */
673void
674xmlFreeAttribute(xmlAttributePtr attr) {
675 if (attr == NULL) return;
676 if (attr->tree != NULL)
677 xmlFreeEnumeration(attr->tree);
678 if (attr->elem != NULL)
679 free((CHAR *) attr->elem);
680 if (attr->name != NULL)
681 free((CHAR *) attr->name);
682 if (attr->defaultValue != NULL)
683 free((CHAR *) attr->defaultValue);
684 memset(attr, -1, sizeof(xmlAttribute));
685}
686
687/**
688 * xmlFreeAttributeTable:
689 * @table: An attribute table
690 *
691 * Deallocate the memory used by an entities hash table.
692 */
693void
694xmlFreeAttributeTable(xmlAttributeTablePtr table) {
695 int i;
696
697 if (table == NULL) return;
698
699 for (i = 0;i < table->nb_attributes;i++) {
700 xmlFreeAttribute(&table->table[i]);
701 }
702 free(table->table);
703 free(table);
704}
705
706/**
707 * xmlCopyAttributeTable:
708 * @table: An attribute table
709 *
710 * Build a copy of an attribute table.
711 *
712 * Returns the new xmlAttributeTablePtr or NULL in case of error.
713 */
714xmlAttributeTablePtr
715xmlCopyAttributeTable(xmlAttributeTablePtr table) {
716 xmlAttributeTablePtr ret;
717 xmlAttributePtr cur, attr;
718 int i;
719
720 ret = (xmlAttributeTablePtr) malloc(sizeof(xmlAttributeTable));
721 if (ret == NULL) {
722 fprintf(stderr, "xmlCopyAttributeTable: out of memory !\n");
723 return(NULL);
724 }
725 ret->table = (xmlAttributePtr) malloc(table->max_attributes *
726 sizeof(xmlAttribute));
727 if (ret->table == NULL) {
728 fprintf(stderr, "xmlCopyAttributeTable: out of memory !\n");
729 free(ret);
730 return(NULL);
731 }
732 ret->max_attributes = table->max_attributes;
733 ret->nb_attributes = table->nb_attributes;
734 for (i = 0;i < ret->nb_attributes;i++) {
735 cur = &ret->table[i];
736 attr = &table->table[i];
737 cur->type = attr->type;
738 cur->def = attr->def;
739 cur->tree = xmlCopyEnumeration(attr->tree);
740 if (attr->elem != NULL)
741 cur->elem = xmlStrdup(attr->elem);
742 else
743 cur->elem = NULL;
744 if (attr->name != NULL)
745 cur->name = xmlStrdup(attr->name);
746 else
747 cur->name = NULL;
748 if (attr->defaultValue != NULL)
749 cur->defaultValue = xmlStrdup(attr->defaultValue);
750 else
751 cur->defaultValue = NULL;
752 }
753 return(ret);
754}
755
756/**
757 * xmlDumpAttributeTable:
758 * @table: An attribute table
759 *
760 * This will dump the content of the attribute table as an XML DTD definition
761 *
762 * NOTE: TODO an extra parameter allowing a reentant implementation will
763 * be added.
764 */
765void
Daniel Veillard5099ae81999-04-21 20:12:07 +0000766xmlDumpAttributeTable(xmlBufferPtr buf, xmlAttributeTablePtr table) {
Daniel Veillard1e346af1999-02-22 10:33:01 +0000767 int i;
768 xmlAttributePtr cur;
769
770 if (table == NULL) return;
771
772 for (i = 0;i < table->nb_attributes;i++) {
773 cur = &table->table[i];
Daniel Veillard5099ae81999-04-21 20:12:07 +0000774 xmlBufferWriteChar(buf, "<!ATTLIST ");
775 xmlBufferWriteCHAR(buf, cur->elem);
776 xmlBufferWriteChar(buf, " ");
777 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000778 switch (cur->type) {
779 case XML_ATTRIBUTE_CDATA:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000780 xmlBufferWriteChar(buf, " CDATA");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000781 break;
782 case XML_ATTRIBUTE_ID:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000783 xmlBufferWriteChar(buf, " ID");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000784 break;
785 case XML_ATTRIBUTE_IDREF:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000786 xmlBufferWriteChar(buf, " IDREF");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000787 break;
788 case XML_ATTRIBUTE_IDREFS:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000789 xmlBufferWriteChar(buf, " IDREFS");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000790 break;
791 case XML_ATTRIBUTE_ENTITY:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000792 xmlBufferWriteChar(buf, " ENTITY");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000793 break;
794 case XML_ATTRIBUTE_ENTITIES:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000795 xmlBufferWriteChar(buf, " ENTITIES");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000796 break;
797 case XML_ATTRIBUTE_NMTOKEN:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000798 xmlBufferWriteChar(buf, " NMTOKEN");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000799 break;
800 case XML_ATTRIBUTE_NMTOKENS:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000801 xmlBufferWriteChar(buf, " NMTOKENS");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000802 break;
803 case XML_ATTRIBUTE_ENUMERATION:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000804 xmlBufferWriteChar(buf, " (pbm)");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000805 break;
806 case XML_ATTRIBUTE_NOTATION:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000807 xmlBufferWriteChar(buf, " NOTATION (pbm)");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000808 break;
809 default:
810 fprintf(stderr,
811 "xmlDumpAttributeTable: internal: unknown type %d\n",
812 cur->type);
813 }
814 switch (cur->def) {
815 case XML_ATTRIBUTE_NONE:
816 break;
817 case XML_ATTRIBUTE_REQUIRED:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000818 xmlBufferWriteChar(buf, " #REQUIRED");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000819 break;
820 case XML_ATTRIBUTE_IMPLIED:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000821 xmlBufferWriteChar(buf, " #IMPLIED");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000822 if (cur->defaultValue != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +0000823 xmlBufferWriteChar(buf, " \"");
824 xmlBufferWriteCHAR(buf, cur->defaultValue);
825 xmlBufferWriteChar(buf, "\"");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000826 }
827 break;
828 case XML_ATTRIBUTE_FIXED:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000829 xmlBufferWriteChar(buf, " #FIXED \"");
830 xmlBufferWriteCHAR(buf, cur->defaultValue);
831 xmlBufferWriteChar(buf, "\"");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000832 break;
833 default:
834 fprintf(stderr,
835 "xmlDumpAttributeTable: internal: unknown default %d\n",
836 cur->def);
837 }
Daniel Veillard5099ae81999-04-21 20:12:07 +0000838 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000839 }
840}
841
842/************************************************************************
843 * *
844 * NOTATIONs *
845 * *
846 ************************************************************************/
847/**
848 * xmlCreateNotationTable:
849 *
850 * create and initialize an empty notation hash table.
851 *
852 * Returns the xmlNotationTablePtr just created or NULL in case
853 * of error.
854 */
855xmlNotationTablePtr
856xmlCreateNotationTable(void) {
857 xmlNotationTablePtr ret;
858
859 ret = (xmlNotationTablePtr)
860 malloc(sizeof(xmlNotationTable));
861 if (ret == NULL) {
862 fprintf(stderr, "xmlCreateNotationTable : malloc(%d) failed\n",
863 sizeof(xmlNotationTable));
864 return(NULL);
865 }
866 ret->max_notations = XML_MIN_NOTATION_TABLE;
867 ret->nb_notations = 0;
868 ret->table = (xmlNotationPtr )
869 malloc(ret->max_notations * sizeof(xmlNotation));
870 if (ret == NULL) {
871 fprintf(stderr, "xmlCreateNotationTable : malloc(%d) failed\n",
872 ret->max_notations * sizeof(xmlNotation));
873 free(ret);
874 return(NULL);
875 }
876 return(ret);
877}
878
879
880/**
881 * xmlAddNotationDecl:
882 * @dtd: pointer to the DTD
883 * @name: the entity name
884 * @PublicID: the public identifier or NULL
885 * @SystemID: the system identifier or NULL
886 *
887 * Register a new notation declaration
888 *
889 * Returns NULL if not, othervise the entity
890 */
891xmlNotationPtr
Daniel Veillard517752b1999-04-05 12:20:10 +0000892xmlAddNotationDecl(xmlDtdPtr dtd, const CHAR *name, const CHAR *PublicID,
893 const CHAR *SystemID) {
Daniel Veillard1e346af1999-02-22 10:33:01 +0000894 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
Daniel Veillard5099ae81999-04-21 20:12:07 +00001064xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
Daniel Veillard1e346af1999-02-22 10:33:01 +00001065 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];
Daniel Veillard5099ae81999-04-21 20:12:07 +00001072 xmlBufferWriteChar(buf, "<!NOTATION ");
1073 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001074 if (cur->PublicID != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00001075 xmlBufferWriteChar(buf, " PUBLIC \"");
1076 xmlBufferWriteCHAR(buf, cur->PublicID);
1077 xmlBufferWriteChar(buf, "\"");
Daniel Veillard1e346af1999-02-22 10:33:01 +00001078 if (cur->SystemID != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00001079 xmlBufferWriteChar(buf, " ");
1080 xmlBufferWriteCHAR(buf, cur->SystemID);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001081 }
1082 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00001083 xmlBufferWriteChar(buf, " SYSTEM ");
1084 xmlBufferWriteCHAR(buf, cur->SystemID);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001085 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00001086 xmlBufferWriteChar(buf, " >\n");
Daniel Veillard1e346af1999-02-22 10:33:01 +00001087 }
1088}