#include "gsint.h"
#include "getopt.h"
static void open_output_file ();
static void close_output_file ();
static void handle_env_options ___P ((char *var));
static void handle_options ___P ((int argc, char *argv[]));
static void usage ();
static void version ();
char *program;
FILE *ofp = NULL;
void *printer_context;
char *version_string = NULL;
char *ps_version_string = NULL;
char *date_string = NULL;
struct tm run_tm;
struct tm mod_tm;
struct passwd *passwd;
char *enscript_library = LIBRARY;
char *libpath = NULL;
char *afm_path = NULL;
MediaEntry *media_names = NULL;
MediaEntry *media = NULL;
int bs = 8;
int total_pages = 0;
int num_truncated_lines = 0;
int num_missing_chars = 0;
int missing_chars[256] = {0};
int num_non_printable_chars = 0;
int non_printable_chars[256] = {0};
int d_page_w = 0;
int d_page_h = 0;
int d_header_w = 0;
int d_header_h = 0;
int d_footer_h = 0;
int d_output_w = 0;
int d_output_h = 0;
int d_output_x_margin = 5;
int d_output_y_margin = 2;
StringHashPtr res_fonts;
StringHashPtr download_fonts;
StringHashPtr pagedevice;
StringHashPtr statusdict;
StringHashPtr user_strings;
StringHashPtr afm_cache = NULL;
StringHashPtr afm_info_cache = NULL;
AFMHandle afm = NULL;
int num_columns = 1;
PageRange *page_ranges = NULL;
unsigned int file_align = 1;
char *page_header = NULL;
LineEndType line_end = LE_CHAR_WRAP;
int line_numbers = 0;
unsigned int start_line_number = 1;
char *printer = NULL;
int special_escapes = 0;
int escape_char = '\0';
int default_escape_char;
int highlight = 0;
char *hl_start_state = NULL;
char *Fname = "Courier";
FontPoint Fpt = {10.0, 10.0};
FontPoint default_Fpt;
char *default_Fname;
InputEncoding default_Fencoding;
int user_body_font_defined = 0;
double font_widths[256];
char font_ctype[256];
int font_is_fixed;
double font_bbox_lly;
char *HFname = "Courier-Bold";
FontPoint HFpt = {10.0, 10.0};
HeaderType header = HDR_SIMPLE;
char *fancy_header_name = NULL;
char *fancy_header_default = NULL;
static int no_job_header = 0;
unsigned int highlight_bars = 0;
double line_indent = 0.0;
char *line_indent_spec = "0";
char *input_filter = NULL;
int borders = 0;
int page_prefeed = 0;
unsigned int lines_per_page = (unsigned int) -1;
int mail = 0;
char *media_name = NULL;
int num_copies = 1;
int nl = -1;
char *output_file = OUTPUT_FILE_NONE;
int list_missing_characters = 0;
int quiet = 0;
int landscape = 0;
double baselineskip = 1.0;
char *title = "Enscript Output";
int title_given = 0;
int tabsize = 8;
double ul_gray = .8;
FontPoint ul_ptsize = {200.0, 200.0};
char *ul_font = "Times-Roman";
char *underlay = NULL;
char *ul_position = NULL;
double ul_x;
double ul_y;
double ul_angle;
unsigned int ul_style = UL_STYLE_OUTLINE;
char *ul_style_str = NULL;
int ul_position_p = 0;
int ul_angle_p = 0;
unsigned int nup = 1;
unsigned int nup_exp = 0;
unsigned int nup_rows = 1;
unsigned int nup_columns = 1;
int nup_landscape = 0;
unsigned int nup_width;
unsigned int nup_height;
double nup_scale;
int verbose = 0;
char *output_language = "PostScript";
int output_language_pass_through = 0;
Buffer *helper_options[256] = {0};
InputEncoding encoding = ENC_ISO_8859_1;
char *encoding_name = NULL;
int interpret_formfeed = 1;
int pass_through = 0;
int continuous_page_numbers = 0;
int extended_return_values = 0;
char *input_filter_stdin = "";
char *page_footer = NULL;
double horizontal_column_height = 283465.0;
int help_highlight = 0;
double highlight_bar_gray = .97;
int list_media = 0;
char *margins_spec = NULL;
char *mark_wrapped_lines_style_name = NULL;
MarkWrappedLinesStyle mark_wrapped_lines_style = MWLS_NONE;
char *npf_name = NULL;
NonPrintableFormat non_printable_format = NPF_OCTAL;
int nup_columnwise = 0;
unsigned int nup_xpad = 10;
unsigned int nup_ypad = 10;
char *page_label_format = NULL;
PageLabelFormat page_label;
unsigned int pslevel = 2;
char *printer_options = NULL;
int rotate_even_pages = 0;
int slicing = 0;
unsigned int slice = 1;
int swap_even_page_margins = 0;
int toc = 0;
FILE *toc_fp;
char *toc_fmt_string;
int accept_composites = 0;
int append_ctrl_D = 0;
int clean_7bit = 1;
FormFeedType formfeed_type = FORMFEED_COLUMN;
int generate_PageSize = 1;
char *no_job_header_switch = NULL;
char *output_first_line = NULL;
char *queue_param = NULL;
char *spooler_command = NULL;
char *states_binary = NULL;
int states_color = 0;
char *states_config_file = NULL;
char *states_highlight_style = NULL;
char *states_path = NULL;
double line_highlight_gray = 1.0;
double bggray = 1.0;
EncodingRegistry encodings[] =
{
{{"88591", "latin1", NULL}, ENC_ISO_8859_1, '\n', 8},
{{"88592", "latin2", NULL}, ENC_ISO_8859_2, '\n', 8},
{{"88593", "latin3", NULL}, ENC_ISO_8859_3, '\n', 8},
{{"88594", "latin4", NULL}, ENC_ISO_8859_4, '\n', 8},
{{"88595", "cyrillic", NULL}, ENC_ISO_8859_5, '\n', 8},
{{"88597", "greek", NULL}, ENC_ISO_8859_7, '\n', 8},
{{"88599", "latin5", NULL}, ENC_ISO_8859_9, '\n', 8},
{{"885910", "latin6", NULL}, ENC_ISO_8859_10, '\n', 8},
{{"ascii", NULL, NULL}, ENC_ASCII, '\n', 8},
{{"asciifise", "asciifi", "asciise"}, ENC_ASCII_FISE, '\n', 8},
{{"asciidkno", "asciidk", "asciino"}, ENC_ASCII_DKNO, '\n', 8},
{{"ibmpc", "pc", "dos"}, ENC_IBMPC, '\n', 8},
{{"mac", NULL, NULL}, ENC_MAC, '\r', 8},
{{"vms", NULL, NULL}, ENC_VMS, '\n', 8},
{{"hp8", NULL, NULL}, ENC_HP8, '\n', 8},
{{"koi8", NULL, NULL}, ENC_KOI8, '\n', 8},
{{"ps", "PS", NULL}, ENC_PS, '\n', 8},
{{"pslatin1", "ISOLatin1Encoding", NULL}, ENC_ISO_8859_1, '\n', 8},
{{NULL, NULL, NULL}, 0, 0, 0},
};
static struct option long_options[] =
{
{"columns", required_argument, 0, 0},
{"pages", required_argument, 0, 'a'},
{"file-align", required_argument, 0, 'A'},
{"header", required_argument, 0, 'b'},
{"no-header", no_argument, 0, 'B'},
{"truncate-lines", no_argument, 0, 'c'},
{"line-numbers", optional_argument, 0, 'C'},
{"printer", required_argument, 0, 'd'},
{"setpagedevice", required_argument, 0, 'D'},
{"escapes", optional_argument, 0, 'e'},
{"highlight", optional_argument, 0, 'E'},
{"font", required_argument, 0, 'f'},
{"header-font", required_argument, 0, 'F'},
{"print-anyway", no_argument, 0, 'g'},
{"fancy-header", optional_argument, 0, 'G'},
{"no-job-header", no_argument, 0, 'h'},
{"highlight-bars", optional_argument, 0, 'H'},
{"indent", required_argument, 0, 'i'},
{"filter", required_argument, 0, 'I'},
{"borders", no_argument, 0, 'j'},
{"page-prefeed", no_argument, 0, 'k'},
{"no-page-prefeed", no_argument, 0, 'K'},
{"lineprinter", no_argument, 0, 'l'},
{"lines-per-page", required_argument, 0, 'L'},
{"mail", no_argument, 0, 'm'},
{"media", required_argument, 0, 'M'},
{"copies", required_argument, 0, 'n'},
{"newline", required_argument, 0, 'N'},
{"output", required_argument, 0, 'p'},
{"missing-characters", no_argument, 0, 'O'},
{"quiet", no_argument, 0, 'q'},
{"silent", no_argument, 0, 'q'},
{"landscape", no_argument, 0, 'r'},
{"portrait", no_argument, 0, 'R'},
{"baselineskip", required_argument, 0, 's'},
{"statusdict", required_argument, 0, 'S'},
{"title", required_argument, 0, 't'},
{"tabsize", required_argument, 0, 'T'},
{"underlay", optional_argument, 0, 'u'},
{"nup", required_argument, 0, 'U'},
{"verbose", optional_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
{"language", required_argument, 0, 'w'},
{"option", required_argument, 0, 'W'},
{"encoding", required_argument, 0, 'X'},
{"no-formfeed", no_argument, 0, 'z'},
{"pass-through", no_argument, 0, 'Z'},
{"color", optional_argument, 0, 142},
{"continuous-page-numbers", no_argument, 0, 156},
{"download-font", required_argument, 0, 131},
{"extended-return-values", no_argument, 0, 154},
{"filter-stdin", required_argument, 0, 138},
{"footer", required_argument, 0, 155},
{"h-column-height", required_argument, 0, 148},
{"help", no_argument, 0, 135},
{"help-highlight", no_argument, 0, 141},
{"highlight-bar-gray", required_argument, 0, 136},
{"list-media", no_argument, &list_media, 1},
{"margins", required_argument, 0, 144},
{"mark-wrapped-lines", optional_argument, 0, 143},
{"non-printable-format", required_argument, 0, 134},
{"nup-columnwise", no_argument, 0, 152},
{"nup-xpad", required_argument, 0, 145},
{"nup-ypad", required_argument, 0, 146},
{"page-label-format", required_argument, 0, 130},
{"ps-level", required_argument, 0, 149},
{"printer-options", required_argument, 0, 139},
{"rotate-even-pages", no_argument, 0, 150},
{"slice", required_argument, 0, 140},
{"style", required_argument, 0, 151},
{"swap-even-page-margins", no_argument, 0, 153},
{"toc", no_argument, &toc, 1},
{"word-wrap", no_argument, 0, 147},
{"ul-angle", required_argument, 0, 132},
{"ul-font", required_argument, 0, 128},
{"ul-gray", required_argument, 0, 129},
{"ul-position", required_argument, 0, 133},
{"ul-style", required_argument, 0, 137},
{"pretty-print", optional_argument, 0, 'E'},
{"help-pretty-print", no_argument, 0, 141},
{NULL, 0, 0, 0},
};
int
main (int argc, char *argv[])
{
InputStream is;
time_t tim;
struct tm *tm;
int i, j, found;
unsigned int ui;
MediaEntry *mentry;
AFMError afm_error;
char *cp, *cp2;
int retval = 0;
Buffer buffer;
buffer_init (&buffer);
program = strrchr (argv[0], '/');
if (program == NULL)
program = argv[0];
else
program++;
argv[0] = program;
buffer_clear (&buffer);
buffer_append (&buffer, "GNU ");
buffer_append (&buffer, PACKAGE);
buffer_append (&buffer, " ");
buffer_append (&buffer, VERSION);
version_string = buffer_copy (&buffer);
ps_version_string = xstrdup (VERSION);
cp = strrchr (ps_version_string, '.');
*cp = ' ';
toc_fmt_string = _("$3v $-40N $3% pages $4L lines $E $C");
#if HAVE_SETLOCALE
#if HAVE_LC_MESSAGES
setlocale (LC_MESSAGES, "");
#endif
#endif
#if ENABLE_NLS
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
#endif
tim = time (NULL);
tm = localtime (&tim);
memcpy (&run_tm, tm, sizeof (*tm));
date_string = xstrdup (asctime (&run_tm));
i = strlen (date_string);
date_string[i - 1] = '\0';
passwd = getpwuid (getuid ());
if (passwd == NULL)
FATAL ((stderr, _("couldn't get passwd entry for uid=%d: %s"), getuid (),
strerror (errno)));
media_name = xstrdup ("A4");
encoding_name = xstrdup ("88591");
npf_name = xstrdup ("octal");
page_label_format = xstrdup ("short");
ul_style_str = xstrdup ("outline");
ul_position = xstrdup ("+0-0");
spooler_command = xstrdup ("lpr");
queue_param = xstrdup ("-P");
no_job_header_switch = xstrdup ("-h");
fancy_header_default = xstrdup ("enscript");
output_first_line = xstrdup ("%!PS-Adobe-3.0");
cp = getenv ("ENSCRIPT_LIBRARY");
if (cp)
enscript_library = cp;
cp = getenv ("HOME");
if (cp == NULL)
cp = passwd->pw_dir;
buffer_clear (&buffer);
buffer_append (&buffer, enscript_library);
buffer_append (&buffer, PATH_SEPARATOR_STR);
buffer_append (&buffer, cp);
buffer_append (&buffer, "/.enscript");
libpath = buffer_copy (&buffer);
states_binary = xstrdup ("states");
buffer_clear (&buffer);
buffer_append (&buffer, enscript_library);
buffer_append (&buffer, "/hl/enscript.st");
states_config_file = buffer_copy (&buffer);
states_highlight_style = xstrdup ("emacs");
buffer_clear (&buffer);
buffer_append (&buffer, cp);
buffer_append (&buffer, "/.enscript");
buffer_append (&buffer, PATH_SEPARATOR_STR);
buffer_append (&buffer, enscript_library);
buffer_append (&buffer, "/hl");
states_path = buffer_copy (&buffer);
res_fonts = strhash_init ();
download_fonts = strhash_init ();
pagedevice = strhash_init ();
statusdict = strhash_init ();
user_strings = strhash_init ();
#define CFG_FILE_NAME "enscript.cfg"
if (!read_config (SYSCONFDIR, CFG_FILE_NAME))
{
int saved_errno = errno;
if (!read_config (enscript_library, CFG_FILE_NAME))
{
buffer_clear (&buffer);
buffer_append (&buffer, enscript_library);
buffer_append (&buffer, "/../../etc");
if (!read_config (buffer_ptr (&buffer), CFG_FILE_NAME))
{
if (!read_config ("../lib", CFG_FILE_NAME)
&& !read_config ("../../lib", CFG_FILE_NAME))
{
ERROR ((stderr, _("couldn't read config file \"%s/%s\": %s"),
enscript_library, CFG_FILE_NAME,
strerror (saved_errno)));
ERROR ((stderr,
_("I did also try the following directories:")));
ERROR ((stderr, _("\t%s"), SYSCONFDIR));
ERROR ((stderr, _("\t%s"), enscript_library));
ERROR ((stderr, _("\t%s"), buffer_ptr (&buffer)));
ERROR ((stderr, _("\t../lib")));
ERROR ((stderr, _("\t../../lib")));
ERROR ((stderr,
_("This is probably an installation error. Please, try to rebuild:")));
ERROR ((stderr, _("\tmake distclean")));
ERROR ((stderr, _("\t./configure --prefix=PREFIX")));
ERROR ((stderr, _("\tmake")));
ERROR ((stderr, _("\tmake check")));
ERROR ((stderr, _("\tmake install")));
ERROR ((stderr,
_("or set the environment variable `ENSCRIPT_LIBRARY' to point to your")));
ERROR ((stderr,
_("library directory.")));
exit (1);
}
buffer_clear (&buffer);
buffer_append (&buffer, libpath);
buffer_append (&buffer, PATH_SEPARATOR_STR);
buffer_append (&buffer, "../lib");
buffer_append (&buffer, PATH_SEPARATOR_STR);
buffer_append (&buffer, "../../lib");
xfree (libpath);
libpath = buffer_copy (&buffer);
}
}
}
(void) read_config (SYSCONFDIR, "enscriptsite.cfg");
(void) read_config (passwd->pw_dir, ".enscriptrc");
handle_env_options ("ENSCRIPT");
handle_env_options ("GENSCRIPT");
handle_options (argc, argv);
default_escape_char = escape_char;
found = 0;
for (i = 0; !found && encodings[i].names[0]; i++)
for (j = 0; j < 3; j++)
if (encodings[i].names[j] != NULL && MATCH (encodings[i].names[j],
encoding_name))
{
encoding = encodings[i].encoding;
xfree (encoding_name);
encoding_name = xstrdup (encodings[i].names[0]);
if (nl < 0)
nl = encodings[i].nl;
bs = encodings[i].bs;
found = 1;
break;
}
if (!found)
FATAL ((stderr, _("unknown encoding: %s"), encoding_name));
if (!user_body_font_defined && landscape && num_columns > 1)
Fpt.w = Fpt.h = 7.0;
afm_cache = strhash_init ();
afm_info_cache = strhash_init ();
afm_error = afm_create (afm_path, verbose, &afm);
if (afm_error != AFM_SUCCESS)
{
char buf[256];
afm_error_to_string (afm_error, buf);
FATAL ((stderr, _("couldn't open AFM library: %s"), buf));
}
default_Fpt.w = Fpt.w;
default_Fpt.h = Fpt.h;
default_Fname = Fname;
default_Fencoding = encoding;
strhash_put (res_fonts, Fname, strlen (Fname) + 1, NULL, NULL);
strhash_put (res_fonts, HFname, strlen (HFname) + 1, NULL, NULL);
strhash_put (download_fonts, Fname, strlen (Fname) + 1, NULL, NULL);
strhash_put (download_fonts, HFname, strlen (HFname) + 1, NULL, NULL);
read_font_info ();
line_indent = parse_float (line_indent_spec, 1, 1);
if (list_media)
{
printf (_("known media:\n\
name width\theight\tllx\tlly\turx\tury\n\
------------------------------------------------------------\n"));
for (mentry = media_names; mentry; mentry = mentry->next)
printf ("%-16s %d\t%d\t%d\t%d\t%d\t%d\n",
mentry->name, mentry->w, mentry->h,
mentry->llx, mentry->lly, mentry->urx, mentry->ury);
exit (0);
}
for (mentry = media_names; mentry; mentry = mentry->next)
if (strcmp (media_name, mentry->name) == 0)
{
media = mentry;
break;
}
if (media == NULL)
FATAL ((stderr, _("do not know anything about media \"%s\""), media_name));
if (margins_spec)
{
for (i = 0; i < 4; i++)
{
if (*margins_spec == '\0')
break;
if (*margins_spec == ':')
{
margins_spec++;
continue;
}
j = atoi (margins_spec);
for (; *margins_spec != ':' && *margins_spec != '\0'; margins_spec++)
;
if (*margins_spec == ':')
margins_spec++;
switch (i)
{
case 0:
media->llx = j;
break;
case 1:
media->urx = media->w - j;
break;
case 2:
media->ury = media->h - j;
break;
case 3:
media->lly = j;
break;
}
}
MESSAGE (1,
(stderr,
_("set new marginals for media `%s' (%dx%d): llx=%d, lly=%d, urx=%d, ury=%d\n"),
media->name, media->w, media->h, media->llx, media->lly,
media->urx, media->ury));
}
if (MATCH (page_label_format, "short"))
page_label = LABEL_SHORT;
else if (MATCH (page_label_format, "long"))
page_label = LABEL_LONG;
else
FATAL ((stderr, _("illegal page label format \"%s\""), page_label_format));
if (MATCH (npf_name, "space"))
non_printable_format = NPF_SPACE;
else if (MATCH (npf_name, "questionmark"))
non_printable_format = NPF_QUESTIONMARK;
else if (MATCH (npf_name, "caret"))
non_printable_format = NPF_CARET;
else if (MATCH (npf_name, "octal"))
non_printable_format = NPF_OCTAL;
else
FATAL ((stderr, _("illegal non-printable format \"%s\""), npf_name));
if (mark_wrapped_lines_style_name)
{
if (MATCH (mark_wrapped_lines_style_name, "none"))
mark_wrapped_lines_style = MWLS_NONE;
else if (MATCH (mark_wrapped_lines_style_name, "plus"))
mark_wrapped_lines_style = MWLS_PLUS;
else if (MATCH (mark_wrapped_lines_style_name, "box"))
mark_wrapped_lines_style = MWLS_BOX;
else if (MATCH (mark_wrapped_lines_style_name, "arrow"))
mark_wrapped_lines_style = MWLS_ARROW;
else
FATAL ((stderr, _("illegal style for wrapped line marker: \"%s\""),
mark_wrapped_lines_style_name));
}
for (i = 0; ; i++)
{
ui = nup >> i;
if (ui == 0)
FATAL ((stderr, _("illegal N-up argument: %d"), nup));
if (ui & 0x1)
{
if (ui != 1)
FATAL ((stderr, _("N-up argument must be power of 2: %d"), nup));
nup_exp = i;
break;
}
}
nup_rows = nup_exp / 2 * 2;
if (nup_rows == 0)
nup_rows = 1;
nup_columns = (nup_exp + 1) / 2 * 2;
if (nup_columns == 0)
nup_columns = 1;
nup_landscape = nup_exp & 0x1;
if (landscape)
{
d_page_w = media->ury - media->lly;
d_page_h = media->urx - media->llx;
}
else
{
d_page_w = media->urx - media->llx;
d_page_h = media->ury - media->lly;
}
if (nup_landscape)
{
nup_width = media->ury - media->lly;
nup_height = media->urx - media->llx;
}
else
{
nup_width = media->urx - media->llx;
nup_height = media->ury - media->lly;
}
{
double w, h;
w = ((double) nup_width - (nup_columns - 1) * nup_xpad) / nup_columns;
h = ((double) nup_height - (nup_rows - 1) * nup_ypad) / nup_rows;
nup_width = w;
nup_height = h;
w = w / (media->urx - media->llx);
h = h / (media->ury - media->lly);
nup_scale = w < h ? w : h;
}
if (underlay != NULL)
{
strhash_put (res_fonts, ul_font, strlen (ul_font) + 1, NULL, NULL);
underlay = escape_string (underlay);
}
ul_x = strtod (ul_position, &cp);
if (cp == ul_position)
{
malformed_position:
FATAL ((stderr, _("malformed underlay position: %s"), ul_position));
}
if (ul_position[0] == '-')
ul_x += d_page_w;
ul_y = strtod (cp, &cp2);
if (cp2 == cp)
goto malformed_position;
if (cp[0] == '-')
ul_y += d_page_h;
if (!ul_angle_p)
ul_angle = (atan2 (-d_page_h, d_page_w) / 3.14159265 * 180);
if (strcmp (ul_style_str, "outline") == 0)
ul_style = UL_STYLE_OUTLINE;
else if (strcmp (ul_style_str, "filled") == 0)
ul_style = UL_STYLE_FILLED;
else
FATAL ((stderr, _("illegal underlay style: %s"), ul_style_str));
d_header_w = d_page_w;
switch (header)
{
case HDR_NONE:
d_header_h = 0;
break;
case HDR_SIMPLE:
d_header_h = HFpt.h * 1.5;
break;
case HDR_FANCY:
d_header_h = 36;
break;
}
if (help_highlight)
{
printf (_("Highlighting is supported for the following languages and file formats:\n\n"));
fflush (stdout);
buffer_clear (&buffer);
buffer_append (&buffer, states_binary);
buffer_append (&buffer, " -f \"");
buffer_append (&buffer, states_config_file);
buffer_append (&buffer, "\" -p \"");
buffer_append (&buffer, states_path);
buffer_append (&buffer, "\" -s describe_languages ");
buffer_append (&buffer, enscript_library);
buffer_append (&buffer, "/hl/*.st");
system (buffer_ptr (&buffer));
exit (0);
}
if (output_language_pass_through)
{
char *start_state;
Buffer cmd;
char intbuf[256];
if (hl_start_state)
start_state = hl_start_state;
else if (highlight)
start_state = NULL;
else
start_state = "passthrough";
buffer_init (&cmd);
buffer_append (&cmd, states_binary);
buffer_append (&cmd, " -f \"");
buffer_append (&cmd, states_config_file);
buffer_append (&cmd, "\" -p \"");
buffer_append (&cmd, states_path);
buffer_append (&cmd, "\" ");
if (verbose > 0)
buffer_append (&cmd, "-v ");
if (start_state)
{
buffer_append (&cmd, "-s");
buffer_append (&cmd, start_state);
buffer_append (&cmd, " ");
}
buffer_append (&cmd, "-Dcolor=");
buffer_append (&cmd, states_color ? "1" : "0");
buffer_append (&cmd, " ");
buffer_append (&cmd, "-Dstyle=");
buffer_append (&cmd, states_highlight_style);
buffer_append (&cmd, " ");
buffer_append (&cmd, "-Dlanguage=");
buffer_append (&cmd, output_language);
buffer_append (&cmd, " ");
buffer_append (&cmd, "-Dnum_input_files=");
sprintf (intbuf, "%d", optind == argc ? 1 : argc - optind);
buffer_append (&cmd, intbuf);
buffer_append (&cmd, " ");
buffer_append (&cmd, "-Ddocument_title=\'");
if ((cp = shell_escape (title)) != NULL)
{
buffer_append (&cmd, cp);
free (cp);
}
buffer_append (&cmd, "\' ");
buffer_append (&cmd, "-Dtoc=");
buffer_append (&cmd, toc ? "1" : "0");
if (helper_options['s'])
{
Buffer *opts = helper_options['s'];
buffer_append (&cmd, " ");
buffer_append_len (&cmd, buffer_ptr (opts), buffer_len (opts));
}
for (i = optind; i < argc; i++)
{
char *cp;
if ((cp = shell_escape (argv[i])) != NULL)
{
buffer_append (&cmd, " \'");
buffer_append (&cmd, cp);
buffer_append (&cmd, "\'");
free (cp);
}
}
if (is_open (&is, stdin, NULL, buffer_ptr (&cmd)))
{
open_output_file ();
process_file ("unused", &is, 0);
is_close (&is);
}
buffer_uninit (&cmd);
}
else
{
if (highlight)
{
char fbuf[256];
buffer_clear (&buffer);
buffer_append (&buffer, states_binary);
buffer_append (&buffer, " -f \"");
buffer_append (&buffer, states_config_file);
buffer_append (&buffer, "\" -p \"");
buffer_append (&buffer, states_path);
buffer_append (&buffer, "\"");
if (verbose > 0)
buffer_append (&buffer, " -v");
if (hl_start_state)
{
buffer_append (&buffer, " -s ");
buffer_append (&buffer, hl_start_state);
}
buffer_append (&buffer, " -Dcolor=");
buffer_append (&buffer, states_color ? "1" : "0");
buffer_append (&buffer, " -Dstyle=");
buffer_append (&buffer, states_highlight_style);
buffer_append (&buffer, " -Dfont_spec=");
buffer_append (&buffer, Fname);
sprintf (fbuf, "@%g/%g", Fpt.w, Fpt.h);
buffer_append (&buffer, fbuf);
if (helper_options['s'])
{
Buffer *opts = helper_options['s'];
buffer_append (&buffer, " ");
buffer_append_len (&buffer,
buffer_ptr (opts), buffer_len (opts));
}
buffer_append (&buffer, " \'%s\'");
input_filter = buffer_copy (&buffer);
input_filter_stdin = "-";
}
if (toc)
{
toc_fp = tmpfile ();
if (toc_fp == NULL)
FATAL ((stderr, _("couldn't create temporary toc file: %s"),
strerror (errno)));
}
if (optind == argc)
{
memcpy (&mod_tm, &run_tm, sizeof (run_tm));
if (is_open (&is, stdin, NULL, input_filter))
{
open_output_file ();
process_file (title_given ? title : "", &is, 0);
is_close (&is);
}
}
else
{
for (; optind < argc; optind++)
{
if (is_open (&is, NULL, argv[optind], input_filter))
{
struct stat stat_st;
if (stat (argv[optind], &stat_st) == 0)
{
tim = stat_st.st_mtime;
tm = localtime (&tim);
memcpy (&mod_tm, tm, sizeof (*tm));
open_output_file ();
process_file (argv[optind], &is, 0);
}
else
ERROR ((stderr, _("couldn't stat input file \"%s\": %s"),
argv[optind],
strerror (errno)));
is_close (&is);
}
}
}
if (toc)
{
toc = 0;
special_escapes = 1;
line_numbers = 0;
if (fseek (toc_fp, 0, SEEK_SET) != 0)
FATAL ((stderr, _("couldn't rewind toc file: %s"),
strerror (errno)));
memcpy (&mod_tm, &run_tm, sizeof (run_tm));
if (is_open (&is, toc_fp, NULL, NULL))
{
process_file (_("Table of Contents"), &is, 1);
is_close (&is);
}
fclose (toc_fp);
}
dump_ps_trailer ();
if (ofp != NULL && append_ctrl_D)
fprintf (ofp, "\004\n");
}
close_output_file ();
if (ofp == NULL)
{
MESSAGE (0, (stderr, _("no output generated\n")));
}
else if (output_language_pass_through)
{
if (output_file == OUTPUT_FILE_NONE)
MESSAGE (0, (stderr, _("output sent to %s\n"),
printer ? printer : _("printer")));
else
MESSAGE (0, (stderr, _("output left in %s\n"),
output_file == OUTPUT_FILE_STDOUT ? "-" : output_file));
}
else
{
unsigned int real_total_pages;
if (nup > 1)
{
if (total_pages > 0)
real_total_pages = (total_pages - 1) / nup + 1;
else
real_total_pages = 0;
}
else
real_total_pages = total_pages;
MESSAGE (0, (stderr, _("[ %d pages * %d copy ]"), real_total_pages,
num_copies));
if (output_file == OUTPUT_FILE_NONE)
MESSAGE (0, (stderr, _(" sent to %s\n"),
printer ? printer : _("printer")));
else
MESSAGE (0, (stderr, _(" left in %s\n"),
output_file == OUTPUT_FILE_STDOUT ? "-" : output_file));
if (num_truncated_lines)
{
retval |= 2;
MESSAGE (0, (stderr, _("%d lines were %s\n"), num_truncated_lines,
line_end == LE_TRUNCATE
? _("truncated") : _("wrapped")));
}
if (num_missing_chars)
{
retval |= 4;
MESSAGE (0, (stderr, _("%d characters were missing\n"),
num_missing_chars));
if (list_missing_characters)
{
MESSAGE (0, (stderr, _("missing character codes (decimal):\n")));
do_list_missing_characters (missing_chars);
}
}
if (num_non_printable_chars)
{
retval |= 8;
MESSAGE (0, (stderr, _("%d non-printable characters\n"),
num_non_printable_chars));
if (list_missing_characters)
{
MESSAGE (0, (stderr,
_("non-printable character codes (decimal):\n")));
do_list_missing_characters (non_printable_chars);
}
}
}
buffer_uninit (&buffer);
if (!extended_return_values)
retval = 0;
return retval;
}
static void
open_output_file ()
{
if (ofp)
return;
if (output_file == OUTPUT_FILE_NONE)
{
char spooler_options[512];
spooler_options[0] = '\0';
if (mail)
strcat (spooler_options, "-m ");
if (no_job_header)
{
strcat (spooler_options, no_job_header_switch);
strcat (spooler_options, " ");
}
if (printer_options)
strcat (spooler_options, printer_options);
ofp = printer_open (spooler_command, spooler_options, queue_param,
printer, &printer_context);
if (ofp == NULL)
FATAL ((stderr, _("couldn't open printer `%s': %s"), printer,
strerror (errno)));
}
else if (output_file == OUTPUT_FILE_STDOUT)
ofp = stdout;
else
{
ofp = fopen (output_file, "w");
if (ofp == NULL)
FATAL ((stderr, _("couldn't create output file \"%s\": %s"),
output_file, strerror (errno)));
}
}
static void
close_output_file ()
{
if (ofp == NULL)
return;
if (output_file == OUTPUT_FILE_NONE)
printer_close (printer_context);
else if (output_file != OUTPUT_FILE_STDOUT)
if (fclose (ofp))
FATAL ((stderr, _("couldn't close output file \"%s\": %s"),
output_file, strerror (errno)));
}
static void
handle_env_options (char *var)
{
int argc;
char **argv;
char *string;
char *str;
int i;
string = getenv (var);
if (string == NULL)
return;
MESSAGE (2, (stderr, "handle_env_options(): %s=\"%s\"\n", var, string));
str = xstrdup (string);
argc = (strlen (str) + 1) / 2 + 2;
argv = xcalloc (argc, sizeof (char *));
argc = 0;
argv[argc++] = program;
i = 0;
while (str[i])
{
for (; str[i] && isspace (str[i]); i++)
;
if (!str[i])
break;
if (str[i] == '"' || str[i] == '\'')
{
int endch = str[i++];
argv[argc++] = str + i;
for (; str[i] && str[i] != endch; i++)
;
if (!str[i])
FATAL ((stderr, _("syntax error in option string %s=\"%s\":\n\
missing end of quotation: %c"), var, string, endch));
str[i++] = '\0';
}
else
{
argv[argc++] = str + i;
for (; str[i] && !isspace (str[i]); i++)
;
if (str[i])
str[i++] = '\0';
}
}
argv[argc] = NULL;
MESSAGE (2, (stderr, "found following options (argc=%d):\n", argc));
for (i = 0; i < argc; i++)
MESSAGE (2, (stderr, "%3d = \"%s\"\n", i, argv[i]));
handle_options (argc, argv);
if (optind != argc)
{
MESSAGE (0,
(stderr,
_("warning: didn't process following options from \
environment variable %s:\n"),
var));
for (; optind < argc; optind++)
MESSAGE (0, (stderr, _(" option %d = \"%s\"\n"), optind,
argv[optind]));
}
xfree (argv);
}
static void
handle_options (int argc, char *argv[])
{
int c;
PageRange *prange;
optind = 0;
while (1)
{
int option_index = 0;
const char *cp;
int i;
c = getopt_long (argc, argv,
"#:123456789a:A:b:BcC::d:D:e::E::f:F:gGhH::i:I:jJ:kKlL:mM:n:N:o:Op:P:qrRs:S:t:T:u::U:vVW:X:zZ",
long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 0:
cp = long_options[option_index].name;
if (strcmp (cp, "columns") == 0)
{
num_columns = atoi (optarg);
if (num_columns < 1)
FATAL ((stderr,
_("number of columns must be larger than zero")));
}
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
num_columns = c - '0';
break;
case 'a':
prange = (PageRange *) xcalloc (1, sizeof (PageRange));
if (strcmp (optarg, "odd") == 0)
prange->odd = 1;
else if (strcmp (optarg, "even") == 0)
prange->even = 1;
else
{
cp = strchr (optarg, '-');
if (cp)
{
if (optarg[0] == '-')
prange->end = atoi (optarg + 1);
else if (cp[1] == '\0')
{
prange->start = atoi (optarg);
prange->end = (unsigned int) -1;
}
else
{
prange->start = atoi (optarg);
prange->end = atoi (cp + 1);
}
}
else
prange->start = prange->end = atoi (optarg);
}
prange->next = page_ranges;
page_ranges = prange;
break;
case 'A':
file_align = atoi (optarg);
if (file_align == 0)
FATAL ((stderr, _("file alignment must be larger than zero")));
break;
case 'b':
page_header = optarg;
break;
case 'B':
header = HDR_NONE;
break;
case 'c':
line_end = LE_TRUNCATE;
break;
case 'C':
line_numbers = 1;
if (optarg)
start_line_number = atoi (optarg);
break;
case 'd':
case 'P':
xfree (printer);
printer = xstrdup (optarg);
output_file = OUTPUT_FILE_NONE;
break;
case 'D':
parse_key_value_pair (pagedevice, optarg);
break;
case 'e':
special_escapes = 1;
if (optarg)
{
if (isdigit (optarg[0]))
escape_char = (int) strtoul (optarg, NULL, 0);
else
escape_char = ((unsigned char *) optarg)[0];
}
break;
case 'E':
highlight = 1;
special_escapes = 1;
escape_char = '\0';
hl_start_state = optarg;
break;
case 'f':
if (!parse_font_spec (optarg, &Fname, &Fpt, NULL))
FATAL ((stderr, _("malformed font spec: %s"), optarg));
user_body_font_defined = 1;
break;
case 'F':
if (!parse_font_spec (optarg, &HFname, &HFpt, NULL))
FATAL ((stderr, _("malformed font spec: %s"), optarg));
break;
case 'g':
break;
case 'G':
header = HDR_FANCY;
if (optarg)
fancy_header_name = optarg;
else
fancy_header_name = fancy_header_default;
if (!file_existsp (fancy_header_name, ".hdr"))
FATAL ((stderr,
_("couldn't find header definition file \"%s.hdr\""),
fancy_header_name));
break;
case 'h':
no_job_header = 1;
break;
case 'H':
if (optarg)
highlight_bars = atoi (optarg);
else
highlight_bars = 2;
break;
case 'i':
line_indent_spec = optarg;
break;
case 'I':
input_filter = optarg;
break;
case 'j':
borders = 1;
break;
case 'k':
page_prefeed = 1;
break;
case 'K':
page_prefeed = 0;
break;
case 'l':
lines_per_page = 66;
header = HDR_NONE;
break;
case 'L':
lines_per_page = atoi (optarg);
if (lines_per_page <= 0)
FATAL ((stderr,
_("must print at least one line per each page: %s"),
argv[optind]));
break;
case 'm':
mail = 1;
break;
case 'M':
media_name = xstrdup (optarg);
break;
case 'n':
case '#':
num_copies = atoi (optarg);
break;
case 'N':
if (!(optarg[0] == 'n' || optarg[0] == 'r') || optarg[1] != '\0')
{
fprintf (stderr, _("%s: illegal newline character specifier: \
'%s': expected 'n' or 'r'\n"),
program, optarg);
goto option_error;
}
if (optarg[0] == 'n')
nl = '\n';
else
nl = '\r';
break;
case 'o':
case 'p':
if (strcmp (optarg, "-") == 0)
output_file = OUTPUT_FILE_STDOUT;
else
output_file = optarg;
break;
case 'O':
list_missing_characters = 1;
break;
case 'q':
quiet = 1;
verbose = 0;
break;
case 'r':
landscape = 1;
break;
case 'R':
landscape = 0;
break;
case 's':
baselineskip = atof (optarg);
break;
case 'S':
parse_key_value_pair (statusdict, optarg);
break;
case 't':
case 'J':
title = optarg;
title_given = 1;
break;
case 'T':
tabsize = atoi (optarg);
if (tabsize <= 0)
tabsize = 1;
break;
case 'u':
underlay = optarg;
break;
case 'U':
nup = atoi (optarg);
break;
case 'v':
if (optarg)
verbose = atoi (optarg);
else
verbose++;
quiet = 0;
break;
case 'V':
version ();
exit (0);
break;
case 'w':
output_language = optarg;
if (strcmp (output_language, "PostScript") != 0)
output_language_pass_through = 1;
break;
case 'W':
cp = strchr (optarg, ',');
if (cp == NULL)
FATAL ((stderr,
_("malformed argument `%s' for option -W, --option: \
no comma found"),
optarg));
if (cp - optarg != 1)
FATAL ((stderr, _("helper application specification must be \
single character: %s"),
optarg));
i = *optarg;
cp++;
if (helper_options[i] == NULL)
helper_options[i] = buffer_alloc ();
else
{
buffer_append (helper_options[i], " ");
}
buffer_append (helper_options[i], cp);
break;
case 'X':
xfree (encoding_name);
encoding_name = xstrdup (optarg);
break;
case 'z':
interpret_formfeed = 0;
break;
case 'Z':
pass_through = 1;
break;
case 128:
if (!parse_font_spec (optarg, &ul_font, &ul_ptsize, NULL))
FATAL ((stderr, _("malformed font spec: %s"), optarg));
break;
case 129:
ul_gray = atof (optarg);
break;
case 130:
xfree (page_label_format);
page_label_format = xstrdup (optarg);
break;
case 131:
strhash_put (download_fonts, optarg, strlen (optarg) + 1, NULL,
NULL);
break;
case 132:
ul_angle = atof (optarg);
ul_angle_p = 1;
break;
case 133:
xfree (ul_position);
ul_position = xstrdup (optarg);
ul_position_p = 1;
break;
case 134:
xfree (npf_name);
npf_name = xstrdup (optarg);
break;
case 135:
usage ();
exit (0);
break;
case 136:
highlight_bar_gray = atof (optarg);
break;
case 137:
xfree (ul_style_str);
ul_style_str = xstrdup (optarg);
break;
case 138:
input_filter_stdin = optarg;
break;
case 139:
printer_options = optarg;
break;
case 140:
slicing = 1;
slice = atoi (optarg);
if (slice <= 0)
FATAL ((stderr, _("slice must be greater than zero")));
break;
case 141:
help_highlight = 1;
break;
case 142:
if (optarg == NULL)
states_color = 1;
else
states_color = atoi (optarg);
break;
case 143:
if (optarg)
{
xfree (mark_wrapped_lines_style_name);
mark_wrapped_lines_style_name = xstrdup (optarg);
}
else
mark_wrapped_lines_style = MWLS_BOX;
break;
case 144:
margins_spec = optarg;
break;
case 145:
nup_xpad = atoi (optarg);
break;
case 146:
nup_ypad = atoi (optarg);
break;
case 147:
line_end = LE_WORD_WRAP;
break;
case 148:
horizontal_column_height = atof (optarg);
formfeed_type = FORMFEED_HCOLUMN;
break;
case 149:
pslevel = atoi (optarg);
break;
case 150:
rotate_even_pages = 1;
break;
case 151:
xfree (states_highlight_style);
states_highlight_style = xstrdup (optarg);
break;
case 152:
nup_columnwise = 1;
break;
case 153:
swap_even_page_margins = 1;
break;
case 154:
extended_return_values = 1;
break;
case 155:
page_footer = optarg;
break;
case 156:
continuous_page_numbers = 1;
break;
case '?':
option_error:
fprintf (stderr, _("Try `%s --help' for more information.\n"),
program);
exit (1);
break;
default:
printf ("Hey! main() didn't handle option \"%c\" (%d)", c, c);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
FATAL ((stderr, "This is a bug!"));
break;
}
}
}
static void
usage ()
{
printf (_("\
Usage: %s [OPTION]... [FILE]...\n\
Mandatory arguments to long options are mandatory for short options too.\n\
-# an alias for option -n, --copies\n\
-1 same as --columns=1\n\
-2 same as --columns=2\n\
--columns=NUM specify the number of columns per page\n\
-a, --pages=PAGES specify which pages are printed\n\
-A, --file-align=ALIGN align separate input files to ALIGN\n\
-b, --header=HEADER set page header\n\
-B, --no-header no page headers\n\
-c, --truncate-lines cut long lines (default is to wrap)\n\
-C, --line-numbers[=START]\n\
precede each line with its line number\n\
-d an alias for option --printer\n\
-D, --setpagedevice=KEY[:VALUE]\n\
pass a page device definition to output\n\
-e, --escapes[=CHAR] enable special escape interpretation\n"),
program);
printf (_("\
-E, --highlight[=LANG] highlight source code\n"));
printf (_("\
-f, --font=NAME use font NAME for body text\n\
-F, --header-font=NAME use font NAME for header texts\n\
-g, --print-anyway nothing (compatibility option)\n\
-G same as --fancy-header\n\
--fancy-header[=NAME] select fancy page header\n\
-h, --no-job-header suppress the job header page\n\
-H, --highlight-bars=NUM specify how high highlight bars are\n\
-i, --indent=NUM set line indent to NUM characters\n\
-I, --filter=CMD read input files through input filter CMD\n\
-j, --borders print borders around columns\n\
-J, an alias for option --title\n\
-k, --page-prefeed enable page prefeed\n\
-K, --no-page-prefeed disable page prefeed\n\
-l, --lineprinter simulate lineprinter, this is an alias for:\n\
--lines-per-page=66, --no-header, --portrait,\n\
--columns=1\n"));
printf (_("\
-L, --lines-per-page=NUM specify how many lines are printed on each page\n\
-m, --mail send mail upon completion\n\
-M, --media=NAME use output media NAME\n\
-n, --copies=NUM print NUM copies of each page\n\
-N, --newline=NL select the newline character. Possible\n\
values for NL are: n (`\\n') and r (`\\r').\n\
-o an alias for option --output\n\
-O, --missing-characters list missing characters\n\
-p, --output=FILE leave output to file FILE. If FILE is `-',\n\
leave output to stdout.\n\
-P, --printer=NAME print output to printer NAME\n\
-q, --quiet, --silent be really quiet\n\
-r, --landscape print in landscape mode\n\
-R, --portrait print in portrait mode\n"));
printf (_("\
-s, --baselineskip=NUM set baselineskip to NUM\n\
-S, --statusdict=KEY[:VALUE]\n\
pass a statusdict definition to the output\n\
-t, --title=TITLE set banner page's job title to TITLE. Option\n\
sets also the name of the input file stdin.\n\
-T, --tabsize=NUM set tabulator size to NUM\n\
-u, --underlay[=TEXT] print TEXT under every page\n\
-U, --nup=NUM print NUM logical pages on each output page\n\
-v, --verbose tell what we are doing\n\
-V, --version print version number\n\
-w, --language=LANG set output language to LANG\n\
-W, --options=APP,OPTION pass option OPTION to helper application APP\n\
-X, --encoding=NAME use input encoding NAME\n\
-z, --no-formfeed do not interpret form feed characters\n\
-Z, --pass-through pass through PostScript and PCL files\n\
without any modifications\n"));
printf (_("Long-only options:\n\
--color[=bool] create color outputs with states\n\
--continuous-page-numbers count page numbers across input files. Don't\n\
restart numbering at beginning of each file.\n\
--download-font=NAME download font NAME\n\
--extended-return-values enable extended return values\n\
--filter-stdin=NAME specify how stdin is shown to the input filter\n\
--footer=FOOTER set page footer\n\
--h-column-height=HEIGHT set the horizontal column height to HEIGHT\n\
--help print this help and exit\n"));
printf (_("\
--help-highlight describe all supported --highlight languages\n\
and file formats\n\
--highlight-bar-gray=NUM print highlight bars with gray NUM (0 - 1)\n\
--list-media list names of all known media\n\
--margins=LEFT:RIGHT:TOP:BOTTOM\n\
adjust page marginals\n\
--mark-wrapped-lines[STYLE]\n\
mark wrapped lines in the output with STYLE\n\
--non-printable-format=FMT specify how non-printable chars are printed\n"));
printf (_("\
--nup-columnwise layout pages in the N-up printing columnwise\n\
--nup-xpad=NUM set the page x-padding of N-up printing to NUM\n\
--nup-ypad=NUM set the page y-padding of N-up printing to NUM\n\
--page-label-format=FMT set page label format to FMT\n\
--ps-level=LEVEL set the PostScript language level that enscript\n\
should use\n\
--printer-options=OPTIONS pass extra options to the printer command\n\
--rotate-even-pages rotate even-numbered pages 180 degrees\n"));
printf (_("\
--slice=NUM print vertical slice NUM\n\
--style=STYLE use highlight style STYLE\n\
--swap-even-page-margins swap left and right side margins for each even\n\
numbered page\n\
--toc print table of contents\n\
--ul-angle=ANGLE set underlay text's angle to ANGLE\n\
--ul-font=NAME print underlays with font NAME\n\
--ul-gray=NUM print underlays with gray value NUM\n\
--ul-position=POS set underlay's starting position to POS\n\
--ul-style=STYLE print underlays with style STYLE\n\
--word-wrap wrap long lines from word boundaries\n\
"));
printf (_("\nReport bugs to mtr@iki.fi.\n"));
}
static void
version ()
{
printf ("%s\n\
Copyright (C) 2003 Markku Rossi.\n\
GNU enscript comes with NO WARRANTY, to the extent permitted by law.\n\
You may redistribute copies of GNU enscript under the terms of the GNU\n\
General Public License. For more information about these matters, see\n\
the files named COPYING.\n",
version_string);
}