1 #include "sgmlincl.h" /* #INCLUDE statements for SGML parser. */
2 /* MDADL: Process ATTLIST declaration.
3 */
mdadl(tbuf)4 VOID mdadl(tbuf)
5 UNCH *tbuf; /* Work area for tokenization (tbuf). */
6 {
7 int i; /* Loop counter; temporary variable. */
8 int adlim; /* Number of unused ad slots in al. */
9 struct ad *alperm = 0; /* Attribute definition list. */
10 int stored = 0;
11
12 mdname = key[KATTLIST]; /* Identify declaration for messages. */
13 subdcl = 0; /* No subject as yet. */
14 parmno = 0; /* No parameters as yet. */
15 mdessv = es; /* Save es level for entity nesting check. */
16 reqadn = noteadn = 0; /* No required attributes yet. */
17 idadn = conradn = 0; /* No special atts yet.*/
18 AN(al) = 0; /* Number of attributes defined. */
19 ADN(al) = 0; /* Number of ad's in al (atts + name vals).*/
20 /* PARAMETER 1: Element name or a group of them.
21 */
22 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
23 TRACEMD("1: element name or group");
24 switch (pcbmd.action) {
25 case NAS:
26 nmgrp[0] = etddef(tbuf);
27 nmgrp[1] = 0;
28 break;
29 case GRPS:
30 parsegrp(nmgrp, &pcbgrnm, tbuf);
31 break;
32 case RNS: /* Reserved name started. */
33 if (ustrcmp(tbuf+1, key[KNOTATION])) {
34 mderr(118, tbuf+1, key[KNOTATION]);
35 return;
36 }
37 mdnadl(tbuf);
38 return;
39 default:
40 mderr(121, (UNCH *)0, (UNCH *)0);
41 return;
42 }
43 /* Save first GI for error msgs. */
44 if (nmgrp[0])
45 subdcl = nmgrp[0]->etdgi+1;
46 /* PARAMETER 2: Attribute definition list.
47 */
48 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
49 TRACEMD("2: attribute list");
50 if (pcbmd.action!=NAS) {
51 mderr(120, (UNCH *)0, (UNCH *)0);
52 return;
53 }
54 while (pcbmd.action==NAS) {
55 al[ADN(al)+1].adname = savenm(tbuf);
56 if ((adlim = ATTCNT-((int)++ADN(al)))<0) {
57 mderr(111, (UNCH *)0, (UNCH *)0);
58 adlfree(al, 1);
59 return;
60 }
61 ++AN(al);
62 if (mdattdef(adlim, 0)) {
63 adlfree(al, 1);
64 return;
65 }
66 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
67 }
68 if (AN(al)>0) { /* Save list only if 1 or more good atts. */
69 if (reqadn) SET(ADLF(al), ADLREQ); /* Element must have start-tag. */
70 if (noteadn) SET(ADLF(al), ADLNOTE); /* Element cannot be EMPTY. */
71 if (conradn) SET(ADLF(al), ADLCONR); /* Element cannot be EMPTY. */
72 alperm = (struct ad *)rmalloc((1+ADN(al))*ADSZ);
73 memcpy((UNIV)alperm, (UNIV)al, (1+ADN(al))*ADSZ );
74 ds.attcnt += AN(al); /* Number of attributes defined. */
75 ds.attgcnt += ADN(al) - AN(al); /* Number of att grp members. */
76 TRACEADL(alperm);
77 }
78 /* Clear attribute list for next declaration. */
79 MEMZERO((UNIV)al, (1+ADN(al))*ADSZ);
80
81 /* PARAMETER 3: End of declaration.
82 */
83 /* Next pcb.action was set during attribute definition loop. */
84 TRACEMD(emd);
85 if (pcbmd.action!=EMD) {mderr(126, (UNCH *)0, (UNCH *)0); return;}
86 if (es!=mdessv) synerr(37, &pcbmd);
87
88 /* EXECUTE: Store the definition for each element name specified.
89 */
90 TRACEGRP(nmgrp);
91 for (i = 0; nmgrp[i]; i++) {
92 if (nmgrp[i]->adl) { /* Error if an ADL exists. */
93 mderr(112, (UNCH *)0, (UNCH *)0);
94 continue;
95 }
96 nmgrp[i]->adl = alperm; /* If virgin, store the adl ptr. */
97 stored = 1;
98 if (alperm && nmgrp[i]->etdmod)
99 etdadl(nmgrp[i]); /* Check for conflicts with ETD. */
100 }
101 if (!stored && alperm) {
102 adlfree(alperm, 1);
103 frem((UNIV)alperm);
104 }
105 }
106 /* ETDADL: Check compatibility between ETD and ADL.
107 */
etdadl(p)108 VOID etdadl(p)
109 struct etd *p; /* Pointer to element type definition. */
110 {
111 parmno = 0;
112 /* Minimizable element cannot have required attribute. */
113 if (GET(p->etdmin, SMO) && GET(p->adl[0].adflags, ADLREQ)) {
114 mderr(40, (UNCH *)0, (UNCH *)0);
115 RESET(p->etdmin, SMO);
116 }
117 /* Empty element cannot have NOTATION attribute.
118 Attribute is not removed (too much trouble), but we trap
119 attempts to specify it on the start-tag in adlval().
120 */
121 if (GET(p->etdmod->ttype, MNONE)) {
122 if (GET(p->adl[0].adflags, ADLNOTE))
123 mderr(83, (UNCH *)0, (UNCH *)0);
124
125 /* Empty element cannot have CONREF attribute.
126 Attribute is not removed because it just acts
127 like IMPLIED anyway.
128 */
129 if (GET(p->adl[0].adflags, ADLCONR))
130 mderr(85, (UNCH *)0, (UNCH *)0);
131 }
132 /* "-" should not be specified for the end-tag minimization if
133 the element has a content reference attribute. */
134 if (GET(p->adl[0].adflags, ADLCONR) && BITON(p->etdmin, EMM))
135 mderr(153, (UNCH *)0, (UNCH *)0);
136 }
137 /* MDNADL: Process ATTLIST declaration for notation.
138 TO DO: Pass deftab and dvtab as parameters so
139 that prohibited types can be handled by leaving
140 them out of the tables.
141 */
mdnadl(tbuf)142 VOID mdnadl(tbuf)
143 UNCH *tbuf; /* Work area for tokenization (tbuf). */
144 {
145 int i; /* Loop counter; temporary variable. */
146 int adlim; /* Number of unused ad slots in al. */
147 struct ad *alperm = 0; /* Attribute definition list. */
148 int stored = 0;
149
150 /* PARAMETER 1: Notation name or a group of them.
151 */
152 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
153 TRACEMD("1: notation name or group");
154 switch (pcbmd.action) {
155 case NAS:
156 nnmgrp[0] = dcndef(tbuf);
157 nnmgrp[1] = 0;
158 break;
159 case GRPS:
160 parsngrp(nnmgrp, &pcbgrnm, tbuf);
161 break;
162 default:
163 mderr(121, (UNCH *)0, (UNCH *)0);
164 return;
165 }
166 subdcl = nnmgrp[0]->ename+1; /* Save first name for error msgs. */
167 /* PARAMETER 2: Attribute definition list.
168 */
169 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
170 TRACEMD("2: attribute list");
171 if (pcbmd.action!=NAS) {
172 mderr(120, (UNCH *)0, (UNCH *)0);
173 return;
174 }
175 while (pcbmd.action==NAS) {
176 al[ADN(al)+1].adname = savenm(tbuf);
177 if ((adlim = ATTCNT-((int)ADN(al)++))<0) {
178 mderr(111, (UNCH *)0, (UNCH *)0);
179 adlfree(al, 1);
180 return;
181 }
182 ++AN(al);
183 if (mdattdef(adlim, 1)) {
184 adlfree(al, 1);
185 return;
186 }
187 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
188 }
189 if (AN(al)>0) { /* Save list only if 1 or more good atts. */
190 alperm = (struct ad *)rmalloc((1+ADN(al))*ADSZ);
191 memcpy((UNIV)alperm, (UNIV)al, (1+ADN(al))*ADSZ );
192 ds.attcnt += AN(al); /* Number of attributes defined. */
193 ds.attgcnt += ADN(al) - AN(al); /* Number of att grp members. */
194 TRACEADL(alperm);
195 }
196 /* Clear attribute list for next declaration. */
197 MEMZERO((UNIV)al, (1+ADN(al))*ADSZ);
198
199 /* PARAMETER 3: End of declaration.
200 */
201 /* Next pcb.action was set during attribute definition loop. */
202 TRACEMD(emd);
203 if (pcbmd.action!=EMD) {mderr(126, (UNCH *)0, (UNCH *)0); return;}
204 if (es!=mdessv) synerr(37, &pcbmd);
205
206 /* EXECUTE: Store the definition for each notation name specified.
207 */
208 TRACENGR(nnmgrp);
209 for (i = 0; nnmgrp[i]; i++) {
210 if (nnmgrp[i]->adl) { /* Error if an ADL exists. */
211 mderr(112, (UNCH *)0, (UNCH *)0);
212 continue;
213 }
214 nnmgrp[i]->adl = alperm; /* If virgin, store the adl ptr. */
215 if (nnmgrp[i]->entsw)
216 fixdatt(nnmgrp[i]);
217 stored = 1;
218 TRACEDCN(nnmgrp[i]);
219 }
220 if (!stored && alperm) {
221 adlfree(alperm, 1);
222 frem((UNIV)alperm);
223 }
224 }
225
226 /* Data attributes have been specified for notation p, but entities
227 have already been declared with notation p. Fix up the definitions of
228 all entities with notation p. Generate an error for any data
229 attribute that was required. */
230
fixdatt(p)231 VOID fixdatt(p)
232 struct dcncb *p;
233 {
234 int i;
235 for (i = 0; i < ENTHASH; i++) {
236 struct entity *ep;
237 for (ep = etab[i]; ep; ep = ep->enext)
238 if (ep->estore == ESN && ep->etx.n && ep->etx.n->nedcn == p) {
239 int adn;
240 initatt(p->adl);
241 /* Don't use adlval because if there were required
242 attributes the error message wouldn't say what
243 entity was involved. */
244 for (adn = 1; adn <= ADN(al); adn++) {
245 if (GET(ADFLAGS(al,adn), AREQ)) {
246 sgmlerr(218, &pcbstag, ADNAME(al,adn),
247 ep->ename + 1);
248 SET(ADFLAGS(al,adn), AINVALID);
249 }
250 if (BITON(ADFLAGS(al, adn), AGROUP))
251 adn += ADNUM(al, adn);
252 }
253 storedatt(ep->etx.n);
254 }
255 }
256 }
257
258 /* MDATTDEF: Process an individual attribute definition.
259 The attribute name is parsed by the caller.
260 Duplicate attributes are parsed, but removed from list.
261 Returns 0 if successful, otherwise returns 1.
262 */
mdattdef(adlim,datt)263 int mdattdef(adlim, datt)
264 int adlim; /* Remaining capacity of al (in tokens).*/
265 int datt; /* Non-zero if a data attribute. */
266 {
267 int deftype; /* Default value type: 0=not keyword. */
268 int errsw = 0; /* 1=semantic error; ignore att. */
269 int novalsw = 0; /* 1=semantic error; treat as IMPLIED. */
270 int attadn = (int)ADN(al); /* Save ad number of this attribute. */
271 struct parse *grppcb = NULL; /* PCB for name/token grp parse. */
272 int errcode; /* Error type returned by PARSEVAL, ANMTGRP. */
273 UNCH *advalsv; /* Save area for permanent value ptr. */
274
275 /* PARAMETER 1: Attribute name (parsed by caller).
276 */
277 TRACEMD("1: attribute name");
278 if (anmget((int)ADN(al)-1, al[attadn].adname)) {
279 errsw = 1;
280 mderr(99, ADNAME(al,attadn), (UNCH *)0);
281 }
282 ADNUM(al,attadn) = ADFLAGS(al,attadn) = ADLEN(al,attadn) = 0;
283 ADVAL(al,attadn) = 0; ADDATA(al,attadn).x = 0; ADTYPE(al,attadn) = ANMTGRP;
284 /* PARAMETER 2: Declared value.
285 */
286 parsemd(lbuf, NAMECASE, &pcblitp, NAMELEN);
287 TRACEMD("2: declared value");
288 switch (pcbmd.action) {
289 case NAS: /* Keyword for value type. */
290 switch (ADTYPE(al,attadn) = (UNCH)mapsrch(dvtab, lbuf+1)) {
291 case 0:
292 mderr(100, ADNAME(al,attadn), lbuf+1);
293 return 1;
294 case ANOTEGRP:
295 if (datt) {
296 errsw = 1;
297 mderr(156, (UNCH *)0, (UNCH *)0);
298 }
299 else if (!noteadn) noteadn = ADN(al);
300 else {
301 errsw = 1;
302 mderr(101, ADNAME(al,attadn), (UNCH *)0);
303 }
304 grppcb = &pcbgrnm; /* NOTATION requires name grp. */
305 parsemd(lbuf, NAMECASE, &pcblitp, NAMELEN);/* Get GRPO*/
306 break;
307 case AID:
308 if (datt) {
309 errsw = 1;
310 mderr(144, (UNCH *)0, (UNCH *)0);
311 }
312 else if (!idadn)
313 idadn = attadn;
314 else {
315 errsw = 1;
316 mderr(102, ADNAME(al,attadn), (UNCH *)0);
317 }
318 break;
319 case AIDREF:
320 case AIDREFS:
321 if (datt) {
322 errsw = 1;
323 mderr(155, (UNCH *)0, (UNCH *)0);
324 }
325 break;
326 case AENTITY:
327 case AENTITYS:
328 if (datt) {
329 errsw = 1;
330 mderr(154, (UNCH *)0, (UNCH *)0);
331 }
332 break;
333 }
334 break;
335 case GRPS:
336 grppcb = &pcbgrnt; /* Normal grp is name token grp. */
337 break;
338 case EMD:
339 mderr(103, ADNAME(al,attadn), (UNCH *)0);
340 return 1;
341 default:
342 mderr(104, ADNAME(al,attadn), (UNCH *)0);
343 return 1;
344 }
345 /* PARAMETER 2A: Name token group.
346 */
347 if (grppcb != NULL) {
348 TRACEMD("2A: name group");
349 switch (pcbmd.action) {
350 case GRPS: /* Name token list. */
351 SET(ADFLAGS(al,attadn), AGROUP);
352 /* Call routine to parse group, create ad entries in adl. */
353 errcode = anmtgrp(grppcb, al+attadn,
354 (GRPCNT<adlim ? GRPCNT+1 : adlim+1),
355 &al[attadn].adnum, ADN(al));
356 if (errcode<=0) {
357 if (adlim < GRPCNT)
358 mderr(111, (UNCH *)0, (UNCH *)0);
359 else
360 mderr(105, ADNAME(al,attadn), (UNCH *)0);
361 return 1;
362 }
363 ADN(al) += ADNUM(al,attadn); /* Add grp size to total ad cnt.*/
364 break;
365 default:
366 mderr(106, ADNAME(al,attadn), (UNCH *)0);
367 return 1;
368 }
369 }
370 /* PARAMETER 3: Default value keyword.
371 */
372 parsemd(lbuf, AVALCASE,
373 (ADTYPE(al,attadn)==ACHARS) ? &pcblitr : &pcblitt, LITLEN);
374 TRACEMD("3: default keyword");
375 switch (pcbmd.action) {
376 case RNS: /* Keyword. */
377 deftype = mapsrch(deftab, lbuf+1);
378 switch (deftype) {
379 case DFIXED: /* FIXED */
380 SET(ADFLAGS(al,attadn), AFIXED);
381 parsemd(lbuf, AVALCASE,
382 (ADTYPE(al,attadn)==ACHARS) ? &pcblitr : &pcblitt,
383 LITLEN); /* Real default. */
384 goto parm3x; /* Go process specified value. */
385 case DCURR: /* CURRENT: If ID, treat as IMPLIED. */
386 if (ADTYPE(al,attadn)==AID) {
387 mderr(80, ADNAME(al,attadn), (UNCH *)0);
388 break;
389 }
390 if (datt) {
391 mderr(157, (UNCH *)0, (UNCH *)0);
392 break;
393 }
394 SET(ADFLAGS(al,attadn), ACURRENT);
395 break;
396 case DREQ: /* REQUIRED */
397 SET(ADFLAGS(al,attadn), AREQ); ++reqadn;
398 break;
399 case DCONR: /* CONREF */
400 if (ADTYPE(al,attadn)==AID) {
401 mderr(107, ADNAME(al,attadn), (UNCH *)0);
402 break;
403 }
404 if (datt) {
405 mderr(158, (UNCH *)0, (UNCH *)0);
406 break;
407 }
408 SET(ADFLAGS(al,attadn), ACONREF); conradn = 1;
409 case DNULL: /* IMPLIED */
410 break;
411 default: /* Unknown keyword is an error. */
412 mderr(108, ADNAME(al,attadn), lbuf+1);
413 errsw = 1;
414 }
415 if (errsw) {
416 /* Ignore erroneous att. */
417 adlfree(al, attadn);
418 --AN(al);
419 ADN(al) = (UNCH)attadn-1;
420 }
421 return(0);
422 default:
423 break;
424 }
425 /* PARAMETER 3x: Default value (non-keyword).
426 */
427 parm3x:
428 TRACEMD("3x: default (non-keyword)");
429 if (ADTYPE(al,attadn)==AID) { /* If ID, treat as IMPLIED. */
430 mderr(81, ADNAME(al,attadn), (UNCH *)0);
431 novalsw = 1; /* Keep parsing to keep things straight. */
432 }
433 switch (pcbmd.action) {
434 case LIT: /* Literal. */
435 case LITE: /* Literal. */
436 /* Null string (except CDATA) is error: msg and treat as IMPLIED. */
437 if (*lbuf == '\0' && ADTYPE(al,attadn)!=ACHARS) {
438 mderr(82, ADNAME(al,attadn), (UNCH *)0);
439 novalsw = 1;
440 }
441 break;
442 case NAS: /* Name character string. */
443 case NMT: /* Name character string. */
444 case NUM: /* Number or number token string. */
445 /* The name won't have a length byte because AVALCASE was specified. */
446 break;
447 case CDR:
448 parsetkn(lbuf, NMC, LITLEN);
449 break;
450 case EMD:
451 mderr(109, ADNAME(al,attadn), (UNCH *)0);
452 return 1;
453 default:
454 mderr(110, ADNAME(al,attadn), (UNCH *)0);
455 return 1;
456 }
457 if (errsw) {
458 /* Ignore erroneous att. */
459 adlfree(al, attadn);
460 --AN(al);
461 ADN(al) = (UNCH)attadn-1;
462 return(0);
463 }
464 if (novalsw) return(0);
465
466 /* PARAMETER 3y: Validate and store default value.
467 */
468 if (ADTYPE(al,attadn)==ACHARS) {
469 UNS len = vallen(ACHARS, 0, lbuf);
470 if (len > LITLEN) {
471 /* Treat as implied. */
472 sgmlerr(224, &pcbmd, ADNAME(al,attadn), (UNCH *)0);
473 return 0;
474 }
475 /* No more checking for CDATA value. */
476 ADNUM(al,attadn) = 0; /* CDATA is 0 tokens. */
477 ADVAL(al,attadn) = savestr(lbuf);/* Store default; save ptr. */
478 ADLEN(al,attadn) = len;
479 ds.attdef += len;
480 return 0;
481 }
482 /* Parse value and save token count (GROUP implies 1 token). */
483 advalsv = (UNCH *)rmalloc(ustrlen(lbuf)+2); /* Storage for tokenized value. */
484 errcode = parseval(lbuf, (UNS)ADTYPE(al,attadn), advalsv);
485 if (BITOFF(ADFLAGS(al,attadn), AGROUP)) ADNUM(al,attadn) = (UNCH)tokencnt;
486
487 /* If value was invalid, or was a group member that was not in the group,
488 issue an appropriate message and set the error switch. */
489 if (errcode)
490 {sgmlerr((UNS)errcode, &pcbmd, ADNAME(al,attadn), lbuf); errsw = 1;}
491 else if ( BITON(ADFLAGS(al,attadn), AGROUP)
492 && !amemget(&al[attadn], (int)ADNUM(al,attadn), advalsv) ) {
493 sgmlerr(79, &pcbmd, ADNAME(al,attadn), advalsv+1);
494 errsw = 1;
495 }
496 ADLEN(al,attadn) = vallen(ADTYPE(al,attadn), ADNUM(al,attadn), advalsv);
497 if (ADLEN(al,attadn) > LITLEN) {
498 sgmlerr(224, &pcbmd, ADNAME(al,attadn), (UNCH *)0);
499 ADLEN(al,attadn) = 0;
500 errsw = 1;
501 }
502 /* For valid tokenized value, save it and update statistics. */
503 if (!errsw) {
504 ADVAL(al,attadn) = advalsv;
505 ds.attdef += ADLEN(al,attadn);
506 return 0;
507 }
508 /* If value was bad, free the value's storage and treat as
509 IMPLIED or REQUIRED. */
510 frem((UNIV)advalsv); /* Release storage for value. */
511 ADVAL(al,attadn) = NULL; /* And make value NULL. */
512 return 0;
513 }
514 /* ANMTGRP: Parse a name or name token group, create attribute descriptors
515 for its members, and add them to the attribute descriptor list.
516 The parse either terminates or returns a good token, so no
517 switch is needed.
518 */
anmtgrp(pcb,nt,grplim,adn,adsz)519 int anmtgrp(pcb, nt, grplim, adn, adsz)
520 struct parse *pcb; /* PCB for name or name token grp. */
521 struct ad nt[]; /* Buffer for creating name token list. */
522 int grplim; /* Maximum size of list (plus 1). */
523 UNS *adn; /* Ptr to number of names or tokens in grp. */
524 int adsz; /* Size of att def list. */
525 {
526 UNCH adtype = (UNCH)(pcb==&pcbgrnt ? ANMTGRP:ANOTEGRP);/*Attribute type.*/
527 int essv = es; /* Entity stack level when grp started. */
528
529 *adn = 0; /* Group is empty to start. */
530 while (parse(pcb)!=GRPE && *adn<grplim) {
531 switch (pcb->action) {
532 case NAS_: /* Name or name token (depending on pcb). */
533 case NMT_:
534 parsenm(lbuf, NAMECASE);
535 nt[*adn+1].adname = savenm(lbuf);
536 if (antvget((int)(adsz+*adn), nt[*adn+1].adname, (UNCH **)0))
537 mderr(98, ntoa((int)*adn+1), nt[*adn+1].adname+1);
538 nt[++*adn].adtype = adtype;
539 nt[*adn].addef = NULL;
540 continue;
541
542 case EE_: /* Entity ended (correctly or incorrectly). */
543 if (es<essv) {synerr(37, pcb); essv = es;}
544 continue;
545
546 case PIE_: /* PI entity reference (invalid). */
547 entpisw = 0; /* Reset PI entity indicator. */
548 synerr(59, pcb);
549 continue;
550
551 default:
552 break;
553 }
554 break;
555 }
556 if (es!=essv) synerr(37, pcb);
557 if (*adn==grplim) return -1;
558 else return *adn; /* Return number of tokens. */
559 }
560 /* MDDTDS: Process start of DOCTYPE declaration (through MSO).
561 */
mddtds(tbuf)562 VOID mddtds(tbuf)
563 UNCH *tbuf; /* Work area for tokenization[LITLEN+2]. */
564 {
565 struct fpi fpicb; /* Formal public identifier structure. */
566 union etext etx; /* Ptr to entity text. */
567 UNCH estore = ESD; /* Entity storage class. */
568 int emdsw = 0; /* 1=end of declaration found; 0=not yet. */
569
570 mdname = key[KDOCTYPE]; /* Identify declaration for messages. */
571 subdcl = NULL; /* No subject as yet. */
572 parmno = 0; /* No parameters as yet. */
573 mdessv = es; /* Save es for checking entity nesting. */
574 dtdrefsw = 0; /* No external DTD entity as yet. */
575 /* PARAMETER 1: Document type name.
576 */
577 pcbmd.newstate = 0;
578 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
579 TRACEMD("1: doc type name");
580 if (pcbmd.action!=NAS) {mderr(120, (UNCH *)0, (UNCH *)0); return;}
581 dtype = savenm(tbuf);
582 subdcl = dtype+1; /* Subject of declaration for error msgs. */
583
584 /* PARAMETER 2: External identifier keyword or MDS.
585 */
586 pcbmd.newstate = 0;
587 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
588 TRACEMD("2: extid or MDS");
589 switch (pcbmd.action) {
590 case NAS:
591 if (mdextid(tbuf, &fpicb, dtype+1, &estore, (PNE)0)==0) return;
592 if ((etx.x = entgen(&fpicb))==0)
593 mderr(146, dtype+1, (UNCH *)0);
594 else
595 dtdrefsw = 1; /* Signal external DTD entity. */
596 break;
597 case MDS:
598 goto execute;
599 default:
600 mderr(128, (UNCH *)0, (UNCH *)0);
601 return;
602 }
603 /* PARAMETER 3: MDS or end of declaration.
604 */
605 TRACEMD("3: MDS or EMD");
606 switch (pcbmd.action) {
607 default: /* Treat as end of declaration. */
608 mderr(126, (UNCH *)0, (UNCH *)0);
609 case EMD:
610 emdsw = 1;
611 case MDS:
612 break;
613 }
614 /* EXECUTE: Store entity definition if an external ID was specified.
615 */
616 execute:
617 if (es!=mdessv) synerr(37, &pcbmd);
618 propcb = &pcbmds; /* Prepare to parse doc type definition (MDS). */
619 if (dtdrefsw) {
620 /* TO DO: If concurrent DTD's supported, free existing
621 etext for all but first DTD (or reuse it). */
622 entdef(indtdent, estore, &etx);
623 ++ds.ecbcnt; ds.ecbtext += entlen;
624 if (emdsw) {
625 REPEATCC; /* Push back the MDC. */
626 *FPOS = lex.d.msc; /* Simulate end of DTD subset. */
627 REPEATCC; /* Back up to read MSC next. */
628 delmscsw = 1; /* Insert MSC after referenced DTD. */
629 }
630 }
631 indtdsw = 1; /* Allow "DTD only" parameters. */
632 return;
633 }
634 /* MDDTDE: Process DOCTYPE declaration end.
635 */
mddtde(tbuf)636 VOID mddtde(tbuf)
637 UNCH *tbuf; /* Work area for tokenization. */
638 {
639 mdessv = es; /* Save es for checking entity nesting. */
640 propcb = &pcbpro; /* Restore normal prolog parse. */
641 indtdsw = 0; /* Prohibit "DTD only" parameters. */
642
643 mdname = key[KDOCTYPE]; /* Identify declaration for messages. */
644 subdcl = dtype+1; /* Subject of declaration for error msgs. */
645 parmno = 0; /* No parameters as yet. */
646 /* PARAMETER 4: End of declaration.
647 */
648 pcbmd.newstate = 0;
649 parsemd(tbuf, NAMECASE, &pcblitp, LITLEN);
650 TRACEMD(emd);
651 if (pcbmd.action!=EMD) mderr(126, (UNCH *)0, (UNCH *)0);
652 if (es!=mdessv) synerr(37, &pcbmd);
653 }
654 /* MDELEM: Process ELEMENT declaration.
655 */
mdelem(tbuf)656 VOID mdelem(tbuf)
657 UNCH *tbuf; /* Work area for tokenization (tbuf). */
658 {
659 UNCH *ranksuff = lbuf; /* Rank suffix. */
660 UNS dctype = 0; /* Declared content type (from dctab). */
661 UNCH fmin = 0; /* Minimization bit flags. */
662 int i; /* Loop counter. */
663 UNS u; /* Temporary variable. */
664 struct etd **mexgrp, **pexgrp; /* Ptr to model exceptions array. */
665 struct thdr *cmod, *cmodsv; /* Ptr to content model. */
666 UNCH *etdgi; /* GI of current etd (when going through group).*/
667 int minomitted = 0; /* Tag minimization parameters omitted. */
668
669 mdname = key[KELEMENT]; /* Identify declaration for messages. */
670 subdcl = NULL; /* No subject as yet. */
671 parmno = 0; /* No parameters as yet. */
672 mdessv = es; /* Save es level for entity nesting check. */
673 ranksuff[0] = 0;
674 mexgrp = pexgrp = 0;
675
676 /* PARAMETER 1: Element name or a group of them.
677 */
678 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
679 TRACEMD("1: element name or grp");
680 switch (pcbmd.action) {
681 case NAS:
682 nmgrp[0] = etddef(tbuf);
683 nmgrp[1] = 0;
684 break;
685 case GRPS:
686 parsegrp(nmgrp, &pcbgrnm, tbuf);
687 break;
688 default:
689 mderr(121, (UNCH *)0, (UNCH *)0);
690 return;
691 }
692 /* Save first GI for trace and error messages. */
693 if (nmgrp[0])
694 subdcl = nmgrp[0]->etdgi+1;
695
696 /* PARAMETER 1A: Rank suffix (optional).
697 */
698 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
699 TRACEMD("1A: rank suffix");
700 switch (pcbmd.action) {
701 case NUM:
702 ustrcpy(ranksuff, tbuf);
703 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
704 default:
705 break;
706 }
707 /* PARAMETER 2A: Start-tag minimization.
708 */
709 TRACEMD("2A: start min");
710 switch (pcbmd.action) {
711 case CDR:
712 break;
713 case NAS:
714 if (!ustrcmp(tbuf+1, key[KO])) {
715 if (OMITTAG==YES) SET(fmin, SMO);
716 break;
717 }
718 /* fall through */
719 default:
720 if (OMITTAG==NO) {minomitted=1; break;}
721 mderr(129, tbuf+1, (UNCH *)0);
722 return;
723 }
724 /* Must omit omitted end-tag minimization, if omitted
725 start-tag minimization was omitted (because OMITTAG == NO). */
726 if (!minomitted) {
727 /* PARAMETER 2B: End-tag minimization.
728 */
729 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
730 TRACEMD("2B: end min");
731 switch (pcbmd.action) {
732 case NAS:
733 if (ustrcmp(tbuf+1, key[KO])) {mderr(129, tbuf+1, (UNCH *)0); return;}
734 if (OMITTAG==YES) SET(fmin, EMO);
735 break;
736 case CDR:
737 SET(fmin, EMM);
738 break;
739 default:
740 mderr(129, tbuf+1, (UNCH *)0);
741 return;
742 }
743 /* PARAMETER 3: Declared content.
744 */
745 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
746 }
747 TRACEMD("3: declared content");
748 switch (pcbmd.action) {
749 case NAS:
750 dctype = mapsrch(dctab, tbuf+1);
751 if (!dctype) {mderr(24, tbuf+1, (UNCH *)0); return;}
752 /* Eliminate incompatibilities among parameters. */
753 if (GET(fmin, SMO) && GET(dctype, MNONE+MCDATA+MRCDATA)) {
754 mderr(58, (UNCH *)0, (UNCH *)0);
755 RESET(fmin, SMO);
756 }
757 if (GET(dctype, MNONE) && BITON(fmin, EMM)) {
758 mderr(87, (UNCH *)0, (UNCH *)0);
759 SET(fmin, EMO);
760 }
761 /* If valid, process like a content model. */
762 case GRPS:
763 cmodsv = parsemod((int)(pcbmd.action==GRPS ? 0 : dctype));
764 if (cmodsv==0) return;
765 u = (dctype ? 1 : cmodsv->tu.tnum+2) * THSZ;
766 cmod = (struct thdr *)rmalloc(u);
767 memcpy((UNIV)cmod , (UNIV)cmodsv, u );
768 ds.modcnt += cmod->tu.tnum;
769 TRACEMOD(cmod);
770 break;
771 default:
772 mderr(130, (UNCH *)0, (UNCH *)0);
773 return;
774 }
775 /* PARAMETERS 3A, 3B: Exceptions or end.
776 */
777 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
778 if (BITOFF(cmod->ttype, MCDATA+MRCDATA+MNONE)) {
779 /* PARAMETER 3A: Minus exceptions.
780 */
781 TRACEMD("3A: -grp");
782 switch (pcbmd.action) {
783 case MGRP:
784 /* We cheat and use nnmgrp for this. */
785 mexgrp = copygrp((PETD *)nnmgrp,
786 u = parsegrp((PETD *)nnmgrp, &pcbgrnm, tbuf));
787 ++ds.pmexgcnt; ds.pmexcnt += u-1;
788 TRACEGRP(mexgrp);
789 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
790 default:
791 break;
792 }
793 /* PARAMETER 3B: Plus exceptions.
794 */
795 TRACEMD("3B: +grp");
796 switch (pcbmd.action) {
797 case PGRP:
798 pexgrp = copygrp((PETD *)nnmgrp,
799 u = parsegrp((PETD *)nnmgrp, &pcbgrnm, tbuf));
800 ++ds.pmexgcnt; ds.pmexcnt += u-1;
801 TRACEGRP(pexgrp);
802 parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
803 default:
804 break;
805 }
806 }
807 /* PARAMETER 4: End of declaration.
808 */
809 TRACEMD(emd);
810 if (pcbmd.action!=EMD) mderr(126, (UNCH *)0, (UNCH *)0);
811 if (es!=mdessv) synerr(37, &pcbmd);
812
813 /* EXECUTE: Store the definition for each element name specified.
814 */
815 TRACEGRP(nmgrp);
816 for (i = -1; nmgrp[++i];) {
817 etdgi = nmgrp[i]->etdgi;
818 if (*ranksuff) {
819 if ((tbuf[0] = *etdgi + ustrlen(ranksuff)) - 2 > NAMELEN) {
820 mderr(131, etdgi+1, ranksuff);
821 continue;
822 }
823 memcpy(tbuf+1, etdgi+1, *etdgi-1);
824 ustrcpy(tbuf+*etdgi-1, ranksuff);
825 etdcan(etdgi);
826 nmgrp[i] = etddef(tbuf);
827 }
828 if (nmgrp[i]->etdmod) {mderr(56, etdgi+1, (UNCH *)0); continue;}
829 etdset(nmgrp[i], fmin+ETDDCL, cmod, mexgrp, pexgrp, nmgrp[i]->etdsrm);
830 ++ds.etdcnt;
831 if (nmgrp[i]->adl) etdadl(nmgrp[i]); /* Check ETD conflicts. */
832 TRACEETD(nmgrp[i]);
833 }
834 }
835
adlfree(al,aln)836 VOID adlfree(al, aln)
837 struct ad *al;
838 int aln;
839 {
840 for (; aln <= ADN(al); aln++) {
841 frem((UNIV)al[aln].adname);
842 if (ADVAL(al, aln))
843 frem((UNIV)ADVAL(al, aln));
844 if (BITON(ADFLAGS(al, aln), AGROUP)) {
845 int i;
846 for (i = 0; i < ADNUM(al, aln); i++)
847 frem((UNIV)al[aln + i + 1].adname);
848 aln += ADNUM(al, aln);
849 }
850 }
851 }
852
853 /*
854 Local Variables:
855 c-indent-level: 5
856 c-continued-statement-offset: 5
857 c-brace-offset: -5
858 c-argdecl-indent: 0
859 c-label-offset: -5
860 comment-column: 30
861 End:
862 */
863