summaryrefslogtreecommitdiff
path: root/sys/src/cmd/postscript/picpack
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/postscript/picpack
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/postscript/picpack')
-rwxr-xr-xsys/src/cmd/postscript/picpack/mkfile57
-rwxr-xr-xsys/src/cmd/postscript/picpack/picpack.1123
-rwxr-xr-xsys/src/cmd/postscript/picpack/picpack.c441
-rwxr-xr-xsys/src/cmd/postscript/picpack/picpack.mk75
4 files changed, 696 insertions, 0 deletions
diff --git a/sys/src/cmd/postscript/picpack/mkfile b/sys/src/cmd/postscript/picpack/mkfile
new file mode 100755
index 000000000..4c713bb60
--- /dev/null
+++ b/sys/src/cmd/postscript/picpack/mkfile
@@ -0,0 +1,57 @@
+BUILTINS=
+</$objtype/mkfile
+MAKE=mk
+
+SYSTEM=plan9
+VERSION=3.3.1
+
+ROOT=
+MAN1DIR=$ROOT/tmp
+POSTBIN=$ROOT/sys/lib/postscript/bin
+
+COMMONDIR=../common
+
+CC=pcc
+LD=pcc
+
+CFLAGS=-c -D$SYSTEM -D_POSIX_SOURCE -I$COMMONDIR -B
+LDFLAGS=
+
+all :V: $O.out
+
+install :V: $POSTBIN/$objtype/picpack $MAN1DIR/picpack.1
+
+installall :V:
+ for(objtype in $CPUS) { \
+ $MAKE 'MAKE=$MAKE' \
+ 'SYSTEM=$SYSTEM' 'VERSION=$VERSION' \
+ 'FONTDIR=$FONTDIR' 'HOSTDIR=$HOSTDIR' 'MAN1DIR=$MAN1DIR' \
+ 'POSTBIN=$POSTBIN' 'POSTLIB=$POSTLIB' 'TMACDIR=$TMACDIR' \
+ 'DKHOST=$DKHOST' 'DKSTREAMS=$DKSTREAMS' \
+ 'ROUNDPAGE=$ROUNDPAGE' \
+ 'CC=$CC' 'LD=$LD' 'CFLAGS=$CFLAGS' 'LDFLAGS=$LDFLAGS' \
+ install \
+ }
+
+clean :V:
+ rm -f *.$O
+
+clobber :V: clean
+ rm -f $O.out
+
+$POSTBIN/$objtype/picpack : $O.out
+ cp $prereq $target
+
+$MAN1DIR/picpack.1 : picpack.1
+ cp $prereq $target
+
+$O.out : picpack.$O $COMMONDIR/glob.$O $COMMONDIR/misc.$O $COMMONDIR/tempnam.$O $COMMONDIR/getopt.$O
+ $LD $LDFLAGS $prereq
+
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+
+picpack.$O : picpack.c $COMMONDIR/ext.h $COMMONDIR/gen.h $COMMONDIR/path.h
+
+common :V:
+ cd $COMMONDIR; $MAKE
diff --git a/sys/src/cmd/postscript/picpack/picpack.1 b/sys/src/cmd/postscript/picpack/picpack.1
new file mode 100755
index 000000000..ee5a428fa
--- /dev/null
+++ b/sys/src/cmd/postscript/picpack/picpack.1
@@ -0,0 +1,123 @@
+.TH PICPACK 1
+.SH NAME
+.B picpack
+\- PostScript picture packing preprocessor
+.SH SYNOPSIS
+\*(mBpicpack\f1
+.OP "" options []
+.OP "" files []
+.SH DESCRIPTION
+.B picpack
+copies
+.I files
+to stdout, expanding picture inclusion requests
+(marked by the
+.MW .BP
+or
+.MW .PI
+macros) into an in-line
+format that can be passed through
+.B troff
+and handled by
+.BR dpost .
+If no
+.I files
+are specified
+or if
+.OP \-
+is one of the input
+.I files
+standard input is read.
+The following
+.I options
+are understood:
+.TP 0.75i
+.OP \-k list
+.I list
+is a comma- or space-separated string of words used to locate
+picture inclusion requests.
+The start of every line in the input
+.I files
+is compared with each word in
+.I list .
+If there is a match, the second string on the line is
+taken as the pathname of a picture file that is added
+to the output file.
+The default
+.I list
+is
+.RM `` ".BP .PI ''.
+.TP
+.OP \-q
+Suppress ``missing picture file'' error messages.
+.PP
+.B picpack
+is a trivial preprocessor that, in a sense, duplicates some of the
+picture inclusion capabilities already available in
+.BR dpost .
+.B picpack
+should not be used if your formatting command line includes
+a call to
+.BR dpost .
+Its only purpose is to combine picture files with text in a single
+file that can be passed through
+.B troff
+and unpacked, at some later time, by
+.BR dpost .
+The original picture inclusion mechanism, with files are pulled in by
+.BR dpost ,
+is the preferred approach.
+.SH EXAMPLES
+A typical application might be in a distributed printing environment
+where everything up to
+.B troff
+is run by the user and everything after
+.B troff
+is handled by a spooling daemon (perhaps
+.BR lp ).
+In that case the command line would be,
+.EX
+pic \f2file\fP | tbl | eqn | picpack | troff -mm -Tpost | lp
+.EE
+A poor example, although one that should still work, would be,
+.EX
+pic \f2file\fP | tbl | eqn | picpack | troff -mm -Tpost | dpost >\f2file\fP.ps
+.EE
+In this case picture inclusion requests could (and should) be handled by
+.BR dpost .
+Running
+.B picpack
+is not needed or even recommended.
+It should be dropped from any pipeline that includes a call to
+.BR dpost .
+.SH DIAGNOSTICS
+A 0 exit status is returned if
+.I files
+were successfully processed.
+.SH WARNINGS
+.PP
+Combining pictures and text using the capabilities available in
+.B dpost
+is the recommended approach and is always guaranteed to be more
+efficient than
+.BR picpack .
+Running
+.B picpack
+and
+.B dpost
+in the same pipeline makes little sense.
+.PP
+Using
+.B picpack
+will likely result in files that can no longer be reliably passed
+through other important
+.B troff
+postprocessors like
+.BR proof .
+At present
+.B picpack
+is only guaranteed to work with
+.BR dpost .
+.SH SEE ALSO
+.BR dpost (1),
+.BR troff (1)
diff --git a/sys/src/cmd/postscript/picpack/picpack.c b/sys/src/cmd/postscript/picpack/picpack.c
new file mode 100755
index 000000000..7d96bc02b
--- /dev/null
+++ b/sys/src/cmd/postscript/picpack/picpack.c
@@ -0,0 +1,441 @@
+/*
+ *
+ * picpack - picture packing pre-processor
+ *
+ * A trivial troff pre-processor that copies files to stdout, expanding picture
+ * requests into an in-line format that's passed transparently through troff and
+ * handled by dpost. The program is an attempt to address requirements, expressed
+ * by several organizations, of being able to store a document as a single file
+ * (usually troff input) that can then be sent through dpost and ultimately to
+ * a PostScript printer.
+ *
+ * The program looks for strings listed in the keys[] array at the start of each
+ * line. When a picture request (as listed in keys[]) is found the second string
+ * on the line is taken to be a picture file pathname that's added (in transparent
+ * mode) to the output file. In addition each in-line picture file is preceeded by
+ * device control command (again passed through in transparent mode) that looks
+ * like,
+ *
+ * x X InlinePicture filename bytes
+ *
+ * where bytes is the size of the picture file (which begins on the next line)
+ * and filename is the pathname of the picture file. dpost uses both arguments to
+ * manage in-line pictures (in a big temp file). To handle pictures in diversions
+ * picpack reads each input file twice. The first pass looks for picture inclusion
+ * requests and copies each picture file transparently to the output file, while
+ * second pass just copies the input file to the output file. Things could still
+ * break, but the two pass method should handle most jobs.
+ *
+ * The recognized in-line picture requests are saved in keys[] and by default only
+ * expand .BP and .PI macro calls. The -k option changes the recognized strings,
+ * and may be needed if you've built your own picture inclusion macros on top of
+ * .BP or .PI or decided to list each picture file at the start of your input file
+ * using a dummy macro. For example you could require every in-line picture be
+ * named by a dummy macro (say .iP), then the command line,
+ *
+ * picpack -k.iP file > file.pack
+ *
+ * hits on lines that begin with .iP (rather than .BP or .PI), and the only files
+ * pulled in would be ones named as the second argument to the new .iP macro. The
+ * -k option accepts a space or comma separated list of up to 10 different key
+ * strings. picpack imposes no contraints on key strings, other than not allowing
+ * spaces or commas. A key string can begin with \" and in that case it would be
+ * troff comment.
+ *
+ * Although the program will help some users, there are obvious disadvantages.
+ * Perhaps the most important is that troff output files (with in-line pictures
+ * included) don't fit the device independent language accepted by important post
+ * processors like proof, and that means you won't be able to reliably preview a
+ * packed file on your 5620 or whatever. Another potential problem is that picture
+ * files can be large. Packing everything together in a single file at an early
+ * stage has a better chance of exceeding your system's ulimit.
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#include "gen.h" /* general purpose definitions */
+#include "ext.h" /* external variable definitions */
+#include "path.h" /* just for TEMPDIR definition */
+
+char *keys[11] = {".BP", ".PI", NULL};
+int quiet = FALSE;
+
+FILE *fp_in = stdin; /* input */
+FILE *fp_out = stdout; /* and output files */
+
+/*****************************************************************************/
+
+main(agc, agv)
+
+ int agc;
+ char *agv[];
+
+{
+
+/*
+ *
+ * A picture packing pre-processor that copies input files to stdout, expanding
+ * picture requests (as listed in keys[]) to an in-line format that can be passed
+ * through troff (using transparent mode) and handled later by dpost.
+ *
+ */
+
+ argc = agc; /* global so everyone can use them */
+ argv = agv;
+
+ prog_name = argv[0]; /* just for error messages */
+
+ options(); /* command line options */
+ arguments(); /* translate all the input files */
+ done(); /* clean things up */
+
+ exit(x_stat); /* everything probably went OK */
+
+} /* End of main */
+
+/*****************************************************************************/
+
+options()
+
+{
+
+ int ch; /* name returned by getopt() */
+
+ extern char *optarg; /* option argument set by getopt() */
+ extern int optind;
+
+/*
+ *
+ * Handles the command line options.
+ *
+ */
+
+ while ( (ch = getopt(argc, argv, "k:qDI")) != EOF ) {
+ switch ( ch ) {
+ case 'k': /* new expansion key strings */
+ newkeys(optarg);
+ break;
+
+ case 'q': /* disables "missing picture" messages */
+ quiet = TRUE;
+ break;
+
+ case 'D': /* debug flag */
+ debug = ON;
+ break;
+
+ case 'I': /* ignore FATAL errors */
+ ignore = ON;
+ break;
+
+ case '?': /* don't know the option */
+ error(FATAL, "");
+ break;
+
+ default:
+ error(FATAL, "missing case for option %c", ch);
+ break;
+ } /* End switch */
+ } /* End while */
+
+ argc -= optind; /* get ready for non-options args */
+ argv += optind;
+
+} /* End of options */
+
+/*****************************************************************************/
+
+newkeys(list)
+
+ char *list; /* comma or space separated key strings */
+
+{
+
+ char *p; /* next key string from *list */
+ int i; /* goes in keys[i] */
+ int n; /* last key string slot in keys[] */
+
+/*
+ *
+ * Separates *list into space or comma separated strings and adds each to the
+ * keys[] array. The strings in keys[] are used to locate the picture inclusion
+ * requests that are translated to the in-line format. The keys array must end
+ * with a NULL pointer and by default only expands .BP and .PI macro calls.
+ *
+ */
+
+ n = (sizeof(keys) / sizeof(char *)) - 1;
+
+ for ( i = 0, p = strtok(list, " ,"); p != NULL; i++, p = strtok(NULL, " ,") )
+ if ( i >= n )
+ error(FATAL, "too many key strings");
+ else keys[i] = p;
+
+ keys[i] = NULL;
+
+} /* End of newkeys */
+
+/*****************************************************************************/
+
+arguments()
+
+{
+
+ FILE *copystdin();
+
+/*
+ *
+ * Makes sure all the non-option command line arguments are processed. If we get
+ * here and there aren't any arguments left, or if '-' is one of the input files
+ * we process stdin, after copying it to a temporary file.
+ *
+ */
+
+ if ( argc < 1 ) {
+ fp_in = copystdin();
+ picpack();
+ } else
+ while ( argc > 0 ) {
+ if ( strcmp(*argv, "-") == 0 )
+ fp_in = copystdin();
+ else if ( (fp_in = fopen(*argv, "r")) == NULL )
+ error(FATAL, "can't open %s", *argv);
+ picpack();
+ fclose(fp_in);
+ argc--;
+ argv++;
+ } /* End while */
+
+} /* End of arguments */
+
+/*****************************************************************************/
+
+FILE *copystdin()
+
+{
+
+ char *tfile; /* temporary file name */
+ int fd_out; /* and its file descriptor */
+ FILE *fp; /* return value - the new input file */
+
+/*
+ *
+ * Copies stdin to a temp file, unlinks the file, and returns the file pointer
+ * for the new temporary file to the caller. Needed because we read each input
+ * file twice in an attempt to handle pictures in diversions.
+ *
+ */
+
+ if ( (tfile = tempnam(TEMPDIR, "post")) == NULL )
+ error(FATAL, "can't generate temp file name");
+
+ if ( (fd_out = creat(tfile, 0660)) == -1 )
+ error(FATAL, "can't create %s", tfile);
+
+ copyfile(fileno(stdin), fd_out);
+ close(fd_out);
+
+ if ( (fp = fopen(tfile, "r")) == NULL )
+ error(FATAL, "can't open %s", tfile);
+
+ unlink(tfile);
+ return(fp);
+
+} /* End of copystdin */
+
+/*****************************************************************************/
+
+copyfile(fd_in, fd_out)
+
+ int fd_in; /* input */
+ int fd_out; /* and output files */
+
+{
+
+ char buf[512]; /* internal buffer for reads and writes */
+ int count; /* number of bytes put in buf[] */
+
+/*
+ *
+ * Copies file fd_in to fd_out. Handles the second pass for each input file and
+ * also used to copy stdin to a temporary file.
+ *
+ */
+
+ while ( (count = read(fd_in, buf, sizeof(buf))) > 0 )
+ if ( write(fd_out, buf, count) != count )
+ error(FATAL, "write error");
+
+} /* End of copyfile */
+
+/*****************************************************************************/
+
+done()
+
+{
+
+/*
+ *
+ * Finished with all the input files - unlink the temporary file that was used
+ * to record the in-line picture file pathnames.
+ *
+ */
+
+ if ( temp_file != NULL )
+ unlink(temp_file);
+
+} /* End of done */
+
+/*****************************************************************************/
+
+picpack()
+
+{
+
+ char line[512]; /* next input line */
+ char name[100]; /* picture file names - from BP or PI */
+ int i; /* for looking through keys[] */
+
+/*
+ *
+ * Handles the two passes over the next input file. First pass compares the start
+ * of each line in *fp_in with the key strings saved in the keys[] array. If a
+ * match is found inline() is called to copy the picture file (ie. the file named
+ * as the second string in line[]) to stdout, provided the file hasn't previously
+ * been copied. The second pass goes back to the start of fp_in and copies it all
+ * to the output file.
+ *
+ */
+
+ while ( fgets(line, sizeof(line), fp_in) != NULL ) {
+ for ( i = 0; keys[i] != NULL; i++ )
+ if ( strncmp(line, keys[i], strlen(keys[i])) == 0 ) {
+ if ( sscanf(line, "%*s %s", name) == 1 ) {
+ strtok(name, "(");
+ if ( gotpicfile(name) == FALSE )
+ inline(name);
+ } /* End if */
+ } /* End if */
+ } /* End while */
+
+ fflush(fp_out); /* second pass - copy fp_in to fp_out */
+ fseek(fp_in, 0L, 0);
+ copyfile(fileno(fp_in), fileno(fp_out));
+
+} /* End of picpack */
+
+/*****************************************************************************/
+
+inline(name)
+
+ char *name; /* name of the in-line picture file */
+
+{
+
+ long size; /* size in bytes - from fstat */
+ FILE *fp; /* for reading *name */
+ int ch; /* next character from picture file */
+ int lastch = '\n'; /* so we know when to put out \! */
+
+ struct stat sbuf; /* for the picture file size */
+
+/*
+ *
+ * Copies the picture file *name to the output file in an in-line format that can
+ * be passed through troff and recovered later by dpost. Transparent mode is used
+ * so each line starts with \! and all \ characters must be escaped. The in-line
+ * picture sequence begins with an "x X InlinePicture" device control command that
+ * names the picture file and gives its size (in bytes).
+ *
+ */
+
+ if ( (fp = fopen(name, "r")) != NULL ) {
+ fstat(fileno(fp), &sbuf);
+ if ( (size = sbuf.st_size) > 0 ) {
+ fprintf(fp_out, "\\!x X InlinePicture %s %ld\n", name, size);
+ while ( (ch = getc(fp)) != EOF ) {
+ if ( lastch == '\n' )
+ fprintf(fp_out, "\\!");
+ if ( ch == '\\' )
+ putc('\\', fp_out);
+ putc(lastch = ch, fp_out);
+ } /* End while */
+ if ( lastch != '\n' )
+ putc('\n', fp_out);
+ } /* End if */
+ fclose(fp);
+ addpicfile(name);
+ } else if ( quiet == FALSE )
+ error(NON_FATAL, "can't read picture file %s", name);
+
+} /* End of inline */
+
+/*****************************************************************************/
+
+gotpicfile(name)
+
+ char *name;
+
+{
+
+ char buf[100];
+ FILE *fp_pic;
+
+/*
+ *
+ * Checks the list of previously added picture files in *temp_file and returns
+ * FALSE if it's a new file and TRUE otherwise. Probably should open the temp
+ * file once for update and leave it open, rather than opening and closing it
+ * every time.
+ *
+ */
+
+ if ( temp_file != NULL )
+ if ( (fp_pic = fopen(temp_file, "r")) != NULL ) {
+ while ( fscanf(fp_pic, "%s", buf) != EOF )
+ if ( strcmp(buf, name) == 0 ) {
+ fclose(fp_pic);
+ return(TRUE);
+ } /* End if */
+ fclose(fp_pic);
+ } /* End if */
+
+ return(FALSE);
+
+} /* End of gotpicfile */
+
+/*****************************************************************************/
+
+addpicfile(name)
+
+ char *name;
+
+{
+
+ FILE *fp_pic;
+
+/*
+ *
+ * Adds string *name to the list of in-line picture files that's maintained in
+ * *temp_file. Should undoubtedly open the file once for update and use fseek()
+ * to move around in the file!
+ *
+ */
+
+ if ( temp_file == NULL )
+ if ( (temp_file = tempnam(TEMPDIR, "picpac")) == NULL )
+ return;
+
+ if ( (fp_pic = fopen(temp_file, "a")) != NULL ) {
+ fprintf(fp_pic, "%s\n", name);
+ fclose(fp_pic);
+ } /* End if */
+
+} /* End of addpicfile */
+
+/*****************************************************************************/
+
diff --git a/sys/src/cmd/postscript/picpack/picpack.mk b/sys/src/cmd/postscript/picpack/picpack.mk
new file mode 100755
index 000000000..e79febae7
--- /dev/null
+++ b/sys/src/cmd/postscript/picpack/picpack.mk
@@ -0,0 +1,75 @@
+MAKE=/bin/make
+MAKEFILE=picpack.mk
+
+SYSTEM=V9
+VERSION=3.3.2
+
+GROUP=bin
+OWNER=bin
+
+MAN1DIR=/tmp
+POSTBIN=/usr/bin/postscript
+
+COMMONDIR=../common
+
+CFLGS=-O
+LDFLGS=-s
+
+CFLAGS=$(CFLGS) -I$(COMMONDIR)
+LDFLAGS=$(LDFLGS)
+
+HFILES=$(COMMONDIR)/ext.h\
+ $(COMMONDIR)/gen.h\
+ $(COMMONDIR)/path.h
+
+OFILES=picpack.o\
+ $(COMMONDIR)/glob.o\
+ $(COMMONDIR)/misc.o\
+ $(COMMONDIR)/tempnam.o
+
+all : picpack
+
+install : all
+ @if [ ! -d "$(POSTBIN)" ]; then \
+ mkdir $(POSTBIN); \
+ chmod 755 $(POSTBIN); \
+ chgrp $(GROUP) $(POSTBIN); \
+ chown $(OWNER) $(POSTBIN); \
+ fi
+ cp picpack $(POSTBIN)/picpack
+ @chmod 755 $(POSTBIN)/picpack
+ @chgrp $(GROUP) $(POSTBIN)/picpack
+ @chown $(OWNER) $(POSTBIN)/picpack
+ cp picpack.1 $(MAN1DIR)/picpack.1
+ @chmod 644 $(MAN1DIR)/picpack.1
+ @chgrp $(GROUP) $(MAN1DIR)/picpack.1
+ @chown $(OWNER) $(MAN1DIR)/picpack.1
+
+clean :
+ rm -f *.o
+
+clobber : clean
+ rm -f picpack
+
+picpack : $(OFILES)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o picpack $(OFILES)
+
+picpack.o : $(HFILES)
+
+$(COMMONDIR)/glob.o\
+$(COMMONDIR)/misc.o\
+$(COMMONDIR)/tempnam.o :
+ @cd $(COMMONDIR); $(MAKE) -f common.mk SYSTEM=$(SYSTEM) `basename $@`
+
+changes :
+ @trap "" 1 2 3 15; \
+ sed \
+ -e "s'^SYSTEM=.*'SYSTEM=$(SYSTEM)'" \
+ -e "s'^VERSION=.*'VERSION=$(VERSION)'" \
+ -e "s'^GROUP=.*'GROUP=$(GROUP)'" \
+ -e "s'^OWNER=.*'OWNER=$(OWNER)'" \
+ -e "s'^MAN1DIR=.*'MAN1DIR=$(MAN1DIR)'" \
+ -e "s'^POSTBIN=.*'POSTBIN=$(POSTBIN)'" \
+ $(MAKEFILE) >XXX.mk; \
+ mv XXX.mk $(MAKEFILE)
+