1 #include "sgmlincl.h" /* #INCLUDE statements for SGML parser. */
2
3 #define ETDCON (tags[ts].tetd->etdmod->ttype) /* ETD content flags. */
4
5 /* SGML: Main SGML driver routine.
6 */
sgmlnext(rcbdafp,rcbtagp)7 enum sgmlevent sgmlnext(rcbdafp, rcbtagp)
8 struct rcbdata *rcbdafp;
9 struct rcbtag *rcbtagp;
10 {
11 while (prologsw && !conactsw) {
12 int oconact;
13 conact = parsepro();
14 conactsw = 0; /* Assume sgmlact() will not be skipped. */
15 switch(conact) {
16
17 case PIS_:
18 case EOD_:
19 case APP_: /* APPINFO */
20 conactsw = 1; /* We can skip sgmlact() in opening state. */
21 break;
22
23 case DAF_:
24 newetd = stagreal = ETDCDATA;
25 conact = stag(datarc = DAF_);
26 conactsw = 1; /* We can skip sgmlact() in opening state. */
27 prologsw = 0; /* End the prolog. */
28 break;
29 case DCE_:
30 case MSS_:
31 /* prcon[2].tu.thetd holds the etd for the document element. */
32 newetd = stagreal = prcon[2].tu.thetd;
33 stagmin = MINSTAG; /* This tag was minimized. */
34 /* It's an error if the start tag of the document element
35 is not minimizable. */
36 if (BITOFF(newetd->etdmin, SMO))
37 sgmlerr(226, conpcb, (UNCH *)0, (UNCH *)0);
38 oconact = conact; /* Save conact. */
39 conact = stag(0); /* Start the document element. */
40 conactsw = 1; /* conact needs processing. */
41 prologsw = 0; /* The prolog is finished. */
42 if (oconact == MSS_) {
43 if (msplevel==0) conpcb = getpcb((int)ETDCON);
44 conpcb = mdms(tbuf, conpcb); /* Parse the marked section
45 start. */
46 }
47 break;
48 default: /* STE_: not defined in SGMLACT.H. */
49 if (msplevel==0) conpcb = getpcb((int)ETDCON);
50 prologsw = 0; /* End the prolog. */
51 break;
52 }
53 }
54 for (;;) {
55 unsigned swact; /* Switch action: saved conact, new, or sgmlact.*/
56
57 if (conactsw) {
58 conactsw = 0;
59 swact = conact;
60 contersw = contersv;
61 }
62 else {
63 conact = parsecon(tbuf, conpcb);
64 swact = sgmlact((UNCH)(conact != EOD_ ? conact : LOP_));
65 }
66
67 switch (swact) {
68
69 case MD_: /* Process markup declaration. */
70 parsenm(tbuf, NAMECASE); /* Get declaration name. */
71 if (!ustrcmp(tbuf+1, key[KUSEMAP])) mdsrmuse(tbuf);
72 else sgmlerr(E_MDNAME, conpcb, tbuf+1, (UNCH *)0);
73 continue;
74 case MDC_: /* Process markup declaration comment. */
75 if (*FPOS!=lex.d.mdc)
76 parsemd(tbuf, NAMECASE, (struct parse *)0, NAMELEN);
77 continue;
78
79 case MSS_: /* Process marked section start. */
80 conpcb = mdms(tbuf, conpcb);
81 continue;
82 case MSE_: /* Process marked section end (drop to LOP_). */
83 if (mdmse()) conpcb = getpcb((int)ETDCON);
84 continue;
85
86 case PIS_: /* Return processing instruction (string). */
87 if (entpisw) rcbdafp->data = data;
88 else {
89 parselit(tbuf, &pcblitc, PILEN, lex.d.pic);
90 rcbdafp->data = tbuf;
91 }
92 rcbdafp->datalen = datalen;
93 rcbdafp->contersw = entpisw;
94 entpisw = 0; /* Reset for next time.*/
95 scbset(); /* Update location in current scb. */
96 return SGMLPIS;
97
98 case APP_:
99 rcbdafp->data = tbuf;
100 rcbdafp->datalen = ustrlen(tbuf);
101 rcbdafp->contersw = 0;
102 scbset();
103 return SGMLAPP;
104 case ETG_: /* Return end-tag. */
105 charmode = 0; /* Not in char mode unless CDATA or RCDATA.*/
106 if (msplevel==0) conpcb = getpcb((int)ETDCON);
107 rcbtagp->contersw = tags[ts+1].tflags;
108 rcbtagp->tagmin = etagimsw ? MINETAG : etagmin;
109 rcbtagp->curgi = tags[ts+1].tetd->etdgi;
110 rcbtagp->ru.oldgi = tags[ts].tetd->etdgi;
111 if (etagmin==MINSTAG) rcbtagp->tagreal =
112 BADPTR(stagreal) ? stagreal : (PETD)stagreal->etdgi;
113 else rcbtagp->tagreal =
114 BADPTR(etagreal) ? etagreal : (PETD)etagreal->etdgi;
115 rcbtagp->etictr = etictr;
116 rcbtagp->srmnm = tags[ts].tsrm!=SRMNULL ? tags[ts].tsrm[0]->ename
117 : 0;
118 scbset(); /* Update location in current scb. */
119 return SGMLETG;
120
121 case STG_: /* Return start-tag. */
122 charmode = 0; /* Not in char mode unless CDATA or RCDATA.*/
123 if (!conrefsw && msplevel==0) conpcb = getpcb((int)ETDCON);
124 rcbtagp->contersw = tags[ts].tflags;
125 rcbtagp->tagmin = dostag ? MINSTAG : stagmin;
126 rcbtagp->curgi = tags[ts].tetd->etdgi;
127 /* Get attribute list if one was defined for this element. */
128 rcbtagp->ru.al = !tags[ts].tetd->adl ? 0 :
129 rcbtagp->tagmin==MINNONE ? al : tags[ts].tetd->adl;
130 rcbtagp->tagreal = BADPTR(stagreal)?stagreal:(PETD)stagreal->etdgi;
131 rcbtagp->etictr = etictr;
132 rcbtagp->srmnm = tags[ts].tsrm!=SRMNULL ? tags[ts].tsrm[0]->ename
133 : 0;
134 scbset(); /* Update location in current scb. */
135 return SGMLSTG;
136
137 case DAF_: /* Return data in source entity buffer. */
138 charmode = 1;
139 rcbdafp->datalen = datalen;
140 rcbdafp->data = data;
141 rcbdafp->contersw = contersw | entdatsw;
142 contersw = entdatsw = 0;/* Reset for next time.*/
143 scbset(); /* Update location in current scb. */
144 return SGMLDAF;
145
146 case CON_: /* Process conact after returning REF_. */
147 conactsw = 1;
148 contersv = contersw;
149 case REF_: /* Return RE found. */
150 if (badresw) {
151 badresw = 0;
152 sgmlerr(E_CHARS, &pcbconm, tags[ts].tetd->etdgi+1, (UNCH *)0);
153 continue;
154 }
155 charmode = 1;
156 rcbdafp->contersw = contersw;
157 contersw = 0; /* Reset for next time.*/
158 scbset(); /* Update location in current scb. */
159 return SGMLREF;
160
161 case EOD_: /* End of source document entity. */
162 if (mslevel != 0) sgmlerr(139, conpcb, (UNCH *)0, (UNCH *)0);
163 idrck(); /* Check idrefs. */
164 scbset(); /* Update location in current scb. */
165 return SGMLEOD;
166
167 default: /* LOP_: Loop again with no action. */
168 continue;
169 }
170 }
171 }
172 /* PCBSGML: State and action table for action codes returned to text processor
173 by SGML.C.
174 Columns are based on SGMLACT.H values minus DAF_, except that end
175 of document has input code LOP_, regardless of its action code.
176 */
177 /* Symbols for state names (end with a number). */
178 #define ST1 0 /* Just had a start tag. */
179 #define NR1 2 /* Just had an RS or RE. */
180 #define DA1 4 /* Just had some data. */
181 #define NR2 6 /* Just had an RE; RE pending. */
182 #define ST2 8 /* Had only markup since last RE/RS; RE pending. */
183
184 static UNCH sgmltab[][11] = {
185 /*daf_ etg_ md_ mdc_ mss_ mse_ pis_ ref_ stg_ rsr_ eod */
186 {DA1 ,DA1 ,ST1 ,ST1 ,ST1 ,ST1 ,ST1 ,NR1 ,ST1 ,NR1 ,ST1 },/*st1*/
187 {DAF_,ETG_,MD_ ,MDC_,MSS_,MSE_,PIS_,LOP_,STG_,LOP_,EOD_},
188
189 {DA1 ,DA1 ,ST1 ,ST1 ,ST1 ,ST1 ,ST1 ,NR2 ,ST1 ,NR1 ,ST1 },/*nr1*/
190 {DAF_,ETG_,MD_ ,MDC_,MSS_,MSE_,PIS_,LOP_,STG_,LOP_,EOD_},
191
192 {DA1 ,DA1 ,DA1 ,DA1 ,DA1 ,DA1 ,DA1 ,NR2 ,ST1 ,NR1 ,ST1 },/*da1*/
193 {DAF_,ETG_,MD_ ,MDC_,MSS_,MSE_,PIS_,LOP_,STG_,LOP_,EOD_},
194
195 {DA1 ,DA1 ,ST2 ,ST2 ,ST2 ,ST2 ,ST2 ,NR2 ,ST1 ,NR2 ,ST1 },/*nr2*/
196 {CON_,ETG_,MD_ ,MDC_,MSS_,MSE_,PIS_,REF_,CON_,LOP_,EOD_},
197
198 {DA1 ,DA1 ,ST2 ,ST2 ,ST2 ,ST2 ,ST2 ,NR1 ,ST1 ,NR2 ,ST1 },/*st2*/
199 {CON_,ETG_,MD_ ,MDC_,MSS_,MSE_,PIS_,REF_,CON_,LOP_,EOD_},
200 };
201 int scbsgmst = ST1; /* SCBSGML: trailing stag or markup; ignore RE. */
202 int scbsgmnr = NR1; /* SCBSGML: new record; do not ignore RE. */
203 /* SGMLACT: Determine action to be taken by SGML.C based on current state and
204 specified input.
205 For start or end of a plus exception element, push or pop the
206 pcbsgml stack.
207 Return to caller with action code.
208 */
209 #ifdef USE_PROTOTYPES
sgmlact(UNCH conret)210 int sgmlact(UNCH conret)
211 #else
212 int sgmlact(conret)
213 UNCH conret; /* Action returned to SGML.C by content parse. */
214 #endif
215 {
216 int action;
217
218 if (conret==STG_ && GET(tags[ts].tflags, TAGPEX))
219 {++pss; scbsgml[pss].snext = ST1;}
220 scbsgml[pss].sstate = scbsgml[pss].snext;
221 scbsgml[pss].snext = sgmltab[scbsgml[pss].sstate]
222 [scbsgml[pss].sinput = conret-DAF_];
223 scbsgml[pss].saction = sgmltab[scbsgml[pss].sstate+1][scbsgml[pss].sinput];
224 TRACEGML(scbsgml, pss, conactsw, conact);
225 action = scbsgml[pss].saction;
226 if (conret==ETG_ && GET(tags[ts+1].tflags, TAGPEX)) {
227 pss--;
228 /* An included subelement affects the enclosing state like a
229 processing instruction (or MDC_ or MD_),
230 that is to say NR1 is changed to ST1 and NR2 to ST2. */
231 scbsgml[pss].sstate = scbsgml[pss].snext;
232 scbsgml[pss].snext = sgmltab[scbsgml[pss].sstate][PIS_ - DAF_];
233 }
234 return action;
235 }
236 /* GETPCB: Choose pcb for new or resumed element.
237 */
getpcb(etdcon)238 struct parse *getpcb(etdcon)
239 int etdcon; /* Content type of new or resumed element. */
240 {
241 if (BITON(etdcon, MGI)) {
242 return(BITON(etdcon, MCHARS) ? &pcbconm : &pcbcone);
243 }
244 if (BITON(etdcon, MCDATA) || BITON(etdcon, MRCDATA)) {
245 charmode = 1;
246 return(BITON(etdcon, MCDATA) ? &pcbconc : (rcessv = es, &pcbconr));
247 }
248 return(&pcbconm);
249 }
250
sgmlset(swp)251 struct markup *sgmlset(swp)
252 struct switches *swp;
253 {
254 /* Initialize variables based on switches structure members. */
255 sw = *swp;
256 rbufs = (UNCH *)rmalloc((UNS)3+sw.swbufsz) + 3; /* DOS file read area. */
257 TRACEPRO(); /* Set trace switches for prolog. */
258 msginit(swp);
259 ioinit(swp);
260 sdinit();
261 return &lex.m;
262 }
263
264 /* Points for each capacity, indexed by *CAP in sgmldecl.h. We'll replace
265 2 with the real NAMELEN at run time. */
266
267 static UNCH cappoints[] = {
268 1,
269 2,
270 1,
271 2,
272 2,
273 2,
274 2,
275 2,
276 1,
277 2,
278 2,
279 1,
280 2,
281 2,
282 2,
283 2,
284 2
285 };
286
287 static long capnumber[NCAPACITY];
288 static long maxsubcap[NCAPACITY];
289
sgmlend(p)290 VOID sgmlend(p)
291 struct sgmlcap *p;
292 {
293 int i;
294 for (; es >= 0; --es)
295 if (FILESW)
296 fileclos();
297
298 capnumber[NOTCAP] = ds.dcncnt;
299 capnumber[EXGRPCAP] = ds.pmexgcnt;
300 capnumber[ELEMCAP] = ds.etdcnt+ds.etdercnt;
301 capnumber[EXNMCAP] = ds.pmexcnt;
302 capnumber[GRPCAP] = ds.modcnt;
303 capnumber[ATTCAP] = ds.attcnt;
304 capnumber[ATTCHCAP] = ds.attdef;
305 capnumber[AVGRPCAP] = ds.attgcnt;
306 capnumber[IDCAP] = ds.idcnt;
307 capnumber[IDREFCAP] = ds.idrcnt;
308 capnumber[ENTCAP] = ds.ecbcnt;
309 capnumber[ENTCHCAP] = ds.ecbtext;
310 capnumber[MAPCAP] = ds.srcnt + ds.srcnt*lex.s.dtb[0].mapdata;
311 capnumber[NOTCHCAP] = ds.dcntext;
312
313 capnumber[TOTALCAP] = 0;
314
315 for (i = 1; i < NCAPACITY; i++) {
316 if (cappoints[i] > 1)
317 cappoints[i] = NAMELEN;
318 capnumber[i] += maxsubcap[i]/cappoints[i];
319 capnumber[TOTALCAP] += (long)capnumber[i] * cappoints[i];
320 }
321 p->number = capnumber;
322 p->points = cappoints;
323 p->limit = sd.capacity;
324 p->name = captab;
325
326 for (i = 0; i < NCAPACITY; i++) {
327 long excess = capnumber[i]*cappoints[i] - sd.capacity[i];
328 if (excess > 0) {
329 char buf[sizeof(long)*3 + 1];
330 sprintf(buf, "%ld", excess);
331 sgmlerr(162, (struct parse *)0,
332 (UNCH *)captab[i], (UNCH *)buf);
333 }
334 }
335 }
336
sgmlsubcap(v)337 VOID sgmlsubcap(v)
338 long *v;
339 {
340 int i;
341 for (i = 0; i < NCAPACITY; i++)
342 if (v[i] > maxsubcap[i])
343 maxsubcap[i] = v[i];
344 }
345
sgmlsdoc(ptr)346 int sgmlsdoc(ptr)
347 UNIV ptr;
348 {
349 struct entity *e;
350 union etext etx;
351 etx.x = ptr;
352
353 e = entdef(indocent, ESF, &etx);
354 if (!e)
355 return -1;
356 return entopen(e);
357 }
358
359 /* SGMLGENT: Get a data entity.
360 Returns:
361 -1 if the entity does not exist
362 -2 if it is not a data entity
363 1 if it is an external entity
364 2 if it is an internal cdata entity
365 3 if it is an internal sdata entity
366 */
sgmlgent(iname,np,tp)367 int sgmlgent(iname, np, tp)
368 UNCH *iname;
369 PNE *np;
370 UNCH **tp;
371 {
372 PECB ep; /* Pointer to an entity control block. */
373
374 ep = entfind(iname);
375 if (!ep)
376 return -1;
377 switch (ep->estore) {
378 case ESN:
379 if (np)
380 *np = ep->etx.n;
381 return 1;
382 case ESC:
383 if (tp)
384 *tp = ep->etx.c;
385 return 2;
386 case ESX:
387 if (tp)
388 *tp = ep->etx.c;
389 return 3;
390 }
391 return -2;
392 }
393
394 /* Mark an entity. */
395
sgmlment(iname)396 int sgmlment(iname)
397 UNCH *iname;
398 {
399 PECB ep;
400 int rc;
401
402 ep = entfind(iname);
403 if (!ep)
404 return -1;
405 rc = ep->mark;
406 ep->mark = 1;
407 return rc;
408 }
409
sgmlgcnterr()410 int sgmlgcnterr()
411 {
412 return msgcnterr();
413 }
414
415 /* This is for error handling functions that want to print a gi backtrace. */
416
getgi(i)417 UNCH *getgi(i)
418 int i;
419 {
420 return i >= 0 && i <= ts ? tags[i].tetd->etdgi + 1 : NULL;
421 }
422
423 /* Returns the value of prologsw for the use by error handling functions. */
424
inprolog()425 int inprolog()
426 {
427 return prologsw;
428 }
429
430 /* Used by the error handling functions to access scbs. */
431
getlocation(level,locp)432 int getlocation(level, locp)
433 int level;
434 struct location *locp;
435 {
436 if (level < 0 || level > es)
437 return 0;
438 if (locp) {
439 int es = level;
440 /* source macros access a variable called `es' */
441
442 locp->filesw = FILESW;
443 locp->rcnt = RCNT;
444 locp->ccnt = CCNT;
445 locp->ename = ENTITY + 1;
446 locp->fcb = SCBFCB;
447 locp->curchar = CC;
448 locp->nextchar = NEXTC;
449 }
450 return 1;
451 }
452
sgmlloc(linenop,filenamep)453 int sgmlloc(linenop, filenamep)
454 unsigned long *linenop;
455 char **filenamep;
456 {
457 int level = es;
458 int es;
459
460 for (es = level; es >= 0 && !FILESW; es--)
461 ;
462 if (es < 0)
463 return 0;
464 *linenop = RCNT;
465 *filenamep = ioflid(SCBFCB);
466 return 1;
467 }
468
469 /*
470 Local Variables:
471 c-indent-level: 5
472 c-continued-statement-offset: 5
473 c-brace-offset: -5
474 c-argdecl-indent: 0
475 c-label-offset: -5
476 End:
477 */
478