[comp.sources.misc] v05i090: a2ps

miguel@imag.imag.fr.UUCP (Miguel Santana) (12/23/88)

Posting-number: Volume 5, Issue 90
Submitted-by: "Miguel Santana" <miguel@imag.imag.fr.UUCP>
Archive-name: a2ps.c

[Let's see now:  "UNIX" != "SYSV", and somewhere SYSV picked up <sys/timeb.h>.
Somehow that doesn't agree with what I know... beware of the #ifdef's, people,
they don't appear to be accurate in all cases.  (Actually, it looks more like
"UNIX != XENIX", which is generally true.  Sigh.)  ++bsa]

This is a new version of a2ps, a program to format an ascii file for
printing in a postcript printer. Initial version was a shell program
written by evan@csli (Evan Kirshenbaum). It was very slow and contained
many bugs. The new version was written in C for improve speed execution
and portability. New features and improvements have been added (see
README and a2ps.1).

Format used to print files is very nice and compact: two pages on each
physical page, borders surrounding pages, headers with useful information
(page number, printing date, file name), line numbering, etc. Very useful
to archive listings of programs.

The a2ps distribution consists of the following files:

	README
	Makefile
	a2ps.c		a2ps source
	a2ps.1		a troff manual (man file)
	header.ps	postcript header used by a2ps

Please send problems and feedback to:

    miguel@imag.fr or miguel@imag.UUCP (uunet.uu.net!imag!miguel)

    Miguel SANTANA
    LGI
    IMAG-Campus
    BP 53X
    38041 Grenoble Cedex

