2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: sgml2.c /main/3 1996/06/19 17:17:20 drk $ */
24 /* Added exiterr() for terminal errors to prevent SGML.MSG errors. */
25 #include "sgmlincl.h" /* #INCLUDE statements for SGML parser. */
26 static int iorc; /* Return code from io* functions */
27 /* ENTDEF: Process an entity definition and return the pointer to it.
28 The entity text must be in permanent storage.
29 There is no checking to see if the entity already exists;
30 the caller must have done that.
33 PECB entdef(UNCH *ename, UNCH estore, union etext *petx)
35 PECB entdef(ename, estore, petx)
36 UNCH *ename; /* Entity name (with length and EOS). */
37 UNCH estore; /* Entity storage class. */
38 union etext *petx; /* Ptr to entity text union. */
43 p = (PECB)hin((THASH)etab, ename, hash(ename, ENTHASH), ENTSZ);
44 memcpy((UNIV)&p->etx, (UNIV)petx, ETEXTSZ);
46 TRACEECB("ENTDEF", p);
49 /* ENTFIND: If an entity exists, return ptr to its ecb.
50 Return NULL if it is not defined.
53 UNCH *ename; /* Entity name (with length and EOS). */
57 p = (PECB)hfind((THASH)etab, ename, hash(ename, ENTHASH));
58 TRACEECB("ENTFIND", p);
61 /* ENTREF: Process a general or parameter entity reference.
62 If the entity is defined it returns the return code from ENTOPEN.
63 It returns ENTUNDEF for undefined parameter entity references
64 and for general entity references when defaulting is not allowed.
65 Otherwise, it uses the default entity text.
68 UNCH *ename; /* Entity name (with length and EOS). */
70 PECB ecb; /* Entity control block. */
72 /* Get the entity control block, if the entity has been defined. */
73 if ((ecb = (PECB)hfind((THASH)etab, ename, hash(ename, ENTHASH)))==0
74 || ecb->estore == 0) {
75 if ( ename[1]==lex.d.pero
77 || (ecb = usedef(ename))==0 ) {
78 sgmlerr(ename[1] == lex.d.pero || ecbdeflt == 0 ? 35 : 150,
79 (struct parse *)0, ename+1, (UNCH *)0);
85 /* ENTOPEN: Open a newly referenced entity.
86 Increment the stack pointer (es) and initialize the new entry.
87 ENTDATA if entity is CDATA or SDATA, ENTPI if it is PI,
88 0 if normal and all o.k.; <0 if not.
91 struct entity *ecb; /* Entity control block. */
93 int i; /* Loop counter. */
95 /* See if we have exceeded the entity nesting level. */
97 sgmlerr(34, (struct parse *)0, ecb->ename+1, ntoa(ENTLVL));
100 /* If entity is an etd, pi, or data, return it without creating an scb. */
101 switch (ecb->estore) {
103 if (NEXTYPE(ecb->etx.n)!=ESNSUB) {
104 if (!NEDCNDEFINED(ecb->etx.n))
105 sgmlerr(78, (struct parse *)0, NEDCN(ecb->etx.n)+1,
110 if (!NEID(ecb->etx.n)) {
111 sgmlerr(149, (struct parse *)0, ecb->ename + 1, (UNCH *)0);
115 if (sw.nopen >= sd.subdoc)
116 sgmlerr(188, (struct parse *)0,
117 (UNCH *)NULL, (UNCH *)NULL);
119 data = (UNCH *)ecb->etx.n;
124 datalen = ustrlen(ecb->etx.c);
126 entdatsw = (ecb->estore==ESC) ? CDECONT : SDECONT;
129 datalen = ustrlen(ecb->etx.c);
134 /* If the same entity is already open, send msg and ignore it.
135 Level 0 needn't be tested, as its entity name is always *DOC.
137 for (i = 0; ++i<=es;) if (scbs[i].ecb.enext==ecb) {
138 sgmlerr(36, (struct parse *)0, ecb->ename+1, (UNCH *)0);
141 /* Update SCB if entity trace is wanted in messages or entity is a file.
142 (Avoid this at start when es==-1 or memory will be corrupted.)
144 if (es >= 0 && (sw.swenttr || FILESW)) scbset();
146 /* Stack the new source control block (we know there is room). */
147 ++es; /* Increment scbs index. */
148 RCNT = CCO = RSCC = 0; /* No records or chars yet. */
150 memcpy((UNIV)&ECB, (UNIV)ecb, (UNS)ENTSZ); /* Copy the ecb into the scb. */
151 ECBPTR = ecb; /* Save the ecb pointer in scb.ecb.enext. */
152 TRACEECB("ENTOPEN", ECBPTR);
154 /* For memory entities, the read buffer is the entity text.
155 The text starts at FBUF, so FPOS should be FBUF-1
156 because it is bumped before each character is read.
158 if (ECB.estore<ESFM) {FPOS = (FBUF = ECB.etx.c)-1; return 0;}
160 /* For file entities, suspend any open file and do first read. */
161 if (ECB.etx.x == 0) {
163 switch (ecb->estore) {
165 sgmlerr(149, (struct parse *)0, ecb->ename + 1, (UNCH *)0);
168 sgmlerr(229, (struct parse *)0, ecb->ename + 2, (UNCH *)0);
175 fileopen(); /* Open new external file. */
176 if (iorc<0) { /* If open not successful: */
177 FPOS = FBUF-1; /* Clean CCNT for OPEN error msg.*/
178 filerr(32, ecb->ename+1);
179 --es; /* Pop the stack. */
182 filepend(es); /* Suspend any open file. */
183 fileread(); /* First read of file must be ok.*/
186 /* ENTGET: Get next record of entity (if there is one).
187 Otherwise, close the file (if entity is a file) and
188 pop the entity stack. If nothing else is on the stack,
189 return -1 to advise the caller.
193 RSCC += (CCO = FPOS-FBUF);
194 /* Characters-in-record (ignore EOB/EOF). */
195 tagctr += CCO; /* Update tag length counter. */
197 case EOBCHAR: /* End of file buffer: refill it. */
198 rbufs[-2] = FPOS[-2];
199 rbufs[-1] = FPOS[-1];
200 fileread(); /* Read the file. */
203 filerr(31, ENTITY+1); /* Treat error as EOF. */
204 case EOFCHAR: /* End of file: close it. */
205 fileclos(); /* Call SGMLIO to close file. */
207 if (es==0) { /* Report if it is primary file. */
208 FPOS = FBUF-1; /* Preserve CCNT for omitted end-tags. */
211 case EOS: /* End of memory entity: pop the stack. */
212 TRACEECB("ENTPOP", ECBPTR);
214 frem((UNIV)(FBUF + 1));
217 --es; /* Pop the SCB stack. */
218 if (FBUF) break; /* Not a PEND file. */
219 filecont(); /* Resume previous file. */
220 if (iorc<0) { /* If CONT not successful: */
221 filerr(94, ENTITY+1);
224 fileread(); /* Read the file. */
225 if (iorc<=0) goto readerr; /* If READ not successful: */
226 rbufs[-1] = SCB.pushback;
229 if (delmscsw && es==0) { /* End of DTD. */
237 /* USEDEF: Use the default value for an entity reference.
238 Returns the ECB for the defaulted entity.
241 UNCH *ename; /* Entity name (with length and EOS). */
243 union etext etx; /* Save return from entgen. */
244 PECB ecb; /* Entity control block. */
245 PNE pne = 0; /* Ptr to NDATA entity control block. */
246 UNCH estore; /* Default entity storage type. */
248 if ((estore = ecbdeflt->estore)<ESFM) /* Default is an internal string. */
249 etx.c = ecbdeflt->etx.c;
251 /* Move entity name into fpi. */
252 fpidf.fpinm = ename + 1;
253 if ((etx.x = entgen(&fpidf))==0) return (PECB)0;
255 memcpy((UNIV)(pne=(PNE)rmalloc((UNS)NESZ)),(UNIV)ecbdeflt->etx.n,(UNS)NESZ);
260 if (sw.swrefmsg) sgmlerr(45, (struct parse *)0, ename+1, (UNCH *)0);
262 ecb = entdef(ename, estore, &etx);
264 if (pne) NEENAME(pne) = ecb->ename;
267 /* SCBSET: Set source control block to current location in the current entity.
268 This routine is called by SGML when it returns to the text
269 processor and by ERROR when it reports an error.
273 if (es >= 0 && FBUF) {
275 if (*FPOS == DELNONCH)
279 CCO = FPOS + 1 - FBUF;
282 /* FILEOPEN: Call IOOPEN to open an external entity (file).
284 VOID fileopen() /* Open an external entity's file. */
286 iorc = ioopen(ECB.etx.x, &SCBFCB);
288 /* FILEREAD: Call IOREAD to read an open external entity (file).
290 VOID fileread() /* Read the current external entity's file. */
293 iorc = ioread(SCBFCB, rbufs, &newfile);
294 FPOS = (FBUF = rbufs) - 1; /* Actual read buffer. */
295 if (newfile) RCNT = 0;
297 /* FILEPEND: Call IOPEND to close an open external entity (file) temporarily.
299 VOID filepend(es) /* Close the current external entity's file. */
300 int es; /* Local index to scbs. */
302 while (--es>=0) { /* Find last external file on stack. */
304 if (!FILESW) continue; /* Not an external file. */
305 if (!FBUF) continue; /* Already suspended. */
308 if (off < 0) off = 0;
311 SCB.pushback = FPOS[-1];
312 FBUF = 0; /* Indicate pending file. */
313 RSCC += off; /* Update characters-in-record counter. */
314 tagctr += off; /* Update tag length counter. */
315 iopend(SCBFCB, off, rbufs);
319 /* FILECONT: Call IOCONT to reopen an external entity (file).
321 VOID filecont() /* Open an external entity's file. */
323 iorc = iocont(SCBFCB);
325 /* FILECLOS: Call IOCLOSE to close an open external entity (file).
327 VOID fileclos() /* Close the current external entity's file. */
332 /* The fcb will have been freed by sgmlio.
333 Make sure we don't access it again. */
336 /* ERROR: Interface to text processor SGML I/O services for error handling.
341 scbset(); /* Update location in source control block. */
344 /* PTRSRCH: Find a pointer in a list and return its index.
345 Search key must be on list as there is no limit test.
346 This routine is internal only -- not for user data.
353 (UNIV)key[KLINKTYPE],
355 (UNIV)key[KNOTATION],
357 (UNIV)key[KSHORTREF],
390 UNS ptrsrch(ptrtab, ptr)
397 if (ptrtab[i] == ptr)
401 /* MDERR: Process errors for markup declarations.
402 Prepare the special parameters that only exist for
403 markup declaration errors.
405 VOID mderr(number, parm1, parm2)
406 UNS number; /* Error number. */
407 UNCH *parm1; /* Additional parameters (or NULL). */
408 UNCH *parm2; /* Additional parameters (or NULL). */
411 errorinit(&err, subdcl ? MDERR : MDERR2, number);
414 err.eparm[0] = (UNIV)parm1;
415 err.eparm[1] = (UNIV)parm2;
416 err.errsp = (sizeof(pcbtab)/sizeof(pcbtab[0])) + ptrsrch(mdnmtab,
420 /* SGMLERR: Process errors for SGML parser.
422 VOID sgmlerr(number, pcb, parm1, parm2)
423 UNS number; /* Error number. */
424 struct parse *pcb; /* Current parse control block. */
425 UNCH *parm1; /* Error message parameters. */
426 UNCH *parm2; /* Error message parameters. */
429 errorinit(&err, DOCERR, number);
430 if (!pcb) pcb = prologsw ? propcb : conpcb;
431 err.errsp = ptrsrch(pcbtab, (UNIV)pcb);
432 err.eparm[0] = (UNIV)parm1;
433 err.eparm[1] = (UNIV)parm2;
436 /* SAVERR: Save an error for possible later use.
438 UNIV saverr(number, pcb, parm1, parm2)
439 UNS number; /* Error number. */
440 struct parse *pcb; /* Current parse control block. */
441 UNCH *parm1; /* Error message parameters. */
442 UNCH *parm2; /* Error message parameters. */
445 errorinit(&err, DOCERR, number);
446 if (!pcb) pcb = prologsw ? propcb : conpcb;
447 err.errsp = ptrsrch(pcbtab, (UNIV)pcb);
448 err.eparm[0] = (UNIV)parm1;
449 err.eparm[1] = (UNIV)parm2;
451 return msgsave(&err);
453 /* SVDERR: Print a saved error.
460 /* EXITERR: Process terminal errors for SGML parser.
462 VOID exiterr(number, pcb)
463 UNS number; /* Error number. */
464 struct parse *pcb; /* Current parse control block. */
467 errorinit(&err, EXITERR, number);
468 if (!pcb) pcb = prologsw ? propcb : conpcb;
469 err.errsp = ptrsrch(pcbtab, (UNIV)pcb);
471 /* The error handler should have exited. */
474 /* SYNERR: Process syntax errors for SGML parser.
476 VOID synerr(number, pcb)
477 UNS number; /* Error number. */
478 struct parse *pcb; /* Current parse control block. */
481 errorinit(&err, DOCERR, number);
482 err.errsp = ptrsrch(pcbtab, (UNIV)pcb);
485 /* FILERR: Process a file access error.
487 VOID filerr(number, parm)
492 errorinit(&err, FILERR, number);
493 err.eparm[0] = (UNIV)parm;
497 /* ERRORINIT: Constructor for struct error.
499 VOID errorinit(e, type, number)
508 for (i = 0; i < MAXARGS; i++)
516 c-continued-statement-offset: 5