[comp.sources.misc] v10i004: Official Patch #6 to thack

everson%compsci.bristol.ac.uk@NSFnet-Relay.AC.UK (01/09/90)

Posting-number: Volume 10, Issue 4
Submitted-by: everson%compsci.bristol.ac.uk@NSFnet-Relay.AC.UK
Archive-name: thack.p6

This is to introduce official patch #6 (it might be #7 by now, I seem
to have lost count) to thack, a troff to postscript filter.
[It's #6.  ++bsa]

I would appreicate it if anyone who makes modifications to this or any other 
program would send me the output of a 'diff -c' with a known version of the 
software rather a full copy from which I have to extract your modifications
myself. We can reduce network traffic and also make official patch creation
easier when there is more than one group working on the code at the same time. 

Here are the changes:

--------------------------------------------------------------------------

I got thack to work under OpenWindows 1.0 as part of a manual page previewer.
Here are some changes to thack that I found needed or helpful.

	Permit 'thack filename'; this is required if we want to use thack in
	Sun's 'man -t' command by setting the environment variable TCAT to
	'thack'.

	Upgrade to (my limited understanding of) PS-Adobe-2.0 EPSF-2.0 format.

	Put 'thack: ' in the front of error messages.
	(It isolates them better in a pipeline.)

	Keep better track of errors for thack's exit status.

	Fix minor spacing and font problems in man page.

-- Paul Eggert <eggert@twinsun.com>

--------------------------------------------------------------------------

The main fix is to generate smaller output; on a large computer science paper
("Eli: A Complete, Flexible Compiler Construction System") the new output is
28% smaller than the old.  On the thack man page itself, the savings is only
21% because the output is so small.  The savings comes from outputting smaller
numbers, and from eliminating some unneeded newlines, turning some blanks into
newlines so that no long lines are generated.  For example, where the old thack
generated

	60 TR F
	(T)270 4533 P
	(H)307 X
	(A)350 X
	(C)393 X
	(K)433 X

the new thack generates

	60 TR(T)270 1511
	P(H)37
	X(A)43
	X(C)43
	X(K)40
	X

A minor fix: npages is now unsigned.

-- Paul Eggert <eggert@twinsun.com>

----------------------------------------------------------------------------

Here is a patch to thack that adds support for the characters circle, 1/4, 1/2,
3/4, and Bell System logo.  For the logo, I use the same character that Adobe
TranScript uses; it displays as an Apple logo on our LaserWriter (and on Sun's
OpenWindows 1.0).  Also, the square is patched to look more like a square.
While I was at it I put the prolog text into a table; this should make things a
tad smaller and/or faster.

-- Paul Eggert <eggert@twinsun.com>



Thanks

Phillip G. Everson
----------------------------------------------------------------------------
Medical Imaging                      Senior Software Engineer
Dept Comp Sci                        Philips Radiotherapy Systems
University of Bristol, UK            Horfield Road, Bristol, UK

*** README	Mon Jan  8 08:49:53 1990
--- README.orig	Mon Jan  8 08:35:08 1990
***************
*** 14,21 ****
  
  It does not claim to be perfect, but I personally have used it for
  printing many documents in the past, especially manual pages and found
! it very useful. It has also been used under OpenWindows1.0 aspart of a 
! manual page previewer.
  
  It was written under SunOS3.5, but has been run on a 3B2 running System V
  and produces particularly nice output under SunOS4.0 or later as Sun
--- 14,20 ----
  
  It does not claim to be perfect, but I personally have used it for
  printing many documents in the past, especially manual pages and found
! it very useful.
  
  It was written under SunOS3.5, but has been run on a 3B2 running System V
  and produces particularly nice output under SunOS4.0 or later as Sun
*** thack.1	Mon Jan  8 08:45:52 1990
--- thack.1.orig	Mon Jan  8 08:35:08 1990
***************
*** 1,5 ****
  .\" .TH name section cent-foot
! .TH THACK 1 "8 January 1990"
  .SH NAME
  .\" name \- function
  thack \- hack about with TROFF output
--- 1,5 ----
  .\" .TH name section cent-foot
! .TH THACK 1 "28 August 1987"
  .SH NAME
  .\" name \- function
  thack \- hack about with TROFF output
***************
*** 6,14 ****
  .SH SYNOPSIS
  .\" Bold keywords, Italic variables, [] options, | alternatives.
  .B thack
- [
- .IR filename .\|.\|.
- ]
  .SH DESCRIPTION
  .\" Italic files, commands, IR manual-entry (manual-section)
  .I Thack
--- 6,11 ----
***************
*** 15,21 ****
  is a hack to
  convert
  .IR troff (1)
! output into
  postscript.
  The postscript it
  produces is not highly
--- 12,18 ----
  is a hack to
  convert
  .IR troff (1)
! output into 
  postscript.
  The postscript it
  produces is not highly
***************
*** 37,45 ****
  that an uncatered for code has been
  sent (24 have yet to be identified).
  More interesting messages such
! as `Sequence Bell Logo is not allowed'
! are also printed.  There are five of these
! cases.  However, some illegal sequences are
  intercepted and used
  as additional font information.
  .SH BUGS
--- 34,42 ----
  that an uncatered for code has been
  sent (24 have yet to be identified).
  More interesting messages such
! as 'Sequence Bell Logo is not allowed'
! are also printed. There are five of these
! cases. However, some illegal sequences are 
  intercepted and used
  as additional font information.
  .SH BUGS
***************
*** 50,56 ****
  .br
  Many Special characters are Wrong.
  .br
! .IR Eqn (1)
! and
! .IR tbl (1)
! are not 100% compatible.
--- 47,50 ----
  .br
  Many Special characters are Wrong.
  .br
! Eqn(1) & Tbl(1) are not 100% compatible.
*** thack.c	Mon Jan  8 08:37:29 1990
--- thack.c.orig	Mon Jan  8 08:35:08 1990
***************
*** 1,8 ****
  #include "th.h"
  
! int error;
! unsigned npages;
! int xpos, ypos, cx, cy;
  int font, cfont, size, csize, tfont, tsize;
  char *pstr, *cstr();
  
--- 1,7 ----
  #include "th.h"
  
! int npages;
! int xpos, ypos, cy;
  int font, cfont, size, csize, tfont, tsize;
  char *pstr, *cstr();
  
***************
*** 21,50 ****
  #define Y_INITIAL ((int)(PAGELENGTH*144 + 0.5))
  #endif
  
! #define POINTS_PER_INCH 72
! 
! int
! main(argc, argv)
! int argc;
! char **argv;
  {
- 	if (argc <= 1)
- 		thack();
- 	else {
- 		char **a = argv;
- 		while (*++a)
- 			if (freopen(*a, "r", stdin))
- 				thack();
- 			else {
- 				fprintf(stderr, "thack: %s: cannot open\n", *a);
- 				error = 1;
- 			}
- 	}
- 	return error || ferror(stdout);
- }
- 
- thack()
- {
  	int c;
  	int sflag;
  	int hdist, vdist;
--- 20,27 ----
  #define Y_INITIAL ((int)(PAGELENGTH*144 + 0.5))
  #endif
  
! main()
  {
  	int c;
  	int sflag;
  	int hdist, vdist;
***************
*** 57,63 ****
  	tsize = size = 12;
  	esc = lead = 1;
  	cy = ypos = Y_INITIAL;
! 	cx = xpos = 0;
  	sflag = 0;
  	prolog();
  	newpage();
--- 34,40 ----
  	tsize = size = 12;
  	esc = lead = 1;
  	cy = ypos = Y_INITIAL;
! 	xpos = 0;
  	sflag = 0;
  	prolog();
  	newpage();
***************
*** 91,108 ****
  								pstr = "\\320";
  								break;	/* \(em */
  							case 28:
! 								pstr = " (1)(4)R";
  								break;	/* \(14 */
  							case 30:
! 								pstr = " (1)(2)R";
  								break;	/* \(12 */
  							case 38:
! 								pstr = " (3)(4)R";
  								break;	/* \(34 */
  							default:
! 								fprintf(stderr, "thack: >>>>> L%d/%d\n", font, c & 0x3f);
  								pstr = "?";
- 								error = 1;
  							}
  						else
  							switch (c & 0x3f) {
--- 68,84 ----
  								pstr = "\\320";
  								break;	/* \(em */
  							case 28:
! 								illegal("1/4");
  								break;	/* \(14 */
  							case 30:
! 								illegal("1/2");
  								break;	/* \(12 */
  							case 38:
! 								illegal("3/4");
  								break;	/* \(34 */
  							default:
! 								fprintf(stderr, ">>>>> L%d/%d\n", font, c & 0x3f);
  								pstr = "?";
  							}
  						else
  							switch (c & 0x3f) {
***************
*** 146,157 ****
  								fontps(3, size, "\\323");
  								break;	/* c'right */
  							case 44:
! 								pstr = "  SQ";
! 								break;	/* square */
  							default:
! 								fprintf(stderr, "thack: >>>>> U%d/%d\n", font, c & 0x3f);
  								pstr = "?";
- 								error = 1;
  							}
  					else if (fh == 0)
  						switch (c & 0x3f) {
--- 122,132 ----
  								fontps(3, size, "\\323");
  								break;	/* c'right */
  							case 44:
! 								pstr = "\\250";
! 								break;	/* square ? */
  							default:
! 								fprintf(stderr, ">>>>> U%d/%d\n", font, c & 0x3f);
  								pstr = "?";
  							}
  					else if (fh == 0)
  						switch (c & 0x3f) {
***************
*** 177,183 ****
  							fontps(0, size, "\\\\");
  							break;	/* Backslash ! */
  						case 35:
! 							pstr = "\\360";
  							break;	/* Bell Logo */
  						case 36:
  							pstr = "\\245";
--- 152,158 ----
  							fontps(0, size, "\\\\");
  							break;	/* Backslash ! */
  						case 35:
! 							illegal("Bell Logo");
  							break;	/* Bell Logo */
  						case 36:
  							pstr = "\\245";
***************
*** 222,230 ****
  							pstr = "\\273";
  							break;	/* ~= */
  						default:
! 							fprintf(stderr, "thack: >>>>> L%d/%d\n", font, c & 0x3f);
  							pstr = "?";
- 							error = 1;
  						}
  					else
  						switch (c & 0x3f) {
--- 197,204 ----
  							pstr = "\\273";
  							break;	/* ~= */
  						default:
! 							fprintf(stderr, ">>>>> L%d/%d\n", font, c & 0x3f);
  							pstr = "?";
  						}
  					else
  						switch (c & 0x3f) {
***************
*** 316,322 ****
  							pstr = "\\315";
  							break;	/* impr. subset */
  						case 41:
! 							pstr = "  O";
  							break;	/* circle */
  						case 44:
  							pstr = "\\256";
--- 290,296 ----
  							pstr = "\\315";
  							break;	/* impr. subset */
  						case 41:
! 							illegal("circle");
  							break;	/* circle */
  						case 44:
  							pstr = "\\256";
***************
*** 325,333 ****
  							fontps(0, size, "\\247");
  							break;	/* section */
  						default:
! 							fprintf(stderr, "thack: >>>>> U%d/%d\n", font, c & 0x3f);
  							pstr = "?";
- 							error = 1;
  						}
  				}
  				else {
--- 299,306 ----
  							fontps(0, size, "\\247");
  							break;	/* section */
  						default:
! 							fprintf(stderr, ">>>>> U%d/%d\n", font, c & 0x3f);
  							pstr = "?";
  						}
  				}
  				else {
***************
*** 394,401 ****
  				size = 36;
  				break;
  			default:
! 				fprintf(stderr, "thack: Size: %x\n", c & 0x0f);
! 				error = 1;
  			}
  			crsize(csize, size);
  			tsize = size;
--- 367,373 ----
  				size = 36;
  				break;
  			default:
! 				fprintf(stderr, "Size: %x\n", c & 0x0f);
  			}
  			crsize(csize, size);
  			tsize = size;
***************
*** 403,409 ****
  		else if ((c & 0xf0) == 0x40) {
  			c &= 0xf;
  			switch (c) {
! 			case 0:/* fputs("thack: INIT\n", stderr); error = 1; */
  				break;
  			case 1:
  				font &= 30;
--- 375,381 ----
  		else if ((c & 0xf0) == 0x40) {
  			c &= 0xf;
  			switch (c) {
! 			case 0:/* fprintf(stderr,"INIT\n"); */
  				break;
  			case 1:
  				font &= 30;
***************
*** 429,435 ****
  			case 8:
  				esc = -1;
  				break;
! 			case 9:/* fputs("thack: STOP\n", stderr); error = 1; */
  				break;
  			case 10:
  				lead = 1;
--- 401,407 ----
  			case 8:
  				esc = -1;
  				break;
! 			case 9:/* fprintf(stderr,"STOP\n"); */
  				break;
  			case 10:
  				lead = 1;
***************
*** 444,451 ****
  				font &= 27;
  				break;
  			default:
! 				fputs( "thack: ILLEGAL\n", stderr );
! 				error = 1;
  				break;
  			}
  			tfont = font;
--- 416,422 ----
  				font &= 27;
  				break;
  			default:
! 				fputs( "ILLEGAL\n", stderr );
  				break;
  			}
  			tfont = font;
***************
*** 454,535 ****
  	if (sflag)
  		endpage();
  	epilog();
  }
  
  tprint()
  {
  	if (font != cfont || size != csize) {
! 		char *fontname;
  		switch (font) {
  		case 0:
! 			fontname = "TR";
  			break;
  		case 1:
! 			fontname = "TI";
  			break;
  		case 2:
! 			fontname = "TB";
  			break;
  		case 3:
! 			fontname = "S";
  			break;
  		case 8:
! 			fontname = "H";
  			break;
  		case 9:
! 			fontname = "HO";
  			break;
  		case 10:
! 			fontname = "HB";
  			break;
  		case 11:
! 			fontname = "S";
  			break;
  		case 16:
! 			fontname = "C";
  			break;
  		case 17:
! 			fontname = "CO";
  			break;
  		case 18:
! 			fontname = "CB";
  			break;
  		case 19:
! 			fontname = "S";
  			break;
  		case 24:
! 			fontname = "TBI";
  			break;
  		case 25:
! 			fontname = "HBO";
  			break;
  		case 26:
! 			fontname = "CBO";
  			break;
  		case 27:
! 			fontname = "S";
  			break;
  		default:
! 			fprintf(stderr, "thack: Illegal Font %d\n", font);
! 			error = 1;
! 			fontname = "TR";
  		}
! 		printf("\n%d %s", size * 6, fontname);
  		cfont = font;
  		csize = size;
  	}
! 	if (*pstr == ' ')
! 		printf(" %d %d\nM%s", xpos, ypos, pstr+1);
! 	else if (ypos != cy)
! 		printf("(%s)%d %d\nP", pstr, xpos, ypos);
! 	else {
! 		int dx = xpos - cx;
! 		if (dx < 0)
! 			printf("(%s)%d\nx", pstr, -dx);
! 		else
! 			printf("(%s)%d\nX", pstr, dx);
! 	}
! 	cx = xpos;
  	cy = ypos;
  }
  
--- 425,498 ----
  	if (sflag)
  		endpage();
  	epilog();
+ 	return 0;
  }
  
  tprint()
  {
  	if (font != cfont || size != csize) {
! 		printf("%d ", size * 6);
  		switch (font) {
  		case 0:
! 			fputs("TR", stdout);
  			break;
  		case 1:
! 			fputs("TI", stdout);
  			break;
  		case 2:
! 			fputs("TB", stdout);
  			break;
  		case 3:
! 			fputs("S", stdout);
  			break;
  		case 8:
! 			fputs("H", stdout);
  			break;
  		case 9:
! 			fputs("HO", stdout);
  			break;
  		case 10:
! 			fputs("HB", stdout);
  			break;
  		case 11:
! 			fputs("S", stdout);
  			break;
  		case 16:
! 			fputs("C", stdout);
  			break;
  		case 17:
! 			fputs("CO", stdout);
  			break;
  		case 18:
! 			fputs("CB", stdout);
  			break;
  		case 19:
! 			fputs("S", stdout);
  			break;
  		case 24:
! 			fputs("TBI", stdout);
  			break;
  		case 25:
! 			fputs("HBO", stdout);
  			break;
  		case 26:
! 			fputs("CBO", stdout);
  			break;
  		case 27:
! 			fputs("S", stdout);
  			break;
  		default:
! 			fprintf(stderr, "Illegal Font %d\n", font);
! 			fputs("TR", stdout);
  		}
! 		fputs(" F\n", stdout);
  		cfont = font;
  		csize = size;
  	}
! 	if (ypos == cy)
! 		printf("(%s)%d X\n", pstr, xpos);
! 	else
! 		printf("(%s)%d %d P\n", pstr, xpos, 3 * ypos);
  	cy = ypos;
  }
  
***************
*** 541,546 ****
--- 504,516 ----
  	font = f1;
  }
  
+ illegal(s)
+ char *s;
+ {
+ 	pstr = s;
+ 	fprintf(stderr, "Sequence \\(%s is not allowed\n", s);
+ }
+ 
  crsize(old, new)
  {
  	if ((old == 16 || old >= 20) && (new != 16 && new < 20))
***************
*** 562,637 ****
  newpage()
  {
  	++npages;
! 	printf("\n%%%%Page: %u %u\nsave", npages, npages);
  }
  
- static char *prolog_text[] = {
- 	"%%Title: troff output",
- 	"%%Creator: (thack - contact <everson@cs.bris.ac.uk>)",
- 	"%%Pages: (atend)",
- 	"%%DocumentFonts: Times-Roman Times-Italic Times-Bold \
- Symbol Helvetica Helvetica-Oblique Helvetica-Bold Courier \
- Courier-Oblique Courier-Bold Times-BoldItalic Helvetica-BoldOblique \
- Courier-BoldOblique",
- 	"%%EndComments",
- 
- 	"/M{3 mul moveto}bind def",
- 	"/P{M gsave show grestore}bind def",
- 	"/X{0 rmoveto gsave show grestore}bind def",
- 	"/x{neg X}bind def",
- 	"/F{findfont exch scalefont setfont}bind def",
- 	"/TR{/Times-Roman F}bind def",
- 	"/TI{/Times-Italic F}bind def",
- 	"/TB{/Times-Bold F}bind def",
- 	"/S{/Symbol F}bind def",
- 	"/H{/Helvetica F}bind def",
- 	"/HO{/Helvetica-Oblique F}bind def",
- 	"/HB{/Helvetica-Bold F}bind def",
- 	"/C{/Courier F}bind def",
- 	"/CO{/Courier-Oblique F}bind def",
- 	"/CB{/Courier-Bold F}bind def",
- 	"/TBI{/Times-BoldItalic F}bind def",
- 	"/HBO{/Helvetica-BoldOblique F}bind def",
- 	"/CBO{/Courier-BoldOblique F}bind def",
- 	"/MR[.65 0 0 .6 0 0]def",
- 	"/1H{gsave newpath 0 0 moveto(1)true charpath flattenpath pathbbox",
- 	" 4 1 roll pop pop pop grestore}bind def",
- 	"/DR{gsave 1H 18 div setlinewidth currentpoint translate}bind def",
- 	"/Z{0 0 transform exch round exch round itransform moveto}bind def",
- 	"/O{DR newpath 1H 2 div dup dup 0 360 arc stroke grestore}bind def",
- 	"/SQ{DR Z newpath 0 0 moveto 1H 0 rlineto 0 1H rlineto 1H neg 0 rlineto",
- 	" closepath stroke grestore}bind def",
- 	"/R{gsave 0 1H .4 mul 2 copy rmoveto currentfont dup MR makefont dup",
- 	" setfont exch 6 -1 roll show setfont 3 1 roll neg rmoveto(\\244)show",
- 	" setfont show grestore}bind def",
- 	"1 6 div dup scale",
- 	"%%EndProlog",
- 	0
- };
- 
  prolog()
  {
  	time_t clock = time((time_t *)0);
! 	char **p;
  
! 	printf("%s%s%s%g\n",
! 		"%!PS-Adobe-2.0 EPSF-2.0\n%%CreationDate: ", asctime(localtime(&clock)),
! 		"%%BoundingBox: 0 0 542.88 ", PAGELENGTH*POINTS_PER_INCH
! 	);
  
! 	for (p = prolog_text;  *p;  p++)
! 		puts(*p);
! 
! 	npages = 0;
  }
  
  endpage()
  {
! 	printf("\nshowpage\nrestore");
  	cfont = csize = -1;	/* Doing this will cause a new font message */
  }
  
  epilog()
  {
! 	printf("\n%%%%Trailer\n%%%%Pages: %u\n", npages);
  }
--- 532,587 ----
  newpage()
  {
  	++npages;
! 	printf("%%%%Page: %d %d\n", npages, npages);
! 	printf("save\n");
  }
  
  prolog()
  {
  	time_t clock = time((time_t *)0);
! 	  
! 	printf("%%!PS-Adobe-\n");
! 	printf("%%%%Creator: (thack - contact <everson@cs.bris.ac.uk>)\n");
! 	printf("%%%%Title: unknown\n");
! 	printf("%%%%CreationDate: %s", asctime (localtime (&clock)));
! 	printf("%%%%Pages: (atend)\n");
! 	printf("%%%%DocumentFonts: Times-Roman Times-Italic Times-Bold \
! Symbol Helvetica Helvetica-Oblique Helvetica-Bold Courier \
! Courier-Oblique Courier-Bold Times-BoldItalic Helvetica-BoldOblique \
! Courier-BoldOblique\n");
! 	printf("%%%%EndComments\n");
  
! 	printf("/P {moveto show} bind def\n");
! 	printf("/X {currentpoint exch pop moveto show} bind def\n");
! 	printf("/F {findfont exch scalefont setfont} bind def\n");
! 	printf("/TR /Times-Roman def\n");
! 	printf("/TI /Times-Italic def\n");
! 	printf("/TB /Times-Bold def\n");
! 	printf("/S /Symbol def\n");
! 	printf("/H /Helvetica def\n");
! 	printf("/HO /Helvetica-Oblique def\n");
! 	printf("/HB /Helvetica-Bold def\n");
! 	printf("/C /Courier def\n");
! 	printf("/CO /Courier-Oblique def\n");
! 	printf("/CB /Courier-Bold def\n");
! 	printf("/TBI /Times-BoldItalic def\n");
! 	printf("/HBO /Helvetica-BoldOblique def\n");
! 	printf("/CBO /Courier-BoldOblique def\n");
! 	printf("1 6 div dup scale\n");
  
! 	printf("%%%%EndProlog\n");
!         npages = 0;
  }
  
  endpage()
  {
! 	printf("showpage\n");
! 	printf("restore\n");
  	cfont = csize = -1;	/* Doing this will cause a new font message */
  }
  
  epilog()
  {
!   printf("%%%%Trailer\n");
!   printf("%%%%Pages: %d\n", npages);
  }