#include "sgmlincl.h" /* #INCLUDE statements for SGML parser. */ #define ETDCON (tags[ts].tetd->etdmod->ttype) /* ETD content flags. */ /* SGML: Main SGML driver routine. */ enum sgmlevent sgmlnext(rcbdafp, rcbtagp) struct rcbdata *rcbdafp; struct rcbtag *rcbtagp; { while (prologsw && !conactsw) { int oconact; conact = parsepro(); conactsw = 0; /* Assume sgmlact() will not be skipped. */ switch(conact) { case PIS_: case EOD_: case APP_: /* APPINFO */ conactsw = 1; /* We can skip sgmlact() in opening state. */ break; case DAF_: newetd = stagreal = ETDCDATA; conact = stag(datarc = DAF_); conactsw = 1; /* We can skip sgmlact() in opening state. */ prologsw = 0; /* End the prolog. */ break; case DCE_: case MSS_: /* prcon[2].tu.thetd holds the etd for the document element. */ newetd = stagreal = prcon[2].tu.thetd; stagmin = MINSTAG; /* This tag was minimized. */ /* It's an error if the start tag of the document element is not minimizable. */ if (BITOFF(newetd->etdmin, SMO)) sgmlerr(226, conpcb, (UNCH *)0, (UNCH *)0); oconact = conact; /* Save conact. */ conact = stag(0); /* Start the document element. */ conactsw = 1; /* conact needs processing. */ prologsw = 0; /* The prolog is finished. */ if (oconact == MSS_) { if (msplevel==0) conpcb = getpcb((int)ETDCON); conpcb = mdms(tbuf, conpcb); /* Parse the marked section start. */ } break; default: /* STE_: not defined in SGMLACT.H. */ if (msplevel==0) conpcb = getpcb((int)ETDCON); prologsw = 0; /* End the prolog. */ break; } } for (;;) { unsigned swact; /* Switch action: saved conact, new, or sgmlact.*/ if (conactsw) { conactsw = 0; swact = conact; contersw = contersv; } else { conact = parsecon(tbuf, conpcb); swact = sgmlact((UNCH)(conact != EOD_ ? conact : LOP_)); } switch (swact) { case MD_: /* Process markup declaration. */ parsenm(tbuf, NAMECASE); /* Get declaration name. */ if (!ustrcmp(tbuf+1, key[KUSEMAP])) mdsrmuse(tbuf); else sgmlerr(E_MDNAME, conpcb, tbuf+1, (UNCH *)0); continue; case MDC_: /* Process markup declaration comment. */ if (*FPOS!=lex.d.mdc) parsemd(tbuf, NAMECASE, (struct parse *)0, NAMELEN); continue; case MSS_: /* Process marked section start. */ conpcb = mdms(tbuf, conpcb); continue; case MSE_: /* Process marked section end (drop to LOP_). */ if (mdmse()) conpcb = getpcb((int)ETDCON); continue; case PIS_: /* Return processing instruction (string). */ if (entpisw) rcbdafp->data = data; else { parselit(tbuf, &pcblitc, PILEN, lex.d.pic); rcbdafp->data = tbuf; } rcbdafp->datalen = datalen; rcbdafp->contersw = entpisw; entpisw = 0; /* Reset for next time.*/ scbset(); /* Update location in current scb. */ return SGMLPIS; case APP_: rcbdafp->data = tbuf; rcbdafp->datalen = ustrlen(tbuf); rcbdafp->contersw = 0; scbset(); return SGMLAPP; case ETG_: /* Return end-tag. */ charmode = 0; /* Not in char mode unless CDATA or RCDATA.*/ if (msplevel==0) conpcb = getpcb((int)ETDCON); rcbtagp->contersw = tags[ts+1].tflags; rcbtagp->tagmin = etagimsw ? MINETAG : etagmin; rcbtagp->curgi = tags[ts+1].tetd->etdgi; rcbtagp->ru.oldgi = tags[ts].tetd->etdgi; if (etagmin==MINSTAG) rcbtagp->tagreal = BADPTR(stagreal) ? stagreal : (PETD)stagreal->etdgi; else rcbtagp->tagreal = BADPTR(etagreal) ? etagreal : (PETD)etagreal->etdgi; rcbtagp->etictr = etictr; rcbtagp->srmnm = tags[ts].tsrm!=SRMNULL ? tags[ts].tsrm[0]->ename : 0; scbset(); /* Update location in current scb. */ return SGMLETG; case STG_: /* Return start-tag. */ charmode = 0; /* Not in char mode unless CDATA or RCDATA.*/ if (!conrefsw && msplevel==0) conpcb = getpcb((int)ETDCON); rcbtagp->contersw = tags[ts].tflags; rcbtagp->tagmin = dostag ? MINSTAG : stagmin; rcbtagp->curgi = tags[ts].tetd->etdgi; /* Get attribute list if one was defined for this element. */ rcbtagp->ru.al = !tags[ts].tetd->adl ? 0 : rcbtagp->tagmin==MINNONE ? al : tags[ts].tetd->adl; rcbtagp->tagreal = BADPTR(stagreal)?stagreal:(PETD)stagreal->etdgi; rcbtagp->etictr = etictr; rcbtagp->srmnm = tags[ts].tsrm!=SRMNULL ? tags[ts].tsrm[0]->ename : 0; scbset(); /* Update location in current scb. */ return SGMLSTG; case DAF_: /* Return data in source entity buffer. */ charmode = 1; rcbdafp->datalen = datalen; rcbdafp->data = data; rcbdafp->contersw = contersw | entdatsw; contersw = entdatsw = 0;/* Reset for next time.*/ scbset(); /* Update location in current scb. */ return SGMLDAF; case CON_: /* Process conact after returning REF_. */ conactsw = 1; contersv = contersw; case REF_: /* Return RE found. */ if (badresw) { badresw = 0; sgmlerr(E_CHARS, &pcbconm, tags[ts].tetd->etdgi+1, (UNCH *)0); continue; } charmode = 1; rcbdafp->contersw = contersw; contersw = 0; /* Reset for next time.*/ scbset(); /* Update location in current scb. */ return SGMLREF; case EOD_: /* End of source document entity. */ if (mslevel != 0) sgmlerr(139, conpcb, (UNCH *)0, (UNCH *)0); idrck(); /* Check idrefs. */ scbset(); /* Update location in current scb. */ return SGMLEOD; default: /* LOP_: Loop again with no action. */ continue; } } } /* PCBSGML: State and action table for action codes returned to text processor by SGML.C. Columns are based on SGMLACT.H values minus DAF_, except that end of document has input code LOP_, regardless of its action code. */ /* Symbols for state names (end with a number). */ #define ST1 0 /* Just had a start tag. */ #define NR1 2 /* Just had an RS or RE. */ #define DA1 4 /* Just had some data. */ #define NR2 6 /* Just had an RE; RE pending. */ #define ST2 8 /* Had only markup since last RE/RS; RE pending. */ static UNCH sgmltab[][11] = { /*daf_ etg_ md_ mdc_ mss_ mse_ pis_ ref_ stg_ rsr_ eod */ {DA1 ,DA1 ,ST1 ,ST1 ,ST1 ,ST1 ,ST1 ,NR1 ,ST1 ,NR1 ,ST1 },/*st1*/ {DAF_,ETG_,MD_ ,MDC_,MSS_,MSE_,PIS_,LOP_,STG_,LOP_,EOD_}, {DA1 ,DA1 ,ST1 ,ST1 ,ST1 ,ST1 ,ST1 ,NR2 ,ST1 ,NR1 ,ST1 },/*nr1*/ {DAF_,ETG_,MD_ ,MDC_,MSS_,MSE_,PIS_,LOP_,STG_,LOP_,EOD_}, {DA1 ,DA1 ,DA1 ,DA1 ,DA1 ,DA1 ,DA1 ,NR2 ,ST1 ,NR1 ,ST1 },/*da1*/ {DAF_,ETG_,MD_ ,MDC_,MSS_,MSE_,PIS_,LOP_,STG_,LOP_,EOD_}, {DA1 ,DA1 ,ST2 ,ST2 ,ST2 ,ST2 ,ST2 ,NR2 ,ST1 ,NR2 ,ST1 },/*nr2*/ {CON_,ETG_,MD_ ,MDC_,MSS_,MSE_,PIS_,REF_,CON_,LOP_,EOD_}, {DA1 ,DA1 ,ST2 ,ST2 ,ST2 ,ST2 ,ST2 ,NR1 ,ST1 ,NR2 ,ST1 },/*st2*/ {CON_,ETG_,MD_ ,MDC_,MSS_,MSE_,PIS_,REF_,CON_,LOP_,EOD_}, }; int scbsgmst = ST1; /* SCBSGML: trailing stag or markup; ignore RE. */ int scbsgmnr = NR1; /* SCBSGML: new record; do not ignore RE. */ /* SGMLACT: Determine action to be taken by SGML.C based on current state and specified input. For start or end of a plus exception element, push or pop the pcbsgml stack. Return to caller with action code. */ #ifdef USE_PROTOTYPES int sgmlact(UNCH conret) #else int sgmlact(conret) UNCH conret; /* Action returned to SGML.C by content parse. */ #endif { int action; if (conret==STG_ && GET(tags[ts].tflags, TAGPEX)) {++pss; scbsgml[pss].snext = ST1;} scbsgml[pss].sstate = scbsgml[pss].snext; scbsgml[pss].snext = sgmltab[scbsgml[pss].sstate] [scbsgml[pss].sinput = conret-DAF_]; scbsgml[pss].saction = sgmltab[scbsgml[pss].sstate+1][scbsgml[pss].sinput]; TRACEGML(scbsgml, pss, conactsw, conact); action = scbsgml[pss].saction; if (conret==ETG_ && GET(tags[ts+1].tflags, TAGPEX)) { pss--; /* An included subelement affects the enclosing state like a processing instruction (or MDC_ or MD_), that is to say NR1 is changed to ST1 and NR2 to ST2. */ scbsgml[pss].sstate = scbsgml[pss].snext; scbsgml[pss].snext = sgmltab[scbsgml[pss].sstate][PIS_ - DAF_]; } return action; } /* GETPCB: Choose pcb for new or resumed element. */ struct parse *getpcb(etdcon) int etdcon; /* Content type of new or resumed element. */ { if (BITON(etdcon, MGI)) { return(BITON(etdcon, MCHARS) ? &pcbconm : &pcbcone); } if (BITON(etdcon, MCDATA) || BITON(etdcon, MRCDATA)) { charmode = 1; return(BITON(etdcon, MCDATA) ? &pcbconc : (rcessv = es, &pcbconr)); } return(&pcbconm); } struct markup *sgmlset(swp) struct switches *swp; { /* Initialize variables based on switches structure members. */ sw = *swp; rbufs = (UNCH *)rmalloc((UNS)3+sw.swbufsz) + 3; /* DOS file read area. */ TRACEPRO(); /* Set trace switches for prolog. */ msginit(swp); ioinit(swp); sdinit(); return &lex.m; } /* Points for each capacity, indexed by *CAP in sgmldecl.h. We'll replace 2 with the real NAMELEN at run time. */ static UNCH cappoints[] = { 1, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2 }; static long capnumber[NCAPACITY]; static long maxsubcap[NCAPACITY]; VOID sgmlend(p) struct sgmlcap *p; { int i; for (; es >= 0; --es) if (FILESW) fileclos(); capnumber[NOTCAP] = ds.dcncnt; capnumber[EXGRPCAP] = ds.pmexgcnt; capnumber[ELEMCAP] = ds.etdcnt+ds.etdercnt; capnumber[EXNMCAP] = ds.pmexcnt; capnumber[GRPCAP] = ds.modcnt; capnumber[ATTCAP] = ds.attcnt; capnumber[ATTCHCAP] = ds.attdef; capnumber[AVGRPCAP] = ds.attgcnt; capnumber[IDCAP] = ds.idcnt; capnumber[IDREFCAP] = ds.idrcnt; capnumber[ENTCAP] = ds.ecbcnt; capnumber[ENTCHCAP] = ds.ecbtext; capnumber[MAPCAP] = ds.srcnt + ds.srcnt*lex.s.dtb[0].mapdata; capnumber[NOTCHCAP] = ds.dcntext; capnumber[TOTALCAP] = 0; for (i = 1; i < NCAPACITY; i++) { if (cappoints[i] > 1) cappoints[i] = NAMELEN; capnumber[i] += maxsubcap[i]/cappoints[i]; capnumber[TOTALCAP] += (long)capnumber[i] * cappoints[i]; } p->number = capnumber; p->points = cappoints; p->limit = sd.capacity; p->name = captab; for (i = 0; i < NCAPACITY; i++) { long excess = capnumber[i]*cappoints[i] - sd.capacity[i]; if (excess > 0) { char buf[sizeof(long)*3 + 1]; sprintf(buf, "%ld", excess); sgmlerr(162, (struct parse *)0, (UNCH *)captab[i], (UNCH *)buf); } } } VOID sgmlsubcap(v) long *v; { int i; for (i = 0; i < NCAPACITY; i++) if (v[i] > maxsubcap[i]) maxsubcap[i] = v[i]; } int sgmlsdoc(ptr) UNIV ptr; { struct entity *e; union etext etx; etx.x = ptr; e = entdef(indocent, ESF, &etx); if (!e) return -1; return entopen(e); } /* SGMLGENT: Get a data entity. Returns: -1 if the entity does not exist -2 if it is not a data entity 1 if it is an external entity 2 if it is an internal cdata entity 3 if it is an internal sdata entity */ int sgmlgent(iname, np, tp) UNCH *iname; PNE *np; UNCH **tp; { PECB ep; /* Pointer to an entity control block. */ ep = entfind(iname); if (!ep) return -1; switch (ep->estore) { case ESN: if (np) *np = ep->etx.n; return 1; case ESC: if (tp) *tp = ep->etx.c; return 2; case ESX: if (tp) *tp = ep->etx.c; return 3; } return -2; } /* Mark an entity. */ int sgmlment(iname) UNCH *iname; { PECB ep; int rc; ep = entfind(iname); if (!ep) return -1; rc = ep->mark; ep->mark = 1; return rc; } int sgmlgcnterr() { return msgcnterr(); } /* This is for error handling functions that want to print a gi backtrace. */ UNCH *getgi(i) int i; { return i >= 0 && i <= ts ? tags[i].tetd->etdgi + 1 : NULL; } /* Returns the value of prologsw for the use by error handling functions. */ int inprolog() { return prologsw; } /* Used by the error handling functions to access scbs. */ int getlocation(level, locp) int level; struct location *locp; { if (level < 0 || level > es) return 0; if (locp) { int es = level; /* source macros access a variable called `es' */ locp->filesw = FILESW; locp->rcnt = RCNT; locp->ccnt = CCNT; locp->ename = ENTITY + 1; locp->fcb = SCBFCB; locp->curchar = CC; locp->nextchar = NEXTC; } return 1; } int sgmlloc(linenop, filenamep) unsigned long *linenop; char **filenamep; { int level = es; int es; for (es = level; es >= 0 && !FILESW; es--) ; if (es < 0) return 0; *linenop = RCNT; *filenamep = ioflid(SCBFCB); return 1; } /* Local Variables: c-indent-level: 5 c-continued-statement-offset: 5 c-brace-offset: -5 c-argdecl-indent: 0 c-label-offset: -5 End: */