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: main.c /main/3 1996/06/19 17:16:04 drk $ */
25 Main program for sgmls.
27 Written by James Clark (jjc@jclark.com).
33 #include "entity.h" /* Templates for entity control blocks. */
34 #include "adl.h" /* Definitions for attribute list processing. */
35 #include "sgmlmain.h" /* Main interface to SGML services. */
40 /* Before using argv[0] in error messages, strip off everything up to and
41 including the last character in prog that occurs in PROG_PREFIX. */
44 #define PROG_PREFIX "/"
45 #endif /* not PROG_PREFIX */
47 /* Message catalogue name. */
48 #define CAT_NAME "sgmls"
49 /* Message set to use for application error messages. */
52 #ifdef HAVE_EXTENDED_PRINTF
53 #define xvfprintf vfprintf
55 extern int xvfprintf P((FILE *, char *, va_list));
58 static VOID usage P((void));
59 static VOID fatal VP((int, ...));
60 static VOID do_error P((int, va_list));
61 static VOID swinit P((struct switches *));
62 static VOID write_caps P((char *, struct sgmlcap *));
64 static UNIV make_docent P((int, char **));
65 static char *munge_program_name P((char *, char *));
66 static VOID die P((void));
68 static VOID build_subargv P((struct switches *));
69 static VOID cleanup P((void));
70 static char *create_subcap_file P((void));
71 #endif /* SUPPORT_SUBDOC */
73 static char *errlist[] = {
76 "Cannot open SGML document entity",
77 "Cannot exec `%s': %s",
79 "Error waiting for process: %s",
80 "Program %s got fatal signal %d",
81 "Cannot open `%s': %s",
82 "Subdocument capacity botch",
83 "Non-existent subdocument entity `%s' not processed",
86 int suppsw = 0; /* Non-zero means suppress output. */
87 int locsw = 0; /* Non-zero means generate location info. */
88 static char *prog; /* Program name (for error messages). */
89 static nl_catd catd; /* Message catalogue descriptor. */
90 static char *capfile = 0; /* File for capacity report. */
91 extern char *version_string;
94 'c', ':', 'd', 'e', 'g', 'i', ':', 'l', 'o', ':', 'p', 'r', 's', 'u', 'v',
95 #ifdef CANT_REDIRECT_STDERR
97 #endif /* CANT_REDIRECT_STDERR */
104 #ifdef SUPPORT_SUBDOC
105 int suberr = 0; /* Error in subdocument. */
106 static char *subargv[sizeof(options)];
107 static int subargc = 0;
108 static char nopenbuf[sizeof(long)*3 + 1];
109 static char sgmldecl_file[L_tmpnam];
110 static char subcap_file[L_tmpnam];
117 static char stderr_buf[BUFSIZ];
119 #ifdef CANT_REDIRECT_STDERR
124 int nincludes = 0; /* number of -i options */
125 setbuf(stderr, stderr_buf);
127 /* Define MAIN_HOOK in config.h if some function needs to be called here. */
129 MAIN_HOOK(argc, argv);
131 #ifdef SUPPORT_SUBDOC
132 subargv[subargc++] = argv[0];
135 prog = argv[0] = munge_program_name(argv[0], "sgmls");
137 catd = catopen(CAT_NAME, 0);
140 while ((opt = getopt(argc, argv, options)) != EOF) {
142 case 'l': /* Generate location information. */
145 case 'c': /* Print capacity usage. */
148 case 's': /* Suppress output. */
151 case 'd': /* Report duplicate entity declarations. */
154 case 'e': /* Provide entity stack trace in error msg. */
157 #ifdef CANT_REDIRECT_STDERR
158 case 'f': /* Redirect errors. */
161 #endif /* CANT_REDIRECT_STDERR */
162 case 'g': /* Provide GI stack trace in error messages. */
165 case 'p': /* Parse only the prolog. */
169 case 'r': /* Give warning for defaulted references. */
176 case 'x': /* Trace options for the document body. */
179 case 'y': /* Trace options for the prolog. */
183 case 'v': /* Print the version number. */
184 fprintf(stderr, "sgmls version %s\n", version_string);
188 sw.nopen = atol(optarg);
192 case 'i': /* Define parameter entity as "INCLUDE". */
193 sw.includes = (char **)xrealloc((UNIV)sw.includes,
194 (nincludes + 2)*sizeof(char *));
195 sw.includes[nincludes++] = optarg;
196 sw.includes[nincludes] = 0;
205 #ifdef CANT_REDIRECT_STDERR
209 fp = fopen(errfile, "w");
211 fatal(E_OPEN, errfile, strerror(errno));
214 if (!freopen(errfile, "w", stderr)) {
215 /* Can't use fatal() since stderr is now closed */
216 printf("%s: ", prog);
217 printf(errlist[E_OPEN], errfile, strerror(errno));
222 #endif /* CANT_REDIRECT_STDERR */
226 #ifdef SUPPORT_SUBDOC
229 if (sgmlsdoc(make_docent(argc - optind, argv + optind)))
232 process_document(sw.nopen > 0);
235 write_caps(capfile, &cap);
236 #ifdef SUPPORT_SUBDOC
240 #endif /* SUPPORT_SUBDOC */
241 if (sgmlgcnterr() > 0)
248 static char *munge_program_name(arg, dflt)
252 #ifdef PROG_STRIP_EXTENSION
257 p = strchr(arg, '\0');
262 if (strchr(PROG_PREFIX, *p)) {
268 #ifdef PROG_STRIP_EXTENSION
269 ext = strrchr(arg, '.');
271 p = (char *)xmalloc(ext - arg + 1);
272 memcpy(p, arg, ext - arg);
276 #endif /* PROG_STRIP_EXTENSION */
278 #ifdef PROG_STRIP_EXTENSION
281 p = xmalloc(strlen(arg) + 1);
284 #ifdef PROG_STRIP_EXTENSION
287 for (p = arg; *p; p++)
288 if (ISASCII((unsigned char)*p) && isupper((unsigned char)*p))
289 *p = tolower((unsigned char)*p);
290 #endif /* PROG_FOLD */
294 static UNIV make_docent(argc, argv)
302 static char *stdinname = STDINNAME;
309 for (i = 0; i < argc; i++)
310 len += strlen(argv[i]) + 1;
314 for (i = 0; i < argc; i++) {
315 strcpy(ptr, argv[i]);
316 ptr = strchr(ptr, '\0') + 1;
325 /* Don't mention -o since this are for internal use only. */
326 fprintf(stderr, "Usage: %s [-deglprsuv]%s [-c file] [-i entity]%s [filename ...]\n",
328 #ifdef CANT_REDIRECT_STDERR
330 #else /* not CANT_REDIRECT_STDERR */
332 #endif /* not CANT_REDIRECT_STDERR */
334 " [-x flags] [-y flags]"
335 #else /* not TRACE */
337 #endif /* not TRACE */
344 #ifdef SUPPORT_SUBDOC
346 #endif /* SUPPORT_SUBDOC */
350 static VOID swinit(swp)
351 struct switches *swp;
355 swp->swbufsz = READCNT+2;
364 swp->swambig = 1; /* Always check for ambiguity. */
372 #ifdef SUPPORT_SUBDOC
374 static VOID build_subargv(swp)
375 struct switches *swp;
378 subargv[subargc++] = "-s";
380 subargv[subargc++] = "-l";
382 subargv[subargc++] = "-d";
384 subargv[subargc++] = "-e";
386 subargv[subargc++] = "-g";
388 subargv[subargc++] = "-r";
391 subargv[subargc++] = "-x";
392 subargv[subargc++] = swp->trace;
395 subargv[subargc++] = "-y";
396 subargv[subargc++] = swp->ptrace;
399 subargv[subargc++] = "-o";
400 sprintf(nopenbuf, "%ld", swp->nopen + 1);
401 subargv[subargc++] = nopenbuf;
409 signal(sig, SIG_DFL);
417 if (sgmldecl_file[0]) {
418 (void)remove(sgmldecl_file);
419 sgmldecl_file[0] = '\0';
421 if (subcap_file[0]) {
422 (void)remove(subcap_file);
423 subcap_file[0] = '\0';
428 char *store_sgmldecl()
430 if (!sgmldecl_file[0]) {
432 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
433 signal(SIGINT, handler);
435 if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
436 signal(SIGTERM, handler);
439 if (signal(SIGPIPE, SIG_IGN) != SIG_IGN)
440 signal(SIGPIPE, handler);
443 if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
444 signal(SIGHUP, handler);
446 tmpnam(sgmldecl_file);
448 fp = fopen(sgmldecl_file, "w");
450 fatal(E_OPEN, sgmldecl_file, strerror(errno));
454 return sgmldecl_file;
458 char *create_subcap_file()
460 if (subcap_file[0] == '\0') {
463 fp = fopen(subcap_file, "w");
465 fatal(E_OPEN, subcap_file, strerror(errno));
479 for (p = (char *)id, nfiles = 0; *p; p = strchr(p, '\0') + 1)
482 argv = (char **)xmalloc((subargc + 2 + 1 + nfiles + 1)*sizeof(char *));
483 memcpy((UNIV)argv, (UNIV)subargv, subargc*sizeof(char *));
488 argv[i++] = create_subcap_file();
490 argv[i++] = store_sgmldecl();
492 for (p = (char *)id; *p; p = strchr(p, '\0') + 1)
507 fp = fopen(subcap_file, "r");
509 fatal(E_OPEN, subcap_file, strerror(errno));
510 for (i = 0; i < NCAPACITY; i++)
511 if (fscanf(fp, "%*s %ld", cap + i) != 1)
518 #endif /* SUPPORT_SUBDOC */
520 /* Print capacity statistics.*/
522 static VOID write_caps(name, p)
528 fp = fopen(name, "w");
530 fatal(E_OPEN, name, strerror(errno));
531 /* This is in RACT format. */
532 for (i = 0; i < NCAPACITY; i++)
533 fprintf(fp, "%s %ld\n", p->name[i], p->number[i]*p->points[i]);
550 s = s ? realloc(s, n) : malloc(n);
558 VOID fatal(va_alist) va_dcl
560 VOID fatal(int errnum,...)
570 errnum = va_arg(ap, int);
572 va_start(ap, errnum);
574 do_error(errnum, ap);
580 VOID appl_error(va_alist) va_dcl
582 VOID appl_error(int errnum,...)
592 errnum = va_arg(ap, int);
594 va_start(ap, errnum);
596 do_error(errnum, ap);
601 VOID do_error(errnum, ap)
606 fprintf(stderr, "%s: ", prog);
608 assert(errnum < sizeof(errlist)/sizeof(errlist[0]));
609 text = catgets(catd, APP_SET, errnum, errlist[errnum]);
611 xvfprintf(stderr, text, ap);
619 c-continued-statement-offset: 5