2 * Argument handling and main.
3 * Copyright (c) 1995-2003 Markku Rossi.
5 * Author: Markku Rossi <mtr@iki.fi>
9 * This file is part of GNU Enscript.
11 * Enscript is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
16 * Enscript is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with Enscript. If not, see <http://www.gnu.org/licenses/>.
29 * Prototypes for static functions.
33 * Open output file according to user options. Void if output file
34 * has already been opened.
36 static void open_output_file ();
38 /* Close output file. */
39 static void close_output_file ();
41 /* Handle options from environment variable <var> */
42 static void handle_env_options ___P ((char *var));
44 /* Handle options from <argv> array. */
45 static void handle_options ___P ((int argc, char *argv[]));
47 /* Print usage info. */
50 /* Print version info. */
51 static void version ();
58 char *program; /* Program's name, used for messages. */
59 FILE *ofp = NULL; /* Output file. */
60 void *printer_context; /* Context for the printer. */
61 char *date_string = NULL; /* Preformatted time string. */
62 struct tm run_tm; /* Time when program is run. */
63 struct tm mod_tm; /* Last modification time for current file. */
64 struct passwd *passwd; /* Passwd entry for the user running this
67 /* Path to our library. */
68 char *enscript_library = LIBRARY;
70 /* Library lookup path. */
73 /* AFM library lookup path. */
74 char *afm_path = NULL;
76 MediaEntry *media_names = NULL; /* List of known media. */
77 MediaEntry *media = NULL; /* Entry for used media. */
78 int bs = 8; /* The backspace character. */
81 int total_pages = 0; /* Total number of pages printed. */
82 int num_truncated_lines = 0; /* Number of lines truncated. */
83 int num_missing_chars = 0; /* Number of unknown characters. */
84 int missing_chars[256] = {0}; /* Table of unknown characters. */
85 int num_non_printable_chars = 0; /* Number of non-printable characters. */
86 int non_printable_chars[256] = {0}; /* Table of non-printable characters. */
88 /* Output media dimensions that are used during PostScript emission. */
89 int d_page_w = 0; /* page's width */
90 int d_page_h = 0; /* page's height */
91 int d_header_w = 0; /* fancy header's width */
92 int d_header_h = 0; /* fancy header's height */
93 int d_footer_h = 0; /* fancy footer's height */
94 int d_output_w = 0; /* output area's width */
95 int d_output_h = 0; /* output area's height */
96 int d_output_x_margin = 5; /* output area's x marginal */
97 int d_output_y_margin = 2; /* output area's y marginal */
99 /* Document needed resources. */
100 StringHashPtr res_fonts; /* fonts */
102 /* Fonts to download. */
103 StringHashPtr download_fonts;
105 /* Additional key-value pairs, passed to the generated PostScript code. */
106 StringHashPtr pagedevice; /* for setpagedevice */
107 StringHashPtr statusdict; /* for statusdict */
109 /* User defined strings. */
110 StringHashPtr user_strings;
112 /* Cache for AFM files. */
113 StringHashPtr afm_cache = NULL;
114 StringHashPtr afm_info_cache = NULL;
116 /* AFM library handle. */
117 AFMHandle afm = NULL;
123 * Free single-letter options are: Q, x, y, Y
129 * An alias for -n, --copies.
133 * -1, -2, -3, -4, -5, -6, -7, -8, -9, --columns=NUM
135 * Number of columns per page. The default is 1 column.
140 * -a PAGES, --pages=PAGES
142 * Specify which pages are printed.
144 PageRange *page_ranges = NULL;
147 * -A ALIGN, --file-align=ALIGN
149 * Align input files to start from ALIGN page count. This is handy
150 * for two-side printings.
152 unsigned int file_align = 1;
155 * -b STRING, --header=STRING
157 * Set the string that is used as the page header. As a default, page
158 * header is constructed from filename, date and page number.
160 char *page_header = NULL;
165 * Do not print page headers.
169 * -c, --truncate-lines
171 * Truncate lines that are longer than the page width. Default is character
174 LineEndType line_end = LE_CHAR_WRAP;
177 * -C [START], --line-numbers[=START]
179 * Precede each line with its line number. As a default, do not mark
180 * line numbers. If the optional argument START is given, it
181 * specifies the number from which the line numbers are assumed to
182 * start in the file. This is useful if the file contains a region
185 int line_numbers = 0;
186 unsigned int start_line_number = 1;
191 * Name of the printer to which output is send. Defaults to system's
194 char *printer = NULL;
197 * -e [CHAR], --escapes[=CHAR]
199 * Enable special escape ('\000') interpretation. If option CHAR is given
200 * it is assumed to specify the escape character.
202 int special_escapes = 0;
203 int escape_char = '\0';
204 int default_escape_char;
207 * -E [LANG], --highlight=[LANG] (deprecated --pretty-print[=LANG])
209 * Highlight program source code. Highlighting is handled by creating
210 * an input filter with the states-program. States makes an educated
211 * guess about the start state but sometimes it fails, so the start
212 * state can also be specified to be LANG. This option overwrites
213 * input filter and enables special escapes.
217 char *hl_start_state = NULL;
224 char *Fname = "Courier";
225 FontPoint Fpt = {10.0, 10.0};
226 FontPoint default_Fpt; /* Point size of the original font. */
227 char *default_Fname; /* Name of the original font. */
228 InputEncoding default_Fencoding; /* The encoding of the original font. */
229 int user_body_font_defined = 0; /* Has user defined new body font? */
231 double font_widths[256]; /* Width array for body font. */
232 char font_ctype[256]; /* Font character types. */
233 int font_is_fixed; /* Is body font a fixed pitch font? */
234 double font_bbox_lly; /* Font's bounding box's lly-coordinate. */
239 * Select font to be used to print the standard simple header.
241 char *HFname = "Courier-Bold";
242 FontPoint HFpt = {10.0, 10.0};
247 * Print document even it contains binary data. This does nothing
248 * since enscript prints files anyway.
254 * Add a fancy header to top of every page. There are several header styles
255 * but the default is 'no fancy header'.
257 HeaderType header = HDR_SIMPLE;
258 char *fancy_header_name = NULL;
259 char *fancy_header_default = NULL;
262 * -h, --no-job-header
264 * Supress the job header page.
266 static int no_job_header = 0;
269 * -H num, --highlight-bars=num
271 * Print highlight bars under text. Bars will be <num> lines high.
272 * As a default, do not print bars.
274 unsigned int highlight_bars = 0;
279 * Indent every line this many characters.
281 double line_indent = 0.0;
282 char *line_indent_spec = "0";
285 * -I CMD, --filter=CMD
287 * Read input files through input filter CMD.
289 char *input_filter = NULL;
294 * Print borders around columns.
301 * An alias for -t, --title.
306 * -K, --no-page-prefeed
308 * Control page prefeed.
310 int page_prefeed = 0;
315 * Emulate lineprinter - make pages 66 lines long and omit headers.
319 * -L, --lines-per-page
321 * Specify how many lines should be printed on a single page. Normally
322 * enscript counts it from font point sizes.
324 unsigned int lines_per_page = (unsigned int) -1;
329 * Send mail notification to user after print job has been completed.
336 * Name of the output media. Default is A4.
338 char *media_name = NULL;
343 * Number of copies to print.
350 * Set the newline character: '\n' or '\r'. As a default, the newline
351 * character is specified by the input encoding.
358 * Leave output to the specified file. As a default result is spooled to
361 char *output_file = OUTPUT_FILE_NONE;
364 * -O, --missing-characters
366 * List all missing characters. Default is no listing.
368 int list_missing_characters = 0;
373 * Do not tell what we are doing. Default is to tell something but
382 * Print with page rotated 90 degrees (landscape mode). Default is
390 * Specify baselineskip value that is used when enscript moves to
391 * a new line. Current point movement is font_point_size + baselineskip.
393 double baselineskip = 1.0;
398 * Title which is printed to the banner page. If this option is given
399 * from the command line, this sets also the name of the stdin which
400 * is by the default "".
402 char *title = "Enscript Output";
408 * Specify tabulator size.
415 * Place text under every page. Default is no underlay.
418 FontPoint ul_ptsize = {200.0, 200.0};
419 char *ul_font = "Times-Roman";
420 char *underlay = NULL;
421 char *ul_position = NULL; /* Position info as a string. */
422 double ul_x; /* Position x-coordinate. */
423 double ul_y; /* Position y-coordinate. */
425 unsigned int ul_style = UL_STYLE_OUTLINE;
426 char *ul_style_str = NULL;
427 int ul_position_p = 0; /* Is ul-position given? */
428 int ul_angle_p = 0; /* Is ul-angle given? */
433 * Print NUM PostScript pages on each output page (n-up printing).
435 unsigned int nup = 1;
436 unsigned int nup_exp = 0;
437 unsigned int nup_rows = 1;
438 unsigned int nup_columns = 1;
439 int nup_landscape = 0;
440 unsigned int nup_width;
441 unsigned int nup_height;
447 * Tell what we are doing. Default is no verbose outputs.
454 * Print version information.
458 * -w LANGUAGE, --language=LANGUAGE
460 * Generate output for language LANGUAGE. The default is PostScript.
462 char *output_language = "PostScript";
463 int output_language_pass_through = 0;
466 * -W APP,option, --options=APP,OPTION
468 * Pass additional option to enscript's helper applications. The
469 * first part of the option's argument (APP) specifies the
470 * helper application to which the options are added. Currently the
471 * following helper application are defined:
475 Buffer *helper_options[256] = {0};
480 * Specifies input encoding. Default is ISO-8859.1.
482 InputEncoding encoding = ENC_ISO_8859_1;
483 char *encoding_name = NULL;
488 * Do not interpret form feed characters. As a default, form feed
489 * characters are interpreted.
491 int interpret_formfeed = 1;
496 * Pass through all PostScript and PCL files without any modifications.
497 * As a default, don't.
499 int pass_through = 0;
504 * Create color output with states?
508 * --continuous-page-numbers
510 * Count page numbers across input files. Don't restart numbering
511 * at beginning of each file.
513 int continuous_page_numbers = 0;
516 * --download-font=FONT
518 * Download font FONT to printer.
522 * --extended-return-values
524 * Enable extended return values.
526 int extended_return_values = 0;
531 * How stdin is shown to the filter command. The default is "" but
532 * some utilities might want it as "-".
534 char *input_filter_stdin = "";
539 * Set the string that is used as the page footer. As a default, the
540 * page has no footer. Setting this option does not necessary show
541 * any footer strings in the output. It depends on the selected
542 * header (`.hdr' file) whether it supports footer strings or not.
544 char *page_footer = NULL;
547 * --h-column-height=HEIGHT
549 * Set the horizontal column (channel) height to be HEIGHT. This option
550 * also sets the FormFeedType to `hcolumn'. The default value is set to be
551 * big enough to cause a jump to the next vertical column (100m).
553 double horizontal_column_height = 283465.0;
556 * --help-highlight (deprecated --help-pretty-print)
558 * Descript all supported -E, --highlight languages and file formats.
560 int help_highlight = 0;
563 * --highlight-bar-gray=val
565 * Specify the gray level for highlight bars.
567 double highlight_bar_gray = .97;
572 * List all known media. As a default do not list media names.
577 * --margins=LEFT:RIGHT:TOP:BOTTOM
579 * Adjust page marginals.
581 char *margins_spec = NULL;
584 * --mark-wrapped-lines[=STYLE]
586 * Mark wrapped lines so that they can be easily detected from the printout.
587 * Optional parameter STYLE specifies the marking style, the system default
590 char *mark_wrapped_lines_style_name = NULL;
591 MarkWrappedLinesStyle mark_wrapped_lines_style = MWLS_NONE;
594 * --non-printable-format=FORMAT
596 * Format in which non-printable characters are printed.
598 char *npf_name = NULL;
599 NonPrintableFormat non_printable_format = NPF_OCTAL;
604 * Layout N-up pages colunwise instead of row-wise.
606 int nup_columnwise = 0;
611 * The x-padding between N-up subpages.
613 unsigned int nup_xpad = 10;
618 * The y-padding between N-up subpages.
620 unsigned int nup_ypad = 10;
623 * --page-label-format=FORMAT
625 * Format in which page labels are printed; the default is "short".
627 char *page_label_format = NULL;
628 PageLabelFormat page_label;
633 * The PostScript language level that enscript should use; the default is 2.
635 unsigned int pslevel = 2;
638 * --printer-options=OPTIONS
640 * Pass extra options OPTIONS to the printer spooler.
642 char *printer_options = NULL;
645 * --rotate-even-pages
647 * Rotate each even-numbered page 180 degrees. This might be handy in
648 * two-side printing when the resulting pages are bind from some side.
649 * Greetings to Jussi-Pekka Sairanen.
651 int rotate_even_pages = 0;
656 * Horizontal input slicing. Print only NUMth wrapped input pages.
659 unsigned int slice = 1;
662 * --swap-even-page-margins
664 * Swap left and right side margins for each even numbered page. This
665 * might be handy in two-side printing.
667 int swap_even_page_margins = 0;
672 * Print Table of Contents page.
676 char *toc_fmt_string;
681 * Wrap long lines from word boundaries. The default is character wrap.
685 * AcceptCompositeCharacters: bool
687 * Specify whatever we accept composite characters or should them be
688 * considered as non-existent. As a default, do not accept them.
690 int accept_composites = 0;
695 * Append ^D character to the end of the output. Some printers require this
696 * but the default is false.
698 int append_ctrl_D = 0;
703 * Specify how characters greater than 127 are printed.
710 * Specify what to do when a formfeed character is encountered from the
711 * input stream. The default action is to jump to the beginning of the
714 FormFeedType formfeed_type = FORMFEED_COLUMN;
717 * GeneratePageSize: bool
719 * Specify whether the `PageSize' pagedevice definitions should be
720 * generated to the output.
722 int generate_PageSize = 1;
725 * NoJobHeaderSwitch: switch
727 * Spooler switch to suppress the job header (-h).
729 char *no_job_header_switch = NULL;
732 * OutputFirstLine: line
734 * Set the PostScript output's first line to something your system can handle.
735 * The default is "%!PS-Adobe-3.0"
737 char *output_first_line = NULL;
742 * The spooler command switch to select the printer queue (-P).
744 char *queue_param = NULL;
749 * The spooler command name (lpr).
751 char *spooler_command = NULL;
756 * An absolute path to the `states' binary.
759 char *states_binary = NULL;
764 * Should the States program generate color outputs.
766 int states_color = 0;
769 * StatesConfigFile: file
771 * The name of the states' configuration file.
773 char *states_config_file = NULL;
776 * StatesHighlightStyle: style
778 * The highlight style.
780 char *states_highlight_style = NULL;
785 * Define the path for the states program. The states program will
786 * lookup its state definition files from this path.
788 char *states_path = NULL;
790 /* ^@shade{GRAY}, set the line highlight gray. */
791 double line_highlight_gray = 1.0;
793 /* ^@bggray{GRAY}, set the text background gray. */
796 EncodingRegistry encodings[] =
798 {{"88591", "latin1", NULL}, ENC_ISO_8859_1, '\n', 8},
799 {{"88592", "latin2", NULL}, ENC_ISO_8859_2, '\n', 8},
800 {{"88593", "latin3", NULL}, ENC_ISO_8859_3, '\n', 8},
801 {{"88594", "latin4", NULL}, ENC_ISO_8859_4, '\n', 8},
802 {{"88595", "cyrillic", NULL}, ENC_ISO_8859_5, '\n', 8},
803 {{"88597", "greek", NULL}, ENC_ISO_8859_7, '\n', 8},
804 {{"88599", "latin5", NULL}, ENC_ISO_8859_9, '\n', 8},
805 {{"885910", "latin6", NULL}, ENC_ISO_8859_10, '\n', 8},
806 {{"ascii", NULL, NULL}, ENC_ASCII, '\n', 8},
807 {{"asciifise", "asciifi", "asciise"}, ENC_ASCII_FISE, '\n', 8},
808 {{"asciidkno", "asciidk", "asciino"}, ENC_ASCII_DKNO, '\n', 8},
809 {{"ibmpc", "pc", "dos"}, ENC_IBMPC, '\n', 8},
810 {{"mac", NULL, NULL}, ENC_MAC, '\r', 8},
811 {{"vms", NULL, NULL}, ENC_VMS, '\n', 8},
812 {{"hp8", NULL, NULL}, ENC_HP8, '\n', 8},
813 {{"koi8", NULL, NULL}, ENC_KOI8, '\n', 8},
814 {{"ps", "PS", NULL}, ENC_PS, '\n', 8},
815 {{"pslatin1", "ISOLatin1Encoding", NULL}, ENC_ISO_8859_1, '\n', 8},
817 {{NULL, NULL, NULL}, 0, 0, 0},
825 static struct option long_options[] =
827 {"columns", required_argument, 0, 0},
828 {"pages", required_argument, 0, 'a'},
829 {"file-align", required_argument, 0, 'A'},
830 {"header", required_argument, 0, 'b'},
831 {"no-header", no_argument, 0, 'B'},
832 {"truncate-lines", no_argument, 0, 'c'},
833 {"line-numbers", optional_argument, 0, 'C'},
834 {"printer", required_argument, 0, 'd'},
835 {"setpagedevice", required_argument, 0, 'D'},
836 {"escapes", optional_argument, 0, 'e'},
837 {"highlight", optional_argument, 0, 'E'},
838 {"font", required_argument, 0, 'f'},
839 {"header-font", required_argument, 0, 'F'},
840 {"print-anyway", no_argument, 0, 'g'},
841 {"fancy-header", optional_argument, 0, 'G'},
842 {"no-job-header", no_argument, 0, 'h'},
843 {"highlight-bars", optional_argument, 0, 'H'},
844 {"indent", required_argument, 0, 'i'},
845 {"filter", required_argument, 0, 'I'},
846 {"borders", no_argument, 0, 'j'},
847 {"page-prefeed", no_argument, 0, 'k'},
848 {"no-page-prefeed", no_argument, 0, 'K'},
849 {"lineprinter", no_argument, 0, 'l'},
850 {"lines-per-page", required_argument, 0, 'L'},
851 {"mail", no_argument, 0, 'm'},
852 {"media", required_argument, 0, 'M'},
853 {"copies", required_argument, 0, 'n'},
854 {"newline", required_argument, 0, 'N'},
855 {"output", required_argument, 0, 'p'},
856 {"missing-characters", no_argument, 0, 'O'},
857 {"quiet", no_argument, 0, 'q'},
858 {"silent", no_argument, 0, 'q'},
859 {"landscape", no_argument, 0, 'r'},
860 {"portrait", no_argument, 0, 'R'},
861 {"baselineskip", required_argument, 0, 's'},
862 {"statusdict", required_argument, 0, 'S'},
863 {"title", required_argument, 0, 't'},
864 {"tabsize", required_argument, 0, 'T'},
865 {"underlay", optional_argument, 0, 'u'},
866 {"nup", required_argument, 0, 'U'},
867 {"verbose", optional_argument, 0, 'v'},
868 {"version", no_argument, 0, 'V'},
869 {"language", required_argument, 0, 'w'},
870 {"option", required_argument, 0, 'W'},
871 {"encoding", required_argument, 0, 'X'},
872 {"no-formfeed", no_argument, 0, 'z'},
873 {"pass-through", no_argument, 0, 'Z'},
875 /* Long options without short counterparts. Next free is 157. */
876 {"color", optional_argument, 0, 142},
877 {"continuous-page-numbers", no_argument, 0, 156},
878 {"download-font", required_argument, 0, 131},
879 {"extended-return-values", no_argument, 0, 154},
880 {"filter-stdin", required_argument, 0, 138},
881 {"footer", required_argument, 0, 155},
882 {"h-column-height", required_argument, 0, 148},
883 {"help", no_argument, 0, 135},
884 {"help-highlight", no_argument, 0, 141},
885 {"highlight-bar-gray", required_argument, 0, 136},
886 {"list-media", no_argument, &list_media, 1},
887 {"margins", required_argument, 0, 144},
888 {"mark-wrapped-lines", optional_argument, 0, 143},
889 {"non-printable-format", required_argument, 0, 134},
890 {"nup-columnwise", no_argument, 0, 152},
891 {"nup-xpad", required_argument, 0, 145},
892 {"nup-ypad", required_argument, 0, 146},
893 {"page-label-format", required_argument, 0, 130},
894 {"ps-level", required_argument, 0, 149},
895 {"printer-options", required_argument, 0, 139},
896 {"rotate-even-pages", no_argument, 0, 150},
897 {"slice", required_argument, 0, 140},
898 {"style", required_argument, 0, 151},
899 {"swap-even-page-margins", no_argument, 0, 153},
900 {"toc", no_argument, &toc, 1},
901 {"word-wrap", no_argument, 0, 147},
902 {"ul-angle", required_argument, 0, 132},
903 {"ul-font", required_argument, 0, 128},
904 {"ul-gray", required_argument, 0, 129},
905 {"ul-position", required_argument, 0, 133},
906 {"ul-style", required_argument, 0, 137},
908 /* Backwards compatiblity options. */
909 {"pretty-print", optional_argument, 0, 'E'},
910 {"help-pretty-print", no_argument, 0, 141},
921 main (int argc, char *argv[])
934 /* Init our dynamic memory buffer. */
935 buffer_init (&buffer);
937 /* Get program's name. */
938 program = strrchr (argv[0], '/');
944 /* Make getopt_long() to use our modified programname. */
947 /* Create the default TOC format string. Wow, this is cool! */
948 /* xgettext:no-c-format */
949 toc_fmt_string = _("$3v $-40N $3% pages $4L lines $E $C");
951 /* Internationalization. */
954 * We want to change only messages (gs do not like decimals in 0,1
958 setlocale (LC_MESSAGES, "");
962 bindtextdomain (PACKAGE, LOCALEDIR);
963 textdomain (PACKAGE);
966 /* Create date string. */
969 tm = localtime (&tim);
970 memcpy (&run_tm, tm, sizeof (*tm));
972 date_string = xstrdup (asctime (&run_tm));
973 i = strlen (date_string);
974 date_string[i - 1] = '\0';
976 /* Get user's passwd entry. */
977 passwd = getpwuid (getuid ());
979 FATAL ((stderr, _("couldn't get passwd entry for uid=%d: %s"), getuid (),
982 /* Defaults for some options. */
983 media_name = xstrdup ("A4");
984 encoding_name = xstrdup ("88591");
985 npf_name = xstrdup ("octal");
986 page_label_format = xstrdup ("short");
987 ul_style_str = xstrdup ("outline");
988 ul_position = xstrdup ("+0-0");
989 spooler_command = xstrdup ("lpr");
990 queue_param = xstrdup ("-P");
991 no_job_header_switch = xstrdup ("-h");
992 fancy_header_default = xstrdup ("enscript");
993 output_first_line = xstrdup ("%!PS-Adobe-3.0");
995 /* Check ENSCRIPT_LIBRARY for custom library location. */
996 cp = getenv ("ENSCRIPT_LIBRARY");
998 enscript_library = cp;
1000 /* Fill up build-in libpath. */
1002 cp = getenv ("HOME");
1004 cp = passwd->pw_dir;
1006 buffer_clear (&buffer);
1007 buffer_append (&buffer, enscript_library);
1008 buffer_append (&buffer, PATH_SEPARATOR_STR);
1009 buffer_append (&buffer, cp);
1010 buffer_append (&buffer, "/.enscript");
1011 libpath = buffer_copy (&buffer);
1013 /* Defaults for the states filter. */
1015 states_binary = xstrdup ("states"); /* Take it from the user path. */
1017 buffer_clear (&buffer);
1018 buffer_append (&buffer, enscript_library);
1019 buffer_append (&buffer, "/hl/enscript.st");
1020 states_config_file = buffer_copy (&buffer);
1022 states_highlight_style = xstrdup ("emacs");
1024 /* The <cp> holds the user's home directory. */
1025 buffer_clear (&buffer);
1026 buffer_append (&buffer, cp);
1027 buffer_append (&buffer, "/.enscript");
1028 buffer_append (&buffer, PATH_SEPARATOR_STR);
1029 buffer_append (&buffer, enscript_library);
1030 buffer_append (&buffer, "/hl");
1031 states_path = buffer_copy (&buffer);
1033 /* Initialize resource sets. */
1034 res_fonts = strhash_init ();
1035 download_fonts = strhash_init ();
1036 pagedevice = strhash_init ();
1037 statusdict = strhash_init ();
1038 user_strings = strhash_init ();
1042 * Read configuration files.
1045 /* Global config. */
1046 #define CFG_FILE_NAME "enscript.cfg"
1047 if (!read_config (SYSCONFDIR, CFG_FILE_NAME))
1049 int saved_errno = errno;
1051 /* Try to read it from our library directory. This is mostly
1052 the case for the micro ports. */
1053 if (!read_config (enscript_library, CFG_FILE_NAME))
1055 /* Try `enscript_library/../../etc/'. This is the case for
1056 installations which set the prefix after the compilation
1057 and our SYSCONFDIR points to wrong directory. */
1059 buffer_clear (&buffer);
1060 buffer_append (&buffer, enscript_library);
1061 buffer_append (&buffer, "/../../etc");
1063 if (!read_config (buffer_ptr (&buffer), CFG_FILE_NAME))
1065 /* Maybe we are not installed yet, let's try `../lib'
1067 if (!read_config ("../lib", CFG_FILE_NAME)
1068 && !read_config ("../../lib", CFG_FILE_NAME))
1070 /* No luck, report error from the original config file. */
1071 ERROR ((stderr, _("couldn't read config file \"%s/%s\": %s"),
1072 enscript_library, CFG_FILE_NAME,
1073 strerror (saved_errno)));
1075 _("I did also try the following directories:")));
1076 ERROR ((stderr, _("\t%s"), SYSCONFDIR));
1077 ERROR ((stderr, _("\t%s"), enscript_library));
1078 ERROR ((stderr, _("\t%s"), buffer_ptr (&buffer)));
1079 ERROR ((stderr, _("\t../lib")));
1080 ERROR ((stderr, _("\t../../lib")));
1082 _("This is probably an installation error. Please, try to rebuild:")));
1083 ERROR ((stderr, _("\tmake distclean")));
1084 ERROR ((stderr, _("\t./configure --prefix=PREFIX")));
1085 ERROR ((stderr, _("\tmake")));
1086 ERROR ((stderr, _("\tmake check")));
1087 ERROR ((stderr, _("\tmake install")));
1088 ERROR ((stderr, _("or set the environment variable `ENSCRIPT_LIBRARY'"
1089 " to point to your library directory.")));
1093 /* Ok, we are not installed yet. Here is a small kludge
1094 to conform the GNU coding standards: we must be able
1095 to run without being installed, so we must append the
1096 `../lib' and `../../lib' directories to the libpath.
1097 The later allows us to be run form the `src/tests'
1099 buffer_clear (&buffer);
1100 buffer_append (&buffer, libpath);
1101 buffer_append (&buffer, PATH_SEPARATOR_STR);
1102 buffer_append (&buffer, "../lib");
1103 buffer_append (&buffer, PATH_SEPARATOR_STR);
1104 buffer_append (&buffer, "../../lib");
1107 libpath = buffer_copy (&buffer);
1113 read_config (SYSCONFDIR, "enscriptsite.cfg");
1115 /* Personal config. */
1116 read_config (cp, ".enscriptrc");
1122 /* Environment variables. */
1123 handle_env_options ("ENSCRIPT");
1124 handle_env_options ("GENSCRIPT");
1126 /* Command line arguments. */
1127 handle_options (argc, argv);
1130 * Check options which have some validity conditions.
1134 * Save the user-specified escape char so ^@escape{default} knows
1137 default_escape_char = escape_char;
1139 /* Input encoding. */
1142 for (i = 0; !found && encodings[i].names[0]; i++)
1143 for (j = 0; j < 3; j++)
1144 if (encodings[i].names[j] != NULL && MATCH (encodings[i].names[j],
1147 /* Found a match for this encoding. Use the first
1150 encoding = encodings[i].encoding;
1151 xfree (encoding_name);
1152 encoding_name = xstrdup (encodings[i].names[0]);
1155 nl = encodings[i].nl;
1156 bs = encodings[i].bs;
1161 FATAL ((stderr, _("unknown encoding: %s"), encoding_name));
1165 /* Default font for landscape, 2 column printing is Courier 7. */
1166 if (!user_body_font_defined && landscape && num_columns > 1)
1167 Fpt.w = Fpt.h = 7.0;
1169 /* Cache for font AFM information. */
1170 afm_cache = strhash_init ();
1171 afm_info_cache = strhash_init ();
1173 /* Open AFM library. */
1174 afm_error = afm_create (afm_path, verbose, &afm);
1175 if (afm_error != AFM_SUCCESS)
1179 afm_error_to_string (afm_error, buf);
1180 FATAL ((stderr, _("couldn't open AFM library: %s"), buf));
1184 * Save default Fpt and Fname since special escape 'font' can change
1185 * it and later we might want to switch back to the "default" font.
1187 default_Fpt.w = Fpt.w;
1188 default_Fpt.h = Fpt.h;
1189 default_Fname = Fname;
1190 default_Fencoding = encoding;
1192 /* Register that document uses at least these fonts. */
1193 strhash_put (res_fonts, Fname, strlen (Fname) + 1, NULL, NULL);
1194 strhash_put (res_fonts, HFname, strlen (HFname) + 1, NULL, NULL);
1196 /* As a default, download both named fonts. */
1197 strhash_put (download_fonts, Fname, strlen (Fname) + 1, NULL, NULL);
1198 strhash_put (download_fonts, HFname, strlen (HFname) + 1, NULL, NULL);
1200 /* Read font's character widths and character types. */
1203 /* Count the line indentation. */
1204 line_indent = parse_float (line_indent_spec, 1, 1);
1206 /* List media names. */
1209 printf (_("known media:\n\
1210 name width\theight\tllx\tlly\turx\tury\n\
1211 ------------------------------------------------------------\n"));
1212 for (mentry = media_names; mentry; mentry = mentry->next)
1213 printf ("%-16s %d\t%d\t%d\t%d\t%d\t%d\n",
1214 mentry->name, mentry->w, mentry->h,
1215 mentry->llx, mentry->lly, mentry->urx, mentry->ury);
1216 /* Exit after listing. */
1221 for (mentry = media_names; mentry; mentry = mentry->next)
1222 if (strcmp (media_name, mentry->name) == 0)
1228 FATAL ((stderr, _("do not know anything about media \"%s\""), media_name));
1232 /* Adjust marginals. */
1233 for (i = 0; i < 4; i++)
1235 if (*margins_spec == '\0')
1239 if (*margins_spec == ':')
1245 j = atoi (margins_spec);
1246 for (; *margins_spec != ':' && *margins_spec != '\0'; margins_spec++)
1248 if (*margins_spec == ':')
1258 media->urx = media->w - j;
1262 media->ury = media->h - j;
1265 case 3: /* bottom */
1272 _("set new marginals for media `%s' (%dx%d): llx=%d, lly=%d, urx=%d, ury=%d\n"),
1273 media->name, media->w, media->h, media->llx, media->lly,
1274 media->urx, media->ury));
1277 /* Page label format. */
1278 if (MATCH (page_label_format, "short"))
1279 page_label = LABEL_SHORT;
1280 else if (MATCH (page_label_format, "long"))
1281 page_label = LABEL_LONG;
1283 FATAL ((stderr, _("illegal page label format \"%s\""), page_label_format));
1285 /* Non-printable format. */
1286 if (MATCH (npf_name, "space"))
1287 non_printable_format = NPF_SPACE;
1288 else if (MATCH (npf_name, "questionmark"))
1289 non_printable_format = NPF_QUESTIONMARK;
1290 else if (MATCH (npf_name, "caret"))
1291 non_printable_format = NPF_CARET;
1292 else if (MATCH (npf_name, "octal"))
1293 non_printable_format = NPF_OCTAL;
1295 FATAL ((stderr, _("illegal non-printable format \"%s\""), npf_name));
1297 /* Mark wrapped lines style. */
1298 if (mark_wrapped_lines_style_name)
1300 if (MATCH (mark_wrapped_lines_style_name, "none"))
1301 mark_wrapped_lines_style = MWLS_NONE;
1302 else if (MATCH (mark_wrapped_lines_style_name, "plus"))
1303 mark_wrapped_lines_style = MWLS_PLUS;
1304 else if (MATCH (mark_wrapped_lines_style_name, "box"))
1305 mark_wrapped_lines_style = MWLS_BOX;
1306 else if (MATCH (mark_wrapped_lines_style_name, "arrow"))
1307 mark_wrapped_lines_style = MWLS_ARROW;
1309 FATAL ((stderr, _("illegal style for wrapped line marker: \"%s\""),
1310 mark_wrapped_lines_style_name));
1313 /* Count N-up stuffs. */
1319 FATAL ((stderr, _("illegal N-up argument: %d"), nup));
1324 FATAL ((stderr, _("N-up argument must be power of 2: %d"), nup));
1331 nup_rows = nup_exp / 2 * 2;
1334 nup_columns = (nup_exp + 1) / 2 * 2;
1335 if (nup_columns == 0)
1338 nup_landscape = nup_exp & 0x1;
1342 * Count output media dimensions.
1347 d_page_w = media->ury - media->lly;
1348 d_page_h = media->urx - media->llx;
1352 d_page_w = media->urx - media->llx;
1353 d_page_h = media->ury - media->lly;
1357 * Count N-up page width, height and scale.
1362 nup_width = media->ury - media->lly;
1363 nup_height = media->urx - media->llx;
1367 nup_width = media->urx - media->llx;
1368 nup_height = media->ury - media->lly;
1374 w = ((double) nup_width - (nup_columns - 1) * nup_xpad) / nup_columns;
1375 h = ((double) nup_height - (nup_rows - 1) * nup_ypad) / nup_rows;
1380 w = w / (media->urx - media->llx);
1381 h = h / (media->ury - media->lly);
1383 nup_scale = w < h ? w : h;
1387 * Underlay (this must come after output media dimensions, because
1388 * `underlay position' needs them).
1390 if (underlay != NULL)
1392 strhash_put (res_fonts, ul_font, strlen (ul_font) + 1, NULL, NULL);
1393 underlay = escape_string (underlay);
1396 /* Underlay X-coordinate. */
1397 ul_x = strtod (ul_position, &cp);
1398 if (cp == ul_position)
1401 FATAL ((stderr, _("malformed underlay position: %s"), ul_position));
1403 if (ul_position[0] == '-')
1406 /* Underlay Y-coordinate. */
1407 ul_y = strtod (cp, &cp2);
1409 goto malformed_position;
1413 /* Underlay Angle. */
1415 /* No angle given, count the default. */
1416 ul_angle = (atan2 (-d_page_h, d_page_w) / 3.14159265 * 180);
1418 /* Underlay style. */
1419 if (strcmp (ul_style_str, "outline") == 0)
1420 ul_style = UL_STYLE_OUTLINE;
1421 else if (strcmp (ul_style_str, "filled") == 0)
1422 ul_style = UL_STYLE_FILLED;
1424 FATAL ((stderr, _("illegal underlay style: %s"), ul_style_str));
1427 * Header. Note! The header attributes can be changed from
1428 * the `.hdr' files, these are only the defaults.
1431 d_header_w = d_page_w;
1439 d_header_h = HFpt.h * 1.5;
1447 /* Help highlight. */
1450 /* Create description with states. */
1451 printf (_("Highlighting is supported for the following languages and file formats:\n\n"));
1454 buffer_clear (&buffer);
1455 buffer_append (&buffer, states_binary);
1456 buffer_append (&buffer, " -f \"");
1457 buffer_append (&buffer, states_config_file);
1458 buffer_append (&buffer, "\" -p \"");
1459 buffer_append (&buffer, states_path);
1460 buffer_append (&buffer, "\" -s describe_languages ");
1461 buffer_append (&buffer, enscript_library);
1462 buffer_append (&buffer, "/hl/*.st");
1464 system (buffer_ptr (&buffer));
1469 * And now to the main business. The actual input file processing
1470 * is divided to two parts: PostScript generation and everything else.
1471 * The PostScript generation is handled in the conventional way, we
1472 * process the input and generate PostScript. However all other input
1473 * languages will be handled with States, we only pass enscript's
1474 * options to the states pre-filter and dump output.
1476 if (output_language_pass_through)
1482 /* The States output generation. */
1484 /* Resolve the start state. */
1486 start_state = hl_start_state;
1490 start_state = "passthrough";
1492 /* Create the states command. */
1496 buffer_append (&cmd, states_binary);
1497 buffer_append (&cmd, " -f \"");
1498 buffer_append (&cmd, states_config_file);
1499 buffer_append (&cmd, "\" -p \"");
1500 buffer_append (&cmd, states_path);
1501 buffer_append (&cmd, "\" ");
1504 buffer_append (&cmd, "-v ");
1508 buffer_append (&cmd, "-s");
1509 buffer_append (&cmd, start_state);
1510 buffer_append (&cmd, " ");
1513 buffer_append (&cmd, "-Dcolor=");
1514 buffer_append (&cmd, states_color ? "1" : "0");
1515 buffer_append (&cmd, " ");
1517 buffer_append (&cmd, "-Dstyle=");
1518 buffer_append (&cmd, states_highlight_style);
1519 buffer_append (&cmd, " ");
1521 buffer_append (&cmd, "-Dlanguage=");
1522 buffer_append (&cmd, output_language);
1523 buffer_append (&cmd, " ");
1525 buffer_append (&cmd, "-Dnum_input_files=");
1526 sprintf (intbuf, "%d", optind == argc ? 1 : argc - optind);
1527 buffer_append (&cmd, intbuf);
1528 buffer_append (&cmd, " ");
1530 buffer_append (&cmd, "-Ddocument_title=\'");
1531 if ((cp = shell_escape (title)) != NULL)
1533 buffer_append (&cmd, cp);
1536 buffer_append (&cmd, "\' ");
1538 buffer_append (&cmd, "-Dtoc=");
1539 buffer_append (&cmd, toc ? "1" : "0");
1541 /* Additional options for states? */
1542 if (helper_options['s'])
1544 Buffer *opts = helper_options['s'];
1546 buffer_append (&cmd, " ");
1547 buffer_append_len (&cmd, buffer_ptr (opts), buffer_len (opts));
1550 /* Append input files. */
1551 for (i = optind; i < argc; i++)
1554 if ((cp = shell_escape (argv[i])) != NULL)
1556 buffer_append (&cmd, " \'");
1557 buffer_append (&cmd, cp);
1558 buffer_append (&cmd, "\'");
1563 /* And do the job. */
1564 if (is_open (&is, stdin, NULL, buffer_ptr (&cmd)))
1566 open_output_file ();
1567 process_file ("unused", &is, 0);
1571 buffer_uninit (&cmd);
1575 /* The conventional way. */
1582 /* Create a highlight input filter. */
1583 buffer_clear (&buffer);
1584 buffer_append (&buffer, states_binary);
1585 buffer_append (&buffer, " -f \"");
1586 buffer_append (&buffer, states_config_file);
1587 buffer_append (&buffer, "\" -p \"");
1588 buffer_append (&buffer, states_path);
1589 buffer_append (&buffer, "\"");
1592 buffer_append (&buffer, " -v");
1596 buffer_append (&buffer, " -s ");
1597 buffer_append (&buffer, hl_start_state);
1600 buffer_append (&buffer, " -Dcolor=");
1601 buffer_append (&buffer, states_color ? "1" : "0");
1603 buffer_append (&buffer, " -Dstyle=");
1604 buffer_append (&buffer, states_highlight_style);
1606 buffer_append (&buffer, " -Dfont_spec=");
1607 buffer_append (&buffer, Fname);
1608 sprintf (fbuf, "@%g/%g", Fpt.w, Fpt.h);
1609 buffer_append (&buffer, fbuf);
1611 /* Additional options for states? */
1612 if (helper_options['s'])
1614 Buffer *opts = helper_options['s'];
1616 buffer_append (&buffer, " ");
1617 buffer_append_len (&buffer,
1618 buffer_ptr (opts), buffer_len (opts));
1621 buffer_append (&buffer, " \'%s\'");
1623 input_filter = buffer_copy (&buffer);
1624 input_filter_stdin = "-";
1627 /* Table of Contents. */
1630 toc_fp = tmpfile ();
1632 FATAL ((stderr, _("couldn't create temporary toc file: %s"),
1643 /* stdin's modification time is the current time. */
1644 memcpy (&mod_tm, &run_tm, sizeof (run_tm));
1646 if (is_open (&is, stdin, NULL, input_filter))
1648 /* Open output file. */
1649 open_output_file ();
1650 process_file (title_given ? title : "", &is, 0);
1656 for (; optind < argc; optind++)
1658 if (is_open (&is, NULL, argv[optind], input_filter))
1660 struct stat stat_st;
1662 /* Get modification time. */
1663 if (stat (argv[optind], &stat_st) == 0)
1665 tim = stat_st.st_mtime;
1666 tm = localtime (&tim);
1667 memcpy (&mod_tm, tm, sizeof (*tm));
1670 * Open output file. Output file opening is delayed to
1671 * this point so we can optimize the case when a
1672 * non-existing input file is printed => we do nothing.
1674 open_output_file ();
1676 process_file (argv[optind], &is, 0);
1679 ERROR ((stderr, _("couldn't stat input file \"%s\": %s"),
1688 /* Table of Contents. */
1691 /* This is really cool... */
1693 /* Set the printing options for toc. */
1695 special_escapes = 1;
1698 if (fseek (toc_fp, 0, SEEK_SET) != 0)
1699 FATAL ((stderr, _("couldn't rewind toc file: %s"),
1702 memcpy (&mod_tm, &run_tm, sizeof (run_tm));
1703 if (is_open (&is, toc_fp, NULL, NULL))
1705 process_file (_("Table of Contents"), &is, 1);
1710 /* Give trailer a chance to dump itself. */
1714 * Append ^D to the end of the output? Note! It must be ^D followed
1717 if (ofp != NULL && append_ctrl_D)
1718 fprintf (ofp, "\004\n");
1721 /* Close output file. */
1722 close_output_file ();
1724 /* Tell how things went. */
1728 * The value of <ofp> is not reset in close_output_file(),
1729 * this is ugly but it saves one flag.
1731 MESSAGE (0, (stderr, _("no output generated\n")));
1733 else if (output_language_pass_through)
1735 if (output_file == OUTPUT_FILE_NONE)
1736 MESSAGE (0, (stderr, _("output sent to %s\n"),
1737 printer ? printer : _("printer")));
1739 MESSAGE (0, (stderr, _("output left in %s\n"),
1740 output_file == OUTPUT_FILE_STDOUT ? "-" : output_file));
1744 unsigned int real_total_pages;
1748 if (total_pages > 0)
1749 real_total_pages = (total_pages - 1) / nup + 1;
1751 real_total_pages = 0;
1754 real_total_pages = total_pages;
1756 /* We did something, tell what. */
1758 snprintf(message, sizeof message, "%s%s%s%s%s",
1760 ngettext("%d page", "%d pages", real_total_pages),
1762 ngettext("%d copy", "%d copies", num_copies),
1764 MESSAGE (0, (stderr, message, real_total_pages, num_copies));
1766 if (output_file == OUTPUT_FILE_NONE)
1767 MESSAGE (0, (stderr, _(" sent to %s\n"),
1768 printer ? printer : _("printer")));
1770 MESSAGE (0, (stderr, _(" left in %s\n"),
1771 output_file == OUTPUT_FILE_STDOUT ? "-" : output_file));
1772 if (num_truncated_lines)
1775 MESSAGE (0, (stderr,
1776 ngettext("%d line was %s\n",
1777 "%d lines were %s\n",
1778 num_truncated_lines),
1779 num_truncated_lines,
1780 line_end == LE_TRUNCATE
1781 ? _("truncated") : _("wrapped")));
1784 if (num_missing_chars)
1787 MESSAGE (0, (stderr,
1788 ngettext("%d character was missing\n",
1789 "%d characters were missing\n",
1791 num_missing_chars));
1792 if (list_missing_characters)
1794 MESSAGE (0, (stderr, _("missing character codes (decimal):\n")));
1795 do_list_missing_characters (missing_chars);
1799 if (num_non_printable_chars)
1802 MESSAGE (0, (stderr,
1803 ngettext("%d non-printable character\n",
1804 "%d non-printable characters\n",
1805 num_non_printable_chars),
1806 num_non_printable_chars));
1807 if (list_missing_characters)
1809 MESSAGE (0, (stderr,
1810 _("non-printable character codes (decimal):\n")));
1811 do_list_missing_characters (non_printable_chars);
1816 /* Uninit our dynamic memory buffer. */
1817 buffer_uninit (&buffer);
1819 /* Return the extended return values only if requested. */
1820 if (!extended_return_values)
1823 /* This is the end. */
1836 /* Output file has already been opened, do nothing. */
1839 if (output_file == OUTPUT_FILE_NONE)
1841 char spooler_options[512];
1843 /* Format spooler options. */
1844 spooler_options[0] = '\0';
1846 strcat (spooler_options, "-m ");
1849 strcat (spooler_options, no_job_header_switch);
1850 strcat (spooler_options, " ");
1852 if (printer_options)
1853 strcat (spooler_options, printer_options);
1856 ofp = printer_open (spooler_command, spooler_options, queue_param,
1857 printer, &printer_context);
1859 FATAL ((stderr, _("couldn't open printer `%s': %s"), printer,
1862 else if (output_file == OUTPUT_FILE_STDOUT)
1866 ofp = fopen (output_file, "w");
1868 FATAL ((stderr, _("couldn't create output file \"%s\": %s"),
1869 output_file, strerror (errno)));
1875 close_output_file ()
1878 /* Output file hasn't been opened, we are done. */
1881 if (output_file == OUTPUT_FILE_NONE)
1882 printer_close (printer_context);
1883 else if (output_file != OUTPUT_FILE_STDOUT)
1885 FATAL ((stderr, _("couldn't close output file \"%s\": %s"),
1886 output_file, strerror (errno)));
1888 /* We do not reset <ofp> since its value is needed in diagnostigs. */
1893 handle_env_options (char *var)
1901 string = getenv (var);
1905 MESSAGE (2, (stderr, "handle_env_options(): %s=\"%s\"\n", var, string));
1907 /* Copy string so we can modify it in place. */
1908 str = xstrdup (string);
1911 * We can count this, each option takes at least 1 character and one
1912 * space. We also need one for program's name and one for the
1915 argc = (strlen (str) + 1) / 2 + 2;
1916 argv = xcalloc (argc, sizeof (char *));
1918 /* Set program name. */
1920 argv[argc++] = program;
1922 /* Split string and set arguments to argv array. */
1926 /* Skip leading whitespace. */
1927 for (; str[i] && isspace (str[i]); i++)
1932 /* Check for quoted arguments. */
1933 if (str[i] == '"' || str[i] == '\'')
1935 int endch = str[i++];
1937 argv[argc++] = str + i;
1939 /* Skip until we found the end of the quotation. */
1940 for (; str[i] && str[i] != endch; i++)
1943 FATAL ((stderr, _("syntax error in option string %s=\"%s\":\n\
1944 missing end of quotation: %c"), var, string, endch));
1950 argv[argc++] = str + i;
1952 /* Skip until whitespace if found. */
1953 for (; str[i] && !isspace (str[i]); i++)
1960 /* argv[argc] must be NULL. */
1963 MESSAGE (2, (stderr, "found following options (argc=%d):\n", argc));
1964 for (i = 0; i < argc; i++)
1965 MESSAGE (2, (stderr, "%3d = \"%s\"\n", i, argv[i]));
1967 /* Process options. */
1968 handle_options (argc, argv);
1970 /* Check that all got processed. */
1975 _("warning: didn't process following options from \
1976 environment variable %s:\n"),
1978 for (; optind < argc; optind++)
1979 MESSAGE (0, (stderr, _(" option %d = \"%s\"\n"), optind,
1987 * <str> must not be freed, since some global variables can point to
1994 handle_options (int argc, char *argv[])
2004 int option_index = 0;
2008 c = getopt_long (argc, argv,
2009 "#: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:W:X:zZ",
2010 long_options, &option_index);
2017 case 0: /* Long option found. */
2018 cp = long_options[option_index].name;
2020 if (strcmp (cp, "columns") == 0)
2022 num_columns = atoi (optarg);
2023 if (num_columns < 1)
2025 _("number of columns must be larger than zero")));
2029 /* Short options. */
2031 case '1': /* 1 column */
2032 case '2': /* 2 columns */
2033 case '3': /* 3 columns */
2034 case '4': /* 4 columns */
2035 case '5': /* 5 columns */
2036 case '6': /* 6 columns */
2037 case '7': /* 7 columns */
2038 case '8': /* 8 columns */
2039 case '9': /* 9 columns */
2040 num_columns = c - '0';
2043 case 'a': /* pages */
2044 prange = (PageRange *) xcalloc (1, sizeof (PageRange));
2046 if (strcmp (optarg, "odd") == 0)
2048 else if (strcmp (optarg, "even") == 0)
2052 cp = strchr (optarg, '-');
2055 if (optarg[0] == '-')
2057 prange->end = atoi (optarg + 1);
2058 else if (cp[1] == '\0')
2061 prange->start = atoi (optarg);
2062 prange->end = (unsigned int) -1;
2067 prange->start = atoi (optarg);
2068 prange->end = atoi (cp + 1);
2073 prange->start = prange->end = atoi (optarg);
2076 prange->next = page_ranges;
2077 page_ranges = prange;
2080 case 'A': /* file alignment */
2081 file_align = atoi (optarg);
2082 if (file_align == 0)
2083 FATAL ((stderr, _("file alignment must be larger than zero")));
2086 case 'b': /* page header */
2087 page_header = optarg;
2090 case 'B': /* no page headers */
2094 case 'c': /* truncate (cut) long lines */
2095 line_end = LE_TRUNCATE;
2098 case 'C': /* line numbers */
2101 start_line_number = atoi (optarg);
2104 case 'd': /* specify printer */
2107 printer = xstrdup (optarg);
2108 output_file = OUTPUT_FILE_NONE;
2111 case 'D': /* setpagedevice */
2112 parse_key_value_pair (pagedevice, optarg);
2115 case 'e': /* special escapes */
2116 special_escapes = 1;
2119 /* Specify the escape character. */
2120 if (isdigit (optarg[0]))
2121 /* As decimal, octal, or hexadicimal number. */
2122 escape_char = (int) strtoul (optarg, NULL, 0);
2124 /* As character directly. */
2125 escape_char = ((unsigned char *) optarg)[0];
2129 case 'E': /* highlight */
2131 special_escapes = 1;
2133 hl_start_state = optarg;
2136 case 'f': /* font */
2137 if (!parse_font_spec (optarg, &Fname, &Fpt, NULL))
2138 FATAL ((stderr, _("malformed font spec: %s"), optarg));
2139 user_body_font_defined = 1;
2142 case 'F': /* header font */
2143 if (!parse_font_spec (optarg, &HFname, &HFpt, NULL))
2144 FATAL ((stderr, _("malformed font spec: %s"), optarg));
2147 case 'g': /* print anyway */
2151 case 'G': /* fancy header */
2154 fancy_header_name = optarg;
2156 fancy_header_name = fancy_header_default;
2158 if (!file_existsp (fancy_header_name, ".hdr"))
2160 _("couldn't find header definition file \"%s.hdr\""),
2161 fancy_header_name));
2164 case 'h': /* no job header */
2168 case 'H': /* highlight bars */
2170 highlight_bars = atoi (optarg);
2175 case 'i': /* line indent */
2176 line_indent_spec = optarg;
2179 case 'I': /* input filter */
2180 input_filter = optarg;
2183 case 'j': /* borders */
2187 case 'k': /* enable page prefeed */
2191 case 'K': /* disable page prefeed */
2195 case 'l': /* emulate lineprinter */
2196 lines_per_page = 66;
2200 case 'L': /* lines per page */
2201 lines_per_page = atoi (optarg);
2202 if (lines_per_page <= 0)
2204 _("must print at least one line per each page: %s"),
2208 case 'm': /* send mail upon completion */
2212 case 'M': /* select output media */
2213 media_name = xstrdup (optarg);
2216 case 'n': /* num copies */
2218 num_copies = atoi (optarg);
2221 case 'N': /* newline character */
2222 if (!(optarg[0] == 'n' || optarg[0] == 'r') || optarg[1] != '\0')
2224 fprintf (stderr, _("%s: illegal newline character specifier: \
2225 '%s': expected 'n' or 'r'\n"),
2229 if (optarg[0] == 'n')
2236 case 'p': /* output file */
2237 /* Check output file "-". */
2238 if (strcmp (optarg, "-") == 0)
2239 output_file = OUTPUT_FILE_STDOUT;
2241 output_file = optarg;
2244 case 'O': /* list missing characters */
2245 list_missing_characters = 1;
2248 case 'q': /* quiet */
2253 case 'r': /* landscape */
2257 case 'R': /* portrait */
2261 case 's': /* baselineskip */
2262 baselineskip = atof (optarg);
2265 case 'S': /* statusdict */
2266 parse_key_value_pair (statusdict, optarg);
2269 case 't': /* title */
2275 case 'T': /* tabulator size */
2276 tabsize = atoi (optarg);
2281 case 'u': /* underlay */
2286 nup = atoi (optarg);
2289 case 'v': /* verbose */
2291 verbose = atoi (optarg);
2297 case 'V': /* version */
2302 case 'w': /* output language */
2303 output_language = optarg;
2304 if (strcmp (output_language, "PostScript") != 0)
2305 /* Other output languages are handled with states. */
2306 output_language_pass_through = 1;
2309 case 'W': /* a helper application option */
2310 cp = strchr (optarg, ',');
2313 _("malformed argument `%s' for option -W, --option: \
2317 if (cp - optarg != 1)
2318 FATAL ((stderr, _("helper application specification must be \
2319 single character: %s"),
2322 /* Take the index of the helper application and update `cp'
2323 to point to the beginning of the option. */
2327 if (helper_options[i] == NULL)
2328 helper_options[i] = buffer_alloc ();
2331 /* We already had some options for this helper
2332 application. Let's separate these arguments. */
2333 buffer_append (helper_options[i], " ");
2336 /* Add this new option. */
2337 buffer_append (helper_options[i], cp);
2340 case 'X': /* input encoding */
2341 xfree (encoding_name);
2342 encoding_name = xstrdup (optarg);
2345 case 'z': /* no form feeds */
2346 interpret_formfeed = 0;
2349 case 'Z': /* pass through */
2353 case 128: /* underlay font */
2354 if (!parse_font_spec (optarg, &ul_font, &ul_ptsize, NULL))
2355 FATAL ((stderr, _("malformed font spec: %s"), optarg));
2358 case 129: /* underlay gray */
2359 ul_gray = atof (optarg);
2362 case 130: /* page label format */
2363 xfree (page_label_format);
2364 page_label_format = xstrdup (optarg);
2367 case 131: /* download font */
2368 strhash_put (download_fonts, optarg, strlen (optarg) + 1, NULL,
2372 case 132: /* underlay angle */
2373 ul_angle = atof (optarg);
2377 case 133: /* underlay position */
2378 xfree (ul_position);
2379 ul_position = xstrdup (optarg);
2383 case 134: /* non-printable format */
2385 npf_name = xstrdup (optarg);
2388 case 135: /* help */
2393 case 136: /* highlight bar gray */
2394 highlight_bar_gray = atof (optarg);
2397 case 137: /* underlay style */
2398 xfree (ul_style_str);
2399 ul_style_str = xstrdup (optarg);
2402 case 138: /* filter stdin */
2403 input_filter_stdin = optarg;
2406 case 139: /* extra options for the printer spooler */
2407 printer_options = optarg;
2410 case 140: /* slicing */
2412 slice = atoi (optarg);
2414 FATAL ((stderr, _("slice must be greater than zero")));
2417 case 141: /* help-highlight */
2421 case 142: /* States color? */
2425 states_color = atoi (optarg);
2428 case 143: /* mark-wrapped-lines */
2431 xfree (mark_wrapped_lines_style_name);
2432 mark_wrapped_lines_style_name = xstrdup (optarg);
2435 /* Set the system default. */
2436 mark_wrapped_lines_style = MWLS_BOX;
2439 case 144: /* adjust margins */
2440 margins_spec = optarg;
2443 case 145: /* N-up x-pad */
2444 nup_xpad = atoi (optarg);
2447 case 146: /* N-up y-pad */
2448 nup_ypad = atoi (optarg);
2451 case 147: /* word wrap */
2452 line_end = LE_WORD_WRAP;
2455 case 148: /* horizontal column height */
2456 horizontal_column_height = atof (optarg);
2457 formfeed_type = FORMFEED_HCOLUMN;
2460 case 149: /* PostScript language level */
2461 pslevel = atoi (optarg);
2464 case 150: /* rotate even-numbered pages */
2465 rotate_even_pages = 1;
2468 case 151: /* highlight style */
2469 xfree (states_highlight_style);
2470 states_highlight_style = xstrdup (optarg);
2473 case 152: /* N-up colunwise */
2477 case 153: /* swap even page margins */
2478 swap_even_page_margins = 1;
2481 case 154: /* extended return values */
2482 extended_return_values = 1;
2485 case 155: /* footer */
2486 page_footer = optarg;
2489 case 156: /* continuous page numbers */
2490 continuous_page_numbers = 1;
2493 case '?': /* Errors found during getopt_long(). */
2495 fprintf (stderr, _("Try `%s --help' for more information.\n"),
2501 printf ("Hey! main() didn't handle option \"%c\" (%d)", c, c);
2503 printf (" with arg %s", optarg);
2505 FATAL ((stderr, "This is a bug!"));
2516 Usage: %s [OPTION]... [FILE]...\n\
2517 Mandatory arguments to long options are mandatory for short options too.\n\
2518 -# an alias for option -n, --copies\n\
2519 -1 same as --columns=1\n\
2520 -2 same as --columns=2\n\
2521 --columns=NUM specify the number of columns per page\n\
2522 -a, --pages=PAGES specify which pages are printed\n\
2523 -A, --file-align=ALIGN align separate input files to ALIGN\n\
2524 -b, --header=HEADER set page header\n\
2525 -B, --no-header no page headers\n\
2526 -c, --truncate-lines cut long lines (default is to wrap)\n\
2527 -C[START], --line-numbers[=START]\n\
2528 precede each line with its line number\n\
2529 -d an alias for option --printer\n\
2530 -D, --setpagedevice=KEY[:VALUE]\n\
2531 pass a page device definition to output\n\
2532 -e[CHAR], --escapes[=CHAR] enable special escape interpretation\n"),
2536 -E[LANG], --highlight[=LANG] highlight source code\n"));
2539 -f, --font=NAME use font NAME for body text\n\
2540 -F, --header-font=NAME use font NAME for header texts\n\
2541 -g, --print-anyway nothing (compatibility option)\n\
2542 -G same as --fancy-header\n\
2543 --fancy-header[=NAME] select fancy page header\n\
2544 -h, --no-job-header suppress the job header page\n\
2545 -H[NUM], --highlight-bars[=NUM] specify how high highlight bars are\n\
2546 -i, --indent=NUM set line indent to NUM characters\n\
2547 -I, --filter=CMD read input files through input filter CMD\n\
2548 -j, --borders print borders around columns\n\
2549 -J, an alias for option --title\n\
2550 -k, --page-prefeed enable page prefeed\n\
2551 -K, --no-page-prefeed disable page prefeed\n\
2552 -l, --lineprinter simulate lineprinter, this is an alias for:\n\
2553 --lines-per-page=66, --no-header, --portrait,\n\
2557 -L, --lines-per-page=NUM specify how many lines are printed on each page\n\
2558 -m, --mail send mail upon completion\n\
2559 -M, --media=NAME use output media NAME\n\
2560 -n, --copies=NUM print NUM copies of each page\n\
2561 -N, --newline=NL select the newline character. Possible\n\
2562 values for NL are: n (`\\n') and r (`\\r').\n\
2563 -o an alias for option --output\n\
2564 -O, --missing-characters list missing characters\n\
2565 -p, --output=FILE leave output to file FILE. If FILE is `-',\n\
2566 leave output to stdout.\n\
2567 -P, --printer=NAME print output to printer NAME\n\
2568 -q, --quiet, --silent be really quiet\n\
2569 -r, --landscape print in landscape mode\n\
2570 -R, --portrait print in portrait mode\n"));
2573 -s, --baselineskip=NUM set baselineskip to NUM\n\
2574 -S, --statusdict=KEY[:VALUE]\n\
2575 pass a statusdict definition to the output\n\
2576 -t, --title=TITLE set banner page's job title to TITLE. Option\n\
2577 sets also the name of the input file stdin.\n\
2578 -T, --tabsize=NUM set tabulator size to NUM\n\
2579 -u[TEXT], --underlay[=TEXT] print TEXT under every page\n\
2580 -U, --nup=NUM print NUM logical pages on each output page\n\
2581 -v, --verbose tell what we are doing\n\
2582 -V, --version print version number\n\
2583 -w, --language=LANG set output language to LANG\n\
2584 -W, --options=APP,OPTION pass option OPTION to helper application APP\n\
2585 -X, --encoding=NAME use input encoding NAME\n\
2586 -z, --no-formfeed do not interpret form feed characters\n\
2587 -Z, --pass-through pass through PostScript and PCL files\n\
2588 without any modifications\n"));
2590 printf (_("Long-only options:\n\
2591 --color[=bool] create color outputs with states\n\
2592 --continuous-page-numbers count page numbers across input files. Don't\n\
2593 restart numbering at beginning of each file.\n\
2594 --download-font=NAME download font NAME\n\
2595 --extended-return-values enable extended return values\n\
2596 --filter-stdin=NAME specify how stdin is shown to the input filter\n\
2597 --footer=FOOTER set page footer\n\
2598 --h-column-height=HEIGHT set the horizontal column height to HEIGHT\n\
2599 --help print this help and exit\n"));
2602 --help-highlight describe all supported --highlight languages\n\
2604 --highlight-bar-gray=NUM print highlight bars with gray NUM (0 - 1)\n\
2605 --list-media list names of all known media\n\
2606 --margins=LEFT:RIGHT:TOP:BOTTOM\n\
2607 adjust page marginals\n\
2608 --mark-wrapped-lines[STYLE]\n\
2609 mark wrapped lines in the output with STYLE\n\
2610 --non-printable-format=FMT specify how non-printable chars are printed\n"));
2613 --nup-columnwise layout pages in the N-up printing columnwise\n\
2614 --nup-xpad=NUM set the page x-padding of N-up printing to NUM\n\
2615 --nup-ypad=NUM set the page y-padding of N-up printing to NUM\n\
2616 --page-label-format=FMT set page label format to FMT\n\
2617 --ps-level=LEVEL set the PostScript language level that enscript\n\
2619 --printer-options=OPTIONS pass extra options to the printer command\n\
2620 --rotate-even-pages rotate even-numbered pages 180 degrees\n"));
2623 --slice=NUM print vertical slice NUM\n\
2624 --style=STYLE use highlight style STYLE\n\
2625 --swap-even-page-margins swap left and right side margins for each even\n\
2627 --toc print table of contents\n\
2628 --ul-angle=ANGLE set underlay text's angle to ANGLE\n\
2629 --ul-font=NAME print underlays with font NAME\n\
2630 --ul-gray=NUM print underlays with gray value NUM\n\
2631 --ul-position=POS set underlay's starting position to POS\n\
2632 --ul-style=STYLE print underlays with style STYLE\n\
2633 --word-wrap wrap long lines from word boundaries\n\
2636 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
2644 Copyright (C) 1995-2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.\n\
2645 %s comes with NO WARRANTY, to the extent permitted by law.\n\
2646 You may redistribute copies of %s under the terms of the GNU\n\
2647 General Public License, version 3 or, at your option, any later version.\n\
2648 For more information about these matters, see the files named COPYING.\n",