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: sgmlmsg.c /main/3 1996/06/19 17:17:57 drk $ */
25 message handling for core parser
27 Written by James Clark (jjc@jclark.com).
36 #define TEXT_SET 1 /* message set number for text of messages */
37 #define HEADER_SET 2 /* message set number for header strings */
38 #define PARM_SET 3 /* message set number for special parameters */
40 #ifdef HAVE_EXTENDED_PRINTF
41 #define xfprintf fprintf
43 extern int xfprintf VP((FILE *, char *,...));
46 #define SIZEOF(v) (sizeof(v)/sizeof(v[0]))
48 static char *gettext P((int));
49 static char *getheader P((int));
50 static char *getparm P((int));
51 static VOID elttrace P((FILE *, int));
52 static int printit P((FILE *, struct error *));
53 static char *transparm P((UNCH *, char *));
54 static VOID spaces P((FILE *, int));
57 static char parmbuf[PARMBUFSIZ*2];
58 static char *parmbuf1 = parmbuf;
59 static char *parmbuf2 = parmbuf + PARMBUFSIZ;
61 static char *prog; /* program name */
62 static int sweltr; /* non-zero means print an element trace */
63 static int swenttr; /* non-zero means print an entity trace */
64 static int cnterr = 0;
65 static VOID (*die) P((void));
67 static char *headers[] = {
69 "SGML error", /* parameters: type, severity, number */
70 "Unsupported feature", /* type U errors */
71 "Error", /* for type R errors */
72 "Warning", /* severity type I */
73 " at %s, %.0sline %lu", /* ignore entity name and ccnt */
74 " at entity %s, line %lu",
75 "%.0s%.0s in declaration parameter %d", /* ignore first two parameters */
76 "%.0s in declaration parameter %d", /* ignore first parameter */
77 "%.0s", /* parse mode */
88 /* Indexes into headers[] */
109 /* Special parameters (error::errsp) */
110 static char *parms[] = {
114 "replaceable character data",
116 "content model group",
117 "content model occurrence indicator",
122 "attribute value literal",
123 "tokenized attribute value literal",
125 "markup declaration",
126 "markup declaration comment",
127 "ignored markup declaration",
128 "declaration subset",
129 "CDATA marked section",
130 "IGNORE marked section",
131 "RCDATA marked section",
134 "attribute specification list",
135 "tokenized attribute value",
136 "attribute specification list close",
138 "attribute definition list",
146 "short reference mapping",
148 "short reference use",
151 static FILE *tfp; /* temporary file for saved messages */
163 if (printit(stderr, e))
166 if (e->errtype == EXITERR) {
176 /* Save an error message. */
183 sv = (struct saved *)rmalloc(sizeof(struct saved));
187 exiterr(160, (struct parse *)0);
189 sv->start = ftell(tfp);
190 sv->countit = (char)printit(tfp, e);
191 sv->end = ftell(tfp);
192 sv->exiterr = (char)(e->errtype == EXITERR);
196 /* Print a saved error message. */
201 struct saved *sv = (struct saved *)p;
206 if (fseek(tfp, sv->start, SEEK_SET) < 0)
208 /* Temporary files are opened in binary mode, so this is portable. */
209 cnt = sv->end - sv->start;
223 /* Free a sved error message. */
231 /* Return 1 if it should be counted as an error. */
233 static int printit(efp, e)
240 int filelevel = -1, prevfilelevel = -1, toplevel;
242 char type[2], severity[2];
244 assert(e->errnum < SIZEOF(messages));
245 assert(messages[e->errnum].text != NULL);
247 fprintf(efp, "%s: ", prog);
248 indent = strlen(prog) + 2; /* don't rely on return value of fprintf */
249 /* Don't want to waste too much space on indenting. */
256 for (toplevel = 0; getlocation(toplevel, &loc); toplevel++)
258 prevfilelevel = filelevel;
259 filelevel = toplevel;
263 if (e->errtype == FILERR) {
265 filelevel = prevfilelevel;
267 if (swenttr && filelevel > 0) {
269 int middle = 0; /* in the middle of a line */
271 (void)getlocation(level, &loc);
279 xfprintf(efp, getheader(HDRPFX));
280 xfprintf(efp, getheader(HDRLOC), ioflid(loc.fcb),
281 loc.ename, loc.rcnt, loc.ccnt);
284 xfprintf(efp, getheader(HDRELOC),
285 loc.ename, loc.rcnt + 1, loc.ccnt);
287 while (++level != filelevel);
294 /* We use strings for the type and severity,
295 so that the format can use %.0s to ignore them. */
297 type[0] = messages[e->errnum].type;
299 severity[0] = messages[e->errnum].severity;
302 countit = (severity[0] != 'I');
305 else if (type[0] == 'R')
307 else if (type[0] == 'U')
312 xfprintf(efp, getheader(hdrcode), type, severity, e->errnum);
314 if (filelevel >= 0) {
315 (void)getlocation(filelevel, &loc);
316 xfprintf(efp, getheader(HDRLOC),
317 ioflid(loc.fcb), loc.ename, loc.rcnt, loc.ccnt);
318 while (filelevel < toplevel) {
321 (void)getlocation(filelevel, &loc);
322 xfprintf(efp, getheader(HDRELOC),
323 loc.ename, loc.rcnt + 1, loc.ccnt);
328 /* It is necessary to copy the result of getparm() because
329 the specification of catgets() says in can return a
330 pointer to a static buffer which may get overwritten
331 by the next call to catgets(). */
333 switch (e->errtype) {
335 strncpy(parmbuf, getparm(e->errsp), PARMBUFSIZ*2 - 1);
336 xfprintf(efp, getheader(HDRMD), parmbuf,
337 (e->subdcl ? e->subdcl : (UNCH *)""), e->parmno);
340 /* no subdcl parameter */
341 strncpy(parmbuf, getparm(e->errsp), PARMBUFSIZ*2 - 1);
342 xfprintf(efp, getheader(HDRMD2), parmbuf, e->parmno);
348 strncpy(parmbuf, getparm(e->errsp), PARMBUFSIZ*2 - 1);
349 xfprintf(efp, getheader(HDRMODE), parmbuf);
350 switch (loc.curchar) {
352 xfprintf(efp, getheader(HDREOF));
355 xfprintf(efp, getheader(HDRRS));
358 xfprintf(efp, getheader(HDRRE));
361 xfprintf(efp, getheader(HDRCTL), UNSHIFTNON(loc.nextchar));
364 xfprintf(efp, getheader(HDREE));
369 if (ISASCII(loc.curchar) && isprint(loc.curchar))
370 xfprintf(efp, getheader(HDRPRT), loc.curchar);
372 xfprintf(efp, getheader(HDRCTL), loc.curchar);
377 if (getlocation(toplevel + 1, &loc))
378 xfprintf(efp, getheader(HDRFIL), ioflid(loc.fcb));
383 if (e->errtype == FILERR && e->sverrno != 0) {
384 char *errstr = strerror(e->sverrno);
385 UNS len = strlen(errstr);
386 /* Strip a trailing newline if there is one. */
387 if (len > 0 && errstr[len - 1] == '\n')
390 for (; len > 0; len--, errstr++)
397 xfprintf(efp, gettext(e->errnum),
398 transparm((UNCH *)e->eparm[0], parmbuf1),
399 transparm((UNCH *)e->eparm[1], parmbuf2));
403 elttrace(efp, indent);
407 /* Print an element trace. */
408 static VOID elttrace(efp, indent)
419 xfprintf(efp, getheader(HDRELT));
421 fprintf(efp, " %s", gi);
427 static VOID spaces(efp, indent)
431 while (--indent >= 0)
436 struct switches *swp;
440 sweltr = swp->sweltr;
441 swenttr = swp->swenttr;
445 /* Return the error count. */
452 /* Transform a parameter into a form suitable for printing. */
454 static char *transparm(s, buf)
465 cnt = PARMBUFSIZ - 4; /* space for `...\0' */
469 if (ch == DELNONCH) {
475 if (ch == DELCDATA || ch == DELSDATA)
477 else if (ch == '\\') {
484 else if (ISASCII(ch) && isprint(ch)) {
493 sprintf(ptr, "\\%03o", ch);
505 /* The message and set numbers in the catgets function must be > 0. */
507 static char *gettext(n)
510 assert(n > 0 && n < SIZEOF(messages));
511 assert(messages[n].text != 0);
512 return catgets(catd, TEXT_SET, n, messages[n].text);
515 static char *getheader(n)
518 assert(n >= 0 && n < SIZEOF(headers));
519 return catgets(catd, HEADER_SET, n + 1, headers[n]);
522 static char *getparm(n)
525 assert(n >= 0 && n < SIZEOF(parms));
526 return catgets(catd, PARM_SET, n + 1, parms[n]);
532 c-continued-statement-offset: 5