---- Cut Here and unpack ----
#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
#	Run the following text with /bin/sh to create:
#	  README
#	  Makefile
#	  a2ps.1
#	  a2ps.c
#	  header.ps
#
if test -f README; then echo "File README exists"; else
echo "x - extracting README (Text)"
sed 's/^X//' << 'SHAR_EOF' > README &&
XThis is a new version of a2ps, a program to format an ascii file for
Xprinting in a postcript printer. As the copyright indicates, this
Xdistribution can be freely redistributed.
X
XInitial version was a shell program written by evan@csli (Evan
XKirshenbaum). It was very slow and contained many bugs. The new
Xversion was written in C for improve speed execution and portability.
XNew features and improvements have been added.
X
X
XSome notes on the distribution:
X
X    Installation is done by modifying and executing Makefile included
X    in this distribution. You must give your own values to two variables:
X    - HEADER_PS   a2ps will search there the file header.ps at execution
X		  time.
X    - compiler	  compiler name, actually one of UNIX, SYSV, ANSIC. Turbo
X		  C and Microsoft C are considered ANSIC compilers.
X
X    a2ps has been successfully ported to Unix 4.3BSD, Unix SystemV and
X    MSDOS.
X
X
XThe a2ps distribution consists of the following files:
X
X	README		This message
X	Makefile
X	a2ps.c		a2ps source
X	a2ps.1		a troff manual (man file)
X	header.ps	postcript header used by a2ps
X
XDecide where you want to keep these files and move it there.
XEdit "Makefile" and change the definition of HEADER_PS (to
Xreflect the full pathname of header.ps) and of compiler name.
XTo make a2ps do:
X
X    make a2ps
X
XTo install it, do:
X
X    make install
X
XFormat the manual entry using
X
X    nroff -man a2ps.1
X
X
XPlease send problems and feedback to:
X
X    miguel@imag.fr or miguel@imag.UUCP (uunet.uu.net!imag!miguel)
X
X    Miguel SANTANA
X    LGI
X    IMAG-Campus
X    BP 53X
X    38041 Grenoble Cedex
SHAR_EOF
chmod 0664 README || echo "restore of README fails"
set `wc -c README`;Sum=$1
if test "$Sum" != "1575"
then echo original size 1575, current size $Sum;fi
fi
if test -f Makefile; then echo "File Makefile exists"; else
echo "x - extracting Makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X#
X# Description: Makefile to construct and install a2ps. Don't forget
X# to give your own values to define variables HEADER_PS and name of
X# compiler (see OPTIONS).
X#
X# File: imag:/users/local/a2ps/Makefile
X# Created: Mon Nov 29 14:05:39 1988 by miguel@imag (Miguel Santana)
X# Version: 2.0
X#
X
X# Copyright (c) 1988, Miguel Santana, miguel@imag.imag.fr
X#
X# Permission is granted to copy and distribute this file in modified
X# or unmodified form, whether for noncommercial or commercial use,
X# provided (a) this copyright notice is preserved, (b) no attempt is
X# made to restrict redistribution of this file, and (c) this file is
X# not distributed as part of any collection whose redistribution is
X# restricted by a compilation copyright.
X#
X
XD	=.
X
XO	=.
X
XI	=/users/local/a2ps
X
XOPTIONS	=-DHEADER_PS="\"$I/header.ps\"" -DUNIX -O
X
XOBJS	      = a2ps.o
X
Xall:		a2ps install
X
Xa2ps:		a2ps.o
X		@echo -n "Compiling and linking a2ps ... "
X		@cc -o $D/xa2ps a2ps.o
X		@echo "done"
X
Xinstall:;	@echo -n "Installing a2ps ... "
X		@cp xa2ps $I/a2ps
X		@cp header.ps $I/header.ps
X		@echo "done"
X
Xclean:;		@rm -f $(OBJS)
X
Xa2ps.o:;
X		cc -c $(OPTIONS) a2ps.c
X
SHAR_EOF
chmod 0664 Makefile || echo "restore of Makefile fails"
set `wc -c Makefile`;Sum=$1
if test "$Sum" != "1132"
then echo original size 1132, current size $Sum;fi
fi
if test -f a2ps.1; then echo "File a2ps.1 exists"; else
echo "x - extracting a2ps.1 (Text)"
sed 's/^X//' << 'SHAR_EOF' > a2ps.1 &&
X.\" @(#)a2ps.man.1 2.0 11/29/88
X.\"
X.TH A2PS 1L "November 29 1988"
X.UC 4
X.SH NAME
Xa2ps \- formats an ascii file for printing in a postscript printer;
Xvery nice and compact format for program listings.
X.SH SYNOPSIS
X.B a2ps
X[ -b ] [ -f ] [ -i ] [ -n ] [ -n{bfinrv} ] [ -r ] [ -v ] [
X.B file1
X] [
X.B file2
X] [...]
X.SH DESCRIPTION
X.B a2ps
Xformats files "file1", "file2", ... for printing in a postscript printer;
Xif no file is given,
X.B a2ps
Xreads from the standard input.
XFormat used is very nice and compact: two pages on each physical page,
Xborders surrounding pages, headers with useful information (page number,
Xprinting date, file name), line numbering, etc. Very useful to
Xarchive listings of programs.
X.PP
XOptions offered by
X.B a2ps
Xare the following:
X.TP 0.6i
X.B -b
XForce printing binary files. By default, binary files printing is
Xstopped before second page (see -nb option).
X.TP 0.6i
X.B -f
XFold lines too large to be printed inside the borders (default option).
XMax size is actually 86 characters.
X.TP 0.6i
X.B -i
XInterpret TAB, BS and FF characters (default option). TAB is replaced by
Xenough spaces to reach next tab stop while BS and FF have their meanings.
X.TP 0.6i
X.B -n
XOutput lines are preceded by line numbers, numbered sequentially from 1
X(default option).
X.TP 0.6i
X.B -nb
XDon't print binary files. To detect such a file we make use of a
Xvery simple heuristic: if the first page of the file contains at
Xless 75% of non-printing characters, it's a binary file. First page
Xis always printed.
X.TP 0.6i
X.B -nf
XCut lines too large (don't fold).
X.TP 0.6i
X.B -ni
XDon't interpret TAB, BS and FF characters. They will be printed
Xaccording to -v option.
X.TP 0.6i
X.B -nn
XDon't number output lines.
X.TP 0.6i
X.B -nr
XSheet numbering (see -r option) must be continue for all files (don't
Xreset on new file).
X.TP 0.6i
X.B -nv
XReplace non-printing characters by a space.
X.TP 0.6i
X.B -r
XReset sheet numbering for each new file (default option). Sheet numbering
Xis used to number physical pages (sheets printed) and is placed
Xin the bottom of each physical page. It differs from page numbering: logical
Xpages of file been printed.
X.TP 0.6i
X.B -v
XReplace non-printing characters so that they are lisible and easy to identify
X(default option). Control characters (ascii codes lower than 0x20) are
Xprinted like ^X for ctrl-x; the delete character (hex 0x3f) is printed
Xas ^?. Non ascii characters (with the high bit set) are printed as M-
X(for meta) followed by the character of the low 7 bits. TAB, BS and FF are
Xhandled like non-printing characters if -ni option was taked.
X.SH USAGE
X.PP
X.B a2ps
Xsends formatted file to standard output. User could redirect this output
Xto a file or pipe it directly to a print command, like lpr in UNIX:
X
X.ti +0.5i
Xa2ps file1 > file2
X
X.ti +0.5i
Xa2ps file1 | lpr -l
X.PP
XDon't forget
X.B -l
Xoption in last line, if you want that 
X.B lpr
Xinterprets your postscript program.
X.PP
XThis filter must be used only with text files. Avoid specially output from
XTeX, troff or any other text formatter.
X.SH "SEE ALSO"
Xpprps(1L) tgrind(1) lpr(1)
X.SH AUTHORS
XEvan Kirshenbaum (evan@csli) for the initial version.
X.br
XMiguel Santana (miguel@imag.imag.fr) for 2.0 version.
SHAR_EOF
chmod 0664 a2ps.1 || echo "restore of a2ps.1 fails"
set `wc -c a2ps.1`;Sum=$1
if test "$Sum" != "3182"
then echo original size 3182, current size $Sum;fi
fi
if test -f a2ps.c; then echo "File a2ps.c exists"; else
echo "x - extracting a2ps.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > a2ps.c &&
X/************************************************************************/
X/*									*/
X/* Description: Ascii to PostScript printer program.			*/
X/* File: imag:/users/local/a2ps/a2ps.c					*/
X/* Created: Mon Nov 28 15:22:15 1988 by miguel@imag (Miguel Santana)	*/
X/* Version: 2.0								*/
X/*									*/
X/* Edit history:							*/
X/* 1) Derived of shell program written by evan@csli (Evan Kirshenbaum).	*/
X/*    Written in C for improve speed execution and portability. Many	*/
X/*    improvements have been added.					*/
X/*									*/
X/************************************************************************/
X
X/*
X * Copyright (c) 1988, Miguel Santana, miguel@imag.imag.fr
X *
X * Permission is granted to copy and distribute this file in modified
X * or unmodified form, for noncommercial use, provided (a) this copyright
X * notice is preserved, (b) no attempt is made to restrict redistribution
X * of this file, and (c) this file is not distributed as part of any
X * collection whose redistribution is restricted by a compilation copyright.
X*/
X
X
X#include <stdio.h>
X#ifdef ANSIC
X#include <time.h>
X#else
X#ifdef UNIX
X#include <sys/time.h>
X#else
X#ifdef SYSV
X#include <sys/types.h>
X#include <sys/timeb.h>
X#include <time.h>
X#else
Xerror !
X#endif
X#endif
X#endif
X
X#ifndef	HEADER_PS
X#define	HEADER_PS	"./header.ps"
X#endif
X#define	LINESPERPAGE	66
X#define	COLUMNSPERLINE	86
X
X#define	FALSE		0
X#define	TRUE		1
X
Xint fold_line();
Xvoid print_file();
Xchar cut_line();
X
X
Xint column = 0;			/* Column number (in current line) */
Xint line = 0;			/* Line number (in current page) */
Xint line_number = 0;		/* Source line number */
Xint first_page;			/* First page for a file */
Xint nonprinting_chars, chars;	/* Number of nonprinting and total chars */
Xint prefix_width;		/* Width in characters for line prefix */
Xint numbering = TRUE;		/* Line numbering option */
Xint folding = TRUE;		/* Line folding option */
Xint restart = TRUE;		/* Restart page number at each file option */
Xint only_printable = FALSE;	/* Replace non printable char by space option */
Xint interpret = TRUE;		/* Interpret TAB, FF and BS chars option */
Xint print_binaries = FALSE;	/* Force printing for binary files */ 
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X   int narg;
X   char *arg;
X
X   /* Option processing */
X   arg = argv[narg = 1];
X   while (narg < argc && arg[0] == '-')
X   {
X      switch (arg[1])
X      {
X      case 'b':
X	 if (arg[2] != NULL)
X	    goto usage;
X	 print_binaries = TRUE;
X	 break;
X      case 'f':
X	 if (arg[2] != NULL)
X	    goto usage;
X	 folding = TRUE;
X	 break;
X      case 'i':
X	 if (arg[2] != NULL)
X	    goto usage;
X	 interpret = TRUE;
X	 break;
X      case 'n':
X	 if (arg[2] == NULL)
X	 {
X	    numbering = TRUE;
X	    break;
X	 }
X	 if (arg[3] != NULL)
X	    goto usage;
X	 switch (arg[2])
X	 {
X	 case 'b':
X	    print_binaries = FALSE;
X	    break;
X	 case 'f':
X	    folding = FALSE;
X	    break;
X	 case 'i':
X	    interpret = FALSE;
X	    break;
X	 case 'n':
X	    numbering = FALSE;
X	    break;
X	 case 'r':
X	    restart = FALSE;
X	    break;
X	 case 'v':
X	    only_printable = TRUE;
X	    break;
X	 default:
X	    goto usage;
X	 }
X	 break;
X      case 'r':
X	 if (arg[2] != NULL)
X	    goto usage;
X	 restart = TRUE;
X	 break;
X      case 'v':
X	 if (arg[2] != NULL)
X	    goto usage;
X	 only_printable = FALSE;
X	 break;
X      default:
X      usage:
X	 fprintf(stderr,
X         "usage: a2ps [-n{bfinrv}] [-b] [-f] [-i] [-n] [-r] [-v] [f1 f2 ... fn]");
X	 exit(1);
X      }
X      arg = argv[++narg];
X   }
X   if (narg >= argc)
X      goto usage;
X
X   /* Header printing (postcript prolog) */
X   print_header();
X
X   /* Print files designated or standard input */
X   prefix_width = numbering ? 6 : 1;
X   if (narg >= argc)
X      print_file("stdin");
X   else
X   {
X      while (narg < argc)
X      {
X	 if (freopen(arg, "r", stdin) == NULL)
X	 {
X	    fprintf(stderr, "Error opening %s\n", arg);
X	    printf("cleanup\n");
X	    exit(1);
X	 }
X	 print_file(arg);
X	 arg = argv[++narg];
X      }
X   }
X
X   printf("cleanup\n");
X}
X
Xvoid print_file(name)
Xchar *name;
X{
X   register int c;
X   int start_line, continue_exit;
X   int char_width;
X
X   /*
X    * Printing binary files is not very useful. We stop printing
X    * if we detect one of these files. Our heuristic to detect them:
X    * if 50% characters of first page are non-printing characters,
X    * the file is a binary file.
X    * Option -b force binary files impression.
X    */
X   first_page = TRUE;
X   nonprinting_chars = chars = 0;
X
X   /*
X    * Preprocessing (before printing):
X    * - TABs expansion (see interpret option)
X    * - FF and BS interpretation
X    * - replace non printable characters by a space or a char sequence
X    *   like:
X    *     ^X for ascii codes < 0x20 (X = [@, A, B, ...])
X    *     ^? for del char
X    *     M-c for ascii codes > 0x3f
X    * - prefix parents and backslash ['(', ')', '\'] by backslash
X    *   (escape character in postcript)
X    */
X   column = 0;
X   line = line_number = 0;
X   start_line = TRUE;
X   printf("(%s) newfile\n", name);
X   if (restart)
X      printf("/sheet 1 def\n");
X   printf("startpage\n");
X
X   c = getchar();
X   while (c != EOF)
X   {
X      /* Form feed */
X      if (c == '\f' && interpret)
X      {
X	 if (!start_line)
X	    printf(") s\n");
X	 start_line = TRUE;
X	 printf("endpage startpage\n");
X	 if (first_page && is_binaryfile(name))
X	    return;
X	 line = 0;
X	 if ((c = getchar()) == EOF)
X	    break;
X      }
X
X      /* Start a new line? */
X      if (start_line)
X      {
X	 if (numbering)
X	    printf("(%-5d ", ++line_number);
X	 else
X	    printf("( ");
X	 start_line = FALSE;
X      }
X
X      /* Interpret each character */
X      switch (c)
X      {
X      case '\b':
X	 if (!interpret)
X	    goto print;
X	 if (column)
X	    column--;
X	 putchar(c);
X	 break;
X      case '\n':
X	 column = 0;
X	 start_line = TRUE;
X	 printf(") s\n");
X	 if (++line >= LINESPERPAGE)
X	 {
X	    printf("endpage startpage\n");
X	    if (first_page && is_binaryfile(name))
X	       return;
X	    line = 0;
X	 }
X	 break;
X      case '\t':
X	 if (interpret)
X	 {
X	    continue_exit = FALSE;
X	    do
X	    {
X	       if (++column + prefix_width > COLUMNSPERLINE)
X		  if (folding)
X		  {
X		     if (fold_line(name) == FALSE)
X			return;
X		  }
X		  else
X		  {
X		     c = cut_line();
X		     continue_exit = TRUE;
X		     break;
X		  }
X	       putchar(' ');
X	    } while (column & 0x7);
X	    if (continue_exit)
X	       continue;
X	    break;
X        }
X      default:
X      print:
X	 if (only_printable)
X	    char_width = 1;
X	 else
X	 {
X	    char_width = c > 0177 ? 2 : 0;
X	    char_width += c < ' ' || c == 0177 ? 2 : 1;
X	 }
X	 if (prefix_width + (column += char_width) > COLUMNSPERLINE)
X	    if (folding)
X	    {
X	       if (fold_line(name) == FALSE)
X		  return;
X	    }
X	    else
X	    {
X	       c = cut_line();
X	       continue;
X	    }
X	 if (c == '(' || c == ')' || c == '\\')
X	    putchar('\\');
X	 if (c >= ' ' && c < 0177)
X	    putchar(c);
X	 else
X	 {
X	    nonprinting_chars++;
X	    if (only_printable)
X	       putchar(' ');
X	    else
X	    {
X	       if (c > 0177)
X	       {
X		  printf("M-");
X		  c &= 0177;
X	       }
X	       if (c < ' ')
X		  printf("^%c", c+'@');
X	       else if (c == 0177)
X		  printf("^?");
X	       else
X		  putchar(c);
X	    }
X	 }
X	 chars++;
X	 break;
X      }
X      c = getchar();
X   }
X
X   if (!start_line)
X      printf(") s\n");
X   printf("endpage\n");
X}
X
Xint fold_line(name)
Xchar *name;
X{
X   column = 0;
X   printf(") s\n");
X   if (++line >= LINESPERPAGE)
X   {
X      printf("endpage startpage\n");
X      if (first_page && is_binaryfile(name))
X	 return FALSE;
X      line = 0;
X   }
X   if (numbering)
X      printf("(      ");
X   else
X      printf("( ");
X
X   return TRUE;
X}
X
Xchar cut_line()
X{
X   char c;
X
X   while ((c = getchar()) != EOF && c != '\n' && c != '\f');
X   return c;
X}
X
Xis_binaryfile(name)
Xchar *name;
X{
X   first_page = FALSE;
X   if (!print_binaries && (nonprinting_chars*100 / chars) >= 75)
X   {
X      fprintf(stderr, "%s is a binary file: printing aborted\n", name);
X      return TRUE;
X   }
X   return FALSE;
X}
X
Xprint_header()
X{
X   register int c;
X   FILE *f;
X   char *string;
X#ifdef ANSIC
X   time_t date;
X#else
X#ifdef UNIX
X   struct timeval date;
X   struct tm *p;
X#else
X#ifdef SYSV
X    struct timeb date;
X#endif
X#endif
X#endif
X
X   if ((f = fopen(HEADER_PS, "r")) == NULL)
X   {
X      fprintf(stderr, "Poscript header missing\n");
X      exit(1);
X   }
X
X   /* Header file printing */
X   while ((c = getc(f)) != EOF)
X      putchar(c);
X
X   /* Retrieve date and hour */
X#ifdef ANSIC
X   if (time(&date) == -1)
X   {
X      fprintf(stderr, "Error calculing time\n");
X      exit(1);
X   }
X   string = ctime(&date);
X
X   /* and print them */
X   printf("/date (%.6s %.4s %.8s) def\n", string+4, string+20, string+11);
X#else
X#ifdef UNIX
X   (void) gettimeofday(&date, (struct timezone *)0);
X   p = localtime(&date.tv_sec);
X   string = asctime(p);
X
X   /* and print them */
X   printf("/date (%.6s %.4s %.8s) def\n", string+4, string+20, string+11);
X#else
X#ifdef SYSV
X   (void)ftime(&date);
X   string = ctime(&date.time);
X   printf("/date (%.6s %.4s %.8s) def\n", string+4, string+20, string+11);
X#endif
X#endif
X#endif
X
X   /* Go on */
X   printf("startdoc\n");
X}
SHAR_EOF
chmod 0664 a2ps.c || echo "restore of a2ps.c fails"
set `wc -c a2ps.c`;Sum=$1
if test "$Sum" != "9038"
then echo original size 9038, current size $Sum;fi
fi
if test -f header.ps; then echo "File header.ps exists"; else
echo "x - extracting header.ps (Text)"
sed 's/^X//' << 'SHAR_EOF' > header.ps &&
X%!  PostScript Source Code
X%
X%  File: imag:/users/local/a2ps/header.ps
X%  Created: Tue Nov 29 12:14:02 1988 by miguel@imag (Miguel Santana)
X%  Version: 2.0
X%  Description: PostScript prolog for a2ps ascii to PostScript program.
X% 
X%  Edit History:
X%  - Original version by evan@csli (Evan Kirshenbaum).
X%  - Modified by miguel@imag to:
X%    1) Correct an overflow bug when printing page number 10 (operator
X%	cvs).
X%    2) Define two other variables (sheetwidth, sheetheight) describing
X%	the physical page (actually A4 format).
X%    3) Minor changes (reorganization, comments, etc).
X%
X
X% Copyright (c) 1988, Miguel Santana, miguel@imag.imag.fr
X%
X% Permission is granted to copy and distribute this file in modified
X% or unmodified form, for noncommercial use, provided (a) this copyright
X% notice is preserved, (b) no attempt is made to restrict redistribution
X% of this file, and (c) this file is not distributed as part of any
X% collection whose redistribution is restricted by a compilation copyright.
X%
X
X
X% General macros.
X/xdef {exch def} bind def
X/inch {72 mul} bind def
X/getfont {exch findfont exch scalefont} bind def
X
X% Dimensions of a physical page.
X/sheetwidth 11.7 inch def
X/sheetheight 8.25 inch def
X
X% Character size for differents fonts.
X/filenamefontsize 12 def
X/datefontsize filenamefontsize 2 sub def
X/headerfontsize filenamefontsize 4 add def
X/bodyfontsize 6.8 def
X
X% Font assignment to differents kinds of "objects"
X/filenamefont /Helvetica-Bold filenamefontsize getfont def
X/datefont /Helvetica datefontsize getfont def
X/bodyfont /Courier bodyfontsize getfont def
X
X
X% Logical page attributs (a half of a real page or sheet).
X/linesperpage 66 def
X/sidemargin 4 def
X/topmargin 4 def
X/pagewidth 
X   bodyfont setfont (0) stringwidth pop 86 mul sidemargin dup add add
X   def
X/pageheight
X   bodyfontsize linesperpage mul topmargin dup add add headerfontsize add
X   def
X
X% Upper corner for a logical page. Coordinate x is not the same for left
X% and right pages: upperx is an array of two elements, indexed by sheetside.
X/uppery sheetheight pageheight add 2 div def
X/upperx [ sheetwidth pagewidth 2 mul sub 3 div	% upperx for left page
X          dup 2 mul pagewidth add		% upperx for right page
X        ] def
X
X% String used to make easy printing numbers
X/pnum 12 string def
X/empty 12 string def
X
X
X% Function startdoc: initializes printer and global variables.
X/startdoc
X    { sheetheight 0 inch translate	% new origin for the coordinate system
X      90 rotate				% landscape format
X      /sheetside 0 def			% sheet side that contains current page
X      /sheet 1 def			% sheet number
X    } bind def
X
X% Function newfile: init file name and reset page number for each new file.
X/newfile
X    { /filename xdef
X      /pagenum 1 def 
X      cleanup
X    } bind def
X
X% Function cleanup: terminates printing, flushing last page if necessary.
X/cleanup
X    { sheetside 1 eq
X         { /sheetside 0 def
X           sheetnumber
X           /sheet sheet 1 add def
X           copypage
X           erasepage
X         }
X      if
X    } bind def
X
X%
X% Function startpage: prints page header and page border and initializes
X% printing of the file lines.
X/startpage
X    { printheader
X      printborder
X      upperx sheetside get  sidemargin  add
X      uppery topmargin sub  bodyfontsize  sub  headerfontsize  sub
X         moveto
X      bodyfont setfont
X    } bind def
X
X% Function printheader: prints page header.
X/printheader
X    { upperx sheetside get  uppery headerfontsize sub 1 add  moveto
X      datefont setfont
X      gsave
X        sidemargin 2 rmoveto date show				% date/hour
X      grestore
X      gsave
X        pagenum pnum cvs
X        pagewidth sidemargin sub pnum stringwidth pop sub
X        (Page ) stringwidth pop sub 3 rmoveto
X        (Page ) show pnum show					% page number
X      grestore
X      empty pnum copy
X      gsave
X        filenamefont setfont
X        pagewidth filename stringwidth pop sub 2 div 2 rmoveto
X        filename show						% file name
X      grestore
X    } bind def
X
X% Function printborder: prints border page.
X/printborder 
X    { upperx sheetside get uppery moveto
X      gsave					% print the four sides
X        pagewidth 0 rlineto			% of the square
X        0 pageheight neg rlineto
X        pagewidth neg 0 rlineto
X        closepath stroke
X      grestore
X      0 headerfontsize neg rmoveto pagewidth 0 rlineto stroke
X    } bind def
X
X%
X% Function endpage: adds a sheet number to the page (footnote) and prints
X% the formatted page (physical impression). Activated at the end of each
X% source page (linesperpage reached or FF character).
X/endpage
X   { sheetside 1 eq
X        { /sheetside 0 def
X          sheetnumber
X          copypage
X          erasepage 
X          /sheet sheet 1 add def
X        }
X        { /sheetside 1 def }
X     ifelse
X     /pagenum pagenum 1 add def
X    } bind def
X
X% Function sheetnumber: prints the sheet number.
X/sheetnumber
X    { sheetwidth  upperx 0 get  sub  sidemargin  add
X      sheetheight  uppery  sub  headerfontsize  sub
X         moveto
X      datefont setfont
X      sheet pnum cvs show
X      empty pnum copy
X    } bind def
X
X% Function s: print a source line
X/s  { gsave
X        show
X      grestore
X      0 bodyfontsize neg rmoveto
X    } bind def
SHAR_EOF
chmod 0664 header.ps || echo "restore of header.ps fails"
set `wc -c header.ps`;Sum=$1
if test "$Sum" != "5200"
then echo original size 5200, current size $Sum;fi
fi
exit 0
-- 
Miguel SANTANA   miguel@imag.fr or miguel@imag.UUCP (uunet.uu.net!imag!miguel)