501 lines
15 KiB
C
501 lines
15 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* $XConsortium: sgml1.c /main/3 1996/06/19 17:17:15 drk $ */
|
|
#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:
|
|
*/
|