From: rkk@cfi.org (Randy Kirchhof)
Subject: UNIX: FM PostScript splitter (shar file)
Summary: program to split Framemaker ps files.
Organization: CAD Framework Initiative, Austin, TX
Date: Wed, 18 Nov 1992 14:42:22 GMT

Hi, Framers -

We ran into a bit of a problem this week and devised a solution that
may be of use to others. I am sorry to say that I don't read this
group as much as I'd like; If we've reinvented the wheel here, sorry 
for the wasted bandwidth.

Situation: We're at a major release point on some documentation, with
1000+ pages of PostScript output ready to send to the printers. The 
linotype people want PostScript, but they neglected to mention that
they want it in 15 page chunks, so that they can change film, etc.

Being a Frame user, but not in any sense a guru, I decided to look for
tools out there on the net; I found a program called "breakps" by
William Chia-Wei Cheng in an old Andrew toolkit archive.  This didn't
work, but one of our programmers, David Mallis, put together a new
program that is tuned to FM PostScript files.

What it does: split-ps takes a big PostScript file from FrameMaker
and turns it into a number of specified-size smaller, free-standing
PostScript files. These can then be printed standalone. It was written
on a Sun, but should be portable.

Note: the aforementioned linotype folks are in a Mac domain; I have
successfully split a large UNIX/FM ps file into smaller, ftp'd to a Mac
(via NCSA Telnet) and printed from the Mac. If you do this, use "ascii"
as your transfer type, and use "download postscript" in the LaserWriter
Utility.

Here is a shar file; we hope that it's useful to you.

thanks,

Randy & David.

---- Cut Here and unpack ----
#!/bin/sh
# This is a shell archive (shar 3.11/nixbbs)
# made 11/18/1992 14:31 UTC by rkk@austin
# Source directory /home/rkk/break-ps
#
# existing files WILL be overwritten
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   5807 -rw-r--r-- split-ps.c
#
touch 2>&1 | fgrep '[-amc]' > /tmp/s3_touch$$
if [ -s /tmp/s3_touch$$ ]
then
	TOUCH=can
else
	TOUCH=cannot
