ARB
arb_a2ps.c
Go to the documentation of this file.
1 //**********************************************************************
2 /* */
3 // Description: Ascii to PostScript printer program.
4 // File: bounty:/archive/src/a2ps/Last/a2ps.c
5 // Created: Fri Nov 5 8:20 1993 by miguel@bountyimag.fr (Miguel Santana)
6 // Version: 4.3
7 /* */
8 // Edit history:
9 // 1) Derived of shell program written by evan@csli (Evan Kirshenbaum).
10 // Written in C for improve speed execution and portability. Many
11 // improvements have been added.
12 // Fixes by Oscar Nierstrasz @ cui.uucp:
13 // 2) Fixed incorrect handling of stdin (removed error if no file names)
14 // 3) Added start_page variable to eliminate blank pages printed for
15 // files that are exactly multiples of 132 lines (e.g., man pages)
16 // Modified by santana@imag.fr:
17 // 4) Added new options at installation : sheet format (height/width in
18 // inches), page format (number of columns per line and of lines per
19 // page).
20 // Modified by santana@imag.fr:
21 // 5) Added new option to print n copies of a same document.
22 // 6) Cut long filenames if don't fit in the page header.
23 // Modified by Tim Clark (T.Clark@warwick.ac.uk):
24 // 7) Two additional modes of printing (portrait and wide format modes)
25 // 8) Fixed to cope with filenames which contain a character which must
26 // be escaped in a PostScript string.
27 // Modified by santana@imag.fr to
28 // 9) Added new option to suppress heading printing.
29 // 10) Added new option to suppress page surrounding border printing.
30 // 11) Added new option to change font size. Lines and columns are
31 // automatically adjusted, depending on font size and printing mode
32 // 12) Minor changes (best layout, usage message, etc).
33 // Modified by tullemans@apolloway.prl.philips.nl
34 // 13) Backspaces (^H) are now handled correctly.
35 // Modified by Johan Vromans (jv@mh.nl) to
36 // 14) Added new option to give a header title that replaces use of
37 // filename.
38 // Modified by craig.r.stevenson@att.com to
39 // 15) Print last modification date/time in header
40 // 16) Printing current date/time on left side of footer (optional)
41 // Modified by erikt@cs.umu.se:
42 // 17) Added lpr support for the BSD version
43 // 18) Added som output of pages printed.
44 // Modified by wstahw@lso.win.tue.nl:
45 // 19) Added option to allowing the printing of 2 files in one sheet
46 // Modified by mai@wolfen.cc.uow.oz
47 // 20) Added an option to set the lines per page to a specified value.
48 // 21) Added support for printing nroff manuals
49 // Modified by santana@imag.fr
50 // 22) Integration of changes.
51 // 23) No more standard header file (printed directly by a2ps).
52 // 24) New format for command options.
53 // 25) Other minor changes.
54 // Modified by Johan Garpendahl (garp@isy.liu.se) and santana@imag.fr:
55 // 26) Added 8-bit characters printing as ISO-latin 1 chars
56 // Modified by John Interrante (interran@uluru.stanford.edu) and
57 // santana@imag.fr:
58 // 27) Two pages per physical page in portrait mode
59 // Modified by santana@imag.fr:
60 // 28) New option for two-sided printing
61 // 29) Several fixes
62 // Modified by Chris Adamo (adamo@ll.mit.edu) and
63 // Larry Barbieri (lbarbieri@ll.mit.edu) 3/12/93
64 // 30) Output format enhancements.
65 // 31) Added login_id flag (for SYSV and BSD only) for printing user's
66 // login ID at top of page. Added command line parameter (-nL) to
67 // suppress this feature.
68 // 33) Added filename_footer flag for printing file name at bottom
69 // of page. Added command line parameter (-nu) to suppress this
70 // feature.
71 // 34) Added -B (-nB) options to enable (disable) bold font
72 // Modified by santana@imag.fr:
73 // 35) Adapted to respect Adobe conventions for page independence. A2ps
74 // output can be now used by other Postscript processors.
75 // 36) Names of most postscript variables have been coded in order to
76 // reduce the size of the output.
77 // 37) Ansi C compilers are now automatically taken into account.
78 // 38) Enhanced routine for cutting long filenames
79 // 39) Added -q option to print files in quiet mode (no summary)
80 // 40) Fixed some little bugs (counters, modification time for stdin,
81 // character separator when printing line numbers and cutting a
82 // line).
83 // 41) Some minor changes (new preprocessing variables, formatting)
84 /* */
85 //**********************************************************************
86 
87 /*
88  * Copyright (c) 1993, 1994, Miguel Santana, M.Santana@frgu.bull.fr
89  *
90  * Permission is granted to use, copy, and distribute this software for
91  * non commercial use, provided that the above copyright notice appear in
92  * all copies and that both that copyright notice and this permission
93  * notice appear in supporting documentation.
94  *
95  * Permission to modify the software is granted, but not the right to
96  * distribute the modified code. Please report bugs and changes to
97  * M.Santana@frgu.bull.fr
98  *
99  * This software is provided "as is" without express or implied warranty.
100  */
101 
102 
103 //**********************************************************************
104 /* */
105 // I n c l u d e f i l e s
106 /* */
107 //**********************************************************************
108 
109 #include <stdio.h>
110 #include <stdlib.h>
111 #include <unistd.h>
112 #include <ctype.h>
113 #include <sys/types.h>
114 #include <sys/stat.h>
115 #include <errno.h>
116 
117 #ifdef __STDC__
118 #include <stdlib.h>
119 #include <time.h>
120 #include <string.h>
121 #else
122 #include <strings.h>
123 #ifdef SYSV
124 #include <sys/timeb.h>
125 #include <time.h>
126 #include <sys/utsname.h>
127 #else
128 #ifndef BSD
129 #define BSD 1
130 #endif
131 #include <sys/time.h>
132 #endif
133 #endif
134 
135 
136 //**********************************************************************
137 /* */
138 // P r e p r o c e s s i n g d e f i n i t i o n s
139 /* */
140 //**********************************************************************
141 
142 /*
143  * Common definitions
144  */
145 #define FALSE 0
146 #define TRUE 1
147 #ifndef NULp
148 #define NULp 0
149 #endif
150 #ifndef NUL
151 #define NUL '\0'
152 #endif
153 #ifndef EXIT_SUCCESS
154 #define EXIT_SUCCESS 0
155 #endif
156 #ifndef EXIT_FAILURE
157 #define EXIT_FAILURE 1
158 #endif
159 
160 
161 /*
162  * Version
163  */
164 #define VERSION "4.3"
165 #define LPR_PRINT 1
166 
167 /*
168  * Default page dimensions
169  */
170 #ifndef WIDTH
171 #define WIDTH 8.27
172 #endif
173 
174 #ifndef HEIGHT
175 #define HEIGHT 11.0
176 #endif
177 
178 #ifndef MARGIN
179 #define MARGIN .5
180 #endif
181 
182 
183 /*
184  * Pathname separator for file system
185  */
186 #ifndef DIR_SEP
187 #define DIR_SEP '/'
188 #endif
189 
190 
191 /*
192  * Printing parameters
193  */
194 #if LPR_PRINT
195 
196 #ifndef LPR_COMMAND
197 #define LPR_COMMAND "lpr"
198 #endif
199 
200 #ifndef LPR_OPT
201 #define LPR_OPT "-l"
202 #endif
203 
204 #if defined(ONESIDED) && defined(TWOSIDED)
205 #define RECTO_VERSO_PRINTING
206 #ifndef TWOSIDED_DFLT
207 #define TWOSIDED_DFLT TRUE
208 #endif
209 #endif
210 
211 #endif
212 
213 
214 /*
215  * Configuration values
216  */
217 #define PORTRAIT_HEADER 0.29
218 #define LANDSCAPE_HEADER 0.22
219 #define PIXELS_INCH 72
220 #define MAXFILENAME 32
221 #define MAX_LINES 320 // max. lines per page
222 #define MAN_LINES 66 // no lines for a man
223 #define IS_ROMAN 0 // normal font
224 #define IS_BOLD 1 // bold sequence flag
225 #if defined(SYSV) || defined(BSD)
226 #define MAX_HOSTNAME 40
227 #endif
228 
229 
230 //**********************************************************************
231 /* */
232 // G l o b a l d e f i n i t i o n s
233 /* */
234 //**********************************************************************
235 
236 
237 /*
238  * Global types
239  */
240 typedef enum { BOLD, NORMAL } WEIGHT; // font weights
241 
242 
243 /*
244  * Function declarations.
245  */
246 
247 static void print_page_prologue(int side);
248 static void print_standard_prologue(char *datestring);
249 static void startpage();
250 static void endpage();
251 
252 #if defined(SYSV) || defined(BSD)
253 char *getlogin();
254 #endif
255 #if defined(BSD)
256 int gethostname(char *name, int namelen);
257 #endif
258 
259 /*
260  * Flags related to options.
261  */
262 static int numbering = FALSE; // Line numbering option
263 static int folding = TRUE; // Line folding option
264 static int restart = FALSE; // Don't restart page number after each file
265 static int only_printable = FALSE; // Replace non printable char by space
266 static int interpret = TRUE; // Interpret TAB, FF and BS chars option
267 static int print_binaries = FALSE; // Force printing for binary files
268 static int landscape = TRUE; // Otherwise portrait format sheets
269 static int new_landscape = TRUE; // To scrute changes of landscape option
270 static int twinpages = TRUE; // 2 pages per sheet if true, 1 otherwise
271 static int new_twinpages = TRUE; // To scrute changes of twinpages option
272 static int twinfiles = FALSE; // Allow 2 files per sheet
273 static int no_header = FALSE; // TRUE if user doesn't want the header
274 static int no_border = FALSE; // Don't print the surrounding border ?
275 static int printdate = FALSE; // Print current date as footnote
276 static int filename_footer = TRUE; // Print file name at bottom of page
277 static int no_summary = FALSE; // Quiet mode?
278 static WEIGHT fontweight = NORMAL; // Control font weight: BOLD or NORMAL
279 static WEIGHT new_fontweight = NORMAL; // To scrute changes of bold option
280 #if defined(SYSV) || defined(BSD)
281 int login_id = TRUE; // Print login ID at top of page
282 #endif
283 #if LPR_PRINT
284 static int lpr_print = TRUE; // Fork a lpr process to do the printing
285 #ifdef RECTO_VERSO_PRINTING
286 int rectoverso = TWOSIDED_DFLT; // Two-side printing
287 #endif
288 #endif
289 static int ISOlatin1 = FALSE; // Print 8-bit characters?
290 
291 
292 /*
293  * Counters of different kinds.
294  */
295 static int column = 0; // Column number (in current line)
296 static int line = 0; // Line number (in current page)
297 static int line_number = 0; // Source line number
298 static int pages = 0; // Number of logical pages printed
299 static int sheets = 0; // Number of physical pages printed
300 static int old_pages, old_sheets; // Value before printing current file
301 static int sheetside = 0; // Side of the sheet currently printing
302 static int linesperpage; // Lines per page
303 static int lines_requested = 0; // Lines per page requested by the user
304 static int new_linesrequest = 0; // To scrute new values for lines_requested
305 static int columnsperline; // Characters per output line
306 static int nonprinting_chars, chars; // Number of nonprinting and total chars
307 static int copies_number = 1; // Number of copies to print
308 static int column_width = 8; // Default column tab width (8)
309 
310 
311 /*
312  * Other global variables.
313  */
314 static int first_page; // First page for a file
315 static int no_files = TRUE; // No file until now
316 static int prefix_width; // Width in characters for line prefix
317 static float fontsize = 0.0; // Size of a char for body font
318 static float new_fontsize = 0.0; // To scrute new values for fontsize
319 static char *command; // Name of a2ps program
320 static char *lpr_opt = NULp; // Options to lpr
321 static char *header_text = NULp; // Allow for different header text
322 static float header_size; // Size of the page header
323 static char *prologue = NULp; // postscript header file
324 static char current_filename[MAXFILENAME+1]; // Name of the file being printed
325 static char currentdate[18]; // Date for today
326 static char filedate[18]; // Last modification time for current file
327 #if defined(SYSV) || defined(BSD)
328 char *login = NULp; // user's login name and host machine
329 #endif
330 
331 
332 /*
333  * Sheet dimensions
334  */
335 static double page_height = HEIGHT; // Paper height
336 static double page_width = WIDTH; // Paper width
337 
338 
339 //**********************************************************************
340 /* */
341 /* */
342 //**********************************************************************
343 
344 /*
345  * Print a usage message.
346  */
347 static void usage(int failure) {
348  // failure: Must we exit with a failure code?
349  fprintf(stderr, "A2ps v%s usage: %s [pos. or global options] [ f1 [ [pos. options] f2 ...] ]\n", VERSION, command);
350  fprintf(stderr, "pos. = -#num\t\tnumber of copies to print\n");
351  fprintf(stderr, " -1\t\tone page per sheet\n");
352  fprintf(stderr, " -2\t\tTWIN PAGES per sheet\n");
353  fprintf(stderr, " -d\t-nd\tprint (DON'T PRINT) current date at the bottom\n");
354  fprintf(stderr, " -Fnum\t\tfont size, num is a float number\n");
355  fprintf(stderr, " -Hstr\t\tuse str like header title for subsequent files\n");
356 #if defined(SYSV) || defined(BSD)
357  fprintf(stderr, " \t-nL\tdon't print login ID on top of page\n");
358 #endif
359  fprintf(stderr, " -l\t\tprint in LANDSCAPE mode\n");
360  fprintf(stderr, " -lnum\t\tuse num lines per page\n");
361  fprintf(stderr, " -m\t\tprocess the file as a man\n");
362  fprintf(stderr, " -n\t-nn\tNUMBER (don't number) line files\n");
363  fprintf(stderr, " -p\t\tprint in portrait mode\n");
364  fprintf(stderr, " -q\t\tprint in quiet mode (no summary)\n");
365  fprintf(stderr, " -s\t-ns\tPRINT (don't print) surrounding borders\n");
366  fprintf(stderr, "\n");
367  fprintf(stderr, "global = -?\t\tprint this information\n");
368  fprintf(stderr, " -B\t-nB\tprint (DON'T PRINT) in bold font\n");
369  fprintf(stderr, " -b\t-nb\tforce (DON'T FORCE) binary printing\n");
370  fprintf(stderr, " -c\t-nc\tallow (DON'T ALLOW) two files on the same sheet\n");
371  fprintf(stderr, " -f\t-nf\tFOLD (don't fold) lines\n");
372  fprintf(stderr, " \t-nH\tdon't print any header\n");
373  fprintf(stderr, " -h\t\tprint this information\n");
374  fprintf(stderr, " -Ifile\tinclude this file as a2ps prologue\n");
375  fprintf(stderr, " -i\t-ni\tINTERPRET (don't interpret) tab, bs and ff chars\n");
376 #if LPR_PRINT
377  fprintf(stderr, " -Pprinter -nP\tSEND (don't send) directly to the printer");
378 #ifdef LPR_OPT
379  if (LPR_OPT && sizeof(LPR_OPT) > 0)
380  fprintf(stderr, "\n\t\t\t(with options '%s' and -Pprinter)", LPR_OPT);
381 #endif
382  fprintf(stderr, "\n");
383 #endif
384  fprintf(stderr, " -r\t-nr\tRESTART (don't restart) page number after each file\n");
385 #ifdef RECTO_VERSO_PRINTING
386 #ifdef TWOSIDED_DFLT
387  fprintf(stderr, " -s1\t-s2\tone-sided (TWO-SIDED) printing\n");
388 #else
389  fprintf(stderr, " -s1\t-s2\tONE-SIDED (two-sided) printing\n");
390 #endif
391 #endif
392  fprintf(stderr, " -tnum\t\tset tab size to n\n");
393  fprintf(stderr, " \t-nu\tdon't print a filename footer\n");
394  fprintf(stderr, " -v\t-nv\tVISIBLE (blank) display of unprintable chars\n");
395  fprintf(stderr, " -8\t-n8\tdisplay (DON'T DISPLAY) 8-bit chars\n");
396  exit(failure);
397 }
398 
399 /*
400  * Set an option only if it's global.
401  */
402 static void set_global_option(char *arg) {
403  switch (arg[1]) {
404  case '?': // help
405  case 'h':
407  case 'b': // print binary files
408  if (arg[2] != NUL)
410  print_binaries = TRUE;
411  break;
412  case 'c': // allow two files per sheet
413  if (arg[2] != NUL)
415  twinfiles = TRUE;
416  break;
417  case 'f': // fold lines too large
418  if (arg[2] != NUL)
420  folding = TRUE;
421  break;
422  case 'I': // include this file as a2ps prologue
423  if (arg[2] == NUL)
425  prologue = arg+2;
426  break;
427  case 'i': // interpret control chars
428  if (arg[2] != NUL)
430  interpret = TRUE;
431  break;
432  case 'n':
433  if (arg[2] == NUL)
434  return;
435  if (arg[3] != NUL)
437  switch (arg[2]) {
438  case 'b': // don't print binaries
439  print_binaries = FALSE;
440  break;
441  case 'c': // don't allow 2 files/sheet
442  twinfiles = FALSE;
443  break;
444  case 'f': // cut lines too long
445  folding = FALSE;
446  break;
447  case 'H': // don't print header
448  no_header = TRUE;
449  break;
450  case 'i': // don't interpret ctrl chars
451  interpret = FALSE;
452  break;
453 #if LPR_PRINT
454  case 'P': // don't lpr
455  lpr_print = FALSE;
456  break;
457 #endif
458  case 'r': // don't restart sheet number
459  restart = FALSE;
460  break;
461  case 'v': // only printable chars
462  only_printable = TRUE;
463  break;
464  case '8': // don't print 8-bit chars
465  ISOlatin1 = FALSE;
466  break;
467  case 'B':
468  case 'd':
469  case 'L':
470  case 'm':
471  case 'n':
472  case 's':
473  case 'u':
474  if (arg[3] != NUL)
476  return;
477  default:
479  }
480  break;
481 #if LPR_PRINT
482  case 'P': // fork a process to print
483  if (arg[2] != NUL) {
484  lpr_opt = (char *)malloc(strlen(arg)+1);
485  strcpy(lpr_opt, arg);
486  }
487  lpr_print = TRUE;
488  break;
489 #endif
490  case 'q': // don't print a summary
491  no_summary = TRUE;
492  break;
493  case 'r': // restart sheet number
494  if (arg[2] != NUL)
496  restart = TRUE;
497  break;
498  case 's':
499  if (arg[2] == NUL)
500  return;
501 #ifdef RECTO_VERSO_PRINTING
502  if (arg[3] == NUL) {
503  if (arg[2] == '1') { // one-sided printing
504  rectoverso = FALSE;
505  break;
506  }
507  if (arg[2] == '2') { // two-sided printing
508  rectoverso = TRUE;
509  break;
510  }
511  }
512 #endif
514  break;
515  case 't': // set tab size
516  if (arg[2] == NUL || (column_width = atoi(arg+2)) <= 0)
518  break;
519  case 'v': // print control chars
520  if (arg[2] != NUL)
522  only_printable = FALSE;
523  break;
524  case '8': // print 8-bit chars
525  if (arg[2] != NUL)
527  ISOlatin1 = TRUE;
528  break;
529  case '1':
530  case '2':
531  case 'B':
532  case 'd':
533  case 'm':
534  case 'p':
535  if (arg[2] != NUL)
537  case '#':
538  case 'F':
539  case 'H':
540  case 'l':
541  return;
542  default:
544  }
545  arg[0] = NUL;
546 }
547 
548 /*
549  * Set an option of the command line. This option will be applied
550  * to all files that will be found in the rest of the command line.
551  * The -H option is the only exception: it is applied only to the
552  * file.
553  */
554 static void set_positional_option(char *arg) {
555  int copies;
556  int lines;
557  float size;
558 
559  switch (arg[1]) {
560  case NUL: // global option
561  break;
562  case '#': // n copies
563  if (sscanf(&arg[2], "%d", &copies) != 1 || copies <= 0)
564  fprintf(stderr, "Bad number of copies: '%s'. Ignored\n", &arg[2]);
565  else
566  copies_number = copies;
567  printf("/#copies %d def\n", copies_number);
568  break;
569  case '1': // 1 logical page per sheet
570  if (arg[2] != NUL)
572  new_twinpages = FALSE;
573  break;
574  case '2': // twin pages
575  if (arg[2] != NUL)
577  new_twinpages = TRUE;
578  break;
579  case 'B':
580  new_fontweight = BOLD; // use bold font
581  break;
582  case 'd': // print current date/time
583  printdate = TRUE;
584  break;
585  case 'F': // change font size
586  if (arg[2] == NUL || sscanf(&arg[2], "%f", &size) != 1 || size == 0.0) {
587  fprintf(stderr, "Wrong value for option -F: '%s'. Ignored\n",
588  &arg[2]);
589  break;
590  }
591  new_fontsize = size;
592  break;
593  case 'H': // header text
594  header_text = arg+2;
595  break;
596  case 'l':
597  if (arg[2] == NUL) { // landscape format
598  new_landscape = TRUE;
599  break;
600  }
601  // set lines per page
602  // Useful with preformatted files. Scaling is automatically
603  // done when necessary.
604  if (sscanf(&arg[2], "%d", &lines) != 1
605  || lines < 0 || lines > MAX_LINES)
606  {
607  fprintf(stderr, "Wrong value for option -l: '%s'. Ignored\n",
608  &arg[2]);
609  break;
610  }
611  new_linesrequest = lines;
612  break;
613  case 'm': // Process file as a man
614  new_linesrequest = MAN_LINES;
615  numbering = FALSE;
616  break;
617  case 'n': // number file lines
618  if (arg[2] == NUL) {
619  numbering = TRUE;
620  break;
621  }
622  switch (arg[2]) {
623  case 'B': // disable bold text
625  break;
626  case 'd': // don't print date/time
627  printdate = FALSE;
628  break;
629 #if defined(SYSV) || defined(BSD)
630  case 'L': // no login name in footer
631  login_id = FALSE;
632  break;
633 #endif
634  case 'l': // portrait format
635  new_landscape = FALSE;
636  break;
637  case 'm': // stop processing as a man
638  new_linesrequest = 0;
639  break;
640  case 'n': // don't number lines
641  numbering = FALSE;
642  break;
643  case 'p': // landscape format
644  new_landscape = TRUE;
645  break;
646  case 's': // no surrounding border
647  no_border = TRUE;
648  break;
649  case 'u': // no filename in footer
650  filename_footer = FALSE;
651  break;
652  default:
654  }
655  break;
656  case 'p': // portrait format
657  if (arg[2] != NUL)
659  new_landscape = FALSE;
660  break;
661  case 's': // surrounding border
662  if (arg[2] != NUL)
664  no_border = FALSE;
665  break;
666  default:
668  }
669 }
670 
671 
672 //**************************************************************
673 // Service routines
674 //**************************************************************
675 
676 /*
677  * This routine buffers a line of input, release one character at a time
678  * or a whole sequence of characters with some meaning like bold sequences
679  * produced by nroff (no others sequences are recognized by the moment):
680  * <c><\b><c><\b><c><\b><c>
681  */
682 static int mygetc(int *statusp) {
683 #define BUFFER_SIZE 512
684  static int curr = 0;
685  static int size = 0;
686  static unsigned char buffer[BUFFER_SIZE+1];
687  int c;
688 
689  *statusp = IS_ROMAN;
690 
691  // Read a new line, if necessary
692  if (curr >= size) {
693  if (!fgets((char *)buffer, BUFFER_SIZE+1, stdin))
694  return EOF;
695  size = strlen((char *)buffer);
696  if (size < BUFFER_SIZE && buffer[size-1] != '\n') {
697  buffer[size] = '\n';
698  buffer[++size] = '\0';
699  }
700  curr = 0;
701  }
702  if (buffer[curr+1] != '\b') // this is not a special sequence
703  return buffer[curr++];
704 
705  // Check if it is a bold sequence
706  c = buffer[curr++];
707  if (c == buffer[curr+1] &&
708  buffer[curr] == buffer[curr+2] &&
709  c == buffer[curr+3] &&
710  buffer[curr] == buffer[curr+4] &&
711  c == buffer[curr+5])
712  {
713  *statusp = IS_BOLD;
714  curr += 6;
715  }
716 
717  // Return the first character of the sequence
718  return c;
719 }
720 
721 /*
722  * Test if we have a binary file.
723  */
724 static int is_binaryfile(char *name) {
725  if (chars > 120 || pages > 1) {
726  first_page = FALSE;
727  if (chars && !print_binaries && (nonprinting_chars*100 / chars) >= 60) {
728  fprintf(stderr, "%s is a binary file: printing aborted\n", name);
729  return TRUE;
730  }
731  }
732  return FALSE;
733 }
734 
735 /*
736  * Cut long filenames.
737  */
738 static void cut_filename(char *old_name, char *new_name) {
739  char *p;
740  int i;
741  char *separator;
742 
743  if ((i = strlen(old_name)) <= MAXFILENAME) {
744  strcpy(new_name, old_name);
745  return;
746  }
747  p = old_name + (i-1);
748  separator = NULp;
749  i = 1;
750  while (p >= old_name && i < MAXFILENAME) {
751  if (*p == DIR_SEP)
752  separator = p;
753  p--;
754  i++;
755  }
756  if (separator)
757  p = separator;
758  else if (p >= old_name)
759  while (p >= old_name && *p != DIR_SEP) p--;
760 
761  for (i = 0, p++; *p != NUL; i++)
762  *new_name++ = *p++;
763  *new_name = NUL;
764 }
765 
766 /*
767  * Print a char in a form accepted by postscript printers.
768  */
769 static int printchar(unsigned char c) {
770 
771  if (c >= ' ' && c < 0177) {
772  if (c == '(' || c == ')' || c == '\\')
773  putchar('\\');
774  putchar(c);
775  return 0;
776  }
777 
778  if (ISOlatin1 && (c > 0177)) {
779  printf("\\%o", c);
780  return 0;
781  }
782 
783  if (only_printable) {
784  putchar(' ');
785  return 1;
786  }
787 
788  if (c > 0177) {
789  printf("M-");
790  c &= 0177;
791  }
792  if (c < ' ') {
793  putchar('^');
794  if ((c = c + '@') == '(' || c == ')' || c == '\\')
795  putchar('\\');
796  putchar(c);
797  }
798  else if (c == 0177)
799  printf("^?");
800  else {
801  if (c == '(' || c == ')' || c == '\\')
802  putchar('\\');
803  putchar(c);
804  }
805 
806  return 1;
807 }
808 
809 /*
810  * Begins a new logical page.
811  */
812 static void skip_page() {
813  if (twinpages == FALSE || sheetside == 0) {
814  printf("%%%%Page: %d %d\n", sheets+1, sheets+1);
815  printf("/pagesave save def\n");
816  // Reinitialize state variables for each new sheet
818  }
819  startpage();
820 }
821 
822 /*
823  * Fold a line too long.
824  */
825 static int fold_line(char *name) {
826  column = 0;
827  printf(") s\n");
828  if (++line >= linesperpage) {
829  endpage();
830  skip_page();
831  if (first_page && is_binaryfile(name))
832  return FALSE;
833  line = 0;
834  }
835  if (numbering)
836  printf("( +");
837  else
838  printf("( ");
839 
840  return TRUE;
841 }
842 
843 /*
844  * Cut a textline too long to the size of a page line.
845  */
846 static int cut_line() {
847  int c;
848  int status;
849 
850  while ((c = mygetc(&status)) != EOF && c != '\n' && c != '\f') ;
851  return c;
852 }
853 
854 
855 //**************************************************************
856 // "Postscript" routines.
857 //**************************************************************
858 
859 /*
860  * Print a physical page.
861  */
862 static void printpage() {
863  sheetside = 0;
864  sheets++;
865  printf("/sd 0 def\n");
866  if (no_border == FALSE)
867  printf("%d sn\n", sheets - (restart ? old_sheets : 0));
868  if (printdate)
869  printf("cd\n");
870  if (filename_footer && landscape)
871  printf("fnf\n");
872 #if defined(SYSV) || defined(BSD)
873  if (login_id)
874  printf("lg lgp\n");
875 #endif
876  printf("pagesave restore\n");
877  printf("showpage\n");
878 }
879 
880 /*
881  * Prints page header and page border and
882  * initializes printing of the file lines.
883  */
884 void startpage() {
885  if (sheetside == 0) {
886 #ifdef RECTO_VERSO_PRINTING
887  if (rectoverso && (sheets & 0x1)) {
888  // Shift to left backside pages.
889  printf("rm neg 0 translate\n");
890  }
891 #endif
892  if (landscape) {
893  printf("sw 0 translate\n");
894  printf("90 rotate\n");
895  }
896  }
897  pages++;
898  if (no_header == FALSE)
899  printf("%d hp\n", pages - old_pages);
900  if (no_border == FALSE) {
901  printf("border\n");
902  if (no_header == FALSE)
903  printf("hborder\n");
904  }
905  printf("/x0 x %d get bm add def\n", sheetside);
906  printf("/y0 y %d get bm bfs add %s add sub def\n",
907  sheetside, no_header ? "0" : "hs");
908  printf("x0 y0 moveto\n");
909  printf("bf setfont\n");
910 }
911 
912 /*
913  * Terminates printing, flushing last page.
914  */
915 static void cleanup() {
916  if (twinpages && sheetside == 1)
917  printpage();
918 #ifdef RECTO_VERSO_PRINTING
919  if (!twinfiles && rectoverso && (sheets & 0x1) != 0) {
920  sheetside = 0;
921  sheets++;
922  printf("%%%%Page: %d %d\n", sheets, sheets);
923  printf("showpage\n");
924  }
925 #endif
926 }
927 
928 /*
929  * Adds a sheet number to the page (footnote) and prints the formatted
930  * page (physical impression). Activated at the end of each source page.
931  */
932 void endpage() {
933  if (twinpages && sheetside == 0) {
934  sheetside = 1;
935  printf("/sd 1 def\n");
936  }
937  else
938  printpage();
939 }
940 
941 
942 //**************************************************************
943 // Printing a file
944 //**************************************************************
945 
946 /*
947  * Print the file prologue.
948  */
949 static void init_file_printing(char *name, char *title) {
950  int new_format, new_font;
951  char *string;
952  int lines;
953  float char_width;
954  struct stat statbuf;
955 
956  // Print last page of previous file, if necessary
957  if (pages > 0 && !twinfiles)
958  cleanup();
959 
960  // Initialize variables related to the format
961  new_format = FALSE;
962  if (new_landscape != landscape || new_twinpages != twinpages) {
963  landscape = new_landscape;
964  twinpages = new_twinpages;
965  new_format = TRUE;
966  }
967 
968  // Initialize variables related to the header
969  if (no_header && name == title)
970  header_size = 0.0;
971  else {
972  if (landscape || twinpages)
974  else
976  cut_filename(title, current_filename);
977  }
978 
979  // Initialize variables related to the font size
980  new_font = FALSE;
981  if (fontsize != new_fontsize || new_format ||
982  lines_requested != new_linesrequest || fontweight != new_fontweight)
983  {
984  if (new_fontsize == 0.0 || (fontsize == new_fontsize && new_format)) {
985  new_fontsize = landscape ? 6.8 : twinpages ? 6.4 : 9.0;
986  }
987  if (lines_requested != new_linesrequest) {
988  if ((lines_requested = new_linesrequest) != 0) {
989  // Scale fontsize
990  if (landscape) lines = (int)((page_width-header_size) / new_fontsize) - 1;
991  else if (twinpages) lines = (int)(((page_height - 2*header_size) / 2) / new_fontsize) - 2;
992  else lines = (int)((page_height-header_size) / new_fontsize) - 1;
993  new_fontsize *= (float)lines / (float)lines_requested;
994  }
995  }
998  new_font = TRUE;
999  }
1000 
1001  // Initialize file printing, if there is any change
1002  if (new_format || new_font) {
1003  char_width = 0.6 * fontsize;
1004  if (landscape) {
1005  linesperpage = (int)((page_width - header_size) / fontsize) - 1;
1006  if (! twinpages)
1007  columnsperline = (int)(page_height / char_width) - 1;
1008  else
1009  columnsperline = (int)((page_height / 2) / char_width) - 1;
1010  }
1011  else {
1012  if (!twinpages)
1013  linesperpage = (int)((page_height - header_size) / fontsize) - 1;
1014  else
1015  linesperpage = (int)(((page_height - 2*header_size) / 2) / fontsize)
1016  - 2;
1017  columnsperline = (int)(page_width / char_width) - 1;
1018  }
1019  if (lines_requested > 0)
1020  linesperpage = lines_requested;
1021  if (linesperpage <= 0 || columnsperline <= 0) {
1022  fprintf(stderr, "Font %g too big !!\n", fontsize);
1023  exit(EXIT_FAILURE);
1024  }
1025  }
1026 
1027  // Retrieve file modification date and hour
1028  if (fstat(fileno(stdin), &statbuf) == -1) {
1029  fprintf(stderr, "Error getting file modification time\n");
1030  exit(EXIT_FAILURE);
1031  }
1032  // Do we have a pipe?
1033  if (S_ISFIFO(statbuf.st_mode))
1034  strcpy(filedate, currentdate);
1035  else {
1036  string = ctime(&statbuf.st_mtime);
1037  sprintf(filedate, "%.6s %.4s %.5s", string+4, string+20, string+11);
1038  }
1039 }
1040 
1041 /*
1042  * Print the prologue necessary for printing each physical page.
1043  * Adobe convention for page independence is enforced through this routine.
1044  */
1045 void print_page_prologue(int side) {
1046  // side: Logical page to print (left/right)
1047 
1048  // General format
1049  printf("/twp %s def\n", twinpages ? "true" : "false");
1050  printf("/fnfs %d def\n", landscape ? 11 : twinpages ? 10 : 15);
1051  printf("/dfs fnfs 0.8 mul def\n");
1052  printf("/df /Helvetica dfs getfont def\n");
1053  printf("/dw df setfont td stringwidth pop def\n");
1054  printf("/sfnf filenmfontname fnfs getfont def\n");
1055  printf("/hm fnfs 0.25 mul def\n");
1056  // Header size
1057  if (header_size == 0.0)
1058  printf("/hs 0.0 def\n");
1059  else
1060  printf("/hs %g inch def\n",
1061  landscape || twinpages ? LANDSCAPE_HEADER : PORTRAIT_HEADER);
1062  // Font sizes
1063  printf("/bfs %g def\n", fontsize);
1064  printf("/bdf /Courier-Bold bfs getfont def\n");
1065  printf("/bm bfs 0.7 mul def\n");
1066  printf("/bf %s bfs getfont def\n",
1067  fontweight == NORMAL ? "/CourierBack" : "/Courier-Bold");
1068  // Page attributes
1069  printf("/l %d def\n", linesperpage);
1070  printf("/c %d def\n", columnsperline);
1071  printf("/pw\n");
1072  printf(" bf setfont (0) stringwidth pop c mul bm dup add add\n");
1073  printf(" def\n");
1074  printf("/ph\n");
1075  printf(" bfs l mul bm dup add add hs add\n");
1076  printf(" def\n");
1077  printf("/fns\n");
1078  printf(" pw\n");
1079  printf(" fnfs 4 mul dw add (Page 999) stringwidth pop add\n");
1080  printf(" sub\n");
1081  printf(" def\n");
1082  printf("/tm margin twp {3} {2} ifelse div def\n");
1083  printf("/sd %d def\n", side);
1084  if (landscape) {
1085  printf("/y [ rm ph add bm add\n");
1086  printf(" dup ] def\n");
1087  printf("/sny dfs dfs add def\n");
1088  printf("/snx sh tm dfs add sub def\n");
1089  printf("/dy sny def\n");
1090  printf("/dx tm dfs add def\n");
1091  if (twinpages) {
1092  printf("/x [ tm %% left page\n");
1093  printf(" dup 2 mul pw add %% right page\n");
1094  printf(" ] def\n");
1095  }
1096  else {
1097  printf("/x [ tm dup ] def\n");
1098  }
1099  printf("/scx sh 2 div def\n");
1100  }
1101  else {
1102  printf("/x [ lm dup ] def\n");
1103  printf("/sny tm dfs 2 mul sub def\n");
1104  printf("/snx sw rm sub dfs sub def\n");
1105  printf("/dy sny def\n");
1106  printf("/dx lm def\n");
1107  if (twinpages) {
1108  printf("/y [ tm ph add 2 mul %% up\n");
1109  printf(" tm ph add %% down\n");
1110  printf(" ] def\n");
1111  }
1112  else {
1113  printf("\n%% Only one logical page\n");
1114  printf("/y [ sh tm sub dup ] def\n");
1115  }
1116  printf("/scx sw 2 div def\n");
1117  }
1118  printf("/fny dy def\n");
1119  printf("/fnx scx def\n");
1120  printf("/ly fnfs 2 div y sd get add def\n");
1121  printf("/lx snx def\n");
1122  printf("/d (%s) def\n", filedate);
1123  printf("( %s ) fn\n", current_filename);
1124 }
1125 
1126 /*
1127  * Print one file.
1128  */
1129 static void print_file(char *name, char *header) {
1130  int c;
1131  int nchars;
1132  int start_line, start_page;
1133  int continue_exit;
1134  int status, new_status;
1135 
1136  // Reinitialize postscript variables depending on positional options
1137  init_file_printing(name, header ? header : name);
1138 
1139  // If we are in compact mode and the file beginning is to be printed
1140  // in the middle of a twinpage, we have to print a new page prologue
1141  if (twinfiles && sheetside == 1)
1143 
1144  /*
1145  * Boolean to indicates that previous char is \n (or interpreted \f)
1146  * and a new page would be started, if more text follows
1147  */
1148  start_page = FALSE;
1149 
1150  /*
1151  * Printing binary files is not very useful. We stop printing
1152  * if we detect one of these files. Our heuristic to detect them:
1153  * if 75% characters of first page are non-printing characters,
1154  * the file is a binary file.
1155  * Option -b force binary files impression.
1156  */
1157  nonprinting_chars = chars = 0;
1158 
1159  // Initialize printing variables
1160  column = 0;
1161  line = line_number = 0;
1162  first_page = TRUE;
1163  start_line = TRUE;
1164  prefix_width = numbering ? 6 : 1;
1165 
1166  // Start printing
1167  skip_page();
1168 
1169  // Process each character of the file
1170  status = IS_ROMAN;
1171  c = mygetc(&new_status);
1172  while (c != EOF) {
1173  /*
1174  * Preprocessing (before printing):
1175  * - TABs expansion (see interpret option)
1176  * - FF and BS interpretation
1177  * - replace non printable characters by a space or a char sequence
1178  * like:
1179  * ^X for ascii codes < 0x20 (X = [@, A, B, ...])
1180  * ^? for del char
1181  * M-c for ascii codes > 0x3f
1182  * - prefix parents and backslash ['(', ')', '\'] by backslash
1183  * (escape character in postscript)
1184  */
1185  // Form feed
1186  if (c == '\f' && interpret) {
1187  // Close current line
1188  if (!start_line) {
1189  printf(") s\n");
1190  start_line = TRUE;
1191  }
1192  // start a new page ?
1193  if (start_page)
1194  skip_page();
1195  // Close current page and begin another
1196  endpage();
1197  start_page = TRUE;
1198  // Verification for binary files
1199  if (first_page && is_binaryfile(name))
1200  return;
1201  line = 0;
1202  column = 0;
1203  if ((c = mygetc(&new_status)) == EOF)
1204  break;
1205  }
1206 
1207  // Start a new line ?
1208  if (start_line) {
1209  if (start_page) {
1210  // only if there is something to print!
1211  skip_page();
1212  start_page = FALSE;
1213  }
1214  if (numbering)
1215  printf("(%4d|", ++line_number);
1216  else
1217  printf("( ");
1218  start_line = FALSE;
1219  }
1220 
1221  // Is a new font ? This feature is used only to detect bold
1222  // sequences produced by nroff (man pages), in connexion with
1223  // mygetc.
1224  if (status != new_status) {
1225  printf(")\n");
1226  printf("%s", status == IS_ROMAN ? "b" : "st");
1227  printf(" (");
1228  status = new_status;
1229  }
1230 
1231  // Interpret each character
1232  switch (c) {
1233  case '\b':
1234  if (!interpret)
1235  goto print;
1236  // A backspace is converted to 2 chars ('\b'). These chars
1237  // with the Courier backspace font produce correct under-
1238  // lined strings.
1239  if (column)
1240  column--;
1241  putchar('\\');
1242  putchar('b');
1243  break;
1244  case '\n':
1245  column = 0;
1246  start_line = TRUE;
1247  printf(") s\n");
1248  if (++line >= linesperpage) {
1249  endpage();
1250  start_page = TRUE;
1251  if (first_page && is_binaryfile(name))
1252  return;
1253  line = 0;
1254  }
1255  break;
1256  case '\t':
1257  if (interpret) {
1258  continue_exit = FALSE;
1259  do {
1260  if (++column + prefix_width > columnsperline) {
1261  if (folding) {
1262  if (fold_line(name) == FALSE)
1263  return;
1264  }
1265  else {
1266  c = cut_line();
1267  continue_exit = TRUE;
1268  break;
1269  }
1270  }
1271  putchar(' ');
1272  } while (column % column_width);
1273  if (continue_exit)
1274  continue;
1275  break;
1276  }
1277  default:
1278  print :
1279  if (only_printable) {
1280  nchars = 1;
1281  }
1282  else if (! ISOlatin1) {
1283  nchars = c > 0177 ? 2 : 0;
1284  nchars += (c&0177) < ' ' || (c&0177) == 0177 ? 2 : 1;
1285  }
1286  else {
1287  nchars = c < ' ' || (c >= 0177 && c < 144) ? 2 : 1;
1288  }
1289 
1290  if (prefix_width + (column += nchars) > columnsperline) {
1291  if (folding) {
1292  if (fold_line(name) == FALSE) {
1293  return;
1294  }
1295  }
1296  else {
1297  c = cut_line();
1298  new_status = IS_ROMAN;
1299  continue;
1300  }
1301  }
1302  nonprinting_chars += printchar(c);
1303  chars++;
1304  break;
1305  }
1306  c = mygetc(&new_status);
1307  }
1308 
1309  if (!start_line)
1310  printf(") s\n");
1311  if (!start_page)
1312  endpage();
1313 }
1314 
1315 
1316 //**************************************************************
1317 // Print a postscript prologue for a2ps.
1318 //**************************************************************
1319 
1320 /*
1321  * Print the a2ps prologue.
1322  */
1323 static void print_prologue() {
1324  int c;
1325  FILE *f = NULp;
1326  char *datestring;
1327 #if defined(SYSV) || defined(BSD)
1328  char *logname, *host;
1329  int rt;
1330 #endif
1331 #if defined(SYSV)
1332  struct utsname snames;
1333 #endif
1334 
1335  // Retrieve date and hour
1336 #if defined(__STDC__)
1337  time_t date;
1338 
1339  if (time(&date) == -1) {
1340  fprintf(stderr, "Error calculating time\n");
1341  exit(EXIT_FAILURE);
1342  }
1343  datestring = ctime(&date);
1344 #else
1345 #ifdef BSD
1346  struct timeval date;
1347  struct tm *p;
1348 
1349  (void) gettimeofday(&date, (struct timezone *)0);
1350  p = localtime(&date.tv_sec);
1351  datestring = asctime(p);
1352 #else
1353 #ifdef SYSV
1354  struct timeb date;
1355 
1356  (void)ftime(&date);
1357  datestring = ctime(&date.time);
1358 #else
1359 
1360  datestring = "--- --- -- --:--:-- ----";
1361 #endif
1362 #endif
1363 #endif
1364 
1365 #if defined(SYSV) || defined(BSD)
1366  // Retrieve user's login name and hostname
1367  logname = getlogin();
1368  host = (char *)malloc(MAX_HOSTNAME);
1369  if (host) {
1370 #if defined(SYSV)
1371  if ((rt = uname(&snames)) == -1 || !snames.nodename[0]) {
1372  free(host);
1373  host = NULp;
1374  }
1375  else
1376  strcpy(host, snames.nodename);
1377 #else
1378  if ((rt = gethostname(host, MAX_HOSTNAME)) == -1 || !host[0]) {
1379  free(host);
1380  host = NULp;
1381  }
1382 #endif
1383  }
1384 #endif
1385 
1386  // Print a general prologue
1387  if (!prologue)
1388  print_standard_prologue(datestring);
1389  else if ((f = fopen(prologue, "r"))) {
1390  // Header file printing
1391  while ((c = getc(f)) != EOF)
1392  putchar(c);
1393  }
1394  else {
1395  fprintf(stderr, "Postscript header missing: %s\n", prologue);
1396  exit(EXIT_FAILURE);
1397  }
1398 
1399  // Completes the prologue with a2ps static variables
1400  printf("\n%% Initialize page description variables.\n");
1401  printf("/x0 0 def\n");
1402  printf("/y0 0 def\n");
1403  printf("/sh %g inch def\n", (double)HEIGHT);
1404  printf("/sw %g inch def\n", (double)WIDTH);
1405  printf("/margin %g inch def\n", (double)MARGIN);
1406  printf("/rm margin 3 div def\n");
1407  printf("/lm margin 2 mul 3 div def\n");
1408  printf("/d () def\n");
1409 
1410  // And print them
1411  sprintf(currentdate, "%.6s %.4s %.5s",
1412  datestring+4, datestring+20, datestring+11);
1413  printf("/td (%s) def\n", currentdate);
1414 
1415 #if defined(SYSV) || defined(BSD)
1416  // Add the user's login name string to the Postscript output
1417  if (logname || host) {
1418  if (logname && host)
1419  printf("/lg (Printed by %s from %s) def\n", logname, host);
1420  else if (logname)
1421  printf("/lg (Printed by %s) def\n", logname);
1422  else
1423  printf("/lg (Printed from %s) def\n", host);
1424  }
1425 
1426  // If the host string was allocated via malloc, release the memory
1427  if (host)
1428  free(host);
1429 #endif
1430 
1431  // Close prolog
1432  printf("%%%%EndProlog\n\n");
1433 
1434  // Go on
1435  printf("/docsave save def\n");
1436  if (f) fclose(f);
1437 }
1438 
1439 /*
1440  * Print the standard prologue.
1441  */
1442 void print_standard_prologue(char *datestring) {
1443  printf("%%!PS-Adobe-3.0\n");
1444  printf("%%%%Creator: A2ps version %s\n", VERSION);
1445  printf("%%%%CreationDate: %.24s\n", datestring);
1446  printf("%%%%Pages: (atend)\n");
1447  printf("%%%%DocumentFonts: Courier Courier-Bold Helvetica Helvetica-Bold\n");
1448  printf("%%%%EndComments\n");
1449  printf("%% Copyright (c) 1993, 1994, Miguel Santana, M.Santana@frgu.bull.fr\n");
1450  printf("\n/$a2psdict 100 dict def\n");
1451  printf("$a2psdict begin\n");
1452  printf("\n%% General macros.\n");
1453  printf("/xdef {exch def} bind def\n");
1454  printf("/getfont {exch findfont exch scalefont} bind def\n");
1455 
1456  if (ISOlatin1) {
1457  printf("\n%% Set up ISO Latin 1 character encoding\n");
1458  printf("/reencodeISO {\n");
1459  printf(" dup dup findfont dup length dict begin\n");
1460  printf(" { 1 index /FID ne { def }{ pop pop } ifelse\n");
1461  printf(" } forall\n");
1462  printf(" /Encoding ISOLatin1Encoding def\n");
1463  printf(" currentdict end definefont\n");
1464  printf("} def\n");
1465  printf("/Helvetica-Bold reencodeISO def\n");
1466  printf("/Helvetica reencodeISO def\n");
1467  printf("/Courier reencodeISO def\n");
1468  printf("/Courier-Bold reencodeISO def\n");
1469  }
1470 
1471  printf("\n%% Create Courier backspace font\n");
1472  printf("/backspacefont {\n");
1473  printf(" /Courier findfont dup length dict begin\n");
1474  printf(" { %% forall\n");
1475  printf(" 1 index /FID eq { pop pop } { def } ifelse\n");
1476  printf(" } forall\n");
1477  printf(" currentdict /UniqueID known { %% if\n");
1478  printf(" /UniqueID UniqueID 16#800000 xor def\n");
1479  printf(" } if\n");
1480  printf(" CharStrings length 1 add dict begin\n");
1481  printf(" CharStrings { def } forall\n");
1482  printf(" /backspace { -600 0 0 0 0 0 setcachedevice } bind def\n");
1483  printf(" currentdict\n");
1484  printf(" end\n");
1485  printf(" /CharStrings exch def\n");
1486  printf(" /Encoding Encoding 256 array copy def\n");
1487  printf(" Encoding 8 /backspace put\n");
1488  printf(" currentdict\n");
1489  printf(" end\n");
1490  printf(" definefont pop\n");
1491  printf("} bind def\n");
1492 
1493  printf("\n%% FUNCTIONS\n");
1494  printf("\n%% Function filename: Initialize file printing.\n");
1495  printf("/fn\n");
1496  printf("{ /filenm xdef\n");
1497  printf(" /filenmwidth filenm stringwidth pop def\n");
1498  printf(" /filenmfont\n");
1499  printf(" filenmwidth fns gt\n");
1500  printf(" {\n");
1501  printf(" filenmfontname\n");
1502  printf(" fnfs fns mul filenmwidth div\n");
1503  printf(" getfont\n");
1504  printf(" }\n");
1505  printf(" { sfnf }\n");
1506  printf(" ifelse\n");
1507  printf(" def\n");
1508  printf("} bind def\n");
1509  printf("\n%% Function header: prints page header. no page\n");
1510  printf("%% is passed as argument.\n");
1511  printf("/hp\n");
1512  printf(" { x sd get y sd get hs sub 1 add moveto\n");
1513  printf(" df setfont\n");
1514  printf(" gsave\n");
1515  printf(" x sd get y sd get moveto\n");
1516  printf(" 0 hs 2 div neg rmoveto \n");
1517  printf(" hs setlinewidth\n");
1518  printf(" 0.95 setgray\n");
1519  printf(" pw 0 rlineto stroke\n");
1520  printf(" grestore\n");
1521  printf(" gsave\n");
1522  printf(" dfs hm rmoveto\n");
1523  printf(" d show %% date/hour\n");
1524  printf(" grestore\n");
1525  printf(" gsave\n");
1526  printf(" pnum cvs pop %% page pop up\n");
1527  printf(" pw (Page 999) stringwidth pop sub\n");
1528  printf(" hm\n");
1529  printf(" rmoveto\n");
1530  printf(" (Page ) show pnum show %% page number\n");
1531  printf(" grestore\n");
1532  printf(" empty pnum copy pop\n");
1533  printf(" gsave\n");
1534  printf(" filenmfont setfont\n");
1535  printf(" fns filenm stringwidth pop sub 2 div dw add\n");
1536  printf(" bm 2 mul \n");
1537  printf(" add \n");
1538  printf(" hm\n");
1539  printf(" rmoveto\n");
1540  printf(" filenm show %% file name\n");
1541  printf(" grestore\n");
1542  printf(" } bind def\n");
1543  printf("\n%% Function border: prints border page\n");
1544  printf("/border \n");
1545  printf("{ x sd get y sd get moveto\n");
1546  printf(" gsave %% print four sides\n");
1547  printf(" 0.7 setlinewidth %% of the square\n");
1548  printf(" pw 0 rlineto\n");
1549  printf(" 0 ph neg rlineto\n");
1550  printf(" pw neg 0 rlineto\n");
1551  printf(" closepath stroke\n");
1552  printf(" grestore\n");
1553  printf("} bind def\n");
1554  printf("\n%% Function hborder: completes border of the header.\n");
1555  printf("/hborder \n");
1556  printf("{ gsave\n");
1557  printf(" 0.7 setlinewidth\n");
1558  printf(" 0 hs neg rmoveto\n");
1559  printf(" pw 0 rlineto\n");
1560  printf(" stroke\n");
1561  printf(" grestore\n");
1562  printf("} bind def\n");
1563  printf("\n%% Function sheetnumber: prints the sheet number.\n");
1564  printf("/sn\n");
1565  printf(" { snx sny moveto\n");
1566  printf(" df setfont\n");
1567  printf(" pnum cvs\n");
1568  printf(" dup stringwidth pop (0) stringwidth pop sub neg 0 rmoveto show\n");
1569  printf(" empty pnum copy pop\n");
1570  printf(" } bind def\n");
1571  printf("\n%% Function loginprint: prints the login id of the requestor.\n");
1572  printf("/lgp\n");
1573  printf(" { lx ly moveto\n");
1574  printf(" df setfont\n");
1575  printf(" dup stringwidth pop neg 0 rmoveto show\n");
1576  printf(" } bind def\n");
1577  printf("\n%% Function currentdate: prints the current date.\n");
1578  printf("/cd\n");
1579  printf(" { dx dy moveto\n");
1580  printf(" df setfont\n");
1581  printf(" (Printed: ) show\n");
1582  printf(" td show\n");
1583  printf(" } bind def\n");
1584  printf("\n%% Function filename_footer: prints the file name at bottom of page.\n");
1585  printf("/fnf\n");
1586  printf(" { fnx fny moveto\n");
1587  printf(" df setfont\n");
1588  printf(" filenm center show\n");
1589  printf(" } bind def\n");
1590  printf("\n%% Function center: centers text.\n");
1591  printf("/center\n");
1592  printf(" { dup stringwidth pop\n");
1593  printf(" 2 div neg 0 rmoveto\n");
1594  printf(" } bind def\n");
1595  printf("\n%% Function s: print a source line\n");
1596  printf("/s { show\n");
1597  printf(" /y0 y0 bfs sub def\n");
1598  printf(" x0 y0 moveto\n");
1599  printf(" } bind def\n");
1600  printf("\n%% Functions b and st: change to bold or standard font\n");
1601  printf("/b { show\n");
1602  printf(" bdf setfont\n");
1603  printf(" } bind def\n");
1604  printf("/st { show\n");
1605  printf(" bf setfont\n");
1606  printf(" } bind def\n");
1607  printf("\n%% Strings used to make easy printing numbers\n");
1608  printf("/pnum 12 string def\n");
1609  printf("/empty 12 string def\n");
1610  printf("\n%% Global initializations\n");
1611  printf("\n/CourierBack backspacefont\n");
1612  printf("/filenmfontname /Helvetica-Bold def\n");
1613  printf("/inch {72 mul} bind def\n");
1614 
1615  printf("\n%%\n");
1616  printf("%% Meaning of some variables and functions (coded names)\n");
1617  printf("%%\n");
1618  printf("%% twp: twinpages?\n");
1619  printf("%% sd: sheet side\n");
1620  printf("%% l: line counter\n");
1621  printf("%% c: column counter\n");
1622  printf("%% d: date\n");
1623  printf("%% td: current date (for today)\n");
1624  printf("%% lg: login name\n");
1625  printf("%% fn: filename printing function\n");
1626  printf("%% sn: sheetnumber printing function\n");
1627  printf("%% cd: current date printing function\n");
1628  printf("%% fnf: filename footer printing function\n");
1629  printf("%% lgp: login printing function\n");
1630  printf("%% hp: header printing function\n");
1631  printf("%% y: y coordinate for the logical page\n");
1632  printf("%% x: x coordinate for the logical page\n");
1633  printf("%% sny: y coordinate for the sheet number\n");
1634  printf("%% snx: x coordinate for the sheet number\n");
1635  printf("%% dy: y coordinate for the date\n");
1636  printf("%% dx: x coordinate for the date\n");
1637  printf("%% ly: y coordinate for the login\n");
1638  printf("%% lx: x coordinate for the login\n");
1639  printf("%% scx: x coordinate for the sheet center\n");
1640  printf("%% fny: y coordinate for the filename (footer)\n");
1641  printf("%% fnx: x coordinate for the filename (footer)\n");
1642  printf("%% fnfs: filename font size\n");
1643  printf("%% bfs: body font size\n");
1644  printf("%% dfs: date font size\n");
1645  printf("%% bfs: body font size\n");
1646  printf("%% df: date font\n");
1647  printf("%% bf: body font\n");
1648  printf("%% bdf: bold font\n");
1649  printf("%% sfnf: standard filename font\n");
1650  printf("%% dw: date width\n");
1651  printf("%% pw: page width\n");
1652  printf("%% sw: sheet width\n");
1653  printf("%% ph: page height\n");
1654  printf("%% sh: sheet height\n");
1655  printf("%% hm: header margin\n");
1656  printf("%% tm: top margin\n");
1657  printf("%% bm: body margin\n");
1658  printf("%% rm: right margin\n");
1659  printf("%% lm: left margin\n");
1660  printf("%% hs: header size\n");
1661  printf("%% fns: filename size\n");
1662 }
1663 
1664 
1665 /*
1666  * Main routine for a2ps.
1667  */
1668 int ARB_main(int argc, char *cargv[]) {
1669  char **argv = (char**)cargv;
1670  int narg;
1671  char *arg;
1672  int total;
1673 #if LPR_PRINT
1674  int fd[2];
1675  const char *lpr_args[10];
1676 #endif
1677 
1678  // Process global options
1679  command = argv[0];
1680  arg = argv[narg = 1];
1681  while (narg < argc) {
1682  if (arg[0] == '-')
1683  set_global_option(arg);
1684  arg = argv[++narg];
1685  }
1686 
1687 #if LPR_PRINT
1688  // Start lpr process
1689  if (lpr_print) {
1690  if (pipe(fd) != 0) {
1691  fprintf(stderr, "Could not create pipe (Reason: %s)\n", strerror(errno));
1692  exit(EXIT_FAILURE);
1693  }
1694 
1695  if (fork() == 0) {
1696  dup2(fd[0], 0);
1697  close(fd[0]); close(fd[1]);
1698  narg = 0;
1699  lpr_args[narg++] = LPR_COMMAND;
1700 #ifdef LPR_OPT
1701  lpr_args[narg++] = LPR_OPT;
1702 #endif
1703  if (lpr_opt)
1704  lpr_args[narg++] = lpr_opt;
1705 #ifdef RECTO_VERSO_PRINTING
1706  if (rectoverso)
1707  lpr_args[narg++] = TWOSIDED;
1708  else
1709  lpr_args[narg++] = ONESIDED;
1710 #endif
1711  lpr_args[narg] = (char *)0;
1712  execvp(LPR_COMMAND, (char**)lpr_args);
1713  fprintf(stderr, "Error starting lpr process \n");
1714  exit(EXIT_FAILURE);
1715  }
1716  dup2(fd[1], 1);
1717  close(fd[0]);
1718  close(fd[1]);
1719  }
1720 #endif
1721 
1722  // Initialize variables not depending of positional options
1723  landscape = twinpages = -1; // To force format switching
1724  fontsize = -1.0; // To force fontsize switching
1725  page_height = (double)(HEIGHT - MARGIN) * PIXELS_INCH;
1726  page_width = (double)(WIDTH - MARGIN) * PIXELS_INCH;
1727 
1728  // Postscript prologue printing
1729  print_prologue();
1730 
1731  // Print files designated or standard input
1732  arg = argv[narg = 1];
1733  while (narg < argc) {
1734  if (arg[0] != NUL) {
1735  if (arg[0] == '-')
1736  set_positional_option(arg);
1737  else {
1738  if (!freopen(arg, "r", stdin)) {
1739  fprintf(stderr, "Error opening %s\n", arg);
1740  cleanup();
1741  printf("\n%%%%Trailer\ndocsave restore end\n\4");
1742  exit(EXIT_FAILURE);
1743  }
1744  no_files = FALSE;
1745 
1746  // Save counters values
1747  old_pages = pages;
1748  if (twinfiles && twinpages)
1749  old_sheets = sheets;
1750  else
1751  old_sheets = sheets + sheetside;
1752 
1753  // Print the file
1754  print_file(arg, header_text);
1755 
1756  // Print the number of pages and sheets printed
1757  if (no_summary == FALSE) {
1758  total = pages - old_pages;
1759  fprintf(stderr, "[%s: %d page%s on ", arg,
1760  total, total == 1 ? "" : "s");
1761  total = sheets - old_sheets + sheetside;
1762 #ifdef RECTO_VERSO_PRINTING
1763  if (rectoverso)
1764  total = (total+1) / 2;
1765 #endif
1766  fprintf(stderr, "%d sheet%s]\n", total, total == 1 ? "" : "s");
1767  }
1768 
1769  // Reinitialize header title
1770  header_text = NULp;
1771  }
1772  }
1773  arg = argv[++narg];
1774  }
1775  if (no_files)
1776  print_file((char*)"stdin", header_text);
1777 
1778  // Print the total number of pages printed
1779  if (no_summary == FALSE && pages != old_pages) {
1780  fprintf(stderr, "[Total: %d page%s on ", pages, pages == 1 ? "" : "s");
1781  total = sheets + sheetside;
1782 #ifdef RECTO_VERSO_PRINTING
1783  if (rectoverso)
1784  total = (total+1) / 2;
1785 #endif
1786  fprintf(stderr, "%d sheet%s]\n", total, total == 1 ? "" : "s");
1787  }
1788 
1789  // And stop
1790  cleanup();
1791  printf("\n%%%%Trailer\n");
1792  printf("%%%%Pages: %d\n", sheets + sheetside);
1793  printf("docsave restore end\n");
1794 
1795  exit(EXIT_SUCCESS);
1796 }
char * getlogin()
static int cut_line()
Definition: arb_a2ps.c:846
return string(buffer, length)
static int lines_requested
Definition: arb_a2ps.c:303
#define IS_BOLD
Definition: arb_a2ps.c:224
#define MAN_LINES
Definition: arb_a2ps.c:222
static int new_linesrequest
Definition: arb_a2ps.c:304
static int chars
Definition: arb_a2ps.c:306
#define NULp
Definition: arb_a2ps.c:148
static void print_page_prologue(int side)
Definition: arb_a2ps.c:1045
static char currentdate[18]
Definition: arb_a2ps.c:325
static int only_printable
Definition: arb_a2ps.c:265
static char filedate[18]
Definition: arb_a2ps.c:326
static void startpage()
Definition: arb_a2ps.c:884
static void print_prologue()
Definition: arb_a2ps.c:1323
static void print_standard_prologue(char *datestring)
Definition: arb_a2ps.c:1442
static int interpret
Definition: arb_a2ps.c:266
static void print_file(char *name, char *header)
Definition: arb_a2ps.c:1129
static int no_border
Definition: arb_a2ps.c:274
const char * title
Definition: readseq.c:22
int gethostname(char *name, int namelen)
static float fontsize
Definition: arb_a2ps.c:317
static int no_files
Definition: arb_a2ps.c:315
static int printchar(unsigned char c)
Definition: arb_a2ps.c:769
static void set_positional_option(char *arg)
Definition: arb_a2ps.c:554
char * login
Definition: arb_a2ps.c:328
static void skip_page()
Definition: arb_a2ps.c:812
static char * lpr_opt
Definition: arb_a2ps.c:320
#define EXIT_SUCCESS
Definition: arb_a2ps.c:154
static int copies_number
Definition: arb_a2ps.c:307
static double page_width
Definition: arb_a2ps.c:336
static char current_filename[MAXFILENAME+1]
Definition: arb_a2ps.c:324
#define IS_ROMAN
Definition: arb_a2ps.c:223
char buffer[MESSAGE_BUFFERSIZE]
Definition: seq_search.cxx:34
WEIGHT
Definition: arb_a2ps.c:240
#define MARGIN
Definition: arb_a2ps.c:179
int ARB_main(int argc, char *cargv[])
Definition: arb_a2ps.c:1668
static int linesperpage
Definition: arb_a2ps.c:302
static int no_summary
Definition: arb_a2ps.c:277
static int nonprinting_chars
Definition: arb_a2ps.c:306
static int sheetside
Definition: arb_a2ps.c:301
#define PIXELS_INCH
Definition: arb_a2ps.c:219
static int new_twinpages
Definition: arb_a2ps.c:271
static int is_binaryfile(char *name)
Definition: arb_a2ps.c:724
static int no_header
Definition: arb_a2ps.c:273
#define PORTRAIT_HEADER
Definition: arb_a2ps.c:217
#define LPR_OPT
Definition: arb_a2ps.c:201
static int sheets
Definition: arb_a2ps.c:299
int login_id
Definition: arb_a2ps.c:281
#define FALSE
Definition: arb_a2ps.c:145
static int new_landscape
Definition: arb_a2ps.c:269
static WEIGHT fontweight
Definition: arb_a2ps.c:278
#define DIR_SEP
Definition: arb_a2ps.c:187
#define LANDSCAPE_HEADER
Definition: arb_a2ps.c:218
static void cut_filename(char *old_name, char *new_name)
Definition: arb_a2ps.c:738
static char * header_text
Definition: arb_a2ps.c:321
static int print_binaries
Definition: arb_a2ps.c:267
static void endpage()
Definition: arb_a2ps.c:932
static int twinpages
Definition: arb_a2ps.c:270
static char * prologue
Definition: arb_a2ps.c:323
static int columnsperline
Definition: arb_a2ps.c:305
static BasicStatus status
static void usage(int failure)
Definition: arb_a2ps.c:347
static void printpage()
Definition: arb_a2ps.c:862
static int ISOlatin1
Definition: arb_a2ps.c:289
#define EXIT_FAILURE
Definition: arb_a2ps.c:157
#define HEIGHT
Definition: arb_a2ps.c:175
static int twinfiles
Definition: arb_a2ps.c:272
static int first_page
Definition: arb_a2ps.c:314
static float new_fontsize
Definition: arb_a2ps.c:318
static int lpr_print
Definition: arb_a2ps.c:284
static double page_height
Definition: arb_a2ps.c:335
#define MAX_HOSTNAME
Definition: arb_a2ps.c:226
static void init_file_printing(char *name, char *title)
Definition: arb_a2ps.c:949
static void cleanup()
Definition: arb_a2ps.c:915
#define MAXFILENAME
Definition: arb_a2ps.c:220
static int filename_footer
Definition: arb_a2ps.c:276
static int fold_line(char *name)
Definition: arb_a2ps.c:825
static int pages
Definition: arb_a2ps.c:298
static int numbering
Definition: arb_a2ps.c:262
#define VERSION
Definition: arb_a2ps.c:164
#define WIDTH
Definition: arb_a2ps.c:171
static void set_global_option(char *arg)
Definition: arb_a2ps.c:402
static int old_pages
Definition: arb_a2ps.c:300
#define NUL
Definition: arb_a2ps.c:151
static int prefix_width
Definition: arb_a2ps.c:316
static int printdate
Definition: arb_a2ps.c:275
static int line
Definition: arb_a2ps.c:296
Definition: arb_a2ps.c:240
static int mygetc(int *statusp)
Definition: arb_a2ps.c:682
static WEIGHT new_fontweight
Definition: arb_a2ps.c:279
static char * command
Definition: arb_a2ps.c:319
static float header_size
Definition: arb_a2ps.c:322
static int landscape
Definition: arb_a2ps.c:268
#define TRUE
Definition: arb_a2ps.c:146
#define LPR_COMMAND
Definition: arb_a2ps.c:197
static int old_sheets
Definition: arb_a2ps.c:300
#define MAX_LINES
Definition: arb_a2ps.c:221
static int restart
Definition: arb_a2ps.c:264
#define BUFFER_SIZE
static int line_number
Definition: arb_a2ps.c:297
static int column_width
Definition: arb_a2ps.c:308
static int folding
Definition: arb_a2ps.c:263
void print(const T &t)
Definition: test_unit.h:348