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  break; // silence warning (never reached)
408  case 'b': // print binary files
409  if (arg[2] != NUL)
411  print_binaries = TRUE;
412  break;
413  case 'c': // allow two files per sheet
414  if (arg[2] != NUL)
416  twinfiles = TRUE;
417  break;
418  case 'f': // fold lines too large
419  if (arg[2] != NUL)
421  folding = TRUE;
422  break;
423  case 'I': // include this file as a2ps prologue
424  if (arg[2] == NUL)
426  prologue = arg+2;
427  break;
428  case 'i': // interpret control chars
429  if (arg[2] != NUL)
431  interpret = TRUE;
432  break;
433  case 'n':
434  if (arg[2] == NUL)
435  return;
436  if (arg[3] != NUL)
438  switch (arg[2]) {
439  case 'b': // don't print binaries
440  print_binaries = FALSE;
441  break;
442  case 'c': // don't allow 2 files/sheet
443  twinfiles = FALSE;
444  break;
445  case 'f': // cut lines too long
446  folding = FALSE;
447  break;
448  case 'H': // don't print header
449  no_header = TRUE;
450  break;
451  case 'i': // don't interpret ctrl chars
452  interpret = FALSE;
453  break;
454 #if LPR_PRINT
455  case 'P': // don't lpr
456  lpr_print = FALSE;
457  break;
458 #endif
459  case 'r': // don't restart sheet number
460  restart = FALSE;
461  break;
462  case 'v': // only printable chars
463  only_printable = TRUE;
464  break;
465  case '8': // don't print 8-bit chars
466  ISOlatin1 = FALSE;
467  break;
468  case 'B':
469  case 'd':
470  case 'L':
471  case 'm':
472  case 'n':
473  case 's':
474  case 'u':
475  if (arg[3] != NUL)
477  return;
478  default:
480  }
481  break;
482 #if LPR_PRINT
483  case 'P': // fork a process to print
484  if (arg[2] != NUL) {
485  lpr_opt = (char *)malloc(strlen(arg)+1);
486  strcpy(lpr_opt, arg);
487  }
488  lpr_print = TRUE;
489  break;
490 #endif
491  case 'q': // don't print a summary
492  no_summary = TRUE;
493  break;
494  case 'r': // restart sheet number
495  if (arg[2] != NUL)
497  restart = TRUE;
498  break;
499  case 's':
500  if (arg[2] == NUL)
501  return;
502 #ifdef RECTO_VERSO_PRINTING
503  if (arg[3] == NUL) {
504  if (arg[2] == '1') { // one-sided printing
505  rectoverso = FALSE;
506  break;
507  }
508  if (arg[2] == '2') { // two-sided printing
509  rectoverso = TRUE;
510  break;
511  }
512  }
513 #endif
515  break;
516  case 't': // set tab size
517  if (arg[2] == NUL || (column_width = atoi(arg+2)) <= 0)
519  break;
520  case 'v': // print control chars
521  if (arg[2] != NUL)
523  only_printable = FALSE;
524  break;
525  case '8': // print 8-bit chars
526  if (arg[2] != NUL)
528  ISOlatin1 = TRUE;
529  break;
530  case '1':
531  case '2':
532  case 'B':
533  case 'd':
534  case 'm':
535  case 'p':
536  if (arg[2] != NUL)
538  case '#':
539  case 'F':
540  case 'H':
541  case 'l':
542  return;
543  default:
545  }
546  arg[0] = NUL;
547 }
548 
549 /*
550  * Set an option of the command line. This option will be applied
551  * to all files that will be found in the rest of the command line.
552  * The -H option is the only exception: it is applied only to the
553  * file.
554  */
555 static void set_positional_option(char *arg) {
556  int copies;
557  int lines;
558  float size;
559 
560  switch (arg[1]) {
561  case NUL: // global option
562  break;
563  case '#': // n copies
564  if (sscanf(&arg[2], "%d", &copies) != 1 || copies <= 0)
565  fprintf(stderr, "Bad number of copies: '%s'. Ignored\n", &arg[2]);
566  else
567  copies_number = copies;
568  printf("/#copies %d def\n", copies_number);
569  break;
570  case '1': // 1 logical page per sheet
571  if (arg[2] != NUL)
573  new_twinpages = FALSE;
574  break;
575  case '2': // twin pages
576  if (arg[2] != NUL)
578  new_twinpages = TRUE;
579  break;
580  case 'B':
581  new_fontweight = BOLD; // use bold font
582  break;
583  case 'd': // print current date/time
584  printdate = TRUE;
585  break;
586  case 'F': // change font size
587  if (arg[2] == NUL || sscanf(&arg[2], "%f", &size) != 1 || size == 0.0) {
588  fprintf(stderr, "Wrong value for option -F: '%s'. Ignored\n",
589  &arg[2]);
590  break;
591  }
592  new_fontsize = size;
593  break;
594  case 'H': // header text
595  header_text = arg+2;
596  break;
597  case 'l':
598  if (arg[2] == NUL) { // landscape format
599  new_landscape = TRUE;
600  break;
601  }
602  // set lines per page
603  // Useful with preformatted files. Scaling is automatically
604  // done when necessary.
605  if (sscanf(&arg[2], "%d", &lines) != 1
606  || lines < 0 || lines > MAX_LINES)
607  {
608  fprintf(stderr, "Wrong value for option -l: '%s'. Ignored\n",
609  &arg[2]);
610  break;
611  }
612  new_linesrequest = lines;
613  break;
614  case 'm': // Process file as a man
615  new_linesrequest = MAN_LINES;
616  numbering = FALSE;
617  break;
618  case 'n': // number file lines
619  if (arg[2] == NUL) {
620  numbering = TRUE;
621  break;
622  }
623  switch (arg[2]) {
624  case 'B': // disable bold text
626  break;
627  case 'd': // don't print date/time
628  printdate = FALSE;
629  break;
630 #if defined(SYSV) || defined(BSD)
631  case 'L': // no login name in footer
632  login_id = FALSE;
633  break;
634 #endif
635  case 'l': // portrait format
636  new_landscape = FALSE;
637  break;
638  case 'm': // stop processing as a man
639  new_linesrequest = 0;
640  break;
641  case 'n': // don't number lines
642  numbering = FALSE;
643  break;
644  case 'p': // landscape format
645  new_landscape = TRUE;
646  break;
647  case 's': // no surrounding border
648  no_border = TRUE;
649  break;
650  case 'u': // no filename in footer
651  filename_footer = FALSE;
652  break;
653  default:
655  }
656  break;
657  case 'p': // portrait format
658  if (arg[2] != NUL)
660  new_landscape = FALSE;
661  break;
662  case 's': // surrounding border
663  if (arg[2] != NUL)
665  no_border = FALSE;
666  break;
667  default:
669  }
670 }
671 
672 
673 //**************************************************************
674 // Service routines
675 //**************************************************************
676 
677 /*
678  * This routine buffers a line of input, release one character at a time
679  * or a whole sequence of characters with some meaning like bold sequences
680  * produced by nroff (no others sequences are recognized by the moment):
681  * <c><\b><c><\b><c><\b><c>
682  */
683 static int mygetc(int *statusp) {
684 #define BUFFER_SIZE 512
685  static int curr = 0;
686  static int size = 0;
687  static unsigned char buffer[BUFFER_SIZE+1];
688  int c;
689 
690  *statusp = IS_ROMAN;
691 
692  // Read a new line, if necessary
693  if (curr >= size) {
694  if (!fgets((char *)buffer, BUFFER_SIZE+1, stdin))
695  return EOF;
696  size = strlen((char *)buffer);
697  if (size < BUFFER_SIZE && buffer[size-1] != '\n') {
698  buffer[size] = '\n';
699  buffer[++size] = '\0';
700  }
701  curr = 0;
702  }
703  if (buffer[curr+1] != '\b') // this is not a special sequence
704  return buffer[curr++];
705 
706  // Check if it is a bold sequence
707  c = buffer[curr++];
708  if (c == buffer[curr+1] &&
709  buffer[curr] == buffer[curr+2] &&
710  c == buffer[curr+3] &&
711  buffer[curr] == buffer[curr+4] &&
712  c == buffer[curr+5])
713  {
714  *statusp = IS_BOLD;
715  curr += 6;
716  }
717 
718  // Return the first character of the sequence
719  return c;
720 }
721 
722 /*
723  * Test if we have a binary file.
724  */
725 static int is_binaryfile(char *name) {
726  if (chars > 120 || pages > 1) {
727  first_page = FALSE;
728  if (chars && !print_binaries && (nonprinting_chars*100 / chars) >= 60) {
729  fprintf(stderr, "%s is a binary file: printing aborted\n", name);
730  return TRUE;
731  }
732  }
733  return FALSE;
734 }
735 
736 /*
737  * Cut long filenames.
738  */
739 static void cut_filename(char *old_name, char *new_name) {
740  char *p;
741  int i;
742  char *separator;
743 
744  if ((i = strlen(old_name)) <= MAXFILENAME) {
745  strcpy(new_name, old_name);
746  return;
747  }
748  p = old_name + (i-1);
749  separator = NULp;
750  i = 1;
751  while (p >= old_name && i < MAXFILENAME) {
752  if (*p == DIR_SEP)
753  separator = p;
754  p--;
755  i++;
756  }
757  if (separator)
758  p = separator;
759  else if (p >= old_name)
760  while (p >= old_name && *p != DIR_SEP) p--;
761 
762  for (i = 0, p++; *p != NUL; i++)
763  *new_name++ = *p++;
764  *new_name = NUL;
765 }
766 
767 /*
768  * Print a char in a form accepted by postscript printers.
769  */
770 static int printchar(unsigned char c) {
771 
772  if (c >= ' ' && c < 0177) {
773  if (c == '(' || c == ')' || c == '\\')
774  putchar('\\');
775  putchar(c);
776  return 0;
777  }
778 
779  if (ISOlatin1 && (c > 0177)) {
780  printf("\\%o", c);
781  return 0;
782  }
783 
784  if (only_printable) {
785  putchar(' ');
786  return 1;
787  }
788 
789  if (c > 0177) {
790  printf("M-");
791  c &= 0177;
792  }
793  if (c < ' ') {
794  putchar('^');
795  if ((c = c + '@') == '(' || c == ')' || c == '\\')
796  putchar('\\');
797  putchar(c);
798  }
799  else if (c == 0177)
800  printf("^?");
801  else {
802  if (c == '(' || c == ')' || c == '\\')
803  putchar('\\');
804  putchar(c);
805  }
806 
807  return 1;
808 }
809 
810 /*
811  * Begins a new logical page.
812  */
813 static void skip_page() {
814  if (twinpages == FALSE || sheetside == 0) {
815  printf("%%%%Page: %d %d\n", sheets+1, sheets+1);
816  printf("/pagesave save def\n");
817  // Reinitialize state variables for each new sheet
819  }
820  startpage();
821 }
822 
823 /*
824  * Fold a line too long.
825  */
826 static int fold_line(char *name) {
827  column = 0;
828  printf(") s\n");
829  if (++line >= linesperpage) {
830  endpage();
831  skip_page();
832  if (first_page && is_binaryfile(name))
833  return FALSE;
834  line = 0;
835  }
836  if (numbering)
837  printf("( +");
838  else
839  printf("( ");
840 
841  return TRUE;
842 }
843 
844 /*
845  * Cut a textline too long to the size of a page line.
846  */
847 static int cut_line() {
848  int c;
849  int status;
850 
851  while ((c = mygetc(&status)) != EOF && c != '\n' && c != '\f') ;
852  return c;
853 }
854 
855 
856 //**************************************************************
857 // "Postscript" routines.
858 //**************************************************************
859 
860 /*
861  * Print a physical page.
862  */
863 static void printpage() {
864  sheetside = 0;
865  sheets++;
866  printf("/sd 0 def\n");
867  if (no_border == FALSE)
868  printf("%d sn\n", sheets - (restart ? old_sheets : 0));
869  if (printdate)
870  printf("cd\n");
871  if (filename_footer && landscape)
872  printf("fnf\n");
873 #if defined(SYSV) || defined(BSD)
874  if (login_id)
875  printf("lg lgp\n");
876 #endif
877  printf("pagesave restore\n");
878  printf("showpage\n");
879 }
880 
881 /*
882  * Prints page header and page border and
883  * initializes printing of the file lines.
884  */
885 void startpage() {
886  if (sheetside == 0) {
887 #ifdef RECTO_VERSO_PRINTING
888  if (rectoverso && (sheets & 0x1)) {
889  // Shift to left backside pages.
890  printf("rm neg 0 translate\n");
891  }
892 #endif
893  if (landscape) {
894  printf("sw 0 translate\n");
895  printf("90 rotate\n");
896  }
897  }
898  pages++;
899  if (no_header == FALSE)
900  printf("%d hp\n", pages - old_pages);
901  if (no_border == FALSE) {
902  printf("border\n");
903  if (no_header == FALSE)
904  printf("hborder\n");
905  }
906  printf("/x0 x %d get bm add def\n", sheetside);
907  printf("/y0 y %d get bm bfs add %s add sub def\n",
908  sheetside, no_header ? "0" : "hs");
909  printf("x0 y0 moveto\n");
910  printf("bf setfont\n");
911 }
912 
913 /*
914  * Terminates printing, flushing last page.
915  */
916 static void cleanup() {
917  if (twinpages && sheetside == 1)
918  printpage();
919 #ifdef RECTO_VERSO_PRINTING
920  if (!twinfiles && rectoverso && (sheets & 0x1) != 0) {
921  sheetside = 0;
922  sheets++;
923  printf("%%%%Page: %d %d\n", sheets, sheets);
924  printf("showpage\n");
925  }
926 #endif
927 }
928 
929 /*
930  * Adds a sheet number to the page (footnote) and prints the formatted
931  * page (physical impression). Activated at the end of each source page.
932  */
933 void endpage() {
934  if (twinpages && sheetside == 0) {
935  sheetside = 1;
936  printf("/sd 1 def\n");
937  }
938  else
939  printpage();
940 }
941 
942 
943 //**************************************************************
944 // Printing a file
945 //**************************************************************
946 
947 /*
948  * Print the file prologue.
949  */
950 static void init_file_printing(char *name, char *title) {
951  int new_format, new_font;
952  char *string;
953  int lines;
954  float char_width;
955  struct stat statbuf;
956 
957  // Print last page of previous file, if necessary
958  if (pages > 0 && !twinfiles)
959  cleanup();
960 
961  // Initialize variables related to the format
962  new_format = FALSE;
963  if (new_landscape != landscape || new_twinpages != twinpages) {
964  landscape = new_landscape;
965  twinpages = new_twinpages;
966  new_format = TRUE;
967  }
968 
969  // Initialize variables related to the header
970  if (no_header && name == title)
971  header_size = 0.0;
972  else {
973  if (landscape || twinpages)
975  else
977  cut_filename(title, current_filename);
978  }
979 
980  // Initialize variables related to the font size
981  new_font = FALSE;
982  if (fontsize != new_fontsize || new_format ||
983  lines_requested != new_linesrequest || fontweight != new_fontweight)
984  {
985  if (new_fontsize == 0.0 || (fontsize == new_fontsize && new_format)) {
986  new_fontsize = landscape ? 6.8 : twinpages ? 6.4 : 9.0;
987  }
988  if (lines_requested != new_linesrequest) {
989  if ((lines_requested = new_linesrequest) != 0) {
990  // Scale fontsize
991  if (landscape) lines = (int)((page_width-header_size) / new_fontsize) - 1;
992  else if (twinpages) lines = (int)(((page_height - 2*header_size) / 2) / new_fontsize) - 2;
993  else lines = (int)((page_height-header_size) / new_fontsize) - 1;
994  new_fontsize *= (float)lines / (float)lines_requested;
995  }
996  }
999  new_font = TRUE;
1000  }
1001 
1002  // Initialize file printing, if there is any change
1003  if (new_format || new_font) {
1004  char_width = 0.6 * fontsize;
1005  if (landscape) {
1006  linesperpage = (int)((page_width - header_size) / fontsize) - 1;
1007  if (! twinpages)
1008  columnsperline = (int)(page_height / char_width) - 1;
1009  else
1010  columnsperline = (int)((page_height / 2) / char_width) - 1;
1011  }
1012  else {
1013  if (!twinpages)
1014  linesperpage = (int)((page_height - header_size) / fontsize) - 1;
1015  else
1016  linesperpage = (int)(((page_height - 2*header_size) / 2) / fontsize)
1017  - 2;
1018  columnsperline = (int)(page_width / char_width) - 1;
1019  }
1020  if (lines_requested > 0)
1021  linesperpage = lines_requested;
1022  if (linesperpage <= 0 || columnsperline <= 0) {
1023  fprintf(stderr, "Font %g too big !!\n", fontsize);
1024  exit(EXIT_FAILURE);
1025  }
1026  }
1027 
1028  // Retrieve file modification date and hour
1029  if (fstat(fileno(stdin), &statbuf) == -1) {
1030  fprintf(stderr, "Error getting file modification time\n");
1031  exit(EXIT_FAILURE);
1032  }
1033  // Do we have a pipe?
1034  if (S_ISFIFO(statbuf.st_mode))
1035  strcpy(filedate, currentdate);
1036  else {
1037  string = ctime(&statbuf.st_mtime);
1038  sprintf(filedate, "%.6s %.4s %.5s", string+4, string+20, string+11);
1039  }
1040 }
1041 
1042 /*
1043  * Print the prologue necessary for printing each physical page.
1044  * Adobe convention for page independence is enforced through this routine.
1045  */
1046 void print_page_prologue(int side) {
1047  // side: Logical page to print (left/right)
1048 
1049  // General format
1050  printf("/twp %s def\n", twinpages ? "true" : "false");
1051  printf("/fnfs %d def\n", landscape ? 11 : twinpages ? 10 : 15);
1052  printf("/dfs fnfs 0.8 mul def\n");
1053  printf("/df /Helvetica dfs getfont def\n");
1054  printf("/dw df setfont td stringwidth pop def\n");
1055  printf("/sfnf filenmfontname fnfs getfont def\n");
1056  printf("/hm fnfs 0.25 mul def\n");
1057  // Header size
1058  if (header_size == 0.0)
1059  printf("/hs 0.0 def\n");
1060  else
1061  printf("/hs %g inch def\n",
1062  landscape || twinpages ? LANDSCAPE_HEADER : PORTRAIT_HEADER);
1063  // Font sizes
1064  printf("/bfs %g def\n", fontsize);
1065  printf("/bdf /Courier-Bold bfs getfont def\n");
1066  printf("/bm bfs 0.7 mul def\n");
1067  printf("/bf %s bfs getfont def\n",
1068  fontweight == NORMAL ? "/CourierBack" : "/Courier-Bold");
1069  // Page attributes
1070  printf("/l %d def\n", linesperpage);
1071  printf("/c %d def\n", columnsperline);
1072  printf("/pw\n");
1073  printf(" bf setfont (0) stringwidth pop c mul bm dup add add\n");
1074  printf(" def\n");
1075  printf("/ph\n");
1076  printf(" bfs l mul bm dup add add hs add\n");
1077  printf(" def\n");
1078  printf("/fns\n");
1079  printf(" pw\n");
1080  printf(" fnfs 4 mul dw add (Page 999) stringwidth pop add\n");
1081  printf(" sub\n");
1082  printf(" def\n");
1083  printf("/tm margin twp {3} {2} ifelse div def\n");
1084  printf("/sd %d def\n", side);
1085  if (landscape) {
1086  printf("/y [ rm ph add bm add\n");
1087  printf(" dup ] def\n");
1088  printf("/sny dfs dfs add def\n");
1089  printf("/snx sh tm dfs add sub def\n");
1090  printf("/dy sny def\n");
1091  printf("/dx tm dfs add def\n");
1092  if (twinpages) {
1093  printf("/x [ tm %% left page\n");
1094  printf(" dup 2 mul pw add %% right page\n");
1095  printf(" ] def\n");
1096  }
1097  else {
1098  printf("/x [ tm dup ] def\n");
1099  }
1100  printf("/scx sh 2 div def\n");
1101  }
1102  else {
1103  printf("/x [ lm dup ] def\n");
1104  printf("/sny tm dfs 2 mul sub def\n");
1105  printf("/snx sw rm sub dfs sub def\n");
1106  printf("/dy sny def\n");
1107  printf("/dx lm def\n");
1108  if (twinpages) {
1109  printf("/y [ tm ph add 2 mul %% up\n");
1110  printf(" tm ph add %% down\n");
1111  printf(" ] def\n");
1112  }
1113  else {
1114  printf("\n%% Only one logical page\n");
1115  printf("/y [ sh tm sub dup ] def\n");
1116  }
1117  printf("/scx sw 2 div def\n");
1118  }
1119  printf("/fny dy def\n");
1120  printf("/fnx scx def\n");
1121  printf("/ly fnfs 2 div y sd get add def\n");
1122  printf("/lx snx def\n");
1123  printf("/d (%s) def\n", filedate);
1124  printf("( %s ) fn\n", current_filename);
1125 }
1126 
1127 /*
1128  * Print one file.
1129  */
1130 static void print_file(char *name, char *header) {
1131  int c;
1132  int nchars;
1133  int start_line, start_page;
1134  int continue_exit;
1135  int status, new_status;
1136 
1137  // Reinitialize postscript variables depending on positional options
1138  init_file_printing(name, header ? header : name);
1139 
1140  // If we are in compact mode and the file beginning is to be printed
1141  // in the middle of a twinpage, we have to print a new page prologue
1142  if (twinfiles && sheetside == 1)
1144 
1145  /*
1146  * Boolean to indicates that previous char is \n (or interpreted \f)
1147  * and a new page would be started, if more text follows
1148  */
1149  start_page = FALSE;
1150 
1151  /*
1152  * Printing binary files is not very useful. We stop printing
1153  * if we detect one of these files. Our heuristic to detect them:
1154  * if 75% characters of first page are non-printing characters,
1155  * the file is a binary file.
1156  * Option -b force binary files impression.
1157  */
1158  nonprinting_chars = chars = 0;
1159 
1160  // Initialize printing variables
1161  column = 0;
1162  line = line_number = 0;
1163  first_page = TRUE;
1164  start_line = TRUE;
1165  prefix_width = numbering ? 6 : 1;
1166 
1167  // Start printing
1168  skip_page();
1169 
1170  // Process each character of the file
1171  status = IS_ROMAN;
1172  c = mygetc(&new_status);
1173  while (c != EOF) {
1174  /*
1175  * Preprocessing (before printing):
1176  * - TABs expansion (see interpret option)
1177  * - FF and BS interpretation
1178  * - replace non printable characters by a space or a char sequence
1179  * like:
1180  * ^X for ascii codes < 0x20 (X = [@, A, B, ...])
1181  * ^? for del char
1182  * M-c for ascii codes > 0x3f
1183  * - prefix parents and backslash ['(', ')', '\'] by backslash
1184  * (escape character in postscript)
1185  */
1186  // Form feed
1187  if (c == '\f' && interpret) {
1188  // Close current line
1189  if (!start_line) {
1190  printf(") s\n");
1191  start_line = TRUE;
1192  }
1193  // start a new page ?
1194  if (start_page)
1195  skip_page();
1196  // Close current page and begin another
1197  endpage();
1198  start_page = TRUE;
1199  // Verification for binary files
1200  if (first_page && is_binaryfile(name))
1201  return;
1202  line = 0;
1203  column = 0;
1204  if ((c = mygetc(&new_status)) == EOF)
1205  break;
1206  }
1207 
1208  // Start a new line ?
1209  if (start_line) {
1210  if (start_page) {
1211  // only if there is something to print!
1212  skip_page();
1213  start_page = FALSE;
1214  }
1215  if (numbering)
1216  printf("(%4d|", ++line_number);
1217  else
1218  printf("( ");
1219  start_line = FALSE;
1220  }
1221 
1222  // Is a new font ? This feature is used only to detect bold
1223  // sequences produced by nroff (man pages), in connexion with
1224  // mygetc.
1225  if (status != new_status) {
1226  printf(")\n");
1227  printf("%s", status == IS_ROMAN ? "b" : "st");
1228  printf(" (");
1229  status = new_status;
1230  }
1231 
1232  // Interpret each character
1233  switch (c) {
1234  case '\b':
1235  if (!interpret)
1236  goto print;
1237  // A backspace is converted to 2 chars ('\b'). These chars
1238  // with the Courier backspace font produce correct under-
1239  // lined strings.
1240  if (column)
1241  column--;
1242  putchar('\\');
1243  putchar('b');
1244  break;
1245  case '\n':
1246  column = 0;
1247  start_line = TRUE;
1248  printf(") s\n");
1249  if (++line >= linesperpage) {
1250  endpage();
1251  start_page = TRUE;
1252  if (first_page && is_binaryfile(name))
1253  return;
1254  line = 0;
1255  }
1256  break;
1257  case '\t':
1258  if (interpret) {
1259  continue_exit = FALSE;
1260  do {
1261  if (++column + prefix_width > columnsperline) {
1262  if (folding) {
1263  if (fold_line(name) == FALSE)
1264  return;
1265  }
1266  else {
1267  c = cut_line();
1268  continue_exit = TRUE;
1269  break;
1270  }
1271  }
1272  putchar(' ');
1273  } while (column % column_width);
1274  if (continue_exit)
1275  continue;
1276  break;
1277  }
1278  __attribute__ ((fallthrough)); // implicit fallthrough
1279  default:
1280  print :
1281  if (only_printable) {
1282  nchars = 1;
1283  }
1284  else if (! ISOlatin1) {
1285  nchars = c > 0177 ? 2 : 0;
1286  nchars += (c&0177) < ' ' || (c&0177) == 0177 ? 2 : 1;
1287  }
1288  else {
1289  nchars = c < ' ' || (c >= 0177 && c < 144) ? 2 : 1;
1290  }
1291 
1292  if (prefix_width + (column += nchars) > columnsperline) {
1293  if (folding) {
1294  if (fold_line(name) == FALSE) {
1295  return;
1296  }
1297  }
1298  else {
1299  c = cut_line();
1300  new_status = IS_ROMAN;
1301  continue;
1302  }
1303  }
1304  nonprinting_chars += printchar(c);
1305  chars++;
1306  break;
1307  }
1308  c = mygetc(&new_status);
1309  }
1310 
1311  if (!start_line)
1312  printf(") s\n");
1313  if (!start_page)
1314  endpage();
1315 }
1316 
1317 
1318 //**************************************************************
1319 // Print a postscript prologue for a2ps.
1320 //**************************************************************
1321 
1322 /*
1323  * Print the a2ps prologue.
1324  */
1325 static void print_prologue() {
1326  int c;
1327  FILE *f = NULp;
1328  char *datestring;
1329 #if defined(SYSV) || defined(BSD)
1330  char *logname, *host;
1331  int rt;
1332 #endif
1333 #if defined(SYSV)
1334  struct utsname snames;
1335 #endif
1336 
1337  // Retrieve date and hour
1338 #if defined(__STDC__)
1339  time_t date;
1340 
1341  if (time(&date) == -1) {
1342  fprintf(stderr, "Error calculating time\n");
1343  exit(EXIT_FAILURE);
1344  }
1345  datestring = ctime(&date);
1346 #else
1347 #ifdef BSD
1348  struct timeval date;
1349  struct tm *p;
1350 
1351  (void) gettimeofday(&date, (struct timezone *)0);
1352  p = localtime(&date.tv_sec);
1353  datestring = asctime(p);
1354 #else
1355 #ifdef SYSV
1356  struct timeb date;
1357 
1358  (void)ftime(&date);
1359  datestring = ctime(&date.time);
1360 #else
1361 
1362  datestring = "--- --- -- --:--:-- ----";
1363 #endif
1364 #endif
1365 #endif
1366 
1367 #if defined(SYSV) || defined(BSD)
1368  // Retrieve user's login name and hostname
1369  logname = getlogin();
1370  host = (char *)malloc(MAX_HOSTNAME);
1371  if (host) {
1372 #if defined(SYSV)
1373  if ((rt = uname(&snames)) == -1 || !snames.nodename[0]) {
1374  free(host);
1375  host = NULp;
1376  }
1377  else
1378  strcpy(host, snames.nodename);
1379 #else
1380  if ((rt = gethostname(host, MAX_HOSTNAME)) == -1 || !host[0]) {
1381  free(host);
1382  host = NULp;
1383  }
1384 #endif
1385  }
1386 #endif
1387 
1388  // Print a general prologue
1389  if (!prologue)
1390  print_standard_prologue(datestring);
1391  else if ((f = fopen(prologue, "r"))) {
1392  // Header file printing
1393  while ((c = getc(f)) != EOF)
1394  putchar(c);
1395  }
1396  else {
1397  fprintf(stderr, "Postscript header missing: %s\n", prologue);
1398  exit(EXIT_FAILURE);
1399  }
1400 
1401  // Completes the prologue with a2ps static variables
1402  printf("\n%% Initialize page description variables.\n");
1403  printf("/x0 0 def\n");
1404  printf("/y0 0 def\n");
1405  printf("/sh %g inch def\n", (double)HEIGHT);
1406  printf("/sw %g inch def\n", (double)WIDTH);
1407  printf("/margin %g inch def\n", (double)MARGIN);
1408  printf("/rm margin 3 div def\n");
1409  printf("/lm margin 2 mul 3 div def\n");
1410  printf("/d () def\n");
1411 
1412  // And print them
1413  sprintf(currentdate, "%.6s %.4s %.5s",
1414  datestring+4, datestring+20, datestring+11);
1415  printf("/td (%s) def\n", currentdate);
1416 
1417 #if defined(SYSV) || defined(BSD)
1418  // Add the user's login name string to the Postscript output
1419  if (logname || host) {
1420  if (logname && host)
1421  printf("/lg (Printed by %s from %s) def\n", logname, host);
1422  else if (logname)
1423  printf("/lg (Printed by %s) def\n", logname);
1424  else
1425  printf("/lg (Printed from %s) def\n", host);
1426  }
1427 
1428  // If the host string was allocated via malloc, release the memory
1429  if (host)
1430  free(host);
1431 #endif
1432 
1433  // Close prolog
1434  printf("%%%%EndProlog\n\n");
1435 
1436  // Go on
1437  printf("/docsave save def\n");
1438  if (f) fclose(f);
1439 }
1440 
1441 /*
1442  * Print the standard prologue.
1443  */
1444 void print_standard_prologue(char *datestring) {
1445  printf("%%!PS-Adobe-3.0\n");
1446  printf("%%%%Creator: A2ps version %s\n", VERSION);
1447  printf("%%%%CreationDate: %.24s\n", datestring);
1448  printf("%%%%Pages: (atend)\n");
1449  printf("%%%%DocumentFonts: Courier Courier-Bold Helvetica Helvetica-Bold\n");
1450  printf("%%%%EndComments\n");
1451  printf("%% Copyright (c) 1993, 1994, Miguel Santana, M.Santana@frgu.bull.fr\n");
1452  printf("\n/$a2psdict 100 dict def\n");
1453  printf("$a2psdict begin\n");
1454  printf("\n%% General macros.\n");
1455  printf("/xdef {exch def} bind def\n");
1456  printf("/getfont {exch findfont exch scalefont} bind def\n");
1457 
1458  if (ISOlatin1) {
1459  printf("\n%% Set up ISO Latin 1 character encoding\n");
1460  printf("/reencodeISO {\n");
1461  printf(" dup dup findfont dup length dict begin\n");
1462  printf(" { 1 index /FID ne { def }{ pop pop } ifelse\n");
1463  printf(" } forall\n");
1464  printf(" /Encoding ISOLatin1Encoding def\n");
1465  printf(" currentdict end definefont\n");
1466  printf("} def\n");
1467  printf("/Helvetica-Bold reencodeISO def\n");
1468  printf("/Helvetica reencodeISO def\n");
1469  printf("/Courier reencodeISO def\n");
1470  printf("/Courier-Bold reencodeISO def\n");
1471  }
1472 
1473  printf("\n%% Create Courier backspace font\n");
1474  printf("/backspacefont {\n");
1475  printf(" /Courier findfont dup length dict begin\n");
1476  printf(" { %% forall\n");
1477  printf(" 1 index /FID eq { pop pop } { def } ifelse\n");
1478  printf(" } forall\n");
1479  printf(" currentdict /UniqueID known { %% if\n");
1480  printf(" /UniqueID UniqueID 16#800000 xor def\n");
1481  printf(" } if\n");
1482  printf(" CharStrings length 1 add dict begin\n");
1483  printf(" CharStrings { def } forall\n");
1484  printf(" /backspace { -600 0 0 0 0 0 setcachedevice } bind def\n");
1485  printf(" currentdict\n");
1486  printf(" end\n");
1487  printf(" /CharStrings exch def\n");
1488  printf(" /Encoding Encoding 256 array copy def\n");
1489  printf(" Encoding 8 /backspace put\n");
1490  printf(" currentdict\n");
1491  printf(" end\n");
1492  printf(" definefont pop\n");
1493  printf("} bind def\n");
1494 
1495  printf("\n%% FUNCTIONS\n");
1496  printf("\n%% Function filename: Initialize file printing.\n");
1497  printf("/fn\n");
1498  printf("{ /filenm xdef\n");
1499  printf(" /filenmwidth filenm stringwidth pop def\n");
1500  printf(" /filenmfont\n");
1501  printf(" filenmwidth fns gt\n");
1502  printf(" {\n");
1503  printf(" filenmfontname\n");
1504  printf(" fnfs fns mul filenmwidth div\n");
1505  printf(" getfont\n");
1506  printf(" }\n");
1507  printf(" { sfnf }\n");
1508  printf(" ifelse\n");
1509  printf(" def\n");
1510  printf("} bind def\n");
1511  printf("\n%% Function header: prints page header. no page\n");
1512  printf("%% is passed as argument.\n");
1513  printf("/hp\n");
1514  printf(" { x sd get y sd get hs sub 1 add moveto\n");
1515  printf(" df setfont\n");
1516  printf(" gsave\n");
1517  printf(" x sd get y sd get moveto\n");
1518  printf(" 0 hs 2 div neg rmoveto \n");
1519  printf(" hs setlinewidth\n");
1520  printf(" 0.95 setgray\n");
1521  printf(" pw 0 rlineto stroke\n");
1522  printf(" grestore\n");
1523  printf(" gsave\n");
1524  printf(" dfs hm rmoveto\n");
1525  printf(" d show %% date/hour\n");
1526  printf(" grestore\n");
1527  printf(" gsave\n");
1528  printf(" pnum cvs pop %% page pop up\n");
1529  printf(" pw (Page 999) stringwidth pop sub\n");
1530  printf(" hm\n");
1531  printf(" rmoveto\n");
1532  printf(" (Page ) show pnum show %% page number\n");
1533  printf(" grestore\n");
1534  printf(" empty pnum copy pop\n");
1535  printf(" gsave\n");
1536  printf(" filenmfont setfont\n");
1537  printf(" fns filenm stringwidth pop sub 2 div dw add\n");
1538  printf(" bm 2 mul \n");
1539  printf(" add \n");
1540  printf(" hm\n");
1541  printf(" rmoveto\n");
1542  printf(" filenm show %% file name\n");
1543  printf(" grestore\n");
1544  printf(" } bind def\n");
1545  printf("\n%% Function border: prints border page\n");
1546  printf("/border \n");
1547  printf("{ x sd get y sd get moveto\n");
1548  printf(" gsave %% print four sides\n");
1549  printf(" 0.7 setlinewidth %% of the square\n");
1550  printf(" pw 0 rlineto\n");
1551  printf(" 0 ph neg rlineto\n");
1552  printf(" pw neg 0 rlineto\n");
1553  printf(" closepath stroke\n");
1554  printf(" grestore\n");
1555  printf("} bind def\n");
1556  printf("\n%% Function hborder: completes border of the header.\n");
1557  printf("/hborder \n");
1558  printf("{ gsave\n");
1559  printf(" 0.7 setlinewidth\n");
1560  printf(" 0 hs neg rmoveto\n");
1561  printf(" pw 0 rlineto\n");
1562  printf(" stroke\n");
1563  printf(" grestore\n");
1564  printf("} bind def\n");
1565  printf("\n%% Function sheetnumber: prints the sheet number.\n");
1566  printf("/sn\n");
1567  printf(" { snx sny moveto\n");
1568  printf(" df setfont\n");
1569  printf(" pnum cvs\n");
1570  printf(" dup stringwidth pop (0) stringwidth pop sub neg 0 rmoveto show\n");
1571  printf(" empty pnum copy pop\n");
1572  printf(" } bind def\n");
1573  printf("\n%% Function loginprint: prints the login id of the requestor.\n");
1574  printf("/lgp\n");
1575  printf(" { lx ly moveto\n");
1576  printf(" df setfont\n");
1577  printf(" dup stringwidth pop neg 0 rmoveto show\n");
1578  printf(" } bind def\n");
1579  printf("\n%% Function currentdate: prints the current date.\n");
1580  printf("/cd\n");
1581  printf(" { dx dy moveto\n");
1582  printf(" df setfont\n");
1583  printf(" (Printed: ) show\n");
1584  printf(" td show\n");
1585  printf(" } bind def\n");
1586  printf("\n%% Function filename_footer: prints the file name at bottom of page.\n");
1587  printf("/fnf\n");
1588  printf(" { fnx fny moveto\n");
1589  printf(" df setfont\n");
1590  printf(" filenm center show\n");
1591  printf(" } bind def\n");
1592  printf("\n%% Function center: centers text.\n");
1593  printf("/center\n");
1594  printf(" { dup stringwidth pop\n");
1595  printf(" 2 div neg 0 rmoveto\n");
1596  printf(" } bind def\n");
1597  printf("\n%% Function s: print a source line\n");
1598  printf("/s { show\n");
1599  printf(" /y0 y0 bfs sub def\n");
1600  printf(" x0 y0 moveto\n");
1601  printf(" } bind def\n");
1602  printf("\n%% Functions b and st: change to bold or standard font\n");
1603  printf("/b { show\n");
1604  printf(" bdf setfont\n");
1605  printf(" } bind def\n");
1606  printf("/st { show\n");
1607  printf(" bf setfont\n");
1608  printf(" } bind def\n");
1609  printf("\n%% Strings used to make easy printing numbers\n");
1610  printf("/pnum 12 string def\n");
1611  printf("/empty 12 string def\n");
1612  printf("\n%% Global initializations\n");
1613  printf("\n/CourierBack backspacefont\n");
1614  printf("/filenmfontname /Helvetica-Bold def\n");
1615  printf("/inch {72 mul} bind def\n");
1616 
1617  printf("\n%%\n");
1618  printf("%% Meaning of some variables and functions (coded names)\n");
1619  printf("%%\n");
1620  printf("%% twp: twinpages?\n");
1621  printf("%% sd: sheet side\n");
1622  printf("%% l: line counter\n");
1623  printf("%% c: column counter\n");
1624  printf("%% d: date\n");
1625  printf("%% td: current date (for today)\n");
1626  printf("%% lg: login name\n");
1627  printf("%% fn: filename printing function\n");
1628  printf("%% sn: sheetnumber printing function\n");
1629  printf("%% cd: current date printing function\n");
1630  printf("%% fnf: filename footer printing function\n");
1631  printf("%% lgp: login printing function\n");
1632  printf("%% hp: header printing function\n");
1633  printf("%% y: y coordinate for the logical page\n");
1634  printf("%% x: x coordinate for the logical page\n");
1635  printf("%% sny: y coordinate for the sheet number\n");
1636  printf("%% snx: x coordinate for the sheet number\n");
1637  printf("%% dy: y coordinate for the date\n");
1638  printf("%% dx: x coordinate for the date\n");
1639  printf("%% ly: y coordinate for the login\n");
1640  printf("%% lx: x coordinate for the login\n");
1641  printf("%% scx: x coordinate for the sheet center\n");
1642  printf("%% fny: y coordinate for the filename (footer)\n");
1643  printf("%% fnx: x coordinate for the filename (footer)\n");
1644  printf("%% fnfs: filename font size\n");
1645  printf("%% bfs: body font size\n");
1646  printf("%% dfs: date font size\n");
1647  printf("%% bfs: body font size\n");
1648  printf("%% df: date font\n");
1649  printf("%% bf: body font\n");
1650  printf("%% bdf: bold font\n");
1651  printf("%% sfnf: standard filename font\n");
1652  printf("%% dw: date width\n");
1653  printf("%% pw: page width\n");
1654  printf("%% sw: sheet width\n");
1655  printf("%% ph: page height\n");
1656  printf("%% sh: sheet height\n");
1657  printf("%% hm: header margin\n");
1658  printf("%% tm: top margin\n");
1659  printf("%% bm: body margin\n");
1660  printf("%% rm: right margin\n");
1661  printf("%% lm: left margin\n");
1662  printf("%% hs: header size\n");
1663  printf("%% fns: filename size\n");
1664 }
1665 
1666 
1667 /*
1668  * Main routine for a2ps.
1669  */
1670 int ARB_main(int argc, char *cargv[]) {
1671  char **argv = (char**)cargv;
1672  int narg;
1673  char *arg;
1674  int total;
1675 #if LPR_PRINT
1676  int fd[2];
1677  const char *lpr_args[10];
1678 #endif
1679 
1680  // Process global options
1681  command = argv[0];
1682  arg = argv[narg = 1];
1683  while (narg < argc) {
1684  if (arg[0] == '-')
1685  set_global_option(arg);
1686  arg = argv[++narg];
1687  }
1688 
1689 #if LPR_PRINT
1690  // Start lpr process
1691  if (lpr_print) {
1692  if (pipe(fd) != 0) {
1693  fprintf(stderr, "Could not create pipe (Reason: %s)\n", strerror(errno));
1694  exit(EXIT_FAILURE);
1695  }
1696 
1697  if (fork() == 0) {
1698  dup2(fd[0], 0);
1699  close(fd[0]); close(fd[1]);
1700  narg = 0;
1701  lpr_args[narg++] = LPR_COMMAND;
1702 #ifdef LPR_OPT
1703  lpr_args[narg++] = LPR_OPT;
1704 #endif
1705  if (lpr_opt)
1706  lpr_args[narg++] = lpr_opt;
1707 #ifdef RECTO_VERSO_PRINTING
1708  if (rectoverso)
1709  lpr_args[narg++] = TWOSIDED;
1710  else
1711  lpr_args[narg++] = ONESIDED;
1712 #endif
1713  lpr_args[narg] = (char *)0;
1714  execvp(LPR_COMMAND, (char**)lpr_args);
1715  fprintf(stderr, "Error starting lpr process \n");
1716  exit(EXIT_FAILURE);
1717  }
1718  dup2(fd[1], 1);
1719  close(fd[0]);
1720  close(fd[1]);
1721  }
1722 #endif
1723 
1724  // Initialize variables not depending of positional options
1725  landscape = twinpages = -1; // To force format switching
1726  fontsize = -1.0; // To force fontsize switching
1727  page_height = (double)(HEIGHT - MARGIN) * PIXELS_INCH;
1728  page_width = (double)(WIDTH - MARGIN) * PIXELS_INCH;
1729 
1730  // Postscript prologue printing
1731  print_prologue();
1732 
1733  // Print files designated or standard input
1734  arg = argv[narg = 1];
1735  while (narg < argc) {
1736  if (arg[0] != NUL) {
1737  if (arg[0] == '-')
1738  set_positional_option(arg);
1739  else {
1740  if (!freopen(arg, "r", stdin)) {
1741  fprintf(stderr, "Error opening %s\n", arg);
1742  cleanup();
1743  printf("\n%%%%Trailer\ndocsave restore end\n\4");
1744  exit(EXIT_FAILURE);
1745  }
1746  no_files = FALSE;
1747 
1748  // Save counters values
1749  old_pages = pages;
1750  if (twinfiles && twinpages)
1751  old_sheets = sheets;
1752  else
1753  old_sheets = sheets + sheetside;
1754 
1755  // Print the file
1756  print_file(arg, header_text);
1757 
1758  // Print the number of pages and sheets printed
1759  if (no_summary == FALSE) {
1760  total = pages - old_pages;
1761  fprintf(stderr, "[%s: %d page%s on ", arg,
1762  total, total == 1 ? "" : "s");
1763  total = sheets - old_sheets + sheetside;
1764 #ifdef RECTO_VERSO_PRINTING
1765  if (rectoverso)
1766  total = (total+1) / 2;
1767 #endif
1768  fprintf(stderr, "%d sheet%s]\n", total, total == 1 ? "" : "s");
1769  }
1770 
1771  // Reinitialize header title
1772  header_text = NULp;
1773  }
1774  }
1775  arg = argv[++narg];
1776  }
1777  if (no_files)
1778  print_file((char*)"stdin", header_text);
1779 
1780  // Print the total number of pages printed
1781  if (no_summary == FALSE && pages != old_pages) {
1782  fprintf(stderr, "[Total: %d page%s on ", pages, pages == 1 ? "" : "s");
1783  total = sheets + sheetside;
1784 #ifdef RECTO_VERSO_PRINTING
1785  if (rectoverso)
1786  total = (total+1) / 2;
1787 #endif
1788  fprintf(stderr, "%d sheet%s]\n", total, total == 1 ? "" : "s");
1789  }
1790 
1791  // And stop
1792  cleanup();
1793  printf("\n%%%%Trailer\n");
1794  printf("%%%%Pages: %d\n", sheets + sheetside);
1795  printf("docsave restore end\n");
1796 
1797  exit(EXIT_SUCCESS);
1798 }
char * getlogin()
static int cut_line()
Definition: arb_a2ps.c:847
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:1046
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:885
static void print_prologue()
Definition: arb_a2ps.c:1325
static void print_standard_prologue(char *datestring)
Definition: arb_a2ps.c:1444
static int interpret
Definition: arb_a2ps.c:266
static void print_file(char *name, char *header)
Definition: arb_a2ps.c:1130
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:770
static void set_positional_option(char *arg)
Definition: arb_a2ps.c:555
char * login
Definition: arb_a2ps.c:328
static void skip_page()
Definition: arb_a2ps.c:813
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:1670
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:725
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:739
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:933
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:863
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:950
static void cleanup()
Definition: arb_a2ps.c:916
#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:826
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:683
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
struct PT_short_chain_header __attribute__
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:359