Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
802
cde/programs/dtdocbook/sgmls/md2.c
Normal file
802
cde/programs/dtdocbook/sgmls/md2.c
Normal file
@@ -0,0 +1,802 @@
|
||||
/* $XConsortium: md2.c /main/3 1996/06/19 17:16:14 drk $ */
|
||||
#include "sgmlincl.h" /* #INCLUDE statements for SGML parser. */
|
||||
/* MDENTITY: Process ENTITY declaration.
|
||||
*/
|
||||
VOID mdentity(tbuf)
|
||||
UNCH *tbuf; /* Work area for tokenization[LITLEN+2]. */
|
||||
{
|
||||
struct fpi fpicb; /* Formal public identifier structure. */
|
||||
struct fpi *fpis = &fpicb; /* Ptr to current or #DEFAULT fpi. */
|
||||
union etext etx; /* Ptr to entity text. */
|
||||
UNCH estore = ESM; /* Entity storage class. */
|
||||
struct entity *ecb; /* Ptr to entity control block. */
|
||||
int parmsw = 0; /* 1=parameter entity declaration; 0 = not. */
|
||||
int defltsw = 0; /* 1=#DEFAULT declaration; 0=not. */
|
||||
PNE pne = 0; /* Ptr to N/C/SDATA entity control block. */
|
||||
|
||||
mdname = key[KENTITY]; /* Declaration name for messages. */
|
||||
subdcl = NULL; /* No subject as yet. */
|
||||
parmno = 0; /* No parameters as yet. */
|
||||
mdessv = es; /* Save es for checking entity nesting. */
|
||||
/* PARAMETER 1: Entity name.
|
||||
*/
|
||||
pcbmd.newstate = 0;
|
||||
parsemd(nmbuf, ENTCASE, &pcblitp, NAMELEN);
|
||||
TRACEMD("1: entity nm");
|
||||
switch (pcbmd.action) {
|
||||
case PEN:
|
||||
parsemd(nmbuf + 1, ENTCASE, &pcblitp, NAMELEN);
|
||||
if (pcbmd.action!=NAS) {mderr(120, (UNCH *)0, (UNCH *)0); return;}
|
||||
if (nmbuf[1] == NAMELEN + 2) {
|
||||
/* It was too long. */
|
||||
nmbuf[0] = NAMELEN + 2;
|
||||
nmbuf[NAMELEN + 1] = '\0';
|
||||
mderr(65, (UNCH *)0, (UNCH *)0);
|
||||
}
|
||||
else
|
||||
nmbuf[0] = nmbuf[1] + 1; /* Increment length for PERO. */
|
||||
nmbuf[1] = lex.d.pero; /* Prefix PERO to name. */
|
||||
parmsw = 1; /* Indicate parameter entity. */
|
||||
case NAS:
|
||||
break;
|
||||
case RNS: /* Reserved name started. */
|
||||
if (ustrcmp(nmbuf+1, key[KDEFAULT])) {
|
||||
mderr(118, nmbuf+1, key[KDEFAULT]);
|
||||
return;
|
||||
}
|
||||
memcpy(nmbuf, indefent, *indefent);/* Copy #DEFAULT to name buffer. */
|
||||
fpis = &fpidf; /* Use #DEFAULT fpi if external. */
|
||||
defltsw = 1; /* Indicate #DEFAULT is being defined.*/
|
||||
break;
|
||||
default:
|
||||
mderr(122, (UNCH *)0, (UNCH *)0);
|
||||
return;
|
||||
}
|
||||
subdcl = nmbuf+1; /* Subject name for error messages. */
|
||||
/* PARAMETER 2: Entity text keyword (optional).
|
||||
*/
|
||||
pcbmd.newstate = 0;
|
||||
parsemd(tbuf, NAMECASE, &pcblitp, LITLEN);
|
||||
TRACEMD("2: keyword");
|
||||
switch (pcbmd.action) {
|
||||
case NAS:
|
||||
if ((estore = (UNCH)mapsrch(enttab, tbuf+1))==0) {
|
||||
estore = parmsw ? ESP : ESF;
|
||||
pne = (PNE)rmalloc(NESZ);
|
||||
if (mdextid(tbuf, fpis, nmbuf+1+parmsw, &estore, pne)==0)
|
||||
return;
|
||||
if (defltsw) etx.x = NULL;
|
||||
else if ((etx.x = entgen(&fpicb))==0) {
|
||||
if (parmsw)
|
||||
mderr(148, nmbuf+2, (UNCH *)0);
|
||||
else
|
||||
mderr(147, nmbuf+1, (UNCH *)0);
|
||||
}
|
||||
goto parm4;
|
||||
}
|
||||
if (parmsw && (estore==ESX || estore==ESC)) {
|
||||
mderr(38, tbuf+1, (UNCH *)0);
|
||||
estore = ESM;
|
||||
}
|
||||
pcbmd.newstate = 0;
|
||||
parsemd(tbuf, NAMECASE, &pcblitp, LITLEN);
|
||||
break;
|
||||
default:
|
||||
estore = ESM;
|
||||
break;
|
||||
}
|
||||
/* PARAMETER 3: Parameter literal.
|
||||
*/
|
||||
TRACEMD("3: literal");
|
||||
switch (pcbmd.action) {
|
||||
case LITE:
|
||||
case LIT:
|
||||
switch (estore) {
|
||||
case ESM: /* LITERAL: parameter literal required. */
|
||||
case ESC: /* CDATA: parameter literal required. */
|
||||
case ESX: /* SDATA: parameter literal required. */
|
||||
case ESI: /* PI: parameter literal required. */
|
||||
etx.c = savestr(tbuf);
|
||||
break;
|
||||
case ESMD: /* MD: parameter literal required. */
|
||||
etx.c = sandwich(tbuf, lex.m.mdo, lex.m.mdc);
|
||||
goto bcheck;
|
||||
case ESMS: /* MS: parameter literal required. */
|
||||
etx.c = sandwich(tbuf, lex.m.mss, lex.m.mse);
|
||||
goto bcheck;
|
||||
case ESS: /* STARTTAG: parameter literal required. */
|
||||
etx.c = sandwich(tbuf, lex.m.stag, lex.m.tagc);
|
||||
goto bcheck;
|
||||
case ESE: /* ENDTAG: parameter literal required. */
|
||||
etx.c = sandwich(tbuf, lex.m.etag, lex.m.tagc);
|
||||
bcheck:
|
||||
if (etx.c == 0) {
|
||||
mderr(225, (UNCH *)0, (UNCH *)0);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
mderr(123, (UNCH *)0, (UNCH *)0);
|
||||
return;
|
||||
}
|
||||
/* PARAMETER 4: End of declaration.
|
||||
*/
|
||||
pcbmd.newstate = 0;
|
||||
parsemd(tbuf, NAMECASE, &pcblitp, LITLEN);
|
||||
parm4:
|
||||
TRACEMD(emd);
|
||||
if (pcbmd.action!=EMD) mderr(126, (UNCH *)0, (UNCH *)0);
|
||||
if (es!=mdessv) synerr(37, &pcbmd);
|
||||
|
||||
/* EXECUTE: If the entity already exists, ignore the new definition.
|
||||
If it is a new entity, store the definition.
|
||||
*/
|
||||
if ((ecb = entfind(nmbuf))!=0 && ecb->estore) {
|
||||
if (ecb->dflt) {
|
||||
mderr(228, nmbuf + 1, (UNCH *)0);
|
||||
hout((THASH)etab, nmbuf, hash(nmbuf, ENTHASH));
|
||||
if (ecb->estore == ESN) {
|
||||
frem((UNIV)NEID(ecb->etx.n));
|
||||
frem((UNIV)ecb->etx.n);
|
||||
}
|
||||
else if (ecb->estore >= ESFM)
|
||||
frem((UNIV)ecb->etx.x);
|
||||
frem((UNIV)ecb);
|
||||
}
|
||||
else {
|
||||
/* Duplicate definition: not an error. */
|
||||
if (sw.swdupent) mderr(68, nmbuf+1, (UNCH *)0);
|
||||
if (estore<ESFM) frem((UNIV)etx.c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
++ds.ecbcnt; /* Do capacity before NOTATION. */
|
||||
ds.ecbtext += estore<ESFM ? ustrlen(etx.c) : entlen;
|
||||
ecb = entdef(nmbuf, estore, &etx); /* Define the entity. */
|
||||
if (estore==ESN) { /* If entity is external: */
|
||||
NEENAME(pne) = ecb->ename; /* Store entity name in ne. */
|
||||
NEID(pne) = etx.x; /* Store system fileid in ne. */
|
||||
NESYSID(pne) = fpis->fpisysis ? savestr(fpis->fpisysis) : 0;
|
||||
NEPUBID(pne) = fpis->fpipubis ? savestr(fpis->fpipubis) : 0;
|
||||
ecb->etx.n = pne; /* Store ne control block in etx. */
|
||||
TRACEESN(pne);
|
||||
}
|
||||
else if (pne)
|
||||
frem((UNIV)pne);
|
||||
if (defltsw) {
|
||||
ecbdeflt = ecb; /* If #DEFAULT save ecb. */
|
||||
if (fpidf.fpipubis)
|
||||
fpidf.fpipubis = savestr(fpidf.fpipubis);
|
||||
if (fpidf.fpisysis)
|
||||
fpidf.fpisysis = savestr(fpidf.fpisysis);
|
||||
}
|
||||
}
|
||||
/* SANDWICH: Catenate a prefix and suffix to a string.
|
||||
The result has an EOS but no length.
|
||||
Return 0 if the result if longer than LITLEN.
|
||||
*/
|
||||
UNCH *sandwich(s, pref, suff)
|
||||
UNCH *s; /* String, with EOS. */
|
||||
UNCH *pref; /* Prefix, with length and EOS. */
|
||||
UNCH *suff; /* Suffix, with length and EOS. */
|
||||
{
|
||||
UNCH *pt;
|
||||
UNS slen, tlen;
|
||||
|
||||
slen = ustrlen(s);
|
||||
tlen = slen + (*pref - 2) + (*suff - 2);
|
||||
if (tlen > LITLEN)
|
||||
return 0;
|
||||
pt = (UNCH *)rmalloc(tlen + 1);
|
||||
memcpy(pt, pref + 1, *pref - 2);
|
||||
memcpy(pt + (*pref - 2), s, slen);
|
||||
memcpy(pt + (*pref - 2) + slen, suff + 1, *suff - 1);
|
||||
return pt;
|
||||
}
|
||||
/* MDEXTID: Process external identifier parameter of a markup declaration.
|
||||
On entry, tbuf contains SYSTEM or PUBLIC if all is well.
|
||||
NULL is returned if an error, otherwise fpis. If it is a
|
||||
valid external data entity, the caller's estore is set to ESN
|
||||
and its nxetype is set to the code for the external entity type.
|
||||
The event that terminated the parse is preserved in pcb.action,
|
||||
so the caller should process it before further parsing.
|
||||
*/
|
||||
struct fpi *mdextid(tbuf, fpis, ename, estore, pne)
|
||||
UNCH *tbuf; /* Work area for tokenization[2*(LITLEN+2)]. */
|
||||
struct fpi *fpis; /* FPI structure. */
|
||||
UNCH *ename; /* Entity or notation name, with EOS, no length.*/
|
||||
/* NOTE: No PERO on parameter entity name. */
|
||||
UNCH *estore; /* DTD, general or parameter entity, DCN. */
|
||||
PNE pne; /* Caller's external entity ptr. */
|
||||
{
|
||||
PDCB dcb; /* Ptr to DCN control block. */
|
||||
int exidtype; /* External ID type: 0=none 1=system 2=public. */
|
||||
int exetype; /* External entity type. */
|
||||
|
||||
MEMZERO((UNIV)fpis, (UNS)FPISZ); /* Initialize fpi structure. */
|
||||
/* Move entity name into fpi (any PERO was stripped by caller). */
|
||||
fpis->fpinm = ename;
|
||||
entlen = 0; /* Initialize external ID length. */
|
||||
|
||||
/* PARAMETER 1: External identifier keyword or error.
|
||||
*/
|
||||
TRACEMD("1: extid keyword");
|
||||
if ((exidtype = mapsrch(exttab, tbuf+1))==0) {
|
||||
mderr(29, (UNCH *)0, (UNCH *)0);
|
||||
return (struct fpi *)0;
|
||||
}
|
||||
if (exidtype==EDSYSTEM) goto parm3;
|
||||
|
||||
/* PARAMETER 2: Public ID literal.
|
||||
*/
|
||||
pcbmd.newstate = 0;
|
||||
/* The length of a minimum literal cannot exceed the value of LITLEN
|
||||
in the reference quantity set. */
|
||||
parsemd(pubibuf, NAMECASE, &pcblitv, REFLITLEN);
|
||||
TRACEMD("2: pub ID literal");
|
||||
switch (pcbmd.action) {
|
||||
case LITE: /* Use alternative literal delimiter. */
|
||||
case LIT: /* Save literal as public ID string. */
|
||||
entlen = ustrlen(pubibuf);
|
||||
fpis->fpipubis = pubibuf;
|
||||
break;
|
||||
default:
|
||||
mderr(117, (UNCH *)0, (UNCH *)0);
|
||||
return (struct fpi *)0; /* Signal error to caller. */
|
||||
}
|
||||
/* PARAMETER 3: System ID literal.
|
||||
*/
|
||||
parm3:
|
||||
pcbmd.newstate = 0;
|
||||
parsemd(sysibuf, NAMECASE, &pcblitc, LITLEN);
|
||||
TRACEMD("3: sys ID literal");
|
||||
if (pcbmd.action==LIT || pcbmd.action==LITE) {
|
||||
entlen += ustrlen(sysibuf);
|
||||
fpis->fpisysis = sysibuf;
|
||||
pcbmd.newstate = 0;
|
||||
parsemd(tbuf, NAMECASE, &pcblitp, LITLEN);
|
||||
}
|
||||
else memcpy(tbuf, sysibuf, *sysibuf);
|
||||
if (*estore!=ESF || pcbmd.action!=NAS) goto genfpi;
|
||||
|
||||
/* PARAMETER 4: Entity type keyword.
|
||||
*/
|
||||
TRACEMD("4: Entity type");
|
||||
if ((exetype = mapsrch(extettab, tbuf+1))==0) {
|
||||
mderr(24, tbuf+1, (UNCH *)0);
|
||||
return (struct fpi *)0;
|
||||
}
|
||||
if (exetype==ESNSUB && SUBDOC == NO) {
|
||||
mderr(90, tbuf+1, (UNCH *)0);
|
||||
return (struct fpi *)0;
|
||||
}
|
||||
|
||||
NEXTYPE(pne) = (UNCH)exetype; /* Save entity type in caller's ne. */
|
||||
*estore = ESN; /* Signal that entity is a data entity. */
|
||||
|
||||
if (exetype==ESNSUB) {
|
||||
pne->nedcn = 0;
|
||||
pcbmd.newstate = 0; /* Parse next token for caller. */
|
||||
parsemd(tbuf, NAMECASE, &pcblitp, LITLEN);
|
||||
goto genfpi;
|
||||
}
|
||||
/* PARAMETER 5: Notation name.
|
||||
*/
|
||||
pcbmd.newstate = 0;
|
||||
parsemd(lbuf, NAMECASE, &pcblitp, NAMELEN);
|
||||
TRACEMD("5: notation");
|
||||
if (pcbmd.action!=NAS) {mderr(119, tbuf+1, (UNCH *)0); return (struct fpi *)0;}
|
||||
/* Locate the data content notation. */
|
||||
pne->nedcn = dcb = dcndef(lbuf);
|
||||
/* Note that we have defined an entity with this notation.
|
||||
If attributes are later defined for this notation, we'll
|
||||
have to fix up this entity. */
|
||||
dcb->entsw = 1;
|
||||
|
||||
/* PARAMETER 6: Data attribute specification.
|
||||
*/
|
||||
pcbmd.newstate = 0;
|
||||
parsemd(lbuf, NAMECASE, &pcblitp, NAMELEN);
|
||||
TRACEMD("6: [att list]");
|
||||
if (pcbmd.action!=MDS) { /* No attributes specified. */
|
||||
if (dcb->adl == 0)
|
||||
NEAL(pne) = 0;
|
||||
else {
|
||||
initatt(dcb->adl);
|
||||
adlval((int)ADN(al), (struct etd *)0);
|
||||
storedatt(pne);
|
||||
}
|
||||
goto genfpi;
|
||||
}
|
||||
if (dcb->adl==0) { /* Atts specified, but none defined. */
|
||||
mderr(22, (UNCH *)0, (UNCH *)0);
|
||||
return (struct fpi *)0;
|
||||
}
|
||||
pcbstag.newstate = pcbstan; /* First separator is optional. */
|
||||
if ((parseatt(dcb->adl, tbuf))==0)/* Empty list. */
|
||||
mderr(91, (UNCH *)0, (UNCH *)0);
|
||||
else {
|
||||
adlval((int)ADN(al), (struct etd *)0);
|
||||
storedatt(pne);
|
||||
}
|
||||
parse(&pcbeal); /* Parse the list ending. */
|
||||
pcbmd.newstate = 0; /* Parse next token for caller. */
|
||||
parsemd(tbuf, NAMECASE, &pcblitp, LITLEN);
|
||||
|
||||
/* GENFPI: Builds a formal public identifier structure, including the
|
||||
entity name, offsets of the components of the public ID, and
|
||||
other data a system might use to identify the actual file.
|
||||
*/
|
||||
genfpi:
|
||||
TRACEMD("7: generate fpi");
|
||||
fpis->fpistore = *estore - ESFM + 1; /* External entity type: 1-6. */
|
||||
if (*estore == ESN) {
|
||||
if (NEXTYPE(pne) == ESNSUB)
|
||||
fpis->fpinedcn = 0;
|
||||
else
|
||||
fpis->fpinedcn = NEDCN(pne) + 1;
|
||||
}
|
||||
/* Analyze public ID and make structure entries. */
|
||||
if (exidtype==EDPUBLIC) {
|
||||
if (FORMAL==NO)
|
||||
fpis->fpiversw = -1;
|
||||
else if (parsefpi(fpis)>0) {
|
||||
mderr(88, fpis->fpipubis, (UNCH *)0);
|
||||
fpis->fpiversw = -1; /* Signal bad formal public ID. */
|
||||
}
|
||||
}
|
||||
return fpis;
|
||||
}
|
||||
|
||||
/* Store a data attribute. */
|
||||
|
||||
VOID storedatt(pne)
|
||||
PNE pne;
|
||||
{
|
||||
int i;
|
||||
|
||||
NEAL(pne) = (struct ad *)rmalloc((1+ADN(al))*ADSZ);
|
||||
memcpy((UNIV)NEAL(pne), (UNIV)al, (1+ADN(al))*ADSZ);
|
||||
for (i = 1; i <= (int)ADN(al); i++) {
|
||||
if (GET(ADFLAGS(al, i), ASPEC))
|
||||
ds.attdef += ADLEN(al, i);
|
||||
if (NEAL(pne)[i].addef != 0)
|
||||
NEAL(pne)[i].addef = savestr(NEAL(pne)[i].addef);
|
||||
}
|
||||
ds.attcnt += AN(al); /* Number of attributes defined. */
|
||||
#if 0
|
||||
/* I can't see any reason to increase AVGRPCNT here. */
|
||||
ds.attgcnt += ADN(al) - AN(al); /* Number of att grp members. */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* PARSEFPI: Parses a formal public identifier and builds a control block.
|
||||
PARSEFPI returns a positive error code (1-10), or 0 if no errors.
|
||||
It set fpiversw if no version was specified in the ID and the
|
||||
public text is in a class that permits display versions.
|
||||
Note: An empty version ("//") can be specified (usually it is
|
||||
the non-device-specific form, such as a definitional entity set).
|
||||
*/
|
||||
int parsefpi(f)
|
||||
PFPI f; /* Ptr to formal public identifier structure. */
|
||||
{
|
||||
UNCH *l; /* Pointer to EOS of public identifier. */
|
||||
UNCH *p, *q; /* Ptrs to current field in public identifier. */
|
||||
UNS len; /* Field length */
|
||||
|
||||
p = f->fpipubis; /* Point to start of identifier. */
|
||||
l = p + ustrlen(p); /* Point to EOS of identifier. */
|
||||
if (*p=='+' || *p=='-') { /* If owner registered, unregistered. */
|
||||
f->fpiot = *p; /* Save owner type. */
|
||||
if ((p += 3)>=l) return 1; /* Get to owner ID field. */
|
||||
}
|
||||
else f->fpiot = '!'; /* Indicate ISO owner identifier. */
|
||||
if ((q = pubfield(p, l, '/', &len))==0) /* Find end of owner ID field. */
|
||||
return 2;
|
||||
f->fpiol = len; /* Save owner ID length. */
|
||||
f->fpio = p - f->fpipubis; /* Save offset in pubis to owner ID. */
|
||||
|
||||
if ((p = pubfield(q, l, ' ', &len))==0) /* Find end of text class field. */
|
||||
return 3;
|
||||
*(--p) = EOS; /* Temporarily make class a string. */
|
||||
f->fpic = mapsrch(pubcltab, q); /* Check for valid uc class name.*/
|
||||
*p++ = ' '; /* Restore the SPACE delimiter. */
|
||||
if (f->fpic==0) return 4; /* Error if not valid uc class name.*/
|
||||
|
||||
/* The public text class in a notation identifier must be NOTATION. */
|
||||
if (f->fpistore == ESK - ESFM + 1 && f->fpic != FPINOT) return 10;
|
||||
|
||||
if (*p=='-') { /* If text is unavailable public text.*/
|
||||
f->fpitt = *p; /* Save text type. */
|
||||
if ((p += 3)>=l) return 5; /* Get to text description field. */
|
||||
}
|
||||
else f->fpitt = '+'; /* Indicate available public text. */
|
||||
if ((q = pubfield(p, l, '/', &len))==0) /* Find end of text description. */
|
||||
return 6;
|
||||
f->fpitl = len; /* Save text description length. */
|
||||
f->fpit = p - f->fpipubis; /* Save ptr to description.*/
|
||||
|
||||
p = pubfield(q, l, '/', &len); /* Bound language field. */
|
||||
if (f->fpic != FPICHARS) {
|
||||
int i;
|
||||
/* Language must be all upper-case letters. */
|
||||
/* The standard only says that it *should* be two letters, so
|
||||
don't enforce that. */
|
||||
for (i = 0; i < len; i++) {
|
||||
/* Don't assume ASCII. */
|
||||
if (!strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ", q[i]))
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
f->fpill = len;
|
||||
f->fpil = q - f->fpipubis;
|
||||
if (p!=0) { /* If there is a version field: */
|
||||
if (f->fpic<FPICMINV) /* Error if class prohibits versions. */
|
||||
return 8;
|
||||
if ((pubfield(p, l, '/', &len))!=0) /* Bound version field. */
|
||||
return 9; /* Error if yet another field. */
|
||||
f->fpivl = len; /* Save version length. */
|
||||
f->fpiv = p - f->fpipubis; /* Save ptr (in pubis) to version. */
|
||||
}
|
||||
else if (f->fpic>=FPICMINV) f->fpiversw = 1;/* No version: get the best. */
|
||||
return(0);
|
||||
}
|
||||
/* PUBFIELD: Returns ptr to next field, or NULL if ID has ended.
|
||||
*/
|
||||
#ifdef USE_PROTOTYPES
|
||||
UNCH *pubfield(UNCH *p, UNCH *l, UNCH d, UNS *lenp)
|
||||
#else
|
||||
UNCH *pubfield(p, l, d, lenp)
|
||||
UNCH *p; /* Public identifier field (no length or EOS). */
|
||||
UNCH *l; /* Pointer to EOS of public identifier. */
|
||||
UNCH d; /* Field delimiter: ' ' or '/'. */
|
||||
UNS *lenp; /* Gets field length */
|
||||
#endif
|
||||
{
|
||||
UNCH *psv = p+1; /* Save starting value of p. */
|
||||
|
||||
while (p<l) {
|
||||
if (*p++==d) { /* Test for delimiter character. */
|
||||
*lenp = p - psv; /* Save field length (no len or EOS). */
|
||||
if (d=='/' && *p++!=d) /* Solidus requires a second one. */
|
||||
continue;
|
||||
return(p); /* Return ptr to next field. */
|
||||
}
|
||||
}
|
||||
*lenp = p - --psv; /* Save field length (no len or EOS). */
|
||||
return NULL;
|
||||
}
|
||||
/* MDMS: Process marked section start.
|
||||
If already in special parse, bump the level counters and return
|
||||
without parsing the declaration.
|
||||
*/
|
||||
struct parse *mdms(tbuf, pcb)
|
||||
UNCH *tbuf; /* Work area for tokenization [NAMELEN+2]. */
|
||||
struct parse *pcb; /* Parse control block for this parse. */
|
||||
{
|
||||
int key; /* Index of keyword in mslist. */
|
||||
int ptype; /* Parameter token type. */
|
||||
int pcbcode = 0; /* Parse code: 0=same; 2-4 per defines. */
|
||||
|
||||
if (++mslevel>TAGLVL) {
|
||||
--mslevel;
|
||||
sgmlerr(27, (struct parse *)0, ntoa(TAGLVL), (UNCH *)0);
|
||||
}
|
||||
|
||||
/* If already in IGNORE mode, return without parsing parameters. */
|
||||
if (msplevel) {++msplevel; return(pcb);}
|
||||
|
||||
parmno = 0; /* No parameters as yet. */
|
||||
mdessv = es; /* Save es for checking entity nesting. */
|
||||
pcbmd.newstate = pcbmdtk; /* First separator is optional. */
|
||||
|
||||
/* PARAMETERS: TEMP, RCDATA, CDATA, IGNORE, INCLUDE, or MDS. */
|
||||
while ((ptype = parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN))==NAS){
|
||||
if ((key = mapsrch(mstab, tbuf+1))==0) {
|
||||
sgmlerr(64, (struct parse *)0, ntoa(parmno), tbuf+1);
|
||||
continue;
|
||||
}
|
||||
if (key==MSTEMP) continue; /* TEMP: for documentation. */
|
||||
msplevel = 1; /* Special parse required. */
|
||||
if (key>pcbcode) pcbcode = key; /* Update if higher priority. */
|
||||
}
|
||||
if (ptype!=MDS) {
|
||||
NEWCC; /* Syntax error did REPEATCC. */
|
||||
sgmlerr(97, (struct parse *)0, lex.m.dso, (UNCH *)0);
|
||||
REPEATCC; /* 1st char of marked section. */
|
||||
}
|
||||
if (es!=mdessv) synerr(37, pcb);
|
||||
TRACEMS(1, pcbcode, mslevel, msplevel);
|
||||
if (pcbcode==MSIGNORE) pcb = &pcbmsi;
|
||||
else if (pcbcode) {
|
||||
pcb = pcbcode==MSCDATA ? &pcbmsc : (rcessv = es, &pcbmsrc);
|
||||
}
|
||||
return(pcb); /* Tell caller whether to change the parse. */
|
||||
}
|
||||
/* MDMSE: Process marked section end.
|
||||
Issue an error if no marked section had started.
|
||||
*/
|
||||
int mdmse()
|
||||
{
|
||||
int retcode = 0; /* Return code: 0=same parse; 1=cancel special. */
|
||||
|
||||
if (mslevel) --mslevel;
|
||||
else sgmlerr(26, (struct parse *)0, (UNCH *)0, (UNCH *)0);
|
||||
|
||||
if (msplevel) if (--msplevel==0) retcode = 1;
|
||||
TRACEMS(0, retcode, mslevel, msplevel);
|
||||
return retcode;
|
||||
}
|
||||
/* MDNOT: Process NOTATION declaration.
|
||||
*/
|
||||
VOID mdnot(tbuf)
|
||||
UNCH *tbuf; /* Work area for tokenization[LITLEN+2]. */
|
||||
{
|
||||
struct fpi fpicb; /* Formal public identifier structure. */
|
||||
PDCB dcb; /* Ptr to notation entity in dcntab. */
|
||||
UNCH estore = ESK; /* Entity storage class. */
|
||||
|
||||
mdname = key[KNOTATION]; /* Identify declaration for messages. */
|
||||
subdcl = NULL; /* No subject as yet. */
|
||||
parmno = 0; /* No parameters as yet. */
|
||||
mdessv = es; /* Save es for checking entity nesting. */
|
||||
|
||||
/* PARAMETER 1: Notation name.
|
||||
*/
|
||||
pcbmd.newstate = 0;
|
||||
parsemd(lbuf, NAMECASE, &pcblitp, NAMELEN);
|
||||
TRACEMD("1: name");
|
||||
if (pcbmd.action!=NAS) {mderr(120, (UNCH *)0, (UNCH *)0); return;}
|
||||
subdcl = lbuf+1; /* Save notation name for error msgs. */
|
||||
|
||||
/* PARAMETER 2: External identifier keyword.
|
||||
*/
|
||||
pcbmd.newstate = 0;
|
||||
parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
|
||||
TRACEMD("2: extid");
|
||||
if (pcbmd.action!=NAS) {mderr(29, (UNCH *)0, (UNCH *)0); return;}
|
||||
if (mdextid(tbuf, &fpicb, lbuf+1, &estore, (PNE)0)==0) return;
|
||||
|
||||
/* PARAMETER 3: End of declaration.
|
||||
Token was parsed by MDEXTID.
|
||||
*/
|
||||
TRACEMD(emd);
|
||||
if (pcbmd.action!=EMD) mderr(126, (UNCH *)0, (UNCH *)0);
|
||||
if (es!=mdessv) synerr(37, &pcbmd);
|
||||
|
||||
/* EXECUTE: Store notation name.
|
||||
*/
|
||||
if ((dcb = dcnfind(lbuf)) != 0 && dcb->defined) {
|
||||
mderr(56, lbuf+1, (UNCH *)0);
|
||||
return;
|
||||
}
|
||||
/* else */
|
||||
dcb = dcndef(lbuf);
|
||||
dcb->defined = 1;
|
||||
dcb->sysid = fpicb.fpisysis ? savestr(fpicb.fpisysis) : 0;
|
||||
dcb->pubid = fpicb.fpipubis ? savestr(fpicb.fpipubis) : 0;
|
||||
++ds.dcncnt;
|
||||
ds.dcntext += entlen;
|
||||
TRACEDCN(dcb);
|
||||
return;
|
||||
}
|
||||
/* DCNDEF: Define a notation and return its DCNCB.
|
||||
If caller does not care if it already exists,
|
||||
he should specify NULL for the notation text
|
||||
so we don't clobber the existing text (if any).
|
||||
*/
|
||||
struct dcncb *dcndef(nname)
|
||||
UNCH *nname; /* Notation name (with length and EOS). */
|
||||
{
|
||||
return((PDCB)hin((THASH)dcntab, nname, 0, DCBSZ));
|
||||
}
|
||||
/* DCNFIND: If a notation was declared, return its DCNCB.
|
||||
Return NULL if it is not defined.
|
||||
*/
|
||||
struct dcncb *dcnfind(nname)
|
||||
UNCH *nname; /* Notation name (with length and EOS). */
|
||||
{
|
||||
return((PDCB)hfind((THASH)dcntab, nname, 0));
|
||||
}
|
||||
#define SRM(i) (srhptr->srhsrm[i]) /* Current entry in SHORTREF map. */
|
||||
/* MDSRMDEF: Process short reference mapping declaration.
|
||||
*/
|
||||
VOID mdsrmdef(tbuf)
|
||||
UNCH *tbuf; /* Work area for tokenization[LITLEN+2]. */
|
||||
{
|
||||
struct entity *entcb; /* Ptr to defined entity. */
|
||||
PSRH srhptr; /* Ptr to short reference map hdr (in srhtab).*/
|
||||
int srn; /* Short reference delimiter number in srdeltab.*/
|
||||
int mapused = 0; /* Has map already been used? */
|
||||
|
||||
mdname = key[KSHORTREF]; /* Identify declaration for messages. */
|
||||
subdcl = NULL; /* No subject as yet. */
|
||||
parmno = 0; /* No parameters as yet. */
|
||||
if (!sd.shortref) {mderr(198, (UNCH *)0, (UNCH *)0); return;}
|
||||
mdessv = es; /* Save es for checking entity nesting. */
|
||||
/* PARAMETER 1: SHORTREF map name.
|
||||
*/
|
||||
pcbmd.newstate = 0;
|
||||
parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
|
||||
TRACEMD("1: map nm");
|
||||
if (pcbmd.action!=NAS) {mderr(120, (UNCH *)0, (UNCH *)0); return;}
|
||||
if ((srhptr = srhfind(tbuf))!=0) {
|
||||
mapused = 1;
|
||||
/* Error if map was declared (not just used). */
|
||||
if (SRM(0)) {mderr(56, tbuf+1, (UNCH *)0); return;}
|
||||
}
|
||||
else srhptr = srhdef(tbuf); /* Create map with SRs mapped to NULL.*/
|
||||
SRM(0) = (PECB)srhptr; /* Indicate map was actually declared.*/
|
||||
subdcl = srhptr->ename+1; /* Save map name for error msgs. */
|
||||
|
||||
while ( pcbmd.newstate = 0,
|
||||
parsemd(tbuf, NAMECASE, &pcblitp, SRMAXLEN)==LIT
|
||||
|| pcbmd.action==LITE ) {
|
||||
/* PARAMETER 2: Delimiter string.
|
||||
*/
|
||||
TRACEMD("2: SR string");
|
||||
if ((srn = mapsrch(lex.s.dtb, tbuf))==0) {
|
||||
mderr(124, tbuf, (UNCH *)0);
|
||||
goto cleanup;
|
||||
}
|
||||
/* PARAMETER 3: Entity name.
|
||||
*/
|
||||
pcbmd.newstate = 0;
|
||||
parsemd(tbuf, ENTCASE, &pcblitp, NAMELEN);
|
||||
TRACEMD("3: entity");
|
||||
if (pcbmd.action!=NAS) {mderr(120, (UNCH *)0, (UNCH *)0); goto cleanup;}
|
||||
if ((entcb = entfind(tbuf))==0) {
|
||||
union etext etx;
|
||||
etx.x = 0;
|
||||
entcb = entdef(tbuf, '\0', &etx);
|
||||
}
|
||||
if (SRM(srn)) {
|
||||
mderr(56, (srn<lex.s.prtmin ? (UNCH *)lex.s.pdtb[srn]
|
||||
: lex.s.dtb[srn].mapnm), (UNCH *)0);
|
||||
continue;
|
||||
}
|
||||
SRM(srn) = entcb;
|
||||
if (srn>=lex.s.fce && srn!=lex.s.hyp && srn!=lex.s.hyp2
|
||||
&& srn!=lex.s.lbr && srn!=lex.s.rbr)
|
||||
lexcnm[*lex.s.dtb[srn].mapnm] = lex.l.fce;
|
||||
else if (srn==lex.s.spc) lexcnm[' '] = lex.l.spcr;
|
||||
}
|
||||
/* PARAMETER 4: End of declaration.
|
||||
*/
|
||||
TRACEMD(emd);
|
||||
if (parmno==2)
|
||||
{mderr((UNS)(pcbmd.action==EMD ? 28:123), (UNCH *)0, (UNCH *)0); goto cleanup;}
|
||||
if (pcbmd.action!=EMD) mderr(126, (UNCH *)0, (UNCH *)0);
|
||||
if (es!=mdessv) synerr(37, &pcbmd);
|
||||
++ds.srcnt;
|
||||
TRACESRM("SHORTREF", srhptr->srhsrm, (UNCH *)0);
|
||||
return;
|
||||
|
||||
cleanup:
|
||||
/* Don't free the map if the map was in use (because of a USEMAP
|
||||
declaration) before this declaration. */
|
||||
if (mapused)
|
||||
MEMZERO((UNIV)srhptr->srhsrm, sizeof(PECB)*(lex.s.dtb[0].mapdata+1));
|
||||
else {
|
||||
frem((UNIV)srhptr->srhsrm);
|
||||
hout((THASH)srhtab, srhptr->ename, 0);
|
||||
frem((UNIV)srhptr);
|
||||
}
|
||||
}
|
||||
/* MDSRMUSE: Activate a short reference map.
|
||||
*/
|
||||
VOID mdsrmuse(tbuf)
|
||||
UNCH *tbuf; /* Work area for tokenization[LITLEN+2]. */
|
||||
{
|
||||
PSRH srhptr; /* Ptr to short reference map hdr (in srhtab).*/
|
||||
TECB srmptr; /* Ptr to short reference map (in header). */
|
||||
int i; /* Loop counter; temporary variable. */
|
||||
|
||||
mdname = key[KUSEMAP]; /* Identify declaration for messages. */
|
||||
subdcl = NULL; /* No subject as yet. */
|
||||
parmno = 0; /* No parameters as yet. */
|
||||
mdessv = es; /* Save es for checking entity nesting. */
|
||||
/* PARAMETER 1: SHORTREF map name or "#EMPTY".
|
||||
*/
|
||||
pcbmd.newstate = 0;
|
||||
parsemd(lbuf, NAMECASE, &pcblitp, NAMELEN);
|
||||
TRACEMD("1: map nm");
|
||||
subdcl = lbuf+1; /* Subject name for error messages. */
|
||||
switch (pcbmd.action) {
|
||||
case RNS: /* Empty SHORTREF map requested. */
|
||||
if (ustrcmp(lbuf+1, key[KEMPTY])) {
|
||||
mderr(118, lbuf+1, key[KEMPTY]);
|
||||
return;
|
||||
}
|
||||
srmptr = SRMNULL;
|
||||
break;
|
||||
case NAS: /* Map name specified; save if undefined. */
|
||||
if ((srhptr = srhfind(lbuf))==0) {
|
||||
if (!indtdsw) {mderr(125, (UNCH *)0, (UNCH *)0); return;}
|
||||
srmptr = NULL;
|
||||
}
|
||||
else
|
||||
srmptr = srhptr->srhsrm;
|
||||
break;
|
||||
default:
|
||||
mderr(120, (UNCH *)0, (UNCH *)0);
|
||||
return;
|
||||
}
|
||||
/* PARAMETER 2: Element name or a group of them. (In DTD only.)
|
||||
*/
|
||||
pcbmd.newstate = 0;
|
||||
parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
|
||||
TRACEMD("2: GI or grp");
|
||||
switch (pcbmd.action) {
|
||||
case NAS:
|
||||
if (!indtdsw) {mderr(142, (UNCH *)0, (UNCH *)0); return;}
|
||||
nmgrp[0] = etddef(tbuf);
|
||||
nmgrp[1] = (PETD)NULL;
|
||||
break;
|
||||
case GRPS:
|
||||
if (!indtdsw) {mderr(142, (UNCH *)0, (UNCH *)0); return;}
|
||||
parsegrp(nmgrp, &pcbgrnm, tbuf);
|
||||
break;
|
||||
case EMD:
|
||||
if (indtdsw) {mderr(28, (UNCH *)0, (UNCH *)0); return;}
|
||||
tags[ts].tsrm = srmptr;
|
||||
TRACESRM("USEMAP", tags[ts].tsrm, tags[ts].tetd->etdgi+1);
|
||||
goto realemd;
|
||||
default:
|
||||
mderr(indtdsw ? 121 : 126, (UNCH *)0, (UNCH *)0);
|
||||
return;
|
||||
}
|
||||
/* PARAMETER 3: End of declaration.
|
||||
*/
|
||||
pcbmd.newstate = 0;
|
||||
parsemd(tbuf, NAMECASE, &pcblitp, NAMELEN);
|
||||
TRACEMD(emd);
|
||||
if (pcbmd.action!=EMD) mderr(126, (UNCH *)0, (UNCH *)0);
|
||||
/* If map has not yet been defined, do it and get map pointer. */
|
||||
if (!srmptr) srmptr = (srhdef(lbuf))->srhsrm;
|
||||
|
||||
/* Store the map pointer for each element name specified.
|
||||
*/
|
||||
TRACEGRP(nmgrp);
|
||||
for (i = -1; nmgrp[++i];) {
|
||||
if (!nmgrp[i]->etdsrm) nmgrp[i]->etdsrm = srmptr;
|
||||
else if (sw.swdupent) mderr(68, nmgrp[i]->etdgi+1, (UNCH *)0);
|
||||
}
|
||||
realemd:
|
||||
if (es!=mdessv) synerr(37, &pcbmd);
|
||||
}
|
||||
/* SRHDEF: Define a SHORTREF map and return ptr to its header.
|
||||
All entries in map are mapped to NULL.
|
||||
Caller must determine whether it already exists.
|
||||
*/
|
||||
PSRH srhdef(sname)
|
||||
UNCH *sname; /* SHORTREF map name (with length and EOS). */
|
||||
{
|
||||
PSRH srh; /* Ptr to SHORTREF map hdr in srhtab. */
|
||||
|
||||
(srh = (PSRH)hin((THASH)srhtab, sname, 0, SRHSZ))->srhsrm =
|
||||
(TECB)rmalloc((UNS)(lex.s.dtb[0].mapdata+1)*sizeof(PECB));
|
||||
return(srh);
|
||||
}
|
||||
/* SRHFIND: If a SHORTREF map was declared, return the ptr to its header.
|
||||
Return NULL if it is not defined.
|
||||
*/
|
||||
PSRH srhfind(sname)
|
||||
UNCH *sname; /* SHORTREF map name (with length and EOS). */
|
||||
{
|
||||
return((PSRH)hfind((THASH)srhtab, sname, 0));
|
||||
}
|
||||
#undef SRM
|
||||
|
||||
/*
|
||||
Local Variables:
|
||||
c-indent-level: 5
|
||||
c-continued-statement-offset: 5
|
||||
c-brace-offset: -5
|
||||
c-argdecl-indent: 0
|
||||
c-label-offset: -5
|
||||
comment-column: 30
|
||||
End:
|
||||
*/
|
||||
Reference in New Issue
Block a user