blob: 0a62b7ee8bef834c9f26d0b1ee050f63b00fdeb1 [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);
Daniel Veillard14fff061999-06-22 21:49:07 +000081 if (ret == NULL) {
82 fprintf(stderr, "xmlCopyElementContent : out of memory\n");
83 return(NULL);
84 }
85 ret->ocur = cur->ocur;
86 if (cur->c1 != NULL) ret->c1 = xmlCopyElementContent(cur->c1);
87 if (cur->c2 != NULL) ret->c2 = xmlCopyElementContent(cur->c2);
Daniel Veillard1e346af1999-02-22 10:33:01 +000088 return(ret);
Daniel Veillard3b9def11999-01-31 22:15:06 +000089}
90
91/**
Daniel Veillard1899e851999-02-01 12:18:54 +000092 * xmlFreeElementContent:
93 * @cur: the element content tree to free
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000094 *
95 * Free an element content structure. This is a recursive call !
96 */
97void
98xmlFreeElementContent(xmlElementContentPtr cur) {
Daniel Veillard1e346af1999-02-22 10:33:01 +000099 if (cur == NULL) return;
100 if (cur->c1 != NULL) xmlFreeElementContent(cur->c1);
101 if (cur->c2 != NULL) xmlFreeElementContent(cur->c2);
102 if (cur->name != NULL) free((CHAR *) cur->name);
103 memset(cur, -1, sizeof(xmlElementContent));
104 free(cur);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000105}
106
Daniel Veillard1899e851999-02-01 12:18:54 +0000107/**
108 * xmlDumpElementContent:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000109 * @buf: An XML buffer
Daniel Veillard1899e851999-02-01 12:18:54 +0000110 * @content: An element table
111 * @glob: 1 if one must print the englobing parenthesis, 0 otherwise
112 *
113 * This will dump the content of the element table as an XML DTD definition
Daniel Veillard1899e851999-02-01 12:18:54 +0000114 */
115void
Daniel Veillard5099ae81999-04-21 20:12:07 +0000116xmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content, int glob) {
Daniel Veillard1899e851999-02-01 12:18:54 +0000117 if (content == NULL) return;
118
Daniel Veillard5099ae81999-04-21 20:12:07 +0000119 if (glob) xmlBufferWriteChar(buf, "(");
Daniel Veillard1899e851999-02-01 12:18:54 +0000120 switch (content->type) {
121 case XML_ELEMENT_CONTENT_PCDATA:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000122 xmlBufferWriteChar(buf, "#PCDATA");
Daniel Veillard1899e851999-02-01 12:18:54 +0000123 break;
124 case XML_ELEMENT_CONTENT_ELEMENT:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000125 xmlBufferWriteCHAR(buf, content->name);
Daniel Veillard1899e851999-02-01 12:18:54 +0000126 break;
127 case XML_ELEMENT_CONTENT_SEQ:
128 if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
129 (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
Daniel Veillard5099ae81999-04-21 20:12:07 +0000130 xmlDumpElementContent(buf, content->c1, 1);
Daniel Veillard1899e851999-02-01 12:18:54 +0000131 else
Daniel Veillard5099ae81999-04-21 20:12:07 +0000132 xmlDumpElementContent(buf, content->c1, 0);
133 xmlBufferWriteChar(buf, " , ");
Daniel Veillard1899e851999-02-01 12:18:54 +0000134 if (content->c2->type == XML_ELEMENT_CONTENT_OR)
Daniel Veillard5099ae81999-04-21 20:12:07 +0000135 xmlDumpElementContent(buf, content->c2, 1);
Daniel Veillard1899e851999-02-01 12:18:54 +0000136 else
Daniel Veillard5099ae81999-04-21 20:12:07 +0000137 xmlDumpElementContent(buf, content->c2, 0);
Daniel Veillard1899e851999-02-01 12:18:54 +0000138 break;
139 case XML_ELEMENT_CONTENT_OR:
140 if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
141 (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
Daniel Veillard5099ae81999-04-21 20:12:07 +0000142 xmlDumpElementContent(buf, content->c1, 1);
Daniel Veillard1899e851999-02-01 12:18:54 +0000143 else
Daniel Veillard5099ae81999-04-21 20:12:07 +0000144 xmlDumpElementContent(buf, content->c1, 0);
145 xmlBufferWriteChar(buf, " | ");
Daniel Veillard1899e851999-02-01 12:18:54 +0000146 if (content->c2->type == XML_ELEMENT_CONTENT_SEQ)
Daniel Veillard5099ae81999-04-21 20:12:07 +0000147 xmlDumpElementContent(buf, content->c2, 1);
Daniel Veillard1899e851999-02-01 12:18:54 +0000148 else
Daniel Veillard5099ae81999-04-21 20:12:07 +0000149 xmlDumpElementContent(buf, content->c2, 0);
Daniel Veillard1899e851999-02-01 12:18:54 +0000150 break;
151 default:
152 fprintf(stderr, "xmlDumpElementContent: unknown type %d\n",
153 content->type);
154 }
155 if (glob)
Daniel Veillard5099ae81999-04-21 20:12:07 +0000156 xmlBufferWriteChar(buf, ")");
Daniel Veillard1899e851999-02-01 12:18:54 +0000157 switch (content->ocur) {
158 case XML_ELEMENT_CONTENT_ONCE:
159 break;
160 case XML_ELEMENT_CONTENT_OPT:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000161 xmlBufferWriteChar(buf, "?");
Daniel Veillard1899e851999-02-01 12:18:54 +0000162 break;
163 case XML_ELEMENT_CONTENT_MULT:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000164 xmlBufferWriteChar(buf, "*");
Daniel Veillard1899e851999-02-01 12:18:54 +0000165 break;
166 case XML_ELEMENT_CONTENT_PLUS:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000167 xmlBufferWriteChar(buf, "+");
Daniel Veillard1899e851999-02-01 12:18:54 +0000168 break;
169 }
170}
171
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000172/****************************************************************
173 * *
174 * Registration of DTD declarations *
175 * *
176 ****************************************************************/
177
Daniel Veillard3b9def11999-01-31 22:15:06 +0000178/**
179 * xmlCreateElementTable:
180 *
181 * create and initialize an empty element hash table.
182 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000183 * Returns the xmlElementTablePtr just created or NULL in case of error.
Daniel Veillard3b9def11999-01-31 22:15:06 +0000184 */
185xmlElementTablePtr
186xmlCreateElementTable(void) {
187 xmlElementTablePtr ret;
188
189 ret = (xmlElementTablePtr)
190 malloc(sizeof(xmlElementTable));
191 if (ret == NULL) {
192 fprintf(stderr, "xmlCreateElementTable : malloc(%d) failed\n",
193 sizeof(xmlElementTable));
194 return(NULL);
195 }
Daniel Veillard1e346af1999-02-22 10:33:01 +0000196 ret->max_elements = XML_MIN_ELEMENT_TABLE;
Daniel Veillard3b9def11999-01-31 22:15:06 +0000197 ret->nb_elements = 0;
198 ret->table = (xmlElementPtr )
199 malloc(ret->max_elements * sizeof(xmlElement));
200 if (ret == NULL) {
201 fprintf(stderr, "xmlCreateElementTable : malloc(%d) failed\n",
202 ret->max_elements * sizeof(xmlElement));
203 free(ret);
204 return(NULL);
205 }
206 return(ret);
207}
208
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000209
210/**
211 * xmlAddElementDecl:
Daniel Veillard1e346af1999-02-22 10:33:01 +0000212 * @dtd: pointer to the DTD
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000213 * @name: the entity name
Daniel Veillard1e346af1999-02-22 10:33:01 +0000214 * @type: the element type
215 * @content: the element content tree or NULL
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000216 *
217 * Register a new element declaration
218 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000219 * Returns NULL if not, othervise the entity
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000220 */
221xmlElementPtr
Daniel Veillard517752b1999-04-05 12:20:10 +0000222xmlAddElementDecl(xmlDtdPtr dtd, const CHAR *name, int type,
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000223 xmlElementContentPtr content) {
Daniel Veillard3b9def11999-01-31 22:15:06 +0000224 xmlElementPtr ret, cur;
225 xmlElementTablePtr table;
226 int i;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000227
228 if (dtd == NULL) {
229 fprintf(stderr, "xmlAddElementDecl: dtd == NULL\n");
230 return(NULL);
231 }
232 if (name == NULL) {
233 fprintf(stderr, "xmlAddElementDecl: name == NULL\n");
234 return(NULL);
235 }
236 switch (type) {
237 case XML_ELEMENT_TYPE_EMPTY:
238 if (content != NULL) {
239 fprintf(stderr,
240 "xmlAddElementDecl: content != NULL for EMPTY\n");
241 return(NULL);
242 }
243 break;
244 case XML_ELEMENT_TYPE_ANY:
245 if (content != NULL) {
246 fprintf(stderr,
247 "xmlAddElementDecl: content != NULL for ANY\n");
248 return(NULL);
249 }
250 break;
251 case XML_ELEMENT_TYPE_MIXED:
252 if (content == NULL) {
253 fprintf(stderr,
254 "xmlAddElementDecl: content == NULL for MIXED\n");
255 return(NULL);
256 }
257 break;
258 case XML_ELEMENT_TYPE_ELEMENT:
259 if (content == NULL) {
260 fprintf(stderr,
261 "xmlAddElementDecl: content == NULL for ELEMENT\n");
262 return(NULL);
263 }
264 break;
265 default:
266 fprintf(stderr, "xmlAddElementDecl: unknown type %d\n", type);
267 return(NULL);
268 }
269
270 /*
Daniel Veillard3b9def11999-01-31 22:15:06 +0000271 * Create the Element table if needed.
272 */
273 table = dtd->elements;
274 if (table == NULL)
275 table = dtd->elements = xmlCreateElementTable();
276 if (table == NULL) {
277 fprintf(stderr, "xmlAddElementDecl: Table creation failed!\n");
278 return(NULL);
279 }
280
281 /*
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000282 * Validity Check:
283 * Search the DTD for previous declarations of the ELEMENT
284 */
Daniel Veillard3b9def11999-01-31 22:15:06 +0000285 for (i = 0;i < table->nb_elements;i++) {
286 cur = &table->table[i];
287 if (!xmlStrcmp(cur->name, name)) {
288 /*
289 * The element is already defined in this Dtd.
290 */
291 fprintf(stderr,
292 "xmlAddElementDecl: %s already defined\n", name);
293 return(NULL);
294 }
295 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000296
297 /*
Daniel Veillard3b9def11999-01-31 22:15:06 +0000298 * Grow the table, if needed.
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000299 */
Daniel Veillard3b9def11999-01-31 22:15:06 +0000300 if (table->nb_elements >= table->max_elements) {
301 /*
302 * need more elements.
303 */
304 table->max_elements *= 2;
305 table->table = (xmlElementPtr)
306 realloc(table->table, table->max_elements * sizeof(xmlElement));
307 if (table->table) {
308 fprintf(stderr, "xmlAddElementDecl: out of memory\n");
309 return(NULL);
310 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000311 }
Daniel Veillard3b9def11999-01-31 22:15:06 +0000312 ret = &table->table[table->nb_elements];
313
314 /*
315 * fill the structure.
316 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000317 ret->type = type;
318 ret->name = xmlStrdup(name);
Daniel Veillard14fff061999-06-22 21:49:07 +0000319 ret->content = xmlCopyElementContent(content);
Daniel Veillard3b9def11999-01-31 22:15:06 +0000320 table->nb_elements++;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000321
322 return(ret);
323}
324
Daniel Veillard3b9def11999-01-31 22:15:06 +0000325/**
326 * xmlFreeElement:
327 * @elem: An element
328 *
329 * Deallocate the memory used by an element definition
330 */
331void
332xmlFreeElement(xmlElementPtr elem) {
333 if (elem == NULL) return;
334 xmlFreeElementContent(elem->content);
335 if (elem->name != NULL)
336 free((CHAR *) elem->name);
337 memset(elem, -1, sizeof(xmlElement));
Daniel Veillard3b9def11999-01-31 22:15:06 +0000338}
339
340/**
341 * xmlFreeElementTable:
342 * @table: An element table
343 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000344 * Deallocate the memory used by an element hash table.
Daniel Veillard3b9def11999-01-31 22:15:06 +0000345 */
346void
347xmlFreeElementTable(xmlElementTablePtr table) {
348 int i;
349
350 if (table == NULL) return;
351
352 for (i = 0;i < table->nb_elements;i++) {
353 xmlFreeElement(&table->table[i]);
354 }
355 free(table->table);
356 free(table);
357}
358
359/**
360 * xmlCopyElementTable:
361 * @table: An element table
362 *
363 * Build a copy of an element table.
364 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000365 * Returns the new xmlElementTablePtr or NULL in case of error.
Daniel Veillard3b9def11999-01-31 22:15:06 +0000366 */
367xmlElementTablePtr
368xmlCopyElementTable(xmlElementTablePtr table) {
369 xmlElementTablePtr ret;
370 xmlElementPtr cur, ent;
371 int i;
372
373 ret = (xmlElementTablePtr) malloc(sizeof(xmlElementTable));
374 if (ret == NULL) {
375 fprintf(stderr, "xmlCopyElementTable: out of memory !\n");
376 return(NULL);
377 }
378 ret->table = (xmlElementPtr) malloc(table->max_elements *
379 sizeof(xmlElement));
380 if (ret->table == NULL) {
381 fprintf(stderr, "xmlCopyElementTable: out of memory !\n");
382 free(ret);
383 return(NULL);
384 }
385 ret->max_elements = table->max_elements;
386 ret->nb_elements = table->nb_elements;
387 for (i = 0;i < ret->nb_elements;i++) {
388 cur = &ret->table[i];
389 ent = &table->table[i];
390 cur->type = ent->type;
391 if (ent->name != NULL)
392 cur->name = xmlStrdup(ent->name);
393 else
394 cur->name = NULL;
395 cur->content = xmlCopyElementContent(ent->content);
396 }
397 return(ret);
398}
399
400/**
401 * xmlDumpElementTable:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000402 * @buf: the XML buffer output
Daniel Veillard3b9def11999-01-31 22:15:06 +0000403 * @table: An element table
404 *
405 * This will dump the content of the element table as an XML DTD definition
Daniel Veillard3b9def11999-01-31 22:15:06 +0000406 */
407void
Daniel Veillard5099ae81999-04-21 20:12:07 +0000408xmlDumpElementTable(xmlBufferPtr buf, xmlElementTablePtr table) {
Daniel Veillard3b9def11999-01-31 22:15:06 +0000409 int i;
410 xmlElementPtr cur;
411
412 if (table == NULL) return;
413
414 for (i = 0;i < table->nb_elements;i++) {
415 cur = &table->table[i];
416 switch (cur->type) {
417 case XML_ELEMENT_TYPE_EMPTY:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000418 xmlBufferWriteChar(buf, "<!ELEMENT ");
419 xmlBufferWriteCHAR(buf, cur->name);
420 xmlBufferWriteChar(buf, " EMPTY>\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000421 break;
422 case XML_ELEMENT_TYPE_ANY:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000423 xmlBufferWriteChar(buf, "<!ELEMENT ");
424 xmlBufferWriteCHAR(buf, cur->name);
425 xmlBufferWriteChar(buf, " ANY>\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000426 break;
427 case XML_ELEMENT_TYPE_MIXED:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000428 xmlBufferWriteChar(buf, "<!ELEMENT ");
429 xmlBufferWriteCHAR(buf, cur->name);
430 xmlBufferWriteChar(buf, " ");
431 xmlDumpElementContent(buf, cur->content, 1);
432 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000433 break;
434 case XML_ELEMENT_TYPE_ELEMENT:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000435 xmlBufferWriteChar(buf, "<!ELEMENT ");
436 xmlBufferWriteCHAR(buf, cur->name);
437 xmlBufferWriteChar(buf, " ");
438 xmlDumpElementContent(buf, cur->content, 1);
439 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000440 break;
441 default:
442 fprintf(stderr,
443 "xmlDumpElementTable: internal: unknown type %d\n",
444 cur->type);
445 }
446 }
447}
Daniel Veillard1e346af1999-02-22 10:33:01 +0000448
449/**
450 * xmlCreateEnumeration:
451 * @name: the enumeration name or NULL
452 *
453 * create and initialize an enumeration attribute node.
454 *
455 * Returns the xmlEnumerationPtr just created or NULL in case
456 * of error.
457 */
458xmlEnumerationPtr
459xmlCreateEnumeration(CHAR *name) {
460 xmlEnumerationPtr ret;
461
462 ret = (xmlEnumerationPtr) malloc(sizeof(xmlEnumeration));
463 if (ret == NULL) {
464 fprintf(stderr, "xmlCreateEnumeration : malloc(%d) failed\n",
465 sizeof(xmlEnumeration));
466 return(NULL);
467 }
468
469 if (name != NULL)
470 ret->name = xmlStrdup(name);
471 else
472 ret->name = NULL;
473 ret->next = NULL;
474 return(ret);
475}
476
477/**
478 * xmlFreeEnumeration:
479 * @cur: the tree to free.
480 *
481 * free an enumeration attribute node (recursive).
482 */
483void
484xmlFreeEnumeration(xmlEnumerationPtr cur) {
485 if (cur == NULL) return;
486
487 if (cur->next != NULL) xmlFreeEnumeration(cur->next);
488
489 if (cur->name != NULL) free((CHAR *) cur->name);
490 memset(cur, -1, sizeof(xmlEnumeration));
491 free(cur);
492}
493
494/**
495 * xmlCopyEnumeration:
496 * @cur: the tree to copy.
497 *
498 * Copy an enumeration attribute node (recursive).
499 *
500 * Returns the xmlEnumerationPtr just created or NULL in case
501 * of error.
502 */
503xmlEnumerationPtr
504xmlCopyEnumeration(xmlEnumerationPtr cur) {
505 xmlEnumerationPtr ret;
506
507 if (cur == NULL) return(NULL);
508 ret = xmlCreateEnumeration((CHAR *) cur->name);
509
510 if (cur->next != NULL) ret->next = xmlCopyEnumeration(cur->next);
511 else ret->next = NULL;
512
513 return(ret);
514}
515
516/**
517 * xmlCreateAttributeTable:
518 *
519 * create and initialize an empty attribute hash table.
520 *
521 * Returns the xmlAttributeTablePtr just created or NULL in case
522 * of error.
523 */
524xmlAttributeTablePtr
525xmlCreateAttributeTable(void) {
526 xmlAttributeTablePtr ret;
527
528 ret = (xmlAttributeTablePtr)
529 malloc(sizeof(xmlAttributeTable));
530 if (ret == NULL) {
531 fprintf(stderr, "xmlCreateAttributeTable : malloc(%d) failed\n",
532 sizeof(xmlAttributeTable));
533 return(NULL);
534 }
535 ret->max_attributes = XML_MIN_ATTRIBUTE_TABLE;
536 ret->nb_attributes = 0;
537 ret->table = (xmlAttributePtr )
538 malloc(ret->max_attributes * sizeof(xmlAttribute));
539 if (ret == NULL) {
540 fprintf(stderr, "xmlCreateAttributeTable : malloc(%d) failed\n",
541 ret->max_attributes * sizeof(xmlAttribute));
542 free(ret);
543 return(NULL);
544 }
545 return(ret);
546}
547
548
549/**
550 * xmlAddAttributeDecl:
551 * @dtd: pointer to the DTD
552 * @elem: the element name
553 * @name: the attribute name
554 * @type: the attribute type
555 * @def: the attribute default type
556 * @defaultValue: the attribute default value
557 * @tree: if it's an enumeration, the associated list
558 *
559 * Register a new attribute declaration
560 *
561 * Returns NULL if not, othervise the entity
562 */
563xmlAttributePtr
Daniel Veillard517752b1999-04-05 12:20:10 +0000564xmlAddAttributeDecl(xmlDtdPtr dtd, const CHAR *elem, const CHAR *name,
565 int type, int def, const CHAR *defaultValue,
566 xmlEnumerationPtr tree) {
Daniel Veillard1e346af1999-02-22 10:33:01 +0000567 xmlAttributePtr ret, cur;
568 xmlAttributeTablePtr table;
569 int i;
570
571 if (dtd == NULL) {
572 fprintf(stderr, "xmlAddAttributeDecl: dtd == NULL\n");
573 return(NULL);
574 }
575 if (name == NULL) {
576 fprintf(stderr, "xmlAddAttributeDecl: name == NULL\n");
577 return(NULL);
578 }
579 if (elem == NULL) {
580 fprintf(stderr, "xmlAddAttributeDecl: elem == NULL\n");
581 return(NULL);
582 }
583 /* TODO: Lacks verifications !!! */
584 switch (type) {
585 case XML_ATTRIBUTE_CDATA:
586 break;
587 case XML_ATTRIBUTE_ID:
588 break;
589 case XML_ATTRIBUTE_IDREF:
590 break;
591 case XML_ATTRIBUTE_IDREFS:
592 break;
593 case XML_ATTRIBUTE_ENTITY:
594 break;
595 case XML_ATTRIBUTE_ENTITIES:
596 break;
597 case XML_ATTRIBUTE_NMTOKEN:
598 break;
599 case XML_ATTRIBUTE_NMTOKENS:
600 break;
601 case XML_ATTRIBUTE_ENUMERATION:
602 break;
603 case XML_ATTRIBUTE_NOTATION:
604 break;
605 default:
606 fprintf(stderr, "xmlAddAttributeDecl: unknown type %d\n", type);
607 return(NULL);
608 }
609
610 /*
611 * Create the Attribute table if needed.
612 */
613 table = dtd->attributes;
614 if (table == NULL)
615 table = dtd->attributes = xmlCreateAttributeTable();
616 if (table == NULL) {
617 fprintf(stderr, "xmlAddAttributeDecl: Table creation failed!\n");
618 return(NULL);
619 }
620
621 /*
622 * Validity Check:
623 * Search the DTD for previous declarations of the ATTLIST
624 */
625 for (i = 0;i < table->nb_attributes;i++) {
626 cur = &table->table[i];
627 if ((!xmlStrcmp(cur->name, name)) && (!xmlStrcmp(cur->elem, elem))) {
628 /*
629 * The attribute is already defined in this Dtd.
630 */
631 fprintf(stderr,
632 "xmlAddAttributeDecl: %s already defined\n", name);
633 }
634 }
635
636 /*
637 * Grow the table, if needed.
638 */
639 if (table->nb_attributes >= table->max_attributes) {
640 /*
641 * need more attributes.
642 */
643 table->max_attributes *= 2;
644 table->table = (xmlAttributePtr)
645 realloc(table->table, table->max_attributes * sizeof(xmlAttribute));
646 if (table->table) {
647 fprintf(stderr, "xmlAddAttributeDecl: out of memory\n");
648 return(NULL);
649 }
650 }
651 ret = &table->table[table->nb_attributes];
652
653 /*
654 * fill the structure.
655 */
656 ret->type = type;
657 ret->name = xmlStrdup(name);
658 ret->elem = xmlStrdup(elem);
659 ret->def = def;
660 ret->tree = tree;
661 if (defaultValue != NULL)
662 ret->defaultValue = xmlStrdup(defaultValue);
663 else
664 ret->defaultValue = NULL;
665 table->nb_attributes++;
666
667 return(ret);
668}
669
670/**
671 * xmlFreeAttribute:
672 * @elem: An attribute
673 *
674 * Deallocate the memory used by an attribute definition
675 */
676void
677xmlFreeAttribute(xmlAttributePtr attr) {
678 if (attr == NULL) return;
679 if (attr->tree != NULL)
680 xmlFreeEnumeration(attr->tree);
681 if (attr->elem != NULL)
682 free((CHAR *) attr->elem);
683 if (attr->name != NULL)
684 free((CHAR *) attr->name);
685 if (attr->defaultValue != NULL)
686 free((CHAR *) attr->defaultValue);
687 memset(attr, -1, sizeof(xmlAttribute));
688}
689
690/**
691 * xmlFreeAttributeTable:
692 * @table: An attribute table
693 *
694 * Deallocate the memory used by an entities hash table.
695 */
696void
697xmlFreeAttributeTable(xmlAttributeTablePtr table) {
698 int i;
699
700 if (table == NULL) return;
701
702 for (i = 0;i < table->nb_attributes;i++) {
703 xmlFreeAttribute(&table->table[i]);
704 }
705 free(table->table);
706 free(table);
707}
708
709/**
710 * xmlCopyAttributeTable:
711 * @table: An attribute table
712 *
713 * Build a copy of an attribute table.
714 *
715 * Returns the new xmlAttributeTablePtr or NULL in case of error.
716 */
717xmlAttributeTablePtr
718xmlCopyAttributeTable(xmlAttributeTablePtr table) {
719 xmlAttributeTablePtr ret;
720 xmlAttributePtr cur, attr;
721 int i;
722
723 ret = (xmlAttributeTablePtr) malloc(sizeof(xmlAttributeTable));
724 if (ret == NULL) {
725 fprintf(stderr, "xmlCopyAttributeTable: out of memory !\n");
726 return(NULL);
727 }
728 ret->table = (xmlAttributePtr) malloc(table->max_attributes *
729 sizeof(xmlAttribute));
730 if (ret->table == NULL) {
731 fprintf(stderr, "xmlCopyAttributeTable: out of memory !\n");
732 free(ret);
733 return(NULL);
734 }
735 ret->max_attributes = table->max_attributes;
736 ret->nb_attributes = table->nb_attributes;
737 for (i = 0;i < ret->nb_attributes;i++) {
738 cur = &ret->table[i];
739 attr = &table->table[i];
740 cur->type = attr->type;
741 cur->def = attr->def;
742 cur->tree = xmlCopyEnumeration(attr->tree);
743 if (attr->elem != NULL)
744 cur->elem = xmlStrdup(attr->elem);
745 else
746 cur->elem = NULL;
747 if (attr->name != NULL)
748 cur->name = xmlStrdup(attr->name);
749 else
750 cur->name = NULL;
751 if (attr->defaultValue != NULL)
752 cur->defaultValue = xmlStrdup(attr->defaultValue);
753 else
754 cur->defaultValue = NULL;
755 }
756 return(ret);
757}
758
759/**
760 * xmlDumpAttributeTable:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000761 * @buf: the XML buffer output
Daniel Veillard1e346af1999-02-22 10:33:01 +0000762 * @table: An attribute table
763 *
764 * This will dump the content of the attribute table as an XML DTD definition
Daniel Veillard1e346af1999-02-22 10:33:01 +0000765 */
766void
Daniel Veillard5099ae81999-04-21 20:12:07 +0000767xmlDumpAttributeTable(xmlBufferPtr buf, xmlAttributeTablePtr table) {
Daniel Veillard1e346af1999-02-22 10:33:01 +0000768 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];
Daniel Veillard5099ae81999-04-21 20:12:07 +0000775 xmlBufferWriteChar(buf, "<!ATTLIST ");
776 xmlBufferWriteCHAR(buf, cur->elem);
777 xmlBufferWriteChar(buf, " ");
778 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000779 switch (cur->type) {
780 case XML_ATTRIBUTE_CDATA:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000781 xmlBufferWriteChar(buf, " CDATA");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000782 break;
783 case XML_ATTRIBUTE_ID:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000784 xmlBufferWriteChar(buf, " ID");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000785 break;
786 case XML_ATTRIBUTE_IDREF:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000787 xmlBufferWriteChar(buf, " IDREF");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000788 break;
789 case XML_ATTRIBUTE_IDREFS:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000790 xmlBufferWriteChar(buf, " IDREFS");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000791 break;
792 case XML_ATTRIBUTE_ENTITY:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000793 xmlBufferWriteChar(buf, " ENTITY");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000794 break;
795 case XML_ATTRIBUTE_ENTITIES:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000796 xmlBufferWriteChar(buf, " ENTITIES");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000797 break;
798 case XML_ATTRIBUTE_NMTOKEN:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000799 xmlBufferWriteChar(buf, " NMTOKEN");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000800 break;
801 case XML_ATTRIBUTE_NMTOKENS:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000802 xmlBufferWriteChar(buf, " NMTOKENS");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000803 break;
804 case XML_ATTRIBUTE_ENUMERATION:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000805 xmlBufferWriteChar(buf, " (pbm)");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000806 break;
807 case XML_ATTRIBUTE_NOTATION:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000808 xmlBufferWriteChar(buf, " NOTATION (pbm)");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000809 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:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000819 xmlBufferWriteChar(buf, " #REQUIRED");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000820 break;
821 case XML_ATTRIBUTE_IMPLIED:
Daniel Veillard5099ae81999-04-21 20:12:07 +0000822 xmlBufferWriteChar(buf, " #IMPLIED");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000823 if (cur->defaultValue != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +0000824 xmlBufferWriteChar(buf, " ");
825 xmlBufferWriteQuotedString(buf, cur->defaultValue);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000826 }
827 break;
828 case XML_ATTRIBUTE_FIXED:
Daniel Veillard011b63c1999-06-02 17:44:04 +0000829 xmlBufferWriteChar(buf, " #FIXED ");
830 xmlBufferWriteQuotedString(buf, cur->defaultValue);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000831 break;
832 default:
833 fprintf(stderr,
834 "xmlDumpAttributeTable: internal: unknown default %d\n",
835 cur->def);
836 }
Daniel Veillard5099ae81999-04-21 20:12:07 +0000837 xmlBufferWriteChar(buf, ">\n");
Daniel Veillard1e346af1999-02-22 10:33:01 +0000838 }
839}
840
841/************************************************************************
842 * *
843 * NOTATIONs *
844 * *
845 ************************************************************************/
846/**
847 * xmlCreateNotationTable:
848 *
849 * create and initialize an empty notation hash table.
850 *
851 * Returns the xmlNotationTablePtr just created or NULL in case
852 * of error.
853 */
854xmlNotationTablePtr
855xmlCreateNotationTable(void) {
856 xmlNotationTablePtr ret;
857
858 ret = (xmlNotationTablePtr)
859 malloc(sizeof(xmlNotationTable));
860 if (ret == NULL) {
861 fprintf(stderr, "xmlCreateNotationTable : malloc(%d) failed\n",
862 sizeof(xmlNotationTable));
863 return(NULL);
864 }
865 ret->max_notations = XML_MIN_NOTATION_TABLE;
866 ret->nb_notations = 0;
867 ret->table = (xmlNotationPtr )
868 malloc(ret->max_notations * sizeof(xmlNotation));
869 if (ret == NULL) {
870 fprintf(stderr, "xmlCreateNotationTable : malloc(%d) failed\n",
871 ret->max_notations * sizeof(xmlNotation));
872 free(ret);
873 return(NULL);
874 }
875 return(ret);
876}
877
878
879/**
880 * xmlAddNotationDecl:
881 * @dtd: pointer to the DTD
882 * @name: the entity name
883 * @PublicID: the public identifier or NULL
884 * @SystemID: the system identifier or NULL
885 *
886 * Register a new notation declaration
887 *
888 * Returns NULL if not, othervise the entity
889 */
890xmlNotationPtr
Daniel Veillard517752b1999-04-05 12:20:10 +0000891xmlAddNotationDecl(xmlDtdPtr dtd, const CHAR *name, const CHAR *PublicID,
892 const CHAR *SystemID) {
Daniel Veillard1e346af1999-02-22 10:33:01 +0000893 xmlNotationPtr ret, cur;
894 xmlNotationTablePtr table;
895 int i;
896
897 if (dtd == NULL) {
898 fprintf(stderr, "xmlAddNotationDecl: dtd == NULL\n");
899 return(NULL);
900 }
901 if (name == NULL) {
902 fprintf(stderr, "xmlAddNotationDecl: name == NULL\n");
903 return(NULL);
904 }
905 if ((PublicID == NULL) && (SystemID == NULL)) {
906 fprintf(stderr, "xmlAddNotationDecl: no PUBLIC ID nor SYSTEM ID\n");
907 }
908
909 /*
910 * Create the Notation table if needed.
911 */
912 table = dtd->notations;
913 if (table == NULL)
914 table = dtd->notations = xmlCreateNotationTable();
915 if (table == NULL) {
916 fprintf(stderr, "xmlAddNotationDecl: Table creation failed!\n");
917 return(NULL);
918 }
919
920 /*
921 * Validity Check:
922 * Search the DTD for previous declarations of the ATTLIST
923 */
924 for (i = 0;i < table->nb_notations;i++) {
925 cur = &table->table[i];
926 if (!xmlStrcmp(cur->name, name)) {
927 /*
928 * The notation is already defined in this Dtd.
929 */
930 fprintf(stderr,
931 "xmlAddNotationDecl: %s already defined\n", name);
932 }
933 }
934
935 /*
936 * Grow the table, if needed.
937 */
938 if (table->nb_notations >= table->max_notations) {
939 /*
940 * need more notations.
941 */
942 table->max_notations *= 2;
943 table->table = (xmlNotationPtr)
944 realloc(table->table, table->max_notations * sizeof(xmlNotation));
945 if (table->table) {
946 fprintf(stderr, "xmlAddNotationDecl: out of memory\n");
947 return(NULL);
948 }
949 }
950 ret = &table->table[table->nb_notations];
951
952 /*
953 * fill the structure.
954 */
955 ret->name = xmlStrdup(name);
956 if (SystemID != NULL)
957 ret->SystemID = xmlStrdup(SystemID);
958 else
959 ret->SystemID = NULL;
960 if (PublicID != NULL)
961 ret->PublicID = xmlStrdup(PublicID);
962 else
963 ret->PublicID = NULL;
964 table->nb_notations++;
965
966 return(ret);
967}
968
969/**
970 * xmlFreeNotation:
971 * @not: A notation
972 *
973 * Deallocate the memory used by an notation definition
974 */
975void
976xmlFreeNotation(xmlNotationPtr nota) {
977 if (nota == NULL) return;
978 if (nota->name != NULL)
979 free((CHAR *) nota->name);
980 if (nota->PublicID != NULL)
981 free((CHAR *) nota->PublicID);
982 if (nota->SystemID != NULL)
983 free((CHAR *) nota->SystemID);
984 memset(nota, -1, sizeof(xmlNotation));
985}
986
987/**
988 * xmlFreeNotationTable:
989 * @table: An notation table
990 *
991 * Deallocate the memory used by an entities hash table.
992 */
993void
994xmlFreeNotationTable(xmlNotationTablePtr table) {
995 int i;
996
997 if (table == NULL) return;
998
999 for (i = 0;i < table->nb_notations;i++) {
1000 xmlFreeNotation(&table->table[i]);
1001 }
1002 free(table->table);
1003 free(table);
1004}
1005
1006/**
1007 * xmlCopyNotationTable:
1008 * @table: A notation table
1009 *
1010 * Build a copy of a notation table.
1011 *
1012 * Returns the new xmlNotationTablePtr or NULL in case of error.
1013 */
1014xmlNotationTablePtr
1015xmlCopyNotationTable(xmlNotationTablePtr table) {
1016 xmlNotationTablePtr ret;
1017 xmlNotationPtr cur, nota;
1018 int i;
1019
1020 ret = (xmlNotationTablePtr) malloc(sizeof(xmlNotationTable));
1021 if (ret == NULL) {
1022 fprintf(stderr, "xmlCopyNotationTable: out of memory !\n");
1023 return(NULL);
1024 }
1025 ret->table = (xmlNotationPtr) malloc(table->max_notations *
1026 sizeof(xmlNotation));
1027 if (ret->table == NULL) {
1028 fprintf(stderr, "xmlCopyNotationTable: out of memory !\n");
1029 free(ret);
1030 return(NULL);
1031 }
1032 ret->max_notations = table->max_notations;
1033 ret->nb_notations = table->nb_notations;
1034 for (i = 0;i < ret->nb_notations;i++) {
1035 cur = &ret->table[i];
1036 nota = &table->table[i];
1037 if (nota->name != NULL)
1038 cur->name = xmlStrdup(nota->name);
1039 else
1040 cur->name = NULL;
1041 if (nota->PublicID != NULL)
1042 cur->PublicID = xmlStrdup(nota->PublicID);
1043 else
1044 cur->PublicID = NULL;
1045 if (nota->SystemID != NULL)
1046 cur->SystemID = xmlStrdup(nota->SystemID);
1047 else
1048 cur->SystemID = NULL;
1049 }
1050 return(ret);
1051}
1052
1053/**
1054 * xmlDumpNotationTable:
Daniel Veillard011b63c1999-06-02 17:44:04 +00001055 * @buf: the XML buffer output
Daniel Veillard1e346af1999-02-22 10:33:01 +00001056 * @table: A notation table
1057 *
1058 * This will dump the content of the notation table as an XML DTD definition
Daniel Veillard1e346af1999-02-22 10:33:01 +00001059 */
1060void
Daniel Veillard5099ae81999-04-21 20:12:07 +00001061xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
Daniel Veillard1e346af1999-02-22 10:33:01 +00001062 int i;
1063 xmlNotationPtr cur;
1064
1065 if (table == NULL) return;
1066
1067 for (i = 0;i < table->nb_notations;i++) {
1068 cur = &table->table[i];
Daniel Veillard5099ae81999-04-21 20:12:07 +00001069 xmlBufferWriteChar(buf, "<!NOTATION ");
1070 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001071 if (cur->PublicID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00001072 xmlBufferWriteChar(buf, " PUBLIC ");
1073 xmlBufferWriteQuotedString(buf, cur->PublicID);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001074 if (cur->SystemID != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00001075 xmlBufferWriteChar(buf, " ");
1076 xmlBufferWriteCHAR(buf, cur->SystemID);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001077 }
1078 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00001079 xmlBufferWriteChar(buf, " SYSTEM ");
1080 xmlBufferWriteCHAR(buf, cur->SystemID);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001081 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00001082 xmlBufferWriteChar(buf, " >\n");
Daniel Veillard1e346af1999-02-22 10:33:01 +00001083 }
1084}