klamer@mi.eltn.utwente.nl (Klamer Schutte -- Universiteit Twente) (01/24/91)
The program boxps makes it possible to put several postscript pages in reduced size on one page. I assume this already is done earlier and better. However, i didn't knew where to get it, so i wrote it myself. Note this is a quick hack to get this job done. No responsibility for any behaviour provided. Klamer (.signature at end) echo x - README sed '/^X/s///' > README << '/' XCopyright Klamer Schutte 1991 XThis software should not be sold without permission of the author. XFree redistribution of original or modified sources of this program Xis allowed. X XThe program boxps makes it possible to put several postscript pages Xin reduced size on one page. X XThere are two source files, boxps.c and err.c. Boxps.c is the real thing; Xerr.c is just my standard error handler. But to compile without any changes Xyou need err.c so i provide this one as well. It could be usefull on its Xown, though. X XThe program is developed and tested on a sun sparcstation 1 with SunOS 4.1 XHowever, it is rather portable. The only difficult part is making the Xnew heading of the generated postscript file - but this can be skipped. XAlso the file err.c might not be to portable - but calls to fatal, Xerror and warning can easily be replaced by fprintf(stderr, and exit. X XBug fixes or enhancements as well as non-trivial ports are appreciated. X XKlamer Schutte XFaculty of electrical engineering -- University of Twente, The Netherlands Xklamer@mi.eltn.utwente.nl {backbone}!mcsun!mi.eltn.utwente.nl!klamer / echo x - boxps.1 sed '/^X/s///' > boxps.1 << '/' X\" Copyright Klamer Schutte 1991 X\" This software should not be sold without permission of the author. X\" Free redistribution of original or modified sources of this program X\" is allowed. X X.TH BOXPS 1 "24 Januari 1991" "University of Twente" X.SH NAME Xboxps \- put several postscript pages in reduced size on one page X.SH SYNOPSIS X.B boxps [-x x_nr][-y y_nr][-lg][-Pprinter] [files] X.SH DESCRIPTION X.B Boxps Xtakes postscript files and makes it possible to display several of them on Xone page. The X.B -x Xand X.B -y Xoptions gives the number of pages in the x resp. y direction. With the X.B -l Xoption output is redirected to the printer. The default printer is X.I postscipt, Xthis can be changed using the X.B -P Xoption. The X.B -g Xoption causes the postscript commands X.I gsave Xand X.I grestore Xto be mapped to dummy functions. This can be necessary for broken programs Xwhich put a X.I showpage Xin a X.I gsave/grestore Xpair. (Example: gnuplot). X.SH SEE ALSO Xpostscript(7). X.SH BUGS XThe whole system is not very robust. X XThe X.B -g Xoption redefines X.I gsave Xand X.I grestore Xglobally. So these operators are Xinaccessable in the rest of the postscript program. X.SH AUTHOR XKlamer Schutte -- klamer@mi.eltn.utwente.nl / echo x - boxps.c sed '/^X/s///' > boxps.c << '/' X/* XCopyright Klamer Schutte 1991 XThis software should not be sold without permission of the author. XFree redistribution of original or modified sources of this program Xis allowed. X*/ X/* X * boxps.c KS 23/1/91 X * X * make several postscript pages one X */ X X#include <stdio.h> X#include <sys/param.h> /* */ X#include <pwd.h> /* */ X Xusage(name) Xchar *name; X{ X fatal("Usage: %s [-x x_nr][-y y_nr][-lg][-Pprinter] [files]\n", X name ); X} X Xwrite_header(x,y,rotate,gsave,fp) Xint x,y,rotate; Xint gsave; XFILE *fp; X{ X char hostname[MAXHOSTNAMELEN]; X struct passwd *pwd, *getpwuid(); X int uid, cur_time; X X int i,j; X X uid = getuid(); X pwd = getpwuid( uid ); X gethostname( hostname, MAXHOSTNAMELEN ); X fprintf(fp,"%%!\n%%%%Creator: %s:%s (%s)\n", X hostname, X pwd->pw_name, pwd->pw_gecos ); X cur_time = time( NULL ); X fprintf(fp,"%%%%CreationDate: %s%%%%EndComments\n", X ctime( &cur_time ) ); X fprintf(fp,"statusdict begin /doprinterrors {true} def end\n"); X X fprintf(fp,"/boxps 10 dict def boxps begin\n/WindowNumber -1 def\n"); X X fprintf(fp,"/XTArray [ "); X for(i=0;i<x;i++) X for(j=0;j<y;j++) X fprintf(fp,"%g ", 8*72*i/(double)x ); X fprintf(fp," 0 ] def\n"); X X fprintf(fp,"/YTArray [ "); X for(i=0;i<x;i++) X for(j=0;j<y;j++) X fprintf(fp,"%g ", 11*72*j/(double)y ); X fprintf(fp," 0 ] def\n"); X X if (gsave) X fprintf(fp,"/gsave {} def\n/grestore {} def {}\n"); X X fprintf(fp,"/showpage {\n"); X fprintf(fp,"initgraphics\n"); X fprintf(fp,"boxps begin\n"); X fprintf(fp,"WindowNumber 1 add dup /WindowNumber exch def\n"); X fprintf(fp,"dup XTArray exch get exch YTArray exch get translate\n"); X fprintf(fp, "end\n"); X fprintf(fp,"%g %g scale\n", 1.0/x, 1.0/y); X /* should also set clippath! */ X fprintf(fp,"} def\n"); X fprintf(fp,"showpage\n"); X} X Xwrite_trailer(x,y,rotate,fp) Xint x,y,rotate; XFILE *fp; X{ X fprintf(fp,"end\nshowpage\n"); X} X Xcopy_file(fpin,name,fpout) XFILE *fpin, *fpout; Xchar *name; X{ X int c; X X while((c = getc(fpin)) != EOF) X putc(c,fpout); X} X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X int c, x=2, y=2, print = 0, rotate = 0, gsave = 0; X char *printer = "postscript"; X extern int optind; X extern char *optarg; X FILE *out,*fp; X char buf[80]; X X while((c = getopt(argc,argv,"x:y:lrP:g")) != EOF) X switch(c) X {case 'x': X x = atoi(optarg); X break; X case 'y': X y = atoi(optarg); X break; X case 'r': X rotate = 1; X warning("%s: rotate not implemented\n", argv[0]); X break; X case 'P': X printer = optarg; X /* FALL THROUGH */ X case 'l': X print = 1; X break; X case 'g': X gsave = 1; X break; X default: X usage(argv[0]); X } X X if (print) X { X sprintf(buf,"lpr -P%s",printer); X out = popen(buf,"w"); X if (out == NULL) X fatal("%s: Can't popen to %s\n", argv[0], buf ); X } else X out = stdout; X X write_header(x,y,rotate,gsave,out); X if (argc - optind == 0) X copy_file(stdin,"(stdin)",out); X else X for(;argc-optind;optind++) X { X fp = fopen( argv[optind], "r" ); X if (fp == NULL) X { X error("Can't open %s\n", argv[optind] ); X continue; X } X copy_file(fp,argv[optind],out); X fclose(fp); X } X write_trailer(x,y,rotate,out); X X if (print) X pclose(out); X X return 0; X} / echo x - err.3 sed '/^X/s///' > err.3 << '/' X\" Copyright Klamer Schutte 1991 X\" This software should not be sold without permission of the author. X\" Free redistribution of original or modified sources of this program X\" is allowed. X X.TH ERR 3 "25 July 1990" "University of Twente" "Utility routines" X.SH NAME Xwarning, error, fatal \- consistent error handling X.SH SYNOPSIS X#include <setjmp.h> X.br X#include <err.h> X.LP Xwarning( fmt, ... ) X.br Xchar *fmt; X.LP Xerror( fmt, ... ) X.br Xchar *fmt; X.LP Xfatal( fmt, ... ) X.br Xchar *fmt; X.LP Xfatal_nr( nr, fmt, ... ) X.br Xint nr; X.br Xchar *fmt; X.LP Xextern int err_nr_errors, err_nr_warnings; X.br Xextern int *err_warning_jmpbuf, *err_error_jmpbuf, *err_fatal_jmpbuf; X.SH DESCRIPTION XThese routines provide a way to handle all kind of errors in a consistent way. XThe differences between the routines are: X.I warning() Xis intended to be used when the error encountered is to be reported, but Xwill probably not harm the result. X.I error() Xshould be called when the error will harm the result (it will probably not be Xvalid), but execution can continue; X.I fatal() Xshould be called when the error means that the program can not continue. X.I fatal() Xwill exit with a return value of 1; X.I fatal_nr() Xwill exit with the return value X.I nr. X.br XThe integers X.I err_nr_warnings Xand X.I err_nr_errors Xhold the number of time these routines are called. X.br XThe X.I err_*_jmpbuf Xvariables are pointers to a X.I jmp_buf. XWhen these are not NULL they should point to a valid X.I jmp_buf Xfor use by X.I longjmp(3). XIn this way the program can catch errors as generated by these routines. X.SH ARGUMENTS XThe string X.I fmt Xand trailing arguments are handled in the way of X.I printf(3). X.SH SEE ALSO Xsetjmp(3), printf(3), fprintf(3), exit(3). X.SH NOTE XObject in library /home/lib/libutil.a X.br Xerr.h can be found in /home/include. X.SH AUTHOR XKlamer Schutte / echo x - err.c sed '/^X/s///' > err.c << '/' X/* XCopyright Klamer Schutte 1991 XThis software should not be sold without permission of the author. XFree redistribution of original or modified sources of this program Xis allowed. X*/ X/* X * error.c Klamer Schutte 25/7/90 X * X * handle errors in a consistent way. X */ X X#include <stdio.h> X#include <varargs.h> X#include <setjmp.h> X Xint err_nr_errors, err_nr_warnings; X/* what is the type of a pointer to a jmp_buf? On sun4 int * will do */ Xint *err_warning_jmpbuf, *err_error_jmpbuf, *err_fatal_jmpbuf; X X/*VARARGS1*/ Xwarning( fmt, va_alist ) Xchar *fmt; Xva_dcl X{ X va_list args; X X va_start( args ); X vfprintf(stderr, fmt, args ); X va_end(args ); X X err_nr_warnings++; X X if (err_warning_jmpbuf != NULL) X longjmp( err_warning_jmpbuf, 1 ); X} X X/*VARARGS1*/ Xerror( fmt, va_alist ) Xchar *fmt; Xva_dcl X{ X va_list args; X X va_start( args ); X vfprintf(stderr, fmt, args ); X va_end(args ); X X err_nr_errors++; X X if (err_error_jmpbuf != NULL) X longjmp( err_error_jmpbuf, 1 ); X} X X/*VARARGS2*/ Xfatal_exit_nr( nr, fmt, va_alist ) Xint nr; Xchar *fmt; Xva_dcl X{ X va_list args; X X va_start( args ); X vfprintf(stderr, fmt, args ); X va_end(args ); X X if (err_fatal_jmpbuf != NULL) X longjmp( err_fatal_jmpbuf, 1 ); X X exit( nr ); X} X X/*VARARGS1*/ Xfatal( fmt, va_alist ) Xchar *fmt; Xva_dcl X{ X va_list args; X X va_start( args ); X vfprintf(stderr, fmt, args ); X va_end(args ); X X if (err_fatal_jmpbuf != NULL) X longjmp( err_fatal_jmpbuf, 1 ); X X exit( 1 ); X} / -- Klamer Schutte Faculty of electrical engineering -- University of Twente, The Netherlands klamer@mi.eltn.utwente.nl {backbone}!mcsun!mi.eltn.utwente.nl!klamer