fi
rm -f /tmp/s3_touch$$
# ============= split-ps.c ==============
echo "x - extracting split-ps.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > split-ps.c &&
X/* 
X* split-ps.c 
X*
X* Author: David Mallis (mallis@cfi.org), CAD Framework Initiative, 11/17/92
X*
X* Inspired by breakps, written by William Chia-Wei Cheng
X*
X* Designed for use on FrameMaker PostScript output in a UNIX environment.
X* Splits existing FM PostScript files into smaller free-standing ps files.
X* To compile: "cc -o split-ps split-ps.c"; should be portable.
X*
X* FrameMaker and PostScript are trademarks of their respective owners.
X* Written for and tested with FrameMaker 3.1X on a Sun, 4.1.1.
X*
X* This is free software, and may be used by any person for any reason.
X* NO WARRANTY is expressed or implied. Use at your own risk. We ask that
X* you acknowledge the origin if you incorporate this code elsewhere.
X*
X* NOTE: code is untested when using non-standard fonts, specifically
X* not tested in downloadable font situations. 
X*
X* Your mileage may vary. Runs with 100% recycled electrons.
X
XNotes from the author:
X
XThis is a quick-and-dirty program to chop up PostScript output files
Xinto subfiles with fewer pages, copying the prolog into each.  A
Xresulting `subfile' is also choppable by the same program.
X
XThis was specifically written for FrameMaker files, although the
Xalgorithm will probably work with minimal modification for other,
Xmodern flavors of PS driver output.
X
XThis has many dependencies and hard-codings, SOME of which are:
X
X  * Assumes PS file has NEWLINE characters FREQUENTLY delimiting the code
X    (at least every 255 characters).  If not, enlarge the  line[256]  
X    buffer.
X
X  * If all \n have been squeezed out then the algorithm will have to 
X    be modified.
X
X  * Assumes the file is structured with these tokens:
X
X          ----Prolog Code used once for whole file----
X        EOH token
X        BOP token
X          ---------ONE PAGE OF PS CODE-----
X        EOP token
X        BOP token
X          ---------ONE PAGE OF PS CODE-----
X        EOP token
X           .
X           .
X           .
X        TRAILER token
X
X  * Note the defines for these expected token delimiters.  Change them 
X    as needed.
X
X  * If the structure of your PS file is more complicated, you will have 
X    to get your hands dirty in the algorithm.
X
X  * Assumes that the PS driver was smart enough to put all font,
X    graphics, and other PS procedure definitions in the prolog.  This
X    is not a trivial expectation.  There are drivers that create new
X    font definitions on the fly in page 32, for example, and then use
X    them later in page 45.  If this is the case with your PS driver
X    output, then if you chop out page 32 you will get a PS error on
X    page 45.
X
X  * Assumes a scratch file named HEAD_FILE (see #define) can be
X    overwritten then deleted.
X
X  * Probably many other implicit assumptions too gross to mention.
X
XAlso, this program does very little error checking on input parameters,
Xfile creation, etc.
X
X                          USE WITH DUE CAUTION.
Xend comments */
X
X#include <errno.h>
X#include <stdio.h>
X
X#define EOH "%%EndSetup"
X#define EOP "%%EndPage"
X#define BOP "%%Page"
X#define TRAILER "%%Trailer"
X#define HEAD_FILE "QQhead"
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
Xchar  line[256];
Xint   ncEOH, ncEOP, ncBOP, ncTRAILER ;
Xchar  fname[50];
Xint   fcount=0, maxpages, pcount;
Xint   notdone=1;
XFILE  *Fhead, *Fout;
X
X/* USAGE CHECK */
Xif (argc<3)
X  {
X  fprintf(stderr,"\n");
X  fprintf(stderr,"USAGE:  split-ps  n  fname < bigfile.ps\n");
X  fprintf(stderr,"where -   n = #pages max in each file\n");
X  fprintf(stderr,"      -   fname = base file name for output files;\n");
X  fprintf(stderr,"                  .0, .1, etc will be appended to each one.\n");
X  fprintf(stderr,"      -   bigfile.ps is a FrameMaker PostScript file.\n");
X  fprintf(stderr,"\n");
X  exit(99);
X  }
X
XncEOH=strlen(EOH);
XncBOP=strlen(BOP);
XncEOP=strlen(EOP);
XncTRAILER=strlen(TRAILER);
Xmaxpages=atoi(argv[1]);
Xprintf("Creating files %s.xxxx of %d pages each.\n", argv[2], maxpages );
X
Xerrno=0; if ( (Fhead=fopen(HEAD_FILE,"w+")) == NULL )
X  {
X  printf("Can't create temp output header file, errno=%d!\n", errno );
X  exit(1);
X  }
X
X/* COPY HEADER TO TEMP FILE */
Xwhile ( fgets(line,255,stdin) != NULL )
X  {
X  fprintf(Fhead, "%s", line);
X  if ( strncmp(EOH,line,ncEOH) == 0 ) break; /* END OF HEADER SENTINEL */
X  }
Xfclose(Fhead);
X
Xwhile (notdone)
X  {
X  sprintf(fname,"%s.%d", argv[2], fcount );  /* CREATE NEW FILE NAME . EXT */
X  CopyHeader(fname,Fout);
X  errno=0; if ( (Fout=fopen(fname,"a")) == NULL )
X    {
X    printf("Can't open append output file %s, errno=%d!\n", fname, errno );
X    exit(3);
X    }
X  pcount=0;
X  while (pcount<maxpages)
X    {
X    if ( fgets(line,255,stdin) == NULL )
X      {
X      fprintf(stderr,"Expecting BOP marker: %s, got EOF, errno=%d.\n", BOP );
X      fclose(Fout);  exit(3);
X      }
X    if ( strncmp(TRAILER,line,ncTRAILER) == 0 )
X      { notdone=0; break; }
X    if ( strncmp(BOP,line,ncBOP) != 0 )
X      {
X      fprintf(stderr,"Expecting BOP marker: %s, got %s, errno=%d.\n", BOP, line );
X      fclose(Fout);  exit(4);
X      }
X    fprintf(Fout,"%s",line);
X    while ( fgets(line,255,stdin) != NULL )
X      {
X      fprintf(Fout,"%s",line);
X      if (strncmp(EOP,line,ncEOP)==0) { break; } 
X      }
X    ++pcount;
X    }
X  ++fcount;
X  fprintf(Fout,"%s\n",TRAILER);
X  fclose(Fout);
X  if (pcount==0) unlink(fname);
X            else fprintf(stderr,"%d pages in file %s\n",pcount,fname);
X  }
Xunlink(HEAD_FILE);
X}
X
X
XCopyHeader(fname)
Xchar *fname;
X{
XFILE  *Fhead, *Fout;
Xchar  line[256];
X
Xerrno=0; if ( (Fout=fopen(fname,"w+")) == NULL )
X  {
X  printf("Can't create output file %s, errno=%d!\n", fname, errno );
X  exit(3);
X  }
X
Xerrno=0; if ( (Fhead=fopen(HEAD_FILE,"r")) == NULL )
X  {
X  printf("Can't read output header file, errno=%d!\n", errno );
X  exit(2);
X  }
X
Xwhile ( fgets(line,255,Fhead) != NULL )
X  {
X  fprintf(Fout, "%s", line);
X  }
X
Xfclose(Fout);
Xfclose(Fhead);
X
X}
X
X
X
SHAR_EOF
chmod 0644 split-ps.c || echo "restore of split-ps.c fails"
if [ $TOUCH = can ]
then
    touch -am 1118082892 split-ps.c
fi
set `wc -c split-ps.c`;Wc_c=$1
if test "$Wc_c" != "5807"
then echo original size 5807, current size $Wc_c;fi
exit 0
-- 
==================================================================
 rkk@cfi.org        | Randy Kirchhof |  CAD Framework Initiative
 Desk: 512/338-3343 | Systems/Apps   | 4030 West Braker Lane #550
 Fax:  512/338-3853 | Administrator  |     Austin, TX 78759