diff options
Diffstat (limited to 'gnu/groff/grops')
| -rw-r--r-- | gnu/groff/grops/Makefile | 12 | ||||
| -rw-r--r-- | gnu/groff/grops/Makefile.dep | 6 | ||||
| -rw-r--r-- | gnu/groff/grops/TODO | 25 | ||||
| -rw-r--r-- | gnu/groff/grops/grops.1 | 797 | ||||
| -rw-r--r-- | gnu/groff/grops/ps.cc | 1507 | ||||
| -rw-r--r-- | gnu/groff/grops/ps.h | 122 | ||||
| -rw-r--r-- | gnu/groff/grops/psfig.diff | 106 | ||||
| -rw-r--r-- | gnu/groff/grops/psrm.cc | 1091 |
8 files changed, 0 insertions, 3666 deletions
diff --git a/gnu/groff/grops/Makefile b/gnu/groff/grops/Makefile deleted file mode 100644 index 4d56054e31a1..000000000000 --- a/gnu/groff/grops/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Makefile for grops - -PROG= grops -SRCS= ps.cc psrm.cc -CFLAGS+= -I$(.CURDIR)/../include -LDADD+= $(LIBDRIVER) $(LIBGROFF) -lm -DPADD+= $(LIBDRIVER) $(LIBGROFF) $(LIBMATH) - -.include <bsd.prog.mk> -.include "../../../usr.bin/Makefile.inc" -.include "../Makefile.cfg" -.include "Makefile.dep" diff --git a/gnu/groff/grops/Makefile.dep b/gnu/groff/grops/Makefile.dep deleted file mode 100644 index 2320a9ecd129..000000000000 --- a/gnu/groff/grops/Makefile.dep +++ /dev/null @@ -1,6 +0,0 @@ -ps.o : ps.cc ../include/driver.h ../include/errarg.h ../include/error.h \ - ../include/font.h ../include/printer.h ../include/lib.h \ - ../include/stringclass.h ../include/cset.h ps.h -psrm.o : psrm.cc ../include/driver.h ../include/errarg.h ../include/error.h \ - ../include/font.h ../include/printer.h ../include/lib.h \ - ../include/stringclass.h ../include/cset.h ps.h diff --git a/gnu/groff/grops/TODO b/gnu/groff/grops/TODO deleted file mode 100644 index 4d1e5fd618a9..000000000000 --- a/gnu/groff/grops/TODO +++ /dev/null @@ -1,25 +0,0 @@ -Read PFB files directly. - -Generate %%DocumentMedia comment. - -For efficiency it might be better to have the printer interface have -support for the t and u commands. - -Angles in arc command: don't generate more digits after the decimal -point than are necessary. - -Possibly generate BoundingBox comment. - -Per font composite character mechanism (sufficient for fractions). - -Consider whether we ought to do rounding of graphical objects other -than lines. What's the point? - -Error messages should refer to output page number. - -Search for downloadable fonts using their PostScript names if not -found in download file. - -Separate path for searching for downloadable font files. - -Clip to the BoundingBox when importing documents. diff --git a/gnu/groff/grops/grops.1 b/gnu/groff/grops/grops.1 deleted file mode 100644 index 2a584d6d681c..000000000000 --- a/gnu/groff/grops/grops.1 +++ /dev/null @@ -1,797 +0,0 @@ -.\" -*- nroff -*- -.\" Like TP, but if specified indent is more than half -.\" the current line-length - indent, use the default indent. -.de Tp -.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP -.el .TP "\\$1" -.. -.TH GROPS 1 "5 April 1993" "Groff Version 1.08" -.SH NAME -grops \- PostScript driver for groff -.SH SYNOPSIS -.B grops -[ -.B \-glv -] [ -.BI \-b n -] [ -.BI \-c n -] [ -.BI \-w n -] [ -.BI \-F dir -] [ -.IR files \|.\|.\|. -] -.SH DESCRIPTION -.B grops -translates the output of GNU -.B troff -to PostScript. -Normally -.B grops -should be invoked by using the groff command -with a -.B \-Tps -option. -.if 'ps'ps' (Actually, this is the default for groff.) -If no files are given, -.B grops -will read the standard input. -A filename of -.B \- -will also cause -.B grops -to read the standard input. -PostScript output is written to the standard output. -When -.B grops -is run by -.B groff -options can be passed to -.B grops -using the -.B groff -.B \-P -option. -.SH OPTIONS -.TP -.BI \-b n -Workaround broken spoolers and previewers. -Normally -.B grops -produces output that conforms -the Document Structuring Conventions version 3.0. -Unfortunately some spoolers and previewers can't handle such output. -The value of -.I n -controls what -.B grops -does to its output acceptable to such programs. -A value of 0 will cause grops not to employ any workarounds. -Add 1 if no -.B %%BeginDocumentSetup -and -.B %%EndDocumentSetup -comments should be generated; -this is needed for early versions of TranScript that get confused by -anything between the -.B %%EndProlog -comment and the first -.B %%Page -comment. -Add 2 if lines in included files beginning with -.B %! -should be stripped out; this is needed for Sun's pageview previewer. -Add 4 if -.BR %%Page , -.BR %%Trailer -and -.B %%EndProlog -comments should be -stripped out of included files; this is needed for spoolers that -don't understand the -.B %%BeginDocument -and -.B %%EndDocument -comments. -Add 8 if the first line of the PostScript output should be -.B %!PS-Adobe-2.0 -rather than -.BR %!PS-Adobe-3.0 ; -this is needed when using Sun's Newsprint with a printer that requires -page reversal. -The default value can be specified by a -.RS -.IP -.BI broken\ n -.LP -command in the DESC file. -Otherwise the default value is 0. -.RE -.TP -.BI \-c n -Print -.I n -copies of each page. -.TP -.BI \-g -Guess the page length. -This generates PostScript code that guesses the page length. -The guess will be correct only if the imageable area is vertically -centered on the page. -This option allows you to generate documents that can be printed -both on letter (8.5\(mu11) paper and on A4 paper without change. -.TP -.BI \-l -Print the document in landscape format. -.TP -.BI \-F dir -Search the directory -.IB dir /dev name -for font and device description files; -.I name -is the name of the device, usually -.BR ps . -.TP -.BI \-w n -Lines should be drawn using a thickness of -.I n -thousandths of an em. -.TP -.B \-v -Print the version number. -.SH USAGE -There are styles called -.BR R , -.BR I , -.BR B , -and -.B BI -mounted at font positions 1 to 4. -The fonts are grouped into families -.BR A , -.BR BM , -.BR C , -.BR H , -.BR HN , -.BR N , -.B P -and -.B T -having members in each of these styles: -.de FT -.if '\\*(.T'ps' .ft \\$1 -.. -.TP -.B AR -.FT AR -AvantGarde-Book -.FT -.TP -.B AI -.FT AI -AvantGarde-BookOblique -.FT -.TP -.B AB -.FT AB -AvantGarde-Demi -.FT -.TP -.B ABI -.FT ABI -AvantGarde-DemiOblique -.FT -.TP -.B BMR -.FT BMR -Bookman-Light -.FT -.TP -.B BMI -.FT BMI -Bookman-LightItalic -.FT -.TP -.B BMB -.FT BMB -Bookman-Demi -.FT -.TP -.B BMBI -.FT BMBI -Bookman-DemiItalic -.FT -.TP -.B CR -.FT CR -Courier -.FT -.TP -.B CI -.FT CI -Courier-Oblique -.FT -.TP -.B CB -.FT CB -Courier-Bold -.FT -.TP -.B CBI -.FT CBI -Courier-BoldOblique -.FT -.TP -.B HR -.FT HR -Helvetica -.FT -.TP -.B HI -.FT HI -Helvetica-Oblique -.FT -.TP -.B HB -.FT HB -Helvetica-Bold -.FT -.TP -.B HBI -.FT HBI -Helvetica-BoldOblique -.FT -.TP -.B HNR -.FT HNR -Helvetica-Narrow -.FT -.TP -.B HNI -.FT HNI -Helvetica-Narrow-Oblique -.FT -.TP -.B HNB -.FT HNB -Helvetica-Narrow-Bold -.FT -.TP -.B HNBI -.FT HNBI -Helvetica-Narrow-BoldOblique -.FT -.TP -.B NR -.FT NR -NewCenturySchlbk-Roman -.FT -.TP -.B NI -.FT NI -NewCenturySchlbk-Italic -.FT -.TP -.B NB -.FT NB -NewCenturySchlbk-Bold -.FT -.TP -.B NBI -.FT NBI -NewCenturySchlbk-BoldItalic -.FT -.TP -.B PR -.FT PR -Palatino-Roman -.FT -.TP -.B PI -.FT PI -Palatino-Italic -.FT -.TP -.B PB -.FT PB -Palatino-Bold -.FT -.TP -.B PBI -.FT PBI -Palatino-BoldItalic -.FT -.TP -.B TR -.FT TR -Times-Roman -.FT -.TP -.B TI -.FT TI -Times-Italic -.FT -.TP -.B TB -.FT TB -Times-Bold -.FT -.TP -.B TBI -.FT TBI -Times-BoldItalic -.FT -.LP -There is also the following font which is not a member of a family: -.TP -.B ZCMI -.FT ZCMI -ZapfChancery-MediumItalic -.FT -.LP -There are also some special fonts called -.B SS -and -.BR S . -Zapf Dingbats is avilable as -.BR ZD -and a reversed version of ZapfDingbats (with symbols pointing in the opposite -direction) is available as -.BR ZDR ; -most characters in these fonts are unnamed and must be accessed using -.BR \eN . -.LP -.B grops -understands various X commands produced using the -.B \eX -escape sequence; -.B grops -will only interpret commands that begin with a -.B ps: -tag. -.TP -.BI \eX'ps:\ exec\ code ' -This executes the arbitrary PostScript commands in -.IR code . -The PostScript currentpoint will be set to the position of the -.B \eX -command before executing -.IR code . -The origin will be at the top left corner of the page, -and y coordinates will increase down the page. -A procedure -.B u -will be defined that converts groff units -to the coordinate system in effect. -For example, -.RS -.IP -.B -\&.nr x 1i -.br -.B -\eX'ps: exec \enx u 0 rlineto stroke' -.br -.RE -.IP -will draw a horizontal line one inch long. -.I code -may make changes to the graphics state, -but any changes will persist only to the -end of the page. -Any definitions will also persist only until the end of the page. -If you use the -.B \eY -escape sequence with an argument that names a macro, -.I code -can extend over multiple lines. -For example, -.RS -.IP -.nf -.ft B -\&.nr x 1i -\&.de y -\&ps: exec -\&\enx u 0 rlineto -\&stroke -\&.. -\&\eYy -.fi -.ft R -.LP -is another way to draw a horizontal line one inch long. -.RE -.TP -.BI \eX'ps:\ file\ name ' -This is the same as the -.B exec -command except that the PostScript code is read from file -.IR name . -.TP -.BI \eX'ps:\ def\ code ' -Place a PostScript definition contained in -.I code -in the prologue. -There should be at most one definition per -.B \eX -command. -Long definitions can be split over several -.B \eX -commands; -all the -.I code -arguments are simply joined together separated by newlines. -The definitions are placed in a dictionary which is automatically -pushed on the dictionary stack when an -.B exec -command is executed. -If you use the -.B \eY -escape sequence with an argument that names a macro, -.I code -can extend over multiple lines. -.TP -.BI \eX'ps:\ mdef\ n\ code ' -Like -.BR def , -except that -.I code -may contain up to -.I n -definitions. -.B grops -needs to know how many definitions -.I code -contains -so that it can create an apppropriately sized PostScript dictionary -to contain them. -.TP -.BI \eX'ps:\ import\ file\ llx\ lly\ urx\ ury\ width\ \fR[\fP\ height\ \fR]\fP ' -Import a PostScript graphic from -.IR file . -The arguments -.IR llx , -.IR lly , -.IR urx , -and -.I ury -give the bounding box of the graphic in the default PostScript -coordinate system; they should all be integers; -.I llx -and -.I lly -are the x and y coordinates of the lower left -corner of the graphic; -.I urx -and -.I ury -are the x and y coordinates of the upper right corner of the graphic; -.I width -and -.I height -are integers that give the desired width and height in groff -units of the graphic. -The graphic will be scaled so that it has this width and height -and translated so that the lower left corner of the graphic is -located at the position associated with -.B \eX -command. -If the height argument is omitted it will be scaled uniformly in the -x and y directions so that it has the specified width. -Note that the contents of the -.B \eX -command are not interpreted by -.BR troff ; -so vertical space for the graphic is not automatically added, -and the -.I width -and -.I height -arguments are not allowed to have attached scaling indicators. -If the PostScript file complies with the Adobe Document Structuring -Conventions and contains a -.B %%BoundingBox -comment, then the bounding box can be automatically -extracted from within groff by using the -.B sy -request to run the -.B psbb -command. -.RS -.LP -The -.B \-mps -macros (which are automatically loaded when -.B grops -is run by the groff command) include a -.B PSPIC -macro which allows a picture to be easily imported. -This has the format -.IP -.BI .PSPIC\ file\ \fR[ width\ \fR[ height \fR]] -.LP -.I file -is the name of the file containing the illustration; -.I width -and -.I height -give the desired width and height of the graphic. -The -.I width -and -.I height -arguments may have scaling indicators attached; -the default scaling indicator is -.BR i . -This macro will scale the graphic uniformly -in the x and y directions so that it is no more than -.I width -wide -and -.I height -high. -.RE -.TP -.B \eX'ps:\ invis' -.br -.ns -.TP -.B \eX'ps:\ endinvis' -No output will be generated for text and drawing commands -that are bracketed with these -.B \eX -commands. -These commands are intended for use when output from -.B troff -will be previewed before being processed with -.BR grops ; -if the previewer is unable to display certain characters -or other constructs, then other substitute characters or constructs -can be used for previewing by bracketing them with these -.B \eX -commands. -.RS -.LP -For example, -.B gxditview -is not able to display a proper -.B \e(em -character because the standard X11 fonts do not provide it; -this problem can be overcome by executing the following -request -.IP -.ft B -.nf -\&.char \e(em \eX'ps: invis'\e -\eZ'\ev'-.25m'\eh'.05m'\eD'l .9m 0'\eh'.05m''\e -\eX'ps: endinvis'\e(em -.ft -.fi -.LP -In this case, -.B gxditview -will be unable to display the -.B \e(em -character and will draw the line, -whereas -.B grops -will print the -.B \e(em -character -and ignore the line. -.RE -.LP -The input to -.B grops -must be in the format output by -.BR troff (1). -This is described in -.BR groff_out (1). -In addition the device and font description files for the device used -must meet certain requirements. -The device and font description files supplied for -.B ps -device meet all these requirements. -.BR afmtodit (1) -can be used to create font files from AFM files. -The resolution must be an integer multiple of 72 times the -.BR sizescale . -The -.B ps -device uses a resolution of 72000 and a sizescale of 1000. -The device description file should contain a command -.IP -.BI paperlength\ n -.LP -which says that output should be generated which is suitable for -printing on a page whose length is -.I n -machine units. -Each font description file must contain a command -.IP -.BI internalname\ psname -.LP -which says that the PostScript name of the font is -.IR psname . -It may also contain a command -.IP -.BI encoding\ enc_file -.LP -which says that -the PostScript font should be reencoded using the encoding described in -.IR enc_file ; -this file should consist of a sequence of lines of the form: -.IP -.I -pschar code -.LP -where -.I pschar -is the PostScript name of the character, -and -.I code -is its position in the encoding expressed as a decimal integer. -The code for each character given in the font file must correspond -to the code for the character in encoding file, or to the code in the default -encoding for the font if the PostScript font is not to be reencoded. -This code can be used with the -.B \eN -escape sequence in -.B troff -to select the character, -even if the character does not have a groff name. -Every character in the font file must exist in the PostScript font, and -the widths given in the font file must match the widths used -in the PostScript font. -.B grops -will assume that a character with a groff name of -.B space -is blank (makes no marks on the page); -it can make use of such a character to generate more efficient and -compact PostScript output. -.LP -.B grops -can automatically include the downloadable fonts necessary -to print the document. -Any downloadable fonts which should, when required, be included by -.B grops -must be listed in the file -.BR /usr/share/groff_font/devps/download ; -this should consist of lines of the form -.IP -.I -font filename -.LP -where -.I font -is the PostScript name of the font, -and -.I filename -is the name of the file containing the font; -lines beginning with -.B # -and blank lines are ignored; -fields may be separated by tabs or spaces; -.I filename -will be searched for using the same mechanism that is used -for groff font metric files. -The -.B download -file itself will also be searched for using this mechanism. -.LP -If the file containing a downloadable font or imported document -conforms to the Adobe Document Structuring Conventions, -then -.B grops -will interpret any comments in the files sufficiently to ensure that its -own output is conforming. -It will also supply any needed font resources that are listed in the -.B download -file -as well as any needed file resources. -It is also able to handle inter-resource dependencies. -For example, suppose that you have a downloadable font called Garamond, -and also a downloadable font called Garamond-Outline -which depends on Garamond -(typically it would be defined to copy Garamond's font dictionary, -and change the PaintType), -then it is necessary for Garamond to be appear before Garamond-Outline -in the PostScript document. -.B grops -will handle this automatically -provided that the downloadable font file for Garamond-Outline -indicates its dependence on Garamond by means of -the Document Structuring Conventions, -for example by beginning with the following lines -.IP -.B -%!PS-Adobe-3.0 Resource-Font -.br -.B -%%DocumentNeededResources: font Garamond -.br -.B -%%EndComments -.br -.B -%%IncludeResource: font Garamond -.LP -In this case both Garamond and Garamond-Outline would need to be listed -in the -.B download -file. -A downloadable font should not include its own name in a -.B %%DocumentSuppliedResources -comment. -.LP -.B grops -will not interpret -.B %%DocumentFonts -comments. -The -.BR %%DocumentNeededResources , -.BR %%DocumentSuppliedResources , -.BR %%IncludeResource , -.BR %%BeginResource -and -.BR %%EndResource -comments -(or possibly the old -.BR %%DocumentNeededFonts , -.BR %%DocumentSuppliedFonts , -.BR %%IncludeFont , -.BR %%BeginFont -and -.BR %%EndFont -comments) -should be used. -.SH FILES -.Tp \w'\fB/usr/share/groff_font/devps/download'u+2n -.B /usr/share/groff_font/devps/DESC -Device desciption file. -.TP -.BI /usr/share/groff_font/devps/ F -Font description file for font -.IR F . -.TP -.B /usr/share/groff_font/devps/download -List of downloadable fonts. -.TP -.B /usr/share/groff_font/devps/text.enc -Encoding used for text fonts. -.TP -.B /usr/share/tmac/tmac.ps -Macros for use with -.BR grops ; -automatically loaded by -.BR troffrc -.TP -.B /usr/share/tmac/tmac.pspic -Definition of -.B PSPIC -macro, -automatically loaded by -.BR tmac.ps . -.TP -.B /usr/share/tmac/tmac.psold -Macros to disable use of characters not present in older -PostScript printers; automatically loaded by -.BR tmac.ps . -.TP -.B /usr/share/tmac/tmac.psnew -Macros to undo the effect of -.BR tmac.psold . -.TP -.BI /tmp/grops XXXXXX -Temporary file. -.SH "SEE ALSO" -.BR afmtodit (1), -.BR groff (1), -.BR troff (1), -.BR psbb (1), -.BR groff_out (5), -.BR groff_font (5), -.BR groff_char (7) diff --git a/gnu/groff/grops/ps.cc b/gnu/groff/grops/ps.cc deleted file mode 100644 index 1dd5d8c77f75..000000000000 --- a/gnu/groff/grops/ps.cc +++ /dev/null @@ -1,1507 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.com) - -This file is part of groff. - -groff is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later -version. - -groff is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License along -with groff; see the file COPYING. If not, write to the Free Software -Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include "driver.h" -#include "stringclass.h" -#include "cset.h" - -#include "ps.h" - -static int landscape_flag = 0; -static int ncopies = 1; -static int linewidth = -1; -// Non-zero means generate PostScript code that guesses the paper -// length using the imageable area. -static int guess_flag = 0; - -// Non-zero if -b was specified on the command line. -static int bflag = 0; -unsigned broken_flags = 0; - -#define DEFAULT_LINEWIDTH 40 /* in ems/1000 */ -#define FILL_MAX 1000 - -const char *const dict_name = "grops"; -const char *const defs_dict_name = "DEFS"; -const int DEFS_DICT_SPARE = 50; - -double degrees(double r) -{ - return r*180.0/M_PI; -} - -double radians(double d) -{ - return d*M_PI/180.0; -} - -inline double transform_fill(int fill) -{ - return 1 - fill/double(FILL_MAX); -} - -ps_output::ps_output(FILE *f, int n) -: fp(f), max_line_length(n), col(0), need_space(0), fixed_point(0) -{ -} - -ps_output &ps_output::set_file(FILE *f) -{ - fp = f; - col = 0; - return *this; -} - -ps_output &ps_output::copy_file(FILE *infp) -{ - int c; - while ((c = getc(infp)) != EOF) - putc(c, fp); - return *this; -} - -ps_output &ps_output::end_line() -{ - if (col != 0) { - putc('\n', fp); - col = 0; - need_space = 0; - } - return *this; -} - -ps_output &ps_output::special(const char *s) -{ - if (s == 0 || *s == '\0') - return *this; - if (col != 0) { - putc('\n', fp); - col = 0; - } - fputs(s, fp); - if (strchr(s, '\0')[-1] != '\n') - putc('\n', fp); - need_space = 0; - return *this; -} - -ps_output &ps_output::simple_comment(const char *s) -{ - if (col != 0) - putc('\n', fp); - putc('%', fp); - putc('%', fp); - fputs(s, fp); - putc('\n', fp); - col = 0; - need_space = 0; - return *this; -} - -ps_output &ps_output::begin_comment(const char *s) -{ - if (col != 0) - putc('\n', fp); - putc('%', fp); - putc('%', fp); - fputs(s, fp); - col = 2 + strlen(s); - return *this; -} - -ps_output &ps_output::end_comment() -{ - if (col != 0) { - putc('\n', fp); - col = 0; - } - need_space = 0; - return *this; -} - -ps_output &ps_output::comment_arg(const char *s) -{ - int len = strlen(s); - if (col + len + 1 > max_line_length) { - putc('\n', fp); - fputs("%%+", fp); - col = 3; - } - putc(' ', fp); - fputs(s, fp); - col += len + 1; - return *this; -} - -ps_output &ps_output::set_fixed_point(int n) -{ - assert(n >= 0 && n <= 10); - fixed_point = n; - return *this; -} - -ps_output &ps_output::put_delimiter(char c) -{ - if (col + 1 > max_line_length) { - putc('\n', fp); - col = 0; - } - putc(c, fp); - col++; - need_space = 0; - return *this; -} - -ps_output &ps_output::put_string(const char *s, int n) -{ - int len = 0; - for (int i = 0; i < n; i++) { - char c = s[i]; - if (isascii(c) && isprint(c)) { - if (c == '(' || c == ')' || c == '\\') - len += 2; - else - len += 1; - } - else - len += 4; - } - if (len > n*2) { - if (col + n*2 + 2 > max_line_length && n*2 + 2 <= max_line_length) { - putc('\n', fp); - col = 0; - } - if (col + 1 > max_line_length) { - putc('\n', fp); - col = 0; - } - putc('<', fp); - col++; - for (i = 0; i < n; i++) { - if (col + 2 > max_line_length) { - putc('\n', fp); - col = 0; - } - fprintf(fp, "%02x", s[i] & 0377); - col += 2; - } - putc('>', fp); - col++; - } - else { - if (col + len + 2 > max_line_length && len + 2 <= max_line_length) { - putc('\n', fp); - col = 0; - } - if (col + 2 > max_line_length) { - putc('\n', fp); - col = 0; - } - putc('(', fp); - col++; - for (i = 0; i < n; i++) { - char c = s[i]; - if (isascii(c) && isprint(c)) { - if (c == '(' || c == ')' || c == '\\') - len = 2; - else - len = 1; - } - else - len = 4; - if (col + len + 1 > max_line_length) { - putc('\\', fp); - putc('\n', fp); - col = 0; - } - switch (len) { - case 1: - putc(c, fp); - break; - case 2: - putc('\\', fp); - putc(c, fp); - break; - case 4: - fprintf(fp, "\\%03o", c & 0377); - break; - default: - assert(0); - } - col += len; - } - putc(')', fp); - col++; - } - need_space = 0; - return *this; -} - -ps_output &ps_output::put_number(int n) -{ - char buf[1 + INT_DIGITS + 1]; - sprintf(buf, "%d", n); - int len = strlen(buf); - if (col > 0 && col + len + need_space > max_line_length) { - putc('\n', fp); - col = 0; - need_space = 0; - } - if (need_space) { - putc(' ', fp); - col++; - } - fputs(buf, fp); - col += len; - need_space = 1; - return *this; -} - -ps_output &ps_output::put_fix_number(int i) -{ - const char *p = iftoa(i, fixed_point); - int len = strlen(p); - if (col > 0 && col + len + need_space > max_line_length) { - putc('\n', fp); - col = 0; - need_space = 0; - } - if (need_space) { - putc(' ', fp); - col++; - } - fputs(p, fp); - col += len; - need_space = 1; - return *this; -} - -ps_output &ps_output::put_float(double d) -{ - char buf[128]; - sprintf(buf, "%.4f", d); - int len = strlen(buf); - if (col > 0 && col + len + need_space > max_line_length) { - putc('\n', fp); - col = 0; - need_space = 0; - } - if (need_space) { - putc(' ', fp); - col++; - } - fputs(buf, fp); - col += len; - need_space = 1; - return *this; -} - -ps_output &ps_output::put_symbol(const char *s) -{ - int len = strlen(s); - if (col > 0 && col + len + need_space > max_line_length) { - putc('\n', fp); - col = 0; - need_space = 0; - } - if (need_space) { - putc(' ', fp); - col++; - } - fputs(s, fp); - col += len; - need_space = 1; - return *this; -} - -ps_output &ps_output::put_literal_symbol(const char *s) -{ - int len = strlen(s); - if (col > 0 && col + len + 1 > max_line_length) { - putc('\n', fp); - col = 0; - } - putc('/', fp); - fputs(s, fp); - col += len + 1; - need_space = 1; - return *this; -} - -class ps_font : public font { - ps_font(const char *); -public: - int encoding_index; - char *encoding; - char *reencoded_name; - ~ps_font(); - void handle_unknown_font_command(const char *command, const char *arg, - const char *filename, int lineno); - static ps_font *load_ps_font(const char *); -}; - -ps_font *ps_font::load_ps_font(const char *s) -{ - ps_font *f = new ps_font(s); - if (!f->load()) { - delete f; - return 0; - } - return f; -} - -ps_font::ps_font(const char *nm) -: font(nm), encoding(0), reencoded_name(0), encoding_index(-1) -{ -} - -ps_font::~ps_font() -{ - a_delete encoding; - a_delete reencoded_name; -} - -void ps_font::handle_unknown_font_command(const char *command, const char *arg, - const char *filename, int lineno) -{ - if (strcmp(command, "encoding") == 0) { - if (arg == 0) - error_with_file_and_line(filename, lineno, - "`encoding' command requires an argument"); - else - encoding = strsave(arg); - } -} - -static void handle_unknown_desc_command(const char *command, const char *arg, - const char *filename, int lineno) -{ - if (strcmp(command, "broken") == 0) { - if (arg == 0) - error_with_file_and_line(filename, lineno, - "`broken' command requires an argument"); - else if (!bflag) - broken_flags = atoi(arg); - } -} - -struct style { - font *f; - int point_size; - int height; - int slant; - style(); - style(font *, int, int, int); - int operator==(const style &) const; - int operator!=(const style &) const; -}; - -style::style() : f(0) -{ -} - -style::style(font *p, int sz, int h, int sl) -: f(p), point_size(sz), height(h), slant(sl) -{ -} - -int style::operator==(const style &s) const -{ - return (f == s.f && point_size == s.point_size - && height == s.height && slant == s.slant); -} - -int style::operator!=(const style &s) const -{ - return !(*this == s); -} - -class ps_printer : public printer { - FILE *tempfp; - ps_output out; - int res; - int space_char_index; - int pages_output; - int paper_length; - int equalise_spaces; - enum { SBUF_SIZE = 256 }; - char sbuf[SBUF_SIZE]; - int sbuf_len; - int sbuf_start_hpos; - int sbuf_vpos; - int sbuf_end_hpos; - int sbuf_space_width; - int sbuf_space_count; - int sbuf_space_diff_count; - int sbuf_space_code; - int sbuf_kern; - style sbuf_style; - style output_style; - int output_hpos; - int output_vpos; - int output_draw_point_size; - int line_thickness; - int output_line_thickness; - int fill; - unsigned char output_space_code; - enum { MAX_DEFINED_STYLES = 50 }; - style defined_styles[MAX_DEFINED_STYLES]; - int ndefined_styles; - int next_encoding_index; - string defs; - int ndefs; - resource_manager rm; - int invis_count; - - void flush_sbuf(); - void set_style(const style &); - void set_space_code(unsigned char c); - int set_encoding_index(ps_font *); - void do_exec(char *, const environment *); - void do_import(char *, const environment *); - void do_def(char *, const environment *); - void do_mdef(char *, const environment *); - void do_file(char *, const environment *); - void do_invis(char *, const environment *); - void do_endinvis(char *, const environment *); - void set_line_thickness(const environment *); - void fill_path(); - void encode_fonts(); - void define_encoding(const char *, int); - void reencode_font(ps_font *); -public: - ps_printer(); - ~ps_printer(); - void set_char(int i, font *f, const environment *env, int w); - void draw(int code, int *p, int np, const environment *env); - void begin_page(int); - void end_page(int); - void special(char *arg, const environment *env); - font *make_font(const char *); - void end_of_line(); -}; - -ps_printer::ps_printer() -: pages_output(0), - sbuf_len(0), - output_hpos(-1), - output_vpos(-1), - out(0, 79), - ndefined_styles(0), - next_encoding_index(0), - line_thickness(-1), - fill(FILL_MAX + 1), - ndefs(0), - invis_count(0) -{ - tempfp = xtmpfile(); - out.set_file(tempfp); - if (linewidth < 0) - linewidth = DEFAULT_LINEWIDTH; - if (font::hor != 1) - fatal("horizontal resolution must be 1"); - if (font::vert != 1) - fatal("vertical resolution must be 1"); - if (font::res % (font::sizescale*72) != 0) - fatal("res must be a multiple of 72*sizescale"); - int r = font::res; - int point = 0; - while (r % 10 == 0) { - r /= 10; - point++; - } - res = r; - out.set_fixed_point(point); - space_char_index = font::name_to_index("space"); - paper_length = font::paperlength; - if (paper_length == 0) - paper_length = 11*font::res; - equalise_spaces = font::res >= 72000; -} - -int ps_printer::set_encoding_index(ps_font *f) -{ - if (f->encoding_index >= 0) - return f->encoding_index; - for (font_pointer_list *p = font_list; p; p = p->next) - if (p->p != f) { - char *encoding = ((ps_font *)p->p)->encoding; - int encoding_index = ((ps_font *)p->p)->encoding_index; - if (encoding != 0 && encoding_index >= 0 - && strcmp(f->encoding, encoding) == 0) { - return f->encoding_index = encoding_index; - } - } - return f->encoding_index = next_encoding_index++; -} - -void ps_printer::set_char(int i, font *f, const environment *env, int w) -{ - if (i == space_char_index || invis_count > 0) - return; - unsigned char code = f->get_code(i); - style sty(f, env->size, env->height, env->slant); - if (sty.slant != 0) { - if (sty.slant > 80 || sty.slant < -80) { - error("silly slant `%1' degrees", sty.slant); - sty.slant = 0; - } - } - if (sbuf_len > 0) { - if (sbuf_len < SBUF_SIZE - && sty == sbuf_style - && sbuf_vpos == env->vpos) { - if (sbuf_end_hpos == env->hpos) { - sbuf[sbuf_len++] = code; - sbuf_end_hpos += w + sbuf_kern; - return; - } - if (sbuf_len == 1 && sbuf_kern == 0) { - sbuf_kern = env->hpos - sbuf_end_hpos; - sbuf_end_hpos = env->hpos + sbuf_kern + w; - sbuf[sbuf_len++] = code; - return; - } - /* If sbuf_end_hpos - sbuf_kern == env->hpos, we are better off - starting a new string. */ - if (sbuf_len < SBUF_SIZE - 1 && env->hpos >= sbuf_end_hpos - && (sbuf_kern == 0 || sbuf_end_hpos - sbuf_kern != env->hpos)) { - if (sbuf_space_code < 0) { - if (f->contains(space_char_index)) { - sbuf_space_code = f->get_code(space_char_index); - sbuf_space_width = env->hpos - sbuf_end_hpos; - sbuf_end_hpos = env->hpos + w + sbuf_kern; - sbuf[sbuf_len++] = sbuf_space_code; - sbuf[sbuf_len++] = code; - sbuf_space_count++; - return; - } - } - else { - int diff = env->hpos - sbuf_end_hpos - sbuf_space_width; - if (diff == 0 || (equalise_spaces && (diff == 1 || diff == -1))) { - sbuf_end_hpos = env->hpos + w + sbuf_kern; - sbuf[sbuf_len++] = sbuf_space_code; - sbuf[sbuf_len++] = code; - sbuf_space_count++; - if (diff == 1) - sbuf_space_diff_count++; - else if (diff == -1) - sbuf_space_diff_count--; - return; - } - } - } - } - flush_sbuf(); - } - sbuf_len = 1; - sbuf[0] = code; - sbuf_end_hpos = env->hpos + w; - sbuf_start_hpos = env->hpos; - sbuf_vpos = env->vpos; - sbuf_style = sty; - sbuf_space_code = -1; - sbuf_space_width = 0; - sbuf_space_count = sbuf_space_diff_count = 0; - sbuf_kern = 0; -} - -int is_small_h(int n) -{ - return n < (font::res*2)/72 && n > -(font::res*10)/72; -} - -int is_small_v(int n) -{ - return n < (font::res*4)/72 && n > -(font::res*4)/72; -} - -static char *make_encoding_name(int encoding_index) -{ - static char buf[3 + INT_DIGITS + 1]; - sprintf(buf, "ENC%d", encoding_index); - return buf; -} - -const char *const WS = " \t\n\r"; - -void ps_printer::define_encoding(const char *encoding, int encoding_index) -{ - char *vec[256]; - for (int i = 0; i < 256; i++) - vec[i] = 0; - char *path; - FILE *fp = font::open_file(encoding, &path); - if (fp == 0) - fatal("can't open encoding file `%1'", encoding); - int lineno = 1; - char buf[256]; - while (fgets(buf, 512, fp) != 0) { - char *p = buf; - while (isascii(*p) && isspace(*p)) - p++; - if (*p != '#' && *p != '\0' && (p = strtok(buf, WS)) != 0) { - char *q = strtok(0, WS); - int n; - if (q == 0 || sscanf(q, "%d", &n) != 1 || n < 0 || n >= 256) - fatal_with_file_and_line(path, lineno, "bad second field"); - vec[n] = new char[strlen(p) + 1]; - strcpy(vec[n], p); - } - lineno++; - } - a_delete path; - out.put_literal_symbol(make_encoding_name(encoding_index)); - out.put_delimiter('['); - for (i = 0; i < 256; i++) { - if (vec[i] == 0) - out.put_literal_symbol(".notdef"); - else { - out.put_literal_symbol(vec[i]); - a_delete vec[i]; - } - } - out.put_delimiter(']').put_symbol("def"); -} - -void ps_printer::reencode_font(ps_font *f) -{ - out.put_literal_symbol(f->reencoded_name) - .put_symbol(make_encoding_name(f->encoding_index)) - .put_literal_symbol(f->get_internal_name()) - .put_symbol("RE"); -} - -void ps_printer::encode_fonts() -{ - if (next_encoding_index == 0) - return; - char *done_encoding = new char[next_encoding_index]; - for (int i = 0; i < next_encoding_index; i++) - done_encoding[i] = 0; - for (font_pointer_list *f = font_list; f; f = f->next) { - int encoding_index = ((ps_font *)f->p)->encoding_index; - if (encoding_index >= 0) { - assert(encoding_index < next_encoding_index); - if (!done_encoding[encoding_index]) { - done_encoding[encoding_index] = 1; - define_encoding(((ps_font *)f->p)->encoding, encoding_index); - } - reencode_font((ps_font *)f->p); - } - } - a_delete done_encoding; -} - -void ps_printer::set_style(const style &sty) -{ - char buf[1 + INT_DIGITS + 1]; - for (int i = 0; i < ndefined_styles; i++) - if (sty == defined_styles[i]) { - sprintf(buf, "F%d", i); - out.put_symbol(buf); - return; - } - if (ndefined_styles >= MAX_DEFINED_STYLES) - ndefined_styles = 0; - sprintf(buf, "F%d", ndefined_styles); - out.put_literal_symbol(buf); - const char *psname = sty.f->get_internal_name(); - if (psname == 0) - fatal("no internalname specified for font `%1'", sty.f->get_name()); - char *encoding = ((ps_font *)sty.f)->encoding; - if (encoding != 0) { - char *s = ((ps_font *)sty.f)->reencoded_name; - if (s == 0) { - int ei = set_encoding_index((ps_font *)sty.f); - char *tem = new char[strlen(psname) + 1 + INT_DIGITS + 1]; - sprintf(tem, "%s@%d", psname, ei); - psname = tem; - ((ps_font *)sty.f)->reencoded_name = tem; - } - else - psname = s; - } - out.put_fix_number((font::res/(72*font::sizescale))*sty.point_size); - if (sty.height != 0 || sty.slant != 0) { - int h = sty.height == 0 ? sty.point_size : sty.height; - h *= font::res/(72*font::sizescale); - int c = int(h*tan(radians(sty.slant)) + .5); - out.put_fix_number(c).put_fix_number(h).put_literal_symbol(psname) - .put_symbol("MF"); - } - else { - out.put_literal_symbol(psname).put_symbol("SF"); - } - defined_styles[ndefined_styles++] = sty; -} - -void ps_printer::set_space_code(unsigned char c) -{ - out.put_literal_symbol("SC").put_number(c).put_symbol("def"); -} - -void ps_printer::end_of_line() -{ - flush_sbuf(); - // this ensures that we do an absolute motion to the beginning of a line - output_vpos = output_hpos = -1; -} - -void ps_printer::flush_sbuf() -{ - enum { - NONE, - RELATIVE_H, - RELATIVE_V, - RELATIVE_HV, - ABSOLUTE - } motion = NONE; - int space_flag = 0; - if (sbuf_len == 0) - return; - if (output_style != sbuf_style) { - set_style(sbuf_style); - output_style = sbuf_style; - } - int extra_space = 0; - if (output_hpos < 0 || output_vpos < 0 - || !is_small_h(output_hpos - sbuf_start_hpos) - || !is_small_v(output_vpos - sbuf_vpos)) - motion = ABSOLUTE; - else { - if (output_hpos != sbuf_start_hpos) - motion = RELATIVE_H; - if (output_vpos != sbuf_vpos) { - if (motion != NONE) - motion = RELATIVE_HV; - else - motion = RELATIVE_V; - } - } - if (sbuf_space_code >= 0) { - int w = sbuf_style.f->get_width(space_char_index, sbuf_style.point_size); - if (w + sbuf_kern != sbuf_space_width) { - if (sbuf_space_code != output_space_code) { - set_space_code(sbuf_space_code); - output_space_code = sbuf_space_code; - } - space_flag = 1; - extra_space = sbuf_space_width - w - sbuf_kern; - if (sbuf_space_diff_count > sbuf_space_count/2) - extra_space++; - else if (sbuf_space_diff_count < -(sbuf_space_count/2)) - extra_space--; - } - } - if (space_flag) - out.put_fix_number(extra_space); - if (sbuf_kern != 0) - out.put_fix_number(sbuf_kern); - out.put_string(sbuf, sbuf_len); - char sym[2]; - sym[0] = 'A' + motion*4 + space_flag + 2*(sbuf_kern != 0); - sym[1] = '\0'; - switch (motion) { - case NONE: - break; - case ABSOLUTE: - out.put_fix_number(sbuf_start_hpos) - .put_fix_number(sbuf_vpos); - break; - case RELATIVE_H: - out.put_fix_number(sbuf_start_hpos - output_hpos); - break; - case RELATIVE_V: - out.put_fix_number(sbuf_vpos - output_vpos); - break; - case RELATIVE_HV: - out.put_fix_number(sbuf_start_hpos - output_hpos) - .put_fix_number(sbuf_vpos - output_vpos); - break; - default: - assert(0); - } - out.put_symbol(sym); - output_hpos = sbuf_end_hpos; - output_vpos = sbuf_vpos; - sbuf_len = 0; -} - - -void ps_printer::set_line_thickness(const environment *env) -{ - if (line_thickness < 0) { - if (output_draw_point_size != env->size) { - // we ought to check for overflow here - int lw = ((font::res/(72*font::sizescale))*linewidth*env->size)/1000; - out.put_fix_number(lw).put_symbol("LW"); - output_draw_point_size = env->size; - output_line_thickness = -1; - } - } - else { - if (output_line_thickness != line_thickness) { - out.put_fix_number(line_thickness).put_symbol("LW"); - output_line_thickness = line_thickness; - output_draw_point_size = -1; - } - } -} - -void ps_printer::fill_path() -{ - if (fill > FILL_MAX) - out.put_symbol("BL"); - else - out.put_float(transform_fill(fill)).put_symbol("FL"); -} - -void ps_printer::draw(int code, int *p, int np, const environment *env) -{ - if (invis_count > 0) - return; - int fill_flag = 0; - switch (code) { - case 'C': - fill_flag = 1; - // fall through - case 'c': - // troff adds an extra argument to C - if (np != 1 && !(code == 'C' && np == 2)) { - error("1 argument required for circle"); - break; - } - out.put_fix_number(env->hpos + p[0]/2) - .put_fix_number(env->vpos) - .put_fix_number(p[0]/2) - .put_symbol("DC"); - if (fill_flag) { - fill_path(); - } - else { - set_line_thickness(env); - out.put_symbol("ST"); - } - break; - case 'l': - if (np != 2) { - error("2 arguments required for line"); - break; - } - set_line_thickness(env); - out.put_fix_number(p[0] + env->hpos) - .put_fix_number(p[1] + env->vpos) - .put_fix_number(env->hpos) - .put_fix_number(env->vpos) - .put_symbol("DL"); - break; - case 'E': - fill_flag = 1; - // fall through - case 'e': - if (np != 2) { - error("2 arguments required for ellipse"); - break; - } - out.put_fix_number(p[0]) - .put_fix_number(p[1]) - .put_fix_number(env->hpos + p[0]/2) - .put_fix_number(env->vpos) - .put_symbol("DE"); - if (fill_flag) { - fill_path(); - } - else { - set_line_thickness(env); - out.put_symbol("ST"); - } - break; - case 'P': - fill_flag = 1; - // fall through - case 'p': - { - if (np & 1) { - error("even number of arguments required for polygon"); - break; - } - if (np == 0) { - error("no arguments for polygon"); - break; - } - out.put_fix_number(env->hpos) - .put_fix_number(env->vpos) - .put_symbol("MT"); - for (int i = 0; i < np; i += 2) - out.put_fix_number(p[i]) - .put_fix_number(p[i+1]) - .put_symbol("RL"); - out.put_symbol("CL"); - if (fill_flag) { - fill_path(); - } - else { - set_line_thickness(env); - out.put_symbol("ST"); - } - break; - } - case '~': - { - if (np & 1) { - error("even number of arguments required for spline"); - break; - } - if (np == 0) { - error("no arguments for spline"); - break; - } - out.put_fix_number(env->hpos) - .put_fix_number(env->vpos) - .put_symbol("MT"); - out.put_fix_number(p[0]/2) - .put_fix_number(p[1]/2) - .put_symbol("RL"); - /* tnum/tden should be between 0 and 1; the closer it is to 1 - the tighter the curve will be to the guiding lines; 2/3 - is the standard value */ - const int tnum = 2; - const int tden = 3; - for (int i = 0; i < np - 2; i += 2) { - out.put_fix_number((p[i]*tnum)/(2*tden)) - .put_fix_number((p[i + 1]*tnum)/(2*tden)) - .put_fix_number(p[i]/2 + (p[i + 2]*(tden - tnum))/(2*tden)) - .put_fix_number(p[i + 1]/2 + (p[i + 3]*(tden - tnum))/(2*tden)) - .put_fix_number((p[i] - p[i]/2) + p[i + 2]/2) - .put_fix_number((p[i + 1] - p[i + 1]/2) + p[i + 3]/2) - .put_symbol("RC"); - } - out.put_fix_number(p[np - 2] - p[np - 2]/2) - .put_fix_number(p[np - 1] - p[np - 1]/2) - .put_symbol("RL"); - set_line_thickness(env); - out.put_symbol("ST"); - } - break; - case 'a': - { - if (np != 4) { - error("4 arguments required for arc"); - break; - } - set_line_thickness(env); - double c[2]; - if (adjust_arc_center(p, c)) - out.put_fix_number(env->hpos + int(c[0])) - .put_fix_number(env->vpos + int(c[1])) - .put_fix_number(int(sqrt(c[0]*c[0] + c[1]*c[1]))) - .put_float(degrees(atan2(-c[1], -c[0]))) - .put_float(degrees(atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0]))) - .put_symbol("DA"); - else - out.put_fix_number(p[0] + p[2] + env->hpos) - .put_fix_number(p[1] + p[3] + env->vpos) - .put_fix_number(env->hpos) - .put_fix_number(env->vpos) - .put_symbol("DL"); - } - break; - case 't': - { - if (np == 0) { - line_thickness = -1; - } - else { - // troff gratuitously adds an extra 0 - if (np != 1 && np != 2) { - error("0 or 1 argument required for thickness"); - break; - } - line_thickness = p[0]; - } - break; - } - case 'f': - { - if (np != 1 && np != 2) { - error("1 argument required for fill"); - break; - } - fill = p[0]; - if (fill < 0 || fill > FILL_MAX) { - // This means fill with the current color. - fill = FILL_MAX + 1; - } - break; - } - default: - error("unrecognised drawing command `%1'", char(code)); - break; - } - - output_hpos = output_vpos = -1; -} - - -void ps_printer::begin_page(int n) -{ - out.begin_comment("Page:").comment_arg(itoa(n)); - out.comment_arg(itoa(++pages_output)).end_comment(); - output_style.f = 0; - output_space_code = 32; - output_draw_point_size = -1; - output_line_thickness = -1; - output_hpos = output_vpos = -1; - ndefined_styles = 0; - out.simple_comment("BeginPageSetup"); - out.put_symbol("BP"); - out.simple_comment("EndPageSetup"); -} - -void ps_printer::end_page(int) -{ - flush_sbuf(); - out.put_symbol("EP"); - if (invis_count != 0) { - error("missing `endinvis' command"); - invis_count = 0; - } -} - -font *ps_printer::make_font(const char *nm) -{ - return ps_font::load_ps_font(nm); -} - -ps_printer::~ps_printer() -{ - out.simple_comment("Trailer"); - out.put_symbol("end"); - out.simple_comment("EOF"); - if (fseek(tempfp, 0L, 0) < 0) - fatal("fseek on temporary file failed"); - fputs("%!PS-Adobe-", stdout); - fputs((broken_flags & USE_PS_ADOBE_2_0) ? "2.0" : "3.0", stdout); - putchar('\n'); - out.set_file(stdout); - { - extern const char *version_string; - out.begin_comment("Creator:") - .comment_arg("groff") - .comment_arg("version") - .comment_arg(version_string) - .end_comment(); - } - for (font_pointer_list *f = font_list; f; f = f->next) { - ps_font *psf = (ps_font *)(f->p); - rm.need_font(psf->get_internal_name()); - } - rm.print_header_comments(out); - out.begin_comment("Pages:").comment_arg(itoa(pages_output)).end_comment(); - out.begin_comment("PageOrder:").comment_arg("Ascend").end_comment(); -#if 0 - fprintf(out.get_file(), "%%%%DocumentMedia: () %g %g 0 () ()\n", - font::paperwidth*72.0/font::res, - paper_length*72.0/font::res); -#endif - out.begin_comment("Orientation:") - .comment_arg(landscape_flag ? "Landscape" : "Portrait") - .end_comment(); - if (ncopies != 1) { - out.end_line(); - fprintf(out.get_file(), "%%%%Requirements: numcopies(%d)\n", ncopies); - } - out.simple_comment("EndComments"); - out.simple_comment("BeginProlog"); - rm.output_prolog(out); - if (!(broken_flags & NO_SETUP_SECTION)) { - out.simple_comment("EndProlog"); - out.simple_comment("BeginSetup"); - } - rm.document_setup(out); - out.put_symbol(dict_name).put_symbol("begin"); - if (ndefs > 0) - ndefs += DEFS_DICT_SPARE; - out.put_literal_symbol(defs_dict_name) - .put_number(ndefs + 1) - .put_symbol("dict") - .put_symbol("def"); - out.put_symbol(defs_dict_name) - .put_symbol("begin"); - out.put_literal_symbol("u") - .put_delimiter('{') - .put_fix_number(1) - .put_symbol("mul") - .put_delimiter('}') - .put_symbol("bind") - .put_symbol("def"); - defs += '\0'; - out.special(defs.contents()); - out.put_symbol("end"); - if (ncopies != 1) - out.put_literal_symbol("#copies").put_number(ncopies).put_symbol("def"); - out.put_literal_symbol("RES").put_number(res).put_symbol("def"); - out.put_literal_symbol("PL"); - if (guess_flag) - out.put_symbol("PLG"); - else - out.put_fix_number(paper_length); - out.put_symbol("def"); - out.put_literal_symbol("LS") - .put_symbol(landscape_flag ? "true" : "false") - .put_symbol("def"); - encode_fonts(); - out.simple_comment((broken_flags & NO_SETUP_SECTION) - ? "EndProlog" - : "EndSetup"); - out.end_line(); - out.copy_file(tempfp); - fclose(tempfp); -} - -void ps_printer::special(char *arg, const environment *env) -{ - typedef void (ps_printer::*SPECIAL_PROCP)(char *, const environment *); - static struct { - const char *name; - SPECIAL_PROCP proc; - } proc_table[] = { - "exec", &ps_printer::do_exec, - "def", &ps_printer::do_def, - "mdef", &ps_printer::do_mdef, - "import", &ps_printer::do_import, - "file", &ps_printer::do_file, - "invis", &ps_printer::do_invis, - "endinvis", &ps_printer::do_endinvis, - }; - for (char *p = arg; *p == ' ' || *p == '\n'; p++) - ; - char *tag = p; - for (; *p != '\0' && *p != ':' && *p != ' ' && *p != '\n'; p++) - ; - if (*p == '\0' || strncmp(tag, "ps", p - tag) != 0) { - error("X command without `ps:' tag ignored"); - return; - } - p++; - for (; *p == ' ' || *p == '\n'; p++) - ; - char *command = p; - for (; *p != '\0' && *p != ' ' && *p != '\n'; p++) - ; - if (*command == '\0') { - error("X command without `ps:' tag ignored"); - return; - } - for (int i = 0; i < sizeof(proc_table)/sizeof(proc_table[0]); i++) - if (strncmp(command, proc_table[i].name, p - command) == 0) { - (this->*(proc_table[i].proc))(p, env); - return; - } - error("X command `%1' not recognised", command); -} - -// A conforming PostScript document must not have lines longer -// than 255 characters (excluding line termination characters). - -static int check_line_lengths(const char *p) -{ - for (;;) { - const char *end = strchr(p, '\n'); - if (end == 0) - end = strchr(p, '\0'); - if (end - p > 255) - return 0; - if (*end == '\0') - break; - p = end + 1; - } - return 1; -} - -void ps_printer::do_exec(char *arg, const environment *env) -{ - flush_sbuf(); - while (csspace(*arg)) - arg++; - if (*arg == '\0') { - error("missing argument to X exec command"); - return; - } - if (!check_line_lengths(arg)) { - error("lines in X exec command must not be more than 255 characters long"); - return; - } - out.put_fix_number(env->hpos) - .put_fix_number(env->vpos) - .put_symbol("EBEGIN") - .special(arg) - .put_symbol("EEND"); - output_hpos = output_vpos = -1; - output_style.f = 0; - output_draw_point_size = -1; - output_line_thickness = -1; - ndefined_styles = 0; - if (!ndefs) - ndefs = 1; -} - -void ps_printer::do_file(char *arg, const environment *env) -{ - flush_sbuf(); - while (csspace(*arg)) - arg++; - if (*arg == '\0') { - error("missing argument to X file command"); - return; - } - const char *filename = arg; - do { - ++arg; - } while (*arg != '\0' && *arg != ' ' && *arg != '\n'); - out.put_fix_number(env->hpos) - .put_fix_number(env->vpos) - .put_symbol("EBEGIN"); - rm.import_file(filename, out); - out.put_symbol("EEND"); - output_hpos = output_vpos = -1; - output_style.f = 0; - output_draw_point_size = -1; - output_line_thickness = -1; - ndefined_styles = 0; - if (!ndefs) - ndefs = 1; -} - -void ps_printer::do_def(char *arg, const environment *) -{ - flush_sbuf(); - while (csspace(*arg)) - arg++; - if (!check_line_lengths(arg)) { - error("lines in X def command must not be more than 255 characters long"); - return; - } - defs += arg; - if (*arg != '\0' && strchr(arg, '\0')[-1] != '\n') - defs += '\n'; - ndefs++; -} - -// Like def, but the first argument says how many definitions it contains. - -void ps_printer::do_mdef(char *arg, const environment *) -{ - flush_sbuf(); - char *p; - int n = (int)strtol(arg, &p, 10); - if (n == 0 && p == arg) { - error("first argument to X mdef must be an integer"); - return; - } - if (n < 0) { - error("out of range argument `%1' to X mdef command", int(n)); - return; - } - arg = p; - while (csspace(*arg)) - arg++; - if (!check_line_lengths(arg)) { - error("lines in X mdef command must not be more than 255 characters long"); - return; - } - defs += arg; - if (*arg != '\0' && strchr(arg, '\0')[-1] != '\n') - defs += '\n'; - ndefs += n; -} - -void ps_printer::do_import(char *arg, const environment *env) -{ - flush_sbuf(); - while (*arg == ' ' || *arg == '\n') - arg++; - for (char *p = arg; *p != '\0' && *p != ' ' && *p != '\n'; p++) - ; - if (*p != '\0') - *p++ = '\0'; - int parms[6]; - int nparms = 0; - while (nparms < 6) { - char *end; - long n = strtol(p, &end, 10); - if (n == 0 && end == p) - break; - parms[nparms++] = int(n); - p = end; - } - if (csalpha(*p) && (p[1] == '\0' || p[1] == ' ' || p[1] == '\n')) { - error("scaling indicators not allowed in arguments for X import command"); - return; - } - while (*p == ' ' || *p == '\n') - p++; - if (nparms < 5) { - if (*p == '\0') - error("too few arguments for X import command"); - else - error("invalid argument `%1' for X import command", p); - return; - } - if (*p != '\0') { - error("superflous argument `%1' for X import command", p); - return; - } - int llx = parms[0]; - int lly = parms[1]; - int urx = parms[2]; - int ury = parms[3]; - int desired_width = parms[4]; - int desired_height = parms[5]; - if (desired_width <= 0) { - error("bad width argument `%1' for X import command: must be > 0", - desired_width); - return; - } - if (nparms == 6 && desired_height <= 0) { - error("bad height argument `%1' for X import command: must be > 0", - desired_height); - return; - } - if (llx == urx) { - error("llx and urx arguments for X import command must not be equal"); - return; - } - if (lly == ury) { - error("lly and ury arguments for X import command must not be equal"); - return; - } - if (nparms == 5) { - int old_wid = urx - llx; - int old_ht = ury - lly; - if (old_wid < 0) - old_wid = -old_wid; - if (old_ht < 0) - old_ht = -old_ht; - desired_height = int(desired_width*(double(old_ht)/double(old_wid)) + .5); - } - if (env->vpos - desired_height < 0) - warning("top of imported graphic is above the top of the page"); - out.put_number(llx) - .put_number(lly) - .put_fix_number(desired_width) - .put_number(urx - llx) - .put_fix_number(-desired_height) - .put_number(ury - lly) - .put_fix_number(env->hpos) - .put_fix_number(env->vpos) - .put_symbol("PBEGIN"); - rm.import_file(arg, out); - // do this here just in case application defines PEND - out.put_symbol("end"); - out.put_symbol("PEND"); -} - -void ps_printer::do_invis(char *, const environment *) -{ - invis_count++; -} - -void ps_printer::do_endinvis(char *, const environment *) -{ - if (invis_count == 0) - error("unbalanced `endinvis' command"); - else - --invis_count; -} - -printer *make_printer() -{ - return new ps_printer; -} - -static void usage(); - -int main(int argc, char **argv) -{ - program_name = argv[0]; - static char stderr_buf[BUFSIZ]; - setbuf(stderr, stderr_buf); - int c; - while ((c = getopt(argc, argv, "F:glc:w:vb:")) != EOF) - switch(c) { - case 'v': - { - extern const char *version_string; - fprintf(stderr, "grops version %s\n", version_string); - fflush(stderr); - break; - } - case 'c': - if (sscanf(optarg, "%d", &ncopies) != 1 || ncopies <= 0) { - error("bad number of copies `%s'", optarg); - ncopies = 1; - } - break; - case 'g': - guess_flag = 1; - break; - case 'l': - landscape_flag = 1; - break; - case 'F': - font::command_line_font_dir(optarg); - break; - case 'w': - if (sscanf(optarg, "%d", &linewidth) != 1 || linewidth < 0) { - error("bad linewidth `%s'", optarg); - linewidth = -1; - } - break; - case 'b': - // XXX check this - broken_flags = atoi(optarg); - bflag = 1; - break; - case '?': - usage(); - break; - default: - assert(0); - } - font::set_unknown_desc_command_handler(handle_unknown_desc_command); - if (optind >= argc) - do_file("-"); - else { - for (int i = optind; i < argc; i++) - do_file(argv[i]); - } - delete pr; - exit(0); -} - -static void usage() -{ - fprintf(stderr, "usage: %s [-glv] [-b n] [-c n] [-w n] [-F dir] [files ...]\n", - program_name); - exit(1); -} diff --git a/gnu/groff/grops/ps.h b/gnu/groff/grops/ps.h deleted file mode 100644 index 50be4e8ba4b6..000000000000 --- a/gnu/groff/grops/ps.h +++ /dev/null @@ -1,122 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.com) - -This file is part of groff. - -groff is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later -version. - -groff is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License along -with groff; see the file COPYING. If not, write to the Free Software -Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -class ps_output { -public: - ps_output(FILE *, int max_line_length); - ps_output &put_string(const char *, int); - ps_output &put_number(int); - ps_output &put_fix_number(int); - ps_output &put_float(double); - ps_output &put_symbol(const char *); - ps_output &put_literal_symbol(const char *); - ps_output &set_fixed_point(int); - ps_output &simple_comment(const char *); - ps_output &begin_comment(const char *); - ps_output &comment_arg(const char *); - ps_output &end_comment(); - ps_output &set_file(FILE *); - ps_output &include_file(FILE *); - ps_output ©_file(FILE *); - ps_output &end_line(); - ps_output &put_delimiter(char); - ps_output &special(const char *); - FILE *get_file(); -private: - FILE *fp; - int col; - int max_line_length; // not including newline - int need_space; - int fixed_point; -}; - -inline FILE *ps_output::get_file() -{ - return fp; -} - -enum resource_type { - RESOURCE_FONT, - RESOURCE_PROCSET, - RESOURCE_FILE, - RESOURCE_ENCODING, - RESOURCE_FORM, - RESOURCE_PATTERN - }; - -struct resource; - -extern string an_empty_string; - -class resource_manager { -public: - resource_manager(); - ~resource_manager(); - void import_file(const char *filename, ps_output &); - void need_font(const char *name); - void print_header_comments(ps_output &); - void document_setup(ps_output &); - void output_prolog(ps_output &); -private: - unsigned extensions; - unsigned language_level; - resource *procset_resource; - resource *resource_list; - resource *lookup_resource(resource_type type, string &name, - string &version = an_empty_string, - unsigned revision = 0); - resource *lookup_font(const char *name); - void read_download_file(); - void supply_resource(resource *r, int rank, FILE *outfp, - int is_document = 0); - void process_file(int rank, FILE *fp, const char *filename, FILE *outfp); - resource *read_file_arg(const char **); - resource *read_procset_arg(const char **); - resource *read_font_arg(const char **); - resource *read_resource_arg(const char **); - void print_resources_comment(unsigned flag, FILE *outfp); - void print_extensions_comment(FILE *outfp); - void print_language_level_comment(FILE *outfp); - int do_begin_resource(const char *ptr, int rank, FILE *fp, FILE *outfp); - int do_include_resource(const char *ptr, int rank, FILE *fp, FILE *outfp); - int do_begin_document(const char *ptr, int rank, FILE *fp, FILE *outfp); - int do_include_document(const char *ptr, int rank, FILE *fp, FILE *outfp); - int do_begin_procset(const char *ptr, int rank, FILE *fp, FILE *outfp); - int do_include_procset(const char *ptr, int rank, FILE *fp, FILE *outfp); - int do_begin_font(const char *ptr, int rank, FILE *fp, FILE *outfp); - int do_include_font(const char *ptr, int rank, FILE *fp, FILE *outfp); - int do_begin_file(const char *ptr, int rank, FILE *fp, FILE *outfp); - int do_include_file(const char *ptr, int rank, FILE *fp, FILE *outfp); - int change_to_end_resource(const char *ptr, int rank, FILE *fp, FILE *outfp); - int do_begin_preview(const char *ptr, int rank, FILE *fp, FILE *outfp); - int do_begin_data(const char *ptr, int rank, FILE *fp, FILE *outfp); - int do_begin_binary(const char *ptr, int rank, FILE *fp, FILE *outfp); -}; - -extern unsigned broken_flags; - -// broken_flags is ored from these - -enum { - NO_SETUP_SECTION = 01, - STRIP_PERCENT_BANG = 02, - STRIP_STRUCTURE_COMMENTS = 04, - USE_PS_ADOBE_2_0 = 010 -}; diff --git a/gnu/groff/grops/psfig.diff b/gnu/groff/grops/psfig.diff deleted file mode 100644 index 77217742dcd9..000000000000 --- a/gnu/groff/grops/psfig.diff +++ /dev/null @@ -1,106 +0,0 @@ -These are patches to makes psfig work with groff. They apply to the -version of psfig in comp.sources.unix/Volume11. After applying them, -psfig should be recompiled with -DGROFF. The resulting psfig will -work only with groff, so you might want to install it under a -different name. The output of this psfig must be processed using the -macros in the file ../macros/tmac.psfig. These will automatically add -the necessary PostScript code to the prologue output by grops. Use of -the `global' feature in psfig will result in non-conformant PostScript -which will fail if processed by a page reversal program. Note that -psfig is unsupported by me (I'm not interested in hearing about psfig -problems.) For new documents, I recommend using the PostScript -inclusion features provided by grops. - -James Clark -jjc@jclark.com - -*** cmds.c.~1~ Thu Feb 14 16:09:45 1991 ---- cmds.c Mon Mar 4 12:49:26 1991 -*************** -*** 245,253 **** ---- 245,261 ---- - (void) sprintf(x, "%.2fp", fx); - (void) sprintf(y, "%.2fp", fy); - } else if (!*x) { -+ #ifndef GROFF - (void) sprintf(x,"(%.2fp*%s/%.2fp)", fx, y, fy); -+ #else /* GROFF */ -+ (void) sprintf(x,"(%.0fu*%s/%.0fu)", fx, y, fy); -+ #endif /* GROFF */ - } else if (!*y) { -+ #ifndef GROFF - (void) sprintf(y,"(%.2fp*%s/%.2fp)", fy, x, fx); -+ #else /* GROFF */ -+ (void) sprintf(y,"(%.0fu*%s/%.0fu)", fy, x, fx); -+ #endif /* GROFF */ - } - - /* -*** troff.c.~1~ Thu Feb 14 16:09:48 1991 ---- troff.c Mon Mar 4 12:48:46 1991 -*************** -*** 26,32 **** ---- 26,36 ---- - } - - -+ #ifndef GROFF - char incl_file_s[] = "\\X'f%s'"; -+ #else /* GROFF */ -+ char incl_file_s[] = "\\X'ps: file %s'"; -+ #endif /* GROFF */ - includeFile(filenm) - char *filenm; { - printf(incl_file_s, filenm); -*************** -*** 40,52 **** ---- 44,64 ---- - error("buffer overflow"); - } - -+ #ifndef GROFF - char endfig_s[] = "\\X'pendFig'"; -+ #else /* GROFF */ -+ char endfig_s[] = "\\X'ps: exec psfigend'"; -+ #endif /* GROFF */ - endfig() { - printf(endfig_s); - } - - char startfig_s[] = -+ #ifndef GROFF - "\\X'p\\w@\\h@%s@@'\\X'p\\w@\\h@%s@@'\\X'p%.2f'\\X'p%.2f'\\X'p%.2f'\\X'p%.2f'\\X'pstartFig'"; -+ #else /* GROFF */ -+ "\\X'ps: exec \\w@\\h@%s@@ \\w@\\h@%s@@ %.2f %.2f %.2f %.2f psfigstart'"; -+ #endif /* GROFF */ - - startfig(x, y, llx, lly, urx, ury) - char *x, *y; -*************** -*** 57,63 **** ---- 69,79 ---- - } - - emitDoClip() { -+ #ifndef GROFF - printf("\\X'pdoclip'"); -+ #else /* GROFF */ -+ printf("\\X'ps: exec psfigclip'"); -+ #endif /* GROFF */ - } - - flushX() -*************** -*** 116,122 **** ---- 132,142 ---- - - #define isWhite(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\n') - -+ #ifndef GROFF - char literal_s[] = "\\X'p%s'"; -+ #else /* GROFF */ -+ char literal_s[] = "\\X'ps: exec %s'"; -+ #endif /* GROFF */ - emitLiteral(text) - char *text; { - static char litbuf[BUFSZ]; diff --git a/gnu/groff/grops/psrm.cc b/gnu/groff/grops/psrm.cc deleted file mode 100644 index e26acf4b15c5..000000000000 --- a/gnu/groff/grops/psrm.cc +++ /dev/null @@ -1,1091 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.com) - -This file is part of groff. - -groff is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later -version. - -groff is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License along -with groff; see the file COPYING. If not, write to the Free Software -Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include "driver.h" -#include "stringclass.h" -#include "cset.h" - -#include "ps.h" - -#define PROLOGUE "prologue" - -static void print_ps_string(const string &s, FILE *outfp); - -cset white_space("\n\r \t"); -string an_empty_string; - -const char *extension_table[] = { - "DPS", - "CMYK", - "Composite", - "FileSystem", -}; - -const int NEXTENSIONS = sizeof(extension_table)/sizeof(extension_table[0]); - -const char *resource_table[] = { - "font", - "procset", - "file", - "encoding", - "form", - "pattern", -}; - -const int NRESOURCES = sizeof(resource_table)/sizeof(resource_table[0]); - -struct resource { - resource *next; - resource_type type; - string name; - enum { NEEDED = 01, SUPPLIED = 02, FONT_NEEDED = 04, BUSY = 010 }; - unsigned flags; - string version; - unsigned revision; - char *filename; - int rank; - resource(resource_type, string &, string & = an_empty_string, unsigned = 0); - ~resource(); - void print_type_and_name(FILE *outfp); -}; - -resource::resource(resource_type t, string &n, string &v, unsigned r) -: type(t), revision(r), flags (0), filename(0), rank(-1), next(0) -{ - name.move(n); - version.move(v); - if (type == RESOURCE_FILE) { - if (name.search('\0') >= 0) - error("filename contains a character with code 0"); - filename = name.extract(); - } -} - -resource::~resource() -{ - a_delete filename; -} - -void resource::print_type_and_name(FILE *outfp) -{ - fputs(resource_table[type], outfp); - putc(' ', outfp); - print_ps_string(name, outfp); - if (type == RESOURCE_PROCSET) { - putc(' ', outfp); - print_ps_string(version, outfp); - fprintf(outfp, " %u", revision); - } -} - -resource_manager::resource_manager() -: resource_list(0), extensions(0), language_level(0) -{ - read_download_file(); - string procset_name("grops"); - extern const char *version_string; - string procset_version(version_string); - procset_resource = lookup_resource(RESOURCE_PROCSET, procset_name, - procset_version, 0); - procset_resource->flags |= resource::SUPPLIED; -} - -resource_manager::~resource_manager() -{ - while (resource_list) { - resource *tem = resource_list; - resource_list = resource_list->next; - delete tem; - } -} - -resource *resource_manager::lookup_resource(resource_type type, - string &name, - string &version, - unsigned revision) -{ - for (resource *r = resource_list; r; r = r->next) - if (r->type == type - && r->name == name - && r->version == version - && r->revision == revision) - return r; - r = new resource(type, name, version, revision); - r->next = resource_list; - resource_list = r; - return r; -} - -// Just a specialized version of lookup_resource(). - -resource *resource_manager::lookup_font(const char *name) -{ - for (resource *r = resource_list; r; r = r->next) - if (r->type == RESOURCE_FONT - && strlen(name) == r->name.length() - && memcmp(name, r->name.contents(), r->name.length()) == 0) - return r; - string s(name); - r = new resource(RESOURCE_FONT, s); - r->next = resource_list; - resource_list = r; - return r; -} - -void resource_manager::need_font(const char *name) -{ - lookup_font(name)->flags |= resource::FONT_NEEDED; -} - -typedef resource *Presource; // Work around g++ bug. - -void resource_manager::document_setup(ps_output &out) -{ - int nranks = 0; - for (resource *r = resource_list; r; r = r->next) - if (r->rank >= nranks) - nranks = r->rank + 1; - if (nranks > 0) { - // Sort resource_list in reverse order of rank. - Presource *head = new Presource[nranks + 1]; - Presource **tail = new Presource *[nranks + 1]; - for (int i = 0; i < nranks + 1; i++) { - head[i] = 0; - tail[i] = &head[i]; - } - for (r = resource_list; r; r = r->next) { - i = r->rank < 0 ? 0 : r->rank + 1; - *tail[i] = r; - tail[i] = &(*tail[i])->next; - } - resource_list = 0; - for (i = 0; i < nranks + 1; i++) - if (head[i]) { - *tail[i] = resource_list; - resource_list = head[i]; - } - a_delete head; - a_delete tail; - // check it - for (r = resource_list; r; r = r->next) - if (r->next) - assert(r->rank >= r->next->rank); - for (r = resource_list; r; r = r->next) - if (r->type == RESOURCE_FONT && r->rank >= 0) - supply_resource(r, -1, out.get_file()); - } -} - -void resource_manager::print_resources_comment(unsigned flag, FILE *outfp) -{ - int continued = 0; - for (resource *r = resource_list; r; r = r->next) - if (r->flags & flag) { - if (continued) - fputs("%%+ ", outfp); - else { - fputs(flag == resource::NEEDED - ? "%%DocumentNeededResources: " - : "%%DocumentSuppliedResources: ", - outfp); - continued = 1; - } - r->print_type_and_name(outfp); - putc('\n', outfp); - } -} - -void resource_manager::print_header_comments(ps_output &out) -{ - for (resource *r = resource_list; r; r = r->next) - if (r->type == RESOURCE_FONT && (r->flags & resource::FONT_NEEDED)) - supply_resource(r, 0, 0); - print_resources_comment(resource::NEEDED, out.get_file()); - print_resources_comment(resource::SUPPLIED, out.get_file()); - print_language_level_comment(out.get_file()); - print_extensions_comment(out.get_file()); -} - -void resource_manager::output_prolog(ps_output &out) -{ - FILE *outfp = out.get_file(); - out.end_line(); - char *path; - FILE *fp = font::open_file(PROLOGUE, &path); - if (!fp) - fatal("can't find `%1'", PROLOGUE); - fputs("%%BeginResource: ", outfp); - procset_resource->print_type_and_name(outfp); - putc('\n', outfp); - process_file(-1, fp, path, outfp); - fclose(fp); - a_delete path; - fputs("%%EndResource\n", outfp); -} - -void resource_manager::import_file(const char *filename, ps_output &out) -{ - out.end_line(); - string name(filename); - resource *r = lookup_resource(RESOURCE_FILE, name); - supply_resource(r, -1, out.get_file(), 1); -} - -void resource_manager::supply_resource(resource *r, int rank, FILE *outfp, - int is_document) -{ - if (r->flags & resource::BUSY) { - r->name += '\0'; - fatal("loop detected in dependency graph for %1 `%2'", - resource_table[r->type], - r->name.contents()); - } - r->flags |= resource::BUSY; - if (rank > r->rank) - r->rank = rank; - char *path; - FILE *fp = 0; - if (r->filename != 0) { - if (r->type == RESOURCE_FONT) { - fp = font::open_file(r->filename, &path); - if (!fp) { - error("can't find `%1'", r->filename); - a_delete r->filename; - r->filename = 0; - } - } - else { - errno = 0; - fp = fopen(r->filename, "r"); - if (!fp) { - error("can't open `%1': %2", r->filename, strerror(errno)); - a_delete r->filename; - r->filename = 0; - } - else - path = r->filename; - } - } - if (fp) { - if (outfp) { - if (r->type == RESOURCE_FILE && is_document) { - fputs("%%BeginDocument: ", outfp); - print_ps_string(r->name, outfp); - putc('\n', outfp); - } - else { - fputs("%%BeginResource: ", outfp); - r->print_type_and_name(outfp); - putc('\n', outfp); - } - } - process_file(rank, fp, path, outfp); - fclose(fp); - if (r->type == RESOURCE_FONT) - a_delete path; - if (outfp) { - if (r->type == RESOURCE_FILE && is_document) - fputs("%%EndDocument\n", outfp); - else - fputs("%%EndResource\n", outfp); - } - r->flags |= resource::SUPPLIED; - } - else { - if (outfp) { - if (r->type == RESOURCE_FILE && is_document) { - fputs("%%IncludeDocument: ", outfp); - print_ps_string(r->name, outfp); - putc('\n', outfp); - } - else { - fputs("%%IncludeResource: ", outfp); - r->print_type_and_name(outfp); - putc('\n', outfp); - } - } - r->flags |= resource::NEEDED; - } - r->flags &= ~resource::BUSY; -} - - -#define PS_LINE_MAX 255 -#define PS_MAGIC "%!PS-Adobe-" - -static int ps_get_line(char *buf, FILE *fp) -{ - int c = getc(fp); - if (c == EOF) { - buf[0] = '\0'; - return 0; - } - current_lineno++; - int i = 0; - int err = 0; - while (c != '\r' && c != '\n' && c != EOF) { - if ((c < 0x1b && !white_space(c)) || c == 0x7f) - error("illegal input character code %1", int(c)); - else if (i < PS_LINE_MAX) - buf[i++] = c; - else if (!err) { - err = 1; - error("PostScript file non-conforming " - "because length of line exceeds 255"); - } - c = getc(fp); - } - buf[i++] = '\n'; - buf[i] = '\0'; - if (c == '\r') { - c = getc(fp); - if (c != EOF && c != '\n') - ungetc(c, fp); - } - return 1; -} - -static int read_text_arg(const char **pp, string &res) -{ - res.clear(); - while (white_space(**pp)) - *pp += 1; - if (**pp == '\0') { - error("missing argument"); - return 0; - } - if (**pp != '(') { - for (; **pp != '\0' && !white_space(**pp); *pp += 1) - res += **pp; - return 1; - } - *pp += 1; - res.clear(); - int level = 0; - for (;;) { - if (**pp == '\0' || **pp == '\r' || **pp == '\n') { - error("missing ')'"); - return 0; - } - if (**pp == ')') { - if (level == 0) { - *pp += 1; - break; - } - res += **pp; - level--; - } - else if (**pp == '(') { - level++; - res += **pp; - } - else if (**pp == '\\') { - *pp += 1; - switch (**pp) { - case 'n': - res += '\n'; - break; - case 'r': - res += '\n'; - break; - case 't': - res += '\t'; - break; - case 'b': - res += '\b'; - break; - case 'f': - res += '\f'; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - { - int val = **pp - '0'; - if ((*pp)[1] >= '0' && (*pp)[1] <= '7') { - *pp += 1; - val = val*8 + (**pp - '0'); - if ((*pp)[1] >= '0' && (*pp)[1] <= '7') { - *pp += 1; - val = val*8 + (**pp - '0'); - } - } - } - break; - default: - res += **pp; - break; - } - } - else - res += **pp; - *pp += 1; - } - return 1; -} - -static int read_uint_arg(const char **pp, unsigned *res) -{ - while (white_space(**pp)) - *pp += 1; - if (**pp == '\0') { - error("missing argument"); - return 0; - } - const char *start = *pp; - // XXX use strtoul - long n = strtol(start, (char **)pp, 10); - if (n == 0 && *pp == start) { - error("not an integer"); - return 0; - } - if (n < 0) { - error("argument must not be negative"); - return 0; - } - *res = unsigned(n); - return 1; -} - -resource *resource_manager::read_file_arg(const char **ptr) -{ - string arg; - if (!read_text_arg(ptr, arg)) - return 0; - return lookup_resource(RESOURCE_FILE, arg); -} - -resource *resource_manager::read_font_arg(const char **ptr) -{ - string arg; - if (!read_text_arg(ptr, arg)) - return 0; - return lookup_resource(RESOURCE_FONT, arg); -} - -resource *resource_manager::read_procset_arg(const char **ptr) -{ - string arg; - if (!read_text_arg(ptr, arg)) - return 0; - string version; - if (!read_text_arg(ptr, version)) - return 0; - unsigned revision; - if (!read_uint_arg(ptr, &revision)) - return 0; - return lookup_resource(RESOURCE_PROCSET, arg, version, revision); -} - -resource *resource_manager::read_resource_arg(const char **ptr) -{ - while (white_space(**ptr)) - *ptr += 1; - const char *name = *ptr; - while (**ptr != '\0' && !white_space(**ptr)) - *ptr += 1; - if (name == *ptr) { - error("missing resource type"); - return 0; - } - for (int ri = 0; ri < NRESOURCES; ri++) - if (strlen(resource_table[ri]) == *ptr - name - && memcmp(resource_table[ri], name, *ptr - name) == 0) - break; - if (ri >= NRESOURCES) { - error("unknown resource type"); - return 0; - } - if (ri == RESOURCE_PROCSET) - return read_procset_arg(ptr); - string arg; - if (!read_text_arg(ptr, arg)) - return 0; - return lookup_resource(resource_type(ri), arg); -} - -static const char *matches_comment(const char *buf, const char *comment) -{ - if (buf[0] != '%' || buf[1] != '%') - return 0; - for (buf += 2; *comment; comment++, buf++) - if (*buf != *comment) - return 0; - if (comment[-1] == ':') - return buf; - if (*buf == '\0' || white_space(*buf)) - return buf; - return 0; -} - -// Return 1 if the line should be copied out. - -int resource_manager::do_begin_resource(const char *ptr, int, FILE *, - FILE *) -{ - resource *r = read_resource_arg(&ptr); - if (r) - r->flags |= resource::SUPPLIED; - return 1; -} - -int resource_manager::do_include_resource(const char *ptr, int rank, FILE *, - FILE *outfp) -{ - resource *r = read_resource_arg(&ptr); - if (r) { - if (r->type == RESOURCE_FONT) { - if (rank >= 0) - supply_resource(r, rank + 1, outfp); - else - r->flags |= resource::FONT_NEEDED; - } - else - supply_resource(r, rank, outfp); - } - return 0; -} - -int resource_manager::do_begin_document(const char *ptr, int, FILE *, - FILE *) -{ - resource *r = read_file_arg(&ptr); - if (r) - r->flags |= resource::SUPPLIED; - return 1; -} - -int resource_manager::do_include_document(const char *ptr, int rank, FILE *, - FILE *outfp) -{ - resource *r = read_file_arg(&ptr); - if (r) - supply_resource(r, rank, outfp, 1); - return 0; -} - -int resource_manager::do_begin_procset(const char *ptr, int, FILE *, - FILE *outfp) -{ - resource *r = read_procset_arg(&ptr); - if (r) { - r->flags |= resource::SUPPLIED; - if (outfp) { - fputs("%%BeginResource: ", outfp); - r->print_type_and_name(outfp); - putc('\n', outfp); - } - } - return 0; -} - -int resource_manager::do_include_procset(const char *ptr, int rank, FILE *, - FILE *outfp) -{ - resource *r = read_procset_arg(&ptr); - if (r) - supply_resource(r, rank, outfp); - return 0; -} - -int resource_manager::do_begin_file(const char *ptr, int, FILE *, - FILE *outfp) -{ - resource *r = read_file_arg(&ptr); - if (r) { - r->flags |= resource::SUPPLIED; - if (outfp) { - fputs("%%BeginResource: ", outfp); - r->print_type_and_name(outfp); - putc('\n', outfp); - } - } - return 0; -} - -int resource_manager::do_include_file(const char *ptr, int rank, FILE *, - FILE *outfp) -{ - resource *r = read_file_arg(&ptr); - if (r) - supply_resource(r, rank, outfp); - return 0; -} - -int resource_manager::do_begin_font(const char *ptr, int, FILE *, - FILE *outfp) -{ - resource *r = read_font_arg(&ptr); - if (r) { - r->flags |= resource::SUPPLIED; - if (outfp) { - fputs("%%BeginResource: ", outfp); - r->print_type_and_name(outfp); - putc('\n', outfp); - } - } - return 0; -} - -int resource_manager::do_include_font(const char *ptr, int rank, FILE *, - FILE *outfp) -{ - resource *r = read_font_arg(&ptr); - if (r) { - if (rank >= 0) - supply_resource(r, rank + 1, outfp); - else - r->flags |= resource::FONT_NEEDED; - } - return 0; -} - -int resource_manager::change_to_end_resource(const char *, int, FILE *, - FILE *outfp) -{ - if (outfp) - fputs("%%EndResource\n", outfp); - return 0; -} - -int resource_manager::do_begin_preview(const char *, int, FILE *fp, FILE *) -{ - char buf[PS_LINE_MAX + 2]; - do { - if (!ps_get_line(buf, fp)) { - error("end of file in preview section"); - break; - } - } while (!matches_comment(buf, "EndPreview")); - return 0; -} - -int read_one_of(const char **ptr, const char **s, int n) -{ - while (white_space(**ptr)) - *ptr += 1; - if (**ptr == '\0') - return -1; - const char *start = *ptr; - do { - ++ptr; - } while (**ptr != '\0' && !white_space(**ptr)); - for (int i = 0; i < n; i++) - if (strlen(s[i]) == *ptr - start - && memcmp(s[i], start, *ptr - start) == 0) - return i; - return -1; -} - -int resource_manager::do_begin_data(const char *ptr, int, FILE *fp, - FILE *outfp) -{ - while (white_space(*ptr)) - ptr++; - const char *start = ptr; - unsigned numberof; - if (!read_uint_arg(&ptr, &numberof)) - return 0; - static const char *types[] = { "Binary", "Hex", "ASCII" }; - const int Binary = 0; - int type = 0; - static const char *units[] = { "Bytes", "Lines" }; - const int Bytes = 0; - int unit = Bytes; - while (white_space(*ptr)) - ptr++; - if (*ptr != '\0') { - type = read_one_of(&ptr, types, 3); - if (type < 0) { - error("bad data type"); - return 0; - } - while (white_space(*ptr)) - ptr++; - if (*ptr != '\0') { - unit = read_one_of(&ptr, units, 2); - if (unit < 0) { - error("expected `Bytes' or `Lines'"); - return 0; - } - } - } - if (type != Binary) - return 1; - if (outfp) { - fputs("%%BeginData: ", outfp); - fputs(start, outfp); - } - if (numberof > 0) { - unsigned bytecount = 0; - unsigned linecount = 0; - do { - int c = getc(fp); - if (c == EOF) { - error("end of file within data section"); - return 0; - } - if (outfp) - putc(c, outfp); - bytecount++; - if (c == '\r') { - int cc = getc(fp); - if (cc != '\n') { - linecount++; - current_lineno++; - } - if (cc != EOF) - ungetc(c, fp); - } - else if (c == '\n') { - linecount++; - current_lineno++; - } - } while ((unit == Bytes ? bytecount : linecount) < numberof); - } - char buf[PS_LINE_MAX + 2]; - if (!ps_get_line(buf, fp)) { - error("missing %%%%EndData line"); - return 0; - } - if (!matches_comment(buf, "EndData")) - error("bad %%%%EndData line"); - if (outfp) - fputs(buf, outfp); - return 0; -} - -int resource_manager::do_begin_binary(const char *ptr, int, FILE *fp, - FILE *outfp) -{ - if (!outfp) - return 0; - unsigned count; - if (!read_uint_arg(&ptr, &count)) - return 0; - if (outfp) - fprintf(outfp, "%%%%BeginData: %u Binary Bytes\n", count); - while (count != 0) { - int c = getc(fp); - if (c == EOF) { - error("end of file within binary section"); - return 0; - } - if (outfp) - putc(c, outfp); - --count; - if (c == '\r') { - int cc = getc(fp); - if (cc != '\n') - current_lineno++; - if (cc != EOF) - ungetc(c, fp); - } - else if (c == '\n') - current_lineno++; - } - char buf[PS_LINE_MAX + 2]; - if (!ps_get_line(buf, fp)) { - error("missing %%%%EndBinary line"); - return 0; - } - if (!matches_comment(buf, "EndBinary")) { - error("bad %%%%EndBinary line"); - if (outfp) - fputs(buf, outfp); - } - else if (outfp) - fputs("%%EndData\n", outfp); - return 0; -} - -static unsigned parse_extensions(const char *ptr) -{ - unsigned flags = 0; - for (;;) { - while (white_space(*ptr)) - ptr++; - if (*ptr == '\0') - break; - const char *name = ptr; - do { - ++ptr; - } while (*ptr != '\0' && !white_space(*ptr)); - for (int i = 0; i < NEXTENSIONS; i++) - if (strlen(extension_table[i]) == ptr - name - && memcmp(extension_table[i], name, ptr - name) == 0) { - flags |= (1 << i); - break; - } - if (i >= NEXTENSIONS) { - string s(name, ptr - name); - s += '\0'; - error("unknown extension `%1'", s.contents()); - } - } - return flags; -} - -// XXX if it has not been surrounded with {Begin,End}Document need to strip -// out Page: Trailer {Begin,End}Prolog {Begin,End}Setup sections. - -// XXX Perhaps the decision whether to use BeginDocument or -// BeginResource: file should be postponed till we have seen -// the first line of the file. - -void resource_manager::process_file(int rank, FILE *fp, const char *filename, - FILE *outfp) -{ - // If none of these comments appear in the header section, and we are - // just analyzing the file (ie outfp is 0), then we can return immediately. - static const char *header_comment_table[] = { - "DocumentNeededResources:", - "DocumentSuppliedResources:", - "DocumentNeededFonts:", - "DocumentSuppliedFonts:", - "DocumentNeededProcSets:", - "DocumentSuppliedProcSets:", - "DocumentNeededFiles:", - "DocumentSuppliedFiles:", - }; - - const int NHEADER_COMMENTS = (sizeof(header_comment_table) - / sizeof(header_comment_table[0])); - struct comment_info { - const char *name; - int (resource_manager::*proc)(const char *, int, FILE *, FILE *); - }; - - static comment_info comment_table[] = { - "BeginResource:", &resource_manager::do_begin_resource, - "IncludeResource:", &resource_manager::do_include_resource, - "BeginDocument:", &resource_manager::do_begin_document, - "IncludeDocument:", &resource_manager::do_include_document, - "BeginProcSet:", &resource_manager::do_begin_procset, - "IncludeProcSet:", &resource_manager::do_include_procset, - "BeginFont:", &resource_manager::do_begin_font, - "IncludeFont:", &resource_manager::do_include_font, - "BeginFile:", &resource_manager::do_begin_file, - "IncludeFile:", &resource_manager::do_include_file, - "EndProcSet", &resource_manager::change_to_end_resource, - "EndFont", &resource_manager::change_to_end_resource, - "EndFile", &resource_manager::change_to_end_resource, - "BeginPreview:", &resource_manager::do_begin_preview, - "BeginData:", &resource_manager::do_begin_data, - "BeginBinary:", &resource_manager::do_begin_binary, - }; - - const int NCOMMENTS = sizeof(comment_table)/sizeof(comment_table[0]); - char buf[PS_LINE_MAX + 2]; - int saved_lineno = current_lineno; - const char *saved_filename = current_filename; - current_filename = filename; - current_lineno = 0; - if (!ps_get_line(buf, fp)) { - current_filename = saved_filename; - current_lineno = saved_lineno; - return; - } - if (strlen(buf) < sizeof(PS_MAGIC) - 1 - || memcmp(buf, PS_MAGIC, sizeof(PS_MAGIC) - 1) != 0) { - if (outfp) { - do { - if (!(broken_flags & STRIP_PERCENT_BANG) - || buf[0] != '%' || buf[1] != '!') - fputs(buf, outfp); - } while (ps_get_line(buf, fp)); - } - } - else { - if (!(broken_flags & STRIP_PERCENT_BANG) && outfp) - fputs(buf, outfp); - int in_header = 1; - int interesting = 0; - int had_extensions_comment = 0; - int had_language_level_comment = 0; - for (;;) { - if (!ps_get_line(buf, fp)) - break; - int copy_this_line = 1; - if (buf[0] == '%') { - if (buf[1] == '%') { - const char *ptr; - for (int i = 0; i < NCOMMENTS; i++) - if (ptr = matches_comment(buf, comment_table[i].name)) { - copy_this_line - = (this->*(comment_table[i].proc))(ptr, rank, fp, outfp); - break; - } - if (i >= NCOMMENTS && in_header) { - if (ptr = matches_comment(buf, "EndComments")) - in_header = 0; - else if (!had_extensions_comment - && (ptr = matches_comment(buf, "Extensions:"))) { - extensions |= parse_extensions(ptr); - // XXX handle possibility that next line is %%+ - had_extensions_comment = 1; - } - else if (!had_language_level_comment - && (ptr = matches_comment(buf, "LanguageLevel:"))) { - unsigned ll; - if (read_uint_arg(&ptr, &ll) && ll > language_level) - language_level = ll; - had_language_level_comment = 1; - } - else { - for (int i = 0; i < NHEADER_COMMENTS; i++) - if (matches_comment(buf, header_comment_table[i])) { - interesting = 1; - break; - } - } - } - if ((broken_flags & STRIP_STRUCTURE_COMMENTS) - && (matches_comment(buf, "EndProlog") - || matches_comment(buf, "Page:") - || matches_comment(buf, "Trailer"))) - copy_this_line = 0; - } - else if (buf[1] == '!') { - if (broken_flags & STRIP_PERCENT_BANG) - copy_this_line = 0; - } - } - else - in_header = 0; - if (!outfp && !in_header && !interesting) - break; - if (copy_this_line && outfp) - fputs(buf, outfp); - } - } - current_filename = saved_filename; - current_lineno = saved_lineno; -} - -void resource_manager::read_download_file() -{ - char *path = 0; - FILE *fp = font::open_file("download", &path); - if (!fp) - fatal("can't find `download'"); - char buf[512]; - int lineno = 0; - while (fgets(buf, sizeof(buf), fp)) { - lineno++; - char *p = strtok(buf, " \t\r\n"); - if (p == 0 || *p == '#') - continue; - char *q = strtok(0, " \t\r\n"); - if (!q) - fatal_with_file_and_line(path, lineno, "missing filename"); - lookup_font(p)->filename = strsave(q); - } - a_delete path; - fclose(fp); -} - -// XXX Can we share some code with ps_output::put_string()? - -static void print_ps_string(const string &s, FILE *outfp) -{ - int len = s.length(); - const char *str = s.contents(); - int funny = 0; - if (str[0] == '(') - funny = 1; - else { - for (int i = 0; i < len; i++) - if (str[i] <= 040 || str[i] > 0176) { - funny = 1; - break; - } - } - if (!funny) { - put_string(s, outfp); - return; - } - int level = 0; - for (int i = 0; i < len; i++) - if (str[i] == '(') - level++; - else if (str[i] == ')' && --level < 0) - break; - putc('(', outfp); - for (i = 0; i < len; i++) - switch (str[i]) { - case '(': - case ')': - if (level != 0) - putc('\\', outfp); - putc(str[i], outfp); - break; - case '\\': - fputs("\\\\", outfp); - break; - case '\n': - fputs("\\n", outfp); - break; - case '\r': - fputs("\\r", outfp); - break; - case '\t': - fputs("\\t", outfp); - break; - case '\b': - fputs("\\b", outfp); - break; - case '\f': - fputs("\\f", outfp); - break; - default: - if (str[i] < 040 || str[i] > 0176) - fprintf(outfp, "\\%03o", str[i] & 0377); - else - putc(str[i], outfp); - break; - } - putc(')', outfp); -} - -void resource_manager::print_extensions_comment(FILE *outfp) -{ - if (extensions) { - fputs("%%Extensions:", outfp); - for (int i = 0; i < NEXTENSIONS; i++) - if (extensions & (1 << i)) { - putc(' ', outfp); - fputs(extension_table[i], outfp); - } - putc('\n', outfp); - } -} - -void resource_manager::print_language_level_comment(FILE *outfp) -{ - if (language_level) - fprintf(outfp, "%%%%LanguageLevel: %u\n", language_level); -} - |
