1 #include <string.h>
2
3 #ifdef FOR_LT
4
5 #include "lt-memory.h"
6 #include "nsllib.h"
7
8 #define Malloc salloc
9 #define Realloc srealloc
10 #define Free sfree
11
12 #else
13
14 #include "system.h"
15
16 #endif
17
18 #include "charset.h"
19 #include "string16.h"
20 #include "dtd.h"
21 #include "url.h"
22
23 extern void FreeFSM(FSM fsm); /* XXX should be in header */
24
25 const char8 *DefaultTypeName[DT_enum_count] = {
26 "#REQUIRED",
27 "bogus1",
28 "#IMPLIED",
29 "bogus2",
30 "NONE",
31 "#FIXED",
32 };
33
34 const char8 *ContentParticleTypeName[CP_enum_count] = {
35 "#PCDATA",
36 "NAME",
37 "SEQUENCE",
38 "CHOICE"
39 };
40
41 const char8 *ContentTypeName[CT_enum_count] = {
42 "MIXED",
43 "ANY",
44 "bogus1",
45 "bogus2",
46 "EMPTY",
47 "ELEMENT"
48 };
49
50 const char8 *AttributeTypeName[AT_enum_count] = {
51 "CDATA",
52 "bogus1",
53 "bogus2",
54 "NMTOKEN",
55 "bogus3",
56 "ENTITY",
57 "IDREF",
58 "bogus4",
59 "bogus5",
60 "NMTOKENS",
61 "bogus6",
62 "ENTITIES",
63 "IDREFS",
64 "ID",
65 "NOTATION",
66 "ENUMERATION"
67 };
68
69 const char8 *StandaloneDeclarationName[SDD_enum_count] = {
70 "unspecified", "no", "yes"
71 };
72
Strndup(const Char * old,int len)73 static Char *Strndup(const Char *old, int len)
74 {
75 Char *new = Malloc((len+1) * sizeof(Char));
76
77 if(!new)
78 return 0;
79
80 memcpy(new, old, len * sizeof(Char));
81 new[len] = 0;
82
83 return new;
84 }
85
86 /* DTDs */
87
NewDtd(void)88 Dtd NewDtd(void)
89 {
90 Dtd d;
91
92 if(!(d = Malloc(sizeof(*d))))
93 return 0;
94
95 d->name = 0;
96 d->internal_part = 0;
97 d->external_part = 0;
98 d->entities = 0;
99 d->parameter_entities = 0;
100 d->predefined_entities = 0;
101 #ifdef FOR_LT
102 d->doctype = 0;
103 #endif
104 d->nelements = 0;
105 d->neltalloc = 20;
106 d->elements = Malloc(d->neltalloc * sizeof(ElementDefinition));
107 if(!d->elements)
108 return 0;
109 d->notations = 0;
110 d->namespace_universe = 0; /* the global universe */
111
112 return d;
113 }
114
115 /* Free a DTD and everything in it */
116
FreeDtd(Dtd dtd)117 void FreeDtd(Dtd dtd)
118 {
119 Entity ent, ent1;
120 int i;
121 NotationDefinition not, not1;
122
123 if(!dtd)
124 return;
125
126 /* Free the name */
127
128 Free((Char *)dtd->name); /* cast is to get rid of const */
129
130 /* Free the entities */
131
132 FreeEntity(dtd->internal_part);
133 FreeEntity(dtd->external_part);
134
135 for(ent = dtd->entities; ent; ent = ent1)
136 {
137 ent1 = ent->next; /* get it before we free ent! */
138 FreeEntity(ent);
139 }
140
141 for(ent = dtd->parameter_entities; ent; ent = ent1)
142 {
143 ent1 = ent->next;
144 FreeEntity(ent);
145 }
146
147 /* The predefined entities are shared, so we don't free them */
148
149 /* Free the elements */
150
151 for(i=0; i<dtd->nelements; i++)
152 FreeElementDefinition(dtd->elements[i]); /* Frees the attributes too */
153
154 Free(dtd->elements);
155
156 /* Free the notations */
157
158 for(not = dtd->notations; not; not = not1)
159 {
160 not1 = not->next;
161 FreeNotationDefinition(not);
162 }
163
164 /* Free the dtd itself */
165
166 Free(dtd);
167 }
168
169 /* Entities */
170
171 /*
172 * Make a new entity. The name and IDs are copied.
173 */
174
NewExternalEntity(const Char * name,char8 * publicid,const char8 * systemid,NotationDefinition notation,Entity parent)175 Entity NewExternalEntity(const Char *name, char8 *publicid,
176 const char8 *systemid, NotationDefinition notation,
177 Entity parent)
178 {
179 if(publicid && !(publicid = strdup8(publicid))) {
180 return 0;
181 }
182 return NewExternalEntityN(name, name ? Strlen(name) : 0, publicid,
183 systemid, notation, parent);
184 }
185
186 /* NB doesn't copy IDs */
187
NewExternalEntityN(const Char * name,int namelen,char8 * publicid,const char8 * systemid,NotationDefinition notation,Entity parent)188 Entity NewExternalEntityN(const Char *name, int namelen, char8 *publicid,
189 const char8 *systemid, NotationDefinition notation,
190 Entity parent)
191 {
192 Entity e;
193
194 if (!(e = Malloc(sizeof(*e))))
195 return NULL;
196 if (name) {
197 if (!(e->name = Strndup(name, namelen)))
198 return NULL;
199 } else
200 e->name = NULL;
201
202 e->type = ET_external;
203 e->base_url = 0;
204 e->encoding = CE_unknown;
205 e->next = 0;
206 e->parent = parent;
207
208 e->publicid = publicid;
209 e->systemid = systemid;
210 e->notation = notation;
211
212 e->ml_decl = ML_unspecified;
213 e->version_decl = 0;
214 e->encoding_decl = CE_unknown;
215 e->standalone_decl = SDD_unspecified;
216 e->ddb_filename = 0;
217 e->xml_version = XV_1_0; /* 1.0 unless otherwise specified */
218
219 e->url = 0;
220
221 e->is_externally_declared = 0;
222 e->is_internal_subset = 0;
223
224 return (Entity)e;
225 }
226
NewInternalEntityN(const Char * name,int namelen,const Char * text,Entity parent,int line_offset,int line1_char_offset,int matches_parent_text)227 Entity NewInternalEntityN(const Char *name, int namelen,
228 const Char *text, Entity parent,
229 int line_offset, int line1_char_offset,
230 int matches_parent_text)
231 {
232 Entity e;
233
234 if(!(e = Malloc(sizeof(*e))))
235 return 0;
236 if(name) {
237 if(!(e->name = Strndup(name, namelen)))
238 return NULL;
239 } else
240 e->name = NULL;
241
242 e->type = ET_internal;
243 e->base_url = 0;
244 e->encoding = InternalCharacterEncoding;
245 e->next = 0;
246 e->parent = parent;
247
248 e->text = text;
249 e->line_offset = line_offset;
250 e->line1_char_offset = line1_char_offset;
251 e->matches_parent_text = matches_parent_text;
252
253 e->url = 0;
254
255 e->is_externally_declared = 0;
256 e->is_internal_subset = 0;
257
258 /* These should not really be accessed for an internal entity, but
259 because the NSL layer uses internal entities to implement reading
260 from strings, sometimes they are. */
261
262 e->publicid = 0;
263 e->systemid = 0;
264 e->notation = 0;
265
266 e->ml_decl = ML_unspecified;
267 e->version_decl = 0;
268 e->encoding_decl = CE_unknown;
269 e->standalone_decl = SDD_unspecified;
270 e->ddb_filename = 0;
271
272 return (Entity)e;
273 }
274
FreeEntity(Entity e)275 void FreeEntity(Entity e)
276 {
277 if(!e)
278 return;
279
280 if (e->name)
281 Free(e->name);
282 Free(e->base_url);
283 Free(e->url);
284
285 switch(e->type)
286 {
287 case ET_internal:
288 Free((void *)e->atext);
289 break;
290 case ET_external:
291 /* Free((void *)e->systemid); XXX const string passed by client */
292 Free(e->publicid);
293 Free(e->version_decl);
294 Free(e->ddb_filename);
295 break;
296 }
297
298 Free(e);
299 }
300
EntityURL(Entity e)301 const char8 *EntityURL(Entity e)
302 {
303 /* Have we already determined the URL? */
304
305 if(e->url)
306 return e->url;
307
308 if(e->type == ET_internal)
309 {
310 if(e->parent)
311 {
312 const char8 *url = EntityURL(e->parent);
313 if(url)
314 e->url = strdup8(url);
315 }
316 }
317 else
318 e->url = url_merge(e->systemid,
319 e->parent ? EntityBaseURL(e->parent) : 0,
320 0, 0, 0, 0);
321
322 return e->url;
323 }
324
325 /* Returns the URL of the entity if it has one, otherwise the system ID.
326 It will certainly have a URL if it was successfully opened by EntityOpen.
327 Intended for error messages, so never returns NULL. */
328
EntityDescription(Entity e)329 const char8 *EntityDescription(Entity e)
330 {
331 if(e->url)
332 return e->url;
333
334 if(e->type == ET_external)
335 return e->systemid;
336
337 if(e->parent)
338 return EntityDescription(e->parent);
339
340 return "<unknown>";
341 }
342
EntitySetBaseURL(Entity e,const char8 * url)343 void EntitySetBaseURL(Entity e, const char8 *url)
344 {
345 if(e->base_url)
346 Free((void *)e->base_url);
347 e->base_url = strdup8(url);
348 }
349
EntityBaseURL(Entity e)350 const char8 *EntityBaseURL(Entity e)
351 {
352 if(e->base_url)
353 return e->base_url;
354
355 if(e->type == ET_internal)
356 {
357 if(e->parent)
358 return EntityBaseURL(e->parent);
359 else
360 return 0;
361 }
362
363 return EntityURL(e);
364 }
365
DefineEntity(Dtd dtd,Entity e,int pe)366 Entity DefineEntity(Dtd dtd, Entity e, int pe)
367 {
368 if(pe)
369 {
370 e->next = dtd->parameter_entities;
371 dtd->parameter_entities = e;
372 }
373 else
374 {
375 e->next = dtd->entities;
376 dtd->entities = e;
377 }
378
379 return e;
380 }
381
FindEntityN(Dtd dtd,const Char * name,int namelen,int pe)382 Entity FindEntityN(Dtd dtd, const Char *name, int namelen, int pe)
383 {
384 Entity e;
385
386 if(!pe)
387 for(e = dtd->predefined_entities; e; e = e->next)
388 if(Strncmp(name, e->name, namelen) == 0 && e->name[namelen] == 0)
389 return e;
390
391
392 for(e = pe ? dtd->parameter_entities : dtd->entities; e; e=e->next)
393 if(Strncmp(name, e->name, namelen) == 0 && e->name[namelen] == 0)
394 return e;
395
396 return 0;
397 }
398
NextEntity(Dtd dtd,Entity previous)399 Entity NextEntity(Dtd dtd, Entity previous)
400 {
401 return previous ? previous->next : dtd->entities;
402 }
403
NextParameterEntity(Dtd dtd,Entity previous)404 Entity NextParameterEntity(Dtd dtd, Entity previous)
405 {
406 return previous ? previous->next : dtd->parameter_entities;
407 }
408
409 /* Elements */
410
411 /*
412 * Define a new element. The name is copied, the content model is not,
413 * but it is freed when the element definition is freed!
414 */
415
DefineElementN(Dtd dtd,const Char * name,int namelen,ContentType type,Char * content,ContentParticle particle,int declared)416 ElementDefinition DefineElementN(Dtd dtd, const Char *name, int namelen,
417 ContentType type, Char *content,
418 ContentParticle particle, int declared)
419 {
420 ElementDefinition e;
421 const Char *t;
422 #ifdef FOR_LT
423 RHTEntry *entry;
424 #endif
425
426 if(!(e = Malloc(sizeof(*e))))
427 return 0;
428
429 e->eltnum = dtd->nelements++;
430 if(e->eltnum >= dtd->neltalloc)
431 {
432 dtd->neltalloc *= 2;
433 dtd->elements =
434 Realloc(dtd->elements, dtd->neltalloc * sizeof(ElementDefinition));
435 if(!dtd->elements)
436 return 0;
437 }
438 dtd->elements[e->eltnum] = e;
439
440 #ifdef FOR_LT
441 entry = DeclareElement(dtd->doctype, name, namelen, 0, (ctVals)type);
442 if (!entry)
443 return 0;
444
445 e->doctype = dtd->doctype;
446 e->eltsum =
447 (NSL_ElementSummary_I *)(dtd->doctype->permanentBase+entry->eval);
448
449 *(short *)&(e->eltsum->omitEnd) = e->eltnum;
450
451 name = (Char *)dtd->doctype->elements+entry->keyptr;
452 #else
453 if(!(e->name = Strndup(name, namelen)))
454 return 0;
455 #endif
456
457 e->tentative = 0;
458 e->namelen = namelen;
459 e->type = type;
460 e->content = content;
461 e->particle = particle;
462 e->declared = declared;
463 e->has_attlist = 0;
464 e->fsm = 0;
465 e->nattributes = 0;
466 e->nattralloc = 20;
467 e->attributes = Malloc(e->nattralloc * sizeof(AttributeDefinition));
468 if(!e->attributes)
469 return 0;
470 e->id_attribute = 0;
471 e->xml_space_attribute = 0;
472 e->xml_lang_attribute = 0;
473 e->xml_id_attribute = 0;
474 e->notation_attribute = 0;
475 e->cached_nsdef = 0;
476 e->is_externally_declared = 0;
477
478 if((t = Strchr(name, ':')))
479 {
480 if(!(e->prefix = Strndup(name, t - name)))
481 return 0;
482 e->local = t+1;
483 }
484 else
485 {
486 e->local = name;
487 e->prefix = 0;
488 }
489
490 return e;
491 }
492
TentativelyDefineElementN(Dtd dtd,const Char * name,int namelen)493 ElementDefinition TentativelyDefineElementN(Dtd dtd,
494 const Char *name, int namelen)
495 {
496 ElementDefinition e;
497
498 if(!(e = DefineElementN(dtd, name, namelen, CT_any, 0, 0, 1)))
499 return 0;
500
501 e->tentative = 1;
502
503 return e;
504 }
505
RedefineElement(ElementDefinition e,ContentType type,Char * content,ContentParticle particle,int declared)506 ElementDefinition RedefineElement(ElementDefinition e, ContentType type,
507 Char *content, ContentParticle particle, int declared)
508 {
509 #ifdef FOR_LT
510 e->eltsum->contentType = type;
511 #endif
512
513 e->tentative = 0;
514 e->type = type;
515 e->content = content;
516 e->particle = particle;
517 e->declared = declared;
518
519 return e;
520 }
521
FindElementN(Dtd dtd,const Char * name,int namelen)522 ElementDefinition FindElementN(Dtd dtd, const Char *name, int namelen)
523 {
524 ElementDefinition e;
525
526 #ifdef FOR_LT
527 /* Derived from FindElementAndName */
528
529 RHTEntry *entry;
530 NSL_ElementSummary_I *eltsum;
531
532 if(!dtd->doctype)
533 return 0;
534
535 entry = rsearch(name, namelen, dtd->doctype->elements);
536 if(!entry)
537 return 0;
538 eltsum = (NSL_ElementSummary_I *)(dtd->doctype->permanentBase+entry->eval);
539
540 if(!dtd->doctype->XMLMode)
541 {
542 /* NSL mode - we have to fake a structure */
543
544 e = &dtd->fake_elt;
545 e->doctype = dtd->doctype;
546 e->name = (Char *)dtd->doctype->elements+entry->keyptr;
547 e->eltsum = eltsum;
548 e->tentative = 0;
549
550 return e;
551 }
552
553 return dtd->elements[*(short *)&(eltsum->omitEnd)];
554 #else
555 int i;
556
557 for(i=dtd->nelements-1; i>=0; i--)
558 {
559 e = dtd->elements[i];
560 if(namelen == e->namelen && *name == *e->name &&
561 memcmp(name, e->name, namelen*sizeof(Char)) == 0)
562 return e;
563 }
564
565 return 0;
566 #endif
567 }
568
NamespacifyElementDefinition(ElementDefinition element,Namespace ns)569 NSElementDefinition NamespacifyElementDefinition(ElementDefinition element,
570 Namespace ns)
571 {
572 if(element->cached_nsdef && element->cached_nsdef->namespace == ns)
573 return element->cached_nsdef;
574
575 element->cached_nsdef = FindNSElementDefinition(ns, element->local, 1);
576 return element->cached_nsdef;
577 }
578
NextElementDefinition(Dtd dtd,ElementDefinition previous)579 ElementDefinition NextElementDefinition(Dtd dtd, ElementDefinition previous)
580 {
581 int next = previous ? previous->eltnum+1 : 0;
582 return next < dtd->nelements ? dtd->elements[next] : 0;
583 }
584
585 /* Free an element definition and its attribute definitions */
586
FreeElementDefinition(ElementDefinition e)587 void FreeElementDefinition(ElementDefinition e)
588 {
589 int i;
590
591 if(!e)
592 return;
593
594 /* Free the attributes */
595
596 for(i=0; i<e->nattributes; i++)
597 FreeAttributeDefinition(e->attributes[i]);
598 Free(e->attributes);
599
600
601 #ifndef FOR_LT
602 /* Free the element name (kept elsewhere in NSL) */
603
604 Free((void *)e->name);
605 #endif
606
607 Free((void *)e->prefix);
608
609 /* Free the content model */
610 Free(e->content);
611 FreeContentParticle(e->particle);
612 FreeFSM(e->fsm);
613
614 /* Free the ElementDefinition itself */
615 Free(e);
616 }
617
618 /* Attributes */
619
620 /*
621 * Define a new attribute. The name is copied, the allowed values and
622 * default are not, but they are freed when the attribute definition is freed!
623 */
624
625 AttributeDefinition
DefineAttributeN(ElementDefinition element,const Char * name,int namelen,AttributeType type,Char ** allowed_values,DefaultType default_type,Char * default_value,int declared)626 DefineAttributeN(ElementDefinition element, const Char *name, int namelen,
627 AttributeType type, Char **allowed_values,
628 DefaultType default_type, Char *default_value,
629 int declared)
630 {
631 #ifdef FOR_LT
632 int nav = 0;
633 Char **avp;
634 NSL_Doctype_I *doctype = element->doctype;
635 #endif
636 AttributeDefinition a;
637 static Char xml_space[] = {'x','m','l',':','s','p','a','c','e',0};
638 static Char xml_lang[] = {'x','m','l',':','l','a','n','g',0};
639 static Char xml_id[] = {'x','m','l',':','i','d',0};
640 static Char xmlns[] = {'x','m','l','n','s',0};
641 const Char *t;
642
643 if(!(a= Malloc(sizeof(*a))))
644 return 0;
645
646 a->attrnum = element->nattributes++;
647 if(a->attrnum >= element->nattralloc)
648 {
649 element->nattralloc *= 2;
650 element->attributes =
651 Realloc(element->attributes,
652 element->nattralloc * sizeof(AttributeDefinition));
653 if(!element->attributes)
654 return 0;
655 }
656 element->attributes[a->attrnum] = a;
657
658 #ifdef FOR_LT
659 if(allowed_values)
660 {
661 for(avp = allowed_values; *avp; avp++)
662 nav++;
663 }
664
665 if (!(name = DeclareAttr(doctype, name, namelen,
666 (NSL_Attr_Declared_Value)type,
667 allowed_values?allowed_values[0]:0, nav,
668 (NSL_ADefType)default_type, default_value,
669 &element->eltsum, element->name)))
670 return 0;
671
672 a->attrsum = FindAttrSpec(element->eltsum, doctype, name);
673 #else
674 if(!(a->name = Strndup(name, namelen)))
675 return 0;
676 #endif
677
678 a->namelen = namelen;
679 a->type = type;
680 a->allowed_values = allowed_values;
681 a->default_type = default_type;
682 a->default_value = default_value;
683 a->declared = declared;
684 if(declared)
685 element->has_attlist = 1;
686 a->is_externally_declared = 0;
687
688 if(a->type == AT_id && !element->id_attribute)
689 element->id_attribute = a;
690 else if(a->type == AT_notation && !element->notation_attribute)
691 element->notation_attribute = a;
692
693 if(Strcmp(name, xml_space) == 0)
694 element->xml_space_attribute = a;
695 else if(Strcmp(name, xml_lang) == 0)
696 element->xml_lang_attribute = a;
697 else if(Strcmp(name, xml_id) == 0)
698 element->xml_id_attribute = a;
699
700 a->cached_nsdef = 0;
701
702 if((t = Strchr(name, ':')))
703 {
704 if(!(a->prefix = Strndup(name, t - name)))
705 return 0;
706 a->local = t+1;
707 if(Strcmp(a->prefix, xmlns) == 0)
708 a->ns_attr_prefix = a->local;
709 else
710 a->ns_attr_prefix = 0;
711 }
712 else
713 {
714 a->local = name;
715 a->prefix = 0;
716 if(Strcmp(name, xmlns) == 0)
717 a->ns_attr_prefix = name+5; /* point to the null */
718 else
719 a->ns_attr_prefix = 0;
720 }
721
722 return a;
723 }
724
FindAttributeN(ElementDefinition element,const Char * name,int namelen)725 AttributeDefinition FindAttributeN(ElementDefinition element,
726 const Char *name, int namelen)
727 {
728 int i;
729
730 #ifdef FOR_LT
731 if(!(name = AttrUniqueName(element->doctype, name, namelen)))
732 return 0;
733 if(!element->doctype->XMLMode)
734 /* XXX Hack for NSL documents.
735 Return the attribute summary itself.
736 Nothing in the RXP layer had better look at it! */
737 return (AttributeDefinition)FindAttrSpec(element->eltsum,
738 element->doctype,
739 name);
740 if(!FindAttrSpecAndNumber(element->eltsum, element->doctype, name, &i))
741 return 0;
742 if(i < 0)
743 i = element->nattributes + i;
744
745 return element->attributes[i];
746 #else
747 for(i=element->nattributes-1; i>=0; i--)
748 {
749 AttributeDefinition a = element->attributes[i];
750
751 if(namelen == a->namelen &&
752 memcmp(name, a->name, namelen * sizeof(Char)) == 0)
753 return a;
754 }
755
756 return 0;
757 #endif
758 }
759
760 NSAttributeDefinition
NamespacifyGlobalAttributeDefinition(AttributeDefinition attribute,Namespace ns)761 NamespacifyGlobalAttributeDefinition(AttributeDefinition attribute,
762 Namespace ns)
763 {
764 if(attribute->cached_nsdef &&
765 !attribute->cached_nsdef->element &&
766 attribute->cached_nsdef->namespace == ns)
767 return attribute->cached_nsdef;
768
769 attribute->cached_nsdef =
770 FindNSGlobalAttributeDefinition(ns, attribute->local, 1);
771 return attribute->cached_nsdef;
772 }
773
774 NSAttributeDefinition
NamespacifyElementAttributeDefinition(AttributeDefinition attribute,NSElementDefinition nselt)775 NamespacifyElementAttributeDefinition(AttributeDefinition attribute,
776 NSElementDefinition nselt)
777 {
778 if(attribute->cached_nsdef &&
779 attribute->cached_nsdef->element &&
780 attribute->cached_nsdef->element == nselt)
781 return attribute->cached_nsdef;
782
783 attribute->cached_nsdef =
784 FindNSElementAttributeDefinition(nselt, attribute->local, 1);
785 return attribute->cached_nsdef;
786 }
787
NextAttributeDefinition(ElementDefinition element,AttributeDefinition previous)788 AttributeDefinition NextAttributeDefinition(ElementDefinition element,
789 AttributeDefinition previous)
790 {
791 int next = previous ? previous->attrnum+1 : 0;
792 return next < element->nattributes ? element->attributes[next] : 0;
793 }
794
795 /* Free an attribute definition */
796
FreeAttributeDefinition(AttributeDefinition a)797 void FreeAttributeDefinition(AttributeDefinition a)
798 {
799 if(!a)
800 return;
801
802 #ifndef FOR_LT
803 /* These things are stored elsewhere in NSL */
804
805 /* Free the name */
806
807 Free((void *)a->name);
808
809 /* Free the allowed values - we rely on them being allocated as in
810 xmlparser.c: the Char * pointers point into one single block. */
811
812 if(a->allowed_values)
813 Free(a->allowed_values[0]);
814
815 /* Free the default value */
816
817 Free((void *)a->default_value);
818
819 #endif
820 /* NSL doesn't ever get its hands on this */
821
822 Free(a->allowed_values);
823
824 Free((void *)a->prefix);
825
826 /* Free the attribute definition itself */
827
828 Free(a);
829 }
830
831 /* Notations */
832
833 /*
834 * Define a new notation. The name is copied, the system and public ids are
835 * not, but they are freed when the notation definition is freed!
836 */
837
DefineNotationN(Dtd dtd,const Char * name,int namelen,char8 * publicid,char8 * systemid,Entity parent)838 NotationDefinition DefineNotationN(Dtd dtd, const Char *name, int namelen,
839 char8 *publicid, char8 *systemid,
840 Entity parent)
841 {
842 NotationDefinition n;
843
844 if(!(n = Malloc(sizeof(*n))) || !(n->name = Strndup(name, namelen)))
845 return 0;
846
847 n->tentative = 0;
848 n->systemid = systemid;
849 n->publicid = publicid;
850 n->url = 0;
851 n->parent = parent;
852 n->next = dtd->notations;
853 dtd->notations = n;
854
855 return n;
856 }
857
TentativelyDefineNotationN(Dtd dtd,const Char * name,int namelen)858 NotationDefinition TentativelyDefineNotationN(Dtd dtd,
859 const Char *name, int namelen)
860 {
861 NotationDefinition n;
862
863 if(!(n = DefineNotationN(dtd, name, namelen, 0, 0, 0)))
864 return 0;
865
866 n->tentative = 1;
867
868 return n;
869 }
870
RedefineNotation(NotationDefinition n,char8 * publicid,char8 * systemid,Entity parent)871 NotationDefinition RedefineNotation(NotationDefinition n,
872 char8 *publicid, char8 *systemid,
873 Entity parent)
874 {
875 n->tentative = 0;
876 n->systemid = systemid;
877 n->publicid = publicid;
878 n->parent = parent;
879
880 return n;
881 }
882
FindNotationN(Dtd dtd,const Char * name,int namelen)883 NotationDefinition FindNotationN(Dtd dtd, const Char *name, int namelen)
884 {
885 NotationDefinition n;
886
887 for(n = dtd->notations; n; n = n->next)
888 if(Strncmp(name, n->name, namelen) == 0 && n->name[namelen] == 0)
889 return n;
890
891 return 0;
892 }
893
NextNotationDefinition(Dtd dtd,NotationDefinition previous)894 NotationDefinition NextNotationDefinition(Dtd dtd, NotationDefinition previous)
895 {
896 return previous ? previous->next : dtd->notations;
897 }
898
NotationURL(NotationDefinition n)899 const char8 *NotationURL(NotationDefinition n)
900 {
901 if(n->url)
902 return n->url;
903
904 n->url = url_merge(n->systemid,
905 n->parent ? EntityBaseURL(n->parent) : 0,
906 0, 0, 0, 0);
907
908 return n->url;
909 }
910
FreeNotationDefinition(NotationDefinition n)911 void FreeNotationDefinition(NotationDefinition n)
912 {
913 if(!n)
914 return;
915
916 /* Free the name */
917
918 Free((void *)n->name);
919
920 /* Free the ids */
921
922 Free((void *)n->systemid);
923 Free((void *)n->publicid);
924 Free((void *)n->url);
925
926 /* Free the notation definition itself */
927
928 Free(n);
929 }
930