diff options
author | rsc <devnull@localhost> | 2004-05-15 23:55:53 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-05-15 23:55:53 +0000 |
commit | 61f5c35c9465f0702739b41249a664d409f0482c (patch) | |
tree | 17546b7dcc76abd9ee74dc7543cc77121acfe39a /src/cmd/postscript/common | |
parent | 173302913ebce353eadcbb12d71c3759cbe79e34 (diff) | |
download | plan9port-61f5c35c9465f0702739b41249a664d409f0482c.tar.gz plan9port-61f5c35c9465f0702739b41249a664d409f0482c.tar.bz2 plan9port-61f5c35c9465f0702739b41249a664d409f0482c.zip |
more files
Diffstat (limited to 'src/cmd/postscript/common')
-rw-r--r-- | src/cmd/postscript/common/bbox.c | 257 | ||||
-rw-r--r-- | src/cmd/postscript/common/comments.h | 127 | ||||
-rw-r--r-- | src/cmd/postscript/common/common.c | 264 | ||||
-rw-r--r-- | src/cmd/postscript/common/common.h | 43 | ||||
-rw-r--r-- | src/cmd/postscript/common/ext.h | 40 | ||||
-rw-r--r-- | src/cmd/postscript/common/gen.h | 65 | ||||
-rw-r--r-- | src/cmd/postscript/common/getopt.c | 56 | ||||
-rw-r--r-- | src/cmd/postscript/common/glob.c | 29 | ||||
-rw-r--r-- | src/cmd/postscript/common/misc.c | 230 | ||||
-rw-r--r-- | src/cmd/postscript/common/mkfile | 23 | ||||
-rw-r--r-- | src/cmd/postscript/common/path.h | 32 | ||||
-rw-r--r-- | src/cmd/postscript/common/request.c | 119 | ||||
-rw-r--r-- | src/cmd/postscript/common/request.h | 22 | ||||
-rw-r--r-- | src/cmd/postscript/common/rune.c | 142 | ||||
-rw-r--r-- | src/cmd/postscript/common/rune.h | 19 | ||||
-rw-r--r-- | src/cmd/postscript/common/tempnam.c | 27 |
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 |