blob: 6f2f440dcc7303782957472524de8a30c7185855 [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 Veillard39a1f9a1999-01-17 19:11:59 +000081 * xmlNewElementContent:
82 * @name: the subelement name or NULL
83 * @type: the type of element content decl
84 *
85 * Free an element content structure. This is a recursive call !
86 */
87void
88xmlFreeElementContent(xmlElementContentPtr cur) {
89/* TODO !!! */
90}
91
92/****************************************************************
93 * *
94 * Registration of DTD declarations *
95 * *
96 ****************************************************************/
97
Daniel Veillard3b9def11999-01-31 22:15:06 +000098/**
99 * xmlCreateElementTable:
100 *
101 * create and initialize an empty element hash table.
102 *
103 * return values: the xmlElementTablePtr just created or NULL in case of error.
104 */
105xmlElementTablePtr
106xmlCreateElementTable(void) {
107 xmlElementTablePtr ret;
108
109 ret = (xmlElementTablePtr)
110 malloc(sizeof(xmlElementTable));
111 if (ret == NULL) {
112 fprintf(stderr, "xmlCreateElementTable : malloc(%d) failed\n",
113 sizeof(xmlElementTable));
114 return(NULL);
115 }
116 ret->max_elements = XML_MIN_ENTITIES_TABLE;
117 ret->nb_elements = 0;
118 ret->table = (xmlElementPtr )
119 malloc(ret->max_elements * sizeof(xmlElement));
120 if (ret == NULL) {
121 fprintf(stderr, "xmlCreateElementTable : malloc(%d) failed\n",
122 ret->max_elements * sizeof(xmlElement));
123 free(ret);
124 return(NULL);
125 }
126 return(ret);
127}
128
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000129
130/**
131 * xmlAddElementDecl:
132 * @name: the entity name
133 *
134 * Register a new element declaration
135 *
136 * return values: NULL if not, othervise the entity
137 */
138xmlElementPtr
139xmlAddElementDecl(xmlDtdPtr dtd, char *name, int type,
140 xmlElementContentPtr content) {
Daniel Veillard3b9def11999-01-31 22:15:06 +0000141 xmlElementPtr ret, cur;
142 xmlElementTablePtr table;
143 int i;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000144
145 if (dtd == NULL) {
146 fprintf(stderr, "xmlAddElementDecl: dtd == NULL\n");
147 return(NULL);
148 }
149 if (name == NULL) {
150 fprintf(stderr, "xmlAddElementDecl: name == NULL\n");
151 return(NULL);
152 }
153 switch (type) {
154 case XML_ELEMENT_TYPE_EMPTY:
155 if (content != NULL) {
156 fprintf(stderr,
157 "xmlAddElementDecl: content != NULL for EMPTY\n");
158 return(NULL);
159 }
160 break;
161 case XML_ELEMENT_TYPE_ANY:
162 if (content != NULL) {
163 fprintf(stderr,
164 "xmlAddElementDecl: content != NULL for ANY\n");
165 return(NULL);
166 }
167 break;
168 case XML_ELEMENT_TYPE_MIXED:
169 if (content == NULL) {
170 fprintf(stderr,
171 "xmlAddElementDecl: content == NULL for MIXED\n");
172 return(NULL);
173 }
174 break;
175 case XML_ELEMENT_TYPE_ELEMENT:
176 if (content == NULL) {
177 fprintf(stderr,
178 "xmlAddElementDecl: content == NULL for ELEMENT\n");
179 return(NULL);
180 }
181 break;
182 default:
183 fprintf(stderr, "xmlAddElementDecl: unknown type %d\n", type);
184 return(NULL);
185 }
186
187 /*
Daniel Veillard3b9def11999-01-31 22:15:06 +0000188 * Create the Element table if needed.
189 */
190 table = dtd->elements;
191 if (table == NULL)
192 table = dtd->elements = xmlCreateElementTable();
193 if (table == NULL) {
194 fprintf(stderr, "xmlAddElementDecl: Table creation failed!\n");
195 return(NULL);
196 }
197
198 /*
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000199 * Validity Check:
200 * Search the DTD for previous declarations of the ELEMENT
201 */
Daniel Veillard3b9def11999-01-31 22:15:06 +0000202 for (i = 0;i < table->nb_elements;i++) {
203 cur = &table->table[i];
204 if (!xmlStrcmp(cur->name, name)) {
205 /*
206 * The element is already defined in this Dtd.
207 */
208 fprintf(stderr,
209 "xmlAddElementDecl: %s already defined\n", name);
210 return(NULL);
211 }
212 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000213
214 /*
Daniel Veillard3b9def11999-01-31 22:15:06 +0000215 * Grow the table, if needed.
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000216 */
Daniel Veillard3b9def11999-01-31 22:15:06 +0000217 if (table->nb_elements >= table->max_elements) {
218 /*
219 * need more elements.
220 */
221 table->max_elements *= 2;
222 table->table = (xmlElementPtr)
223 realloc(table->table, table->max_elements * sizeof(xmlElement));
224 if (table->table) {
225 fprintf(stderr, "xmlAddElementDecl: out of memory\n");
226 return(NULL);
227 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000228 }
Daniel Veillard3b9def11999-01-31 22:15:06 +0000229 ret = &table->table[table->nb_elements];
230
231 /*
232 * fill the structure.
233 */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000234 ret->type = type;
235 ret->name = xmlStrdup(name);
236 ret->content = content;
Daniel Veillard3b9def11999-01-31 22:15:06 +0000237 table->nb_elements++;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000238
239 return(ret);
240}
241
Daniel Veillard3b9def11999-01-31 22:15:06 +0000242/**
243 * xmlFreeElement:
244 * @elem: An element
245 *
246 * Deallocate the memory used by an element definition
247 */
248void
249xmlFreeElement(xmlElementPtr elem) {
250 if (elem == NULL) return;
251 xmlFreeElementContent(elem->content);
252 if (elem->name != NULL)
253 free((CHAR *) elem->name);
254 memset(elem, -1, sizeof(xmlElement));
255 free(elem);
256}
257
258/**
259 * xmlFreeElementTable:
260 * @table: An element table
261 *
262 * Deallocate the memory used by an entities hash table.
263 */
264void
265xmlFreeElementTable(xmlElementTablePtr table) {
266 int i;
267
268 if (table == NULL) return;
269
270 for (i = 0;i < table->nb_elements;i++) {
271 xmlFreeElement(&table->table[i]);
272 }
273 free(table->table);
274 free(table);
275}
276
277/**
278 * xmlCopyElementTable:
279 * @table: An element table
280 *
281 * Build a copy of an element table.
282 *
283 * return values: the new xmlElementTablePtr or NULL in case of error.
284 */
285xmlElementTablePtr
286xmlCopyElementTable(xmlElementTablePtr table) {
287 xmlElementTablePtr ret;
288 xmlElementPtr cur, ent;
289 int i;
290
291 ret = (xmlElementTablePtr) malloc(sizeof(xmlElementTable));
292 if (ret == NULL) {
293 fprintf(stderr, "xmlCopyElementTable: out of memory !\n");
294 return(NULL);
295 }
296 ret->table = (xmlElementPtr) malloc(table->max_elements *
297 sizeof(xmlElement));
298 if (ret->table == NULL) {
299 fprintf(stderr, "xmlCopyElementTable: out of memory !\n");
300 free(ret);
301 return(NULL);
302 }
303 ret->max_elements = table->max_elements;
304 ret->nb_elements = table->nb_elements;
305 for (i = 0;i < ret->nb_elements;i++) {
306 cur = &ret->table[i];
307 ent = &table->table[i];
308 cur->type = ent->type;
309 if (ent->name != NULL)
310 cur->name = xmlStrdup(ent->name);
311 else
312 cur->name = NULL;
313 cur->content = xmlCopyElementContent(ent->content);
314 }
315 return(ret);
316}
317
318/**
319 * xmlDumpElementTable:
320 * @table: An element table
321 *
322 * This will dump the content of the element table as an XML DTD definition
323 *
324 * NOTE: TODO an extra parameter allowing a reentant implementation will
325 * be added.
326 */
327void
328xmlDumpElementTable(xmlElementTablePtr table) {
329 int i;
330 xmlElementPtr cur;
331
332 if (table == NULL) return;
333
334 for (i = 0;i < table->nb_elements;i++) {
335 cur = &table->table[i];
336 switch (cur->type) {
337 case XML_ELEMENT_TYPE_EMPTY:
338 xmlBufferWriteChar("<!ELEMENT ");
339 xmlBufferWriteCHAR(cur->name);
340 xmlBufferWriteChar(" EMPTY>");
341 break;
342 case XML_ELEMENT_TYPE_ANY:
343 xmlBufferWriteChar("<!ELEMENT ");
344 xmlBufferWriteCHAR(cur->name);
345 xmlBufferWriteChar(" ANY>");
346 break;
347 case XML_ELEMENT_TYPE_MIXED:
348 /* TODO !!! */
349 break;
350 case XML_ELEMENT_TYPE_ELEMENT:
351 /* TODO !!! */
352 break;
353 default:
354 fprintf(stderr,
355 "xmlDumpElementTable: internal: unknown type %d\n",
356 cur->type);
357 }
358 }
359}