home *** CD-ROM | disk | FTP | other *** search
- /* 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:
- */
-