169484Sbostic // -*- C++ -*-
269484Sbostic /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
369484Sbostic Written by James Clark (jjc@jclark.com)
469484Sbostic
569484Sbostic This file is part of groff.
669484Sbostic
769484Sbostic groff is free software; you can redistribute it and/or modify it under
869484Sbostic the terms of the GNU General Public License as published by the Free
969484Sbostic Software Foundation; either version 2, or (at your option) any later
1069484Sbostic version.
1169484Sbostic
1269484Sbostic groff is distributed in the hope that it will be useful, but WITHOUT ANY
1369484Sbostic WARRANTY; without even the implied warranty of MERCHANTABILITY or
1469484Sbostic FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1569484Sbostic for more details.
1669484Sbostic
1769484Sbostic You should have received a copy of the GNU General Public License along
1869484Sbostic with groff; see the file COPYING. If not, write to the Free Software
1969484Sbostic Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
2069484Sbostic
2169484Sbostic // A front end for groff.
2269484Sbostic
2369484Sbostic #include <stdio.h>
2469484Sbostic #include <string.h>
25*69501Sbostic #include <unistd.h>
2669484Sbostic #include <stdlib.h>
2769484Sbostic #include <signal.h>
2869484Sbostic #include <errno.h>
2969484Sbostic
3069484Sbostic #include "lib.h"
3169484Sbostic #include "assert.h"
3269484Sbostic #include "errarg.h"
3369484Sbostic #include "error.h"
3469484Sbostic #include "stringclass.h"
3569484Sbostic #include "cset.h"
3669484Sbostic #include "font.h"
3769484Sbostic #include "device.h"
3869484Sbostic #include "pipeline.h"
3969484Sbostic #include "defs.h"
4069484Sbostic
4169484Sbostic #define BSHELL "/bin/sh"
4269484Sbostic #define GXDITVIEW "gxditview"
4369484Sbostic
4469484Sbostic // troff will be passed an argument of -rXREG=1 if the -X option is
4569484Sbostic // specified
4669484Sbostic #define XREG ".X"
4769484Sbostic
4869484Sbostic #ifndef STDLIB_H_DECLARES_PUTENV
4969484Sbostic extern "C" {
5069484Sbostic int putenv(const char *);
5169484Sbostic }
5269484Sbostic #endif /* not STDLIB_H_DECLARES_PUTENV */
5369484Sbostic
5469484Sbostic const char *strsignal(int);
5569484Sbostic
5669484Sbostic const int SOELIM_INDEX = 0;
5769484Sbostic const int REFER_INDEX = SOELIM_INDEX + 1;
5869484Sbostic const int PIC_INDEX = REFER_INDEX + 1;
5969484Sbostic const int TBL_INDEX = PIC_INDEX + 1;
6069484Sbostic const int EQN_INDEX = TBL_INDEX + 1;
6169484Sbostic const int TROFF_INDEX = EQN_INDEX + 1;
6269484Sbostic const int POST_INDEX = TROFF_INDEX + 1;
6369484Sbostic const int SPOOL_INDEX = POST_INDEX + 1;
6469484Sbostic
6569484Sbostic const int NCOMMANDS = SPOOL_INDEX + 1;
6669484Sbostic
6769484Sbostic class possible_command {
6869484Sbostic char *name;
6969484Sbostic string args;
7069484Sbostic char **argv;
7169484Sbostic
7269484Sbostic void build_argv();
7369484Sbostic public:
7469484Sbostic possible_command();
7569484Sbostic ~possible_command();
7669484Sbostic void set_name(const char *);
7769484Sbostic void set_name(const char *, const char *);
7869484Sbostic const char *get_name();
7969484Sbostic void append_arg(const char *, const char * = 0);
8069484Sbostic void clear_args();
8169484Sbostic char **get_argv();
8269484Sbostic void print(int is_last, FILE *fp);
8369484Sbostic };
8469484Sbostic
8569484Sbostic int lflag = 0;
8669484Sbostic char *spooler = 0;
8769484Sbostic char *driver = 0;
8869484Sbostic
8969484Sbostic possible_command commands[NCOMMANDS];
9069484Sbostic
9169484Sbostic int run_commands();
9269484Sbostic void print_commands();
9369484Sbostic void append_arg_to_string(const char *arg, string &str);
9469484Sbostic void handle_unknown_desc_command(const char *command, const char *arg,
9569484Sbostic const char *filename, int lineno);
9669484Sbostic const char *basename(const char *);
9769484Sbostic
9869484Sbostic void usage();
9969484Sbostic void help();
10069484Sbostic
main(int argc,char ** argv)10169484Sbostic int main(int argc, char **argv)
10269484Sbostic {
10369484Sbostic program_name = argv[0];
10469484Sbostic static char stderr_buf[BUFSIZ];
10569484Sbostic setbuf(stderr, stderr_buf);
10669484Sbostic assert(NCOMMANDS <= MAX_COMMANDS);
10769484Sbostic string Pargs, Largs, Fargs;
10869484Sbostic int Vflag = 0;
10969484Sbostic int zflag = 0;
11069484Sbostic int iflag = 0;
11169484Sbostic int Xflag = 0;
11269484Sbostic int opt;
11369484Sbostic const char *command_prefix = getenv("GROFF_COMMAND_PREFIX");
11469484Sbostic if (!command_prefix)
11569484Sbostic command_prefix = PROG_PREFIX;
11669484Sbostic commands[TROFF_INDEX].set_name(command_prefix, "troff");
11769484Sbostic while ((opt = getopt(argc, argv,
11869484Sbostic "itpeRszavVhblCENXZF:m:T:f:w:W:M:d:r:n:o:P:L:"))
11969484Sbostic != EOF) {
12069484Sbostic char buf[3];
12169484Sbostic buf[0] = '-';
12269484Sbostic buf[1] = opt;
12369484Sbostic buf[2] = '\0';
12469484Sbostic switch (opt) {
12569484Sbostic case 'i':
12669484Sbostic iflag = 1;
12769484Sbostic break;
12869484Sbostic case 't':
12969484Sbostic commands[TBL_INDEX].set_name(command_prefix, "tbl");
13069484Sbostic break;
13169484Sbostic case 'p':
13269484Sbostic commands[PIC_INDEX].set_name(command_prefix, "pic");
13369484Sbostic break;
13469484Sbostic case 'e':
13569484Sbostic commands[EQN_INDEX].set_name(command_prefix, "eqn");
13669484Sbostic break;
13769484Sbostic case 's':
13869484Sbostic commands[SOELIM_INDEX].set_name(command_prefix, "soelim");
13969484Sbostic break;
14069484Sbostic case 'R':
14169484Sbostic commands[REFER_INDEX].set_name(command_prefix, "refer");
14269484Sbostic break;
14369484Sbostic case 'z':
14469484Sbostic case 'a':
14569484Sbostic commands[TROFF_INDEX].append_arg(buf);
14669484Sbostic // fall through
14769484Sbostic case 'Z':
14869484Sbostic zflag++;
14969484Sbostic break;
15069484Sbostic case 'l':
15169484Sbostic lflag++;
15269484Sbostic break;
15369484Sbostic case 'V':
15469484Sbostic Vflag++;
15569484Sbostic break;
15669484Sbostic case 'v':
15769484Sbostic case 'C':
15869484Sbostic commands[SOELIM_INDEX].append_arg(buf);
15969484Sbostic commands[PIC_INDEX].append_arg(buf);
16069484Sbostic commands[TBL_INDEX].append_arg(buf);
16169484Sbostic commands[EQN_INDEX].append_arg(buf);
16269484Sbostic commands[TROFF_INDEX].append_arg(buf);
16369484Sbostic break;
16469484Sbostic case 'N':
16569484Sbostic commands[EQN_INDEX].append_arg(buf);
16669484Sbostic break;
16769484Sbostic case 'h':
16869484Sbostic help();
16969484Sbostic break;
17069484Sbostic case 'E':
17169484Sbostic case 'b':
17269484Sbostic commands[TROFF_INDEX].append_arg(buf);
17369484Sbostic break;
17469484Sbostic case 'T':
17569484Sbostic if (strcmp(optarg, "Xps") == 0) {
17669484Sbostic warning("-TXps option is obsolete: use -X -Tps instead");
17769484Sbostic device = "ps";
17869484Sbostic Xflag++;
17969484Sbostic }
18069484Sbostic else
18169484Sbostic device = optarg;
18269484Sbostic break;
18369484Sbostic case 'F':
18469484Sbostic font::command_line_font_dir(optarg);
18569484Sbostic if (Fargs.length() > 0) {
18669484Sbostic Fargs += ':';
18769484Sbostic Fargs += optarg;
18869484Sbostic }
18969484Sbostic else
19069484Sbostic Fargs = optarg;
19169484Sbostic break;
19269484Sbostic case 'f':
19369484Sbostic case 'o':
19469484Sbostic case 'm':
19569484Sbostic case 'r':
19669484Sbostic case 'd':
19769484Sbostic case 'n':
19869484Sbostic case 'w':
19969484Sbostic case 'W':
20069484Sbostic commands[TROFF_INDEX].append_arg(buf, optarg);
20169484Sbostic break;
20269484Sbostic case 'M':
20369484Sbostic commands[EQN_INDEX].append_arg(buf, optarg);
20469484Sbostic commands[TROFF_INDEX].append_arg(buf, optarg);
20569484Sbostic break;
20669484Sbostic case 'P':
20769484Sbostic Pargs += optarg;
20869484Sbostic Pargs += '\0';
20969484Sbostic break;
21069484Sbostic case 'L':
21169484Sbostic append_arg_to_string(optarg, Largs);
21269484Sbostic break;
21369484Sbostic case 'X':
21469484Sbostic Xflag++;
21569484Sbostic break;
21669484Sbostic case '?':
21769484Sbostic usage();
21869484Sbostic break;
21969484Sbostic default:
22069484Sbostic assert(0);
22169484Sbostic break;
22269484Sbostic }
22369484Sbostic }
22469484Sbostic font::set_unknown_desc_command_handler(handle_unknown_desc_command);
22569484Sbostic if (!font::load_desc())
22669484Sbostic fatal("invalid device `%1'", device);
22769484Sbostic if (!driver)
22869484Sbostic fatal("no `postpro' command in DESC file for device `%1'", device);
22969484Sbostic const char *real_driver = 0;
23069484Sbostic if (Xflag) {
23169484Sbostic real_driver = driver;
23269484Sbostic driver = GXDITVIEW;
23369484Sbostic commands[TROFF_INDEX].append_arg("-r" XREG "=", "1");
23469484Sbostic }
23569484Sbostic if (driver)
23669484Sbostic commands[POST_INDEX].set_name(driver);
23769484Sbostic int gxditview_flag = driver && strcmp(basename(driver), GXDITVIEW) == 0;
23869484Sbostic if (gxditview_flag && argc - optind == 1) {
23969484Sbostic commands[POST_INDEX].append_arg("-title");
24069484Sbostic commands[POST_INDEX].append_arg(argv[optind]);
24169484Sbostic commands[POST_INDEX].append_arg("-xrm");
24269484Sbostic commands[POST_INDEX].append_arg("*iconName:", argv[optind]);
24369484Sbostic string filename_string("|");
24469484Sbostic append_arg_to_string(argv[0], filename_string);
24569484Sbostic append_arg_to_string("-Z", filename_string);
24669484Sbostic for (int i = 1; i < argc; i++)
24769484Sbostic append_arg_to_string(argv[i], filename_string);
24869484Sbostic filename_string += '\0';
24969484Sbostic commands[POST_INDEX].append_arg("-filename");
25069484Sbostic commands[POST_INDEX].append_arg(filename_string.contents());
25169484Sbostic }
25269484Sbostic if (gxditview_flag && Xflag) {
25369484Sbostic string print_string(real_driver);
25469484Sbostic if (spooler) {
25569484Sbostic print_string += " | ";
25669484Sbostic print_string += spooler;
25769484Sbostic print_string += Largs;
25869484Sbostic }
25969484Sbostic print_string += '\0';
26069484Sbostic commands[POST_INDEX].append_arg("-printCommand");
26169484Sbostic commands[POST_INDEX].append_arg(print_string.contents());
26269484Sbostic }
26369484Sbostic const char *p = Pargs.contents();
26469484Sbostic const char *end = p + Pargs.length();
26569484Sbostic while (p < end) {
26669484Sbostic commands[POST_INDEX].append_arg(p);
26769484Sbostic p = strchr(p, '\0') + 1;
26869484Sbostic }
26969484Sbostic if (gxditview_flag)
27069484Sbostic commands[POST_INDEX].append_arg("-");
27169484Sbostic if (lflag && !Xflag && spooler) {
27269484Sbostic commands[SPOOL_INDEX].set_name(BSHELL);
27369484Sbostic commands[SPOOL_INDEX].append_arg("-c");
27469484Sbostic Largs += '\0';
27569484Sbostic Largs = spooler + Largs;
27669484Sbostic commands[SPOOL_INDEX].append_arg(Largs.contents());
27769484Sbostic }
27869484Sbostic if (zflag) {
27969484Sbostic commands[POST_INDEX].set_name(0);
28069484Sbostic commands[SPOOL_INDEX].set_name(0);
28169484Sbostic }
28269484Sbostic commands[TROFF_INDEX].append_arg("-T", device);
28369484Sbostic commands[EQN_INDEX].append_arg("-T", device);
28469484Sbostic
28569484Sbostic for (int first_index = 0; first_index < TROFF_INDEX; first_index++)
28669484Sbostic if (commands[first_index].get_name() != 0)
28769484Sbostic break;
28869484Sbostic if (optind < argc) {
28969484Sbostic if (argv[optind][0] == '-' && argv[optind][1] != '\0')
29069484Sbostic commands[first_index].append_arg("--");
29169484Sbostic for (int i = optind; i < argc; i++)
29269484Sbostic commands[first_index].append_arg(argv[i]);
29369484Sbostic if (iflag)
29469484Sbostic commands[first_index].append_arg("-");
29569484Sbostic }
29669484Sbostic if (Fargs.length() > 0) {
29769484Sbostic string e = "GROFF_FONT_PATH";
29869484Sbostic e += '=';
29969484Sbostic e += Fargs;
30069484Sbostic char *fontpath = getenv("GROFF_FONT_PATH");
30169484Sbostic if (fontpath && *fontpath) {
30269484Sbostic e += ':';
30369484Sbostic e += fontpath;
30469484Sbostic }
30569484Sbostic e += '\0';
30669484Sbostic if (putenv(strsave(e.contents())))
30769484Sbostic fatal("putenv failed");
30869484Sbostic }
30969484Sbostic if (Vflag) {
31069484Sbostic print_commands();
31169484Sbostic exit(0);
31269484Sbostic }
31369484Sbostic exit(run_commands());
31469484Sbostic }
31569484Sbostic
basename(const char * s)31669484Sbostic const char *basename(const char *s)
31769484Sbostic {
31869484Sbostic if (!s)
31969484Sbostic return 0;
32069484Sbostic const char *p = strrchr(s, '/');
32169484Sbostic return p ? p + 1 : s;
32269484Sbostic }
32369484Sbostic
handle_unknown_desc_command(const char * command,const char * arg,const char * filename,int lineno)32469484Sbostic void handle_unknown_desc_command(const char *command, const char *arg,
32569484Sbostic const char *filename, int lineno)
32669484Sbostic {
32769484Sbostic if (strcmp(command, "print") == 0) {
32869484Sbostic if (arg == 0)
32969484Sbostic error_with_file_and_line(filename, lineno,
33069484Sbostic "`print' command requires an argument");
33169484Sbostic else
33269484Sbostic spooler = strsave(arg);
33369484Sbostic }
33469484Sbostic if (strcmp(command, "postpro") == 0) {
33569484Sbostic if (arg == 0)
33669484Sbostic error_with_file_and_line(filename, lineno,
33769484Sbostic "`postpro' command requires an argument");
33869484Sbostic else {
33969484Sbostic for (const char *p = arg; *p; p++)
34069484Sbostic if (csspace(*p)) {
34169484Sbostic error_with_file_and_line(filename, lineno,
34269484Sbostic "invalid `postpro' argument `%1'"
34369484Sbostic ": program name required", arg);
34469484Sbostic return;
34569484Sbostic }
34669484Sbostic driver = strsave(arg);
34769484Sbostic }
34869484Sbostic }
34969484Sbostic }
35069484Sbostic
print_commands()35169484Sbostic void print_commands()
35269484Sbostic {
35369484Sbostic for (int last = SPOOL_INDEX; last >= 0; last--)
35469484Sbostic if (commands[last].get_name() != 0)
35569484Sbostic break;
35669484Sbostic for (int i = 0; i <= last; i++)
35769484Sbostic if (commands[i].get_name() != 0)
35869484Sbostic commands[i].print(i == last, stdout);
35969484Sbostic }
36069484Sbostic
36169484Sbostic // Run the commands. Return the code with which to exit.
36269484Sbostic
run_commands()36369484Sbostic int run_commands()
36469484Sbostic {
36569484Sbostic char **v[NCOMMANDS];
36669484Sbostic int j = 0;
36769484Sbostic for (int i = 0; i < NCOMMANDS; i++)
36869484Sbostic if (commands[i].get_name() != 0)
36969484Sbostic v[j++] = commands[i].get_argv();
37069484Sbostic return run_pipeline(j, v);
37169484Sbostic }
37269484Sbostic
possible_command()37369484Sbostic possible_command::possible_command()
37469484Sbostic : name(0), argv(0)
37569484Sbostic {
37669484Sbostic }
37769484Sbostic
~possible_command()37869484Sbostic possible_command::~possible_command()
37969484Sbostic {
38069484Sbostic a_delete name;
38169484Sbostic a_delete argv;
38269484Sbostic }
38369484Sbostic
set_name(const char * s)38469484Sbostic void possible_command::set_name(const char *s)
38569484Sbostic {
38669484Sbostic a_delete name;
38769484Sbostic name = strsave(s);
38869484Sbostic }
38969484Sbostic
set_name(const char * s1,const char * s2)39069484Sbostic void possible_command::set_name(const char *s1, const char *s2)
39169484Sbostic {
39269484Sbostic a_delete name;
39369484Sbostic name = new char[strlen(s1) + strlen(s2) + 1];
39469484Sbostic strcpy(name, s1);
39569484Sbostic strcat(name, s2);
39669484Sbostic }
39769484Sbostic
get_name()39869484Sbostic const char *possible_command::get_name()
39969484Sbostic {
40069484Sbostic return name;
40169484Sbostic }
40269484Sbostic
clear_args()40369484Sbostic void possible_command::clear_args()
40469484Sbostic {
40569484Sbostic args.clear();
40669484Sbostic }
40769484Sbostic
append_arg(const char * s,const char * t)40869484Sbostic void possible_command::append_arg(const char *s, const char *t)
40969484Sbostic {
41069484Sbostic args += s;
41169484Sbostic if (t)
41269484Sbostic args += t;
41369484Sbostic args += '\0';
41469484Sbostic }
41569484Sbostic
build_argv()41669484Sbostic void possible_command::build_argv()
41769484Sbostic {
41869484Sbostic if (argv)
41969484Sbostic return;
42069484Sbostic // Count the number of arguments.
42169484Sbostic int len = args.length();
42269484Sbostic int argc = 1;
42369484Sbostic char *p = 0;
42469484Sbostic if (len > 0) {
42569484Sbostic p = &args[0];
42669484Sbostic for (int i = 0; i < len; i++)
42769484Sbostic if (p[i] == '\0')
42869484Sbostic argc++;
42969484Sbostic }
43069484Sbostic // Build an argument vector.
43169484Sbostic argv = new char *[argc + 1];
43269484Sbostic argv[0] = name;
43369484Sbostic for (int i = 1; i < argc; i++) {
43469484Sbostic argv[i] = p;
43569484Sbostic p = strchr(p, '\0') + 1;
43669484Sbostic }
43769484Sbostic argv[argc] = 0;
43869484Sbostic }
43969484Sbostic
print(int is_last,FILE * fp)44069484Sbostic void possible_command::print(int is_last, FILE *fp)
44169484Sbostic {
44269484Sbostic build_argv();
44369484Sbostic if (argv[0] != 0 && strcmp(argv[0], BSHELL) == 0
44469484Sbostic && argv[1] != 0 && strcmp(argv[1], "-c") == 0
44569484Sbostic && argv[2] != 0 && argv[3] == 0)
44669484Sbostic fputs(argv[2], fp);
44769484Sbostic else {
44869484Sbostic fputs(argv[0], fp);
44969484Sbostic string str;
45069484Sbostic for (int i = 1; argv[i] != 0; i++) {
45169484Sbostic str.clear();
45269484Sbostic append_arg_to_string(argv[i], str);
45369484Sbostic put_string(str, fp);
45469484Sbostic }
45569484Sbostic }
45669484Sbostic if (is_last)
45769484Sbostic putc('\n', fp);
45869484Sbostic else
45969484Sbostic fputs(" | ", fp);
46069484Sbostic }
46169484Sbostic
append_arg_to_string(const char * arg,string & str)46269484Sbostic void append_arg_to_string(const char *arg, string &str)
46369484Sbostic {
46469484Sbostic str += ' ';
46569484Sbostic int needs_quoting = 0;
46669484Sbostic int contains_single_quote = 0;
46769484Sbostic for (const char *p = arg; *p != '\0'; p++)
46869484Sbostic switch (*p) {
46969484Sbostic case ';':
47069484Sbostic case '&':
47169484Sbostic case '(':
47269484Sbostic case ')':
47369484Sbostic case '|':
47469484Sbostic case '^':
47569484Sbostic case '<':
47669484Sbostic case '>':
47769484Sbostic case '\n':
47869484Sbostic case ' ':
47969484Sbostic case '\t':
48069484Sbostic case '\\':
48169484Sbostic case '"':
48269484Sbostic case '$':
48369484Sbostic case '?':
48469484Sbostic case '*':
48569484Sbostic needs_quoting = 1;
48669484Sbostic break;
48769484Sbostic case '\'':
48869484Sbostic contains_single_quote = 1;
48969484Sbostic break;
49069484Sbostic }
49169484Sbostic if (contains_single_quote || arg[0] == '\0') {
49269484Sbostic str += '"';
49369484Sbostic for (p = arg; *p != '\0'; p++)
49469484Sbostic switch (*p) {
49569484Sbostic case '"':
49669484Sbostic case '\\':
49769484Sbostic case '$':
49869484Sbostic str += '\\';
49969484Sbostic // fall through
50069484Sbostic default:
50169484Sbostic str += *p;
50269484Sbostic break;
50369484Sbostic }
50469484Sbostic str += '"';
50569484Sbostic }
50669484Sbostic else if (needs_quoting) {
50769484Sbostic str += '\'';
50869484Sbostic str += arg;
50969484Sbostic str += '\'';
51069484Sbostic }
51169484Sbostic else
51269484Sbostic str += arg;
51369484Sbostic }
51469484Sbostic
get_argv()51569484Sbostic char **possible_command::get_argv()
51669484Sbostic {
51769484Sbostic build_argv();
51869484Sbostic return argv;
51969484Sbostic }
52069484Sbostic
synopsis()52169484Sbostic void synopsis()
52269484Sbostic {
52369484Sbostic fprintf(stderr,
52469484Sbostic "usage: %s [-abehilpstvzCENRVXZ] [-Fdir] [-mname] [-Tdev] [-ffam] [-wname]\n"
52569484Sbostic " [-Wname] [ -Mdir] [-dcs] [-rcn] [-nnum] [-olist] [-Parg] [-Larg]\n"
52669484Sbostic " [files...]\n",
52769484Sbostic program_name);
52869484Sbostic }
52969484Sbostic
help()53069484Sbostic void help()
53169484Sbostic {
53269484Sbostic synopsis();
53369484Sbostic fputs("\n"
53469484Sbostic "-h\tprint this message\n"
53569484Sbostic "-t\tpreprocess with tbl\n"
53669484Sbostic "-p\tpreprocess with pic\n"
53769484Sbostic "-e\tpreprocess with eqn\n"
53869484Sbostic "-s\tpreprocess with soelim\n"
53969484Sbostic "-R\tpreprocess with refer\n"
54069484Sbostic "-Tdev\tuse device dev\n"
54169484Sbostic "-X\tuse X11 previewer rather than usual postprocessor\n"
54269484Sbostic "-mname\tread macros tmac.name\n"
54369484Sbostic "-dcs\tdefine a string c as s\n"
54469484Sbostic "-rcn\tdefine a number register c as n\n"
54569484Sbostic "-nnum\tnumber first page n\n"
54669484Sbostic "-olist\toutput only pages in list\n"
54769484Sbostic "-ffam\tuse fam as the default font family\n"
54869484Sbostic "-Fdir\tsearch directory dir for device directories\n"
54969484Sbostic "-Mdir\tsearch dir for macro files\n"
55069484Sbostic "-v\tprint version number\n"
55169484Sbostic "-z\tsuppress formatted output\n"
55269484Sbostic "-Z\tdon't postprocess\n"
55369484Sbostic "-a\tproduce ASCII description of output\n"
55469484Sbostic "-i\tread standard input after named input files\n"
55569484Sbostic "-wname\tenable warning name\n"
55669484Sbostic "-Wname\tinhibit warning name\n"
55769484Sbostic "-E\tinhibit all errors\n"
55869484Sbostic "-b\tprint backtraces with errors or warnings\n"
55969484Sbostic "-l\tspool the output\n"
56069484Sbostic "-C\tenable compatibility mode\n"
56169484Sbostic "-V\tprint commands on stdout instead of running them\n"
56269484Sbostic "-Parg\tpass arg to the postprocessor\n"
56369484Sbostic "-Larg\tpass arg to the spooler\n"
56469484Sbostic "-N\tdon't allow newlines within eqn delimiters\n"
56569484Sbostic "\n",
56669484Sbostic stderr);
56769484Sbostic exit(0);
56869484Sbostic }
56969484Sbostic
usage()57069484Sbostic void usage()
57169484Sbostic {
57269484Sbostic synopsis();
57369484Sbostic fprintf(stderr, "%s -h gives more help\n", program_name);
57469484Sbostic exit(1);
57569484Sbostic }
57669484Sbostic
57769484Sbostic extern "C" {
57869484Sbostic
c_error(const char * format,const char * arg1,const char * arg2,const char * arg3)57969484Sbostic void c_error(const char *format, const char *arg1, const char *arg2,
58069484Sbostic const char *arg3)
58169484Sbostic {
58269484Sbostic error(format, arg1, arg2, arg3);
58369484Sbostic }
58469484Sbostic
c_fatal(const char * format,const char * arg1,const char * arg2,const char * arg3)58569484Sbostic void c_fatal(const char *format, const char *arg1, const char *arg2,
58669484Sbostic const char *arg3)
58769484Sbostic {
58869484Sbostic fatal(format, arg1, arg2, arg3);
58969484Sbostic }
59069484Sbostic
59169484Sbostic }
592