Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
500
cde/programs/dtdocbook/sgmls/sgml2.c
Normal file
500
cde/programs/dtdocbook/sgmls/sgml2.c
Normal file
@@ -0,0 +1,500 @@
|
||||
/* $XConsortium: sgml2.c /main/3 1996/06/19 17:17:20 drk $ */
|
||||
/* Added exiterr() for terminal errors to prevent SGML.MSG errors. */
|
||||
#include "sgmlincl.h" /* #INCLUDE statements for SGML parser. */
|
||||
static int iorc; /* Return code from io* functions */
|
||||
/* ENTDEF: Process an entity definition and return the pointer to it.
|
||||
The entity text must be in permanent storage.
|
||||
There is no checking to see if the entity already exists;
|
||||
the caller must have done that.
|
||||
*/
|
||||
#ifdef USE_PROTOTYPES
|
||||
PECB entdef(UNCH *ename, UNCH estore, union etext *petx)
|
||||
#else
|
||||
PECB entdef(ename, estore, petx)
|
||||
UNCH *ename; /* Entity name (with length and EOS). */
|
||||
UNCH estore; /* Entity storage class. */
|
||||
union etext *petx; /* Ptr to entity text union. */
|
||||
#endif
|
||||
{
|
||||
PECB p;
|
||||
|
||||
p = (PECB)hin((THASH)etab, ename, hash(ename, ENTHASH), ENTSZ);
|
||||
memcpy((UNIV)&p->etx, (UNIV)petx, ETEXTSZ);
|
||||
p->estore = estore;
|
||||
TRACEECB("ENTDEF", p);
|
||||
return(p);
|
||||
}
|
||||
/* ENTFIND: If an entity exists, return ptr to its ecb.
|
||||
Return NULL if it is not defined.
|
||||
*/
|
||||
PECB entfind(ename)
|
||||
UNCH *ename; /* Entity name (with length and EOS). */
|
||||
{
|
||||
PECB p;
|
||||
|
||||
p = (PECB)hfind((THASH)etab, ename, hash(ename, ENTHASH));
|
||||
TRACEECB("ENTFIND", p);
|
||||
return p;
|
||||
}
|
||||
/* ENTREF: Process a general or parameter entity reference.
|
||||
If the entity is defined it returns the return code from ENTOPEN.
|
||||
It returns ENTUNDEF for undefined parameter entity references
|
||||
and for general entity references when defaulting is not allowed.
|
||||
Otherwise, it uses the default entity text.
|
||||
*/
|
||||
int entref(ename)
|
||||
UNCH *ename; /* Entity name (with length and EOS). */
|
||||
{
|
||||
PECB ecb; /* Entity control block. */
|
||||
|
||||
/* Get the entity control block, if the entity has been defined. */
|
||||
if ((ecb = (PECB)hfind((THASH)etab, ename, hash(ename, ENTHASH)))==0
|
||||
|| ecb->estore == 0) {
|
||||
if ( ename[1]==lex.d.pero
|
||||
|| ecbdeflt==0
|
||||
|| (ecb = usedef(ename))==0 ) {
|
||||
sgmlerr(ename[1] == lex.d.pero || ecbdeflt == 0 ? 35 : 150,
|
||||
(struct parse *)0, ename+1, (UNCH *)0);
|
||||
return(ENTUNDEF);
|
||||
}
|
||||
}
|
||||
return(entopen(ecb));
|
||||
}
|
||||
/* ENTOPEN: Open a newly referenced entity.
|
||||
Increment the stack pointer (es) and initialize the new entry.
|
||||
ENTDATA if entity is CDATA or SDATA, ENTPI if it is PI,
|
||||
0 if normal and all o.k.; <0 if not.
|
||||
*/
|
||||
int entopen(ecb)
|
||||
struct entity *ecb; /* Entity control block. */
|
||||
{
|
||||
int i; /* Loop counter. */
|
||||
|
||||
/* See if we have exceeded the entity nesting level. */
|
||||
if (es>=ENTLVL) {
|
||||
sgmlerr(34, (struct parse *)0, ecb->ename+1, ntoa(ENTLVL));
|
||||
return(ENTMAX);
|
||||
}
|
||||
/* If entity is an etd, pi, or data, return it without creating an scb. */
|
||||
switch (ecb->estore) {
|
||||
case ESN:
|
||||
if (NEXTYPE(ecb->etx.n)!=ESNSUB) {
|
||||
if (!NEDCNDEFINED(ecb->etx.n))
|
||||
sgmlerr(78, (struct parse *)0, NEDCN(ecb->etx.n)+1,
|
||||
ecb->ename+1);
|
||||
}
|
||||
else {
|
||||
#if 0
|
||||
if (!NEID(ecb->etx.n)) {
|
||||
sgmlerr(149, (struct parse *)0, ecb->ename + 1, (UNCH *)0);
|
||||
return ENTFILE;
|
||||
}
|
||||
#endif
|
||||
if (sw.nopen >= sd.subdoc)
|
||||
sgmlerr(188, (struct parse *)0,
|
||||
(UNCH *)NULL, (UNCH *)NULL);
|
||||
}
|
||||
data = (UNCH *)ecb->etx.n;
|
||||
entdatsw = NDECONT;
|
||||
return(ENTDATA);
|
||||
case ESC:
|
||||
case ESX:
|
||||
datalen = ustrlen(ecb->etx.c);
|
||||
data = ecb->etx.c;
|
||||
entdatsw = (ecb->estore==ESC) ? CDECONT : SDECONT;
|
||||
return(ENTDATA);
|
||||
case ESI:
|
||||
datalen = ustrlen(ecb->etx.c);
|
||||
data = ecb->etx.c;
|
||||
entpisw = 4;
|
||||
return(ENTPI);
|
||||
}
|
||||
/* If the same entity is already open, send msg and ignore it.
|
||||
Level 0 needn't be tested, as its entity name is always *DOC.
|
||||
*/
|
||||
for (i = 0; ++i<=es;) if (scbs[i].ecb.enext==ecb) {
|
||||
sgmlerr(36, (struct parse *)0, ecb->ename+1, (UNCH *)0);
|
||||
return(ENTLOOP);
|
||||
}
|
||||
/* Update SCB if entity trace is wanted in messages or entity is a file.
|
||||
(Avoid this at start when es==-1 or memory will be corrupted.)
|
||||
*/
|
||||
if (es >= 0 && (sw.swenttr || FILESW)) scbset();
|
||||
|
||||
/* Stack the new source control block (we know there is room). */
|
||||
++es; /* Increment scbs index. */
|
||||
RCNT = CCO = RSCC = 0; /* No records or chars yet. */
|
||||
COPIEDSW = 0;
|
||||
memcpy((UNIV)&ECB, (UNIV)ecb, (UNS)ENTSZ); /* Copy the ecb into the scb. */
|
||||
ECBPTR = ecb; /* Save the ecb pointer in scb.ecb.enext. */
|
||||
TRACEECB("ENTOPEN", ECBPTR);
|
||||
|
||||
/* For memory entities, the read buffer is the entity text.
|
||||
The text starts at FBUF, so FPOS should be FBUF-1
|
||||
because it is bumped before each character is read.
|
||||
*/
|
||||
if (ECB.estore<ESFM) {FPOS = (FBUF = ECB.etx.c)-1; return 0;}
|
||||
|
||||
/* For file entities, suspend any open file and do first read. */
|
||||
if (ECB.etx.x == 0) {
|
||||
--es;
|
||||
switch (ecb->estore) {
|
||||
case ESF:
|
||||
sgmlerr(149, (struct parse *)0, ecb->ename + 1, (UNCH *)0);
|
||||
break;
|
||||
case ESP:
|
||||
sgmlerr(229, (struct parse *)0, ecb->ename + 2, (UNCH *)0);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
return ENTFILE;
|
||||
}
|
||||
fileopen(); /* Open new external file. */
|
||||
if (iorc<0) { /* If open not successful: */
|
||||
FPOS = FBUF-1; /* Clean CCNT for OPEN error msg.*/
|
||||
filerr(32, ecb->ename+1);
|
||||
--es; /* Pop the stack. */
|
||||
return(ENTFILE);
|
||||
}
|
||||
filepend(es); /* Suspend any open file. */
|
||||
fileread(); /* First read of file must be ok.*/
|
||||
return 0;
|
||||
}
|
||||
/* ENTGET: Get next record of entity (if there is one).
|
||||
Otherwise, close the file (if entity is a file) and
|
||||
pop the entity stack. If nothing else is on the stack,
|
||||
return -1 to advise the caller.
|
||||
*/
|
||||
int entget()
|
||||
{
|
||||
RSCC += (CCO = FPOS-FBUF);
|
||||
/* Characters-in-record (ignore EOB/EOF). */
|
||||
tagctr += CCO; /* Update tag length counter. */
|
||||
switch (*FPOS) {
|
||||
case EOBCHAR: /* End of file buffer: refill it. */
|
||||
rbufs[-2] = FPOS[-2];
|
||||
rbufs[-1] = FPOS[-1];
|
||||
fileread(); /* Read the file. */
|
||||
if (iorc > 0) break;
|
||||
readerr:
|
||||
filerr(31, ENTITY+1); /* Treat error as EOF. */
|
||||
case EOFCHAR: /* End of file: close it. */
|
||||
fileclos(); /* Call SGMLIO to close file. */
|
||||
conterr:
|
||||
if (es==0) { /* Report if it is primary file. */
|
||||
FPOS = FBUF-1; /* Preserve CCNT for omitted end-tags. */
|
||||
return -1;
|
||||
}
|
||||
case EOS: /* End of memory entity: pop the stack. */
|
||||
TRACEECB("ENTPOP", ECBPTR);
|
||||
if (COPIEDSW) {
|
||||
frem((UNIV)(FBUF + 1));
|
||||
COPIEDSW = 0;
|
||||
}
|
||||
--es; /* Pop the SCB stack. */
|
||||
if (FBUF) break; /* Not a PEND file. */
|
||||
filecont(); /* Resume previous file. */
|
||||
if (iorc<0) { /* If CONT not successful: */
|
||||
filerr(94, ENTITY+1);
|
||||
goto conterr;
|
||||
}
|
||||
fileread(); /* Read the file. */
|
||||
if (iorc<=0) goto readerr; /* If READ not successful: */
|
||||
rbufs[-1] = SCB.pushback;
|
||||
FPOS += CCO;
|
||||
CCO = 0;
|
||||
if (delmscsw && es==0) { /* End of DTD. */
|
||||
delmscsw = 0;
|
||||
*rbufs = lex.d.msc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* USEDEF: Use the default value for an entity reference.
|
||||
Returns the ECB for the defaulted entity.
|
||||
*/
|
||||
PECB usedef(ename)
|
||||
UNCH *ename; /* Entity name (with length and EOS). */
|
||||
{
|
||||
union etext etx; /* Save return from entgen. */
|
||||
PECB ecb; /* Entity control block. */
|
||||
PNE pne = 0; /* Ptr to NDATA entity control block. */
|
||||
UNCH estore; /* Default entity storage type. */
|
||||
|
||||
if ((estore = ecbdeflt->estore)<ESFM) /* Default is an internal string. */
|
||||
etx.c = ecbdeflt->etx.c;
|
||||
else {
|
||||
/* Move entity name into fpi. */
|
||||
fpidf.fpinm = ename + 1;
|
||||
if ((etx.x = entgen(&fpidf))==0) return (PECB)0;
|
||||
if (estore==ESN) {
|
||||
memcpy((UNIV)(pne=(PNE)rmalloc((UNS)NESZ)),(UNIV)ecbdeflt->etx.n,(UNS)NESZ);
|
||||
NEID(pne) = etx.x;
|
||||
etx.n = pne;
|
||||
}
|
||||
}
|
||||
if (sw.swrefmsg) sgmlerr(45, (struct parse *)0, ename+1, (UNCH *)0);
|
||||
++ds.ecbcnt;
|
||||
ecb = entdef(ename, estore, &etx);
|
||||
ecb->dflt = 1;
|
||||
if (pne) NEENAME(pne) = ecb->ename;
|
||||
return(ecb);
|
||||
}
|
||||
/* SCBSET: Set source control block to current location in the current entity.
|
||||
This routine is called by SGML when it returns to the text
|
||||
processor and by ERROR when it reports an error.
|
||||
*/
|
||||
VOID scbset()
|
||||
{
|
||||
if (es >= 0 && FBUF) {
|
||||
CC = *FPOS;
|
||||
if (*FPOS == DELNONCH)
|
||||
NEXTC = FPOS[1];
|
||||
else
|
||||
NEXTC = 0;
|
||||
CCO = FPOS + 1 - FBUF;
|
||||
}
|
||||
}
|
||||
/* FILEOPEN: Call IOOPEN to open an external entity (file).
|
||||
*/
|
||||
VOID fileopen() /* Open an external entity's file. */
|
||||
{
|
||||
iorc = ioopen(ECB.etx.x, &SCBFCB);
|
||||
}
|
||||
/* FILEREAD: Call IOREAD to read an open external entity (file).
|
||||
*/
|
||||
VOID fileread() /* Read the current external entity's file. */
|
||||
{
|
||||
int newfile;
|
||||
iorc = ioread(SCBFCB, rbufs, &newfile);
|
||||
FPOS = (FBUF = rbufs) - 1; /* Actual read buffer. */
|
||||
if (newfile) RCNT = 0;
|
||||
}
|
||||
/* FILEPEND: Call IOPEND to close an open external entity (file) temporarily.
|
||||
*/
|
||||
VOID filepend(es) /* Close the current external entity's file. */
|
||||
int es; /* Local index to scbs. */
|
||||
{
|
||||
while (--es>=0) { /* Find last external file on stack. */
|
||||
int off;
|
||||
if (!FILESW) continue; /* Not an external file. */
|
||||
if (!FBUF) continue; /* Already suspended. */
|
||||
off = CCO;
|
||||
assert(off >= -1);
|
||||
if (off < 0) off = 0;
|
||||
else CCO = 0;
|
||||
FPOS -= CCO;
|
||||
SCB.pushback = FPOS[-1];
|
||||
FBUF = 0; /* Indicate pending file. */
|
||||
RSCC += off; /* Update characters-in-record counter. */
|
||||
tagctr += off; /* Update tag length counter. */
|
||||
iopend(SCBFCB, off, rbufs);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* FILECONT: Call IOCONT to reopen an external entity (file).
|
||||
*/
|
||||
VOID filecont() /* Open an external entity's file. */
|
||||
{
|
||||
iorc = iocont(SCBFCB);
|
||||
}
|
||||
/* FILECLOS: Call IOCLOSE to close an open external entity (file).
|
||||
*/
|
||||
VOID fileclos() /* Close the current external entity's file. */
|
||||
{
|
||||
if (!SCBFCB)
|
||||
return;
|
||||
ioclose(SCBFCB);
|
||||
/* The fcb will have been freed by sgmlio.
|
||||
Make sure we don't access it again. */
|
||||
SCBFCB = NULL;
|
||||
}
|
||||
/* ERROR: Interface to text processor SGML I/O services for error handling.
|
||||
*/
|
||||
VOID error(e)
|
||||
struct error *e;
|
||||
{
|
||||
scbset(); /* Update location in source control block. */
|
||||
msgprint(e);
|
||||
}
|
||||
/* PTRSRCH: Find a pointer in a list and return its index.
|
||||
Search key must be on list as there is no limit test.
|
||||
This routine is internal only -- not for user data.
|
||||
*/
|
||||
UNIV mdnmtab[] = {
|
||||
(UNIV)key[KATTLIST],
|
||||
(UNIV)key[KDOCTYPE],
|
||||
(UNIV)key[KELEMENT],
|
||||
(UNIV)key[KENTITY],
|
||||
(UNIV)key[KLINKTYPE],
|
||||
(UNIV)key[KLINK],
|
||||
(UNIV)key[KNOTATION],
|
||||
(UNIV)sgmlkey,
|
||||
(UNIV)key[KSHORTREF],
|
||||
(UNIV)key[KUSELINK],
|
||||
(UNIV)key[KUSEMAP]
|
||||
};
|
||||
UNIV pcbtab[] = {
|
||||
(UNIV)&pcbconc,
|
||||
(UNIV)&pcbcone,
|
||||
(UNIV)&pcbconm,
|
||||
(UNIV)&pcbconr,
|
||||
(UNIV)&pcbetag,
|
||||
(UNIV)&pcbgrcm,
|
||||
(UNIV)&pcbgrcs,
|
||||
(UNIV)&pcbgrnm,
|
||||
(UNIV)&pcbgrnt,
|
||||
(UNIV)&pcblitc,
|
||||
(UNIV)&pcblitp,
|
||||
(UNIV)&pcblitr,
|
||||
(UNIV)&pcblitt,
|
||||
(UNIV)&pcblitv,
|
||||
(UNIV)&pcbmd,
|
||||
(UNIV)&pcbmdc,
|
||||
(UNIV)&pcbmdi,
|
||||
(UNIV)&pcbmds,
|
||||
(UNIV)&pcbmsc,
|
||||
(UNIV)&pcbmsi,
|
||||
(UNIV)&pcbmsrc,
|
||||
(UNIV)&pcbpro,
|
||||
(UNIV)&pcbref,
|
||||
(UNIV)&pcbstag,
|
||||
(UNIV)&pcbval,
|
||||
(UNIV)&pcbeal,
|
||||
(UNIV)&pcbsd,
|
||||
};
|
||||
UNS ptrsrch(ptrtab, ptr)
|
||||
UNIV ptrtab[];
|
||||
UNIV ptr;
|
||||
{
|
||||
UNS i;
|
||||
|
||||
for (i = 0; ; ++i)
|
||||
if (ptrtab[i] == ptr)
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
/* MDERR: Process errors for markup declarations.
|
||||
Prepare the special parameters that only exist for
|
||||
markup declaration errors.
|
||||
*/
|
||||
VOID mderr(number, parm1, parm2)
|
||||
UNS number; /* Error number. */
|
||||
UNCH *parm1; /* Additional parameters (or NULL). */
|
||||
UNCH *parm2; /* Additional parameters (or NULL). */
|
||||
{
|
||||
struct error err;
|
||||
errorinit(&err, subdcl ? MDERR : MDERR2, number);
|
||||
err.parmno = parmno;
|
||||
err.subdcl = subdcl;
|
||||
err.eparm[0] = (UNIV)parm1;
|
||||
err.eparm[1] = (UNIV)parm2;
|
||||
err.errsp = (sizeof(pcbtab)/sizeof(pcbtab[0])) + ptrsrch(mdnmtab,
|
||||
(UNIV)mdname);
|
||||
error(&err);
|
||||
}
|
||||
/* SGMLERR: Process errors for SGML parser.
|
||||
*/
|
||||
VOID sgmlerr(number, pcb, parm1, parm2)
|
||||
UNS number; /* Error number. */
|
||||
struct parse *pcb; /* Current parse control block. */
|
||||
UNCH *parm1; /* Error message parameters. */
|
||||
UNCH *parm2; /* Error message parameters. */
|
||||
{
|
||||
struct error err;
|
||||
errorinit(&err, DOCERR, number);
|
||||
if (!pcb) pcb = prologsw ? propcb : conpcb;
|
||||
err.errsp = ptrsrch(pcbtab, (UNIV)pcb);
|
||||
err.eparm[0] = (UNIV)parm1;
|
||||
err.eparm[1] = (UNIV)parm2;
|
||||
error(&err);
|
||||
}
|
||||
/* SAVERR: Save an error for possible later use.
|
||||
*/
|
||||
UNIV saverr(number, pcb, parm1, parm2)
|
||||
UNS number; /* Error number. */
|
||||
struct parse *pcb; /* Current parse control block. */
|
||||
UNCH *parm1; /* Error message parameters. */
|
||||
UNCH *parm2; /* Error message parameters. */
|
||||
{
|
||||
struct error err;
|
||||
errorinit(&err, DOCERR, number);
|
||||
if (!pcb) pcb = prologsw ? propcb : conpcb;
|
||||
err.errsp = ptrsrch(pcbtab, (UNIV)pcb);
|
||||
err.eparm[0] = (UNIV)parm1;
|
||||
err.eparm[1] = (UNIV)parm2;
|
||||
scbset();
|
||||
return msgsave(&err);
|
||||
}
|
||||
/* SVDERR: Print a saved error.
|
||||
*/
|
||||
VOID svderr(p)
|
||||
UNIV p;
|
||||
{
|
||||
msgsprint(p);
|
||||
}
|
||||
/* EXITERR: Process terminal errors for SGML parser.
|
||||
*/
|
||||
VOID exiterr(number, pcb)
|
||||
UNS number; /* Error number. */
|
||||
struct parse *pcb; /* Current parse control block. */
|
||||
{
|
||||
struct error err;
|
||||
errorinit(&err, EXITERR, number);
|
||||
if (!pcb) pcb = prologsw ? propcb : conpcb;
|
||||
err.errsp = ptrsrch(pcbtab, (UNIV)pcb);
|
||||
error(&err);
|
||||
/* The error handler should have exited. */
|
||||
abort();
|
||||
}
|
||||
/* SYNERR: Process syntax errors for SGML parser.
|
||||
*/
|
||||
VOID synerr(number, pcb)
|
||||
UNS number; /* Error number. */
|
||||
struct parse *pcb; /* Current parse control block. */
|
||||
{
|
||||
struct error err;
|
||||
errorinit(&err, DOCERR, number);
|
||||
err.errsp = ptrsrch(pcbtab, (UNIV)pcb);
|
||||
error(&err);
|
||||
}
|
||||
/* FILERR: Process a file access error.
|
||||
*/
|
||||
VOID filerr(number, parm)
|
||||
UNS number;
|
||||
UNCH *parm;
|
||||
{
|
||||
struct error err;
|
||||
errorinit(&err, FILERR, number);
|
||||
err.eparm[0] = (UNIV)parm;
|
||||
err.sverrno = errno;
|
||||
error(&err);
|
||||
}
|
||||
/* ERRORINIT: Constructor for struct error.
|
||||
*/
|
||||
VOID errorinit(e, type, number)
|
||||
struct error *e;
|
||||
UNS type;
|
||||
UNS number;
|
||||
{
|
||||
int i;
|
||||
e->errtype = type;
|
||||
e->errnum = number;
|
||||
e->errsp = 0;
|
||||
for (i = 0; i < MAXARGS; i++)
|
||||
e->eparm[i] = 0;
|
||||
e->parmno = 0;
|
||||
e->subdcl = 0;
|
||||
}
|
||||
/*
|
||||
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