aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/postscript/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/postscript/common')
-rw-r--r--src/cmd/postscript/common/bbox.c257
-rw-r--r--src/cmd/postscript/common/comments.h127
-rw-r--r--src/cmd/postscript/common/common.c264
-rw-r--r--src/cmd/postscript/common/common.h43
-rw-r--r--src/cmd/postscript/common/ext.h40
-rw-r--r--src/cmd/postscript/common/gen.h65
-rw-r--r--src/cmd/postscript/common/getopt.c56
-rw-r--r--src/cmd/postscript/common/glob.c29
-rw-r--r--src/cmd/postscript/common/misc.c230
-rw-r--r--src/cmd/postscript/common/mkfile23
-rw-r--r--src/cmd/postscript/common/path.h32
-rw-r--r--src/cmd/postscript/common/request.c119
-rw-r--r--src/cmd/postscript/common/request.h22
-rw-r--r--src/cmd/postscript/common/rune.c142
-rw-r--r--src/cmd/postscript/common/rune.h19
-rw-r--r--src/cmd/postscript/common/tempnam.c27
16 files changed, 1495 insertions, 0 deletions
diff --git a/src/cmd/postscript/common/bbox.c b/src/cmd/postscript/common/bbox.c
new file mode 100644
index 00000000..7e1f14a5
--- /dev/null
+++ b/src/cmd/postscript/common/bbox.c
@@ -0,0 +1,257 @@
+/*
+ *
+ * Boundingbox code for PostScript translators. The boundingbox for each page
+ * is accumulated in bbox - the one for the whole document goes in docbbox. A
+ * call to writebbox() puts out an appropriate comment, updates docbbox, and
+ * resets bbox for the next page. The assumption made at the end of writebbox()
+ * is that we're really printing the current page only if output is now going
+ * to stdout - a valid assumption for all supplied translators. Needs the math
+ * library.
+ *
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <math.h>
+
+#include "comments.h" /* PostScript file structuring comments */
+#include "gen.h" /* a few general purpose definitions */
+#include "ext.h" /* external variable declarations */
+
+typedef struct bbox {
+ int set;
+ double llx, lly;
+ double urx, ury;
+} Bbox;
+
+Bbox bbox = {FALSE, 0.0, 0.0, 0.0, 0.0};
+Bbox docbbox = {FALSE, 0.0, 0.0, 0.0, 0.0};
+
+double ctm[6] = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
+double matrix1[6], matrix2[6];
+
+/*****************************************************************************/
+
+cover(x, y)
+
+ double x, y;
+
+{
+
+/*
+ *
+ * Adds point (x, y) to bbox. Coordinates are in user space - the transformation
+ * to default coordinates happens in writebbox().
+ *
+ */
+
+ if ( bbox.set == FALSE ) {
+ bbox.llx = bbox.urx = x;
+ bbox.lly = bbox.ury = y;
+ bbox.set = TRUE;
+ } else {
+ if ( x < bbox.llx )
+ bbox.llx = x;
+ if ( y < bbox.lly )
+ bbox.lly = y;
+ if ( x > bbox.urx )
+ bbox.urx = x;
+ if ( y > bbox.ury )
+ bbox.ury = y;
+ } /* End else */
+
+} /* End of cover */
+
+/*****************************************************************************/
+
+writebbox(fp, keyword, slop)
+
+ FILE *fp; /* the comment is written here */
+ char *keyword; /* the boundingbox comment string */
+ int slop; /* expand (or contract?) the box a bit */
+
+{
+
+ Bbox ubbox; /* user space bounding box */
+ double x, y;
+
+/*
+ *
+ * Transforms the numbers in the bbox[] using ctm[], adjusts the corners a bit
+ * (depending on slop) and then writes comment. If *keyword is BoundingBox use
+ * whatever's been saved in docbbox, otherwise assume the comment is just for
+ * the current page.
+ *
+ */
+
+ if ( strcmp(keyword, BOUNDINGBOX) == 0 )
+ bbox = docbbox;
+
+ if ( bbox.set == TRUE ) {
+ ubbox = bbox;
+ bbox.set = FALSE; /* so cover() works properly */
+ x = ctm[0] * ubbox.llx + ctm[2] * ubbox.lly + ctm[4];
+ y = ctm[1] * ubbox.llx + ctm[3] * ubbox.lly + ctm[5];
+ cover(x, y);
+ x = ctm[0] * ubbox.llx + ctm[2] * ubbox.ury + ctm[4];
+ y = ctm[1] * ubbox.llx + ctm[3] * ubbox.ury + ctm[5];
+ cover(x, y);
+ x = ctm[0] * ubbox.urx + ctm[2] * ubbox.ury + ctm[4];
+ y = ctm[1] * ubbox.urx + ctm[3] * ubbox.ury + ctm[5];
+ cover(x, y);
+ x = ctm[0] * ubbox.urx + ctm[2] * ubbox.lly + ctm[4];
+ y = ctm[1] * ubbox.urx + ctm[3] * ubbox.lly + ctm[5];
+ cover(x, y);
+ bbox.llx -= slop + 0.5;
+ bbox.lly -= slop + 0.5;
+ bbox.urx += slop + 0.5;
+ bbox.ury += slop + 0.5;
+ fprintf(fp, "%s %d %d %d %d\n", keyword, (int)bbox.llx, (int)bbox.lly,(int)bbox.urx, (int)bbox.ury);
+ bbox = ubbox;
+ } /* End if */
+
+ resetbbox((fp == stdout) ? TRUE : FALSE);
+
+} /* End of writebbox */
+
+/*****************************************************************************/
+
+resetbbox(output)
+
+ int output;
+
+{
+
+/*
+ *
+ * Adds bbox to docbbox and resets bbox for the next page. Only update docbbox
+ * if we really did output on the last page.
+ *
+ */
+
+ if ( docbbox.set == TRUE ) {
+ cover(docbbox.llx, docbbox.lly);
+ cover(docbbox.urx, docbbox.ury);
+ } /* End if */
+
+ if ( output == TRUE ) {
+ docbbox = bbox;
+ docbbox.set = TRUE;
+ } /* End if */
+
+ bbox.set = FALSE;
+
+} /* End of resetbbox */
+
+/*****************************************************************************/
+
+scale(sx, sy)
+
+ double sx, sy;
+
+{
+
+/*
+ *
+ * Scales the default matrix.
+ *
+ */
+
+ matrix1[0] = sx;
+ matrix1[1] = 0;
+ matrix1[2] = 0;
+ matrix1[3] = sy;
+ matrix1[4] = 0;
+ matrix1[5] = 0;
+
+ concat(matrix1);
+
+} /* End of scale */
+
+/*****************************************************************************/
+
+translate(tx, ty)
+
+ double tx, ty;
+
+{
+
+/*
+ *
+ * Translates the default matrix.
+ *
+ */
+
+ matrix1[0] = 1.0;
+ matrix1[1] = 0.0;
+ matrix1[2] = 0.0;
+ matrix1[3] = 1.0;
+ matrix1[4] = tx;
+ matrix1[5] = ty;
+
+ concat(matrix1);
+
+} /* End of translate */
+
+/*****************************************************************************/
+
+rotate(angle)
+
+ double angle;
+
+{
+
+/*
+ *
+ * Rotates by angle degrees.
+ *
+ */
+
+ angle *= 3.1416 / 180;
+
+ matrix1[0] = matrix1[3] = cos(angle);
+ matrix1[1] = sin(angle);
+ matrix1[2] = -matrix1[1];
+ matrix1[4] = 0.0;
+ matrix1[5] = 0.0;
+
+ concat(matrix1);
+
+} /* End of rotate */
+
+/*****************************************************************************/
+
+concat(m1)
+
+ double m1[];
+
+{
+
+ double m2[6];
+
+/*
+ *
+ * Replaces the ctm[] by the result of the matrix multiplication m1[] x ctm[].
+ *
+ */
+
+ m2[0] = ctm[0];
+ m2[1] = ctm[1];
+ m2[2] = ctm[2];
+ m2[3] = ctm[3];
+ m2[4] = ctm[4];
+ m2[5] = ctm[5];
+
+ ctm[0] = m1[0] * m2[0] + m1[1] * m2[2];
+ ctm[1] = m1[0] * m2[1] + m1[1] * m2[3];
+ ctm[2] = m1[2] * m2[0] + m1[3] * m2[2];
+ ctm[3] = m1[2] * m2[1] + m1[3] * m2[3];
+ ctm[4] = m1[4] * m2[0] + m1[5] * m2[2] + m2[4];
+ ctm[5] = m1[4] * m2[1] + m1[5] * m2[3] + m2[5];
+
+} /* End of concat */
+
+/*****************************************************************************/
+
diff --git a/src/cmd/postscript/common/comments.h b/src/cmd/postscript/common/comments.h
new file mode 100644
index 00000000..6b409cad
--- /dev/null
+++ b/src/cmd/postscript/common/comments.h
@@ -0,0 +1,127 @@
+/*
+ *
+ * Currently defined file structuring comments from Adobe - plus a few others.
+ * Ones that end with a colon expect arguments, while those ending with a newline
+ * stand on their own. Truly overkill on Adobe's part and mine for including them
+ * all!
+ *
+ * All PostScript files should begin with a header that starts with one of the
+ * following comments.
+ *
+ */
+
+#define NONCONFORMING "%!PS\n"
+#define MINCONFORMING "%!PS-Adobe-\n"
+#define OLDCONFORMING "%!PS-Adobe-1.0\n"
+
+#define CONFORMING "%!PS-Adobe-2.0\n"
+#define CONFORMINGEPS "%!PS-Adobe-2.0 EPS\n"
+#define CONFORMINGQUERY "%!PS-Adobe-2.0 Query\n"
+#define CONFORMINGEXITSERVER "%!PS-Adobe-2.0 ExitServer\n"
+
+/*
+ *
+ * Header comments - immediately follow the appropriate document classification
+ * comment.
+ *
+ */
+
+#define TITLE "%%Title:"
+#define CREATOR "%%Creator:"
+#define CREATIONDATE "%%CreationDate:"
+#define FOR "%%For:"
+#define ROUTING "%%Routing:"
+#define BOUNDINGBOX "%%BoundingBox:"
+#define PAGES "%%Pages:"
+#define REQUIREMENTS "%%Requirements:"
+
+#define DOCUMENTFONTS "%%DocumentFonts:"
+#define DOCUMENTNEEDEDFONTS "%%DocumentNeededFonts:"
+#define DOCUMENTSUPPLIEDFONTS "%%DocumentSuppliedFonts:"
+#define DOCUMENTNEEDEDPROCSETS "%%DocumentNeededProcSets:"
+#define DOCUMENTSUPPLIEDPROCSETS "%%DocumentSuppliedProcSets:"
+#define DOCUMENTNEEDEDFILES "%%DocumentNeededFiles:"
+#define DOCUMENTSUPPLIEDFILES "%%DocumentSuppliedFiles:"
+#define DOCUMENTPAPERSIZES "%%DocumentPaperSizes:"
+#define DOCUMENTPAPERFORMS "%%DocumentPaperForms:"
+#define DOCUMENTPAPERCOLORS "%%DocumentPaperColors:"
+#define DOCUMENTPAPERWEIGHTS "%%DocumentPaperWeights:"
+#define DOCUMENTPRINTERREQUIRED "%%DocumentPrinterREquired:"
+#define ENDCOMMENTS "%%EndComments\n"
+#define ENDPROLOG "%%EndProlog\n"
+
+/*
+ *
+ * Body comments - can appear anywhere in a document.
+ *
+ */
+
+#define BEGINSETUP "%%BeginSetup\n"
+#define ENDSETUP "%%EndSetup\n"
+#define BEGINDOCUMENT "%%BeginDocument:"
+#define ENDDOCUMENT "%%EndDocument\n"
+#define BEGINFILE "%%BeginFile:"
+#define ENDFILE "%%EndFile\n"
+#define BEGINPROCSET "%%BeginProcSet:"
+#define ENDPROCSET "%%EndProcSet\n"
+#define BEGINBINARY "%%BeginBinary:"
+#define ENDBINARY "%%EndBinary\n"
+#define BEGINPAPERSIZE "%%BeginePaperSize:"
+#define ENDPAPERSIZE "%%EndPaperSize\n"
+#define BEGINFEATURE "%%BeginFeature:"
+#define ENDFEATURE "%%EndFeature\n"
+#define BEGINEXITSERVER "%%BeginExitServer:"
+#define ENDEXITSERVER "%%EndExitServer\n"
+#define TRAILER "%%Trailer\n"
+
+/*
+ *
+ * Page level comments - usually will occur once per page.
+ *
+ */
+
+#define PAGE "%%Page:"
+#define PAGEFONTS "%%PageFonts:"
+#define PAGEFILES "%%PageFiles:"
+#define PAGEBOUNDINGBOX "%%PageBoundingBox:"
+#define BEGINPAGESETUP "%%BeginPageSetup\n"
+#define BEGINOBJECT "%%BeginObject:"
+#define ENDOBJECT "%%EndObject\n"
+
+/*
+ *
+ * Resource requirements - again can appear anywhere in a document.
+ *
+ */
+
+#define INCLUDEFONT "%%IncludeFont:"
+#define INCLUDEPROCSET "%%IncludeProcSet:"
+#define INCLUDEFILE "%%IncludeFile:"
+#define EXECUTEFILE "%%ExecuteFile:"
+#define CHANGEFONT "%%ChangeFont:"
+#define PAPERFORM "%%PaparForm:"
+#define PAPERCOLOR "%%PaperColor:"
+#define PAPERWEIGHT "%%PaperWeight:"
+#define PAPERSIZE "%%PaperSize:"
+#define FEATURE "%%Feature:"
+#define ENDOFFILE "%%EOF\n"
+
+#define CONTINUECOMMENT "%%+"
+#define ATEND "(atend)"
+
+/*
+ *
+ * Some non-standard document comments. Global definitions are occasionally used
+ * in dpost and are marked by BEGINGLOBAL and ENDGLOBAL. The resulting document
+ * violates page independence, but can easily be converted to a conforming file
+ * using a utililty program.
+ *
+ */
+
+#define BEGINSCRIPT "%%BeginScript\n"
+#define BEGINGLOBAL "%%BeginGlobal\n"
+#define ENDGLOBAL "%%EndGlobal\n"
+#define ENDPAGE "%%EndPage:"
+#define FORMSPERPAGE "%%FormsPerPage:"
+#define VERSION "%%Version:"
+
diff --git a/src/cmd/postscript/common/common.c b/src/cmd/postscript/common/common.c
new file mode 100644
index 00000000..945ef6a0
--- /dev/null
+++ b/src/cmd/postscript/common/common.c
@@ -0,0 +1,264 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ctype.h>
+#include "common.h"
+#include "comments.h"
+#include "path.h"
+
+struct strtab charcode[FONTSIZE] = {
+ {4, "\\000"}, {4, "\\001"}, {4, "\\002"}, {4, "\\003"},
+ {4, "\\004"}, {4, "\\005"}, {4, "\\006"}, {4, "\\007"},
+ {4, "\\010"}, {4, "\\011"}, {4, "\\012"}, {4, "\\013"},
+ {4, "\\014"}, {4, "\\015"}, {4, "\\016"}, {4, "\\017"},
+ {4, "\\020"}, {4, "\\021"}, {4, "\\022"}, {4, "\\023"},
+ {4, "\\024"}, {4, "\\025"}, {4, "\\026"}, {4, "\\027"},
+ {4, "\\030"}, {4, "\\031"}, {4, "\\032"}, {4, "\\033"},
+ {4, "\\034"}, {4, "\\035"}, {4, "\\036"}, {4, "\\037"},
+ {1, " "}, {1, "!"}, {1, "\""}, {1, "#"},
+ {1, "$"}, {1, "%"}, {1, "&"}, {1, "'"},
+ {2, "\\("}, {2, "\\)"}, {1, "*"}, {1, "+"},
+ {1, ","}, {1, "-"}, {1, "."}, {1, "/"},
+ {1, "0"}, {1, "1"}, {1, "2"}, {1, "3"},
+ {1, "4"}, {1, "5"}, {1, "6"}, {1, "7"},
+ {1, "8"}, {1, "9"}, {1, ":"}, {1, ";"},
+ {1, "<"}, {1, "="}, {1, ">"}, {1, "?"},
+ {1, "@"}, {1, "A"}, {1, "B"}, {1, "C"},
+ {1, "D"}, {1, "E"}, {1, "F"}, {1, "G"},
+ {1, "H"}, {1, "I"}, {1, "J"}, {1, "K"},
+ {1, "L"}, {1, "M"}, {1, "N"}, {1, "O"},
+ {1, "P"}, {1, "Q"}, {1, "R"}, {1, "S"},
+ {1, "T"}, {1, "U"}, {1, "V"}, {1, "W"},
+ {1, "X"}, {1, "Y"}, {1, "Z"}, {1, "["},
+ {2, "\\\\"}, {1, "]"}, {1, "^"}, {1, "_"},
+ {1, "`"}, {1, "a"}, {1, "b"}, {1, "c"},
+ {1, "d"}, {1, "e"}, {1, "f"}, {1, "g"},
+ {1, "h"}, {1, "i"}, {1, "j"}, {1, "k"},
+ {1, "l"}, {1, "m"}, {1, "n"}, {1, "o"},
+ {1, "p"}, {1, "q"}, {1, "r"}, {1, "s"},
+ {1, "t"}, {1, "u"}, {1, "v"}, {1, "w"},
+ {1, "x"}, {1, "y"}, {1, "z"}, {1, "{"},
+ {1, "|"}, {1, "}"}, {1, "~"}, {4, "\\177"},
+ {4, "\\200"}, {4, "\\201"}, {4, "\\202"}, {4, "\\203"},
+ {4, "\\204"}, {4, "\\205"}, {4, "\\206"}, {4, "\\207"},
+ {4, "\\210"}, {4, "\\211"}, {4, "\\212"}, {4, "\\213"},
+ {4, "\\214"}, {4, "\\215"}, {4, "\\216"}, {4, "\\217"},
+ {4, "\\220"}, {4, "\\221"}, {4, "\\222"}, {4, "\\223"},
+ {4, "\\224"}, {4, "\\225"}, {4, "\\226"}, {4, "\\227"},
+ {4, "\\230"}, {4, "\\231"}, {4, "\\232"}, {4, "\\233"},
+ {4, "\\234"}, {4, "\\235"}, {4, "\\236"}, {4, "\\237"},
+ {4, "\\240"}, {4, "\\241"}, {4, "\\242"}, {4, "\\243"},
+ {4, "\\244"}, {4, "\\245"}, {4, "\\246"}, {4, "\\247"},
+ {4, "\\250"}, {4, "\\251"}, {4, "\\252"}, {4, "\\253"},
+ {4, "\\254"}, {4, "\\255"}, {4, "\\256"}, {4, "\\257"},
+ {4, "\\260"}, {4, "\\261"}, {4, "\\262"}, {4, "\\263"},
+ {4, "\\264"}, {4, "\\265"}, {4, "\\266"}, {4, "\\267"},
+ {4, "\\270"}, {4, "\\271"}, {4, "\\272"}, {4, "\\273"},
+ {4, "\\274"}, {4, "\\275"}, {4, "\\276"}, {4, "\\277"},
+ {4, "\\300"}, {4, "\\301"}, {4, "\\302"}, {4, "\\303"},
+ {4, "\\304"}, {4, "\\305"}, {4, "\\306"}, {4, "\\307"},
+ {4, "\\310"}, {4, "\\311"}, {4, "\\312"}, {4, "\\313"},
+ {4, "\\314"}, {4, "\\315"}, {4, "\\316"}, {4, "\\317"},
+ {4, "\\320"}, {4, "\\321"}, {4, "\\322"}, {4, "\\323"},
+ {4, "\\324"}, {4, "\\325"}, {4, "\\326"}, {4, "\\327"},
+ {4, "\\330"}, {4, "\\331"}, {4, "\\332"}, {4, "\\333"},
+ {4, "\\334"}, {4, "\\335"}, {4, "\\336"}, {4, "\\337"},
+ {4, "\\340"}, {4, "\\341"}, {4, "\\342"}, {4, "\\343"},
+ {4, "\\344"}, {4, "\\345"}, {4, "\\346"}, {4, "\\347"},
+ {4, "\\350"}, {4, "\\351"}, {4, "\\352"}, {4, "\\353"},
+ {4, "\\354"}, {4, "\\355"}, {4, "\\356"}, {4, "\\357"},
+ {4, "\\360"}, {4, "\\361"}, {4, "\\362"}, {4, "\\363"},
+ {4, "\\364"}, {4, "\\365"}, {4, "\\366"}, {4, "\\367"},
+ {4, "\\370"}, {4, "\\371"}, {4, "\\372"}, {4, "\\373"},
+ {4, "\\374"}, {4, "\\375"}, {4, "\\376"}, {4, "\\377"}
+};
+
+static BOOLEAN in_string = FALSE;
+int char_no = 0;
+int line_no = 0;
+int page_no = 0; /* page number in a document */
+int pages_printed = 0;
+static int pplistmaxsize=0;
+
+static unsigned char *pplist=0; /* bitmap list for storing pages to print */
+
+void
+pagelist(char *list) {
+ char c;
+ int n, m;
+ int state, start;
+
+ if (list == 0) return;
+ state = 1;
+ start = 0;
+ while ((c=*list) != '\0') {
+ n = 0;
+ while (isdigit(c)) {
+ n = n * 10 + c - '0';
+ c = *++list;
+ }
+ switch (state) {
+ case 1:
+ start = n;
+ case 2:
+ if (n/8+1 > pplistmaxsize) {
+ pplistmaxsize = n/8+1;
+ pplist = galloc(pplist, n/8+1, "page list");
+ }
+ for (m=start; m<=n; m++)
+ pplist[m/8] |= 1<<(m%8);
+ break;
+ }
+ switch (c) {
+ case '-':
+ state = 2;
+ list++;
+ break;
+ case ',':
+ state = 1;
+ list++;
+ break;
+ case '\0':
+ break;
+ }
+ }
+}
+
+BOOLEAN
+pageon(void) {
+ extern BOOLEAN debug;
+ static BOOLEAN privdebug = FALSE;
+
+ if (pplist == 0 && page_no != 0) {
+ if (privdebug && !debug) {
+ privdebug = FALSE;
+ debug = TRUE;
+ }
+ return(TRUE); /* no page list, print all pages */
+ }
+ if (page_no/8 < pplistmaxsize && (pplist[page_no/8] & 1<<(page_no%8))) {
+ if (privdebug && !debug) {
+ privdebug = FALSE;
+ debug = TRUE;
+ }
+ return(TRUE);
+ } else {
+ if (!privdebug && debug) {
+ privdebug = TRUE;
+ debug = FALSE;
+ }
+ return(FALSE);
+ }
+}
+
+static int stringhpos, stringvpos;
+
+void
+startstring(void) {
+ if (!in_string) {
+ stringhpos = hpos;
+ stringvpos = vpos;
+ if (pageon()) Bprint(Bstdout, "(");
+ in_string = 1;
+ }
+}
+
+void
+endstring(void) {
+ if (in_string) {
+ if (pageon()) Bprint(Bstdout, ") %d %d w\n", stringhpos, stringvpos);
+ in_string = 0;
+ }
+}
+
+BOOLEAN
+isinstring(void) {
+ return(in_string);
+}
+
+void
+startpage(void) {
+ ++char_no;
+ ++line_no;
+ ++page_no;
+ if (pageon()) {
+ ++pages_printed;
+ Bprint(Bstdout, "%s %d %d\n", PAGE, page_no, pages_printed);
+ Bprint(Bstdout, "/saveobj save def\n");
+ Bprint(Bstdout, "mark\n");
+ Bprint(Bstdout, "%d pagesetup\n", pages_printed);
+ }
+}
+
+void
+endpage(void) {
+ endstring();
+ curpostfontid = -1;
+ line_no = 0;
+ char_no = 0;
+ if (pageon()) {
+ Bprint(Bstdout, "cleartomark\n");
+ Bprint(Bstdout, "showpage\n");
+ Bprint(Bstdout, "saveobj restore\n");
+ Bprint(Bstdout, "%s %d %d\n", ENDPAGE, page_no, pages_printed);
+ }
+}
+
+/* This was taken from postprint */
+
+int
+cat(char *filename) {
+ Biobuf *bfile;
+ Biobuf *Bfile;
+ int n;
+ static char buf[Bsize];
+
+ if ((bfile = Bopen(unsharp(filename), OREAD)) == 0) {
+ return(1);
+ }
+ Bfile = bfile;
+ while ((n=Bread(Bfile, buf, Bsize)) > 0) {
+ if (Bwrite(Bstdout, buf, n) != n)
+ break;
+ }
+ Bterm(Bfile);
+ if (n != 0) {
+ return(1);
+ }
+ return(0);
+}
+extern int debug;
+void *
+galloc(void *ptr, int size, char *perstr) {
+ void *x;
+
+ if ((x=realloc(ptr, size)) == 0) {
+ perror(perstr);
+ exits("malloc");
+ }
+ return(x);
+}
+
+static char *errorstrings[] = {
+ {""}, /* NONE */
+ {"WARNING"},
+ {"FATAL"}
+};
+
+char *programname;
+char *inputfilename = "<stdin>";
+int inputlineno;
+
+void
+error(int errtype, char *fmt, ...) {
+ va_list arg;
+
+ Bflush(Bstdout);
+ Bflush(Bstderr);
+ fprint(2, "%s: %s:%d :%s: ", programname, inputfilename, inputlineno, errorstrings[errtype]);
+ va_start(arg, fmt);
+ vfprint(2, fmt, arg);
+ va_end(arg);
+ if (errtype == FATAL)
+ exits("fatal error");
+}
diff --git a/src/cmd/postscript/common/common.h b/src/cmd/postscript/common/common.h
new file mode 100644
index 00000000..62eba08e
--- /dev/null
+++ b/src/cmd/postscript/common/common.h
@@ -0,0 +1,43 @@
+#define NONE 0
+#define WARNING 1
+#define FATAL 2
+
+#define RUNEGETGROUP(a) ((a>>8)&0xff)
+#define RUNEGETCHAR(a) (a&0xff)
+
+typedef int BOOLEAN;
+
+#define TRUE 1
+#define FALSE 0
+
+#define NUMOFONTS 0x100
+#define FONTSIZE 0x100
+
+extern char *programname;
+extern char *inputfilename;
+extern int inputlineno;
+
+extern int page_no;
+extern int pages_printed;
+extern int curpostfontid;
+extern int hpos, vpos;
+
+extern Biobuf *Bstdout, *Bstderr;
+
+struct strtab {
+ int size;
+ char *str;
+ int used;
+};
+
+extern struct strtab charcode[];
+BOOLEAN pageon(void);
+void startstring(void);
+void endstring(void);
+BOOLEAN isinstring(void);
+void startpage(void);
+void endpage(void);
+int cat(char *);
+int Bgetfield(Biobuf *, int, void *, int);
+void *galloc(void *, int, char *);
+void pagelist(char *);
diff --git a/src/cmd/postscript/common/ext.h b/src/cmd/postscript/common/ext.h
new file mode 100644
index 00000000..e260cee1
--- /dev/null
+++ b/src/cmd/postscript/common/ext.h
@@ -0,0 +1,40 @@
+/*
+ *
+ * External varibles - most are in glob.c.
+ *
+ */
+
+extern char **argv; /* global so everyone can use them */
+extern int argc;
+
+extern int x_stat; /* program exit status */
+extern int debug; /* debug flag */
+extern int ignore; /* what we do with FATAL errors */
+
+extern long lineno; /* line number */
+extern long position; /* byte position */
+extern char *prog_name; /* and program name - for errors */
+extern char *temp_file; /* temporary file - for some programs */
+extern char *fontencoding; /* text font encoding scheme */
+
+extern int dobbox; /* enable BoundingBox stuff if TRUE */
+extern double pageheight; /* only for BoundingBox calculations! */
+extern double pagewidth;
+
+extern int reading; /* input */
+extern int writing; /* and output encoding */
+
+extern char *optarg; /* for getopt() */
+extern int optind;
+
+extern void interrupt();
+//extern char *tempnam(char*,char*);
+/*
+ * extern char *malloc();
+ * extern char *calloc();
+ * extern char *strtok();
+ * extern long ftell();
+ * extern double atof();
+ * extern double sqrt();
+ * extern double atan2();
+ */
diff --git a/src/cmd/postscript/common/gen.h b/src/cmd/postscript/common/gen.h
new file mode 100644
index 00000000..ba8cbbac
--- /dev/null
+++ b/src/cmd/postscript/common/gen.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * A few definitions that shouldn't have to change. Used by most programs in
+ * this package.
+ *
+ */
+
+#define PROGRAMVERSION "3.3.2"
+
+#define NON_FATAL 0
+#define FATAL 1
+#define USER_FATAL 2
+
+#define OFF 0
+#define ON 1
+
+#define FALSE 0
+#define TRUE 1
+
+#define BYTE 8
+#define BMASK 0377
+
+#define POINTS 72.3
+
+#ifndef PI
+#define PI 3.141592654
+#endif
+
+#define ONEBYTE 0
+#define UTFENCODING 1
+
+#define READING ONEBYTE
+#define WRITING ONEBYTE
+
+/*
+ *
+ * DOROUND controls whether some translators include file ROUNDPAGE (path.h)
+ * after the prologue. Used to round page dimensions obtained from the clippath
+ * to know paper sizes. Enabled by setting DOROUND to TRUE (or 1).
+ *
+ */
+
+#define DOROUND TRUE
+
+/*
+ *
+ * Default resolution and the height and width of a page (in case we need to get
+ * to upper left corner) - only used in BoundingBox calculations!!
+ *
+ */
+
+#define DEFAULT_RES 72
+#define PAGEHEIGHT 11.0 * DEFAULT_RES
+#define PAGEWIDTH 8.5 * DEFAULT_RES
+
+/*
+ *
+ * Simple macros.
+ *
+ */
+
+#define ABS(A) ((A) >= 0 ? (A) : -(A))
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+#define MAX(A, B) ((A) > (B) ? (A) : (B))
+
diff --git a/src/cmd/postscript/common/getopt.c b/src/cmd/postscript/common/getopt.c
new file mode 100644
index 00000000..cf6619f7
--- /dev/null
+++ b/src/cmd/postscript/common/getopt.c
@@ -0,0 +1,56 @@
+#ifndef _POSIX_SOURCE
+#include <u.h>
+#include <libc.h>
+#endif
+#include <stdio.h>
+#define ERR(str, chr) if(opterr){fprintf(stderr, "%s%s%c\n", argv[0], str, chr);}
+int opterr = 1;
+int optind = 1;
+int optopt;
+char *optarg;
+char *strchr();
+
+int
+getopt (argc, argv, opts)
+char **argv, *opts;
+{
+ static int sp = 1;
+ register c;
+ register char *cp;
+
+ if (sp == 1)
+ if (optind >= argc ||
+ argv[optind][0] != '-' || argv[optind][1] == '\0')
+ return EOF;
+ else if (strcmp(argv[optind], "--") == NULL) {
+ optind++;
+ return EOF;
+ }
+ optopt = c = argv[optind][sp];
+ if (c == ':' || (cp=strchr(opts, c)) == NULL) {
+ ERR (": illegal option -- ", c);
+ if (argv[optind][++sp] == '\0') {
+ optind++;
+ sp = 1;
+ }
+ return '?';
+ }
+ if (*++cp == ':') {
+ if (argv[optind][sp+1] != '\0')
+ optarg = &argv[optind++][sp+1];
+ else if (++optind >= argc) {
+ ERR (": option requires an argument -- ", c);
+ sp = 1;
+ return '?';
+ } else
+ optarg = argv[optind++];
+ sp = 1;
+ } else {
+ if (argv[optind][++sp] == '\0') {
+ sp = 1;
+ optind++;
+ }
+ optarg = NULL;
+ }
+ return c;
+}
diff --git a/src/cmd/postscript/common/glob.c b/src/cmd/postscript/common/glob.c
new file mode 100644
index 00000000..2826f4e5
--- /dev/null
+++ b/src/cmd/postscript/common/glob.c
@@ -0,0 +1,29 @@
+/*
+ *
+ * Global varibles - for PostScript translators.
+ *
+ */
+
+#include <stdio.h>
+#include "gen.h"
+
+char **argv; /* global so everyone can use them */
+int argc;
+
+int x_stat = 0; /* program exit status */
+int debug = OFF; /* debug flag */
+int ignore = OFF; /* what we do with FATAL errors */
+
+long lineno = 0; /* line number */
+long position = 0; /* byte position */
+char *prog_name = ""; /* and program name - for errors */
+char *temp_file = NULL; /* temporary file - for some programs */
+char *fontencoding = NULL; /* text font encoding scheme */
+
+int dobbox = FALSE; /* enable BoundingBox stuff if TRUE */
+double pageheight = PAGEHEIGHT; /* only for BoundingBox calculations! */
+double pagewidth = PAGEWIDTH;
+
+int reading = UTFENCODING; /* input */
+int writing = WRITING; /* and output encoding */
+
diff --git a/src/cmd/postscript/common/misc.c b/src/cmd/postscript/common/misc.c
new file mode 100644
index 00000000..25bd37aa
--- /dev/null
+++ b/src/cmd/postscript/common/misc.c
@@ -0,0 +1,230 @@
+/*
+ *
+ * General purpose routines.
+ *
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "gen.h"
+#include "ext.h"
+#include "path.h"
+
+int nolist = 0; /* number of specified ranges */
+int olist[50]; /* processing range pairs */
+
+/*****************************************************************************/
+
+out_list(str)
+
+ char *str;
+
+{
+
+ int start, stop;
+
+/*
+ *
+ * Grab page ranges from str, save them in olist[], and update the nolist
+ * count. Range syntax matches nroff/troff syntax.
+ *
+ */
+
+ while ( *str && nolist < sizeof(olist) - 2 ) {
+ start = stop = str_convert(&str, 0);
+
+ if ( *str == '-' && *str++ )
+ stop = str_convert(&str, 9999);
+
+ if ( start > stop )
+ error(FATAL, "illegal range %d-%d", start, stop);
+
+ olist[nolist++] = start;
+ olist[nolist++] = stop;
+
+ if ( *str != '\0' ) str++;
+ } /* End while */
+
+ olist[nolist] = 0;
+
+} /* End of out_list */
+
+/*****************************************************************************/
+
+in_olist(num)
+
+ int num;
+
+{
+
+ int i;
+
+/*
+ *
+ * Return ON if num is in the current page range list. Print everything if
+ * there's no list.
+ *
+ */
+ if ( nolist == 0 )
+ return(ON);
+
+ for ( i = 0; i < nolist; i += 2 )
+ if ( num >= olist[i] && num <= olist[i+1] )
+ return(ON);
+
+ return(OFF);
+
+} /* End of in_olist */
+
+/*****************************************************************************/
+
+setencoding(name)
+
+ char *name;
+
+{
+
+ char path[150];
+
+/*
+ *
+ * Include the font encoding file selected by name. It's a full pathname if
+ * it begins with /, otherwise append suffix ".enc" and look for the file in
+ * ENCODINGDIR. Missing files are silently ignored.
+ *
+ */
+
+ if ( name == NULL )
+ name = "Default";
+
+ if ( *name == '/' )
+ strcpy(path, name);
+ else sprintf(path, "%s/%s.enc", ENCODINGDIR, name);
+
+ if ( cat(path) == TRUE )
+ writing = strncmp(name, "UTF", 3) == 0;
+
+} /* End of setencoding */
+
+/*****************************************************************************/
+
+cat(file)
+
+ char *file;
+
+{
+
+ int fd_in;
+ int fd_out;
+ char buf[512];
+ int count;
+
+/*
+ *
+ * Copy *file to stdout. Return FALSE is there was a problem.
+ *
+ */
+
+ fflush(stdout);
+
+ if ( (fd_in = open(file, O_RDONLY)) == -1 )
+ return(FALSE);
+
+ fd_out = fileno(stdout);
+ while ( (count = read(fd_in, buf, sizeof(buf))) > 0 )
+ write(fd_out, buf, count);
+
+ close(fd_in);
+
+ return(TRUE);
+
+} /* End of cat */
+
+/*****************************************************************************/
+
+str_convert(str, err)
+
+ char **str;
+ int err;
+
+{
+
+ int i;
+
+/*
+ *
+ * Grab the next integer from **str and return its value or err if *str
+ * isn't an integer. *str is modified after each digit is read.
+ *
+ */
+
+ if ( ! isdigit(**str) )
+ return(err);
+
+ for ( i = 0; isdigit(**str); *str += 1 )
+ i = 10 * i + **str - '0';
+
+ return(i);
+
+} /* End of str_convert */
+
+/*****************************************************************************/
+
+error(kind, mesg, a1, a2, a3)
+
+ int kind;
+ char *mesg;
+ unsigned a1, a2, a3;
+
+{
+
+/*
+ *
+ * Print an error message and quit if kind is FATAL.
+ *
+ */
+
+ if ( mesg != NULL && *mesg != '\0' ) {
+ fprintf(stderr, "%s: ", prog_name);
+ fprintf(stderr, mesg, a1, a2, a3);
+ if ( lineno > 0 )
+ fprintf(stderr, " (line %d)", lineno);
+ if ( position > 0 )
+ fprintf(stderr, " (near byte %d)", position);
+ putc('\n', stderr);
+ } /* End if */
+
+ if ( kind == FATAL && ignore == OFF ) {
+ if ( temp_file != NULL )
+ unlink(temp_file);
+ exit(x_stat | 01);
+ } /* End if */
+
+} /* End of error */
+
+/*****************************************************************************/
+
+void interrupt(sig)
+
+ int sig;
+
+{
+
+/*
+ *
+ * Signal handler for translators.
+ *
+ */
+
+ if ( temp_file != NULL )
+ unlink(temp_file);
+
+ exit(1);
+
+} /* End of interrupt */
+
+/*****************************************************************************/
+
diff --git a/src/cmd/postscript/common/mkfile b/src/cmd/postscript/common/mkfile
new file mode 100644
index 00000000..09d43035
--- /dev/null
+++ b/src/cmd/postscript/common/mkfile
@@ -0,0 +1,23 @@
+<$PLAN9/src/mkhdr
+
+<../config
+
+LIB=com.a
+OFILES=bbox.$O\
+ glob.$O\
+ misc.$O\
+ request.$O\
+ rune.$O\
+ tempnam.$O\
+ getopt.$O\
+
+HFILES=comments.h\
+ gen.h\
+ ext.h\
+ request.h\
+ path.h\
+ rune.h\
+
+<$PLAN9/src/mklib
+
+CFLAGS=-c -D$SYSTEM -D_POSIX_SOURCE
diff --git a/src/cmd/postscript/common/path.h b/src/cmd/postscript/common/path.h
new file mode 100644
index 00000000..a3692139
--- /dev/null
+++ b/src/cmd/postscript/common/path.h
@@ -0,0 +1,32 @@
+/*
+ *
+ * pathname definitions for important files and directories.
+ *
+ */
+
+#define DPOST "#9/sys/lib/postscript/prologues/dpost.ps"
+#define POSTBGI "#9/sys/lib/postscript/prologues/postbgi.ps"
+#define POSTDAISY "#9/sys/lib/postscript/prologues/postdaisy.ps"
+#define POSTDMD "#9/sys/lib/postscript/prologues/postdmd.ps"
+#define POSTMD "#9/sys/lib/postscript/prologues/postmd.ps"
+#define POSTPLOT "#9/sys/lib/postscript/prologues/postplot.ps"
+#define POSTPRINT "#9/sys/lib/postscript/prologues/postprint.ps"
+#define POSTNPRINT "#9/sys/lib/postscript/prologues/postnprint.ps"
+#define POSTTEK "#9/sys/lib/postscript/prologues/posttek.ps"
+#define POSTGIF "#9/sys/lib/postscript/prologues/postgif.ps"
+
+#define BASELINE "#9/sys/lib/postscript/prologues/baseline.ps"
+#define COLOR "#9/sys/lib/postscript/prologues/color.ps"
+#define DRAW "#9/sys/lib/postscript/prologues/draw.ps"
+#define FORMFILE "#9/sys/lib/postscript/prologues/forms.ps"
+#define SHADEFILE "#9/sys/lib/postscript/prologues/shade.ps"
+#define KERNING "#9/sys/lib/postscript/prologues/kerning.ps"
+#define REQUESTFILE "#9/sys/lib/postscript/prologues/ps.requests"
+#define ROUNDPAGE "#9/sys/lib/postscript/prologues/roundpage.ps"
+
+#define ENCODINGDIR "#9/sys/lib/postscript/prologues"
+#define HOSTDIR "#9/sys/lib/postscript/font"
+#define FONTDIR "#9/sys/lib/troff/font"
+#define POSTLIBDIR "#9/sys/lib/postscript/prologues"
+#define TEMPDIR "/tmp"
+
diff --git a/src/cmd/postscript/common/request.c b/src/cmd/postscript/common/request.c
new file mode 100644
index 00000000..d8d7dd13
--- /dev/null
+++ b/src/cmd/postscript/common/request.c
@@ -0,0 +1,119 @@
+/*
+ *
+ * Things used to handle special requests (eg. manual feed) globally or on a per
+ * page basis. Requests are passed through to the translator using the -R option.
+ * The argument to -R can be "request", "request:page", or "request:page:file".
+ * If page is omitted (as in the first form) or set to 0 request will be applied
+ * to the global environment. In all other cases it applies only to the selected
+ * page. If a file is given, page must be supplied, and the lookup is in that file
+ * rather than *requestfile.
+ *
+ */
+
+#include <stdio.h>
+
+#include "gen.h" /* general purpose definitions */
+#include "request.h" /* a few special definitions */
+#include "path.h" /* for the default request file */
+
+Request request[MAXREQUEST]; /* next page or global request */
+int nextreq = 0; /* goes in request[nextreq] */
+char *requestfile = REQUESTFILE; /* default lookup file */
+
+/*****************************************************************************/
+
+saverequest(want)
+
+ char *want; /* grab code for this stuff */
+
+{
+
+ char *page; /* and save it for this page */
+ char *strtok();
+
+/*
+ *
+ * Save the request until we get to appropriate page - don't even bother with
+ * the lookup right now. Format of *want string is "request", "request:page", or
+ * "request:page:file", and we assume we can change the string here as needed.
+ * If page is omitted or given as 0 the request will be done globally. If *want
+ * includes a file, request and page must also be given, and in that case *file
+ * will be used for the lookup.
+ *
+ */
+
+ if ( nextreq < MAXREQUEST ) {
+ request[nextreq].want = strtok(want, ": ");
+ if ( (page = strtok(NULL, ": ")) == NULL )
+ request[nextreq].page = 0;
+ else request[nextreq].page = atoi(page);
+ if ( (request[nextreq].file = strtok(NULL, ": ")) == NULL )
+ request[nextreq].file = requestfile;
+ nextreq++;
+ } else error(NON_FATAL, "too many requests - ignoring %s", want);
+
+} /* End of saverequest */
+
+/*****************************************************************************/
+
+writerequest(page, fp_out)
+
+ int page; /* write everything for this page */
+ FILE *fp_out; /* to this file */
+
+{
+
+ int i; /* loop index */
+
+/*
+ *
+ * Writes out all the requests that have been saved for page. Page 0 refers to
+ * the global environment and is done during initial setup.
+ *
+ */
+
+ for ( i = 0; i < nextreq; i++ )
+ if ( request[i].page == page )
+ dumprequest(request[i].want, request[i].file, fp_out);
+
+} /* End of writerequest */
+
+/*****************************************************************************/
+
+dumprequest(want, file, fp_out)
+
+ char *want; /* look for this string */
+ char *file; /* in this file */
+ FILE *fp_out; /* and write the value out here */
+
+{
+
+ char buf[100]; /* line buffer for reading *file */
+ FILE *fp_in;
+
+/*
+ *
+ * Looks for *want in the request file and if it's found the associated value
+ * is copied to the output file. Keywords (ie. the *want strings) begin an @ in
+ * the first column of file, while the values (ie. the stuff that's copied to
+ * the output file) starts on the next line and extends to the next keyword or
+ * to the end of file.
+ *
+ */
+
+ if ( (fp_in = fopen(file, "r")) != NULL ) {
+ while ( fgets(buf, sizeof(buf), fp_in) != NULL )
+ if ( buf[0] == '@' && strncmp(want, &buf[1], strlen(want)) == 0 )
+ while ( fgets(buf, sizeof(buf), fp_in) != NULL )
+ if ( buf[0] == '#' || buf[0] == '%' )
+ continue;
+ else if ( buf[0] != '@' )
+ fprintf(fp_out, "%s", buf);
+ else break;
+ fclose(fp_in);
+ } /* End if */
+
+} /* End of dumprequest */
+
+/*****************************************************************************/
+
diff --git a/src/cmd/postscript/common/request.h b/src/cmd/postscript/common/request.h
new file mode 100644
index 00000000..25d94d01
--- /dev/null
+++ b/src/cmd/postscript/common/request.h
@@ -0,0 +1,22 @@
+/*
+ *
+ * Things used to handle special PostScript requests (like manual feed) globally
+ * or on a per page basis. All the translators I've supplied accept the -R option
+ * that can be used to insert special PostScript code before the global setup is
+ * done, or at the start of named pages. The argument to the -R option is a string
+ * that can be "request", "request:page", or "request:page:file". If page isn't
+ * given (as in the first form) or if it's 0 in the last two, the request applies
+ * to the global environment, otherwise request holds only for the named page.
+ * If a file name is given a page number must be supplied, and in that case the
+ * request will be looked up in that file.
+ *
+ */
+
+#define MAXREQUEST 30
+
+typedef struct {
+ char *want;
+ int page;
+ char *file;
+} Request;
+
diff --git a/src/cmd/postscript/common/rune.c b/src/cmd/postscript/common/rune.c
new file mode 100644
index 00000000..01ee6ba8
--- /dev/null
+++ b/src/cmd/postscript/common/rune.c
@@ -0,0 +1,142 @@
+#include "rune.h"
+
+enum
+{
+ Bit1 = 7,
+ Bitx = 6,
+ Bit2 = 5,
+ Bit3 = 4,
+ Bit4 = 3,
+
+ T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */
+ Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */
+ T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */
+ T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */
+ T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */
+
+ Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */
+ Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */
+ Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */
+
+ Maskx = (1<<Bitx)-1, /* 0011 1111 */
+ Testx = Maskx ^ 0xFF, /* 1100 0000 */
+
+ Bad = Runeerror,
+};
+
+int
+chartorune(Rune *rune, char *str)
+{
+ int c, c1, c2;
+ long l;
+
+ /*
+ * one character sequence
+ * 00000-0007F => T1
+ */
+ c = *(unsigned char*)str;
+ if(c < Tx) {
+ *rune = c;
+ return 1;
+ }
+
+ /*
+ * two character sequence
+ * 0080-07FF => T2 Tx
+ */
+ c1 = *(unsigned char*)(str+1) ^ Tx;
+ if(c1 & Testx)
+ goto bad;
+ if(c < T3) {
+ if(c < T2)
+ goto bad;
+ l = ((c << Bitx) | c1) & Rune2;
+ if(l <= Rune1)
+ goto bad;
+ *rune = l;
+ return 2;
+ }
+
+ /*
+ * three character sequence
+ * 0800-FFFF => T3 Tx Tx
+ */
+ c2 = *(unsigned char*)(str+2) ^ Tx;
+ if(c2 & Testx)
+ goto bad;
+ if(c < T4) {
+ l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
+ if(l <= Rune2)
+ goto bad;
+ *rune = l;
+ return 3;
+ }
+
+ /*
+ * bad decoding
+ */
+bad:
+ *rune = Bad;
+ return 1;
+}
+
+int
+runetochar(char *str, Rune *rune)
+{
+ long c;
+
+ /*
+ * one character sequence
+ * 00000-0007F => 00-7F
+ */
+ c = *rune;
+ if(c <= Rune1) {
+ str[0] = c;
+ return 1;
+ }
+
+ /*
+ * two character sequence
+ * 0080-07FF => T2 Tx
+ */
+ if(c <= Rune2) {
+ str[0] = T2 | (c >> 1*Bitx);
+ str[1] = Tx | (c & Maskx);
+ return 2;
+ }
+
+ /*
+ * three character sequence
+ * 0800-FFFF => T3 Tx Tx
+ */
+ str[0] = T3 | (c >> 2*Bitx);
+ str[1] = Tx | ((c >> 1*Bitx) & Maskx);
+ str[2] = Tx | (c & Maskx);
+ return 3;
+}
+
+int
+runelen(long c)
+{
+ Rune rune;
+ char str[10];
+
+ rune = c;
+ return runetochar(str, &rune);
+}
+
+int
+fullrune(char *str, int n)
+{
+ int c;
+
+ if(n > 0) {
+ c = *(unsigned char*)str;
+ if(c < Tx)
+ return 1;
+ if(n > 1)
+ if(c < T3 || n > 2)
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/cmd/postscript/common/rune.h b/src/cmd/postscript/common/rune.h
new file mode 100644
index 00000000..2df5f767
--- /dev/null
+++ b/src/cmd/postscript/common/rune.h
@@ -0,0 +1,19 @@
+/*
+ *
+ * Rune declarations - for supporting UTF encoding.
+ *
+ */
+
+#define RUNELIB 1
+
+#ifdef RUNELIB
+typedef unsigned short Rune;
+
+enum
+{
+ UTFmax = 3, /* maximum bytes per rune */
+ Runesync = 0x80, /* cannot represent part of a utf sequence (<) */
+ Runeself = 0x80, /* rune and utf sequences are the same (<) */
+ Runeerror = 0x80, /* decoding error in utf */
+};
+#endif
diff --git a/src/cmd/postscript/common/tempnam.c b/src/cmd/postscript/common/tempnam.c
new file mode 100644
index 00000000..529025ed
--- /dev/null
+++ b/src/cmd/postscript/common/tempnam.c
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <errno.h>
+
+#if defined(V9) || defined(BSD4_2) || defined(plan9)
+char *tempnam(char *dir, char *pfx) {
+ int pid;
+ unsigned int len;
+ char *tnm, *malloc();
+ static int seq = 0;
+
+ pid = getpid();
+ len = strlen(dir) + strlen(pfx) + 10;
+ if ((tnm = malloc(len)) != NULL) {
+ sprintf(tnm, "%s", dir);
+ if (access(tnm, 7) == -1)
+ return(NULL);
+ do {
+ sprintf(tnm, "%s/%s%d%d", dir, pfx, pid, seq++);
+ errno = 0;
+ if (access(tnm, 7) == -1)
+ if (errno == ENOENT)
+ return(tnm);
+ } while (1);
+ }
+ return(tnm);
+}
+#endif