blob: 942e47878eeb39233181ed631eec463551eb6c59 [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 *
29 * return values: NULL if not, othervise the new element content structure
30 */
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 Veillard39a1f9a1999-01-17 19:11:59 +000063 return(ret);
64}
65
66/**
Daniel Veillard3b9def11999-01-31 22:15:06 +000067 * xmlCopyElementContent:
68 * @content: An element content pointer.
69 *
70 * Build a copy of an element content description.
71 *
72 * return values: the new xmlElementContentPtr or NULL in case of error.
73 */
74xmlElementContentPtr
75xmlCopyElementContent(xmlElementContentPtr content) {
76/* TODO !!! */
77 return(NULL);
78}
79
80/**
Daniel Veillard1899e851999-02-01 12:18:54 +000081 * xmlFreeElementContent:
82 * @cur: the element content tree to free
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000083 *
84 * Free an element content structure. This is a recursive call !
85 */
86void
87xmlFreeElementContent(xmlElementContentPtr cur) {
88/* TODO !!! */
89}
90
Daniel Veillard1899e851999-02-01 12:18:54 +000091/**
92 * xmlDumpElementContent:
93 * @content: An element table
94 * @glob: 1 if one must print the englobing parenthesis, 0 otherwise
95 *
96 * This will dump the content of the element table as an XML DTD definition
97 *
98 * NOTE: TODO an extra parameter allowing a reentant implementation will
99 * be added.
100 */
101void
102xmlDumpElementContent(xmlElementContentPtr content, int glob) {
103 if (content == NULL) return;
104
105 if (glob) xmlBufferWriteChar("(");
106 switch (content->type) {
107 case XML_ELEMENT_CONTENT_PCDATA:
108 xmlBufferWriteChar("#PCDATA");
109 break;
110 case XML_ELEMENT_CONTENT_ELEMENT:
111 xmlBufferWriteCHAR(content->name);
112 break;
113 case XML_ELEMENT_CONTENT_SEQ:
114 if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
115 (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
116 xmlDumpElementContent(content->c1, 1);
117 else
118 xmlDumpElementContent(content->c1, 0);
119 xmlBufferWriteChar(" , ");
120 if (content->c2->type == XML_ELEMENT_CONTENT_OR)
121 xmlDumpElementContent(content->c2, 1);
122 else
123 xmlDumpElementContent(content->c2, 0);
124 break;
125 case XML_ELEMENT_CONTENT_OR:
126 if ((content->c1->type == XML_ELEMENT_CONTENT_OR) ||
127 (content->c1->type == XML_ELEMENT_CONTENT_SEQ))
128 xmlDumpElementContent(content->c1, 1);
129 else
130 xmlDumpElementContent(content->c1, 0);
131 xmlBufferWriteChar(" | ");
132 if (content->c2->type == XML_ELEMENT_CONTENT_SEQ)
133 xmlDumpElementContent(content->c2, 1);
134 else
135 xmlDumpElementContent(content->c2, 0);
136 break;
137 default:
138 fprintf(stderr, "xmlDumpElementContent: unknown type %d\n",
139 content->type);
140 }
141 if (glob)
142 xmlBufferWriteChar(")");
143 switch (content->ocur) {
144 case XML_ELEMENT_CONTENT_ONCE:
145 break;
146 case XML_ELEMENT_CONTENT_OPT:
147 xmlBufferWriteChar("?");
148 break;
149 case XML_ELEMENT_CONTENT_MULT:
150 xmlBufferWriteChar("*");
151 break;
152 case XML_ELEMENT_CONTENT_PLUS:
153 xmlBufferWriteChar("+");
154 break;
155 }
156}
157
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000158/****************************************************************
159 * *
160 * Registration of DTD declarations *
161 * *
162 ****************************************************************/
163
Daniel Veillard3b9def11999-01-31 22:15:06 +0000164/**
165 * xmlCreateElementTable:
166 *
167 * create and initialize an empty element hash table.
168 *
169 * return values: the xmlElementTablePtr just created or NULL in case of error.
170 */
171xmlElementTablePtr
172xmlCreateElementTable(void) {
173 xmlElementTablePtr ret;
174
175 ret = (xmlElementTablePtr)
176 malloc(sizeof(xmlElementTable));
177 if (ret == NULL) {
178 fprintf(stderr, "xmlCreateElementTable : malloc(%d) failed\n",
179 sizeof(xmlElementTable));
180 return(NULL);
181 }
182 ret->max_elements = XML_MIN_ENTITIES_TABLE;
183 ret->nb_elements = 0;
184 ret->table = (xmlElementPtr )
185 malloc(ret->max_elements * sizeof(xmlElement));
186 if (ret == NULL) {
187 fprintf(stderr, "xmlCreateElementTable : malloc(%d) failed\n",
188 ret->max_elements * sizeof(xmlElement));
189 free(ret);
190 return(NULL);
191 }
192 return(ret);
193}
194
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000195
196/**
197 * xmlAddElementDecl:
198 * @name: the entity name
199 *
200 * Register a new element declaration
201 *
202 * return values: NULL if not, othervise the entity
203 */
204xmlElementPtr
205xmlAddElementDecl(xmlDtdPtr dtd, char *name, int type,
206 xmlElementContentPtr content) {
Daniel Veillard3b9def11999-01-31 22:15:06 +0000207 xmlElementPtr ret, cur;
208 xmlElementTablePtr table;
209 int i;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000210
211 if (dtd == NULL) {
212 fprintf(stderr, "xmlAddElementDecl: dtd == NULL\n");
213 return(NULL);
214 }
215 if (name == NULL) {
216 fprintf(stderr, "xmlAddElementDecl: name == NULL\n");
217 return(NULL);
218 }
219 switch (type) {
220 case XML_ELEMENT_TYPE_EMPTY:
221 if (content != NULL) {
222 fprintf(stderr,
223 "xmlAddElementDecl: content != NULL for EMPTY\n");
224 return(NULL);
225 }
226 break;
227 case XML_ELEMENT_TYPE_ANY:
228 if (content != NULL) {
229 fprintf(stderr,
230 "xmlAddElementDecl: content != NULL for ANY\n");
231 return(NULL);
232 }
233 break;
234 case XML_ELEMENT_TYPE_MIXED:
235 if (content == NULL) {
236 fprintf(stderr,
237 "xmlAddElementDecl: content == NULL for MIXED\n");
238 return(NULL);
239 }
240 break;
241 case XML_ELEMENT_TYPE_ELEMENT:
242 if (content == NULL) {
243 fprintf(stderr,
244 "xmlAddElementDecl: content == NULL for ELEMENT\n");
245 return(NULL);
246 }
247 break;
248 default:
249 fprintf(stderr, "xmlAddElementDecl: unknown type %d\n", type);
250 return(NULL);
251 }
252
253 /*
Daniel Veillard3b9def11999-01-31 22:15:06 +0000254 * Create the Element table if needed.
255 */
256 table = dtd->elements;
257 if (table == NULL)
258 table = dtd->elements = xmlCreateElementTable();
259 if (table == NULL) {
260 fprintf(stderr, "xmlAddElementDecl: Table creation failed!\n");
261 return(NULL);
262 }
263
264 /*
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000265 * Validity Check:
266 * Search the DTD for previous declarations of the ELEMENT
267 */
Daniel Veillard3b9def11999-01-31 22:15:06 +0000268 for (i = 0;i < table->nb_elements;i++) {
269 cur = &table->table[i];
270 if (!xmlStrcmp(cur->name, name)) {
271 /*
272 * The element is already defined in this Dtd.
273 */
274 fprintf(stderr,
275 "xmlAddElementDecl: %s already defined\n", name);
276 return(NULL);
277 }
278 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000279
280 /*
Daniel Veillard3b9def11999-01-31 22:15:06 +0000281 * Grow the table, if needed.
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000282 */
Daniel Veillard3b9def11999-01-31 22:15:06 +0000283 if (table->nb_elements >= table->max_elements) {
284 /*
285 * need more elements.
286 */
287 table->max_elements *= 2;
288 table->table = (xmlElementPtr)
289 realloc(table->table, table->max_elements * sizeof(xmlElement));
290 if (table->table) {
291 fprintf(stderr, "xmlAddElementDecl: out of memory\n");
292 return(NULL);
293 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000294 }
Daniel Veillard3b9def11999-01-31 22:15:06 +0000295 ret = &table->table[table->nb_elements];
296
297 /*
298 * fill the structure.
299 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000300 ret->type = type;
301 ret->name = xmlStrdup(name);
302 ret->content = content;
Daniel Veillard3b9def11999-01-31 22:15:06 +0000303 table->nb_elements++;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000304
305 return(ret);
306}
307
Daniel Veillard3b9def11999-01-31 22:15:06 +0000308/**
309 * xmlFreeElement:
310 * @elem: An element
311 *
312 * Deallocate the memory used by an element definition
313 */
314void
315xmlFreeElement(xmlElementPtr elem) {
316 if (elem == NULL) return;
317 xmlFreeElementContent(elem->content);
318 if (elem->name != NULL)
319 free((CHAR *) elem->name);
320 memset(elem, -1, sizeof(xmlElement));
321 free(elem);
322}
323
324/**
325 * xmlFreeElementTable:
326 * @table: An element table
327 *
328 * Deallocate the memory used by an entities hash table.
329 */
330void
331xmlFreeElementTable(xmlElementTablePtr table) {
332 int i;
333
334 if (table == NULL) return;
335
336 for (i = 0;i < table->nb_elements;i++) {
337 xmlFreeElement(&table->table[i]);
338 }
339 free(table->table);
340 free(table);
341}
342
343/**
344 * xmlCopyElementTable:
345 * @table: An element table
346 *
347 * Build a copy of an element table.
348 *
349 * return values: the new xmlElementTablePtr or NULL in case of error.
350 */
351xmlElementTablePtr
352xmlCopyElementTable(xmlElementTablePtr table) {
353 xmlElementTablePtr ret;
354 xmlElementPtr cur, ent;
355 int i;
356
357 ret = (xmlElementTablePtr) malloc(sizeof(xmlElementTable));
358 if (ret == NULL) {
359 fprintf(stderr, "xmlCopyElementTable: out of memory !\n");
360 return(NULL);
361 }
362 ret->table = (xmlElementPtr) malloc(table->max_elements *
363 sizeof(xmlElement));
364 if (ret->table == NULL) {
365 fprintf(stderr, "xmlCopyElementTable: out of memory !\n");
366 free(ret);
367 return(NULL);
368 }
369 ret->max_elements = table->max_elements;
370 ret->nb_elements = table->nb_elements;
371 for (i = 0;i < ret->nb_elements;i++) {
372 cur = &ret->table[i];
373 ent = &table->table[i];
374 cur->type = ent->type;
375 if (ent->name != NULL)
376 cur->name = xmlStrdup(ent->name);
377 else
378 cur->name = NULL;
379 cur->content = xmlCopyElementContent(ent->content);
380 }
381 return(ret);
382}
383
384/**
385 * xmlDumpElementTable:
386 * @table: An element table
387 *
388 * This will dump the content of the element table as an XML DTD definition
389 *
390 * NOTE: TODO an extra parameter allowing a reentant implementation will
391 * be added.
392 */
393void
394xmlDumpElementTable(xmlElementTablePtr table) {
395 int i;
396 xmlElementPtr cur;
397
398 if (table == NULL) return;
399
400 for (i = 0;i < table->nb_elements;i++) {
401 cur = &table->table[i];
402 switch (cur->type) {
403 case XML_ELEMENT_TYPE_EMPTY:
404 xmlBufferWriteChar("<!ELEMENT ");
405 xmlBufferWriteCHAR(cur->name);
Daniel Veillard1899e851999-02-01 12:18:54 +0000406 xmlBufferWriteChar(" EMPTY>\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000407 break;
408 case XML_ELEMENT_TYPE_ANY:
409 xmlBufferWriteChar("<!ELEMENT ");
410 xmlBufferWriteCHAR(cur->name);
Daniel Veillard1899e851999-02-01 12:18:54 +0000411 xmlBufferWriteChar(" ANY>\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000412 break;
413 case XML_ELEMENT_TYPE_MIXED:
Daniel Veillard1899e851999-02-01 12:18:54 +0000414 xmlBufferWriteChar("<!ELEMENT ");
415 xmlBufferWriteCHAR(cur->name);
416 xmlBufferWriteChar(" ");
417 xmlDumpElementContent(cur->content, 1);
418 xmlBufferWriteChar(">\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000419 break;
420 case XML_ELEMENT_TYPE_ELEMENT:
Daniel Veillard1899e851999-02-01 12:18:54 +0000421 xmlBufferWriteChar("<!ELEMENT ");
422 xmlBufferWriteCHAR(cur->name);
423 xmlBufferWriteChar(" ");
424 xmlDumpElementContent(cur->content, 1);
425 xmlBufferWriteChar(">\n");
Daniel Veillard3b9def11999-01-31 22:15:06 +0000426 break;
427 default:
428 fprintf(stderr,
429 "xmlDumpElementTable: internal: unknown type %d\n",
430 cur->type);
431 }
432 }
433}