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